From d1b31f6a5285a862f71628c935581d19217db5e9 Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Sun, 18 Apr 2021 17:03:50 +0300 Subject: SQL auth: supply backend-specific parameters via the "param" statement. For MySQL, backend-specific parameter is a list of keuword=value pairs delimited by semicolons. Valid keywords are: defaults_file - read configuration from the supplied file; group - if default_file is supplied, read configuration from this named group (default - "client"); ca - name of the certificate authority file; * include/mailutils/sql.h (mu_sql_module_config): New member. (mu_sql_connection): New member. (mu_sql_connection_init): Take additional argument (param). All uses changed. * libmu_auth/sql.c: New keyword: "param". * sql/mysql.c (mu_mysql_connect): Parse backend-specific parameters: defaults_file, group, and ca. * sql/sql.c (mu_sql_connection_init): Take additional argument. Initialize the connection param member. --- include/mailutils/sql.h | 4 ++- libmu_auth/sql.c | 12 ++++++--- mda/lib/mailquota.c | 3 ++- sql/mysql.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++- sql/sql.c | 3 ++- 5 files changed, 84 insertions(+), 7 deletions(-) diff --git a/include/mailutils/sql.h b/include/mailutils/sql.h index dfa2dbc16..cc43dd540 100644 --- a/include/mailutils/sql.h +++ b/include/mailutils/sql.h @@ -39,6 +39,7 @@ struct mu_sql_module_config int port; enum mu_sql_password_encryption password_encryption; mu_assoc_t field_map; + char *param; }; extern struct mu_sql_module_config mu_sql_module_config; @@ -77,6 +78,7 @@ struct mu_sql_connection char *login; char *password; char *dbname; + char *param; void *data; enum mu_sql_connection_state state; }; @@ -115,7 +117,7 @@ int mu_sql_interface_index (char const *name); int mu_sql_connection_init (mu_sql_connection_t *conn, int interface, char *server, int port, char *login, - char *password, char *dbname); + char *password, char *dbname, char *param); int mu_sql_connection_destroy (mu_sql_connection_t *conn); int mu_sql_connect (mu_sql_connection_t conn); diff --git a/libmu_auth/sql.c b/libmu_auth/sql.c index 0d848ebdb..f1c2c7150 100644 --- a/libmu_auth/sql.c +++ b/libmu_auth/sql.c @@ -152,6 +152,9 @@ static struct mu_cfg_param mu_sql_param[] = { "gecos, dir, shell, mailbox, quota, and is the name of " "the corresponding SQL column."), N_("map: definition") }, + { "param", mu_c_string, &mu_sql_module_config.param, 0, NULL, + N_("Extra parameters for connection (backend-specific)"), + N_("arg") }, { NULL } }; @@ -376,7 +379,8 @@ mu_auth_sql_by_name (struct mu_auth_data **return_data, mu_sql_module_config.port, mu_sql_module_config.user, mu_sql_module_config.passwd, - mu_sql_module_config.db); + mu_sql_module_config.db, + mu_sql_module_config.param); if (status) { @@ -470,7 +474,8 @@ mu_auth_sql_by_uid (struct mu_auth_data **return_data, mu_sql_module_config.port, mu_sql_module_config.user, mu_sql_module_config.passwd, - mu_sql_module_config.db); + mu_sql_module_config.db, + mu_sql_module_config.param); if (status) { @@ -556,7 +561,8 @@ mu_sql_getpass (const char *username, char **passwd) mu_sql_module_config.port, mu_sql_module_config.user, mu_sql_module_config.passwd, - mu_sql_module_config.db); + mu_sql_module_config.db, + mu_sql_module_config.param); if (status) { diff --git a/mda/lib/mailquota.c b/mda/lib/mailquota.c index db2f30f4c..6f6812cf6 100644 --- a/mda/lib/mailquota.c +++ b/mda/lib/mailquota.c @@ -206,7 +206,8 @@ sql_retrieve_quota (char *name, mu_off_t *quota) mu_sql_module_config.port, mu_sql_module_config.user, mu_sql_module_config.passwd, - mu_sql_module_config.db); + mu_sql_module_config.db, + mu_sql_module_config.param); if (status) { diff --git a/sql/mysql.c b/sql/mysql.c index 079b50132..8f8316000 100644 --- a/sql/mysql.c +++ b/sql/mysql.c @@ -78,7 +78,20 @@ mu_mysql_destroy (mu_sql_connection_t conn) conn->data = NULL; return 0; } - + +enum + { + PARAM_DEFAULTS_FILE, + PARAM_GROUP, + PARAM_CA + }; + +static struct mu_kwd param_kwd[] = { + { "defaults_file", PARAM_DEFAULTS_FILE }, + { "group", PARAM_GROUP }, + { "ca", PARAM_CA }, + { NULL } +}; static int mu_mysql_connect (mu_sql_connection_t conn) @@ -92,6 +105,60 @@ mu_mysql_connect (mu_sql_connection_t conn) mysql_init (mp->mysql); + if (conn->param) { + struct mu_wordsplit ws; + + ws.ws_delim = ";"; + if (mu_wordsplit (conn->param, &ws, + WRDSF_NOVAR | WRDSF_NOCMD | WRDSF_QUOTE | WRDSF_DELIM | + WRDSF_WS)) + { + mu_error (_("can't parse MySQL parameter line %s: %s"), + conn->param, mu_wordsplit_strerror (&ws)); + } + else + { + size_t i; + for (i = 0; i < ws.ws_wordc; i++) + { + int tok; + size_t len = strcspn (ws.ws_wordv[i], "="); + + if (ws.ws_wordv[i][len] == 0) + { + mu_error (_("malformed MySQL parameter keyword (missing '='): %s"), + ws.ws_wordv[i]); + continue; + } + if (mu_kwd_xlat_name_len (param_kwd, ws.ws_wordv[i], len, &tok)) + { + mu_error (_("unrecognized MySQL parameter: %s"), + ws.ws_wordv[i]); + continue; + } + + switch (tok) + { + case PARAM_DEFAULTS_FILE: + mysql_options (mp->mysql, MYSQL_READ_DEFAULT_FILE, + ws.ws_wordv[i] + len + 1); + break; + + case PARAM_GROUP: + mysql_options (mp->mysql, MYSQL_READ_DEFAULT_GROUP, + ws.ws_wordv[i] + len + 1); + break; + + case PARAM_CA: + mysql_ssl_set (mp->mysql, NULL, NULL, ws.ws_wordv[i] + len + 1, + NULL, NULL); + break; + } + } + mu_wordsplit_free (&ws); + } + } + if (conn->server && conn->server[0] == '/') { host = "localhost"; diff --git a/sql/sql.c b/sql/sql.c index a4d303b28..3fc7775d9 100644 --- a/sql/sql.c +++ b/sql/sql.c @@ -111,7 +111,7 @@ get_sql_entry (int type) int mu_sql_connection_init (mu_sql_connection_t *pconn, int interface, char *server, int port, char *login, - char *password, char *dbname) + char *password, char *dbname, char *param) { static mu_sql_dispatch_t *tab; mu_sql_connection_t conn; @@ -130,6 +130,7 @@ mu_sql_connection_init (mu_sql_connection_t *pconn, int interface, conn->login = login; conn->password = password; conn->dbname = dbname; + conn->param = param; if (tab->init) { int rc = tab->init (conn); -- cgit v1.2.1