1 /*++
2 /* NAME
3 /*	smtpd_milter 3
4 /* SUMMARY
5 /*	SMTP server milter glue
6 /* SYNOPSIS
7 /*	#include <smtpd.h>
8 /*	#include <smtpd_milter.h>
9 /*
10 /*	const char *smtpd_milter_eval(name, context)
11 /*	const char *name;
12 /*	void	*context;
13 /* DESCRIPTION
14 /*	smtpd_milter_eval() is a milter(3) call-back routine to
15 /*	expand Sendmail macros before they are sent to filters.
16 /* DIAGNOSTICS
17 /*	Panic: interface violations. Fatal errors: out of memory.
18 /*	internal protocol errors.
19 /* LICENSE
20 /* .ad
21 /* .fi
22 /*	The Secure Mailer license must be distributed with this software.
23 /* AUTHOR(S)
24 /*	Wietse Venema
25 /*	IBM T.J. Watson Research
26 /*	P.O. Box 704
27 /*	Yorktown Heights, NY 10598, USA
28 /*
29 /*	Wietse Venema
30 /*	Google, Inc.
31 /*	111 8th Avenue
32 /*	New York, NY 10011, USA
33 /*--*/
34 
35 /* System library. */
36 
37 #include <sys_defs.h>
38 
39 /* Utility library. */
40 
41 #include <split_at.h>
42 #include <stringops.h>
43 
44 /* Global library. */
45 
46 #include <mail_params.h>
47 #include <quote_821_local.h>
48 
49 /* Milter library. */
50 
51 #include <milter.h>
52 
53 /* Application-specific. */
54 
55 #include <smtpd.h>
56 #include <smtpd_sasl_glue.h>
57 #include <smtpd_resolve.h>
58 #include <smtpd_milter.h>
59 
60  /*
61   * SLMs.
62   */
63 #define STR(x)	vstring_str(x)
64 
65 /* smtpd_milter_eval - evaluate milter macro */
66 
smtpd_milter_eval(const char * name,void * ptr)67 const char *smtpd_milter_eval(const char *name, void *ptr)
68 {
69     SMTPD_STATE *state = (SMTPD_STATE *) ptr;
70     const RESOLVE_REPLY *reply;
71     char   *cp;
72 
73     /*
74      * On-the-fly initialization.
75      */
76     if (state->expand_buf == 0)
77 	state->expand_buf = vstring_alloc(10);
78 
79     /*
80      * System macros.
81      */
82     if (strcmp(name, S8_MAC_DAEMON_NAME) == 0)
83 	return (var_milt_daemon_name);
84     if (strcmp(name, S8_MAC_V) == 0)
85 	return (var_milt_v);
86 
87     /*
88      * Connect macros.
89      */
90     if (strcmp(name, S8_MAC__) == 0) {
91 	vstring_sprintf(state->expand_buf, "%s [%s]",
92 			state->reverse_name, state->addr);
93 	if (strcasecmp_utf8(state->name, state->reverse_name) != 0)
94 	    vstring_strcat(state->expand_buf, " (may be forged)");
95 	return (STR(state->expand_buf));
96     }
97     if (strcmp(name, S8_MAC_J) == 0)
98 	return (var_myhostname);
99     if (strcmp(name, S8_MAC_CLIENT_ADDR) == 0)
100 	return (state->rfc_addr);
101     if (strcmp(name, S8_MAC_CLIENT_PORT) == 0)
102 	return (strcmp(state->port, CLIENT_PORT_UNKNOWN) ? state->port : "0");
103     if (strcmp(name, S8_MAC_CLIENT_CONN) == 0) {
104 	vstring_sprintf(state->expand_buf, "%d", state->conn_count);
105 	return (STR(state->expand_buf));
106     }
107     if (strcmp(name, S8_MAC_CLIENT_NAME) == 0)
108 	return (state->name);
109     if (strcmp(name, S8_MAC_CLIENT_PTR) == 0)
110 	return (state->reverse_name);
111     if (strcmp(name, S8_MAC_CLIENT_RES) == 0)
112 	return (state->name_status == SMTPD_PEER_CODE_OK ? "OK" :
113 		state->name_status == SMTPD_PEER_CODE_FORGED ? "FORGED" :
114 	      state->name_status == SMTPD_PEER_CODE_TEMP ? "TEMP" : "FAIL");
115 
116     if (strcmp(name, S8_MAC_DAEMON_ADDR) == 0)
117 	return (state->dest_addr);
118     if (strcmp(name, S8_MAC_DAEMON_PORT) == 0)
119 	return (state->dest_port);
120 
121     /*
122      * HELO macros.
123      */
124 #ifdef USE_TLS
125 #define IF_ENCRYPTED(x) (state->tls_context ? (x) : 0)
126 #define IF_TRUSTED(x) (TLS_CERT_IS_TRUSTED(state->tls_context) ? (x) : 0)
127 
128     if (strcmp(name, S8_MAC_TLS_VERSION) == 0)
129 	return (IF_ENCRYPTED(state->tls_context->protocol));
130     if (strcmp(name, S8_MAC_CIPHER) == 0)
131 	return (IF_ENCRYPTED(state->tls_context->cipher_name));
132     if (strcmp(name, S8_MAC_CIPHER_BITS) == 0) {
133 	if (state->tls_context == 0)
134 	    return (0);
135 	vstring_sprintf(state->expand_buf, "%d",
136 			IF_ENCRYPTED(state->tls_context->cipher_usebits));
137 	return (STR(state->expand_buf));
138     }
139     if (strcmp(name, S8_MAC_CERT_SUBJECT) == 0)
140 	return (IF_TRUSTED(state->tls_context->peer_CN));
141     if (strcmp(name, S8_MAC_CERT_ISSUER) == 0)
142 	return (IF_TRUSTED(state->tls_context->issuer_CN));
143 #endif
144 
145     /*
146      * MAIL FROM macros.
147      */
148 #define IF_SASL_ENABLED(s) ((s) ? (s) : 0)
149 
150     if (strcmp(name, S8_MAC_I) == 0)
151 	return (state->queue_id);
152 #ifdef USE_SASL_AUTH
153     if (strcmp(name, S8_MAC_AUTH_TYPE) == 0)
154 	return (IF_SASL_ENABLED(state->sasl_method));
155     if (strcmp(name, S8_MAC_AUTH_AUTHEN) == 0)
156 	return (IF_SASL_ENABLED(state->sasl_username));
157     if (strcmp(name, S8_MAC_AUTH_AUTHOR) == 0)
158 	return (IF_SASL_ENABLED(state->sasl_sender));
159 #endif
160     if (strcmp(name, S8_MAC_MAIL_ADDR) == 0) {
161 	if (state->sender == 0)
162 	    return (0);
163 	if (state->sender[0] == 0)
164 	    return ("");
165 	reply = smtpd_resolve_addr(state->recipient, state->sender);
166 	/* Sendmail 8.13 does not externalize the null string. */
167 	if (STR(reply->recipient)[0])
168 	    quote_821_local(state->expand_buf, STR(reply->recipient));
169 	else
170 	    vstring_strcpy(state->expand_buf, STR(reply->recipient));
171 	return (STR(state->expand_buf));
172     }
173     if (strcmp(name, S8_MAC_MAIL_HOST) == 0) {
174 	if (state->sender == 0)
175 	    return (0);
176 	reply = smtpd_resolve_addr(state->recipient, state->sender);
177 	return (STR(reply->nexthop));
178     }
179     if (strcmp(name, S8_MAC_MAIL_MAILER) == 0) {
180 	if (state->sender == 0)
181 	    return (0);
182 	reply = smtpd_resolve_addr(state->recipient, state->sender);
183 	return (STR(reply->transport));
184     }
185 
186     /*
187      * RCPT TO macros.
188      */
189     if (strcmp(name, S8_MAC_RCPT_ADDR) == 0) {
190 	if (state->recipient == 0)
191 	    return (0);
192 	if (state->recipient[0] == 0)
193 	    return ("");
194 	if (state->milter_reject_text) {
195 	    /* 554 5.7.1 <user@example.com>: Relay access denied */
196 	    vstring_strcpy(state->expand_buf, state->milter_reject_text + 4);
197 	    cp = split_at(STR(state->expand_buf), ' ');
198 	    return (cp ? split_at(cp, ' ') : cp);
199 	}
200 	reply = smtpd_resolve_addr(state->sender, state->recipient);
201 	/* Sendmail 8.13 does not externalize the null string. */
202 	if (STR(reply->recipient)[0])
203 	    quote_821_local(state->expand_buf, STR(reply->recipient));
204 	else
205 	    vstring_strcpy(state->expand_buf, STR(reply->recipient));
206 	return (STR(state->expand_buf));
207     }
208     if (strcmp(name, S8_MAC_RCPT_HOST) == 0) {
209 	if (state->recipient == 0)
210 	    return (0);
211 	if (state->milter_reject_text) {
212 	    /* 554 5.7.1 <user@example.com>: Relay access denied */
213 	    vstring_strcpy(state->expand_buf, state->milter_reject_text + 4);
214 	    (void) split_at(STR(state->expand_buf), ' ');
215 	    return (STR(state->expand_buf));
216 	}
217 	reply = smtpd_resolve_addr(state->sender, state->recipient);
218 	return (STR(reply->nexthop));
219     }
220     if (strcmp(name, S8_MAC_RCPT_MAILER) == 0) {
221 	if (state->recipient == 0)
222 	    return (0);
223 	if (state->milter_reject_text)
224 	    return (S8_RCPT_MAILER_ERROR);
225 	reply = smtpd_resolve_addr(state->sender, state->recipient);
226 	return (STR(reply->transport));
227     }
228     return (0);
229 }
230