Home | History | Annotate | Line # | Download | only in milter
      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