Merge lp:~sergei.glushchenko/percona-pam-for-mysql/two-plugins into lp:percona-pam-for-mysql
- two-plugins
- Merge into percona-pam-for-mysql
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 |
Related bugs: | |
Related blueprints: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Laurynas Biveinis (community) | Approve | ||
Review via email: mp+92716@code.launchpad.net |
Commit message
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_
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_
Preview Diff
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2012-02-09 16:25:22 +0000 |
3 | +++ CMakeLists.txt 2012-02-13 06:42:18 +0000 |
4 | @@ -19,9 +19,12 @@ |
5 | CHECK_SYMBOL_EXISTS(getpwnam_r "pwd.h" HAVE_GETPWNAM_R) |
6 | CHECK_SYMBOL_EXISTS(getgrgid_r "grp.h" HAVE_GETGRGID_R) |
7 | IF(HAVE_PAM AND HAVE_MYSQLCLIENT AND HAVE_GETPWNAM_R AND HAVE_GETGRGID_R) |
8 | - SET(AUTH_PAM_SOURCES |
9 | - src/auth_pam.c src/lib_auth_pam_client.c src/lib_auth_pam_client.h |
10 | + SET(AUTH_PAM_COMMON_SOURCES |
11 | + src/auth_pam_common.c src/lib_auth_pam_client.c src/lib_auth_pam_client.h |
12 | src/auth_mapping.h src/auth_mapping.c) |
13 | + SET(AUTH_PAM_SOURCES ${AUTH_PAM_COMMON_SOURCES} src/auth_pam.c) |
14 | + SET(AUTH_PAM_COMPAT_SOURCES ${AUTH_PAM_COMMON_SOURCES} src/auth_pam_compat.c) |
15 | MYSQL_ADD_PLUGIN(auth_pam ${AUTH_PAM_SOURCES} LINK_LIBRARIES pam) |
16 | + MYSQL_ADD_PLUGIN(auth_pam_compat ${AUTH_PAM_COMPAT_SOURCES} LINK_LIBRARIES pam) |
17 | MYSQL_ADD_PLUGIN(dialog src/dialog.c LINK_LIBRARIES mysqlclient) |
18 | ENDIF(HAVE_PAM AND HAVE_MYSQLCLIENT AND HAVE_GETPWNAM_R AND HAVE_GETGRGID_R) |
19 | |
20 | === modified file 'src/Makefile.am' |
21 | --- src/Makefile.am 2012-02-10 04:21:32 +0000 |
22 | +++ src/Makefile.am 2012-02-13 06:42:18 +0000 |
23 | @@ -16,14 +16,18 @@ |
24 | |
25 | plugindir = @PLUGINDIR@ |
26 | |
27 | -plugin_LTLIBRARIES = auth_pam.la test_auth_pam_client.la dialog.la |
28 | +plugin_LTLIBRARIES = auth_pam.la auth_pam_compat.la test_auth_pam_client.la dialog.la |
29 | plugin_CPPFLAGS = -DMYSQL_DYNAMIC_PLUGIN |
30 | plugin_LDFLAGS = -module -avoid-version -shared |
31 | |
32 | -auth_pam_la_SOURCES = auth_pam.c lib_auth_pam_client.h lib_auth_pam_client.c auth_mapping.c |
33 | +auth_pam_la_SOURCES = auth_pam_common.c auth_pam.c lib_auth_pam_client.h lib_auth_pam_client.c auth_mapping.c |
34 | auth_pam_la_CPPFLAGS = $(plugin_CPPFLAGS) |
35 | auth_pam_la_LDFLAGS = $(plugin_LDFLAGS) $(AUTH_PAM_LIBS) |
36 | |
37 | +auth_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 |
38 | +auth_pam_compat_la_CPPFLAGS = $(plugin_CPPFLAGS) |
39 | +auth_pam_compat_la_LDFLAGS = $(plugin_LDFLAGS) $(AUTH_PAM_LIBS) |
40 | + |
41 | test_auth_pam_client_la_SOURCES = test_auth_pam_client.c \ |
42 | lib_auth_pam_client.h lib_auth_pam_client.c |
43 | test_auth_pam_client_la_LDFLAGS = $(plugin_LDFLAGS) |
44 | |
45 | === modified file 'src/auth_mapping.h' |
46 | --- src/auth_mapping.h 2012-02-09 16:25:22 +0000 |
47 | +++ src/auth_mapping.h 2012-02-13 06:42:18 +0000 |
48 | @@ -20,9 +20,8 @@ |
49 | /** |
50 | @file |
51 | |
52 | - PAM authentication for MySQL, common definitions for side plugins. |
53 | + PAM authentication for MySQL, interface for user mapping. |
54 | |
55 | - For the general description, see the top comment in auth_pam.c. |
56 | */ |
57 | |
58 | #ifdef __cplusplus |
59 | |
60 | === added file 'src/auth_pam.c' |
61 | --- src/auth_pam.c 1970-01-01 00:00:00 +0000 |
62 | +++ src/auth_pam.c 2012-02-13 06:42:18 +0000 |
63 | @@ -0,0 +1,175 @@ |
64 | +/* |
65 | +(C) 2012 Percona Inc. |
66 | + |
67 | +This program is free software; you can redistribute it and/or modify |
68 | +it under the terms of the GNU General Public License as published by |
69 | +the Free Software Foundation; version 2 of the License. |
70 | + |
71 | +This program is distributed in the hope that it will be useful, |
72 | +but WITHOUT ANY WARRANTY; without even the implied warranty of |
73 | +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
74 | +GNU General Public License for more details. |
75 | + |
76 | +You should have received a copy of the GNU General Public License |
77 | +along with this program; if not, write to the Free Software |
78 | +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
79 | +*/ |
80 | + |
81 | +/** |
82 | + @file |
83 | + |
84 | + PAM authentication for MySQL, server-side plugin for the |
85 | + production use. |
86 | + |
87 | + A general-purpose PAM authentication plugin for MySQL. Acts as a mediator |
88 | + between the MySQL server, the MySQL client, and the PAM backend. Dialog plugin |
89 | + used as client plugin. |
90 | + |
91 | + The server plugin requests authentication from the PAM backend, forwards any |
92 | + requests and messages from the PAM backend over the wire to the client (in |
93 | + cleartext) and reads back any replies for the backend. |
94 | + |
95 | + This plugin does not encrypt the communication channel in any way. If this is |
96 | + required, a SSL connection should be used. |
97 | + |
98 | + To install this plugin, copy the .so file to the plugin directory and do |
99 | + |
100 | + INSTALL PLUGIN auth_pam SONAME 'auth_pam.so'; |
101 | + |
102 | + To use this plugin for one particular user, specify it at user's creation time |
103 | + (TODO: tested with localhost only): |
104 | + |
105 | + CREATE USER 'username'@'hostname' IDENTIFIED WITH auth_pam; |
106 | + |
107 | + Alternatively UPDATE the mysql.user table to set the plugin value for an |
108 | + existing user. |
109 | + |
110 | + Also it is possible to use this plugin to authenticate anonymous users: |
111 | + |
112 | + CREATE USER ''@'hostname' IDENTIFIED WITH auth_pam; |
113 | + |
114 | +*/ |
115 | + |
116 | +#ifdef HAVE_CONFIG_H |
117 | +#include "config.h" |
118 | +#endif |
119 | + |
120 | +#include "auth_pam_common.h" |
121 | + |
122 | +/** The maximum length of buffered PAM messages, i.e. any messages up to the |
123 | + next PAM reply-requiring message. 10K should be more than enough by order |
124 | + of magnitude. */ |
125 | +enum { max_pam_buffered_msg_len = 10240 }; |
126 | + |
127 | +struct pam_msg_buf { |
128 | + unsigned char buf[max_pam_buffered_msg_len]; |
129 | + unsigned char* ptr; |
130 | +}; |
131 | + |
132 | +static char pam_msg_style_to_char (int pam_msg_style) |
133 | +{ |
134 | + /* Magic byte for the dialog plugin, '\2' is defined as ORDINARY_QUESTION |
135 | + and '\4' as PASSWORD_QUESTION there. */ |
136 | + return (pam_msg_style == PAM_PROMPT_ECHO_ON) ? '\2' : '\4'; |
137 | +} |
138 | + |
139 | +int auth_pam_client_talk_init(void **talk_data) |
140 | +{ |
141 | + struct pam_msg_buf *msg_buf= calloc(1, sizeof(struct pam_msg_buf)); |
142 | + *talk_data= (void*)msg_buf; |
143 | + if (msg_buf != NULL) |
144 | + { |
145 | + msg_buf->ptr= msg_buf->buf + 1; |
146 | + return PAM_SUCCESS; |
147 | + } |
148 | + return PAM_BUF_ERR; |
149 | +} |
150 | + |
151 | +void auth_pam_client_talk_finalize(void *talk_data) |
152 | +{ |
153 | + free(talk_data); |
154 | +} |
155 | + |
156 | +int auth_pam_talk_perform(const struct pam_message *msg, |
157 | + struct pam_response *resp, |
158 | + struct pam_conv_data *data, |
159 | + void *talk_data) |
160 | +{ |
161 | + struct pam_msg_buf *msg_buf= (struct pam_msg_buf*)talk_data; |
162 | + |
163 | + /* Append the PAM message or prompt to the unsent message buffer */ |
164 | + if (msg->msg) |
165 | + { |
166 | + unsigned char *last_buf_pos = msg_buf->buf + max_pam_buffered_msg_len - 1; |
167 | + if (msg_buf->ptr + strlen(msg->msg) >= last_buf_pos) |
168 | + { |
169 | + /* Cannot happen: the PAM message buffer too small. */ |
170 | + MY_ASSERT_UNREACHABLE(); |
171 | + return PAM_CONV_ERR; |
172 | + } |
173 | + memcpy(msg_buf->ptr, msg->msg, strlen(msg->msg)); |
174 | + msg_buf->ptr+= strlen(msg->msg); |
175 | + *(msg_buf->ptr)++= '\n'; |
176 | + } |
177 | + |
178 | + if (msg->msg_style == PAM_PROMPT_ECHO_OFF |
179 | + || msg->msg_style == PAM_PROMPT_ECHO_ON) |
180 | + { |
181 | + int pkt_len; |
182 | + unsigned char *pkt; |
183 | + |
184 | + msg_buf->buf[0]= pam_msg_style_to_char(msg->msg_style); |
185 | + |
186 | + /* Write the message. */ |
187 | + if (data->vio->write_packet(data->vio, msg_buf->buf, |
188 | + msg_buf->ptr - msg_buf->buf - 1)) |
189 | + return PAM_CONV_ERR; |
190 | + |
191 | + /* Read the answer */ |
192 | + if ((pkt_len= data->vio->read_packet(data->vio, &pkt)) |
193 | + < 0) |
194 | + return PAM_CONV_ERR; |
195 | + |
196 | + resp->resp= malloc(pkt_len + 1); |
197 | + if (resp->resp == NULL) |
198 | + return PAM_BUF_ERR; |
199 | + |
200 | + strncpy(resp->resp, (char *)pkt, pkt_len); |
201 | + resp->resp[pkt_len]= '\0'; |
202 | + |
203 | + if (msg->msg_style == PAM_PROMPT_ECHO_OFF) |
204 | + data->info->password_used= PASSWORD_USED_YES; |
205 | + |
206 | + msg_buf->ptr= msg_buf->buf + 1; |
207 | + } |
208 | + |
209 | + return PAM_SUCCESS; |
210 | +} |
211 | + |
212 | +static struct st_mysql_auth pam_auth_handler= |
213 | +{ |
214 | + MYSQL_AUTHENTICATION_INTERFACE_VERSION, |
215 | + "dialog", |
216 | + &authenticate_user_with_pam_server |
217 | +}; |
218 | + |
219 | +mysql_declare_plugin(auth_pam) |
220 | +{ |
221 | + MYSQL_AUTHENTICATION_PLUGIN, |
222 | + &pam_auth_handler, |
223 | + "auth_pam", |
224 | + "Percona, Inc.", |
225 | + "PAM authentication plugin", |
226 | + PLUGIN_LICENSE_GPL, |
227 | + NULL, |
228 | + NULL, |
229 | + 0x0001, |
230 | + NULL, |
231 | + NULL, |
232 | + NULL |
233 | +#if MYSQL_PLUGIN_INTERFACE_VERSION >= 0x103 |
234 | + , |
235 | + 0 |
236 | +#endif |
237 | +} |
238 | +mysql_declare_plugin_end; |
239 | |
240 | === renamed file 'src/auth_pam.c' => 'src/auth_pam_common.c' |
241 | --- src/auth_pam.c 2012-02-09 16:25:22 +0000 |
242 | +++ src/auth_pam_common.c 2012-02-13 06:42:18 +0000 |
243 | @@ -15,69 +15,11 @@ |
244 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
245 | */ |
246 | |
247 | -/** |
248 | - @file |
249 | - |
250 | - PAM authentication for MySQL, server- and client-side plugins for the |
251 | - production use. |
252 | - |
253 | - A general-purpose PAM authentication plugin for MySQL. Acts as a mediator |
254 | - between the MySQL server, the MySQL client, and the PAM backend. Consists of |
255 | - both the server and the client plugin. |
256 | - |
257 | - The server plugin requests authentication from the PAM backend, forwards any |
258 | - requests and messages from the PAM backend over the wire to the client (in |
259 | - cleartext) and reads back any replies for the backend. |
260 | - |
261 | - The client plugin inputs from the TTY any requested info/passwords as |
262 | - requested and sends them back over the wire to the server. |
263 | - |
264 | - This plugin does not encrypt the communication channel in any way. If this is |
265 | - required, a SSL connection should be used. |
266 | - |
267 | - To install this plugin, copy the .so file to the plugin directory and do |
268 | - |
269 | - INSTALL PLUGIN auth_pam SONAME 'auth_pam.so'; |
270 | - |
271 | - To use this plugin for one particular user, specify it at user's creation time |
272 | - (TODO: tested with localhost only): |
273 | - |
274 | - CREATE USER 'username'@'hostname' IDENTIFIED WITH auth_pam; |
275 | - |
276 | - Alternatively UPDATE the mysql.user table to set the plugin value for an |
277 | - existing user. |
278 | - |
279 | - Also it is possible to use this plugin to authenticate anonymous users: |
280 | - |
281 | - CREATE USER ''@'hostname' IDENTIFIED WITH auth_pam; |
282 | - |
283 | -*/ |
284 | #ifdef HAVE_CONFIG_H |
285 | #include "config.h" |
286 | #endif |
287 | |
288 | -#include <assert.h> |
289 | - |
290 | -#include <security/pam_appl.h> |
291 | -#include <security/pam_modules.h> |
292 | -#include <security/pam_misc.h> |
293 | - |
294 | -/* Define these macros ourselves, so we don't have to include my_global.h and |
295 | -can compile against unconfigured MySQL source tree. */ |
296 | -#define STDCALL |
297 | - |
298 | -#define MY_ASSERT_UNREACHABLE() assert(0) |
299 | - |
300 | -#include <mysql/plugin.h> |
301 | -#include <mysql/plugin_auth.h> |
302 | -#include <mysql/client_plugin.h> |
303 | - |
304 | -#ifdef HAVE_GETPASS |
305 | -#include <unistd.h> /* getpass() */ |
306 | -#else |
307 | -#error "Please add support for echo-less input for your platform" |
308 | -#endif |
309 | - |
310 | +#include "auth_pam_common.h" |
311 | #include "auth_mapping.h" |
312 | |
313 | /* The server plugin */ |
314 | @@ -99,37 +41,10 @@ |
315 | } |
316 | } |
317 | |
318 | -static char pam_msg_style_to_char (int pam_msg_style) |
319 | -{ |
320 | - /* Do not use any of MySQL client-server protocol reserved values, i.e. \0 */ |
321 | - switch (pam_msg_style) |
322 | - { |
323 | - case PAM_PROMPT_ECHO_OFF: return '\2'; |
324 | - case PAM_PROMPT_ECHO_ON: return '\3'; |
325 | - case PAM_ERROR_MSG: return '\4'; |
326 | - case PAM_TEXT_INFO: return '\5'; |
327 | - default: |
328 | - MY_ASSERT_UNREACHABLE(); |
329 | - return '\1'; |
330 | - } |
331 | -} |
332 | - |
333 | -/** The maximum length of buffered PAM messages, i.e. any messages up to the |
334 | - next PAM reply-requiring message. 10K should be more than enough by order |
335 | - of magnitude. */ |
336 | -enum { max_pam_buffered_msg_len = 10240 }; |
337 | - |
338 | /** The maximum length of service name. It shouldn't be too long as it's |
339 | filename in pam.d directory also */ |
340 | enum { max_pam_service_name_len = 64 }; |
341 | |
342 | -struct pam_conv_data { |
343 | - MYSQL_PLUGIN_VIO *vio; |
344 | - MYSQL_SERVER_AUTH_INFO *info; |
345 | - unsigned char buf[max_pam_buffered_msg_len]; |
346 | - unsigned char* ptr; |
347 | -}; |
348 | - |
349 | static void free_pam_response (struct pam_response ** resp, int n) |
350 | { |
351 | int i; |
352 | @@ -145,6 +60,8 @@ |
353 | struct pam_response ** resp, void *appdata_ptr) |
354 | { |
355 | int i; |
356 | + int error; |
357 | + void *talk_data; |
358 | struct pam_conv_data *data= (struct pam_conv_data *)appdata_ptr; |
359 | |
360 | if (data == NULL) |
361 | @@ -157,80 +74,39 @@ |
362 | if (*resp == NULL) |
363 | return PAM_BUF_ERR; |
364 | |
365 | + error= auth_pam_client_talk_init(&talk_data); |
366 | + if (error != PAM_SUCCESS) |
367 | + { |
368 | + free_pam_response(resp, 0); |
369 | + return error; |
370 | + } |
371 | + |
372 | for (i = 0; i < num_msg; i++) |
373 | { |
374 | if (!valid_pam_msg_style(msg[i]->msg_style)) |
375 | { |
376 | + auth_pam_client_talk_finalize(talk_data); |
377 | free_pam_response(resp, i); |
378 | return PAM_CONV_ERR; |
379 | } |
380 | |
381 | - /* Append the PAM message or prompt to the unsent message buffer */ |
382 | - if (msg[i]->msg) |
383 | - { |
384 | - unsigned char *last_buf_pos = data->buf + max_pam_buffered_msg_len - 1; |
385 | - if (data->ptr + strlen(msg[i]->msg) >= last_buf_pos) |
386 | - { |
387 | - free_pam_response(resp, i); |
388 | - /* Cannot happen: the PAM message buffer too small. */ |
389 | - MY_ASSERT_UNREACHABLE(); |
390 | - return PAM_CONV_ERR; |
391 | - } |
392 | - memcpy(data->ptr, msg[i]->msg, strlen(msg[i]->msg)); |
393 | - data->ptr+= strlen(msg[i]->msg); |
394 | - *(data->ptr)++= '\n'; |
395 | - } |
396 | - |
397 | - if (msg[i]->msg_style == PAM_PROMPT_ECHO_OFF |
398 | - || msg[i]->msg_style == PAM_PROMPT_ECHO_ON) |
399 | - { |
400 | - int pkt_len; |
401 | - unsigned char *pkt; |
402 | - |
403 | - /* Magic byte for the dialog plugin, '\2' is defined as ORDINARY_QUESTION |
404 | - and '\4' as PASSWORD_QUESTION there. */ |
405 | - data->buf[0]= (msg[i]->msg_style == PAM_PROMPT_ECHO_ON ? '\2' : '\4'); |
406 | - |
407 | - /* Write the message. */ |
408 | - if (data->vio->write_packet(data->vio, data->buf, |
409 | - data->ptr - data->buf - 1)) |
410 | - { |
411 | - free_pam_response(resp, i); |
412 | - return PAM_CONV_ERR; |
413 | - } |
414 | - |
415 | - /* Read the answer */ |
416 | - if ((pkt_len= data->vio->read_packet(data->vio, &pkt)) |
417 | - < 0) |
418 | - { |
419 | - free_pam_response(resp, i); |
420 | - return PAM_CONV_ERR; |
421 | - } |
422 | - |
423 | - (*resp)[i].resp= malloc(pkt_len + 1); |
424 | - if ((*resp)[i].resp == NULL) |
425 | - { |
426 | - free_pam_response(resp, i); |
427 | - return PAM_BUF_ERR; |
428 | - } |
429 | - |
430 | - strncpy((*resp)[i].resp, (char *)pkt, pkt_len); |
431 | - (*resp)[i].resp[pkt_len]= '\0'; |
432 | - |
433 | - if (msg[i]->msg_style == PAM_PROMPT_ECHO_OFF) |
434 | - data->info->password_used= PASSWORD_USED_YES; |
435 | - |
436 | - data->ptr= data->buf + 1; |
437 | + error= auth_pam_talk_perform(msg[i], resp[i], data, talk_data); |
438 | + if (error != PAM_SUCCESS) |
439 | + { |
440 | + auth_pam_client_talk_finalize(talk_data); |
441 | + free_pam_response(resp, i); |
442 | + return error; |
443 | } |
444 | } |
445 | + auth_pam_client_talk_finalize(talk_data); |
446 | return PAM_SUCCESS; |
447 | } |
448 | |
449 | -static int authenticate_user_with_pam_server (MYSQL_PLUGIN_VIO *vio, |
450 | - MYSQL_SERVER_AUTH_INFO *info) |
451 | +int authenticate_user_with_pam_server (MYSQL_PLUGIN_VIO *vio, |
452 | + MYSQL_SERVER_AUTH_INFO *info) |
453 | { |
454 | pam_handle_t *pam_handle; |
455 | - struct pam_conv_data data= { vio, info, "", data.buf+1 }; |
456 | + struct pam_conv_data data= { vio, info }; |
457 | struct pam_conv conv_func_info= { &vio_server_conv, &data }; |
458 | int error; |
459 | char *pam_mapped_user_name; |
460 | @@ -312,57 +188,3 @@ |
461 | |
462 | return CR_OK; |
463 | } |
464 | - |
465 | -static struct st_mysql_auth pam_auth_handler= |
466 | -{ |
467 | - MYSQL_AUTHENTICATION_INTERFACE_VERSION, |
468 | - "dialog", |
469 | - &authenticate_user_with_pam_server |
470 | -}; |
471 | - |
472 | -static struct st_mysql_auth test_pam_auth_handler= |
473 | -{ |
474 | - MYSQL_AUTHENTICATION_INTERFACE_VERSION, |
475 | - "auth_pam_test", |
476 | - &authenticate_user_with_pam_server |
477 | -}; |
478 | - |
479 | -mysql_declare_plugin(auth_pam) |
480 | -{ |
481 | - MYSQL_AUTHENTICATION_PLUGIN, |
482 | - &pam_auth_handler, |
483 | - "auth_pam", |
484 | - "Percona, Inc.", |
485 | - "PAM authentication plugin", |
486 | - PLUGIN_LICENSE_GPL, |
487 | - NULL, |
488 | - NULL, |
489 | - 0x0001, |
490 | - NULL, |
491 | - NULL, |
492 | - NULL |
493 | -#if MYSQL_PLUGIN_INTERFACE_VERSION >= 0x103 |
494 | - , |
495 | - 0 |
496 | -#endif |
497 | -}, |
498 | -{ |
499 | - MYSQL_AUTHENTICATION_PLUGIN, |
500 | - &test_pam_auth_handler, |
501 | - "test_auth_pam_server", |
502 | - "Percona, Inc.", |
503 | - "PAM authentication plugin that requests the test version of the" |
504 | - " client-side plugin. DO NOT USE IN PRODUCTION.", |
505 | - PLUGIN_LICENSE_GPL, |
506 | - NULL, |
507 | - NULL, |
508 | - 0x0001, |
509 | - NULL, |
510 | - NULL, |
511 | - NULL |
512 | -#if MYSQL_PLUGIN_INTERFACE_VERSION >= 0x103 |
513 | - , |
514 | - 0 |
515 | -#endif |
516 | -} |
517 | -mysql_declare_plugin_end; |
518 | |
519 | === added file 'src/auth_pam_common.h' |
520 | --- src/auth_pam_common.h 1970-01-01 00:00:00 +0000 |
521 | +++ src/auth_pam_common.h 2012-02-13 06:42:18 +0000 |
522 | @@ -0,0 +1,71 @@ |
523 | +#ifndef AUTH_PAM_COMMON_INCLUDED |
524 | +#define AUTH_PAM_COMMON_INCLUDED |
525 | +/* |
526 | + (C) 2012 Percona Inc. |
527 | + |
528 | + This program is free software; you can redistribute it and/or modify |
529 | + it under the terms of the GNU General Public License as published by |
530 | + the Free Software Foundation; version 2 of the License. |
531 | + |
532 | + This program is distributed in the hope that it will be useful, |
533 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
534 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
535 | + GNU General Public License for more details. |
536 | + |
537 | + You should have received a copy of the GNU General Public License |
538 | + along with this program; if not, write to the Free Software |
539 | + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
540 | +*/ |
541 | + |
542 | +/** |
543 | + @file |
544 | + |
545 | + PAM authentication for MySQL, common definitions for side plugins. |
546 | + |
547 | + For the general description, see the top comment in auth_pam_common.c. |
548 | +*/ |
549 | + |
550 | +/* Define these macros ourselves, so we don't have to include my_global.h and |
551 | +can compile against unconfigured MySQL source tree. */ |
552 | +#define STDCALL |
553 | + |
554 | +#include <security/pam_appl.h> |
555 | +#include <security/pam_modules.h> |
556 | +#include <security/pam_misc.h> |
557 | + |
558 | +#include <mysql/plugin.h> |
559 | +#include <mysql/plugin_auth.h> |
560 | +#include <mysql/client_plugin.h> |
561 | + |
562 | +#include <assert.h> |
563 | + |
564 | +#define MY_ASSERT_UNREACHABLE() assert(0) |
565 | + |
566 | +#ifdef __cplusplus |
567 | +extern "C" { |
568 | +#endif |
569 | + |
570 | +struct pam_conv_data { |
571 | + MYSQL_PLUGIN_VIO *vio; |
572 | + MYSQL_SERVER_AUTH_INFO *info; |
573 | +}; |
574 | + |
575 | +/** Define following three functions for your specific client plugin */ |
576 | + |
577 | +int auth_pam_client_talk_init(void **talk_data); |
578 | + |
579 | +int auth_pam_talk_perform(const struct pam_message *msg, |
580 | + struct pam_response *resp, |
581 | + struct pam_conv_data *data, |
582 | + void *talk_data); |
583 | + |
584 | +void auth_pam_client_talk_finalize(void *talk_data); |
585 | + |
586 | +int authenticate_user_with_pam_server (MYSQL_PLUGIN_VIO *vio, |
587 | + MYSQL_SERVER_AUTH_INFO *info); |
588 | + |
589 | +#ifdef __cplusplus |
590 | +} |
591 | +#endif |
592 | + |
593 | +#endif |
594 | |
595 | === added file 'src/auth_pam_compat.c' |
596 | --- src/auth_pam_compat.c 1970-01-01 00:00:00 +0000 |
597 | +++ src/auth_pam_compat.c 2012-02-13 06:42:18 +0000 |
598 | @@ -0,0 +1,131 @@ |
599 | +/* |
600 | +(C) 2012 Percona Inc. |
601 | + |
602 | +This program is free software; you can redistribute it and/or modify |
603 | +it under the terms of the GNU General Public License as published by |
604 | +the Free Software Foundation; version 2 of the License. |
605 | + |
606 | +This program is distributed in the hope that it will be useful, |
607 | +but WITHOUT ANY WARRANTY; without even the implied warranty of |
608 | +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
609 | +GNU General Public License for more details. |
610 | + |
611 | +You should have received a copy of the GNU General Public License |
612 | +along with this program; if not, write to the Free Software |
613 | +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
614 | +*/ |
615 | + |
616 | +/** |
617 | + @file |
618 | + |
619 | + PAM authentication for MySQL, server-side plugin for the |
620 | + production use. |
621 | + |
622 | + Oracle MySQL-compatible plugin. Acts as a mediator |
623 | + between the MySQL server, the MySQL client, and the PAM backend. |
624 | + |
625 | + The server plugin requests authentication from the PAM backend, and reads one |
626 | + phrase from client plugin. mysql_clear_password plugin used as client plugin. |
627 | + |
628 | + This plugin does not encrypt the communication channel in any way. If this is |
629 | + required, a SSL connection should be used. |
630 | + |
631 | + To install this plugin, copy the .so file to the plugin directory and do |
632 | + |
633 | + INSTALL PLUGIN auth_pam SONAME 'auth_pam_compat.so'; |
634 | + |
635 | + To use this plugin for one particular user, specify it at user's creation time |
636 | + (TODO: tested with localhost only): |
637 | + |
638 | + CREATE USER 'username'@'hostname' IDENTIFIED WITH auth_pam_compat; |
639 | + |
640 | + Alternatively UPDATE the mysql.user table to set the plugin value for an |
641 | + existing user. |
642 | + |
643 | + Also it is possible to use this plugin to authenticate anonymous users: |
644 | + |
645 | + CREATE USER ''@'hostname' IDENTIFIED WITH auth_pam_compat; |
646 | + |
647 | +*/ |
648 | + |
649 | +#ifdef HAVE_CONFIG_H |
650 | +#include "config.h" |
651 | +#endif |
652 | + |
653 | +#include "auth_pam_common.h" |
654 | + |
655 | +int auth_pam_client_talk_init(void **talk_data) |
656 | +{ |
657 | + int *num_talks= calloc(1, sizeof(int)); |
658 | + *talk_data= (void*)num_talks; |
659 | + return (num_talks != NULL) ? PAM_SUCCESS : PAM_BUF_ERR; |
660 | +} |
661 | + |
662 | +void auth_pam_client_talk_finalize(void *talk_data) |
663 | +{ |
664 | + free(talk_data); |
665 | +} |
666 | + |
667 | +int auth_pam_talk_perform(const struct pam_message *msg, |
668 | + struct pam_response *resp, |
669 | + struct pam_conv_data *data, |
670 | + void *talk_data) |
671 | +{ |
672 | + int pkt_len; |
673 | + unsigned char *pkt; |
674 | + int *num_talks= (int*)talk_data; |
675 | + |
676 | + if (msg->msg_style == PAM_PROMPT_ECHO_OFF |
677 | + || msg->msg_style == PAM_PROMPT_ECHO_ON) |
678 | + { |
679 | + /* mysql_clear_password plugin has support for only single phrase */ |
680 | + if (*num_talks > 1) |
681 | + return PAM_CONV_ERR; |
682 | + |
683 | + /* Read the answer */ |
684 | + if ((pkt_len= data->vio->read_packet(data->vio, &pkt)) |
685 | + < 0) |
686 | + return PAM_CONV_ERR; |
687 | + |
688 | + resp->resp= malloc(pkt_len + 1); |
689 | + if (resp->resp == NULL) |
690 | + return PAM_BUF_ERR; |
691 | + |
692 | + strncpy(resp->resp, (char *)pkt, pkt_len); |
693 | + resp->resp[pkt_len]= '\0'; |
694 | + |
695 | + /* we could only guess whether password was used or not */ |
696 | + data->info->password_used= PASSWORD_USED_NO_MENTION; |
697 | + ++(*num_talks); |
698 | + } |
699 | + |
700 | + return PAM_SUCCESS; |
701 | +} |
702 | + |
703 | +static struct st_mysql_auth pam_auth_handler= |
704 | +{ |
705 | + MYSQL_AUTHENTICATION_INTERFACE_VERSION, |
706 | + "mysql_clear_password", |
707 | + &authenticate_user_with_pam_server |
708 | +}; |
709 | + |
710 | +mysql_declare_plugin(auth_pam) |
711 | +{ |
712 | + MYSQL_AUTHENTICATION_PLUGIN, |
713 | + &pam_auth_handler, |
714 | + "auth_pam_compat", |
715 | + "Percona, Inc.", |
716 | + "PAM authentication plugin", |
717 | + PLUGIN_LICENSE_GPL, |
718 | + NULL, |
719 | + NULL, |
720 | + 0x0001, |
721 | + NULL, |
722 | + NULL, |
723 | + NULL |
724 | +#if MYSQL_PLUGIN_INTERFACE_VERSION >= 0x103 |
725 | + , |
726 | + 0 |
727 | +#endif |
728 | +} |
729 | +mysql_declare_plugin_end; |
LGTM, thank you.