⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 srvrsmtp.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1983 Eric P. Allman * Copyright (c) 1988, 1993 *	The 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 SMTPstatic char sccsid[] = "@(#)srvrsmtp.c	8.37 (Berkeley) 4/13/94 (with SMTP)";#elsestatic char sccsid[] = "@(#)srvrsmtp.c	8.37 (Berkeley) 4/13/94 (without SMTP)";#endif#endif /* not lint */# include <errno.h># 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 CMDEXPN	6	/* expn -- expand address */# define CMDNOOP	7	/* noop -- do nothing */# define CMDQUIT	8	/* quit -- close connection and die */# define CMDHELO	9	/* helo -- be polite */# define CMDHELP	10	/* help -- give usage info */# define CMDEHLO	11	/* ehlo -- extended helo (RFC 1425) *//* non-standard commands */# define CMDONEX	16	/* onex -- sending one transaction only */# define CMDVERB	17	/* verb -- go into verbose mode *//* use this to catch and log "door handle" attempts on your system */# define CMDLOGBOGUS	23	/* bogus command that should be logged *//* debugging-only commands, only enabled if SMTPDEBUG is defined */# define CMDDBGQSHOW	24	/* showq -- show send queue */# define CMDDBGDEBUG	25	/* debug -- set debug mode */static struct cmd	CmdTab[] ={	"mail",		CMDMAIL,	"rcpt",		CMDRCPT,	"data",		CMDDATA,	"rset",		CMDRSET,	"vrfy",		CMDVRFY,	"expn",		CMDEXPN,	"help",		CMDHELP,	"noop",		CMDNOOP,	"quit",		CMDQUIT,	"helo",		CMDHELO,	"ehlo",		CMDEHLO,	"verb",		CMDVERB,	"onex",		CMDONEX,	/*	 * remaining commands are here only	 * to trap and log attempts to use them	 */	"showq",	CMDDBGQSHOW,	"debug",	CMDDBGDEBUG,	"wiz",		CMDLOGBOGUS,	NULL,		CMDERROR,};bool	OneXact = FALSE;		/* one xaction only this run */char	*CurSmtpClient;			/* who's at the other end of channel */static char	*skipword();extern char	RealUserName[];#define MAXBADCOMMANDS	25		/* maximum number of bad commands */smtp(e)	register ENVELOPE *e;{	register char *p;	register struct cmd *c;	char *cmd;	auto ADDRESS *vrfyqueue;	ADDRESS *a;	bool gotmail;			/* mail command received */	bool gothello;			/* helo command received */	bool vrfy;			/* set if this is a vrfy command */	char *protocol;			/* sending protocol */	char *sendinghost;		/* sending hostname */	unsigned long msize;		/* approximate maximum message size */	char *peerhostname;		/* name of SMTP peer or "localhost" */	auto char *delimptr;	char *id;	int nrcpts;			/* number of RCPT commands */	bool doublequeue;	int badcommands = 0;		/* count of bad commands */	char inp[MAXLINE];	char cmdbuf[MAXLINE];	extern char Version[];	extern ENVELOPE BlankEnvelope;	if (fileno(OutChannel) != fileno(stdout))	{		/* arrange for debugging output to go to remote host */		(void) dup2(fileno(OutChannel), fileno(stdout));	}	settime(e);	peerhostname = RealHostName;	if (peerhostname == NULL)		peerhostname = "localhost";	CurHostName = peerhostname;	CurSmtpClient = macvalue('_', e);	if (CurSmtpClient == NULL)		CurSmtpClient = CurHostName;	setproctitle("server %s startup", CurSmtpClient);	expand("\201e", inp, &inp[sizeof inp], e);	if (BrokenSmtpPeers)	{		p = strchr(inp, '\n');		if (p != NULL)			*p = '\0';		message("220 %s", inp);	}	else	{		char *q = inp;		while (q != NULL)		{			p = strchr(q, '\n');			if (p != NULL)				*p++ = '\0';			message("220-%s", q);			q = p;		}		message("220 ESMTP spoken here");	}	protocol = NULL;	sendinghost = macvalue('s', e);	gothello = FALSE;	gotmail = FALSE;	for (;;)	{		/* arrange for backout */		if (setjmp(TopFrame) > 0)		{			/* if() nesting is necessary for Cray UNICOS */			if (InChild)			{				QuickAbort = FALSE;				SuprErrs = TRUE;				finis();			}		}		QuickAbort = FALSE;		HoldErrs = FALSE;		LogUsrErrs = FALSE;		e->e_flags &= ~(EF_VRFYONLY|EF_GLOBALERRS);		/* setup for the read */		e->e_to = NULL;		Errors = 0;		(void) fflush(stdout);		/* read the input line */		SmtpPhase = "server cmd read";		setproctitle("server %s cmd read", CurHostName);		p = sfgets(inp, sizeof inp, InChannel, TimeOuts.to_nextcommand,				SmtpPhase);		/* handle errors */		if (p == NULL)		{			/* end of file, just die */			disconnect(1, e);			message("421 %s Lost input channel from %s",				MyHostName, CurSmtpClient);#ifdef LOG			if (LogLevel > (gotmail ? 1 : 19))				syslog(LOG_NOTICE, "lost input channel from %s",					CurSmtpClient);#endif			if (InChild)				ExitStat = EX_QUIT;			finis();		}		/* clean up end of line */		fixcrlf(inp, TRUE);		/* echo command to transcript */		if (e->e_xfp != NULL)			fprintf(e->e_xfp, "<<< %s\n", inp);		if (e->e_id == NULL)			setproctitle("%s: %.80s", CurSmtpClient, inp);		else			setproctitle("%s %s: %.80s", e->e_id, CurSmtpClient, inp);		/* break off command */		for (p = inp; isascii(*p) && isspace(*p); p++)			continue;		cmd = cmdbuf;		while (*p != '\0' &&		       !(isascii(*p) && isspace(*p)) &&		       cmd < &cmdbuf[sizeof cmdbuf - 2])			*cmd++ = *p++;		*cmd = '\0';		/* throw away leading whitespace */		while (isascii(*p) && isspace(*p))			p++;		/* decode command */		for (c = CmdTab; c->cmdname != NULL; c++)		{			if (!strcasecmp(c->cmdname, cmdbuf))				break;		}		/* reset errors */		errno = 0;		/* process command */		switch (c->cmdcode)		{		  case CMDHELO:		/* hello -- introduce yourself */		  case CMDEHLO:		/* extended hello */			if (c->cmdcode == CMDEHLO)			{				protocol = "ESMTP";				SmtpPhase = "server EHLO";			}			else			{				protocol = "SMTP";				SmtpPhase = "server HELO";			}			sendinghost = newstr(p);			gothello = TRUE;			if (c->cmdcode != CMDEHLO)			{				/* print old message and be done with it */				message("250 %s Hello %s, pleased to meet you",					MyHostName, CurSmtpClient);				break;			}						/* print extended message and brag */			message("250-%s Hello %s, pleased to meet you",				MyHostName, CurSmtpClient);			if (!bitset(PRIV_NOEXPN, PrivacyFlags))				message("250-EXPN");			if (MaxMessageSize > 0)				message("250-SIZE %ld", MaxMessageSize);			else				message("250-SIZE");			message("250 HELP");			break;		  case CMDMAIL:		/* mail -- designate sender */			SmtpPhase = "server MAIL";			/* check for validity of this command */			if (!gothello)			{				/* set sending host to our known value */				if (sendinghost == NULL)					sendinghost = peerhostname;				if (bitset(PRIV_NEEDMAILHELO, PrivacyFlags))				{					message("503 Polite people say HELO first");					break;				}			}			if (gotmail)			{				message("503 Sender already specified");				if (InChild)					finis();				break;			}			if (InChild)			{				errno = 0;				syserr("503 Nested MAIL command: MAIL %s", p);				finis();			}			/* fork a subprocess to process this command */			if (runinchild("SMTP-MAIL", e) > 0)				break;			if (!gothello)			{				auth_warning(e,					"Host %s didn't use HELO protocol",					peerhostname);			}#ifdef PICKY_HELO_CHECK			if (strcasecmp(sendinghost, peerhostname) != 0 &&			    (strcasecmp(peerhostname, "localhost") != 0 ||			     strcasecmp(sendinghost, MyHostName) != 0))			{				auth_warning(e, "Host %s claimed to be %s",					peerhostname, sendinghost);			}#endif			if (protocol == NULL)				protocol = "SMTP";			define('r', protocol, e);			define('s', sendinghost, e);			initsys(e);			nrcpts = 0;			e->e_flags |= EF_LOGSENDER;			setproctitle("%s %s: %.80s", e->e_id, CurSmtpClient, inp);			/* child -- go do the processing */			p = skipword(p, "from");			if (p == NULL)				break;			if (setjmp(TopFrame) > 0)			{				/* this failed -- undo work */				if (InChild)				{					QuickAbort = FALSE;					SuprErrs = TRUE;					e->e_flags &= ~EF_FATALERRS;					finis();				}				break;			}			QuickAbort = TRUE;			/* must parse sender first */			delimptr = NULL;			setsender(p, e, &delimptr, FALSE);			p = delimptr;			if (p != NULL && *p != '\0')				*p++ = '\0';			/* check for possible spoofing */			if (RealUid != 0 && OpMode == MD_SMTP &&			    (e->e_from.q_mailer != LocalMailer &&			     strcmp(e->e_from.q_user, RealUserName) != 0))			{				auth_warning(e, "%s owned process doing -bs",					RealUserName);			}			/* now parse ESMTP arguments */			msize = 0;			while (p != NULL && *p != '\0')			{				char *kp;				char *vp = NULL;				/* locate the beginning of the keyword */				while (isascii(*p) && isspace(*p))					p++;				if (*p == '\0')					break;				kp = p;				/* skip to the value portion */				while (isascii(*p) && isalnum(*p) || *p == '-')					p++;				if (*p == '=')				{					*p++ = '\0';					vp = p;					/* skip to the end of the value */					while (*p != '\0' && *p != ' ' &&					       !(isascii(*p) && iscntrl(*p)) &&					       *p != '=')						p++;				}				if (*p != '\0')					*p++ = '\0';				if (tTd(19, 1))					printf("MAIL: got arg %s=\"%s\"\n", kp,						vp == NULL ? "<null>" : vp);				if (strcasecmp(kp, "size") == 0)				{					if (vp == NULL)					{						usrerr("501 SIZE requires a value");						/* NOTREACHED */					}# ifdef __STDC__					msize = strtoul(vp, (char **) NULL, 10);# else					msize = strtol(vp, (char **) NULL, 10);# endif				}				else if (strcasecmp(kp, "body") == 0)				{					if (vp == NULL)					{						usrerr("501 BODY requires a value");						/* NOTREACHED */					}# ifdef MIME					if (strcasecmp(vp, "8bitmime") == 0)					{						e->e_bodytype = "8BITMIME";						SevenBit = FALSE;					}					else if (strcasecmp(vp, "7bit") == 0)					{						e->e_bodytype = "7BIT";						SevenBit = TRUE;					}					else					{						usrerr("501 Unknown BODY type %s",							vp);					}# endif				}				else				{					usrerr("501 %s parameter unrecognized", kp);					/* NOTREACHED */				}			}			if (MaxMessageSize > 0 && msize > MaxMessageSize)			{				usrerr("552 Message size exceeds fixed maximum message size (%ld)",					MaxMessageSize);				/* NOTREACHED */			}							if (!enoughspace(msize))			{				message("452 Insufficient disk space; try again later");				break;			}			message("250 Sender ok");			gotmail = TRUE;			break;		  case CMDRCPT:		/* rcpt -- designate recipient */			if (!gotmail)			{				usrerr("503 Need MAIL before RCPT");				break;			}			SmtpPhase = "server RCPT";			if (setjmp(TopFrame) > 0)			{				e->e_flags &= ~EF_FATALERRS;				break;			}			QuickAbort = TRUE;			LogUsrErrs = TRUE;			if (e->e_sendmode != SM_DELIVER)				e->e_flags |= EF_VRFYONLY;			p = skipword(p, "to");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -