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