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