17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <auth.h>
47dd7cddfSDavid du Colombier #include <libsec.h>
57dd7cddfSDavid du Colombier #include <bio.h>
67dd7cddfSDavid du Colombier #include "imap4d.h"
77dd7cddfSDavid du Colombier
880ee5cbfSDavid du Colombier /*
980ee5cbfSDavid du Colombier * hack to allow smtp forwarding.
1080ee5cbfSDavid du Colombier * hide the peer IP address under a rock in the ratifier FS.
1180ee5cbfSDavid du Colombier */
1280ee5cbfSDavid du Colombier void
enableForwarding(void)1380ee5cbfSDavid du Colombier enableForwarding(void)
1480ee5cbfSDavid du Colombier {
1580ee5cbfSDavid du Colombier char buf[64], peer[64], *p;
1680ee5cbfSDavid du Colombier static ulong last;
1780ee5cbfSDavid du Colombier ulong now;
1880ee5cbfSDavid du Colombier int fd;
1980ee5cbfSDavid du Colombier
2080ee5cbfSDavid du Colombier if(remote == nil)
2180ee5cbfSDavid du Colombier return;
2280ee5cbfSDavid du Colombier
2380ee5cbfSDavid du Colombier now = time(0);
2480ee5cbfSDavid du Colombier if(now < last + 5*60)
2580ee5cbfSDavid du Colombier return;
2680ee5cbfSDavid du Colombier last = now;
2780ee5cbfSDavid du Colombier
2880ee5cbfSDavid du Colombier fd = open("/srv/ratify", ORDWR);
2980ee5cbfSDavid du Colombier if(fd < 0)
3080ee5cbfSDavid du Colombier return;
31*9a747e4fSDavid du Colombier if(!mount(fd, -1, "/mail/ratify", MBEFORE, "")){
3280ee5cbfSDavid du Colombier close(fd);
3380ee5cbfSDavid du Colombier return;
3480ee5cbfSDavid du Colombier }
3580ee5cbfSDavid du Colombier close(fd);
3680ee5cbfSDavid du Colombier
3780ee5cbfSDavid du Colombier strncpy(peer, remote, sizeof(peer));
3880ee5cbfSDavid du Colombier peer[sizeof(peer) - 1] = '\0';
3980ee5cbfSDavid du Colombier p = strchr(peer, '!');
4080ee5cbfSDavid du Colombier if(p != nil)
4180ee5cbfSDavid du Colombier *p = '\0';
4280ee5cbfSDavid du Colombier
4380ee5cbfSDavid du Colombier snprint(buf, sizeof(buf), "/mail/ratify/trusted/%s#32", peer);
4480ee5cbfSDavid du Colombier
4580ee5cbfSDavid du Colombier /*
4680ee5cbfSDavid du Colombier * if the address is already there and the user owns it,
4780ee5cbfSDavid du Colombier * remove it and recreate it to give him a new time quanta.
4880ee5cbfSDavid du Colombier */
4980ee5cbfSDavid du Colombier if(access(buf, 0) >= 0 && remove(buf) < 0)
5080ee5cbfSDavid du Colombier return;
5180ee5cbfSDavid du Colombier
5280ee5cbfSDavid du Colombier fd = create(buf, OREAD, 0666);
5380ee5cbfSDavid du Colombier if(fd >= 0)
5480ee5cbfSDavid du Colombier close(fd);
5580ee5cbfSDavid du Colombier }
5680ee5cbfSDavid du Colombier
577dd7cddfSDavid du Colombier void
setupuser(AuthInfo * ai)58*9a747e4fSDavid du Colombier setupuser(AuthInfo *ai)
597dd7cddfSDavid du Colombier {
60*9a747e4fSDavid du Colombier Waitmsg *w;
617dd7cddfSDavid du Colombier int pid;
627dd7cddfSDavid du Colombier
63*9a747e4fSDavid du Colombier if(ai){
64*9a747e4fSDavid du Colombier strecpy(username, username+sizeof username, ai->cuid);
65*9a747e4fSDavid du Colombier
66*9a747e4fSDavid du Colombier if(auth_chuid(ai, nil) < 0)
67*9a747e4fSDavid du Colombier bye("user auth failed: %r");
68*9a747e4fSDavid du Colombier auth_freeAI(ai);
69*9a747e4fSDavid du Colombier }else
70*9a747e4fSDavid du Colombier strecpy(username, username+sizeof username, getuser());
71*9a747e4fSDavid du Colombier
727dd7cddfSDavid du Colombier if(newns(username, 0) < 0)
737dd7cddfSDavid du Colombier bye("user login failed: %r");
7480ee5cbfSDavid du Colombier
7580ee5cbfSDavid du Colombier /*
7680ee5cbfSDavid du Colombier * hack to allow access to outgoing smtp forwarding
7780ee5cbfSDavid du Colombier */
7880ee5cbfSDavid du Colombier enableForwarding();
7980ee5cbfSDavid du Colombier
80*9a747e4fSDavid du Colombier snprint(mboxDir, MboxNameLen, "/mail/box/%s", username);
817dd7cddfSDavid du Colombier if(myChdir(mboxDir) < 0)
827dd7cddfSDavid du Colombier bye("can't open user's mailbox");
837dd7cddfSDavid du Colombier
847dd7cddfSDavid du Colombier switch(pid = fork()){
857dd7cddfSDavid du Colombier case -1:
867dd7cddfSDavid du Colombier bye("can't initialize mail system");
877dd7cddfSDavid du Colombier break;
887dd7cddfSDavid du Colombier case 0:
8959cc4ca5SDavid du Colombier execl("/bin/upas/fs", "upas/fs", "-np", nil);
90*9a747e4fSDavid du Colombier _exits("rob1");
917dd7cddfSDavid du Colombier _exits(0);
927dd7cddfSDavid du Colombier break;
937dd7cddfSDavid du Colombier default:
947dd7cddfSDavid du Colombier break;
957dd7cddfSDavid du Colombier }
96*9a747e4fSDavid du Colombier if((w=wait()) == nil || w->pid != pid || w->msg[0] != '\0')
977dd7cddfSDavid du Colombier bye("can't initialize mail system");
98*9a747e4fSDavid du Colombier free(w);
997dd7cddfSDavid du Colombier }
1007dd7cddfSDavid du Colombier
1017dd7cddfSDavid du Colombier static char*
authresp(void)1027dd7cddfSDavid du Colombier authresp(void)
1037dd7cddfSDavid du Colombier {
1047dd7cddfSDavid du Colombier char *s, *t;
1057dd7cddfSDavid du Colombier int n;
1067dd7cddfSDavid du Colombier
1077dd7cddfSDavid du Colombier t = Brdline(&bin, '\n');
1087dd7cddfSDavid du Colombier n = Blinelen(&bin);
1097dd7cddfSDavid du Colombier if(n < 2)
1107dd7cddfSDavid du Colombier return nil;
1117dd7cddfSDavid du Colombier n--;
1127dd7cddfSDavid du Colombier if(t[n-1] == '\r')
1137dd7cddfSDavid du Colombier n--;
1147dd7cddfSDavid du Colombier t[n] = '\0';
1157dd7cddfSDavid du Colombier if(n == 0 || strcmp(t, "*") == 0)
1167dd7cddfSDavid du Colombier return nil;
1177dd7cddfSDavid du Colombier
11880ee5cbfSDavid du Colombier s = binalloc(&parseBin, n + 1, 0);
1197dd7cddfSDavid du Colombier n = dec64((uchar*)s, n, t, n);
1207dd7cddfSDavid du Colombier s[n] = '\0';
1217dd7cddfSDavid du Colombier return s;
1227dd7cddfSDavid du Colombier }
1237dd7cddfSDavid du Colombier
1247dd7cddfSDavid du Colombier /*
1257dd7cddfSDavid du Colombier * rfc 2195 cram-md5 authentication
1267dd7cddfSDavid du Colombier */
1277dd7cddfSDavid du Colombier char*
cramauth(void)1287dd7cddfSDavid du Colombier cramauth(void)
1297dd7cddfSDavid du Colombier {
130*9a747e4fSDavid du Colombier AuthInfo *ai;
131*9a747e4fSDavid du Colombier Chalstate *cs;
1327dd7cddfSDavid du Colombier char *s, *t;
1337dd7cddfSDavid du Colombier int n;
1347dd7cddfSDavid du Colombier
135*9a747e4fSDavid du Colombier if((cs = auth_challenge("proto=cram role=server")) == nil)
1367dd7cddfSDavid du Colombier return "couldn't get cram challenge";
1377dd7cddfSDavid du Colombier
138*9a747e4fSDavid du Colombier n = cs->nchal;
13980ee5cbfSDavid du Colombier s = binalloc(&parseBin, n * 2, 0);
140*9a747e4fSDavid du Colombier n = enc64(s, n * 2, (uchar*)cs->chal, n);
1417dd7cddfSDavid du Colombier Bprint(&bout, "+ ");
1427dd7cddfSDavid du Colombier Bwrite(&bout, s, n);
1437dd7cddfSDavid du Colombier Bprint(&bout, "\r\n");
1447dd7cddfSDavid du Colombier if(Bflush(&bout) < 0)
1457dd7cddfSDavid du Colombier writeErr();
1467dd7cddfSDavid du Colombier
1477dd7cddfSDavid du Colombier s = authresp();
1487dd7cddfSDavid du Colombier if(s == nil)
1497dd7cddfSDavid du Colombier return "client cancelled authentication";
1507dd7cddfSDavid du Colombier
1517dd7cddfSDavid du Colombier t = strchr(s, ' ');
1527dd7cddfSDavid du Colombier if(t == nil)
1537dd7cddfSDavid du Colombier bye("bad auth response");
1547dd7cddfSDavid du Colombier *t++ = '\0';
155*9a747e4fSDavid du Colombier strncpy(username, s, UserNameLen);
156*9a747e4fSDavid du Colombier username[UserNameLen-1] = '\0';
1577dd7cddfSDavid du Colombier
158*9a747e4fSDavid du Colombier cs->user = username;
159*9a747e4fSDavid du Colombier cs->resp = t;
160*9a747e4fSDavid du Colombier cs->nresp = strlen(t);
161*9a747e4fSDavid du Colombier if((ai = auth_response(cs)) == nil)
1627dd7cddfSDavid du Colombier return "login failed";
163*9a747e4fSDavid du Colombier auth_freechal(cs);
164*9a747e4fSDavid du Colombier setupuser(ai);
1657dd7cddfSDavid du Colombier return nil;
1667dd7cddfSDavid du Colombier }
1677dd7cddfSDavid du Colombier
168*9a747e4fSDavid du Colombier AuthInfo*
passLogin(char * user,char * secret)169*9a747e4fSDavid du Colombier passLogin(char *user, char *secret)
1707dd7cddfSDavid du Colombier {
171*9a747e4fSDavid du Colombier AuthInfo *ai;
172*9a747e4fSDavid du Colombier Chalstate *cs;
1737dd7cddfSDavid du Colombier uchar digest[MD5dlen];
1747dd7cddfSDavid du Colombier char response[2*MD5dlen+1];
1757dd7cddfSDavid du Colombier int i;
1767dd7cddfSDavid du Colombier
177*9a747e4fSDavid du Colombier if((cs = auth_challenge("proto=cram role=server")) == nil)
178*9a747e4fSDavid du Colombier return nil;
1797dd7cddfSDavid du Colombier
180*9a747e4fSDavid du Colombier hmac_md5((uchar*)cs->chal, strlen(cs->chal),
1817dd7cddfSDavid du Colombier (uchar*)secret, strlen(secret), digest,
1827dd7cddfSDavid du Colombier nil);
1837dd7cddfSDavid du Colombier for(i = 0; i < MD5dlen; i++)
1847dd7cddfSDavid du Colombier snprint(response + 2*i, sizeof(response) - 2*i, "%2.2ux", digest[i]);
1857dd7cddfSDavid du Colombier
186*9a747e4fSDavid du Colombier cs->user = user;
187*9a747e4fSDavid du Colombier cs->resp = response;
188*9a747e4fSDavid du Colombier cs->nresp = strlen(response);
189*9a747e4fSDavid du Colombier ai = auth_response(cs);
190*9a747e4fSDavid du Colombier auth_freechal(cs);
191*9a747e4fSDavid du Colombier return ai;
1927dd7cddfSDavid du Colombier }
193