1 /* $NetBSD: smtpd_milter.c,v 1.3 2020/03/18 19:05:20 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 if (strcmp(name, S8_MAC_DAEMON_ADDR) == 0) 119 return (state->dest_addr); 120 if (strcmp(name, S8_MAC_DAEMON_PORT) == 0) 121 return (state->dest_port); 122 123 /* 124 * HELO macros. 125 */ 126 #ifdef USE_TLS 127 #define IF_ENCRYPTED(x) (state->tls_context ? (x) : 0) 128 #define IF_TRUSTED(x) (TLS_CERT_IS_TRUSTED(state->tls_context) ? (x) : 0) 129 130 if (strcmp(name, S8_MAC_TLS_VERSION) == 0) 131 return (IF_ENCRYPTED(state->tls_context->protocol)); 132 if (strcmp(name, S8_MAC_CIPHER) == 0) 133 return (IF_ENCRYPTED(state->tls_context->cipher_name)); 134 if (strcmp(name, S8_MAC_CIPHER_BITS) == 0) { 135 if (state->tls_context == 0) 136 return (0); 137 vstring_sprintf(state->expand_buf, "%d", 138 IF_ENCRYPTED(state->tls_context->cipher_usebits)); 139 return (STR(state->expand_buf)); 140 } 141 if (strcmp(name, S8_MAC_CERT_SUBJECT) == 0) 142 return (IF_TRUSTED(state->tls_context->peer_CN)); 143 if (strcmp(name, S8_MAC_CERT_ISSUER) == 0) 144 return (IF_TRUSTED(state->tls_context->issuer_CN)); 145 #endif 146 147 /* 148 * MAIL FROM macros. 149 */ 150 #define IF_SASL_ENABLED(s) ((s) ? (s) : 0) 151 152 if (strcmp(name, S8_MAC_I) == 0) 153 return (state->queue_id); 154 #ifdef USE_SASL_AUTH 155 if (strcmp(name, S8_MAC_AUTH_TYPE) == 0) 156 return (IF_SASL_ENABLED(state->sasl_method)); 157 if (strcmp(name, S8_MAC_AUTH_AUTHEN) == 0) 158 return (IF_SASL_ENABLED(state->sasl_username)); 159 if (strcmp(name, S8_MAC_AUTH_AUTHOR) == 0) 160 return (IF_SASL_ENABLED(state->sasl_sender)); 161 #endif 162 if (strcmp(name, S8_MAC_MAIL_ADDR) == 0) { 163 if (state->sender == 0) 164 return (0); 165 if (state->sender[0] == 0) 166 return (""); 167 reply = smtpd_resolve_addr(state->recipient, state->sender); 168 /* Sendmail 8.13 does not externalize the null string. */ 169 if (STR(reply->recipient)[0]) 170 quote_821_local(state->expand_buf, STR(reply->recipient)); 171 else 172 vstring_strcpy(state->expand_buf, STR(reply->recipient)); 173 return (STR(state->expand_buf)); 174 } 175 if (strcmp(name, S8_MAC_MAIL_HOST) == 0) { 176 if (state->sender == 0) 177 return (0); 178 reply = smtpd_resolve_addr(state->recipient, state->sender); 179 return (STR(reply->nexthop)); 180 } 181 if (strcmp(name, S8_MAC_MAIL_MAILER) == 0) { 182 if (state->sender == 0) 183 return (0); 184 reply = smtpd_resolve_addr(state->recipient, state->sender); 185 return (STR(reply->transport)); 186 } 187 188 /* 189 * RCPT TO macros. 190 */ 191 if (strcmp(name, S8_MAC_RCPT_ADDR) == 0) { 192 if (state->recipient == 0) 193 return (0); 194 if (state->recipient[0] == 0) 195 return (""); 196 if (state->milter_reject_text) { 197 /* 554 5.7.1 <user@example.com>: Relay access denied */ 198 vstring_strcpy(state->expand_buf, state->milter_reject_text + 4); 199 cp = split_at(STR(state->expand_buf), ' '); 200 return (cp ? split_at(cp, ' ') : cp); 201 } 202 reply = smtpd_resolve_addr(state->sender, state->recipient); 203 /* Sendmail 8.13 does not externalize the null string. */ 204 if (STR(reply->recipient)[0]) 205 quote_821_local(state->expand_buf, STR(reply->recipient)); 206 else 207 vstring_strcpy(state->expand_buf, STR(reply->recipient)); 208 return (STR(state->expand_buf)); 209 } 210 if (strcmp(name, S8_MAC_RCPT_HOST) == 0) { 211 if (state->recipient == 0) 212 return (0); 213 if (state->milter_reject_text) { 214 /* 554 5.7.1 <user@example.com>: Relay access denied */ 215 vstring_strcpy(state->expand_buf, state->milter_reject_text + 4); 216 (void) split_at(STR(state->expand_buf), ' '); 217 return (STR(state->expand_buf)); 218 } 219 reply = smtpd_resolve_addr(state->sender, state->recipient); 220 return (STR(reply->nexthop)); 221 } 222 if (strcmp(name, S8_MAC_RCPT_MAILER) == 0) { 223 if (state->recipient == 0) 224 return (0); 225 if (state->milter_reject_text) 226 return (S8_RCPT_MAILER_ERROR); 227 reply = smtpd_resolve_addr(state->sender, state->recipient); 228 return (STR(reply->transport)); 229 } 230 return (0); 231 } 232