Implement field mapping and retrieval by field names
Showing
1 changed file
with
174 additions
and
12 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, 2005, 2006 Free Software Foundation, Inc. | 2 | Copyright (C) 2002, 2003, 2004, 2005, 2006, |
3 | 2007 Free Software Foundation, Inc. | ||
3 | 4 | ||
4 | This library is free software; you can redistribute it and/or | 5 | This library is free software; you can redistribute it and/or |
5 | modify it under the terms of the GNU Lesser General Public | 6 | modify it under the terms of the GNU Lesser General Public |
... | @@ -39,6 +40,7 @@ | ... | @@ -39,6 +40,7 @@ |
39 | # include <crypt.h> | 40 | # include <crypt.h> |
40 | #endif | 41 | #endif |
41 | 42 | ||
43 | #include <mailutils/assoc.h> | ||
42 | #include <mailutils/list.h> | 44 | #include <mailutils/list.h> |
43 | #include <mailutils/iterator.h> | 45 | #include <mailutils/iterator.h> |
44 | #include <mailutils/mailbox.h> | 46 | #include <mailutils/mailbox.h> |
... | @@ -47,6 +49,7 @@ | ... | @@ -47,6 +49,7 @@ |
47 | #include <mailutils/error.h> | 49 | #include <mailutils/error.h> |
48 | #include <mailutils/errno.h> | 50 | #include <mailutils/errno.h> |
49 | #include <mailutils/nls.h> | 51 | #include <mailutils/nls.h> |
52 | #include <mailutils/mutil.h> | ||
50 | #include <mailutils/sql.h> | 53 | #include <mailutils/sql.h> |
51 | 54 | ||
52 | #ifdef USE_SQL | 55 | #ifdef USE_SQL |
... | @@ -66,6 +69,8 @@ int mu_sql_port = 0; /* Port number to connect to. | ... | @@ -66,6 +69,8 @@ int mu_sql_port = 0; /* Port number to connect to. |
66 | 0 means default port */ | 69 | 0 means default port */ |
67 | enum mu_password_type mu_sql_password_type = password_hash; | 70 | enum mu_password_type mu_sql_password_type = password_hash; |
68 | 71 | ||
72 | static mu_assoc_t sql_field_map; | ||
73 | |||
69 | static char * | 74 | static char * |
70 | sql_escape_string (const char *ustr) | 75 | sql_escape_string (const char *ustr) |
71 | { | 76 | { |
... | @@ -170,16 +175,17 @@ mu_sql_expand_query (const char *query, const char *ustr) | ... | @@ -170,16 +175,17 @@ mu_sql_expand_query (const char *query, const char *ustr) |
170 | return res; | 175 | return res; |
171 | } | 176 | } |
172 | 177 | ||
173 | # define ARG_SQL_INTERFACE 256 | 178 | # define ARG_SQL_INTERFACE 256 |
174 | # define ARG_SQL_GETPWNAM 257 | 179 | # define ARG_SQL_GETPWNAM 257 |
175 | # define ARG_SQL_GETPWUID 258 | 180 | # define ARG_SQL_GETPWUID 258 |
176 | # define ARG_SQL_GETPASS 259 | 181 | # define ARG_SQL_GETPASS 259 |
177 | # define ARG_SQL_HOST 260 | 182 | # define ARG_SQL_HOST 260 |
178 | # define ARG_SQL_USER 261 | 183 | # define ARG_SQL_USER 261 |
179 | # define ARG_SQL_PASSWD 262 | 184 | # define ARG_SQL_PASSWD 262 |
180 | # define ARG_SQL_DB 263 | 185 | # define ARG_SQL_DB 263 |
181 | # define ARG_SQL_PORT 264 | 186 | # define ARG_SQL_PORT 264 |
182 | # define ARG_SQL_MU_PASSWORD_TYPE 265 | 187 | # define ARG_SQL_MU_PASSWORD_TYPE 265 |
188 | # define ARG_SQL_FIELD_MAP 266 | ||
183 | 189 | ||
184 | static struct argp_option mu_sql_argp_option[] = { | 190 | static struct argp_option mu_sql_argp_option[] = { |
185 | {"sql-interface", ARG_SQL_INTERFACE, N_("NAME"), 0, | 191 | {"sql-interface", ARG_SQL_INTERFACE, N_("NAME"), 0, |
... | @@ -202,12 +208,17 @@ static struct argp_option mu_sql_argp_option[] = { | ... | @@ -202,12 +208,17 @@ static struct argp_option mu_sql_argp_option[] = { |
202 | N_("Port to use"), 0}, | 208 | N_("Port to use"), 0}, |
203 | {"sql-password-type", ARG_SQL_MU_PASSWORD_TYPE, N_("STRING"), 0, | 209 | {"sql-password-type", ARG_SQL_MU_PASSWORD_TYPE, N_("STRING"), 0, |
204 | N_("Type of password returned by --sql-getpass query. STRING is one of: plain, hash, scrambled"), 0}, | 210 | N_("Type of password returned by --sql-getpass query. STRING is one of: plain, hash, scrambled"), 0}, |
211 | {"sql-field-map", ARG_SQL_FIELD_MAP, N_("MAP"), 0, | ||
212 | N_("Declare a name translation map for SQL fields in results of sql-getpwnam and " | ||
213 | "sql-getpwuid queries"), 0}, | ||
205 | { NULL, 0, NULL, 0, NULL, 0 } | 214 | { NULL, 0, NULL, 0, NULL, 0 } |
206 | }; | 215 | }; |
207 | 216 | ||
208 | static error_t | 217 | static error_t |
209 | mu_sql_argp_parser (int key, char *arg, struct argp_state *state) | 218 | mu_sql_argp_parser (int key, char *arg, struct argp_state *state) |
210 | { | 219 | { |
220 | int rc, err; | ||
221 | |||
211 | switch (key) | 222 | switch (key) |
212 | { | 223 | { |
213 | case ARG_SQL_INTERFACE: | 224 | case ARG_SQL_INTERFACE: |
... | @@ -258,6 +269,13 @@ mu_sql_argp_parser (int key, char *arg, struct argp_state *state) | ... | @@ -258,6 +269,13 @@ mu_sql_argp_parser (int key, char *arg, struct argp_state *state) |
258 | else | 269 | else |
259 | argp_error (state, _("Unknown password type `%s'"), arg); | 270 | argp_error (state, _("Unknown password type `%s'"), arg); |
260 | break; | 271 | break; |
272 | |||
273 | case ARG_SQL_FIELD_MAP: | ||
274 | rc = mutil_parse_field_map (arg, &sql_field_map, &err); | ||
275 | if (rc) | ||
276 | argp_error (state, _("Error near element %d: %s"), | ||
277 | err, mu_strerror (rc)); | ||
278 | break; | ||
261 | 279 | ||
262 | default: | 280 | default: |
263 | return ARGP_ERR_UNKNOWN; | 281 | return ARGP_ERR_UNKNOWN; |
... | @@ -271,7 +289,8 @@ struct argp mu_sql_argp = { | ... | @@ -271,7 +289,8 @@ struct argp mu_sql_argp = { |
271 | }; | 289 | }; |
272 | 290 | ||
273 | static int | 291 | static int |
274 | decode_tuple (mu_sql_connection_t conn, int n, struct mu_auth_data **return_data) | 292 | decode_tuple_v1_0 (mu_sql_connection_t conn, int n, |
293 | struct mu_auth_data **return_data) | ||
275 | { | 294 | { |
276 | int rc; | 295 | int rc; |
277 | char *mailbox_name = NULL; | 296 | char *mailbox_name = NULL; |
... | @@ -296,10 +315,15 @@ decode_tuple (mu_sql_connection_t conn, int n, struct mu_auth_data **return_data | ... | @@ -296,10 +315,15 @@ decode_tuple (mu_sql_connection_t conn, int n, struct mu_auth_data **return_data |
296 | char *passwd, *suid, *sgid, *dir, *shell; | 315 | char *passwd, *suid, *sgid, *dir, *shell; |
297 | 316 | ||
298 | if (mu_sql_get_column (conn, 0, 1, &passwd) | 317 | if (mu_sql_get_column (conn, 0, 1, &passwd) |
318 | || !passwd | ||
299 | || mu_sql_get_column (conn, 0, 2, &suid) | 319 | || mu_sql_get_column (conn, 0, 2, &suid) |
320 | || !suid | ||
300 | || mu_sql_get_column (conn, 0, 3, &sgid) | 321 | || mu_sql_get_column (conn, 0, 3, &sgid) |
322 | || !sgid | ||
301 | || mu_sql_get_column (conn, 0, 4, &dir) | 323 | || mu_sql_get_column (conn, 0, 4, &dir) |
302 | || mu_sql_get_column (conn, 0, 5, &shell)) | 324 | || !dir |
325 | || mu_sql_get_column (conn, 0, 5, &shell) | ||
326 | || !shell) | ||
303 | return MU_ERR_FAILURE; | 327 | return MU_ERR_FAILURE; |
304 | 328 | ||
305 | rc = mu_auth_data_alloc (return_data, | 329 | rc = mu_auth_data_alloc (return_data, |
... | @@ -321,6 +345,144 @@ decode_tuple (mu_sql_connection_t conn, int n, struct mu_auth_data **return_data | ... | @@ -321,6 +345,144 @@ decode_tuple (mu_sql_connection_t conn, int n, struct mu_auth_data **return_data |
321 | } | 345 | } |
322 | 346 | ||
323 | static int | 347 | static int |
348 | get_field (mu_sql_connection_t conn, const char *id, char **ret, int mandatory) | ||
349 | { | ||
350 | const char **name = mu_assoc_ref (sql_field_map, id); | ||
351 | int rc = mu_sql_get_field (conn, 0, name ? *name : id, ret); | ||
352 | if (rc) | ||
353 | { | ||
354 | if (mandatory || rc != MU_ERR_NOENT) | ||
355 | mu_error (_("Cannot get SQL field `%s' (`%s'): %s"), | ||
356 | id, name ? *name : id, mu_strerror (rc)); | ||
357 | } | ||
358 | else if (!*ret) | ||
359 | { | ||
360 | mu_error (_("SQL field `%s' (`%s') has NULL value"), | ||
361 | id, name ? *name : id); | ||
362 | rc = MU_READ_ERROR; | ||
363 | } | ||
364 | |||
365 | return rc; | ||
366 | } | ||
367 | |||
368 | static int | ||
369 | decode_tuple_new (mu_sql_connection_t conn, int n, | ||
370 | struct mu_auth_data **return_data) | ||
371 | { | ||
372 | int rc; | ||
373 | char *mailbox_name = NULL; | ||
374 | char *name; | ||
375 | char *passwd, *suid, *sgid, *dir, *shell, *gecos, *squota; | ||
376 | mu_off_t quota = 0; | ||
377 | char *p; | ||
378 | uid_t uid; | ||
379 | gid_t gid; | ||
380 | |||
381 | if (get_field (conn, MU_AUTH_NAME, &name, 1) | ||
382 | || get_field (conn, MU_AUTH_PASSWD, &passwd, 1) | ||
383 | || get_field (conn, MU_AUTH_UID, &suid, 1) | ||
384 | || get_field (conn, MU_AUTH_GID, &sgid, 1) | ||
385 | || get_field (conn, MU_AUTH_DIR, &dir, 1) | ||
386 | || get_field (conn, MU_AUTH_SHELL, &shell, 1)) | ||
387 | return MU_ERR_FAILURE; | ||
388 | |||
389 | if (get_field (conn, MU_AUTH_GECOS, &gecos, 0)) | ||
390 | gecos = "SQL user"; | ||
391 | |||
392 | uid = strtoul (suid, &p, 0); | ||
393 | if (*p) | ||
394 | { | ||
395 | mu_error (_("Invalid value for uid: %s"), suid); | ||
396 | return MU_ERR_FAILURE; | ||
397 | } | ||
398 | |||
399 | gid = strtoul (sgid, &p, 0); | ||
400 | if (*p) | ||
401 | { | ||
402 | mu_error (_("Invalid value for gid: %s"), sgid); | ||
403 | return MU_ERR_FAILURE; | ||
404 | } | ||
405 | |||
406 | rc = get_field (conn, MU_AUTH_MAILBOX, &mailbox_name, 0); | ||
407 | switch (rc) | ||
408 | { | ||
409 | case 0: | ||
410 | mailbox_name = strdup (mailbox_name); | ||
411 | break; | ||
412 | |||
413 | case MU_ERR_NOENT: | ||
414 | if (mu_construct_user_mailbox_url (&mailbox_name, name)) | ||
415 | return MU_ERR_FAILURE; | ||
416 | break; | ||
417 | |||
418 | default: | ||
419 | return MU_ERR_FAILURE; | ||
420 | } | ||
421 | |||
422 | rc = get_field (conn, MU_AUTH_QUOTA, &squota, 0); | ||
423 | if (rc == 0) | ||
424 | { | ||
425 | if (strcasecmp (squota, "none") == 0) | ||
426 | quota = 0; | ||
427 | else | ||
428 | { | ||
429 | quota = strtoul (squota, &p, 10); | ||
430 | switch (*p) | ||
431 | { | ||
432 | case 0: | ||
433 | break; | ||
434 | |||
435 | case 'k': | ||
436 | case 'K': | ||
437 | quota *= 1024; | ||
438 | break; | ||
439 | |||
440 | case 'm': | ||
441 | case 'M': | ||
442 | quota *= 1024*1024; | ||
443 | break; | ||
444 | |||
445 | default: | ||
446 | mu_error (_("Invalid value for quota: %s"), squota); | ||
447 | free (mailbox_name); | ||
448 | return MU_ERR_FAILURE; | ||
449 | } | ||
450 | } | ||
451 | } | ||
452 | else if (rc == MU_ERR_NOENT) | ||
453 | quota = 0; | ||
454 | else | ||
455 | { | ||
456 | free (mailbox_name); | ||
457 | return MU_ERR_FAILURE; | ||
458 | } | ||
459 | |||
460 | rc = mu_auth_data_alloc (return_data, | ||
461 | name, | ||
462 | passwd, | ||
463 | uid, | ||
464 | gid, | ||
465 | gecos, | ||
466 | dir, | ||
467 | shell, | ||
468 | mailbox_name, | ||
469 | 1); | ||
470 | |||
471 | free (mailbox_name); | ||
472 | return rc; | ||
473 | } | ||
474 | |||
475 | static int | ||
476 | decode_tuple (mu_sql_connection_t conn, int n, | ||
477 | struct mu_auth_data **return_data) | ||
478 | { | ||
479 | if (sql_field_map) | ||
480 | return decode_tuple_new (conn, n, return_data); | ||
481 | else | ||
482 | return decode_tuple_v1_0 (conn, n, return_data); | ||
483 | } | ||
484 | |||
485 | static int | ||
324 | mu_auth_sql_by_name (struct mu_auth_data **return_data, | 486 | mu_auth_sql_by_name (struct mu_auth_data **return_data, |
325 | const void *key, | 487 | const void *key, |
326 | void *func_data ARG_UNUSED, | 488 | void *func_data ARG_UNUSED, | ... | ... |
-
Please register or sign in to post a comment