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