(mu_sql_password_type): New variable
(--sql-password-type): New command line option (mu_sql_getpass): New function. (mu_sql_authenticate): Recognize hashed, plaintext and mysql scrambled passwords.
Showing
1 changed file
with
78 additions
and
30 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, 2004 Free Software Foundation, Inc. | 2 | Copyright (C) 2002, 2003, 2004, 2005 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 |
... | @@ -50,6 +50,7 @@ | ... | @@ -50,6 +50,7 @@ |
50 | 50 | ||
51 | #ifdef USE_SQL | 51 | #ifdef USE_SQL |
52 | 52 | ||
53 | |||
53 | int sql_interface = 0; | 54 | int sql_interface = 0; |
54 | char *mu_sql_getpwnam_query; | 55 | char *mu_sql_getpwnam_query; |
55 | char *mu_sql_getpass_query; | 56 | char *mu_sql_getpass_query; |
... | @@ -62,6 +63,7 @@ char *mu_sql_passwd = "yurpass"; /* Password for mysql access */ | ... | @@ -62,6 +63,7 @@ char *mu_sql_passwd = "yurpass"; /* Password for mysql access */ |
62 | char *mu_sql_db = "accounts"; /* Database Name */ | 63 | char *mu_sql_db = "accounts"; /* Database Name */ |
63 | int mu_sql_port = 0; /* Port number to connect to. | 64 | int mu_sql_port = 0; /* Port number to connect to. |
64 | 0 means default port */ | 65 | 0 means default port */ |
66 | enum mu_password_type mu_sql_password_type = password_hash; | ||
65 | 67 | ||
66 | static char * | 68 | static char * |
67 | sql_escape_string (const char *ustr) | 69 | sql_escape_string (const char *ustr) |
... | @@ -175,6 +177,7 @@ mu_sql_expand_query (const char *query, const char *ustr) | ... | @@ -175,6 +177,7 @@ mu_sql_expand_query (const char *query, const char *ustr) |
175 | # define ARG_SQL_PASSWD 262 | 177 | # define ARG_SQL_PASSWD 262 |
176 | # define ARG_SQL_DB 263 | 178 | # define ARG_SQL_DB 263 |
177 | # define ARG_SQL_PORT 264 | 179 | # define ARG_SQL_PORT 264 |
180 | # define ARG_SQL_MU_PASSWORD_TYPE 265 | ||
178 | 181 | ||
179 | static struct argp_option mu_sql_argp_option[] = { | 182 | static struct argp_option mu_sql_argp_option[] = { |
180 | {"sql-interface", ARG_SQL_INTERFACE, N_("NAME"), 0, | 183 | {"sql-interface", ARG_SQL_INTERFACE, N_("NAME"), 0, |
... | @@ -195,6 +198,8 @@ static struct argp_option mu_sql_argp_option[] = { | ... | @@ -195,6 +198,8 @@ static struct argp_option mu_sql_argp_option[] = { |
195 | N_("Name of the database to connect to"), 0}, | 198 | N_("Name of the database to connect to"), 0}, |
196 | {"sql-port", ARG_SQL_PORT, N_("NUMBER"), 0, | 199 | {"sql-port", ARG_SQL_PORT, N_("NUMBER"), 0, |
197 | N_("Port to use"), 0}, | 200 | N_("Port to use"), 0}, |
201 | {"sql-password-type", ARG_SQL_MU_PASSWORD_TYPE, N_("STRING"), 0, | ||
202 | N_("Type of password returned by --sql-getpass query. STRING is one of: plain, hash, scrambled"), 0}, | ||
198 | { NULL, 0, NULL, 0, NULL, 0 } | 203 | { NULL, 0, NULL, 0, NULL, 0 } |
199 | }; | 204 | }; |
200 | 205 | ||
... | @@ -241,6 +246,17 @@ mu_sql_argp_parser (int key, char *arg, struct argp_state *state) | ... | @@ -241,6 +246,17 @@ mu_sql_argp_parser (int key, char *arg, struct argp_state *state) |
241 | mu_sql_port = strtoul (arg, NULL, 0); | 246 | mu_sql_port = strtoul (arg, NULL, 0); |
242 | break; | 247 | break; |
243 | 248 | ||
249 | case ARG_SQL_MU_PASSWORD_TYPE: | ||
250 | if (strcmp (arg, "plain") == 0) | ||
251 | mu_sql_password_type = password_plaintext; | ||
252 | else if (strcmp (arg, "hash") == 0) | ||
253 | mu_sql_password_type = password_hash; | ||
254 | else if (strcmp (arg, "scrambled") == 0) | ||
255 | mu_sql_password_type = password_scrambled; | ||
256 | else | ||
257 | argp_error (state, _("Unknown password type '%s'"), arg); | ||
258 | break; | ||
259 | |||
244 | default: | 260 | default: |
245 | return ARGP_ERR_UNKNOWN; | 261 | return ARGP_ERR_UNKNOWN; |
246 | } | 262 | } |
... | @@ -283,8 +299,7 @@ mu_auth_sql_by_name (struct mu_auth_data **return_data, | ... | @@ -283,8 +299,7 @@ mu_auth_sql_by_name (struct mu_auth_data **return_data, |
283 | 299 | ||
284 | if (status) | 300 | if (status) |
285 | { | 301 | { |
286 | mu_error ("%s. SQL error: %s", | 302 | mu_error ("%s: %s", mu_strerror (status), mu_sql_strerror (conn)); |
287 | mu_strerror (status), mu_sql_strerror (conn)); | ||
288 | mu_sql_connection_destroy (&conn); | 303 | mu_sql_connection_destroy (&conn); |
289 | free (query_str); | 304 | free (query_str); |
290 | return status; | 305 | return status; |
... | @@ -294,8 +309,7 @@ mu_auth_sql_by_name (struct mu_auth_data **return_data, | ... | @@ -294,8 +309,7 @@ mu_auth_sql_by_name (struct mu_auth_data **return_data, |
294 | 309 | ||
295 | if (status) | 310 | if (status) |
296 | { | 311 | { |
297 | mu_error ("%s. SQL error: %s", | 312 | mu_error ("%s: %s", mu_strerror (status), mu_sql_strerror (conn)); |
298 | mu_strerror (status), mu_sql_strerror (conn)); | ||
299 | mu_sql_connection_destroy (&conn); | 313 | mu_sql_connection_destroy (&conn); |
300 | free (query_str); | 314 | free (query_str); |
301 | return status; | 315 | return status; |
... | @@ -417,8 +431,7 @@ mu_auth_sql_by_uid (struct mu_auth_data **return_data, | ... | @@ -417,8 +431,7 @@ mu_auth_sql_by_uid (struct mu_auth_data **return_data, |
417 | 431 | ||
418 | if (status) | 432 | if (status) |
419 | { | 433 | { |
420 | mu_error ("%s. SQL error: %s", | 434 | mu_error ("%s: %s", mu_strerror (status), mu_sql_strerror (conn)); |
421 | mu_strerror (status), mu_sql_strerror (conn)); | ||
422 | mu_sql_connection_destroy (&conn); | 435 | mu_sql_connection_destroy (&conn); |
423 | free (query_str); | 436 | free (query_str); |
424 | return status; | 437 | return status; |
... | @@ -428,8 +441,7 @@ mu_auth_sql_by_uid (struct mu_auth_data **return_data, | ... | @@ -428,8 +441,7 @@ mu_auth_sql_by_uid (struct mu_auth_data **return_data, |
428 | 441 | ||
429 | if (status) | 442 | if (status) |
430 | { | 443 | { |
431 | mu_error ("%s. SQL error: %s", | 444 | mu_error ("%s: %s", mu_strerror (status), mu_sql_strerror (conn)); |
432 | mu_strerror (status), mu_sql_strerror (conn)); | ||
433 | mu_sql_connection_destroy (&conn); | 445 | mu_sql_connection_destroy (&conn); |
434 | free (query_str); | 446 | free (query_str); |
435 | return status; | 447 | return status; |
... | @@ -518,25 +530,18 @@ mu_auth_sql_by_uid (struct mu_auth_data **return_data, | ... | @@ -518,25 +530,18 @@ mu_auth_sql_by_uid (struct mu_auth_data **return_data, |
518 | return rc; | 530 | return rc; |
519 | } | 531 | } |
520 | 532 | ||
521 | static int | 533 | int |
522 | mu_sql_authenticate (struct mu_auth_data **return_data ARG_UNUSED, | 534 | mu_sql_getpass (const char *username, char **passwd) |
523 | const void *key, | ||
524 | void *func_data ARG_UNUSED, void *call_data) | ||
525 | { | 535 | { |
526 | mu_sql_connection_t conn; | 536 | mu_sql_connection_t conn; |
527 | struct mu_auth_data *auth_data = key; | 537 | char *query_str; |
528 | char *pass = call_data; | 538 | int status; |
529 | char *sql_pass; | 539 | char *sql_pass; |
530 | char *query_str = NULL; | ||
531 | int rc, status; | ||
532 | |||
533 | if (!auth_data) | ||
534 | return 1; | ||
535 | 540 | ||
536 | query_str = mu_sql_expand_query (mu_sql_getpass_query, auth_data->name); | 541 | query_str = mu_sql_expand_query (mu_sql_getpass_query, username); |
537 | 542 | ||
538 | if (!query_str) | 543 | if (!query_str) |
539 | return 1; | 544 | return MU_ERR_FAILURE; |
540 | 545 | ||
541 | status = mu_sql_connection_init (&conn, | 546 | status = mu_sql_connection_init (&conn, |
542 | sql_interface, | 547 | sql_interface, |
... | @@ -547,8 +552,7 @@ mu_sql_authenticate (struct mu_auth_data **return_data ARG_UNUSED, | ... | @@ -547,8 +552,7 @@ mu_sql_authenticate (struct mu_auth_data **return_data ARG_UNUSED, |
547 | 552 | ||
548 | if (status) | 553 | if (status) |
549 | { | 554 | { |
550 | mu_error ("%s. SQL error: %s", | 555 | mu_error ("%s: %s", mu_strerror (status), mu_sql_strerror (conn)); |
551 | mu_strerror (status), mu_sql_strerror (conn)); | ||
552 | mu_sql_connection_destroy (&conn); | 556 | mu_sql_connection_destroy (&conn); |
553 | free (query_str); | 557 | free (query_str); |
554 | return status; | 558 | return status; |
... | @@ -558,8 +562,7 @@ mu_sql_authenticate (struct mu_auth_data **return_data ARG_UNUSED, | ... | @@ -558,8 +562,7 @@ mu_sql_authenticate (struct mu_auth_data **return_data ARG_UNUSED, |
558 | 562 | ||
559 | if (status) | 563 | if (status) |
560 | { | 564 | { |
561 | mu_error ("%s. SQL error: %s", | 565 | mu_error ("%s: %s", mu_strerror (status), mu_sql_strerror (conn)); |
562 | mu_strerror (status), mu_sql_strerror (conn)); | ||
563 | mu_sql_connection_destroy (&conn); | 566 | mu_sql_connection_destroy (&conn); |
564 | free (query_str); | 567 | free (query_str); |
565 | return status; | 568 | return status; |
... | @@ -574,7 +577,7 @@ mu_sql_authenticate (struct mu_auth_data **return_data ARG_UNUSED, | ... | @@ -574,7 +577,7 @@ mu_sql_authenticate (struct mu_auth_data **return_data ARG_UNUSED, |
574 | (status == MU_ERR_SQL) ? mu_sql_strerror (conn) : | 577 | (status == MU_ERR_SQL) ? mu_sql_strerror (conn) : |
575 | mu_strerror (status)); | 578 | mu_strerror (status)); |
576 | mu_sql_connection_destroy (&conn); | 579 | mu_sql_connection_destroy (&conn); |
577 | return 1; | 580 | return status; |
578 | } | 581 | } |
579 | 582 | ||
580 | status = mu_sql_store_result (conn); | 583 | status = mu_sql_store_result (conn); |
... | @@ -585,7 +588,7 @@ mu_sql_authenticate (struct mu_auth_data **return_data ARG_UNUSED, | ... | @@ -585,7 +588,7 @@ mu_sql_authenticate (struct mu_auth_data **return_data ARG_UNUSED, |
585 | (status == MU_ERR_SQL) ? mu_sql_strerror (conn) : | 588 | (status == MU_ERR_SQL) ? mu_sql_strerror (conn) : |
586 | mu_strerror (status)); | 589 | mu_strerror (status)); |
587 | mu_sql_connection_destroy (&conn); | 590 | mu_sql_connection_destroy (&conn); |
588 | return 1; | 591 | return status; |
589 | } | 592 | } |
590 | 593 | ||
591 | status = mu_sql_get_column (conn, 0, 0, &sql_pass); | 594 | status = mu_sql_get_column (conn, 0, 0, &sql_pass); |
... | @@ -596,14 +599,59 @@ mu_sql_authenticate (struct mu_auth_data **return_data ARG_UNUSED, | ... | @@ -596,14 +599,59 @@ mu_sql_authenticate (struct mu_auth_data **return_data ARG_UNUSED, |
596 | mu_strerror (status)); | 599 | mu_strerror (status)); |
597 | mu_sql_release_result (conn); | 600 | mu_sql_release_result (conn); |
598 | mu_sql_connection_destroy (&conn); | 601 | mu_sql_connection_destroy (&conn); |
599 | return 1; | 602 | return status; |
600 | } | 603 | } |
601 | 604 | ||
602 | rc = strcmp (sql_pass, crypt (pass, sql_pass)); | 605 | *passwd = strdup (sql_pass); |
603 | 606 | ||
604 | mu_sql_disconnect (conn); | 607 | mu_sql_disconnect (conn); |
605 | mu_sql_connection_destroy (&conn); | 608 | mu_sql_connection_destroy (&conn); |
606 | 609 | ||
610 | if (!*passwd) | ||
611 | return ENOMEM; | ||
612 | |||
613 | return 0; | ||
614 | } | ||
615 | |||
616 | static int | ||
617 | mu_sql_authenticate (struct mu_auth_data **return_data ARG_UNUSED, | ||
618 | const void *key, | ||
619 | void *func_data ARG_UNUSED, void *call_data) | ||
620 | { | ||
621 | struct mu_auth_data *auth_data = key; | ||
622 | char *pass = call_data; | ||
623 | char *sql_pass; | ||
624 | int rc; | ||
625 | |||
626 | if (!auth_data) | ||
627 | return 1; | ||
628 | |||
629 | if (mu_sql_getpass (auth_data->name, &sql_pass)) | ||
630 | return 1; | ||
631 | |||
632 | switch (mu_sql_password_type) | ||
633 | { | ||
634 | case password_hash: | ||
635 | rc = strcmp (sql_pass, crypt (pass, sql_pass)); | ||
636 | break; | ||
637 | |||
638 | case password_scrambled: | ||
639 | /* FIXME: Should this call be implementation-independent? I mean, | ||
640 | should we have mu_sql_check_scrambled() that will match the | ||
641 | password depending on the exact type of the underlying database, | ||
642 | just as the rest of mu_sql_.* functions do */ | ||
643 | #ifdef HAVE_MYSQL | ||
644 | rc = mu_check_mysql_scrambled_password (sql_pass, pass); | ||
645 | #endif | ||
646 | break; | ||
647 | |||
648 | case password_plaintext: | ||
649 | rc = strcmp (sql_pass, pass); | ||
650 | break; | ||
651 | } | ||
652 | |||
653 | free (sql_pass); | ||
654 | |||
607 | return rc; | 655 | return rc; |
608 | } | 656 | } |
609 | 657 | ... | ... |
-
Please register or sign in to post a comment