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