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

📄 recipient.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
	*fuzzyp = FALSE;	/* DEC Hesiod getpwnam accepts numeric strings -- short circuit it */	for (p = name; *p != '\0'; p++)		if (!isascii(*p) || !isdigit(*p))			break;	if (*p == '\0')	{		if (tTd(29, 4))			printf("failed (numeric input)\n");		return NULL;	}	/* look up this login name using fast path */	if ((pw = getpwnam(name)) != NULL)	{		if (tTd(29, 4))			printf("found (non-fuzzy)\n");		return (pw);	}#ifdef MATCHGECOS	/* see if fuzzy matching allowed */	if (!MatchGecos)	{		if (tTd(29, 4))			printf("not found (fuzzy disabled)\n");		return NULL;	}	/* search for a matching full name instead */	for (p = name; *p != '\0'; p++)	{		if (*p == (SpaceSub & 0177) || *p == '_')			*p = ' ';	}	(void) setpwent();	while ((pw = getpwent()) != NULL)	{		char buf[MAXNAME];		buildfname(pw->pw_gecos, pw->pw_name, buf);		if (strchr(buf, ' ') != NULL && !strcasecmp(buf, name))		{			if (tTd(29, 4))				printf("fuzzy matches %s\n", pw->pw_name);			message("sending to login name %s", pw->pw_name);			*fuzzyp = TRUE;			return (pw);		}	}	if (tTd(29, 4))		printf("no fuzzy match found\n");#else	if (tTd(29, 4))		printf("not found (fuzzy disabled)\n");#endif	return (NULL);}/***  WRITABLE -- predicate returning if the file is writable.****	This routine must duplicate the algorithm in sys/fio.c.**	Unfortunately, we cannot use the access call since we**	won't necessarily be the real uid when we try to**	actually open the file.****	Notice that ANY file with ANY execute bit is automatically**	not writable.  This is also enforced by mailfile.****	Parameters:**		filename -- the file name to check.**		ctladdr -- the controlling address for this file.**		flags -- SFF_* flags to control the function.****	Returns:**		TRUE -- if we will be able to write this file.**		FALSE -- if we cannot write this file.****	Side Effects:**		none.*/boolwritable(filename, ctladdr, flags)	char *filename;	ADDRESS *ctladdr;	int flags;{	uid_t euid;	gid_t egid;	int bits;	register char *p;	char *uname;	struct stat stb;	extern char RealUserName[];	if (tTd(29, 5))		printf("writable(%s, %x)\n", filename, flags);#ifdef HASLSTAT	if ((bitset(SFF_NOSLINK, flags) ? lstat(filename, &stb)					: stat(filename, &stb)) < 0)#else	if (stat(filename, &stb) < 0)#endif	{		/* file does not exist -- see if directory is safe */		p = strrchr(filename, '/');		if (p == NULL)		{			errno = ENOTDIR;			return FALSE;		}		*p = '\0';		errno = safefile(filename, RealUid, RealGid, RealUserName,				 SFF_MUSTOWN, S_IWRITE|S_IEXEC);		*p = '/';		return errno == 0;	}#ifdef SUID_ROOT_FILES_OK	/* really ought to be passed down -- and not a good idea */	flags |= SFF_ROOTOK;#endif	/*	**  File does exist -- check that it is writable.	*/	if (bitset(0111, stb.st_mode))	{		if (tTd(29, 5))			printf("failed (mode %o: x bits)\n", stb.st_mode);		errno = EPERM;		return (FALSE);	}	if (ctladdr != NULL && geteuid() == 0)	{		euid = ctladdr->q_uid;		egid = ctladdr->q_gid;		uname = ctladdr->q_user;	}	else	{		euid = RealUid;		egid = RealGid;		uname = RealUserName;	}	if (euid == 0)	{		euid = DefUid;		uname = DefUser;	}	if (egid == 0)		egid = DefGid;	if (geteuid() == 0)	{		if (bitset(S_ISUID, stb.st_mode) &&		    (stb.st_uid != 0 || bitset(SFF_ROOTOK, flags)))		{			euid = stb.st_uid;			uname = NULL;		}		if (bitset(S_ISGID, stb.st_mode) &&		    (stb.st_gid != 0 || bitset(SFF_ROOTOK, flags)))			egid = stb.st_gid;	}	if (tTd(29, 5))		printf("\teu/gid=%d/%d, st_u/gid=%d/%d\n",			euid, egid, stb.st_uid, stb.st_gid);	errno = safefile(filename, euid, egid, uname, flags, S_IWRITE);	return errno == 0;}/***  INCLUDE -- handle :include: specification.****	Parameters:**		fname -- filename to include.**		forwarding -- if TRUE, we are reading a .forward file.**			if FALSE, it's a :include: file.**		ctladdr -- address template to use to fill in these**			addresses -- effective user/group id are**			the important things.**		sendq -- a pointer to the head of the send queue**			to put these addresses in.****	Returns:**		open error status****	Side Effects:**		reads the :include: file and sends to everyone**		listed in that file.****	Security Note:**		If you have restricted chown (that is, you can't**		give a file away), it is reasonable to allow programs**		and files called from this :include: file to be to be**		run as the owner of the :include: file.  This is bogus**		if there is any chance of someone giving away a file.**		We assume that pre-POSIX systems can give away files.****		There is an additional restriction that if you**		forward to a :include: file, it will not take on**		the ownership of the :include: file.  This may not**		be necessary, but shouldn't hurt.*/static jmp_buf	CtxIncludeTimeout;static int	includetimeout();#ifndef S_IWOTH# define S_IWOTH	(S_IWRITE >> 6)#endifintinclude(fname, forwarding, ctladdr, sendq, e)	char *fname;	bool forwarding;	ADDRESS *ctladdr;	ADDRESS **sendq;	ENVELOPE *e;{	register FILE *fp = NULL;	char *oldto = e->e_to;	char *oldfilename = FileName;	int oldlinenumber = LineNumber;	register EVENT *ev = NULL;	int nincludes;	register ADDRESS *ca;	uid_t saveduid, uid;	gid_t savedgid, gid;	char *uname;	int rval = 0;	int sfflags = forwarding ? SFF_MUSTOWN : SFF_ANYFILE;	struct stat st;	char buf[MAXLINE];#ifdef _POSIX_CHOWN_RESTRICTED# if _POSIX_CHOWN_RESTRICTED == -1#  define safechown	FALSE# else#  define safechown	TRUE# endif#else# ifdef _PC_CHOWN_RESTRICTED	bool safechown;# else#  ifdef BSD#   define safechown	TRUE#  else#   define safechown	FALSE#  endif# endif#endif	extern bool chownsafe();	if (tTd(27, 2))		printf("include(%s)\n", fname);	if (tTd(27, 4))		printf("   ruid=%d euid=%d\n", getuid(), geteuid());	if (tTd(27, 14))	{		printf("ctladdr ");		printaddr(ctladdr, FALSE);	}	if (tTd(27, 9))		printf("include: old uid = %d/%d\n", getuid(), geteuid());	ca = getctladdr(ctladdr);	if (ca == NULL)	{		uid = DefUid;		gid = DefGid;		uname = DefUser;		saveduid = -1;	}	else	{		uid = ca->q_uid;		gid = ca->q_gid;		uname = ca->q_user;#ifdef HASSETREUID		saveduid = geteuid();		savedgid = getegid();		if (saveduid == 0)		{			initgroups(uname, gid);			if (uid != 0)				(void) setreuid(0, uid);		}#endif                   	}	if (tTd(27, 9))		printf("include: new uid = %d/%d\n", getuid(), geteuid());	/*	**  If home directory is remote mounted but server is down,	**  this can hang or give errors; use a timeout to avoid this	*/	if (setjmp(CtxIncludeTimeout) != 0)	{		ctladdr->q_flags |= QQUEUEUP;		errno = 0;		/* return pseudo-error code */		rval = EOPENTIMEOUT;		goto resetuid;	}	ev = setevent((time_t) 60, includetimeout, 0);	/* the input file must be marked safe */	rval = safefile(fname, uid, gid, uname, sfflags, S_IREAD);	if (rval != 0)	{		/* don't use this :include: file */		if (tTd(27, 4))			printf("include: not safe (uid=%d): %s\n",				uid, errstring(rval));	}	else	{		fp = fopen(fname, "r");		if (fp == NULL)		{			rval = errno;			if (tTd(27, 4))				printf("include: open: %s\n", errstring(rval));		}	}	clrevent(ev);resetuid:#ifdef HASSETREUID	if (saveduid == 0)	{		if (uid != 0)			if (setreuid(-1, 0) < 0 || setreuid(RealUid, 0) < 0)				syserr("setreuid(%d, 0) failure (real=%d, eff=%d)",					RealUid, getuid(), geteuid());		setgid(savedgid);	}#endif	if (tTd(27, 9))		printf("include: reset uid = %d/%d\n", getuid(), geteuid());	if (rval == EOPENTIMEOUT)		usrerr("451 open timeout on %s", fname);	if (fp == NULL)		return rval;	if (fstat(fileno(fp), &st) < 0)	{		rval = errno;		syserr("Cannot fstat %s!", fname);		return rval;	}#ifndef safechown	safechown = chownsafe(fileno(fp));#endif	if (ca == NULL && safechown)	{		ctladdr->q_uid = st.st_uid;		ctladdr->q_gid = st.st_gid;		ctladdr->q_flags |= QGOODUID;	}	if (ca != NULL && ca->q_uid == st.st_uid)	{		/* optimization -- avoid getpwuid if we already have info */		ctladdr->q_flags |= ca->q_flags & QBOGUSSHELL;		ctladdr->q_ruser = ca->q_ruser;	}	else	{		char *sh;		register struct passwd *pw;		sh = "/SENDMAIL/ANY/SHELL/";		pw = getpwuid(st.st_uid);		if (pw != NULL)		{			ctladdr->q_ruser = newstr(pw->pw_name);			if (safechown)				sh = pw->pw_shell;		}		if (pw == NULL)			ctladdr->q_flags |= QBOGUSSHELL;		else if(!usershellok(sh))		{			if (safechown)				ctladdr->q_flags |= QBOGUSSHELL;			else				ctladdr->q_flags |= QUNSAFEADDR;		}	}	if (bitset(EF_VRFYONLY, e->e_flags))	{		/* don't do any more now */		ctladdr->q_flags |= QVERIFIED;		e->e_nrcpts++;		xfclose(fp, "include", fname);		return rval;	}	/*	** Check to see if some bad guy can write this file	**	**	This should really do something clever with group	**	permissions; currently we just view world writable	**	as unsafe.  Also, we don't check for writable	**	directories in the path.  We've got to leave	**	something for the local sysad to do.	*/	if (bitset(S_IWOTH, st.st_mode))		ctladdr->q_flags |= QUNSAFEADDR;	/* read the file -- each line is a comma-separated list. */	FileName = fname;	LineNumber = 0;	ctladdr->q_flags &= ~QSELFREF;	nincludes = 0;	while (fgets(buf, sizeof buf, fp) != NULL)	{		register char *p = strchr(buf, '\n');		LineNumber++;		if (p != NULL)			*p = '\0';		if (buf[0] == '#' || buf[0] == '\0')			continue;		e->e_to = NULL;		message("%s to %s",			forwarding ? "forwarding" : "sending", buf);#ifdef LOG		if (forwarding && LogLevel > 9)			syslog(LOG_INFO, "%s: forward %s => %s",				e->e_id == NULL ? "NOQUEUE" : e->e_id,				oldto, buf);#endif		AliasLevel++;		nincludes += sendtolist(buf, ctladdr, sendq, e);		AliasLevel--;	}	if (ferror(fp) && tTd(27, 3))		printf("include: read error: %s\n", errstring(errno));	if (nincludes > 0 && !bitset(QSELFREF, ctladdr->q_flags))	{		if (tTd(27, 5))		{			printf("include: QDONTSEND ");			printaddr(ctladdr, FALSE);		}		ctladdr->q_flags |= QDONTSEND;	}	(void) xfclose(fp, "include", fname);	FileName = oldfilename;	LineNumber = oldlinenumber;	e->e_to = oldto;	return rval;}staticincludetimeout(){	longjmp(CtxIncludeTimeout, 1);}/***  SENDTOARGV -- send to an argument vector.****	Parameters:**		argv -- argument vector to send to.**		e -- the current envelope.****	Returns:**		none.****	Side Effects:**		puts all addresses on the argument vector onto the**			send queue.*/sendtoargv(argv, e)	register char **argv;	register ENVELOPE *e;{	register char *p;	while ((p = *argv++) != NULL)	{		(void) sendtolist(p, NULLADDR, &e->e_sendqueue, e);	}}/***  GETCTLADDR -- get controlling address from an address header.****	If none, get one corresponding to the effective userid.****	Parameters:**		a -- the address to find the controller of.****	Returns:**		the controlling address.****	Side Effects:**		none.*/ADDRESS *getctladdr(a)	register ADDRESS *a;{	while (a != NULL && !bitset(QGOODUID, a->q_flags))		a = a->q_alias;	return (a);}

⌨️ 快捷键说明

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