1 /* 2 * Copyright (c) 1998-2006, 2008 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.472 2008/01/31 18:48:29 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 char in64[MAXOUTLEN]; 1572 #if NETINET || (NETINET6 && SASL >= 20000) 1573 extern SOCKADDR CurHostAddr; 1574 #endif /* NETINET || (NETINET6 && SASL >= 20000) */ 1575 1576 /* no mechanism selected (yet) */ 1577 (*sai)[SASL_MECH] = NULL; 1578 1579 /* dispose old connection */ 1580 if (mci->mci_conn != NULL) 1581 sasl_dispose(&(mci->mci_conn)); 1582 1583 /* make a new client sasl connection */ 1584 # if SASL >= 20000 1585 /* 1586 ** We provide the callbacks again because global callbacks in 1587 ** sasl_client_init() are ignored if SASL has been initialized 1588 ** before, for example, by a library such as libnss-ldap. 1589 */ 1590 1591 saslresult = sasl_client_new(bitnset(M_LMTP, m->m_flags) ? "lmtp" 1592 : "smtp", 1593 CurHostName, NULL, NULL, callbacks, 0, 1594 &mci->mci_conn); 1595 # else /* SASL >= 20000 */ 1596 saslresult = sasl_client_new(bitnset(M_LMTP, m->m_flags) ? "lmtp" 1597 : "smtp", 1598 CurHostName, NULL, 0, &mci->mci_conn); 1599 # endif /* SASL >= 20000 */ 1600 if (saslresult != SASL_OK) 1601 return EX_TEMPFAIL; 1602 1603 /* set properties */ 1604 (void) memset(&ssp, '\0', sizeof(ssp)); 1605 1606 /* XXX should these be options settable via .cf ? */ 1607 { 1608 ssp.max_ssf = MaxSLBits; 1609 ssp.maxbufsize = MAXOUTLEN; 1610 # if 0 1611 ssp.security_flags = SASL_SEC_NOPLAINTEXT; 1612 # endif /* 0 */ 1613 } 1614 saslresult = sasl_setprop(mci->mci_conn, SASL_SEC_PROPS, &ssp); 1615 if (saslresult != SASL_OK) 1616 return EX_TEMPFAIL; 1617 1618 # if SASL >= 20000 1619 /* external security strength factor, authentication id */ 1620 ssf = 0; 1621 auth_id = NULL; 1622 # if STARTTLS 1623 out = macvalue(macid("{cert_subject}"), e); 1624 if (out != NULL && *out != '\0') 1625 auth_id = out; 1626 out = macvalue(macid("{cipher_bits}"), e); 1627 if (out != NULL && *out != '\0') 1628 ssf = atoi(out); 1629 # endif /* STARTTLS */ 1630 saslresult = sasl_setprop(mci->mci_conn, SASL_SSF_EXTERNAL, &ssf); 1631 if (saslresult != SASL_OK) 1632 return EX_TEMPFAIL; 1633 saslresult = sasl_setprop(mci->mci_conn, SASL_AUTH_EXTERNAL, auth_id); 1634 if (saslresult != SASL_OK) 1635 return EX_TEMPFAIL; 1636 1637 # if NETINET || NETINET6 1638 /* set local/remote ipv4 addresses */ 1639 if (mci->mci_out != NULL && ( 1640 # if NETINET6 1641 CurHostAddr.sa.sa_family == AF_INET6 || 1642 # endif /* NETINET6 */ 1643 CurHostAddr.sa.sa_family == AF_INET)) 1644 { 1645 SOCKADDR_LEN_T addrsize; 1646 SOCKADDR saddr_l; 1647 char localip[60], remoteip[60]; 1648 1649 switch (CurHostAddr.sa.sa_family) 1650 { 1651 case AF_INET: 1652 addrsize = sizeof(struct sockaddr_in); 1653 break; 1654 # if NETINET6 1655 case AF_INET6: 1656 addrsize = sizeof(struct sockaddr_in6); 1657 break; 1658 # endif /* NETINET6 */ 1659 default: 1660 break; 1661 } 1662 if (iptostring(&CurHostAddr, addrsize, 1663 remoteip, sizeof(remoteip))) 1664 { 1665 if (sasl_setprop(mci->mci_conn, SASL_IPREMOTEPORT, 1666 remoteip) != SASL_OK) 1667 return EX_TEMPFAIL; 1668 } 1669 addrsize = sizeof(saddr_l); 1670 if (getsockname(sm_io_getinfo(mci->mci_out, SM_IO_WHAT_FD, 1671 NULL), 1672 (struct sockaddr *) &saddr_l, &addrsize) == 0) 1673 { 1674 if (iptostring(&saddr_l, addrsize, 1675 localip, sizeof(localip))) 1676 { 1677 if (sasl_setprop(mci->mci_conn, 1678 SASL_IPLOCALPORT, 1679 localip) != SASL_OK) 1680 return EX_TEMPFAIL; 1681 } 1682 } 1683 } 1684 # endif /* NETINET || NETINET6 */ 1685 1686 /* start client side of sasl */ 1687 saslresult = sasl_client_start(mci->mci_conn, mci->mci_saslcap, 1688 &client_interact, 1689 &out, &outlen, 1690 (const char **) &mechusing); 1691 # else /* SASL >= 20000 */ 1692 /* external security strength factor, authentication id */ 1693 ssf.ssf = 0; 1694 ssf.auth_id = NULL; 1695 # if STARTTLS 1696 out = macvalue(macid("{cert_subject}"), e); 1697 if (out != NULL && *out != '\0') 1698 ssf.auth_id = out; 1699 out = macvalue(macid("{cipher_bits}"), e); 1700 if (out != NULL && *out != '\0') 1701 ssf.ssf = atoi(out); 1702 # endif /* STARTTLS */ 1703 saslresult = sasl_setprop(mci->mci_conn, SASL_SSF_EXTERNAL, &ssf); 1704 if (saslresult != SASL_OK) 1705 return EX_TEMPFAIL; 1706 1707 # if NETINET 1708 /* set local/remote ipv4 addresses */ 1709 if (mci->mci_out != NULL && CurHostAddr.sa.sa_family == AF_INET) 1710 { 1711 SOCKADDR_LEN_T addrsize; 1712 struct sockaddr_in saddr_l; 1713 1714 if (sasl_setprop(mci->mci_conn, SASL_IP_REMOTE, 1715 (struct sockaddr_in *) &CurHostAddr) 1716 != SASL_OK) 1717 return EX_TEMPFAIL; 1718 addrsize = sizeof(struct sockaddr_in); 1719 if (getsockname(sm_io_getinfo(mci->mci_out, SM_IO_WHAT_FD, 1720 NULL), 1721 (struct sockaddr *) &saddr_l, &addrsize) == 0) 1722 { 1723 if (sasl_setprop(mci->mci_conn, SASL_IP_LOCAL, 1724 &saddr_l) != SASL_OK) 1725 return EX_TEMPFAIL; 1726 } 1727 } 1728 # endif /* NETINET */ 1729 1730 /* start client side of sasl */ 1731 saslresult = sasl_client_start(mci->mci_conn, mci->mci_saslcap, 1732 NULL, &client_interact, 1733 &out, &outlen, 1734 (const char **) &mechusing); 1735 # endif /* SASL >= 20000 */ 1736 1737 if (saslresult != SASL_OK && saslresult != SASL_CONTINUE) 1738 { 1739 if (saslresult == SASL_NOMECH && LogLevel > 8) 1740 { 1741 sm_syslog(LOG_NOTICE, e->e_id, 1742 "AUTH=client, available mechanisms do not fulfill requirements"); 1743 } 1744 return EX_TEMPFAIL; 1745 } 1746 1747 /* just point current mechanism to the data in the sasl library */ 1748 (*sai)[SASL_MECH] = mechusing; 1749 1750 /* send the info across the wire */ 1751 if (out == NULL 1752 /* login and digest-md5 up to 1.5.28 set out="" */ 1753 || (outlen == 0 && 1754 (sm_strcasecmp(mechusing, "LOGIN") == 0 || 1755 sm_strcasecmp(mechusing, "DIGEST-MD5") == 0)) 1756 ) 1757 { 1758 /* no initial response */ 1759 smtpmessage("AUTH %s", m, mci, mechusing); 1760 } 1761 else if (outlen == 0) 1762 { 1763 /* 1764 ** zero-length initial response, per RFC 2554 4.: 1765 ** "Unlike a zero-length client answer to a 334 reply, a zero- 1766 ** length initial response is sent as a single equals sign" 1767 */ 1768 1769 smtpmessage("AUTH %s =", m, mci, mechusing); 1770 } 1771 else 1772 { 1773 saslresult = sasl_encode64(out, outlen, in64, MAXOUTLEN, NULL); 1774 if (saslresult != SASL_OK) /* internal error */ 1775 { 1776 if (LogLevel > 8) 1777 sm_syslog(LOG_ERR, e->e_id, 1778 "encode64 for AUTH failed"); 1779 return EX_TEMPFAIL; 1780 } 1781 smtpmessage("AUTH %s %s", m, mci, mechusing, in64); 1782 } 1783 # if SASL < 20000 1784 sm_sasl_free(out); /* XXX only if no rpool is used */ 1785 # endif /* SASL < 20000 */ 1786 1787 /* get the reply */ 1788 smtpresult = reply(m, mci, e, TimeOuts.to_auth, getsasldata, NULL, 1789 XS_AUTH); 1790 1791 for (;;) 1792 { 1793 /* check return code from server */ 1794 if (smtpresult == 235) 1795 { 1796 macdefine(&mci->mci_macro, A_TEMP, macid("{auth_type}"), 1797 mechusing); 1798 return EX_OK; 1799 } 1800 if (smtpresult == -1) 1801 return EX_IOERR; 1802 if (REPLYTYPE(smtpresult) == 5) 1803 return EX_NOPERM; /* ugly, but ... */ 1804 if (REPLYTYPE(smtpresult) != 3) 1805 { 1806 /* should we fail deliberately, see RFC 2554 4. ? */ 1807 /* smtpmessage("*", m, mci); */ 1808 return EX_TEMPFAIL; 1809 } 1810 1811 saslresult = sasl_client_step(mci->mci_conn, 1812 mci->mci_sasl_string, 1813 mci->mci_sasl_string_len, 1814 &client_interact, 1815 &out, &outlen); 1816 1817 if (saslresult != SASL_OK && saslresult != SASL_CONTINUE) 1818 { 1819 if (tTd(95, 5)) 1820 sm_dprintf("AUTH FAIL=%s (%d)\n", 1821 sasl_errstring(saslresult, NULL, NULL), 1822 saslresult); 1823 1824 /* fail deliberately, see RFC 2554 4. */ 1825 smtpmessage("*", m, mci); 1826 1827 /* 1828 ** but we should only fail for this authentication 1829 ** mechanism; how to do that? 1830 */ 1831 1832 smtpresult = reply(m, mci, e, TimeOuts.to_auth, 1833 getsasldata, NULL, XS_AUTH); 1834 return EX_NOPERM; 1835 } 1836 1837 if (outlen > 0) 1838 { 1839 saslresult = sasl_encode64(out, outlen, in64, 1840 MAXOUTLEN, NULL); 1841 if (saslresult != SASL_OK) 1842 { 1843 /* give an error reply to the other side! */ 1844 smtpmessage("*", m, mci); 1845 return EX_TEMPFAIL; 1846 } 1847 } 1848 else 1849 in64[0] = '\0'; 1850 # if SASL < 20000 1851 sm_sasl_free(out); /* XXX only if no rpool is used */ 1852 # endif /* SASL < 20000 */ 1853 smtpmessage("%s", m, mci, in64); 1854 smtpresult = reply(m, mci, e, TimeOuts.to_auth, 1855 getsasldata, NULL, XS_AUTH); 1856 } 1857 /* NOTREACHED */ 1858 } 1859 /* 1860 ** SMTPAUTH -- try to AUTHenticate 1861 ** 1862 ** This will try mechanisms in the order the sasl library decided until: 1863 ** - there are no more mechanisms 1864 ** - a mechanism succeeds 1865 ** - the sasl library fails initializing 1866 ** 1867 ** Parameters: 1868 ** m -- the mailer. 1869 ** mci -- the mailer connection info. 1870 ** e -- the envelope. 1871 ** 1872 ** Returns: 1873 ** EX_OK -- authentication was successful 1874 ** EX_UNAVAILABLE -- authentication not possible, e.g., 1875 ** no data available. 1876 ** EX_NOPERM -- authentication failed. 1877 ** EX_TEMPFAIL -- temporary failure. 1878 ** 1879 ** Notice: AuthInfo is used for all connections, hence we must 1880 ** return EX_TEMPFAIL only if we really want to retry, i.e., 1881 ** iff getauth() tempfailed or getauth() was used and 1882 ** authentication tempfailed. 1883 */ 1884 1885 int 1886 smtpauth(m, mci, e) 1887 MAILER *m; 1888 MCI *mci; 1889 ENVELOPE *e; 1890 { 1891 int result; 1892 int i; 1893 bool usedgetauth; 1894 1895 mci->mci_sasl_auth = false; 1896 for (i = 0; i < SASL_MECH ; i++) 1897 mci->mci_sai[i] = NULL; 1898 1899 result = getauth(mci, e, &(mci->mci_sai)); 1900 if (result == EX_TEMPFAIL) 1901 return result; 1902 usedgetauth = true; 1903 1904 /* no data available: don't try to authenticate */ 1905 if (result == EX_OK && mci->mci_sai[SASL_AUTHID] == NULL) 1906 return result; 1907 if (result != EX_OK) 1908 { 1909 if (SASLInfo == NULL) 1910 return EX_UNAVAILABLE; 1911 1912 /* read authinfo from file */ 1913 result = readauth(SASLInfo, true, &(mci->mci_sai), 1914 mci->mci_rpool); 1915 if (result != EX_OK) 1916 return result; 1917 usedgetauth = false; 1918 } 1919 1920 /* check whether sufficient data is available */ 1921 if (mci->mci_sai[SASL_PASSWORD] == NULL || 1922 *(mci->mci_sai)[SASL_PASSWORD] == '\0') 1923 return EX_UNAVAILABLE; 1924 if ((mci->mci_sai[SASL_AUTHID] == NULL || 1925 *(mci->mci_sai)[SASL_AUTHID] == '\0') && 1926 (mci->mci_sai[SASL_USER] == NULL || 1927 *(mci->mci_sai)[SASL_USER] == '\0')) 1928 return EX_UNAVAILABLE; 1929 1930 /* set the context for the callback function to sai */ 1931 # if SASL >= 20000 1932 callbacks[CB_PASS_IDX].context = (void *) mci; 1933 # else /* SASL >= 20000 */ 1934 callbacks[CB_PASS_IDX].context = (void *) &mci->mci_sai; 1935 # endif /* SASL >= 20000 */ 1936 callbacks[CB_USER_IDX].context = (void *) &mci->mci_sai; 1937 callbacks[CB_AUTHNAME_IDX].context = (void *) &mci->mci_sai; 1938 callbacks[CB_GETREALM_IDX].context = (void *) &mci->mci_sai; 1939 #if 0 1940 callbacks[CB_SAFESASL_IDX].context = (void *) &mci->mci_sai; 1941 #endif /* 0 */ 1942 1943 /* set default value for realm */ 1944 if ((mci->mci_sai)[SASL_DEFREALM] == NULL) 1945 (mci->mci_sai)[SASL_DEFREALM] = sm_rpool_strdup_x(e->e_rpool, 1946 macvalue('j', CurEnv)); 1947 1948 /* set default value for list of mechanism to use */ 1949 if ((mci->mci_sai)[SASL_MECHLIST] == NULL || 1950 *(mci->mci_sai)[SASL_MECHLIST] == '\0') 1951 (mci->mci_sai)[SASL_MECHLIST] = AuthMechanisms; 1952 1953 /* create list of mechanisms to try */ 1954 mci->mci_saslcap = intersect((mci->mci_sai)[SASL_MECHLIST], 1955 mci->mci_saslcap, mci->mci_rpool); 1956 1957 /* initialize sasl client library */ 1958 result = init_sasl_client(); 1959 if (result != SASL_OK) 1960 return usedgetauth ? EX_TEMPFAIL : EX_UNAVAILABLE; 1961 do 1962 { 1963 result = attemptauth(m, mci, e, &(mci->mci_sai)); 1964 if (result == EX_OK) 1965 mci->mci_sasl_auth = true; 1966 else if (result == EX_TEMPFAIL || result == EX_NOPERM) 1967 { 1968 mci->mci_saslcap = removemech((mci->mci_sai)[SASL_MECH], 1969 mci->mci_saslcap, 1970 mci->mci_rpool); 1971 if (mci->mci_saslcap == NULL || 1972 *(mci->mci_saslcap) == '\0') 1973 return usedgetauth ? result 1974 : EX_UNAVAILABLE; 1975 } 1976 else 1977 return result; 1978 } while (result != EX_OK); 1979 return result; 1980 } 1981 #endif /* SASL */ 1982 1983 /* 1984 ** SMTPMAILFROM -- send MAIL command 1985 ** 1986 ** Parameters: 1987 ** m -- the mailer. 1988 ** mci -- the mailer connection structure. 1989 ** e -- the envelope (including the sender to specify). 1990 */ 1991 1992 int 1993 smtpmailfrom(m, mci, e) 1994 MAILER *m; 1995 MCI *mci; 1996 ENVELOPE *e; 1997 { 1998 int r; 1999 char *bufp; 2000 char *bodytype; 2001 char *enhsc; 2002 char buf[MAXNAME + 1]; 2003 char optbuf[MAXLINE]; 2004 2005 if (tTd(18, 2)) 2006 sm_dprintf("smtpmailfrom: CurHost=%s\n", CurHostName); 2007 enhsc = NULL; 2008 2009 /* 2010 ** Check if connection is gone, if so 2011 ** it's a tempfail and we use mci_errno 2012 ** for the reason. 2013 */ 2014 2015 if (mci->mci_state == MCIS_CLOSED) 2016 { 2017 errno = mci->mci_errno; 2018 return EX_TEMPFAIL; 2019 } 2020 2021 /* set up appropriate options to include */ 2022 if (bitset(MCIF_SIZE, mci->mci_flags) && e->e_msgsize > 0) 2023 { 2024 (void) sm_snprintf(optbuf, sizeof(optbuf), " SIZE=%ld", 2025 e->e_msgsize); 2026 bufp = &optbuf[strlen(optbuf)]; 2027 } 2028 else 2029 { 2030 optbuf[0] = '\0'; 2031 bufp = optbuf; 2032 } 2033 2034 bodytype = e->e_bodytype; 2035 if (bitset(MCIF_8BITMIME, mci->mci_flags)) 2036 { 2037 if (bodytype == NULL && 2038 bitset(MM_MIME8BIT, MimeMode) && 2039 bitset(EF_HAS8BIT, e->e_flags) && 2040 !bitset(EF_DONT_MIME, e->e_flags) && 2041 !bitnset(M_8BITS, m->m_flags)) 2042 bodytype = "8BITMIME"; 2043 if (bodytype != NULL && 2044 SPACELEFT(optbuf, bufp) > strlen(bodytype) + 7) 2045 { 2046 (void) sm_snprintf(bufp, SPACELEFT(optbuf, bufp), 2047 " BODY=%s", bodytype); 2048 bufp += strlen(bufp); 2049 } 2050 } 2051 else if (bitnset(M_8BITS, m->m_flags) || 2052 !bitset(EF_HAS8BIT, e->e_flags) || 2053 bitset(MCIF_8BITOK, mci->mci_flags)) 2054 { 2055 /* EMPTY */ 2056 /* just pass it through */ 2057 } 2058 #if MIME8TO7 2059 else if (bitset(MM_CVTMIME, MimeMode) && 2060 !bitset(EF_DONT_MIME, e->e_flags) && 2061 (!bitset(MM_PASS8BIT, MimeMode) || 2062 bitset(EF_IS_MIME, e->e_flags))) 2063 { 2064 /* must convert from 8bit MIME format to 7bit encoded */ 2065 mci->mci_flags |= MCIF_CVT8TO7; 2066 } 2067 #endif /* MIME8TO7 */ 2068 else if (!bitset(MM_PASS8BIT, MimeMode)) 2069 { 2070 /* cannot just send a 8-bit version */ 2071 extern char MsgBuf[]; 2072 2073 usrerrenh("5.6.3", "%s does not support 8BITMIME", CurHostName); 2074 mci_setstat(mci, EX_NOTSTICKY, "5.6.3", MsgBuf); 2075 return EX_DATAERR; 2076 } 2077 2078 if (bitset(MCIF_DSN, mci->mci_flags)) 2079 { 2080 if (e->e_envid != NULL && 2081 SPACELEFT(optbuf, bufp) > strlen(e->e_envid) + 7) 2082 { 2083 (void) sm_snprintf(bufp, SPACELEFT(optbuf, bufp), 2084 " ENVID=%s", e->e_envid); 2085 bufp += strlen(bufp); 2086 } 2087 2088 /* RET= parameter */ 2089 if (bitset(EF_RET_PARAM, e->e_flags) && 2090 SPACELEFT(optbuf, bufp) > 9) 2091 { 2092 (void) sm_snprintf(bufp, SPACELEFT(optbuf, bufp), 2093 " RET=%s", 2094 bitset(EF_NO_BODY_RETN, e->e_flags) ? 2095 "HDRS" : "FULL"); 2096 bufp += strlen(bufp); 2097 } 2098 } 2099 2100 if (bitset(MCIF_AUTH, mci->mci_flags) && e->e_auth_param != NULL && 2101 SPACELEFT(optbuf, bufp) > strlen(e->e_auth_param) + 7 2102 #if SASL 2103 && (!bitset(SASL_AUTH_AUTH, SASLOpts) || mci->mci_sasl_auth) 2104 #endif /* SASL */ 2105 ) 2106 { 2107 (void) sm_snprintf(bufp, SPACELEFT(optbuf, bufp), 2108 " AUTH=%s", e->e_auth_param); 2109 bufp += strlen(bufp); 2110 } 2111 2112 /* 2113 ** 17 is the max length required, we could use log() to compute 2114 ** the exact length (and check IS_DLVR_TRACE()) 2115 */ 2116 2117 if (bitset(MCIF_DLVR_BY, mci->mci_flags) && 2118 IS_DLVR_BY(e) && SPACELEFT(optbuf, bufp) > 17) 2119 { 2120 long dby; 2121 2122 /* 2123 ** Avoid problems with delays (for R) since the check 2124 ** in deliver() whether min-deliver-time is sufficient. 2125 ** Alternatively we could pass the computed time to this 2126 ** function. 2127 */ 2128 2129 dby = e->e_deliver_by - (curtime() - e->e_ctime); 2130 if (dby <= 0 && IS_DLVR_RETURN(e)) 2131 dby = mci->mci_min_by <= 0 ? 1 : mci->mci_min_by; 2132 (void) sm_snprintf(bufp, SPACELEFT(optbuf, bufp), 2133 " BY=%ld;%c%s", 2134 dby, 2135 IS_DLVR_RETURN(e) ? 'R' : 'N', 2136 IS_DLVR_TRACE(e) ? "T" : ""); 2137 bufp += strlen(bufp); 2138 } 2139 2140 /* 2141 ** Send the MAIL command. 2142 ** Designates the sender. 2143 */ 2144 2145 mci->mci_state = MCIS_MAIL; 2146 2147 if (bitset(EF_RESPONSE, e->e_flags) && 2148 !bitnset(M_NO_NULL_FROM, m->m_flags)) 2149 buf[0] = '\0'; 2150 else 2151 expand("\201g", buf, sizeof(buf), e); 2152 if (buf[0] == '<') 2153 { 2154 /* strip off <angle brackets> (put back on below) */ 2155 bufp = &buf[strlen(buf) - 1]; 2156 if (*bufp == '>') 2157 *bufp = '\0'; 2158 bufp = &buf[1]; 2159 } 2160 else 2161 bufp = buf; 2162 if (bitnset(M_LOCALMAILER, e->e_from.q_mailer->m_flags) || 2163 !bitnset(M_FROMPATH, m->m_flags)) 2164 { 2165 smtpmessage("MAIL From:<%s>%s", m, mci, bufp, optbuf); 2166 } 2167 else 2168 { 2169 smtpmessage("MAIL From:<@%s%c%s>%s", m, mci, MyHostName, 2170 *bufp == '@' ? ',' : ':', bufp, optbuf); 2171 } 2172 SmtpPhase = mci->mci_phase = "client MAIL"; 2173 sm_setproctitle(true, e, "%s %s: %s", qid_printname(e), 2174 CurHostName, mci->mci_phase); 2175 r = reply(m, mci, e, TimeOuts.to_mail, NULL, &enhsc, XS_DEFAULT); 2176 if (r < 0) 2177 { 2178 /* communications failure */ 2179 mci_setstat(mci, EX_TEMPFAIL, "4.4.2", NULL); 2180 return EX_TEMPFAIL; 2181 } 2182 else if (r == SMTPCLOSING) 2183 { 2184 /* service shutting down: handled by reply() */ 2185 return EX_TEMPFAIL; 2186 } 2187 else if (REPLYTYPE(r) == 4) 2188 { 2189 mci_setstat(mci, EX_NOTSTICKY, ENHSCN(enhsc, smtptodsn(r)), 2190 SmtpReplyBuffer); 2191 return EX_TEMPFAIL; 2192 } 2193 else if (REPLYTYPE(r) == 2) 2194 { 2195 return EX_OK; 2196 } 2197 else if (r == 501) 2198 { 2199 /* syntax error in arguments */ 2200 mci_setstat(mci, EX_NOTSTICKY, ENHSCN(enhsc, "5.5.2"), 2201 SmtpReplyBuffer); 2202 return EX_DATAERR; 2203 } 2204 else if (r == 553) 2205 { 2206 /* mailbox name not allowed */ 2207 mci_setstat(mci, EX_NOTSTICKY, ENHSCN(enhsc, "5.1.3"), 2208 SmtpReplyBuffer); 2209 return EX_DATAERR; 2210 } 2211 else if (r == 552) 2212 { 2213 /* exceeded storage allocation */ 2214 mci_setstat(mci, EX_NOTSTICKY, ENHSCN(enhsc, "5.3.4"), 2215 SmtpReplyBuffer); 2216 if (bitset(MCIF_SIZE, mci->mci_flags)) 2217 e->e_flags |= EF_NO_BODY_RETN; 2218 return EX_UNAVAILABLE; 2219 } 2220 else if (REPLYTYPE(r) == 5) 2221 { 2222 /* unknown error */ 2223 mci_setstat(mci, EX_NOTSTICKY, ENHSCN(enhsc, "5.0.0"), 2224 SmtpReplyBuffer); 2225 return EX_UNAVAILABLE; 2226 } 2227 2228 if (LogLevel > 1) 2229 { 2230 sm_syslog(LOG_CRIT, e->e_id, 2231 "%.100s: SMTP MAIL protocol error: %s", 2232 CurHostName, 2233 shortenstring(SmtpReplyBuffer, 403)); 2234 } 2235 2236 /* protocol error -- close up */ 2237 mci_setstat(mci, EX_PROTOCOL, ENHSCN(enhsc, "5.5.1"), 2238 SmtpReplyBuffer); 2239 smtpquit(m, mci, e); 2240 return EX_PROTOCOL; 2241 } 2242 /* 2243 ** SMTPRCPT -- designate recipient. 2244 ** 2245 ** Parameters: 2246 ** to -- address of recipient. 2247 ** m -- the mailer we are sending to. 2248 ** mci -- the connection info for this transaction. 2249 ** e -- the envelope for this transaction. 2250 ** 2251 ** Returns: 2252 ** exit status corresponding to recipient status. 2253 ** 2254 ** Side Effects: 2255 ** Sends the mail via SMTP. 2256 */ 2257 2258 int 2259 smtprcpt(to, m, mci, e, ctladdr, xstart) 2260 ADDRESS *to; 2261 register MAILER *m; 2262 MCI *mci; 2263 ENVELOPE *e; 2264 ADDRESS *ctladdr; 2265 time_t xstart; 2266 { 2267 char *bufp; 2268 char optbuf[MAXLINE]; 2269 2270 #if PIPELINING 2271 /* 2272 ** If there is status waiting from the other end, read it. 2273 ** This should normally happen because of SMTP pipelining. 2274 */ 2275 2276 while (mci->mci_nextaddr != NULL && 2277 sm_io_getinfo(mci->mci_in, SM_IO_IS_READABLE, NULL) > 0) 2278 { 2279 int r; 2280 2281 r = smtprcptstat(mci->mci_nextaddr, m, mci, e); 2282 if (r != EX_OK) 2283 { 2284 markfailure(e, mci->mci_nextaddr, mci, r, false); 2285 giveresponse(r, mci->mci_nextaddr->q_status, m, mci, 2286 ctladdr, xstart, e, to); 2287 } 2288 mci->mci_nextaddr = mci->mci_nextaddr->q_pchain; 2289 } 2290 #endif /* PIPELINING */ 2291 2292 /* 2293 ** Check if connection is gone, if so 2294 ** it's a tempfail and we use mci_errno 2295 ** for the reason. 2296 */ 2297 2298 if (mci->mci_state == MCIS_CLOSED) 2299 { 2300 errno = mci->mci_errno; 2301 return EX_TEMPFAIL; 2302 } 2303 2304 optbuf[0] = '\0'; 2305 bufp = optbuf; 2306 2307 /* 2308 ** Warning: in the following it is assumed that the free space 2309 ** in bufp is sizeof(optbuf) 2310 */ 2311 2312 if (bitset(MCIF_DSN, mci->mci_flags)) 2313 { 2314 if (IS_DLVR_NOTIFY(e) && 2315 !bitset(MCIF_DLVR_BY, mci->mci_flags)) 2316 { 2317 /* RFC 2852: 4.1.4.2 */ 2318 if (!bitset(QHASNOTIFY, to->q_flags)) 2319 to->q_flags |= QPINGONFAILURE|QPINGONDELAY|QHASNOTIFY; 2320 else if (bitset(QPINGONSUCCESS, to->q_flags) || 2321 bitset(QPINGONFAILURE, to->q_flags) || 2322 bitset(QPINGONDELAY, to->q_flags)) 2323 to->q_flags |= QPINGONDELAY; 2324 } 2325 2326 /* NOTIFY= parameter */ 2327 if (bitset(QHASNOTIFY, to->q_flags) && 2328 bitset(QPRIMARY, to->q_flags) && 2329 !bitnset(M_LOCALMAILER, m->m_flags)) 2330 { 2331 bool firstone = true; 2332 2333 (void) sm_strlcat(bufp, " NOTIFY=", sizeof(optbuf)); 2334 if (bitset(QPINGONSUCCESS, to->q_flags)) 2335 { 2336 (void) sm_strlcat(bufp, "SUCCESS", sizeof(optbuf)); 2337 firstone = false; 2338 } 2339 if (bitset(QPINGONFAILURE, to->q_flags)) 2340 { 2341 if (!firstone) 2342 (void) sm_strlcat(bufp, ",", 2343 sizeof(optbuf)); 2344 (void) sm_strlcat(bufp, "FAILURE", sizeof(optbuf)); 2345 firstone = false; 2346 } 2347 if (bitset(QPINGONDELAY, to->q_flags)) 2348 { 2349 if (!firstone) 2350 (void) sm_strlcat(bufp, ",", 2351 sizeof(optbuf)); 2352 (void) sm_strlcat(bufp, "DELAY", sizeof(optbuf)); 2353 firstone = false; 2354 } 2355 if (firstone) 2356 (void) sm_strlcat(bufp, "NEVER", sizeof(optbuf)); 2357 bufp += strlen(bufp); 2358 } 2359 2360 /* ORCPT= parameter */ 2361 if (to->q_orcpt != NULL && 2362 SPACELEFT(optbuf, bufp) > strlen(to->q_orcpt) + 7) 2363 { 2364 (void) sm_snprintf(bufp, SPACELEFT(optbuf, bufp), 2365 " ORCPT=%s", to->q_orcpt); 2366 bufp += strlen(bufp); 2367 } 2368 } 2369 2370 smtpmessage("RCPT To:<%s>%s", m, mci, to->q_user, optbuf); 2371 mci->mci_state = MCIS_RCPT; 2372 2373 SmtpPhase = mci->mci_phase = "client RCPT"; 2374 sm_setproctitle(true, e, "%s %s: %s", qid_printname(e), 2375 CurHostName, mci->mci_phase); 2376 2377 #if PIPELINING 2378 /* 2379 ** If running SMTP pipelining, we will pick up status later 2380 */ 2381 2382 if (bitset(MCIF_PIPELINED, mci->mci_flags)) 2383 return EX_OK; 2384 #endif /* PIPELINING */ 2385 2386 return smtprcptstat(to, m, mci, e); 2387 } 2388 /* 2389 ** SMTPRCPTSTAT -- get recipient status 2390 ** 2391 ** This is only called during SMTP pipelining 2392 ** 2393 ** Parameters: 2394 ** to -- address of recipient. 2395 ** m -- mailer being sent to. 2396 ** mci -- the mailer connection information. 2397 ** e -- the envelope for this message. 2398 ** 2399 ** Returns: 2400 ** EX_* -- protocol status 2401 */ 2402 2403 static int 2404 smtprcptstat(to, m, mci, e) 2405 ADDRESS *to; 2406 MAILER *m; 2407 register MCI *mci; 2408 register ENVELOPE *e; 2409 { 2410 int r; 2411 int save_errno; 2412 char *enhsc; 2413 2414 /* 2415 ** Check if connection is gone, if so 2416 ** it's a tempfail and we use mci_errno 2417 ** for the reason. 2418 */ 2419 2420 if (mci->mci_state == MCIS_CLOSED) 2421 { 2422 errno = mci->mci_errno; 2423 return EX_TEMPFAIL; 2424 } 2425 2426 enhsc = NULL; 2427 r = reply(m, mci, e, TimeOuts.to_rcpt, NULL, &enhsc, XS_DEFAULT); 2428 save_errno = errno; 2429 to->q_rstatus = sm_rpool_strdup_x(e->e_rpool, SmtpReplyBuffer); 2430 to->q_status = ENHSCN_RPOOL(enhsc, smtptodsn(r), e->e_rpool); 2431 if (!bitnset(M_LMTP, m->m_flags)) 2432 to->q_statmta = mci->mci_host; 2433 if (r < 0 || REPLYTYPE(r) == 4) 2434 { 2435 mci->mci_retryrcpt = true; 2436 errno = save_errno; 2437 return EX_TEMPFAIL; 2438 } 2439 else if (REPLYTYPE(r) == 2) 2440 { 2441 char *t; 2442 2443 if ((t = mci->mci_tolist) != NULL) 2444 { 2445 char *p; 2446 2447 *t++ = ','; 2448 for (p = to->q_paddr; *p != '\0'; *t++ = *p++) 2449 continue; 2450 *t = '\0'; 2451 mci->mci_tolist = t; 2452 } 2453 #if PIPELINING 2454 mci->mci_okrcpts++; 2455 #endif /* PIPELINING */ 2456 return EX_OK; 2457 } 2458 else if (r == 550) 2459 { 2460 to->q_status = ENHSCN_RPOOL(enhsc, "5.1.1", e->e_rpool); 2461 return EX_NOUSER; 2462 } 2463 else if (r == 551) 2464 { 2465 to->q_status = ENHSCN_RPOOL(enhsc, "5.1.6", e->e_rpool); 2466 return EX_NOUSER; 2467 } 2468 else if (r == 553) 2469 { 2470 to->q_status = ENHSCN_RPOOL(enhsc, "5.1.3", e->e_rpool); 2471 return EX_NOUSER; 2472 } 2473 else if (REPLYTYPE(r) == 5) 2474 { 2475 return EX_UNAVAILABLE; 2476 } 2477 2478 if (LogLevel > 1) 2479 { 2480 sm_syslog(LOG_CRIT, e->e_id, 2481 "%.100s: SMTP RCPT protocol error: %s", 2482 CurHostName, 2483 shortenstring(SmtpReplyBuffer, 403)); 2484 } 2485 2486 mci_setstat(mci, EX_PROTOCOL, ENHSCN(enhsc, "5.5.1"), 2487 SmtpReplyBuffer); 2488 return EX_PROTOCOL; 2489 } 2490 /* 2491 ** SMTPDATA -- send the data and clean up the transaction. 2492 ** 2493 ** Parameters: 2494 ** m -- mailer being sent to. 2495 ** mci -- the mailer connection information. 2496 ** e -- the envelope for this message. 2497 ** 2498 ** Returns: 2499 ** exit status corresponding to DATA command. 2500 */ 2501 2502 int 2503 smtpdata(m, mci, e, ctladdr, xstart) 2504 MAILER *m; 2505 register MCI *mci; 2506 register ENVELOPE *e; 2507 ADDRESS *ctladdr; 2508 time_t xstart; 2509 { 2510 register int r; 2511 int rstat; 2512 int xstat; 2513 int timeout; 2514 char *enhsc; 2515 2516 /* 2517 ** Check if connection is gone, if so 2518 ** it's a tempfail and we use mci_errno 2519 ** for the reason. 2520 */ 2521 2522 if (mci->mci_state == MCIS_CLOSED) 2523 { 2524 errno = mci->mci_errno; 2525 return EX_TEMPFAIL; 2526 } 2527 2528 enhsc = NULL; 2529 2530 /* 2531 ** Send the data. 2532 ** First send the command and check that it is ok. 2533 ** Then send the data (if there are valid recipients). 2534 ** Follow it up with a dot to terminate. 2535 ** Finally get the results of the transaction. 2536 */ 2537 2538 /* send the command and check ok to proceed */ 2539 smtpmessage("DATA", m, mci); 2540 2541 #if PIPELINING 2542 if (mci->mci_nextaddr != NULL) 2543 { 2544 char *oldto = e->e_to; 2545 2546 /* pick up any pending RCPT responses for SMTP pipelining */ 2547 while (mci->mci_nextaddr != NULL) 2548 { 2549 int r; 2550 2551 e->e_to = mci->mci_nextaddr->q_paddr; 2552 r = smtprcptstat(mci->mci_nextaddr, m, mci, e); 2553 if (r != EX_OK) 2554 { 2555 markfailure(e, mci->mci_nextaddr, mci, r, 2556 false); 2557 giveresponse(r, mci->mci_nextaddr->q_status, m, 2558 mci, ctladdr, xstart, e, 2559 mci->mci_nextaddr); 2560 if (r == EX_TEMPFAIL) 2561 mci->mci_nextaddr->q_state = QS_RETRY; 2562 } 2563 mci->mci_nextaddr = mci->mci_nextaddr->q_pchain; 2564 } 2565 e->e_to = oldto; 2566 2567 /* 2568 ** Connection might be closed in response to a RCPT command, 2569 ** i.e., the server responded with 421. In that case (at 2570 ** least) one RCPT has a temporary failure, hence we don't 2571 ** need to check mci_okrcpts (as it is done below) to figure 2572 ** out which error to return. 2573 */ 2574 2575 if (mci->mci_state == MCIS_CLOSED) 2576 { 2577 errno = mci->mci_errno; 2578 return EX_TEMPFAIL; 2579 } 2580 } 2581 #endif /* PIPELINING */ 2582 2583 /* now proceed with DATA phase */ 2584 SmtpPhase = mci->mci_phase = "client DATA 354"; 2585 mci->mci_state = MCIS_DATA; 2586 sm_setproctitle(true, e, "%s %s: %s", 2587 qid_printname(e), CurHostName, mci->mci_phase); 2588 r = reply(m, mci, e, TimeOuts.to_datainit, NULL, &enhsc, XS_DEFAULT); 2589 if (r < 0 || REPLYTYPE(r) == 4) 2590 { 2591 if (r >= 0) 2592 smtpquit(m, mci, e); 2593 errno = mci->mci_errno; 2594 return EX_TEMPFAIL; 2595 } 2596 else if (REPLYTYPE(r) == 5) 2597 { 2598 smtprset(m, mci, e); 2599 #if PIPELINING 2600 if (mci->mci_okrcpts <= 0) 2601 return mci->mci_retryrcpt ? EX_TEMPFAIL 2602 : EX_UNAVAILABLE; 2603 #endif /* PIPELINING */ 2604 return EX_UNAVAILABLE; 2605 } 2606 else if (REPLYTYPE(r) != 3) 2607 { 2608 if (LogLevel > 1) 2609 { 2610 sm_syslog(LOG_CRIT, e->e_id, 2611 "%.100s: SMTP DATA-1 protocol error: %s", 2612 CurHostName, 2613 shortenstring(SmtpReplyBuffer, 403)); 2614 } 2615 smtprset(m, mci, e); 2616 mci_setstat(mci, EX_PROTOCOL, ENHSCN(enhsc, "5.5.1"), 2617 SmtpReplyBuffer); 2618 #if PIPELINING 2619 if (mci->mci_okrcpts <= 0) 2620 return mci->mci_retryrcpt ? EX_TEMPFAIL 2621 : EX_PROTOCOL; 2622 #endif /* PIPELINING */ 2623 return EX_PROTOCOL; 2624 } 2625 2626 #if PIPELINING 2627 if (mci->mci_okrcpts > 0) 2628 { 2629 #endif /* PIPELINING */ 2630 2631 /* 2632 ** Set timeout around data writes. Make it at least large 2633 ** enough for DNS timeouts on all recipients plus some fudge 2634 ** factor. The main thing is that it should not be infinite. 2635 */ 2636 2637 if (tTd(18, 101)) 2638 { 2639 /* simulate a DATA timeout */ 2640 timeout = 10; 2641 } 2642 else 2643 timeout = DATA_PROGRESS_TIMEOUT * 1000; 2644 sm_io_setinfo(mci->mci_out, SM_IO_WHAT_TIMEOUT, &timeout); 2645 2646 2647 /* 2648 ** Output the actual message. 2649 */ 2650 2651 if (!(*e->e_puthdr)(mci, e->e_header, e, M87F_OUTER)) 2652 goto writeerr; 2653 2654 if (tTd(18, 101)) 2655 { 2656 /* simulate a DATA timeout */ 2657 (void) sleep(2); 2658 } 2659 2660 if (!(*e->e_putbody)(mci, e, NULL)) 2661 goto writeerr; 2662 2663 /* 2664 ** Cleanup after sending message. 2665 */ 2666 2667 2668 #if PIPELINING 2669 } 2670 #endif /* PIPELINING */ 2671 2672 #if _FFR_CATCH_BROKEN_MTAS 2673 if (sm_io_getinfo(mci->mci_in, SM_IO_IS_READABLE, NULL) > 0) 2674 { 2675 /* terminate the message */ 2676 (void) sm_io_fprintf(mci->mci_out, SM_TIME_DEFAULT, ".%s", 2677 m->m_eol); 2678 if (TrafficLogFile != NULL) 2679 (void) sm_io_fprintf(TrafficLogFile, SM_TIME_DEFAULT, 2680 "%05d >>> .\n", (int) CurrentPid); 2681 if (Verbose) 2682 nmessage(">>> ."); 2683 2684 sm_syslog(LOG_CRIT, e->e_id, 2685 "%.100s: SMTP DATA-1 protocol error: remote server returned response before final dot", 2686 CurHostName); 2687 mci->mci_errno = EIO; 2688 mci->mci_state = MCIS_ERROR; 2689 mci_setstat(mci, EX_PROTOCOL, "5.5.0", NULL); 2690 smtpquit(m, mci, e); 2691 return EX_PROTOCOL; 2692 } 2693 #endif /* _FFR_CATCH_BROKEN_MTAS */ 2694 2695 if (sm_io_error(mci->mci_out)) 2696 { 2697 /* error during processing -- don't send the dot */ 2698 mci->mci_errno = EIO; 2699 mci->mci_state = MCIS_ERROR; 2700 mci_setstat(mci, EX_IOERR, "4.4.2", NULL); 2701 smtpquit(m, mci, e); 2702 return EX_IOERR; 2703 } 2704 2705 /* terminate the message */ 2706 if (sm_io_fprintf(mci->mci_out, SM_TIME_DEFAULT, "%s.%s", 2707 bitset(MCIF_INLONGLINE, mci->mci_flags) ? m->m_eol : "", 2708 m->m_eol) == SM_IO_EOF) 2709 goto writeerr; 2710 if (TrafficLogFile != NULL) 2711 (void) sm_io_fprintf(TrafficLogFile, SM_TIME_DEFAULT, 2712 "%05d >>> .\n", (int) CurrentPid); 2713 if (Verbose) 2714 nmessage(">>> ."); 2715 2716 /* check for the results of the transaction */ 2717 SmtpPhase = mci->mci_phase = "client DATA status"; 2718 sm_setproctitle(true, e, "%s %s: %s", qid_printname(e), 2719 CurHostName, mci->mci_phase); 2720 if (bitnset(M_LMTP, m->m_flags)) 2721 return EX_OK; 2722 r = reply(m, mci, e, TimeOuts.to_datafinal, NULL, &enhsc, XS_DEFAULT); 2723 if (r < 0) 2724 return EX_TEMPFAIL; 2725 if (mci->mci_state == MCIS_DATA) 2726 mci->mci_state = MCIS_OPEN; 2727 xstat = EX_NOTSTICKY; 2728 if (r == 452) 2729 rstat = EX_TEMPFAIL; 2730 else if (REPLYTYPE(r) == 4) 2731 rstat = xstat = EX_TEMPFAIL; 2732 else if (REPLYTYPE(r) == 2) 2733 rstat = xstat = EX_OK; 2734 else if (REPLYCLASS(r) != 5) 2735 rstat = xstat = EX_PROTOCOL; 2736 else if (REPLYTYPE(r) == 5) 2737 rstat = EX_UNAVAILABLE; 2738 else 2739 rstat = EX_PROTOCOL; 2740 mci_setstat(mci, xstat, ENHSCN(enhsc, smtptodsn(r)), 2741 SmtpReplyBuffer); 2742 if (bitset(MCIF_ENHSTAT, mci->mci_flags) && 2743 (r = isenhsc(SmtpReplyBuffer + 4, ' ')) > 0) 2744 r += 5; 2745 else 2746 r = 4; 2747 e->e_statmsg = sm_rpool_strdup_x(e->e_rpool, &SmtpReplyBuffer[r]); 2748 SmtpPhase = mci->mci_phase = "idle"; 2749 sm_setproctitle(true, e, "%s: %s", CurHostName, mci->mci_phase); 2750 if (rstat != EX_PROTOCOL) 2751 return rstat; 2752 if (LogLevel > 1) 2753 { 2754 sm_syslog(LOG_CRIT, e->e_id, 2755 "%.100s: SMTP DATA-2 protocol error: %s", 2756 CurHostName, 2757 shortenstring(SmtpReplyBuffer, 403)); 2758 } 2759 return rstat; 2760 2761 writeerr: 2762 mci->mci_errno = errno; 2763 mci->mci_state = MCIS_ERROR; 2764 mci_setstat(mci, EX_TEMPFAIL, "4.4.2", NULL); 2765 2766 /* 2767 ** If putbody() couldn't finish due to a timeout, 2768 ** rewind it here in the timeout handler. See 2769 ** comments at the end of putbody() for reasoning. 2770 */ 2771 2772 if (e->e_dfp != NULL) 2773 (void) bfrewind(e->e_dfp); 2774 2775 errno = mci->mci_errno; 2776 syserr("451 4.4.1 timeout writing message to %s", CurHostName); 2777 smtpquit(m, mci, e); 2778 return EX_TEMPFAIL; 2779 } 2780 2781 /* 2782 ** SMTPGETSTAT -- get status code from DATA in LMTP 2783 ** 2784 ** Parameters: 2785 ** m -- the mailer to which we are sending the message. 2786 ** mci -- the mailer connection structure. 2787 ** e -- the current envelope. 2788 ** 2789 ** Returns: 2790 ** The exit status corresponding to the reply code. 2791 */ 2792 2793 int 2794 smtpgetstat(m, mci, e) 2795 MAILER *m; 2796 MCI *mci; 2797 ENVELOPE *e; 2798 { 2799 int r; 2800 int off; 2801 int status, xstat; 2802 char *enhsc; 2803 2804 enhsc = NULL; 2805 2806 /* check for the results of the transaction */ 2807 r = reply(m, mci, e, TimeOuts.to_datafinal, NULL, &enhsc, XS_DEFAULT); 2808 if (r < 0) 2809 return EX_TEMPFAIL; 2810 xstat = EX_NOTSTICKY; 2811 if (REPLYTYPE(r) == 4) 2812 status = EX_TEMPFAIL; 2813 else if (REPLYTYPE(r) == 2) 2814 status = xstat = EX_OK; 2815 else if (REPLYCLASS(r) != 5) 2816 status = xstat = EX_PROTOCOL; 2817 else if (REPLYTYPE(r) == 5) 2818 status = EX_UNAVAILABLE; 2819 else 2820 status = EX_PROTOCOL; 2821 if (bitset(MCIF_ENHSTAT, mci->mci_flags) && 2822 (off = isenhsc(SmtpReplyBuffer + 4, ' ')) > 0) 2823 off += 5; 2824 else 2825 off = 4; 2826 e->e_statmsg = sm_rpool_strdup_x(e->e_rpool, &SmtpReplyBuffer[off]); 2827 mci_setstat(mci, xstat, ENHSCN(enhsc, smtptodsn(r)), SmtpReplyBuffer); 2828 if (LogLevel > 1 && status == EX_PROTOCOL) 2829 { 2830 sm_syslog(LOG_CRIT, e->e_id, 2831 "%.100s: SMTP DATA-3 protocol error: %s", 2832 CurHostName, 2833 shortenstring(SmtpReplyBuffer, 403)); 2834 } 2835 return status; 2836 } 2837 /* 2838 ** SMTPQUIT -- close the SMTP connection. 2839 ** 2840 ** Parameters: 2841 ** m -- a pointer to the mailer. 2842 ** mci -- the mailer connection information. 2843 ** e -- the current envelope. 2844 ** 2845 ** Returns: 2846 ** none. 2847 ** 2848 ** Side Effects: 2849 ** sends the final protocol and closes the connection. 2850 */ 2851 2852 void 2853 smtpquit(m, mci, e) 2854 register MAILER *m; 2855 register MCI *mci; 2856 ENVELOPE *e; 2857 { 2858 bool oldSuprErrs = SuprErrs; 2859 int rcode; 2860 char *oldcurhost; 2861 2862 if (mci->mci_state == MCIS_CLOSED) 2863 { 2864 mci_close(mci, "smtpquit:1"); 2865 return; 2866 } 2867 2868 oldcurhost = CurHostName; 2869 CurHostName = mci->mci_host; /* XXX UGLY XXX */ 2870 if (CurHostName == NULL) 2871 CurHostName = MyHostName; 2872 2873 #if PIPELINING 2874 mci->mci_okrcpts = 0; 2875 #endif /* PIPELINING */ 2876 2877 /* 2878 ** Suppress errors here -- we may be processing a different 2879 ** job when we do the quit connection, and we don't want the 2880 ** new job to be penalized for something that isn't it's 2881 ** problem. 2882 */ 2883 2884 SuprErrs = true; 2885 2886 /* send the quit message if we haven't gotten I/O error */ 2887 if (mci->mci_state != MCIS_ERROR && 2888 mci->mci_state != MCIS_QUITING) 2889 { 2890 SmtpPhase = "client QUIT"; 2891 mci->mci_state = MCIS_QUITING; 2892 smtpmessage("QUIT", m, mci); 2893 (void) reply(m, mci, e, TimeOuts.to_quit, NULL, NULL, 2894 XS_DEFAULT); 2895 SuprErrs = oldSuprErrs; 2896 if (mci->mci_state == MCIS_CLOSED) 2897 goto end; 2898 } 2899 2900 /* now actually close the connection and pick up the zombie */ 2901 rcode = endmailer(mci, e, NULL); 2902 if (rcode != EX_OK) 2903 { 2904 char *mailer = NULL; 2905 2906 if (mci->mci_mailer != NULL && 2907 mci->mci_mailer->m_name != NULL) 2908 mailer = mci->mci_mailer->m_name; 2909 2910 /* look for naughty mailers */ 2911 sm_syslog(LOG_ERR, e->e_id, 2912 "smtpquit: mailer%s%s exited with exit value %d", 2913 mailer == NULL ? "" : " ", 2914 mailer == NULL ? "" : mailer, 2915 rcode); 2916 } 2917 2918 SuprErrs = oldSuprErrs; 2919 2920 end: 2921 CurHostName = oldcurhost; 2922 return; 2923 } 2924 /* 2925 ** SMTPRSET -- send a RSET (reset) command 2926 ** 2927 ** Parameters: 2928 ** m -- a pointer to the mailer. 2929 ** mci -- the mailer connection information. 2930 ** e -- the current envelope. 2931 ** 2932 ** Returns: 2933 ** none. 2934 ** 2935 ** Side Effects: 2936 ** closes the connection if there is no reply to RSET. 2937 */ 2938 2939 void 2940 smtprset(m, mci, e) 2941 register MAILER *m; 2942 register MCI *mci; 2943 ENVELOPE *e; 2944 { 2945 int r; 2946 2947 CurHostName = mci->mci_host; /* XXX UGLY XXX */ 2948 if (CurHostName == NULL) 2949 CurHostName = MyHostName; 2950 2951 #if PIPELINING 2952 mci->mci_okrcpts = 0; 2953 #endif /* PIPELINING */ 2954 2955 /* 2956 ** Check if connection is gone, if so 2957 ** it's a tempfail and we use mci_errno 2958 ** for the reason. 2959 */ 2960 2961 if (mci->mci_state == MCIS_CLOSED) 2962 { 2963 errno = mci->mci_errno; 2964 return; 2965 } 2966 2967 SmtpPhase = "client RSET"; 2968 smtpmessage("RSET", m, mci); 2969 r = reply(m, mci, e, TimeOuts.to_rset, NULL, NULL, XS_DEFAULT); 2970 if (r < 0) 2971 return; 2972 2973 /* 2974 ** Any response is deemed to be acceptable. 2975 ** The standard does not state the proper action 2976 ** to take when a value other than 250 is received. 2977 ** 2978 ** However, if 421 is returned for the RSET, leave 2979 ** mci_state alone (MCIS_SSD can be set in reply() 2980 ** and MCIS_CLOSED can be set in smtpquit() if 2981 ** reply() gets a 421 and calls smtpquit()). 2982 */ 2983 2984 if (mci->mci_state != MCIS_SSD && mci->mci_state != MCIS_CLOSED) 2985 mci->mci_state = MCIS_OPEN; 2986 else if (mci->mci_exitstat == EX_OK) 2987 mci_setstat(mci, EX_TEMPFAIL, "4.5.0", NULL); 2988 } 2989 /* 2990 ** SMTPPROBE -- check the connection state 2991 ** 2992 ** Parameters: 2993 ** mci -- the mailer connection information. 2994 ** 2995 ** Returns: 2996 ** none. 2997 ** 2998 ** Side Effects: 2999 ** closes the connection if there is no reply to RSET. 3000 */ 3001 3002 int 3003 smtpprobe(mci) 3004 register MCI *mci; 3005 { 3006 int r; 3007 MAILER *m = mci->mci_mailer; 3008 ENVELOPE *e; 3009 extern ENVELOPE BlankEnvelope; 3010 3011 CurHostName = mci->mci_host; /* XXX UGLY XXX */ 3012 if (CurHostName == NULL) 3013 CurHostName = MyHostName; 3014 3015 e = &BlankEnvelope; 3016 SmtpPhase = "client probe"; 3017 smtpmessage("RSET", m, mci); 3018 r = reply(m, mci, e, TimeOuts.to_miscshort, NULL, NULL, XS_DEFAULT); 3019 if (REPLYTYPE(r) != 2) 3020 smtpquit(m, mci, e); 3021 return r; 3022 } 3023 /* 3024 ** REPLY -- read arpanet reply 3025 ** 3026 ** Parameters: 3027 ** m -- the mailer we are reading the reply from. 3028 ** mci -- the mailer connection info structure. 3029 ** e -- the current envelope. 3030 ** timeout -- the timeout for reads. 3031 ** pfunc -- processing function called on each line of response. 3032 ** If null, no special processing is done. 3033 ** enhstat -- optional, returns enhanced error code string (if set) 3034 ** rtype -- type of SmtpMsgBuffer: does it contains secret data? 3035 ** 3036 ** Returns: 3037 ** reply code it reads. 3038 ** 3039 ** Side Effects: 3040 ** flushes the mail file. 3041 */ 3042 3043 int 3044 reply(m, mci, e, timeout, pfunc, enhstat, rtype) 3045 MAILER *m; 3046 MCI *mci; 3047 ENVELOPE *e; 3048 time_t timeout; 3049 void (*pfunc) __P((char *, bool, MAILER *, MCI *, ENVELOPE *)); 3050 char **enhstat; 3051 int rtype; 3052 { 3053 register char *bufp; 3054 register int r; 3055 bool firstline = true; 3056 char junkbuf[MAXLINE]; 3057 static char enhstatcode[ENHSCLEN]; 3058 int save_errno; 3059 3060 /* 3061 ** Flush the output before reading response. 3062 ** 3063 ** For SMTP pipelining, it would be better if we didn't do 3064 ** this if there was already data waiting to be read. But 3065 ** to do it properly means pushing it to the I/O library, 3066 ** since it really needs to be done below the buffer layer. 3067 */ 3068 3069 if (mci->mci_out != NULL) 3070 (void) sm_io_flush(mci->mci_out, SM_TIME_DEFAULT); 3071 3072 if (tTd(18, 1)) 3073 sm_dprintf("reply\n"); 3074 3075 /* 3076 ** Read the input line, being careful not to hang. 3077 */ 3078 3079 bufp = SmtpReplyBuffer; 3080 set_tls_rd_tmo(timeout); 3081 for (;;) 3082 { 3083 register char *p; 3084 3085 /* actually do the read */ 3086 if (e->e_xfp != NULL) /* for debugging */ 3087 (void) sm_io_flush(e->e_xfp, SM_TIME_DEFAULT); 3088 3089 /* if we are in the process of closing just give the code */ 3090 if (mci->mci_state == MCIS_CLOSED) 3091 return SMTPCLOSING; 3092 3093 /* don't try to read from a non-existent fd */ 3094 if (mci->mci_in == NULL) 3095 { 3096 if (mci->mci_errno == 0) 3097 mci->mci_errno = EBADF; 3098 3099 /* errors on QUIT should be ignored */ 3100 if (strncmp(SmtpMsgBuffer, "QUIT", 4) == 0) 3101 { 3102 errno = mci->mci_errno; 3103 mci_close(mci, "reply:1"); 3104 return -1; 3105 } 3106 mci->mci_state = MCIS_ERROR; 3107 smtpquit(m, mci, e); 3108 errno = mci->mci_errno; 3109 return -1; 3110 } 3111 3112 if (mci->mci_out != NULL) 3113 (void) sm_io_flush(mci->mci_out, SM_TIME_DEFAULT); 3114 3115 /* get the line from the other side */ 3116 p = sfgets(bufp, MAXLINE, mci->mci_in, timeout, SmtpPhase); 3117 save_errno = errno; 3118 mci->mci_lastuse = curtime(); 3119 3120 if (p == NULL) 3121 { 3122 bool oldholderrs; 3123 extern char MsgBuf[]; 3124 3125 /* errors on QUIT should be ignored */ 3126 if (strncmp(SmtpMsgBuffer, "QUIT", 4) == 0) 3127 { 3128 mci_close(mci, "reply:2"); 3129 return -1; 3130 } 3131 3132 /* if the remote end closed early, fake an error */ 3133 errno = save_errno; 3134 if (errno == 0) 3135 { 3136 (void) sm_snprintf(SmtpReplyBuffer, 3137 sizeof(SmtpReplyBuffer), 3138 "421 4.4.1 Connection reset by %s", 3139 CURHOSTNAME); 3140 #ifdef ECONNRESET 3141 errno = ECONNRESET; 3142 #else /* ECONNRESET */ 3143 errno = EPIPE; 3144 #endif /* ECONNRESET */ 3145 } 3146 3147 mci->mci_errno = errno; 3148 oldholderrs = HoldErrs; 3149 HoldErrs = true; 3150 usrerr("451 4.4.1 reply: read error from %s", 3151 CURHOSTNAME); 3152 mci_setstat(mci, EX_TEMPFAIL, "4.4.2", MsgBuf); 3153 3154 /* if debugging, pause so we can see state */ 3155 if (tTd(18, 100)) 3156 (void) pause(); 3157 mci->mci_state = MCIS_ERROR; 3158 smtpquit(m, mci, e); 3159 #if XDEBUG 3160 { 3161 char wbuf[MAXLINE]; 3162 3163 p = wbuf; 3164 if (e->e_to != NULL) 3165 { 3166 (void) sm_snprintf(p, 3167 SPACELEFT(wbuf, p), 3168 "%s... ", 3169 shortenstring(e->e_to, MAXSHORTSTR)); 3170 p += strlen(p); 3171 } 3172 (void) sm_snprintf(p, SPACELEFT(wbuf, p), 3173 "reply(%.100s) during %s", 3174 CURHOSTNAME, SmtpPhase); 3175 checkfd012(wbuf); 3176 } 3177 #endif /* XDEBUG */ 3178 HoldErrs = oldholderrs; 3179 errno = save_errno; 3180 return -1; 3181 } 3182 fixcrlf(bufp, true); 3183 3184 /* EHLO failure is not a real error */ 3185 if (e->e_xfp != NULL && (bufp[0] == '4' || 3186 (bufp[0] == '5' && strncmp(SmtpMsgBuffer, "EHLO", 4) != 0))) 3187 { 3188 /* serious error -- log the previous command */ 3189 if (SmtpNeedIntro) 3190 { 3191 /* inform user who we are chatting with */ 3192 (void) sm_io_fprintf(CurEnv->e_xfp, 3193 SM_TIME_DEFAULT, 3194 "... while talking to %s:\n", 3195 CURHOSTNAME); 3196 SmtpNeedIntro = false; 3197 } 3198 if (SmtpMsgBuffer[0] != '\0') 3199 { 3200 (void) sm_io_fprintf(e->e_xfp, 3201 SM_TIME_DEFAULT, 3202 ">>> %s\n", 3203 (rtype == XS_STARTTLS) 3204 ? "STARTTLS dialogue" 3205 : ((rtype == XS_AUTH) 3206 ? "AUTH dialogue" 3207 : SmtpMsgBuffer)); 3208 SmtpMsgBuffer[0] = '\0'; 3209 } 3210 3211 /* now log the message as from the other side */ 3212 (void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT, 3213 "<<< %s\n", bufp); 3214 } 3215 3216 /* display the input for verbose mode */ 3217 if (Verbose) 3218 nmessage("050 %s", bufp); 3219 3220 /* ignore improperly formatted input */ 3221 if (!ISSMTPREPLY(bufp)) 3222 continue; 3223 3224 if (bitset(MCIF_ENHSTAT, mci->mci_flags) && 3225 enhstat != NULL && 3226 extenhsc(bufp + 4, ' ', enhstatcode) > 0) 3227 *enhstat = enhstatcode; 3228 3229 /* process the line */ 3230 if (pfunc != NULL) 3231 (*pfunc)(bufp, firstline, m, mci, e); 3232 3233 firstline = false; 3234 3235 /* decode the reply code */ 3236 r = atoi(bufp); 3237 3238 /* extra semantics: 0xx codes are "informational" */ 3239 if (r < 100) 3240 continue; 3241 3242 /* if no continuation lines, return this line */ 3243 if (bufp[3] != '-') 3244 break; 3245 3246 /* first line of real reply -- ignore rest */ 3247 bufp = junkbuf; 3248 } 3249 3250 /* 3251 ** Now look at SmtpReplyBuffer -- only care about the first 3252 ** line of the response from here on out. 3253 */ 3254 3255 /* save temporary failure messages for posterity */ 3256 if (SmtpReplyBuffer[0] == '4') 3257 (void) sm_strlcpy(SmtpError, SmtpReplyBuffer, sizeof(SmtpError)); 3258 3259 /* reply code 421 is "Service Shutting Down" */ 3260 if (r == SMTPCLOSING && mci->mci_state != MCIS_SSD && 3261 mci->mci_state != MCIS_QUITING) 3262 { 3263 /* send the quit protocol */ 3264 mci->mci_state = MCIS_SSD; 3265 smtpquit(m, mci, e); 3266 } 3267 3268 return r; 3269 } 3270 /* 3271 ** SMTPMESSAGE -- send message to server 3272 ** 3273 ** Parameters: 3274 ** f -- format 3275 ** m -- the mailer to control formatting. 3276 ** a, b, c -- parameters 3277 ** 3278 ** Returns: 3279 ** none. 3280 ** 3281 ** Side Effects: 3282 ** writes message to mci->mci_out. 3283 */ 3284 3285 /*VARARGS1*/ 3286 void 3287 #ifdef __STDC__ 3288 smtpmessage(char *f, MAILER *m, MCI *mci, ...) 3289 #else /* __STDC__ */ 3290 smtpmessage(f, m, mci, va_alist) 3291 char *f; 3292 MAILER *m; 3293 MCI *mci; 3294 va_dcl 3295 #endif /* __STDC__ */ 3296 { 3297 SM_VA_LOCAL_DECL 3298 3299 SM_VA_START(ap, mci); 3300 (void) sm_vsnprintf(SmtpMsgBuffer, sizeof(SmtpMsgBuffer), f, ap); 3301 SM_VA_END(ap); 3302 3303 if (tTd(18, 1) || Verbose) 3304 nmessage(">>> %s", SmtpMsgBuffer); 3305 if (TrafficLogFile != NULL) 3306 (void) sm_io_fprintf(TrafficLogFile, SM_TIME_DEFAULT, 3307 "%05d >>> %s\n", (int) CurrentPid, 3308 SmtpMsgBuffer); 3309 if (mci->mci_out != NULL) 3310 { 3311 (void) sm_io_fprintf(mci->mci_out, SM_TIME_DEFAULT, "%s%s", 3312 SmtpMsgBuffer, m == NULL ? "\r\n" 3313 : m->m_eol); 3314 } 3315 else if (tTd(18, 1)) 3316 { 3317 sm_dprintf("smtpmessage: NULL mci_out\n"); 3318 } 3319 } 3320