7 /* SMTP server milter glue
10 /* #include <smtpd_milter.h>
12 /* const char *smtpd_milter_eval(name, context)
16 /* smtpd_milter_eval() is a milter(3) call-back routine to
17 /* expand Sendmail macros before they are sent to filters.
19 /* Panic: interface violations. Fatal errors: out of memory.
20 /* internal protocol errors.
24 /* The Secure Mailer license must be distributed with this software.
27 /* IBM T.J. Watson Research
29 /* Yorktown Heights, NY 10598, USA
36 /* Utility library. */
42 #include <mail_params.h>
43 #include <quote_821_local.h>
49 /* Application-specific. */
52 #include <smtpd_sasl_glue.h>
53 #include <smtpd_resolve.h>
54 #include <smtpd_milter.h>
59 #define STR(x) vstring_str(x)
61 /* smtpd_milter_eval - evaluate milter macro */
63 const char *smtpd_milter_eval(const char *name
, void *ptr
)
65 SMTPD_STATE
*state
= (SMTPD_STATE
*) ptr
;
66 const RESOLVE_REPLY
*reply
;
70 * On-the-fly initialization.
72 if (state
->expand_buf
== 0)
73 state
->expand_buf
= vstring_alloc(10);
76 * Canonicalize the name.
78 if (*name
!= '{') { /* } */
79 vstring_sprintf(state
->expand_buf
, "{%s}", name
);
80 name
= STR(state
->expand_buf
);
86 if (strcmp(name
, S8_MAC_DAEMON_NAME
) == 0)
87 return (var_milt_daemon_name
);
88 if (strcmp(name
, S8_MAC_V
) == 0)
94 if (strcmp(name
, S8_MAC__
) == 0) {
95 vstring_sprintf(state
->expand_buf
, "%s [%s]",
96 state
->reverse_name
, state
->addr
);
97 if (strcasecmp(state
->name
, state
->reverse_name
) != 0)
98 vstring_strcat(state
->expand_buf
, " (may be forged)");
99 return (STR(state
->expand_buf
));
101 if (strcmp(name
, S8_MAC_J
) == 0)
102 return (var_myhostname
);
103 if (strcmp(name
, S8_MAC_CLIENT_ADDR
) == 0)
104 return (state
->rfc_addr
);
105 if (strcmp(name
, S8_MAC_CLIENT_PORT
) == 0)
106 return (strcmp(state
->port
, CLIENT_PORT_UNKNOWN
) ? state
->port
: "0");
107 if (strcmp(name
, S8_MAC_CLIENT_CONN
) == 0) {
108 vstring_sprintf(state
->expand_buf
, "%d", state
->conn_count
);
109 return (STR(state
->expand_buf
));
111 if (strcmp(name
, S8_MAC_CLIENT_NAME
) == 0)
112 return (state
->name
);
113 if (strcmp(name
, S8_MAC_CLIENT_PTR
) == 0)
114 return (state
->reverse_name
);
115 if (strcmp(name
, S8_MAC_CLIENT_RES
) == 0)
116 return (state
->name_status
== SMTPD_PEER_CODE_OK
? "OK" :
117 state
->name_status
== SMTPD_PEER_CODE_FORGED
? "FORGED" :
118 state
->name_status
== SMTPD_PEER_CODE_TEMP
? "TEMP" : "FAIL");
124 #define IF_ENCRYPTED(x) (state->tls_context ? (x) : 0)
125 #define IF_TRUSTED(x) (TLS_CERT_IS_TRUSTED(state->tls_context) ? (x) : 0)
127 if (strcmp(name
, S8_MAC_TLS_VERSION
) == 0)
128 return (IF_ENCRYPTED(state
->tls_context
->protocol
));
129 if (strcmp(name
, S8_MAC_CIPHER
) == 0)
130 return (IF_ENCRYPTED(state
->tls_context
->cipher_name
));
131 if (strcmp(name
, S8_MAC_CIPHER_BITS
) == 0) {
132 if (state
->tls_context
== 0)
134 vstring_sprintf(state
->expand_buf
, "%d",
135 IF_ENCRYPTED(state
->tls_context
->cipher_usebits
));
136 return (STR(state
->expand_buf
));
138 if (strcmp(name
, S8_MAC_CERT_SUBJECT
) == 0)
139 return (IF_TRUSTED(state
->tls_context
->peer_CN
));
140 if (strcmp(name
, S8_MAC_CERT_ISSUER
) == 0)
141 return (IF_TRUSTED(state
->tls_context
->issuer_CN
));
147 #define IF_SASL_ENABLED(s) (smtpd_sasl_is_active(state) && (s) ? (s) : 0)
149 if (strcmp(name
, S8_MAC_I
) == 0)
150 return (state
->queue_id
);
152 if (strcmp(name
, S8_MAC_AUTH_TYPE
) == 0)
153 return (IF_SASL_ENABLED(state
->sasl_method
));
154 if (strcmp(name
, S8_MAC_AUTH_AUTHEN
) == 0)
155 return (IF_SASL_ENABLED(state
->sasl_username
));
156 if (strcmp(name
, S8_MAC_AUTH_AUTHOR
) == 0)
157 return (IF_SASL_ENABLED(state
->sasl_sender
));
159 if (strcmp(name
, S8_MAC_MAIL_ADDR
) == 0) {
160 if (state
->sender
== 0)
162 if (state
->sender
[0] == 0)
164 reply
= smtpd_resolve_addr(state
->sender
);
165 /* Sendmail 8.13 does not externalize the null string. */
166 if (STR(reply
->recipient
)[0])
167 quote_821_local(state
->expand_buf
, STR(reply
->recipient
));
169 vstring_strcpy(state
->expand_buf
, STR(reply
->recipient
));
170 return (STR(state
->expand_buf
));
172 if (strcmp(name
, S8_MAC_MAIL_HOST
) == 0) {
173 if (state
->sender
== 0)
175 reply
= smtpd_resolve_addr(state
->sender
);
176 return (STR(reply
->nexthop
));
178 if (strcmp(name
, S8_MAC_MAIL_MAILER
) == 0) {
179 if (state
->sender
== 0)
181 reply
= smtpd_resolve_addr(state
->sender
);
182 return (STR(reply
->transport
));
188 if (strcmp(name
, S8_MAC_RCPT_ADDR
) == 0) {
189 if (state
->recipient
== 0)
191 if (state
->recipient
[0] == 0)
193 if (state
->milter_reject_text
) {
194 /* 554 5.7.1 <user@example.com>: Relay access denied */
195 vstring_strcpy(state
->expand_buf
, state
->milter_reject_text
+ 4);
196 cp
= split_at(STR(state
->expand_buf
), ' ');
197 return (cp
? split_at(cp
, ' ') : cp
);
199 reply
= smtpd_resolve_addr(state
->recipient
);
200 /* Sendmail 8.13 does not externalize the null string. */
201 if (STR(reply
->recipient
)[0])
202 quote_821_local(state
->expand_buf
, STR(reply
->recipient
));
204 vstring_strcpy(state
->expand_buf
, STR(reply
->recipient
));
205 return (STR(state
->expand_buf
));
207 if (strcmp(name
, S8_MAC_RCPT_HOST
) == 0) {
208 if (state
->recipient
== 0)
210 if (state
->milter_reject_text
) {
211 /* 554 5.7.1 <user@example.com>: Relay access denied */
212 vstring_strcpy(state
->expand_buf
, state
->milter_reject_text
+ 4);
213 (void) split_at(STR(state
->expand_buf
), ' ');
214 return (STR(state
->expand_buf
));
216 reply
= smtpd_resolve_addr(state
->recipient
);
217 return (STR(reply
->nexthop
));
219 if (strcmp(name
, S8_MAC_RCPT_MAILER
) == 0) {
220 if (state
->recipient
== 0)
222 if (state
->milter_reject_text
)
223 return (S8_RCPT_MAILER_ERROR
);
224 reply
= smtpd_resolve_addr(state
->recipient
);
225 return (STR(reply
->transport
));