cgi: allow conf.cgi_docroot_path to be NULL
[project/uhttpd.git] / client.c
1 /*
2  * uhttpd - Tiny single-threaded httpd
3  *
4  *   Copyright (C) 2010-2013 Jo-Philipp Wich <xm@subsignal.org>
5  *   Copyright (C) 2013 Felix Fietkau <nbd@openwrt.org>
6  *
7  * Permission to use, copy, modify, and/or distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19
20 #include <libubox/blobmsg.h>
21 #include <ctype.h>
22
23 #include "uhttpd.h"
24 #include "tls.h"
25
26 static LIST_HEAD(clients);
27 static bool client_done = false;
28
29 int n_clients = 0;
30 struct config conf = {};
31
32 const char * const http_versions[] = {
33         [UH_HTTP_VER_0_9] = "HTTP/0.9",
34         [UH_HTTP_VER_1_0] = "HTTP/1.0",
35         [UH_HTTP_VER_1_1] = "HTTP/1.1",
36 };
37
38 const char * const http_methods[] = {
39         [UH_HTTP_MSG_GET] = "GET",
40         [UH_HTTP_MSG_POST] = "POST",
41         [UH_HTTP_MSG_HEAD] = "HEAD",
42         [UH_HTTP_MSG_OPTIONS] = "OPTIONS",
43 };
44
45 void uh_http_header(struct client *cl, int code, const char *summary)
46 {
47         struct http_request *r = &cl->request;
48         struct blob_attr *cur;
49         const char *enc = "Transfer-Encoding: chunked\r\n";
50         const char *conn;
51         int rem;
52
53         cl->http_code = code;
54
55         if (!uh_use_chunked(cl))
56                 enc = "";
57
58         if (r->connection_close)
59                 conn = "Connection: close";
60         else
61                 conn = "Connection: Keep-Alive";
62
63         ustream_printf(cl->us, "%s %03i %s\r\n%s\r\n%s",
64                 http_versions[cl->request.version],
65                 code, summary, conn, enc);
66
67         if (!r->connection_close)
68                 ustream_printf(cl->us, "Keep-Alive: timeout=%d\r\n", conf.http_keepalive);
69
70         blobmsg_for_each_attr(cur, cl->hdr_response.head, rem)
71                 ustream_printf(cl->us, "%s: %s\r\n", blobmsg_name(cur),
72                                blobmsg_get_string(cur));
73 }
74
75 static void uh_connection_close(struct client *cl)
76 {
77         cl->state = CLIENT_STATE_CLOSE;
78         cl->us->eof = true;
79         ustream_state_change(cl->us);
80 }
81
82 static void uh_dispatch_done(struct client *cl)
83 {
84         if (cl->dispatch.free)
85                 cl->dispatch.free(cl);
86         if (cl->dispatch.req_free)
87                 cl->dispatch.req_free(cl);
88 }
89
90 static void client_timeout(struct uloop_timeout *timeout)
91 {
92         struct client *cl = container_of(timeout, struct client, timeout);
93
94         cl->state = CLIENT_STATE_CLOSE;
95         uh_connection_close(cl);
96 }
97
98 static void uh_set_client_timeout(struct client *cl, int timeout)
99 {
100         cl->timeout.cb = client_timeout;
101         uloop_timeout_set(&cl->timeout, timeout * 1000);
102 }
103
104 static void uh_keepalive_poll_cb(struct uloop_timeout *timeout)
105 {
106         struct client *cl = container_of(timeout, struct client, timeout);
107         int sec = cl->requests > 0 ? conf.http_keepalive : conf.network_timeout;
108
109         uh_set_client_timeout(cl, sec);
110         cl->us->notify_read(cl->us, 0);
111 }
112
113 static void uh_poll_connection(struct client *cl)
114 {
115         cl->timeout.cb = uh_keepalive_poll_cb;
116         uloop_timeout_set(&cl->timeout, 1);
117 }
118
119 void uh_request_done(struct client *cl)
120 {
121         uh_chunk_eof(cl);
122         uh_dispatch_done(cl);
123         blob_buf_init(&cl->hdr_response, 0);
124         memset(&cl->dispatch, 0, sizeof(cl->dispatch));
125
126         if (!conf.http_keepalive || cl->request.connection_close)
127                 return uh_connection_close(cl);
128
129         cl->state = CLIENT_STATE_INIT;
130         cl->requests++;
131         uh_poll_connection(cl);
132 }
133
134 void __printf(4, 5)
135 uh_client_error(struct client *cl, int code, const char *summary, const char *fmt, ...)
136 {
137         va_list arg;
138
139         uh_http_header(cl, code, summary);
140         ustream_printf(cl->us, "Content-Type: text/html\r\n\r\n");
141
142         uh_chunk_printf(cl, "<h1>%s</h1>", summary);
143
144         if (fmt) {
145                 va_start(arg, fmt);
146                 uh_chunk_vprintf(cl, fmt, arg);
147                 va_end(arg);
148         }
149
150         uh_request_done(cl);
151 }
152
153 static void uh_header_error(struct client *cl, int code, const char *summary)
154 {
155         uh_client_error(cl, code, summary, NULL);
156         uh_connection_close(cl);
157 }
158
159 static int find_idx(const char * const *list, int max, const char *str)
160 {
161         int i;
162
163         for (i = 0; i < max; i++)
164                 if (!strcmp(list[i], str))
165                         return i;
166
167         return -1;
168 }
169
170 static int client_parse_request(struct client *cl, char *data)
171 {
172         struct http_request *req = &cl->request;
173         char *type, *path, *version;
174         int h_method, h_version;
175
176         type = strtok(data, " ");
177         path = strtok(NULL, " ");
178         version = strtok(NULL, " ");
179         if (!type || !path || !version)
180                 return CLIENT_STATE_DONE;
181
182         blobmsg_add_string(&cl->hdr, "URL", path);
183
184         memset(&cl->request, 0, sizeof(cl->request));
185         h_method = find_idx(http_methods, ARRAY_SIZE(http_methods), type);
186         h_version = find_idx(http_versions, ARRAY_SIZE(http_versions), version);
187         if (h_method < 0 || h_version < 0) {
188                 req->version = UH_HTTP_VER_1_0;
189                 return CLIENT_STATE_DONE;
190         }
191
192         req->method = h_method;
193         req->version = h_version;
194         if (req->version < UH_HTTP_VER_1_1 || req->method == UH_HTTP_MSG_POST ||
195             !conf.http_keepalive)
196                 req->connection_close = true;
197
198         return CLIENT_STATE_HEADER;
199 }
200
201 static bool client_init_cb(struct client *cl, char *buf, int len)
202 {
203         char *newline;
204
205         newline = strstr(buf, "\r\n");
206         if (!newline)
207                 return false;
208
209         if (newline == buf) {
210                 ustream_consume(cl->us, 2);
211                 return true;
212         }
213
214         *newline = 0;
215         blob_buf_init(&cl->hdr, 0);
216         cl->state = client_parse_request(cl, buf);
217         ustream_consume(cl->us, newline + 2 - buf);
218         if (cl->state == CLIENT_STATE_DONE)
219                 uh_header_error(cl, 400, "Bad Request");
220
221         return true;
222 }
223
224 static bool rfc1918_filter_check(struct client *cl)
225 {
226         if (!conf.rfc1918_filter)
227                 return true;
228
229         if (!uh_addr_rfc1918(&cl->peer_addr) || uh_addr_rfc1918(&cl->srv_addr))
230                 return true;
231
232         uh_client_error(cl, 403, "Forbidden",
233                         "Rejected request from RFC1918 IP "
234                         "to public server address");
235         return false;
236 }
237
238 static bool tls_redirect_check(struct client *cl)
239 {
240         int rem, port;
241         struct blob_attr *cur;
242         char *ptr, *url = NULL, *host = NULL;
243
244         if (cl->tls || !conf.tls_redirect)
245                 return true;
246
247         if ((port = uh_first_tls_port(cl->srv_addr.family)) == -1)
248                 return true;
249
250         blob_for_each_attr(cur, cl->hdr.head, rem) {
251                 if (!strcmp(blobmsg_name(cur), "host"))
252                         host = blobmsg_get_string(cur);
253
254                 if (!strcmp(blobmsg_name(cur), "URL"))
255                         url = blobmsg_get_string(cur);
256
257                 if (url && host)
258                         break;
259         }
260
261         if (!url || !host)
262                 return true;
263
264         if ((ptr = strchr(host, ']')) != NULL)
265                 *(ptr+1) = 0;
266         else if ((ptr = strchr(host, ':')) != NULL)
267                 *ptr = 0;
268
269         cl->request.disable_chunked = true;
270         cl->request.connection_close = true;
271
272         uh_http_header(cl, 307, "Temporary Redirect");
273
274         if (port != 443)
275                 ustream_printf(cl->us, "Location: https://%s:%d%s\r\n\r\n", host, port, url);
276         else
277                 ustream_printf(cl->us, "Location: https://%s%s\r\n\r\n", host, url);
278
279         uh_request_done(cl);
280
281         return false;
282 }
283
284 static void client_header_complete(struct client *cl)
285 {
286         struct http_request *r = &cl->request;
287
288         if (!rfc1918_filter_check(cl))
289                 return;
290
291         if (!tls_redirect_check(cl))
292                 return;
293
294         if (r->expect_cont)
295                 ustream_printf(cl->us, "HTTP/1.1 100 Continue\r\n\r\n");
296
297         switch(r->ua) {
298         case UH_UA_MSIE_OLD:
299                 if (r->method != UH_HTTP_MSG_POST)
300                         break;
301
302                 /* fall through */
303         case UH_UA_SAFARI:
304                 r->connection_close = true;
305                 break;
306         default:
307                 break;
308         }
309
310         uh_handle_request(cl);
311 }
312
313 static void client_parse_header(struct client *cl, char *data)
314 {
315         struct http_request *r = &cl->request;
316         char *err;
317         char *name;
318         char *val;
319
320         if (!*data) {
321                 uloop_timeout_cancel(&cl->timeout);
322                 cl->state = CLIENT_STATE_DATA;
323                 client_header_complete(cl);
324                 return;
325         }
326
327         val = uh_split_header(data);
328         if (!val) {
329                 cl->state = CLIENT_STATE_DONE;
330                 return;
331         }
332
333         for (name = data; *name; name++)
334                 if (isupper(*name))
335                         *name = tolower(*name);
336
337         if (!strcmp(data, "expect")) {
338                 if (!strcasecmp(val, "100-continue"))
339                         r->expect_cont = true;
340                 else {
341                         uh_header_error(cl, 412, "Precondition Failed");
342                         return;
343                 }
344         } else if (!strcmp(data, "content-length")) {
345                 r->content_length = strtoul(val, &err, 0);
346                 if (err && *err) {
347                         uh_header_error(cl, 400, "Bad Request");
348                         return;
349                 }
350         } else if (!strcmp(data, "transfer-encoding")) {
351                 if (!strcmp(val, "chunked"))
352                         r->transfer_chunked = true;
353         } else if (!strcmp(data, "connection")) {
354                 if (!strcasecmp(val, "close"))
355                         r->connection_close = true;
356         } else if (!strcmp(data, "user-agent")) {
357                 char *str;
358
359                 if (strstr(val, "Opera"))
360                         r->ua = UH_UA_OPERA;
361                 else if ((str = strstr(val, "MSIE ")) != NULL) {
362                         r->ua = UH_UA_MSIE_NEW;
363                         if (str[5] && str[6] == '.') {
364                                 switch (str[5]) {
365                                 case '6':
366                                         if (strstr(str, "SV1"))
367                                                 break;
368                                         /* fall through */
369                                 case '5':
370                                 case '4':
371                                         r->ua = UH_UA_MSIE_OLD;
372                                         break;
373                                 }
374                         }
375                 }
376                 else if (strstr(val, "Chrome/"))
377                         r->ua = UH_UA_CHROME;
378                 else if (strstr(val, "Safari/") && strstr(val, "Mac OS X"))
379                         r->ua = UH_UA_SAFARI;
380                 else if (strstr(val, "Gecko/"))
381                         r->ua = UH_UA_GECKO;
382                 else if (strstr(val, "Konqueror"))
383                         r->ua = UH_UA_KONQUEROR;
384         }
385
386
387         blobmsg_add_string(&cl->hdr, data, val);
388
389         cl->state = CLIENT_STATE_HEADER;
390 }
391
392 void client_poll_post_data(struct client *cl)
393 {
394         struct dispatch *d = &cl->dispatch;
395         struct http_request *r = &cl->request;
396         char *buf;
397         int len;
398
399         if (cl->state == CLIENT_STATE_DONE)
400                 return;
401
402         while (1) {
403                 char *sep;
404                 int offset = 0;
405                 int cur_len;
406
407                 buf = ustream_get_read_buf(cl->us, &len);
408                 if (!buf || !len)
409                         break;
410
411                 if (!d->data_send)
412                         return;
413
414                 cur_len = min(r->content_length, len);
415                 if (cur_len) {
416                         if (d->data_blocked)
417                                 break;
418
419                         if (d->data_send)
420                                 cur_len = d->data_send(cl, buf, cur_len);
421
422                         r->content_length -= cur_len;
423                         ustream_consume(cl->us, cur_len);
424                         continue;
425                 }
426
427                 if (!r->transfer_chunked)
428                         break;
429
430                 if (r->transfer_chunked > 1)
431                         offset = 2;
432
433                 sep = strstr(buf + offset, "\r\n");
434                 if (!sep)
435                         break;
436
437                 *sep = 0;
438
439                 r->content_length = strtoul(buf + offset, &sep, 16);
440                 r->transfer_chunked++;
441                 ustream_consume(cl->us, sep + 2 - buf);
442
443                 /* invalid chunk length */
444                 if (sep && *sep) {
445                         r->content_length = 0;
446                         r->transfer_chunked = 0;
447                         break;
448                 }
449
450                 /* empty chunk == eof */
451                 if (!r->content_length) {
452                         r->transfer_chunked = false;
453                         break;
454                 }
455         }
456
457         buf = ustream_get_read_buf(cl->us, &len);
458         if (!r->content_length && !r->transfer_chunked &&
459                 cl->state != CLIENT_STATE_DONE) {
460                 if (cl->dispatch.data_done)
461                         cl->dispatch.data_done(cl);
462
463                 cl->state = CLIENT_STATE_DONE;
464         }
465 }
466
467 static bool client_data_cb(struct client *cl, char *buf, int len)
468 {
469         client_poll_post_data(cl);
470         return false;
471 }
472
473 static bool client_header_cb(struct client *cl, char *buf, int len)
474 {
475         char *newline;
476         int line_len;
477
478         newline = strstr(buf, "\r\n");
479         if (!newline)
480                 return false;
481
482         *newline = 0;
483         client_parse_header(cl, buf);
484         line_len = newline + 2 - buf;
485         ustream_consume(cl->us, line_len);
486         if (cl->state == CLIENT_STATE_DATA)
487                 return client_data_cb(cl, newline + 2, len - line_len);
488
489         return true;
490 }
491
492 typedef bool (*read_cb_t)(struct client *cl, char *buf, int len);
493 static read_cb_t read_cbs[] = {
494         [CLIENT_STATE_INIT] = client_init_cb,
495         [CLIENT_STATE_HEADER] = client_header_cb,
496         [CLIENT_STATE_DATA] = client_data_cb,
497 };
498
499 void uh_client_read_cb(struct client *cl)
500 {
501         struct ustream *us = cl->us;
502         char *str;
503         int len;
504
505         client_done = false;
506         do {
507                 str = ustream_get_read_buf(us, &len);
508                 if (!str || !len)
509                         break;
510
511                 if (cl->state >= array_size(read_cbs) || !read_cbs[cl->state])
512                         break;
513
514                 if (!read_cbs[cl->state](cl, str, len)) {
515                         if (len == us->r.buffer_len &&
516                             cl->state != CLIENT_STATE_DATA)
517                                 uh_header_error(cl, 413, "Request Entity Too Large");
518                         break;
519                 }
520         } while (!client_done);
521 }
522
523 static void client_close(struct client *cl)
524 {
525         if (cl->refcount) {
526                 cl->state = CLIENT_STATE_CLEANUP;
527                 return;
528         }
529
530         client_done = true;
531         n_clients--;
532         uh_dispatch_done(cl);
533         uloop_timeout_cancel(&cl->timeout);
534         if (cl->tls)
535                 uh_tls_client_detach(cl);
536         ustream_free(&cl->sfd.stream);
537         close(cl->sfd.fd.fd);
538         list_del(&cl->list);
539         blob_buf_free(&cl->hdr);
540         blob_buf_free(&cl->hdr_response);
541         free(cl);
542
543         uh_unblock_listeners();
544 }
545
546 void uh_client_notify_state(struct client *cl)
547 {
548         struct ustream *s = cl->us;
549
550         if (!s->write_error && cl->state != CLIENT_STATE_CLEANUP) {
551                 if (cl->state == CLIENT_STATE_DATA)
552                         return;
553
554                 if (!s->eof || s->w.data_bytes)
555                         return;
556         }
557
558         return client_close(cl);
559 }
560
561 static void client_ustream_read_cb(struct ustream *s, int bytes)
562 {
563         struct client *cl = container_of(s, struct client, sfd.stream);
564
565         uh_client_read_cb(cl);
566 }
567
568 static void client_ustream_write_cb(struct ustream *s, int bytes)
569 {
570         struct client *cl = container_of(s, struct client, sfd.stream);
571
572         if (cl->dispatch.write_cb)
573                 cl->dispatch.write_cb(cl);
574 }
575
576 static void client_notify_state(struct ustream *s)
577 {
578         struct client *cl = container_of(s, struct client, sfd.stream);
579
580         uh_client_notify_state(cl);
581 }
582
583 static void set_addr(struct uh_addr *addr, void *src)
584 {
585         struct sockaddr_in *sin = src;
586         struct sockaddr_in6 *sin6 = src;
587
588         addr->family = sin->sin_family;
589         if (addr->family == AF_INET) {
590                 addr->port = ntohs(sin->sin_port);
591                 memcpy(&addr->in, &sin->sin_addr, sizeof(addr->in));
592         } else {
593                 addr->port = ntohs(sin6->sin6_port);
594                 memcpy(&addr->in6, &sin6->sin6_addr, sizeof(addr->in6));
595         }
596 }
597
598 bool uh_accept_client(int fd, bool tls)
599 {
600         static struct client *next_client;
601         struct client *cl;
602         unsigned int sl;
603         int sfd;
604         static int client_id = 0;
605         struct sockaddr_in6 addr;
606
607         if (!next_client)
608                 next_client = calloc(1, sizeof(*next_client));
609
610         cl = next_client;
611
612         sl = sizeof(addr);
613         sfd = accept(fd, (struct sockaddr *) &addr, &sl);
614         if (sfd < 0)
615                 return false;
616
617         set_addr(&cl->peer_addr, &addr);
618         sl = sizeof(addr);
619         getsockname(sfd, (struct sockaddr *) &addr, &sl);
620         set_addr(&cl->srv_addr, &addr);
621
622         cl->us = &cl->sfd.stream;
623         if (tls) {
624                 uh_tls_client_attach(cl);
625         } else {
626                 cl->us->notify_read = client_ustream_read_cb;
627                 cl->us->notify_write = client_ustream_write_cb;
628                 cl->us->notify_state = client_notify_state;
629         }
630
631         cl->us->string_data = true;
632         ustream_fd_init(&cl->sfd, sfd);
633
634         uh_poll_connection(cl);
635         list_add_tail(&cl->list, &clients);
636
637         next_client = NULL;
638         n_clients++;
639         cl->id = client_id++;
640         cl->tls = tls;
641
642         return true;
643 }
644
645 void uh_close_fds(void)
646 {
647         struct client *cl;
648
649         uloop_done();
650         uh_close_listen_fds();
651         list_for_each_entry(cl, &clients, list) {
652                 close(cl->sfd.fd.fd);
653                 if (cl->dispatch.close_fds)
654                         cl->dispatch.close_fds(cl);
655         }
656 }