1 /* $NetBSD: dict.h,v 1.7 2026/05/09 18:49:22 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 char *reg_name; /* managed by dict_register() */ 103 void (*saved_close) (struct DICT *); /* managed by dict_register() */ 104 } DICT; 105 106 extern DICT *dict_alloc(const char *, const char *, ssize_t); 107 extern void dict_free(DICT *); 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 #define DICT_FLAG_SURROGATE (1<22) /* This is a surrogate dictionary */ 138 139 #define DICT_FLAG_UTF8_MASK (DICT_FLAG_UTF8_REQUEST) 140 141 /* IMPORTANT: Update the dict_mask[] table when the above changes */ 142 143 /* 144 * The subsets of flags that control how a map is used. These are relevant 145 * mainly for proxymap support. Note: some categories overlap. 146 * 147 * DICT_FLAG_PARANOID - requestor flags that forbid the use of insecure map 148 * types for security-sensitive operations. These flags are checked by the 149 * map implementation itself upon open, lookup etc. requests. 150 */ 151 #define DICT_FLAG_PARANOID \ 152 (DICT_FLAG_NO_REGSUB | DICT_FLAG_NO_PROXY | DICT_FLAG_NO_UNAUTH) 153 154 /* 155 * Feature tests. 156 */ 157 #define DICT_NEED_UTF8_ACTIVATION(enable, flags) \ 158 ((enable) && ((flags) & DICT_FLAG_UTF8_MASK)) 159 160 /* 161 * dict->error values. Errors must be negative; smtpd_check depends on this. 162 */ 163 #define DICT_ERR_NONE 0 /* no error */ 164 #define DICT_ERR_RETRY (-1) /* soft error */ 165 #define DICT_ERR_CONFIG (-2) /* configuration error */ 166 167 /* 168 * Result values for exposed functions except lookup. FAIL/ERROR are 169 * suggested values, not for use in comparisons for equality. 170 */ 171 #define DICT_STAT_FAIL 1 /* any value > 0: notfound, conflict */ 172 #define DICT_STAT_SUCCESS 0 /* request satisfied */ 173 #define DICT_STAT_ERROR (-1) /* any value < 0: database error */ 174 175 /* 176 * Set an error code and return a result value. 177 */ 178 #define DICT_ERR_VAL_RETURN(dict, err, val) do { \ 179 (dict)->error = (err); \ 180 return (val); \ 181 } while (0) 182 183 /* 184 * Sequence function types. 185 */ 186 #define DICT_SEQ_FUN_FIRST 0 /* set cursor to first record */ 187 #define DICT_SEQ_FUN_NEXT 1 /* set cursor to next record */ 188 189 /* 190 * Interface for dictionary types. 191 */ 192 extern ARGV *dict_mapnames(void); 193 typedef void (*DICT_MAPNAMES_EXTEND_FN) (ARGV *); 194 extern DICT_MAPNAMES_EXTEND_FN dict_mapnames_extend(DICT_MAPNAMES_EXTEND_FN); 195 196 197 /* 198 * High-level interface, with logical dictionary names. 199 */ 200 extern void dict_register(const char *, DICT *); 201 extern DICT *dict_handle(const char *); 202 extern void dict_unregister(const char *); 203 extern int dict_update(const char *, const char *, const char *); 204 extern const char *dict_lookup(const char *, const char *); 205 extern int dict_delete(const char *, const char *); 206 extern int dict_sequence(const char *, const int, const char **, const char **); 207 extern int dict_load_file_xt(const char *, const char *); 208 extern void dict_load_fp(const char *, VSTREAM *); 209 extern const char *dict_eval(const char *, const char *, int); 210 extern int dict_error(const char *); 211 212 /* 213 * Low-level interface, with physical dictionary handles. 214 */ 215 typedef DICT *(*DICT_OPEN_FN) (const char *, int, int); 216 typedef struct { 217 const char *type; 218 DICT_OPEN_FN dict_fn; 219 struct MKMAP *(*mkmap_fn) (const char *); 220 } DICT_OPEN_INFO; 221 typedef const DICT_OPEN_INFO *(*DICT_OPEN_EXTEND_FN) (const char *); 222 extern DICT *dict_open(const char *, int, int); 223 extern DICT *dict_open3(const char *, const char *, int, int); 224 extern void dict_open_register(const DICT_OPEN_INFO *); 225 extern void dict_open_unregister(const char *); 226 extern const DICT_OPEN_INFO *dict_open_lookup(const char *); 227 extern DICT_OPEN_EXTEND_FN dict_open_extend(DICT_OPEN_EXTEND_FN); 228 229 #define dict_get(dp, key) ((const char *) (dp)->lookup((dp), (key))) 230 #define dict_put(dp, key, val) (dp)->update((dp), (key), (val)) 231 #define dict_del(dp, key) (dp)->delete((dp), (key)) 232 #define dict_seq(dp, f, key, val) (dp)->sequence((dp), (f), (key), (val)) 233 #define dict_close(dp) (dp)->close(dp) 234 typedef void (*DICT_WALK_ACTION) (const char *, DICT *, void *); 235 extern void dict_walk(DICT_WALK_ACTION, void *); 236 extern int dict_changed(void); 237 extern const char *dict_changed_name(void); 238 extern const char *dict_flags_str(int); 239 extern int dict_flags_mask(const char *); 240 extern void dict_type_override(DICT *, const char *); 241 242 /* 243 * Check and convert UTF-8 keys and values. 244 */ 245 typedef struct DICT_UTF8_BACKUP { 246 const char *(*lookup) (struct DICT *, const char *); 247 int (*update) (struct DICT *, const char *, const char *); 248 int (*delete) (struct DICT *, const char *); 249 } DICT_UTF8_BACKUP; 250 251 extern DICT *dict_utf8_activate(DICT *); 252 253 /* 254 * Driver for interactive or scripted tests. 255 */ 256 void dict_test(int, char **); 257 258 /* 259 * Behind-the-scenes support to continue execution with reduced 260 * functionality. 261 */ 262 extern int dict_allow_surrogate; 263 extern DICT *PRINTFLIKE(5, 6) dict_surrogate(const char *, const char *, int, int, const char *,...); 264 265 /* 266 * Support for consistent sharing and collision avoidance when tables are 267 * registered with dict_register(). Only share instances that have the same 268 * type, name, open_flags, and (initial) dict_flags. 269 */ 270 extern char *dict_make_registered_name(VSTRING *, const char *, int, int); 271 extern char *dict_make_registered_name4(VSTRING *, const char *, const char *, int, int); 272 273 /* 274 * This name is reserved for matchlist error handling. 275 */ 276 #define DICT_TYPE_NOFILE "non-existent" 277 #define DICT_TYPE_NOUTF8 "non-UTF-8" 278 279 /* 280 * Duplicated from vstream(3). This should probably be abstracted out. 281 * 282 * Exception handling. We use pointer to jmp_buf to avoid a lot of unused 283 * baggage for streams that don't need this functionality. 284 * 285 * XXX sigsetjmp()/siglongjmp() save and restore the signal mask which can 286 * avoid surprises in code that manipulates signals, but unfortunately some 287 * systems have bugs in their implementation. 288 */ 289 #ifdef NO_SIGSETJMP 290 #define dict_setjmp(dict) setjmp((dict)->jbuf[0]) 291 #define dict_longjmp(dict, val) longjmp((dict)->jbuf[0], (val)) 292 #else 293 #define dict_setjmp(dict) sigsetjmp((dict)->jbuf[0], 1) 294 #define dict_longjmp(dict, val) siglongjmp((dict)->jbuf[0], (val)) 295 #endif 296 #define dict_isjmp(dict) ((dict)->jbuf != 0) 297 298 /* 299 * Temporary API. If exception handling proves to be useful, 300 * dict_jmp_alloc() should be integrated into dict_alloc(). 301 */ 302 extern void dict_jmp_alloc(DICT *); 303 304 /* 305 * dict_file(3). 306 */ 307 extern struct VSTRING *dict_file_to_buf(DICT *, const char *); 308 extern struct VSTRING *dict_file_to_b64(DICT *, const char *); 309 extern struct VSTRING *dict_file_from_b64(DICT *, const char *); 310 extern char *dict_file_get_error(DICT *); 311 extern void dict_file_purge_buffers(DICT *); 312 extern const char *dict_file_lookup(DICT *dict, const char *); 313 314 /* 315 * dict_stream(3) 316 */ 317 extern VSTREAM *dict_stream_open(const char *dict_type, const char *mapname, 318 int open_flags, int dict_flags, struct stat * st, VSTRING **why); 319 320 /* LICENSE 321 /* .ad 322 /* .fi 323 /* The Secure Mailer license must be distributed with this software. 324 /* AUTHOR(S) 325 /* Wietse Venema 326 /* IBM T.J. Watson Research 327 /* P.O. Box 704 328 /* Yorktown Heights, NY 10598, USA 329 /* 330 /* Wietse Venema 331 /* Google, Inc. 332 /* 111 8th Avenue 333 /* New York, NY 10011, USA 334 /*--*/ 335 336 #endif 337