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)
}
#ifdef USE_SQL
if (mu_sql_module_config.password_type == password_plaintext)
if (mu_sql_module_config.password_encryption == mu_sql_password_plaintext)
{
char *passwd;
int status = mu_sql_getpass (*username, &passwd);
......
......@@ -297,6 +297,10 @@ int mu_cfg_create_subtree (const char *path, mu_cfg_node_t **pnode);
int mu_cfg_parse_config (mu_cfg_tree_t **ptree,
struct mu_cfg_parse_hints *hints);
int mu_cfg_field_map (struct mu_config_value const *val, mu_assoc_t *passoc,
char **err_term);
#ifdef __cplusplus
}
#endif
......
......@@ -20,11 +20,11 @@
#define _MAILUTILS_SQL_H
/* Configuration */
enum mu_password_type
enum mu_sql_password_encryption
{
password_plaintext, /* Plaintext passwords */
password_scrambled, /* Scrambled MySQL (>=3.21) password */
password_hash, /* MD5 (or DES or whatever) hash */
mu_sql_password_plaintext, /* Plaintext passwords */
mu_sql_password_scrambled, /* Scrambled MySQL (>=3.21) password */
mu_sql_password_hash, /* MD5 (or DES or whatever) hash */
};
struct mu_sql_module_config
......@@ -38,8 +38,7 @@ struct mu_sql_module_config
char *passwd;
char *db;
int port;
enum mu_password_type password_type;
int positional;
enum mu_sql_password_encryption password_encryption;
mu_assoc_t field_map;
};
......@@ -143,6 +142,4 @@ extern int mu_sql_getpass (const char *username, char **passwd);
extern int mu_check_mysql_scrambled_password (const char *scrambled,
const char *message);
int mu_sql_decode_password_type (const char *arg, enum mu_password_type *t);
#endif
......
......@@ -118,21 +118,6 @@ mutil_parse_field_map (const char *map, mu_assoc_t *passoc_tab, int *perr)
return rc;
}
/* FIXME: should it be here? */
int
mu_sql_decode_password_type (const char *arg, enum mu_password_type *t)
{
if (strcmp (arg, "plain") == 0)
*t = password_plaintext;
else if (strcmp (arg, "hash") == 0)
*t = password_hash;
else if (strcmp (arg, "scrambled") == 0)
*t = password_scrambled;
else
return 1;
return 0;
}
int
mu_stream_flags_to_mode (int flags, int isdir)
{
......
......@@ -38,7 +38,7 @@
#include <mailutils/stream.h>
#include <mailutils/assoc.h>
#include <mailutils/alloc.h>
#include <mailutils/cstr.h>
static mu_assoc_t section_tab;
......@@ -587,3 +587,92 @@ mu_cfg_string_value_cb (mu_config_value_t *val,
}
return rc;
}
struct mapping_closure
{
mu_assoc_t assoc;
char *err_term;
int err;
};
static int
parse_mapping (void *item, void *data)
{
struct mapping_closure *clos = data;
char *str = item;
size_t len;
char *key, *val;
len = strcspn (str, "=");
if (str[len] == 0)
{
clos->err_term = mu_strdup (str);
return MU_ERR_PARSE;
}
key = mu_alloc (len + 1);
memcpy (key, str, len);
key[len] = 0;
val = mu_strdup (str + len + 1);
if (!val)
return ENOMEM;
clos->err = mu_assoc_install (clos->assoc, key, &val);
free (key);
if (clos->err)
return 1;
return 0;
}
static void
assoc_str_free (void *data)
{
free (data);
}
int
mu_cfg_field_map (struct mu_config_value const *val, mu_assoc_t *passoc,
char **err_term)
{
int rc;
struct mapping_closure clos;
mu_list_t list = NULL;
rc = mu_assoc_create (&clos.assoc, sizeof(char*), 0);
if (rc)
return rc;
mu_assoc_set_free (clos.assoc, assoc_str_free);
clos.err_term = NULL;
switch (val->type)
{
case MU_CFG_STRING:
mu_list_create (&list);
mu_list_set_destroy_item (list, mu_list_free_item);
rc = mu_string_split (val->v.string, ":", list);
if (rc == 0)
rc = mu_list_foreach (list, parse_mapping, &clos);
mu_list_destroy (&list);
break;
case MU_CFG_LIST:
rc = mu_list_foreach (val->v.list, parse_mapping, &clos);
break;
case MU_CFG_ARRAY:
rc = EINVAL;
}
if (rc)
{
if (err_term)
*err_term = clos.err_term;
else
free (clos.err_term);
mu_assoc_destroy (&clos.assoc);
}
else
*passoc = clos.assoc;
return rc;
}
......
......@@ -39,12 +39,8 @@
#include <gsasl.h>
struct mu_gsasl_module_data mu_gsasl_module_data = {
1,
NULL,
NULL,
NULL,
NULL,
SITE_CRAM_MD5_PWD
.enable = 1,
.cram_md5_pwd = SITE_CRAM_MD5_PWD
};
static struct mu_cfg_param mu_gsasl_param[] = {
......
......@@ -61,23 +61,21 @@ const char *default_field_map =
static struct mu_ldap_module_config ldap_param;
static int
_cb2_field_map (const char *arg, void *data)
cb_field_map (void *data, mu_config_value_t *val)
{
int err;
int rc = mutil_parse_field_map (arg, &ldap_param.field_map, &err);
char *err_term;
int rc = mu_cfg_field_map (val, &ldap_param.field_map, &err_term);
if (rc)
/* FIXME: this message can be misleading */
mu_error (_("error near element %d: %s"), err, mu_strerror (rc));
return 0;
}
{
if (err_term)
mu_error (_("error near %s: %s"), err_term, mu_strerror (rc));
else
mu_error ("%s", mu_strerror (rc));
}
static int
cb_field_map (void *data, mu_config_value_t *val)
{
return mu_cfg_string_value_cb (val, _cb2_field_map, NULL);
return rc;
}
static struct mu_cfg_param mu_ldap_param[] = {
......@@ -140,14 +138,18 @@ module_init (void *ptr)
if (ldap_param.enable)
{
if (!ldap_param.getpwnam_filter)
ldap_param.getpwnam_filter = "(&(objectClass=posixAccount) (uid=%u))";
ldap_param.getpwnam_filter =
"(&(objectClass=posixAccount) (uid=$user))";
if (!ldap_param.getpwuid_filter)
ldap_param.getpwuid_filter =
"&(objectClass=posixAccount) (uidNumber=%u))";
"(&(objectClass=posixAccount) (uidNumber=$user))";
if (!ldap_param.field_map)
{
int d;
mutil_parse_field_map (default_field_map, &ldap_param.field_map, &d);
struct mu_config_value val;
val.type = MU_CFG_STRING;
val.v.string = default_field_map;
if (mu_cfg_field_map (&val, &ldap_param.field_map, NULL))
abort ();
}
}
}
......
......@@ -51,38 +51,53 @@
#include <mailutils/cstr.h>
#include <mailutils/wordsplit.h>
#include <mailutils/cli.h>
#include <mailutils/kwd.h>
#include "sql.h"
#ifdef USE_SQL
struct mu_sql_module_config mu_sql_module_config;
/* Resource file configuration */
static struct mu_kwd password_encryption[] = {
{ "plain", mu_sql_password_plaintext },
{ "scrambled", mu_sql_password_scrambled },
{ "hash", mu_sql_password_hash },
{ "crypt", mu_sql_password_hash },
{ NULL }
};
static int
cb_password_type (void *data, mu_config_value_t *val)
cb_password_encryption (void *data, mu_config_value_t *val)
{
int res;
if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
return 1;
if (mu_sql_decode_password_type (val->v.string, &mu_sql_module_config.password_type))
mu_error (_("unknown password type `%s'"), val->v.string);
if (mu_kwd_xlat_name (password_encryption, val->v.string, &res))
mu_error ("%s", _("unrecognized password encryption"));
else
mu_sql_module_config.password_encryption = res;
return 0;
}
static int
_cb2_field_map (const char *arg, void *data)
cb_field_map (void *data, mu_config_value_t *val)
{
int err;
int rc = mutil_parse_field_map (arg, &mu_sql_module_config.field_map, &err);
char *err_term;
int rc = mu_cfg_field_map (val, &mu_sql_module_config.field_map, &err_term);
if (rc)
/* FIXME: this message may be misleading */
mu_error (_("error near element %d: %s"), err, mu_strerror (rc));
return 0;
}
{
if (err_term)
mu_error (_("error near %s: %s"), err_term, mu_strerror (rc));
else
mu_error ("%s", mu_strerror (rc));
}
static int
cb_field_map (void *data, mu_config_value_t *val)
{
return mu_cfg_string_value_cb (val, _cb2_field_map, NULL);
return rc;
}
static int
......@@ -124,12 +139,10 @@ static struct mu_cfg_param mu_sql_param[] = {
N_("SQL server port.") },
{ "db", mu_c_string, &mu_sql_module_config.db, 0, NULL,
N_("Database name.") },
{ "password-type", mu_cfg_callback, NULL, 0, cb_password_type,
{ "password-encryption", mu_cfg_callback, NULL, 0, cb_password_encryption,
N_("Type of password returned by getpass query."),
/* TRANSLATORS: Words to the right of : are keywords - do not translate */
N_("arg: plain|hash|scrambled") },
{ "positional", mu_c_bool, &mu_sql_module_config.positional, 0, NULL,
N_("Use positional (v1.0 compatible) field interface.") },
N_("arg: plain|hash|crypt|scrambled") },
{ "field-map", mu_cfg_callback, NULL, 0, cb_field_map,
N_("Set a field-map for parsing SQL replies. The map is a "
"column-separated list of definitions. Each definition has the "
......@@ -208,63 +221,6 @@ mu_sql_expand_query (const char *query, const char *ustr)
return res;
}
static int
decode_tuple_v1_0 (mu_sql_connection_t conn, int n,
struct mu_auth_data **return_data)
{
int rc;
char *mailbox_name = NULL;
char *name;
if (mu_sql_get_column (conn, 0, 0, &name))
return MU_ERR_FAILURE;
if (n == 7)
{
char *tmp;
if (mu_sql_get_column (conn, 0, 6, &tmp))
return MU_ERR_FAILURE;
if (tmp && (mailbox_name = strdup (tmp)) == NULL)
return ENOMEM;
}
else if (mu_construct_user_mailbox_url (&mailbox_name, name))
return MU_ERR_FAILURE;
if (mailbox_name)
{
char *passwd, *suid, *sgid, *dir, *shell;
if (mu_sql_get_column (conn, 0, 1, &passwd)
|| !passwd
|| mu_sql_get_column (conn, 0, 2, &suid)
|| !suid
|| mu_sql_get_column (conn, 0, 3, &sgid)
|| !sgid
|| mu_sql_get_column (conn, 0, 4, &dir)
|| !dir
|| mu_sql_get_column (conn, 0, 5, &shell)
|| !shell)
return MU_ERR_FAILURE;
rc = mu_auth_data_alloc (return_data,
name,
passwd,
atoi (suid),
atoi (sgid),
"SQL User",
dir,
shell,
mailbox_name,
1);
}
else
rc = MU_ERR_AUTH_FAILURE;
free (mailbox_name);
return rc;
}
static int
get_field (mu_sql_connection_t conn, const char *id, char **ret, int mandatory)
{
......@@ -292,7 +248,7 @@ get_field (mu_sql_connection_t conn, const char *id, char **ret, int mandatory)
}
static int
decode_tuple_new (mu_sql_connection_t conn, int n,
decode_tuple (mu_sql_connection_t conn, int n,
struct mu_auth_data **return_data)
{
int rc;
......@@ -403,16 +359,6 @@ decode_tuple_new (mu_sql_connection_t conn, int n,
}
static int
decode_tuple (mu_sql_connection_t conn, int n,
struct mu_auth_data **return_data)
{
if (mu_sql_module_config.field_map || !mu_sql_module_config.positional)
return decode_tuple_new (conn, n, return_data);
else
return decode_tuple_v1_0 (conn, n, return_data);
}
static int
mu_auth_sql_by_name (struct mu_auth_data **return_data,
const void *key,
void *func_data MU_ARG_UNUSED,
......@@ -723,9 +669,9 @@ mu_sql_authenticate (struct mu_auth_data **return_data MU_ARG_UNUSED,
if ((rc = mu_sql_getpass (auth_data->name, &sql_pass)))
return rc;
switch (mu_sql_module_config.password_type)
switch (mu_sql_module_config.password_encryption)
{
case password_hash:
case mu_sql_password_hash:
crypt_pass = crypt (pass, sql_pass);
if (!crypt_pass)
rc = 1;
......@@ -733,7 +679,7 @@ mu_sql_authenticate (struct mu_auth_data **return_data MU_ARG_UNUSED,
rc = strcmp (sql_pass, crypt_pass);
break;
case password_scrambled:
case mu_sql_password_scrambled:
/* FIXME: Should this call be implementation-independent? I mean,
should we have mu_sql_check_scrambled() that will match the
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,
#endif
break;
case password_plaintext:
case mu_sql_password_plaintext:
rc = strcmp (sql_pass, pass);
break;
}
......