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