Пример #1
0
/* return 1 if name found in one of the files
 *	  0 if name not found in one of the files
 *	  -1 if neither file exists
 */
extern int
lookup(char *cp, char *local, Biobuf **lfpp, char *global, Biobuf **gfpp)
{
	static String *file = 0;

	if (local) {
		if (file == 0)
			file = s_new();
		abspath(local, UPASLIB, s_restart(file));
		if (*lfpp != 0 || (*lfpp = sysopen(s_to_c(file), "r", 0)) != 0) {
			if (okfile(cp, *lfpp))
				return 1;
		} else
			local = 0;
	}
	if (global) {
		abspath(global, UPASLIB, s_restart(file));
		if (*gfpp != 0 || (*gfpp = sysopen(s_to_c(file), "r", 0)) != 0) {
			if (okfile(cp, *gfpp))
				return 1;
		} else
			global = 0;
	}
	return (local || global)? 0 : -1;
}
Пример #2
0
/*
 *  rules are of the form:
 *	<reg exp> <String> <repl exp> [<repl exp>]
 */
extern int
getrules(void)
{
	Biobuf	*rfp;
	String	*line;
	String	*type;
	String	*file;

	file = abspath("rewrite", UPASLIB, (String *)0);
	rfp = sysopen(s_to_c(file), "r", 0);
	if(rfp == 0) {
		rulep = 0;
		return -1;
	}
	rlastp = 0;
	line = s_new();
	type = s_new();
	while(s_getline(rfp, s_restart(line)))
		if(getrule(line, type, thissys) && altthissys)
			getrule(s_restart(line), type, altthissys);
	s_free(type);
	s_free(line);
	s_free(file);
	sysclose(rfp);
	return 0;
}
Пример #3
0
/* parse a mailbox style header */
int
parse_header(char *line, String *sender, String *date)
{
	if (!IS_HEADER(line))
		return -1;
	line += sizeof("From ") - 1;
	s_restart(sender);
	while(*line==' '||*line=='\t')
		line++;
	if(*line == '"'){
		s_putc(sender, *line++);
		while(*line && *line != '"')
			s_putc(sender, *line++);
		s_putc(sender, *line++);
	} else {
		while(*line && *line != ' ' && *line != '\t')
			s_putc(sender, *line++);
	}
	s_terminate(sender);
	s_restart(date);
	while(*line==' '||*line=='\t')
		line++;
	while(*line)
		s_putc(date, *line++);
	s_terminate(date);
	return 0;
}
Пример #4
0
static int
getrule(String *line, String *type, char *system)
{
	rule	*rp;
	String	*re;
	int	backl;

	backl = 0;

	/* get a rule */
	re = rule_parse(s_restart(line), system, &backl);
	if(re == 0)
		return 0;
	rp = (rule *)malloc(sizeof(rule));
	if(rp == 0) {
		perror("getrules:");
		exit(1);
	}
	rp->next = 0;
	s_tolower(re);
	rp->matchre = s_new();
	s_append(rp->matchre, s_to_c(re));
	s_restart(rp->matchre);
	s_free(re);
	s_parse(line, s_restart(type));
	rp->repl1 = rule_parse(line, system, &backl);
	rp->repl2 = rule_parse(line, system, &backl);
	rp->program = 0;
	if(strcmp(s_to_c(type), "|") == 0)
		rp->type = d_pipe;
	else if(strcmp(s_to_c(type), ">>") == 0)
		rp->type = d_cat;
	else if(strcmp(s_to_c(type), "alias") == 0)
		rp->type = d_alias;
	else if(strcmp(s_to_c(type), "translate") == 0)
		rp->type = d_translate;
	else if(strcmp(s_to_c(type), "auth") == 0)
		rp->type = d_auth;
	else {
		s_free(rp->matchre);
		s_free(rp->repl1);
		s_free(rp->repl2);
		free((char *)rp);
		fprint(2,"illegal rewrite rule: %s\n", s_to_c(line));
		return 0;
	}
	if(rulep == 0)
		rulep = rlastp = rp;
	else
		rlastp = rlastp->next = rp;
	return backl;
}
Пример #5
0
/*  Transforms the address into a command.
 *  Returns:	-1 ifaddress not matched by reules
 *		 0 ifaddress matched and ok to forward
 *		 1 ifaddress matched and not ok to forward
 */
