Merge lp:~sergei.glushchenko/percona-pam-for-mysql/two-plugins into lp:percona-pam-for-mysql

Proposed by Sergei Glushchenko
Status: Merged
Approved by: Laurynas Biveinis
Approved revision: 23
Merged at revision: 23
Proposed branch: lp:~sergei.glushchenko/percona-pam-for-mysql/two-plugins
Merge into: lp:percona-pam-for-mysql
Diff against target: 729 lines (+410/-205)
7 files modified
CMakeLists.txt (+5/-2)
src/Makefile.am (+6/-2)
src/auth_mapping.h (+1/-2)
src/auth_pam.c (+175/-0)
src/auth_pam_common.c (+21/-199)
src/auth_pam_common.h (+71/-0)
src/auth_pam_compat.c (+131/-0)
To merge this branch: bzr merge lp:~sergei.glushchenko/percona-pam-for-mysql/two-plugins
Reviewer Review Type Date Requested Status
Laurynas Biveinis (community) Approve
Review via email: mp+92716@code.launchpad.net

Description of the change

Full-featured PAM auth server plugin was split into two parts.
First one is generic PAM conversation function, second one performs
client-specific message sending and receiving.
(auth_pam_common.c and auth_pam.c) modules. Oracle-compatible
server-side plugin was implemented (auth_pam_compat.c).
Both plugins use auth_pam_common.c. All client-specific behavior
localized in auth_pam.c and auth_pam_compat.c.

auth_pam_compat plugin do not support dialog with client and the only
way to specify password with *mysql* client is using -p option.

Example:
mysql -u test -p111

or
mysql -u test -p
Enter password:

Besides there is no visible difference between case when -p option
used and when it not. So password_used is always set to
PASSWORD_USED_NO_MENTION.

To post a comment you must log in.
Revision history for this message
Laurynas Biveinis (laurynas-biveinis) wrote :

