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

📄 spam.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include "common.h"#include "smtpd.h"#include <ip.h>enum {	NORELAY = 0,	DNSVERIFY,	SAVEBLOCK,	DOMNAME,	OURNETS,	OURDOMS,	IP = 0,	STRING,};typedef struct Keyword Keyword;struct Keyword {	char	*name;	int	code;};static Keyword options[] = {	"norelay",		NORELAY,	"verifysenderdom",	DNSVERIFY,	"saveblockedmsg",	SAVEBLOCK,	"defaultdomain",	DOMNAME,		"ournets",		OURNETS,	"ourdomains",		OURDOMS,	0,			NONE,};static Keyword actions[] = {	"allow",		ACCEPT,	"block",		BLOCKED,	"deny",			DENIED,	"dial",			DIALUP,	"delay",		DELAY,	0,			NONE,};static	int	hisaction;static	List	ourdoms;static	List 	badguys;static	ulong	v4peerip;static	char*	getline(Biobuf*);static	int	cidrcheck(char*);static intfindkey(char *val, Keyword *p){	for(; p->name; p++)		if(strcmp(val, p->name) == 0)				break;	return p->code;}char*actstr(int a){	static char buf[32];	Keyword *p;	for(p=actions; p->name; p++)		if(p->code == a)			return p->name;	if(a==NONE)		return "none";	sprint(buf, "%d", a);	return buf;}intgetaction(char *s, char *type){	char buf[1024];	Keyword *k;	if(s == nil || *s == 0)		return ACCEPT;	for(k = actions; k->name != 0; k++){		snprint(buf, sizeof buf, "/mail/ratify/%s/%s/%s", k->name, type, s);		if(access(buf,0) >= 0)			return k->code;	}	return ACCEPT;}intistrusted(char *s){	char buf[1024];	if(s == nil || *s == 0)		return 0;	snprint(buf, sizeof buf, "/mail/ratify/trusted/%s", s);	return access(buf,0) >= 0;}voidgetconf(void){	Biobuf *bp;	char *cp, *p;	String *s;	char buf[512];	uchar addr[4];	v4parseip(addr, nci->rsys);	v4peerip = nhgetl(addr);	trusted = istrusted(nci->rsys);	hisaction = getaction(nci->rsys, "ip");	if(debug){		fprint(2, "istrusted(%s)=%d\n", nci->rsys, trusted);		fprint(2, "getaction(%s, ip)=%s\n", nci->rsys, actstr(hisaction));	}	snprint(buf, sizeof(buf), "%s/smtpd.conf", UPASLIB);	bp = sysopen(buf, "r", 0);	if(bp == 0)		return;	for(;;){		cp = getline(bp);		if(cp == 0)			break;		p = cp+strlen(cp)+1;		switch(findkey(cp, options)){		case NORELAY:			if(fflag == 0 && strcmp(p, "on") == 0)				fflag++;			break;		case DNSVERIFY:			if(rflag == 0 && strcmp(p, "on") == 0)				rflag++;			break;		case SAVEBLOCK:			if(sflag == 0 && strcmp(p, "on") == 0)				sflag++;			break;		case DOMNAME:			if(dom == 0)				dom = strdup(p);			break;		case OURNETS:			if (trusted == 0)				trusted = cidrcheck(p);			break;		case OURDOMS:			while(*p){				s = s_new();				s_append(s, p);				listadd(&ourdoms, s);				p += strlen(p)+1;			}			break;		default:			break;		}	}	sysclose(bp);}/* *	match a user name.  the only meta-char is '*' which matches all *	characters.  we only allow it as "*", which matches anything or *	an * at the end of the name (e.g., "username*") which matches *	trailing characters. */static intusermatch(char *pathuser, char *specuser){	int n;	n = strlen(specuser)-1;	if(specuser[n] == '*'){		if(n == 0)		/* match everything */			return 0;		return strncmp(pathuser, specuser, n);	}	return strcmp(pathuser, specuser);}static intdommatch(char *pathdom, char *specdom){	int n;	if (*specdom == '*'){		if (specdom[1] == '.' && specdom[2]){			specdom += 2;			n = strlen(pathdom)-strlen(specdom);			if(n == 0 || (n > 0 && pathdom[n-1] == '.'))				return strcmp(pathdom+n, specdom);			return n;		}	}	return strcmp(pathdom, specdom);}/* *  figure out action for this sender */intblocked(String *path){	String *lpath;	int action;	if(debug)		fprint(2, "blocked(%s)\n", s_to_c(path));	/* if the sender's IP address is blessed, ignore sender email address */	if(trusted){		if(debug)			fprint(2, "\ttrusted => trusted\n");		return TRUSTED;	}	/* if sender's IP address is blocked, ignore sender email address */	if(hisaction != ACCEPT){		if(debug)			fprint(2, "\thisaction=%s => %s\n", actstr(hisaction), actstr(hisaction));		return hisaction;	}	/* convert to lower case */	lpath = s_copy(s_to_c(path));	s_tolower(lpath);	/* classify */	action = getaction(s_to_c(lpath), "account");	if(debug)		fprint(2, "\tgetaction account %s => %s\n", s_to_c(lpath), actstr(action));	s_free(lpath);	return action;}/* * get a canonicalized line: a string of null-terminated lower-case * tokens with a two null bytes at the end. */static char*getline(Biobuf *bp){	char c, *cp, *p, *q;	int n;	static char *buf;	static int bufsize;	for(;;){		cp = Brdline(bp, '\n');		if(cp == 0)			return 0;		n = Blinelen(bp);		cp[n-1] = 0;		if(buf == 0 || bufsize < n+1){			bufsize += 512;			if(bufsize < n+1)				bufsize = n+1;			buf = realloc(buf, bufsize);			if(buf == 0)				break;		}		q = buf;		for (p = cp; *p; p++){			c = *p;			if(c == '\\' && p[1])	/* we don't allow \<newline> */				c = *++p;			else			if(c == '#')				break;			else			if(c == ' ' || c == '\t' || c == ',')				if(q == buf || q[-1] == 0)					continue;				else					c = 0;			*q++ = tolower(c);		}		if(q != buf){			if(q[-1])				*q++ = 0;			*q = 0;			break;		}	}	return buf;}static intisourdom(char *s){	Link *l;	if(strchr(s, '.') == nil)		return 1;	for(l = ourdoms.first; l; l = l->next){		if(dommatch(s, s_to_c(l->p)) == 0)			return 1;	}	return 0;}intforwarding(String *path){	char *cp, *s;	String *lpath;	if(debug)		fprint(2, "forwarding(%s)\n", s_to_c(path));	/* first check if they want loopback */	lpath = s_copy(s_to_c(s_restart(path)));	if(nci->rsys && *nci->rsys){		cp = s_to_c(lpath);		if(strncmp(cp, "[]!", 3) == 0){found:			s_append(path, "[");			s_append(path, nci->rsys);			s_append(path, "]!");			s_append(path, cp+3);			s_terminate(path);			s_free(lpath);			return 0;		}		cp = strchr(cp,'!');			/* skip our domain and check next */		if(cp++ && strncmp(cp, "[]!", 3) == 0)			goto found;	}	/* if mail is from a trusted IP addr, allow it to forward */	if(trusted) {		s_free(lpath);		return 0;	}	/* sender is untrusted; ensure receiver is in one of our domains */	for(cp = s_to_c(lpath); *cp; cp++)		/* convert receiver lc */		*cp = tolower(*cp);	for(s = s_to_c(lpath); cp = strchr(s, '!'); s = cp+1){		*cp = 0;		if(!isourdom(s)){			s_free(lpath);			return 1;		}	}	s_free(lpath);	return 0;}intmasquerade(String *path, char *him){	char *cp, *s;	String *lpath;	int rv = 0;	if(debug)		fprint(2, "masquerade(%s)\n", s_to_c(path));	if(trusted)		return 0;	if(path == nil)		return 0;	lpath = s_copy(s_to_c(path));	/* sender is untrusted; ensure receiver is in one of our domains */	for(cp = s_to_c(lpath); *cp; cp++)		/* convert receiver lc */		*cp = tolower(*cp);	s = s_to_c(lpath);	/* scan first element of ! or last element of @ paths */	if((cp = strchr(s, '!')) != nil){		*cp = 0;		if(isourdom(s))			rv = 1;	} else if((cp = strrchr(s, '@')) != nil){		if(isourdom(cp+1))			rv = 1;	} else {		if(isourdom(him))			rv = 1;	}	s_free(lpath);	return rv;}/* this is a v4 only check */static intcidrcheck(char *cp){	char *p;	ulong a, m;	uchar addr[IPv4addrlen];	uchar mask[IPv4addrlen];	if(v4peerip == 0)		return 0;	/* parse a list of CIDR addresses comparing each to the peer IP addr */	while(cp && *cp){		v4parsecidr(addr, mask, cp);		a = nhgetl(addr);		m = nhgetl(mask);		/*		 * if a mask isn't specified, we build a minimal mask		 * instead of using the default mask for that net.  in this		 * case we never allow a class A mask (0xff000000).		 */		if(strchr(cp, '/') == 0){			m = 0xff000000;			p = cp;			for(p = strchr(p, '.'); p && p[1]; p = strchr(p+1, '.'))					m = (m>>8)|0xff000000;			/* force at least a class B */			m |= 0xffff0000;		}		if((v4peerip&m) == a)			return 1;		cp += strlen(cp)+1;	}			return 0;}intisbadguy(void){	Link *l;	/* check if this IP address is banned */	for(l = badguys.first; l; l = l->next)		if(cidrcheck(s_to_c(l->p)))			return 1;	return 0;}voidaddbadguy(char *p){	listadd(&badguys, s_copy(p));};char*dumpfile(char *sender){	int i, fd;	ulong h;	static char buf[512];	char *cp;	if (sflag == 1){		cp = ctime(time(0));		cp[7] = 0;		if(cp[8] == ' ')			sprint(buf, "%s/queue.dump/%s%c", SPOOL, cp+4, cp[9]);		else			sprint(buf, "%s/queue.dump/%s%c%c", SPOOL, cp+4, cp[8], cp[9]);		cp = buf+strlen(buf);		if(access(buf, 0) < 0 && sysmkdir(buf, 0777) < 0)			return "/dev/null";		h = 0;		while(*sender)			h = h*257 + *sender++;		for(i = 0; i < 50; i++){			h += lrand();			sprint(cp, "/%lud", h);			if(access(buf, 0) >= 0)				continue;			fd = syscreate(buf, ORDWR, 0666);			if(fd >= 0){				if(debug)					fprint(2, "saving in %s\n", buf);				close(fd);				return buf;			}		}	}	return "/dev/null";}char *validator = "/mail/lib/validateaddress";intrecipok(char *user){	char *cp, *p, c;	char buf[512];	int n;	Biobuf *bp;	int pid;	Waitmsg *w;	if(shellchars(user)){		syslog(0, "smtpd", "shellchars in user name");		return 0;	}	if(access(validator, AEXEC) == 0)	switch(pid = fork()) {	case -1:		break;	case 0:		execl(validator, "validateaddress", user, nil);		exits(0);	default:		while(w = wait()) {			if(w->pid != pid)				continue;			if(w->msg[0] != 0){				/*				syslog(0, "smtpd", "validateaddress %s: %s", user, w->msg);				*/				return 0;			}			break;		}	}	snprint(buf, sizeof(buf), "%s/names.blocked", UPASLIB);	bp = sysopen(buf, "r", 0);	if(bp == 0)		return 1;	for(;;){		cp = Brdline(bp, '\n');		if(cp == 0)			break;		n = Blinelen(bp);		cp[n-1] = 0;		while(*cp == ' ' || *cp == '\t')			cp++;		for(p = cp; c = *p; p++){			if(c == '#')				break;			if(c == ' ' || c == '\t')				break;		}		if(p > cp){			*p = 0;			if(cistrcmp(user, cp) == 0){				syslog(0, "smtpd", "names.blocked blocks %s", user);				Bterm(bp);				return 0;			}		}	}	Bterm(bp);	return 1;}/* *  a user can opt out of spam filtering by creating *  a file in his mail directory named 'nospamfiltering'. */intoptoutofspamfilter(char *addr){	char *p, *f;	int rv;	p = strchr(addr, '!');	if(p)		p++;	else		p = addr;	rv = 0;	f = smprint("/mail/box/%s/nospamfiltering", p);	if(f != nil){		rv = access(f, 0)==0;		free(f);	}	return rv;}

⌨️ 快捷键说明

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