postconf_dbms.c revision 1.1
1/*	$NetBSD: postconf_dbms.c,v 1.1 2013/01/02 18:59:03 tron 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	register_dbms_parameters(param_value, flag_parameter,
12/*					local_scope)
13/*	const char *param_value;
14/*	const char *(flag_parameter) (const char *, int, char *);
15/*	PC_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, an unused value, and a local namespace 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
60/* Global library. */
61
62#include <mail_conf.h>
63#include <dict_proxy.h>
64#include <dict_ldap.h>
65#include <dict_mysql.h>
66#include <dict_pgsql.h>
67#include <dict_sqlite.h>
68#include <dict_memcache.h>
69
70/* Application-specific. */
71
72#include <postconf.h>
73
74 /*
75  * SLMs.
76  */
77#define STR(x)	vstring_str(x)
78
79#ifdef LEGACY_DBMS_SUPPORT
80
81 /*
82  * The legacy database interface automagically instantiates a list of
83  * parameters by prepending the table name to database-specific suffixes.
84  */
85
86/* See ldap_table(5). */
87
88static const char *ldap_suffixes[] = {
89    "bind", "bind_dn", "bind_pw", "cache", "cache_expiry", "cache_size",
90    "chase_referrals", "debuglevel", "dereference", "domain",
91    "expansion_limit", "leaf_result_attribute", "query_filter",
92    "recursion_limit", "result_attribute", "result_format", "scope",
93    "search_base", "server_host", "server_port", "size_limit",
94    "special_result_attribute", "terminal_result_attribute",
95    "timeout", "version", 0,
96};
97
98/* See mysql_table(5). */
99
100static const char *mysql_suffixes[] = {
101    "additional_conditions", "dbname", "domain", "expansion_limit",
102    "hosts", "password", "query", "result_format", "select_field",
103    "table", "user", "where_field", 0,
104};
105
106/* See pgsql_table(5). */
107
108static const char *pgsql_suffixes[] = {
109    "additional_conditions", "dbname", "domain", "expansion_limit",
110    "hosts", "password", "query", "result_format", "select_field",
111    "select_function", "table", "user", "where_field", 0,
112};
113
114/* See sqlite_table(5). */
115
116static const char *sqlite_suffixes[] = {
117    "additional_conditions", "dbpath", "domain", "expansion_limit",
118    "query", "result_format", "select_field", "table", "where_field",
119    0,
120};
121
122/* See memcache_table(5). */
123
124static const char *memcache_suffixes[] = {
125    "backup", "data_size_limit", "domain", "flags", "key_format",
126    "line_size_limit", "max_try", "memcache", "retry_pause",
127    "timeout", "ttl", 0,
128};
129
130 /*
131  * Bundle up the database types and their suffix lists.
132  */
133typedef struct {
134    const char *db_type;
135    const char **db_suffixes;
136} PC_DBMS_INFO;
137
138static const PC_DBMS_INFO dbms_info[] = {
139    DICT_TYPE_LDAP, ldap_suffixes,
140    DICT_TYPE_MYSQL, mysql_suffixes,
141    DICT_TYPE_PGSQL, pgsql_suffixes,
142    DICT_TYPE_SQLITE, sqlite_suffixes,
143    DICT_TYPE_MEMCACHE, memcache_suffixes,
144    0,
145};
146
147/* register_dbms_parameters_cb - mac_expand() call-back */
148
149static const char *register_dbms_parameters_cb(const char *mac_name,
150					               int unused_mode,
151					               char *context)
152{
153    PC_MASTER_ENT *local_scope = (PC_MASTER_ENT *) context;
154    const char *mac_val;
155
156    /*
157     * Local namespace "name=value" settings are always explicit. They have
158     * precedence over global namespace "name=value" settings which are
159     * either explicit or defined by their default value.
160     */
161    if (local_scope == 0
162	|| (mac_val = dict_get(local_scope->all_params, mac_name)) == 0)
163	mac_val = mail_conf_lookup(mac_name);
164    return (mac_val);
165}
166
167/* register_dbms_parameters - look for database_type:prefix_name */
168
169void    register_dbms_parameters(const char *param_value,
170	           const char *(flag_parameter) (const char *, int, char *),
171				         PC_MASTER_ENT *local_scope)
172{
173    const PC_DBMS_INFO *dp;
174    char   *bufp;
175    char   *db_type;
176    char   *prefix;
177    static VSTRING *buffer = 0;
178    static VSTRING *candidate = 0;
179    const char **cpp;
180
181    /*
182     * Emulate Postfix parameter value expansion, prepending the appropriate
183     * local (master.cf "-o name-value") namespace to the global (main.cf
184     * "name=value") namespace.
185     *
186     * XXX This does not examine both sides of conditional macro expansion, and
187     * may expand the "wrong" conditional macros. This is the best we can do
188     * for legacy database configuration support.
189     */
190#define NO_SCAN_FILTER	((char *) 0)
191
192    (void) mac_expand(buffer ? buffer : (buffer = vstring_alloc(100)),
193		      param_value, MAC_EXP_FLAG_RECURSE, NO_SCAN_FILTER,
194		      register_dbms_parameters_cb, (char *) local_scope);
195
196    /*
197     * Naive parsing. We don't really know if the parameter specifies free
198     * text or a list of databases.
199     */
200    bufp = STR(buffer);
201    while ((db_type = mystrtok(&bufp, " ,\t\r\n")) != 0) {
202
203	/*
204	 * Skip over "proxy:" indirections.
205	 */
206	while ((prefix = split_at(db_type, ':')) != 0
207	       && strcmp(db_type, DICT_TYPE_PROXY) == 0)
208	    db_type = prefix;
209
210	/*
211	 * Look for database:prefix where the prefix is not a pathname and
212	 * the database is a known type. Synthesize candidate parameter names
213	 * from the user-defined prefix and from the database-defined suffix
214	 * list, and see if those parameters have a "name=value" entry in the
215	 * local or global namespace.
216	 */
217	if (prefix != 0 && *prefix != '/' && *prefix != '.') {
218	    for (dp = dbms_info; dp->db_type != 0; dp++) {
219		if (strcmp(db_type, dp->db_type) == 0) {
220		    for (cpp = dp->db_suffixes; *cpp; cpp++) {
221			vstring_sprintf(candidate ? candidate :
222					(candidate = vstring_alloc(30)),
223					"%s_%s", prefix, *cpp);
224			flag_parameter(STR(candidate), 0, (char *) local_scope);
225		    }
226		    break;
227		}
228	    }
229	}
230    }
231}
232
233#endif
234