1 #include <u.h>
2 #include <libc.h>
3 #include <auth.h>
4 #include <libsec.h>
5 #include <bio.h>
6 #include "imap4d.h"
7
8 /*
9 * hack to allow smtp forwarding.
10 * hide the peer IP address under a rock in the ratifier FS.
11 */
12 void
enableForwarding(void)13 enableForwarding(void)
14 {
15 char buf[64], peer[64], *p;
16 static ulong last;
17 ulong now;
18 int fd;
19
20 if(remote == nil)
21 return;
22
23 now = time(0);
24 if(now < last + 5*60)
25 return;
26 last = now;
27
28 fd = open("/srv/ratify", ORDWR);
29 if(fd < 0)
30 return;
31 if(!mount(fd, -1, "/mail/ratify", MBEFORE, "")){
32 close(fd);
33 return;
34 }
35 close(fd);
36
37 strncpy(peer, remote, sizeof(peer));
38 peer[sizeof(peer) - 1] = '\0';
39 p = strchr(peer, '!');
40 if(p != nil)
41 *p = '\0';
42
43 snprint(buf, sizeof(buf), "/mail/ratify/trusted/%s#32", peer);
44
45 /*
46 * if the address is already there and the user owns it,
47 * remove it and recreate it to give him a new time quanta.
48 */
49 if(access(buf, 0) >= 0 && remove(buf) < 0)
50 return;
51
52 fd = create(buf, OREAD, 0666);
53 if(fd >= 0)
54 close(fd);
55 }
56
57 void
setupuser(AuthInfo * ai)58 setupuser(AuthInfo *ai)
59 {
60 Waitmsg *w;
61 int pid;
62
63 if(ai){
64 strecpy(username, username+sizeof username, ai->cuid);
65
66 if(auth_chuid(ai, nil) < 0)
67 bye("user auth failed: %r");
68 auth_freeAI(ai);
69 }else
70 strecpy(username, username+sizeof username, getuser());
71
72 if(newns(username, 0) < 0)
73 bye("user login failed: %r");
74
75 /*
76 * hack to allow access to outgoing smtp forwarding
77 */
78 enableForwarding();
79
80 snprint(mboxDir, MboxNameLen, "/mail/box/%s", username);
81 if(myChdir(mboxDir) < 0)
82 bye("can't open user's mailbox");
83
84 switch(pid = fork()){
85 case -1:
86 bye("can't initialize mail system");
87 break;
88 case 0:
89 execl("/bin/upas/fs", "upas/fs", "-np", nil);
90 _exits("rob1");
91 _exits(0);
92 break;
93 default:
94 break;
95 }
96 if((w=wait()) == nil || w->pid != pid || w->msg[0] != '\0')
97 bye("can't initialize mail system");
98 free(w);
99 }
100
101 static char*
authresp(void)102 authresp(void)
103 {
104 char *s, *t;
105 int n;
106
107 t = Brdline(&bin, '\n');
108 n = Blinelen(&bin);
109 if(n < 2)
110 return nil;
111 n--;
112 if(t[n-1] == '\r')
113 n--;
114 t[n] = '\0';
115 if(n == 0 || strcmp(t, "*") == 0)
116 return nil;
117
118 s = binalloc(&parseBin, n + 1, 0);
119 n = dec64((uchar*)s, n, t, n);
120 s[n] = '\0';
121 return s;
122 }
123
124 /*
125 * rfc 2195 cram-md5 authentication
126 */
127 char*
cramauth(void)128 cramauth(void)
129 {
130 AuthInfo *ai;
131 Chalstate *cs;
132 char *s, *t;
133 int n;
134
135 if((cs = auth_challenge("proto=cram role=server")) == nil)
136 return "couldn't get cram challenge";
137
138 n = cs->nchal;
139 s = binalloc(&parseBin, n * 2, 0);
140 n = enc64(s, n * 2, (uchar*)cs->chal, n);
141 Bprint(&bout, "+ ");
142 Bwrite(&bout, s, n);
143 Bprint(&bout, "\r\n");
144 if(Bflush(&bout) < 0)
145 writeErr();
146
147 s = authresp();
148 if(s == nil)
149 return "client cancelled authentication";
150
151 t = strchr(s, ' ');
152 if(t == nil)
153 bye("bad auth response");
154 *t++ = '\0';
155 strncpy(username, s, UserNameLen);
156 username[UserNameLen-1] = '\0';
157
158 cs->user = username;
159 cs->resp = t;
160 cs->nresp = strlen(t);
161 if((ai = auth_response(cs)) == nil)
162 return "login failed";
163 auth_freechal(cs);
164 setupuser(ai);
165 return nil;
166 }
167
168 AuthInfo*
passLogin(char * user,char * secret)169 passLogin(char *user, char *secret)
170 {
171 AuthInfo *ai;
172 Chalstate *cs;
173 uchar digest[MD5dlen];
174 char response[2*MD5dlen+1];
175 int i;
176
177 if((cs = auth_challenge("proto=cram role=server")) == nil)
178 return nil;
179
180 hmac_md5((uchar*)cs->chal, strlen(cs->chal),
181 (uchar*)secret, strlen(secret), digest,
182 nil);
183 for(i = 0; i < MD5dlen; i++)
184 snprint(response + 2*i, sizeof(response) - 2*i, "%2.2ux", digest[i]);
185
186 cs->user = user;
187 cs->resp = response;
188 cs->nresp = strlen(response);
189 ai = auth_response(cs);
190 auth_freechal(cs);
191 return ai;
192 }
193