1 /* 2 * Copyright (c) 1983 Eric P. Allman 3 * Copyright (c) 1988 Regents of the University of California. 4 * All rights reserved. 5 * 6 * %sccs.include.redist.c% 7 */ 8 9 # include "sendmail.h" 10 11 #ifndef lint 12 #ifdef SMTP 13 static char sccsid[] = "@(#)usersmtp.c 6.30 (Berkeley) 05/12/93 (with SMTP)"; 14 #else 15 static char sccsid[] = "@(#)usersmtp.c 6.30 (Berkeley) 05/12/93 (without SMTP)"; 16 #endif 17 #endif /* not lint */ 18 19 # include <sysexits.h> 20 # include <errno.h> 21 22 # ifdef SMTP 23 24 /* 25 ** USERSMTP -- run SMTP protocol from the user end. 26 ** 27 ** This protocol is described in RFC821. 28 */ 29 30 #define REPLYTYPE(r) ((r) / 100) /* first digit of reply code */ 31 #define REPLYCLASS(r) (((r) / 10) % 10) /* second digit of reply code */ 32 #define SMTPCLOSING 421 /* "Service Shutting Down" */ 33 34 char SmtpMsgBuffer[MAXLINE]; /* buffer for commands */ 35 char SmtpReplyBuffer[MAXLINE]; /* buffer for replies */ 36 char SmtpError[MAXLINE] = ""; /* save failure error messages */ 37 int SmtpPid; /* pid of mailer */ 38 39 #ifdef __STDC__ 40 extern smtpmessage(char *f, MAILER *m, MCI *mci, ...); 41 #endif 42 /* 43 ** SMTPINIT -- initialize SMTP. 44 ** 45 ** Opens the connection and sends the initial protocol. 46 ** 47 ** Parameters: 48 ** m -- mailer to create connection to. 49 ** pvp -- pointer to parameter vector to pass to 50 ** the mailer. 51 ** 52 ** Returns: 53 ** none. 54 ** 55 ** Side Effects: 56 ** creates connection and sends initial protocol. 57 */ 58 59 smtpinit(m, mci, e) 60 struct mailer *m; 61 register MCI *mci; 62 ENVELOPE *e; 63 { 64 register int r; 65 register char *p; 66 extern STAB *stab(); 67 extern void helo_options(); 68 69 if (tTd(17, 1)) 70 { 71 printf("smtpinit "); 72 mci_dump(mci); 73 } 74 75 /* 76 ** Open the connection to the mailer. 77 */ 78 79 SmtpError[0] = '\0'; 80 CurHostName = mci->mci_host; /* XXX UGLY XXX */ 81 switch (mci->mci_state) 82 { 83 case MCIS_ACTIVE: 84 /* need to clear old information */ 85 smtprset(m, mci, e); 86 /* fall through */ 87 88 case MCIS_OPEN: 89 return; 90 91 case MCIS_ERROR: 92 case MCIS_SSD: 93 /* shouldn't happen */ 94 smtpquit(m, mci, e); 95 /* fall through */ 96 97 case MCIS_CLOSED: 98 syserr("451 smtpinit: state CLOSED"); 99 return; 100 101 case MCIS_OPENING: 102 break; 103 } 104 105 mci->mci_state = MCIS_OPENING; 106 107 /* 108 ** Get the greeting message. 109 ** This should appear spontaneously. Give it five minutes to 110 ** happen. 111 */ 112 113 SmtpPhase = mci->mci_phase = "greeting wait"; 114 setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase); 115 r = reply(m, mci, e, TimeOuts.to_initial, NULL); 116 if (r < 0 || REPLYTYPE(r) != 2) 117 goto tempfail1; 118 119 /* 120 ** Send the HELO command. 121 ** My mother taught me to always introduce myself. 122 */ 123 124 if (bitnset(M_ESMTP, m->m_flags)) 125 mci->mci_flags |= MCIF_ESMTP; 126 127 tryhelo: 128 if (bitset(MCIF_ESMTP, mci->mci_flags)) 129 { 130 smtpmessage("EHLO %s", m, mci, MyHostName); 131 SmtpPhase = mci->mci_phase = "EHLO wait"; 132 } 133 else 134 { 135 smtpmessage("HELO %s", m, mci, MyHostName); 136 SmtpPhase = mci->mci_phase = "HELO wait"; 137 } 138 setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase); 139 r = reply(m, mci, e, TimeOuts.to_helo, helo_options); 140 if (r < 0) 141 goto tempfail1; 142 else if (REPLYTYPE(r) == 5) 143 { 144 if (bitset(MCIF_ESMTP, mci->mci_flags)) 145 { 146 /* try old SMTP instead */ 147 mci->mci_flags &= ~MCIF_ESMTP; 148 goto tryhelo; 149 } 150 goto unavailable; 151 } 152 else if (REPLYTYPE(r) != 2) 153 goto tempfail1; 154 155 /* 156 ** Check to see if we actually ended up talking to ourself. 157 ** This means we didn't know about an alias or MX, or we managed 158 ** to connect to an echo server. 159 */ 160 161 p = strchr(&SmtpReplyBuffer[4], ' '); 162 if (p != NULL) 163 *p == '\0'; 164 if (strcasecmp(&SmtpReplyBuffer[4], MyHostName) == 0) 165 { 166 syserr("553 %s config error: mail loops back to myself", 167 MyHostName); 168 mci->mci_exitstat = EX_CONFIG; 169 mci->mci_errno = 0; 170 smtpquit(m, mci, e); 171 return; 172 } 173 174 /* 175 ** If this is expected to be another sendmail, send some internal 176 ** commands. 177 */ 178 179 if (bitnset(M_INTERNAL, m->m_flags)) 180 { 181 /* tell it to be verbose */ 182 smtpmessage("VERB", m, mci); 183 r = reply(m, mci, e, TimeOuts.to_miscshort, NULL); 184 if (r < 0) 185 goto tempfail2; 186 } 187 188 mci->mci_state = MCIS_OPEN; 189 return; 190 191 tempfail1: 192 tempfail2: 193 mci->mci_exitstat = EX_TEMPFAIL; 194 if (mci->mci_errno == 0) 195 mci->mci_errno = errno; 196 if (mci->mci_state != MCIS_CLOSED) 197 smtpquit(m, mci, e); 198 return; 199 200 unavailable: 201 mci->mci_exitstat = EX_UNAVAILABLE; 202 mci->mci_errno = errno; 203 smtpquit(m, mci, e); 204 return; 205 } 206 /* 207 ** HELO_OPTIONS -- process the options on a HELO line. 208 ** 209 ** Parameters: 210 ** line -- the response line. 211 ** m -- the mailer. 212 ** mci -- the mailer connection info. 213 ** e -- the envelope. 214 ** 215 ** Returns: 216 ** none. 217 */ 218 219 void 220 helo_options(line, m, mci, e) 221 char *line; 222 MAILER *m; 223 register MCI *mci; 224 ENVELOPE *e; 225 { 226 register char *p; 227 228 if (strlen(line) < 5) 229 return; 230 line += 4; 231 p = strchr(line, ' '); 232 if (p != NULL) 233 *p++ = '\0'; 234 if (strcasecmp(line, "size") == 0) 235 { 236 mci->mci_flags |= MCIF_SIZE; 237 if (p != NULL) 238 mci->mci_maxsize = atol(p); 239 } 240 else if (strcasecmp(line, "8bitmime") == 0) 241 mci->mci_flags |= MCIF_8BITMIME; 242 else if (strcasecmp(line, "expn") == 0) 243 mci->mci_flags |= MCIF_EXPN; 244 } 245 /* 246 ** SMTPMAILFROM -- send MAIL command 247 ** 248 ** Parameters: 249 ** m -- the mailer. 250 ** mci -- the mailer connection structure. 251 ** e -- the envelope (including the sender to specify). 252 */ 253 254 smtpmailfrom(m, mci, e) 255 struct mailer *m; 256 MCI *mci; 257 ENVELOPE *e; 258 { 259 int r; 260 char buf[MAXNAME]; 261 char optbuf[MAXLINE]; 262 263 if (tTd(17, 2)) 264 printf("smtpmailfrom: CurHost=%s\n", CurHostName); 265 266 /* set up appropriate options to include */ 267 if (bitset(MCIF_SIZE, mci->mci_flags)) 268 sprintf(optbuf, " SIZE=%ld", e->e_msgsize); 269 else 270 strcpy(optbuf, ""); 271 272 /* 273 ** Send the MAIL command. 274 ** Designates the sender. 275 */ 276 277 mci->mci_state = MCIS_ACTIVE; 278 279 if (bitset(EF_RESPONSE, e->e_flags) && 280 !bitnset(M_NO_NULL_FROM, m->m_flags)) 281 (void) strcpy(buf, ""); 282 else 283 expand("\201g", buf, &buf[sizeof buf - 1], e); 284 if (e->e_from.q_mailer == LocalMailer || 285 !bitnset(M_FROMPATH, m->m_flags)) 286 { 287 smtpmessage("MAIL From:<%s>%s", m, mci, buf, optbuf); 288 } 289 else 290 { 291 smtpmessage("MAIL From:<@%s%c%s>%s", m, mci, MyHostName, 292 buf[0] == '@' ? ',' : ':', buf, optbuf); 293 } 294 SmtpPhase = mci->mci_phase = "MAIL wait"; 295 setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase); 296 r = reply(m, mci, e, TimeOuts.to_mail, NULL); 297 if (r < 0 || REPLYTYPE(r) == 4) 298 { 299 mci->mci_exitstat = EX_TEMPFAIL; 300 mci->mci_errno = errno; 301 smtpquit(m, mci, e); 302 return EX_TEMPFAIL; 303 } 304 else if (r == 250) 305 { 306 mci->mci_exitstat = EX_OK; 307 return EX_OK; 308 } 309 else if (r == 552) 310 { 311 /* signal service unavailable */ 312 mci->mci_exitstat = EX_UNAVAILABLE; 313 smtpquit(m, mci, e); 314 return EX_UNAVAILABLE; 315 } 316 317 #ifdef LOG 318 if (LogLevel > 1) 319 { 320 syslog(LOG_CRIT, "%s: SMTP MAIL protocol error: %s", 321 e->e_id, SmtpReplyBuffer); 322 } 323 #endif 324 325 /* protocol error -- close up */ 326 smtpquit(m, mci, e); 327 mci->mci_exitstat = EX_PROTOCOL; 328 return EX_PROTOCOL; 329 } 330 /* 331 ** SMTPRCPT -- designate recipient. 332 ** 333 ** Parameters: 334 ** to -- address of recipient. 335 ** m -- the mailer we are sending to. 336 ** mci -- the connection info for this transaction. 337 ** e -- the envelope for this transaction. 338 ** 339 ** Returns: 340 ** exit status corresponding to recipient status. 341 ** 342 ** Side Effects: 343 ** Sends the mail via SMTP. 344 */ 345 346 smtprcpt(to, m, mci, e) 347 ADDRESS *to; 348 register MAILER *m; 349 MCI *mci; 350 ENVELOPE *e; 351 { 352 register int r; 353 354 smtpmessage("RCPT To:<%s>", m, mci, to->q_user); 355 356 SmtpPhase = mci->mci_phase = "RCPT wait"; 357 setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase); 358 r = reply(m, mci, e, TimeOuts.to_rcpt, NULL); 359 if (r < 0 || REPLYTYPE(r) == 4) 360 return (EX_TEMPFAIL); 361 else if (REPLYTYPE(r) == 2) 362 return (EX_OK); 363 else if (r == 550 || r == 551 || r == 553) 364 return (EX_NOUSER); 365 else if (r == 552 || r == 554) 366 return (EX_UNAVAILABLE); 367 368 #ifdef LOG 369 if (LogLevel > 1) 370 { 371 syslog(LOG_CRIT, "%s: SMTP RCPT protocol error: %s", 372 e->e_id, SmtpReplyBuffer); 373 } 374 #endif 375 376 return (EX_PROTOCOL); 377 } 378 /* 379 ** SMTPDATA -- send the data and clean up the transaction. 380 ** 381 ** Parameters: 382 ** m -- mailer being sent to. 383 ** e -- the envelope for this message. 384 ** 385 ** Returns: 386 ** exit status corresponding to DATA command. 387 ** 388 ** Side Effects: 389 ** none. 390 */ 391 392 smtpdata(m, mci, e) 393 struct mailer *m; 394 register MCI *mci; 395 register ENVELOPE *e; 396 { 397 register int r; 398 399 /* 400 ** Send the data. 401 ** First send the command and check that it is ok. 402 ** Then send the data. 403 ** Follow it up with a dot to terminate. 404 ** Finally get the results of the transaction. 405 */ 406 407 /* send the command and check ok to proceed */ 408 smtpmessage("DATA", m, mci); 409 SmtpPhase = mci->mci_phase = "DATA wait"; 410 setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase); 411 r = reply(m, mci, e, TimeOuts.to_datainit, NULL); 412 if (r < 0 || REPLYTYPE(r) == 4) 413 { 414 smtpquit(m, mci, e); 415 return (EX_TEMPFAIL); 416 } 417 else if (r == 554) 418 { 419 smtprset(m, mci, e); 420 return (EX_UNAVAILABLE); 421 } 422 else if (r != 354) 423 { 424 #ifdef LOG 425 if (LogLevel > 1) 426 { 427 syslog(LOG_CRIT, "%s: SMTP DATA-1 protocol error: %s", 428 e->e_id, SmtpReplyBuffer); 429 } 430 #endif 431 smtprset(m, mci, e); 432 return (EX_PROTOCOL); 433 } 434 435 /* now output the actual message */ 436 (*e->e_puthdr)(mci->mci_out, m, e); 437 putline("\n", mci->mci_out, m); 438 (*e->e_putbody)(mci->mci_out, m, e, NULL); 439 440 /* terminate the message */ 441 fprintf(mci->mci_out, ".%s", m->m_eol); 442 if (Verbose) 443 nmessage(">>> ."); 444 445 /* check for the results of the transaction */ 446 SmtpPhase = mci->mci_phase = "result wait"; 447 setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase); 448 r = reply(m, mci, e, TimeOuts.to_datafinal, NULL); 449 if (r < 0) 450 { 451 smtpquit(m, mci, e); 452 return (EX_TEMPFAIL); 453 } 454 mci->mci_state = MCIS_OPEN; 455 e->e_statmsg = newstr(&SmtpReplyBuffer[4]); 456 if (REPLYTYPE(r) == 4) 457 return (EX_TEMPFAIL); 458 else if (r == 250) 459 return (EX_OK); 460 else if (r == 552 || r == 554) 461 return (EX_UNAVAILABLE); 462 #ifdef LOG 463 if (LogLevel > 1) 464 { 465 syslog(LOG_CRIT, "%s: SMTP DATA-2 protocol error: %s", 466 e->e_id, SmtpReplyBuffer); 467 } 468 #endif 469 return (EX_PROTOCOL); 470 } 471 /* 472 ** SMTPQUIT -- close the SMTP connection. 473 ** 474 ** Parameters: 475 ** m -- a pointer to the mailer. 476 ** 477 ** Returns: 478 ** none. 479 ** 480 ** Side Effects: 481 ** sends the final protocol and closes the connection. 482 */ 483 484 smtpquit(m, mci, e) 485 register MAILER *m; 486 register MCI *mci; 487 ENVELOPE *e; 488 { 489 int i; 490 491 /* send the quit message if we haven't gotten I/O error */ 492 if (mci->mci_state != MCIS_ERROR) 493 { 494 smtpmessage("QUIT", m, mci); 495 (void) reply(m, mci, e, TimeOuts.to_quit, NULL); 496 if (mci->mci_state == MCIS_CLOSED) 497 return; 498 } 499 500 /* now actually close the connection and pick up the zombie */ 501 i = endmailer(mci, e, m->m_argv); 502 if (i != EX_OK) 503 syserr("451 smtpquit %s: stat %d", m->m_argv[0], i); 504 } 505 /* 506 ** SMTPRSET -- send a RSET (reset) command 507 */ 508 509 smtprset(m, mci, e) 510 register MAILER *m; 511 register MCI *mci; 512 ENVELOPE *e; 513 { 514 int r; 515 516 smtpmessage("RSET", m, mci); 517 r = reply(m, mci, e, TimeOuts.to_rset, NULL); 518 if (r < 0) 519 mci->mci_state = MCIS_ERROR; 520 else if (REPLYTYPE(r) == 2) 521 { 522 mci->mci_state = MCIS_OPEN; 523 return; 524 } 525 smtpquit(m, mci, e); 526 } 527 /* 528 ** SMTPPROBE -- check the connection state 529 */ 530 531 smtpprobe(mci) 532 register MCI *mci; 533 { 534 int r; 535 MAILER *m = mci->mci_mailer; 536 extern ENVELOPE BlankEnvelope; 537 ENVELOPE *e = &BlankEnvelope; 538 539 smtpmessage("RSET", m, mci); 540 r = reply(m, mci, e, TimeOuts.to_miscshort, NULL); 541 if (r < 0 || REPLYTYPE(r) != 2) 542 smtpquit(m, mci, e); 543 return r; 544 } 545 /* 546 ** REPLY -- read arpanet reply 547 ** 548 ** Parameters: 549 ** m -- the mailer we are reading the reply from. 550 ** mci -- the mailer connection info structure. 551 ** e -- the current envelope. 552 ** timeout -- the timeout for reads. 553 ** pfunc -- processing function for second and subsequent 554 ** lines of response -- if null, no special 555 ** processing is done. 556 ** 557 ** Returns: 558 ** reply code it reads. 559 ** 560 ** Side Effects: 561 ** flushes the mail file. 562 */ 563 564 reply(m, mci, e, timeout, pfunc) 565 MAILER *m; 566 MCI *mci; 567 ENVELOPE *e; 568 time_t timeout; 569 void (*pfunc)(); 570 { 571 register char *bufp; 572 register int r; 573 bool firstline = TRUE; 574 char junkbuf[MAXLINE]; 575 576 if (mci->mci_out != NULL) 577 (void) fflush(mci->mci_out); 578 579 if (tTd(18, 1)) 580 printf("reply\n"); 581 582 /* 583 ** Read the input line, being careful not to hang. 584 */ 585 586 for (bufp = SmtpReplyBuffer;; bufp = junkbuf) 587 { 588 register char *p; 589 extern time_t curtime(); 590 591 /* actually do the read */ 592 if (e->e_xfp != NULL) 593 (void) fflush(e->e_xfp); /* for debugging */ 594 595 /* if we are in the process of closing just give the code */ 596 if (mci->mci_state == MCIS_CLOSED) 597 return (SMTPCLOSING); 598 599 if (mci->mci_out != NULL) 600 fflush(mci->mci_out); 601 602 /* get the line from the other side */ 603 p = sfgets(bufp, MAXLINE, mci->mci_in, timeout); 604 mci->mci_lastuse = curtime(); 605 606 if (p == NULL) 607 { 608 extern char MsgBuf[]; /* err.c */ 609 610 /* if the remote end closed early, fake an error */ 611 if (errno == 0) 612 # ifdef ECONNRESET 613 errno = ECONNRESET; 614 # else /* ECONNRESET */ 615 errno = EPIPE; 616 # endif /* ECONNRESET */ 617 618 mci->mci_errno = errno; 619 mci->mci_exitstat = EX_TEMPFAIL; 620 message("451 %s: reply: read error from %s", 621 e->e_id == NULL ? "NOQUEUE" : e->e_id, 622 mci->mci_host); 623 /* if debugging, pause so we can see state */ 624 if (tTd(18, 100)) 625 pause(); 626 # ifdef LOG 627 if (LogLevel > 1) 628 syslog(LOG_INFO, "%s", &MsgBuf[4]); 629 # endif /* LOG */ 630 mci->mci_state = MCIS_ERROR; 631 smtpquit(m, mci, e); 632 return (-1); 633 } 634 fixcrlf(bufp, TRUE); 635 636 if (e->e_xfp != NULL && strchr("45", bufp[0]) != NULL) 637 { 638 /* serious error -- log the previous command */ 639 if (SmtpMsgBuffer[0] != '\0') 640 fprintf(e->e_xfp, ">>> %s\n", SmtpMsgBuffer); 641 SmtpMsgBuffer[0] = '\0'; 642 643 /* now log the message as from the other side */ 644 fprintf(e->e_xfp, "<<< %s\n", bufp); 645 } 646 647 /* display the input for verbose mode */ 648 if (Verbose) 649 nmessage("050 %s", bufp); 650 651 /* process the line */ 652 if (pfunc != NULL && !firstline) 653 (*pfunc)(bufp, m, mci, e); 654 655 firstline = FALSE; 656 657 /* if continuation is required, we can go on */ 658 if (bufp[3] == '-') 659 continue; 660 661 /* ignore improperly formated input */ 662 if (!(isascii(bufp[0]) && isdigit(bufp[0]))) 663 continue; 664 665 /* decode the reply code */ 666 r = atoi(bufp); 667 668 /* extra semantics: 0xx codes are "informational" */ 669 if (r >= 100) 670 break; 671 } 672 673 /* 674 ** Now look at SmtpReplyBuffer -- only care about the first 675 ** line of the response from here on out. 676 */ 677 678 /* save temporary failure messages for posterity */ 679 if (SmtpReplyBuffer[0] == '4' && SmtpError[0] == '\0') 680 (void) strcpy(SmtpError, SmtpReplyBuffer); 681 682 /* reply code 421 is "Service Shutting Down" */ 683 if (r == SMTPCLOSING && mci->mci_state != MCIS_SSD) 684 { 685 /* send the quit protocol */ 686 mci->mci_state = MCIS_SSD; 687 smtpquit(m, mci, e); 688 } 689 690 return (r); 691 } 692 /* 693 ** SMTPMESSAGE -- send message to server 694 ** 695 ** Parameters: 696 ** f -- format 697 ** m -- the mailer to control formatting. 698 ** a, b, c -- parameters 699 ** 700 ** Returns: 701 ** none. 702 ** 703 ** Side Effects: 704 ** writes message to mci->mci_out. 705 */ 706 707 /*VARARGS1*/ 708 #ifdef __STDC__ 709 smtpmessage(char *f, MAILER *m, MCI *mci, ...) 710 #else 711 smtpmessage(f, m, mci, va_alist) 712 char *f; 713 MAILER *m; 714 MCI *mci; 715 va_dcl 716 #endif 717 { 718 VA_LOCAL_DECL 719 720 VA_START(mci); 721 (void) vsprintf(SmtpMsgBuffer, f, ap); 722 VA_END; 723 724 if (tTd(18, 1) || Verbose) 725 nmessage(">>> %s", SmtpMsgBuffer); 726 if (mci->mci_out != NULL) 727 { 728 fprintf(mci->mci_out, "%s%s", SmtpMsgBuffer, 729 m == NULL ? "\r\n" : m->m_eol); 730 } 731 else if (tTd(18, 1)) 732 { 733 printf("smtpmessage: NULL mci_out\n"); 734 } 735 } 736 737 # endif /* SMTP */ 738