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