1*68e5c67bSchristos /*	$NetBSD: postscreen_expand.c,v 1.2 2017/02/14 01:16:47 christos Exp $	*/
2e8314800Stron 
3e8314800Stron /*++
4e8314800Stron /* NAME
5e8314800Stron /*	postscreen_expand 3
6e8314800Stron /* SUMMARY
7e8314800Stron /*	SMTP server macro expansion
8e8314800Stron /* SYNOPSIS
9e8314800Stron /*	#include <postscreen.h>
10e8314800Stron /*
11e8314800Stron /*	void	psc_expand_init()
12e8314800Stron /*
13e8314800Stron /*	VSTRING *psc_expand_filter;
14e8314800Stron /*
15e8314800Stron /*	const char *psc_expand_lookup(name, unused_mode, context)
16e8314800Stron /*	const char *name;
17e8314800Stron /*	int	unused_mode;
18e8314800Stron /*	char	*context;
19e8314800Stron /* DESCRIPTION
20e8314800Stron /*	This module expands session-related macros.
21e8314800Stron /*
22e8314800Stron /*	psc_expand_init() performs one-time initialization
23e8314800Stron /*	of the psc_expand_filter buffer.
24e8314800Stron /*
25e8314800Stron /*	The psc_expand_filter buffer contains the characters
26e8314800Stron /*	that are allowed in macro expansion, as specified with the
27e8314800Stron /*	psc_expand_filter configuration parameter.
28e8314800Stron /*
29e8314800Stron /*	psc_expand_lookup() returns the value of the named
30e8314800Stron /*	macro or a null pointer.
31e8314800Stron /*
32e8314800Stron /*	Arguments:
33e8314800Stron /* .IP name
34e8314800Stron /*	Macro name.
35e8314800Stron /* .IP context
36e8314800Stron /*	Call-back context (a PSC_STATE pointer).
37e8314800Stron /* DIAGNOSTICS
38e8314800Stron /*	Panic: interface violations. Fatal errors: out of memory.
39e8314800Stron /*	internal protocol errors. postscreen_expand() returns the
40e8314800Stron /*	binary OR of MAC_PARSE_ERROR (syntax error) and MAC_PARSE_UNDEF
41e8314800Stron /*	(undefined macro name).
42e8314800Stron /* LICENSE
43e8314800Stron /* .ad
44e8314800Stron /* .fi
45e8314800Stron /*	The Secure Mailer license must be distributed with this software.
46e8314800Stron /* AUTHOR(S)
47e8314800Stron /*	Wietse Venema
48e8314800Stron /*	IBM T.J. Watson Research
49e8314800Stron /*	P.O. Box 704
50e8314800Stron /*	Yorktown Heights, NY 10598, USA
51e8314800Stron /*--*/
52e8314800Stron 
53e8314800Stron /* System library. */
54e8314800Stron 
55e8314800Stron #include <sys_defs.h>
56e8314800Stron #include <time.h>
57e8314800Stron 
58e8314800Stron /* Utility library. */
59e8314800Stron 
60e8314800Stron #include <msg.h>
61e8314800Stron #include <vstring.h>
62e8314800Stron #include <stringops.h>
63e8314800Stron 
64e8314800Stron /* Global library. */
65e8314800Stron 
66e8314800Stron #include <mail_params.h>
67e8314800Stron #include <mail_proto.h>
68e8314800Stron 
69e8314800Stron /* Application-specific. */
70e8314800Stron 
71e8314800Stron #include <postscreen.h>
72e8314800Stron 
73e8314800Stron  /*
74e8314800Stron   * Pre-parsed expansion filter.
75e8314800Stron   */
76e8314800Stron VSTRING *psc_expand_filter;
77e8314800Stron 
78e8314800Stron /* psc_expand_init - initialize once during process lifetime */
79e8314800Stron 
psc_expand_init(void)80e8314800Stron void    psc_expand_init(void)
81e8314800Stron {
82e8314800Stron 
83e8314800Stron     /*
84e8314800Stron      * Expand the expansion filter :-)
85e8314800Stron      */
86e8314800Stron     psc_expand_filter = vstring_alloc(10);
87e8314800Stron     unescape(psc_expand_filter, var_psc_exp_filter);
88e8314800Stron }
89e8314800Stron 
90e8314800Stron /* psc_expand_lookup - generic SMTP attribute $name expansion */
91e8314800Stron 
psc_expand_lookup(const char * name,int unused_mode,void * context)92e8314800Stron const char *psc_expand_lookup(const char *name, int unused_mode,
93837e7c1aSchristos 			              void *context)
94e8314800Stron {
95e8314800Stron     PSC_STATE *state = (PSC_STATE *) context;
96e8314800Stron     time_t  now;
97e8314800Stron     struct tm *lt;
98e8314800Stron 
99e8314800Stron     if (state->expand_buf == 0)
100e8314800Stron 	state->expand_buf = vstring_alloc(10);
101e8314800Stron 
102e8314800Stron     if (msg_verbose > 1)
103e8314800Stron 	msg_info("psc_expand_lookup: ${%s}", name);
104e8314800Stron 
105e8314800Stron #define STREQ(x,y)    (*(x) == *(y) && strcmp((x), (y)) == 0)
106e8314800Stron #define STREQN(x,y,n) (*(x) == *(y) && strncmp((x), (y), (n)) == 0)
107e8314800Stron #define CONST_LEN(x)  (sizeof(x) - 1)
108e8314800Stron 
109e8314800Stron     /*
110e8314800Stron      * Don't query main.cf parameters, as the result of expansion could
111e8314800Stron      * reveal system-internal information in server replies.
112e8314800Stron      *
113e8314800Stron      * XXX: This said, multiple servers may be behind a single client-visible
114e8314800Stron      * name or IP address, and each may generate its own logs. Therefore, it
115e8314800Stron      * may be useful to expose the replying MTA id (myhostname) in the
116e8314800Stron      * contact footer, to identify the right logs. So while we don't expose
117e8314800Stron      * the raw configuration dictionary, we do expose "$myhostname" as
118e8314800Stron      * expanded in var_myhostname.
119e8314800Stron      *
120e8314800Stron      * Return NULL only for non-existent names.
121e8314800Stron      */
122e8314800Stron     if (STREQ(name, MAIL_ATTR_SERVER_NAME)) {
123e8314800Stron 	return (var_myhostname);
124e8314800Stron     } else if (STREQ(name, MAIL_ATTR_ACT_CLIENT_ADDR)) {
125e8314800Stron 	return (state->smtp_client_addr);
126e8314800Stron     } else if (STREQ(name, MAIL_ATTR_ACT_CLIENT_PORT)) {
127e8314800Stron 	return (state->smtp_client_port);
128e8314800Stron     } if (STREQ(name, MAIL_ATTR_LOCALTIME)) {
129e8314800Stron 	if (time(&now) == (time_t) -1)
130e8314800Stron 	    msg_fatal("time lookup failed: %m");
131e8314800Stron 	lt = localtime(&now);
132e8314800Stron 	VSTRING_RESET(state->expand_buf);
133e8314800Stron 	do {
134e8314800Stron 	    VSTRING_SPACE(state->expand_buf, 100);
135e8314800Stron 	} while (strftime(STR(state->expand_buf),
136e8314800Stron 			  vstring_avail(state->expand_buf),
137e8314800Stron 			  "%b %d %H:%M:%S", lt) == 0);
138e8314800Stron 	return (STR(state->expand_buf));
139e8314800Stron     } else {
140e8314800Stron 	msg_warn("unknown macro name \"%s\" in expansion request", name);
141e8314800Stron 	return (0);
142e8314800Stron     }
143e8314800Stron }
144