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