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