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