Blame


1 5cdb1798 2005-10-29 devnull #include "common.h"
2 5cdb1798 2005-10-29 devnull #include <ctype.h>
3 5cdb1798 2005-10-29 devnull #include <auth.h>
4 5cdb1798 2005-10-29 devnull #include <libsec.h>
5 5cdb1798 2005-10-29 devnull
6 5cdb1798 2005-10-29 devnull typedef struct Cmd Cmd;
7 5cdb1798 2005-10-29 devnull struct Cmd
8 5cdb1798 2005-10-29 devnull {
9 5cdb1798 2005-10-29 devnull char *name;
10 5cdb1798 2005-10-29 devnull int needauth;
11 5cdb1798 2005-10-29 devnull int (*f)(char*);
12 5cdb1798 2005-10-29 devnull };
13 5cdb1798 2005-10-29 devnull
14 5cdb1798 2005-10-29 devnull static void hello(void);
15 5cdb1798 2005-10-29 devnull static int apopcmd(char*);
16 5cdb1798 2005-10-29 devnull static int capacmd(char*);
17 5cdb1798 2005-10-29 devnull static int delecmd(char*);
18 5cdb1798 2005-10-29 devnull static int listcmd(char*);
19 5cdb1798 2005-10-29 devnull static int noopcmd(char*);
20 5cdb1798 2005-10-29 devnull static int passcmd(char*);
21 5cdb1798 2005-10-29 devnull static int quitcmd(char*);
22 5cdb1798 2005-10-29 devnull static int rsetcmd(char*);
23 5cdb1798 2005-10-29 devnull static int retrcmd(char*);
24 5cdb1798 2005-10-29 devnull static int statcmd(char*);
25 5cdb1798 2005-10-29 devnull static int stlscmd(char*);
26 5cdb1798 2005-10-29 devnull static int topcmd(char*);
27 5cdb1798 2005-10-29 devnull static int synccmd(char*);
28 5cdb1798 2005-10-29 devnull static int uidlcmd(char*);
29 5cdb1798 2005-10-29 devnull static int usercmd(char*);
30 5cdb1798 2005-10-29 devnull static char *nextarg(char*);
31 5cdb1798 2005-10-29 devnull static int getcrnl(char*, int);
32 5cdb1798 2005-10-29 devnull static int readmbox(char*);
33 5cdb1798 2005-10-29 devnull static void sendcrnl(char*, ...);
34 5cdb1798 2005-10-29 devnull static int senderr(char*, ...);
35 5cdb1798 2005-10-29 devnull static int sendok(char*, ...);
36 5cdb1798 2005-10-29 devnull #pragma varargck argpos sendcrnl 1
37 5cdb1798 2005-10-29 devnull #pragma varargck argpos senderr 1
38 5cdb1798 2005-10-29 devnull #pragma varargck argpos sendok 1
39 5cdb1798 2005-10-29 devnull
40 5cdb1798 2005-10-29 devnull Cmd cmdtab[] =
41 5cdb1798 2005-10-29 devnull {
42 5cdb1798 2005-10-29 devnull "apop", 0, apopcmd,
43 5cdb1798 2005-10-29 devnull "capa", 0, capacmd,
44 5cdb1798 2005-10-29 devnull "dele", 1, delecmd,
45 5cdb1798 2005-10-29 devnull "list", 1, listcmd,
46 5cdb1798 2005-10-29 devnull "noop", 0, noopcmd,
47 5cdb1798 2005-10-29 devnull "pass", 0, passcmd,
48 5cdb1798 2005-10-29 devnull "quit", 0, quitcmd,
49 5cdb1798 2005-10-29 devnull "rset", 0, rsetcmd,
50 5cdb1798 2005-10-29 devnull "retr", 1, retrcmd,
51 5cdb1798 2005-10-29 devnull "stat", 1, statcmd,
52 5cdb1798 2005-10-29 devnull "stls", 0, stlscmd,
53 5cdb1798 2005-10-29 devnull "sync", 1, synccmd,
54 5cdb1798 2005-10-29 devnull "top", 1, topcmd,
55 5cdb1798 2005-10-29 devnull "uidl", 1, uidlcmd,
56 5cdb1798 2005-10-29 devnull "user", 0, usercmd,
57 5cdb1798 2005-10-29 devnull 0, 0, 0,
58 5cdb1798 2005-10-29 devnull };
59 5cdb1798 2005-10-29 devnull
60 5cdb1798 2005-10-29 devnull static Biobuf in;
61 5cdb1798 2005-10-29 devnull static Biobuf out;
62 5cdb1798 2005-10-29 devnull static int passwordinclear;
63 5cdb1798 2005-10-29 devnull static int didtls;
64 5cdb1798 2005-10-29 devnull
65 5cdb1798 2005-10-29 devnull typedef struct Msg Msg;
66 5cdb1798 2005-10-29 devnull struct Msg
67 5cdb1798 2005-10-29 devnull {
68 5cdb1798 2005-10-29 devnull int upasnum;
69 5cdb1798 2005-10-29 devnull char digest[64];
70 5cdb1798 2005-10-29 devnull int bytes;
71 5cdb1798 2005-10-29 devnull int deleted;
72 5cdb1798 2005-10-29 devnull };
73 5cdb1798 2005-10-29 devnull
74 5cdb1798 2005-10-29 devnull static int totalbytes;
75 5cdb1798 2005-10-29 devnull static int totalmsgs;
76 5cdb1798 2005-10-29 devnull static Msg *msg;
77 5cdb1798 2005-10-29 devnull static int nmsg;
78 5cdb1798 2005-10-29 devnull static int loggedin;
79 5cdb1798 2005-10-29 devnull static int debug;
80 5cdb1798 2005-10-29 devnull static uchar *tlscert;
81 5cdb1798 2005-10-29 devnull static int ntlscert;
82 5cdb1798 2005-10-29 devnull static char *peeraddr;
83 5cdb1798 2005-10-29 devnull static char tmpaddr[64];
84 5cdb1798 2005-10-29 devnull
85 5cdb1798 2005-10-29 devnull void
86 5cdb1798 2005-10-29 devnull usage(void)
87 5cdb1798 2005-10-29 devnull {
88 5cdb1798 2005-10-29 devnull fprint(2, "usage: upas/pop3 [-a authmboxfile] [-d debugfile] [-p]\n");
89 5cdb1798 2005-10-29 devnull exits("usage");
90 5cdb1798 2005-10-29 devnull }
91 5cdb1798 2005-10-29 devnull
92 5cdb1798 2005-10-29 devnull void
93 5cdb1798 2005-10-29 devnull main(int argc, char **argv)
94 5cdb1798 2005-10-29 devnull {
95 5cdb1798 2005-10-29 devnull int fd;
96 5cdb1798 2005-10-29 devnull char *arg, cmdbuf[1024];
97 5cdb1798 2005-10-29 devnull Cmd *c;
98 5cdb1798 2005-10-29 devnull
99 5cdb1798 2005-10-29 devnull rfork(RFNAMEG);
100 5cdb1798 2005-10-29 devnull Binit(&in, 0, OREAD);
101 5cdb1798 2005-10-29 devnull Binit(&out, 1, OWRITE);
102 5cdb1798 2005-10-29 devnull
103 5cdb1798 2005-10-29 devnull ARGBEGIN{
104 5cdb1798 2005-10-29 devnull case 'a':
105 5cdb1798 2005-10-29 devnull loggedin = 1;
106 5cdb1798 2005-10-29 devnull if(readmbox(EARGF(usage())) < 0)
107 5cdb1798 2005-10-29 devnull exits(nil);
108 5cdb1798 2005-10-29 devnull break;
109 5cdb1798 2005-10-29 devnull case 'd':
110 5cdb1798 2005-10-29 devnull debug++;
111 5cdb1798 2005-10-29 devnull if((fd = create(EARGF(usage()), OWRITE, 0666)) >= 0 && fd != 2){
112 5cdb1798 2005-10-29 devnull dup(fd, 2);
113 5cdb1798 2005-10-29 devnull close(fd);
114 5cdb1798 2005-10-29 devnull }
115 5cdb1798 2005-10-29 devnull break;
116 5cdb1798 2005-10-29 devnull case 'r':
117 5cdb1798 2005-10-29 devnull strecpy(tmpaddr, tmpaddr+sizeof tmpaddr, EARGF(usage()));
118 5cdb1798 2005-10-29 devnull if(arg = strchr(tmpaddr, '!'))
119 5cdb1798 2005-10-29 devnull *arg = '\0';
120 5cdb1798 2005-10-29 devnull peeraddr = tmpaddr;
121 5cdb1798 2005-10-29 devnull break;
122 5cdb1798 2005-10-29 devnull case 't':
123 5cdb1798 2005-10-29 devnull tlscert = readcert(EARGF(usage()), &ntlscert);
124 5cdb1798 2005-10-29 devnull if(tlscert == nil){
125 5cdb1798 2005-10-29 devnull senderr("cannot read TLS certificate: %r");
126 5cdb1798 2005-10-29 devnull exits(nil);
127 5cdb1798 2005-10-29 devnull }
128 5cdb1798 2005-10-29 devnull break;
129 5cdb1798 2005-10-29 devnull case 'p':
130 5cdb1798 2005-10-29 devnull passwordinclear = 1;
131 5cdb1798 2005-10-29 devnull break;
132 5cdb1798 2005-10-29 devnull }ARGEND
133 5cdb1798 2005-10-29 devnull
134 5cdb1798 2005-10-29 devnull /* do before TLS */
135 5cdb1798 2005-10-29 devnull if(peeraddr == nil)
136 5cdb1798 2005-10-29 devnull peeraddr = remoteaddr(0,0);
137 5cdb1798 2005-10-29 devnull
138 5cdb1798 2005-10-29 devnull hello();
139 5cdb1798 2005-10-29 devnull
140 5cdb1798 2005-10-29 devnull while(Bflush(&out), getcrnl(cmdbuf, sizeof cmdbuf) > 0){
141 5cdb1798 2005-10-29 devnull arg = nextarg(cmdbuf);
142 5cdb1798 2005-10-29 devnull for(c=cmdtab; c->name; c++)
143 5cdb1798 2005-10-29 devnull if(cistrcmp(c->name, cmdbuf) == 0)
144 5cdb1798 2005-10-29 devnull break;
145 5cdb1798 2005-10-29 devnull if(c->name == 0){
146 5cdb1798 2005-10-29 devnull senderr("unknown command %s", cmdbuf);
147 5cdb1798 2005-10-29 devnull continue;
148 5cdb1798 2005-10-29 devnull }
149 5cdb1798 2005-10-29 devnull if(c->needauth && !loggedin){
150 5cdb1798 2005-10-29 devnull senderr("%s requires authentication", cmdbuf);
151 5cdb1798 2005-10-29 devnull continue;
152 5cdb1798 2005-10-29 devnull }
153 5cdb1798 2005-10-29 devnull (*c->f)(arg);
154 5cdb1798 2005-10-29 devnull }
155 5cdb1798 2005-10-29 devnull exits(nil);
156 5cdb1798 2005-10-29 devnull }
157 5cdb1798 2005-10-29 devnull
158 5cdb1798 2005-10-29 devnull /* sort directories in increasing message number order */
159 5cdb1798 2005-10-29 devnull static int
160 5cdb1798 2005-10-29 devnull dircmp(void *a, void *b)
161 5cdb1798 2005-10-29 devnull {
162 5cdb1798 2005-10-29 devnull return atoi(((Dir*)a)->name) - atoi(((Dir*)b)->name);
163 5cdb1798 2005-10-29 devnull }
164 5cdb1798 2005-10-29 devnull
165 5cdb1798 2005-10-29 devnull static int
166 5cdb1798 2005-10-29 devnull readmbox(char *box)
167 5cdb1798 2005-10-29 devnull {
168 5cdb1798 2005-10-29 devnull int fd, i, n, nd, lines, pid;
169 5cdb1798 2005-10-29 devnull char buf[100], err[ERRMAX];
170 5cdb1798 2005-10-29 devnull char *p;
171 5cdb1798 2005-10-29 devnull Biobuf *b;
172 5cdb1798 2005-10-29 devnull Dir *d, *draw;
173 5cdb1798 2005-10-29 devnull Msg *m;
174 5cdb1798 2005-10-29 devnull Waitmsg *w;
175 5cdb1798 2005-10-29 devnull
176 5cdb1798 2005-10-29 devnull unmount(nil, "/mail/fs");
177 5cdb1798 2005-10-29 devnull switch(pid = fork()){
178 5cdb1798 2005-10-29 devnull case -1:
179 5cdb1798 2005-10-29 devnull return senderr("can't fork to start upas/fs");
180 5cdb1798 2005-10-29 devnull
181 5cdb1798 2005-10-29 devnull case 0:
182 5cdb1798 2005-10-29 devnull close(0);
183 5cdb1798 2005-10-29 devnull close(1);
184 5cdb1798 2005-10-29 devnull open("/dev/null", OREAD);
185 5cdb1798 2005-10-29 devnull open("/dev/null", OWRITE);
186 5cdb1798 2005-10-29 devnull execl("/bin/upas/fs", "upas/fs", "-np", "-f", box, nil);
187 5cdb1798 2005-10-29 devnull snprint(err, sizeof err, "upas/fs: %r");
188 5cdb1798 2005-10-29 devnull _exits(err);
189 5cdb1798 2005-10-29 devnull break;
190 5cdb1798 2005-10-29 devnull
191 5cdb1798 2005-10-29 devnull default:
192 5cdb1798 2005-10-29 devnull break;
193 5cdb1798 2005-10-29 devnull }
194 5cdb1798 2005-10-29 devnull
195 5cdb1798 2005-10-29 devnull if((w = wait()) == nil || w->pid != pid || w->msg[0] != '\0'){
196 5cdb1798 2005-10-29 devnull if(w && w->pid==pid)
197 5cdb1798 2005-10-29 devnull return senderr("%s", w->msg);
198 5cdb1798 2005-10-29 devnull else
199 5cdb1798 2005-10-29 devnull return senderr("can't initialize upas/fs");
200 5cdb1798 2005-10-29 devnull }
201 5cdb1798 2005-10-29 devnull free(w);
202 5cdb1798 2005-10-29 devnull
203 5cdb1798 2005-10-29 devnull if(chdir("/mail/fs/mbox") < 0)
204 5cdb1798 2005-10-29 devnull return senderr("can't initialize upas/fs: %r");
205 5cdb1798 2005-10-29 devnull
206 5cdb1798 2005-10-29 devnull if((fd = open(".", OREAD)) < 0)
207 5cdb1798 2005-10-29 devnull return senderr("cannot open /mail/fs/mbox: %r");
208 5cdb1798 2005-10-29 devnull nd = dirreadall(fd, &d);
209 5cdb1798 2005-10-29 devnull close(fd);
210 5cdb1798 2005-10-29 devnull if(nd < 0)
211 5cdb1798 2005-10-29 devnull return senderr("cannot read from /mail/fs/mbox: %r");
212 5cdb1798 2005-10-29 devnull
213 5cdb1798 2005-10-29 devnull msg = mallocz(sizeof(Msg)*nd, 1);
214 5cdb1798 2005-10-29 devnull if(msg == nil)
215 5cdb1798 2005-10-29 devnull return senderr("out of memory");
216 5cdb1798 2005-10-29 devnull
217 5cdb1798 2005-10-29 devnull if(nd == 0)
218 5cdb1798 2005-10-29 devnull return 0;
219 5cdb1798 2005-10-29 devnull qsort(d, nd, sizeof(d[0]), dircmp);
220 5cdb1798 2005-10-29 devnull
221 5cdb1798 2005-10-29 devnull for(i=0; i<nd; i++){
222 5cdb1798 2005-10-29 devnull m = &msg[nmsg];
223 5cdb1798 2005-10-29 devnull m->upasnum = atoi(d[i].name);
224 5cdb1798 2005-10-29 devnull sprint(buf, "%d/digest", m->upasnum);
225 5cdb1798 2005-10-29 devnull if((fd = open(buf, OREAD)) < 0)
226 5cdb1798 2005-10-29 devnull continue;
227 5cdb1798 2005-10-29 devnull n = readn(fd, m->digest, sizeof m->digest - 1);
228 5cdb1798 2005-10-29 devnull close(fd);
229 5cdb1798 2005-10-29 devnull if(n < 0)
230 5cdb1798 2005-10-29 devnull continue;
231 5cdb1798 2005-10-29 devnull m->digest[n] = '\0';
232 5cdb1798 2005-10-29 devnull
233 5cdb1798 2005-10-29 devnull /*
234 5cdb1798 2005-10-29 devnull * We need the number of message lines so that we
235 5cdb1798 2005-10-29 devnull * can adjust the byte count to include \r's.
236 5cdb1798 2005-10-29 devnull * Upas/fs gives us the number of lines in the raw body
237 5cdb1798 2005-10-29 devnull * in the lines file, but we have to count rawheader ourselves.
238 5cdb1798 2005-10-29 devnull * There is one blank line between raw header and raw body.
239 5cdb1798 2005-10-29 devnull */
240 5cdb1798 2005-10-29 devnull sprint(buf, "%d/rawheader", m->upasnum);
241 5cdb1798 2005-10-29 devnull if((b = Bopen(buf, OREAD)) == nil)
242 5cdb1798 2005-10-29 devnull continue;
243 5cdb1798 2005-10-29 devnull lines = 0;
244 5cdb1798 2005-10-29 devnull for(;;){
245 5cdb1798 2005-10-29 devnull p = Brdline(b, '\n');
246 5cdb1798 2005-10-29 devnull if(p == nil){
247 5cdb1798 2005-10-29 devnull if((n = Blinelen(b)) == 0)
248 5cdb1798 2005-10-29 devnull break;
249 5cdb1798 2005-10-29 devnull Bseek(b, n, 1);
250 5cdb1798 2005-10-29 devnull }else
251 5cdb1798 2005-10-29 devnull lines++;
252 5cdb1798 2005-10-29 devnull }
253 5cdb1798 2005-10-29 devnull Bterm(b);
254 5cdb1798 2005-10-29 devnull lines++;
255 5cdb1798 2005-10-29 devnull sprint(buf, "%d/lines", m->upasnum);
256 5cdb1798 2005-10-29 devnull if((fd = open(buf, OREAD)) < 0)
257 5cdb1798 2005-10-29 devnull continue;
258 5cdb1798 2005-10-29 devnull n = readn(fd, buf, sizeof buf - 1);
259 5cdb1798 2005-10-29 devnull close(fd);
260 5cdb1798 2005-10-29 devnull if(n < 0)
261 5cdb1798 2005-10-29 devnull continue;
262 5cdb1798 2005-10-29 devnull buf[n] = '\0';
263 5cdb1798 2005-10-29 devnull lines += atoi(buf);
264 5cdb1798 2005-10-29 devnull
265 5cdb1798 2005-10-29 devnull sprint(buf, "%d/raw", m->upasnum);
266 5cdb1798 2005-10-29 devnull if((draw = dirstat(buf)) == nil)
267 5cdb1798 2005-10-29 devnull continue;
268 5cdb1798 2005-10-29 devnull m->bytes = lines+draw->length;
269 5cdb1798 2005-10-29 devnull free(draw);
270 5cdb1798 2005-10-29 devnull nmsg++;
271 5cdb1798 2005-10-29 devnull totalmsgs++;
272 5cdb1798 2005-10-29 devnull totalbytes += m->bytes;
273 5cdb1798 2005-10-29 devnull }
274 5cdb1798 2005-10-29 devnull return 0;
275 5cdb1798 2005-10-29 devnull }
276 5cdb1798 2005-10-29 devnull
277 5cdb1798 2005-10-29 devnull /*
278 5cdb1798 2005-10-29 devnull * get a line that ends in crnl or cr, turn terminating crnl into a nl
279 5cdb1798 2005-10-29 devnull *
280 5cdb1798 2005-10-29 devnull * return 0 on EOF
281 5cdb1798 2005-10-29 devnull */
282 5cdb1798 2005-10-29 devnull static int
283 5cdb1798 2005-10-29 devnull getcrnl(char *buf, int n)
284 5cdb1798 2005-10-29 devnull {
285 5cdb1798 2005-10-29 devnull int c;
286 5cdb1798 2005-10-29 devnull char *ep;
287 5cdb1798 2005-10-29 devnull char *bp;
288 5cdb1798 2005-10-29 devnull Biobuf *fp = &in;
289 5cdb1798 2005-10-29 devnull
290 5cdb1798 2005-10-29 devnull Bflush(&out);
291 5cdb1798 2005-10-29 devnull
292 5cdb1798 2005-10-29 devnull bp = buf;
293 5cdb1798 2005-10-29 devnull ep = bp + n - 1;
294 5cdb1798 2005-10-29 devnull while(bp != ep){
295 5cdb1798 2005-10-29 devnull c = Bgetc(fp);
296 5cdb1798 2005-10-29 devnull if(debug) {
297 5cdb1798 2005-10-29 devnull seek(2, 0, 2);
298 5cdb1798 2005-10-29 devnull fprint(2, "%c", c);
299 5cdb1798 2005-10-29 devnull }
300 5cdb1798 2005-10-29 devnull switch(c){
301 5cdb1798 2005-10-29 devnull case -1:
302 5cdb1798 2005-10-29 devnull *bp = 0;
303 5cdb1798 2005-10-29 devnull if(bp==buf)
304 5cdb1798 2005-10-29 devnull return 0;
305 5cdb1798 2005-10-29 devnull else
306 5cdb1798 2005-10-29 devnull return bp-buf;
307 5cdb1798 2005-10-29 devnull case '\r':
308 5cdb1798 2005-10-29 devnull c = Bgetc(fp);
309 5cdb1798 2005-10-29 devnull if(c == '\n'){
310 5cdb1798 2005-10-29 devnull if(debug) {
311 5cdb1798 2005-10-29 devnull seek(2, 0, 2);
312 5cdb1798 2005-10-29 devnull fprint(2, "%c", c);
313 5cdb1798 2005-10-29 devnull }
314 5cdb1798 2005-10-29 devnull *bp = 0;
315 5cdb1798 2005-10-29 devnull return bp-buf;
316 5cdb1798 2005-10-29 devnull }
317 5cdb1798 2005-10-29 devnull Bungetc(fp);
318 5cdb1798 2005-10-29 devnull c = '\r';
319 5cdb1798 2005-10-29 devnull break;
320 5cdb1798 2005-10-29 devnull case '\n':
321 5cdb1798 2005-10-29 devnull *bp = 0;
322 5cdb1798 2005-10-29 devnull return bp-buf;
323 5cdb1798 2005-10-29 devnull }
324 5cdb1798 2005-10-29 devnull *bp++ = c;
325 5cdb1798 2005-10-29 devnull }
326 5cdb1798 2005-10-29 devnull *bp = 0;
327 5cdb1798 2005-10-29 devnull return bp-buf;
328 5cdb1798 2005-10-29 devnull }
329 5cdb1798 2005-10-29 devnull
330 5cdb1798 2005-10-29 devnull static void
331 5cdb1798 2005-10-29 devnull sendcrnl(char *fmt, ...)
332 5cdb1798 2005-10-29 devnull {
333 5cdb1798 2005-10-29 devnull char buf[1024];
334 5cdb1798 2005-10-29 devnull va_list arg;
335 5cdb1798 2005-10-29 devnull
336 5cdb1798 2005-10-29 devnull va_start(arg, fmt);
337 5cdb1798 2005-10-29 devnull vseprint(buf, buf+sizeof(buf), fmt, arg);
338 5cdb1798 2005-10-29 devnull va_end(arg);
339 5cdb1798 2005-10-29 devnull if(debug)
340 5cdb1798 2005-10-29 devnull fprint(2, "-> %s\n", buf);
341 5cdb1798 2005-10-29 devnull Bprint(&out, "%s\r\n", buf);
342 5cdb1798 2005-10-29 devnull }
343 5cdb1798 2005-10-29 devnull
344 5cdb1798 2005-10-29 devnull static int
345 5cdb1798 2005-10-29 devnull senderr(char *fmt, ...)
346 5cdb1798 2005-10-29 devnull {
347 5cdb1798 2005-10-29 devnull char buf[1024];
348 5cdb1798 2005-10-29 devnull va_list arg;
349 5cdb1798 2005-10-29 devnull
350 5cdb1798 2005-10-29 devnull va_start(arg, fmt);
351 5cdb1798 2005-10-29 devnull vseprint(buf, buf+sizeof(buf), fmt, arg);
352 5cdb1798 2005-10-29 devnull va_end(arg);
353 5cdb1798 2005-10-29 devnull if(debug)
354 5cdb1798 2005-10-29 devnull fprint(2, "-> -ERR %s\n", buf);
355 5cdb1798 2005-10-29 devnull Bprint(&out, "-ERR %s\r\n", buf);
356 5cdb1798 2005-10-29 devnull return -1;
357 5cdb1798 2005-10-29 devnull }
358 5cdb1798 2005-10-29 devnull
359 5cdb1798 2005-10-29 devnull static int
360 5cdb1798 2005-10-29 devnull sendok(char *fmt, ...)
361 5cdb1798 2005-10-29 devnull {
362 5cdb1798 2005-10-29 devnull char buf[1024];
363 5cdb1798 2005-10-29 devnull va_list arg;
364 5cdb1798 2005-10-29 devnull
365 5cdb1798 2005-10-29 devnull va_start(arg, fmt);
366 5cdb1798 2005-10-29 devnull vseprint(buf, buf+sizeof(buf), fmt, arg);
367 5cdb1798 2005-10-29 devnull va_end(arg);
368 5cdb1798 2005-10-29 devnull if(*buf){
369 5cdb1798 2005-10-29 devnull if(debug)
370 5cdb1798 2005-10-29 devnull fprint(2, "-> +OK %s\n", buf);
371 5cdb1798 2005-10-29 devnull Bprint(&out, "+OK %s\r\n", buf);
372 5cdb1798 2005-10-29 devnull } else {
373 5cdb1798 2005-10-29 devnull if(debug)
374 5cdb1798 2005-10-29 devnull fprint(2, "-> +OK\n");
375 5cdb1798 2005-10-29 devnull Bprint(&out, "+OK\r\n");
376 5cdb1798 2005-10-29 devnull }
377 5cdb1798 2005-10-29 devnull return 0;
378 5cdb1798 2005-10-29 devnull }
379 5cdb1798 2005-10-29 devnull
380 5cdb1798 2005-10-29 devnull static int
381 5cdb1798 2005-10-29 devnull capacmd(char*)
382 5cdb1798 2005-10-29 devnull {
383 5cdb1798 2005-10-29 devnull sendok("");
384 5cdb1798 2005-10-29 devnull sendcrnl("TOP");
385 5cdb1798 2005-10-29 devnull if(passwordinclear || didtls)
386 5cdb1798 2005-10-29 devnull sendcrnl("USER");
387 5cdb1798 2005-10-29 devnull sendcrnl("PIPELINING");
388 5cdb1798 2005-10-29 devnull sendcrnl("UIDL");
389 5cdb1798 2005-10-29 devnull sendcrnl("STLS");
390 5cdb1798 2005-10-29 devnull sendcrnl(".");
391 5cdb1798 2005-10-29 devnull return 0;
392 5cdb1798 2005-10-29 devnull }
393 5cdb1798 2005-10-29 devnull
394 5cdb1798 2005-10-29 devnull static int
395 5cdb1798 2005-10-29 devnull delecmd(char *arg)
396 5cdb1798 2005-10-29 devnull {
397 5cdb1798 2005-10-29 devnull int n;
398 5cdb1798 2005-10-29 devnull
399 5cdb1798 2005-10-29 devnull if(*arg==0)
400 5cdb1798 2005-10-29 devnull return senderr("DELE requires a message number");
401 5cdb1798 2005-10-29 devnull
402 5cdb1798 2005-10-29 devnull n = atoi(arg)-1;
403 5cdb1798 2005-10-29 devnull if(n < 0 || n >= nmsg || msg[n].deleted)
404 5cdb1798 2005-10-29 devnull return senderr("no such message");
405 5cdb1798 2005-10-29 devnull
406 5cdb1798 2005-10-29 devnull msg[n].deleted = 1;
407 5cdb1798 2005-10-29 devnull totalmsgs--;
408 5cdb1798 2005-10-29 devnull totalbytes -= msg[n].bytes;
409 5cdb1798 2005-10-29 devnull sendok("message %d deleted", n+1);
410 5cdb1798 2005-10-29 devnull return 0;
411 5cdb1798 2005-10-29 devnull }
412 5cdb1798 2005-10-29 devnull
413 5cdb1798 2005-10-29 devnull static int
414 5cdb1798 2005-10-29 devnull listcmd(char *arg)
415 5cdb1798 2005-10-29 devnull {
416 5cdb1798 2005-10-29 devnull int i, n;
417 5cdb1798 2005-10-29 devnull
418 5cdb1798 2005-10-29 devnull if(*arg == 0){
419 5cdb1798 2005-10-29 devnull sendok("+%d message%s (%d octets)", totalmsgs, totalmsgs==1 ? "":"s", totalbytes);
420 5cdb1798 2005-10-29 devnull for(i=0; i<nmsg; i++){
421 5cdb1798 2005-10-29 devnull if(msg[i].deleted)
422 5cdb1798 2005-10-29 devnull continue;
423 5cdb1798 2005-10-29 devnull sendcrnl("%d %d", i+1, msg[i].bytes);
424 5cdb1798 2005-10-29 devnull }
425 5cdb1798 2005-10-29 devnull sendcrnl(".");
426 5cdb1798 2005-10-29 devnull }else{
427 5cdb1798 2005-10-29 devnull n = atoi(arg)-1;
428 5cdb1798 2005-10-29 devnull if(n < 0 || n >= nmsg || msg[n].deleted)
429 5cdb1798 2005-10-29 devnull return senderr("no such message");
430 5cdb1798 2005-10-29 devnull sendok("%d %d", n+1, msg[n].bytes);
431 5cdb1798 2005-10-29 devnull }
432 5cdb1798 2005-10-29 devnull return 0;
433 5cdb1798 2005-10-29 devnull }
434 5cdb1798 2005-10-29 devnull
435 5cdb1798 2005-10-29 devnull static int
436 5cdb1798 2005-10-29 devnull noopcmd(char *arg)
437 5cdb1798 2005-10-29 devnull {
438 5cdb1798 2005-10-29 devnull USED(arg);
439 5cdb1798 2005-10-29 devnull sendok("");
440 5cdb1798 2005-10-29 devnull return 0;
441 5cdb1798 2005-10-29 devnull }
442 5cdb1798 2005-10-29 devnull
443 5cdb1798 2005-10-29 devnull static void
444 5cdb1798 2005-10-29 devnull _synccmd(char*)
445 5cdb1798 2005-10-29 devnull {
446 5cdb1798 2005-10-29 devnull int i, fd;
447 5cdb1798 2005-10-29 devnull char *s;
448 5cdb1798 2005-10-29 devnull Fmt f;
449 5cdb1798 2005-10-29 devnull
450 5cdb1798 2005-10-29 devnull if(!loggedin){
451 5cdb1798 2005-10-29 devnull sendok("");
452 5cdb1798 2005-10-29 devnull return;
453 5cdb1798 2005-10-29 devnull }
454 5cdb1798 2005-10-29 devnull
455 5cdb1798 2005-10-29 devnull fmtstrinit(&f);
456 5cdb1798 2005-10-29 devnull fmtprint(&f, "delete mbox");
457 5cdb1798 2005-10-29 devnull for(i=0; i<nmsg; i++)
458 5cdb1798 2005-10-29 devnull if(msg[i].deleted)
459 5cdb1798 2005-10-29 devnull fmtprint(&f, " %d", msg[i].upasnum);
460 5cdb1798 2005-10-29 devnull s = fmtstrflush(&f);
461 5cdb1798 2005-10-29 devnull if(strcmp(s, "delete mbox") != 0){ /* must have something to delete */
462 5cdb1798 2005-10-29 devnull if((fd = open("../ctl", OWRITE)) < 0){
463 5cdb1798 2005-10-29 devnull senderr("open ctl to delete messages: %r");
464 5cdb1798 2005-10-29 devnull return;
465 5cdb1798 2005-10-29 devnull }
466 5cdb1798 2005-10-29 devnull if(write(fd, s, strlen(s)) < 0){
467 5cdb1798 2005-10-29 devnull senderr("error deleting messages: %r");
468 5cdb1798 2005-10-29 devnull return;
469 5cdb1798 2005-10-29 devnull }
470 5cdb1798 2005-10-29 devnull }
471 5cdb1798 2005-10-29 devnull sendok("");
472 5cdb1798 2005-10-29 devnull }
473 5cdb1798 2005-10-29 devnull
474 5cdb1798 2005-10-29 devnull static int
475 5cdb1798 2005-10-29 devnull synccmd(char*)
476 5cdb1798 2005-10-29 devnull {
477 5cdb1798 2005-10-29 devnull _synccmd(nil);
478 5cdb1798 2005-10-29 devnull return 0;
479 5cdb1798 2005-10-29 devnull }
480 5cdb1798 2005-10-29 devnull
481 5cdb1798 2005-10-29 devnull static int
482 5cdb1798 2005-10-29 devnull quitcmd(char*)
483 5cdb1798 2005-10-29 devnull {
484 5cdb1798 2005-10-29 devnull synccmd(nil);
485 5cdb1798 2005-10-29 devnull exits(nil);
486 5cdb1798 2005-10-29 devnull return 0;
487 5cdb1798 2005-10-29 devnull }
488 5cdb1798 2005-10-29 devnull
489 5cdb1798 2005-10-29 devnull static int
490 5cdb1798 2005-10-29 devnull retrcmd(char *arg)
491 5cdb1798 2005-10-29 devnull {
492 5cdb1798 2005-10-29 devnull int n;
493 5cdb1798 2005-10-29 devnull Biobuf *b;
494 5cdb1798 2005-10-29 devnull char buf[40], *p;
495 5cdb1798 2005-10-29 devnull
496 5cdb1798 2005-10-29 devnull if(*arg == 0)
497 5cdb1798 2005-10-29 devnull return senderr("RETR requires a message number");
498 5cdb1798 2005-10-29 devnull n = atoi(arg)-1;
499 5cdb1798 2005-10-29 devnull if(n < 0 || n >= nmsg || msg[n].deleted)
500 5cdb1798 2005-10-29 devnull return senderr("no such message");
501 5cdb1798 2005-10-29 devnull snprint(buf, sizeof buf, "%d/raw", msg[n].upasnum);
502 5cdb1798 2005-10-29 devnull if((b = Bopen(buf, OREAD)) == nil)
503 5cdb1798 2005-10-29 devnull return senderr("message disappeared");
504 5cdb1798 2005-10-29 devnull sendok("");
505 5cdb1798 2005-10-29 devnull while((p = Brdstr(b, '\n', 1)) != nil){
506 5cdb1798 2005-10-29 devnull if(p[0]=='.')
507 5cdb1798 2005-10-29 devnull Bwrite(&out, ".", 1);
508 5cdb1798 2005-10-29 devnull Bwrite(&out, p, strlen(p));
509 5cdb1798 2005-10-29 devnull Bwrite(&out, "\r\n", 2);
510 5cdb1798 2005-10-29 devnull free(p);
511 5cdb1798 2005-10-29 devnull }
512 5cdb1798 2005-10-29 devnull Bterm(b);
513 5cdb1798 2005-10-29 devnull sendcrnl(".");
514 5cdb1798 2005-10-29 devnull return 0;
515 5cdb1798 2005-10-29 devnull }
516 5cdb1798 2005-10-29 devnull
517 5cdb1798 2005-10-29 devnull static int
518 5cdb1798 2005-10-29 devnull rsetcmd(char*)
519 5cdb1798 2005-10-29 devnull {
520 5cdb1798 2005-10-29 devnull int i;
521 5cdb1798 2005-10-29 devnull
522 5cdb1798 2005-10-29 devnull for(i=0; i<nmsg; i++){
523 5cdb1798 2005-10-29 devnull if(msg[i].deleted){
524 5cdb1798 2005-10-29 devnull msg[i].deleted = 0;
525 5cdb1798 2005-10-29 devnull totalmsgs++;
526 5cdb1798 2005-10-29 devnull totalbytes += msg[i].bytes;
527 5cdb1798 2005-10-29 devnull }
528 5cdb1798 2005-10-29 devnull }
529 5cdb1798 2005-10-29 devnull return sendok("");
530 5cdb1798 2005-10-29 devnull }
531 5cdb1798 2005-10-29 devnull
532 5cdb1798 2005-10-29 devnull static int
533 5cdb1798 2005-10-29 devnull statcmd(char*)
534 5cdb1798 2005-10-29 devnull {
535 5cdb1798 2005-10-29 devnull return sendok("%d %d", totalmsgs, totalbytes);
536 5cdb1798 2005-10-29 devnull }
537 5cdb1798 2005-10-29 devnull
538 5cdb1798 2005-10-29 devnull static int
539 5cdb1798 2005-10-29 devnull trace(char *fmt, ...)
540 5cdb1798 2005-10-29 devnull {
541 5cdb1798 2005-10-29 devnull va_list arg;
542 5cdb1798 2005-10-29 devnull int n;
543 5cdb1798 2005-10-29 devnull
544 5cdb1798 2005-10-29 devnull va_start(arg, fmt);
545 5cdb1798 2005-10-29 devnull n = vfprint(2, fmt, arg);
546 5cdb1798 2005-10-29 devnull va_end(arg);
547 5cdb1798 2005-10-29 devnull return n;
548 5cdb1798 2005-10-29 devnull }
549 5cdb1798 2005-10-29 devnull
550 5cdb1798 2005-10-29 devnull static int
551 5cdb1798 2005-10-29 devnull stlscmd(char*)
552 5cdb1798 2005-10-29 devnull {
553 5cdb1798 2005-10-29 devnull int fd;
554 5cdb1798 2005-10-29 devnull TLSconn conn;
555 5cdb1798 2005-10-29 devnull
556 5cdb1798 2005-10-29 devnull if(didtls)
557 5cdb1798 2005-10-29 devnull return senderr("tls already started");
558 5cdb1798 2005-10-29 devnull if(!tlscert)
559 5cdb1798 2005-10-29 devnull return senderr("don't have any tls credentials");
560 5cdb1798 2005-10-29 devnull sendok("");
561 5cdb1798 2005-10-29 devnull Bflush(&out);
562 5cdb1798 2005-10-29 devnull
563 5cdb1798 2005-10-29 devnull memset(&conn, 0, sizeof conn);
564 5cdb1798 2005-10-29 devnull conn.cert = tlscert;
565 5cdb1798 2005-10-29 devnull conn.certlen = ntlscert;
566 5cdb1798 2005-10-29 devnull if(debug)
567 5cdb1798 2005-10-29 devnull conn.trace = trace;
568 5cdb1798 2005-10-29 devnull fd = tlsServer(0, &conn);
569 5cdb1798 2005-10-29 devnull if(fd < 0)
570 5cdb1798 2005-10-29 devnull sysfatal("tlsServer: %r");
571 5cdb1798 2005-10-29 devnull dup(fd, 0);
572 5cdb1798 2005-10-29 devnull dup(fd, 1);
573 5cdb1798 2005-10-29 devnull close(fd);
574 5cdb1798 2005-10-29 devnull Binit(&in, 0, OREAD);
575 5cdb1798 2005-10-29 devnull Binit(&out, 1, OWRITE);
576 5cdb1798 2005-10-29 devnull didtls = 1;
577 5cdb1798 2005-10-29 devnull return 0;
578 5cdb1798 2005-10-29 devnull }
579 5cdb1798 2005-10-29 devnull
580 5cdb1798 2005-10-29 devnull static int
581 5cdb1798 2005-10-29 devnull topcmd(char *arg)
582 5cdb1798 2005-10-29 devnull {
583 5cdb1798 2005-10-29 devnull int done, i, lines, n;
584 5cdb1798 2005-10-29 devnull char buf[40], *p;
585 5cdb1798 2005-10-29 devnull Biobuf *b;
586 5cdb1798 2005-10-29 devnull
587 5cdb1798 2005-10-29 devnull if(*arg == 0)
588 5cdb1798 2005-10-29 devnull return senderr("TOP requires a message number");
589 5cdb1798 2005-10-29 devnull n = atoi(arg)-1;
590 5cdb1798 2005-10-29 devnull if(n < 0 || n >= nmsg || msg[n].deleted)
591 5cdb1798 2005-10-29 devnull return senderr("no such message");
592 5cdb1798 2005-10-29 devnull arg = nextarg(arg);
593 5cdb1798 2005-10-29 devnull if(*arg == 0)
594 5cdb1798 2005-10-29 devnull return senderr("TOP requires a line count");
595 5cdb1798 2005-10-29 devnull lines = atoi(arg);
596 5cdb1798 2005-10-29 devnull if(lines < 0)
597 5cdb1798 2005-10-29 devnull return senderr("bad args to TOP");
598 5cdb1798 2005-10-29 devnull snprint(buf, sizeof buf, "%d/raw", msg[n].upasnum);
599 5cdb1798 2005-10-29 devnull if((b = Bopen(buf, OREAD)) == nil)
600 5cdb1798 2005-10-29 devnull return senderr("message disappeared");
601 5cdb1798 2005-10-29 devnull sendok("");
602 5cdb1798 2005-10-29 devnull while(p = Brdstr(b, '\n', 1)){
603 5cdb1798 2005-10-29 devnull if(p[0]=='.')
604 5cdb1798 2005-10-29 devnull Bputc(&out, '.');
605 5cdb1798 2005-10-29 devnull Bwrite(&out, p, strlen(p));
606 5cdb1798 2005-10-29 devnull Bwrite(&out, "\r\n", 2);
607 5cdb1798 2005-10-29 devnull done = p[0]=='\0';
608 5cdb1798 2005-10-29 devnull free(p);
609 5cdb1798 2005-10-29 devnull if(done)
610 5cdb1798 2005-10-29 devnull break;
611 5cdb1798 2005-10-29 devnull }
612 5cdb1798 2005-10-29 devnull for(i=0; i<lines; i++){
613 5cdb1798 2005-10-29 devnull p = Brdstr(b, '\n', 1);
614 5cdb1798 2005-10-29 devnull if(p == nil)
615 5cdb1798 2005-10-29 devnull break;
616 5cdb1798 2005-10-29 devnull if(p[0]=='.')
617 5cdb1798 2005-10-29 devnull Bwrite(&out, ".", 1);
618 5cdb1798 2005-10-29 devnull Bwrite(&out, p, strlen(p));
619 5cdb1798 2005-10-29 devnull Bwrite(&out, "\r\n", 2);
620 5cdb1798 2005-10-29 devnull free(p);
621 5cdb1798 2005-10-29 devnull }
622 5cdb1798 2005-10-29 devnull sendcrnl(".");
623 5cdb1798 2005-10-29 devnull Bterm(b);
624 5cdb1798 2005-10-29 devnull return 0;
625 5cdb1798 2005-10-29 devnull }
626 5cdb1798 2005-10-29 devnull
627 5cdb1798 2005-10-29 devnull static int
628 5cdb1798 2005-10-29 devnull uidlcmd(char *arg)
629 5cdb1798 2005-10-29 devnull {
630 5cdb1798 2005-10-29 devnull int n;
631 5cdb1798 2005-10-29 devnull
632 5cdb1798 2005-10-29 devnull if(*arg==0){
633 5cdb1798 2005-10-29 devnull sendok("");
634 5cdb1798 2005-10-29 devnull for(n=0; n<nmsg; n++){
635 5cdb1798 2005-10-29 devnull if(msg[n].deleted)
636 5cdb1798 2005-10-29 devnull continue;
637 5cdb1798 2005-10-29 devnull sendcrnl("%d %s", n+1, msg[n].digest);
638 5cdb1798 2005-10-29 devnull }
639 5cdb1798 2005-10-29 devnull sendcrnl(".");
640 5cdb1798 2005-10-29 devnull }else{
641 5cdb1798 2005-10-29 devnull n = atoi(arg)-1;
642 5cdb1798 2005-10-29 devnull if(n < 0 || n >= nmsg || msg[n].deleted)
643 5cdb1798 2005-10-29 devnull return senderr("no such message");
644 5cdb1798 2005-10-29 devnull sendok("%d %s", n+1, msg[n].digest);
645 5cdb1798 2005-10-29 devnull }
646 5cdb1798 2005-10-29 devnull return 0;
647 5cdb1798 2005-10-29 devnull }
648 5cdb1798 2005-10-29 devnull
649 5cdb1798 2005-10-29 devnull static char*
650 5cdb1798 2005-10-29 devnull nextarg(char *p)
651 5cdb1798 2005-10-29 devnull {
652 5cdb1798 2005-10-29 devnull while(*p && *p != ' ' && *p != '\t')
653 5cdb1798 2005-10-29 devnull p++;
654 5cdb1798 2005-10-29 devnull while(*p == ' ' || *p == '\t')
655 5cdb1798 2005-10-29 devnull *p++ = 0;
656 5cdb1798 2005-10-29 devnull return p;
657 5cdb1798 2005-10-29 devnull }
658 5cdb1798 2005-10-29 devnull
659 5cdb1798 2005-10-29 devnull /*
660 5cdb1798 2005-10-29 devnull * authentication
661 5cdb1798 2005-10-29 devnull */
662 5cdb1798 2005-10-29 devnull Chalstate *chs;
663 5cdb1798 2005-10-29 devnull char user[256];
664 5cdb1798 2005-10-29 devnull char box[256];
665 5cdb1798 2005-10-29 devnull char cbox[256];
666 5cdb1798 2005-10-29 devnull
667 5cdb1798 2005-10-29 devnull static void
668 5cdb1798 2005-10-29 devnull hello(void)
669 5cdb1798 2005-10-29 devnull {
670 5cdb1798 2005-10-29 devnull fmtinstall('H', encodefmt);
671 5cdb1798 2005-10-29 devnull if((chs = auth_challenge("proto=apop role=server")) == nil){
672 5cdb1798 2005-10-29 devnull senderr("auth server not responding, try later");
673 5cdb1798 2005-10-29 devnull exits(nil);
674 5cdb1798 2005-10-29 devnull }
675 5cdb1798 2005-10-29 devnull
676 5cdb1798 2005-10-29 devnull sendok("POP3 server ready %s", chs->chal);
677 5cdb1798 2005-10-29 devnull }
678 5cdb1798 2005-10-29 devnull
679 5cdb1798 2005-10-29 devnull static int
680 5cdb1798 2005-10-29 devnull setuser(char *arg)
681 5cdb1798 2005-10-29 devnull {
682 5cdb1798 2005-10-29 devnull char *p;
683 5cdb1798 2005-10-29 devnull
684 5cdb1798 2005-10-29 devnull strcpy(box, "/mail/box/");
685 5cdb1798 2005-10-29 devnull strecpy(box+strlen(box), box+sizeof box-7, arg);
686 5cdb1798 2005-10-29 devnull strcpy(cbox, box);
687 5cdb1798 2005-10-29 devnull cleanname(cbox);
688 5cdb1798 2005-10-29 devnull if(strcmp(cbox, box) != 0)
689 5cdb1798 2005-10-29 devnull return senderr("bad mailbox name");
690 5cdb1798 2005-10-29 devnull strcat(box, "/mbox");
691 5cdb1798 2005-10-29 devnull
692 5cdb1798 2005-10-29 devnull strecpy(user, user+sizeof user, arg);
693 5cdb1798 2005-10-29 devnull if(p = strchr(user, '/'))
694 5cdb1798 2005-10-29 devnull *p = '\0';
695 5cdb1798 2005-10-29 devnull return 0;
696 5cdb1798 2005-10-29 devnull }
697 5cdb1798 2005-10-29 devnull
698 5cdb1798 2005-10-29 devnull static int
699 5cdb1798 2005-10-29 devnull usercmd(char *arg)
700 5cdb1798 2005-10-29 devnull {
701 5cdb1798 2005-10-29 devnull if(loggedin)
702 5cdb1798 2005-10-29 devnull return senderr("already authenticated");
703 5cdb1798 2005-10-29 devnull if(*arg == 0)
704 5cdb1798 2005-10-29 devnull return senderr("USER requires argument");
705 5cdb1798 2005-10-29 devnull if(setuser(arg) < 0)
706 5cdb1798 2005-10-29 devnull return -1;
707 5cdb1798 2005-10-29 devnull return sendok("");
708 5cdb1798 2005-10-29 devnull }
709 5cdb1798 2005-10-29 devnull
710 5cdb1798 2005-10-29 devnull static void
711 5cdb1798 2005-10-29 devnull enableaddr(void)
712 5cdb1798 2005-10-29 devnull {
713 5cdb1798 2005-10-29 devnull int fd;
714 5cdb1798 2005-10-29 devnull char buf[64];
715 5cdb1798 2005-10-29 devnull
716 5cdb1798 2005-10-29 devnull /* hide the peer IP address under a rock in the ratifier FS */
717 5cdb1798 2005-10-29 devnull if(peeraddr == 0 || *peeraddr == 0)
718 5cdb1798 2005-10-29 devnull return;
719 5cdb1798 2005-10-29 devnull
720 5cdb1798 2005-10-29 devnull sprint(buf, "/mail/ratify/trusted/%s#32", peeraddr);
721 5cdb1798 2005-10-29 devnull
722 5cdb1798 2005-10-29 devnull /*
723 5cdb1798 2005-10-29 devnull * if the address is already there and the user owns it,
724 5cdb1798 2005-10-29 devnull * remove it and recreate it to give him a new time quanta.
725 5cdb1798 2005-10-29 devnull */
726 5cdb1798 2005-10-29 devnull if(access(buf, 0) >= 0 && remove(buf) < 0)
727 5cdb1798 2005-10-29 devnull return;
728 5cdb1798 2005-10-29 devnull
729 5cdb1798 2005-10-29 devnull fd = create(buf, OREAD, 0666);
730 5cdb1798 2005-10-29 devnull if(fd >= 0){
731 5cdb1798 2005-10-29 devnull close(fd);
732 5cdb1798 2005-10-29 devnull // syslog(0, "pop3", "ratified %s", peeraddr);
733 5cdb1798 2005-10-29 devnull }
734 5cdb1798 2005-10-29 devnull }
735 5cdb1798 2005-10-29 devnull
736 5cdb1798 2005-10-29 devnull static int
737 5cdb1798 2005-10-29 devnull dologin(char *response)
738 5cdb1798 2005-10-29 devnull {
739 5cdb1798 2005-10-29 devnull AuthInfo *ai;
740 5cdb1798 2005-10-29 devnull static int tries;
741 5cdb1798 2005-10-29 devnull
742 5cdb1798 2005-10-29 devnull chs->user = user;
743 5cdb1798 2005-10-29 devnull chs->resp = response;
744 5cdb1798 2005-10-29 devnull chs->nresp = strlen(response);
745 5cdb1798 2005-10-29 devnull if((ai = auth_response(chs)) == nil){
746 5cdb1798 2005-10-29 devnull if(tries++ >= 5){
747 5cdb1798 2005-10-29 devnull senderr("authentication failed: %r; server exiting");
748 5cdb1798 2005-10-29 devnull exits(nil);
749 5cdb1798 2005-10-29 devnull }
750 5cdb1798 2005-10-29 devnull return senderr("authentication failed");
751 5cdb1798 2005-10-29 devnull }
752 5cdb1798 2005-10-29 devnull
753 5cdb1798 2005-10-29 devnull if(auth_chuid(ai, nil) < 0){
754 5cdb1798 2005-10-29 devnull senderr("chuid failed: %r; server exiting");
755 5cdb1798 2005-10-29 devnull exits(nil);
756 5cdb1798 2005-10-29 devnull }
757 5cdb1798 2005-10-29 devnull auth_freeAI(ai);
758 5cdb1798 2005-10-29 devnull auth_freechal(chs);
759 5cdb1798 2005-10-29 devnull chs = nil;
760 5cdb1798 2005-10-29 devnull
761 5cdb1798 2005-10-29 devnull loggedin = 1;
762 5cdb1798 2005-10-29 devnull if(newns(user, 0) < 0){
763 5cdb1798 2005-10-29 devnull senderr("newns failed: %r; server exiting");
764 5cdb1798 2005-10-29 devnull exits(nil);
765 5cdb1798 2005-10-29 devnull }
766 5cdb1798 2005-10-29 devnull
767 5cdb1798 2005-10-29 devnull enableaddr();
768 5cdb1798 2005-10-29 devnull if(readmbox(box) < 0)
769 5cdb1798 2005-10-29 devnull exits(nil);
770 5cdb1798 2005-10-29 devnull return sendok("mailbox is %s", box);
771 5cdb1798 2005-10-29 devnull }
772 5cdb1798 2005-10-29 devnull
773 5cdb1798 2005-10-29 devnull static int
774 5cdb1798 2005-10-29 devnull passcmd(char *arg)
775 5cdb1798 2005-10-29 devnull {
776 5cdb1798 2005-10-29 devnull DigestState *s;
777 5cdb1798 2005-10-29 devnull uchar digest[MD5dlen];
778 5cdb1798 2005-10-29 devnull char response[2*MD5dlen+1];
779 5cdb1798 2005-10-29 devnull
780 5cdb1798 2005-10-29 devnull if(passwordinclear==0 && didtls==0)
781 5cdb1798 2005-10-29 devnull return senderr("password in the clear disallowed");
782 5cdb1798 2005-10-29 devnull
783 5cdb1798 2005-10-29 devnull /* use password to encode challenge */
784 5cdb1798 2005-10-29 devnull if((chs = auth_challenge("proto=apop role=server")) == nil)
785 5cdb1798 2005-10-29 devnull return senderr("couldn't get apop challenge");
786 5cdb1798 2005-10-29 devnull
787 5cdb1798 2005-10-29 devnull // hash challenge with secret and convert to ascii
788 5cdb1798 2005-10-29 devnull s = md5((uchar*)chs->chal, chs->nchal, 0, 0);
789 5cdb1798 2005-10-29 devnull md5((uchar*)arg, strlen(arg), digest, s);
790 5cdb1798 2005-10-29 devnull snprint(response, sizeof response, "%.*H", MD5dlen, digest);
791 5cdb1798 2005-10-29 devnull return dologin(response);
792 5cdb1798 2005-10-29 devnull }
793 5cdb1798 2005-10-29 devnull
794 5cdb1798 2005-10-29 devnull static int
795 5cdb1798 2005-10-29 devnull apopcmd(char *arg)
796 5cdb1798 2005-10-29 devnull {
797 5cdb1798 2005-10-29 devnull char *resp;
798 5cdb1798 2005-10-29 devnull
799 5cdb1798 2005-10-29 devnull resp = nextarg(arg);
800 5cdb1798 2005-10-29 devnull if(setuser(arg) < 0)
801 5cdb1798 2005-10-29 devnull return -1;
802 5cdb1798 2005-10-29 devnull return dologin(resp);
803 5cdb1798 2005-10-29 devnull }
804 5cdb1798 2005-10-29 devnull