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 <fcntl.h>
18#include <setjmp.h>
19
20#ifdef NO_SIGSETJMP
21#define DICT_JMP_BUF jmp_buf
22#else
23#define DICT_JMP_BUF sigjmp_buf
24#endif
25
26 /*
27  * Utility library.
28  */
29#include <vstream.h>
30#include <argv.h>
31#include <vstring.h>
32#include <myflock.h>
33
34 /*
35  * Provenance information.
36  */
37typedef struct DICT_OWNER {
38    int     status;			/* see below */
39    uid_t   uid;			/* use only if status == UNTRUSTED */
40} DICT_OWNER;
41
42#define DICT_OWNER_UNKNOWN	(-1)	/* ex: unauthenticated tcp, proxy */
43#define DICT_OWNER_TRUSTED	(!1)	/* ex: root-owned config file */
44#define DICT_OWNER_UNTRUSTED	(!0)	/* ex: non-root config file */
45
46 /*
47  * Generic dictionary interface - in reality, a dictionary extends this
48  * structure with private members to maintain internal state.
49  */
50typedef struct DICT {
51    char   *type;			/* for diagnostics */
52    char   *name;			/* for diagnostics */
53    int     flags;			/* see below */
54    const char *(*lookup) (struct DICT *, const char *);
55    int     (*update) (struct DICT *, const char *, const char *);
56    int     (*delete) (struct DICT *, const char *);
57    int     (*sequence) (struct DICT *, int, const char **, const char **);
58    int     (*lock) (struct DICT *, int);
59    void    (*close) (struct DICT *);
60    int     lock_type;			/* for read/write lock */
61    int     lock_fd;			/* for read/write lock */
62    int     stat_fd;			/* change detection */
63    time_t  mtime;			/* mod time at open */
64    VSTRING *fold_buf;			/* key folding buffer */
65    DICT_OWNER owner;			/* provenance */
66    int     error;			/* last operation only */
67    DICT_JMP_BUF *jbuf;			/* exception handling */
68} DICT;
69
70extern DICT *dict_alloc(const char *, const char *, ssize_t);
71extern void dict_free(DICT *);
72
73extern DICT *dict_debug(DICT *);
74
75#define DICT_DEBUG(d) ((d)->flags & DICT_FLAG_DEBUG ? dict_debug(d) : (d))
76
77 /*
78  * See dict_open.c embedded manpage for flag definitions.
79  */
80#define DICT_FLAG_NONE		(0)
81#define DICT_FLAG_DUP_WARN	(1<<0)	/* warn about dups if not supported */
82#define DICT_FLAG_DUP_IGNORE	(1<<1)	/* ignore dups if not supported */
83#define DICT_FLAG_TRY0NULL	(1<<2)	/* do not append 0 to key/value */
84#define DICT_FLAG_TRY1NULL	(1<<3)	/* append 0 to key/value */
85#define DICT_FLAG_FIXED		(1<<4)	/* fixed key map */
86#define DICT_FLAG_PATTERN	(1<<5)	/* keys are patterns */
87#define DICT_FLAG_LOCK		(1<<6)	/* use temp lock before access */
88#define DICT_FLAG_DUP_REPLACE	(1<<7)	/* replace dups if supported */
89#define DICT_FLAG_SYNC_UPDATE	(1<<8)	/* sync updates if supported */
90#define DICT_FLAG_DEBUG		(1<<9)	/* log access */
91/*#define DICT_FLAG_FOLD_KEY	(1<<10)	/* lowercase the lookup key */
92#define DICT_FLAG_NO_REGSUB	(1<<11)	/* disallow regexp substitution */
93#define DICT_FLAG_NO_PROXY	(1<<12)	/* disallow proxy mapping */
94#define DICT_FLAG_NO_UNAUTH	(1<<13)	/* disallow unauthenticated data */
95#define DICT_FLAG_FOLD_FIX	(1<<14)	/* case-fold key with fixed-case map */
96#define DICT_FLAG_FOLD_MUL	(1<<15)	/* case-fold key with multi-case map */
97#define DICT_FLAG_FOLD_ANY	(DICT_FLAG_FOLD_FIX | DICT_FLAG_FOLD_MUL)
98#define DICT_FLAG_OPEN_LOCK	(1<<16)	/* perm lock if not multi-writer safe */
99#define DICT_FLAG_BULK_UPDATE	(1<<17)	/* optimize for bulk updates */
100#define DICT_FLAG_MULTI_WRITER	(1<<18)	/* multi-writer safe map */
101
102 /* IMPORTANT: Update the dict_mask[] table when the above changes */
103
104 /*
105  * The subsets of flags that control how a map is used. These are relevant
106  * mainly for proxymap support. Note: some categories overlap.
107  *
108  * DICT_FLAG_IMPL_MASK - flags that are set by the map implementation itself.
109  *
110  * DICT_FLAG_PARANOID - requestor flags that forbid the use of insecure map
111  * types for security-sensitive operations. These flags are checked by the
112  * map implementation itself upon open, lookup etc. requests.
113  *
114  * DICT_FLAG_RQST_MASK - all requestor flags, including paranoid flags, that
115  * the requestor may change between open, lookup etc. requests. These
116  * specify requestor properties, not map properties.
117  *
118  * DICT_FLAG_INST_MASK - none of the above flags. The requestor may not change
119  * these flags between open, lookup, etc. requests (although a map may make
120  * changes to its copy of some of these flags). The proxymap server opens
121  * only one map instance for all client requests with the same values of
122  * these flags, and the proxymap client uses its own saved copy of these
123  * flags.
124  */
125#define DICT_FLAG_PARANOID \
126	(DICT_FLAG_NO_REGSUB | DICT_FLAG_NO_PROXY | DICT_FLAG_NO_UNAUTH)
127#define DICT_FLAG_IMPL_MASK	(DICT_FLAG_FIXED | DICT_FLAG_PATTERN | \
128				DICT_FLAG_MULTI_WRITER)
129#define DICT_FLAG_RQST_MASK	(DICT_FLAG_FOLD_ANY | DICT_FLAG_LOCK | \
130				DICT_FLAG_DUP_REPLACE | DICT_FLAG_DUP_WARN | \
131				DICT_FLAG_DUP_IGNORE | DICT_FLAG_SYNC_UPDATE | \
132				DICT_FLAG_PARANOID)
133#define DICT_FLAG_INST_MASK	~(DICT_FLAG_IMPL_MASK | DICT_FLAG_RQST_MASK)
134
135 /*
136  * dict->error values. Errors must be negative; smtpd_check depends on this.
137  */
138#define DICT_ERR_NONE	0		/* no error */
139#define DICT_ERR_RETRY	(-1)		/* soft error */
140#define DICT_ERR_CONFIG	(-2)		/* configuration error */
141
142 /*
143  * Result values for exposed functions except lookup. FAIL/ERROR are
144  * suggested values, not for use in comparisons for equality.
145  */
146#define DICT_STAT_FAIL		1	/* any value > 0: notfound, conflict */
147#define DICT_STAT_SUCCESS	0	/* request satisfied */
148#define DICT_STAT_ERROR		(-1)	/* any value < 0: database error */
149
150 /*
151  * Set an error code and return a result value.
152  */
153#define DICT_ERR_VAL_RETURN(dict, err, val) do { \
154	(dict)->error = (err); \
155	return (val); \
156    } while (0)
157
158 /*
159  * Sequence function types.
160  */
161#define DICT_SEQ_FUN_FIRST     0	/* set cursor to first record */
162#define DICT_SEQ_FUN_NEXT      1	/* set cursor to next record */
163
164 /*
165  * Interface for dictionary types.
166  */
167extern ARGV *dict_mapnames(void);
168
169 /*
170  * High-level interface, with logical dictionary names.
171  */
172extern void dict_register(const char *, DICT *);
173extern DICT *dict_handle(const char *);
174extern void dict_unregister(const char *);
175extern int dict_update(const char *, const char *, const char *);
176extern const char *dict_lookup(const char *, const char *);
177extern int dict_delete(const char *, const char *);
178extern int dict_sequence(const char *, const int, const char **, const char **);
179extern int dict_load_file_xt(const char *, const char *);
180extern void dict_load_fp(const char *, VSTREAM *);
181extern const char *dict_eval(const char *, const char *, int);
182extern int dict_error(const char *);
183
184 /*
185  * Low-level interface, with physical dictionary handles.
186  */
187extern DICT *dict_open(const char *, int, int);
188extern DICT *dict_open3(const char *, const char *, int, int);
189extern void dict_open_register(const char *, DICT *(*) (const char *, int, int));
190
191#define dict_get(dp, key)	((const char *) (dp)->lookup((dp), (key)))
192#define dict_put(dp, key, val)	(dp)->update((dp), (key), (val))
193#define dict_del(dp, key)	(dp)->delete((dp), (key))
194#define dict_seq(dp, f, key, val) (dp)->sequence((dp), (f), (key), (val))
195#define dict_close(dp)		(dp)->close(dp)
196typedef void (*DICT_WALK_ACTION) (const char *, DICT *, char *);
197extern void dict_walk(DICT_WALK_ACTION, char *);
198extern int dict_changed(void);
199extern const char *dict_changed_name(void);
200extern const char *dict_flags_str(int);
201extern int dict_flags_mask(const char *);
202
203 /*
204  * Driver for interactive or scripted tests.
205  */
206void    dict_test(int, char **);
207
208 /*
209  * Behind-the-scenes support to continue execution with reduced
210  * functionality.
211  */
212extern int dict_allow_surrogate;
213extern DICT *dict_surrogate(const char *, const char *, int, int, const char *,...);
214
215 /*
216  * This name is reserved for matchlist error handling.
217  */
218#define DICT_TYPE_NOFILE	"non-existent"
219
220 /*
221  * Duplicated from vstream(3). This should probably be abstracted out.
222  *
223  * Exception handling. We use pointer to jmp_buf to avoid a lot of unused
224  * baggage for streams that don't need this functionality.
225  *
226  * XXX sigsetjmp()/siglongjmp() save and restore the signal mask which can
227  * avoid surprises in code that manipulates signals, but unfortunately some
228  * systems have bugs in their implementation.
229  */
230#ifdef NO_SIGSETJMP
231#define dict_setjmp(stream)		setjmp((stream)->jbuf[0])
232#define dict_longjmp(stream, val)	longjmp((stream)->jbuf[0], (val))
233#else
234#define dict_setjmp(stream)		sigsetjmp((stream)->jbuf[0], 1)
235#define dict_longjmp(stream, val)	siglongjmp((stream)->jbuf[0], (val))
236#endif
237#define dict_isjmp(stream)		((stream)->jbuf != 0)
238
239 /*
240  * Temporary API. If exception handling proves to be useful,
241  * dict_jmp_alloc() should be integrated into dict_alloc().
242  */
243extern void dict_jmp_alloc(DICT *);
244
245/* LICENSE
246/* .ad
247/* .fi
248/*	The Secure Mailer license must be distributed with this software.
249/* AUTHOR(S)
250/*	Wietse Venema
251/*	IBM T.J. Watson Research
252/*	P.O. Box 704
253/*	Yorktown Heights, NY 10598, USA
254/*--*/
255
256#endif
257