Commit edb05144 edb05144ade1984e28d88cfaea7c2fb0ec675f5b by Sergey Poznyakoff

Fix docs. Change argument of the field-map configuration statement

The field-map statement (.ldap.field-map & .sql.field-map) takes a
list of mappings as argument.  For compatibility and for internal purposes,
a string is still allowed.

* doc/texinfo/programs.texi: Update.
* include/mailutils/cfg.h (mu_cfg_field_map): New proto.
* include/mailutils/sql.h (mu_password_type): Rename.
(mu_sql_module_config) <positional>: Remove.
(mu_sql_decode_password_type): Remove prototype.
* libmailutils/base/mutil.c (mu_sql_decode_password_type): Remove
function.
* libmailutils/cfg/driver.c (mu_cfg_field_map): New function.
* libmu_auth/ldap.c (cb_field_map): Use mu_cfg_field_map.
(module_init): Fix default filter.
* libmu_auth/sql.c (cb_field_map): Use mu_cfg_field_map.
(mu_sql_param): Rename "password-type" statement to "password-encryption".
Remove the "positional" statement.
1 parent d644964e
...@@ -243,7 +243,7 @@ retrieve_password (Gsasl *ctx, Gsasl_session *sctx) ...@@ -243,7 +243,7 @@ retrieve_password (Gsasl *ctx, Gsasl_session *sctx)
243 } 243 }
244 244
245 #ifdef USE_SQL 245 #ifdef USE_SQL
246 if (mu_sql_module_config.password_type == password_plaintext) 246 if (mu_sql_module_config.password_encryption == mu_sql_password_plaintext)
247 { 247 {
248 char *passwd; 248 char *passwd;
249 int status = mu_sql_getpass (*username, &passwd); 249 int status = mu_sql_getpass (*username, &passwd);
......
...@@ -297,6 +297,10 @@ int mu_cfg_create_subtree (const char *path, mu_cfg_node_t **pnode); ...@@ -297,6 +297,10 @@ int mu_cfg_create_subtree (const char *path, mu_cfg_node_t **pnode);
297 int mu_cfg_parse_config (mu_cfg_tree_t **ptree, 297 int mu_cfg_parse_config (mu_cfg_tree_t **ptree,
298 struct mu_cfg_parse_hints *hints); 298 struct mu_cfg_parse_hints *hints);
299 299
300 int mu_cfg_field_map (struct mu_config_value const *val, mu_assoc_t *passoc,
301 char **err_term);
302
303
300 #ifdef __cplusplus 304 #ifdef __cplusplus
301 } 305 }
302 #endif 306 #endif
......
...@@ -20,11 +20,11 @@ ...@@ -20,11 +20,11 @@
20 #define _MAILUTILS_SQL_H 20 #define _MAILUTILS_SQL_H
21 21
22 /* Configuration */ 22 /* Configuration */
23 enum mu_password_type 23 enum mu_sql_password_encryption
24 { 24 {
25 password_plaintext, /* Plaintext passwords */ 25 mu_sql_password_plaintext, /* Plaintext passwords */
26 password_scrambled, /* Scrambled MySQL (>=3.21) password */ 26 mu_sql_password_scrambled, /* Scrambled MySQL (>=3.21) password */
27 password_hash, /* MD5 (or DES or whatever) hash */ 27 mu_sql_password_hash, /* MD5 (or DES or whatever) hash */
28 }; 28 };
29 29
30 struct mu_sql_module_config 30 struct mu_sql_module_config
...@@ -38,8 +38,7 @@ struct mu_sql_module_config ...@@ -38,8 +38,7 @@ struct mu_sql_module_config
38 char *passwd; 38 char *passwd;
39 char *db; 39 char *db;
40 int port; 40 int port;
41 enum mu_password_type password_type; 41 enum mu_sql_password_encryption password_encryption;
42 int positional;
43 mu_assoc_t field_map; 42 mu_assoc_t field_map;
44 }; 43 };
45 44
...@@ -143,6 +142,4 @@ extern int mu_sql_getpass (const char *username, char **passwd); ...@@ -143,6 +142,4 @@ extern int mu_sql_getpass (const char *username, char **passwd);
143 extern int mu_check_mysql_scrambled_password (const char *scrambled, 142 extern int mu_check_mysql_scrambled_password (const char *scrambled,
144 const char *message); 143 const char *message);
145 144
146 int mu_sql_decode_password_type (const char *arg, enum mu_password_type *t);
147
148 #endif 145 #endif
......
...@@ -118,21 +118,6 @@ mutil_parse_field_map (const char *map, mu_assoc_t *passoc_tab, int *perr) ...@@ -118,21 +118,6 @@ mutil_parse_field_map (const char *map, mu_assoc_t *passoc_tab, int *perr)
118 return rc; 118 return rc;
119 } 119 }
120 120
121 /* FIXME: should it be here? */
122 int
123 mu_sql_decode_password_type (const char *arg, enum mu_password_type *t)
124 {
125 if (strcmp (arg, "plain") == 0)
126 *t = password_plaintext;
127 else if (strcmp (arg, "hash") == 0)
128 *t = password_hash;
129 else if (strcmp (arg, "scrambled") == 0)
130 *t = password_scrambled;
131 else
132 return 1;
133 return 0;
134 }
135
136 int 121 int
137 mu_stream_flags_to_mode (int flags, int isdir) 122 mu_stream_flags_to_mode (int flags, int isdir)
138 { 123 {
......
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
38 #include <mailutils/stream.h> 38 #include <mailutils/stream.h>
39 #include <mailutils/assoc.h> 39 #include <mailutils/assoc.h>
40 #include <mailutils/alloc.h> 40 #include <mailutils/alloc.h>
41 41 #include <mailutils/cstr.h>
42 42
43 static mu_assoc_t section_tab; 43 static mu_assoc_t section_tab;
44 44
...@@ -587,3 +587,92 @@ mu_cfg_string_value_cb (mu_config_value_t *val, ...@@ -587,3 +587,92 @@ mu_cfg_string_value_cb (mu_config_value_t *val,
587 } 587 }
588 return rc; 588 return rc;
589 } 589 }
590
591 struct mapping_closure
592 {
593 mu_assoc_t assoc;
594 char *err_term;
595 int err;
596 };
597
598 static int
599 parse_mapping (void *item, void *data)
600 {
601 struct mapping_closure *clos = data;
602 char *str = item;
603 size_t len;
604 char *key, *val;
605
606 len = strcspn (str, "=");
607 if (str[len] == 0)
608 {
609 clos->err_term = mu_strdup (str);
610 return MU_ERR_PARSE;
611 }
612 key = mu_alloc (len + 1);
613 memcpy (key, str, len);
614 key[len] = 0;
615 val = mu_strdup (str + len + 1);
616 if (!val)
617 return ENOMEM;
618 clos->err = mu_assoc_install (clos->assoc, key, &val);
619 free (key);
620 if (clos->err)
621 return 1;
622 return 0;
623 }
624
625 static void
626 assoc_str_free (void *data)
627 {
628 free (data);
629 }
630
631 int
632 mu_cfg_field_map (struct mu_config_value const *val, mu_assoc_t *passoc,
633 char **err_term)
634 {
635 int rc;
636 struct mapping_closure clos;
637 mu_list_t list = NULL;
638
639 rc = mu_assoc_create (&clos.assoc, sizeof(char*), 0);
640 if (rc)
641 return rc;
642 mu_assoc_set_free (clos.assoc, assoc_str_free);
643 clos.err_term = NULL;
644
645 switch (val->type)
646 {
647 case MU_CFG_STRING:
648 mu_list_create (&list);
649 mu_list_set_destroy_item (list, mu_list_free_item);
650 rc = mu_string_split (val->v.string, ":", list);
651 if (rc == 0)
652 rc = mu_list_foreach (list, parse_mapping, &clos);
653 mu_list_destroy (&list);
654 break;
655
656 case MU_CFG_LIST:
657 rc = mu_list_foreach (val->v.list, parse_mapping, &clos);
658 break;
659
660 case MU_CFG_ARRAY:
661 rc = EINVAL;
662 }
663
664 if (rc)
665 {
666 if (err_term)
667 *err_term = clos.err_term;
668 else
669 free (clos.err_term);
670 mu_assoc_destroy (&clos.assoc);
671 }
672 else
673 *passoc = clos.assoc;
674
675 return rc;
676 }
677
678
......
...@@ -39,12 +39,8 @@ ...@@ -39,12 +39,8 @@
39 #include <gsasl.h> 39 #include <gsasl.h>
40 40
41 struct mu_gsasl_module_data mu_gsasl_module_data = { 41 struct mu_gsasl_module_data mu_gsasl_module_data = {
42 1, 42 .enable = 1,
43 NULL, 43 .cram_md5_pwd = SITE_CRAM_MD5_PWD
44 NULL,
45 NULL,
46 NULL,
47 SITE_CRAM_MD5_PWD
48 }; 44 };
49 45
50 static struct mu_cfg_param mu_gsasl_param[] = { 46 static struct mu_cfg_param mu_gsasl_param[] = {
...@@ -65,7 +61,7 @@ static struct mu_cfg_param mu_gsasl_param[] = { ...@@ -65,7 +61,7 @@ static struct mu_cfg_param mu_gsasl_param[] = {
65 { "anonymous-user", mu_c_string, &mu_gsasl_module_data.anon_user, 0, NULL, 61 { "anonymous-user", mu_c_string, &mu_gsasl_module_data.anon_user, 0, NULL,
66 N_("Anonymous user name."), 62 N_("Anonymous user name."),
67 N_("name") }, 63 N_("name") },
68 64
69 { NULL } 65 { NULL }
70 }; 66 };
71 67
......
...@@ -60,24 +60,22 @@ const char *default_field_map = ...@@ -60,24 +60,22 @@ const char *default_field_map =
60 "shell=loginShell"; 60 "shell=loginShell";
61 61
62 static struct mu_ldap_module_config ldap_param; 62 static struct mu_ldap_module_config ldap_param;
63
64
65 63
66 static int 64 static int
67 _cb2_field_map (const char *arg, void *data) 65 cb_field_map (void *data, mu_config_value_t *val)
68 { 66 {
69 int err; 67 char *err_term;
70 int rc = mutil_parse_field_map (arg, &ldap_param.field_map, &err); 68 int rc = mu_cfg_field_map (val, &ldap_param.field_map, &err_term);
69
71 if (rc) 70 if (rc)
72 /* FIXME: this message can be misleading */ 71 {
73 mu_error (_("error near element %d: %s"), err, mu_strerror (rc)); 72 if (err_term)
74 return 0; 73 mu_error (_("error near %s: %s"), err_term, mu_strerror (rc));
75 } 74 else
75 mu_error ("%s", mu_strerror (rc));
76 }
76 77
77 static int 78 return rc;
78 cb_field_map (void *data, mu_config_value_t *val)
79 {
80 return mu_cfg_string_value_cb (val, _cb2_field_map, NULL);
81 } 79 }
82 80
83 static struct mu_cfg_param mu_ldap_param[] = { 81 static struct mu_cfg_param mu_ldap_param[] = {
...@@ -140,14 +138,18 @@ module_init (void *ptr) ...@@ -140,14 +138,18 @@ module_init (void *ptr)
140 if (ldap_param.enable) 138 if (ldap_param.enable)
141 { 139 {
142 if (!ldap_param.getpwnam_filter) 140 if (!ldap_param.getpwnam_filter)
143 ldap_param.getpwnam_filter = "(&(objectClass=posixAccount) (uid=%u))"; 141 ldap_param.getpwnam_filter =
142 "(&(objectClass=posixAccount) (uid=$user))";
144 if (!ldap_param.getpwuid_filter) 143 if (!ldap_param.getpwuid_filter)
145 ldap_param.getpwuid_filter = 144 ldap_param.getpwuid_filter =
146 "&(objectClass=posixAccount) (uidNumber=%u))"; 145 "(&(objectClass=posixAccount) (uidNumber=$user))";
147 if (!ldap_param.field_map) 146 if (!ldap_param.field_map)
148 { 147 {
149 int d; 148 struct mu_config_value val;
150 mutil_parse_field_map (default_field_map, &ldap_param.field_map, &d); 149 val.type = MU_CFG_STRING;
150 val.v.string = default_field_map;
151 if (mu_cfg_field_map (&val, &ldap_param.field_map, NULL))
152 abort ();
151 } 153 }
152 } 154 }
153 } 155 }
......
...@@ -51,38 +51,53 @@ ...@@ -51,38 +51,53 @@
51 #include <mailutils/cstr.h> 51 #include <mailutils/cstr.h>
52 #include <mailutils/wordsplit.h> 52 #include <mailutils/wordsplit.h>
53 #include <mailutils/cli.h> 53 #include <mailutils/cli.h>
54 #include <mailutils/kwd.h>
54 #include "sql.h" 55 #include "sql.h"
55 56
56 #ifdef USE_SQL 57 #ifdef USE_SQL
57 58
58 struct mu_sql_module_config mu_sql_module_config; 59 struct mu_sql_module_config mu_sql_module_config;
60
59 /* Resource file configuration */ 61 /* Resource file configuration */
62
63 static struct mu_kwd password_encryption[] = {
64 { "plain", mu_sql_password_plaintext },
65 { "scrambled", mu_sql_password_scrambled },
66 { "hash", mu_sql_password_hash },
67 { "crypt", mu_sql_password_hash },
68 { NULL }
69 };
70
60 static int 71 static int
61 cb_password_type (void *data, mu_config_value_t *val) 72 cb_password_encryption (void *data, mu_config_value_t *val)
62 { 73 {
74 int res;
75
63 if (mu_cfg_assert_value_type (val, MU_CFG_STRING)) 76 if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
64 return 1; 77 return 1;
65
66 if (mu_sql_decode_password_type (val->v.string, &mu_sql_module_config.password_type))
67 mu_error (_("unknown password type `%s'"), val->v.string);
68 return 0;
69 }
70 78
71 static int 79 if (mu_kwd_xlat_name (password_encryption, val->v.string, &res))
72 _cb2_field_map (const char *arg, void *data) 80 mu_error ("%s", _("unrecognized password encryption"));
73 { 81 else
74 int err; 82 mu_sql_module_config.password_encryption = res;
75 int rc = mutil_parse_field_map (arg, &mu_sql_module_config.field_map, &err);
76 if (rc)
77 /* FIXME: this message may be misleading */
78 mu_error (_("error near element %d: %s"), err, mu_strerror (rc));
79 return 0; 83 return 0;
80 } 84 }
81 85
82 static int 86 static int
83 cb_field_map (void *data, mu_config_value_t *val) 87 cb_field_map (void *data, mu_config_value_t *val)
84 { 88 {
85 return mu_cfg_string_value_cb (val, _cb2_field_map, NULL); 89 char *err_term;
90 int rc = mu_cfg_field_map (val, &mu_sql_module_config.field_map, &err_term);
91
92 if (rc)
93 {
94 if (err_term)
95 mu_error (_("error near %s: %s"), err_term, mu_strerror (rc));
96 else
97 mu_error ("%s", mu_strerror (rc));
98 }
99
100 return rc;
86 } 101 }
87 102
88 static int 103 static int
...@@ -124,12 +139,10 @@ static struct mu_cfg_param mu_sql_param[] = { ...@@ -124,12 +139,10 @@ static struct mu_cfg_param mu_sql_param[] = {
124 N_("SQL server port.") }, 139 N_("SQL server port.") },
125 { "db", mu_c_string, &mu_sql_module_config.db, 0, NULL, 140 { "db", mu_c_string, &mu_sql_module_config.db, 0, NULL,
126 N_("Database name.") }, 141 N_("Database name.") },
127 { "password-type", mu_cfg_callback, NULL, 0, cb_password_type, 142 { "password-encryption", mu_cfg_callback, NULL, 0, cb_password_encryption,
128 N_("Type of password returned by getpass query."), 143 N_("Type of password returned by getpass query."),
129 /* TRANSLATORS: Words to the right of : are keywords - do not translate */ 144 /* TRANSLATORS: Words to the right of : are keywords - do not translate */
130 N_("arg: plain|hash|scrambled") }, 145 N_("arg: plain|hash|crypt|scrambled") },
131 { "positional", mu_c_bool, &mu_sql_module_config.positional, 0, NULL,
132 N_("Use positional (v1.0 compatible) field interface.") },
133 { "field-map", mu_cfg_callback, NULL, 0, cb_field_map, 146 { "field-map", mu_cfg_callback, NULL, 0, cb_field_map,
134 N_("Set a field-map for parsing SQL replies. The map is a " 147 N_("Set a field-map for parsing SQL replies. The map is a "
135 "column-separated list of definitions. Each definition has the " 148 "column-separated list of definitions. Each definition has the "
...@@ -207,65 +220,8 @@ mu_sql_expand_query (const char *query, const char *ustr) ...@@ -207,65 +220,8 @@ mu_sql_expand_query (const char *query, const char *ustr)
207 free (esc_ustr); 220 free (esc_ustr);
208 return res; 221 return res;
209 } 222 }
210
211 223
212 static int 224 static int
213 decode_tuple_v1_0 (mu_sql_connection_t conn, int n,
214 struct mu_auth_data **return_data)
215 {
216 int rc;
217 char *mailbox_name = NULL;
218 char *name;
219
220 if (mu_sql_get_column (conn, 0, 0, &name))
221 return MU_ERR_FAILURE;
222
223 if (n == 7)
224 {
225 char *tmp;
226 if (mu_sql_get_column (conn, 0, 6, &tmp))
227 return MU_ERR_FAILURE;
228 if (tmp && (mailbox_name = strdup (tmp)) == NULL)
229 return ENOMEM;
230 }
231 else if (mu_construct_user_mailbox_url (&mailbox_name, name))
232 return MU_ERR_FAILURE;
233
234 if (mailbox_name)
235 {
236 char *passwd, *suid, *sgid, *dir, *shell;
237
238 if (mu_sql_get_column (conn, 0, 1, &passwd)
239 || !passwd
240 || mu_sql_get_column (conn, 0, 2, &suid)
241 || !suid
242 || mu_sql_get_column (conn, 0, 3, &sgid)
243 || !sgid
244 || mu_sql_get_column (conn, 0, 4, &dir)
245 || !dir
246 || mu_sql_get_column (conn, 0, 5, &shell)
247 || !shell)
248 return MU_ERR_FAILURE;
249
250 rc = mu_auth_data_alloc (return_data,
251 name,
252 passwd,
253 atoi (suid),
254 atoi (sgid),
255 "SQL User",
256 dir,
257 shell,
258 mailbox_name,
259 1);
260 }
261 else
262 rc = MU_ERR_AUTH_FAILURE;
263
264 free (mailbox_name);
265 return rc;
266 }
267
268 static int
269 get_field (mu_sql_connection_t conn, const char *id, char **ret, int mandatory) 225 get_field (mu_sql_connection_t conn, const char *id, char **ret, int mandatory)
270 { 226 {
271 const char **name = mu_assoc_ref (mu_sql_module_config.field_map, id); 227 const char **name = mu_assoc_ref (mu_sql_module_config.field_map, id);
...@@ -292,8 +248,8 @@ get_field (mu_sql_connection_t conn, const char *id, char **ret, int mandatory) ...@@ -292,8 +248,8 @@ get_field (mu_sql_connection_t conn, const char *id, char **ret, int mandatory)
292 } 248 }
293 249
294 static int 250 static int
295 decode_tuple_new (mu_sql_connection_t conn, int n, 251 decode_tuple (mu_sql_connection_t conn, int n,
296 struct mu_auth_data **return_data) 252 struct mu_auth_data **return_data)
297 { 253 {
298 int rc; 254 int rc;
299 char *mailbox_name = NULL; 255 char *mailbox_name = NULL;
...@@ -403,16 +359,6 @@ decode_tuple_new (mu_sql_connection_t conn, int n, ...@@ -403,16 +359,6 @@ decode_tuple_new (mu_sql_connection_t conn, int n,
403 } 359 }
404 360
405 static int 361 static int
406 decode_tuple (mu_sql_connection_t conn, int n,
407 struct mu_auth_data **return_data)
408 {
409 if (mu_sql_module_config.field_map || !mu_sql_module_config.positional)
410 return decode_tuple_new (conn, n, return_data);
411 else
412 return decode_tuple_v1_0 (conn, n, return_data);
413 }
414
415 static int
416 mu_auth_sql_by_name (struct mu_auth_data **return_data, 362 mu_auth_sql_by_name (struct mu_auth_data **return_data,
417 const void *key, 363 const void *key,
418 void *func_data MU_ARG_UNUSED, 364 void *func_data MU_ARG_UNUSED,
...@@ -723,9 +669,9 @@ mu_sql_authenticate (struct mu_auth_data **return_data MU_ARG_UNUSED, ...@@ -723,9 +669,9 @@ mu_sql_authenticate (struct mu_auth_data **return_data MU_ARG_UNUSED,
723 if ((rc = mu_sql_getpass (auth_data->name, &sql_pass))) 669 if ((rc = mu_sql_getpass (auth_data->name, &sql_pass)))
724 return rc; 670 return rc;
725 671
726 switch (mu_sql_module_config.password_type) 672 switch (mu_sql_module_config.password_encryption)
727 { 673 {
728 case password_hash: 674 case mu_sql_password_hash:
729 crypt_pass = crypt (pass, sql_pass); 675 crypt_pass = crypt (pass, sql_pass);
730 if (!crypt_pass) 676 if (!crypt_pass)
731 rc = 1; 677 rc = 1;
...@@ -733,7 +679,7 @@ mu_sql_authenticate (struct mu_auth_data **return_data MU_ARG_UNUSED, ...@@ -733,7 +679,7 @@ mu_sql_authenticate (struct mu_auth_data **return_data MU_ARG_UNUSED,
733 rc = strcmp (sql_pass, crypt_pass); 679 rc = strcmp (sql_pass, crypt_pass);
734 break; 680 break;
735 681
736 case password_scrambled: 682 case mu_sql_password_scrambled:
737 /* FIXME: Should this call be implementation-independent? I mean, 683 /* FIXME: Should this call be implementation-independent? I mean,
738 should we have mu_sql_check_scrambled() that will match the 684 should we have mu_sql_check_scrambled() that will match the
739 password depending on the exact type of the underlying database, 685 password depending on the exact type of the underlying database,
...@@ -745,7 +691,7 @@ mu_sql_authenticate (struct mu_auth_data **return_data MU_ARG_UNUSED, ...@@ -745,7 +691,7 @@ mu_sql_authenticate (struct mu_auth_data **return_data MU_ARG_UNUSED,
745 #endif 691 #endif
746 break; 692 break;
747 693
748 case password_plaintext: 694 case mu_sql_password_plaintext:
749 rc = strcmp (sql_pass, pass); 695 rc = strcmp (sql_pass, pass);
750 break; 696 break;
751 } 697 }
......