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