201 lines · 3.8 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include <u.h>#include <libc.h>#include <auth.h>#include <libsec.h>#include <bio.h>#include "imap4d.h" /* * hack to allow smtp forwarding. * hide the peer IP address under a rock in the ratifier FS. */voidenableForwarding(void){	char buf[64], peer[64], *p;	static ulong last;	ulong now;	int fd; 	if(remote == nil)		return; 	now = time(0);	if(now < last + 5*60)		return;	last = now; 	fd = open("/srv/ratify", ORDWR);	if(fd < 0)		return;	if(!mount(fd, -1, "/mail/ratify", MBEFORE, "")){		close(fd);		return;	}	close(fd); 	strncpy(peer, remote, sizeof(peer));	peer[sizeof(peer) - 1] = '\0';	p = strchr(peer, '!');	if(p != nil)		*p = '\0'; 	snprint(buf, sizeof(buf), "/mail/ratify/trusted/%s#32", peer); 	/*	 * if the address is already there and the user owns it,	 * remove it and recreate it to give him a new time quanta.	 */	if(access(buf, 0) >= 0 && remove(buf) < 0)		return; 	fd = create(buf, OREAD, 0666);	if(fd >= 0)		close(fd);} voidsetupuser(AuthInfo *ai){	Waitmsg *w;	int pid; 	if(ai){		strecpy(username, username+sizeof username, ai->cuid); 		if(auth_chuid(ai, nil) < 0)			bye("user auth failed: %r");		auth_freeAI(ai);	}else		strecpy(username, username+sizeof username, getuser()); 	if(newns(username, 0) < 0)		bye("user login failed: %r"); 	/*	 * hack to allow access to outgoing smtp forwarding	 */	enableForwarding(); 	snprint(mboxDir, MboxNameLen, "/mail/box/%s", username);	if(myChdir(mboxDir) < 0)		bye("can't open user's mailbox"); 	switch(pid = fork()){	case -1:		bye("can't initialize mail system");		break;	case 0:		execl("/bin/upas/fs", "upas/fs", "-np", nil);_exits("rob1");		_exits(0);		break;	default:		break;	}	if((w=wait()) == nil || w->pid != pid || w->msg[0] != '\0')		bye("can't initialize mail system");	free(w);} static char*authresp(void){	char *s, *t;	int n; 	t = Brdline(&bin, '\n');	n = Blinelen(&bin);	if(n < 2)		return nil;	n--;	if(t[n-1] == '\r')		n--;	t[n] = '\0';	if(n == 0 || strcmp(t, "*") == 0)		return nil; 	s = binalloc(&parseBin, n + 1, 0);	n = dec64((uchar*)s, n, t, n);	s[n] = '\0';	return s;} /* * rfc 2195 cram-md5 authentication */char*cramauth(void){	AuthInfo *ai;	Chalstate *cs;	char *s, *t;	int n; 	if((cs = auth_challenge("proto=cram role=server")) == nil)		return "couldn't get cram challenge"; 	n = cs->nchal;	s = binalloc(&parseBin, n * 2, 0);	n = enc64(s, n * 2, (uchar*)cs->chal, n);	Bprint(&bout, "+ ");	Bwrite(&bout, s, n);	Bprint(&bout, "\r\n");	if(Bflush(&bout) < 0)		writeErr(); 	s = authresp();	if(s == nil)		return "client cancelled authentication"; 	t = strchr(s, ' ');	if(t == nil)		bye("bad auth response");	*t++ = '\0';	strncpy(username, s, UserNameLen);	username[UserNameLen-1] = '\0'; 	cs->user = username;	cs->resp = t;	cs->nresp = strlen(t);	if((ai = auth_response(cs)) == nil)		return "login failed";	auth_freechal(cs);	setupuser(ai);	return nil;} AuthInfo*passLogin(char *user, char *secret){	AuthInfo *ai;	Chalstate *cs;	uchar digest[MD5dlen];	char response[2*MD5dlen+1];	int i; 	if((cs = auth_challenge("proto=cram role=server")) == nil)		return nil; 	hmac_md5((uchar*)cs->chal, strlen(cs->chal),		(uchar*)secret, strlen(secret), digest,		nil);	for(i = 0; i < MD5dlen; i++)		snprint(response + 2*i, sizeof(response) - 2*i, "%2.2ux", digest[i]); 	cs->user = user;	cs->resp = response;	cs->nresp = strlen(response);	ai = auth_response(cs);	auth_freechal(cs);	return ai;}