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