extern int
rewrite(dest *dp, message *mp)
{
	rule *rp;		/* rewriting rule */
	String *lower;		/* lower case version of destination */

	/*
	 *  Rewrite the address.  Matching is case insensitive.
	 */
	lower = s_clone(dp->addr);
	s_tolower(s_restart(lower));
	rp = findrule(lower, dp->authorized);
	if(rp == 0){
		s_free(lower);
		return -1;
	}
	strcpy(s_to_c(lower), s_to_c(dp->addr));
	dp->repl1 = substitute(rp->repl1, rp->subexp, mp);
	dp->repl2 = substitute(rp->repl2, rp->subexp, mp);
	dp->status = rp->type;
	if(debug){
		fprint(2, "\t->");
		if(dp->repl1)
			fprint(2, "%s", s_to_c(dp->repl1));
		if(dp->repl2)
			fprint(2, "%s", s_to_c(dp->repl2));
		fprint(2, "\n");
	}
	s_free(lower);
	return 0;
}
Пример #6
0
/* loop through the translation files */
static int
translate(char *name,		/* name to translate */
	char **namev,		/* names of this system */
	String *files,		/* names of system alias files */
	String *alias)		/* where to put the alias */
{
	String *file = s_new();
	String **fullnamev;
	int n, rv;

	rv = -1;

	DEBUG print("translate(%s, %s, %s)\n", name,
		s_to_c(files), s_to_c(alias));

	/* create the full name to avoid loops (system!name) */
	for(n = 0; namev[n]; n++)
		;
	fullnamev = (String**)malloc(sizeof(String*)*(n+2));
	n = 0;
	fullnamev[n++] = s_copy(name);
	for(; *namev; namev++){
		fullnamev[n] = s_copy(*namev);
		s_append(fullnamev[n], "!");
		s_append(fullnamev[n], name);
		n++;
	}
	fullnamev[n] = 0;

	/* look at system-wide names */
	s_restart(files);
	while (s_parse(files, s_restart(file)) != 0) {
		if (lookup(fullnamev, file, alias)==0) {
			rv = 0;
			goto out;
		}
	}

out:
	for(n = 0; fullnamev[n]; n++)
		s_free(fullnamev[n]);
	s_free(file);
	free(fullnamev);
	return rv;
}
Пример #7
0
int
matcher(char *action, Pattern *p, char *message, Resub *m)
{
    char *cp;
    String *s;

    for(cp = message; matchpat(p, cp, m); cp = m->ep) {
        switch(p->action) {
        case SaveLine:
            if(vflag)
                xprint(2, action, m);
            saveline(linefile, sender, m);
            break;
        case HoldHeader:
        case Hold:
            if(nflag)
                continue;
            if(vflag)
                xprint(2, action, m);
            *qdir = holdqueue;
            if(hflag && qname) {
                cp = strchr(sender, '!');
                if(cp) {
                    *cp = 0;
                    *qname = strdup(sender);
                    *cp = '!';
                } else
                    *qname = strdup(sender);
            }
            return 1;
        case Dump:
            if(vflag)
                xprint(2, action, m);
            *(m->ep) = 0;
            if(!tflag) {
                s = s_new();
                s_append(s, sender);
                s = unescapespecial(s);
                syslog(0, "smtpd", "Dumped %s [%s] to %s", s_to_c(s), m->sp,
                       s_to_c(s_restart(recips)));
                s_free(s);
            }
            tflag = 1;
            if(sflag)
                cout = opendump(sender);
            return 1;
        default:
            break;
        }
    }
    return 0;
}
Пример #8
0
/* pipe an address through a command to translate it */
extern dest *
translate(dest *dp)
{
	process *pp;
	String *line;
	dest *rv;
	char *cp;
	int n;

	pp = proc_start(s_to_c(dp->repl1), (stream *)0, outstream(), outstream(), 1, 0);
	if (pp == 0) {
		dp->status = d_resource;
		return 0;
	}
	line = s_new();
	for(;;) {
		cp = Brdline(pp->std[1]->fp, '\n');
		if(cp == 0)
			break;
		if(strncmp(cp, "_nosummary_", 11) == 0){
			nosummary = 1;
			continue;
		}
		n = Blinelen(pp->std[1]->fp);
		cp[n-1] = ' ';
		s_nappend(line, cp, n);
	}
	rv = s_to_dest(s_restart(line), dp);
	s_restart(line);
	while(s_read_line(pp->std[2]->fp, line))
		;
	if ((dp->pstat = proc_wait(pp)) != 0) {
		dp->repl2 = line;
		rv = 0;
	} else
		s_free(line);
	proc_free(pp);
	return rv;
}
Пример #9
0
/*
 *  send the damn thing
 */
