postconf_dbms.c revision 1.2
1/* $NetBSD: postconf_dbms.c,v 1.2 2017/02/14 01:16:46 christos Exp $ */ 2 3/*++ 4/* NAME 5/* postconf_dbms 3 6/* SUMMARY 7/* legacy support for database-defined main.cf parameter names 8/* SYNOPSIS 9/* #include <postconf.h> 10/* 11/* void pcf_register_dbms_parameters(param_value, flag_parameter, 12/* local_scope) 13/* const char *param_value; 14/* const char *(flag_parameter) (const char *, int, PCF_MASTER_ENT *); 15/* PCF_MASTER_ENT *local_scope; 16/* DESCRIPTION 17/* This module implements legacy support for database configuration 18/* where main.cf parameter names are generated by prepending 19/* the database name to a database-defined suffix. 20/* 21/* Arguments: 22/* .IP param_value 23/* A parameter value to be searched for "type:table" strings. 24/* When a database type is found that supports legacy-style 25/* configuration, the table name is combined with each of the 26/* database-defined suffixes to generate candidate parameter 27/* names for that database type. 28/* .IP flag_parameter 29/* A function that takes as arguments a candidate parameter 30/* name, parameter flags, and a PCF_MASTER_ENT pointer. The 31/* function will flag the parameter as "used" if it has a 32/* "name=value" entry in the local or global namespace. 33/* .IP local_scope 34/* The local namespace. 35/* DIAGNOSTICS 36/* No explicit diagnostics. 37/* LICENSE 38/* .ad 39/* .fi 40/* The Secure Mailer license must be distributed with this software. 41/* AUTHOR(S) 42/* Wietse Venema 43/* IBM T.J. Watson Research 44/* P.O. Box 704 45/* Yorktown Heights, NY 10598, USA 46/*--*/ 47 48/* System library. */ 49 50#include <sys_defs.h> 51#include <string.h> 52 53/* Utility library. */ 54 55#include <stringops.h> 56#include <split_at.h> 57#include <mac_expand.h> 58#include <dict.h> 59#include <msg.h> 60#include <mymalloc.h> 61 62/* Global library. */ 63 64#include <mail_conf.h> 65#include <mail_params.h> 66#include <dict_proxy.h> 67#include <dict_ldap.h> 68#include <dict_mysql.h> 69#include <dict_pgsql.h> 70#include <dict_sqlite.h> 71#include <dict_memcache.h> 72 73/* Application-specific. */ 74 75#include <postconf.h> 76 77 /* 78 * SLMs. 79 */ 80#define STR(x) vstring_str(x) 81 82#ifdef LEGACY_DBMS_SUPPORT 83 84 /* 85 * The legacy database interface automagically instantiates a list of 86 * parameters by prepending the table name to database-specific suffixes. 87 */ 88 89/* See ldap_table(5). */ 90 91static const char *pcf_ldap_suffixes[] = { 92 "bind", "bind_dn", "bind_pw", "cache", "cache_expiry", "cache_size", 93 "chase_referrals", "debuglevel", "dereference", "domain", 94 "expansion_limit", "leaf_result_attribute", "query_filter", 95 "recursion_limit", "result_attribute", "result_format", "scope", 96 "search_base", "server_host", "server_port", "size_limit", 97 "special_result_attribute", "terminal_result_attribute", 98 "timeout", "version", 0, 99}; 100 101/* See mysql_table(5). */ 102 103static const char *pcf_mysql_suffixes[] = { 104 "additional_conditions", "dbname", "domain", "expansion_limit", 105 "hosts", "password", "query", "result_format", "select_field", 106 "table", "user", "where_field", 0, 107}; 108 109/* See pgsql_table(5). */ 110 111static const char *pcf_pgsql_suffixes[] = { 112 "additional_conditions", "dbname", "domain", "expansion_limit", 113 "hosts", "password", "query", "result_format", "select_field", 114 "select_function", "table", "user", "where_field", 0, 115}; 116 117/* See sqlite_table(5). */ 118 119static const char *pcf_sqlite_suffixes[] = { 120 "additional_conditions", "dbpath", "domain", "expansion_limit", 121 "query", "result_format", "select_field", "table", "where_field", 122 0, 123}; 124 125/* See memcache_table(5). */ 126 127static const char *pcf_memcache_suffixes[] = { 128 "backup", "data_size_limit", "domain", "flags", "key_format", 129 "line_size_limit", "max_try", "memcache", "retry_pause", 130 "timeout", "ttl", 0, 131}; 132 133 /* 134 * Bundle up the database types and their suffix lists. 135 */ 136typedef struct { 137 const char *db_type; 138 const char **db_suffixes; 139} PCF_DBMS_INFO; 140 141static const PCF_DBMS_INFO pcf_dbms_info[] = { 142 DICT_TYPE_LDAP, pcf_ldap_suffixes, 143 DICT_TYPE_MYSQL, pcf_mysql_suffixes, 144 DICT_TYPE_PGSQL, pcf_pgsql_suffixes, 145 DICT_TYPE_SQLITE, pcf_sqlite_suffixes, 146 DICT_TYPE_MEMCACHE, pcf_memcache_suffixes, 147 0, 148}; 149 150/* pcf_register_dbms_helper - parse one possible database type:name */ 151 152static void pcf_register_dbms_helper(char *str_value, 153 const char *(flag_parameter) (const char *, int, PCF_MASTER_ENT *), 154 PCF_MASTER_ENT *local_scope) 155{ 156 const PCF_DBMS_INFO *dp; 157 char *db_type; 158 char *prefix; 159 static VSTRING *candidate = 0; 160 const char **cpp; 161 char *err; 162 163 /* 164 * Naive parsing. We don't really know if this substring specifies a 165 * database or some other text. 166 */ 167 while ((db_type = mystrtokq(&str_value, CHARS_COMMA_SP, CHARS_BRACE)) != 0) { 168 169 /* 170 * Skip over "proxy:" maptypes, to emulate the proxymap(8) server's 171 * behavior when opening a local database configuration file. 172 */ 173 while ((prefix = split_at(db_type, ':')) != 0 174 && strcmp(db_type, DICT_TYPE_PROXY) == 0) 175 db_type = prefix; 176 177 /* 178 * Look for database:prefix where the prefix is not a pathname and 179 * the database is a known type. Synthesize candidate parameter names 180 * from the user-defined prefix and from the database-defined suffix 181 * list, and see if those parameters have a "name=value" entry in the 182 * local or global namespace. 183 */ 184 if (prefix != 0 && *prefix != '/' && *prefix != '.') { 185 if (*prefix == CHARS_BRACE[0]) { 186 if ((err = extpar(&prefix, CHARS_BRACE, EXTPAR_FLAG_NONE)) != 0) { 187 /* XXX Encapsulate this in pcf_warn() function. */ 188 if (local_scope) 189 msg_warn("%s:%s: %s", 190 MASTER_CONF_FILE, local_scope->name_space, 191 err); 192 else 193 msg_warn("%s: %s", MAIN_CONF_FILE, err); 194 myfree(err); 195 } 196 pcf_register_dbms_helper(prefix, flag_parameter, 197 local_scope); 198 } else { 199 for (dp = pcf_dbms_info; dp->db_type != 0; dp++) { 200 if (strcmp(db_type, dp->db_type) == 0) { 201 for (cpp = dp->db_suffixes; *cpp; cpp++) { 202 vstring_sprintf(candidate ? candidate : 203 (candidate = vstring_alloc(30)), 204 "%s_%s", prefix, *cpp); 205 flag_parameter(STR(candidate), 206 PCF_PARAM_FLAG_DBMS | PCF_PARAM_FLAG_USER, 207 local_scope); 208 } 209 break; 210 } 211 } 212 } 213 } 214 } 215} 216 217/* pcf_register_dbms_parameters - look for database_type:prefix_name */ 218 219void pcf_register_dbms_parameters(const char *param_value, 220 const char *(flag_parameter) (const char *, int, PCF_MASTER_ENT *), 221 PCF_MASTER_ENT *local_scope) 222{ 223 char *bufp; 224 static VSTRING *buffer = 0; 225 226 /* 227 * XXX This does not examine both sides of conditional macro expansion, 228 * and may expand the "wrong" conditional macros. This is the best we can 229 * do for legacy database configuration support. 230 */ 231 if (buffer == 0) 232 buffer = vstring_alloc(100); 233 bufp = pcf_expand_parameter_value(buffer, PCF_SHOW_EVAL, param_value, 234 local_scope); 235 pcf_register_dbms_helper(bufp, flag_parameter, local_scope); 236} 237 238#endif 239