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