1 #ifndef _DICT_H_INCLUDED_
2 #define _DICT_H_INCLUDED_
3 
4 /*++
5 /* NAME
6 /*	dict 3h
7 /* SUMMARY
8 /*	dictionary manager
9 /* SYNOPSIS
10 /*	#include <dict.h>
11 /* DESCRIPTION
12 /* .nf
13 
14  /*
15   * System library.
16   */
17 #include <sys/stat.h>
18 #include <fcntl.h>
19 #include <setjmp.h>
20 
21 #ifdef NO_SIGSETJMP
22 #define DICT_JMP_BUF jmp_buf
23 #else
24 #define DICT_JMP_BUF sigjmp_buf
25 #endif
26 
27  /*
28   * Utility library.
29   */
30 #include <vstream.h>
31 #include <argv.h>
32 #include <vstring.h>
33 #include <myflock.h>
34 
35  /*
36   * Provenance information.
37   */
38 typedef struct DICT_OWNER {
39     int     status;			/* see below */
40     uid_t   uid;			/* use only if status == UNTRUSTED */
41 } DICT_OWNER;
42 
43  /*
44   * Note that trust levels are not in numerical order.
45   */
46 #define DICT_OWNER_UNKNOWN	(-1)	/* ex: unauthenticated tcp, proxy */
47 #define DICT_OWNER_TRUSTED	(!1)	/* ex: root-owned config file */
48 #define DICT_OWNER_UNTRUSTED	(!0)	/* ex: non-root config file */
49 
50  /*
51   * When combining tables with different provenance, we initialize to the
52   * highest trust level, and remember the lowest trust level that we find
53   * during aggregation. If we combine tables that are owned by different
54   * untrusted users, the resulting provenance is "unknown".
55   */
56 #define DICT_OWNER_AGGREGATE_INIT(dst) { \
57 	(dst).status = DICT_OWNER_TRUSTED; \
58 	(dst).uid = 0; \
59     } while (0)
60 
61  /*
62   * The following is derived from the 3x3 transition matrix.
63   */
64 #define DICT_OWNER_AGGREGATE_UPDATE(dst, src) do { \
65 	if ((dst).status == DICT_OWNER_TRUSTED \
66 	    || (src).status == DICT_OWNER_UNKNOWN) { \
67 	    (dst) = (src); \
68 	} else if ((dst).status == (src).status \
69 		&& (dst).uid != (src).uid) { \
70 	    (dst).status = DICT_OWNER_UNKNOWN; \
71 	    (dst).uid = ~0; \
72 	} \
73     } while (0)
74 
75  /*
76   * Generic dictionary interface - in reality, a dictionary extends this
77   * structure with private members to maintain internal state.
78   */
79 typedef struct DICT {
80     char   *type;			/* for diagnostics */
81     char   *name;			/* for diagnostics */
82     int     flags;			/* see below */
83     const char *(*lookup) (struct DICT *, const char *);
84     int     (*update) (struct DICT *, const char *, const char *);
85     int     (*delete) (struct DICT *, const char *);
86     int     (*sequence) (struct DICT *, int, const char **, const char **);
87     int     (*lock) (struct DICT *, int);
88     void    (*close) (struct DICT *);
89     int     lock_type;			/* for read/write lock */
90     int     lock_fd;			/* for read/write lock */
91     int     stat_fd;			/* change detection */
92     time_t  mtime;			/* mod time at open */
93     VSTRING *fold_buf;			/* key folding buffer */
94     DICT_OWNER owner;			/* provenance */
95     int     error;			/* last operation only */
96     DICT_JMP_BUF *jbuf;			/* exception handling */
97     struct DICT_UTF8_BACKUP *utf8_backup;	/* see below */
98     struct VSTRING *file_buf;		/* dict_file_to_buf() */
99     struct VSTRING *file_b64;		/* dict_file_to_b64() */
100 } DICT;
101 
102 extern DICT *dict_alloc(const char *, const char *, ssize_t);
103 extern void dict_free(DICT *);
104 
105 extern DICT *dict_debug(DICT *);
106 
107 #define DICT_DEBUG(d) ((d)->flags & DICT_FLAG_DEBUG ? dict_debug(d) : (d))
108 
109  /*
110   * See dict_open.c embedded manpage for flag definitions.
111   */
112 #define DICT_FLAG_NONE		(0)
113 #define DICT_FLAG_DUP_WARN	(1<<0)	/* warn about dups if not supported */
114 #define DICT_FLAG_DUP_IGNORE	(1<<1)	/* ignore dups if not supported */
115 #define DICT_FLAG_TRY0NULL	(1<<2)	/* do not append 0 to key/value */
116 #define DICT_FLAG_TRY1NULL	(1<<3)	/* append 0 to key/value */
117 #define DICT_FLAG_FIXED		(1<<4)	/* fixed key map */
118 #define DICT_FLAG_PATTERN	(1<<5)	/* keys are patterns */
119 #define DICT_FLAG_LOCK		(1<<6)	/* use temp lock before access */
120 #define DICT_FLAG_DUP_REPLACE	(1<<7)	/* replace dups if supported */
121 #define DICT_FLAG_SYNC_UPDATE	(1<<8)	/* sync updates if supported */
122 #define DICT_FLAG_DEBUG		(1<<9)	/* log access */
123 /*#define DICT_FLAG_FOLD_KEY	(1<<10)	/* lowercase the lookup key */
124 #define DICT_FLAG_NO_REGSUB	(1<<11)	/* disallow regexp substitution */
125 #define DICT_FLAG_NO_PROXY	(1<<12)	/* disallow proxy mapping */
126 #define DICT_FLAG_NO_UNAUTH	(1<<13)	/* disallow unauthenticated data */
127 #define DICT_FLAG_FOLD_FIX	(1<<14)	/* case-fold key with fixed-case map */
128 #define DICT_FLAG_FOLD_MUL	(1<<15)	/* case-fold key with multi-case map */
129 #define DICT_FLAG_FOLD_ANY	(DICT_FLAG_FOLD_FIX | DICT_FLAG_FOLD_MUL)
130 #define DICT_FLAG_OPEN_LOCK	(1<<16)	/* perm lock if not multi-writer safe */
131 #define DICT_FLAG_BULK_UPDATE	(1<<17)	/* optimize for bulk updates */
132 #define DICT_FLAG_MULTI_WRITER	(1<<18)	/* multi-writer safe map */
133 #define DICT_FLAG_UTF8_REQUEST	(1<<19)	/* activate UTF-8 if possible */
134 #define DICT_FLAG_UTF8_ACTIVE	(1<<20)	/* UTF-8 proxy layer is present */
135 #define DICT_FLAG_SRC_RHS_IS_FILE \
136 				(1<<21)	/* Map source RHS is a file */
137 
138 #define DICT_FLAG_UTF8_MASK	(DICT_FLAG_UTF8_REQUEST)
139 
140  /* IMPORTANT: Update the dict_mask[] table when the above changes */
141 
142  /*
143   * The subsets of flags that control how a map is used. These are relevant
144   * mainly for proxymap support. Note: some categories overlap.
145   *
146   * DICT_FLAG_IMPL_MASK - flags that are set by the map implementation itself.
147   *
148   * DICT_FLAG_PARANOID - requestor flags that forbid the use of insecure map
149   * types for security-sensitive operations. These flags are checked by the
150   * map implementation itself upon open, lookup etc. requests.
151   *
152   * DICT_FLAG_RQST_MASK - all requestor flags, including paranoid flags, that
153   * the requestor may change between open, lookup etc. requests. These
154   * specify requestor properties, not map properties.
155   *
156   * DICT_FLAG_INST_MASK - none of the above flags. The requestor may not change
157   * these flags between open, lookup, etc. requests (although a map may make
158   * changes to its copy of some of these flags). The proxymap server opens
159   * only one map instance for all client requests with the same values of
160   * these flags, and the proxymap client uses its own saved copy of these
161   * flags. DICT_FLAG_SRC_RHS_IS_FILE is an example of such a flag.
162   */
163 #define DICT_FLAG_PARANOID \
164 	(DICT_FLAG_NO_REGSUB | DICT_FLAG_NO_PROXY | DICT_FLAG_NO_UNAUTH)
165 #define DICT_FLAG_IMPL_MASK	(DICT_FLAG_FIXED | DICT_FLAG_PATTERN | \
166 				DICT_FLAG_MULTI_WRITER)
167 #define DICT_FLAG_RQST_MASK	(DICT_FLAG_FOLD_ANY | DICT_FLAG_LOCK | \
168 				DICT_FLAG_DUP_REPLACE | DICT_FLAG_DUP_WARN | \
169 				DICT_FLAG_DUP_IGNORE | DICT_FLAG_SYNC_UPDATE | \
170 				DICT_FLAG_PARANOID | DICT_FLAG_UTF8_MASK)
171 #define DICT_FLAG_INST_MASK	~(DICT_FLAG_IMPL_MASK | DICT_FLAG_RQST_MASK)
172 
173  /*
174   * Feature tests.
175   */
176 #define DICT_NEED_UTF8_ACTIVATION(enable, flags) \
177 	((enable) && ((flags) & DICT_FLAG_UTF8_MASK))
178 
179  /*
180   * dict->error values. Errors must be negative; smtpd_check depends on this.
181   */
182 #define DICT_ERR_NONE	0		/* no error */
183 #define DICT_ERR_RETRY	(-1)		/* soft error */
184 #define DICT_ERR_CONFIG	(-2)		/* configuration error */
185 
186  /*
187   * Result values for exposed functions except lookup. FAIL/ERROR are
188   * suggested values, not for use in comparisons for equality.
189   */
190 #define DICT_STAT_FAIL		1	/* any value > 0: notfound, conflict */
191 #define DICT_STAT_SUCCESS	0	/* request satisfied */
192 #define DICT_STAT_ERROR		(-1)	/* any value < 0: database error */
193 
194  /*
195   * Set an error code and return a result value.
196   */
197 #define DICT_ERR_VAL_RETURN(dict, err, val) do { \
198 	(dict)->error = (err); \
199 	return (val); \
200     } while (0)
201 
202  /*
203   * Sequence function types.
204   */
205 #define DICT_SEQ_FUN_FIRST     0	/* set cursor to first record */
206 #define DICT_SEQ_FUN_NEXT      1	/* set cursor to next record */
207 
208  /*
209   * Interface for dictionary types.
210   */
211 extern ARGV *dict_mapnames(void);
212 typedef void (*DICT_MAPNAMES_EXTEND_FN) (ARGV *);
213 extern DICT_MAPNAMES_EXTEND_FN dict_mapnames_extend(DICT_MAPNAMES_EXTEND_FN);
214 
215 
216  /*
217   * High-level interface, with logical dictionary names.
218   */
219 extern void dict_register(const char *, DICT *);
220 extern DICT *dict_handle(const char *);
221 extern void dict_unregister(const char *);
222 extern int dict_update(const char *, const char *, const char *);
223 extern const char *dict_lookup(const char *, const char *);
224 extern int dict_delete(const char *, const char *);
225 extern int dict_sequence(const char *, const int, const char **, const char **);
226 extern int dict_load_file_xt(const char *, const char *);
227 extern void dict_load_fp(const char *, VSTREAM *);
228 extern const char *dict_eval(const char *, const char *, int);
229 extern int dict_error(const char *);
230 
231  /*
232   * Low-level interface, with physical dictionary handles.
233   */
234 typedef DICT *(*DICT_OPEN_FN) (const char *, int, int);
235 typedef DICT_OPEN_FN (*DICT_OPEN_EXTEND_FN) (const char *);
236 extern DICT *dict_open(const char *, int, int);
237 extern DICT *dict_open3(const char *, const char *, int, int);
238 extern void dict_open_register(const char *, DICT_OPEN_FN);
239 extern DICT_OPEN_EXTEND_FN dict_open_extend(DICT_OPEN_EXTEND_FN);
240 
241 #define dict_get(dp, key)	((const char *) (dp)->lookup((dp), (key)))
242 #define dict_put(dp, key, val)	(dp)->update((dp), (key), (val))
243 #define dict_del(dp, key)	(dp)->delete((dp), (key))
244 #define dict_seq(dp, f, key, val) (dp)->sequence((dp), (f), (key), (val))
245 #define dict_close(dp)		(dp)->close(dp)
246 typedef void (*DICT_WALK_ACTION) (const char *, DICT *, void *);
247 extern void dict_walk(DICT_WALK_ACTION, void *);
248 extern int dict_changed(void);
249 extern const char *dict_changed_name(void);
250 extern const char *dict_flags_str(int);
251 extern int dict_flags_mask(const char *);
252 extern void dict_type_override(DICT *, const char *);
253 
254  /*
255   * Check and convert UTF-8 keys and values.
256   */
257 typedef struct DICT_UTF8_BACKUP {
258     const char *(*lookup) (struct DICT *, const char *);
259     int     (*update) (struct DICT *, const char *, const char *);
260     int     (*delete) (struct DICT *, const char *);
261 } DICT_UTF8_BACKUP;
262 
263 extern DICT *dict_utf8_activate(DICT *);
264 
265  /*
266   * Driver for interactive or scripted tests.
267   */
268 void    dict_test(int, char **);
269 
270  /*
271   * Behind-the-scenes support to continue execution with reduced
272   * functionality.
273   */
274 extern int dict_allow_surrogate;
275 extern DICT *PRINTFLIKE(5, 6) dict_surrogate(const char *, const char *, int, int, const char *,...);
276 
277  /*
278   * This name is reserved for matchlist error handling.
279   */
280 #define DICT_TYPE_NOFILE	"non-existent"
281 #define DICT_TYPE_NOUTF8	"non-UTF-8"
282 
283  /*
284   * Duplicated from vstream(3). This should probably be abstracted out.
285   *
286   * Exception handling. We use pointer to jmp_buf to avoid a lot of unused
287   * baggage for streams that don't need this functionality.
288   *
289   * XXX sigsetjmp()/siglongjmp() save and restore the signal mask which can
290   * avoid surprises in code that manipulates signals, but unfortunately some
291   * systems have bugs in their implementation.
292   */
293 #ifdef NO_SIGSETJMP
294 #define dict_setjmp(dict)	setjmp((dict)->jbuf[0])
295 #define dict_longjmp(dict, val)	longjmp((dict)->jbuf[0], (val))
296 #else
297 #define dict_setjmp(dict)	sigsetjmp((dict)->jbuf[0], 1)
298 #define dict_longjmp(dict, val)	siglongjmp((dict)->jbuf[0], (val))
299 #endif
300 #define dict_isjmp(dict)	((dict)->jbuf != 0)
301 
302  /*
303   * Temporary API. If exception handling proves to be useful,
304   * dict_jmp_alloc() should be integrated into dict_alloc().
305   */
306 extern void dict_jmp_alloc(DICT *);
307 
308  /*
309   * dict_file(3).
310   */
311 extern struct VSTRING *dict_file_to_buf(DICT *, const char *);
312 extern struct VSTRING *dict_file_to_b64(DICT *, const char *);
313 extern struct VSTRING *dict_file_from_b64(DICT *, const char *);
314 extern char *dict_file_get_error(DICT *);
315 extern void dict_file_purge_buffers(DICT *);
316 extern const char *dict_file_lookup(DICT *dict, const char *);
317 
318  /*
319   * dict_stream(3)
320   */
321 extern VSTREAM *dict_stream_open(const char *dict_type, const char *mapname,
322             int open_flags, int dict_flags, struct stat * st, VSTRING **why);
323 
324 /* LICENSE
325 /* .ad
326 /* .fi
327 /*	The Secure Mailer license must be distributed with this software.
328 /* AUTHOR(S)
329 /*	Wietse Venema
330 /*	IBM T.J. Watson Research
331 /*	P.O. Box 704
332 /*	Yorktown Heights, NY 10598, USA
333 /*
334 /*	Wietse Venema
335 /*	Google, Inc.
336 /*	111 8th Avenue
337 /*	New York, NY 10011, USA
338 /*--*/
339 
340 #endif
341