Spec-Zone .ru
спецификации, руководства, описания, API
|
MySQL поддерживает сменную аутентификацию, в которой плагины вызываются, чтобы аутентифицировать клиентские
соединения. Плагины аутентификации включают использованию методов аутентификации кроме встроенного метода
паролей, сохраненных в mysql.user
таблица. Например, плагины могут быть записаны,
чтобы получить доступ к внешним методам аутентификации. Кроме того, плагины аутентификации могут поддерживать
пользовательскую возможность прокси, так, что соединяющийся пользователь является прокси для другого
пользователя и обрабатывается, в целях управления доступом, как наличие полномочий различного пользователя. Для
получения дополнительной информации см. Раздел 6.3.7, "Сменная
Аутентификация", и Раздел
6.3.8, "Пользователи Прокси".
Плагин аутентификации может быть записан для стороны сервера или стороны клиента. Серверные плагины используют тот же самый сменный API, который используется для других типов плагина сервера, таких как полнотекстовый синтаксический анализатор или контрольные плагины (хотя с различным специфичным для типа дескриптором). Клиентские плагины используют клиентский API плагина.
Несколько заголовочных файлов содержат информацию, относящуюся к плагинам аутентификации:
plugin.h
: Определяет MYSQL_AUTHENTICATION_PLUGIN
тип плагина сервера.
client_plugin.h
: Определяет API для клиентских
плагинов. Это включает клиентский дескриптор плагина и прототипов функции для клиентского плагина C
вызовы API (см. Раздел 22.8.14, "Клиентские
Функции Плагина API C").
plugin_auth.h
: Определяет часть API плагина сервера,
определенного для плагинов аутентификации. Это включает специфичный для типа дескриптор для серверных
плагинов аутентификации и MYSQL_SERVER_AUTH_INFO
структура.
plugin_auth_common.h
: Содержит общие элементы плагинов
аутентификации клиента и сервера. Это включает определения возвращаемого значения и MYSQL_PLUGIN_VIO
структура.
Чтобы записать плагин аутентификации, включайте следующие заголовочные файлы в сменный исходный файл. Другой MySQL или общие заголовочные файлы могли бы также быть необходимы.
Для исходного файла, который реализует плагин аутентификации сервера, включайте этот файл:
#include <mysql/plugin_auth.h>
Для исходного файла, который реализует плагин аутентификации клиента, или оба плагина клиента и сервера, включают эти файлы:
#include <mysql/plugin_auth.h>#include <mysql/client_plugin.h>#include <mysql>
plugin_auth.h
включает plugin.h
и plugin_auth_common.h
, таким образом, Вы не должны включать последние файлы явно.
Этот раздел описывает, как записать пару простого сервера и плагинов аутентификации клиента, которые сотрудничают.
Эти плагины принимают любой непустой пароль, и пароль отправляется в открытом тексте. Это небезопасно, таким образом, плагины не должны использоваться в продуктивных средах.
Серверные и клиентские плагины, разработанные здесь, обоих называют auth_simple
.
Как описано в Разделе 23.2.4.2, "Сменные Структуры
данных", у сменного файла библиотеки должно быть то же самое базовое имя как клиентский плагин,
таким образом, имя исходного файла auth_simple.c
и производит названную библиотеку
auth_simple.so
(предполагающий, что Ваша система использует .so
как суффикс для файлов библиотеки).
В исходных дистрибутивах MySQL источник плагина аутентификации располагается в plugin/auth
каталог и может быть исследован как руководство по записи других плагинов аутентификации. Кроме того, чтобы
видеть, как встроенные плагины аутентификации реализуются, см. sql/sql_acl.cc
для
плагинов, которые встраиваются к серверу MySQL и sql-common/client.c
для плагинов,
которые встраиваются к libmysqlclient
клиентская библиотека. (Для встроенных
клиентских плагинов отметьте что auth_plugin_t
структуры, используемые там,
отличаются от структур, используемых с обычными клиентскими макросами объявления плагина. В частности первые два
элемента обеспечиваются явно, не макросами объявления.)
Объявите серверный плагин с обычным общим форматом дескриптора, который используется для всех типов плагина
сервера (см. Раздел 23.2.4.2.1, "Библиотека
Плагина сервера и Сменные Дескрипторы"). Для auth_simple
плагин,
дескриптор похож на это:
mysql_declare_plugin(auth_simple){ MYSQL_AUTHENTICATION_PLUGIN, &auth_simple_handler, /* type-specific descriptor */ "auth_simple", /* plugin name */ "Author Name", /* author */ "Any-password authentication plugin", /* description */ PLUGIN_LICENSE_GPL, /* license type */ NULL, /* no init function */ NULL, /* no deinit function */ 0x0100, /* version = 1.0 */ NULL, /* no status variables */ NULL, /* no system variables */ NULL, /* no reserved information */ 0 /* no flags */}mysql_declare_plugin_end;
name
элемент (auth_simple
) указывает на имя, чтобы
использовать для ссылок на плагин в операторах такой как INSTALL PLUGIN
или UNINSTALL PLUGIN
. Это - также имя, выведенное на экран SHOW PLUGINS
или INFORMATION_SCHEMA.PLUGINS
.
auth_simple_handler
элемент общего дескриптора указывает на специфичный для типа
дескриптор. Для плагина аутентификации специфичный для типа дескриптор является экземпляром st_mysql_auth
структура (определенный в plugin_auth.h
):
struct st_mysql_auth{ int interface_version; const char *client_auth_plugin; int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info);};
st_mysql_auth
у структуры есть три элемента: специфичный для типа номер версии
API, клиентское имя плагина, и указатель на основную сменную функцию, которая связывается с клиентом. client_auth_plugin
элемент должен указать на имя клиентского плагина, если
определенный плагин требуется. Значение NULL
означает "любой плагин." В последнем случае безотносительно плагина
клиентское использование сделает. Это полезно, если плагин сервера не заботится о клиентском плагине или
какое имя пользователя или пароль это отправляет. Например, это могло бы быть истиной, если плагин сервера
аутентифицирует только локальные клиенты и использует некоторое свойство операционной системы, а не
информации, отправленной клиентским плагином.
Для auth_simple
, специфичный для типа дескриптор похож на это:
static struct st_mysql_auth auth_simple_handler ={ MYSQL_AUTHENTICATION_INTERFACE_VERSION, "auth_simple", /* required client-side plugin name */ auth_simple_server /* server-side plugin main function */};
Основная функция берет два параметра, представляющие структуру ввода-вывода и a MYSQL_SERVER_AUTH_INFO
структура. Определение структуры находится в plugin_auth.h
. Это похоже на это:
typedef struct st_mysql_server_auth_info{ char *user_name; unsigned int user_name_length; const char *auth_string; unsigned long auth_string_length; char authenticated_as[MYSQL_USERNAME_LENGTH+1]; char external_user[512]; int password_used; const char *host_or_ip; unsigned int host_or_ip_length;} MYSQL_SERVER_AUTH_INFO;
Набор символов для строковых элементов является UTF-8. Если есть a _length
элемент, связанный со строкой, это указывает на строковую длину в байтах. Строки также завершаются нулем.
Когда плагин аутентификации вызывается сервером, он должен интерпретировать MYSQL_SERVER_AUTH_INFO
элементы структуры следующим образом. Некоторые из них используются, чтобы установить значение функций SQL
или системных переменных в пределах клиентского сеанса, как обозначено.
user_name
: Имя пользователя передалось клиентом.
Значение становится USER()
значение функции.
user_name_length
: Длина user_name
в байтах.
auth_string
: Значение authentication_string
столбец mysql.user
строка таблицы для соответствующего имени учетной
записи (то есть, строка, которая соответствует клиентское имя пользователя и имя хоста и что
использование сервера, чтобы определить, как аутентифицировать клиент).
Предположите, что Вы создаете учетную запись, используя следующий оператор:
CREATE USER 'my_user'@'localhost' IDENTIFIED WITH my_plugin AS 'my_auth_string';
Когда my_user
соединяется от локального узла, сервер вызывает my_plugin
и передачи 'my_auth_string'
к
этому как auth_string
значение.
auth_string_length
: Длина auth_string
в байтах.
authenticated_as
: Сервер устанавливает это в имя
пользователя (значение user_name
). Плагин может изменить это, чтобы
указать, что у клиента должны быть полномочия различного пользователя. Например, если плагин
поддерживает пользователей прокси, начальное значение является именем соединяющегося (прокси)
пользователь, и плагин может изменить этот элемент на проксированное имя пользователя. Сервер тогда
обрабатывает пользователя прокси как наличие полномочий проксированного пользователя
(предполагающий, что другие условия для пользовательской поддержки прокси удовлетворяются; см. Раздел
23.2.4.9.4, "Реализовывая Пользовательскую Поддержку Прокси в Плагинах
Аутентификации"). Значение представляется как строка самое большее MYSQL_USER_NAME_LENGTH
байты долго, плюс завершающийся нуль. Значение
становится CURRENT_USER()
значение функции.
external_user
: Сервер устанавливает это в пустую
строку (завершенный нуль). Его значение становится external_user
системное значение переменной. Если плагин хочет,
чтобы у той системной переменной было различное значение, это должно установить этот элемент
соответственно; например, к соединяющемуся имени пользователя. Значение представляется как строка,
самое большее 511 байтов длиной плюс завершающийся нуль.
password_used
: Этот элемент применяется, когда
аутентификация перестала работать. Плагин может установить это или проигнорировать это. Значение
используется, чтобы создать сообщение об ошибке отказа Authentication fails.
Password used: %s
. Значение password_used
определяет как
%s
обрабатывается, как показано в следующей таблице.
password_used |
%s Обработка |
---|---|
0 | НЕТ |
1 | ДА |
2 | Будет нет %s |
host_or_ip
: Имя хоста клиента, если это может быть
разрешено, или IP-адрес иначе.
host_or_ip_length
: Длина host_or_ip
в байтах.
auth_simple
основная функция, auth_simple_server()
,
читает пароль (завершенная нулем строка) от клиента и успешно выполняется, если пароль непуст (первый байт
не нуль):
static int auth_simple_server (MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info){ unsigned char *pkt; int pkt_len; /* read the password as null-terminated string, fail on error */ if ((pkt_len= vio->read_packet(vio, &pkt)) < 0) return CR_ERROR; /* fail on empty password */ if (!pkt_len || *pkt == '\0') { info->password_used= PASSWORD_USED_NO; return CR_ERROR; } /* accept any nonempty password */ info->password_used= PASSWORD_USED_YES; return CR_OK;}
Основная функция должна возвратить один из кодов ошибки, показанных в следующей таблице.
Код ошибки | Значение |
---|---|
CR_OK |
Успех |
CR_OK_HANDSHAKE_COMPLETE |
Не отсылайте пакет состояния назад к клиенту |
CR_ERROR |
Ошибка |
CR_AUTH_USER_CREDENTIALS |
Отказ аутентификации |
CR_AUTH_HANDSHAKE |
Отказ обмена аутентификационными данными |
CR_AUTH_PLUGIN_ERROR |
Внутренняя сменная ошибка |
Для примера того, как квитирование работает, см. plugin/auth/dialog.c
исходный
файл.
Коды ошибки после CR_ERROR
доступны от MySQL 5.6.5. Сервер считает сменные
ошибки в Схеме Производительности host_cache
таблица, также доступная с MySQL 5.6.5.
auth_simple_server_main()
является настолько основным, что это не использует
информационную структуру аутентификации кроме установить элемент, который указывает, был ли пароль получен.
Плагин, который поддерживает пользователей прокси, должен возвратить серверу имя проксированного
пользователя (пользователь MySQL, права которого клиентский пользователь должен получить). Чтобы сделать
это, плагин должен установить info->authenticated_as
элемент к
проксированному имени пользователя. Для получения информации о проксировании см. Раздел
6.3.8, "Пользователи Прокси", и Раздел
23.2.4.9.4, "Реализовывая Пользовательскую Поддержку Прокси в Плагинах Аутентификации".
Объявите клиентский дескриптор плагина с mysql_declare_client_plugin()
и mysql_end_client_plugin
макросы (см. Раздел
23.2.4.2.3, "Клиентские Дескрипторы Плагина"). Для auth_simple
плагин, дескриптор похож на это:
mysql_declare_client_plugin(AUTHENTICATION) "auth_simple", /* plugin name */ "Author Name", /* author */ "Any-password authentication plugin", /* description */ {1,0,0}, /* version = 1.0.0 */ "GPL", /* license type */ NULL, /* for internal use */ NULL, /* no init function */ NULL, /* no deinit function */ NULL, /* no option-handling function */ auth_simple_client /* main function */mysql_end_client_plugin;
Элементы дескриптора, характерные для всех клиентских плагинов, являются сменным именем через обрабатывающую опцию функцию. После общих элементов у плагина аутентификации также есть один дополнительный элемент. Это - "основная" функция, которая обрабатывает передачу с сервером. Функция берет два параметра, представляющие структуру ввода-вывода и обработчик соединения. Для нашего простого плагина любого-пароля основная функция действительно только пишет в сервер пароль, обеспеченный пользователем:
static int auth_simple_client (MYSQL_PLUGIN_VIO *vio, MYSQL *mysql){ int res; /* send password as null-terminated string in clear text */ res= vio->write_packet(vio, (const unsigned char *) mysql->passwd, strlen(mysql->passwd) + 1); return res ? CR_ERROR : CR_OK;}
Основная функция должна возвратить один из кодов ошибки, показанных в следующей таблице.
Код ошибки | Значение |
---|---|
CR_OK |
Успех |
CR_OK_HANDSHAKE_COMPLETE |
Успех, сделанный клиент |
CR_ERROR |
Ошибка |
CR_OK_HANDSHAKE_COMPLETE
указывает, что клиент внес свой вклад успешно и считал
последний пакет. Клиентский плагин может возвратиться CR_OK_HANDSHAKE_COMPLETE
если число циклов обработки в протоколе аутентификации не известно заранее, и плагин должен считать другой
пакет, чтобы определить, заканчивается ли аутентификация.
Чтобы скомпилировать и установить сменный объектный файл библиотеки, см. инструкции в Разделе
23.2.4.3, "Компилируя и Устанавливая Сменные Библиотеки". Чтобы использовать файл библиотеки,
это должно быть установлено в сменном каталоге (каталог, названный plugin_dir
системная переменная).
Зарегистрируйте серверный плагин в сервере. Например, чтобы загрузить плагин при запуске сервера,
используйте a --plugin-load=auth_simple.so
опция (изменяют суффикс библиотеки по мере
необходимости для Вашей системы).
Создайте пользователя, для которого сервер будет использовать auth_simple
плагин для аутентификации:
mysql>CREATE USER 'x'@'localhost'
->IDENTIFIED WITH auth_simple;
Используйте клиентскую программу, чтобы соединиться с сервером как пользователь x
. Сторона сервера auth_simple
плагин связывается с
клиентской программой, что это должно использовать сторону клиента auth_simple
плагин, и последний отправляют пароль серверу. Плагин сервера должен отклонить соединения, которые
отправляют пустой пароль и принимают соединения, которые отправляют непустой пароль. Вызовите клиентскую
программу каждый способ проверить это:
shell>mysql --user=x --skip-password
ERROR 1045 (28000): Access denied for user 'x'@'localhost' (using password: NO)shell>mysql --user=x --password=abc
mysql>
Поскольку плагин сервера принимает любой непустой пароль, это нужно считать небезопасным. После тестирования
плагина, чтобы проверить, что это работает, перезапустите сервер без --plugin-load
опция, чтобы не к indavertently оставляют сервер, работающий
с небезопасным плагином аутентификации загруженным. Кроме того, отбросьте пользователя с DROP USER 'x'@'localhost'
.
Для дополнительной информации о загрузке и использовании плагинов аутентификации, см. Раздел 5.1.8.1, "Устанавливая и Удаляя Плагины", и Раздел 6.3.7, "Сменная Аутентификация".
Если Вы пишете клиентскую программу, которая поддерживает использование плагинов аутентификации, обычно
такая программа заставляет плагин быть загруженным, вызывая mysql_options()
установить MYSQL_DEFAULT_AUTH
и MYSQL_PLUGIN_DIR
опции:
char *plugin_dir = "path_to_plugin_dir
";char *default_auth = "plugin_name
";/* ... process command-line options ... */mysql_options(&mysql, MYSQL_PLUGIN_DIR, plugin_dir);mysql_options(&mysql, MYSQL_DEFAULT_AUTH, default_auth);
Как правило, программа также примет --plugin-dir
и --default-auth
опции, которые позволяют пользователям переопределить значения по умолчанию.
Если клиентская программа требует сменного управления низшего уровня, клиентская библиотека содержит
функции, которые берут st_mysql_client_plugin
параметр. См. Раздел
22.8.14, "Клиентские Функции Плагина API C".
Одна из возможностей, которые сменная аутентификация делает возможным, является пользователями прокси (см. Раздел 6.3.8, "Пользователи Прокси"). Для серверного плагина аутентификации, чтобы участвовать в пользовательской поддержке прокси, должны быть удовлетворены эти условия:
Когда соединяющийся клиент должен быть обработан как пользователь прокси,
плагин должен возвратить другое имя в authenticated_as
элемент MYSQL_SERVER_AUTH_INFO
структура, чтобы указать на проксированное имя
пользователя. Это может также дополнительно установить external_user
элемент, чтобы установить значение external_user
системная переменная.
Учетные записи пользователей прокси должны быть установлены, чтобы
аутентифицироваться плагином. Используйте CREATE USER
или GRANT
оператор, чтобы связать учетные записи с плагинами.
Учетные записи пользователей прокси должны иметь PROXY
полномочие для проксированных учетных записей. Используйте GRANT
оператор, чтобы предоставить это полномочие.
Другими словами единственный аспект пользовательской поддержки прокси, требуемой плагина, - то, что это
установило authenticated_as
к проксированному имени пользователя. Остальное
является дополнительным (установка external_user
) или сделанный DBA, используя
SQL-операторы.
Как плагин аутентификации определяет, который проксировал пользователя, чтобы возвратиться, когда
пользователь прокси соединяется? Это зависит от плагина. Как правило, плагин отображает клиенты на
проксированных пользователей, основанных на строке аутентификации, которую передает к этому сервер. Эта
строка прибывает из AS
часть IDENTIFIED WITH
пункт
CREATE USER
оператор, который определяет использование плагина для
аутентификации.
Сменный разработчик определяет правила синтаксиса для строки аутентификации и реализует плагин согласно тем правилам. Предположите, что плагин берет список разделенных запятой значений пар, которые отображают внешних пользователей на пользователей MySQL. Например:
CREATE USER ''@'%.example.com' IDENTIFIED WITH my_plugin AS 'extuser1=mysqlusera, extuser2=mysqluserb'CREATE USER ''@'%.example.org' IDENTIFIED WITH my_plugin AS 'extuser1=mysqluserc, extuser2=mysqluserd'
Когда сервер вызывает плагин, чтобы аутентифицировать клиент, он передает соответствующую строку аутентификации к плагину. Плагин ответственен:
Проанализируйте строку в ее компоненты, чтобы определить отображение на использование
Сравните клиентское имя пользователя с отображением
Возвратите надлежащее имя пользователя MySQL
Например, если extuser2
соединяется от example.com
узел, передачи сервера 'extuser1=mysqlusera, extuser2=mysqluserb'
к плагину, и
плагину должен скопировать mysqluserb
в authenticated_as
, с завершающимся нулевым байтом. Если extuser2
соединяется от example.org
узел, передачи сервера 'extuser1=mysqluserc,
extuser2=mysqluserd'
, и плагин должен скопировать mysqluserd
вместо
этого.
Если там не идет ни в какое сравнение в отображении, действие зависит от плагина. Если соответствие будет
требоваться, то плагин, вероятно, возвратит ошибку. Или плагин мог бы просто возвратить имя клиента; в этом
случае это не должно измениться authenticated_as
, и сервер не будет
обрабатывать клиент как прокси.
Следующий пример демонстрирует, как обработать пользователей прокси, использующих названный плагин auth_simple_proxy
. Как auth_simple
плагин, описанный
ранее, auth_simple_proxy
принимает любой непустой пароль как допустимый (и
таким образом не должен использоваться в продуктивных средах). Кроме того, это исследует auth_string
строковый элемент аутентификации и использование эти очень
простые правила для того, чтобы интерпретировать это:
Если строка пуста, плагин возвращает имя пользователя как дано, и никакое
проксирование не происходит. Таким образом, сменные листы значение authenticated_as
неизменный.
Если строка непуста, плагин обрабатывает ее как имя проксированного
пользователя и копирует ее в authenticated_as
так, чтобы проксирование
произошло.
Для того, чтобы протестировать, устанавливает одну учетную запись, которая не проксируется согласно
предыдущим правилам, и тому, который является. Это означает, что одна учетная запись имеет нет AS
пункт, и каждый включает AS
пункт, который
называет проксированного пользователя:
CREATE USER 'plugin_user1'@'localhost' IDENTIFIED WITH auth_simple_proxy;CREATE USER 'plugin_user2'@'localhost' IDENTIFIED WITH auth_simple_proxy AS 'proxied_user';
Кроме того, создайте учетную запись за проксированного пользователя и предоставление plugin_user2
PROXY
полномочие для этого:
CREATE USER 'proxied_user'@'localhost' IDENTIFIED BY 'proxied_user_pass';GRANT PROXY ON 'proxied_user'@'localhost' TO 'plugin_user2'@'localhost';
Прежде, чем сервер вызывает плагин аутентификации, он устанавливает authenticated_as
к клиентскому имени пользователя. Чтобы указать, что
пользователь является прокси, плагин должен установить authenticated_as
к
проксированному имени пользователя. Для auth_simple_proxy
, это означает, что
должно исследовать auth_string
значение, и, если значение непусто, копирует его
в authenticated_as
элемент, чтобы возвратить это как имя проксированного
пользователя. Кроме того, когда проксирование происходит, плагин устанавливает external_user
элемент к клиентскому имени пользователя; это становится значением external_user
системная переменная.
static int auth_simple_proxy_server (MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info){ unsigned char *pkt; int pkt_len; /* read the password as null-terminated string, fail on error */ if ((pkt_len= vio->read_packet(vio, &pkt)) < 0) return CR_ERROR; /* fail on empty password */ if (!pkt_len || *pkt == '\0') { info->password_used= PASSWORD_USED_NO; return CR_ERROR; } /* accept any nonempty password */ info->password_used= PASSWORD_USED_YES; /* if authentication string is nonempty, use as proxied user name */ /* and use client name as external_user value */ if (info->auth_string_length > 0) { strcpy (info->authenticated_as, info->auth_string); strcpy (info->external_user, info->user_name); } return CR_OK;}
После успешного соединения, USER()
функция должна указать на соединяющееся клиентское имя пользователя и
имя хоста, и CURRENT_USER()
должен указать на учетную запись, полномочия которой применяются во время сеанса. Последнее значение должно
быть соединяющейся учетной записью пользователя, если никакое проксирование не происходит или проксированная
учетная запись, если проксирование действительно происходит.
Скомпилируйте и установите плагин, затем протестируйте его. Во-первых, соединитесь как plugin_user1
:
shell> mysql --user=plugin_user1
--password=x
В этом случае не должно быть никакого проксирования:
mysql> SELECT USER(), CURRENT_USER(),
@@proxy_user, @@external_user\G
*************************** 1. row *************************** USER(): plugin_user1@localhost CURRENT_USER(): plugin_user1@localhost @@proxy_user: NULL@@external_user: NULL
Затем соединитесь как plugin_user2
:
shell> mysql --user=plugin_user2
--password=x
В этом случае, plugin_user2
должен быть проксирован к proxied_user
:
mysql> SELECT USER(), CURRENT_USER(),
@@proxy_user, @@external_user\G
*************************** 1. row *************************** USER(): plugin_user2@localhost CURRENT_USER(): proxied_user@localhost @@proxy_user: 'plugin_user2'@'localhost'@@external_user: 'plugin_user2'@'localhost'