Fixed HTTP-client query-string handling bug.
[doldaconnect.git] / daemon / fnet-adc.c
1 /*
2  *  Dolda Connect - Modular multiuser Direct Connect-style client
3  *  Copyright (C) 2004 Fredrik Tolf <fredrik@dolda2000.com>
4  *  
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *  
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *  
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 */
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <unistd.h>
22 #include <fcntl.h>
23 #include <stdarg.h>
24 #include <string.h>
25 #include <netinet/in.h>
26 #include <arpa/inet.h>
27 #include <wctype.h>
28 #include <iconv.h>
29 #include <errno.h>
30
31 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
34 #include "filenet.h"
35 #include "log.h"
36 #include "module.h"
37 #include "utils.h"
38 #include "client.h"
39 #include "transfer.h"
40 #include "sysevents.h"
41 #include "net.h"
42 #include <tiger.h>
43
44 /* Protocol states */
45 #define ADC_PROTOCOL 0
46 #define ADC_IDENTIFY 1
47 #define ADC_VERIFY 2
48 #define ADC_NORMAL 3
49 #define ADC_DATA 4
50
51 struct command {
52     wchar_t *name;
53     int minargs, needsid, needsender;
54     void (*func)(struct fnetnode *fn, wchar_t *command, wchar_t *sender, int argc, wchar_t **argv);
55 };
56
57 struct qcmd {
58     struct qcmd *next;
59     wchar_t **args;
60 };
61
62 struct qcmdqueue {
63     struct qcmd *f, *l;
64     int size;
65 };
66
67 struct adchub {
68     struct socket *sk;
69     char *inbuf;
70     size_t inbufdata, inbufsize;
71     wchar_t *sid;
72     wchar_t *cb;
73     size_t cbdata, cbsize;
74     wchar_t **sup;
75     iconv_t ich;
76     int state;
77     struct wcspair *hubinf;
78     struct qcmdqueue queue;
79 };
80
81 static wchar_t *eoc, *ns, *fmt;
82 /* I've never understood why both of these are necessary, but... */
83 static wchar_t *privid, *cid;
84 struct socket *udpsock;
85 struct lport *tcpsock;
86
87 static wchar_t **parseadc(wchar_t *cmdline)
88 {
89     wchar_t **ret;
90     size_t retsize, retdata;
91     wchar_t *p, *p2, *ep;
92     wchar_t r;
93     ssize_t len;
94     
95     ret = NULL;
96     retsize = retdata = 0;
97     p = cmdline;
98     do {
99         if((p2 = wcschr(p, L' ')) != NULL)
100             *(p2++) = L'\0';
101         len = wcslen(p);
102         for(ep = p; len > 0; ep++, len--) {
103             if(*ep == L'\\') {
104                 if(ep[1] == L's') {
105                     r = L' ';
106                 } else if(ep[1] == L'n') {
107                     r = L'\n';
108                 } else if(ep[1] == L'\\') {
109                     r = L'\\';
110                 } else {
111                     memmove(ep, ep + 2, (len -= 2) * sizeof(*ep));
112                     ep--;
113                     continue;
114                 }
115                 memmove(ep, ep + 1, --len * sizeof(*ep));
116                 *ep = r;
117             }
118         }
119         *ep = L'\0';
120         addtobuf(ret, swcsdup(p));
121         p = p2;
122     } while(p2 != NULL);
123     addtobuf(ret, NULL);
124     return(ret);
125 }
126
127 static void sendeoc(struct socket *sk)
128 {
129     sockqueue(sk, "\n", 1);
130 }
131
132 static void sendadc1(struct socket *sk, int sep, wchar_t *arg)
133 {
134     char *mbsbuf;
135     wchar_t *buf;
136     size_t bufsize, bufdata;
137     
138     buf = NULL;
139     bufsize = bufdata = 0;
140     if(sep)
141         addtobuf(buf, L' ');
142     for(; *arg != L'\0'; arg++) {
143         if(*arg == L' ')
144             bufcat(buf, L"\\s", 2);
145         else if(*arg == L'\n')
146             bufcat(buf, L"\\n", 2);
147         else if(*arg == L'\\')
148             bufcat(buf, L"\\\\", 2);
149         else
150             addtobuf(buf, *arg);
151     }
152     addtobuf(buf, L'\0');
153     mbsbuf = icwcstombs(buf, "utf-8");
154     sockqueue(sk, mbsbuf, strlen(mbsbuf));
155     free(mbsbuf);
156 }
157
158 static void sendadc(struct socket *sk, int sep, ...)
159 {
160     int i;
161     va_list args;
162     wchar_t *arg;
163     wchar_t *type, *buf;
164     
165     va_start(args, sep);
166     for(i = 0; (arg = va_arg(args, wchar_t *)) != NULL; i++) {
167         if(arg == eoc) {
168             sendeoc(sk);
169         } else if(arg == ns) {
170             sep = 0;
171         } else if(arg == fmt) {
172             type = va_arg(args, wchar_t *);
173             if(!wcscmp(type, L"i")) {
174                 buf = swprintf2(L"%i", va_arg(args, int));
175             } else if(!wcscmp(type, L"mi")) {
176                 buf = swprintf2(L"%ji", va_arg(args, intmax_t));
177             }
178             sendadc1(sk, sep, buf);
179             free(buf);
180             sep = 1;
181         } else {
182             sendadc1(sk, sep, arg);
183             sep = 1;
184         }
185     }
186     va_end(args);
187 }
188
189 static wchar_t *findkv(wchar_t **argv, wchar_t *name)
190 {
191     while(*argv != NULL) {
192         if(!wcsncmp(*argv, name, 2))
193             return((*argv) + 2);
194     }
195     return(NULL);
196 }
197
198 static struct qcmd *newqcmd(struct qcmdqueue *queue, wchar_t **args)
199 {
200     struct qcmd *new;
201     
202     new = smalloc(sizeof(*new));
203     new->next = NULL;
204     new->args = args;
205     if(queue->l == NULL)
206         queue->f = new;
207     else
208         queue->l->next = new;
209     queue->l = new;
210     queue->size++;
211     return(new);
212 }
213
214 static struct qcmd *ulqcmd(struct qcmdqueue *queue)
215 {
216     struct qcmd *ret;
217     
218     if((ret = queue->f) == NULL)
219         return(NULL);
220     if((queue->f = ret->next) == NULL)
221         queue->l = NULL;
222     queue->size--;
223     return(ret);
224 }
225
226 static void freeqcmd(struct qcmd *qcmd)
227 {
228     freeparr(qcmd->args);
229     free(qcmd);
230 }
231
232 static void sendinf(struct fnetnode *fn)
233 {
234     struct adchub *hub = fn->data;
235     struct socket *sk = hub->sk;
236     struct sockaddr_in *a4;
237     socklen_t alen;
238     
239     sendadc(sk, 0, L"BINF", hub->sid, NULL);
240     sendadc(sk, 1, L"PD", ns, privid, L"ID", ns, cid, NULL);
241     sendadc(sk, 1, L"VEDolda ", ns, icsmbstowcs(VERSION, "us-ascii", NULL), NULL);
242     sendadc(sk, 1, L"NI", ns, fn->mynick, NULL);
243     sendadc(sk, 1, L"SS", ns, fmt, L"mi", (intmax_t)sharesize, L"SF", ns, fmt, L"i", sharedfiles, NULL);
244     if(sockfamily(sk) == AF_INET)
245         sendadc(sk, 1, L"I40.0.0.0", NULL);
246     else if(sockfamily(sk) == AF_INET6)
247         sendadc(sk, 1, L"I6::", NULL);
248     sendadc(sk, 1, L"SL", ns, fmt, L"i", confgetint("transfer", "slot"), NULL);
249     if(tcpsock != NULL) {
250         if((sockfamily(sk) == AF_INET) && !sockgetremotename(udpsock, (struct sockaddr **)&a4, &alen)) {
251             sendadc(sk, 1, L"U4", ns, fmt, L"i", ntohs(a4->sin_port), NULL);
252             free(a4);
253         }
254     }
255     sendadc(sk, 1, eoc, NULL);
256 }
257
258 #define ADC_CMDFN(name) static void name(struct fnetnode *fn, wchar_t *command, wchar_t *sender, int argc, wchar_t **argv)
259 #ifdef __GNUC__
260 #define UNUSED __attribute__ ((unused))
261 #else
262 #define UNUSED
263 #endif
264 #define ADC_CMDCOM \
265         struct adchub *hub UNUSED = fn->data; \
266         struct socket *sk UNUSED = hub->sk;
267
268 ADC_CMDFN(cmd_sup)
269 {
270     ADC_CMDCOM;
271     int i, o, f;
272     
273     for(i = 1; i < argc; i++) {
274         if(wcslen(argv[i]) < 3)
275             continue;
276         for(o = 0, f = 0; hub->sup[o]; o++) {
277             if(!wcscmp(argv[i] + 2, hub->sup[o])) {
278                 f = 1;
279                 break;
280             }
281         }
282         if(!wcsncmp(argv[i], L"AD", 2)) {
283             if(f)
284                 continue;
285             hub->sup = srealloc(hub->sup, sizeof(*(hub->sup)) * (o + 1));
286             hub->sup[o] = swcsdup(argv[i] + 2);
287         } else if(!wcsncmp(argv[i], L"RM", 2)) {
288             if(!f)
289                 continue;
290             free(hub->sup[o]);
291             memmove(hub->sup[o], hub->sup[o + 1], parrlen(hub->sup) - o);
292         }
293     }
294 }
295
296 ADC_CMDFN(cmd_sid)
297 {
298     ADC_CMDCOM;
299     
300     if(hub->sid != NULL)
301         free(hub->sid);
302     hub->sid = swcsdup(argv[1]);
303     if(hub->state == ADC_PROTOCOL) {
304         hub->state = ADC_IDENTIFY;
305         sendinf(fn);
306     }
307 }
308
309 ADC_CMDFN(cmd_inf)
310 {
311     ADC_CMDCOM;
312     wchar_t *p;
313     
314     if(sender == NULL) {
315         if((p = findkv(argv, L"NI")) != NULL)
316             fnetsetname(fn, p);
317     }
318 }
319
320 static struct command hubcmds[] = {
321     {L"SUP", 1, 0, 0, cmd_sup},
322     {L"SID", 2, 0, 0, cmd_sid},
323     {L"INF", 1, 0, 0, cmd_inf},
324     {NULL, 0, 0, 0, NULL}
325 };
326
327 static void dispatch(struct qcmd *qcmd, struct fnetnode *fn)
328 {
329     struct command *cmd;
330     int argc;
331     wchar_t *cmdnm, *sender, **argv;
332     
333     if((argc = parrlen(argv = qcmd->args)) < 1)
334         return;
335     cmdnm = *(argv++);
336     argc--;
337     if(wcslen(cmdnm) < 2)
338         return;
339     sender = NULL;
340     if((*cmdnm == L'B') || (*cmdnm == L'F')) {
341         if(argc < 1)
342             return;
343         sender = *(argv++);
344         argc--;
345     } else if((*cmdnm == L'D') || (*cmdnm == L'E')) {
346         if(argc < 2)
347             return;
348         sender = *argv;
349         argv += 2;
350         argc -= 2;
351     }
352     for(cmd = hubcmds; cmd->func != NULL; cmd++) {
353         if(!wcscmp(cmd->name, qcmd->args[0] + 1)) {
354             if(argc < cmd->minargs)
355                 return;
356             cmd->func(fn, cmdnm, sender, argc, argv);
357             return;
358         }
359     }
360     flog(LOG_DEBUG, "unknown adc command: %ls", qcmd->args[0]);
361 }
362
363 static void peeraccept(struct lport *lp, struct socket *newsk, void *uudata)
364 {
365 }
366
367 static void udpread(struct socket *sk, void *uudata)
368 {
369 }
370
371 static void hubread(struct socket *sk, struct fnetnode *fn)
372 {
373     int ret;
374     struct adchub *hub;
375     char *newbuf, *p1, *p2;
376     wchar_t *p;
377     size_t datalen, cblen;
378     
379     hub = fn->data;
380     if((newbuf = sockgetinbuf(sk, &datalen)) == NULL)
381         return;
382     if(hub->inbufdata > 1024)
383         hub->inbufdata = 0;
384     bufcat(hub->inbuf, newbuf, datalen);
385     free(newbuf);
386     /* Memory eating protection */
387     if(hub->cbdata > 65536)
388         hub->cbdata = 0;
389     while(hub->inbufdata > 0) {
390         if(hub->cbdata == hub->cbsize)
391             sizebuf2(hub->cb, hub->cbdata + datalen, 1);
392         p1 = hub->inbuf;
393         p2 = (char *)(hub->cb + hub->cbdata);
394         cblen = sizeof(*(hub->cb)) * (hub->cbsize - hub->cbdata);
395         ret = iconv(hub->ich, &p1, &hub->inbufdata, &p2, &cblen);
396         memmove(hub->inbuf, p1, hub->inbufdata);
397         if(((p2 - ((char *)hub->cb)) % sizeof(*hub->cb)) != 0) {
398             flog(LOG_CRIT, "Spotted a dismembered wchar_t!");
399             abort();
400         }
401         hub->cbdata = hub->cbsize - (cblen / sizeof(*(hub->cb)));
402         if(ret < 0) {
403             if(errno == EILSEQ) {
404                 flog(LOG_DEBUG, "adc fnetnode %i sent illegal utf-8 sequence", fn->id);
405                 killfnetnode(fn);
406                 return;
407             } else if(errno == EINVAL) {
408                 break;
409             } else if(errno == E2BIG) {
410                 /* continue; */
411             } else {
412                 flog(LOG_WARNING, "bug? iconv returned unexpected error: %s", strerror(errno));
413                 return;
414             }
415         }
416     }
417     while((p = wmemchr(hub->cb, L'\n', hub->cbdata)) != NULL) {
418         *(p++) = L'\0';
419         newqcmd(&hub->queue, parseadc(hub->cb));
420         memmove(hub->cb, p, (hub->cbdata -= (p - hub->cb)) * sizeof(*(hub->cb)));
421     }
422 }
423
424 static void huberr(struct socket *sk, int err, struct fnetnode *fn)
425 {
426     killfnetnode(fn);
427 }
428
429 static void hubconnect(struct fnetnode *fn, struct socket *sk)
430 {
431     struct adchub *hub;
432     
433     sk->readcb = (void (*)(struct socket *, void *))hubread;
434     sk->errcb = (void (*)(struct socket *, int, void *))huberr;
435     sk->data = fn;
436     
437     hub = smalloc(sizeof(*hub));
438     memset(hub, 0, sizeof(*hub));
439     getsock(hub->sk = sk);
440     if((hub->ich = iconv_open("wchar_t", "utf-8")) == (iconv_t)-1) {
441         flog(LOG_CRIT, "iconv cannot handle UTF-8: %s", strerror(errno));
442         killfnetnode(fn);
443         return;
444     }
445     fn->data = hub;
446     sendadc(sk, 0, L"HSUP", L"ADBASE", L"ADTIGR", eoc, NULL);
447 }
448
449 static void hubdestroy(struct fnetnode *fn)
450 {
451     struct adchub *hub;
452     
453     hub = fn->data;
454     iconv_close(hub->ich);
455     if(hub->inbuf != NULL)
456         free(hub->inbuf);
457     if(hub->sup != NULL)
458         freeparr(hub->sup);
459     free(hub);
460 }
461
462 static void hubkill(struct fnetnode *fn)
463 {
464     struct adchub *hub;
465     
466     hub = fn->data;
467     closesock(hub->sk);
468 }
469
470 static int hubsetnick(struct fnetnode *fn, wchar_t *newnick)
471 {
472     return(0);
473 }
474
475 static int hubreqconn(struct fnetpeer *peer)
476 {
477     return(0);
478 }
479
480 static struct fnet adcnet_store = {
481     .connect = hubconnect,
482     .destroy = hubdestroy,
483     .kill = hubkill,
484     .setnick = hubsetnick,
485     .reqconn = hubreqconn,
486     .name = L"adc"
487 };
488
489 static struct fnet *adcnet = &adcnet_store;
490
491 static int run(void)
492 {
493     int ret;
494     struct fnetnode *fn, *nextfn;
495     struct adchub *hub;
496     struct qcmd *qcmd;
497     
498     ret = 0;
499     for(fn = fnetnodes; fn != NULL; fn = nextfn) {
500         nextfn = fn->next;
501         if(fn->fnet != adcnet)
502             continue;
503         if((hub = fn->data) == NULL)
504             continue;
505         if((qcmd = ulqcmd(&hub->queue)) != NULL) {
506             if((hub->sk != NULL) && (hub->sk->state == SOCK_EST))
507                 dispatch(qcmd, fn);
508             freeqcmd(qcmd);
509             ret = 1;
510             break;
511         }
512     }
513     return(ret);
514 }
515
516 static void preinit(int hup)
517 {
518     if(hup)
519         return;
520     regfnet(adcnet);
521 }
522
523 static void makepid(char *idbuf)
524 {
525     int i;
526     int fd, ret;
527     
528     i = 0;
529     if((fd = open("/dev/urandom", O_RDONLY)) >= 0) {
530         for(i = 0; i < 24; i += ret) {
531             if((ret = read(fd, idbuf + i, 24 - i)) <= 0) {
532                 flog(LOG_WARNING, "could not read random data from /dev/urandom for ADC PID: %s", (errno == 0)?"EOF":strerror(errno));
533                 break;
534             }
535         }
536         close(fd);
537     } else {
538         flog(LOG_WARNING, "could not open /dev/urandom: %s", strerror(errno));
539     }
540     if(i != 24) {
541         for(i = 0; i < sizeof(idbuf); i++)
542             idbuf[i] = rand() % 256;
543     }
544 }
545
546 static int updateudpport(struct configvar *var, void *uudata)
547 {
548     struct sockaddr_in addr;
549     struct socket *newsock;
550     
551     memset(&addr, 0, sizeof(addr));
552     addr.sin_family = AF_INET;
553     addr.sin_port = htons(var->val.num);
554     if((newsock = netcsdgram((struct sockaddr *)&addr, sizeof(addr))) == NULL)
555     {
556         flog(LOG_WARNING, "could not create new DC UDP socket, reverting to old: %s", strerror(errno));
557         return(0);
558     }
559     newsock->readcb = udpread;
560     if(udpsock != NULL)
561         putsock(udpsock);
562     udpsock = newsock;
563     return(0);
564 }
565
566 static int updatetcpport(struct configvar *var, void *uudata)
567 {
568     struct sockaddr_in addr;
569     struct lport *newsock;
570     
571     memset(&addr, 0, sizeof(addr));
572     addr.sin_family = AF_INET;
573     addr.sin_port = htons(var->val.num);
574     if((newsock = netcslisten(SOCK_STREAM, (struct sockaddr *)&addr, sizeof(addr), peeraccept, NULL)) == NULL)
575         flog(LOG_INFO, "could not listen to a remote address, going into passive mode");
576     if(tcpsock != NULL)
577         closelport(tcpsock);
578     tcpsock = newsock;
579     return(0);
580 }
581
582 static int init(int hup)
583 {
584     char idbuf[24], *id32;
585     struct tigerhash th;
586     struct sockaddr_in addr;
587     
588     if(!hup) {
589         eoc = swcsdup(L"");
590         ns = swcsdup(L"");
591         fmt = swcsdup(L"");
592         
593         if((privid = fetchvar("adc.pid", NULL)) == NULL) {
594             makepid(idbuf);
595             id32 = base32encode(idbuf, sizeof(idbuf));
596             id32[39] = 0;
597             privid = icmbstowcs(id32, "us-ascii");
598             free(id32);
599             storevar("adc.pid", privid, sizeof(*privid) * (wcslen(privid) + 1));
600         }
601         
602         id32 = base32decode(icswcstombs(privid, "us-ascii", NULL), NULL);
603         inittiger(&th);
604         dotiger(&th, id32, 24);
605         synctiger(&th);
606         free(id32);
607         restiger(&th, idbuf);
608         id32 = base32encode(idbuf, sizeof(idbuf));
609         id32[39] = 0;
610         cid = icmbstowcs(id32, "us-ascii");
611         free(id32);
612         
613         memset(&addr, 0, sizeof(addr));
614         addr.sin_family = AF_INET;
615         addr.sin_port = htons(confgetint("adc", "udpport"));
616         if((udpsock = netcsdgram((struct sockaddr *)&addr, sizeof(addr))) == NULL) {
617             flog(LOG_CRIT, "could not create ADC UDP socket: %s", strerror(errno));
618             return(1);
619         }
620         udpsock->readcb = udpread;
621         addr.sin_port = htons(confgetint("adc", "tcpport"));
622         if((tcpsock = netcslisten(SOCK_STREAM, (struct sockaddr *)&addr, sizeof(addr), peeraccept, NULL)) == NULL) {
623             flog(LOG_CRIT, "could not create ADC TCP socket: %s", strerror(errno));
624             return(1);
625         }
626         CBREG(confgetvar("adc", "udpport"), conf_update, updateudpport, NULL, NULL);
627         CBREG(confgetvar("adc", "tcpport"), conf_update, updatetcpport, NULL, NULL);
628         CBREG(confgetvar("net", "mode"), conf_update, updatetcpport, NULL, NULL);
629     }
630     return(0);
631 }
632
633 static void terminate(void)
634 {
635     
636 }
637
638 static struct configvar myvars[] = {
639     /** Specifies a specific UDP port to use for ADC search
640      * results. If left unspecified, a port is allocated
641      * dynamically. Useful for NAT routers (see also the
642      * net.visibleipv4 address for those cases). */
643     {CONF_VAR_INT, "udpport", {.num = 0}},
644     /** Specifies a specific TCP port to use for ADC peer
645      * connections. If left unspecified, a port is allocated
646      * dynamically. Useful for NAT routers (see also the
647      * net.visibleipv4 address for those cases). */
648     {CONF_VAR_INT, "tcpport", {.num = 0}},
649     {CONF_VAR_END}
650 };
651
652 static struct module me = {
653     .conf = {
654         .vars = myvars
655     },
656     .preinit = preinit,
657     .init = init,
658     .run = run,
659     .terminate = terminate,
660     .name = "adc"
661 };
662
663 MODULE(me)