Rewritten using general SQL interface.
Showing
1 changed file
with
373 additions
and
44 deletions
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | 1 | /* GNU Mailutils -- a suite of utilities for electronic mail |
2 | Copyright (C) 2002, 2003 Free Software Foundation, Inc. | 2 | Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. |
3 | 3 | ||
4 | This library is free software; you can redistribute it and/or | 4 | This library is free software; you can redistribute it and/or |
5 | modify it under the terms of the GNU Lesser General Public | 5 | modify it under the terms of the GNU Lesser General Public |
... | @@ -44,23 +44,24 @@ | ... | @@ -44,23 +44,24 @@ |
44 | #include <mailutils/argp.h> | 44 | #include <mailutils/argp.h> |
45 | #include <mailutils/mu_auth.h> | 45 | #include <mailutils/mu_auth.h> |
46 | #include <mailutils/error.h> | 46 | #include <mailutils/error.h> |
47 | #include <mailutils/errno.h> | ||
47 | #include <mailutils/nls.h> | 48 | #include <mailutils/nls.h> |
49 | #include <mailutils/sql.h> | ||
48 | 50 | ||
49 | #ifdef USE_SQL | 51 | #ifdef USE_SQL |
50 | 52 | ||
53 | int sql_interface = 0; | ||
51 | char *mu_sql_getpwnam_query; | 54 | char *mu_sql_getpwnam_query; |
52 | char *mu_sql_getpass_query; | 55 | char *mu_sql_getpass_query; |
53 | char *mu_sql_getpwuid_query; | 56 | char *mu_sql_getpwuid_query; |
54 | 57 | ||
55 | char *mu_sql_host = NULL; /* Hostname to connect to. NULL for UNIX | 58 | char *mu_sql_host = NULL; /* Hostname to connect to. NULL for UNIX |
56 | socket connection */ | 59 | socket connection */ |
57 | char *mu_sql_user = "accounts"; /* Username for mysql access */ | 60 | char *mu_sql_user = "accounts"; /* Username for mysql access */ |
58 | char *mu_sql_passwd = "yurpass"; /* Password for mysql access */ | 61 | char *mu_sql_passwd = "yurpass"; /* Password for mysql access */ |
59 | char *mu_sql_db = "accounts"; /* Database Name */ | 62 | char *mu_sql_db = "accounts"; /* Database Name */ |
60 | char *mu_sql_socket = NULL; /* Socket name to use. Valid only if | ||
61 | connecting via UNIX sockets */ | ||
62 | int mu_sql_port = 0; /* Port number to connect to. | 63 | int mu_sql_port = 0; /* Port number to connect to. |
63 | 0 means default port */ | 64 | 0 means default port */ |
64 | 65 | ||
65 | char * | 66 | char * |
66 | mu_sql_expand_query (const char *query, const char *ustr) | 67 | mu_sql_expand_query (const char *query, const char *ustr) |
... | @@ -130,16 +131,19 @@ mu_sql_expand_query (const char *query, const char *ustr) | ... | @@ -130,16 +131,19 @@ mu_sql_expand_query (const char *query, const char *ustr) |
130 | return res; | 131 | return res; |
131 | } | 132 | } |
132 | 133 | ||
133 | # define ARG_SQL_GETPWNAM 1 | 134 | # define ARG_SQL_INTERFACE 256 |
134 | # define ARG_SQL_GETPWUID 2 | 135 | # define ARG_SQL_GETPWNAM 257 |
135 | # define ARG_SQL_GETPASS 3 | 136 | # define ARG_SQL_GETPWUID 258 |
136 | # define ARG_SQL_HOST 4 | 137 | # define ARG_SQL_GETPASS 259 |
137 | # define ARG_SQL_USER 5 | 138 | # define ARG_SQL_HOST 260 |
138 | # define ARG_SQL_PASSWD 6 | 139 | # define ARG_SQL_USER 261 |
139 | # define ARG_SQL_DB 7 | 140 | # define ARG_SQL_PASSWD 262 |
140 | # define ARG_SQL_PORT 8 | 141 | # define ARG_SQL_DB 263 |
142 | # define ARG_SQL_PORT 264 | ||
141 | 143 | ||
142 | static struct argp_option mu_sql_argp_option[] = { | 144 | static struct argp_option mu_sql_argp_option[] = { |
145 | {"sql-interface", ARG_SQL_INTERFACE, N_("NAME"), 0, | ||
146 | N_("Type of SQL interface to use"), 0}, | ||
143 | {"sql-getpwnam", ARG_SQL_GETPWNAM, N_("QUERY"), 0, | 147 | {"sql-getpwnam", ARG_SQL_GETPWNAM, N_("QUERY"), 0, |
144 | N_("SQL query to retrieve a passwd entry based on username"), 0}, | 148 | N_("SQL query to retrieve a passwd entry based on username"), 0}, |
145 | {"sql-getpwuid", ARG_SQL_GETPWUID, N_("QUERY"), 0, | 149 | {"sql-getpwuid", ARG_SQL_GETPWUID, N_("QUERY"), 0, |
... | @@ -164,6 +168,12 @@ mu_sql_argp_parser (int key, char *arg, struct argp_state *state) | ... | @@ -164,6 +168,12 @@ mu_sql_argp_parser (int key, char *arg, struct argp_state *state) |
164 | { | 168 | { |
165 | switch (key) | 169 | switch (key) |
166 | { | 170 | { |
171 | case ARG_SQL_INTERFACE: | ||
172 | sql_interface = mu_sql_interface_index (arg); | ||
173 | if (sql_interface == 0) | ||
174 | argp_error (state, _("Unknown SQL interface '%s'"), arg); | ||
175 | break; | ||
176 | |||
167 | case ARG_SQL_GETPWNAM: | 177 | case ARG_SQL_GETPWNAM: |
168 | mu_sql_getpwnam_query = arg; | 178 | mu_sql_getpwnam_query = arg; |
169 | break; | 179 | break; |
... | @@ -194,11 +204,6 @@ mu_sql_argp_parser (int key, char *arg, struct argp_state *state) | ... | @@ -194,11 +204,6 @@ mu_sql_argp_parser (int key, char *arg, struct argp_state *state) |
194 | 204 | ||
195 | case ARG_SQL_PORT: | 205 | case ARG_SQL_PORT: |
196 | mu_sql_port = strtoul (arg, NULL, 0); | 206 | mu_sql_port = strtoul (arg, NULL, 0); |
197 | if (mu_sql_port == 0) | ||
198 | { | ||
199 | mu_sql_host = NULL; | ||
200 | mu_sql_socket = arg; | ||
201 | } | ||
202 | break; | 207 | break; |
203 | 208 | ||
204 | default: | 209 | default: |
... | @@ -212,46 +217,370 @@ struct argp mu_sql_argp = { | ... | @@ -212,46 +217,370 @@ struct argp mu_sql_argp = { |
212 | mu_sql_argp_parser, | 217 | mu_sql_argp_parser, |
213 | }; | 218 | }; |
214 | 219 | ||
220 | static int | ||
221 | mu_auth_sql_by_name (struct mu_auth_data **return_data, | ||
222 | const void *key, | ||
223 | void *func_data ARG_UNUSED, | ||
224 | void *call_data ARG_UNUSED) | ||
225 | { | ||
226 | int status, rc; | ||
227 | char *query_str = NULL; | ||
228 | mu_sql_connection_t conn; | ||
229 | size_t n; | ||
230 | |||
231 | if (!key) | ||
232 | { | ||
233 | errno = EINVAL; | ||
234 | return 1; | ||
235 | } | ||
236 | |||
237 | query_str = mu_sql_expand_query (mu_sql_getpwnam_query, key); | ||
238 | |||
239 | if (!query_str) | ||
240 | return 1; | ||
241 | |||
242 | status = mu_sql_connection_init (&conn, | ||
243 | sql_interface, | ||
244 | mu_sql_host, | ||
245 | mu_sql_port, | ||
246 | mu_sql_user, mu_sql_passwd, | ||
247 | mu_sql_db); | ||
248 | |||
249 | if (status) | ||
250 | { | ||
251 | mu_error ("%s. SQL error: %s", | ||
252 | mu_strerror (status), mu_sql_strerror (conn)); | ||
253 | mu_sql_connection_destroy (&conn); | ||
254 | free (query_str); | ||
255 | return status; | ||
256 | } | ||
257 | |||
258 | status = mu_sql_connect (conn); | ||
259 | |||
260 | if (status) | ||
261 | { | ||
262 | mu_error ("%s. SQL error: %s", | ||
263 | mu_strerror (status), mu_sql_strerror (conn)); | ||
264 | mu_sql_connection_destroy (&conn); | ||
265 | free (query_str); | ||
266 | return status; | ||
267 | } | ||
268 | |||
269 | status = mu_sql_query (conn, query_str); | ||
270 | free (query_str); | ||
271 | |||
272 | if (status) | ||
273 | { | ||
274 | mu_error (_("SQL Query failed: %s"), | ||
275 | (status == MU_ERR_SQL) ? mu_sql_strerror (conn) : | ||
276 | mu_strerror (status)); | ||
277 | mu_sql_connection_destroy (&conn); | ||
278 | return 1; | ||
279 | } | ||
280 | |||
281 | status = mu_sql_store_result (conn); | ||
282 | |||
283 | if (status) | ||
284 | { | ||
285 | mu_error (_("cannot store SQL result: %s"), | ||
286 | (status == MU_ERR_SQL) ? mu_sql_strerror (conn) : | ||
287 | mu_strerror (status)); | ||
288 | mu_sql_connection_destroy (&conn); | ||
289 | return 1; | ||
290 | } | ||
291 | |||
292 | mu_sql_num_tuples (conn, &n); | ||
293 | if (n == 0) | ||
294 | { | ||
295 | rc = 1; | ||
296 | } | ||
297 | else | ||
298 | { | ||
299 | char *mailbox_name; | ||
300 | char *name; | ||
301 | |||
302 | mu_sql_get_column (conn, 0, 0, &name); | ||
303 | |||
304 | if (n == 7) | ||
305 | { | ||
306 | char *tmp; | ||
307 | mu_sql_get_column (conn, 0, 6, &tmp); | ||
308 | mailbox_name = strdup (tmp); | ||
309 | } | ||
310 | else | ||
311 | { | ||
312 | mailbox_name = malloc (strlen (mu_path_maildir) + | ||
313 | strlen (name) + 1); | ||
314 | if (mailbox_name) | ||
315 | sprintf (mailbox_name, "%s%s", mu_path_maildir, name); | ||
316 | } | ||
317 | |||
318 | if (mailbox_name) | ||
319 | { | ||
320 | char *passwd, *suid, *sgid, *dir, *shell; | ||
321 | |||
322 | mu_sql_get_column (conn, 0, 1, &passwd); | ||
323 | mu_sql_get_column (conn, 0, 2, &suid); | ||
324 | mu_sql_get_column (conn, 0, 3, &sgid); | ||
325 | mu_sql_get_column (conn, 0, 4, &dir); | ||
326 | mu_sql_get_column (conn, 0, 5, &shell); | ||
327 | |||
328 | rc = mu_auth_data_alloc (return_data, | ||
329 | name, | ||
330 | passwd, | ||
331 | atoi (suid), | ||
332 | atoi (sgid), | ||
333 | "SQL User", | ||
334 | dir, | ||
335 | shell, | ||
336 | mailbox_name, | ||
337 | 1); | ||
338 | } | ||
339 | else | ||
340 | rc = 1; | ||
341 | |||
342 | free (mailbox_name); | ||
343 | } | ||
344 | |||
345 | mu_sql_release_result (conn); | ||
346 | mu_sql_disconnect (conn); | ||
347 | mu_sql_connection_destroy (&conn); | ||
348 | |||
349 | return rc; | ||
350 | } | ||
351 | |||
352 | static int | ||
353 | mu_auth_sql_by_uid (struct mu_auth_data **return_data, | ||
354 | const void *key, | ||
355 | void *func_data ARG_UNUSED, | ||
356 | void *call_data ARG_UNUSED) | ||
357 | { | ||
358 | char uidstr[64]; | ||
359 | int status, rc; | ||
360 | char *query_str = NULL; | ||
361 | mu_sql_connection_t conn; | ||
362 | size_t n; | ||
363 | |||
364 | if (!key) | ||
365 | { | ||
366 | errno = EINVAL; | ||
367 | return 1; | ||
368 | } | ||
369 | |||
370 | snprintf (uidstr, sizeof (uidstr), "%u", *(uid_t*)key); | ||
371 | query_str = mu_sql_expand_query (mu_sql_getpwuid_query, uidstr); | ||
372 | |||
373 | if (!query_str) | ||
374 | return 1; | ||
375 | |||
376 | status = mu_sql_connection_init (&conn, | ||
377 | sql_interface, | ||
378 | mu_sql_host, | ||
379 | mu_sql_port, | ||
380 | mu_sql_user, mu_sql_passwd, | ||
381 | mu_sql_db); | ||
382 | |||
383 | if (status) | ||
384 | { | ||
385 | mu_error ("%s. SQL error: %s", | ||
386 | mu_strerror (status), mu_sql_strerror (conn)); | ||
387 | mu_sql_connection_destroy (&conn); | ||
388 | free (query_str); | ||
389 | return status; | ||
390 | } | ||
391 | |||
392 | status = mu_sql_connect (conn); | ||
215 | 393 | ||
216 | # ifdef HAVE_MYSQL | 394 | if (status) |
217 | int mysql_auth_sql_by_name __P((struct mu_auth_data **return_data, | 395 | { |
218 | const void *key, | 396 | mu_error ("%s. SQL error: %s", |
219 | void *func_data, void *call_data)); | 397 | mu_strerror (status), mu_sql_strerror (conn)); |
220 | int mysql_auth_sql_by_uid __P((struct mu_auth_data **return_data, | 398 | mu_sql_connection_destroy (&conn); |
221 | const void *key, | 399 | free (query_str); |
222 | void *func_data, void *call_data)); | 400 | return status; |
223 | int mysql_sql_authenticate __P((struct mu_auth_data **return_data, | 401 | } |
224 | const void *key, | 402 | |
225 | void *func_data, void *call_data)); | 403 | status = mu_sql_query (conn, query_str); |
404 | free (query_str); | ||
405 | |||
406 | if (status) | ||
407 | { | ||
408 | mu_error (_("SQL Query failed: %s"), | ||
409 | (status == MU_ERR_SQL) ? mu_sql_strerror (conn) : | ||
410 | mu_strerror (status)); | ||
411 | mu_sql_connection_destroy (&conn); | ||
412 | return 1; | ||
413 | } | ||
226 | 414 | ||
227 | # define mu_sql_authenticate mysql_sql_authenticate | 415 | status = mu_sql_store_result (conn); |
228 | # define mu_auth_sql_by_name mysql_auth_sql_by_name | ||
229 | # define mu_auth_sql_by_uid mysql_auth_sql_by_uid | ||
230 | 416 | ||
231 | # endif | 417 | if (status) |
418 | { | ||
419 | mu_error (_("cannot store SQL result: %s"), | ||
420 | (status == MU_ERR_SQL) ? mu_sql_strerror (conn) : | ||
421 | mu_strerror (status)); | ||
422 | mu_sql_connection_destroy (&conn); | ||
423 | return 1; | ||
424 | } | ||
232 | 425 | ||
233 | # ifdef HAVE_PGSQL | 426 | mu_sql_num_tuples (conn, &n); |
234 | int pg_auth_sql_by_name __P((struct mu_auth_data **return_data, void *key, | ||
235 | void *func_data, void *call_data)); | ||
236 | int pg_auth_sql_by_uid __P((struct mu_auth_data **return_data, void *key, | ||
237 | void *func_data, void *call_data)); | ||
238 | int pg_sql_authenticate __P((struct mu_auth_data **return_data, void *key, | ||
239 | void *func_data, void *call_data)); | ||
240 | 427 | ||
241 | # define mu_sql_authenticate pg_sql_authenticate | 428 | if (n == 0) |
242 | # define mu_auth_sql_by_name pg_auth_sql_by_name | 429 | { |
243 | # define mu_auth_sql_by_uid pg_auth_sql_by_uid | 430 | rc = 1; |
431 | } | ||
432 | else | ||
433 | { | ||
434 | char *name; | ||
435 | char *mailbox_name; | ||
436 | |||
437 | mu_sql_get_column (conn, 0, 0, &name); | ||
438 | |||
439 | if (n == 7) | ||
440 | { | ||
441 | char *tmp; | ||
442 | mu_sql_get_column (conn, 0, 6, &tmp); | ||
443 | mailbox_name = strdup (tmp); | ||
444 | } | ||
445 | else | ||
446 | { | ||
447 | mailbox_name = malloc (strlen (mu_path_maildir) + | ||
448 | strlen (name) + 1); | ||
449 | if (mailbox_name) | ||
450 | sprintf (mailbox_name, "%s%s", mu_path_maildir, name); | ||
451 | } | ||
452 | |||
453 | if (mailbox_name) | ||
454 | { | ||
455 | char *passwd, *suid, *sgid, *dir, *shell; | ||
456 | |||
457 | mu_sql_get_column (conn, 0, 1, &passwd); | ||
458 | mu_sql_get_column (conn, 0, 2, &suid); | ||
459 | mu_sql_get_column (conn, 0, 3, &sgid); | ||
460 | mu_sql_get_column (conn, 0, 4, &dir); | ||
461 | mu_sql_get_column (conn, 0, 5, &shell); | ||
462 | |||
463 | rc = mu_auth_data_alloc (return_data, | ||
464 | name, | ||
465 | passwd, | ||
466 | atoi (suid), | ||
467 | atoi (sgid), | ||
468 | "SQL User", | ||
469 | dir, | ||
470 | shell, | ||
471 | mailbox_name, | ||
472 | 1); | ||
473 | } | ||
474 | else | ||
475 | rc = 1; | ||
476 | free (mailbox_name); | ||
477 | } | ||
478 | |||
479 | mu_sql_release_result (conn); | ||
480 | mu_sql_disconnect (conn); | ||
481 | mu_sql_connection_destroy (&conn); | ||
482 | |||
483 | return rc; | ||
484 | } | ||
244 | 485 | ||
245 | # endif | 486 | static int |
487 | mu_sql_authenticate (struct mu_auth_data **return_data ARG_UNUSED, | ||
488 | const void *key, | ||
489 | void *func_data ARG_UNUSED, void *call_data) | ||
490 | { | ||
491 | mu_sql_connection_t conn; | ||
492 | struct mu_auth_data *auth_data = key; | ||
493 | char *pass = call_data; | ||
494 | char *sql_pass; | ||
495 | char *query_str = NULL; | ||
496 | int rc, status; | ||
497 | |||
498 | if (!auth_data) | ||
499 | return 1; | ||
500 | |||
501 | query_str = mu_sql_expand_query (mu_sql_getpass_query, auth_data->name); | ||
502 | |||
503 | if (!query_str) | ||
504 | return 1; | ||
505 | |||
506 | status = mu_sql_connection_init (&conn, | ||
507 | sql_interface, | ||
508 | mu_sql_host, | ||
509 | mu_sql_port, | ||
510 | mu_sql_user, mu_sql_passwd, | ||
511 | mu_sql_db); | ||
512 | |||
513 | if (status) | ||
514 | { | ||
515 | mu_error ("%s. SQL error: %s", | ||
516 | mu_strerror (status), mu_sql_strerror (conn)); | ||
517 | mu_sql_connection_destroy (&conn); | ||
518 | free (query_str); | ||
519 | return status; | ||
520 | } | ||
521 | |||
522 | status = mu_sql_connect (conn); | ||
523 | |||
524 | if (status) | ||
525 | { | ||
526 | mu_error ("%s. SQL error: %s", | ||
527 | mu_strerror (status), mu_sql_strerror (conn)); | ||
528 | mu_sql_connection_destroy (&conn); | ||
529 | free (query_str); | ||
530 | return status; | ||
531 | } | ||
532 | |||
533 | status = mu_sql_query (conn, query_str); | ||
534 | free (query_str); | ||
535 | |||
536 | if (status) | ||
537 | { | ||
538 | mu_error (_("SQL Query failed: %s"), | ||
539 | (status == MU_ERR_SQL) ? mu_sql_strerror (conn) : | ||
540 | mu_strerror (status)); | ||
541 | mu_sql_connection_destroy (&conn); | ||
542 | return 1; | ||
543 | } | ||
544 | |||
545 | status = mu_sql_store_result (conn); | ||
546 | |||
547 | if (status) | ||
548 | { | ||
549 | mu_error (_("cannot store SQL result: %s"), | ||
550 | (status == MU_ERR_SQL) ? mu_sql_strerror (conn) : | ||
551 | mu_strerror (status)); | ||
552 | mu_sql_connection_destroy (&conn); | ||
553 | return 1; | ||
554 | } | ||
555 | |||
556 | status = mu_sql_get_column (conn, 0, 0, &sql_pass); | ||
557 | if (status) | ||
558 | { | ||
559 | mu_error (_("cannot get password from SQL: %s"), | ||
560 | (status == MU_ERR_SQL) ? mu_sql_strerror (conn) : | ||
561 | mu_strerror (status)); | ||
562 | mu_sql_release_result (conn); | ||
563 | mu_sql_connection_destroy (&conn); | ||
564 | return 1; | ||
565 | } | ||
566 | |||
567 | rc = strcmp (sql_pass, crypt (pass, sql_pass)); | ||
568 | |||
569 | mu_sql_disconnect (conn); | ||
570 | mu_sql_connection_destroy (&conn); | ||
571 | |||
572 | return rc; | ||
573 | } | ||
246 | 574 | ||
247 | #else | 575 | #else |
248 | 576 | ||
249 | # define mu_sql_authenticate mu_auth_nosupport | 577 | # define mu_sql_authenticate mu_auth_nosupport |
250 | # define mu_auth_sql_by_name mu_auth_nosupport | 578 | # define mu_auth_sql_by_name mu_auth_nosupport |
251 | # define mu_auth_sql_by_uid mu_auth_nosupport | 579 | # define mu_auth_sql_by_uid mu_auth_nosupport |
252 | 580 | ||
253 | #endif | 581 | #endif |
254 | 582 | ||
583 | |||
255 | struct mu_auth_module mu_auth_sql_module = { | 584 | struct mu_auth_module mu_auth_sql_module = { |
256 | "sql", | 585 | "sql", |
257 | #ifdef USE_SQL | 586 | #ifdef USE_SQL | ... | ... |
-
Please register or sign in to post a comment