diff options
Diffstat (limited to 'plugin/auth_examples')
-rw-r--r-- | plugin/auth_examples/CMakeLists.txt | 36 | ||||
-rw-r--r-- | plugin/auth_examples/auth_0x0100.c | 91 | ||||
-rw-r--r-- | plugin/auth_examples/clear_password_client.c | 47 | ||||
-rw-r--r-- | plugin/auth_examples/dialog_examples.c | 158 | ||||
-rw-r--r-- | plugin/auth_examples/qa_auth_client.c | 117 | ||||
-rw-r--r-- | plugin/auth_examples/qa_auth_interface.c | 254 | ||||
-rw-r--r-- | plugin/auth_examples/qa_auth_server.c | 79 | ||||
-rw-r--r-- | plugin/auth_examples/test_plugin.c | 234 |
8 files changed, 1016 insertions, 0 deletions
diff --git a/plugin/auth_examples/CMakeLists.txt b/plugin/auth_examples/CMakeLists.txt new file mode 100644 index 00000000..0efd8348 --- /dev/null +++ b/plugin/auth_examples/CMakeLists.txt @@ -0,0 +1,36 @@ +# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; version 2 of the +# License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA + +MYSQL_ADD_PLUGIN(dialog_examples dialog_examples.c + MODULE_ONLY COMPONENT Test) +MYSQL_ADD_PLUGIN(auth_test_plugin test_plugin.c + MODULE_ONLY COMPONENT Test) +MYSQL_ADD_PLUGIN(qa_auth_interface qa_auth_interface.c + MODULE_ONLY COMPONENT Test) + +MYSQL_ADD_PLUGIN(qa_auth_server qa_auth_server.c + MODULE_ONLY COMPONENT Test) + +MYSQL_ADD_PLUGIN(qa_auth_client qa_auth_client.c + MODULE_ONLY COMPONENT Test) + +MYSQL_ADD_PLUGIN(auth_0x0100 auth_0x0100.c MODULE_ONLY COMPONENT Test) + +# disabled in favor of +# libmariadb/plugins/auth/mariadb_cleartext.c +# +#MYSQL_ADD_PLUGIN(mysql_clear_password clear_password_client.c +# MODULE_ONLY CLIENT COMPONENT ClientPlugins) diff --git a/plugin/auth_examples/auth_0x0100.c b/plugin/auth_examples/auth_0x0100.c new file mode 100644 index 00000000..e23f495f --- /dev/null +++ b/plugin/auth_examples/auth_0x0100.c @@ -0,0 +1,91 @@ +/* Copyright (C) 2013 Sergei Golubchik and Monty Program Ab + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; version 2 of the + License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + + auth plugin that uses old structures as of + MYSQL_AUTHENTICATION_INTERFACE_VERSION 0x0100 + + To test the old version support. + It intentionally uses no constants like CR_OK ok PASSWORD_USED_YES. +*/ + +#include <mysql/plugin.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> + +#if 0 +#include <mysql/plugin_auth.h> +#else +#define MYSQL_AUTHENTICATION_INTERFACE_VERSION 0x0100 +typedef void MYSQL_PLUGIN_VIO; /* we don't use it here */ + +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[49]; + char external_user[512]; + int password_used; + const char *host_or_ip; + unsigned int host_or_ip_length; +} MYSQL_SERVER_AUTH_INFO; + +struct st_mysql_auth +{ + int interface_version; + const char *client_auth_plugin; + int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info); +}; +#endif + +static int do_auth_0x0100(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info) +{ + info->password_used= 1; + strcpy(info->authenticated_as, "zzzzzzzzzzzzzzzz"); + memset(info->external_user, 'o', 510); + info->external_user[510]='.'; + info->external_user[511]=0; + return vio ? -1 : 0; /* use vio to avoid the 'unused' warning */ +} + +static struct st_mysql_auth auth_0x0100_struct= +{ + MYSQL_AUTHENTICATION_INTERFACE_VERSION, 0, do_auth_0x0100 +}; + +maria_declare_plugin(auth_0x0100) +{ + MYSQL_AUTHENTICATION_PLUGIN, + &auth_0x0100_struct, + "auth_0x0100", + "Sergei Golubchik", + "Test for API 0x0100 support", + PLUGIN_LICENSE_GPL, + NULL, + NULL, + 0x0100, + NULL, + NULL, + "1.0", + MariaDB_PLUGIN_MATURITY_EXPERIMENTAL, +} +maria_declare_plugin_end; + diff --git a/plugin/auth_examples/clear_password_client.c b/plugin/auth_examples/clear_password_client.c new file mode 100644 index 00000000..726d200d --- /dev/null +++ b/plugin/auth_examples/clear_password_client.c @@ -0,0 +1,47 @@ +/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ + +#include <mysql/client_plugin.h> +#include <mysql.h> +#include <string.h> + +/** + The main function of the mysql_clear_password authentication plugin. +*/ + +static int clear_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql) +{ + int res; + + /* send password in clear text */ + res= vio->write_packet(vio, (const unsigned char *) mysql->passwd, + strlen(mysql->passwd) + 1); + + return res ? CR_ERROR : CR_OK; +} + +mysql_declare_client_plugin(AUTHENTICATION) + "mysql_clear_password", + "Georgi Kodinov", + "Clear password authentication plugin", + {0,1,0}, + "GPL", + NULL, + NULL, + NULL, + NULL, + clear_password_auth_client +mysql_end_client_plugin; + diff --git a/plugin/auth_examples/dialog_examples.c b/plugin/auth_examples/dialog_examples.c new file mode 100644 index 00000000..834c028c --- /dev/null +++ b/plugin/auth_examples/dialog_examples.c @@ -0,0 +1,158 @@ +/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab + Copyright (c) 2010, 2011, Oracle and/or its affiliates. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; version 2 of the + License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + + examples for dialog client authentication plugin + + Two examples are provided: two_questions server plugin, that asks + the password and an "Are you sure?" question with a reply "yes, of course". + It demonstrates the usage of "password" (input is hidden) and "ordinary" + (input can be echoed) questions, and how to mark the last question, + to avoid an extra roundtrip. + + And three_attempts plugin that gives the user three attempts to enter + a correct password. It shows the situation when a number of questions + is not known in advance. +*/ + +#include <mysql/plugin_auth.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <mysql/auth_dialog_client.h> + +/********************* SERVER SIDE ****************************************/ + +/** + dialog demo with two questions, one password and one, the last, ordinary. +*/ +static int two_questions(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info) +{ + unsigned char *pkt; + int pkt_len; + + /* send a password question */ + if (vio->write_packet(vio, + (const unsigned char *) PASSWORD_QUESTION "Password, please:", + 18)) + return CR_ERROR; + + /* read the answer */ + if ((pkt_len= vio->read_packet(vio, &pkt)) < 0) + return CR_ERROR; + + info->password_used= PASSWORD_USED_YES; + + /* fail if the password is wrong */ + if (strcmp((const char *) pkt, info->auth_string)) + return CR_ERROR; + + /* send the last, ordinary, question */ + if (vio->write_packet(vio, + (const unsigned char *) LAST_QUESTION "Are you sure ?", + 15)) + return CR_ERROR; + + /* read the answer */ + if ((pkt_len= vio->read_packet(vio, &pkt)) < 0) + return CR_ERROR; + + /* check the reply */ + return strcmp((const char *) pkt, "yes, of course") ? CR_ERROR : CR_OK; +} + +static struct st_mysql_auth two_handler= +{ + MYSQL_AUTHENTICATION_INTERFACE_VERSION, + "dialog", /* requires dialog client plugin */ + two_questions, + NULL, NULL /* no PASSWORD() */ +}; + +/* dialog demo where the number of questions is not known in advance */ +static int three_attempts(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info) +{ + unsigned char *pkt; + int pkt_len, i; + + for (i= 0; i < 3; i++) + { + /* send the prompt */ + if (vio->write_packet(vio, + (const unsigned char *) PASSWORD_QUESTION "Password, please:", 18)) + return CR_ERROR; + + /* read the password */ + if ((pkt_len= vio->read_packet(vio, &pkt)) < 0) + return CR_ERROR; + + info->password_used= PASSWORD_USED_YES; + + /* + finish, if the password is correct. + note, that we did not mark the prompt packet as "last" + */ + if (strcmp((const char *) pkt, info->auth_string) == 0) + return CR_OK; + } + + return CR_ERROR; +} + +static struct st_mysql_auth three_handler= +{ + MYSQL_AUTHENTICATION_INTERFACE_VERSION, + "dialog", /* requires dialog client plugin */ + three_attempts, + NULL, NULL /* no PASSWORD() */ +}; + +mysql_declare_plugin(dialog) +{ + MYSQL_AUTHENTICATION_PLUGIN, + &two_handler, + "two_questions", + "Sergei Golubchik", + "Dialog plugin demo 1", + PLUGIN_LICENSE_GPL, + NULL, + NULL, + 0x0100, + NULL, + NULL, + NULL, + 0, +}, +{ + MYSQL_AUTHENTICATION_PLUGIN, + &three_handler, + "three_attempts", + "Sergei Golubchik", + "Dialog plugin demo 2", + PLUGIN_LICENSE_GPL, + NULL, + NULL, + 0x0100, + NULL, + NULL, + NULL, + 0, +} +mysql_declare_plugin_end; + diff --git a/plugin/auth_examples/qa_auth_client.c b/plugin/auth_examples/qa_auth_client.c new file mode 100644 index 00000000..a915306e --- /dev/null +++ b/plugin/auth_examples/qa_auth_client.c @@ -0,0 +1,117 @@ +/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; version 2 of the + License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#include <my_global.h> +#include <mysql/plugin_auth.h> +#include <mysql/client_plugin.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> + +/********************* CLIENT SIDE ***************************************/ +/* + client plugin used for testing the plugin API +*/ +#include <mysql.h> + +/** + The main function of the test plugin. + + Reads the prompt, check if the handshake is done and if the prompt is a + password request and returns the password. Otherwise return error. + + @note + 1. this plugin shows how a client authentication plugin + may read a MySQL protocol OK packet internally - which is important + where a number of packets is not known in advance. + 2. the first byte of the prompt is special. it is not + shown to the user, but signals whether it is the last question + (prompt[0] & 1 == 1) or not last (prompt[0] & 1 == 0), + and whether the input is a password (not echoed). + 3. the prompt is expected to be sent zero-terminated +*/ +static int test_plugin_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql) +{ + unsigned char *pkt, cmd= 0; + int pkt_len, res; + char *reply; + + do + { + /* read the prompt */ + pkt_len= vio->read_packet(vio, &pkt); + if (pkt_len < 0) + return CR_ERROR; + + if (pkt == 0) + { + /* + in mysql_change_user() the client sends the first packet, so + the first vio->read_packet() does nothing (pkt == 0). + + We send the "password", assuming the client knows what its doing. + (in other words, the dialog plugin should be only set as a default + authentication plugin on the client if the first question + asks for a password - which will be sent in cleat text, by the way) + */ + reply= mysql->passwd; + } + else + { + cmd= *pkt++; + + /* is it MySQL protocol (0=OK or 254=need old password) packet ? */ + if (cmd == 0 || cmd == 254) + return CR_OK_HANDSHAKE_COMPLETE; /* yes. we're done */ + + /* + asking for a password with an empty prompt means mysql->password + otherwise return an error + */ + if ((cmd == LAST_PASSWORD[0] || cmd == PASSWORD_QUESTION[0]) && *pkt == 0) + reply= mysql->passwd; + else + return CR_ERROR; + } + if (!reply) + return CR_ERROR; + /* send the reply to the server */ + res= vio->write_packet(vio, (const unsigned char *) reply, + (int)strlen(reply) + 1); + + if (res) + return CR_ERROR; + + /* repeat unless it was the last question */ + } while (cmd != LAST_QUESTION[0] && cmd != PASSWORD_QUESTION[0]); + + /* the job of reading the ok/error packet is left to the server */ + return CR_OK; +} + + +mysql_declare_client_plugin(AUTHENTICATION) + "qa_auth_client", + "Horst Hunger", + "Dialog Client Authentication Plugin", + {0,1,0}, + "GPL", + NULL, + NULL, + NULL, + NULL, + test_plugin_client +mysql_end_client_plugin; diff --git a/plugin/auth_examples/qa_auth_interface.c b/plugin/auth_examples/qa_auth_interface.c new file mode 100644 index 00000000..ad1f6fff --- /dev/null +++ b/plugin/auth_examples/qa_auth_interface.c @@ -0,0 +1,254 @@ +/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; version 2 of the + License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#include <my_global.h> +#include <mysql/plugin_auth.h> +#include <mysql/client_plugin.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> + +/********************* SERVER SIDE ****************************************/ + +static int qa_auth_interface (MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info) +{ + unsigned char *pkt; + int pkt_len, err= CR_OK; + + /* send a password question */ + if (vio->write_packet(vio, (const unsigned char *) PASSWORD_QUESTION, 1)) + return CR_ERROR; + + /* read the answer */ + if ((pkt_len= vio->read_packet(vio, &pkt)) < 0) + return CR_ERROR; + + info->password_used= PASSWORD_USED_YES; + + /* fail if the password is wrong */ + if (strcmp((const char *) pkt, info->auth_string)) + return CR_ERROR; + +/* Check the contens of components of info */ + if (strcmp(info->user_name, "qa_test_1_user")== 0) + { + if (info->user_name_length != 14) + err= CR_ERROR; + if (strcmp(info->auth_string, "qa_test_1_dest")) + err= CR_ERROR; + if (info->auth_string_length != 14) + err= CR_ERROR; +/* To be set by the plugin */ +/* if (strcmp(info->authenticated_as, "qa_test_1_user")) */ +/* err= CR_ERROR; */ +/* To be set by the plugin */ +/* if (strcmp(info->external_user, "")) */ +/* err= CR_ERROR; */ + if (info->password_used != PASSWORD_USED_YES) + err= CR_ERROR; + if (strcmp(info->host_or_ip, "localhost")) + err= CR_ERROR; + if (info->host_or_ip_length != 9) + err= CR_ERROR; + } +/* Assign values to the components of info even if not intended and watch the effect */ + else if (strcmp(info->user_name, "qa_test_2_user")== 0) + { + /* Overwriting not intended, but with effect on USER() */ + strcpy((char*) info->user_name, "user_name"); + info->user_name_length= 9; + /* Overwriting not intended, effect not visible */ + strcpy((char *)info->auth_string, "auth_string"); + info->auth_string_length= 11; + /* Assign with account for authorization, effect on CURRENT_USER() */ + strcpy(info->authenticated_as, "authenticated_as"); + /* Assign with an external account, effect on @@local.EXTERNAL_USER */ + strcpy(info->external_user, "externaluser"); + /* Overwriting will cause a core dump */ +/* strcpy(info->host_or_ip, "host_or_ip"); */ +/* info->host_or_ip_length= 10; */ + } +/* Invalid, means too high values for length */ + else if (strcmp(info->user_name, "qa_test_3_user")== 0) + { +/* Original value is 14. Test runs also with higher value. Changes have no effect.*/ + info->user_name_length= 28; + strcpy((char *)info->auth_string, "qa_test_3_dest"); +/* Original value is 14. Test runs also with higher value. Changes have no effect.*/ + info->auth_string_length= 28; + strcpy(info->authenticated_as, info->auth_string); + strcpy(info->external_user, info->auth_string); + } +/* Invalid, means too low values for length */ + else if (strcmp(info->user_name, "qa_test_4_user")== 0) + { +/* Original value is 14. Test runs also with lower value. Changes have no effect.*/ + info->user_name_length= 8; + strcpy((char *)info->auth_string, "qa_test_4_dest"); +/* Original value is 14. Test runs also with lower value. Changes have no effect.*/ + info->auth_string_length= 8; + strcpy(info->authenticated_as, info->auth_string); + strcpy(info->external_user, info->auth_string); + } +/* Overwrite with empty values */ + else if (strcmp(info->user_name, "qa_test_5_user")== 0) + { +/* This assignment has no effect.*/ + strcpy((char*) info->user_name, ""); + info->user_name_length= 0; +/* This assignment has no effect.*/ + strcpy((char *)info->auth_string, ""); + info->auth_string_length= 0; +/* This assignment caused an error or an "empty" user */ + strcpy(info->authenticated_as, ""); +/* This assignment has no effect.*/ + strcpy(info->external_user, ""); + /* Overwriting will cause a core dump */ +/* strcpy(info->host_or_ip, ""); */ +/* info->host_or_ip_length= 0; */ + } +/* Set to 'root' */ + else if (strcmp(info->user_name, "qa_test_6_user")== 0) + { + strcpy(info->authenticated_as, "root"); + } + else + { + err= CR_ERROR; + } + return err; +} + +static struct st_mysql_auth qa_auth_test_handler= +{ + MYSQL_AUTHENTICATION_INTERFACE_VERSION, + "qa_auth_interface", /* requires test_plugin client's plugin */ + qa_auth_interface, + NULL, NULL /* no PASSWORD() */ +}; + +mysql_declare_plugin(test_plugin) +{ + MYSQL_AUTHENTICATION_PLUGIN, + &qa_auth_test_handler, + "qa_auth_interface", + "Horst Hunger", + "plugin API test plugin", + PLUGIN_LICENSE_GPL, + NULL, + NULL, + 0x0100, + NULL, + NULL, + NULL, + 0, +} +mysql_declare_plugin_end; + +/********************* CLIENT SIDE ***************************************/ +/* + client plugin used for testing the plugin API +*/ +#include <mysql.h> + +/** + The main function of the test plugin. + + Reads the prompt, check if the handshake is done and if the prompt is a + password request and returns the password. Otherwise return error. + + @note + 1. this plugin shows how a client authentication plugin + may read a MySQL protocol OK packet internally - which is important + where a number of packets is not known in advance. + 2. the first byte of the prompt is special. it is not + shown to the user, but signals whether it is the last question + (prompt[0] & 1 == 1) or not last (prompt[0] & 1 == 0), + and whether the input is a password (not echoed). + 3. the prompt is expected to be sent zero-terminated +*/ +static int test_plugin_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql) +{ + unsigned char *pkt, cmd= 0; + int pkt_len, res; + char *reply; + + do + { + /* read the prompt */ + pkt_len= vio->read_packet(vio, &pkt); + if (pkt_len < 0) + return CR_ERROR; + + if (pkt == 0) + { + /* + in mysql_change_user() the client sends the first packet, so + the first vio->read_packet() does nothing (pkt == 0). + + We send the "password", assuming the client knows what its doing. + (in other words, the dialog plugin should be only set as a default + authentication plugin on the client if the first question + asks for a password - which will be sent in cleat text, by the way) + */ + reply= mysql->passwd; + } + else + { + cmd= *pkt++; + + /* is it MySQL protocol (0=OK or 254=need old password) packet ? */ + if (cmd == 0 || cmd == 254) + return CR_OK_HANDSHAKE_COMPLETE; /* yes. we're done */ + + /* + asking for a password with an empty prompt means mysql->password + otherwise return an error + */ + if ((cmd == LAST_PASSWORD[0] || cmd == PASSWORD_QUESTION[0]) && *pkt == 0) + reply= mysql->passwd; + else + return CR_ERROR; + } + if (!reply) + return CR_ERROR; + /* send the reply to the server */ + res= vio->write_packet(vio, (const unsigned char *) reply, + (int)strlen(reply) + 1); + + if (res) + return CR_ERROR; + + /* repeat unless it was the last question */ + } while (cmd != LAST_QUESTION[0] && cmd != PASSWORD_QUESTION[0]); + + /* the job of reading the ok/error packet is left to the server */ + return CR_OK; +} + + +mysql_declare_client_plugin(AUTHENTICATION) + "qa_auth_interface", + "Horst Hunger", + "Dialog Client Authentication Plugin", + {0,1,0}, + "GPL", + NULL, + NULL, + NULL, + NULL, + test_plugin_client +mysql_end_client_plugin; diff --git a/plugin/auth_examples/qa_auth_server.c b/plugin/auth_examples/qa_auth_server.c new file mode 100644 index 00000000..67b29d26 --- /dev/null +++ b/plugin/auth_examples/qa_auth_server.c @@ -0,0 +1,79 @@ +/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; version 2 of the + License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +#include <my_global.h> +#include <mysql/plugin_auth.h> +#include <mysql/client_plugin.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> + +/********************* SERVER SIDE ****************************************/ + +static int qa_auth_interface (MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info) +{ + unsigned char *pkt; + int pkt_len, err= CR_OK; + + /* send a password question */ + if (vio->write_packet(vio, (const unsigned char *) PASSWORD_QUESTION, 1)) + return CR_ERROR; + + /* read the answer */ + if ((pkt_len= vio->read_packet(vio, &pkt)) < 0) + return CR_ERROR; + + info->password_used= PASSWORD_USED_YES; + + /* fail if the password is wrong */ + if (strcmp((const char *) pkt, info->auth_string)) + return CR_ERROR; + +/* Test of default_auth */ + if (strcmp(info->user_name, "qa_test_11_user")== 0) + { + strcpy(info->authenticated_as, "qa_test_11_dest"); + } + else + err= CR_ERROR; + return err; +} + +static struct st_mysql_auth qa_auth_test_handler= +{ + MYSQL_AUTHENTICATION_INTERFACE_VERSION, + "qa_auth_interface", /* requires test_plugin client's plugin */ + qa_auth_interface, + NULL, NULL /* no PASSWORD() */ +}; + +mysql_declare_plugin(test_plugin) +{ + MYSQL_AUTHENTICATION_PLUGIN, + &qa_auth_test_handler, + "qa_auth_server", + "Horst Hunger", + "plugin API test plugin", + PLUGIN_LICENSE_GPL, + NULL, + NULL, + 0x0100, + NULL, + NULL, + NULL, + 0, +} +mysql_declare_plugin_end; diff --git a/plugin/auth_examples/test_plugin.c b/plugin/auth_examples/test_plugin.c new file mode 100644 index 00000000..04405a1c --- /dev/null +++ b/plugin/auth_examples/test_plugin.c @@ -0,0 +1,234 @@ +/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; version 2 of the + License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ + +/** + @file + + Test driver for the mysql-test/t/plugin_auth.test + + This is a set of test plugins used to test the external authentication + implementation. + See the above test file for more details. + This test plugin is based on the dialog plugin example. +*/ + +#include <my_global.h> +#include <mysql/plugin_auth.h> +#include <mysql/client_plugin.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> + +/********************* SERVER SIDE ****************************************/ + +/** + dialog test plugin mimicking the ordinary auth mechanism. Used to test the auth plugin API +*/ +static int auth_test_plugin(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info) +{ + unsigned char *pkt; + int pkt_len; + + /* send a password question */ + if (vio->write_packet(vio, (const unsigned char *) PASSWORD_QUESTION, 1)) + return CR_ERROR; + + /* read the answer */ + if ((pkt_len= vio->read_packet(vio, &pkt)) < 0) + return CR_ERROR; + + info->password_used= PASSWORD_USED_YES; + + /* fail if the password is wrong */ + if (strcmp((const char *) pkt, info->auth_string)) + return CR_ERROR; + + /* copy auth string as a destination name to check it */ + strcpy (info->authenticated_as, info->auth_string); + + /* copy something into the external user name */ + strcpy (info->external_user, info->auth_string); + + return CR_OK; +} + +static struct st_mysql_auth auth_test_handler= +{ + MYSQL_AUTHENTICATION_INTERFACE_VERSION, + "auth_test_plugin", /* requires test_plugin client's plugin */ + auth_test_plugin, + NULL, NULL /* no PASSWORD() */ +}; + +/** + dialog test plugin mimicking the ordinary auth mechanism. Used to test the clear text plugin API +*/ +static int auth_cleartext_plugin(MYSQL_PLUGIN_VIO *vio, + MYSQL_SERVER_AUTH_INFO *info) +{ + unsigned char *pkt; + int pkt_len; + + /* read the password */ + if ((pkt_len= vio->read_packet(vio, &pkt)) < 0) + return CR_ERROR; + + info->password_used= PASSWORD_USED_YES; + + /* fail if the password is wrong */ + if (strcmp((const char *) pkt, info->auth_string)) + return CR_ERROR; + + return CR_OK; +} + + +static struct st_mysql_auth auth_cleartext_handler= +{ + MYSQL_AUTHENTICATION_INTERFACE_VERSION, + "mysql_clear_password", /* requires the clear text plugin */ + auth_cleartext_plugin, + NULL, NULL /* no PASSWORD() */ +}; + +mysql_declare_plugin(test_plugin) +{ + MYSQL_AUTHENTICATION_PLUGIN, + &auth_test_handler, + "test_plugin_server", + "Georgi Kodinov", + "plugin API test plugin", + PLUGIN_LICENSE_GPL, + NULL, + NULL, + 0x0100, + NULL, + NULL, + NULL, + 0, +}, +{ + MYSQL_AUTHENTICATION_PLUGIN, + &auth_cleartext_handler, + "cleartext_plugin_server", + "Georgi Kodinov", + "cleartext plugin API test plugin", + PLUGIN_LICENSE_GPL, + NULL, + NULL, + 0x0100, + NULL, + NULL, + NULL, + 0, +} +mysql_declare_plugin_end; + + +/********************* CLIENT SIDE ***************************************/ +/* + client plugin used for testing the plugin API +*/ +#include <mysql.h> + +/** + The main function of the test plugin. + + Reads the prompt, check if the handshake is done and if the prompt is a + password request and returns the password. Otherwise return error. + + @note + 1. this plugin shows how a client authentication plugin + may read a MySQL protocol OK packet internally - which is important + where a number of packets is not known in advance. + 2. the first byte of the prompt is special. it is not + shown to the user, but signals whether it is the last question + (prompt[0] & 1 == 1) or not last (prompt[0] & 1 == 0), + and whether the input is a password (not echoed). + 3. the prompt is expected to be sent zero-terminated +*/ +static int test_plugin_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql) +{ + unsigned char *pkt, cmd= 0; + int pkt_len, res; + char *reply; + + do + { + /* read the prompt */ + pkt_len= vio->read_packet(vio, &pkt); + if (pkt_len < 0) + return CR_ERROR; + + if (pkt == 0) + { + /* + in mysql_change_user() the client sends the first packet, so + the first vio->read_packet() does nothing (pkt == 0). + + We send the "password", assuming the client knows what it's doing. + (in other words, the dialog plugin should be only set as a default + authentication plugin on the client if the first question + asks for a password - which will be sent in clear text, by the way) + */ + reply= mysql->passwd; + } + else + { + cmd= *pkt++; + + /* is it MySQL protocol (0=OK or 254=need old password) packet ? */ + if (cmd == 0 || cmd == 254) + return CR_OK_HANDSHAKE_COMPLETE; /* yes. we're done */ + + /* + asking for a password with an empty prompt means mysql->password + otherwise return an error + */ + if ((cmd == LAST_PASSWORD[0] || cmd == PASSWORD_QUESTION[0]) && *pkt == 0) + reply= mysql->passwd; + else + return CR_ERROR; + } + if (!reply) + return CR_ERROR; + /* send the reply to the server */ + res= vio->write_packet(vio, (const unsigned char *) reply, + (int)strlen(reply) + 1); + + if (res) + return CR_ERROR; + + /* repeat unless it was the last question */ + } while (cmd != LAST_QUESTION[0] && cmd != PASSWORD_QUESTION[0]); + + /* the job of reading the ok/error packet is left to the server */ + return CR_OK; +} + + +mysql_declare_client_plugin(AUTHENTICATION) + "auth_test_plugin", + "Georgi Kodinov", + "Dialog Client Authentication Plugin", + {0,1,0}, + "GPL", + NULL, + NULL, + NULL, + NULL, + test_plugin_client +mysql_end_client_plugin; |