Commit 9c3249d1 9c3249d18099f6ca8b1ed6c19968e60484feb664 by Sergey Poznyakoff

Rewritten using general SQL interface.

1 parent 6d84a2bc
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
......