1 0 stevel /* 2 6562 jbeck * Copyright (c) 1998-2008 Sendmail, Inc. and its suppliers. 3 0 stevel * All rights reserved. 4 0 stevel * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 5 0 stevel * Copyright (c) 1988, 1993 6 0 stevel * The Regents of the University of California. All rights reserved. 7 0 stevel * 8 0 stevel * By using this file, you agree to the terms and conditions set 9 0 stevel * forth in the LICENSE file which can be found at the top level of 10 0 stevel * the sendmail distribution. 11 0 stevel * 12 0 stevel */ 13 0 stevel 14 0 stevel #pragma ident "%Z%%M% %I% %E% SMI" 15 0 stevel 16 0 stevel #include <sendmail.h> 17 0 stevel #if MILTER 18 0 stevel # include <libmilter/mfapi.h> 19 0 stevel # include <libmilter/mfdef.h> 20 0 stevel #endif /* MILTER */ 21 0 stevel 22 6562 jbeck SM_RCSID("@(#)$Id: srvrsmtp.c,v 8.975 2008/03/31 16:32:13 ca Exp $") 23 616 jbeck 24 616 jbeck #include <sm/time.h> 25 0 stevel #include <sm/fdset.h> 26 0 stevel 27 0 stevel #if SASL || STARTTLS 28 0 stevel # include "sfsasl.h" 29 0 stevel #endif /* SASL || STARTTLS */ 30 0 stevel #if SASL 31 0 stevel # define ENC64LEN(l) (((l) + 2) * 4 / 3 + 1) 32 0 stevel static int saslmechs __P((sasl_conn_t *, char **)); 33 0 stevel #endif /* SASL */ 34 0 stevel #if STARTTLS 35 0 stevel # include <sysexits.h> 36 0 stevel 37 0 stevel static SSL_CTX *srv_ctx = NULL; /* TLS server context */ 38 0 stevel static SSL *srv_ssl = NULL; /* per connection context */ 39 0 stevel 40 0 stevel static bool tls_ok_srv = false; 41 3544 jbeck 42 3544 jbeck # define TLS_VERIFY_CLIENT() tls_set_verify(srv_ctx, srv_ssl, \ 43 3544 jbeck bitset(SRV_VRFY_CLT, features)) 44 3544 jbeck #endif /* STARTTLS */ 45 3544 jbeck 46 1658 jbeck #if _FFR_DM_ONE 47 1658 jbeck static bool NotFirstDelivery = false; 48 1658 jbeck #endif /* _FFR_DM_ONE */ 49 0 stevel 50 0 stevel /* server features */ 51 0 stevel #define SRV_NONE 0x0000 /* none... */ 52 0 stevel #define SRV_OFFER_TLS 0x0001 /* offer STARTTLS */ 53 0 stevel #define SRV_VRFY_CLT 0x0002 /* request a cert */ 54 0 stevel #define SRV_OFFER_AUTH 0x0004 /* offer AUTH */ 55 0 stevel #define SRV_OFFER_ETRN 0x0008 /* offer ETRN */ 56 0 stevel #define SRV_OFFER_VRFY 0x0010 /* offer VRFY (not yet used) */ 57 0 stevel #define SRV_OFFER_EXPN 0x0020 /* offer EXPN */ 58 0 stevel #define SRV_OFFER_VERB 0x0040 /* offer VERB */ 59 0 stevel #define SRV_OFFER_DSN 0x0080 /* offer DSN */ 60 0 stevel #if PIPELINING 61 0 stevel # define SRV_OFFER_PIPE 0x0100 /* offer PIPELINING */ 62 0 stevel # if _FFR_NO_PIPE 63 0 stevel # define SRV_NO_PIPE 0x0200 /* disable PIPELINING, sleep if used */ 64 0 stevel # endif /* _FFR_NO_PIPE */ 65 0 stevel #endif /* PIPELINING */ 66 0 stevel #define SRV_REQ_AUTH 0x0400 /* require AUTH */ 67 0 stevel #define SRV_REQ_SEC 0x0800 /* require security - equiv to AuthOptions=p */ 68 0 stevel #define SRV_TMP_FAIL 0x1000 /* ruleset caused a temporary failure */ 69 0 stevel 70 0 stevel static unsigned int srvfeatures __P((ENVELOPE *, char *, unsigned int)); 71 0 stevel 72 0 stevel #define STOP_ATTACK ((time_t) -1) 73 0 stevel static time_t checksmtpattack __P((volatile unsigned int *, unsigned int, 74 0 stevel bool, char *, ENVELOPE *)); 75 0 stevel static void printvrfyaddr __P((ADDRESS *, bool, bool)); 76 0 stevel static char *skipword __P((char *volatile, char *)); 77 0 stevel static void setup_smtpd_io __P((void)); 78 0 stevel 79 0 stevel #if SASL 80 0 stevel # if SASL >= 20000 81 0 stevel static int reset_saslconn __P((sasl_conn_t **_conn, char *_hostname, 82 0 stevel char *_remoteip, char *_localip, 83 0 stevel char *_auth_id, sasl_ssf_t *_ext_ssf)); 84 0 stevel 85 0 stevel # define RESET_SASLCONN \ 86 0 stevel do \ 87 0 stevel { \ 88 0 stevel result = reset_saslconn(&conn, AuthRealm, remoteip, \ 89 0 stevel localip, auth_id, &ext_ssf); \ 90 0 stevel if (result != SASL_OK) \ 91 0 stevel sasl_ok = false; \ 92 0 stevel } while (0) 93 0 stevel 94 0 stevel # else /* SASL >= 20000 */ 95 0 stevel static int reset_saslconn __P((sasl_conn_t **_conn, char *_hostname, 96 0 stevel struct sockaddr_in *_saddr_r, 97 0 stevel struct sockaddr_in *_saddr_l, 98 0 stevel sasl_external_properties_t *_ext_ssf)); 99 0 stevel # define RESET_SASLCONN \ 100 0 stevel do \ 101 0 stevel { \ 102 0 stevel result = reset_saslconn(&conn, AuthRealm, &saddr_r, \ 103 0 stevel &saddr_l, &ext_ssf); \ 104 0 stevel if (result != SASL_OK) \ 105 0 stevel sasl_ok = false; \ 106 0 stevel } while (0) 107 0 stevel 108 0 stevel # endif /* SASL >= 20000 */ 109 0 stevel #endif /* SASL */ 110 0 stevel 111 0 stevel extern ENVELOPE BlankEnvelope; 112 0 stevel 113 0 stevel #define NBADRCPTS \ 114 0 stevel do \ 115 0 stevel { \ 116 0 stevel char buf[16]; \ 117 3544 jbeck (void) sm_snprintf(buf, sizeof(buf), "%d", \ 118 0 stevel BadRcptThrottle > 0 && n_badrcpts > BadRcptThrottle \ 119 0 stevel ? n_badrcpts - 1 : n_badrcpts); \ 120 0 stevel macdefine(&e->e_macro, A_TEMP, macid("{nbadrcpts}"), buf); \ 121 0 stevel } while (0) 122 0 stevel 123 0 stevel #define SKIP_SPACE(s) while (isascii(*s) && isspace(*s)) \ 124 0 stevel (s)++ 125 3544 jbeck 126 3544 jbeck /* 127 3544 jbeck ** PARSE_ESMTP_ARGS -- parse EMSTP arguments (for MAIL, RCPT) 128 3544 jbeck ** 129 3544 jbeck ** Parameters: 130 3544 jbeck ** e -- the envelope 131 3544 jbeck ** addr_st -- address (RCPT only) 132 3544 jbeck ** p -- read buffer 133 3544 jbeck ** delimptr -- current position in read buffer 134 3544 jbeck ** which -- MAIL/RCPT 135 3544 jbeck ** args -- arguments (output) 136 3544 jbeck ** esmtp_args -- function to process a single ESMTP argument 137 3544 jbeck ** 138 3544 jbeck ** Returns: 139 3544 jbeck ** none 140 3544 jbeck */ 141 3544 jbeck 142 3544 jbeck void 143 3544 jbeck parse_esmtp_args(e, addr_st, p, delimptr, which, args, esmtp_args) 144 3544 jbeck ENVELOPE *e; 145 3544 jbeck ADDRESS *addr_st; 146 3544 jbeck char *p; 147 3544 jbeck char *delimptr; 148 3544 jbeck char *which; 149 3544 jbeck char *args[]; 150 3544 jbeck esmtp_args_F esmtp_args; 151 3544 jbeck { 152 3544 jbeck int argno; 153 3544 jbeck 154 3544 jbeck argno = 0; 155 3544 jbeck if (args != NULL) 156 3544 jbeck args[argno++] = p; 157 3544 jbeck p = delimptr; 158 3544 jbeck while (p != NULL && *p != '\0') 159 3544 jbeck { 160 3544 jbeck char *kp; 161 3544 jbeck char *vp = NULL; 162 3544 jbeck char *equal = NULL; 163 3544 jbeck 164 3544 jbeck /* locate the beginning of the keyword */ 165 3544 jbeck SKIP_SPACE(p); 166 3544 jbeck if (*p == '\0') 167 3544 jbeck break; 168 3544 jbeck kp = p; 169 3544 jbeck 170 3544 jbeck /* skip to the value portion */ 171 3544 jbeck while ((isascii(*p) && isalnum(*p)) || *p == '-') 172 3544 jbeck p++; 173 3544 jbeck if (*p == '=') 174 3544 jbeck { 175 3544 jbeck equal = p; 176 3544 jbeck *p++ = '\0'; 177 3544 jbeck vp = p; 178 3544 jbeck 179 3544 jbeck /* skip to the end of the value */ 180 3544 jbeck while (*p != '\0' && *p != ' ' && 181 3544 jbeck !(isascii(*p) && iscntrl(*p)) && 182 3544 jbeck *p != '=') 183 3544 jbeck p++; 184 3544 jbeck } 185 3544 jbeck 186 3544 jbeck if (*p != '\0') 187 3544 jbeck *p++ = '\0'; 188 3544 jbeck 189 3544 jbeck if (tTd(19, 1)) 190 3544 jbeck sm_dprintf("%s: got arg %s=\"%s\"\n", which, kp, 191 3544 jbeck vp == NULL ? "<null>" : vp); 192 3544 jbeck 193 3544 jbeck esmtp_args(addr_st, kp, vp, e); 194 3544 jbeck if (equal != NULL) 195 3544 jbeck *equal = '='; 196 3544 jbeck if (args != NULL) 197 3544 jbeck args[argno] = kp; 198 3544 jbeck argno++; 199 3544 jbeck if (argno >= MAXSMTPARGS - 1) 200 3544 jbeck usrerr("501 5.5.4 Too many parameters"); 201 3544 jbeck if (Errors > 0) 202 3544 jbeck break; 203 3544 jbeck } 204 3544 jbeck if (args != NULL) 205 3544 jbeck args[argno] = NULL; 206 3544 jbeck } 207 0 stevel 208 0 stevel /* 209 0 stevel ** SMTP -- run the SMTP protocol. 210 0 stevel ** 211 0 stevel ** Parameters: 212 0 stevel ** nullserver -- if non-NULL, rejection message for 213 0 stevel ** (almost) all SMTP commands. 214 0 stevel ** d_flags -- daemon flags 215 0 stevel ** e -- the envelope. 216 0 stevel ** 217 0 stevel ** Returns: 218 0 stevel ** never. 219 0 stevel ** 220 0 stevel ** Side Effects: 221 0 stevel ** Reads commands from the input channel and processes them. 222 0 stevel */ 223 0 stevel 224 0 stevel /* 225 0 stevel ** Notice: The smtp server doesn't have a session context like the client 226 0 stevel ** side has (mci). Therefore some data (session oriented) is allocated 227 0 stevel ** or assigned to the "wrong" structure (esp. STARTTLS, AUTH). 228 0 stevel ** This should be fixed in a successor version. 229 0 stevel */ 230 0 stevel 231 0 stevel struct cmd 232 0 stevel { 233 0 stevel char *cmd_name; /* command name */ 234 0 stevel int cmd_code; /* internal code, see below */ 235 0 stevel }; 236 0 stevel 237 0 stevel /* values for cmd_code */ 238 0 stevel #define CMDERROR 0 /* bad command */ 239 0 stevel #define CMDMAIL 1 /* mail -- designate sender */ 240 0 stevel #define CMDRCPT 2 /* rcpt -- designate recipient */ 241 0 stevel #define CMDDATA 3 /* data -- send message text */ 242 0 stevel #define CMDRSET 4 /* rset -- reset state */ 243 0 stevel #define CMDVRFY 5 /* vrfy -- verify address */ 244 0 stevel #define CMDEXPN 6 /* expn -- expand address */ 245 0 stevel #define CMDNOOP 7 /* noop -- do nothing */ 246 0 stevel #define CMDQUIT 8 /* quit -- close connection and die */ 247 0 stevel #define CMDHELO 9 /* helo -- be polite */ 248 0 stevel #define CMDHELP 10 /* help -- give usage info */ 249 0 stevel #define CMDEHLO 11 /* ehlo -- extended helo (RFC 1425) */ 250 0 stevel #define CMDETRN 12 /* etrn -- flush queue */ 251 0 stevel #if SASL 252 0 stevel # define CMDAUTH 13 /* auth -- SASL authenticate */ 253 0 stevel #endif /* SASL */ 254 0 stevel #if STARTTLS 255 0 stevel # define CMDSTLS 14 /* STARTTLS -- start TLS session */ 256 0 stevel #endif /* STARTTLS */ 257 0 stevel /* non-standard commands */ 258 0 stevel #define CMDVERB 17 /* verb -- go into verbose mode */ 259 0 stevel /* unimplemented commands from RFC 821 */ 260 0 stevel #define CMDUNIMPL 19 /* unimplemented rfc821 commands */ 261 0 stevel /* use this to catch and log "door handle" attempts on your system */ 262 0 stevel #define CMDLOGBOGUS 23 /* bogus command that should be logged */ 263 0 stevel /* debugging-only commands, only enabled if SMTPDEBUG is defined */ 264 0 stevel #define CMDDBGQSHOW 24 /* showq -- show send queue */ 265 0 stevel #define CMDDBGDEBUG 25 /* debug -- set debug mode */ 266 0 stevel 267 0 stevel /* 268 0 stevel ** Note: If you change this list, remember to update 'helpfile' 269 0 stevel */ 270 0 stevel 271 0 stevel static struct cmd CmdTab[] = 272 0 stevel { 273 0 stevel { "mail", CMDMAIL }, 274 0 stevel { "rcpt", CMDRCPT }, 275 0 stevel { "data", CMDDATA }, 276 0 stevel { "rset", CMDRSET }, 277 0 stevel { "vrfy", CMDVRFY }, 278 0 stevel { "expn", CMDEXPN }, 279 0 stevel { "help", CMDHELP }, 280 0 stevel { "noop", CMDNOOP }, 281 0 stevel { "quit", CMDQUIT }, 282 0 stevel { "helo", CMDHELO }, 283 0 stevel { "ehlo", CMDEHLO }, 284 0 stevel { "etrn", CMDETRN }, 285 0 stevel { "verb", CMDVERB }, 286 0 stevel { "send", CMDUNIMPL }, 287 0 stevel { "saml", CMDUNIMPL }, 288 0 stevel { "soml", CMDUNIMPL }, 289 0 stevel { "turn", CMDUNIMPL }, 290 0 stevel #if SASL 291 0 stevel { "auth", CMDAUTH, }, 292 0 stevel #endif /* SASL */ 293 0 stevel #if STARTTLS 294 0 stevel { "starttls", CMDSTLS, }, 295 0 stevel #endif /* STARTTLS */ 296 0 stevel /* remaining commands are here only to trap and log attempts to use them */ 297 0 stevel { "showq", CMDDBGQSHOW }, 298 0 stevel { "debug", CMDDBGDEBUG }, 299 0 stevel { "wiz", CMDLOGBOGUS }, 300 0 stevel 301 0 stevel { NULL, CMDERROR } 302 0 stevel }; 303 0 stevel 304 0 stevel static char *CurSmtpClient; /* who's at the other end of channel */ 305 0 stevel 306 0 stevel #ifndef MAXBADCOMMANDS 307 0 stevel # define MAXBADCOMMANDS 25 /* maximum number of bad commands */ 308 0 stevel #endif /* ! MAXBADCOMMANDS */ 309 0 stevel #ifndef MAXHELOCOMMANDS 310 0 stevel # define MAXHELOCOMMANDS 3 /* max HELO/EHLO commands before slowdown */ 311 0 stevel #endif /* ! MAXHELOCOMMANDS */ 312 0 stevel #ifndef MAXVRFYCOMMANDS 313 0 stevel # define MAXVRFYCOMMANDS 6 /* max VRFY/EXPN commands before slowdown */ 314 0 stevel #endif /* ! MAXVRFYCOMMANDS */ 315 0 stevel #ifndef MAXETRNCOMMANDS 316 0 stevel # define MAXETRNCOMMANDS 8 /* max ETRN commands before slowdown */ 317 0 stevel #endif /* ! MAXETRNCOMMANDS */ 318 0 stevel #ifndef MAXTIMEOUT 319 0 stevel # define MAXTIMEOUT (4 * 60) /* max timeout for bad commands */ 320 0 stevel #endif /* ! MAXTIMEOUT */ 321 0 stevel 322 0 stevel /* 323 0 stevel ** Maximum shift value to compute timeout for bad commands. 324 0 stevel ** This introduces an upper limit of 2^MAXSHIFT for the timeout. 325 0 stevel */ 326 0 stevel 327 0 stevel #ifndef MAXSHIFT 328 0 stevel # define MAXSHIFT 8 329 0 stevel #endif /* ! MAXSHIFT */ 330 0 stevel #if MAXSHIFT > 31 331 0 stevel ERROR _MAXSHIFT > 31 is invalid 332 0 stevel #endif /* MAXSHIFT */ 333 0 stevel 334 0 stevel 335 0 stevel #if MAXBADCOMMANDS > 0 336 0 stevel # define STOP_IF_ATTACK(r) do \ 337 0 stevel { \ 338 0 stevel if ((r) == STOP_ATTACK) \ 339 0 stevel goto stopattack; \ 340 0 stevel } while (0) 341 0 stevel 342 0 stevel #else /* MAXBADCOMMANDS > 0 */ 343 0 stevel # define STOP_IF_ATTACK(r) r 344 0 stevel #endif /* MAXBADCOMMANDS > 0 */ 345 0 stevel 346 0 stevel 347 0 stevel #if SM_HEAP_CHECK 348 0 stevel static SM_DEBUG_T DebugLeakSmtp = SM_DEBUG_INITIALIZER("leak_smtp", 349 0 stevel "@(#)$Debug: leak_smtp - trace memory leaks during SMTP processing $"); 350 0 stevel #endif /* SM_HEAP_CHECK */ 351 0 stevel 352 0 stevel typedef struct 353 0 stevel { 354 5402 jbeck bool sm_gotmail; /* mail command received */ 355 5402 jbeck unsigned int sm_nrcpts; /* number of successful RCPT commands */ 356 5402 jbeck bool sm_discard; 357 5402 jbeck #if MILTER 358 5402 jbeck bool sm_milterize; 359 5402 jbeck bool sm_milterlist; /* any filters in the list? */ 360 5402 jbeck milters_T sm_milters; 361 5402 jbeck 362 5402 jbeck /* e_nrcpts from envelope before recipient() call */ 363 5402 jbeck unsigned int sm_e_nrcpts_orig; 364 5402 jbeck #endif /* MILTER */ 365 5402 jbeck char *sm_quarmsg; /* carry quarantining across messages */ 366 0 stevel } SMTP_T; 367 0 stevel 368 0 stevel static bool smtp_data __P((SMTP_T *, ENVELOPE *)); 369 0 stevel 370 0 stevel #define MSG_TEMPFAIL "451 4.3.2 Please try again later" 371 0 stevel 372 0 stevel #if MILTER 373 0 stevel # define MILTER_ABORT(e) milter_abort((e)) 374 0 stevel 375 0 stevel # define MILTER_REPLY(str) \ 376 0 stevel { \ 377 0 stevel int savelogusrerrs = LogUsrErrs; \ 378 0 stevel \ 379 3966 jbeck milter_cmd_fail = true; \ 380 0 stevel switch (state) \ 381 0 stevel { \ 382 1658 jbeck case SMFIR_SHUTDOWN: \ 383 1658 jbeck if (MilterLogLevel > 3) \ 384 1658 jbeck { \ 385 1658 jbeck sm_syslog(LOG_INFO, e->e_id, \ 386 1658 jbeck "Milter: %s=%s, reject=421, errormode=4", \ 387 1658 jbeck str, addr); \ 388 1658 jbeck LogUsrErrs = false; \ 389 1658 jbeck } \ 390 1658 jbeck { \ 391 1658 jbeck bool tsave = QuickAbort; \ 392 1658 jbeck \ 393 1658 jbeck QuickAbort = false; \ 394 1658 jbeck usrerr("421 4.3.0 closing connection"); \ 395 1658 jbeck QuickAbort = tsave; \ 396 1658 jbeck e->e_sendqueue = NULL; \ 397 1658 jbeck goto doquit; \ 398 1658 jbeck } \ 399 1658 jbeck break; \ 400 0 stevel case SMFIR_REPLYCODE: \ 401 0 stevel if (MilterLogLevel > 3) \ 402 0 stevel { \ 403 0 stevel sm_syslog(LOG_INFO, e->e_id, \ 404 0 stevel "Milter: %s=%s, reject=%s", \ 405 0 stevel str, addr, response); \ 406 0 stevel LogUsrErrs = false; \ 407 0 stevel } \ 408 616 jbeck if (strncmp(response, "421 ", 4) == 0 \ 409 616 jbeck || strncmp(response, "421-", 4) == 0) \ 410 0 stevel { \ 411 0 stevel bool tsave = QuickAbort; \ 412 0 stevel \ 413 0 stevel QuickAbort = false; \ 414 0 stevel usrerr(response); \ 415 0 stevel QuickAbort = tsave; \ 416 0 stevel e->e_sendqueue = NULL; \ 417 0 stevel goto doquit; \ 418 0 stevel } \ 419 0 stevel else \ 420 0 stevel usrerr(response); \ 421 0 stevel break; \ 422 0 stevel \ 423 0 stevel case SMFIR_REJECT: \ 424 0 stevel if (MilterLogLevel > 3) \ 425 0 stevel { \ 426 0 stevel sm_syslog(LOG_INFO, e->e_id, \ 427 0 stevel "Milter: %s=%s, reject=550 5.7.1 Command rejected", \ 428 0 stevel str, addr); \ 429 0 stevel LogUsrErrs = false; \ 430 0 stevel } \ 431 0 stevel usrerr("550 5.7.1 Command rejected"); \ 432 0 stevel break; \ 433 0 stevel \ 434 0 stevel case SMFIR_DISCARD: \ 435 0 stevel if (MilterLogLevel > 3) \ 436 0 stevel sm_syslog(LOG_INFO, e->e_id, \ 437 0 stevel "Milter: %s=%s, discard", \ 438 0 stevel str, addr); \ 439 0 stevel e->e_flags |= EF_DISCARD; \ 440 3966 jbeck milter_cmd_fail = false; \ 441 0 stevel break; \ 442 0 stevel \ 443 0 stevel case SMFIR_TEMPFAIL: \ 444 0 stevel if (MilterLogLevel > 3) \ 445 0 stevel { \ 446 0 stevel sm_syslog(LOG_INFO, e->e_id, \ 447 0 stevel "Milter: %s=%s, reject=%s", \ 448 0 stevel str, addr, MSG_TEMPFAIL); \ 449 0 stevel LogUsrErrs = false; \ 450 0 stevel } \ 451 0 stevel usrerr(MSG_TEMPFAIL); \ 452 3966 jbeck break; \ 453 3966 jbeck default: \ 454 3966 jbeck milter_cmd_fail = false; \ 455 0 stevel break; \ 456 0 stevel } \ 457 0 stevel LogUsrErrs = savelogusrerrs; \ 458 0 stevel if (response != NULL) \ 459 0 stevel sm_free(response); /* XXX */ \ 460 0 stevel } 461 0 stevel 462 0 stevel #else /* MILTER */ 463 0 stevel # define MILTER_ABORT(e) 464 0 stevel #endif /* MILTER */ 465 0 stevel 466 0 stevel /* clear all SMTP state (for HELO/EHLO/RSET) */ 467 0 stevel #define CLEAR_STATE(cmd) \ 468 0 stevel do \ 469 0 stevel { \ 470 0 stevel /* abort milter filters */ \ 471 0 stevel MILTER_ABORT(e); \ 472 0 stevel \ 473 0 stevel if (smtp.sm_nrcpts > 0) \ 474 0 stevel { \ 475 0 stevel logundelrcpts(e, cmd, 10, false); \ 476 0 stevel smtp.sm_nrcpts = 0; \ 477 0 stevel macdefine(&e->e_macro, A_PERM, \ 478 0 stevel macid("{nrcpts}"), "0"); \ 479 0 stevel } \ 480 0 stevel \ 481 0 stevel e->e_sendqueue = NULL; \ 482 0 stevel e->e_flags |= EF_CLRQUEUE; \ 483 0 stevel \ 484 0 stevel if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags)) \ 485 0 stevel logsender(e, NULL); \ 486 0 stevel e->e_flags &= ~EF_LOGSENDER; \ 487 0 stevel \ 488 0 stevel /* clean up a bit */ \ 489 0 stevel smtp.sm_gotmail = false; \ 490 0 stevel SuprErrs = true; \ 491 0 stevel dropenvelope(e, true, false); \ 492 0 stevel sm_rpool_free(e->e_rpool); \ 493 0 stevel e = newenvelope(e, CurEnv, sm_rpool_new_x(NULL)); \ 494 0 stevel CurEnv = e; \ 495 3544 jbeck e->e_features = features; \ 496 0 stevel \ 497 0 stevel /* put back discard bit */ \ 498 0 stevel if (smtp.sm_discard) \ 499 0 stevel e->e_flags |= EF_DISCARD; \ 500 0 stevel \ 501 0 stevel /* restore connection quarantining */ \ 502 0 stevel if (smtp.sm_quarmsg == NULL) \ 503 0 stevel { \ 504 0 stevel e->e_quarmsg = NULL; \ 505 0 stevel macdefine(&e->e_macro, A_PERM, \ 506 0 stevel macid("{quarantine}"), ""); \ 507 0 stevel } \ 508 0 stevel else \ 509 0 stevel { \ 510 0 stevel e->e_quarmsg = sm_rpool_strdup_x(e->e_rpool, \ 511 0 stevel smtp.sm_quarmsg); \ 512 0 stevel macdefine(&e->e_macro, A_PERM, macid("{quarantine}"), \ 513 0 stevel e->e_quarmsg); \ 514 0 stevel } \ 515 0 stevel } while (0) 516 0 stevel 517 0 stevel /* sleep to flatten out connection load */ 518 0 stevel #define MIN_DELAY_LOG 15 /* wait before logging this again */ 519 0 stevel 520 0 stevel /* is it worth setting the process title for 1s? */ 521 0 stevel #define DELAY_CONN(cmd) \ 522 0 stevel if (DelayLA > 0 && (CurrentLA = getla()) >= DelayLA) \ 523 0 stevel { \ 524 0 stevel time_t dnow; \ 525 0 stevel \ 526 0 stevel sm_setproctitle(true, e, \ 527 0 stevel "%s: %s: delaying %s: load average: %d", \ 528 0 stevel qid_printname(e), CurSmtpClient, \ 529 0 stevel cmd, DelayLA); \ 530 0 stevel if (LogLevel > 8 && (dnow = curtime()) > log_delay) \ 531 0 stevel { \ 532 0 stevel sm_syslog(LOG_INFO, e->e_id, \ 533 0 stevel "delaying=%s, load average=%d >= %d", \ 534 0 stevel cmd, CurrentLA, DelayLA); \ 535 0 stevel log_delay = dnow + MIN_DELAY_LOG; \ 536 0 stevel } \ 537 0 stevel (void) sleep(1); \ 538 0 stevel sm_setproctitle(true, e, "%s %s: %.80s", \ 539 0 stevel qid_printname(e), CurSmtpClient, inp); \ 540 0 stevel } 541 0 stevel 542 3544 jbeck static bool SevenBitInput_Saved; /* saved version of SevenBitInput */ 543 0 stevel 544 0 stevel void 545 0 stevel smtp(nullserver, d_flags, e) 546 0 stevel char *volatile nullserver; 547 0 stevel BITMAP256 d_flags; 548 0 stevel register ENVELOPE *volatile e; 549 0 stevel { 550 0 stevel register char *volatile p; 551 0 stevel register struct cmd *volatile c = NULL; 552 0 stevel char *cmd; 553 0 stevel auto ADDRESS *vrfyqueue; 554 0 stevel ADDRESS *a; 555 0 stevel volatile bool gothello; /* helo command received */ 556 0 stevel bool vrfy; /* set if this is a vrfy command */ 557 0 stevel char *volatile protocol; /* sending protocol */ 558 0 stevel char *volatile sendinghost; /* sending hostname */ 559 0 stevel char *volatile peerhostname; /* name of SMTP peer or "localhost" */ 560 0 stevel auto char *delimptr; 561 0 stevel char *id; 562 0 stevel volatile unsigned int n_badcmds = 0; /* count of bad commands */ 563 0 stevel volatile unsigned int n_badrcpts = 0; /* number of rejected RCPT */ 564 0 stevel volatile unsigned int n_verifies = 0; /* count of VRFY/EXPN */ 565 0 stevel volatile unsigned int n_etrn = 0; /* count of ETRN */ 566 0 stevel volatile unsigned int n_noop = 0; /* count of NOOP/VERB/etc */ 567 0 stevel volatile unsigned int n_helo = 0; /* count of HELO/EHLO */ 568 0 stevel bool ok; 569 0 stevel volatile bool first; 570 0 stevel volatile bool tempfail = false; 571 0 stevel volatile time_t wt; /* timeout after too many commands */ 572 0 stevel volatile time_t previous; /* time after checksmtpattack() */ 573 0 stevel volatile bool lognullconnection = true; 574 0 stevel register char *q; 575 0 stevel SMTP_T smtp; 576 0 stevel char *addr; 577 0 stevel char *greetcode = "220"; 578 0 stevel char *hostname; /* my hostname ($j) */ 579 0 stevel QUEUE_CHAR *new; 580 0 stevel char *args[MAXSMTPARGS]; 581 3544 jbeck char inp[MAXINPLINE]; 582 3544 jbeck #if MAXINPLINE < MAXLINE 583 3544 jbeck ERROR _MAXINPLINE must NOT be less than _MAXLINE: MAXINPLINE < MAXLINE 584 3544 jbeck #endif /* MAXINPLINE < MAXLINE */ 585 0 stevel char cmdbuf[MAXLINE]; 586 0 stevel #if SASL 587 0 stevel sasl_conn_t *conn; 588 0 stevel volatile bool sasl_ok; 589 0 stevel volatile unsigned int n_auth = 0; /* count of AUTH commands */ 590 0 stevel bool ismore; 591 0 stevel int result; 592 0 stevel volatile int authenticating; 593 0 stevel char *user; 594 0 stevel char *in, *out2; 595 0 stevel # if SASL >= 20000 596 3544 jbeck char *auth_id = NULL; 597 0 stevel const char *out; 598 0 stevel sasl_ssf_t ext_ssf; 599 0 stevel char localip[60], remoteip[60]; 600 0 stevel # else /* SASL >= 20000 */ 601 0 stevel char *out; 602 0 stevel const char *errstr; 603 0 stevel sasl_external_properties_t ext_ssf; 604 0 stevel struct sockaddr_in saddr_l; 605 0 stevel struct sockaddr_in saddr_r; 606 0 stevel # endif /* SASL >= 20000 */ 607 0 stevel sasl_security_properties_t ssp; 608 0 stevel sasl_ssf_t *ssf; 609 0 stevel unsigned int inlen, out2len; 610 0 stevel unsigned int outlen; 611 0 stevel char *volatile auth_type; 612 0 stevel char *mechlist; 613 0 stevel volatile unsigned int n_mechs; 614 0 stevel unsigned int len; 615 3544 jbeck #else /* SASL */ 616 0 stevel #endif /* SASL */ 617 0 stevel int r; 618 0 stevel #if STARTTLS 619 0 stevel int rfd, wfd; 620 0 stevel volatile bool tls_active = false; 621 0 stevel volatile bool smtps = bitnset(D_SMTPS, d_flags); 622 0 stevel bool saveQuickAbort; 623 0 stevel bool saveSuprErrs; 624 0 stevel time_t tlsstart; 625 0 stevel #endif /* STARTTLS */ 626 0 stevel volatile unsigned int features; 627 0 stevel #if PIPELINING 628 0 stevel # if _FFR_NO_PIPE 629 0 stevel int np_log = 0; 630 0 stevel # endif /* _FFR_NO_PIPE */ 631 0 stevel #endif /* PIPELINING */ 632 0 stevel volatile time_t log_delay = (time_t) 0; 633 3544 jbeck #if MILTER 634 3544 jbeck volatile bool milter_cmd_done, milter_cmd_safe; 635 3966 jbeck volatile bool milter_rcpt_added, milter_cmd_fail; 636 3544 jbeck ADDRESS addr_st; 637 3544 jbeck # define p_addr_st &addr_st 638 3544 jbeck #else /* MILTER */ 639 3544 jbeck # define p_addr_st NULL 640 3544 jbeck #endif /* MILTER */ 641 3544 jbeck size_t inplen; 642 6562 jbeck #if _FFR_BADRCPT_SHUTDOWN 643 6562 jbeck int n_badrcpts_adj; 644 6562 jbeck #endif /* _FFR_BADRCPT_SHUTDOWN */ 645 3544 jbeck 646 3544 jbeck SevenBitInput_Saved = SevenBitInput; 647 0 stevel smtp.sm_nrcpts = 0; 648 0 stevel #if MILTER 649 0 stevel smtp.sm_milterize = (nullserver == NULL); 650 0 stevel smtp.sm_milterlist = false; 651 3544 jbeck addr = NULL; 652 0 stevel #endif /* MILTER */ 653 0 stevel 654 0 stevel /* setup I/O fd correctly for the SMTP server */ 655 0 stevel setup_smtpd_io(); 656 0 stevel 657 0 stevel #if SM_HEAP_CHECK 658 0 stevel if (sm_debug_active(&DebugLeakSmtp, 1)) 659 0 stevel { 660 0 stevel sm_heap_newgroup(); 661 0 stevel sm_dprintf("smtp() heap group #%d\n", sm_heap_group()); 662 0 stevel } 663 0 stevel #endif /* SM_HEAP_CHECK */ 664 0 stevel 665 0 stevel /* XXX the rpool should be set when e is initialized in main() */ 666 0 stevel e->e_rpool = sm_rpool_new_x(NULL); 667 0 stevel e->e_macro.mac_rpool = e->e_rpool; 668 0 stevel 669 0 stevel settime(e); 670 0 stevel sm_getla(); 671 0 stevel peerhostname = RealHostName; 672 0 stevel if (peerhostname == NULL) 673 0 stevel peerhostname = "localhost"; 674 0 stevel CurHostName = peerhostname; 675 0 stevel CurSmtpClient = macvalue('_', e); 676 0 stevel if (CurSmtpClient == NULL) 677 0 stevel CurSmtpClient = CurHostName; 678 0 stevel 679 0 stevel /* check_relay may have set discard bit, save for later */ 680 0 stevel smtp.sm_discard = bitset(EF_DISCARD, e->e_flags); 681 0 stevel 682 0 stevel #if PIPELINING 683 0 stevel /* auto-flush output when reading input */ 684 0 stevel (void) sm_io_autoflush(InChannel, OutChannel); 685 0 stevel #endif /* PIPELINING */ 686 0 stevel 687 0 stevel sm_setproctitle(true, e, "server %s startup", CurSmtpClient); 688 0 stevel 689 0 stevel /* Set default features for server. */ 690 0 stevel features = ((bitset(PRIV_NOETRN, PrivacyFlags) || 691 0 stevel bitnset(D_NOETRN, d_flags)) ? SRV_NONE : SRV_OFFER_ETRN) 692 0 stevel | (bitnset(D_AUTHREQ, d_flags) ? SRV_REQ_AUTH : SRV_NONE) 693 0 stevel | (bitset(PRIV_NOEXPN, PrivacyFlags) ? SRV_NONE 694 0 stevel : (SRV_OFFER_EXPN 695 0 stevel | (bitset(PRIV_NOVERB, PrivacyFlags) 696 0 stevel ? SRV_NONE : SRV_OFFER_VERB))) 697 2197 jbeck | ((bitset(PRIV_NORECEIPTS, PrivacyFlags) || !SendMIMEErrors) 698 2197 jbeck ? SRV_NONE : SRV_OFFER_DSN) 699 0 stevel #if SASL 700 0 stevel | (bitnset(D_NOAUTH, d_flags) ? SRV_NONE : SRV_OFFER_AUTH) 701 0 stevel | (bitset(SASL_SEC_NOPLAINTEXT, SASLOpts) ? SRV_REQ_SEC 702 0 stevel : SRV_NONE) 703 0 stevel #endif /* SASL */ 704 0 stevel #if PIPELINING 705 0 stevel | SRV_OFFER_PIPE 706 0 stevel #endif /* PIPELINING */ 707 0 stevel #if STARTTLS 708 0 stevel | (bitnset(D_NOTLS, d_flags) ? SRV_NONE : SRV_OFFER_TLS) 709 0 stevel | (bitset(TLS_I_NO_VRFY, TLS_Srv_Opts) ? SRV_NONE 710 0 stevel : SRV_VRFY_CLT) 711 0 stevel #endif /* STARTTLS */ 712 0 stevel ; 713 0 stevel if (nullserver == NULL) 714 0 stevel { 715 0 stevel features = srvfeatures(e, CurSmtpClient, features); 716 0 stevel if (bitset(SRV_TMP_FAIL, features)) 717 0 stevel { 718 0 stevel if (LogLevel > 4) 719 0 stevel sm_syslog(LOG_ERR, NOQID, 720 0 stevel "ERROR: srv_features=tempfail, relay=%.100s, access temporarily disabled", 721 0 stevel CurSmtpClient); 722 0 stevel nullserver = "450 4.3.0 Please try again later."; 723 0 stevel } 724 0 stevel else 725 0 stevel { 726 0 stevel #if PIPELINING 727 0 stevel # if _FFR_NO_PIPE 728 0 stevel if (bitset(SRV_NO_PIPE, features)) 729 0 stevel { 730 0 stevel /* for consistency */ 731 0 stevel features &= ~SRV_OFFER_PIPE; 732 0 stevel } 733 0 stevel # endif /* _FFR_NO_PIPE */ 734 0 stevel #endif /* PIPELINING */ 735 0 stevel #if SASL 736 0 stevel if (bitset(SRV_REQ_SEC, features)) 737 0 stevel SASLOpts |= SASL_SEC_NOPLAINTEXT; 738 0 stevel else 739 0 stevel SASLOpts &= ~SASL_SEC_NOPLAINTEXT; 740 0 stevel #endif /* SASL */ 741 0 stevel } 742 0 stevel } 743 0 stevel else if (strncmp(nullserver, "421 ", 4) == 0) 744 0 stevel { 745 0 stevel message(nullserver); 746 0 stevel goto doquit; 747 0 stevel } 748 0 stevel 749 3544 jbeck e->e_features = features; 750 0 stevel hostname = macvalue('j', e); 751 0 stevel #if SASL 752 0 stevel if (AuthRealm == NULL) 753 0 stevel AuthRealm = hostname; 754 0 stevel sasl_ok = bitset(SRV_OFFER_AUTH, features); 755 0 stevel n_mechs = 0; 756 0 stevel authenticating = SASL_NOT_AUTH; 757 0 stevel 758 0 stevel /* SASL server new connection */ 759 0 stevel if (sasl_ok) 760 0 stevel { 761 0 stevel # if SASL >= 20000 762 0 stevel result = sasl_server_new("smtp", AuthRealm, NULL, NULL, NULL, 763 0 stevel NULL, 0, &conn); 764 0 stevel # elif SASL > 10505 765 0 stevel /* use empty realm: only works in SASL > 1.5.5 */ 766 0 stevel result = sasl_server_new("smtp", AuthRealm, "", NULL, 0, &conn); 767 0 stevel # else /* SASL >= 20000 */ 768 0 stevel /* use no realm -> realm is set to hostname by SASL lib */ 769 0 stevel result = sasl_server_new("smtp", AuthRealm, NULL, NULL, 0, 770 0 stevel &conn); 771 0 stevel # endif /* SASL >= 20000 */ 772 0 stevel sasl_ok = result == SASL_OK; 773 0 stevel if (!sasl_ok) 774 0 stevel { 775 0 stevel if (LogLevel > 9) 776 0 stevel sm_syslog(LOG_WARNING, NOQID, 777 0 stevel "AUTH error: sasl_server_new failed=%d", 778 0 stevel result); 779 0 stevel } 780 0 stevel } 781 0 stevel if (sasl_ok) 782 0 stevel { 783 0 stevel /* 784 0 stevel ** SASL set properties for sasl 785 0 stevel ** set local/remote IP 786 0 stevel ** XXX Cyrus SASL v1 only supports IPv4 787 0 stevel ** 788 0 stevel ** XXX where exactly are these used/required? 789 0 stevel ** Kerberos_v4 790 0 stevel */ 791 0 stevel 792 0 stevel # if SASL >= 20000 793 0 stevel localip[0] = remoteip[0] = '\0'; 794 0 stevel # if NETINET || NETINET6 795 0 stevel in = macvalue(macid("{daemon_family}"), e); 796 0 stevel if (in != NULL && ( 797 0 stevel # if NETINET6 798 0 stevel strcmp(in, "inet6") == 0 || 799 0 stevel # endif /* NETINET6 */ 800 0 stevel strcmp(in, "inet") == 0)) 801 0 stevel { 802 0 stevel SOCKADDR_LEN_T addrsize; 803 0 stevel SOCKADDR saddr_l; 804 0 stevel SOCKADDR saddr_r; 805 0 stevel 806 0 stevel addrsize = sizeof(saddr_r); 807 0 stevel if (getpeername(sm_io_getinfo(InChannel, SM_IO_WHAT_FD, 808 0 stevel NULL), 809 0 stevel (struct sockaddr *) &saddr_r, 810 0 stevel &addrsize) == 0) 811 0 stevel { 812 0 stevel if (iptostring(&saddr_r, addrsize, 813 3544 jbeck remoteip, sizeof(remoteip))) 814 0 stevel { 815 0 stevel sasl_setprop(conn, SASL_IPREMOTEPORT, 816 0 stevel remoteip); 817 0 stevel } 818 0 stevel addrsize = sizeof(saddr_l); 819 0 stevel if (getsockname(sm_io_getinfo(InChannel, 820 0 stevel SM_IO_WHAT_FD, 821 0 stevel NULL), 822 0 stevel (struct sockaddr *) &saddr_l, 823 0 stevel &addrsize) == 0) 824 0 stevel { 825 0 stevel if (iptostring(&saddr_l, addrsize, 826 0 stevel localip, 827 3544 jbeck sizeof(localip))) 828 0 stevel { 829 0 stevel sasl_setprop(conn, 830 0 stevel SASL_IPLOCALPORT, 831 0 stevel localip); 832 0 stevel } 833 0 stevel } 834 0 stevel } 835 0 stevel } 836 0 stevel # endif /* NETINET || NETINET6 */ 837 0 stevel # else /* SASL >= 20000 */ 838 0 stevel # if NETINET 839 0 stevel in = macvalue(macid("{daemon_family}"), e); 840 0 stevel if (in != NULL && strcmp(in, "inet") == 0) 841 0 stevel { 842 0 stevel SOCKADDR_LEN_T addrsize; 843 0 stevel 844 0 stevel addrsize = sizeof(struct sockaddr_in); 845 0 stevel if (getpeername(sm_io_getinfo(InChannel, SM_IO_WHAT_FD, 846 0 stevel NULL), 847 0 stevel (struct sockaddr *)&saddr_r, 848 0 stevel &addrsize) == 0) 849 0 stevel { 850 0 stevel sasl_setprop(conn, SASL_IP_REMOTE, &saddr_r); 851 0 stevel addrsize = sizeof(struct sockaddr_in); 852 0 stevel if (getsockname(sm_io_getinfo(InChannel, 853 0 stevel SM_IO_WHAT_FD, 854 0 stevel NULL), 855 0 stevel (struct sockaddr *)&saddr_l, 856 0 stevel &addrsize) == 0) 857 0 stevel sasl_setprop(conn, SASL_IP_LOCAL, 858 0 stevel &saddr_l); 859 0 stevel } 860 0 stevel } 861 0 stevel # endif /* NETINET */ 862 0 stevel # endif /* SASL >= 20000 */ 863 0 stevel 864 0 stevel auth_type = NULL; 865 0 stevel mechlist = NULL; 866 0 stevel user = NULL; 867 0 stevel # if 0 868 0 stevel macdefine(&BlankEnvelope.e_macro, A_PERM, 869 0 stevel macid("{auth_author}"), NULL); 870 0 stevel # endif /* 0 */ 871 0 stevel 872 0 stevel /* set properties */ 873 3544 jbeck (void) memset(&ssp, '\0', sizeof(ssp)); 874 0 stevel 875 0 stevel /* XXX should these be options settable via .cf ? */ 876 0 stevel /* ssp.min_ssf = 0; is default due to memset() */ 877 0 stevel { 878 0 stevel ssp.max_ssf = MaxSLBits; 879 0 stevel ssp.maxbufsize = MAXOUTLEN; 880 0 stevel } 881 0 stevel ssp.security_flags = SASLOpts & SASL_SEC_MASK; 882 0 stevel sasl_ok = sasl_setprop(conn, SASL_SEC_PROPS, &ssp) == SASL_OK; 883 0 stevel 884 0 stevel if (sasl_ok) 885 0 stevel { 886 0 stevel /* 887 0 stevel ** external security strength factor; 888 0 stevel ** currently we have none so zero 889 0 stevel */ 890 0 stevel 891 0 stevel # if SASL >= 20000 892 0 stevel ext_ssf = 0; 893 0 stevel auth_id = NULL; 894 0 stevel sasl_ok = ((sasl_setprop(conn, SASL_SSF_EXTERNAL, 895 0 stevel &ext_ssf) == SASL_OK) && 896 0 stevel (sasl_setprop(conn, SASL_AUTH_EXTERNAL, 897 0 stevel auth_id) == SASL_OK)); 898 0 stevel # else /* SASL >= 20000 */ 899 0 stevel ext_ssf.ssf = 0; 900 0 stevel ext_ssf.auth_id = NULL; 901 0 stevel sasl_ok = sasl_setprop(conn, SASL_SSF_EXTERNAL, 902 0 stevel &ext_ssf) == SASL_OK; 903 0 stevel # endif /* SASL >= 20000 */ 904 0 stevel } 905 0 stevel if (sasl_ok) 906 0 stevel n_mechs = saslmechs(conn, &mechlist); 907 0 stevel } 908 0 stevel #endif /* SASL */ 909 0 stevel 910 0 stevel #if STARTTLS 911 6562 jbeck 912 6562 jbeck set_tls_rd_tmo(TimeOuts.to_nextcommand); 913 0 stevel #endif /* STARTTLS */ 914 0 stevel 915 0 stevel #if MILTER 916 0 stevel if (smtp.sm_milterize) 917 0 stevel { 918 0 stevel char state; 919 0 stevel 920 0 stevel /* initialize mail filter connection */ 921 5402 jbeck smtp.sm_milterlist = milter_init(e, &state, &smtp.sm_milters); 922 0 stevel switch (state) 923 0 stevel { 924 0 stevel case SMFIR_REJECT: 925 0 stevel if (MilterLogLevel > 3) 926 0 stevel sm_syslog(LOG_INFO, e->e_id, 927 0 stevel "Milter: initialization failed, rejecting commands"); 928 0 stevel greetcode = "554"; 929 0 stevel nullserver = "Command rejected"; 930 0 stevel smtp.sm_milterize = false; 931 0 stevel break; 932 0 stevel 933 0 stevel case SMFIR_TEMPFAIL: 934 0 stevel if (MilterLogLevel > 3) 935 0 stevel sm_syslog(LOG_INFO, e->e_id, 936 0 stevel "Milter: initialization failed, temp failing commands"); 937 0 stevel tempfail = true; 938 0 stevel smtp.sm_milterize = false; 939 0 stevel break; 940 1658 jbeck 941 1658 jbeck case SMFIR_SHUTDOWN: 942 1658 jbeck if (MilterLogLevel > 3) 943 1658 jbeck sm_syslog(LOG_INFO, e->e_id, 944 1658 jbeck "Milter: initialization failed, closing connection"); 945 1658 jbeck tempfail = true; 946 1658 jbeck smtp.sm_milterize = false; 947 1658 jbeck message("421 4.7.0 %s closing connection", 948 1658 jbeck MyHostName); 949 1658 jbeck 950 1658 jbeck /* arrange to ignore send list */ 951 1658 jbeck e->e_sendqueue = NULL; 952 6562 jbeck lognullconnection = false; 953 1658 jbeck goto doquit; 954 0 stevel } 955 0 stevel } 956 0 stevel 957 0 stevel if (smtp.sm_milterlist && smtp.sm_milterize && 958 0 stevel !bitset(EF_DISCARD, e->e_flags)) 959 0 stevel { 960 0 stevel char state; 961 0 stevel char *response; 962 0 stevel 963 2526 jbeck q = macvalue(macid("{client_name}"), e); 964 3544 jbeck SM_ASSERT(q != NULL || OpMode == MD_SMTP); 965 3544 jbeck if (q == NULL) 966 3544 jbeck q = "localhost"; 967 2526 jbeck response = milter_connect(q, RealHostAddr, e, &state); 968 0 stevel switch (state) 969 0 stevel { 970 0 stevel case SMFIR_REPLYCODE: /* REPLYCODE shouldn't happen */ 971 0 stevel case SMFIR_REJECT: 972 0 stevel if (MilterLogLevel > 3) 973 0 stevel sm_syslog(LOG_INFO, e->e_id, 974 0 stevel "Milter: connect: host=%s, addr=%s, rejecting commands", 975 0 stevel peerhostname, 976 0 stevel anynet_ntoa(&RealHostAddr)); 977 0 stevel greetcode = "554"; 978 0 stevel nullserver = "Command rejected"; 979 0 stevel smtp.sm_milterize = false; 980 0 stevel break; 981 0 stevel 982 0 stevel case SMFIR_TEMPFAIL: 983 0 stevel if (MilterLogLevel > 3) 984 0 stevel sm_syslog(LOG_INFO, e->e_id, 985 0 stevel "Milter: connect: host=%s, addr=%s, temp failing commands", 986 0 stevel peerhostname, 987 0 stevel anynet_ntoa(&RealHostAddr)); 988 0 stevel tempfail = true; 989 0 stevel smtp.sm_milterize = false; 990 0 stevel break; 991 0 stevel 992 0 stevel case SMFIR_SHUTDOWN: 993 0 stevel if (MilterLogLevel > 3) 994 0 stevel sm_syslog(LOG_INFO, e->e_id, 995 0 stevel "Milter: connect: host=%s, addr=%s, shutdown", 996 0 stevel peerhostname, 997 0 stevel anynet_ntoa(&RealHostAddr)); 998 0 stevel tempfail = true; 999 0 stevel smtp.sm_milterize = false; 1000 0 stevel message("421 4.7.0 %s closing connection", 1001 0 stevel MyHostName); 1002 0 stevel 1003 0 stevel /* arrange to ignore send list */ 1004 0 stevel e->e_sendqueue = NULL; 1005 0 stevel goto doquit; 1006 0 stevel } 1007 0 stevel if (response != NULL) 1008 0 stevel sm_free(response); /* XXX */ 1009 0 stevel } 1010 0 stevel #endif /* MILTER */ 1011 0 stevel 1012 0 stevel /* 1013 0 stevel ** Broken proxies and SMTP slammers 1014 0 stevel ** push data without waiting, catch them 1015 0 stevel */ 1016 0 stevel 1017 0 stevel if ( 1018 0 stevel #if STARTTLS 1019 0 stevel !smtps && 1020 0 stevel #endif /* STARTTLS */ 1021 3544 jbeck *greetcode == '2' && nullserver == NULL) 1022 0 stevel { 1023 0 stevel time_t msecs = 0; 1024 0 stevel char **pvp; 1025 0 stevel char pvpbuf[PSBUFSIZE]; 1026 0 stevel 1027 0 stevel /* Ask the rulesets how long to pause */ 1028 0 stevel pvp = NULL; 1029 0 stevel r = rscap("greet_pause", peerhostname, 1030 0 stevel anynet_ntoa(&RealHostAddr), e, 1031 0 stevel &pvp, pvpbuf, sizeof(pvpbuf)); 1032 0 stevel if (r == EX_OK && pvp != NULL && pvp[0] != NULL && 1033 0 stevel (pvp[0][0] & 0377) == CANONNET && pvp[1] != NULL) 1034 0 stevel { 1035 0 stevel msecs = strtol(pvp[1], NULL, 10); 1036 0 stevel } 1037 0 stevel 1038 0 stevel if (msecs > 0) 1039 0 stevel { 1040 0 stevel int fd; 1041 0 stevel fd_set readfds; 1042 0 stevel struct timeval timeout; 1043 616 jbeck struct timeval bp, ep, tp; /* {begin,end,total}pause */ 1044 3544 jbeck int eoftest; 1045 0 stevel 1046 0 stevel /* pause for a moment */ 1047 0 stevel timeout.tv_sec = msecs / 1000; 1048 0 stevel timeout.tv_usec = (msecs % 1000) * 1000; 1049 0 stevel 1050 0 stevel /* Obey RFC 2821: 4.3.5.2: 220 timeout of 5 minutes */ 1051 0 stevel if (timeout.tv_sec >= 300) 1052 0 stevel { 1053 0 stevel timeout.tv_sec = 300; 1054 0 stevel timeout.tv_usec = 0; 1055 0 stevel } 1056 0 stevel 1057 0 stevel /* check if data is on the socket during the pause */ 1058 0 stevel fd = sm_io_getinfo(InChannel, SM_IO_WHAT_FD, NULL); 1059 0 stevel FD_ZERO(&readfds); 1060 0 stevel SM_FD_SET(fd, &readfds); 1061 616 jbeck gettimeofday(&bp, NULL); 1062 0 stevel if (select(fd + 1, FDSET_CAST &readfds, 1063 0 stevel NULL, NULL, &timeout) > 0 && 1064 3544 jbeck FD_ISSET(fd, &readfds) && 1065 6562 jbeck (eoftest = sm_io_getc(InChannel, SM_TIME_DEFAULT)) 1066 3544 jbeck != SM_IO_EOF) 1067 3544 jbeck { 1068 6562 jbeck sm_io_ungetc(InChannel, SM_TIME_DEFAULT, 1069 3544 jbeck eoftest); 1070 616 jbeck gettimeofday(&ep, NULL); 1071 616 jbeck timersub(&ep, &bp, &tp); 1072 0 stevel greetcode = "554"; 1073 0 stevel nullserver = "Command rejected"; 1074 0 stevel sm_syslog(LOG_INFO, e->e_id, 1075 3544 jbeck "rejecting commands from %s [%s] due to pre-greeting traffic after %d seconds", 1076 0 stevel peerhostname, 1077 3544 jbeck anynet_ntoa(&RealHostAddr), 1078 3544 jbeck (int) tp.tv_sec + 1079 616 jbeck (tp.tv_usec >= 500000 ? 1 : 0) 1080 616 jbeck ); 1081 0 stevel } 1082 0 stevel } 1083 0 stevel } 1084 0 stevel 1085 0 stevel #if STARTTLS 1086 0 stevel /* If this an smtps connection, start TLS now */ 1087 0 stevel if (smtps) 1088 0 stevel { 1089 0 stevel Errors = 0; 1090 0 stevel goto starttls; 1091 0 stevel } 1092 0 stevel 1093 0 stevel greeting: 1094 0 stevel 1095 0 stevel #endif /* STARTTLS */ 1096 0 stevel 1097 0 stevel /* output the first line, inserting "ESMTP" as second word */ 1098 0 stevel if (*greetcode == '5') 1099 3544 jbeck (void) sm_snprintf(inp, sizeof(inp), 1100 3544 jbeck "%s not accepting messages", hostname); 1101 3544 jbeck else 1102 3544 jbeck expand(SmtpGreeting, inp, sizeof(inp), e); 1103 0 stevel 1104 0 stevel p = strchr(inp, '\n'); 1105 0 stevel if (p != NULL) 1106 0 stevel *p++ = '\0'; 1107 0 stevel id = strchr(inp, ' '); 1108 0 stevel if (id == NULL) 1109 0 stevel id = &inp[strlen(inp)]; 1110 0 stevel if (p == NULL) 1111 3544 jbeck (void) sm_snprintf(cmdbuf, sizeof(cmdbuf), 1112 0 stevel "%s %%.*s ESMTP%%s", greetcode); 1113 0 stevel else 1114 3544 jbeck (void) sm_snprintf(cmdbuf, sizeof(cmdbuf), 1115 0 stevel "%s-%%.*s ESMTP%%s", greetcode); 1116 0 stevel message(cmdbuf, (int) (id - inp), inp, id); 1117 0 stevel 1118 0 stevel /* output remaining lines */ 1119 0 stevel while ((id = p) != NULL && (p = strchr(id, '\n')) != NULL) 1120 0 stevel { 1121 0 stevel *p++ = '\0'; 1122 0 stevel if (isascii(*id) && isspace(*id)) 1123 0 stevel id++; 1124 3544 jbeck (void) sm_strlcpyn(cmdbuf, sizeof(cmdbuf), 2, greetcode, "-%s"); 1125 0 stevel message(cmdbuf, id); 1126 0 stevel } 1127 0 stevel if (id != NULL) 1128 0 stevel { 1129 0 stevel if (isascii(*id) && isspace(*id)) 1130 0 stevel id++; 1131 3544 jbeck (void) sm_strlcpyn(cmdbuf, sizeof(cmdbuf), 2, greetcode, " %s"); 1132 0 stevel message(cmdbuf, id); 1133 0 stevel } 1134 0 stevel 1135 0 stevel protocol = NULL; 1136 0 stevel sendinghost = macvalue('s', e); 1137 0 stevel 1138 0 stevel /* If quarantining by a connect/ehlo action, save between messages */ 1139 0 stevel if (e->e_quarmsg == NULL) 1140 0 stevel smtp.sm_quarmsg = NULL; 1141 0 stevel else 1142 0 stevel smtp.sm_quarmsg = newstr(e->e_quarmsg); 1143 0 stevel 1144 0 stevel /* sendinghost's storage must outlive the current envelope */ 1145 0 stevel if (sendinghost != NULL) 1146 0 stevel sendinghost = sm_strdup_x(sendinghost); 1147 0 stevel first = true; 1148 0 stevel gothello = false; 1149 0 stevel smtp.sm_gotmail = false; 1150 0 stevel for (;;) 1151 0 stevel { 1152 0 stevel SM_TRY 1153 0 stevel { 1154 0 stevel QuickAbort = false; 1155 0 stevel HoldErrs = false; 1156 0 stevel SuprErrs = false; 1157 0 stevel LogUsrErrs = false; 1158 0 stevel OnlyOneError = true; 1159 0 stevel e->e_flags &= ~(EF_VRFYONLY|EF_GLOBALERRS); 1160 3966 jbeck #if MILTER 1161 3966 jbeck milter_cmd_fail = false; 1162 3966 jbeck #endif /* MILTER */ 1163 0 stevel 1164 0 stevel /* setup for the read */ 1165 0 stevel e->e_to = NULL; 1166 0 stevel Errors = 0; 1167 0 stevel FileName = NULL; 1168 0 stevel (void) sm_io_flush(smioout, SM_TIME_DEFAULT); 1169 0 stevel 1170 0 stevel /* read the input line */ 1171 0 stevel SmtpPhase = "server cmd read"; 1172 0 stevel sm_setproctitle(true, e, "server %s cmd read", CurSmtpClient); 1173 0 stevel 1174 0 stevel /* handle errors */ 1175 0 stevel if (sm_io_error(OutChannel) || 1176 3544 jbeck (p = sfgets(inp, sizeof(inp), InChannel, 1177 0 stevel TimeOuts.to_nextcommand, SmtpPhase)) == NULL) 1178 0 stevel { 1179 0 stevel char *d; 1180 0 stevel 1181 0 stevel d = macvalue(macid("{daemon_name}"), e); 1182 0 stevel if (d == NULL) 1183 0 stevel d = "stdin"; 1184 0 stevel /* end of file, just die */ 1185 0 stevel disconnect(1, e); 1186 0 stevel 1187 0 stevel #if MILTER 1188 0 stevel /* close out milter filters */ 1189 0 stevel milter_quit(e); 1190 0 stevel #endif /* MILTER */ 1191 0 stevel 1192 0 stevel message("421 4.4.1 %s Lost input channel from %s", 1193 0 stevel MyHostName, CurSmtpClient); 1194 0 stevel if (LogLevel > (smtp.sm_gotmail ? 1 : 19)) 1195 0 stevel sm_syslog(LOG_NOTICE, e->e_id, 1196 0 stevel "lost input channel from %s to %s after %s", 1197 0 stevel CurSmtpClient, d, 1198 0 stevel (c == NULL || c->cmd_name == NULL) ? "startup" : c->cmd_name); 1199 0 stevel /* 1200 0 stevel ** If have not accepted mail (DATA), do not bounce 1201 0 stevel ** bad addresses back to sender. 1202 0 stevel */ 1203 0 stevel 1204 0 stevel if (bitset(EF_CLRQUEUE, e->e_flags)) 1205 0 stevel e->e_sendqueue = NULL; 1206 0 stevel goto doquit; 1207 0 stevel } 1208 0 stevel 1209 3544 jbeck /* also used by "proxy" check below */ 1210 3544 jbeck inplen = strlen(inp); 1211 3544 jbeck #if SASL 1212 3544 jbeck /* 1213 3544 jbeck ** SMTP AUTH requires accepting any length, 1214 3544 jbeck ** at least for challenge/response. However, not imposing 1215 3544 jbeck ** a limit is a bad idea (denial of service). 1216 3544 jbeck */ 1217 3544 jbeck 1218 3544 jbeck if (authenticating != SASL_PROC_AUTH 1219 3544 jbeck && sm_strncasecmp(inp, "AUTH ", 5) != 0 1220 3544 jbeck && inplen > MAXLINE) 1221 3544 jbeck { 1222 3544 jbeck message("421 4.7.0 %s Command too long, possible attack %s", 1223 3544 jbeck MyHostName, CurSmtpClient); 1224 3544 jbeck sm_syslog(LOG_INFO, e->e_id, 1225 3544 jbeck "%s: SMTP violation, input too long: %lu", 1226 3544 jbeck CurSmtpClient, (unsigned long) inplen); 1227 3544 jbeck goto doquit; 1228 3544 jbeck } 1229 3544 jbeck #endif /* SASL */ 1230 3544 jbeck 1231 0 stevel if (first) 1232 0 stevel { 1233 3544 jbeck size_t cmdlen; 1234 0 stevel int idx; 1235 0 stevel char *http_cmd; 1236 0 stevel static char *http_cmds[] = { "GET", "POST", 1237 0 stevel "CONNECT", "USER", NULL }; 1238 0 stevel 1239 0 stevel for (idx = 0; (http_cmd = http_cmds[idx]) != NULL; 1240 0 stevel idx++) 1241 0 stevel { 1242 0 stevel cmdlen = strlen(http_cmd); 1243 0 stevel if (cmdlen < inplen && 1244 0 stevel sm_strncasecmp(inp, http_cmd, cmdlen) == 0 && 1245 0 stevel isascii(inp[cmdlen]) && isspace(inp[cmdlen])) 1246 0 stevel { 1247 0 stevel /* Open proxy, drop it */ 1248 0 stevel message("421 4.7.0 %s Rejecting open proxy %s", 1249 0 stevel MyHostName, CurSmtpClient); 1250 0 stevel sm_syslog(LOG_INFO, e->e_id, 1251 0 stevel "%s: probable open proxy: command=%.40s", 1252 0 stevel CurSmtpClient, inp); 1253 0 stevel goto doquit; 1254 0 stevel } 1255 0 stevel } 1256 0 stevel first = false; 1257 0 stevel } 1258 0 stevel 1259 0 stevel /* clean up end of line */ 1260 0 stevel fixcrlf(inp, true); 1261 0 stevel 1262 0 stevel #if PIPELINING 1263 0 stevel # if _FFR_NO_PIPE 1264 0 stevel /* 1265 0 stevel ** if there is more input and pipelining is disabled: 1266 0 stevel ** delay ... (and maybe discard the input?) 1267 0 stevel ** XXX this doesn't really work, at least in tests using 1268 0 stevel ** telnet SM_IO_IS_READABLE only returns 1 if there were 1269 0 stevel ** more than 2 input lines available. 1270 0 stevel */ 1271 0 stevel 1272 0 stevel if (bitset(SRV_NO_PIPE, features) && 1273 0 stevel sm_io_getinfo(InChannel, SM_IO_IS_READABLE, NULL) > 0) 1274 0 stevel { 1275 0 stevel if (++np_log < 3) 1276 0 stevel sm_syslog(LOG_INFO, NOQID, 1277 0 stevel "unauthorized PIPELINING, sleeping"); 1278 0 stevel sleep(1); 1279 0 stevel } 1280 0 stevel 1281 0 stevel # endif /* _FFR_NO_PIPE */ 1282 0 stevel #endif /* PIPELINING */ 1283 0 stevel 1284 0 stevel #if SASL 1285 0 stevel if (authenticating == SASL_PROC_AUTH) 1286 0 stevel { 1287 0 stevel # if 0 1288 0 stevel if (*inp == '\0') 1289 0 stevel { 1290 0 stevel authenticating = SASL_NOT_AUTH; 1291 0 stevel message("501 5.5.2 missing input"); 1292 0 stevel RESET_SASLCONN; 1293 0 stevel continue; 1294 0 stevel } 1295 0 stevel # endif /* 0 */ 1296 0 stevel if (*inp == '*' && *(inp + 1) == '\0') 1297 0 stevel { 1298 0 stevel authenticating = SASL_NOT_AUTH; 1299 0 stevel 1300 5402 jbeck /* RFC 2554 4. */ 1301 0 stevel message("501 5.0.0 AUTH aborted"); 1302 0 stevel RESET_SASLCONN; 1303 0 stevel continue; 1304 0 stevel } 1305 0 stevel 1306 0 stevel /* could this be shorter? XXX */ 1307 0 stevel # if SASL >= 20000 1308 0 stevel in = xalloc(strlen(inp) + 1); 1309 0 stevel result = sasl_decode64(inp, strlen(inp), in, 1310 0 stevel strlen(inp), &inlen); 1311 0 stevel # else /* SASL >= 20000 */ 1312 0 stevel out = xalloc(strlen(inp)); 1313 0 stevel result = sasl_decode64(inp, strlen(inp), out, &outlen); 1314 0 stevel # endif /* SASL >= 20000 */ 1315 0 stevel if (result != SASL_OK) 1316 0 stevel { 1317 0 stevel authenticating = SASL_NOT_AUTH; 1318 0 stevel 1319 5402 jbeck /* RFC 2554 4. */ 1320 0 stevel message("501 5.5.4 cannot decode AUTH parameter %s", 1321 0 stevel inp); 1322 0 stevel # if SASL >= 20000 1323 0 stevel sm_free(in); 1324 0 stevel # endif /* SASL >= 20000 */ 1325 0 stevel RESET_SASLCONN; 1326 0 stevel continue; 1327 0 stevel } 1328 0 stevel 1329 0 stevel # if SASL >= 20000 1330 0 stevel result = sasl_server_step(conn, in, inlen, 1331 0 stevel &out, &outlen); 1332 0 stevel sm_free(in); 1333 0 stevel # else /* SASL >= 20000 */ 1334 0 stevel result = sasl_server_step(conn, out, outlen, 1335 0 stevel &out, &outlen, &errstr); 1336 0 stevel # endif /* SASL >= 20000 */ 1337 0 stevel 1338 0 stevel /* get an OK if we're done */ 1339 0 stevel if (result == SASL_OK) 1340 0 stevel { 1341 0 stevel authenticated: 1342 0 stevel message("235 2.0.0 OK Authenticated"); 1343 0 stevel authenticating = SASL_IS_AUTH; 1344 0 stevel macdefine(&BlankEnvelope.e_macro, A_TEMP, 1345 0 stevel macid("{auth_type}"), auth_type); 1346 0 stevel 1347 0 stevel # if SASL >= 20000 1348 0 stevel user = macvalue(macid("{auth_authen}"), e); 1349 0 stevel 1350 0 stevel /* get security strength (features) */ 1351 0 stevel result = sasl_getprop(conn, SASL_SSF, 1352 0 stevel (const void **) &ssf); 1353 0 stevel # else /* SASL >= 20000 */ 1354 0 stevel result = sasl_getprop(conn, SASL_USERNAME, 1355 0 stevel (void **)&user); 1356 0 stevel if (result != SASL_OK) 1357 0 stevel { 1358 0 stevel user = ""; 1359 0 stevel macdefine(&BlankEnvelope.e_macro, 1360 0 stevel A_PERM, 1361 0 stevel macid("{auth_authen}"), NULL); 1362 0 stevel } 1363 0 stevel else 1364 0 stevel { 1365 0 stevel macdefine(&BlankEnvelope.e_macro, 1366 0 stevel A_TEMP, 1367 0 stevel macid("{auth_authen}"), 1368 0 stevel xtextify(user, "<>\")")); 1369 0 stevel } 1370 0 stevel 1371 0 stevel # if 0 1372 0 stevel /* get realm? */ 1373 0 stevel sasl_getprop(conn, SASL_REALM, (void **) &data); 1374 0 stevel # endif /* 0 */ 1375 0 stevel 1376 0 stevel /* get security strength (features) */ 1377 0 stevel result = sasl_getprop(conn, SASL_SSF, 1378 0 stevel (void **) &ssf); 1379 0 stevel # endif /* SASL >= 20000 */ 1380 0 stevel if (result != SASL_OK) 1381 0 stevel { 1382 0 stevel macdefine(&BlankEnvelope.e_macro, 1383 0 stevel A_PERM, 1384 0 stevel macid("{auth_ssf}"), "0"); 1385 0 stevel ssf = NULL; 1386 0 stevel } 1387 0 stevel else 1388 0 stevel { 1389 0 stevel char pbuf[8]; 1390 0 stevel 1391 3544 jbeck (void) sm_snprintf(pbuf, sizeof(pbuf), 1392 0 stevel "%u", *ssf); 1393 0 stevel macdefine(&BlankEnvelope.e_macro, 1394 0 stevel A_TEMP, 1395 0 stevel macid("{auth_ssf}"), pbuf); 1396 0 stevel if (tTd(95, 8)) 1397 0 stevel sm_dprintf("AUTH auth_ssf: %u\n", 1398 0 stevel *ssf); 1399 0 stevel } 1400 0 stevel 1401 0 stevel /* 1402 0 stevel ** Only switch to encrypted connection 1403 0 stevel ** if a security layer has been negotiated 1404 0 stevel */ 1405 0 stevel 1406 0 stevel if (ssf != NULL && *ssf > 0) 1407 0 stevel { 1408 2197 jbeck int tmo; 1409 2197 jbeck 1410 0 stevel /* 1411 0 stevel ** Convert I/O layer to use SASL. 1412 0 stevel ** If the call fails, the connection 1413 0 stevel ** is aborted. 1414 0 stevel */ 1415 0 stevel 1416 2197 jbeck tmo = TimeOuts.to_datablock * 1000; 1417 0 stevel if (sfdcsasl(&InChannel, &OutChannel, 1418 2197 jbeck conn, tmo) == 0) 1419 0 stevel { 1420 0 stevel /* restart dialogue */ 1421 0 stevel n_helo = 0; 1422 0 stevel # if PIPELINING 1423 0 stevel (void) sm_io_autoflush(InChannel, 1424 0 stevel OutChannel); 1425 0 stevel # endif /* PIPELINING */ 1426 0 stevel } 1427 0 stevel else 1428 0 stevel syserr("503 5.3.3 SASL TLS failed"); 1429 0 stevel } 1430 0 stevel 1431 0 stevel /* NULL pointer ok since it's our function */ 1432 0 stevel if (LogLevel > 8) 1433 0 stevel sm_syslog(LOG_INFO, NOQID, 1434 0 stevel "AUTH=server, relay=%s, authid=%.128s, mech=%.16s, bits=%d", 1435 0 stevel CurSmtpClient, 1436 0 stevel shortenstring(user, 128), 1437 0 stevel auth_type, *ssf); 1438 0 stevel } 1439 0 stevel else if (result == SASL_CONTINUE) 1440 0 stevel { 1441 0 stevel len = ENC64LEN(outlen); 1442 0 stevel out2 = xalloc(len); 1443 0 stevel result = sasl_encode64(out, outlen, out2, len, 1444 0 stevel &out2len); 1445 0 stevel if (result != SASL_OK) 1446 0 stevel { 1447 0 stevel /* correct code? XXX */ 1448 0 stevel /* 454 Temp. authentication failure */ 1449 0 stevel message("454 4.5.4 Internal error: unable to encode64"); 1450 0 stevel if (LogLevel > 5) 1451 0 stevel sm_syslog(LOG_WARNING, e->e_id, 1452 0 stevel "AUTH encode64 error [%d for \"%s\"]", 1453 0 stevel result, out); 1454 0 stevel /* start over? */ 1455 0 stevel authenticating = SASL_NOT_AUTH; 1456 0 stevel } 1457 0 stevel else 1458 0 stevel { 1459 0 stevel message("334 %s", out2); 1460 0 stevel if (tTd(95, 2)) 1461 0 stevel sm_dprintf("AUTH continue: msg='%s' len=%u\n", 1462 0 stevel out2, out2len); 1463 0 stevel } 1464 0 stevel # if SASL >= 20000 1465 0 stevel sm_free(out2); 1466 0 stevel # endif /* SASL >= 20000 */ 1467 0 stevel } 1468 0 stevel else 1469 0 stevel { 1470 0 stevel /* not SASL_OK or SASL_CONT */ 1471 0 stevel message("535 5.7.0 authentication failed"); 1472 0 stevel if (LogLevel > 9) 1473 0 stevel sm_syslog(LOG_WARNING, e->e_id, 1474 0 stevel "AUTH failure (%s): %s (%d) %s", 1475 0 stevel auth_type, 1476 0 stevel sasl_errstring(result, NULL, 1477 0 stevel NULL), 1478 0 stevel result, 1479 0 stevel # if SASL >= 20000 1480 0 stevel sasl_errdetail(conn)); 1481 0 stevel # else /* SASL >= 20000 */ 1482 0 stevel errstr == NULL ? "" : errstr); 1483 0 stevel # endif /* SASL >= 20000 */ 1484 0 stevel RESET_SASLCONN; 1485 0 stevel authenticating = SASL_NOT_AUTH; 1486 0 stevel } 1487 0 stevel } 1488 0 stevel else 1489 0 stevel { 1490 0 stevel /* don't want to do any of this if authenticating */ 1491 0 stevel #endif /* SASL */ 1492 0 stevel 1493 0 stevel /* echo command to transcript */ 1494 0 stevel if (e->e_xfp != NULL) 1495 0 stevel (void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT, 1496 0 stevel "<<< %s\n", inp); 1497 0 stevel 1498 0 stevel if (LogLevel > 14) 1499 0 stevel sm_syslog(LOG_INFO, e->e_id, "<-- %s", inp); 1500 0 stevel 1501 0 stevel /* break off command */ 1502 0 stevel for (p = inp; isascii(*p) && isspace(*p); p++) 1503 0 stevel continue; 1504 0 stevel cmd = cmdbuf; 1505 0 stevel while (*p != '\0' && 1506 0 stevel !(isascii(*p) && isspace(*p)) && 1507 3544 jbeck cmd < &cmdbuf[sizeof(cmdbuf) - 2]) 1508 0 stevel *cmd++ = *p++; 1509 0 stevel *cmd = '\0'; 1510 0 stevel 1511 0 stevel /* throw away leading whitespace */ 1512 0 stevel SKIP_SPACE(p); 1513 0 stevel 1514 0 stevel /* decode command */ 1515 0 stevel for (c = CmdTab; c->cmd_name != NULL; c++) 1516 0 stevel { 1517 0 stevel if (sm_strcasecmp(c->cmd_name, cmdbuf) == 0) 1518 0 stevel break; 1519 0 stevel } 1520 0 stevel 1521 0 stevel /* reset errors */ 1522 0 stevel errno = 0; 1523 0 stevel 1524 0 stevel /* check whether a "non-null" command has been used */ 1525 0 stevel switch (c->cmd_code) 1526 0 stevel { 1527 0 stevel #if SASL 1528 0 stevel case CMDAUTH: 1529 0 stevel /* avoid information leak; take first two words? */ 1530 0 stevel q = "AUTH"; 1531 0 stevel break; 1532 0 stevel #endif /* SASL */ 1533 0 stevel 1534 0 stevel case CMDMAIL: 1535 0 stevel case CMDEXPN: 1536 0 stevel case CMDVRFY: 1537 0 stevel case CMDETRN: 1538 0 stevel lognullconnection = false; 1539 0 stevel /* FALLTHROUGH */ 1540 0 stevel default: 1541 0 stevel q = inp; 1542 0 stevel break; 1543 0 stevel } 1544 0 stevel 1545 0 stevel if (e->e_id == NULL) 1546 0 stevel sm_setproctitle(true, e, "%s: %.80s", 1547 0 stevel CurSmtpClient, q); 1548 0 stevel else 1549 0 stevel sm_setproctitle(true, e, "%s %s: %.80s", 1550 0 stevel qid_printname(e), 1551 0 stevel CurSmtpClient, q); 1552 0 stevel 1553 0 stevel /* 1554 0 stevel ** Process command. 1555 0 stevel ** 1556 0 stevel ** If we are running as a null server, return 550 1557 0 stevel ** to almost everything. 1558 0 stevel */ 1559 0 stevel 1560 0 stevel if (nullserver != NULL || bitnset(D_ETRNONLY, d_flags)) 1561 0 stevel { 1562 0 stevel switch (c->cmd_code) 1563 0 stevel { 1564 0 stevel case CMDQUIT: 1565 0 stevel case CMDHELO: 1566 0 stevel case CMDEHLO: 1567 0 stevel case CMDNOOP: 1568 0 stevel case CMDRSET: 1569 0 stevel case CMDERROR: 1570 0 stevel /* process normally */ 1571 0 stevel break; 1572 0 stevel 1573 0 stevel case CMDETRN: 1574 0 stevel if (bitnset(D_ETRNONLY, d_flags) && 1575 0 stevel nullserver == NULL) 1576 0 stevel break; 1577 0 stevel DELAY_CONN("ETRN"); 1578 0 stevel /* FALLTHROUGH */ 1579 0 stevel 1580 0 stevel default: 1581 0 stevel #if MAXBADCOMMANDS > 0 1582 0 stevel /* theoretically this could overflow */ 1583 0 stevel if (nullserver != NULL && 1584 0 stevel ++n_badcmds > MAXBADCOMMANDS) 1585 0 stevel { 1586 0 stevel message("421 4.7.0 %s Too many bad commands; closing connection", 1587 0 stevel MyHostName); 1588 0 stevel 1589 0 stevel /* arrange to ignore send list */ 1590 0 stevel e->e_sendqueue = NULL; 1591 0 stevel goto doquit; 1592 0 stevel } 1593 0 stevel #endif /* MAXBADCOMMANDS > 0 */ 1594 0 stevel if (nullserver != NULL) 1595 0 stevel { 1596 0 stevel if (ISSMTPREPLY(nullserver)) 1597 0 stevel usrerr(nullserver); 1598 0 stevel else 1599 0 stevel usrerr("550 5.0.0 %s", 1600 0 stevel nullserver); 1601 0 stevel } 1602 0 stevel else 1603 0 stevel usrerr("452 4.4.5 Insufficient disk space; try again later"); 1604 0 stevel continue; 1605 0 stevel } 1606 0 stevel } 1607 0 stevel 1608 0 stevel switch (c->cmd_code) 1609 0 stevel { 1610 0 stevel #if SASL 1611 0 stevel case CMDAUTH: /* sasl */ 1612 0 stevel DELAY_CONN("AUTH"); 1613 0 stevel if (!sasl_ok || n_mechs <= 0) 1614 0 stevel { 1615 0 stevel message("503 5.3.3 AUTH not available"); 1616 0 stevel break; 1617 0 stevel } 1618 0 stevel if (authenticating == SASL_IS_AUTH) 1619 0 stevel { 1620 0 stevel message("503 5.5.0 Already Authenticated"); 1621 0 stevel break; 1622 0 stevel } 1623 0 stevel if (smtp.sm_gotmail) 1624 0 stevel { 1625 0 stevel message("503 5.5.0 AUTH not permitted during a mail transaction"); 1626 0 stevel break; 1627 0 stevel } 1628 0 stevel if (tempfail) 1629 0 stevel { 1630 0 stevel if (LogLevel > 9) 1631 0 stevel sm_syslog(LOG_INFO, e->e_id, 1632 0 stevel "SMTP AUTH command (%.100s) from %s tempfailed (due to previous checks)", 1633 0 stevel p, CurSmtpClient); 1634 0 stevel usrerr("454 4.3.0 Please try again later"); 1635 0 stevel break; 1636 0 stevel } 1637 0 stevel 1638 0 stevel ismore = false; 1639 0 stevel 1640 0 stevel /* crude way to avoid crack attempts */ 1641 0 stevel STOP_IF_ATTACK(checksmtpattack(&n_auth, n_mechs + 1, 1642 0 stevel true, "AUTH", e)); 1643 0 stevel 1644 0 stevel /* make sure mechanism (p) is a valid string */ 1645 0 stevel for (q = p; *q != '\0' && isascii(*q); q++) 1646 0 stevel { 1647 0 stevel if (isspace(*q)) 1648 0 stevel { 1649 0 stevel *q = '\0'; 1650 0 stevel while (*++q != '\0' && 1651 0 stevel isascii(*q) && isspace(*q)) 1652 0 stevel continue; 1653 0 stevel *(q - 1) = '\0'; 1654 0 stevel ismore = (*q != '\0'); 1655 0 stevel break; 1656 0 stevel } 1657 0 stevel } 1658 0 stevel 1659 0 stevel if (*p == '\0') 1660 0 stevel { 1661 0 stevel message("501 5.5.2 AUTH mechanism must be specified"); 1662 0 stevel break; 1663 0 stevel } 1664 0 stevel 1665 0 stevel /* check whether mechanism is available */ 1666 0 stevel if (iteminlist(p, mechlist, " ") == NULL) 1667 0 stevel { 1668 0 stevel message("504 5.3.3 AUTH mechanism %.32s not available", 1669 0 stevel p); 1670 0 stevel break; 1671 0 stevel } 1672 0 stevel 1673 5402 jbeck /* 1674 5402 jbeck ** RFC 2554 4. 1675 5402 jbeck ** Unlike a zero-length client answer to a 1676 5402 jbeck ** 334 reply, a zero- length initial response 1677 5402 jbeck ** is sent as a single equals sign ("="). 1678 5402 jbeck */ 1679 5402 jbeck 1680 5402 jbeck if (ismore && *q == '=' && *(q + 1) == '\0') 1681 5402 jbeck { 1682 5402 jbeck /* will be free()d, don't use in=""; */ 1683 5402 jbeck in = xalloc(1); 1684 5402 jbeck *in = '\0'; 1685 5402 jbeck inlen = 0; 1686 5402 jbeck } 1687 5402 jbeck else if (ismore) 1688 0 stevel { 1689 0 stevel /* could this be shorter? XXX */ 1690 0 stevel # if SASL >= 20000 1691 0 stevel in = xalloc(strlen(q) + 1); 1692 0 stevel result = sasl_decode64(q, strlen(q), in, 1693 0 stevel strlen(q), &inlen); 1694 0 stevel # else /* SASL >= 20000 */ 1695 0 stevel in = sm_rpool_malloc(e->e_rpool, strlen(q)); 1696 0 stevel result = sasl_decode64(q, strlen(q), in, 1697 0 stevel &inlen); 1698 0 stevel # endif /* SASL >= 20000 */ 1699 0 stevel if (result != SASL_OK) 1700 0 stevel { 1701 0 stevel message("501 5.5.4 cannot BASE64 decode '%s'", 1702 0 stevel q); 1703 0 stevel if (LogLevel > 5) 1704 0 stevel sm_syslog(LOG_WARNING, e->e_id, 1705 0 stevel "AUTH decode64 error [%d for \"%s\"]", 1706 0 stevel result, q); 1707 0 stevel /* start over? */ 1708 0 stevel authenticating = SASL_NOT_AUTH; 1709 0 stevel # if SASL >= 20000 1710 0 stevel sm_free(in); 1711 0 stevel # endif /* SASL >= 20000 */ 1712 0 stevel in = NULL; 1713 0 stevel inlen = 0; 1714 0 stevel break; 1715 0 stevel } 1716 0 stevel } 1717 0 stevel else 1718 0 stevel { 1719 0 stevel in = NULL; 1720 0 stevel inlen = 0; 1721 0 stevel } 1722 0 stevel 1723 0 stevel /* see if that auth type exists */ 1724 0 stevel # if SASL >= 20000 1725 0 stevel result = sasl_server_start(conn, p, in, inlen, 1726 0 stevel &out, &outlen); 1727 0 stevel if (in != NULL) 1728 0 stevel sm_free(in); 1729 0 stevel # else /* SASL >= 20000 */ 1730 0 stevel result = sasl_server_start(conn, p, in, inlen, 1731 0 stevel &out, &outlen, &errstr); 1732 0 stevel # endif /* SASL >= 20000 */ 1733 0 stevel 1734 0 stevel if (result != SASL_OK && result != SASL_CONTINUE) 1735 0 stevel { 1736 0 stevel message("535 5.7.0 authentication failed"); 1737 0 stevel if (LogLevel > 9) 1738 0 stevel sm_syslog(LOG_ERR, e->e_id, 1739 0 stevel "AUTH failure (%s): %s (%d) %s", 1740 0 stevel p, 1741 0 stevel sasl_errstring(result, NULL, 1742 0 stevel NULL), 1743 0 stevel result, 1744 0 stevel # if SASL >= 20000 1745 0 stevel sasl_errdetail(conn)); 1746 0 stevel # else /* SASL >= 20000 */ 1747 0 stevel errstr); 1748 0 stevel # endif /* SASL >= 20000 */ 1749 0 stevel RESET_SASLCONN; 1750 0 stevel break; 1751 0 stevel } 1752 0 stevel auth_type = newstr(p); 1753 0 stevel 1754 0 stevel if (result == SASL_OK) 1755 0 stevel { 1756 0 stevel /* ugly, but same code */ 1757 0 stevel goto authenticated; 1758 0 stevel /* authenticated by the initial response */ 1759 0 stevel } 1760 0 stevel 1761 0 stevel /* len is at least 2 */ 1762 0 stevel len = ENC64LEN(outlen); 1763 0 stevel out2 = xalloc(len); 1764 0 stevel result = sasl_encode64(out, outlen, out2, len, 1765 0 stevel &out2len); 1766 0 stevel 1767 0 stevel if (result != SASL_OK) 1768 0 stevel { 1769 0 stevel message("454 4.5.4 Temporary authentication failure"); 1770 0 stevel if (LogLevel > 5) 1771 0 stevel sm_syslog(LOG_WARNING, e->e_id, 1772 0 stevel "AUTH encode64 error [%d for \"%s\"]", 1773 0 stevel result, out); 1774 0 stevel 1775 0 stevel /* start over? */ 1776 0 stevel authenticating = SASL_NOT_AUTH; 1777 0 stevel RESET_SASLCONN; 1778 0 stevel } 1779 0 stevel else 1780 0 stevel { 1781 0 stevel message("334 %s", out2); 1782 0 stevel authenticating = SASL_PROC_AUTH; 1783 0 stevel } 1784 0 stevel # if SASL >= 20000 1785 0 stevel sm_free(out2); 1786 0 stevel # endif /* SASL >= 20000 */ 1787 0 stevel break; 1788 0 stevel #endif /* SASL */ 1789 0 stevel 1790 0 stevel #if STARTTLS 1791 0 stevel case CMDSTLS: /* starttls */ 1792 0 stevel DELAY_CONN("STARTTLS"); 1793 0 stevel if (*p != '\0') 1794 0 stevel { 1795 0 stevel message("501 5.5.2 Syntax error (no parameters allowed)"); 1796 0 stevel break; 1797 0 stevel } 1798 0 stevel if (!bitset(SRV_OFFER_TLS, features)) 1799 0 stevel { 1800 0 stevel message("503 5.5.0 TLS not available"); 1801 0 stevel break; 1802 0 stevel } 1803 0 stevel if (!tls_ok_srv) 1804 0 stevel { 1805 0 stevel message("454 4.3.3 TLS not available after start"); 1806 0 stevel break; 1807 0 stevel } 1808 0 stevel if (smtp.sm_gotmail) 1809 0 stevel { 1810 0 stevel message("503 5.5.0 TLS not permitted during a mail transaction"); 1811 0 stevel break; 1812 0 stevel } 1813 0 stevel if (tempfail) 1814 0 stevel { 1815 0 stevel if (LogLevel > 9) 1816 0 stevel sm_syslog(LOG_INFO, e->e_id, 1817 0 stevel "SMTP STARTTLS command (%.100s) from %s tempfailed (due to previous checks)", 1818 0 stevel p, CurSmtpClient); 1819 0 stevel usrerr("454 4.7.0 Please try again later"); 1820 0 stevel break; 1821 0 stevel } 1822 0 stevel starttls: 1823 0 stevel # if TLS_NO_RSA 1824 0 stevel /* 1825 0 stevel ** XXX do we need a temp key ? 1826 0 stevel */ 1827 0 stevel # else /* TLS_NO_RSA */ 1828 0 stevel # endif /* TLS_NO_RSA */ 1829 0 stevel 1830 0 stevel # if TLS_VRFY_PER_CTX 1831 0 stevel /* 1832 0 stevel ** Note: this sets the verification globally 1833 0 stevel ** (per SSL_CTX) 1834 0 stevel ** it's ok since it applies only to one transaction 1835 0 stevel */ 1836 0 stevel 1837 0 stevel TLS_VERIFY_CLIENT(); 1838 0 stevel # endif /* TLS_VRFY_PER_CTX */ 1839 0 stevel 1840 0 stevel if (srv_ssl != NULL) 1841 0 stevel SSL_clear(srv_ssl); 1842 0 stevel else if ((srv_ssl = SSL_new(srv_ctx)) == NULL) 1843 0 stevel { 1844 0 stevel message("454 4.3.3 TLS not available: error generating SSL handle"); 1845 0 stevel if (LogLevel > 8) 1846 0 stevel tlslogerr("server"); 1847 0 stevel goto tls_done; 1848 0 stevel } 1849 0 stevel 1850 0 stevel # if !TLS_VRFY_PER_CTX 1851 0 stevel /* 1852 0 stevel ** this could be used if it were possible to set 1853 0 stevel ** verification per SSL (connection) 1854 0 stevel ** not just per SSL_CTX (global) 1855 0 stevel */ 1856 0 stevel 1857 0 stevel TLS_VERIFY_CLIENT(); 1858 0 stevel # endif /* !TLS_VRFY_PER_CTX */ 1859 0 stevel 1860 0 stevel rfd = sm_io_getinfo(InChannel, SM_IO_WHAT_FD, NULL); 1861 0 stevel wfd = sm_io_getinfo(OutChannel, SM_IO_WHAT_FD, NULL); 1862 0 stevel 1863 0 stevel if (rfd < 0 || wfd < 0 || 1864 0 stevel SSL_set_rfd(srv_ssl, rfd) <= 0 || 1865 0 stevel SSL_set_wfd(srv_ssl, wfd) <= 0) 1866 0 stevel { 1867 0 stevel message("454 4.3.3 TLS not available: error set fd"); 1868 0 stevel SSL_free(srv_ssl); 1869 0 stevel srv_ssl = NULL; 1870 0 stevel goto tls_done; 1871 0 stevel } 1872 0 stevel if (!smtps) 1873 0 stevel message("220 2.0.0 Ready to start TLS"); 1874 0 stevel # if PIPELINING 1875 0 stevel (void) sm_io_flush(OutChannel, SM_TIME_DEFAULT); 1876 0 stevel # endif /* PIPELINING */ 1877 0 stevel 1878 0 stevel SSL_set_accept_state(srv_ssl); 1879 0 stevel 1880 0 stevel # define SSL_ACC(s) SSL_accept(s) 1881 0 stevel 1882 0 stevel tlsstart = curtime(); 1883 0 stevel ssl_retry: 1884 0 stevel if ((r = SSL_ACC(srv_ssl)) <= 0) 1885 0 stevel { 1886 1658 jbeck int i, ssl_err; 1887 1658 jbeck 1888 1658 jbeck ssl_err = SSL_get_error(srv_ssl, r); 1889 1658 jbeck i = tls_retry(srv_ssl, rfd, wfd, tlsstart, 1890 1658 jbeck TimeOuts.to_starttls, ssl_err, 1891 1658 jbeck "server"); 1892 1658 jbeck if (i > 0) 1893 1658 jbeck goto ssl_retry; 1894 1658 jbeck 1895 0 stevel if (LogLevel > 5) 1896 0 stevel { 1897 0 stevel sm_syslog(LOG_WARNING, NOQID, 1898 1658 jbeck "STARTTLS=server, error: accept failed=%d, SSL_error=%d, errno=%d, retry=%d", 1899 1658 jbeck r, ssl_err, errno, i); 1900 0 stevel if (LogLevel > 8) 1901 0 stevel tlslogerr("server"); 1902 0 stevel } 1903 0 stevel tls_ok_srv = false; 1904 0 stevel SSL_free(srv_ssl); 1905 0 stevel srv_ssl = NULL; 1906 0 stevel 1907 0 stevel /* 1908 0 stevel ** according to the next draft of 1909 0 stevel ** RFC 2487 the connection should be dropped 1910 0 stevel */ 1911 0 stevel 1912 0 stevel /* arrange to ignore any current send list */ 1913 0 stevel e->e_sendqueue = NULL; 1914 0 stevel goto doquit; 1915 0 stevel } 1916 0 stevel 1917 0 stevel /* ignore return code for now, it's in {verify} */ 1918 0 stevel (void) tls_get_info(srv_ssl, true, 1919 0 stevel CurSmtpClient, 1920 0 stevel &BlankEnvelope.e_macro, 1921 0 stevel bitset(SRV_VRFY_CLT, features)); 1922 0 stevel 1923 0 stevel /* 1924 0 stevel ** call Stls_client to find out whether 1925 0 stevel ** to accept the connection from the client 1926 0 stevel */ 1927 0 stevel 1928 0 stevel saveQuickAbort = QuickAbort; 1929 0 stevel saveSuprErrs = SuprErrs; 1930 0 stevel SuprErrs = true; 1931 0 stevel QuickAbort = false; 1932 0 stevel if (rscheck("tls_client", 1933 0 stevel macvalue(macid("{verify}"), e), 1934 0 stevel "STARTTLS", e, 1935 0 stevel RSF_RMCOMM|RSF_COUNT, 1936 3544 jbeck 5, NULL, NOQID, NULL) != EX_OK || 1937 0 stevel Errors > 0) 1938 0 stevel { 1939 0 stevel extern char MsgBuf[]; 1940 0 stevel 1941 0 stevel if (MsgBuf[0] != '\0' && ISSMTPREPLY(MsgBuf)) 1942 0 stevel nullserver = newstr(MsgBuf); 1943 0 stevel else 1944 0 stevel nullserver = "503 5.7.0 Authentication required."; 1945 0 stevel } 1946 0 stevel QuickAbort = saveQuickAbort; 1947 0 stevel SuprErrs = saveSuprErrs; 1948 0 stevel 1949 0 stevel tls_ok_srv = false; /* don't offer STARTTLS again */ 1950 0 stevel n_helo = 0; 1951 0 stevel # if SASL 1952 0 stevel if (sasl_ok) 1953 0 stevel { 1954 0 stevel int cipher_bits; 1955 0 stevel bool verified; 1956 0 stevel char *s, *v, *c; 1957 0 stevel 1958 0 stevel s = macvalue(macid("{cipher_bits}"), e); 1959 0 stevel v = macvalue(macid("{verify}"), e); 1960 0 stevel c = macvalue(macid("{cert_subject}"), e); 1961 0 stevel verified = (v != NULL && strcmp(v, "OK") == 0); 1962 0 stevel if (s != NULL && (cipher_bits = atoi(s)) > 0) 1963 0 stevel { 1964 0 stevel # if SASL >= 20000 1965 0 stevel ext_ssf = cipher_bits; 1966 0 stevel auth_id = verified ? c : NULL; 1967 0 stevel sasl_ok = ((sasl_setprop(conn, 1968 0 stevel SASL_SSF_EXTERNAL, 1969 0 stevel &ext_ssf) == SASL_OK) && 1970 0 stevel (sasl_setprop(conn, 1971 0 stevel SASL_AUTH_EXTERNAL, 1972 0 stevel auth_id) == SASL_OK)); 1973 0 stevel # else /* SASL >= 20000 */ 1974 0 stevel ext_ssf.ssf = cipher_bits; 1975 0 stevel ext_ssf.auth_id = verified ? c : NULL; 1976 0 stevel sasl_ok = sasl_setprop(conn, 1977 0 stevel SASL_SSF_EXTERNAL, 1978 0 stevel &ext_ssf) == SASL_OK; 1979 0 stevel # endif /* SASL >= 20000 */ 1980 0 stevel mechlist = NULL; 1981 0 stevel if (sasl_ok) 1982 0 stevel n_mechs = saslmechs(conn, 1983 0 stevel &mechlist); 1984 0 stevel } 1985 0 stevel } 1986 0 stevel # endif /* SASL */ 1987 0 stevel 1988 0 stevel /* switch to secure connection */ 1989 0 stevel if (sfdctls(&InChannel, &OutChannel, srv_ssl) == 0) 1990 0 stevel { 1991 0 stevel tls_active = true; 1992 0 stevel # if PIPELINING 1993 0 stevel (void) sm_io_autoflush(InChannel, OutChannel); 1994 0 stevel # endif /* PIPELINING */ 1995 0 stevel } 1996 0 stevel else 1997 0 stevel { 1998 0 stevel /* 1999 0 stevel ** XXX this is an internal error 2000 0 stevel ** how to deal with it? 2001 0 stevel ** we can't generate an error message 2002 0 stevel ** since the other side switched to an 2003 0 stevel ** encrypted layer, but we could not... 2004 0 stevel ** just "hang up"? 2005 0 stevel */ 2006 0 stevel 2007 0 stevel nullserver = "454 4.3.3 TLS not available: can't switch to encrypted layer"; 2008 0 stevel syserr("STARTTLS: can't switch to encrypted layer"); 2009 0 stevel } 2010 0 stevel tls_done: 2011 0 stevel if (smtps) 2012 0 stevel { 2013 0 stevel if (tls_active) 2014 0 stevel goto greeting; 2015 0 stevel else 2016 0 stevel goto doquit; 2017 0 stevel } 2018 0 stevel break; 2019 0 stevel #endif /* STARTTLS */ 2020 0 stevel 2021 0 stevel case CMDHELO: /* hello -- introduce yourself */ 2022 0 stevel case CMDEHLO: /* extended hello */ 2023 0 stevel DELAY_CONN("EHLO"); 2024 0 stevel if (c->cmd_code == CMDEHLO) 2025 0 stevel { 2026 0 stevel protocol = "ESMTP"; 2027 0 stevel SmtpPhase = "server EHLO"; 2028 0 stevel } 2029 0 stevel else 2030 0 stevel { 2031 0 stevel protocol = "SMTP"; 2032 0 stevel SmtpPhase = "server HELO"; 2033 0 stevel } 2034 0 stevel 2035 0 stevel /* avoid denial-of-service */ 2036 0 stevel STOP_IF_ATTACK(checksmtpattack(&n_helo, MAXHELOCOMMANDS, 2037 0 stevel true, "HELO/EHLO", e)); 2038 0 stevel 2039 0 stevel #if 0 2040 0 stevel /* RFC2821 4.1.4 allows duplicate HELO/EHLO */ 2041 0 stevel /* check for duplicate HELO/EHLO per RFC 1651 4.2 */ 2042 0 stevel if (gothello) 2043 0 stevel { 2044 0 stevel usrerr("503 %s Duplicate HELO/EHLO", 2045 0 stevel MyHostName); 2046 0 stevel break; 2047 0 stevel } 2048 0 stevel #endif /* 0 */ 2049 0 stevel 2050 0 stevel /* check for valid domain name (re 1123 5.2.5) */ 2051 0 stevel if (*p == '\0' && !AllowBogusHELO) 2052 0 stevel { 2053 0 stevel usrerr("501 %s requires domain address", 2054 0 stevel cmdbuf); 2055 0 stevel break; 2056 0 stevel } 2057 0 stevel 2058 0 stevel /* check for long domain name (hides Received: info) */ 2059 0 stevel if (strlen(p) > MAXNAME) 2060 0 stevel { 2061 0 stevel usrerr("501 Invalid domain name"); 2062 0 stevel if (LogLevel > 9) 2063 0 stevel sm_syslog(LOG_INFO, CurEnv->e_id, 2064 0 stevel "invalid domain name (too long) from %s", 2065 0 stevel CurSmtpClient); 2066 0 stevel break; 2067 0 stevel } 2068 0 stevel 2069 0 stevel ok = true; 2070 0 stevel for (q = p; *q != '\0'; q++) 2071 0 stevel { 2072 0 stevel if (!isascii(*q)) 2073 0 stevel break; 2074 0 stevel if (isalnum(*q)) 2075 0 stevel continue; 2076 0 stevel if (isspace(*q)) 2077 0 stevel { 2078 0 stevel *q = '\0'; 2079 0 stevel 2080 0 stevel /* only complain if strict check */ 2081 0 stevel ok = AllowBogusHELO; 2082 0 stevel 2083 0 stevel /* allow trailing whitespace */ 2084 0 stevel while (!ok && *++q != '\0' && 2085 0 stevel isspace(*q)) 2086 0 stevel ; 2087 0 stevel if (*q == '\0') 2088 0 stevel ok = true; 2089 0 stevel break; 2090 0 stevel } 2091 0 stevel if (strchr("[].-_#:", *q) == NULL) 2092 0 stevel break; 2093 0 stevel } 2094 0 stevel 2095 0 stevel if (*q == '\0' && ok) 2096 0 stevel { 2097 0 stevel q = "pleased to meet you"; 2098 0 stevel sendinghost = sm_strdup_x(p); 2099 0 stevel } 2100 0 stevel else if (!AllowBogusHELO) 2101 0 stevel { 2102 0 stevel usrerr("501 Invalid domain name"); 2103 0 stevel if (LogLevel > 9) 2104 0 stevel sm_syslog(LOG_INFO, CurEnv->e_id, 2105 0 stevel "invalid domain name (%s) from %.100s", 2106 0 stevel p, CurSmtpClient); 2107 0 stevel break; 2108 0 stevel } 2109 0 stevel else 2110 0 stevel { 2111 0 stevel q = "accepting invalid domain name"; 2112 0 stevel } 2113 0 stevel 2114 1658 jbeck if (gothello || smtp.sm_gotmail) 2115 0 stevel CLEAR_STATE(cmdbuf); 2116 0 stevel 2117 0 stevel #if MILTER 2118 0 stevel if (smtp.sm_milterlist && smtp.sm_milterize && 2119 0 stevel !bitset(EF_DISCARD, e->e_flags)) 2120 0 stevel { 2121 0 stevel char state; 2122 0 stevel char *response; 2123 0 stevel 2124 0 stevel response = milter_helo(p, e, &state); 2125 0 stevel switch (state) 2126 0 stevel { 2127 0 stevel case SMFIR_REJECT: 2128 0 stevel if (MilterLogLevel > 3) 2129 0 stevel sm_syslog(LOG_INFO, e->e_id, 2130 0 stevel "Milter: helo=%s, reject=Command rejected", 2131 0 stevel p); 2132 0 stevel nullserver = "Command rejected"; 2133 0 stevel smtp.sm_milterize = false; 2134 0 stevel break; 2135 0 stevel 2136 0 stevel case SMFIR_TEMPFAIL: 2137 0 stevel if (MilterLogLevel > 3) 2138 0 stevel sm_syslog(LOG_INFO, e->e_id, 2139 0 stevel "Milter: helo=%s, reject=%s", 2140 0 stevel p, MSG_TEMPFAIL); 2141 0 stevel tempfail = true; 2142 0 stevel smtp.sm_milterize = false; 2143 0 stevel break; 2144 1658 jbeck 2145 3544 jbeck case SMFIR_REPLYCODE: 2146 3544 jbeck if (MilterLogLevel > 3) 2147 3544 jbeck sm_syslog(LOG_INFO, e->e_id, 2148 3544 jbeck "Milter: helo=%s, reject=%s", 2149 3544 jbeck p, response); 2150 3544 jbeck if (strncmp(response, "421 ", 4) != 0 2151 3544 jbeck && strncmp(response, "421-", 4) != 0) 2152 3544 jbeck { 2153 3544 jbeck nullserver = newstr(response); 2154 3544 jbeck smtp.sm_milterize = false; 2155 3544 jbeck break; 2156 3544 jbeck } 2157 3544 jbeck /* FALLTHROUGH */ 2158 3544 jbeck 2159 1658 jbeck case SMFIR_SHUTDOWN: 2160 3544 jbeck if (MilterLogLevel > 3 && 2161 3544 jbeck response == NULL) 2162 1658 jbeck sm_syslog(LOG_INFO, e->e_id, 2163 2197 jbeck "Milter: helo=%s, reject=421 4.7.0 %s closing connection", 2164 1658 jbeck p, MyHostName); 2165 1658 jbeck tempfail = true; 2166 1658 jbeck smtp.sm_milterize = false; 2167 3544 jbeck if (response != NULL) 2168 3544 jbeck usrerr(response); 2169 3544 jbeck else 2170 3544 jbeck message("421 4.7.0 %s closing connection", 2171 3544 jbeck MyHostName); 2172 1658 jbeck /* arrange to ignore send list */ 2173 1658 jbeck e->e_sendqueue = NULL; 2174 3544 jbeck lognullconnection = false; 2175 1658 jbeck goto doquit; 2176 0 stevel } 2177 0 stevel if (response != NULL) 2178 0 stevel sm_free(response); 2179 0 stevel 2180 0 stevel /* 2181 0 stevel ** If quarantining by a connect/ehlo action, 2182 0 stevel ** save between messages 2183 0 stevel */ 2184 0 stevel 2185 0 stevel if (smtp.sm_quarmsg == NULL && 2186 0 stevel e->e_quarmsg != NULL) 2187 0 stevel smtp.sm_quarmsg = newstr(e->e_quarmsg); 2188 0 stevel } 2189 0 stevel #endif /* MILTER */ 2190 0 stevel gothello = true; 2191 0 stevel 2192 0 stevel /* print HELO response message */ 2193 0 stevel if (c->cmd_code != CMDEHLO) 2194 0 stevel { 2195 0 stevel message("250 %s Hello %s, %s", 2196 0 stevel MyHostName, CurSmtpClient, q); 2197 0 stevel break; 2198 0 stevel } 2199 0 stevel 2200 0 stevel message("250-%s Hello %s, %s", 2201 0 stevel MyHostName, CurSmtpClient, q); 2202 0 stevel 2203 0 stevel /* offer ENHSC even for nullserver */ 2204 0 stevel if (nullserver != NULL) 2205 0 stevel { 2206 0 stevel message("250 ENHANCEDSTATUSCODES"); 2207 0 stevel break; 2208 0 stevel } 2209 0 stevel 2210 0 stevel /* 2211 0 stevel ** print EHLO features list 2212 0 stevel ** 2213 0 stevel ** Note: If you change this list, 2214 0 stevel ** remember to update 'helpfile' 2215 0 stevel */ 2216 0 stevel 2217 0 stevel message("250-ENHANCEDSTATUSCODES"); 2218 0 stevel #if PIPELINING 2219 0 stevel if (bitset(SRV_OFFER_PIPE, features)) 2220 0 stevel message("250-PIPELINING"); 2221 0 stevel #endif /* PIPELINING */ 2222 0 stevel if (bitset(SRV_OFFER_EXPN, features)) 2223 0 stevel { 2224 0 stevel message("250-EXPN"); 2225 0 stevel if (bitset(SRV_OFFER_VERB, features)) 2226 0 stevel message("250-VERB"); 2227 0 stevel } 2228 0 stevel #if MIME8TO7 2229 0 stevel message("250-8BITMIME"); 2230 0 stevel #endif /* MIME8TO7 */ 2231 0 stevel if (MaxMessageSize > 0) 2232 0 stevel message("250-SIZE %ld", MaxMessageSize); 2233 0 stevel else 2234 0 stevel message("250-SIZE"); 2235 0 stevel #if DSN 2236 0 stevel if (SendMIMEErrors && bitset(SRV_OFFER_DSN, features)) 2237 0 stevel message("250-DSN"); 2238 0 stevel #endif /* DSN */ 2239 0 stevel if (bitset(SRV_OFFER_ETRN, features)) 2240 0 stevel message("250-ETRN"); 2241 0 stevel #if SASL 2242 0 stevel if (sasl_ok && mechlist != NULL && *mechlist != '\0') 2243 0 stevel message("250-AUTH %s", mechlist); 2244 0 stevel #endif /* SASL */ 2245 0 stevel #if STARTTLS 2246 0 stevel if (tls_ok_srv && 2247 0 stevel bitset(SRV_OFFER_TLS, features)) 2248 0 stevel message("250-STARTTLS"); 2249 0 stevel #endif /* STARTTLS */ 2250 0 stevel if (DeliverByMin > 0) 2251 0 stevel message("250-DELIVERBY %ld", 2252 0 stevel (long) DeliverByMin); 2253 0 stevel else if (DeliverByMin == 0) 2254 0 stevel message("250-DELIVERBY"); 2255 0 stevel 2256 0 stevel /* < 0: no deliver-by */ 2257 0 stevel 2258 0 stevel message("250 HELP"); 2259 0 stevel break; 2260 0 stevel 2261 0 stevel case CMDMAIL: /* mail -- designate sender */ 2262 0 stevel SmtpPhase = "server MAIL"; 2263 0 stevel DELAY_CONN("MAIL"); 2264 0 stevel 2265 0 stevel /* check for validity of this command */ 2266 0 stevel if (!gothello && bitset(PRIV_NEEDMAILHELO, PrivacyFlags)) 2267 0 stevel { 2268 0 stevel usrerr("503 5.0.0 Polite people say HELO first"); 2269 0 stevel break; 2270 0 stevel } 2271 0 stevel if (smtp.sm_gotmail) 2272 0 stevel { 2273 0 stevel usrerr("503 5.5.0 Sender already specified"); 2274 0 stevel break; 2275 0 stevel } 2276 0 stevel #if SASL 2277 0 stevel if (bitset(SRV_REQ_AUTH, features) && 2278 0 stevel authenticating != SASL_IS_AUTH) 2279 0 stevel { 2280 0 stevel usrerr("530 5.7.0 Authentication required"); 2281 0 stevel break; 2282 0 stevel } 2283 0 stevel #endif /* SASL */ 2284 0 stevel 2285 0 stevel p = skipword(p, "from"); 2286 0 stevel if (p == NULL) 2287 0 stevel break; 2288 0 stevel if (tempfail) 2289 0 stevel { 2290 0 stevel if (LogLevel > 9) 2291 0 stevel sm_syslog(LOG_INFO, e->e_id, 2292 0 stevel "SMTP MAIL command (%.100s) from %s tempfailed (due to previous checks)", 2293 0 stevel p, CurSmtpClient); 2294 0 stevel usrerr(MSG_TEMPFAIL); 2295 0 stevel break; 2296 0 stevel } 2297 0 stevel 2298 0 stevel /* make sure we know who the sending host is */ 2299 0 stevel if (sendinghost == NULL) 2300 0 stevel sendinghost = peerhostname; 2301 0 stevel 2302 0 stevel 2303 0 stevel #if SM_HEAP_CHECK 2304 0 stevel if (sm_debug_active(&DebugLeakSmtp, 1)) 2305 0 stevel { 2306 0 stevel sm_heap_newgroup(); 2307 0 stevel sm_dprintf("smtp() heap group #%d\n", 2308 0 stevel sm_heap_group()); 2309 0 stevel } 2310 0 stevel #endif /* SM_HEAP_CHECK */ 2311 0 stevel 2312 0 stevel if (Errors > 0) 2313 0 stevel goto undo_no_pm; 2314 0 stevel if (!gothello) 2315 0 stevel { 2316 0 stevel auth_warning(e, "%s didn't use HELO protocol", 2317 0 stevel CurSmtpClient); 2318 0 stevel } 2319 0 stevel #ifdef PICKY_HELO_CHECK 2320 0 stevel if (sm_strcasecmp(sendinghost, peerhostname) != 0 && 2321 0 stevel (sm_strcasecmp(peerhostname, "localhost") != 0 || 2322 0 stevel sm_strcasecmp(sendinghost, MyHostName) != 0)) 2323 0 stevel { 2324 0 stevel auth_warning(e, "Host %s claimed to be %s", 2325 0 stevel CurSmtpClient, sendinghost); 2326 0 stevel } 2327 0 stevel #endif /* PICKY_HELO_CHECK */ 2328 0 stevel 2329 0 stevel if (protocol == NULL) 2330 0 stevel protocol = "SMTP"; 2331 0 stevel macdefine(&e->e_macro, A_PERM, 'r', protocol); 2332 0 stevel macdefine(&e->e_macro, A_PERM, 's', sendinghost); 2333 0 stevel 2334 0 stevel if (Errors > 0) 2335 0 stevel goto undo_no_pm; 2336 0 stevel smtp.sm_nrcpts = 0; 2337 0 stevel n_badrcpts = 0; 2338 0 stevel macdefine(&e->e_macro, A_PERM, macid("{ntries}"), "0"); 2339 0 stevel macdefine(&e->e_macro, A_PERM, macid("{nrcpts}"), "0"); 2340 0 stevel macdefine(&e->e_macro, A_PERM, macid("{nbadrcpts}"), 2341 0 stevel "0"); 2342 0 stevel e->e_flags |= EF_CLRQUEUE; 2343 0 stevel sm_setproctitle(true, e, "%s %s: %.80s", 2344 0 stevel qid_printname(e), 2345 0 stevel CurSmtpClient, inp); 2346 0 stevel 2347 0 stevel /* do the processing */ 2348 0 stevel SM_TRY 2349 0 stevel { 2350 0 stevel extern char *FullName; 2351 0 stevel 2352 0 stevel QuickAbort = true; 2353 0 stevel SM_FREE_CLR(FullName); 2354 0 stevel 2355 0 stevel /* must parse sender first */ 2356 0 stevel delimptr = NULL; 2357 0 stevel setsender(p, e, &delimptr, ' ', false); 2358 0 stevel if (delimptr != NULL && *delimptr != '\0') 2359 0 stevel *delimptr++ = '\0'; 2360 0 stevel if (Errors > 0) 2361 0 stevel sm_exc_raisenew_x(&EtypeQuickAbort, 1); 2362 0 stevel 2363 0 stevel /* Successfully set e_from, allow logging */ 2364 0 stevel e->e_flags |= EF_LOGSENDER; 2365 0 stevel 2366 0 stevel /* put resulting triple from parseaddr() into macros */ 2367 0 stevel if (e->e_from.q_mailer != NULL) 2368 0 stevel macdefine(&e->e_macro, A_PERM, 2369 0 stevel macid("{mail_mailer}"), 2370 0 stevel e->e_from.q_mailer->m_name); 2371 0 stevel else 2372 0 stevel macdefine(&e->e_macro, A_PERM, 2373 0 stevel macid("{mail_mailer}"), NULL); 2374 0 stevel if (e->e_from.q_host != NULL) 2375 0 stevel macdefine(&e->e_macro, A_PERM, 2376 0 stevel macid("{mail_host}"), 2377 0 stevel e->e_from.q_host); 2378 0 stevel else 2379 0 stevel macdefine(&e->e_macro, A_PERM, 2380 0 stevel macid("{mail_host}"), "localhost"); 2381 0 stevel if (e->e_from.q_user != NULL) 2382 0 stevel macdefine(&e->e_macro, A_PERM, 2383 0 stevel macid("{mail_addr}"), 2384 0 stevel e->e_from.q_user); 2385 0 stevel else 2386 0 stevel macdefine(&e->e_macro, A_PERM, 2387 0 stevel macid("{mail_addr}"), NULL); 2388 0 stevel if (Errors > 0) 2389 0 stevel sm_exc_raisenew_x(&EtypeQuickAbort, 1); 2390 0 stevel 2391 0 stevel /* check for possible spoofing */ 2392 0 stevel if (RealUid != 0 && OpMode == MD_SMTP && 2393 0 stevel !wordinclass(RealUserName, 't') && 2394 0 stevel (!bitnset(M_LOCALMAILER, 2395 0 stevel e->e_from.q_mailer->m_flags) || 2396 0 stevel strcmp(e->e_from.q_user, RealUserName) != 0)) 2397 0 stevel { 2398 0 stevel auth_warning(e, "%s owned process doing -bs", 2399 0 stevel RealUserName); 2400 0 stevel } 2401 0 stevel 2402 0 stevel /* reset to default value */ 2403 3544 jbeck SevenBitInput = SevenBitInput_Saved; 2404 0 stevel 2405 0 stevel /* now parse ESMTP arguments */ 2406 0 stevel e->e_msgsize = 0; 2407 0 stevel addr = p; 2408 3544 jbeck parse_esmtp_args(e, NULL, p, delimptr, "MAIL", args, 2409 3544 jbeck mail_esmtp_args); 2410 0 stevel if (Errors > 0) 2411 0 stevel sm_exc_raisenew_x(&EtypeQuickAbort, 1); 2412 0 stevel 2413 0 stevel #if SASL 2414 0 stevel # if _FFR_AUTH_PASSING 2415 0 stevel /* set the default AUTH= if the sender didn't */ 2416 0 stevel if (e->e_auth_param == NULL) 2417 0 stevel { 2418 0 stevel /* XXX only do this for an MSA? */ 2419 0 stevel e->e_auth_param = macvalue(macid("{auth_authen}"), 2420 0 stevel e); 2421 0 stevel if (e->e_auth_param == NULL) 2422 0 stevel e->e_auth_param = "<>"; 2423 0 stevel 2424 0 stevel /* 2425 0 stevel ** XXX should we invoke Strust_auth now? 2426 0 stevel ** authorizing as the client that just 2427 0 stevel ** authenticated, so we'll trust implicitly 2428 0 stevel */ 2429 0 stevel } 2430 0 stevel # endif /* _FFR_AUTH_PASSING */ 2431 0 stevel #endif /* SASL */ 2432 0 stevel 2433 0 stevel /* do config file checking of the sender */ 2434 0 stevel macdefine(&e->e_macro, A_PERM, 2435 0 stevel macid("{addr_type}"), "e s"); 2436 0 stevel #if _FFR_MAIL_MACRO 2437 0 stevel /* make the "real" sender address available */ 2438 0 stevel macdefine(&e->e_macro, A_TEMP, macid("{mail_from}"), 2439 0 stevel e->e_from.q_paddr); 2440 0 stevel #endif /* _FFR_MAIL_MACRO */ 2441 0 stevel if (rscheck("check_mail", addr, 2442 0 stevel NULL, e, RSF_RMCOMM|RSF_COUNT, 3, 2443 3544 jbeck NULL, e->e_id, NULL) != EX_OK || 2444 0 stevel Errors > 0) 2445 0 stevel sm_exc_raisenew_x(&EtypeQuickAbort, 1); 2446 0 stevel macdefine(&e->e_macro, A_PERM, 2447 0 stevel macid("{addr_type}"), NULL); 2448 0 stevel 2449 0 stevel if (MaxMessageSize > 0 && 2450 0 stevel (e->e_msgsize > MaxMessageSize || 2451 0 stevel e->e_msgsize < 0)) 2452 0 stevel { 2453 0 stevel usrerr("552 5.2.3 Message size exceeds fixed maximum message size (%ld)", 2454 0 stevel MaxMessageSize); 2455 0 stevel sm_exc_raisenew_x(&EtypeQuickAbort, 1); 2456 0 stevel } 2457 0 stevel 2458 0 stevel /* 2459 0 stevel ** XXX always check whether there is at least one fs 2460 0 stevel ** with enough space? 2461 0 stevel ** However, this may not help much: the queue group 2462 0 stevel ** selection may later on select a FS that hasn't 2463 0 stevel ** enough space. 2464 0 stevel */ 2465 0 stevel 2466 0 stevel if ((NumFileSys == 1 || NumQueue == 1) && 2467 0 stevel !enoughdiskspace(e->e_msgsize, e) 2468 0 stevel #if _FFR_ANY_FREE_FS 2469 0 stevel && !filesys_free(e->e_msgsize) 2470 0 stevel #endif /* _FFR_ANY_FREE_FS */ 2471 0 stevel ) 2472 0 stevel { 2473 0 stevel /* 2474 0 stevel ** We perform this test again when the 2475 0 stevel ** queue directory is selected, in collect. 2476 0 stevel */ 2477 0 stevel 2478 0 stevel usrerr("452 4.4.5 Insufficient disk space; try again later"); 2479 0 stevel sm_exc_raisenew_x(&EtypeQuickAbort, 1); 2480 0 stevel } 2481 0 stevel if (Errors > 0) 2482 0 stevel sm_exc_raisenew_x(&EtypeQuickAbort, 1); 2483 0 stevel 2484 0 stevel LogUsrErrs = true; 2485 0 stevel #if MILTER 2486 0 stevel if (smtp.sm_milterlist && smtp.sm_milterize && 2487 0 stevel !bitset(EF_DISCARD, e->e_flags)) 2488 0 stevel { 2489 0 stevel char state; 2490 0 stevel char *response; 2491 0 stevel 2492 0 stevel response = milter_envfrom(args, e, &state); 2493 0 stevel MILTER_REPLY("from"); 2494 0 stevel } 2495 0 stevel #endif /* MILTER */ 2496 0 stevel if (Errors > 0) 2497 0 stevel sm_exc_raisenew_x(&EtypeQuickAbort, 1); 2498 0 stevel 2499 0 stevel message("250 2.1.0 Sender ok"); 2500 0 stevel smtp.sm_gotmail = true; 2501 0 stevel } 2502 0 stevel SM_EXCEPT(exc, "[!F]*") 2503 0 stevel { 2504 0 stevel /* 2505 0 stevel ** An error occurred while processing a MAIL command. 2506 0 stevel ** Jump to the common error handling code. 2507 0 stevel */ 2508 0 stevel 2509 0 stevel sm_exc_free(exc); 2510 0 stevel goto undo_no_pm; 2511 0 stevel } 2512 0 stevel SM_END_TRY 2513 0 stevel break; 2514 0 stevel 2515 0 stevel undo_no_pm: 2516 0 stevel e->e_flags &= ~EF_PM_NOTIFY; 2517 0 stevel undo: 2518 0 stevel break; 2519 0 stevel 2520 0 stevel case CMDRCPT: /* rcpt -- designate recipient */ 2521 0 stevel DELAY_CONN("RCPT"); 2522 3544 jbeck macdefine(&e->e_macro, A_PERM, 2523 3544 jbeck macid("{rcpt_mailer}"), NULL); 2524 3544 jbeck macdefine(&e->e_macro, A_PERM, 2525 3544 jbeck macid("{rcpt_host}"), NULL); 2526 3544 jbeck macdefine(&e->e_macro, A_PERM, 2527 3544 jbeck macid("{rcpt_addr}"), NULL); 2528 3544 jbeck #if MILTER 2529 3544 jbeck (void) memset(&addr_st, '\0', sizeof(addr_st)); 2530 3544 jbeck a = NULL; 2531 3966 jbeck milter_rcpt_added = false; 2532 5402 jbeck smtp.sm_e_nrcpts_orig = e->e_nrcpts; 2533 3544 jbeck #endif 2534 6562 jbeck #if _FFR_BADRCPT_SHUTDOWN 2535 6562 jbeck /* 2536 6562 jbeck ** hack to deal with hack, see below: 2537 6562 jbeck ** n_badrcpts is increased is limit is reached. 2538 6562 jbeck */ 2539 6562 jbeck 2540 6562 jbeck n_badrcpts_adj = (BadRcptThrottle > 0 && 2541 6562 jbeck n_badrcpts > BadRcptThrottle && 2542 6562 jbeck LogLevel > 5) 2543 6562 jbeck ? n_badrcpts - 1 : n_badrcpts; 2544 6562 jbeck if (BadRcptShutdown > 0 && 2545 6562 jbeck n_badrcpts_adj >= BadRcptShutdown && 2546 6562 jbeck (BadRcptShutdownGood == 0 || 2547 6562 jbeck smtp.sm_nrcpts == 0 || 2548 6562 jbeck (n_badrcpts_adj * 100 / 2549 6562 jbeck (smtp.sm_nrcpts + n_badrcpts) >= 2550 6562 jbeck BadRcptShutdownGood))) 2551 6562 jbeck { 2552 6562 jbeck if (LogLevel > 5) 2553 6562 jbeck sm_syslog(LOG_INFO, e->e_id, 2554 6562 jbeck "%s: Possible SMTP RCPT flood, shutting down connection.", 2555 6562 jbeck CurSmtpClient); 2556 6562 jbeck message("421 4.7.0 %s Too many bad recipients; closing connection", 2557 6562 jbeck MyHostName); 2558 6562 jbeck 2559 6562 jbeck /* arrange to ignore any current send list */ 2560 6562 jbeck e->e_sendqueue = NULL; 2561 6562 jbeck goto doquit; 2562 6562 jbeck } 2563 6562 jbeck #endif /* _FFR_BADRCPT_SHUTDOWN */ 2564 0 stevel if (BadRcptThrottle > 0 && 2565 0 stevel n_badrcpts >= BadRcptThrottle) 2566 0 stevel { 2567 0 stevel if (LogLevel > 5 && 2568 0 stevel n_badrcpts == BadRcptThrottle) 2569 0 stevel { 2570 0 stevel sm_syslog(LOG_INFO, e->e_id, 2571 0 stevel "%s: Possible SMTP RCPT flood, throttling.", 2572 0 stevel CurSmtpClient); 2573 0 stevel 2574 0 stevel /* To avoid duplicated message */ 2575 0 stevel n_badrcpts++; 2576 0 stevel } 2577 0 stevel NBADRCPTS; 2578 0 stevel 2579 0 stevel /* 2580 0 stevel ** Don't use exponential backoff for now. 2581 0 stevel ** Some servers will open more connections 2582 0 stevel ** and actually overload the receiver even 2583 0 stevel ** more. 2584 0 stevel */ 2585 0 stevel 2586 0 stevel (void) sleep(1); 2587 0 stevel } 2588 0 stevel if (!smtp.sm_gotmail) 2589 0 stevel { 2590 0 stevel usrerr("503 5.0.0 Need MAIL before RCPT"); 2591 0 stevel break; 2592 0 stevel } 2593 0 stevel SmtpPhase = "server RCPT"; 2594 0 stevel SM_TRY 2595 0 stevel { 2596 0 stevel QuickAbort = true; 2597 0 stevel LogUsrErrs = true; 2598 0 stevel 2599 0 stevel /* limit flooding of our machine */ 2600 0 stevel if (MaxRcptPerMsg > 0 && 2601 0 stevel smtp.sm_nrcpts >= MaxRcptPerMsg) 2602 0 stevel { 2603 0 stevel /* sleep(1); / * slow down? */ 2604 0 stevel usrerr("452 4.5.3 Too many recipients"); 2605 0 stevel goto rcpt_done; 2606 0 stevel } 2607 0 stevel 2608 1658 jbeck if (e->e_sendmode != SM_DELIVER 2609 1658 jbeck #if _FFR_DM_ONE 2610 1658 jbeck && (NotFirstDelivery || SM_DM_ONE != e->e_sendmode) 2611 1658 jbeck #endif /* _FFR_DM_ONE */ 2612 1658 jbeck ) 2613 0 stevel e->e_flags |= EF_VRFYONLY; 2614 0 stevel 2615 0 stevel #if MILTER 2616 0 stevel /* 2617 3966 jbeck ** Do not expand recipients at RCPT time (in the call 2618 5402 jbeck ** to recipient()) if a milter can delete or reject 2619 5402 jbeck ** a RCPT. If they are expanded, it is impossible 2620 5402 jbeck ** for removefromlist() to figure out the expanded 2621 5402 jbeck ** members of the original recipient and mark them 2622 5402 jbeck ** as QS_DONTSEND. 2623 5402 jbeck */ 2624 5402 jbeck 2625 5402 jbeck if (!(smtp.sm_milterlist && smtp.sm_milterize && 2626 5402 jbeck !bitset(EF_DISCARD, e->e_flags)) && 2627 5402 jbeck (smtp.sm_milters.mis_flags & 2628 5402 jbeck (MIS_FL_DEL_RCPT|MIS_FL_REJ_RCPT)) != 0) 2629 5402 jbeck e->e_flags |= EF_VRFYONLY; 2630 3544 jbeck milter_cmd_done = false; 2631 3544 jbeck milter_cmd_safe = false; 2632 0 stevel #endif /* MILTER */ 2633 0 stevel 2634 0 stevel p = skipword(p, "to"); 2635 0 stevel if (p == NULL) 2636 0 stevel goto rcpt_done; 2637 0 stevel macdefine(&e->e_macro, A_PERM, 2638 0 stevel macid("{addr_type}"), "e r"); 2639 0 stevel a = parseaddr(p, NULLADDR, RF_COPYALL, ' ', &delimptr, 2640 0 stevel e, true); 2641 0 stevel macdefine(&e->e_macro, A_PERM, 2642 0 stevel macid("{addr_type}"), NULL); 2643 0 stevel if (Errors > 0) 2644 0 stevel goto rcpt_done; 2645 0 stevel if (a == NULL) 2646 0 stevel { 2647 0 stevel usrerr("501 5.0.0 Missing recipient"); 2648 0 stevel goto rcpt_done; 2649 0 stevel } 2650 0 stevel 2651 0 stevel if (delimptr != NULL && *delimptr != '\0') 2652 0 stevel *delimptr++ = '\0'; 2653 0 stevel 2654 0 stevel /* put resulting triple from parseaddr() into macros */ 2655 0 stevel if (a->q_mailer != NULL) 2656 0 stevel macdefine(&e->e_macro, A_PERM, 2657 0 stevel macid("{rcpt_mailer}"), 2658 0 stevel a->q_mailer->m_name); 2659 0 stevel else 2660 0 stevel macdefine(&e->e_macro, A_PERM, 2661 0 stevel macid("{rcpt_mailer}"), NULL); 2662 0 stevel if (a->q_host != NULL) 2663 0 stevel macdefine(&e->e_macro, A_PERM, 2664 0 stevel macid("{rcpt_host}"), a->q_host); 2665 0 stevel else 2666 0 stevel macdefine(&e->e_macro, A_PERM, 2667 0 stevel macid("{rcpt_host}"), "localhost"); 2668 0 stevel if (a->q_user != NULL) 2669 0 stevel macdefine(&e->e_macro, A_PERM, 2670 0 stevel macid("{rcpt_addr}"), a->q_user); 2671 0 stevel else 2672 0 stevel macdefine(&e->e_macro, A_PERM, 2673 0 stevel macid("{rcpt_addr}"), NULL); 2674 0 stevel if (Errors > 0) 2675 0 stevel goto rcpt_done; 2676 0 stevel 2677 0 stevel /* now parse ESMTP arguments */ 2678 0 stevel addr = p; 2679 3544 jbeck parse_esmtp_args(e, a, p, delimptr, "RCPT", args, 2680 3544 jbeck rcpt_esmtp_args); 2681 0 stevel if (Errors > 0) 2682 0 stevel goto rcpt_done; 2683 3966 jbeck 2684 3966 jbeck #if MILTER 2685 3966 jbeck /* 2686 3966 jbeck ** rscheck() can trigger an "exception" 2687 3966 jbeck ** in which case the execution continues at 2688 3966 jbeck ** SM_EXCEPT(exc, "[!F]*") 2689 3966 jbeck ** This means milter_cmd_safe is not set 2690 3966 jbeck ** and hence milter is not invoked. 2691 3966 jbeck ** Would it be "safe" to change that, i.e., use 2692 3966 jbeck ** milter_cmd_safe = true; 2693 3966 jbeck ** here so a milter is informed (if requested) 2694 3966 jbeck ** about RCPTs that are rejected by check_rcpt? 2695 3966 jbeck */ 2696 3966 jbeck # if _FFR_MILTER_CHECK_REJECTIONS_TOO 2697 3966 jbeck milter_cmd_safe = true; 2698 3966 jbeck # endif 2699 3966 jbeck #endif 2700 0 stevel 2701 0 stevel /* do config file checking of the recipient */ 2702 0 stevel macdefine(&e->e_macro, A_PERM, 2703 0 stevel macid("{addr_type}"), "e r"); 2704 0 stevel if (rscheck("check_rcpt", addr, 2705 0 stevel NULL, e, RSF_RMCOMM|RSF_COUNT, 3, 2706 3544 jbeck NULL, e->e_id, p_addr_st) != EX_OK || 2707 0 stevel Errors > 0) 2708 0 stevel goto rcpt_done; 2709 0 stevel macdefine(&e->e_macro, A_PERM, 2710 0 stevel macid("{addr_type}"), NULL); 2711 0 stevel 2712 0 stevel /* If discarding, don't bother to verify user */ 2713 0 stevel if (bitset(EF_DISCARD, e->e_flags)) 2714 0 stevel a->q_state = QS_VERIFIED; 2715 3544 jbeck #if MILTER 2716 3544 jbeck milter_cmd_safe = true; 2717 3544 jbeck #endif 2718 0 stevel 2719 0 stevel /* save in recipient list after ESMTP mods */ 2720 0 stevel a = recipient(a, &e->e_sendqueue, 0, e); 2721 3544 jbeck /* may trigger exception... */ 2722 3966 jbeck 2723 3966 jbeck #if MILTER 2724 3966 jbeck milter_rcpt_added = true; 2725 3966 jbeck #endif 2726 3544 jbeck 2727 3544 jbeck if(!(Errors > 0) && QS_IS_BADADDR(a->q_state)) 2728 3544 jbeck { 2729 3544 jbeck /* punt -- should keep message in ADDRESS.... */ 2730 3544 jbeck usrerr("550 5.1.1 Addressee unknown"); 2731 3544 jbeck } 2732 3544 jbeck 2733 3544 jbeck #if MILTER 2734 3544 jbeck rcpt_done: 2735 3544 jbeck if (smtp.sm_milterlist && smtp.sm_milterize && 2736 3544 jbeck !bitset(EF_DISCARD, e->e_flags)) 2737 3544 jbeck { 2738 3544 jbeck char state; 2739 3544 jbeck char *response; 2740 3544 jbeck 2741 3544 jbeck /* how to get the error codes? */ 2742 3544 jbeck if (Errors > 0) 2743 3544 jbeck { 2744 3544 jbeck macdefine(&e->e_macro, A_PERM, 2745 3544 jbeck macid("{rcpt_mailer}"), 2746 3544 jbeck "error"); 2747 3544 jbeck if (a != NULL && 2748 3544 jbeck a->q_status != NULL && 2749 3544 jbeck a->q_rstatus != NULL) 2750 3544 jbeck { 2751 3544 jbeck macdefine(&e->e_macro, A_PERM, 2752 3544 jbeck macid("{rcpt_host}"), 2753 3544 jbeck a->q_status); 2754 3544 jbeck macdefine(&e->e_macro, A_PERM, 2755 3544 jbeck macid("{rcpt_addr}"), 2756 3544 jbeck a->q_rstatus); 2757 3544 jbeck } 2758 3544 jbeck else 2759 3544 jbeck { 2760 3544 jbeck if (addr_st.q_host != NULL) 2761 3544 jbeck macdefine(&e->e_macro, 2762 3544 jbeck A_PERM, 2763 3544 jbeck macid("{rcpt_host}"), 2764 3544 jbeck addr_st.q_host); 2765 3544 jbeck if (addr_st.q_user != NULL) 2766 3544 jbeck macdefine(&e->e_macro, 2767 3544 jbeck A_PERM, 2768 3544 jbeck macid("{rcpt_addr}"), 2769 3544 jbeck addr_st.q_user); 2770 3544 jbeck } 2771 3544 jbeck } 2772 3544 jbeck 2773 3544 jbeck response = milter_envrcpt(args, e, &state, 2774 3544 jbeck Errors > 0); 2775 3544 jbeck milter_cmd_done = true; 2776 3544 jbeck MILTER_REPLY("to"); 2777 3544 jbeck } 2778 3544 jbeck #endif /* MILTER */ 2779 0 stevel 2780 0 stevel /* no errors during parsing, but might be a duplicate */ 2781 0 stevel e->e_to = a->q_paddr; 2782 3544 jbeck if (!(Errors > 0) && !QS_IS_BADADDR(a->q_state)) 2783 0 stevel { 2784 0 stevel if (smtp.sm_nrcpts == 0) 2785 0 stevel initsys(e); 2786 0 stevel message("250 2.1.5 Recipient ok%s", 2787 0 stevel QS_IS_QUEUEUP(a->q_state) ? 2788 0 stevel " (will queue)" : ""); 2789 0 stevel smtp.sm_nrcpts++; 2790 0 stevel } 2791 3544 jbeck 2792 3544 jbeck /* Is this needed? */ 2793 3544 jbeck #if !MILTER 2794 3544 jbeck rcpt_done: 2795 3544 jbeck #endif /* !MILTER */ 2796 3544 jbeck macdefine(&e->e_macro, A_PERM, 2797 3544 jbeck macid("{rcpt_mailer}"), NULL); 2798 3544 jbeck macdefine(&e->e_macro, A_PERM, 2799 3544 jbeck macid("{rcpt_host}"), NULL); 2800 3544 jbeck macdefine(&e->e_macro, A_PERM, 2801 3544 jbeck macid("{rcpt_addr}"), NULL); 2802 3544 jbeck macdefine(&e->e_macro, A_PERM, 2803 3544 jbeck macid("{dsn_notify}"), NULL); 2804 3544 jbeck 2805 0 stevel if (Errors > 0) 2806 0 stevel { 2807 0 stevel ++n_badrcpts; 2808 0 stevel NBADRCPTS; 2809 0 stevel } 2810 0 stevel } 2811 0 stevel SM_EXCEPT(exc, "[!F]*") 2812 0 stevel { 2813 0 stevel /* An exception occurred while processing RCPT */ 2814 0 stevel e->e_flags &= ~(EF_FATALERRS|EF_PM_NOTIFY); 2815 0 stevel ++n_badrcpts; 2816 0 stevel NBADRCPTS; 2817 3544 jbeck #if MILTER 2818 3544 jbeck if (smtp.sm_milterlist && smtp.sm_milterize && 2819 3544 jbeck !bitset(EF_DISCARD, e->e_flags) && 2820 3544 jbeck !milter_cmd_done && milter_cmd_safe) 2821 3544 jbeck { 2822 3544 jbeck char state; 2823 3544 jbeck char *response; 2824 3544 jbeck 2825 3544 jbeck macdefine(&e->e_macro, A_PERM, 2826 3544 jbeck macid("{rcpt_mailer}"), "error"); 2827 3544 jbeck 2828 3544 jbeck /* how to get the error codes? */ 2829 3544 jbeck if (addr_st.q_host != NULL) 2830 3544 jbeck macdefine(&e->e_macro, A_PERM, 2831 3544 jbeck macid("{rcpt_host}"), 2832 3544 jbeck addr_st.q_host); 2833 3544 jbeck else if (a != NULL && a->q_status != NULL) 2834 3544 jbeck macdefine(&e->e_macro, A_PERM, 2835 3544 jbeck macid("{rcpt_host}"), 2836 3544 jbeck a->q_status); 2837 3544 jbeck 2838 3544 jbeck if (addr_st.q_user != NULL) 2839 3544 jbeck macdefine(&e->e_macro, A_PERM, 2840 3544 jbeck macid("{rcpt_addr}"), 2841 3544 jbeck addr_st.q_user); 2842 3544 jbeck else if (a != NULL && a->q_rstatus != NULL) 2843 3544 jbeck macdefine(&e->e_macro, A_PERM, 2844 3544 jbeck macid("{rcpt_addr}"), 2845 3544 jbeck a->q_rstatus); 2846 3544 jbeck 2847 3544 jbeck response = milter_envrcpt(args, e, &state, 2848 3544 jbeck true); 2849 3544 jbeck milter_cmd_done = true; 2850 3544 jbeck MILTER_REPLY("to"); 2851 3544 jbeck macdefine(&e->e_macro, A_PERM, 2852 3544 jbeck macid("{rcpt_mailer}"), NULL); 2853 3544 jbeck macdefine(&e->e_macro, A_PERM, 2854 3544 jbeck macid("{rcpt_host}"), NULL); 2855 3544 jbeck macdefine(&e->e_macro, A_PERM, 2856 3544 jbeck macid("{rcpt_addr}"), NULL); 2857 3966 jbeck } 2858 3966 jbeck if (smtp.sm_milterlist && smtp.sm_milterize && 2859 3966 jbeck milter_rcpt_added && milter_cmd_done && 2860 3966 jbeck milter_cmd_fail) 2861 3966 jbeck { 2862 3966 jbeck (void) removefromlist(addr, &e->e_sendqueue, e); 2863 3966 jbeck milter_cmd_fail = false; 2864 5402 jbeck if (smtp.sm_e_nrcpts_orig < e->e_nrcpts) 2865 5402 jbeck e->e_nrcpts = smtp.sm_e_nrcpts_orig; 2866 3544 jbeck } 2867 3544 jbeck #endif /* MILTER */ 2868 0 stevel } 2869 0 stevel SM_END_TRY 2870 0 stevel break; 2871 0 stevel 2872 0 stevel case CMDDATA: /* data -- text of mail */ 2873 0 stevel DELAY_CONN("DATA"); 2874 0 stevel if (!smtp_data(&smtp, e)) 2875 0 stevel goto doquit; 2876 0 stevel break; 2877 0 stevel 2878 0 stevel case CMDRSET: /* rset -- reset state */ 2879 0 stevel if (tTd(94, 100)) 2880 0 stevel message("451 4.0.0 Test failure"); 2881 0 stevel else 2882 0 stevel message("250 2.0.0 Reset state"); 2883 0 stevel CLEAR_STATE(cmdbuf); 2884 0 stevel break; 2885 0 stevel 2886 0 stevel case CMDVRFY: /* vrfy -- verify address */ 2887 0 stevel case CMDEXPN: /* expn -- expand address */ 2888 0 stevel vrfy = c->cmd_code == CMDVRFY; 2889 0 stevel DELAY_CONN(vrfy ? "VRFY" : "EXPN"); 2890 0 stevel if (tempfail) 2891 0 stevel { 2892 0 stevel if (LogLevel > 9) 2893 0 stevel sm_syslog(LOG_INFO, e->e_id, 2894 0 stevel "SMTP %s command (%.100s) from %s tempfailed (due to previous checks)", 2895 0 stevel vrfy ? "VRFY" : "EXPN", 2896 0 stevel p, CurSmtpClient); 2897 0 stevel 2898 0 stevel /* RFC 821 doesn't allow 4xy reply code */ 2899 0 stevel usrerr("550 5.7.1 Please try again later"); 2900 0 stevel break; 2901 0 stevel } 2902 0 stevel wt = checksmtpattack(&n_verifies, MAXVRFYCOMMANDS, 2903 0 stevel false, vrfy ? "VRFY" : "EXPN", e); 2904 0 stevel STOP_IF_ATTACK(wt); 2905 0 stevel previous = curtime(); 2906 0 stevel if ((vrfy && bitset(PRIV_NOVRFY, PrivacyFlags)) || 2907 0 stevel (!vrfy && !bitset(SRV_OFFER_EXPN, features))) 2908 0 stevel { 2909 0 stevel if (vrfy) 2910 0 stevel message("252 2.5.2 Cannot VRFY user; try RCPT to attempt delivery (or try finger)"); 2911 0 stevel else 2912 0 stevel message("502 5.7.0 Sorry, we do not allow this operation"); 2913 0 stevel if (LogLevel > 5) 2914 0 stevel sm_syslog(LOG_INFO, e->e_id, 2915 0 stevel "%s: %s [rejected]", 2916 0 stevel CurSmtpClient, 2917 0 stevel shortenstring(inp, MAXSHORTSTR)); 2918 0 stevel break; 2919 0 stevel } 2920 0 stevel else if (!gothello && 2921 0 stevel bitset(vrfy ? PRIV_NEEDVRFYHELO : PRIV_NEEDEXPNHELO, 2922 0 stevel PrivacyFlags)) 2923 0 stevel { 2924 0 stevel usrerr("503 5.0.0 I demand that you introduce yourself first"); 2925 0 stevel break; 2926 0 stevel } 2927 0 stevel if (Errors > 0) 2928 0 stevel break; 2929 0 stevel if (LogLevel > 5) 2930 0 stevel sm_syslog(LOG_INFO, e->e_id, "%s: %s", 2931 0 stevel CurSmtpClient, 2932 0 stevel shortenstring(inp, MAXSHORTSTR)); 2933 0 stevel SM_TRY 2934 0 stevel { 2935 0 stevel QuickAbort = true; 2936 0 stevel vrfyqueue = NULL; 2937 0 stevel if (vrfy) 2938 0 stevel e->e_flags |= EF_VRFYONLY; 2939 0 stevel while (*p != '\0' && isascii(*p) && isspace(*p)) 2940 0 stevel p++; 2941 0 stevel if (*p == '\0') 2942 0 stevel { 2943 0 stevel usrerr("501 5.5.2 Argument required"); 2944 0 stevel } 2945 0 stevel else 2946 0 stevel { 2947 0 stevel /* do config file checking of the address */ 2948 0 stevel if (rscheck(vrfy ? "check_vrfy" : "check_expn", 2949 0 stevel p, NULL, e, RSF_RMCOMM, 2950 3544 jbeck 3, NULL, NOQID, NULL) != EX_OK || 2951 0 stevel Errors > 0) 2952 0 stevel sm_exc_raisenew_x(&EtypeQuickAbort, 1); 2953 0 stevel (void) sendtolist(p, NULLADDR, &vrfyqueue, 0, e); 2954 0 stevel } 2955 0 stevel if (wt > 0) 2956 0 stevel { 2957 0 stevel time_t t; 2958 0 stevel 2959 0 stevel t = wt - (curtime() - previous); 2960 0 stevel if (t > 0) 2961 0 stevel (void) sleep(t); 2962 0 stevel } 2963 0 stevel if (Errors > 0) 2964 0 stevel sm_exc_raisenew_x(&EtypeQuickAbort, 1); 2965 0 stevel if (vrfyqueue == NULL) 2966 0 stevel { 2967 0 stevel usrerr("554 5.5.2 Nothing to %s", vrfy ? "VRFY" : "EXPN"); 2968 0 stevel } 2969 0 stevel while (vrfyqueue != NULL) 2970 0 stevel { 2971 0 stevel if (!QS_IS_UNDELIVERED(vrfyqueue->q_state)) 2972 0 stevel { 2973 0 stevel vrfyqueue = vrfyqueue->q_next; 2974 0 stevel continue; 2975 0 stevel } 2976 0 stevel 2977 0 stevel /* see if there is more in the vrfy list */ 2978 0 stevel a = vrfyqueue; 2979 0 stevel while ((a = a->q_next) != NULL && 2980 0 stevel (!QS_IS_UNDELIVERED(a->q_state))) 2981 0 stevel continue; 2982 0 stevel printvrfyaddr(vrfyqueue, a == NULL, vrfy); 2983 0 stevel vrfyqueue = a; 2984 0 stevel } 2985 0 stevel } 2986 0 stevel SM_EXCEPT(exc, "[!F]*") 2987 0 stevel { 2988 0 stevel /* 2989 0 stevel ** An exception occurred while processing VRFY/EXPN 2990 0 stevel */ 2991 0 stevel 2992 0 stevel sm_exc_free(exc); 2993 0 stevel goto undo; 2994 0 stevel } 2995 0 stevel SM_END_TRY 2996 0 stevel break; 2997 0 stevel 2998 0 stevel case CMDETRN: /* etrn -- force queue flush */ 2999 0 stevel DELAY_CONN("ETRN"); 3000 0 stevel 3001 0 stevel /* Don't leak queue information via debug flags */ 3002 0 stevel if (!bitset(SRV_OFFER_ETRN, features) || UseMSP || 3003 0 stevel (RealUid != 0 && RealUid != TrustedUid && 3004 0 stevel OpMode == MD_SMTP)) 3005 0 stevel { 3006 0 stevel /* different message for MSA ? */ 3007 0 stevel message("502 5.7.0 Sorry, we do not allow this operation"); 3008 0 stevel if (LogLevel > 5) 3009 0 stevel sm_syslog(LOG_INFO, e->e_id, 3010 0 stevel "%s: %s [rejected]", 3011 0 stevel CurSmtpClient, 3012 0 stevel shortenstring(inp, MAXSHORTSTR)); 3013 0 stevel break; 3014 0 stevel } 3015 0 stevel if (tempfail) 3016 0 stevel { 3017 0 stevel if (LogLevel > 9) 3018 0 stevel sm_syslog(LOG_INFO, e->e_id, 3019 0 stevel "SMTP ETRN command (%.100s) from %s tempfailed (due to previous checks)", 3020 0 stevel p, CurSmtpClient); 3021 0 stevel usrerr(MSG_TEMPFAIL); 3022 0 stevel break; 3023 0 stevel } 3024 0 stevel 3025 0 stevel if (strlen(p) <= 0) 3026 0 stevel { 3027 0 stevel usrerr("500 5.5.2 Parameter required"); 3028 0 stevel break; 3029 0 stevel } 3030 0 stevel 3031 0 stevel /* crude way to avoid denial-of-service attacks */ 3032 0 stevel STOP_IF_ATTACK(checksmtpattack(&n_etrn, MAXETRNCOMMANDS, 3033 0 stevel true, "ETRN", e)); 3034 0 stevel 3035 0 stevel /* 3036 0 stevel ** Do config file checking of the parameter. 3037 0 stevel ** Even though we have srv_features now, we still 3038 0 stevel ** need this ruleset because the former is called 3039 0 stevel ** when the connection has been established, while 3040 0 stevel ** this ruleset is called when the command is 3041 0 stevel ** actually issued and therefore has all information 3042 0 stevel ** available to make a decision. 3043 0 stevel */ 3044 0 stevel 3045 0 stevel if (rscheck("check_etrn", p, NULL, e, 3046 3544 jbeck RSF_RMCOMM, 3, NULL, NOQID, NULL) 3047 3544 jbeck != EX_OK || 3048 0 stevel Errors > 0) 3049 0 stevel break; 3050 0 stevel 3051 0 stevel if (LogLevel > 5) 3052 0 stevel sm_syslog(LOG_INFO, e->e_id, 3053 0 stevel "%s: ETRN %s", CurSmtpClient, 3054 0 stevel shortenstring(p, MAXSHORTSTR)); 3055 0 stevel 3056 0 stevel id = p; 3057 0 stevel if (*id == '#') 3058 0 stevel { 3059 0 stevel int i, qgrp; 3060 0 stevel 3061 0 stevel id++; 3062 0 stevel qgrp = name2qid(id); 3063 0 stevel if (!ISVALIDQGRP(qgrp)) 3064 0 stevel { 3065 0 stevel usrerr("459 4.5.4 Queue %s unknown", 3066 0 stevel id); 3067 0 stevel break; 3068 0 stevel } 3069 0 stevel for (i = 0; i < NumQueue && Queue[i] != NULL; 3070 0 stevel i++) 3071 0 stevel Queue[i]->qg_nextrun = (time_t) -1; 3072 0 stevel Queue[qgrp]->qg_nextrun = 0; 3073 0 stevel ok = run_work_group(Queue[qgrp]->qg_wgrp, 3074 0 stevel RWG_FORK|RWG_FORCE); 3075 0 stevel if (ok && Errors == 0) 3076 0 stevel message("250 2.0.0 Queuing for queue group %s started", id); 3077 0 stevel break; 3078 0 stevel } 3079 0 stevel 3080 0 stevel if (*id == '@') 3081 0 stevel id++; 3082 0 stevel else 3083 0 stevel *--id = '@'; 3084 0 stevel 3085 0 stevel new = (QUEUE_CHAR *) sm_malloc(sizeof(QUEUE_CHAR)); 3086 0 stevel if (new == NULL) 3087 0 stevel { 3088 0 stevel syserr("500 5.5.0 ETRN out of memory"); 3089 0 stevel break; 3090 0 stevel } 3091 0 stevel new->queue_match = id; 3092 0 stevel new->queue_negate = false; 3093 0 stevel new->queue_next = NULL; 3094 0 stevel QueueLimitRecipient = new; 3095 0 stevel ok = runqueue(true, false, false, true); 3096 0 stevel sm_free(QueueLimitRecipient); /* XXX */ 3097 0 stevel QueueLimitRecipient = NULL; 3098 0 stevel if (ok && Errors == 0) 3099 0 stevel message("250 2.0.0 Queuing for node %s started", p); 3100 0 stevel break; 3101 0 stevel 3102 0 stevel case CMDHELP: /* help -- give user info */ 3103 0 stevel DELAY_CONN("HELP"); 3104 0 stevel help(p, e); 3105 0 stevel break; 3106 0 stevel 3107 0 stevel case CMDNOOP: /* noop -- do nothing */ 3108 0 stevel DELAY_CONN("NOOP"); 3109 1658 jbeck STOP_IF_ATTACK(checksmtpattack(&n_noop, MaxNOOPCommands, 3110 0 stevel true, "NOOP", e)); 3111 0 stevel message("250 2.0.0 OK"); 3112 0 stevel break; 3113 0 stevel 3114 0 stevel case CMDQUIT: /* quit -- leave mail */ 3115 0 stevel message("221 2.0.0 %s closing connection", MyHostName); 3116 0 stevel #if PIPELINING 3117 0 stevel (void) sm_io_flush(OutChannel, SM_TIME_DEFAULT); 3118 0 stevel #endif /* PIPELINING */ 3119 0 stevel 3120 0 stevel if (smtp.sm_nrcpts > 0) 3121 0 stevel logundelrcpts(e, "aborted by sender", 9, false); 3122 0 stevel 3123 0 stevel /* arrange to ignore any current send list */ 3124 0 stevel e->e_sendqueue = NULL; 3125 0 stevel 3126 0 stevel #if STARTTLS 3127 0 stevel /* shutdown TLS connection */ 3128 0 stevel if (tls_active) 3129 0 stevel { 3130 0 stevel (void) endtls(srv_ssl, "server"); 3131 0 stevel tls_active = false; 3132 0 stevel } 3133 0 stevel #endif /* STARTTLS */ 3134 0 stevel #if SASL 3135 0 stevel if (authenticating == SASL_IS_AUTH) 3136 0 stevel { 3137 0 stevel sasl_dispose(&conn); 3138 0 stevel authenticating = SASL_NOT_AUTH; 3139 0 stevel /* XXX sasl_done(); this is a child */ 3140 0 stevel } 3141 0 stevel #endif /* SASL */ 3142 0 stevel 3143 0 stevel doquit: 3144 0 stevel /* avoid future 050 messages */ 3145 0 stevel disconnect(1, e); 3146 0 stevel 3147 0 stevel #if MILTER 3148 0 stevel /* close out milter filters */ 3149 0 stevel milter_quit(e); 3150 0 stevel #endif /* MILTER */ 3151 0 stevel 3152 0 stevel if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags)) 3153 0 stevel logsender(e, NULL); 3154 0 stevel e->e_flags &= ~EF_LOGSENDER; 3155 0 stevel 3156 0 stevel if (lognullconnection && LogLevel > 5 && 3157 0 stevel nullserver == NULL) 3158 0 stevel { 3159 0 stevel char *d; 3160 0 stevel 3161 0 stevel d = macvalue(macid("{daemon_name}"), e); 3162 0 stevel if (d == NULL) 3163 0 stevel d = "stdin"; 3164 0 stevel 3165 0 stevel /* 3166 0 stevel ** even though this id is "bogus", it makes 3167 0 stevel ** it simpler to "grep" related events, e.g., 3168 0 stevel ** timeouts for the same connection. 3169 0 stevel */ 3170 0 stevel 3171 0 stevel sm_syslog(LOG_INFO, e->e_id, 3172 0 stevel "%s did not issue MAIL/EXPN/VRFY/ETRN during connection to %s", 3173 0 stevel CurSmtpClient, d); 3174 0 stevel } 3175 0 stevel if (tTd(93, 100)) 3176 0 stevel { 3177 0 stevel /* return to handle next connection */ 3178 0 stevel return; 3179 0 stevel } 3180 0 stevel finis(true, true, ExitStat); 3181 0 stevel /* NOTREACHED */ 3182 1658 jbeck 3183 1658 jbeck /* just to avoid bogus warning from some compilers */ 3184 1658 jbeck exit(EX_OSERR); 3185 0 stevel 3186 0 stevel case CMDVERB: /* set verbose mode */ 3187 0 stevel DELAY_CONN("VERB"); 3188 0 stevel if (!bitset(SRV_OFFER_EXPN, features) || 3189 0 stevel !bitset(SRV_OFFER_VERB, features)) 3190 0 stevel { 3191 0 stevel /* this would give out the same info */ 3192 0 stevel message("502 5.7.0 Verbose unavailable"); 3193 0 stevel break; 3194 0 stevel } 3195 1658 jbeck STOP_IF_ATTACK(checksmtpattack(&n_noop, MaxNOOPCommands, 3196 0 stevel true, "VERB", e)); 3197 0 stevel Verbose = 1; 3198 0 stevel set_delivery_mode(SM_DELIVER, e); 3199 0 stevel message("250 2.0.0 Verbose mode"); 3200 0 stevel break; 3201 0 stevel 3202 0 stevel #if SMTPDEBUG 3203 0 stevel case CMDDBGQSHOW: /* show queues */ 3204 0 stevel (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 3205 0 stevel "Send Queue="); 3206 0 stevel printaddr(smioout, e->e_sendqueue, true); 3207 0 stevel break; 3208 0 stevel 3209 0 stevel case CMDDBGDEBUG: /* set debug mode */ 3210 3544 jbeck tTsetup(tTdvect, sizeof(tTdvect), "0-99.1"); 3211 0 stevel tTflag(p); 3212 0 stevel message("200 2.0.0 Debug set"); 3213 0 stevel break; 3214 0 stevel 3215 0 stevel #else /* SMTPDEBUG */ 3216 0 stevel case CMDDBGQSHOW: /* show queues */ 3217 0 stevel case CMDDBGDEBUG: /* set debug mode */ 3218 0 stevel #endif /* SMTPDEBUG */ 3219 0 stevel case CMDLOGBOGUS: /* bogus command */ 3220 0 stevel DELAY_CONN("Bogus"); 3221 0 stevel if (LogLevel > 0) 3222 0 stevel