1/* $NetBSD$ */ 2 3/*++ 4/* NAME 5/* milter_macros 6/* SUMMARY 7/* manipulate MILTER_MACROS structures 8/* SYNOPSIS 9/* #include <milter.h> 10/* 11/* MILTER_MACROS *milter_macros_create(conn_macros, helo_macros, 12/* mail_macros, rcpt_macros, 13/* data_macros, eoh_macros, 14/* eod_macros, unk_macros) 15/* const char *conn_macros; 16/* const char *helo_macros; 17/* const char *mail_macros; 18/* const char *rcpt_macrps; 19/* const char *data_macros; 20/* const char *eoh_macros; 21/* const char *eod_macros; 22/* const char *unk_macros; 23/* 24/* MILTER_MACROS *milter_macros_alloc(init_mode) 25/* int init_mode; 26/* 27/* void milter_macros_free(mp) 28/* MILTER_MACROS *mp; 29/* 30/* int milter_macros_print(print_fn, stream, flags, ptr) 31/* ATTR_PRINT_MASTER_FN print_fn; 32/* VSTREAM *stream; 33/* int flags; 34/* void *ptr; 35/* 36/* int milter_macros_scan(scan_fn, fp, flags, ptr) 37/* ATTR_SCAN_MASTER_FN scan_fn; 38/* VSTREAM *fp; 39/* int flags; 40/* void *ptr; 41/* DESCRIPTION 42/* Sendmail mail filter (Milter) applications receive sets of 43/* macro name=value pairs with each SMTP or content event. 44/* In Postfix, these macro names are stored in MILTER_MACROS 45/* structures, as one list for each event type. By default, 46/* the same structure is shared by all Milter applications; 47/* it is initialized with information from main.cf. With 48/* Sendmail 8.14 a Milter can override one or more lists of 49/* macro names. Postfix implements this by giving the Milter 50/* its own MILTER_MACROS structure and by storing the per-Milter 51/* information there. 52/* 53/* This module maintains per-event macro name lists as 54/* mystrdup()'ed values. The user is explicitly allowed to 55/* update these values directly, as long as the result is 56/* compatible with mystrdup(). 57/* 58/* milter_macros_create() creates a MILTER_MACROS structure 59/* and initializes it with copies of its string arguments. 60/* Null pointers are not valid as input. 61/* 62/* milter_macros_alloc() creates am empty MILTER_MACROS structure 63/* that is initialized according to its init_mode argument. 64/* .IP MILTER_MACROS_ALLOC_ZERO 65/* Initialize all structure members as null pointers. This 66/* mode must be used with milter_macros_scan(), because that 67/* function blindly overwrites all structure members. No other 68/* function except milter_macros_free() allows structure members 69/* with null pointer values. 70/* .IP MILTER_MACROS_ALLOC_EMPTY 71/* Initialize all structure members with mystrdup(""). This 72/* is not as expensive as it appears to be. 73/* .PP 74/* milter_macros_free() destroys a MILTER_MACROS structure and 75/* frees any strings referenced by it. 76/* 77/* milter_macros_print() writes the contents of a MILTER_MACROS 78/* structure to the named stream using the specified attribute 79/* print routine. milter_macros_print() is meant to be passed 80/* as a call-back to attr_print*(), thusly: 81/* 82/* ATTR_TYPE_FUNC, milter_macros_print, (void *) macros, 83/* 84/* milter_macros_scan() reads a MILTER_MACROS structure from 85/* the named stream using the specified attribute scan routine. 86/* No attempt is made to free the memory of existing structure 87/* members. milter_macros_scan() is meant to be passed as a 88/* call-back to attr_scan*(), thusly: 89/* 90/* ATTR_TYPE_FUNC, milter_macros_scan, (void *) macros, 91/* DIAGNOSTICS 92/* Fatal: out of memory. 93/* LICENSE 94/* .ad 95/* .fi 96/* The Secure Mailer license must be distributed with this 97/* software. 98/* AUTHOR(S) 99/* Wietse Venema IBM T.J. Watson Research P.O. Box 704 Yorktown 100/* Heights, NY 10598, USA 101/*--*/ 102 103/* System library. */ 104 105#include <sys_defs.h> 106 107/* Utility library. */ 108 109#include <msg.h> 110#include <attr.h> 111#include <mymalloc.h> 112#include <vstring.h> 113 114/* Global library. */ 115 116#include <mail_proto.h> 117#include <milter.h> 118 119 /* 120 * Ad-hoc protocol to send/receive milter macro name lists. 121 */ 122#define MAIL_ATTR_MILT_MAC_CONN "conn_macros" 123#define MAIL_ATTR_MILT_MAC_HELO "helo_macros" 124#define MAIL_ATTR_MILT_MAC_MAIL "mail_macros" 125#define MAIL_ATTR_MILT_MAC_RCPT "rcpt_macros" 126#define MAIL_ATTR_MILT_MAC_DATA "data_macros" 127#define MAIL_ATTR_MILT_MAC_EOH "eoh_macros" 128#define MAIL_ATTR_MILT_MAC_EOD "eod_macros" 129#define MAIL_ATTR_MILT_MAC_UNK "unk_macros" 130 131/* milter_macros_print - write macros structure to stream */ 132 133int milter_macros_print(ATTR_PRINT_MASTER_FN print_fn, VSTREAM *fp, 134 int flags, void *ptr) 135{ 136 MILTER_MACROS *mp = (MILTER_MACROS *) ptr; 137 int ret; 138 139 /* 140 * The attribute order does not matter, except that it must be the same 141 * as in the milter_macros_scan() function. 142 */ 143 ret = print_fn(fp, flags | ATTR_FLAG_MORE, 144 ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_CONN, mp->conn_macros, 145 ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_HELO, mp->helo_macros, 146 ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_MAIL, mp->mail_macros, 147 ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_RCPT, mp->rcpt_macros, 148 ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_DATA, mp->data_macros, 149 ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_EOH, mp->eoh_macros, 150 ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_EOD, mp->eod_macros, 151 ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_UNK, mp->unk_macros, 152 ATTR_TYPE_END); 153 return (ret); 154} 155 156/* milter_macros_scan - receive macros structure from stream */ 157 158int milter_macros_scan(ATTR_SCAN_MASTER_FN scan_fn, VSTREAM *fp, 159 int flags, void *ptr) 160{ 161 MILTER_MACROS *mp = (MILTER_MACROS *) ptr; 162 int ret; 163 164 /* 165 * We could simplify this by moving memory allocation into attr_scan*(). 166 */ 167 VSTRING *conn_macros = vstring_alloc(10); 168 VSTRING *helo_macros = vstring_alloc(10); 169 VSTRING *mail_macros = vstring_alloc(10); 170 VSTRING *rcpt_macros = vstring_alloc(10); 171 VSTRING *data_macros = vstring_alloc(10); 172 VSTRING *eoh_macros = vstring_alloc(10); 173 VSTRING *eod_macros = vstring_alloc(10); 174 VSTRING *unk_macros = vstring_alloc(10); 175 176 /* 177 * The attribute order does not matter, except that it must be the same 178 * as in the milter_macros_print() function. 179 */ 180 ret = scan_fn(fp, flags | ATTR_FLAG_MORE, 181 ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_CONN, conn_macros, 182 ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_HELO, helo_macros, 183 ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_MAIL, mail_macros, 184 ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_RCPT, rcpt_macros, 185 ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_DATA, data_macros, 186 ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_EOH, eoh_macros, 187 ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_EOD, eod_macros, 188 ATTR_TYPE_STR, MAIL_ATTR_MILT_MAC_UNK, unk_macros, 189 ATTR_TYPE_END); 190 191 /* 192 * Don't optimize for error. 193 */ 194 mp->conn_macros = vstring_export(conn_macros); 195 mp->helo_macros = vstring_export(helo_macros); 196 mp->mail_macros = vstring_export(mail_macros); 197 mp->rcpt_macros = vstring_export(rcpt_macros); 198 mp->data_macros = vstring_export(data_macros); 199 mp->eoh_macros = vstring_export(eoh_macros); 200 mp->eod_macros = vstring_export(eod_macros); 201 mp->unk_macros = vstring_export(unk_macros); 202 203 return (ret == 8 ? 1 : -1); 204} 205 206/* milter_macros_create - create and initialize macros structure */ 207 208MILTER_MACROS *milter_macros_create(const char *conn_macros, 209 const char *helo_macros, 210 const char *mail_macros, 211 const char *rcpt_macros, 212 const char *data_macros, 213 const char *eoh_macros, 214 const char *eod_macros, 215 const char *unk_macros) 216{ 217 MILTER_MACROS *mp; 218 219 mp = (MILTER_MACROS *) mymalloc(sizeof(*mp)); 220 mp->conn_macros = mystrdup(conn_macros); 221 mp->helo_macros = mystrdup(helo_macros); 222 mp->mail_macros = mystrdup(mail_macros); 223 mp->rcpt_macros = mystrdup(rcpt_macros); 224 mp->data_macros = mystrdup(data_macros); 225 mp->eoh_macros = mystrdup(eoh_macros); 226 mp->eod_macros = mystrdup(eod_macros); 227 mp->unk_macros = mystrdup(unk_macros); 228 229 return (mp); 230} 231 232/* milter_macros_alloc - allocate macros structure with simple initialization */ 233 234MILTER_MACROS *milter_macros_alloc(int mode) 235{ 236 MILTER_MACROS *mp; 237 238 /* 239 * This macro was originally in milter.h, but no-one else needed it. 240 */ 241#define milter_macros_init(mp, expr) do { \ 242 MILTER_MACROS *__mp = (mp); \ 243 char *__expr = (expr); \ 244 __mp->conn_macros = __expr; \ 245 __mp->helo_macros = __expr; \ 246 __mp->mail_macros = __expr; \ 247 __mp->rcpt_macros = __expr; \ 248 __mp->data_macros = __expr; \ 249 __mp->eoh_macros = __expr; \ 250 __mp->eod_macros = __expr; \ 251 __mp->unk_macros = __expr; \ 252 } while (0) 253 254 mp = (MILTER_MACROS *) mymalloc(sizeof(*mp)); 255 switch (mode) { 256 case MILTER_MACROS_ALLOC_ZERO: 257 milter_macros_init(mp, 0); 258 break; 259 case MILTER_MACROS_ALLOC_EMPTY: 260 milter_macros_init(mp, mystrdup("")); 261 break; 262 default: 263 msg_panic("milter_macros_alloc: unknown mode %d", mode); 264 } 265 return (mp); 266} 267 268/* milter_macros_free - destroy memory for MILTER_MACROS structure */ 269 270void milter_macros_free(MILTER_MACROS *mp) 271{ 272 273 /* 274 * This macro was originally in milter.h, but no-one else needed it. 275 */ 276#define milter_macros_wipe(mp) do { \ 277 MILTER_MACROS *__mp = mp; \ 278 if (__mp->conn_macros) \ 279 myfree(__mp->conn_macros); \ 280 if (__mp->helo_macros) \ 281 myfree(__mp->helo_macros); \ 282 if (__mp->mail_macros) \ 283 myfree(__mp->mail_macros); \ 284 if (__mp->rcpt_macros) \ 285 myfree(__mp->rcpt_macros); \ 286 if (__mp->data_macros) \ 287 myfree(__mp->data_macros); \ 288 if (__mp->eoh_macros) \ 289 myfree(__mp->eoh_macros); \ 290 if (__mp->eod_macros) \ 291 myfree(__mp->eod_macros); \ 292 if (__mp->unk_macros) \ 293 myfree(__mp->unk_macros); \ 294 } while (0) 295 296 milter_macros_wipe(mp); 297 myfree((char *) mp); 298} 299