1 /* $NetBSD: smtpd_milter.c,v 1.1.1.1 2009/06/23 10:08:56 tron 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 32 /* System library. */ 33 34 #include <sys_defs.h> 35 36 /* Utility library. */ 37 38 #include <split_at.h> 39 40 /* Global library. */ 41 42 #include <mail_params.h> 43 #include <quote_821_local.h> 44 45 /* Milter library. */ 46 47 #include <milter.h> 48 49 /* Application-specific. */ 50 51 #include <smtpd.h> 52 #include <smtpd_sasl_glue.h> 53 #include <smtpd_resolve.h> 54 #include <smtpd_milter.h> 55 56 /* 57 * SLMs. 58 */ 59 #define STR(x) vstring_str(x) 60 61 /* smtpd_milter_eval - evaluate milter macro */ 62 63 const char *smtpd_milter_eval(const char *name, void *ptr) 64 { 65 SMTPD_STATE *state = (SMTPD_STATE *) ptr; 66 const RESOLVE_REPLY *reply; 67 char *cp; 68 69 /* 70 * On-the-fly initialization. 71 */ 72 if (state->expand_buf == 0) 73 state->expand_buf = vstring_alloc(10); 74 75 /* 76 * Canonicalize the name. 77 */ 78 if (*name != '{') { /* } */ 79 vstring_sprintf(state->expand_buf, "{%s}", name); 80 name = STR(state->expand_buf); 81 } 82 83 /* 84 * System macros. 85 */ 86 if (strcmp(name, S8_MAC_DAEMON_NAME) == 0) 87 return (var_milt_daemon_name); 88 if (strcmp(name, S8_MAC_V) == 0) 89 return (var_milt_v); 90 91 /* 92 * Connect macros. 93 */ 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)); 100 } 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)); 110 } 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"); 119 120 /* 121 * HELO macros. 122 */ 123 #ifdef USE_TLS 124 #define IF_ENCRYPTED(x) (state->tls_context ? (x) : 0) 125 #define IF_TRUSTED(x) (TLS_CERT_IS_TRUSTED(state->tls_context) ? (x) : 0) 126 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) 133 return (0); 134 vstring_sprintf(state->expand_buf, "%d", 135 IF_ENCRYPTED(state->tls_context->cipher_usebits)); 136 return (STR(state->expand_buf)); 137 } 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)); 142 #endif 143 144 /* 145 * MAIL FROM macros. 146 */ 147 #define IF_SASL_ENABLED(s) (smtpd_sasl_is_active(state) && (s) ? (s) : 0) 148 149 if (strcmp(name, S8_MAC_I) == 0) 150 return (state->queue_id); 151 #ifdef USE_SASL_AUTH 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)); 158 #endif 159 if (strcmp(name, S8_MAC_MAIL_ADDR) == 0) { 160 if (state->sender == 0) 161 return (0); 162 if (state->sender[0] == 0) 163 return (""); 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)); 168 else 169 vstring_strcpy(state->expand_buf, STR(reply->recipient)); 170 return (STR(state->expand_buf)); 171 } 172 if (strcmp(name, S8_MAC_MAIL_HOST) == 0) { 173 if (state->sender == 0) 174 return (0); 175 reply = smtpd_resolve_addr(state->sender); 176 return (STR(reply->nexthop)); 177 } 178 if (strcmp(name, S8_MAC_MAIL_MAILER) == 0) { 179 if (state->sender == 0) 180 return (0); 181 reply = smtpd_resolve_addr(state->sender); 182 return (STR(reply->transport)); 183 } 184 185 /* 186 * RCPT TO macros. 187 */ 188 if (strcmp(name, S8_MAC_RCPT_ADDR) == 0) { 189 if (state->recipient == 0) 190 return (0); 191 if (state->recipient[0] == 0) 192 return (""); 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); 198 } 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)); 203 else 204 vstring_strcpy(state->expand_buf, STR(reply->recipient)); 205 return (STR(state->expand_buf)); 206 } 207 if (strcmp(name, S8_MAC_RCPT_HOST) == 0) { 208 if (state->recipient == 0) 209 return (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)); 215 } 216 reply = smtpd_resolve_addr(state->recipient); 217 return (STR(reply->nexthop)); 218 } 219 if (strcmp(name, S8_MAC_RCPT_MAILER) == 0) { 220 if (state->recipient == 0) 221 return (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)); 226 } 227 return (0); 228 } 229