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