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