示例#1
0
/*
 *  read a reply into a string, return the reply code
 */
int
getreply(void)
{
	char *line;
	int rv;

	reply = s_reset(reply);
	for(;;){
		line = getcrnl(reply);
		if(debug)
			Bflush(&berr);
		if(line == 0)
			return -1;
		if(!isdigit(line[0]) || !isdigit(line[1]) || !isdigit(line[2]))
			return -1;
		if(line[3] != '-')
			break;
	}
	if(debug)
		Bflush(&berr);
	rv = atoi(line)/100;
	return rv;
}
示例#2
0
文件: smtpd.c 项目: 99years/plan9
/*
 *  pipe message to mailer with the following transformations:
 *	- change \r\n into \n.
 *	- add sender's domain to any addrs with no domain
 *	- add a From: if none of From:, Sender:, or Replyto: exists
 *	- add a Received: line
 */
int
pipemsg(int *byteswritten)
{
	int n, nbytes, sawdot, status, nonhdr, bpr;
	char *cp;
	Field *f;
	Link *l;
	Node *p;
	String *hdr, *line;

	pipesig(&status);	/* set status to 1 on write to closed pipe */
	sawdot = 0;
	status = 0;

	/*
	 *  add a 'From ' line as envelope
	 */
	nbytes = 0;
	nbytes += Bprint(pp->std[0]->fp, "From %s %s remote from \n",
		s_to_c(senders.first->p), thedate());

	/*
	 *  add our own Received: stamp
	 */
	nbytes += Bprint(pp->std[0]->fp, "Received: from %s ", him);
	if(nci->rsys)
		nbytes += Bprint(pp->std[0]->fp, "([%s]) ", nci->rsys);
	nbytes += Bprint(pp->std[0]->fp, "by %s; %s\n", me, thedate());

	/*
	 *  read first 16k obeying '.' escape.  we're assuming
	 *  the header will all be there.
	 */
	line = s_new();
	hdr = s_new();
	while(sawdot == 0 && s_len(hdr) < 16*1024){
		n = getcrnl(s_reset(line), &bin);

		/* eof or error ends the message */
		if(n <= 0)
			break;

		/* a line with only a '.' ends the message */
		cp = s_to_c(line);
		if(n == 2 && *cp == '.' && *(cp+1) == '\n'){
			sawdot = 1;
			break;
		}

		s_append(hdr, *cp == '.' ? cp+1 : cp);
	}

	/*
	 *  parse header
	 */
	yyinit(s_to_c(hdr), s_len(hdr));
	yyparse();

	/*
	 *  Look for masquerades.  Let Sender: trump From: to allow mailing list
	 *  forwarded messages.
	 */
	if(fflag)
		nbytes += forgedheaderwarnings();

	/*
	 *  add an orginator and/or destination if either is missing
	 */
	if(originator == 0){
		if(senders.last == nil || senders.last->p == nil)
			nbytes += Bprint(pp->std[0]->fp, "From: /dev/null@%s\n",
				him);
		else
			nbytes += Bprint(pp->std[0]->fp, "From: %s\n",
				s_to_c(senders.last->p));
	}
	if(destination == 0){
		nbytes += Bprint(pp->std[0]->fp, "To: ");
		for(l = rcvers.first; l; l = l->next){
			if(l != rcvers.first)
				nbytes += Bprint(pp->std[0]->fp, ", ");
			nbytes += Bprint(pp->std[0]->fp, "%s", s_to_c(l->p));
		}
		nbytes += Bprint(pp->std[0]->fp, "\n");
	}

	/*
	 *  add sender's domain to any domainless addresses
	 *  (to avoid forging local addresses)
	 */
	cp = s_to_c(hdr);
	for(f = firstfield; cp != nil && f; f = f->next){
		for(p = f->node; cp != 0 && p; p = p->next) {
			bpr = 0;
			cp = bprintnode(pp->std[0]->fp, p, &bpr);
			nbytes += bpr;
		}
		if(status == 0 && Bprint(pp->std[0]->fp, "\n") < 0){
			piperror = "write error";
			status = 1;
		}
		nbytes++;		/* for newline */
	}
	if(cp == nil){
		piperror = "sender domain";
		status = 1;
	}

	/* write anything we read following the header */
	nonhdr = s_to_c(hdr) + s_len(hdr) - cp;
	if(status == 0 && Bwrite(pp->std[0]->fp, cp, nonhdr) < 0){
		piperror = "write error 2";
		status = 1;
	}
	nbytes += nonhdr;
	s_free(hdr);

	/*
	 *  pass rest of message to mailer.  take care of '.'
	 *  escapes.
	 */
	while(sawdot == 0){
		n = getcrnl(s_reset(line), &bin);

		/* eof or error ends the message */
		if(n <= 0)
			break;

		/* a line with only a '.' ends the message */
		cp = s_to_c(line);
		if(n == 2 && *cp == '.' && *(cp+1) == '\n'){
			sawdot = 1;
			break;
		}
		if(cp[0] == '.'){
			cp++;
			n--;
		}
		nbytes += n;
		if(status == 0 && Bwrite(pp->std[0]->fp, cp, n) < 0){
			piperror = "write error 3";
			status = 1;
		}
	}
	s_free(line);
	if(sawdot == 0){
		/* message did not terminate normally */
		snprint(pipbuf, sizeof pipbuf, "network eof: %r");
		piperror = pipbuf;
		if (pp->pid > 0) {
			syskillpg(pp->pid);
			/* none can't syskillpg, so try a variant */
			sleep(500);
			syskill(pp->pid);
		}
		status = 1;
	}

	if(status == 0 && Bflush(pp->std[0]->fp) < 0){
		piperror = "write error 4";
		status = 1;
	}
	if (debug) {
		stamp();
		fprint(2, "at end of message; %s .\n",
			(sawdot? "saw": "didn't see"));
	}
	stream_free(pp->std[0]);
	pp->std[0] = 0;
	*byteswritten = nbytes;
	pipesigoff();
	if(status && !piperror)
		piperror = "write on closed pipe";
	return status;
}
示例#3
0
文件: smtpd.c 项目: 99years/plan9
void
auth(String *mech, String *resp)
{
	char *user, *pass, *scratch = nil;
	AuthInfo *ai = nil;
	Chalstate *chs = nil;
	String *s_resp1_64 = nil, *s_resp2_64 = nil, *s_resp1 = nil;
	String *s_resp2 = nil;

	if (rejectcheck())
		goto bomb_out;

	syslog(0, "smtpd", "auth(%s, %s) from %s", s_to_c(mech),
		"(protected)", him);

	if (authenticated) {
	bad_sequence:
		rejectcount++;
		reply("503 5.5.2 Bad sequence of commands\r\n");
		goto bomb_out;
	}
	if (cistrcmp(s_to_c(mech), "plain") == 0) {
		if (!passwordinclear) {
			rejectcount++;
			reply("538 5.7.1 Encryption required for requested "
				"authentication mechanism\r\n");
			goto bomb_out;
		}
		s_resp1_64 = resp;
		if (s_resp1_64 == nil) {
			reply("334 \r\n");
			s_resp1_64 = s_new();
			if (getcrnl(s_resp1_64, &bin) <= 0)
				goto bad_sequence;
		}
		s_resp1 = s_dec64(s_resp1_64);
		if (s_resp1 == nil) {
			rejectcount++;
			reply("501 5.5.4 Cannot decode base64\r\n");
			goto bomb_out;
		}
		memset(s_to_c(s_resp1_64), 'X', s_len(s_resp1_64));
		user = s_to_c(s_resp1) + strlen(s_to_c(s_resp1)) + 1;
		pass = user + strlen(user) + 1;
		ai = auth_userpasswd(user, pass);
		authenticated = ai != nil;
		memset(pass, 'X', strlen(pass));
		goto windup;
	}
	else if (cistrcmp(s_to_c(mech), "login") == 0) {
		if (!passwordinclear) {
			rejectcount++;
			reply("538 5.7.1 Encryption required for requested "
				"authentication mechanism\r\n");
			goto bomb_out;
		}
		if (resp == nil) {
			reply("334 VXNlcm5hbWU6\r\n");
			s_resp1_64 = s_new();
			if (getcrnl(s_resp1_64, &bin) <= 0)
				goto bad_sequence;
		}
		reply("334 UGFzc3dvcmQ6\r\n");
		s_resp2_64 = s_new();
		if (getcrnl(s_resp2_64, &bin) <= 0)
			goto bad_sequence;
		s_resp1 = s_dec64(s_resp1_64);
		s_resp2 = s_dec64(s_resp2_64);
		memset(s_to_c(s_resp2_64), 'X', s_len(s_resp2_64));
		if (s_resp1 == nil || s_resp2 == nil) {
			rejectcount++;
			reply("501 5.5.4 Cannot decode base64\r\n");
			goto bomb_out;
		}
		ai = auth_userpasswd(s_to_c(s_resp1), s_to_c(s_resp2));
		authenticated = ai != nil;
		memset(s_to_c(s_resp2), 'X', s_len(s_resp2));
windup:
		if (authenticated) {
			/* if you authenticated, we trust you despite your IP */
			trusted = 1;
			reply("235 2.0.0 Authentication successful\r\n");
		} else {
			rejectcount++;
			reply("535 5.7.1 Authentication failed\r\n");
			syslog(0, "smtpd", "authentication failed: %r");
		}
		goto bomb_out;
	}
	else if (cistrcmp(s_to_c(mech), "cram-md5") == 0) {
		int chal64n;
		char *resp, *t;

		chs = auth_challenge("proto=cram role=server");
		if (chs == nil) {
			rejectcount++;
			reply("501 5.7.5 Couldn't get CRAM-MD5 challenge\r\n");
			goto bomb_out;
		}
		scratch = malloc(chs->nchal * 2 + 1);
		chal64n = enc64(scratch, chs->nchal * 2, (uchar *)chs->chal,
			chs->nchal);
		scratch[chal64n] = 0;
		reply("334 %s\r\n", scratch);
		s_resp1_64 = s_new();
		if (getcrnl(s_resp1_64, &bin) <= 0)
			goto bad_sequence;
		s_resp1 = s_dec64(s_resp1_64);
		if (s_resp1 == nil) {
			rejectcount++;
			reply("501 5.5.4 Cannot decode base64\r\n");
			goto bomb_out;
		}
		/* should be of form <user><space><response> */
		resp = s_to_c(s_resp1);
		t = strchr(resp, ' ');
		if (t == nil) {
			rejectcount++;
			reply("501 5.5.4 Poorly formed CRAM-MD5 response\r\n");
			goto bomb_out;
		}
		*t++ = 0;
		chs->user = resp;
		chs->resp = t;
		chs->nresp = strlen(t);
		ai = auth_response(chs);
		authenticated = ai != nil;
		goto windup;
	}
	rejectcount++;
	reply("501 5.5.1 Unrecognised authentication type %s\r\n", s_to_c(mech));
bomb_out:
	if (ai)
		auth_freeAI(ai);
	if (chs)
		auth_freechal(chs);
	if (scratch)
		free(scratch);
	if (s_resp1)
		s_free(s_resp1);
	if (s_resp2)
		s_free(s_resp2);
	if (s_resp1_64)
		s_free(s_resp1_64);
	if (s_resp2_64)
		s_free(s_resp2_64);
}
示例#4
0
文件: pop3.c 项目: npe9/harvey
void
main(int argc, char **argv)
{
	int fd;
	char *arg, cmdbuf[1024];
	Cmd *c;

	rfork(RFNAMEG);
	Binit(&in, 0, OREAD);
	Binit(&out, 1, OWRITE);

	ARGBEGIN{
	case 'a':
		loggedin = 1;
		if(readmbox(EARGF(usage())) < 0)
			exits(nil);
		break;
	case 'd':
		debug++;
		if((fd = create(EARGF(usage()), OWRITE, 0666)) >= 0 && fd != 2){
			dup(fd, 2);
			close(fd);
		}
		break;
	case 'p':
		passwordinclear = 1;
		break;
	case 'r':
		strecpy(tmpaddr, tmpaddr+sizeof tmpaddr, EARGF(usage()));
		if(arg = strchr(tmpaddr, '!'))
			*arg = '\0';
		peeraddr = tmpaddr;
		break;
	case 't':
		tlscert = readcert(EARGF(usage()), &ntlscert);
		if(tlscert == nil){
			senderr("cannot read TLS certificate: %r");
			exits(nil);
		}
		break;
	}ARGEND

	/* do before TLS */
	if(peeraddr == nil)
		peeraddr = remoteaddr(0,0);

	hello();

	while(Bflush(&out), getcrnl(cmdbuf, sizeof cmdbuf) > 0){
		arg = nextarg(cmdbuf);
		for(c=cmdtab; c->name; c++)
			if(cistrcmp(c->name, cmdbuf) == 0)
				break;
		if(c->name == 0){
			senderr("unknown command %s", cmdbuf);
			continue;
		}
		if(c->needauth && !loggedin){
			senderr("%s requires authentication", cmdbuf);
			continue;
		}
		(*c->f)(arg);
	}
	exits(nil);
}