Commit 15060e45 15060e45eb0abbba8bbe3e6501a9ece7708a13a7 by Sergey Poznyakoff

(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.
1 parent ea09d596
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
......