From 22466dff9f76e4f32a123d1a8645286984a6ae51 Mon Sep 17 00:00:00 2001 From: "William F. Jolitz" Date: Fri, 10 May 1991 22:49:22 -0800 Subject: [PATCH] 386BSD 0.0 development Work on file usr/src/usr.sbin/sendmail/src/version.c Work on file usr/src/usr.sbin/sendmail/src/srvrsmtp.c Co-Authored-By: Lynne Greer Jolitz Synthesized-from: 386BSD-0.0/src --- usr/src/usr.sbin/sendmail/src/srvrsmtp.c | 658 +++++++++++++++++++++++ usr/src/usr.sbin/sendmail/src/version.c | 39 ++ 2 files changed, 697 insertions(+) create mode 100644 usr/src/usr.sbin/sendmail/src/srvrsmtp.c create mode 100644 usr/src/usr.sbin/sendmail/src/version.c diff --git a/usr/src/usr.sbin/sendmail/src/srvrsmtp.c b/usr/src/usr.sbin/sendmail/src/srvrsmtp.c new file mode 100644 index 0000000000..b33a1ef334 --- /dev/null +++ b/usr/src/usr.sbin/sendmail/src/srvrsmtp.c @@ -0,0 +1,658 @@ +/* + * Copyright (c) 1983 Eric P. Allman + * Copyright (c) 1988 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +# include "sendmail.h" + +#ifndef lint +#ifdef SMTP +static char sccsid[] = "@(#)srvrsmtp.c 5.31 (Berkeley) 5/10/91 (with SMTP)"; +#else +static char sccsid[] = "@(#)srvrsmtp.c 5.31 (Berkeley) 5/10/91 (without SMTP)"; +#endif +#endif /* not lint */ + +# include +# include + +# ifdef SMTP + +/* +** SMTP -- run the SMTP protocol. +** +** Parameters: +** none. +** +** Returns: +** never. +** +** Side Effects: +** Reads commands from the input channel and processes +** them. +*/ + +struct cmd +{ + char *cmdname; /* command name */ + int cmdcode; /* internal code, see below */ +}; + +/* values for cmdcode */ +# define CMDERROR 0 /* bad command */ +# define CMDMAIL 1 /* mail -- designate sender */ +# define CMDRCPT 2 /* rcpt -- designate recipient */ +# define CMDDATA 3 /* data -- send message text */ +# define CMDRSET 4 /* rset -- reset state */ +# define CMDVRFY 5 /* vrfy -- verify address */ +# define CMDHELP 6 /* help -- give usage info */ +# define CMDNOOP 7 /* noop -- do nothing */ +# define CMDQUIT 8 /* quit -- close connection and die */ +# define CMDHELO 9 /* helo -- be polite */ +# define CMDONEX 10 /* onex -- sending one transaction only */ +# define CMDVERB 11 /* verb -- go into verbose mode */ +/* debugging-only commands, only enabled if SMTPDEBUG is defined */ +# define CMDDBGQSHOW 12 /* showq -- show send queue */ +# define CMDDBGDEBUG 13 /* debug -- set debug mode */ + +static struct cmd CmdTab[] = +{ + "mail", CMDMAIL, + "rcpt", CMDRCPT, + "data", CMDDATA, + "rset", CMDRSET, + "vrfy", CMDVRFY, + "expn", CMDVRFY, + "help", CMDHELP, + "noop", CMDNOOP, + "quit", CMDQUIT, + "helo", CMDHELO, + "verb", CMDVERB, + "onex", CMDONEX, + /* + * remaining commands are here only + * to trap and log attempts to use them + */ + "showq", CMDDBGQSHOW, + "debug", CMDDBGDEBUG, + NULL, CMDERROR, +}; + +bool InChild = FALSE; /* true if running in a subprocess */ +bool OneXact = FALSE; /* one xaction only this run */ + +#define EX_QUIT 22 /* special code for QUIT command */ + +smtp() +{ + register char *p; + register struct cmd *c; + char *cmd; + static char *skipword(); + bool hasmail; /* mail command received */ + auto ADDRESS *vrfyqueue; + ADDRESS *a; + char *sendinghost; + char inp[MAXLINE]; + char cmdbuf[100]; + extern char Version[]; + extern char *macvalue(); + extern ADDRESS *recipient(); + extern ENVELOPE BlankEnvelope; + extern ENVELOPE *newenvelope(); + + hasmail = FALSE; + if (OutChannel != stdout) + { + /* arrange for debugging output to go to remote host */ + (void) close(1); + (void) dup(fileno(OutChannel)); + } + settime(); + if (RealHostName != NULL) + { + CurHostName = RealHostName; + setproctitle("srvrsmtp %s", CurHostName); + } + else + { + /* this must be us!! */ + CurHostName = MyHostName; + } + expand("\001e", inp, &inp[sizeof inp], CurEnv); + message("220", inp); + SmtpPhase = "startup"; + sendinghost = NULL; + for (;;) + { + /* arrange for backout */ + if (setjmp(TopFrame) > 0 && InChild) + finis(); + QuickAbort = FALSE; + HoldErrs = FALSE; + + /* setup for the read */ + CurEnv->e_to = NULL; + Errors = 0; + (void) fflush(stdout); + + /* read the input line */ + p = sfgets(inp, sizeof inp, InChannel); + + /* handle errors */ + if (p == NULL) + { + /* end of file, just die */ + message("421", "%s Lost input channel from %s", + MyHostName, CurHostName); + finis(); + } + + /* clean up end of line */ + fixcrlf(inp, TRUE); + + /* echo command to transcript */ + if (CurEnv->e_xfp != NULL) + fprintf(CurEnv->e_xfp, "<<< %s\n", inp); + + /* break off command */ + for (p = inp; isspace(*p); p++) + continue; + cmd = p; + for (cmd = cmdbuf; *p != '\0' && !isspace(*p); ) + *cmd++ = *p++; + *cmd = '\0'; + + /* throw away leading whitespace */ + while (isspace(*p)) + p++; + + /* decode command */ + for (c = CmdTab; c->cmdname != NULL; c++) + { + if (!strcasecmp(c->cmdname, cmdbuf)) + break; + } + + /* process command */ + switch (c->cmdcode) + { + case CMDHELO: /* hello -- introduce yourself */ + SmtpPhase = "HELO"; + setproctitle("%s: %s", CurHostName, inp); + if (!strcasecmp(p, MyHostName)) + { + /* + * didn't know about alias, + * or connected to an echo server + */ + message("553", "%s config error: mail loops back to myself", + MyHostName); + break; + } + if (RealHostName != NULL && strcasecmp(p, RealHostName)) + { + char hostbuf[MAXNAME]; + + (void) sprintf(hostbuf, "%s (%s)", p, RealHostName); + sendinghost = newstr(hostbuf); + } + else + sendinghost = newstr(p); + message("250", "%s Hello %s, pleased to meet you", + MyHostName, sendinghost); + break; + + case CMDMAIL: /* mail -- designate sender */ + SmtpPhase = "MAIL"; + + /* force a sending host even if no HELO given */ + if (RealHostName != NULL && macvalue('s', CurEnv) == NULL) + sendinghost = RealHostName; + + /* check for validity of this command */ + if (hasmail) + { + message("503", "Sender already specified"); + break; + } + if (InChild) + { + errno = 0; + syserr("Nested MAIL command"); + exit(0); + } + + /* fork a subprocess to process this command */ + if (runinchild("SMTP-MAIL") > 0) + break; + define('s', sendinghost, CurEnv); + define('r', "SMTP", CurEnv); + initsys(); + setproctitle("%s %s: %s", CurEnv->e_id, + CurHostName, inp); + + /* child -- go do the processing */ + p = skipword(p, "from"); + if (p == NULL) + break; + setsender(p); + if (Errors == 0) + { + message("250", "Sender ok"); + hasmail = TRUE; + } + else if (InChild) + finis(); + break; + + case CMDRCPT: /* rcpt -- designate recipient */ + SmtpPhase = "RCPT"; + setproctitle("%s %s: %s", CurEnv->e_id, + CurHostName, inp); + if (setjmp(TopFrame) > 0) + { + CurEnv->e_flags &= ~EF_FATALERRS; + break; + } + QuickAbort = TRUE; + p = skipword(p, "to"); + if (p == NULL) + break; + a = parseaddr(p, (ADDRESS *) NULL, 1, '\0'); + if (a == NULL) + break; + a->q_flags |= QPRIMARY; + a = recipient(a, &CurEnv->e_sendqueue); + if (Errors != 0) + break; + + /* no errors during parsing, but might be a duplicate */ + CurEnv->e_to = p; + if (!bitset(QBADADDR, a->q_flags)) + message("250", "Recipient ok"); + else + { + /* punt -- should keep message in ADDRESS.... */ + message("550", "Addressee unknown"); + } + CurEnv->e_to = NULL; + break; + + case CMDDATA: /* data -- text of mail */ + SmtpPhase = "DATA"; + if (!hasmail) + { + message("503", "Need MAIL command"); + break; + } + else if (CurEnv->e_nrcpts <= 0) + { + message("503", "Need RCPT (recipient)"); + break; + } + + /* collect the text of the message */ + SmtpPhase = "collect"; + setproctitle("%s %s: %s", CurEnv->e_id, + CurHostName, inp); + collect(TRUE); + if (Errors != 0) + break; + + /* + ** Arrange to send to everyone. + ** If sending to multiple people, mail back + ** errors rather than reporting directly. + ** In any case, don't mail back errors for + ** anything that has happened up to + ** now (the other end will do this). + ** Truncate our transcript -- the mail has gotten + ** to us successfully, and if we have + ** to mail this back, it will be easier + ** on the reader. + ** Then send to everyone. + ** Finally give a reply code. If an error has + ** already been given, don't mail a + ** message back. + ** We goose error returns by clearing error bit. + */ + + SmtpPhase = "delivery"; + if (CurEnv->e_nrcpts != 1) + { + HoldErrs = TRUE; + ErrorMode = EM_MAIL; + } + CurEnv->e_flags &= ~EF_FATALERRS; + CurEnv->e_xfp = freopen(queuename(CurEnv, 'x'), "w", CurEnv->e_xfp); + + /* send to all recipients */ + sendall(CurEnv, SM_DEFAULT); + CurEnv->e_to = NULL; + + /* save statistics */ + markstats(CurEnv, (ADDRESS *) NULL); + + /* issue success if appropriate and reset */ + if (Errors == 0 || HoldErrs) + message("250", "Ok"); + else + CurEnv->e_flags &= ~EF_FATALERRS; + + /* if in a child, pop back to our parent */ + if (InChild) + finis(); + + /* clean up a bit */ + hasmail = 0; + dropenvelope(CurEnv); + CurEnv = newenvelope(CurEnv); + CurEnv->e_flags = BlankEnvelope.e_flags; + break; + + case CMDRSET: /* rset -- reset state */ + message("250", "Reset state"); + if (InChild) + finis(); + break; + + case CMDVRFY: /* vrfy -- verify address */ + if (runinchild("SMTP-VRFY") > 0) + break; + setproctitle("%s: %s", CurHostName, inp); + vrfyqueue = NULL; + QuickAbort = TRUE; + sendtolist(p, (ADDRESS *) NULL, &vrfyqueue); + if (Errors != 0) + { + if (InChild) + finis(); + break; + } + while (vrfyqueue != NULL) + { + register ADDRESS *a = vrfyqueue->q_next; + char *code; + + while (a != NULL && bitset(QDONTSEND|QBADADDR, a->q_flags)) + a = a->q_next; + + if (!bitset(QDONTSEND|QBADADDR, vrfyqueue->q_flags)) + { + if (a != NULL) + code = "250-"; + else + code = "250"; + if (vrfyqueue->q_fullname == NULL) + message(code, "<%s>", vrfyqueue->q_paddr); + else + message(code, "%s <%s>", + vrfyqueue->q_fullname, vrfyqueue->q_paddr); + } + else if (a == NULL) + message("554", "Self destructive alias loop"); + vrfyqueue = a; + } + if (InChild) + finis(); + break; + + case CMDHELP: /* help -- give user info */ + help(p); + break; + + case CMDNOOP: /* noop -- do nothing */ + message("200", "OK"); + break; + + case CMDQUIT: /* quit -- leave mail */ + message("221", "%s closing connection", MyHostName); + if (InChild) + ExitStat = EX_QUIT; + finis(); + + case CMDVERB: /* set verbose mode */ + Verbose = TRUE; + SendMode = SM_DELIVER; + message("200", "Verbose mode"); + break; + + case CMDONEX: /* doing one transaction only */ + OneXact = TRUE; + message("200", "Only one transaction"); + break; + +# ifdef SMTPDEBUG + case CMDDBGQSHOW: /* show queues */ + printf("Send Queue="); + printaddr(CurEnv->e_sendqueue, TRUE); + break; + + case CMDDBGDEBUG: /* set debug mode */ + tTsetup(tTdvect, sizeof tTdvect, "0-99.1"); + tTflag(p); + message("200", "Debug set"); + break; + +# else /* not SMTPDEBUG */ + + case CMDDBGQSHOW: /* show queues */ + case CMDDBGDEBUG: /* set debug mode */ +# ifdef LOG + if (RealHostName != NULL && LogLevel > 0) + syslog(LOG_NOTICE, + "\"%s\" command from %s (%s)\n", + c->cmdname, RealHostName, + inet_ntoa(RealHostAddr.sin_addr)); +# endif + /* FALL THROUGH */ +# endif /* SMTPDEBUG */ + + case CMDERROR: /* unknown command */ + message("500", "Command unrecognized"); + break; + + default: + errno = 0; + syserr("smtp: unknown code %d", c->cmdcode); + break; + } + } +} + /* +** SKIPWORD -- skip a fixed word. +** +** Parameters: +** p -- place to start looking. +** w -- word to skip. +** +** Returns: +** p following w. +** NULL on error. +** +** Side Effects: +** clobbers the p data area. +*/ + +static char * +skipword(p, w) + register char *p; + char *w; +{ + register char *q; + + /* find beginning of word */ + while (isspace(*p)) + p++; + q = p; + + /* find end of word */ + while (*p != '\0' && *p != ':' && !isspace(*p)) + p++; + while (isspace(*p)) + *p++ = '\0'; + if (*p != ':') + { + syntax: + message("501", "Syntax error"); + Errors++; + return (NULL); + } + *p++ = '\0'; + while (isspace(*p)) + p++; + + /* see if the input word matches desired word */ + if (strcasecmp(q, w)) + goto syntax; + + return (p); +} + /* +** HELP -- implement the HELP command. +** +** Parameters: +** topic -- the topic we want help for. +** +** Returns: +** none. +** +** Side Effects: +** outputs the help file to message output. +*/ + +help(topic) + char *topic; +{ + register FILE *hf; + int len; + char buf[MAXLINE]; + bool noinfo; + + if (HelpFile == NULL || (hf = fopen(HelpFile, "r")) == NULL) + { + /* no help */ + errno = 0; + message("502", "HELP not implemented"); + return; + } + + if (topic == NULL || *topic == '\0') + topic = "smtp"; + else + makelower(topic); + + len = strlen(topic); + noinfo = TRUE; + + while (fgets(buf, sizeof buf, hf) != NULL) + { + if (strncmp(buf, topic, len) == 0) + { + register char *p; + + p = index(buf, '\t'); + if (p == NULL) + p = buf; + else + p++; + fixcrlf(p, TRUE); + message("214-", p); + noinfo = FALSE; + } + } + + if (noinfo) + message("504", "HELP topic unknown"); + else + message("214", "End of HELP info"); + (void) fclose(hf); +} + /* +** RUNINCHILD -- return twice -- once in the child, then in the parent again +** +** Parameters: +** label -- a string used in error messages +** +** Returns: +** zero in the child +** one in the parent +** +** Side Effects: +** none. +*/ + +runinchild(label) + char *label; +{ + int childpid; + + if (!OneXact) + { + childpid = dofork(); + if (childpid < 0) + { + syserr("%s: cannot fork", label); + return (1); + } + if (childpid > 0) + { + auto int st; + + /* parent -- wait for child to complete */ + st = waitfor(childpid); + if (st == -1) + syserr("%s: lost child", label); + + /* if we exited on a QUIT command, complete the process */ + if (st == (EX_QUIT << 8)) + finis(); + + return (1); + } + else + { + /* child */ + InChild = TRUE; + QuickAbort = FALSE; + clearenvelope(CurEnv, FALSE); + } + } + + /* open alias database */ + initaliases(AliasFile, FALSE); + + return (0); +} + +# endif SMTP diff --git a/usr/src/usr.sbin/sendmail/src/version.c b/usr/src/usr.sbin/sendmail/src/version.c new file mode 100644 index 0000000000..6896049acf --- /dev/null +++ b/usr/src/usr.sbin/sendmail/src/version.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 1983 Eric P. Allman + * Copyright (c) 1988 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)version.c 5.67 (Berkeley) 5/10/91"; +#endif /* not lint */ + +char Version[] = "5.67"; -- 2.20.1