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