1 /* 2 * Copyright (c) 1998-2006, 2008, 2009 Sendmail, Inc. and its suppliers. 3 * All rights reserved. 4 * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 5 * Copyright (c) 1988, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * By using this file, you agree to the terms and conditions set 9 * forth in the LICENSE file which can be found at the top level of 10 * the sendmail distribution. 11 * 12 */ 13 14 #include <sendmail.h> 15 16 SM_RCSID("@(#)$Id: usersmtp.c,v 8.473 2009/06/17 17:26:51 ca Exp $") 17 18 #include <sysexits.h> 19 20 21 static void esmtp_check __P((char *, bool, MAILER *, MCI *, ENVELOPE *)); 22 static void helo_options __P((char *, bool, MAILER *, MCI *, ENVELOPE *)); 23 static int smtprcptstat __P((ADDRESS *, MAILER *, MCI *, ENVELOPE *)); 24 25 #if SASL 26 extern void *sm_sasl_malloc __P((unsigned long)); 27 extern void sm_sasl_free __P((void *)); 28 #endif /* SASL */ 29 30 /* 31 ** USERSMTP -- run SMTP protocol from the user end. 32 ** 33 ** This protocol is described in RFC821. 34 */ 35 36 #define REPLYCLASS(r) (((r) / 10) % 10) /* second digit of reply code */ 37 #define SMTPCLOSING 421 /* "Service Shutting Down" */ 38 39 #define ENHSCN(e, d) ((e) == NULL ? (d) : (e)) 40 41 #define ENHSCN_RPOOL(e, d, rpool) \ 42 ((e) == NULL ? (d) : sm_rpool_strdup_x(rpool, e)) 43 44 static char SmtpMsgBuffer[MAXLINE]; /* buffer for commands */ 45 static char SmtpReplyBuffer[MAXLINE]; /* buffer for replies */ 46 static bool SmtpNeedIntro; /* need "while talking" in transcript */ 47 /* 48 ** SMTPINIT -- initialize SMTP. 49 ** 50 ** Opens the connection and sends the initial protocol. 51 ** 52 ** Parameters: 53 ** m -- mailer to create connection to. 54 ** mci -- the mailer connection info. 55 ** e -- the envelope. 56 ** onlyhelo -- send only helo command? 57 ** 58 ** Returns: 59 ** none. 60 ** 61 ** Side Effects: 62 ** creates connection and sends initial protocol. 63 */ 64 65 void 66 smtpinit(m, mci, e, onlyhelo) 67 MAILER *m; 68 register MCI *mci; 69 ENVELOPE *e; 70 bool onlyhelo; 71 { 72 register int r; 73 int state; 74 register char *p; 75 register char *hn; 76 char *enhsc; 77 78 enhsc = NULL; 79 if (tTd(18, 1)) 80 { 81 sm_dprintf("smtpinit "); 82 mci_dump(sm_debug_file(), mci, false); 83 } 84 85 /* 86 ** Open the connection to the mailer. 87 */ 88 89 SmtpError[0] = '\0'; 90 SmtpMsgBuffer[0] = '\0'; 91 CurHostName = mci->mci_host; /* XXX UGLY XXX */ 92 if (CurHostName == NULL) 93 CurHostName = MyHostName; 94 SmtpNeedIntro = true; 95 state = mci->mci_state; 96 switch (state) 97 { 98 case MCIS_MAIL: 99 case MCIS_RCPT: 100 case MCIS_DATA: 101 /* need to clear old information */ 102 smtprset(m, mci, e); 103 /* FALLTHROUGH */ 104 105 case MCIS_OPEN: 106 if (!onlyhelo) 107 return; 108 break; 109 110 case MCIS_ERROR: 111 case MCIS_QUITING: 112 case MCIS_SSD: 113 /* shouldn't happen */ 114 smtpquit(m, mci, e); 115 /* FALLTHROUGH */ 116 117 case MCIS_CLOSED: 118 syserr("451 4.4.0 smtpinit: state CLOSED (was %d)", state); 119 return; 120 121 case MCIS_OPENING: 122 break; 123 } 124 if (onlyhelo) 125 goto helo; 126 127 mci->mci_state = MCIS_OPENING; 128 clrsessenvelope(e); 129 130 /* 131 ** Get the greeting message. 132 ** This should appear spontaneously. Give it five minutes to 133 ** happen. 134 */ 135 136 SmtpPhase = mci->mci_phase = "client greeting"; 137 sm_setproctitle(true, e, "%s %s: %s", 138 qid_printname(e), CurHostName, mci->mci_phase); 139 r = reply(m, mci, e, TimeOuts.to_initial, esmtp_check, NULL, 140 XS_DEFAULT); 141 if (r < 0) 142 goto tempfail1; 143 if (REPLYTYPE(r) == 4) 144 goto tempfail2; 145 if (REPLYTYPE(r) != 2) 146 goto unavailable; 147 148 /* 149 ** Send the HELO command. 150 ** My mother taught me to always introduce myself. 151 */ 152 153 helo: 154 if (bitnset(M_ESMTP, m->m_flags) || bitnset(M_LMTP, m->m_flags)) 155 mci->mci_flags |= MCIF_ESMTP; 156 hn = mci->mci_heloname ? mci->mci_heloname : MyHostName; 157 158 tryhelo: 159 #if _FFR_IGNORE_EXT_ON_HELO 160 mci->mci_flags &= ~MCIF_HELO; 161 #endif /* _FFR_IGNORE_EXT_ON_HELO */ 162 if (bitnset(M_LMTP, m->m_flags)) 163 { 164 smtpmessage("LHLO %s", m, mci, hn); 165 SmtpPhase = mci->mci_phase = "client LHLO"; 166 } 167 else if (bitset(MCIF_ESMTP, mci->mci_flags) && 168 !bitnset(M_FSMTP, m->m_flags)) 169 { 170 smtpmessage("EHLO %s", m, mci, hn); 171 SmtpPhase = mci->mci_phase = "client EHLO"; 172 } 173 else 174 { 175 smtpmessage("HELO %s", m, mci, hn); 176 SmtpPhase = mci->mci_phase = "client HELO"; 177 #if _FFR_IGNORE_EXT_ON_HELO 178 mci->mci_flags |= MCIF_HELO; 179 #endif /* _FFR_IGNORE_EXT_ON_HELO */ 180 } 181 sm_setproctitle(true, e, "%s %s: %s", qid_printname(e), 182 CurHostName, mci->mci_phase); 183 r = reply(m, mci, e, 184 bitnset(M_LMTP, m->m_flags) ? TimeOuts.to_lhlo 185 : TimeOuts.to_helo, 186 helo_options, NULL, XS_DEFAULT); 187 if (r < 0) 188 goto tempfail1; 189 else if (REPLYTYPE(r) == 5) 190 { 191 if (bitset(MCIF_ESMTP, mci->mci_flags) && 192 !bitnset(M_LMTP, m->m_flags)) 193 { 194 /* try old SMTP instead */ 195 mci->mci_flags &= ~MCIF_ESMTP; 196 goto tryhelo; 197 } 198 goto unavailable; 199 } 200 else if (REPLYTYPE(r) != 2) 201 goto tempfail2; 202 203 /* 204 ** Check to see if we actually ended up talking to ourself. 205 ** This means we didn't know about an alias or MX, or we managed 206 ** to connect to an echo server. 207 */ 208 209 p = strchr(&SmtpReplyBuffer[4], ' '); 210 if (p != NULL) 211 *p = '\0'; 212 if (!bitnset(M_NOLOOPCHECK, m->m_flags) && 213 !bitnset(M_LMTP, m->m_flags) && 214 sm_strcasecmp(&SmtpReplyBuffer[4], MyHostName) == 0) 215 { 216 syserr("553 5.3.5 %s config error: mail loops back to me (MX problem?)", 217 CurHostName); 218 mci_setstat(mci, EX_CONFIG, "5.3.5", 219 "553 5.3.5 system config error"); 220 mci->mci_errno = 0; 221 smtpquit(m, mci, e); 222 return; 223 } 224 225 /* 226 ** If this is expected to be another sendmail, send some internal 227 ** commands. 228 ** If we're running as MSP, "propagate" -v flag if possible. 229 */ 230 231 if ((UseMSP && Verbose && bitset(MCIF_VERB, mci->mci_flags)) 232 # if !_FFR_DEPRECATE_MAILER_FLAG_I 233 || bitnset(M_INTERNAL, m->m_flags) 234 # endif /* !_FFR_DEPRECATE_MAILER_FLAG_I */ 235 ) 236 { 237 /* tell it to be verbose */ 238 smtpmessage("VERB", m, mci); 239 r = reply(m, mci, e, TimeOuts.to_miscshort, NULL, &enhsc, 240 XS_DEFAULT); 241 if (r < 0) 242 goto tempfail1; 243 } 244 245 if (mci->mci_state != MCIS_CLOSED) 246 { 247 mci->mci_state = MCIS_OPEN; 248 return; 249 } 250 251 /* got a 421 error code during startup */ 252 253 tempfail1: 254 mci_setstat(mci, EX_TEMPFAIL, ENHSCN(enhsc, "4.4.2"), NULL); 255 if (mci->mci_state != MCIS_CLOSED) 256 smtpquit(m, mci, e); 257 return; 258 259 tempfail2: 260 /* XXX should use code from other end iff ENHANCEDSTATUSCODES */ 261 mci_setstat(mci, EX_TEMPFAIL, ENHSCN(enhsc, "4.5.0"), 262 SmtpReplyBuffer); 263 if (mci->mci_state != MCIS_CLOSED) 264 smtpquit(m, mci, e); 265 return; 266 267 unavailable: 268 mci_setstat(mci, EX_UNAVAILABLE, "5.5.0", SmtpReplyBuffer); 269 smtpquit(m, mci, e); 270 return; 271 } 272 /* 273 ** ESMTP_CHECK -- check to see if this implementation likes ESMTP protocol 274 ** 275 ** Parameters: 276 ** line -- the response line. 277 ** firstline -- set if this is the first line of the reply. 278 ** m -- the mailer. 279 ** mci -- the mailer connection info. 280 ** e -- the envelope. 281 ** 282 ** Returns: 283 ** none. 284 */ 285 286 static void 287 esmtp_check(line, firstline, m, mci, e) 288 char *line; 289 bool firstline; 290 MAILER *m; 291 register MCI *mci; 292 ENVELOPE *e; 293 { 294 if (strstr(line, "ESMTP") != NULL) 295 mci->mci_flags |= MCIF_ESMTP; 296 297 /* 298 ** Dirty hack below. Quoting the author: 299 ** This was a response to people who wanted SMTP transmission to be 300 ** just-send-8 by default. Essentially, you could put this tag into 301 ** your greeting message to behave as though the F=8 flag was set on 302 ** the mailer. 303 */ 304 305 if (strstr(line, "8BIT-OK") != NULL) 306 mci->mci_flags |= MCIF_8BITOK; 307 } 308 309 #if SASL 310 /* specify prototype so compiler can check calls */ 311 static char *str_union __P((char *, char *, SM_RPOOL_T *)); 312 313 /* 314 ** STR_UNION -- create the union of two lists 315 ** 316 ** Parameters: 317 ** s1, s2 -- lists of items (separated by single blanks). 318 ** rpool -- resource pool from which result is allocated. 319 ** 320 ** Returns: 321 ** the union of both lists. 322 */ 323 324 static char * 325 str_union(s1, s2, rpool) 326 char *s1, *s2; 327 SM_RPOOL_T *rpool; 328 { 329 char *hr, *h1, *h, *res; 330 int l1, l2, rl; 331 332 if (s1 == NULL || *s1 == '\0') 333 return s2; 334 if (s2 == NULL || *s2 == '\0') 335 return s1; 336 l1 = strlen(s1); 337 l2 = strlen(s2); 338 rl = l1 + l2; 339 res = (char *) sm_rpool_malloc(rpool, rl + 2); 340 if (res == NULL) 341 { 342 if (l1 > l2) 343 return s1; 344 return s2; 345 } 346 (void) sm_strlcpy(res, s1, rl); 347 hr = res + l1; 348 h1 = s2; 349 h = s2; 350 351 /* walk through s2 */ 352 while (h != NULL && *h1 != '\0') 353 { 354 /* is there something after the current word? */ 355 if ((h = strchr(h1, ' ')) != NULL) 356 *h = '\0'; 357 l1 = strlen(h1); 358 359 /* does the current word appear in s1 ? */ 360 if (iteminlist(h1, s1, " ") == NULL) 361 { 362 /* add space as delimiter */ 363 *hr++ = ' '; 364 365 /* copy the item */ 366 memcpy(hr, h1, l1); 367 368 /* advance pointer in result list */ 369 hr += l1; 370 *hr = '\0'; 371 } 372 if (h != NULL) 373 { 374 /* there are more items */ 375 *h = ' '; 376 h1 = h + 1; 377 } 378 } 379 return res; 380 } 381 #endif /* SASL */ 382 383 /* 384 ** HELO_OPTIONS -- process the options on a HELO line. 385 ** 386 ** Parameters: 387 ** line -- the response line. 388 ** firstline -- set if this is the first line of the reply. 389 ** m -- the mailer. 390 ** mci -- the mailer connection info. 391 ** e -- the envelope (unused). 392 ** 393 ** Returns: 394 ** none. 395 */ 396 397 static void 398 helo_options(line, firstline, m, mci, e) 399 char *line; 400 bool firstline; 401 MAILER *m; 402 register MCI *mci; 403 ENVELOPE *e; 404 { 405 register char *p; 406 #if _FFR_IGNORE_EXT_ON_HELO 407 static bool logged = false; 408 #endif /* _FFR_IGNORE_EXT_ON_HELO */ 409 410 if (firstline) 411 { 412 #if SASL 413 mci->mci_saslcap = NULL; 414 #endif /* SASL */ 415 #if _FFR_IGNORE_EXT_ON_HELO 416 logged = false; 417 #endif /* _FFR_IGNORE_EXT_ON_HELO */ 418 return; 419 } 420 #if _FFR_IGNORE_EXT_ON_HELO 421 else if (bitset(MCIF_HELO, mci->mci_flags)) 422 { 423 if (LogLevel > 8 && !logged) 424 { 425 sm_syslog(LOG_WARNING, NOQID, 426 "server=%s [%s] returned extensions despite HELO command", 427 macvalue(macid("{server_name}"), e), 428 macvalue(macid("{server_addr}"), e)); 429 logged = true; 430 } 431 return; 432 } 433 #endif /* _FFR_IGNORE_EXT_ON_HELO */ 434 435 if (strlen(line) < 5) 436 return; 437 line += 4; 438 p = strpbrk(line, " ="); 439 if (p != NULL) 440 *p++ = '\0'; 441 if (sm_strcasecmp(line, "size") == 0) 442 { 443 mci->mci_flags |= MCIF_SIZE; 444 if (p != NULL) 445 mci->mci_maxsize = atol(p); 446 } 447 else if (sm_strcasecmp(line, "8bitmime") == 0) 448 { 449 mci->mci_flags |= MCIF_8BITMIME; 450 mci->mci_flags &= ~MCIF_7BIT; 451 } 452 else if (sm_strcasecmp(line, "expn") == 0) 453 mci->mci_flags |= MCIF_EXPN; 454 else if (sm_strcasecmp(line, "dsn") == 0) 455 mci->mci_flags |= MCIF_DSN; 456 else if (sm_strcasecmp(line, "enhancedstatuscodes") == 0) 457 mci->mci_flags |= MCIF_ENHSTAT; 458 else if (sm_strcasecmp(line, "pipelining") == 0) 459 mci->mci_flags |= MCIF_PIPELINED; 460 else if (sm_strcasecmp(line, "verb") == 0) 461 mci->mci_flags |= MCIF_VERB; 462 #if STARTTLS 463 else if (sm_strcasecmp(line, "starttls") == 0) 464 mci->mci_flags |= MCIF_TLS; 465 #endif /* STARTTLS */ 466 else if (sm_strcasecmp(line, "deliverby") == 0) 467 { 468 mci->mci_flags |= MCIF_DLVR_BY; 469 if (p != NULL) 470 mci->mci_min_by = atol(p); 471 } 472 #if SASL 473 else if (sm_strcasecmp(line, "auth") == 0) 474 { 475 if (p != NULL && *p != '\0') 476 { 477 if (mci->mci_saslcap != NULL) 478 { 479 /* 480 ** Create the union with previous auth 481 ** offerings because we recognize "auth " 482 ** and "auth=" (old format). 483 */ 484 485 mci->mci_saslcap = str_union(mci->mci_saslcap, 486 p, mci->mci_rpool); 487 mci->mci_flags |= MCIF_AUTH; 488 } 489 else 490 { 491 int l; 492 493 l = strlen(p) + 1; 494 mci->mci_saslcap = (char *) 495 sm_rpool_malloc(mci->mci_rpool, l); 496 if (mci->mci_saslcap != NULL) 497 { 498 (void) sm_strlcpy(mci->mci_saslcap, p, 499 l); 500 mci->mci_flags |= MCIF_AUTH; 501 } 502 } 503 } 504 } 505 #endif /* SASL */ 506 } 507 #if SASL 508 509 static int getsimple __P((void *, int, const char **, unsigned *)); 510 static int getsecret __P((sasl_conn_t *, void *, int, sasl_secret_t **)); 511 static int saslgetrealm __P((void *, int, const char **, const char **)); 512 static int readauth __P((char *, bool, SASL_AI_T *m, SM_RPOOL_T *)); 513 static int getauth __P((MCI *, ENVELOPE *, SASL_AI_T *)); 514 static char *removemech __P((char *, char *, SM_RPOOL_T *)); 515 static int attemptauth __P((MAILER *, MCI *, ENVELOPE *, SASL_AI_T *)); 516 517 static sasl_callback_t callbacks[] = 518 { 519 { SASL_CB_GETREALM, &saslgetrealm, NULL }, 520 #define CB_GETREALM_IDX 0 521 { SASL_CB_PASS, &getsecret, NULL }, 522 #define CB_PASS_IDX 1 523 { SASL_CB_USER, &getsimple, NULL }, 524 #define CB_USER_IDX 2 525 { SASL_CB_AUTHNAME, &getsimple, NULL }, 526 #define CB_AUTHNAME_IDX 3 527 { SASL_CB_VERIFYFILE, &safesaslfile, NULL }, 528 #define CB_SAFESASL_IDX 4 529 { SASL_CB_LIST_END, NULL, NULL } 530 }; 531 532 /* 533 ** INIT_SASL_CLIENT -- initialize client side of Cyrus-SASL 534 ** 535 ** Parameters: 536 ** none. 537 ** 538 ** Returns: 539 ** SASL_OK -- if successful. 540 ** SASL error code -- otherwise. 541 ** 542 ** Side Effects: 543 ** checks/sets sasl_clt_init. 544 ** 545 ** Note: 546 ** Callbacks are ignored if sasl_client_init() has 547 ** been called before (by a library such as libnss_ldap) 548 */ 549 550 static bool sasl_clt_init = false; 551 552 static int 553 init_sasl_client() 554 { 555 int result; 556 557 if (sasl_clt_init) 558 return SASL_OK; 559 result = sasl_client_init(callbacks); 560 561 /* should we retry later again or just remember that it failed? */ 562 if (result == SASL_OK) 563 sasl_clt_init = true; 564 return result; 565 } 566 /* 567 ** STOP_SASL_CLIENT -- shutdown client side of Cyrus-SASL 568 ** 569 ** Parameters: 570 ** none. 571 ** 572 ** Returns: 573 ** none. 574 ** 575 ** Side Effects: 576 ** checks/sets sasl_clt_init. 577 */ 578 579 void 580 stop_sasl_client() 581 { 582 if (!sasl_clt_init) 583 return; 584 sasl_clt_init = false; 585 sasl_done(); 586 } 587 /* 588 ** GETSASLDATA -- process the challenges from the SASL protocol 589 ** 590 ** This gets the relevant sasl response data out of the reply 591 ** from the server. 592 ** 593 ** Parameters: 594 ** line -- the response line. 595 ** firstline -- set if this is the first line of the reply. 596 ** m -- the mailer. 597 ** mci -- the mailer connection info. 598 ** e -- the envelope (unused). 599 ** 600 ** Returns: 601 ** none. 602 */ 603 604 static void getsasldata __P((char *, bool, MAILER *, MCI *, ENVELOPE *)); 605 606 static void 607 getsasldata(line, firstline, m, mci, e) 608 char *line; 609 bool firstline; 610 MAILER *m; 611 register MCI *mci; 612 ENVELOPE *e; 613 { 614 int len; 615 int result; 616 # if SASL < 20000 617 char *out; 618 # endif /* SASL < 20000 */ 619 620 /* if not a continue we don't care about it */ 621 len = strlen(line); 622 if ((len <= 4) || 623 (line[0] != '3') || 624 !isascii(line[1]) || !isdigit(line[1]) || 625 !isascii(line[2]) || !isdigit(line[2])) 626 { 627 SM_FREE_CLR(mci->mci_sasl_string); 628 return; 629 } 630 631 /* forget about "334 " */ 632 line += 4; 633 len -= 4; 634 # if SASL >= 20000 635 /* XXX put this into a macro/function? It's duplicated below */ 636 if (mci->mci_sasl_string != NULL) 637 { 638 if (mci->mci_sasl_string_len <= len) 639 { 640 sm_free(mci->mci_sasl_string); /* XXX */ 641 mci->mci_sasl_string = xalloc(len + 1); 642 } 643 } 644 else 645 mci->mci_sasl_string = xalloc(len + 1); 646 647 result = sasl_decode64(line, len, mci->mci_sasl_string, len + 1, 648 (unsigned int *) &mci->mci_sasl_string_len); 649 if (result != SASL_OK) 650 { 651 mci->mci_sasl_string_len = 0; 652 *mci->mci_sasl_string = '\0'; 653 } 654 # else /* SASL >= 20000 */ 655 out = (char *) sm_rpool_malloc_x(mci->mci_rpool, len + 1); 656 result = sasl_decode64(line, len, out, (unsigned int *) &len); 657 if (result != SASL_OK) 658 { 659 len = 0; 660 *out = '\0'; 661 } 662 663 /* 664 ** mci_sasl_string is "shared" with Cyrus-SASL library; hence 665 ** it can't be in an rpool unless we use the same memory 666 ** management mechanism (with same rpool!) for Cyrus SASL. 667 */ 668 669 if (mci->mci_sasl_string != NULL) 670 { 671 if (mci->mci_sasl_string_len <= len) 672 { 673 sm_free(mci->mci_sasl_string); /* XXX */ 674 mci->mci_sasl_string = xalloc(len + 1); 675 } 676 } 677 else 678 mci->mci_sasl_string = xalloc(len + 1); 679 680 memcpy(mci->mci_sasl_string, out, len); 681 mci->mci_sasl_string[len] = '\0'; 682 mci->mci_sasl_string_len = len; 683 # endif /* SASL >= 20000 */ 684 return; 685 } 686 /* 687 ** READAUTH -- read auth values from a file 688 ** 689 ** Parameters: 690 ** filename -- name of file to read. 691 ** safe -- if set, this is a safe read. 692 ** sai -- where to store auth_info. 693 ** rpool -- resource pool for sai. 694 ** 695 ** Returns: 696 ** EX_OK -- data succesfully read. 697 ** EX_UNAVAILABLE -- no valid filename. 698 ** EX_TEMPFAIL -- temporary failure. 699 */ 700 701 static char *sasl_info_name[] = 702 { 703 "user id", 704 "authentication id", 705 "password", 706 "realm", 707 "mechlist" 708 }; 709 static int 710 readauth(filename, safe, sai, rpool) 711 char *filename; 712 bool safe; 713 SASL_AI_T *sai; 714 SM_RPOOL_T *rpool; 715 { 716 SM_FILE_T *f; 717 long sff; 718 pid_t pid; 719 int lc; 720 char *s; 721 char buf[MAXLINE]; 722 723 if (filename == NULL || filename[0] == '\0') 724 return EX_UNAVAILABLE; 725 726 #if !_FFR_ALLOW_SASLINFO 727 /* 728 ** make sure we don't use a program that is not 729 ** accesible to the user who specified a different authinfo file. 730 ** However, currently we don't pass this info (authinfo file 731 ** specified by user) around, so we just turn off program access. 732 */ 733 734 if (filename[0] == '|') 735 { 736 auto int fd; 737 int i; 738 char *p; 739 char *argv[MAXPV + 1]; 740 741 i = 0; 742 for (p = strtok(&filename[1], " \t"); p != NULL; 743 p = strtok(NULL, " \t")) 744 { 745 if (i >= MAXPV) 746 break; 747 argv[i++] = p; 748 } 749 argv[i] = NULL; 750 pid = prog_open(argv, &fd, CurEnv); 751 if (pid < 0) 752 f = NULL; 753 else 754 f = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT, 755 (void *) &fd, SM_IO_RDONLY, NULL); 756 } 757 else 758 #endif /* !_FFR_ALLOW_SASLINFO */ 759 { 760 pid = -1; 761 sff = SFF_REGONLY|SFF_SAFEDIRPATH|SFF_NOWLINK 762 |SFF_NOGWFILES|SFF_NOWWFILES|SFF_NOWRFILES; 763 # if _FFR_GROUPREADABLEAUTHINFOFILE 764 if (!bitnset(DBS_GROUPREADABLEAUTHINFOFILE, DontBlameSendmail)) 765 # endif /* _FFR_GROUPREADABLEAUTHINFOFILE */ 766 sff |= SFF_NOGRFILES; 767 if (DontLockReadFiles) 768 sff |= SFF_NOLOCK; 769 770 #if _FFR_ALLOW_SASLINFO 771 /* 772 ** XXX: make sure we don't read or open files that are not 773 ** accesible to the user who specified a different authinfo 774 ** file. 775 */ 776 777 sff |= SFF_MUSTOWN; 778 #else /* _FFR_ALLOW_SASLINFO */ 779 if (safe) 780 sff |= SFF_OPENASROOT; 781 #endif /* _FFR_ALLOW_SASLINFO */ 782 783 f = safefopen(filename, O_RDONLY, 0, sff); 784 } 785 if (f == NULL) 786 { 787 if (LogLevel > 5) 788 sm_syslog(LOG_ERR, NOQID, 789 "AUTH=client, error: can't open %s: %s", 790 filename, sm_errstring(errno)); 791 return EX_TEMPFAIL; 792 } 793 794 lc = 0; 795 while (lc <= SASL_MECHLIST && 796 sm_io_fgets(f, SM_TIME_DEFAULT, buf, sizeof(buf)) != NULL) 797 { 798 if (buf[0] != '#') 799 { 800 (*sai)[lc] = sm_rpool_strdup_x(rpool, buf); 801 if ((s = strchr((*sai)[lc], '\n')) != NULL) 802 *s = '\0'; 803 lc++; 804 } 805 } 806 807 (void) sm_io_close(f, SM_TIME_DEFAULT); 808 if (pid > 0) 809 (void) waitfor(pid); 810 if (lc < SASL_PASSWORD) 811 { 812 if (LogLevel > 8) 813 sm_syslog(LOG_ERR, NOQID, 814 "AUTH=client, error: can't read %s from %s", 815 sasl_info_name[lc + 1], filename); 816 return EX_TEMPFAIL; 817 } 818 return EX_OK; 819 } 820 821 /* 822 ** GETAUTH -- get authinfo from ruleset call 823 ** 824 ** {server_name}, {server_addr} must be set 825 ** 826 ** Parameters: 827 ** mci -- the mailer connection structure. 828 ** e -- the envelope (including the sender to specify). 829 ** sai -- pointer to authinfo (result). 830 ** 831 ** Returns: 832 ** EX_OK -- ruleset was succesfully called, data may not 833 ** be available, sai must be checked. 834 ** EX_UNAVAILABLE -- ruleset unavailable (or failed). 835 ** EX_TEMPFAIL -- temporary failure (from ruleset). 836 ** 837 ** Side Effects: 838 ** Fills in sai if successful. 839 */ 840 841 static int 842 getauth(mci, e, sai) 843 MCI *mci; 844 ENVELOPE *e; 845 SASL_AI_T *sai; 846 { 847 int i, r, l, got, ret; 848 char **pvp; 849 char pvpbuf[PSBUFSIZE]; 850 851 r = rscap("authinfo", macvalue(macid("{server_name}"), e), 852 macvalue(macid("{server_addr}"), e), e, 853 &pvp, pvpbuf, sizeof(pvpbuf)); 854 855 if (r != EX_OK) 856 return EX_UNAVAILABLE; 857 858 /* other than expected return value: ok (i.e., no auth) */ 859 if (pvp == NULL || pvp[0] == NULL || (pvp[0][0] & 0377) != CANONNET) 860 return EX_OK; 861 if (pvp[1] != NULL && sm_strncasecmp(pvp[1], "temp", 4) == 0) 862 return EX_TEMPFAIL; 863 864 /* 865 ** parse the data, put it into sai 866 ** format: "TDstring" (including the '"' !) 867 ** where T is a tag: 'U', ... 868 ** D is a delimiter: ':' or '=' 869 */ 870 871 ret = EX_OK; /* default return value */ 872 i = 0; 873 got = 0; 874 while (i < SASL_ENTRIES) 875 { 876 if (pvp[i + 1] == NULL) 877 break; 878 if (pvp[i + 1][0] != '"') 879 break; 880 switch (pvp[i + 1][1]) 881 { 882 case 'U': 883 case 'u': 884 r = SASL_USER; 885 break; 886 case 'I': 887 case 'i': 888 r = SASL_AUTHID; 889 break; 890 case 'P': 891 case 'p': 892 r = SASL_PASSWORD; 893 break; 894 case 'R': 895 case 'r': 896 r = SASL_DEFREALM; 897 break; 898 case 'M': 899 case 'm': 900 r = SASL_MECHLIST; 901 break; 902 default: 903 goto fail; 904 } 905 l = strlen(pvp[i + 1]); 906 907 /* check syntax */ 908 if (l <= 3 || pvp[i + 1][l - 1] != '"') 909 goto fail; 910 911 /* remove closing quote */ 912 pvp[i + 1][l - 1] = '\0'; 913 914 /* remove "TD and " */ 915 l -= 4; 916 (*sai)[r] = (char *) sm_rpool_malloc(mci->mci_rpool, l + 1); 917 if ((*sai)[r] == NULL) 918 goto tempfail; 919 if (pvp[i + 1][2] == ':') 920 { 921 /* ':text' (just copy) */ 922 (void) sm_strlcpy((*sai)[r], pvp[i + 1] + 3, l + 1); 923 got |= 1 << r; 924 } 925 else if (pvp[i + 1][2] == '=') 926 { 927 unsigned int len; 928 929 /* '=base64' (decode) */ 930 # if SASL >= 20000 931 ret = sasl_decode64(pvp[i + 1] + 3, 932 (unsigned int) l, (*sai)[r], 933 (unsigned int) l + 1, &len); 934 # else /* SASL >= 20000 */ 935 ret = sasl_decode64(pvp[i + 1] + 3, 936 (unsigned int) l, (*sai)[r], &len); 937 # endif /* SASL >= 20000 */ 938 if (ret != SASL_OK) 939 goto fail; 940 got |= 1 << r; 941 } 942 else 943 goto fail; 944 if (tTd(95, 5)) 945 sm_syslog(LOG_DEBUG, NOQID, "getauth %s=%s", 946 sasl_info_name[r], (*sai)[r]); 947 ++i; 948 } 949 950 /* did we get the expected data? */ 951 /* XXX: EXTERNAL mechanism only requires (and only uses) SASL_USER */ 952 if (!(bitset(SASL_USER_BIT|SASL_AUTHID_BIT, got) && 953 bitset(SASL_PASSWORD_BIT, got))) 954 goto fail; 955 956 /* no authid? copy uid */ 957 if (!bitset(SASL_AUTHID_BIT, got)) 958 { 959 l = strlen((*sai)[SASL_USER]) + 1; 960 (*sai)[SASL_AUTHID] = (char *) sm_rpool_malloc(mci->mci_rpool, 961 l + 1); 962 if ((*sai)[SASL_AUTHID] == NULL) 963 goto tempfail; 964 (void) sm_strlcpy((*sai)[SASL_AUTHID], (*sai)[SASL_USER], l); 965 } 966 967 /* no uid? copy authid */ 968 if (!bitset(SASL_USER_BIT, got)) 969 { 970 l = strlen((*sai)[SASL_AUTHID]) + 1; 971 (*sai)[SASL_USER] = (char *) sm_rpool_malloc(mci->mci_rpool, 972 l + 1); 973 if ((*sai)[SASL_USER] == NULL) 974 goto tempfail; 975 (void) sm_strlcpy((*sai)[SASL_USER], (*sai)[SASL_AUTHID], l); 976 } 977 return EX_OK; 978 979 tempfail: 980 ret = EX_TEMPFAIL; 981 fail: 982 if (LogLevel > 8) 983 sm_syslog(LOG_WARNING, NOQID, 984 "AUTH=client, relay=%.64s [%.16s], authinfo %sfailed", 985 macvalue(macid("{server_name}"), e), 986 macvalue(macid("{server_addr}"), e), 987 ret == EX_TEMPFAIL ? "temp" : ""); 988 for (i = 0; i <= SASL_MECHLIST; i++) 989 (*sai)[i] = NULL; /* just clear; rpool */ 990 return ret; 991 } 992 993 # if SASL >= 20000 994 /* 995 ** GETSIMPLE -- callback to get userid or authid 996 ** 997 ** Parameters: 998 ** context -- sai 999 ** id -- what to do 1000 ** result -- (pointer to) result 1001 ** len -- (pointer to) length of result 1002 ** 1003 ** Returns: 1004 ** OK/failure values 1005 */ 1006 1007 static int 1008 getsimple(context, id, result, len) 1009 void *context; 1010 int id; 1011 const char **result; 1012 unsigned *len; 1013 { 1014 SASL_AI_T *sai; 1015 1016 if (result == NULL || context == NULL) 1017 return SASL_BADPARAM; 1018 sai = (SASL_AI_T *) context; 1019 1020 switch (id) 1021 { 1022 case SASL_CB_USER: 1023 *result = (*sai)[SASL_USER]; 1024 if (tTd(95, 5)) 1025 sm_syslog(LOG_DEBUG, NOQID, "AUTH username '%s'", 1026 *result); 1027 if (len != NULL) 1028 *len = *result != NULL ? strlen(*result) : 0; 1029 break; 1030 1031 case SASL_CB_AUTHNAME: 1032 *result = (*sai)[SASL_AUTHID]; 1033 if (tTd(95, 5)) 1034 sm_syslog(LOG_DEBUG, NOQID, "AUTH authid '%s'", 1035 *result); 1036 if (len != NULL) 1037 *len = *result != NULL ? strlen(*result) : 0; 1038 break; 1039 1040 case SASL_CB_LANGUAGE: 1041 *result = NULL; 1042 if (len != NULL) 1043 *len = 0; 1044 break; 1045 1046 default: 1047 return SASL_BADPARAM; 1048 } 1049 return SASL_OK; 1050 } 1051 /* 1052 ** GETSECRET -- callback to get password 1053 ** 1054 ** Parameters: 1055 ** conn -- connection information 1056 ** context -- sai 1057 ** id -- what to do 1058 ** psecret -- (pointer to) result 1059 ** 1060 ** Returns: 1061 ** OK/failure values 1062 */ 1063 1064 static int 1065 getsecret(conn, context, id, psecret) 1066 sasl_conn_t *conn; 1067 SM_UNUSED(void *context); 1068 int id; 1069 sasl_secret_t **psecret; 1070 { 1071 int len; 1072 char *authpass; 1073 MCI *mci; 1074 1075 if (conn == NULL || psecret == NULL || id != SASL_CB_PASS) 1076 return SASL_BADPARAM; 1077 1078 mci = (MCI *) context; 1079 authpass = mci->mci_sai[SASL_PASSWORD]; 1080 len = strlen(authpass); 1081 1082 /* 1083 ** use an rpool because we are responsible for free()ing the secret, 1084 ** but we can't free() it until after the auth completes 1085 */ 1086 1087 *psecret = (sasl_secret_t *) sm_rpool_malloc(mci->mci_rpool, 1088 sizeof(sasl_secret_t) + 1089 len + 1); 1090 if (*psecret == NULL) 1091 return SASL_FAIL; 1092 (void) sm_strlcpy((char *) (*psecret)->data, authpass, len + 1); 1093 (*psecret)->len = (unsigned long) len; 1094 return SASL_OK; 1095 } 1096 # else /* SASL >= 20000 */ 1097 /* 1098 ** GETSIMPLE -- callback to get userid or authid 1099 ** 1100 ** Parameters: 1101 ** context -- sai 1102 ** id -- what to do 1103 ** result -- (pointer to) result 1104 ** len -- (pointer to) length of result 1105 ** 1106 ** Returns: 1107 ** OK/failure values 1108 */ 1109 1110 static int 1111 getsimple(context, id, result, len) 1112 void *context; 1113 int id; 1114 const char **result; 1115 unsigned *len; 1116 { 1117 char *h, *s; 1118 # if SASL > 10509 1119 bool addrealm; 1120 # endif /* SASL > 10509 */ 1121 size_t l; 1122 SASL_AI_T *sai; 1123 char *authid = NULL; 1124 1125 if (result == NULL || context == NULL) 1126 return SASL_BADPARAM; 1127 sai = (SASL_AI_T *) context; 1128 1129 /* 1130 ** Unfortunately it is not clear whether this routine should 1131 ** return a copy of a string or just a pointer to a string. 1132 ** The Cyrus-SASL plugins treat these return values differently, e.g., 1133 ** plugins/cram.c free()s authid, plugings/digestmd5.c does not. 1134 ** The best solution to this problem is to fix Cyrus-SASL, but it 1135 ** seems there is nobody who creates patches... Hello CMU!? 1136 ** The second best solution is to have flags that tell this routine 1137 ** whether to return an malloc()ed copy. 1138 ** The next best solution is to always return an malloc()ed copy, 1139 ** and suffer from some memory leak, which is ugly for persistent 1140 ** queue runners. 1141 ** For now we go with the last solution... 1142 ** We can't use rpools (which would avoid this particular problem) 1143 ** as explained in sasl.c. 1144 */ 1145 1146 switch (id) 1147 { 1148 case SASL_CB_USER: 1149 l = strlen((*sai)[SASL_USER]) + 1; 1150 s = sm_sasl_malloc(l); 1151 if (s == NULL) 1152 { 1153 if (len != NULL) 1154 *len = 0; 1155 *result = NULL; 1156 return SASL_NOMEM; 1157 } 1158 (void) sm_strlcpy(s, (*sai)[SASL_USER], l); 1159 *result = s; 1160 if (tTd(95, 5)) 1161 sm_syslog(LOG_DEBUG, NOQID, "AUTH username '%s'", 1162 *result); 1163 if (len != NULL) 1164 *len = *result != NULL ? strlen(*result) : 0; 1165 break; 1166 1167 case SASL_CB_AUTHNAME: 1168 h = (*sai)[SASL_AUTHID]; 1169 # if SASL > 10509 1170 /* XXX maybe other mechanisms too?! */ 1171 addrealm = (*sai)[SASL_MECH] != NULL && 1172 sm_strcasecmp((*sai)[SASL_MECH], "CRAM-MD5") == 0; 1173 1174 /* 1175 ** Add realm to authentication id unless authid contains 1176 ** '@' (i.e., a realm) or the default realm is empty. 1177 */ 1178 1179 if (addrealm && h != NULL && strchr(h, '@') == NULL) 1180 { 1181 /* has this been done before? */ 1182 if ((*sai)[SASL_ID_REALM] == NULL) 1183 { 1184 char *realm; 1185 1186 realm = (*sai)[SASL_DEFREALM]; 1187 1188 /* do not add an empty realm */ 1189 if (*realm == '\0') 1190 { 1191 authid = h; 1192 (*sai)[SASL_ID_REALM] = NULL; 1193 } 1194 else 1195 { 1196 l = strlen(h) + strlen(realm) + 2; 1197 1198 /* should use rpool, but from where? */ 1199 authid = sm_sasl_malloc(l); 1200 if (authid != NULL) 1201 { 1202 (void) sm_snprintf(authid, l, 1203 "%s@%s", 1204 h, realm); 1205 (*sai)[SASL_ID_REALM] = authid; 1206 } 1207 else 1208 { 1209 authid = h; 1210 (*sai)[SASL_ID_REALM] = NULL; 1211 } 1212 } 1213 } 1214 else 1215 authid = (*sai)[SASL_ID_REALM]; 1216 } 1217 else 1218 # endif /* SASL > 10509 */ 1219 authid = h; 1220 l = strlen(authid) + 1; 1221 s = sm_sasl_malloc(l); 1222 if (s == NULL) 1223 { 1224 if (len != NULL) 1225 *len = 0; 1226 *result = NULL; 1227 return SASL_NOMEM; 1228 } 1229 (void) sm_strlcpy(s, authid, l); 1230 *result = s; 1231 if (tTd(95, 5)) 1232 sm_syslog(LOG_DEBUG, NOQID, "AUTH authid '%s'", 1233 *result); 1234 if (len != NULL) 1235 *len = authid ? strlen(authid) : 0; 1236 break; 1237 1238 case SASL_CB_LANGUAGE: 1239 *result = NULL; 1240 if (len != NULL) 1241 *len = 0; 1242 break; 1243 1244 default: 1245 return SASL_BADPARAM; 1246 } 1247 return SASL_OK; 1248 } 1249 /* 1250 ** GETSECRET -- callback to get password 1251 ** 1252 ** Parameters: 1253 ** conn -- connection information 1254 ** context -- sai 1255 ** id -- what to do 1256 ** psecret -- (pointer to) result 1257 ** 1258 ** Returns: 1259 ** OK/failure values 1260 */ 1261 1262 static int 1263 getsecret(conn, context, id, psecret) 1264 sasl_conn_t *conn; 1265 SM_UNUSED(void *context); 1266 int id; 1267 sasl_secret_t **psecret; 1268 { 1269 int len; 1270 char *authpass; 1271 SASL_AI_T *sai; 1272 1273 if (conn == NULL || psecret == NULL || id != SASL_CB_PASS) 1274 return SASL_BADPARAM; 1275 1276 sai = (SASL_AI_T *) context; 1277 authpass = (*sai)[SASL_PASSWORD]; 1278 len = strlen(authpass); 1279 *psecret = (sasl_secret_t *) sm_sasl_malloc(sizeof(sasl_secret_t) + 1280 len + 1); 1281 if (*psecret == NULL) 1282 return SASL_FAIL; 1283 (void) sm_strlcpy((*psecret)->data, authpass, len + 1); 1284 (*psecret)->len = (unsigned long) len; 1285 return SASL_OK; 1286 } 1287 # endif /* SASL >= 20000 */ 1288 1289 /* 1290 ** SAFESASLFILE -- callback for sasl: is file safe? 1291 ** 1292 ** Parameters: 1293 ** context -- pointer to context between invocations (unused) 1294 ** file -- name of file to check 1295 ** type -- type of file to check 1296 ** 1297 ** Returns: 1298 ** SASL_OK -- file can be used 1299 ** SASL_CONTINUE -- don't use file 1300 ** SASL_FAIL -- failure (not used here) 1301 ** 1302 */ 1303 1304 int 1305 #if SASL > 10515 1306 safesaslfile(context, file, type) 1307 #else /* SASL > 10515 */ 1308 safesaslfile(context, file) 1309 #endif /* SASL > 10515 */ 1310 void *context; 1311 # if SASL >= 20000 1312 const char *file; 1313 # else /* SASL >= 20000 */ 1314 char *file; 1315 # endif /* SASL >= 20000 */ 1316 #if SASL > 10515 1317 # if SASL >= 20000 1318 sasl_verify_type_t type; 1319 # else /* SASL >= 20000 */ 1320 int type; 1321 # endif /* SASL >= 20000 */ 1322 #endif /* SASL > 10515 */ 1323 { 1324 long sff; 1325 int r; 1326 #if SASL <= 10515 1327 size_t len; 1328 #endif /* SASL <= 10515 */ 1329 char *p; 1330 1331 if (file == NULL || *file == '\0') 1332 return SASL_OK; 1333 sff = SFF_SAFEDIRPATH|SFF_NOWLINK|SFF_NOWWFILES|SFF_ROOTOK; 1334 #if SASL <= 10515 1335 if ((p = strrchr(file, '/')) == NULL) 1336 p = file; 1337 else 1338 ++p; 1339 1340 /* everything beside libs and .conf files must not be readable */ 1341 len = strlen(p); 1342 if ((len <= 3 || strncmp(p, "lib", 3) != 0) && 1343 (len <= 5 || strncmp(p + len - 5, ".conf", 5) != 0)) 1344 { 1345 if (!bitnset(DBS_GROUPREADABLESASLDBFILE, DontBlameSendmail)) 1346 sff |= SFF_NORFILES; 1347 if (!bitnset(DBS_GROUPWRITABLESASLDBFILE, DontBlameSendmail)) 1348 sff |= SFF_NOGWFILES; 1349 } 1350 #else /* SASL <= 10515 */ 1351 /* files containing passwords should be not readable */ 1352 if (type == SASL_VRFY_PASSWD) 1353 { 1354 if (bitnset(DBS_GROUPREADABLESASLDBFILE, DontBlameSendmail)) 1355 sff |= SFF_NOWRFILES; 1356 else 1357 sff |= SFF_NORFILES; 1358 if (!bitnset(DBS_GROUPWRITABLESASLDBFILE, DontBlameSendmail)) 1359 sff |= SFF_NOGWFILES; 1360 } 1361 #endif /* SASL <= 10515 */ 1362 1363 p = (char *) file; 1364 if ((r = safefile(p, RunAsUid, RunAsGid, RunAsUserName, sff, 1365 S_IRUSR, NULL)) == 0) 1366 return SASL_OK; 1367 if (LogLevel > (r != ENOENT ? 8 : 10)) 1368 sm_syslog(LOG_WARNING, NOQID, "error: safesasl(%s) failed: %s", 1369 p, sm_errstring(r)); 1370 return SASL_CONTINUE; 1371 } 1372 1373 /* 1374 ** SASLGETREALM -- return the realm for SASL 1375 ** 1376 ** return the realm for the client 1377 ** 1378 ** Parameters: 1379 ** context -- context shared between invocations 1380 ** availrealms -- list of available realms 1381 ** {realm, realm, ...} 1382 ** result -- pointer to result 1383 ** 1384 ** Returns: 1385 ** failure/success 1386 */ 1387 1388 static int 1389 saslgetrealm(context, id, availrealms, result) 1390 void *context; 1391 int id; 1392 const char **availrealms; 1393 const char **result; 1394 { 1395 char *r; 1396 SASL_AI_T *sai; 1397 1398 sai = (SASL_AI_T *) context; 1399 if (sai == NULL) 1400 return SASL_FAIL; 1401 r = (*sai)[SASL_DEFREALM]; 1402 1403 if (LogLevel > 12) 1404 sm_syslog(LOG_INFO, NOQID, 1405 "AUTH=client, realm=%s, available realms=%s", 1406 r == NULL ? "<No Realm>" : r, 1407 (availrealms == NULL || *availrealms == NULL) 1408 ? "<No Realms>" : *availrealms); 1409 1410 /* check whether context is in list */ 1411 if (availrealms != NULL && *availrealms != NULL) 1412 { 1413 if (iteminlist(context, (char *)(*availrealms + 1), " ,}") == 1414 NULL) 1415 { 1416 if (LogLevel > 8) 1417 sm_syslog(LOG_ERR, NOQID, 1418 "AUTH=client, realm=%s not in list=%s", 1419 r, *availrealms); 1420 return SASL_FAIL; 1421 } 1422 } 1423 *result = r; 1424 return SASL_OK; 1425 } 1426 /* 1427 ** ITEMINLIST -- does item appear in list? 1428 ** 1429 ** Check whether item appears in list (which must be separated by a 1430 ** character in delim) as a "word", i.e. it must appear at the begin 1431 ** of the list or after a space, and it must end with a space or the 1432 ** end of the list. 1433 ** 1434 ** Parameters: 1435 ** item -- item to search. 1436 ** list -- list of items. 1437 ** delim -- list of delimiters. 1438 ** 1439 ** Returns: 1440 ** pointer to occurrence (NULL if not found). 1441 */ 1442 1443 char * 1444 iteminlist(item, list, delim) 1445 char *item; 1446 char *list; 1447 char *delim; 1448 { 1449 char *s; 1450 int len; 1451 1452 if (list == NULL || *list == '\0') 1453 return NULL; 1454 if (item == NULL || *item == '\0') 1455 return NULL; 1456 s = list; 1457 len = strlen(item); 1458 while (s != NULL && *s != '\0') 1459 { 1460 if (sm_strncasecmp(s, item, len) == 0 && 1461 (s[len] == '\0' || strchr(delim, s[len]) != NULL)) 1462 return s; 1463 s = strpbrk(s, delim); 1464 if (s != NULL) 1465 while (*++s == ' ') 1466 continue; 1467 } 1468 return NULL; 1469 } 1470 /* 1471 ** REMOVEMECH -- remove item [rem] from list [list] 1472 ** 1473 ** Parameters: 1474 ** rem -- item to remove 1475 ** list -- list of items 1476 ** rpool -- resource pool from which result is allocated. 1477 ** 1478 ** Returns: 1479 ** pointer to new list (NULL in case of error). 1480 */ 1481 1482 static char * 1483 removemech(rem, list, rpool) 1484 char *rem; 1485 char *list; 1486 SM_RPOOL_T *rpool; 1487 { 1488 char *ret; 1489 char *needle; 1490 int len; 1491 1492 if (list == NULL) 1493 return NULL; 1494 if (rem == NULL || *rem == '\0') 1495 { 1496 /* take out what? */ 1497 return NULL; 1498 } 1499 1500 /* find the item in the list */ 1501 if ((needle = iteminlist(rem, list, " ")) == NULL) 1502 { 1503 /* not in there: return original */ 1504 return list; 1505 } 1506 1507 /* length of string without rem */ 1508 len = strlen(list) - strlen(rem); 1509 if (len <= 0) 1510 { 1511 ret = (char *) sm_rpool_malloc_x(rpool, 1); 1512 *ret = '\0'; 1513 return ret; 1514 } 1515 ret = (char *) sm_rpool_malloc_x(rpool, len); 1516 memset(ret, '\0', len); 1517 1518 /* copy from start to removed item */ 1519 memcpy(ret, list, needle - list); 1520 1521 /* length of rest of string past removed item */ 1522 len = strlen(needle) - strlen(rem) - 1; 1523 if (len > 0) 1524 { 1525 /* not last item -- copy into string */ 1526 memcpy(ret + (needle - list), 1527 list + (needle - list) + strlen(rem) + 1, 1528 len); 1529 } 1530 else 1531 ret[(needle - list) - 1] = '\0'; 1532 return ret; 1533 } 1534 /* 1535 ** ATTEMPTAUTH -- try to AUTHenticate using one mechanism 1536 ** 1537 ** Parameters: 1538 ** m -- the mailer. 1539 ** mci -- the mailer connection structure. 1540 ** e -- the envelope (including the sender to specify). 1541 ** sai - sasl authinfo 1542 ** 1543 ** Returns: 1544 ** EX_OK -- authentication was successful. 1545 ** EX_NOPERM -- authentication failed. 1546 ** EX_IOERR -- authentication dialogue failed (I/O problem?). 1547 ** EX_TEMPFAIL -- temporary failure. 1548 ** 1549 */ 1550 1551 static int 1552 attemptauth(m, mci, e, sai) 1553 MAILER *m; 1554 MCI *mci; 1555 ENVELOPE *e; 1556 SASL_AI_T *sai; 1557 { 1558 int saslresult, smtpresult; 1559 # if SASL >= 20000 1560 sasl_ssf_t ssf; 1561 const char *auth_id; 1562 const char *out; 1563 # else /* SASL >= 20000 */ 1564 sasl_external_properties_t ssf; 1565 char *out; 1566 # endif /* SASL >= 20000 */ 1567 unsigned int outlen; 1568 sasl_interact_t *client_interact = NULL; 1569 char *mechusing; 1570 sasl_security_properties_t ssp; 1571 1572 /* MUST NOT be a multiple of 4: bug in some sasl_encode64() versions */ 1573 char in64[MAXOUTLEN + 1]; 1574 #if NETINET || (NETINET6 && SASL >= 20000) 1575 extern SOCKADDR CurHostAddr; 1576 #endif /* NETINET || (NETINET6 && SASL >= 20000) */ 1577 1578 /* no mechanism selected (yet) */ 1579 (*sai)[SASL_MECH] = NULL; 1580 1581 /* dispose old connection */ 1582 if (mci->mci_conn != NULL) 1583 sasl_dispose(&(mci->mci_conn)); 1584 1585 /* make a new client sasl connection */ 1586 # if SASL >= 20000 1587 /* 1588 ** We provide the callbacks again because global callbacks in 1589 ** sasl_client_init() are ignored if SASL has been initialized 1590 ** before, for example, by a library such as libnss-ldap. 1591 */ 1592 1593 saslresult = sasl_client_new(bitnset(M_LMTP, m->m_flags) ? "lmtp" 1594 : "smtp", 1595 CurHostName, NULL, NULL, callbacks, 0, 1596 &mci->mci_conn); 1597 # else /* SASL >= 20000 */ 1598 saslresult = sasl_client_new(bitnset(M_LMTP, m->m_flags) ? "lmtp" 1599 : "smtp", 1600 CurHostName, NULL, 0, &mci->mci_conn); 1601 # endif /* SASL >= 20000 */ 1602 if (saslresult != SASL_OK) 1603 return EX_TEMPFAIL; 1604 1605 /* set properties */ 1606 (void) memset(&ssp, '\0', sizeof(ssp)); 1607 1608 /* XXX should these be options settable via .cf ? */ 1609 { 1610 ssp.max_ssf = MaxSLBits; 1611 ssp.maxbufsize = MAXOUTLEN; 1612 # if 0 1613 ssp.security_flags = SASL_SEC_NOPLAINTEXT; 1614 # endif /* 0 */ 1615 } 1616 saslresult = sasl_setprop(mci->mci_conn, SASL_SEC_PROPS, &ssp); 1617 if (saslresult != SASL_OK) 1618 return EX_TEMPFAIL; 1619 1620 # if SASL >= 20000 1621 /* external security strength factor, authentication id */ 1622 ssf = 0; 1623 auth_id = NULL; 1624 # if STARTTLS 1625 out = macvalue(macid("{cert_subject}"), e); 1626 if (out != NULL && *out != '\0') 1627 auth_id = out; 1628 out = macvalue(macid("{cipher_bits}"), e); 1629 if (out != NULL && *out != '\0') 1630 ssf = atoi(out); 1631 # endif /* STARTTLS */ 1632 saslresult = sasl_setprop(mci->mci_conn, SASL_SSF_EXTERNAL, &ssf); 1633 if (saslresult != SASL_OK) 1634 return EX_TEMPFAIL; 1635 saslresult = sasl_setprop(mci->mci_conn, SASL_AUTH_EXTERNAL, auth_id); 1636 if (saslresult != SASL_OK) 1637 return EX_TEMPFAIL; 1638 1639 # if NETINET || NETINET6 1640 /* set local/remote ipv4 addresses */ 1641 if (mci->mci_out != NULL && ( 1642 # if NETINET6 1643 CurHostAddr.sa.sa_family == AF_INET6 || 1644 # endif /* NETINET6 */ 1645 CurHostAddr.sa.sa_family == AF_INET)) 1646 { 1647 SOCKADDR_LEN_T addrsize; 1648 SOCKADDR saddr_l; 1649 char localip[60], remoteip[60]; 1650 1651 switch (CurHostAddr.sa.sa_family) 1652 { 1653 case AF_INET: 1654 addrsize = sizeof(struct sockaddr_in); 1655 break; 1656 # if NETINET6 1657 case AF_INET6: 1658 addrsize = sizeof(struct sockaddr_in6); 1659 break; 1660 # endif /* NETINET6 */ 1661 default: 1662 break; 1663 } 1664 if (iptostring(&CurHostAddr, addrsize, 1665 remoteip, sizeof(remoteip))) 1666 { 1667 if (sasl_setprop(mci->mci_conn, SASL_IPREMOTEPORT, 1668 remoteip) != SASL_OK) 1669 return EX_TEMPFAIL; 1670 } 1671 addrsize = sizeof(saddr_l); 1672 if (getsockname(sm_io_getinfo(mci->mci_out, SM_IO_WHAT_FD, 1673 NULL), 1674 (struct sockaddr *) &saddr_l, &addrsize) == 0) 1675 { 1676 if (iptostring(&saddr_l, addrsize, 1677 localip, sizeof(localip))) 1678 { 1679 if (sasl_setprop(mci->mci_conn, 1680 SASL_IPLOCALPORT, 1681 localip) != SASL_OK) 1682 return EX_TEMPFAIL; 1683 } 1684 } 1685 } 1686 # endif /* NETINET || NETINET6 */ 1687 1688 /* start client side of sasl */ 1689 saslresult = sasl_client_start(mci->mci_conn, mci->mci_saslcap, 1690 &client_interact, 1691 &out, &outlen, 1692 (const char **) &mechusing); 1693 # else /* SASL >= 20000 */ 1694 /* external security strength factor, authentication id */ 1695 ssf.ssf = 0; 1696 ssf.auth_id = NULL; 1697 # if STARTTLS 1698 out = macvalue(macid("{cert_subject}"), e); 1699 if (out != NULL && *out != '\0') 1700 ssf.auth_id = out; 1701 out = macvalue(macid("{cipher_bits}"), e); 1702 if (out != NULL && *out != '\0') 1703 ssf.ssf = atoi(out); 1704 # endif /* STARTTLS */ 1705 saslresult = sasl_setprop(mci->mci_conn, SASL_SSF_EXTERNAL, &ssf); 1706 if (saslresult != SASL_OK) 1707 return EX_TEMPFAIL; 1708 1709 # if NETINET 1710 /* set local/remote ipv4 addresses */ 1711 if (mci->mci_out != NULL && CurHostAddr.sa.sa_family == AF_INET) 1712 { 1713 SOCKADDR_LEN_T addrsize; 1714 struct sockaddr_in saddr_l; 1715 1716 if (sasl_setprop(mci->mci_conn, SASL_IP_REMOTE, 1717 (struct sockaddr_in *) &CurHostAddr) 1718 != SASL_OK) 1719 return EX_TEMPFAIL; 1720 addrsize = sizeof(struct sockaddr_in); 1721 if (getsockname(sm_io_getinfo(mci->mci_out, SM_IO_WHAT_FD, 1722 NULL), 1723 (struct sockaddr *) &saddr_l, &addrsize) == 0) 1724 { 1725 if (sasl_setprop(mci->mci_conn, SASL_IP_LOCAL, 1726 &saddr_l) != SASL_OK) 1727 return EX_TEMPFAIL; 1728 } 1729 } 1730 # endif /* NETINET */ 1731 1732 /* start client side of sasl */ 1733 saslresult = sasl_client_start(mci->mci_conn, mci->mci_saslcap, 1734 NULL, &client_interact, 1735 &out, &outlen, 1736 (const char **) &mechusing); 1737 # endif /* SASL >= 20000 */ 1738 1739 if (saslresult != SASL_OK && saslresult != SASL_CONTINUE) 1740 { 1741 if (saslresult == SASL_NOMECH && LogLevel > 8) 1742 { 1743 sm_syslog(LOG_NOTICE, e->e_id, 1744 "AUTH=client, available mechanisms do not fulfill requirements"); 1745 } 1746 return EX_TEMPFAIL; 1747 } 1748 1749 /* just point current mechanism to the data in the sasl library */ 1750 (*sai)[SASL_MECH] = mechusing; 1751 1752 /* send the info across the wire */ 1753 if (out == NULL 1754 /* login and digest-md5 up to 1.5.28 set out="" */ 1755 || (outlen == 0 && 1756 (sm_strcasecmp(mechusing, "LOGIN") == 0 || 1757 sm_strcasecmp(mechusing, "DIGEST-MD5") == 0)) 1758 ) 1759 { 1760 /* no initial response */ 1761 smtpmessage("AUTH %s", m, mci, mechusing); 1762 } 1763 else if (outlen == 0) 1764 { 1765 /* 1766 ** zero-length initial response, per RFC 2554 4.: 1767 ** "Unlike a zero-length client answer to a 334 reply, a zero- 1768 ** length initial response is sent as a single equals sign" 1769 */ 1770 1771 smtpmessage("AUTH %s =", m, mci, mechusing); 1772 } 1773 else 1774 { 1775 saslresult = sasl_encode64(out, outlen, in64, sizeof(in64), 1776 NULL); 1777 if (saslresult != SASL_OK) /* internal error */ 1778 { 1779 if (LogLevel > 8) 1780 sm_syslog(LOG_ERR, e->e_id, 1781 "encode64 for AUTH failed"); 1782 return EX_TEMPFAIL; 1783 } 1784 smtpmessage("AUTH %s %s", m, mci, mechusing, in64); 1785 } 1786 # if SASL < 20000 1787 sm_sasl_free(out); /* XXX only if no rpool is used */ 1788 # endif /* SASL < 20000 */ 1789 1790 /* get the reply */ 1791 smtpresult = reply(m, mci, e, TimeOuts.to_auth, getsasldata, NULL, 1792 XS_AUTH); 1793 1794 for (;;) 1795 { 1796 /* check return code from server */ 1797 if (smtpresult == 235) 1798 { 1799 macdefine(&mci->mci_macro, A_TEMP, macid("{auth_type}"), 1800 mechusing); 1801 return EX_OK; 1802 } 1803 if (smtpresult == -1) 1804 return EX_IOERR; 1805 if (REPLYTYPE(smtpresult) == 5) 1806 return EX_NOPERM; /* ugly, but ... */ 1807 if (REPLYTYPE(smtpresult) != 3) 1808 { 1809 /* should we fail deliberately, see RFC 2554 4. ? */ 1810 /* smtpmessage("*", m, mci); */ 1811 return EX_TEMPFAIL; 1812 } 1813 1814 saslresult = sasl_client_step(mci->mci_conn, 1815 mci->mci_sasl_string, 1816 mci->mci_sasl_string_len, 1817 &client_interact, 1818 &out, &outlen); 1819 1820 if (saslresult != SASL_OK && saslresult != SASL_CONTINUE) 1821 { 1822 if (tTd(95, 5)) 1823 sm_dprintf("AUTH FAIL=%s (%d)\n", 1824 sasl_errstring(saslresult, NULL, NULL), 1825 saslresult); 1826 1827 /* fail deliberately, see RFC 2554 4. */ 1828 smtpmessage("*", m, mci); 1829 1830 /* 1831 ** but we should only fail for this authentication 1832 ** mechanism; how to do that? 1833 */ 1834 1835 smtpresult = reply(m, mci, e, TimeOuts.to_auth, 1836 getsasldata, NULL, XS_AUTH); 1837 return EX_NOPERM; 1838 } 1839 1840 if (outlen > 0) 1841 { 1842 saslresult = sasl_encode64(out, outlen, in64, 1843 sizeof(in64), NULL); 1844 if (saslresult != SASL_OK) 1845 { 1846 /* give an error reply to the other side! */ 1847 smtpmessage("*", m, mci); 1848 return EX_TEMPFAIL; 1849 } 1850 } 1851 else 1852 in64[0] = '\0'; 1853 # if SASL < 20000 1854 sm_sasl_free(out); /* XXX only if no rpool is used */ 1855 # endif /* SASL < 20000 */ 1856 smtpmessage("%s", m, mci, in64); 1857 smtpresult = reply(m, mci, e, TimeOuts.to_auth, 1858 getsasldata, NULL, XS_AUTH); 1859 } 1860 /* NOTREACHED */ 1861 } 1862 /* 1863 ** SMTPAUTH -- try to AUTHenticate 1864 ** 1865 ** This will try mechanisms in the order the sasl library decided until: 1866 ** - there are no more mechanisms 1867 ** - a mechanism succeeds 1868 ** - the sasl library fails initializing 1869 ** 1870 ** Parameters: 1871 ** m -- the mailer. 1872 ** mci -- the mailer connection info. 1873 ** e -- the envelope. 1874 ** 1875 ** Returns: 1876 ** EX_OK -- authentication was successful 1877 ** EX_UNAVAILABLE -- authentication not possible, e.g., 1878 ** no data available. 1879 ** EX_NOPERM -- authentication failed. 1880 ** EX_TEMPFAIL -- temporary failure. 1881 ** 1882 ** Notice: AuthInfo is used for all connections, hence we must 1883 ** return EX_TEMPFAIL only if we really want to retry, i.e., 1884 ** iff getauth() tempfailed or getauth() was used and 1885 ** authentication tempfailed. 1886 */ 1887 1888 int 1889 smtpauth(m, mci, e) 1890 MAILER *m; 1891 MCI *mci; 1892 ENVELOPE *e; 1893 { 1894 int result; 1895 int i; 1896 bool usedgetauth; 1897 1898 mci->mci_sasl_auth = false; 1899 for (i = 0; i < SASL_MECH ; i++) 1900 mci->mci_sai[i] = NULL; 1901 1902 result = getauth(mci, e, &(mci->mci_sai)); 1903 if (result == EX_TEMPFAIL) 1904 return result; 1905 usedgetauth = true; 1906 1907 /* no data available: don't try to authenticate */ 1908 if (result == EX_OK && mci->mci_sai[SASL_AUTHID] == NULL) 1909 return result; 1910 if (result != EX_OK) 1911 { 1912 if (SASLInfo == NULL) 1913 return EX_UNAVAILABLE; 1914 1915 /* read authinfo from file */ 1916 result = readauth(SASLInfo, true, &(mci->mci_sai), 1917 mci->mci_rpool); 1918 if (result != EX_OK) 1919 return result; 1920 usedgetauth = false; 1921 } 1922 1923 /* check whether sufficient data is available */ 1924 if (mci->mci_sai[SASL_PASSWORD] == NULL || 1925 *(mci->mci_sai)[SASL_PASSWORD] == '\0') 1926 return EX_UNAVAILABLE; 1927 if ((mci->mci_sai[SASL_AUTHID] == NULL || 1928 *(mci->mci_sai)[SASL_AUTHID] == '\0') && 1929 (mci->mci_sai[SASL_USER] == NULL || 1930 *(mci->mci_sai)[SASL_USER] == '\0')) 1931 return EX_UNAVAILABLE; 1932 1933 /* set the context for the callback function to sai */ 1934 # if SASL >= 20000 1935 callbacks[CB_PASS_IDX].context = (void *) mci; 1936 # else /* SASL >= 20000 */ 1937 callbacks[CB_PASS_IDX].context = (void *) &mci->mci_sai; 1938 # endif /* SASL >= 20000 */ 1939 callbacks[CB_USER_IDX].context = (void *) &mci->mci_sai; 1940 callbacks[CB_AUTHNAME_IDX].context = (void *) &mci->mci_sai; 1941 callbacks[CB_GETREALM_IDX].context = (void *) &mci->mci_sai; 1942 #if 0 1943 callbacks[CB_SAFESASL_IDX].context = (void *) &mci->mci_sai; 1944 #endif /* 0 */ 1945 1946 /* set default value for realm */ 1947 if ((mci->mci_sai)[SASL_DEFREALM] == NULL) 1948 (mci->mci_sai)[SASL_DEFREALM] = sm_rpool_strdup_x(e->e_rpool, 1949 macvalue('j', CurEnv)); 1950 1951 /* set default value for list of mechanism to use */ 1952 if ((mci->mci_sai)[SASL_MECHLIST] == NULL || 1953 *(mci->mci_sai)[SASL_MECHLIST] == '\0') 1954 (mci->mci_sai)[SASL_MECHLIST] = AuthMechanisms; 1955 1956 /* create list of mechanisms to try */ 1957 mci->mci_saslcap = intersect((mci->mci_sai)[SASL_MECHLIST], 1958 mci->mci_saslcap, mci->mci_rpool); 1959 1960 /* initialize sasl client library */ 1961 result = init_sasl_client(); 1962 if (result != SASL_OK) 1963 return usedgetauth ? EX_TEMPFAIL : EX_UNAVAILABLE; 1964 do 1965 { 1966 result = attemptauth(m, mci, e, &(mci->mci_sai)); 1967 if (result == EX_OK) 1968 mci->mci_sasl_auth = true; 1969 else if (result == EX_TEMPFAIL || result == EX_NOPERM) 1970 { 1971 mci->mci_saslcap = removemech((mci->mci_sai)[SASL_MECH], 1972 mci->mci_saslcap, 1973 mci->mci_rpool); 1974 if (mci->mci_saslcap == NULL || 1975 *(mci->mci_saslcap) == '\0') 1976 return usedgetauth ? result 1977 : EX_UNAVAILABLE; 1978 } 1979 else 1980 return result; 1981 } while (result != EX_OK); 1982 return result; 1983 } 1984 #endif /* SASL */ 1985 1986 /* 1987 ** SMTPMAILFROM -- send MAIL command 1988 ** 1989 ** Parameters: 1990 ** m -- the mailer. 1991 ** mci -- the mailer connection structure. 1992 ** e -- the envelope (including the sender to specify). 1993 */ 1994 1995 int 1996 smtpmailfrom(m, mci, e) 1997 MAILER *m; 1998 MCI *mci; 1999 ENVELOPE *e; 2000 { 2001 int r; 2002 char *bufp; 2003 char *bodytype; 2004 char *enhsc; 2005 char buf[MAXNAME + 1]; 2006 char optbuf[MAXLINE]; 2007 2008 if (tTd(18, 2)) 2009 sm_dprintf("smtpmailfrom: CurHost=%s\n", CurHostName); 2010 enhsc = NULL; 2011 2012 /* 2013 ** Check if connection is gone, if so 2014 ** it's a tempfail and we use mci_errno 2015 ** for the reason. 2016 */ 2017 2018 if (mci->mci_state == MCIS_CLOSED) 2019 { 2020 errno = mci->mci_errno; 2021 return EX_TEMPFAIL; 2022 } 2023 2024 /* set up appropriate options to include */ 2025 if (bitset(MCIF_SIZE, mci->mci_flags) && e->e_msgsize > 0) 2026 { 2027 (void) sm_snprintf(optbuf, sizeof(optbuf), " SIZE=%ld", 2028 e->e_msgsize); 2029 bufp = &optbuf[strlen(optbuf)]; 2030 } 2031 else 2032 { 2033 optbuf[0] = '\0'; 2034 bufp = optbuf; 2035 } 2036 2037 bodytype = e->e_bodytype; 2038 if (bitset(MCIF_8BITMIME, mci->mci_flags)) 2039 { 2040 if (bodytype == NULL && 2041 bitset(MM_MIME8BIT, MimeMode) && 2042 bitset(EF_HAS8BIT, e->e_flags) && 2043 !bitset(EF_DONT_MIME, e->e_flags) && 2044 !bitnset(M_8BITS, m->m_flags)) 2045 bodytype = "8BITMIME"; 2046 if (bodytype != NULL && 2047 SPACELEFT(optbuf, bufp) > strlen(bodytype) + 7) 2048 { 2049 (void) sm_snprintf(bufp, SPACELEFT(optbuf, bufp), 2050 " BODY=%s", bodytype); 2051 bufp += strlen(bufp); 2052 } 2053 } 2054 else if (bitnset(M_8BITS, m->m_flags) || 2055 !bitset(EF_HAS8BIT, e->e_flags) || 2056 bitset(MCIF_8BITOK, mci->mci_flags)) 2057 { 2058 /* EMPTY */ 2059 /* just pass it through */ 2060 } 2061 #if MIME8TO7 2062 else if (bitset(MM_CVTMIME, MimeMode) && 2063 !bitset(EF_DONT_MIME, e->e_flags) && 2064 (!bitset(MM_PASS8BIT, MimeMode) || 2065 bitset(EF_IS_MIME, e->e_flags))) 2066 { 2067 /* must convert from 8bit MIME format to 7bit encoded */ 2068 mci->mci_flags |= MCIF_CVT8TO7; 2069 } 2070 #endif /* MIME8TO7 */ 2071 else if (!bitset(MM_PASS8BIT, MimeMode)) 2072 { 2073 /* cannot just send a 8-bit version */ 2074 extern char MsgBuf[]; 2075 2076 usrerrenh("5.6.3", "%s does not support 8BITMIME", CurHostName); 2077 mci_setstat(mci, EX_NOTSTICKY, "5.6.3", MsgBuf); 2078 return EX_DATAERR; 2079 } 2080 2081 if (bitset(MCIF_DSN, mci->mci_flags)) 2082 { 2083 if (e->e_envid != NULL && 2084 SPACELEFT(optbuf, bufp) > strlen(e->e_envid) + 7) 2085 { 2086 (void) sm_snprintf(bufp, SPACELEFT(optbuf, bufp), 2087 " ENVID=%s", e->e_envid); 2088 bufp += strlen(bufp); 2089 } 2090 2091 /* RET= parameter */ 2092 if (bitset(EF_RET_PARAM, e->e_flags) && 2093 SPACELEFT(optbuf, bufp) > 9) 2094 { 2095 (void) sm_snprintf(bufp, SPACELEFT(optbuf, bufp), 2096 " RET=%s", 2097 bitset(EF_NO_BODY_RETN, e->e_flags) ? 2098 "HDRS" : "FULL"); 2099 bufp += strlen(bufp); 2100 } 2101 } 2102 2103 if (bitset(MCIF_AUTH, mci->mci_flags) && e->e_auth_param != NULL && 2104 SPACELEFT(optbuf, bufp) > strlen(e->e_auth_param) + 7 2105 #if SASL 2106 && (!bitset(SASL_AUTH_AUTH, SASLOpts) || mci->mci_sasl_auth) 2107 #endif /* SASL */ 2108 ) 2109 { 2110 (void) sm_snprintf(bufp, SPACELEFT(optbuf, bufp), 2111 " AUTH=%s", e->e_auth_param); 2112 bufp += strlen(bufp); 2113 } 2114 2115 /* 2116 ** 17 is the max length required, we could use log() to compute 2117 ** the exact length (and check IS_DLVR_TRACE()) 2118 */ 2119 2120 if (bitset(MCIF_DLVR_BY, mci->mci_flags) && 2121 IS_DLVR_BY(e) && SPACELEFT(optbuf, bufp) > 17) 2122 { 2123 long dby; 2124 2125 /* 2126 ** Avoid problems with delays (for R) since the check 2127 ** in deliver() whether min-deliver-time is sufficient. 2128 ** Alternatively we could pass the computed time to this 2129 ** function. 2130 */ 2131 2132 dby = e->e_deliver_by - (curtime() - e->e_ctime); 2133 if (dby <= 0 && IS_DLVR_RETURN(e)) 2134 dby = mci->mci_min_by <= 0 ? 1 : mci->mci_min_by; 2135 (void) sm_snprintf(bufp, SPACELEFT(optbuf, bufp), 2136 " BY=%ld;%c%s", 2137 dby, 2138 IS_DLVR_RETURN(e) ? 'R' : 'N', 2139 IS_DLVR_TRACE(e) ? "T" : ""); 2140 bufp += strlen(bufp); 2141 } 2142 2143 /* 2144 ** Send the MAIL command. 2145 ** Designates the sender. 2146 */ 2147 2148 mci->mci_state = MCIS_MAIL; 2149 2150 if (bitset(EF_RESPONSE, e->e_flags) && 2151 !bitnset(M_NO_NULL_FROM, m->m_flags)) 2152 buf[0] = '\0'; 2153 else 2154 expand("\201g", buf, sizeof(buf), e); 2155 if (buf[0] == '<') 2156 { 2157 /* strip off <angle brackets> (put back on below) */ 2158 bufp = &buf[strlen(buf) - 1]; 2159 if (*bufp == '>') 2160 *bufp = '\0'; 2161 bufp = &buf[1]; 2162 } 2163 else 2164 bufp = buf; 2165 if (bitnset(M_LOCALMAILER, e->e_from.q_mailer->m_flags) || 2166 !bitnset(M_FROMPATH, m->m_flags)) 2167 { 2168 smtpmessage("MAIL From:<%s>%s", m, mci, bufp, optbuf); 2169 } 2170 else 2171 { 2172 smtpmessage("MAIL From:<@%s%c%s>%s", m, mci, MyHostName, 2173 *bufp == '@' ? ',' : ':', bufp, optbuf); 2174 } 2175 SmtpPhase = mci->mci_phase = "client MAIL"; 2176 sm_setproctitle(true, e, "%s %s: %s", qid_printname(e), 2177 CurHostName, mci->mci_phase); 2178 r = reply(m, mci, e, TimeOuts.to_mail, NULL, &enhsc, XS_DEFAULT); 2179 if (r < 0) 2180 { 2181 /* communications failure */ 2182 mci_setstat(mci, EX_TEMPFAIL, "4.4.2", NULL); 2183 return EX_TEMPFAIL; 2184 } 2185 else if (r == SMTPCLOSING) 2186 { 2187 /* service shutting down: handled by reply() */ 2188 return EX_TEMPFAIL; 2189 } 2190 else if (REPLYTYPE(r) == 4) 2191 { 2192 mci_setstat(mci, EX_NOTSTICKY, ENHSCN(enhsc, smtptodsn(r)), 2193 SmtpReplyBuffer); 2194 return EX_TEMPFAIL; 2195 } 2196 else if (REPLYTYPE(r) == 2) 2197 { 2198 return EX_OK; 2199 } 2200 else if (r == 501) 2201 { 2202 /* syntax error in arguments */ 2203 mci_setstat(mci, EX_NOTSTICKY, ENHSCN(enhsc, "5.5.2"), 2204 SmtpReplyBuffer); 2205 return EX_DATAERR; 2206 } 2207 else if (r == 553) 2208 { 2209 /* mailbox name not allowed */ 2210 mci_setstat(mci, EX_NOTSTICKY, ENHSCN(enhsc, "5.1.3"), 2211 SmtpReplyBuffer); 2212 return EX_DATAERR; 2213 } 2214 else if (r == 552) 2215 { 2216 /* exceeded storage allocation */ 2217 mci_setstat(mci, EX_NOTSTICKY, ENHSCN(enhsc, "5.3.4"), 2218 SmtpReplyBuffer); 2219 if (bitset(MCIF_SIZE, mci->mci_flags)) 2220 e->e_flags |= EF_NO_BODY_RETN; 2221 return EX_UNAVAILABLE; 2222 } 2223 else if (REPLYTYPE(r) == 5) 2224 { 2225 /* unknown error */ 2226 mci_setstat(mci, EX_NOTSTICKY, ENHSCN(enhsc, "5.0.0"), 2227 SmtpReplyBuffer); 2228 return EX_UNAVAILABLE; 2229 } 2230 2231 if (LogLevel > 1) 2232 { 2233 sm_syslog(LOG_CRIT, e->e_id, 2234 "%.100s: SMTP MAIL protocol error: %s", 2235 CurHostName, 2236 shortenstring(SmtpReplyBuffer, 403)); 2237 } 2238 2239 /* protocol error -- close up */ 2240 mci_setstat(mci, EX_PROTOCOL, ENHSCN(enhsc, "5.5.1"), 2241 SmtpReplyBuffer); 2242 smtpquit(m, mci, e); 2243 return EX_PROTOCOL; 2244 } 2245 /* 2246 ** SMTPRCPT -- designate recipient. 2247 ** 2248 ** Parameters: 2249 ** to -- address of recipient. 2250 ** m -- the mailer we are sending to. 2251 ** mci -- the connection info for this transaction. 2252 ** e -- the envelope for this transaction. 2253 ** 2254 ** Returns: 2255 ** exit status corresponding to recipient status. 2256 ** 2257 ** Side Effects: 2258 ** Sends the mail via SMTP. 2259 */ 2260 2261 int 2262 smtprcpt(to, m, mci, e, ctladdr, xstart) 2263 ADDRESS *to; 2264 register MAILER *m; 2265 MCI *mci; 2266 ENVELOPE *e; 2267 ADDRESS *ctladdr; 2268 time_t xstart; 2269 { 2270 char *bufp; 2271 char optbuf[MAXLINE]; 2272 2273 #if PIPELINING 2274 /* 2275 ** If there is status waiting from the other end, read it. 2276 ** This should normally happen because of SMTP pipelining. 2277 */ 2278 2279 while (mci->mci_nextaddr != NULL && 2280 sm_io_getinfo(mci->mci_in, SM_IO_IS_READABLE, NULL) > 0) 2281 { 2282 int r; 2283 2284 r = smtprcptstat(mci->mci_nextaddr, m, mci, e); 2285 if (r != EX_OK) 2286 { 2287 markfailure(e, mci->mci_nextaddr, mci, r, false); 2288 giveresponse(r, mci->mci_nextaddr->q_status, m, mci, 2289 ctladdr, xstart, e, to); 2290 } 2291 mci->mci_nextaddr = mci->mci_nextaddr->q_pchain; 2292 } 2293 #endif /* PIPELINING */ 2294 2295 /* 2296 ** Check if connection is gone, if so 2297 ** it's a tempfail and we use mci_errno 2298 ** for the reason. 2299 */ 2300 2301 if (mci->mci_state == MCIS_CLOSED) 2302 { 2303 errno = mci->mci_errno; 2304 return EX_TEMPFAIL; 2305 } 2306 2307 optbuf[0] = '\0'; 2308 bufp = optbuf; 2309 2310 /* 2311 ** Warning: in the following it is assumed that the free space 2312 ** in bufp is sizeof(optbuf) 2313 */ 2314 2315 if (bitset(MCIF_DSN, mci->mci_flags)) 2316 { 2317 if (IS_DLVR_NOTIFY(e) && 2318 !bitset(MCIF_DLVR_BY, mci->mci_flags)) 2319 { 2320 /* RFC 2852: 4.1.4.2 */ 2321 if (!bitset(QHASNOTIFY, to->q_flags)) 2322 to->q_flags |= QPINGONFAILURE|QPINGONDELAY|QHASNOTIFY; 2323 else if (bitset(QPINGONSUCCESS, to->q_flags) || 2324 bitset(QPINGONFAILURE, to->q_flags) || 2325 bitset(QPINGONDELAY, to->q_flags)) 2326 to->q_flags |= QPINGONDELAY; 2327 } 2328 2329 /* NOTIFY= parameter */ 2330 if (bitset(QHASNOTIFY, to->q_flags) && 2331 bitset(QPRIMARY, to->q_flags) && 2332 !bitnset(M_LOCALMAILER, m->m_flags)) 2333 { 2334 bool firstone = true; 2335 2336 (void) sm_strlcat(bufp, " NOTIFY=", sizeof(optbuf)); 2337 if (bitset(QPINGONSUCCESS, to->q_flags)) 2338 { 2339 (void) sm_strlcat(bufp, "SUCCESS", sizeof(optbuf)); 2340 firstone = false; 2341 } 2342 if (bitset(QPINGONFAILURE, to->q_flags)) 2343 { 2344 if (!firstone) 2345 (void) sm_strlcat(bufp, ",", 2346 sizeof(optbuf)); 2347 (void) sm_strlcat(bufp, "FAILURE", sizeof(optbuf)); 2348 firstone = false; 2349 } 2350 if (bitset(QPINGONDELAY, to->q_flags)) 2351 { 2352 if (!firstone) 2353 (void) sm_strlcat(bufp, ",", 2354 sizeof(optbuf)); 2355 (void) sm_strlcat(bufp, "DELAY", sizeof(optbuf)); 2356 firstone = false; 2357 } 2358 if (firstone) 2359 (void) sm_strlcat(bufp, "NEVER", sizeof(optbuf)); 2360 bufp += strlen(bufp); 2361 } 2362 2363 /* ORCPT= parameter */ 2364 if (to->q_orcpt != NULL && 2365 SPACELEFT(optbuf, bufp) > strlen(to->q_orcpt) + 7) 2366 { 2367 (void) sm_snprintf(bufp, SPACELEFT(optbuf, bufp), 2368 " ORCPT=%s", to->q_orcpt); 2369 bufp += strlen(bufp); 2370 } 2371 } 2372 2373 smtpmessage("RCPT To:<%s>%s", m, mci, to->q_user, optbuf); 2374 mci->mci_state = MCIS_RCPT; 2375 2376 SmtpPhase = mci->mci_phase = "client RCPT"; 2377 sm_setproctitle(true, e, "%s %s: %s", qid_printname(e), 2378 CurHostName, mci->mci_phase); 2379 2380 #if PIPELINING 2381 /* 2382 ** If running SMTP pipelining, we will pick up status later 2383 */ 2384 2385 if (bitset(MCIF_PIPELINED, mci->mci_flags)) 2386 return EX_OK; 2387 #endif /* PIPELINING */ 2388 2389 return smtprcptstat(to, m, mci, e); 2390 } 2391 /* 2392 ** SMTPRCPTSTAT -- get recipient status 2393 ** 2394 ** This is only called during SMTP pipelining 2395 ** 2396 ** Parameters: 2397 ** to -- address of recipient. 2398 ** m -- mailer being sent to. 2399 ** mci -- the mailer connection information. 2400 ** e -- the envelope for this message. 2401 ** 2402 ** Returns: 2403 ** EX_* -- protocol status 2404 */ 2405 2406 static int 2407 smtprcptstat(to, m, mci, e) 2408 ADDRESS *to; 2409 MAILER *m; 2410 register MCI *mci; 2411 register ENVELOPE *e; 2412 { 2413 int r; 2414 int save_errno; 2415 char *enhsc; 2416 2417 /* 2418 ** Check if connection is gone, if so 2419 ** it's a tempfail and we use mci_errno 2420 ** for the reason. 2421 */ 2422 2423 if (mci->mci_state == MCIS_CLOSED) 2424 { 2425 errno = mci->mci_errno; 2426 return EX_TEMPFAIL; 2427 } 2428 2429 enhsc = NULL; 2430 r = reply(m, mci, e, TimeOuts.to_rcpt, NULL, &enhsc, XS_DEFAULT); 2431 save_errno = errno; 2432 to->q_rstatus = sm_rpool_strdup_x(e->e_rpool, SmtpReplyBuffer); 2433 to->q_status = ENHSCN_RPOOL(enhsc, smtptodsn(r), e->e_rpool); 2434 if (!bitnset(M_LMTP, m->m_flags)) 2435 to->q_statmta = mci->mci_host; 2436 if (r < 0 || REPLYTYPE(r) == 4) 2437 { 2438 mci->mci_retryrcpt = true; 2439 errno = save_errno; 2440 return EX_TEMPFAIL; 2441 } 2442 else if (REPLYTYPE(r) == 2) 2443 { 2444 char *t; 2445 2446 if ((t = mci->mci_tolist) != NULL) 2447 { 2448 char *p; 2449 2450 *t++ = ','; 2451 for (p = to->q_paddr; *p != '\0'; *t++ = *p++) 2452 continue; 2453 *t = '\0'; 2454 mci->mci_tolist = t; 2455 } 2456 #if PIPELINING 2457 mci->mci_okrcpts++; 2458 #endif /* PIPELINING */ 2459 return EX_OK; 2460 } 2461 else if (r == 550) 2462 { 2463 to->q_status = ENHSCN_RPOOL(enhsc, "5.1.1", e->e_rpool); 2464 return EX_NOUSER; 2465 } 2466 else if (r == 551) 2467 { 2468 to->q_status = ENHSCN_RPOOL(enhsc, "5.1.6", e->e_rpool); 2469 return EX_NOUSER; 2470 } 2471 else if (r == 553) 2472 { 2473 to->q_status = ENHSCN_RPOOL(enhsc, "5.1.3", e->e_rpool); 2474 return EX_NOUSER; 2475 } 2476 else if (REPLYTYPE(r) == 5) 2477 { 2478 return EX_UNAVAILABLE; 2479 } 2480 2481 if (LogLevel > 1) 2482 { 2483 sm_syslog(LOG_CRIT, e->e_id, 2484 "%.100s: SMTP RCPT protocol error: %s", 2485 CurHostName, 2486 shortenstring(SmtpReplyBuffer, 403)); 2487 } 2488 2489 mci_setstat(mci, EX_PROTOCOL, ENHSCN(enhsc, "5.5.1"), 2490 SmtpReplyBuffer); 2491 return EX_PROTOCOL; 2492 } 2493 /* 2494 ** SMTPDATA -- send the data and clean up the transaction. 2495 ** 2496 ** Parameters: 2497 ** m -- mailer being sent to. 2498 ** mci -- the mailer connection information. 2499 ** e -- the envelope for this message. 2500 ** 2501 ** Returns: 2502 ** exit status corresponding to DATA command. 2503 */ 2504 2505 int 2506 smtpdata(m, mci, e, ctladdr, xstart) 2507 MAILER *m; 2508 register MCI *mci; 2509 register ENVELOPE *e; 2510 ADDRESS *ctladdr; 2511 time_t xstart; 2512 { 2513 register int r; 2514 int rstat; 2515 int xstat; 2516 int timeout; 2517 char *enhsc; 2518 2519 /* 2520 ** Check if connection is gone, if so 2521 ** it's a tempfail and we use mci_errno 2522 ** for the reason. 2523 */ 2524 2525 if (mci->mci_state == MCIS_CLOSED) 2526 { 2527 errno = mci->mci_errno; 2528 return EX_TEMPFAIL; 2529 } 2530 2531 enhsc = NULL; 2532 2533 /* 2534 ** Send the data. 2535 ** First send the command and check that it is ok. 2536 ** Then send the data (if there are valid recipients). 2537 ** Follow it up with a dot to terminate. 2538 ** Finally get the results of the transaction. 2539 */ 2540 2541 /* send the command and check ok to proceed */ 2542 smtpmessage("DATA", m, mci); 2543 2544 #if PIPELINING 2545 if (mci->mci_nextaddr != NULL) 2546 { 2547 char *oldto = e->e_to; 2548 2549 /* pick up any pending RCPT responses for SMTP pipelining */ 2550 while (mci->mci_nextaddr != NULL) 2551 { 2552 int r; 2553 2554 e->e_to = mci->mci_nextaddr->q_paddr; 2555 r = smtprcptstat(mci->mci_nextaddr, m, mci, e); 2556 if (r != EX_OK) 2557 { 2558 markfailure(e, mci->mci_nextaddr, mci, r, 2559 false); 2560 giveresponse(r, mci->mci_nextaddr->q_status, m, 2561 mci, ctladdr, xstart, e, 2562 mci->mci_nextaddr); 2563 if (r == EX_TEMPFAIL) 2564 mci->mci_nextaddr->q_state = QS_RETRY; 2565 } 2566 mci->mci_nextaddr = mci->mci_nextaddr->q_pchain; 2567 } 2568 e->e_to = oldto; 2569 2570 /* 2571 ** Connection might be closed in response to a RCPT command, 2572 ** i.e., the server responded with 421. In that case (at 2573 ** least) one RCPT has a temporary failure, hence we don't 2574 ** need to check mci_okrcpts (as it is done below) to figure 2575 ** out which error to return. 2576 */ 2577 2578 if (mci->mci_state == MCIS_CLOSED) 2579 { 2580 errno = mci->mci_errno; 2581 return EX_TEMPFAIL; 2582 } 2583 } 2584 #endif /* PIPELINING */ 2585 2586 /* now proceed with DATA phase */ 2587 SmtpPhase = mci->mci_phase = "client DATA 354"; 2588 mci->mci_state = MCIS_DATA; 2589 sm_setproctitle(true, e, "%s %s: %s", 2590 qid_printname(e), CurHostName, mci->mci_phase); 2591 r = reply(m, mci, e, TimeOuts.to_datainit, NULL, &enhsc, XS_DEFAULT); 2592 if (r < 0 || REPLYTYPE(r) == 4) 2593 { 2594 if (r >= 0) 2595 smtpquit(m, mci, e); 2596 errno = mci->mci_errno; 2597 return EX_TEMPFAIL; 2598 } 2599 else if (REPLYTYPE(r) == 5) 2600 { 2601 smtprset(m, mci, e); 2602 #if PIPELINING 2603 if (mci->mci_okrcpts <= 0) 2604 return mci->mci_retryrcpt ? EX_TEMPFAIL 2605 : EX_UNAVAILABLE; 2606 #endif /* PIPELINING */ 2607 return EX_UNAVAILABLE; 2608 } 2609 else if (REPLYTYPE(r) != 3) 2610 { 2611 if (LogLevel > 1) 2612 { 2613 sm_syslog(LOG_CRIT, e->e_id, 2614 "%.100s: SMTP DATA-1 protocol error: %s", 2615 CurHostName, 2616 shortenstring(SmtpReplyBuffer, 403)); 2617 } 2618 smtprset(m, mci, e); 2619 mci_setstat(mci, EX_PROTOCOL, ENHSCN(enhsc, "5.5.1"), 2620 SmtpReplyBuffer); 2621 #if PIPELINING 2622 if (mci->mci_okrcpts <= 0) 2623 return mci->mci_retryrcpt ? EX_TEMPFAIL 2624 : EX_PROTOCOL; 2625 #endif /* PIPELINING */ 2626 return EX_PROTOCOL; 2627 } 2628 2629 #if PIPELINING 2630 if (mci->mci_okrcpts > 0) 2631 { 2632 #endif /* PIPELINING */ 2633 2634 /* 2635 ** Set timeout around data writes. Make it at least large 2636 ** enough for DNS timeouts on all recipients plus some fudge 2637 ** factor. The main thing is that it should not be infinite. 2638 */ 2639 2640 if (tTd(18, 101)) 2641 { 2642 /* simulate a DATA timeout */ 2643 timeout = 10; 2644 } 2645 else 2646 timeout = DATA_PROGRESS_TIMEOUT * 1000; 2647 sm_io_setinfo(mci->mci_out, SM_IO_WHAT_TIMEOUT, &timeout); 2648 2649 2650 /* 2651 ** Output the actual message. 2652 */ 2653 2654 if (!(*e->e_puthdr)(mci, e->e_header, e, M87F_OUTER)) 2655 goto writeerr; 2656 2657 if (tTd(18, 101)) 2658 { 2659 /* simulate a DATA timeout */ 2660 (void) sleep(2); 2661 } 2662 2663 if (!(*e->e_putbody)(mci, e, NULL)) 2664 goto writeerr; 2665 2666 /* 2667 ** Cleanup after sending message. 2668 */ 2669 2670 2671 #if PIPELINING 2672 } 2673 #endif /* PIPELINING */ 2674 2675 #if _FFR_CATCH_BROKEN_MTAS 2676 if (sm_io_getinfo(mci->mci_in, SM_IO_IS_READABLE, NULL) > 0) 2677 { 2678 /* terminate the message */ 2679 (void) sm_io_fprintf(mci->mci_out, SM_TIME_DEFAULT, ".%s", 2680 m->m_eol); 2681 if (TrafficLogFile != NULL) 2682 (void) sm_io_fprintf(TrafficLogFile, SM_TIME_DEFAULT, 2683 "%05d >>> .\n", (int) CurrentPid); 2684 if (Verbose) 2685 nmessage(">>> ."); 2686 2687 sm_syslog(LOG_CRIT, e->e_id, 2688 "%.100s: SMTP DATA-1 protocol error: remote server returned response before final dot", 2689 CurHostName); 2690 mci->mci_errno = EIO; 2691 mci->mci_state = MCIS_ERROR; 2692 mci_setstat(mci, EX_PROTOCOL, "5.5.0", NULL); 2693 smtpquit(m, mci, e); 2694 return EX_PROTOCOL; 2695 } 2696 #endif /* _FFR_CATCH_BROKEN_MTAS */ 2697 2698 if (sm_io_error(mci->mci_out)) 2699 { 2700 /* error during processing -- don't send the dot */ 2701 mci->mci_errno = EIO; 2702 mci->mci_state = MCIS_ERROR; 2703 mci_setstat(mci, EX_IOERR, "4.4.2", NULL); 2704 smtpquit(m, mci, e); 2705 return EX_IOERR; 2706 } 2707 2708 /* terminate the message */ 2709 if (sm_io_fprintf(mci->mci_out, SM_TIME_DEFAULT, "%s.%s", 2710 bitset(MCIF_INLONGLINE, mci->mci_flags) ? m->m_eol : "", 2711 m->m_eol) == SM_IO_EOF) 2712 goto writeerr; 2713 if (TrafficLogFile != NULL) 2714 (void) sm_io_fprintf(TrafficLogFile, SM_TIME_DEFAULT, 2715 "%05d >>> .\n", (int) CurrentPid); 2716 if (Verbose) 2717 nmessage(">>> ."); 2718 2719 /* check for the results of the transaction */ 2720 SmtpPhase = mci->mci_phase = "client DATA status"; 2721 sm_setproctitle(true, e, "%s %s: %s", qid_printname(e), 2722 CurHostName, mci->mci_phase); 2723 if (bitnset(M_LMTP, m->m_flags)) 2724 return EX_OK; 2725 r = reply(m, mci, e, TimeOuts.to_datafinal, NULL, &enhsc, XS_DEFAULT); 2726 if (r < 0) 2727 return EX_TEMPFAIL; 2728 if (mci->mci_state == MCIS_DATA) 2729 mci->mci_state = MCIS_OPEN; 2730 xstat = EX_NOTSTICKY; 2731 if (r == 452) 2732 rstat = EX_TEMPFAIL; 2733 else if (REPLYTYPE(r) == 4) 2734 rstat = xstat = EX_TEMPFAIL; 2735 else if (REPLYTYPE(r) == 2) 2736 rstat = xstat = EX_OK; 2737 else if (REPLYCLASS(r) != 5) 2738 rstat = xstat = EX_PROTOCOL; 2739 else if (REPLYTYPE(r) == 5) 2740 rstat = EX_UNAVAILABLE; 2741 else 2742 rstat = EX_PROTOCOL; 2743 mci_setstat(mci, xstat, ENHSCN(enhsc, smtptodsn(r)), 2744 SmtpReplyBuffer); 2745 if (bitset(MCIF_ENHSTAT, mci->mci_flags) && 2746 (r = isenhsc(SmtpReplyBuffer + 4, ' ')) > 0) 2747 r += 5; 2748 else 2749 r = 4; 2750 e->e_statmsg = sm_rpool_strdup_x(e->e_rpool, &SmtpReplyBuffer[r]); 2751 SmtpPhase = mci->mci_phase = "idle"; 2752 sm_setproctitle(true, e, "%s: %s", CurHostName, mci->mci_phase); 2753 if (rstat != EX_PROTOCOL) 2754 return rstat; 2755 if (LogLevel > 1) 2756 { 2757 sm_syslog(LOG_CRIT, e->e_id, 2758 "%.100s: SMTP DATA-2 protocol error: %s", 2759 CurHostName, 2760 shortenstring(SmtpReplyBuffer, 403)); 2761 } 2762 return rstat; 2763 2764 writeerr: 2765 mci->mci_errno = errno; 2766 mci->mci_state = MCIS_ERROR; 2767 mci_setstat(mci, EX_TEMPFAIL, "4.4.2", NULL); 2768 2769 /* 2770 ** If putbody() couldn't finish due to a timeout, 2771 ** rewind it here in the timeout handler. See 2772 ** comments at the end of putbody() for reasoning. 2773 */ 2774 2775 if (e->e_dfp != NULL) 2776 (void) bfrewind(e->e_dfp); 2777 2778 errno = mci->mci_errno; 2779 syserr("451 4.4.1 timeout writing message to %s", CurHostName); 2780 smtpquit(m, mci, e); 2781 return EX_TEMPFAIL; 2782 } 2783 2784 /* 2785 ** SMTPGETSTAT -- get status code from DATA in LMTP 2786 ** 2787 ** Parameters: 2788 ** m -- the mailer to which we are sending the message. 2789 ** mci -- the mailer connection structure. 2790 ** e -- the current envelope. 2791 ** 2792 ** Returns: 2793 ** The exit status corresponding to the reply code. 2794 */ 2795 2796 int 2797 smtpgetstat(m, mci, e) 2798 MAILER *m; 2799 MCI *mci; 2800 ENVELOPE *e; 2801 { 2802 int r; 2803 int off; 2804 int status, xstat; 2805 char *enhsc; 2806 2807 enhsc = NULL; 2808 2809 /* check for the results of the transaction */ 2810 r = reply(m, mci, e, TimeOuts.to_datafinal, NULL, &enhsc, XS_DEFAULT); 2811 if (r < 0) 2812 return EX_TEMPFAIL; 2813 xstat = EX_NOTSTICKY; 2814 if (REPLYTYPE(r) == 4) 2815 status = EX_TEMPFAIL; 2816 else if (REPLYTYPE(r) == 2) 2817 status = xstat = EX_OK; 2818 else if (REPLYCLASS(r) != 5) 2819 status = xstat = EX_PROTOCOL; 2820 else if (REPLYTYPE(r) == 5) 2821 status = EX_UNAVAILABLE; 2822 else 2823 status = EX_PROTOCOL; 2824 if (bitset(MCIF_ENHSTAT, mci->mci_flags) && 2825 (off = isenhsc(SmtpReplyBuffer + 4, ' ')) > 0) 2826 off += 5; 2827 else 2828 off = 4; 2829 e->e_statmsg = sm_rpool_strdup_x(e->e_rpool, &SmtpReplyBuffer[off]); 2830 mci_setstat(mci, xstat, ENHSCN(enhsc, smtptodsn(r)), SmtpReplyBuffer); 2831 if (LogLevel > 1 && status == EX_PROTOCOL) 2832 { 2833 sm_syslog(LOG_CRIT, e->e_id, 2834 "%.100s: SMTP DATA-3 protocol error: %s", 2835 CurHostName, 2836 shortenstring(SmtpReplyBuffer, 403)); 2837 } 2838 return status; 2839 } 2840 /* 2841 ** SMTPQUIT -- close the SMTP connection. 2842 ** 2843 ** Parameters: 2844 ** m -- a pointer to the mailer. 2845 ** mci -- the mailer connection information. 2846 ** e -- the current envelope. 2847 ** 2848 ** Returns: 2849 ** none. 2850 ** 2851 ** Side Effects: 2852 ** sends the final protocol and closes the connection. 2853 */ 2854 2855 void 2856 smtpquit(m, mci, e) 2857 register MAILER *m; 2858 register MCI *mci; 2859 ENVELOPE *e; 2860 { 2861 bool oldSuprErrs = SuprErrs; 2862 int rcode; 2863 char *oldcurhost; 2864 2865 if (mci->mci_state == MCIS_CLOSED) 2866 { 2867 mci_close(mci, "smtpquit:1"); 2868 return; 2869 } 2870 2871 oldcurhost = CurHostName; 2872 CurHostName = mci->mci_host; /* XXX UGLY XXX */ 2873 if (CurHostName == NULL) 2874 CurHostName = MyHostName; 2875 2876 #if PIPELINING 2877 mci->mci_okrcpts = 0; 2878 #endif /* PIPELINING */ 2879 2880 /* 2881 ** Suppress errors here -- we may be processing a different 2882 ** job when we do the quit connection, and we don't want the 2883 ** new job to be penalized for something that isn't it's 2884 ** problem. 2885 */ 2886 2887 SuprErrs = true; 2888 2889 /* send the quit message if we haven't gotten I/O error */ 2890 if (mci->mci_state != MCIS_ERROR && 2891 mci->mci_state != MCIS_QUITING) 2892 { 2893 SmtpPhase = "client QUIT"; 2894 mci->mci_state = MCIS_QUITING; 2895 smtpmessage("QUIT", m, mci); 2896 (void) reply(m, mci, e, TimeOuts.to_quit, NULL, NULL, 2897 XS_DEFAULT); 2898 SuprErrs = oldSuprErrs; 2899 if (mci->mci_state == MCIS_CLOSED) 2900 goto end; 2901 } 2902 2903 /* now actually close the connection and pick up the zombie */ 2904 rcode = endmailer(mci, e, NULL); 2905 if (rcode != EX_OK) 2906 { 2907 char *mailer = NULL; 2908 2909 if (mci->mci_mailer != NULL && 2910 mci->mci_mailer->m_name != NULL) 2911 mailer = mci->mci_mailer->m_name; 2912 2913 /* look for naughty mailers */ 2914 sm_syslog(LOG_ERR, e->e_id, 2915 "smtpquit: mailer%s%s exited with exit value %d", 2916 mailer == NULL ? "" : " ", 2917 mailer == NULL ? "" : mailer, 2918 rcode); 2919 } 2920 2921 SuprErrs = oldSuprErrs; 2922 2923 end: 2924 CurHostName = oldcurhost; 2925 return; 2926 } 2927 /* 2928 ** SMTPRSET -- send a RSET (reset) command 2929 ** 2930 ** Parameters: 2931 ** m -- a pointer to the mailer. 2932 ** mci -- the mailer connection information. 2933 ** e -- the current envelope. 2934 ** 2935 ** Returns: 2936 ** none. 2937 ** 2938 ** Side Effects: 2939 ** closes the connection if there is no reply to RSET. 2940 */ 2941 2942 void 2943 smtprset(m, mci, e) 2944 register MAILER *m; 2945 register MCI *mci; 2946 ENVELOPE *e; 2947 { 2948 int r; 2949 2950 CurHostName = mci->mci_host; /* XXX UGLY XXX */ 2951 if (CurHostName == NULL) 2952 CurHostName = MyHostName; 2953 2954 #if PIPELINING 2955 mci->mci_okrcpts = 0; 2956 #endif /* PIPELINING */ 2957 2958 /* 2959 ** Check if connection is gone, if so 2960 ** it's a tempfail and we use mci_errno 2961 ** for the reason. 2962 */ 2963 2964 if (mci->mci_state == MCIS_CLOSED) 2965 { 2966 errno = mci->mci_errno; 2967 return; 2968 } 2969 2970 SmtpPhase = "client RSET"; 2971 smtpmessage("RSET", m, mci); 2972 r = reply(m, mci, e, TimeOuts.to_rset, NULL, NULL, XS_DEFAULT); 2973 if (r < 0) 2974 return; 2975 2976 /* 2977 ** Any response is deemed to be acceptable. 2978 ** The standard does not state the proper action 2979 ** to take when a value other than 250 is received. 2980 ** 2981 ** However, if 421 is returned for the RSET, leave 2982 ** mci_state alone (MCIS_SSD can be set in reply() 2983 ** and MCIS_CLOSED can be set in smtpquit() if 2984 ** reply() gets a 421 and calls smtpquit()). 2985 */ 2986 2987 if (mci->mci_state != MCIS_SSD && mci->mci_state != MCIS_CLOSED) 2988 mci->mci_state = MCIS_OPEN; 2989 else if (mci->mci_exitstat == EX_OK) 2990 mci_setstat(mci, EX_TEMPFAIL, "4.5.0", NULL); 2991 } 2992 /* 2993 ** SMTPPROBE -- check the connection state 2994 ** 2995 ** Parameters: 2996 ** mci -- the mailer connection information. 2997 ** 2998 ** Returns: 2999 ** none. 3000 ** 3001 ** Side Effects: 3002 ** closes the connection if there is no reply to RSET. 3003 */ 3004 3005 int 3006 smtpprobe(mci) 3007 register MCI *mci; 3008 { 3009 int r; 3010 MAILER *m = mci->mci_mailer; 3011 ENVELOPE *e; 3012 extern ENVELOPE BlankEnvelope; 3013 3014 CurHostName = mci->mci_host; /* XXX UGLY XXX */ 3015 if (CurHostName == NULL) 3016 CurHostName = MyHostName; 3017 3018 e = &BlankEnvelope; 3019 SmtpPhase = "client probe"; 3020 smtpmessage("RSET", m, mci); 3021 r = reply(m, mci, e, TimeOuts.to_miscshort, NULL, NULL, XS_DEFAULT); 3022 if (REPLYTYPE(r) != 2) 3023 smtpquit(m, mci, e); 3024 return r; 3025 } 3026 /* 3027 ** REPLY -- read arpanet reply 3028 ** 3029 ** Parameters: 3030 ** m -- the mailer we are reading the reply from. 3031 ** mci -- the mailer connection info structure. 3032 ** e -- the current envelope. 3033 ** timeout -- the timeout for reads. 3034 ** pfunc -- processing function called on each line of response. 3035 ** If null, no special processing is done. 3036 ** enhstat -- optional, returns enhanced error code string (if set) 3037 ** rtype -- type of SmtpMsgBuffer: does it contains secret data? 3038 ** 3039 ** Returns: 3040 ** reply code it reads. 3041 ** 3042 ** Side Effects: 3043 ** flushes the mail file. 3044 */ 3045 3046 int 3047 reply(m, mci, e, timeout, pfunc, enhstat, rtype) 3048 MAILER *m; 3049 MCI *mci; 3050 ENVELOPE *e; 3051 time_t timeout; 3052 void (*pfunc) __P((char *, bool, MAILER *, MCI *, ENVELOPE *)); 3053 char **enhstat; 3054 int rtype; 3055 { 3056 register char *bufp; 3057 register int r; 3058 bool firstline = true; 3059 char junkbuf[MAXLINE]; 3060 static char enhstatcode[ENHSCLEN]; 3061 int save_errno; 3062 3063 /* 3064 ** Flush the output before reading response. 3065 ** 3066 ** For SMTP pipelining, it would be better if we didn't do 3067 ** this if there was already data waiting to be read. But 3068 ** to do it properly means pushing it to the I/O library, 3069 ** since it really needs to be done below the buffer layer. 3070 */ 3071 3072 if (mci->mci_out != NULL) 3073 (void) sm_io_flush(mci->mci_out, SM_TIME_DEFAULT); 3074 3075 if (tTd(18, 1)) 3076 sm_dprintf("reply\n"); 3077 3078 /* 3079 ** Read the input line, being careful not to hang. 3080 */ 3081 3082 bufp = SmtpReplyBuffer; 3083 set_tls_rd_tmo(timeout); 3084 for (;;) 3085 { 3086 register char *p; 3087 3088 /* actually do the read */ 3089 if (e->e_xfp != NULL) /* for debugging */ 3090 (void) sm_io_flush(e->e_xfp, SM_TIME_DEFAULT); 3091 3092 /* if we are in the process of closing just give the code */ 3093 if (mci->mci_state == MCIS_CLOSED) 3094 return SMTPCLOSING; 3095 3096 /* don't try to read from a non-existent fd */ 3097 if (mci->mci_in == NULL) 3098 { 3099 if (mci->mci_errno == 0) 3100 mci->mci_errno = EBADF; 3101 3102 /* errors on QUIT should be ignored */ 3103 if (strncmp(SmtpMsgBuffer, "QUIT", 4) == 0) 3104 { 3105 errno = mci->mci_errno; 3106 mci_close(mci, "reply:1"); 3107 return -1; 3108 } 3109 mci->mci_state = MCIS_ERROR; 3110 smtpquit(m, mci, e); 3111 errno = mci->mci_errno; 3112 return -1; 3113 } 3114 3115 if (mci->mci_out != NULL) 3116 (void) sm_io_flush(mci->mci_out, SM_TIME_DEFAULT); 3117 3118 /* get the line from the other side */ 3119 p = sfgets(bufp, MAXLINE, mci->mci_in, timeout, SmtpPhase); 3120 save_errno = errno; 3121 mci->mci_lastuse = curtime(); 3122 3123 if (p == NULL) 3124 { 3125 bool oldholderrs; 3126 extern char MsgBuf[]; 3127 3128 /* errors on QUIT should be ignored */ 3129 if (strncmp(SmtpMsgBuffer, "QUIT", 4) == 0) 3130 { 3131 mci_close(mci, "reply:2"); 3132 return -1; 3133 } 3134 3135 /* if the remote end closed early, fake an error */ 3136 errno = save_errno; 3137 if (errno == 0) 3138 { 3139 (void) sm_snprintf(SmtpReplyBuffer, 3140 sizeof(SmtpReplyBuffer), 3141 "421 4.4.1 Connection reset by %s", 3142 CURHOSTNAME); 3143 #ifdef ECONNRESET 3144 errno = ECONNRESET; 3145 #else /* ECONNRESET */ 3146 errno = EPIPE; 3147 #endif /* ECONNRESET */ 3148 } 3149 3150 mci->mci_errno = errno; 3151 oldholderrs = HoldErrs; 3152 HoldErrs = true; 3153 usrerr("451 4.4.1 reply: read error from %s", 3154 CURHOSTNAME); 3155 mci_setstat(mci, EX_TEMPFAIL, "4.4.2", MsgBuf); 3156 3157 /* if debugging, pause so we can see state */ 3158 if (tTd(18, 100)) 3159 (void) pause(); 3160 mci->mci_state = MCIS_ERROR; 3161 smtpquit(m, mci, e); 3162 #if XDEBUG 3163 { 3164 char wbuf[MAXLINE]; 3165 3166 p = wbuf; 3167 if (e->e_to != NULL) 3168 { 3169 (void) sm_snprintf(p, 3170 SPACELEFT(wbuf, p), 3171 "%s... ", 3172 shortenstring(e->e_to, MAXSHORTSTR)); 3173 p += strlen(p); 3174 } 3175 (void) sm_snprintf(p, SPACELEFT(wbuf, p), 3176 "reply(%.100s) during %s", 3177 CURHOSTNAME, SmtpPhase); 3178 checkfd012(wbuf); 3179 } 3180 #endif /* XDEBUG */ 3181 HoldErrs = oldholderrs; 3182 errno = save_errno; 3183 return -1; 3184 } 3185 fixcrlf(bufp, true); 3186 3187 /* EHLO failure is not a real error */ 3188 if (e->e_xfp != NULL && (bufp[0] == '4' || 3189 (bufp[0] == '5' && strncmp(SmtpMsgBuffer, "EHLO", 4) != 0))) 3190 { 3191 /* serious error -- log the previous command */ 3192 if (SmtpNeedIntro) 3193 { 3194 /* inform user who we are chatting with */ 3195 (void) sm_io_fprintf(CurEnv->e_xfp, 3196 SM_TIME_DEFAULT, 3197 "... while talking to %s:\n", 3198 CURHOSTNAME); 3199 SmtpNeedIntro = false; 3200 } 3201 if (SmtpMsgBuffer[0] != '\0') 3202 { 3203 (void) sm_io_fprintf(e->e_xfp, 3204 SM_TIME_DEFAULT, 3205 ">>> %s\n", 3206 (rtype == XS_STARTTLS) 3207 ? "STARTTLS dialogue" 3208 : ((rtype == XS_AUTH) 3209 ? "AUTH dialogue" 3210 : SmtpMsgBuffer)); 3211 SmtpMsgBuffer[0] = '\0'; 3212 } 3213 3214 /* now log the message as from the other side */ 3215 (void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT, 3216 "<<< %s\n", bufp); 3217 } 3218 3219 /* display the input for verbose mode */ 3220 if (Verbose) 3221 nmessage("050 %s", bufp); 3222 3223 /* ignore improperly formatted input */ 3224 if (!ISSMTPREPLY(bufp)) 3225 continue; 3226 3227 if (bitset(MCIF_ENHSTAT, mci->mci_flags) && 3228 enhstat != NULL && 3229 extenhsc(bufp + 4, ' ', enhstatcode) > 0) 3230 *enhstat = enhstatcode; 3231 3232 /* process the line */ 3233 if (pfunc != NULL) 3234 (*pfunc)(bufp, firstline, m, mci, e); 3235 3236 firstline = false; 3237 3238 /* decode the reply code */ 3239 r = atoi(bufp); 3240 3241 /* extra semantics: 0xx codes are "informational" */ 3242 if (r < 100) 3243 continue; 3244 3245 /* if no continuation lines, return this line */ 3246 if (bufp[3] != '-') 3247 break; 3248 3249 /* first line of real reply -- ignore rest */ 3250 bufp = junkbuf; 3251 } 3252 3253 /* 3254 ** Now look at SmtpReplyBuffer -- only care about the first 3255 ** line of the response from here on out. 3256 */ 3257 3258 /* save temporary failure messages for posterity */ 3259 if (SmtpReplyBuffer[0] == '4') 3260 (void) sm_strlcpy(SmtpError, SmtpReplyBuffer, sizeof(SmtpError)); 3261 3262 /* reply code 421 is "Service Shutting Down" */ 3263 if (r == SMTPCLOSING && mci->mci_state != MCIS_SSD && 3264 mci->mci_state != MCIS_QUITING) 3265 { 3266 /* send the quit protocol */ 3267 mci->mci_state = MCIS_SSD; 3268 smtpquit(m, mci, e); 3269 } 3270 3271 return r; 3272 } 3273 /* 3274 ** SMTPMESSAGE -- send message to server 3275 ** 3276 ** Parameters: 3277 ** f -- format 3278 ** m -- the mailer to control formatting. 3279 ** a, b, c -- parameters 3280 ** 3281 ** Returns: 3282 ** none. 3283 ** 3284 ** Side Effects: 3285 ** writes message to mci->mci_out. 3286 */ 3287 3288 /*VARARGS1*/ 3289 void 3290 #ifdef __STDC__ 3291 smtpmessage(char *f, MAILER *m, MCI *mci, ...) 3292 #else /* __STDC__ */ 3293 smtpmessage(f, m, mci, va_alist) 3294 char *f; 3295 MAILER *m; 3296 MCI *mci; 3297 va_dcl 3298 #endif /* __STDC__ */ 3299 { 3300 SM_VA_LOCAL_DECL 3301 3302 SM_VA_START(ap, mci); 3303 (void) sm_vsnprintf(SmtpMsgBuffer, sizeof(SmtpMsgBuffer), f, ap); 3304 SM_VA_END(ap); 3305 3306 if (tTd(18, 1) || Verbose) 3307 nmessage(">>> %s", SmtpMsgBuffer); 3308 if (TrafficLogFile != NULL) 3309 (void) sm_io_fprintf(TrafficLogFile, SM_TIME_DEFAULT, 3310 "%05d >>> %s\n", (int) CurrentPid, 3311 SmtpMsgBuffer); 3312 if (mci->mci_out != NULL) 3313 { 3314 (void) sm_io_fprintf(mci->mci_out, SM_TIME_DEFAULT, "%s%s", 3315 SmtpMsgBuffer, m == NULL ? "\r\n" 3316 : m->m_eol); 3317 } 3318 else if (tTd(18, 1)) 3319 { 3320 sm_dprintf("smtpmessage: NULL mci_out\n"); 3321 } 3322 } 3323