/*++ /* NAME /* milter_macros /* SUMMARY /* manipulate MILTER_MACROS structures /* SYNOPSIS /* #include /* /* MILTER_MACROS *milter_macros_create(conn_macros, helo_macros, /* mail_macros, rcpt_macros, /* data_macros, eoh_macros, /* eod_macros, unk_macros) /* const char *conn_macros; /* const char *helo_macros; /* const char *mail_macros; /* const char *rcpt_macrps; /* const char *data_macros; /* const char *eoh_macros; /* const char *eod_macros; /* const char *unk_macros; /* /* MILTER_MACROS *milter_macros_alloc(init_mode) /* int init_mode; /* /* void milter_macros_free(mp) /* MILTER_MACROS *mp; /* /* int milter_macros_print(print_fn, stream, flags, ptr) /* ATTR_PRINT_COMMON_FN print_fn; /* VSTREAM *stream; /* int flags; /* void *ptr; /* /* int milter_macros_scan(scan_fn, fp, flags, ptr) /* ATTR_SCAN_COMMON_FN scan_fn; /* VSTREAM *fp; /* int flags; /* void *ptr; /* DESCRIPTION /* Sendmail mail filter (Milter) applications receive sets of /* macro name=value pairs with each SMTP or content event. /* In Postfix, these macro names are stored in MILTER_MACROS /* structures, as one list for each event type. By default, /* the same structure is shared by all Milter applications; /* it is initialized with information from main.cf. With /* Sendmail 8.14 a Milter can override one or more lists of /* macro names. Postfix implements this by giving the Milter /* its own MILTER_MACROS structure and by storing the per-Milter /* information there. /* /* This module maintains per-event macro name lists as /* mystrdup()'ed values. The user is explicitly allowed to /* update these values directly, as long as the result is /* compatible with mystrdup(). /* /* milter_macros_create() creates a MILTER_MACROS structure /* and initializes it with copies of its string arguments. /* Null pointers are not valid as input. /* /* milter_macros_alloc() creates am empty MILTER_MACROS structure /* that is initialized according to its init_mode argument. /* .IP MILTER_MACROS_ALLOC_ZERO /* Initialize all structure members as null pointers. This /* mode must be used with milter_macros_scan(), because that /* function blindly overwrites all structure members. No other /* function except milter_macros_free() allows structure members /* with null pointer values. /* .IP MILTER_MACROS_ALLOC_EMPTY /* Initialize all structure members with mystrdup(""). This /* is not as expensive as it appears to be. /* .PP /* milter_macros_free() destroys a MILTER_MACROS structure and /* frees any strings referenced by it. /* /* milter_macros_print() writes the contents of a MILTER_MACROS /* structure to the named stream using the specified attribute /* print routine. milter_macros_print() is meant to be passed /* as a call-back to attr_print*(), thusly: /* /* SEND_ATTR_FUNC(milter_macros_print, (const void *) macros), /* /* milter_macros_scan() reads a MILTER_MACROS structure from /* the named stream using the specified attribute scan routine. /* No attempt is made to free the memory of existing structure /* members. milter_macros_scan() is meant to be passed as a /* call-back to attr_scan*(), thusly: /* /* RECV_ATTR_FUNC(milter_macros_scan, (void *) macros), /* DIAGNOSTICS /* Fatal: out of memory. /* LICENSE /* .ad /* .fi /* The Secure Mailer license must be distributed with this /* software. /* AUTHOR(S) /* Wietse Venema /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA /* /* Wietse Venema /* Google, Inc. /* 111 8th Avenue /* New York, NY 10011, USA /*--*/ /* System library. */ #include /* Utility library. */ #include #include #include #include /* Global library. */ #include #include /* * Ad-hoc protocol to send/receive milter macro name lists. */ #define MAIL_ATTR_MILT_MAC_CONN "conn_macros" #define MAIL_ATTR_MILT_MAC_HELO "helo_macros" #define MAIL_ATTR_MILT_MAC_MAIL "mail_macros" #define MAIL_ATTR_MILT_MAC_RCPT "rcpt_macros" #define MAIL_ATTR_MILT_MAC_DATA "data_macros" #define MAIL_ATTR_MILT_MAC_EOH "eoh_macros" #define MAIL_ATTR_MILT_MAC_EOD "eod_macros" #define MAIL_ATTR_MILT_MAC_UNK "unk_macros" /* milter_macros_print - write macros structure to stream */ int milter_macros_print(ATTR_PRINT_COMMON_FN print_fn, VSTREAM *fp, int flags, const void *ptr) { MILTER_MACROS *mp = (MILTER_MACROS *) ptr; int ret; /* * The attribute order does not matter, except that it must be the same * as in the milter_macros_scan() function. */ ret = print_fn(fp, flags | ATTR_FLAG_MORE, SEND_ATTR_STR(MAIL_ATTR_MILT_MAC_CONN, mp->conn_macros), SEND_ATTR_STR(MAIL_ATTR_MILT_MAC_HELO, mp->helo_macros), SEND_ATTR_STR(MAIL_ATTR_MILT_MAC_MAIL, mp->mail_macros), SEND_ATTR_STR(MAIL_ATTR_MILT_MAC_RCPT, mp->rcpt_macros), SEND_ATTR_STR(MAIL_ATTR_MILT_MAC_DATA, mp->data_macros), SEND_ATTR_STR(MAIL_ATTR_MILT_MAC_EOH, mp->eoh_macros), SEND_ATTR_STR(MAIL_ATTR_MILT_MAC_EOD, mp->eod_macros), SEND_ATTR_STR(MAIL_ATTR_MILT_MAC_UNK, mp->unk_macros), ATTR_TYPE_END); return (ret); } /* milter_macros_scan - receive macros structure from stream */ int milter_macros_scan(ATTR_SCAN_COMMON_FN scan_fn, VSTREAM *fp, int flags, void *ptr) { MILTER_MACROS *mp = (MILTER_MACROS *) ptr; int ret; /* * We could simplify this by moving memory allocation into attr_scan*(). */ VSTRING *conn_macros = vstring_alloc(10); VSTRING *helo_macros = vstring_alloc(10); VSTRING *mail_macros = vstring_alloc(10); VSTRING *rcpt_macros = vstring_alloc(10); VSTRING *data_macros = vstring_alloc(10); VSTRING *eoh_macros = vstring_alloc(10); VSTRING *eod_macros = vstring_alloc(10); VSTRING *unk_macros = vstring_alloc(10); /* * The attribute order does not matter, except that it must be the same * as in the milter_macros_print() function. */ ret = scan_fn(fp, flags | ATTR_FLAG_MORE, RECV_ATTR_STR(MAIL_ATTR_MILT_MAC_CONN, conn_macros), RECV_ATTR_STR(MAIL_ATTR_MILT_MAC_HELO, helo_macros), RECV_ATTR_STR(MAIL_ATTR_MILT_MAC_MAIL, mail_macros), RECV_ATTR_STR(MAIL_ATTR_MILT_MAC_RCPT, rcpt_macros), RECV_ATTR_STR(MAIL_ATTR_MILT_MAC_DATA, data_macros), RECV_ATTR_STR(MAIL_ATTR_MILT_MAC_EOH, eoh_macros), RECV_ATTR_STR(MAIL_ATTR_MILT_MAC_EOD, eod_macros), RECV_ATTR_STR(MAIL_ATTR_MILT_MAC_UNK, unk_macros), ATTR_TYPE_END); /* * Don't optimize for error. */ mp->conn_macros = vstring_export(conn_macros); mp->helo_macros = vstring_export(helo_macros); mp->mail_macros = vstring_export(mail_macros); mp->rcpt_macros = vstring_export(rcpt_macros); mp->data_macros = vstring_export(data_macros); mp->eoh_macros = vstring_export(eoh_macros); mp->eod_macros = vstring_export(eod_macros); mp->unk_macros = vstring_export(unk_macros); return (ret == 8 ? 1 : -1); } /* milter_macros_create - create and initialize macros structure */ MILTER_MACROS *milter_macros_create(const char *conn_macros, const char *helo_macros, const char *mail_macros, const char *rcpt_macros, const char *data_macros, const char *eoh_macros, const char *eod_macros, const char *unk_macros) { MILTER_MACROS *mp; mp = (MILTER_MACROS *) mymalloc(sizeof(*mp)); mp->conn_macros = mystrdup(conn_macros); mp->helo_macros = mystrdup(helo_macros); mp->mail_macros = mystrdup(mail_macros); mp->rcpt_macros = mystrdup(rcpt_macros); mp->data_macros = mystrdup(data_macros); mp->eoh_macros = mystrdup(eoh_macros); mp->eod_macros = mystrdup(eod_macros); mp->unk_macros = mystrdup(unk_macros); return (mp); } /* milter_macros_alloc - allocate macros structure with simple initialization */ MILTER_MACROS *milter_macros_alloc(int mode) { MILTER_MACROS *mp; /* * This macro was originally in milter.h, but no-one else needed it. */ #define milter_macros_init(mp, expr) do { \ MILTER_MACROS *__mp = (mp); \ char *__expr = (expr); \ __mp->conn_macros = __expr; \ __mp->helo_macros = __expr; \ __mp->mail_macros = __expr; \ __mp->rcpt_macros = __expr; \ __mp->data_macros = __expr; \ __mp->eoh_macros = __expr; \ __mp->eod_macros = __expr; \ __mp->unk_macros = __expr; \ } while (0) mp = (MILTER_MACROS *) mymalloc(sizeof(*mp)); switch (mode) { case MILTER_MACROS_ALLOC_ZERO: milter_macros_init(mp, 0); break; case MILTER_MACROS_ALLOC_EMPTY: milter_macros_init(mp, mystrdup("")); break; default: msg_panic("milter_macros_alloc: unknown mode %d", mode); } return (mp); } /* milter_macros_free - destroy memory for MILTER_MACROS structure */ void milter_macros_free(MILTER_MACROS *mp) { /* * This macro was originally in milter.h, but no-one else needed it. */ #define milter_macros_wipe(mp) do { \ MILTER_MACROS *__mp = mp; \ if (__mp->conn_macros) \ myfree(__mp->conn_macros); \ if (__mp->helo_macros) \ myfree(__mp->helo_macros); \ if (__mp->mail_macros) \ myfree(__mp->mail_macros); \ if (__mp->rcpt_macros) \ myfree(__mp->rcpt_macros); \ if (__mp->data_macros) \ myfree(__mp->data_macros); \ if (__mp->eoh_macros) \ myfree(__mp->eoh_macros); \ if (__mp->eod_macros) \ myfree(__mp->eod_macros); \ if (__mp->unk_macros) \ myfree(__mp->unk_macros); \ } while (0) milter_macros_wipe(mp); myfree((void *) mp); }