summaryrefslogtreecommitdiff
path: root/plugin
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2011-12-12 13:00:33 +0100
committerSergei Golubchik <sergii@pisem.net>2011-12-12 13:00:33 +0100
commit745c53ec06794c4faaf0c9c3f9a1bf4ffc3f0759 (patch)
tree560abf8d5af4977dcacbce07a9502cb84d6bb003 /plugin
parent63d32c115dd962b53cf7bcaa340472ee2f44f9e2 (diff)
parent6404504d0c10d58ad5861bdb72edd54508f1364c (diff)
downloadmariadb-git-745c53ec06794c4faaf0c9c3f9a1bf4ffc3f0759.tar.gz
5.2->5.3 merge
Diffstat (limited to 'plugin')
-rw-r--r--plugin/auth/CMakeLists.txt2
-rw-r--r--plugin/auth/Makefile.am2
-rw-r--r--plugin/auth/dialog.c64
-rw-r--r--plugin/auth_pam/Makefile.am16
-rw-r--r--plugin/auth_pam/auth_pam.c130
-rw-r--r--plugin/auth_pam/plug.in4
-rw-r--r--plugin/auth_pam/testing/pam_mariadb_mtr.c87
-rw-r--r--plugin/feedback/feedback.h5
8 files changed, 263 insertions, 47 deletions
diff --git a/plugin/auth/CMakeLists.txt b/plugin/auth/CMakeLists.txt
index 931a47fec5e..2174826b2cd 100644
--- a/plugin/auth/CMakeLists.txt
+++ b/plugin/auth/CMakeLists.txt
@@ -1,3 +1,3 @@
INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake")
-SET(AUTH_SOURCES dialog.c)
+SET(AUTH_SOURCES dialog.c ${CMAKE_SOURCE_DIR}/libmysql/get_password.c)
MYSQL_PLUGIN(AUTH)
diff --git a/plugin/auth/Makefile.am b/plugin/auth/Makefile.am
index acca98e26f8..2995d35adf4 100644
--- a/plugin/auth/Makefile.am
+++ b/plugin/auth/Makefile.am
@@ -4,7 +4,7 @@ AM_LDFLAGS=-module -rpath $(pkgplugindir)
AM_CPPFLAGS=-DMYSQL_DYNAMIC_PLUGIN -I$(top_srcdir)/include
pkgplugin_LTLIBRARIES= dialog.la
-dialog_la_SOURCES= dialog.c
+dialog_la_SOURCES= dialog.c $(top_srcdir)/libmysql/get_password.c
if HAVE_PEERCRED
pkgplugin_LTLIBRARIES+= auth_socket.la
diff --git a/plugin/auth/dialog.c b/plugin/auth/dialog.c
index 76b2ddae528..24765c17d1c 100644
--- a/plugin/auth/dialog.c
+++ b/plugin/auth/dialog.c
@@ -142,36 +142,6 @@ static struct st_mysql_auth three_handler=
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,
@@ -186,7 +156,7 @@ maria_declare_plugin(dialog)
NULL,
NULL,
"1.0",
- MariaDB_PLUGIN_MATURITY_BETA
+ MariaDB_PLUGIN_MATURITY_EXPERIMENTAL
},
{
MYSQL_AUTHENTICATION_PLUGIN,
@@ -201,7 +171,7 @@ maria_declare_plugin(dialog)
NULL,
NULL,
"1.0",
- MariaDB_PLUGIN_MATURITY_BETA
+ MariaDB_PLUGIN_MATURITY_EXPERIMENTAL
}
maria_declare_plugin_end;
@@ -224,16 +194,25 @@ static char *builtin_ask(MYSQL *mysql __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;
+ if (type == 2) /* password */
+ {
+ get_tty_password_buff("", buf, buf_len);
+ buf[buf_len-1]= 0;
+ }
+ else
+ {
+ if (!fgets(buf, buf_len-1, stdin))
+ buf[0]= 0;
+ else
+ {
+ int len= strlen(buf);
+ if (len && buf[len-1] == '\n')
+ buf[len-1]= 0;
+ }
+ }
return buf;
}
@@ -261,6 +240,7 @@ static int perform_dialog(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
unsigned char *pkt, cmd= 0;
int pkt_len, res;
char reply_buf[1024], *reply;
+ int first = 1;
do
{
@@ -269,7 +249,7 @@ static int perform_dialog(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
if (pkt_len < 0)
return CR_ERROR;
- if (pkt == 0)
+ if (pkt == 0 && first)
{
/*
in mysql_change_user() the client sends the first packet, so
@@ -291,10 +271,10 @@ static int perform_dialog(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
return CR_OK_HANDSHAKE_COMPLETE; /* yes. we're done */
/*
- asking for a password with an empty prompt means mysql->password
+ asking for a password in the first packet mean mysql->password, if it's set
otherwise we ask the user and read the reply
*/
- if ((cmd >> 1) == 2 && *pkt == 0)
+ if ((cmd >> 1) == 2 && first && mysql->passwd[0])
reply= mysql->passwd;
else
reply= ask(mysql, cmd >> 1, (char*) pkt, reply_buf, sizeof(reply_buf));
diff --git a/plugin/auth_pam/Makefile.am b/plugin/auth_pam/Makefile.am
new file mode 100644
index 00000000000..be20d393781
--- /dev/null
+++ b/plugin/auth_pam/Makefile.am
@@ -0,0 +1,16 @@
+EXTRA_LTLIBRARIES = auth_pam.la libauth_pam.la
+
+pkgplugindir=$(pkglibdir)/plugin
+AM_CPPFLAGS = -I$(top_srcdir)/include
+
+pkgplugin_LTLIBRARIES = @plugin_auth_pam_shared_target@
+auth_pam_la_LDFLAGS = -module -rpath $(pkgplugindir) -L$(top_builddir)/libservices -lmysqlservices -lpam
+auth_pam_la_CFLAGS = -shared -DMYSQL_DYNAMIC_PLUGIN
+auth_pam_la_SOURCES = auth_pam.c
+
+noinst_LTLIBRARIES = @plugin_auth_pam_static_target@
+libauth_pam_la_LDFLAGS = -lpam
+libauth_pam_la_SOURCES = auth_pam.c
+
+EXTRA_DIST = plug.in
+
diff --git a/plugin/auth_pam/auth_pam.c b/plugin/auth_pam/auth_pam.c
new file mode 100644
index 00000000000..45c49975f6e
--- /dev/null
+++ b/plugin/auth_pam/auth_pam.c
@@ -0,0 +1,130 @@
+#include <mysql/plugin_auth.h>
+#include <string.h>
+#include <security/pam_appl.h>
+#include <security/pam_modules.h>
+
+struct param {
+ unsigned char buf[10240], *ptr;
+ MYSQL_PLUGIN_VIO *vio;
+};
+
+static int conv(int n, const struct pam_message **msg,
+ struct pam_response **resp, void *data)
+{
+ struct param *param = (struct param *)data;
+ unsigned char *end = param->buf + sizeof(param->buf) - 1;
+ int i;
+
+ *resp = 0;
+
+ for (i = 0; i < n; i++)
+ {
+ /* if there's a message - append it to the buffer */
+ if (msg[i]->msg)
+ {
+ int len = strlen(msg[i]->msg);
+ if (len > end - param->ptr)
+ len = end - param->ptr;
+ if (len > 0)
+ {
+ memcpy(param->ptr, msg[i]->msg, len);
+ param->ptr+= len;
+ *(param->ptr)++ = '\n';
+ }
+ }
+ /* if the message style is *_PROMPT_*, meaning PAM asks a question,
+ send the accumulated text to the client, read the reply */
+ if (msg[i]->msg_style == PAM_PROMPT_ECHO_OFF ||
+ msg[i]->msg_style == PAM_PROMPT_ECHO_ON)
+ {
+ int pkt_len;
+ unsigned char *pkt;
+
+ /* allocate the response array.
+ freeing it is the responsibility of the caller */
+ if (*resp == 0)
+ {
+ *resp = calloc(sizeof(struct pam_response), n);
+ if (*resp == 0)
+ return PAM_BUF_ERR;
+ }
+
+ /* dialog plugin interprets the first byte of the packet
+ as the magic number.
+ 2 means "read the input with the echo enabled"
+ 4 means "password-like input, echo disabled"
+ C'est la vie. */
+ param->buf[0] = msg[i]->msg_style == PAM_PROMPT_ECHO_ON ? 2 : 4;
+ if (param->vio->write_packet(param->vio, param->buf, param->ptr - param->buf - 1))
+ return PAM_CONV_ERR;
+
+ pkt_len = param->vio->read_packet(param->vio, &pkt);
+ if (pkt_len < 0)
+ return PAM_CONV_ERR;
+ /* allocate and copy the reply to the response array */
+ (*resp)[i].resp = strndup((char*)pkt, pkt_len);
+ param->ptr = param->buf + 1;
+ }
+ }
+ return PAM_SUCCESS;
+}
+
+#define DO(X) if ((status = (X)) != PAM_SUCCESS) goto end
+
+static int pam_auth(MYSQL_PLUGIN_VIO *vio, MYSQL_SERVER_AUTH_INFO *info)
+{
+ pam_handle_t *pamh = NULL;
+ int status;
+ const char *new_username;
+ struct param param;
+ struct pam_conv c = { &conv, &param };
+
+ /*
+ get the service name, as specified in
+
+ CREATE USER ... IDENTIFIED WITH pam_auth AS "service"
+ */
+ const char *service = info->auth_string && info->auth_string[0]
+ ? info->auth_string : "mysql";
+
+ param.ptr = param.buf + 1;
+ param.vio = vio;
+
+ DO( pam_start(service, info->user_name, &c, &pamh) );
+ DO( pam_authenticate (pamh, 0) );
+ DO( pam_acct_mgmt(pamh, 0) );
+ DO( pam_get_item(pamh, PAM_USER, (const void**)&new_username) );
+
+ if (new_username && strcmp(new_username, info->user_name))
+ strncpy(info->authenticated_as, new_username,
+ sizeof(info->authenticated_as));
+
+end:
+ pam_end(pamh, status);
+ return status == PAM_SUCCESS ? CR_OK : CR_ERROR;
+}
+
+static struct st_mysql_auth pam_info =
+{
+ MYSQL_AUTHENTICATION_INTERFACE_VERSION,
+ "dialog",
+ pam_auth
+};
+
+maria_declare_plugin(pam)
+{
+ MYSQL_AUTHENTICATION_PLUGIN,
+ &pam_info,
+ "pam",
+ "Sergei Golubchik",
+ "PAM 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_pam/plug.in b/plugin/auth_pam/plug.in
new file mode 100644
index 00000000000..05af6ce6461
--- /dev/null
+++ b/plugin/auth_pam/plug.in
@@ -0,0 +1,4 @@
+MYSQL_PLUGIN(auth_pam, [PAM Authentication Plugin], [PAM Authentication Plugin])
+MYSQL_PLUGIN_DYNAMIC(auth_pam, [auth_pam.la])
+
+AC_CHECK_HEADER([security/pam_appl.h],,[MYSQL_PLUGIN_WITHOUT(auth_pam)])
diff --git a/plugin/auth_pam/testing/pam_mariadb_mtr.c b/plugin/auth_pam/testing/pam_mariadb_mtr.c
new file mode 100644
index 00000000000..73defe30112
--- /dev/null
+++ b/plugin/auth_pam/testing/pam_mariadb_mtr.c
@@ -0,0 +1,87 @@
+/*
+ Pam module to test pam authentication plugin. Used in pam.test.
+ Linux only.
+
+ Compile as
+
+ gcc pam_mariadb_mtr.c -shared -lpam -fPIC -o pam_mariadb_mtr.so
+
+ Install as appropriate (for example, in /lib/security/).
+ Create /etc/pam.d/mariadb_mtr with
+=========================================================
+auth required pam_mariadb_mtr.so pam_test
+account required pam_mariadb_mtr.so
+=========================================================
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <security/pam_modules.h>
+#include <security/pam_appl.h>
+
+#define N 3
+
+PAM_EXTERN int
+pam_sm_authenticate(pam_handle_t *pamh, int flags,
+ int argc, const char *argv[])
+{
+ struct pam_conv *conv;
+ struct pam_response *resp = 0;
+ int pam_err, retval = PAM_SYSTEM_ERR;
+ struct pam_message msg[N] = {
+ { PAM_TEXT_INFO, "Challenge input first." },
+ { PAM_PROMPT_ECHO_ON, "Enter:" },
+ { PAM_ERROR_MSG, "Now, the magic number!" }
+ };
+ const struct pam_message *msgp[N] = { msg, msg+1, msg+2 };
+ char *r1 = 0, *r2 = 0;
+
+ pam_err = pam_get_item(pamh, PAM_CONV, (const void **)&conv);
+ if (pam_err != PAM_SUCCESS)
+ goto ret;
+
+ pam_err = (*conv->conv)(N, msgp, &resp, conv->appdata_ptr);
+
+ if (pam_err != PAM_SUCCESS || !resp || !((r1= resp[1].resp)))
+ goto ret;
+
+ free(resp);
+
+ msg[0].msg_style = PAM_PROMPT_ECHO_OFF;
+ msg[0].msg = "PIN:";
+ pam_err = (*conv->conv)(1, msgp, &resp, conv->appdata_ptr);
+
+ if (pam_err != PAM_SUCCESS || !resp || !((r2= resp[0].resp)))
+ goto ret;
+
+ if (strlen(r1) == atoi(r2) % 100)
+ retval = PAM_SUCCESS;
+ else
+ retval = PAM_AUTH_ERR;
+
+ if (argc > 0 && argv[0])
+ pam_set_item(pamh, PAM_USER, argv[0]);
+
+ret:
+ free(resp);
+ free(r1);
+ free(r2);
+ return retval;
+}
+
+PAM_EXTERN int
+pam_sm_setcred(pam_handle_t *pamh, int flags,
+ int argc, const char *argv[])
+{
+
+ return PAM_SUCCESS;
+}
+
+PAM_EXTERN int
+pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
+ int argc, const char *argv[])
+{
+
+ return PAM_SUCCESS;
+}
+
diff --git a/plugin/feedback/feedback.h b/plugin/feedback/feedback.h
index df9020fc37e..f9e2cd34231 100644
--- a/plugin/feedback/feedback.h
+++ b/plugin/feedback/feedback.h
@@ -12,9 +12,8 @@
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 */
-#ifndef MYSQL_SERVER
-#define MYSQL_SERVER
-#endif
+
+#define MYSQL_SERVER 1
#include <mysql_priv.h>
namespace feedback {