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