char *
data(String *from, Biobuf *b)
{
	char *buf, *cp;
	int i, n, nbytes, bufsize, eof, r;
	String *fromline;
	char errmsg[Errlen];
	char id[40];

	/*
	 *  input the header.
	 */

	buf = malloc(1);
	if(buf == 0){
		s_append(s_restart(reply), "out of memory");
		return Retry;
	}
	n = 0;
	eof = 0;
	for(;;){
		cp = Brdline(b, '\n');
		if(cp == nil){
			eof = 1;
			break;
		}
		nbytes = Blinelen(b);
		buf = realloc(buf, n+nbytes+1);
		if(buf == 0){
			s_append(s_restart(reply), "out of memory");
			return Retry;
		}
		strncpy(buf+n, cp, nbytes);
		n += nbytes;
		if(nbytes == 1)		/* end of header */
			break;
	}
	buf[n] = 0;
	bufsize = n;

	/*
	 *  parse the header, turn all addresses into @ format
	 */
	yyinit(buf, n);
	yyparse();

	/*
	 *  print message observing '.' escapes and using \r\n for \n
	 */
	alarm(20*alarmscale);
	if(!filter){
		dBprint("DATA\r\n");
		switch(getreply()){
		case 3:
			break;
		case 5:
			free(buf);
			return Giveup;
		default:
			free(buf);
			return Retry;
		}
	}
	/*
	 *  send header.  add a message-id, a sender, and a date if there
	 *  isn't one
	 */
	nbytes = 0;
	fromline = convertheader(from);
	uneaten = buf;

	srand(truerand());
	if(messageid == 0){
		for(i=0; i<16; i++){
			r = rand()&0xFF;
			id[2*i] = hex[r&0xF];
			id[2*i+1] = hex[(r>>4)&0xF];
		}
		id[2*i] = '\0';
		nbytes += Bprint(&bout, "Message-ID: <%s@%s>\r\n", id, hostdomain);
		if(debug)
			Bprint(&berr, "Message-ID: <%s@%s>\r\n", id, hostdomain);
	}

	if(originator==0){
		nbytes += Bprint(&bout, "From: %s\r\n", s_to_c(fromline));
		if(debug)
			Bprint(&berr, "From: %s\r\n", s_to_c(fromline));
	}
	s_free(fromline);

	if(destination == 0 && toline)
		if(*s_to_c(toline) == '@'){	/* route addr */
			nbytes += Bprint(&bout, "To: <%s>\r\n", s_to_c(toline));
			if(debug)
				Bprint(&berr, "To: <%s>\r\n", s_to_c(toline));
		} else {
			nbytes += Bprint(&bout, "To: %s\r\n", s_to_c(toline));
			if(debug)
				Bprint(&berr, "To: %s\r\n", s_to_c(toline));
		}

	if(date==0 && udate)
		nbytes += printdate(udate);
	if (usys)
		uneaten = usys->end + 1;
	nbytes += printheader();
	if (*uneaten != '\n')
		putcrnl("\n", 1);

	/*
	 *  send body
	 */

	putcrnl(uneaten, buf+n - uneaten);
	nbytes += buf+n - uneaten;
	if(eof == 0){
		for(;;){
			n = Bread(b, buf, bufsize);
			if(n < 0){
				rerrstr(errmsg, sizeof(errmsg));
				s_append(s_restart(reply), errmsg);
				free(buf);
				return Retry;
			}
			if(n == 0)
				break;
			alarm(10*alarmscale);
			putcrnl(buf, n);
			nbytes += n;
		}
	}
	free(buf);
	if(!filter){
		if(last != '\n')
			dBprint("\r\n.\r\n");
		else
			dBprint(".\r\n");
		alarm(10*alarmscale);
		switch(getreply()){
		case 2:
			break;
		case 5:
			return Giveup;
		default:
			return Retry;
		}
		syslog(0, "smtp", "%s sent %d bytes to %s", s_to_c(from),
				nbytes, s_to_c(toline));/**/
	}
	return 0;
}
Пример #10
0
/* read in a message, interpret the 'From' header */
extern message *
m_read(Biobuf *fp, int rmail, int interactive)
{
	message *mp;
	Resub subexp[10];
	char *line;
	int first;
	int n;

	mp = m_new();

	/* parse From lines if remote */
	if (rmail) {
		/* get remote address */
		String *sender=s_new();

		if (rfprog == 0)
			rfprog = regcomp(REMFROMRE);
		first = 1;
		while(s_read_line(fp, s_restart(mp->body)) != 0) {
			memset(subexp, 0, sizeof(subexp));
			if (regexec(rfprog, s_to_c(mp->body), subexp, 10) == 0){
				if(first == 0)
					break;
				if (fprog == 0)
					fprog = regcomp(FROMRE);
				memset(subexp, 0, sizeof(subexp));
				if(regexec(fprog, s_to_c(mp->body), subexp,10) == 0)
					break;
				s_restart(mp->body);
				append_match(subexp, s_restart(sender), SENDERMATCH);
				append_match(subexp, s_restart(mp->date), DATEMATCH);
				break;
			}
			append_match(subexp, s_restart(sender), REMSENDERMATCH);
			append_match(subexp, s_restart(mp->date), REMDATEMATCH);
			if(subexp[REMSYSMATCH].sp!=subexp[REMSYSMATCH].ep){
				append_match(subexp, mp->sender, REMSYSMATCH);
				s_append(mp->sender, "!");
			}
			first = 0;
		}
		s_append(mp->sender, s_to_c(sender));

		s_free(sender);
	}
	if(*s_to_c(mp->sender)=='\0')
		default_from(mp);

	/* if sender address is unreturnable, treat message as bulk mail */
	if(!returnable(s_to_c(mp->sender)))
		mp->bulk = 1;

	/* get body */
	if(interactive && !rmail){
		/* user typing on terminal: terminator == '.' or EOF */
		for(;;) {
			line = s_read_line(fp, mp->body);
			if (line == 0)
				break;
			if (strcmp(".\n", line)==0) {
				mp->body->ptr -= 2;
				*mp->body->ptr = '\0';
				break;
			}
		}
		mp->size = mp->body->ptr - mp->body->base;
	} else {
		/*
		 *  read up to VMLIMIT bytes (more or less) into main memory.
		 *  if message is longer put the rest in a tmp file.
		 */
		mp->size = mp->body->ptr - mp->body->base;
		n = s_read(fp, mp->body, VMLIMIT);
		if(n < 0){
			perror("m_read");
			exit(1);
		}
		mp->size += n;
		if(n == VMLIMIT){
			if(m_read_to_file(fp, mp) < 0){
				perror("m_read");
				exit(1);
			}
		}

	}

	/*
	 *  ignore 0 length messages from a terminal
	 */
	if (!rmail && mp->size == 0)
		return 0;

	rfc822cruft(mp);

	return mp;
}
Пример #11
0
/*  Loop through the entries in a translation file looking for a match.
 *  Return 0 if found, -1 otherwise.
 */
