xref: /netbsd-src/external/ibm-public/postfix/dist/src/postconf/postconf_dbms.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
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 
91 static 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 
103 static 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 
111 static 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 
119 static 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 
127 static 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   */
136 typedef struct {
137     const char *db_type;
138     const char **db_suffixes;
139 } PCF_DBMS_INFO;
140 
141 static 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 
152 static 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 
219 void    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