38
38
To install this plugin, copy the .so file to the plugin directory and do
40
INSTALL PLUGIN auth_pam_server SONAME 'auth_pam.so';
40
INSTALL PLUGIN auth_pam SONAME 'auth_pam.so';
42
42
To use this plugin for one particular user, specify it at user's creation time
43
43
(TODO: tested with localhost only):
45
CREATE USER 'username'@'hostname' IDENTIFIED WITH auth_pam_server;
45
CREATE USER 'username'@'hostname' IDENTIFIED WITH auth_pam;
47
47
Alternatively UPDATE the mysql.user table to set the plugin value for an
146
156
for (i = 0; i < num_msg; i++)
150
158
if (!valid_pam_msg_style(msg[i]->msg_style))
152
160
free_pam_response(resp, i);
153
161
return PAM_CONV_ERR;
156
/* Format the message. The first byte is the message type, followed by the
157
NUL-terminated message string itself. */
158
buf= malloc(strlen(msg[i]->msg) + 2);
161
free_pam_response(resp, i);
164
buf[0]= pam_msg_style_to_char(msg[i]->msg_style);
165
strcpy(buf + 1, msg[i]->msg);
167
/* Write the message. */
168
if (vio->write_packet(vio, (unsigned char *)buf, strlen(buf) + 1))
171
free_pam_response(resp, i);
176
/* Is the answer expected? */
177
if ((msg[i]->msg_style != PAM_PROMPT_ECHO_ON)
178
&& (msg[i]->msg_style != PAM_PROMPT_ECHO_OFF))
181
/* Read the answer */
182
if ((pkt_len= vio->read_packet(vio, (unsigned char **)&buf)) < 0)
184
free_pam_response(resp, i);
188
(*resp)[i].resp= malloc(pkt_len + 1);
189
if ((*resp)[i].resp == NULL)
191
free_pam_response(resp, i);
194
strncpy((*resp)[i].resp, buf, pkt_len);
195
(*resp)[i].resp[pkt_len]= '\0';
164
/* Append the PAM message or prompt to the unsent message buffer */
167
unsigned char *last_buf_pos = data->buf + max_pam_buffered_msg_len - 1;
168
if (data->ptr + strlen(msg[i]->msg) >= last_buf_pos)
170
free_pam_response(resp, i);
171
/* Cannot happen: the PAM message buffer too small. */
172
MY_ASSERT_UNREACHABLE();
175
memcpy(data->ptr, msg[i]->msg, strlen(msg[i]->msg));
176
data->ptr+= strlen(msg[i]->msg);
177
*(data->ptr)++= '\n';
180
if (msg[i]->msg_style == PAM_PROMPT_ECHO_OFF
181
|| msg[i]->msg_style == PAM_PROMPT_ECHO_ON)
186
/* Magic byte for the dialog plugin, '\2' is defined as ORDINARY_QUESTION
187
and '\4' as PASSWORD_QUESTION there. */
188
data->buf[0]= (msg[i]->msg_style == PAM_PROMPT_ECHO_ON ? '\2' : '\4');
190
/* Write the message. */
191
if (data->vio->write_packet(data->vio, data->buf,
192
data->ptr - data->buf - 1))
194
free_pam_response(resp, i);
198
/* Read the answer */
199
if ((pkt_len= data->vio->read_packet(data->vio, &pkt))
202
free_pam_response(resp, i);
206
(*resp)[i].resp= malloc(pkt_len + 1);
207
if ((*resp)[i].resp == NULL)
209
free_pam_response(resp, i);
213
strncpy((*resp)[i].resp, (char *)pkt, pkt_len);
214
(*resp)[i].resp[pkt_len]= '\0';
216
if (msg[i]->msg_style == PAM_PROMPT_ECHO_OFF)
217
data->info->password_used= PASSWORD_USED_YES;
219
data->ptr= data->buf + 1;
197
222
return PAM_SUCCESS;
201
226
MYSQL_SERVER_AUTH_INFO *info)
203
228
pam_handle_t *pam_handle;
204
struct pam_conv conv_func_info= { &vio_server_conv, vio };
229
struct pam_conv_data data= { vio, info, "", data.buf+1 };
230
struct pam_conv conv_func_info= { &vio_server_conv, &data };
206
232
char *pam_mapped_user_name;
208
/* Impossible to tell if PAM will use passwords or something else */
209
234
info->password_used= PASSWORD_USED_NO_MENTION;
211
236
error= pam_start(service_name,
245
/* Send end-of-auth message */
246
if (vio->write_packet(vio, (const unsigned char *)"\0", 1))
248
pam_end(pam_handle, error);
252
270
/* Get the authenticated user name from PAM */
253
271
error= pam_get_item(pam_handle, PAM_USER, (void *)&pam_mapped_user_name);
254
272
if (error != PAM_SUCCESS)
329
347
mysql_declare_plugin_end;
331
/* The client plugin */
333
/* Returns malloc-allocated string, NULL in case of memory error. */
334
static char * prompt_echo_off (const char * prompt)
336
/* TODO: getpass not thread safe. Probably not a big deal in the mysql
337
client program, but may be missing on non-glibc systems. */
338
char* getpass_input= getpass(prompt);
339
return strdup(getpass_input);
342
/* Returns malloc-allocated string, NULL in case of memory or (unlikely)
344
static char * prompt_echo_on (const char * prompt)
347
char fgets_buf[1024];
348
fputs(prompt, stdout);
350
c= fgets(fgets_buf, sizeof(fgets_buf), stdin);
357
if ((c= strchr(fgets_buf, '\n')))
360
fgets_buf[sizeof(fgets_buf) - 1]= '\0';
361
return strdup(fgets_buf);
364
static void show_error(const char * message)
366
fprintf(stderr, "ERROR %s\n", message);
369
static void show_info(const char * message)
371
printf("%s\n", message);
374
static int authenticate_user_with_pam_client (MYSQL_PLUGIN_VIO *vio,
375
struct st_mysql *mysql)
377
return authenticate_user_with_pam_client_common (vio, mysql,
380
&show_error, &show_info);
383
mysql_declare_client_plugin(AUTHENTICATION)
386
"PAM authentication plugin",
393
&authenticate_user_with_pam_client
394
mysql_end_client_plugin;