185 lines
3.3 KiB
C
185 lines
3.3 KiB
C
#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.
|
|
*/
|
|
void
|
|
enableForwarding(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);
|
|
}
|
|
|
|
void
|
|
setupuser(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;
|
|
|
|
if((cs = auth_challenge("proto=cram role=server")) == nil)
|
|
return "couldn't get cram challenge";
|
|
|
|
Bprint(&bout, "+ %.*[\r\n", cs->nchal, cs->chal);
|
|
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];
|
|
|
|
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);
|
|
snprint(response, sizeof(response), "%.*H", MD5dlen, digest);
|
|
|
|
cs->user = user;
|
|
cs->resp = response;
|
|
cs->nresp = strlen(response);
|
|
ai = auth_response(cs);
|
|
auth_freechal(cs);
|
|
return ai;
|
|
}
|