diff options
Diffstat (limited to 'plugin')
-rw-r--r-- | plugin/auth/Makefile.am | 15 | ||||
-rw-r--r-- | plugin/auth/auth_socket.c | 119 | ||||
-rw-r--r-- | plugin/auth/dialog.c | 349 | ||||
-rw-r--r-- | plugin/auth/plug.in | 15 | ||||
-rw-r--r-- | plugin/daemon_example/Makefile.am | 2 | ||||
-rw-r--r-- | plugin/daemon_example/daemon_example.cc | 17 | ||||
-rw-r--r-- | plugin/feedback/Makefile.am | 2 | ||||
-rw-r--r-- | plugin/feedback/feedback.cc | 20 | ||||
-rw-r--r-- | plugin/feedback/sender_thread.cc | 2 | ||||
-rw-r--r-- | plugin/fulltext/plugin_example.c | 18 |
10 files changed, 555 insertions, 4 deletions
diff --git a/plugin/auth/Makefile.am b/plugin/auth/Makefile.am new file mode 100644 index 00000000000..acca98e26f8 --- /dev/null +++ b/plugin/auth/Makefile.am @@ -0,0 +1,15 @@ +pkgplugindir=$(pkglibdir)/plugin + +AM_LDFLAGS=-module -rpath $(pkgplugindir) +AM_CPPFLAGS=-DMYSQL_DYNAMIC_PLUGIN -I$(top_srcdir)/include + +pkgplugin_LTLIBRARIES= dialog.la +dialog_la_SOURCES= dialog.c + +if HAVE_PEERCRED +pkgplugin_LTLIBRARIES+= auth_socket.la +auth_socket_la_SOURCES= auth_socket.c +endif + +EXTRA_DIST= plug.in + diff --git a/plugin/auth/auth_socket.c b/plugin/auth/auth_socket.c new file mode 100644 index 00000000000..cc406dac331 --- /dev/null +++ b/plugin/auth/auth_socket.c @@ -0,0 +1,119 @@ +/* Copyright (C) 2010 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/** + @file + + socket_peercred authentication plugin. + + Authentication is successful if the connection is done via a unix socket and + the owner of the client process matches the user name that was used when + connecting to mysqld. +*/ +#define _GNU_SOURCE /* for struct ucred */ + +#include <mysql/plugin_auth.h> +#include <sys/socket.h> +#include <pwd.h> +#include <string.h> + +/** + perform the unix socket based authentication + + This authentication callback performs a unix socket based authentication - + it gets the uid of the client process and considers the user authenticated + if it uses username of this uid. That is - if the user is already + authenticated to the OS (if she is logged in) - she can use MySQL as herself +*/ + +static int socket_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info) +{ + unsigned char *pkt; + MYSQL_PLUGIN_VIO_INFO vio_info; + struct ucred cred; + socklen_t cred_len= sizeof(cred); + struct passwd pwd_buf, *pwd; + char buf[1024]; + + /* no user name yet ? read the client handshake packet with the user name */ + if (info->user_name == 0) + { + if (vio->read_packet(vio, &pkt) < 0) + return CR_ERROR; + } + + info->password_used = 0; + + vio->info(vio, &vio_info); + if (vio_info.protocol != MYSQL_VIO_SOCKET) + return CR_ERROR; + + /* get the UID of the client process */ + if (getsockopt(vio_info.socket, SOL_SOCKET, SO_PEERCRED, &cred, &cred_len)) + return CR_ERROR; + + if (cred_len != sizeof(cred)) + return CR_ERROR; + + /* and find the username for this uid */ + getpwuid_r(cred.uid, &pwd_buf, buf, sizeof(buf), &pwd); + if (pwd == NULL) + return CR_ERROR; + + /* now it's simple as that */ + return strcmp(pwd->pw_name, info->user_name) ? CR_ERROR : CR_OK; +} + +static struct st_mysql_auth socket_auth_handler= +{ + MYSQL_AUTHENTICATION_INTERFACE_VERSION, + 0, + socket_auth +}; + +mysql_declare_plugin(socket_auth) +{ + MYSQL_AUTHENTICATION_PLUGIN, + &socket_auth_handler, + "socket_peercred", + "Sergei Golubchik", + "Unix Socket based authentication", + PLUGIN_LICENSE_GPL, + NULL, + NULL, + 0x0100, + NULL, + NULL, + NULL +} +mysql_declare_plugin_end; +maria_declare_plugin(socket_auth) +{ + MYSQL_AUTHENTICATION_PLUGIN, + &socket_auth_handler, + "socket_peercred", + "Sergei Golubchik", + "Unix Socket based authentication", + PLUGIN_LICENSE_GPL, + NULL, + NULL, + 0x0100, + NULL, + NULL, + "1.0", + MariaDB_PLUGIN_MATURITY_BETA +} +maria_declare_plugin_end; + diff --git a/plugin/auth/dialog.c b/plugin/auth/dialog.c new file mode 100644 index 00000000000..49ab0c9a158 --- /dev/null +++ b/plugin/auth/dialog.c @@ -0,0 +1,349 @@ +/* Copyright (C) 2010 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/** + @file + + dialog client authentication plugin with examples + + dialog is a general purpose client authentication plugin, it simply + asks the user the question, as provided by the server and reports + the answer back to the server. No encryption is involved, + the answers are sent in clear text. + + 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. +*/ +#define _GNU_SOURCE /* for RTLD_DEFAULT */ + +#include <mysql/plugin_auth.h> +#include <mysql/client_plugin.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> + +/** + first byte of the question string is the question "type". + It can be a "ordinary" or a "password" question. + The last bit set marks a last question in the authentication exchange. +*/ +#define ORDINARY_QUESTION "\2" +#define LAST_QUESTION "\3" +#define PASSWORD_QUESTION "\4" +#define LAST_PASSWORD "\5" + +typedef unsigned char uchar; + +/********************* SERVER SIDE ****************************************/ + +/** + dialog demo with two questions, one password and one 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 uchar*) (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 = 1; + + /* fail if the password is wrong */ + if (strcmp((char*) pkt, info->auth_string)) + return CR_ERROR; + + /* send the last, ordinary, question */ + if (vio->write_packet(vio, + (const uchar*) (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((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 +}; + + +/** + 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 uchar*) (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 = 1; + + /* + finish, if the password is correct. + note, that we did not mark the prompt packet as "last" + */ + if (strcmp((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 +}; + +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 +}, +{ + MYSQL_AUTHENTICATION_PLUGIN, + &three_handler, + "three_attempts", + "Sergei Golubchik", + "Dialog plugin demo 2", + PLUGIN_LICENSE_GPL, + NULL, + NULL, + 0x0100, + NULL, + NULL, + NULL +} +mysql_declare_plugin_end; +maria_declare_plugin(dialog) +{ + MYSQL_AUTHENTICATION_PLUGIN, + &two_handler, + "two_questions", + "Sergei Golubchik", + "Dialog plugin demo 1", + PLUGIN_LICENSE_GPL, + NULL, + NULL, + 0x0100, + NULL, + NULL, + "1.0", + MariaDB_PLUGIN_MATURITY_BETA +}, +{ + MYSQL_AUTHENTICATION_PLUGIN, + &three_handler, + "three_attempts", + "Sergei Golubchik", + "Dialog plugin demo 2", + PLUGIN_LICENSE_GPL, + NULL, + NULL, + 0x0100, + NULL, + NULL, + "1.0", + MariaDB_PLUGIN_MATURITY_BETA +} +maria_declare_plugin_end; + +/********************* CLIENT SIDE ***************************************/ +/* + This plugin performs a dialog with the user, asking questions and + reading answers. Depending on the client it may be desirable to do it + using GUI, or console, with or without curses, or read answers + from a smardcard, for example. + + To support all this variety, the dialog plugin has a callback function + "authentication_dialog_ask". If the client has a function of this name + dialog plugin will use it for communication with the user. Otherwise + a default gets() based implementation will be used. +*/ +#include <mysql.h> +#include <dlfcn.h> + +static mysql_authentication_dialog_ask_t ask; + +static char *builtin_ask(MYSQL *mysql __attribute__((unused)), + int type __attribute__((unused)), + const char *prompt, + char *buf, int buf_len) +{ + int len; + + fputs(prompt, stdout); + fputc(' ', stdout); + if (fgets(buf, buf_len, stdin) == 0) + return 0; + + len= strlen(buf); + if (len && buf[len-1]=='\n') + buf[len-1]=0; + + return buf; +} + + +/** + The main function of the dialog plugin. + + Read the prompt, ask the question, send the reply, repeat until + the server is satisfied. + + @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 perform_dialog(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql) +{ + unsigned char *pkt, cmd= 0; + int pkt_len, res; + char reply_buf[1024], *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 clear text, by the way) + */ + reply= mysql->passwd; + } + else + { + cmd= *pkt++; + + /* is it MySQL protocol 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 we ask the user and read the reply + */ + if ((cmd >> 1) == 2 && *pkt == 0) + reply= mysql->passwd; + else + reply= ask(mysql, cmd >> 1, (char*) pkt, reply_buf, sizeof(reply_buf)); + if (!reply) + return CR_ERROR; + } + /* send the reply to the server */ + res= vio->write_packet(vio, (uchar*) reply, strlen(reply)+1); + + if (reply != mysql->passwd && reply != reply_buf) + free(reply); + + if (res) + return CR_ERROR; + + /* repeat unless it was the last question */ + } while ((cmd & 1) != 1); + + /* the job of reading the ok/error packet is left to the server */ + return CR_OK; +} + + +/** + initialization function of the dialog plugin + + Pick up the client's authentication_dialog_ask() function, if exists, + or fall back to the default implementation. +*/ + +static int init_dialog(char *errbuf __attribute__((unused)), + size_t sizeof_errbuf __attribute__((unused)), + int argc __attribute__((unused)), + va_list args __attribute__((unused))) +{ + void *sym= dlsym(RTLD_DEFAULT, "mysql_authentication_dialog_ask"); + ask= sym ? (mysql_authentication_dialog_ask_t)sym : builtin_ask; + return 0; +} + +mysql_declare_client_plugin(AUTHENTICATION) + "dialog", + "Sergei Golubchik", + "Dialog Client Authentication Plugin", + {0,1,0}, + init_dialog, + NULL, + perform_dialog +mysql_end_client_plugin; + diff --git a/plugin/auth/plug.in b/plugin/auth/plug.in new file mode 100644 index 00000000000..ce31465b056 --- /dev/null +++ b/plugin/auth/plug.in @@ -0,0 +1,15 @@ +MYSQL_PLUGIN(auth, [Collection of Authentication Plugins], + [Collection of Authentication Plugins]) +MYSQL_PLUGIN_DYNAMIC(auth, [dialog.la]) +MYSQL_PLUGIN_ACTIONS(auth,[ +AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([[ +#define _GNU_SOURCE +#include <sys/socket.h> +]],[[ + struct ucred cred; + getsockopt(0, SOL_SOCKET, SO_PEERCRED, &cred, 0); +]])],have_peercred=yes) +AM_CONDITIONAL(HAVE_PEERCRED, test x$have_peercred = xyes) +]) +AM_CONDITIONAL(HAVE_PEERCRED, false) diff --git a/plugin/daemon_example/Makefile.am b/plugin/daemon_example/Makefile.am index 96be7171b08..4a7409518b6 100644 --- a/plugin/daemon_example/Makefile.am +++ b/plugin/daemon_example/Makefile.am @@ -26,7 +26,7 @@ INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \ EXTRA_LTLIBRARIES = libdaemon_example.la pkgplugin_LTLIBRARIES = @plugin_daemon_example_shared_target@ -libdaemon_example_la_LDFLAGS = -module -rpath $(pkgplugindir) +libdaemon_example_la_LDFLAGS = -module -rpath $(pkgplugindir) -L$(top_builddir)/libservices -lmysqlservices libdaemon_example_la_CXXFLAGS= -shared $(AM_CXXFLAGS) -DMYSQL_DYNAMIC_PLUGIN libdaemon_example_la_SOURCES = daemon_example.cc diff --git a/plugin/daemon_example/daemon_example.cc b/plugin/daemon_example/daemon_example.cc index e683bf7ab7a..38c1f2f3181 100644 --- a/plugin/daemon_example/daemon_example.cc +++ b/plugin/daemon_example/daemon_example.cc @@ -200,3 +200,20 @@ mysql_declare_plugin(daemon_example) NULL /* config options */ } mysql_declare_plugin_end; +maria_declare_plugin(daemon_example) +{ + MYSQL_DAEMON_PLUGIN, + &daemon_example_plugin, + "daemon_example", + "Brian Aker", + "Daemon example, creates a heartbeat beat file in mysql-heartbeat.log", + PLUGIN_LICENSE_GPL, + daemon_example_plugin_init, /* Plugin Init */ + daemon_example_plugin_deinit, /* Plugin Deinit */ + 0x0100 /* 1.0 */, + NULL, /* status variables */ + NULL, /* system variables */ + "1.0", /* string version */ + MariaDB_PLUGIN_MATURITY_EXPERIMENTAL /* maturity */ +} +maria_declare_plugin_end; diff --git a/plugin/feedback/Makefile.am b/plugin/feedback/Makefile.am index 31727ad0d73..7d2a61d593f 100644 --- a/plugin/feedback/Makefile.am +++ b/plugin/feedback/Makefile.am @@ -4,7 +4,7 @@ INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \ EXTRA_LTLIBRARIES = feedback.la libfeedback.la pkgplugin_LTLIBRARIES = @plugin_feedback_shared_target@ -feedback_la_LDFLAGS = -module -rpath $(pkgplugindir) +feedback_la_LDFLAGS = -module -rpath $(pkgplugindir) -L$(top_builddir)/libservices -lmysqlservices feedback_la_CXXFLAGS = -shared -DMYSQL_DYNAMIC_PLUGIN feedback_la_SOURCES = feedback.cc utils.cc url_base.cc url_http.cc \ sender_thread.cc diff --git a/plugin/feedback/feedback.cc b/plugin/feedback/feedback.cc index a8c7ee82ac2..3ade31b80b4 100644 --- a/plugin/feedback/feedback.cc +++ b/plugin/feedback/feedback.cc @@ -352,4 +352,22 @@ mysql_declare_plugin(feedback) NULL } mysql_declare_plugin_end; - +#ifdef MARIA_PLUGIN_INTERFACE_VERSION +maria_declare_plugin(feedback) +{ + MYSQL_INFORMATION_SCHEMA_PLUGIN, + &feedback::feedback, + "FEEDBACK", + "Sergei Golubchik", + "MariaDB User Feedback Plugin", + PLUGIN_LICENSE_GPL, + feedback::init, + feedback::free, + 0x0101, + NULL, + feedback::settings, + "1.1", + MariaDB_PLUGIN_MATURITY_BETA +} +mysql_declare_plugin_end; +#endif diff --git a/plugin/feedback/sender_thread.cc b/plugin/feedback/sender_thread.cc index 86627add808..617ca0213dc 100644 --- a/plugin/feedback/sender_thread.cc +++ b/plugin/feedback/sender_thread.cc @@ -46,7 +46,7 @@ static int table_to_string(TABLE *table, String *result) dbug_tmp_use_all_columns(table, table->read_set); - while(!res && !table->file->rnd_next(table->record[0])) + while(!res && !table->file->ha_rnd_next(table->record[0])) { table->field[0]->val_str(&str1); table->field[1]->val_str(&str2); diff --git a/plugin/fulltext/plugin_example.c b/plugin/fulltext/plugin_example.c index de951375820..cc84cb6161b 100644 --- a/plugin/fulltext/plugin_example.c +++ b/plugin/fulltext/plugin_example.c @@ -270,3 +270,21 @@ mysql_declare_plugin(ftexample) NULL } mysql_declare_plugin_end; + +maria_declare_plugin(ftexample) +{ + MYSQL_FTPARSER_PLUGIN, /* type */ + &simple_parser_descriptor, /* descriptor */ + "simple_parser", /* name */ + "Sergei Golubchik", /* author */ + "Simple Full-Text Parser", /* description */ + PLUGIN_LICENSE_GPL, + simple_parser_plugin_init, /* init function (when loaded) */ + simple_parser_plugin_deinit,/* deinit function (when unloaded) */ + 0x0001, /* version */ + simple_status, /* status variables */ + simple_system_variables, /* system variables */ + "0.01", /* string version */ + MariaDB_PLUGIN_MATURITY_EXPERIMENTAL /* maturity */ +} +maria_declare_plugin_end; |