1 /* $NetBSD: milter_macros.c,v 1.3 2022/10/08 16:12:46 christos Exp $ */ 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_COMMON_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_COMMON_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 /* SEND_ATTR_FUNC(milter_macros_print, (const 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 /* RECV_ATTR_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 100 /* IBM T.J. Watson Research 101 /* P.O. Box 704 102 /* Yorktown Heights, NY 10598, USA 103 /* 104 /* Wietse Venema 105 /* Google, Inc. 106 /* 111 8th Avenue 107 /* New York, NY 10011, USA 108 /*--*/ 109 110 /* System library. */ 111 112 #include <sys_defs.h> 113 114 /* Utility library. */ 115 116 #include <msg.h> 117 #include <attr.h> 118 #include <mymalloc.h> 119 #include <vstring.h> 120 121 /* Global library. */ 122 123 #include <mail_proto.h> 124 #include <milter.h> 125 126 /* 127 * Ad-hoc protocol to send/receive milter macro name lists. 128 */ 129 #define MAIL_ATTR_MILT_MAC_CONN "conn_macros" 130 #define MAIL_ATTR_MILT_MAC_HELO "helo_macros" 131 #define MAIL_ATTR_MILT_MAC_MAIL "mail_macros" 132 #define MAIL_ATTR_MILT_MAC_RCPT "rcpt_macros" 133 #define MAIL_ATTR_MILT_MAC_DATA "data_macros" 134 #define MAIL_ATTR_MILT_MAC_EOH "eoh_macros" 135 #define MAIL_ATTR_MILT_MAC_EOD "eod_macros" 136 #define MAIL_ATTR_MILT_MAC_UNK "unk_macros" 137 138 /* milter_macros_print - write macros structure to stream */ 139 140 int milter_macros_print(ATTR_PRINT_COMMON_FN print_fn, VSTREAM *fp, 141 int flags, const void *ptr) 142 { 143 MILTER_MACROS *mp = (MILTER_MACROS *) ptr; 144 int ret; 145 146 /* 147 * The attribute order does not matter, except that it must be the same 148 * as in the milter_macros_scan() function. 149 */ 150 ret = print_fn(fp, flags | ATTR_FLAG_MORE, 151 SEND_ATTR_STR(MAIL_ATTR_MILT_MAC_CONN, mp->conn_macros), 152 SEND_ATTR_STR(MAIL_ATTR_MILT_MAC_HELO, mp->helo_macros), 153 SEND_ATTR_STR(MAIL_ATTR_MILT_MAC_MAIL, mp->mail_macros), 154 SEND_ATTR_STR(MAIL_ATTR_MILT_MAC_RCPT, mp->rcpt_macros), 155 SEND_ATTR_STR(MAIL_ATTR_MILT_MAC_DATA, mp->data_macros), 156 SEND_ATTR_STR(MAIL_ATTR_MILT_MAC_EOH, mp->eoh_macros), 157 SEND_ATTR_STR(MAIL_ATTR_MILT_MAC_EOD, mp->eod_macros), 158 SEND_ATTR_STR(MAIL_ATTR_MILT_MAC_UNK, mp->unk_macros), 159 ATTR_TYPE_END); 160 return (ret); 161 } 162 163 /* milter_macros_scan - receive macros structure from stream */ 164 165 int milter_macros_scan(ATTR_SCAN_COMMON_FN scan_fn, VSTREAM *fp, 166 int flags, void *ptr) 167 { 168 MILTER_MACROS *mp = (MILTER_MACROS *) ptr; 169 int ret; 170 171 /* 172 * We could simplify this by moving memory allocation into attr_scan*(). 173 */ 174 VSTRING *conn_macros = vstring_alloc(10); 175 VSTRING *helo_macros = vstring_alloc(10); 176 VSTRING *mail_macros = vstring_alloc(10); 177 VSTRING *rcpt_macros = vstring_alloc(10); 178 VSTRING *data_macros = vstring_alloc(10); 179 VSTRING *eoh_macros = vstring_alloc(10); 180 VSTRING *eod_macros = vstring_alloc(10); 181 VSTRING *unk_macros = vstring_alloc(10); 182 183 /* 184 * The attribute order does not matter, except that it must be the same 185 * as in the milter_macros_print() function. 186 */ 187 ret = scan_fn(fp, flags | ATTR_FLAG_MORE, 188 RECV_ATTR_STR(MAIL_ATTR_MILT_MAC_CONN, conn_macros), 189 RECV_ATTR_STR(MAIL_ATTR_MILT_MAC_HELO, helo_macros), 190 RECV_ATTR_STR(MAIL_ATTR_MILT_MAC_MAIL, mail_macros), 191 RECV_ATTR_STR(MAIL_ATTR_MILT_MAC_RCPT, rcpt_macros), 192 RECV_ATTR_STR(MAIL_ATTR_MILT_MAC_DATA, data_macros), 193 RECV_ATTR_STR(MAIL_ATTR_MILT_MAC_EOH, eoh_macros), 194 RECV_ATTR_STR(MAIL_ATTR_MILT_MAC_EOD, eod_macros), 195 RECV_ATTR_STR(MAIL_ATTR_MILT_MAC_UNK, unk_macros), 196 ATTR_TYPE_END); 197 198 /* 199 * Don't optimize for error. 200 */ 201 mp->conn_macros = vstring_export(conn_macros); 202 mp->helo_macros = vstring_export(helo_macros); 203 mp->mail_macros = vstring_export(mail_macros); 204 mp->rcpt_macros = vstring_export(rcpt_macros); 205 mp->data_macros = vstring_export(data_macros); 206 mp->eoh_macros = vstring_export(eoh_macros); 207 mp->eod_macros = vstring_export(eod_macros); 208 mp->unk_macros = vstring_export(unk_macros); 209 210 return (ret == 8 ? 1 : -1); 211 } 212 213 /* milter_macros_create - create and initialize macros structure */ 214 215 MILTER_MACROS *milter_macros_create(const char *conn_macros, 216 const char *helo_macros, 217 const char *mail_macros, 218 const char *rcpt_macros, 219 const char *data_macros, 220 const char *eoh_macros, 221 const char *eod_macros, 222 const char *unk_macros) 223 { 224 MILTER_MACROS *mp; 225 226 mp = (MILTER_MACROS *) mymalloc(sizeof(*mp)); 227 mp->conn_macros = mystrdup(conn_macros); 228 mp->helo_macros = mystrdup(helo_macros); 229 mp->mail_macros = mystrdup(mail_macros); 230 mp->rcpt_macros = mystrdup(rcpt_macros); 231 mp->data_macros = mystrdup(data_macros); 232 mp->eoh_macros = mystrdup(eoh_macros); 233 mp->eod_macros = mystrdup(eod_macros); 234 mp->unk_macros = mystrdup(unk_macros); 235 236 return (mp); 237 } 238 239 /* milter_macros_alloc - allocate macros structure with simple initialization */ 240 241 MILTER_MACROS *milter_macros_alloc(int mode) 242 { 243 MILTER_MACROS *mp; 244 245 /* 246 * This macro was originally in milter.h, but no-one else needed it. 247 */ 248 #define milter_macros_init(mp, expr) do { \ 249 MILTER_MACROS *__mp = (mp); \ 250 char *__expr = (expr); \ 251 __mp->conn_macros = __expr; \ 252 __mp->helo_macros = __expr; \ 253 __mp->mail_macros = __expr; \ 254 __mp->rcpt_macros = __expr; \ 255 __mp->data_macros = __expr; \ 256 __mp->eoh_macros = __expr; \ 257 __mp->eod_macros = __expr; \ 258 __mp->unk_macros = __expr; \ 259 } while (0) 260 261 mp = (MILTER_MACROS *) mymalloc(sizeof(*mp)); 262 switch (mode) { 263 case MILTER_MACROS_ALLOC_ZERO: 264 milter_macros_init(mp, 0); 265 break; 266 case MILTER_MACROS_ALLOC_EMPTY: 267 milter_macros_init(mp, mystrdup("")); 268 break; 269 default: 270 msg_panic("milter_macros_alloc: unknown mode %d", mode); 271 } 272 return (mp); 273 } 274 275 /* milter_macros_free - destroy memory for MILTER_MACROS structure */ 276 277 void milter_macros_free(MILTER_MACROS *mp) 278 { 279 280 /* 281 * This macro was originally in milter.h, but no-one else needed it. 282 */ 283 #define milter_macros_wipe(mp) do { \ 284 MILTER_MACROS *__mp = mp; \ 285 if (__mp->conn_macros) \ 286 myfree(__mp->conn_macros); \ 287 if (__mp->helo_macros) \ 288 myfree(__mp->helo_macros); \ 289 if (__mp->mail_macros) \ 290 myfree(__mp->mail_macros); \ 291 if (__mp->rcpt_macros) \ 292 myfree(__mp->rcpt_macros); \ 293 if (__mp->data_macros) \ 294 myfree(__mp->data_macros); \ 295 if (__mp->eoh_macros) \ 296 myfree(__mp->eoh_macros); \ 297 if (__mp->eod_macros) \ 298 myfree(__mp->eod_macros); \ 299 if (__mp->unk_macros) \ 300 myfree(__mp->unk_macros); \ 301 } while (0) 302 303 milter_macros_wipe(mp); 304 myfree((void *) mp); 305 } 306