LGTM, thank you.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt 2012-02-09 16:25:22 +0000
+++ CMakeLists.txt 2012-02-13 06:42:18 +0000
@@ -19,9 +19,12 @@
19CHECK_SYMBOL_EXISTS(getpwnam_r "pwd.h" HAVE_GETPWNAM_R)19CHECK_SYMBOL_EXISTS(getpwnam_r "pwd.h" HAVE_GETPWNAM_R)
20CHECK_SYMBOL_EXISTS(getgrgid_r "grp.h" HAVE_GETGRGID_R)20CHECK_SYMBOL_EXISTS(getgrgid_r "grp.h" HAVE_GETGRGID_R)
21IF(HAVE_PAM AND HAVE_MYSQLCLIENT AND HAVE_GETPWNAM_R AND HAVE_GETGRGID_R)21IF(HAVE_PAM AND HAVE_MYSQLCLIENT AND HAVE_GETPWNAM_R AND HAVE_GETGRGID_R)
22 SET(AUTH_PAM_SOURCES 22 SET(AUTH_PAM_COMMON_SOURCES
23 src/auth_pam.c src/lib_auth_pam_client.c src/lib_auth_pam_client.h23 src/auth_pam_common.c src/lib_auth_pam_client.c src/lib_auth_pam_client.h
24 src/auth_mapping.h src/auth_mapping.c)24 src/auth_mapping.h src/auth_mapping.c)
25 SET(AUTH_PAM_SOURCES ${AUTH_PAM_COMMON_SOURCES} src/auth_pam.c)
26 SET(AUTH_PAM_COMPAT_SOURCES ${AUTH_PAM_COMMON_SOURCES} src/auth_pam_compat.c)
25 MYSQL_ADD_PLUGIN(auth_pam ${AUTH_PAM_SOURCES} LINK_LIBRARIES pam)27 MYSQL_ADD_PLUGIN(auth_pam ${AUTH_PAM_SOURCES} LINK_LIBRARIES pam)
28 MYSQL_ADD_PLUGIN(auth_pam_compat ${AUTH_PAM_COMPAT_SOURCES} LINK_LIBRARIES pam)
26 MYSQL_ADD_PLUGIN(dialog src/dialog.c LINK_LIBRARIES mysqlclient)29 MYSQL_ADD_PLUGIN(dialog src/dialog.c LINK_LIBRARIES mysqlclient)
27ENDIF(HAVE_PAM AND HAVE_MYSQLCLIENT AND HAVE_GETPWNAM_R AND HAVE_GETGRGID_R)30ENDIF(HAVE_PAM AND HAVE_MYSQLCLIENT AND HAVE_GETPWNAM_R AND HAVE_GETGRGID_R)
2831
=== modified file 'src/Makefile.am'
--- src/Makefile.am 2012-02-10 04:21:32 +0000
+++ src/Makefile.am 2012-02-13 06:42:18 +0000
@@ -16,14 +16,18 @@
1616
17plugindir = @PLUGINDIR@17plugindir = @PLUGINDIR@
1818
19plugin_LTLIBRARIES = auth_pam.la test_auth_pam_client.la dialog.la19plugin_LTLIBRARIES = auth_pam.la auth_pam_compat.la test_auth_pam_client.la dialog.la
20plugin_CPPFLAGS = -DMYSQL_DYNAMIC_PLUGIN20plugin_CPPFLAGS = -DMYSQL_DYNAMIC_PLUGIN
21plugin_LDFLAGS = -module -avoid-version -shared21plugin_LDFLAGS = -module -avoid-version -shared
2222
23auth_pam_la_SOURCES = auth_pam.c lib_auth_pam_client.h lib_auth_pam_client.c auth_mapping.c23auth_pam_la_SOURCES = auth_pam_common.c auth_pam.c lib_auth_pam_client.h lib_auth_pam_client.c auth_mapping.c
24auth_pam_la_CPPFLAGS = $(plugin_CPPFLAGS)24auth_pam_la_CPPFLAGS = $(plugin_CPPFLAGS)
25auth_pam_la_LDFLAGS = $(plugin_LDFLAGS) $(AUTH_PAM_LIBS)25auth_pam_la_LDFLAGS = $(plugin_LDFLAGS) $(AUTH_PAM_LIBS)
2626
27auth_pam_compat_la_SOURCES = auth_pam_common.c auth_pam_compat.c lib_auth_pam_client.h lib_auth_pam_client.c auth_mapping.c
28auth_pam_compat_la_CPPFLAGS = $(plugin_CPPFLAGS)
29auth_pam_compat_la_LDFLAGS = $(plugin_LDFLAGS) $(AUTH_PAM_LIBS)
30
27test_auth_pam_client_la_SOURCES = test_auth_pam_client.c \31test_auth_pam_client_la_SOURCES = test_auth_pam_client.c \
28 lib_auth_pam_client.h lib_auth_pam_client.c32 lib_auth_pam_client.h lib_auth_pam_client.c
29test_auth_pam_client_la_LDFLAGS = $(plugin_LDFLAGS)33test_auth_pam_client_la_LDFLAGS = $(plugin_LDFLAGS)
3034
=== modified file 'src/auth_mapping.h'
--- src/auth_mapping.h 2012-02-09 16:25:22 +0000
+++ src/auth_mapping.h 2012-02-13 06:42:18 +0000
@@ -20,9 +20,8 @@
20/**20/**
21 @file21 @file
2222
23 PAM authentication for MySQL, common definitions for side plugins.23 PAM authentication for MySQL, interface for user mapping.
2424
25 For the general description, see the top comment in auth_pam.c.
26*/25*/
2726
28#ifdef __cplusplus27#ifdef __cplusplus
2928
=== added file 'src/auth_pam.c'
--- src/auth_pam.c 1970-01-01 00:00:00 +0000
+++ src/auth_pam.c 2012-02-13 06:42:18 +0000
@@ -0,0 +1,175 @@
1/*
2(C) 2012 Percona Inc.
3
4This program is free software; you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation; version 2 of the License.
7
8This program is distributed in the hope that it will be useful,
9but WITHOUT ANY WARRANTY; without even the implied warranty of
10MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11GNU General Public License for more details.
12
13You should have received a copy of the GNU General Public License
14along with this program; if not, write to the Free Software
15Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16*/
17
18/**
19 @file
20
21 PAM authentication for MySQL, server-side plugin for the
22 production use.
23
24 A general-purpose PAM authentication plugin for MySQL. Acts as a mediator
25 between the MySQL server, the MySQL client, and the PAM backend. Dialog plugin
26 used as client plugin.
27
28 The server plugin requests authentication from the PAM backend, forwards any
29 requests and messages from the PAM backend over the wire to the client (in
30 cleartext) and reads back any replies for the backend.
31
32 This plugin does not encrypt the communication channel in any way. If this is
33 required, a SSL connection should be used.
34
35 To install this plugin, copy the .so file to the plugin directory and do
36
37 INSTALL PLUGIN auth_pam SONAME 'auth_pam.so';
38
39 To use this plugin for one particular user, specify it at user's creation time
40 (TODO: tested with localhost only):
41
42 CREATE USER 'username'@'hostname' IDENTIFIED WITH auth_pam;
43
44 Alternatively UPDATE the mysql.user table to set the plugin value for an
45 existing user.
46
47 Also it is possible to use this plugin to authenticate anonymous users:
48
49 CREATE USER ''@'hostname' IDENTIFIED WITH auth_pam;
50
51*/
52
53#ifdef HAVE_CONFIG_H
54#include "config.h"
55#endif
56
57#include "auth_pam_common.h"
58
59/** The maximum length of buffered PAM messages, i.e. any messages up to the
60 next PAM reply-requiring message. 10K should be more than enough by order
61 of magnitude. */
62enum { max_pam_buffered_msg_len = 10240 };
63
64struct pam_msg_buf {
65 unsigned char buf[max_pam_buffered_msg_len];
66 unsigned char* ptr;
67};
68
69static char pam_msg_style_to_char (int pam_msg_style)
70{
71 /* Magic byte for the dialog plugin, '\2' is defined as ORDINARY_QUESTION
72 and '\4' as PASSWORD_QUESTION there. */
73 return (pam_msg_style == PAM_PROMPT_ECHO_ON) ? '\2' : '\4';
74}
75
76int auth_pam_client_talk_init(void **talk_data)
77{
78 struct pam_msg_buf *msg_buf= calloc(1, sizeof(struct pam_msg_buf));
79 *talk_data= (void*)msg_buf;
80 if (msg_buf != NULL)
81 {
82 msg_buf->ptr= msg_buf->buf + 1;
83 return PAM_SUCCESS;
84 }
85 return PAM_BUF_ERR;
86}
87
88void auth_pam_client_talk_finalize(void *talk_data)
89{
90 free(talk_data);
91}
92
93int auth_pam_talk_perform(const struct pam_message *msg,
94 struct pam_response *resp,
95 struct pam_conv_data *data,
96 void *talk_data)
97{
98 struct pam_msg_buf *msg_buf= (struct pam_msg_buf*)talk_data;
99
100 /* Append the PAM message or prompt to the unsent message buffer */
101 if (msg->msg)
102 {
103 unsigned char *last_buf_pos = msg_buf->buf + max_pam_buffered_msg_len - 1;
104 if (msg_buf->ptr + strlen(msg->msg) >= last_buf_pos)
105 {
106 /* Cannot happen: the PAM message buffer too small. */
107 MY_ASSERT_UNREACHABLE();
108 return PAM_CONV_ERR;
109 }
110 memcpy(msg_buf->ptr, msg->msg, strlen(msg->msg));
111 msg_buf->ptr+= strlen(msg->msg);
112 *(msg_buf->ptr)++= '\n';
113 }
114
115 if (msg->msg_style == PAM_PROMPT_ECHO_OFF
116 || msg->msg_style == PAM_PROMPT_ECHO_ON)
117 {
118 int pkt_len;
119 unsigned char *pkt;
120
121 msg_buf->buf[0]= pam_msg_style_to_char(msg->msg_style);
122
123 /* Write the message. */
124 if (data->vio->write_packet(data->vio, msg_buf->buf,
125 msg_buf->ptr - msg_buf->buf - 1))
126 return PAM_CONV_ERR;
127
128 /* Read the answer */
129 if ((pkt_len= data->vio->read_packet(data->vio, &pkt))
130 < 0)
131 return PAM_CONV_ERR;
132
133 resp->resp= malloc(pkt_len + 1);
134 if (resp->resp == NULL)
135 return PAM_BUF_ERR;
136
137 strncpy(resp->resp, (char *)pkt, pkt_len);
138 resp->resp[pkt_len]= '\0';
139
140 if (msg->msg_style == PAM_PROMPT_ECHO_OFF)
141 data->info->password_used= PASSWORD_USED_YES;
142
143 msg_buf->ptr= msg_buf->buf + 1;
144 }
145
146 return PAM_SUCCESS;
147}
148
149static struct st_mysql_auth pam_auth_handler=
150{
151 MYSQL_AUTHENTICATION_INTERFACE_VERSION,
152 "dialog",
153 &authenticate_user_with_pam_server
154};
155
156mysql_declare_plugin(auth_pam)
157{
158 MYSQL_AUTHENTICATION_PLUGIN,
159 &pam_auth_handler,
160 "auth_pam",
161 "Percona, Inc.",
162 "PAM authentication plugin",
163 PLUGIN_LICENSE_GPL,
164 NULL,
165 NULL,
166 0x0001,
167 NULL,
168 NULL,
169 NULL
170#if MYSQL_PLUGIN_INTERFACE_VERSION >= 0x103
171 ,
172 0
173#endif
174}
175mysql_declare_plugin_end;
0176
=== renamed file 'src/auth_pam.c' => 'src/auth_pam_common.c'
--- src/auth_pam.c 2012-02-09 16:25:22 +0000
+++ src/auth_pam_common.c 2012-02-13 06:42:18 +0000
@@ -15,69 +15,11 @@
15Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA15Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16*/16*/
1717
18/**
19 @file
20
21 PAM authentication for MySQL, server- and client-side plugins for the
22 production use.
23
24 A general-purpose PAM authentication plugin for MySQL. Acts as a mediator
25 between the MySQL server, the MySQL client, and the PAM backend. Consists of
26 both the server and the client plugin.
27
28 The server plugin requests authentication from the PAM backend, forwards any
29 requests and messages from the PAM backend over the wire to the client (in
30 cleartext) and reads back any replies for the backend.
31
32 The client plugin inputs from the TTY any requested info/passwords as
33 requested and sends them back over the wire to the server.
34
35 This plugin does not encrypt the communication channel in any way. If this is
36 required, a SSL connection should be used.
37
38 To install this plugin, copy the .so file to the plugin directory and do
39
40 INSTALL PLUGIN auth_pam SONAME 'auth_pam.so';
41
42 To use this plugin for one particular user, specify it at user's creation time
43 (TODO: tested with localhost only):
44
45 CREATE USER 'username'@'hostname' IDENTIFIED WITH auth_pam;
46
47 Alternatively UPDATE the mysql.user table to set the plugin value for an
48 existing user.
49
50 Also it is possible to use this plugin to authenticate anonymous users:
51
52 CREATE USER ''@'hostname' IDENTIFIED WITH auth_pam;
53
54*/
55#ifdef HAVE_CONFIG_H18#ifdef HAVE_CONFIG_H
56#include "config.h"19#include "config.h"
57#endif20#endif
5821
59#include <assert.h>22#include "auth_pam_common.h"
60
61#include <security/pam_appl.h>
62#include <security/pam_modules.h>
63#include <security/pam_misc.h>
64
65/* Define these macros ourselves, so we don't have to include my_global.h and
66can compile against unconfigured MySQL source tree. */
67#define STDCALL
68
69#define MY_ASSERT_UNREACHABLE() assert(0)
70
71#include <mysql/plugin.h>
72#include <mysql/plugin_auth.h>
73#include <mysql/client_plugin.h>
74
75#ifdef HAVE_GETPASS
76#include <unistd.h> /* getpass() */
77#else
78#error "Please add support for echo-less input for your platform"
79#endif
80
81#include "auth_mapping.h"23#include "auth_mapping.h"
8224
83/* The server plugin */25/* The server plugin */
@@ -99,37 +41,10 @@
99 }41 }
100}42}
10143
102static char pam_msg_style_to_char (int pam_msg_style)
103{
104 /* Do not use any of MySQL client-server protocol reserved values, i.e. \0 */
105 switch (pam_msg_style)
106 {
107 case PAM_PROMPT_ECHO_OFF: return '\2';
108 case PAM_PROMPT_ECHO_ON: return '\3';
109 case PAM_ERROR_MSG: return '\4';
110 case PAM_TEXT_INFO: return '\5';
111 default:
112 MY_ASSERT_UNREACHABLE();
113 return '\1';
114 }
115}
116
117/** The maximum length of buffered PAM messages, i.e. any messages up to the
118 next PAM reply-requiring message. 10K should be more than enough by order
119 of magnitude. */
120enum { max_pam_buffered_msg_len = 10240 };
121
122/** The maximum length of service name. It shouldn't be too long as it's44/** The maximum length of service name. It shouldn't be too long as it's
123 filename in pam.d directory also */45 filename in pam.d directory also */
124enum { max_pam_service_name_len = 64 };46enum { max_pam_service_name_len = 64 };
12547
126struct pam_conv_data {
127 MYSQL_PLUGIN_VIO *vio;
128 MYSQL_SERVER_AUTH_INFO *info;
129 unsigned char buf[max_pam_buffered_msg_len];
130 unsigned char* ptr;
131};
132
133static void free_pam_response (struct pam_response ** resp, int n)48static void free_pam_response (struct pam_response ** resp, int n)
134{49{
135 int i;50 int i;
@@ -145,6 +60,8 @@
145 struct pam_response ** resp, void *appdata_ptr)60 struct pam_response ** resp, void *appdata_ptr)
146{61{
147 int i;62 int i;
63 int error;
64 void *talk_data;
148 struct pam_conv_data *data= (struct pam_conv_data *)appdata_ptr;65 struct pam_conv_data *data= (struct pam_conv_data *)appdata_ptr;
14966
150 if (data == NULL)67 if (data == NULL)
@@ -157,80 +74,39 @@
157 if (*resp == NULL)74 if (*resp == NULL)
158 return PAM_BUF_ERR;75 return PAM_BUF_ERR;
15976
77 error= auth_pam_client_talk_init(&talk_data);
78 if (error != PAM_SUCCESS)
79 {
80 free_pam_response(resp, 0);
81 return error;
82 }
83
160 for (i = 0; i < num_msg; i++)84 for (i = 0; i < num_msg; i++)
161 {85 {
162 if (!valid_pam_msg_style(msg[i]->msg_style))86 if (!valid_pam_msg_style(msg[i]->msg_style))
163 {87 {
88 auth_pam_client_talk_finalize(talk_data);
164 free_pam_response(resp, i);89 free_pam_response(resp, i);
165 return PAM_CONV_ERR;90 return PAM_CONV_ERR;
166 }91 }
16792
168 /* Append the PAM message or prompt to the unsent message buffer */93 error= auth_pam_talk_perform(msg[i], resp[i], data, talk_data);
169 if (msg[i]->msg)94 if (error != PAM_SUCCESS)
170 {95 {
171 unsigned char *last_buf_pos = data->buf + max_pam_buffered_msg_len - 1;96 auth_pam_client_talk_finalize(talk_data);
172 if (data->ptr + strlen(msg[i]->msg) >= last_buf_pos)97 free_pam_response(resp, i);
173 {98 return error;
174 free_pam_response(resp, i);
175 /* Cannot happen: the PAM message buffer too small. */
176 MY_ASSERT_UNREACHABLE();
177 return PAM_CONV_ERR;
178 }
179 memcpy(data->ptr, msg[i]->msg, strlen(msg[i]->msg));
180 data->ptr+= strlen(msg[i]->msg);
181 *(data->ptr)++= '\n';
182 }
183
184 if (msg[i]->msg_style == PAM_PROMPT_ECHO_OFF
185 || msg[i]->msg_style == PAM_PROMPT_ECHO_ON)
186 {
187 int pkt_len;
188 unsigned char *pkt;
189
190 /* Magic byte for the dialog plugin, '\2' is defined as ORDINARY_QUESTION
191 and '\4' as PASSWORD_QUESTION there. */
192 data->buf[0]= (msg[i]->msg_style == PAM_PROMPT_ECHO_ON ? '\2' : '\4');
193
194 /* Write the message. */
195 if (data->vio->write_packet(data->vio, data->buf,
196 data->ptr - data->buf - 1))
197 {
198 free_pam_response(resp, i);
199 return PAM_CONV_ERR;
200 }
201
202 /* Read the answer */
203 if ((pkt_len= data->vio->read_packet(data->vio, &pkt))
204 < 0)
205 {
206 free_pam_response(resp, i);
207 return PAM_CONV_ERR;
208 }
209
210 (*resp)[i].resp= malloc(pkt_len + 1);
211 if ((*resp)[i].resp == NULL)
212 {
213 free_pam_response(resp, i);
214 return PAM_BUF_ERR;
215 }
216
217 strncpy((*resp)[i].resp, (char *)pkt, pkt_len);
218 (*resp)[i].resp[pkt_len]= '\0';
219
220 if (msg[i]->msg_style == PAM_PROMPT_ECHO_OFF)
221 data->info->password_used= PASSWORD_USED_YES;
222
223 data->ptr= data->buf + 1;
224 }99 }
225 }100 }
101 auth_pam_client_talk_finalize(talk_data);
226 return PAM_SUCCESS;102 return PAM_SUCCESS;
227}103}
228104
229static int authenticate_user_with_pam_server (MYSQL_PLUGIN_VIO *vio,105int authenticate_user_with_pam_server (MYSQL_PLUGIN_VIO *vio,
230 MYSQL_SERVER_AUTH_INFO *info)106 MYSQL_SERVER_AUTH_INFO *info)
231{107{
232 pam_handle_t *pam_handle;108 pam_handle_t *pam_handle;
233 struct pam_conv_data data= { vio, info, "", data.buf+1 };109 struct pam_conv_data data= { vio, info };
234 struct pam_conv conv_func_info= { &vio_server_conv, &data };110 struct pam_conv conv_func_info= { &vio_server_conv, &data };
235 int error;111 int error;
236 char *pam_mapped_user_name;112 char *pam_mapped_user_name;
@@ -312,57 +188,3 @@
312188
313 return CR_OK;189 return CR_OK;
314}190}
315
316static struct st_mysql_auth pam_auth_handler=
317{
318 MYSQL_AUTHENTICATION_INTERFACE_VERSION,
319 "dialog",
320 &authenticate_user_with_pam_server
321};
322
323static struct st_mysql_auth test_pam_auth_handler=
324{
325 MYSQL_AUTHENTICATION_INTERFACE_VERSION,
326 "auth_pam_test",
327 &authenticate_user_with_pam_server
328};
329
330mysql_declare_plugin(auth_pam)
331{
332 MYSQL_AUTHENTICATION_PLUGIN,
333 &pam_auth_handler,
334 "auth_pam",
335 "Percona, Inc.",
336 "PAM authentication plugin",
337 PLUGIN_LICENSE_GPL,
338 NULL,
339 NULL,
340 0x0001,
341 NULL,
342 NULL,
343 NULL
344#if MYSQL_PLUGIN_INTERFACE_VERSION >= 0x103
345 ,
346 0
347#endif
348},
349{
350 MYSQL_AUTHENTICATION_PLUGIN,
351 &test_pam_auth_handler,
352 "test_auth_pam_server",
353 "Percona, Inc.",
354 "PAM authentication plugin that requests the test version of the"
355 " client-side plugin. DO NOT USE IN PRODUCTION.",
356 PLUGIN_LICENSE_GPL,
357 NULL,
358 NULL,
359 0x0001,
360 NULL,
361 NULL,
362 NULL
363#if MYSQL_PLUGIN_INTERFACE_VERSION >= 0x103
364 ,
365 0
366#endif
367}
368mysql_declare_plugin_end;
369191
=== added file 'src/auth_pam_common.h'
--- src/auth_pam_common.h 1970-01-01 00:00:00 +0000
+++ src/auth_pam_common.h 2012-02-13 06:42:18 +0000
@@ -0,0 +1,71 @@
1#ifndef AUTH_PAM_COMMON_INCLUDED
2#define AUTH_PAM_COMMON_INCLUDED
3/*
4 (C) 2012 Percona Inc.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; version 2 of the License.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18*/
19
20/**
21 @file
22
23 PAM authentication for MySQL, common definitions for side plugins.
24
25 For the general description, see the top comment in auth_pam_common.c.
26*/
27
28/* Define these macros ourselves, so we don't have to include my_global.h and
29can compile against unconfigured MySQL source tree. */
30#define STDCALL
31
32#include <security/pam_appl.h>
33#include <security/pam_modules.h>
34#include <security/pam_misc.h>
35
36#include <mysql/plugin.h>
37#include <mysql/plugin_auth.h>
38#include <mysql/client_plugin.h>
39
40#include <assert.h>
41
42#define MY_ASSERT_UNREACHABLE() assert(0)
43
44#ifdef __cplusplus
45extern "C" {
46#endif
47
48struct pam_conv_data {
49 MYSQL_PLUGIN_VIO *vio;
50 MYSQL_SERVER_AUTH_INFO *info;
51};
52
53/** Define following three functions for your specific client plugin */
54
55int auth_pam_client_talk_init(void **talk_data);
56
57int auth_pam_talk_perform(const struct pam_message *msg,
58 struct pam_response *resp,
59 struct pam_conv_data *data,
60 void *talk_data);
61
62void auth_pam_client_talk_finalize(void *talk_data);
63
64int authenticate_user_with_pam_server (MYSQL_PLUGIN_VIO *vio,
65 MYSQL_SERVER_AUTH_INFO *info);
66
67#ifdef __cplusplus
68}
69#endif
70
71#endif
072
=== added file 'src/auth_pam_compat.c'
--- src/auth_pam_compat.c 1970-01-01 00:00:00 +0000
+++ src/auth_pam_compat.c 2012-02-13 06:42:18 +0000
@@ -0,0 +1,131 @@
1/*
2(C) 2012 Percona Inc.
3
4This program is free software; you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation; version 2 of the License.
7
8This program is distributed in the hope that it will be useful,
9but WITHOUT ANY WARRANTY; without even the implied warranty of
10MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11GNU General Public License for more details.
12
13You should have received a copy of the GNU General Public License
14along with this program; if not, write to the Free Software
15Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16*/
17
18/**
19 @file
20
21 PAM authentication for MySQL, server-side plugin for the
22 production use.
23
24 Oracle MySQL-compatible plugin. Acts as a mediator
25 between the MySQL server, the MySQL client, and the PAM backend.
26
27 The server plugin requests authentication from the PAM backend, and reads one
28 phrase from client plugin. mysql_clear_password plugin used as client plugin.
29
30 This plugin does not encrypt the communication channel in any way. If this is
31 required, a SSL connection should be used.
32
33 To install this plugin, copy the .so file to the plugin directory and do
34
35 INSTALL PLUGIN auth_pam SONAME 'auth_pam_compat.so';
36
37 To use this plugin for one particular user, specify it at user's creation time
38 (TODO: tested with localhost only):
39
40 CREATE USER 'username'@'hostname' IDENTIFIED WITH auth_pam_compat;
41
42 Alternatively UPDATE the mysql.user table to set the plugin value for an
43 existing user.
44
45 Also it is possible to use this plugin to authenticate anonymous users:
46
47 CREATE USER ''@'hostname' IDENTIFIED WITH auth_pam_compat;
48
49*/
50
51#ifdef HAVE_CONFIG_H
52#include "config.h"
53#endif
54
55#include "auth_pam_common.h"
56
57int auth_pam_client_talk_init(void **talk_data)
58{
59 int *num_talks= calloc(1, sizeof(int));
60 *talk_data= (void*)num_talks;
61 return (num_talks != NULL) ? PAM_SUCCESS : PAM_BUF_ERR;
62}
63
64void auth_pam_client_talk_finalize(void *talk_data)
65{
66 free(talk_data);
67}
68
69int auth_pam_talk_perform(const struct pam_message *msg,
70 struct pam_response *resp,
71 struct pam_conv_data *data,
72 void *talk_data)
73{
74 int pkt_len;
75 unsigned char *pkt;
76 int *num_talks= (int*)talk_data;
77
78 if (msg->msg_style == PAM_PROMPT_ECHO_OFF
79 || msg->msg_style == PAM_PROMPT_ECHO_ON)
80 {
81 /* mysql_clear_password plugin has support for only single phrase */
82 if (*num_talks > 1)
83 return PAM_CONV_ERR;
84
85 /* Read the answer */
86 if ((pkt_len= data->vio->read_packet(data->vio, &pkt))
87 < 0)
88 return PAM_CONV_ERR;
89
90 resp->resp= malloc(pkt_len + 1);
91 if (resp->resp == NULL)
92 return PAM_BUF_ERR;
93
94 strncpy(resp->resp, (char *)pkt, pkt_len);
95 resp->resp[pkt_len]= '\0';
96
97 /* we could only guess whether password was used or not */
98 data->info->password_used= PASSWORD_USED_NO_MENTION;
99 ++(*num_talks);
100 }
101
102 return PAM_SUCCESS;
103}
104
105static struct st_mysql_auth pam_auth_handler=
106{
107 MYSQL_AUTHENTICATION_INTERFACE_VERSION,
108 "mysql_clear_password",
109 &authenticate_user_with_pam_server
110};
111
112mysql_declare_plugin(auth_pam)
113{
114 MYSQL_AUTHENTICATION_PLUGIN,
115 &pam_auth_handler,
116 "auth_pam_compat",
117 "Percona, Inc.",
118 "PAM authentication plugin",
119 PLUGIN_LICENSE_GPL,
120 NULL,
121 NULL,
122 0x0001,
123 NULL,
124 NULL,
125 NULL
126#if MYSQL_PLUGIN_INTERFACE_VERSION >= 0x103
127 ,
128 0
129#endif
130}
131mysql_declare_plugin_end;

Subscribers

People subscribed via source and target branches