static int
lookup(
	String **namev,
	String *file,
	String *alias)	/* returned String */
{
	String *line = s_new();
	String *token = s_new();
	String *bangtoken;
	int i, rv = -1;
	char *name =  s_to_c(namev[0]);
	Sinstack *sp;

	DEBUG print("lookup(%s, %s, %s, %s)\n", s_to_c(namev[0]), s_to_c(namev[1]),
		s_to_c(file), s_to_c(alias));

	s_reset(alias);
	if ((sp = s_allocinstack(s_to_c(file))) == 0)
		return -1;

	/* look for a match */
	while (s_rdinstack(sp, s_restart(line))!=0) {
		DEBUG print("line is %s\n", s_to_c(line));
		s_restart(token);
		if (s_parse(s_restart(line), token)==0)
			continue;
		if (compare(token, "#include")==0){
			if(s_parse(line, s_restart(token))!=0) {
				if(lookup(namev, line, alias) == 0)
					break;
			}
			continue;
		}
		if (compare(token, name)!=0)
			continue;
		/* match found, get the alias */
		while(s_parse(line, s_restart(token))!=0) {
			bangtoken = attobang(token);

			/* avoid definition loops */
			for(i = 0; namev[i]; i++)
				if(compare(bangtoken, s_to_c(namev[i]))==0) {
					s_append(alias, "local");
					s_append(alias, "!");
					s_append(alias, name);
					break;
				}

			if(namev[i] == 0)
				s_append(alias, s_to_c(token));
			s_append(alias, "\n");

			if(bangtoken != token)
				s_free(bangtoken);
		}
		rv = 0;
		break;
	}
	s_free(line);
	s_free(token);
	s_freeinstack(sp);
	return rv;
}
Пример #12
0
static String *
substitute(String *source, Resub *subexp, message *mp)
{
	int i;
	char *s;
	char *sp;
	String *stp;
	
	if(source == 0)
		return 0;
	sp = s_to_c(source);

	/* someplace to put it */
	stp = s_new();

	/* do the substitution */
	while (*sp != '\0') {
		if(*sp == '\\') {
			switch (*++sp) {
			case '0': case '1': case '2': case '3': case '4':
			case '5': case '6': case '7': case '8': case '9':
				i = *sp-'0';
				if(subexp[i].s.sp != 0)
					for (s = subexp[i].s.sp;
					     s < subexp[i].e.ep;
					     s++)
						s_putc(stp, *s);
				break;
			case '\\':
				s_putc(stp, '\\');
				break;
			case '\0':
				sp--;
				break;
			case 's':
				for(s = s_to_c(mp->replyaddr); *s; s++)
					s_putc(stp, *s);
				break;
			case 'p':
				if(mp->bulk)
					s = "bulk";
				else
					s = "normal";
				for(;*s; s++)
					s_putc(stp, *s);
				break;
			default:
				s_putc(stp, *sp);
				break;
			}
		} else if(*sp == '&') {			
			if(subexp[0].s.sp != 0)
				for (s = subexp[0].s.sp;
				     s < subexp[0].e.ep; s++)
					s_putc(stp, *s);
		} else if(*sp == '$') {
			sp = getrcvar(sp+1, &s);
			s_append(stp, s);
			free(s);
			sp--;	/* counter sp++ below */
		} else
			s_putc(stp, *sp);
		sp++;
	}
	s_terminate(stp);

	return s_restart(stp);
}