version 0.2.1
[fms.git] / libs / shttpd / shttpd.c
1 /*
2  * Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
3  * All rights reserved
4  *
5  * "THE BEER-WARE LICENSE" (Revision 42):
6  * Sergey Lyubka wrote this file.  As long as you retain this notice you
7  * can do whatever you want with this stuff. If we meet some day, and you think
8  * this stuff is worth it, you can buy me a beer in return.
9  */
10
11 /*
12  * Small and portable HTTP server, http://shttpd.sourceforge.net
13  * $Id: shttpd.c,v 1.28 2008/02/17 21:45:09 drozd Exp $
14  */
15
16 #include "defs.h"
17
18 time_t          current_time;   /* Current UTC time             */
19 int             tz_offset;      /* Time zone offset from UTC    */
20
21 const struct vec known_http_methods[] = {
22         {"GET",         3},
23         {"POST",        4},
24         {"PUT",         3},
25         {"DELETE",      6},
26         {"HEAD",        4},
27         {NULL,          0}
28 };
29
30 struct listener {
31         struct llhead   link;
32         struct shttpd_ctx *ctx;         /* Context that socket belongs  */
33         int             sock;           /* Listening socket             */
34         int             is_ssl;         /* Should be SSL-ed             */
35 };
36
37 /*
38  * This structure tells how HTTP headers must be parsed.
39  * Used by parse_headers() function.
40  */
41 #define OFFSET(x)       offsetof(struct headers, x)
42 static const struct http_header http_headers[] = {
43         {16, HDR_INT,    OFFSET(cl),            "Content-Length: "      },
44         {14, HDR_STRING, OFFSET(ct),            "Content-Type: "        },
45         {12, HDR_STRING, OFFSET(useragent),     "User-Agent: "          },
46         {19, HDR_DATE,   OFFSET(ims),           "If-Modified-Since: "   },
47         {15, HDR_STRING, OFFSET(auth),          "Authorization: "       },
48         {9,  HDR_STRING, OFFSET(referer),       "Referer: "             },
49         {8,  HDR_STRING, OFFSET(cookie),        "Cookie: "              },
50         {10, HDR_STRING, OFFSET(location),      "Location: "            },
51         {8,  HDR_INT,    OFFSET(status),        "Status: "              },
52         {7,  HDR_STRING, OFFSET(range),         "Range: "               },
53         {12, HDR_STRING, OFFSET(connection),    "Connection: "          },
54         {19, HDR_STRING, OFFSET(transenc),      "Transfer-Encoding: "   },
55         {0,  HDR_INT,    0,                     NULL                    }
56 };
57
58 struct shttpd_ctx *init_ctx(const char *config_file, int argc, char *argv[]);
59 static void process_connection(struct conn *, int, int);
60
61 int
62 url_decode(const char *src, int src_len, char *dst, int dst_len)
63 {
64         int     i, j, a, b;
65 #define HEXTOI(x)  (isdigit(x) ? x - '0' : x - 'W')
66
67         for (i = j = 0; i < src_len && j < dst_len - 1; i++, j++)
68                 switch (src[i]) {
69                 case '%':
70                         if (isxdigit(((unsigned char *) src)[i + 1]) &&
71                             isxdigit(((unsigned char *) src)[i + 2])) {
72                                 a = tolower(((unsigned char *)src)[i + 1]);
73                                 b = tolower(((unsigned char *)src)[i + 2]);
74                                 dst[j] = (HEXTOI(a) << 4) | HEXTOI(b);
75                                 i += 2;
76                         } else {
77                                 dst[j] = '%';
78                         }
79                         break;
80                 default:
81                         dst[j] = src[i];
82                         break;
83                 }
84
85         dst[j] = '\0';  /* Null-terminate the destination */
86
87         return (j);
88 }
89
90 static const char *
91 is_alias(struct shttpd_ctx *ctx, const char *uri,
92                 struct vec *a_uri, struct vec *a_path)
93 {
94         const char      *p, *s = ctx->options[OPT_ALIASES];
95         size_t          len;
96
97         DBG(("is_alias: aliases [%s]", s == NULL ? "" : s));
98
99         FOR_EACH_WORD_IN_LIST(s, len) {
100
101                 if ((p = memchr(s, '=', len)) == NULL || p >= s + len || p == s)
102                         continue;
103
104                 if (memcmp(uri, s, p - s) == 0) {
105                         a_uri->ptr = s;
106                         a_uri->len = p - s;
107                         a_path->ptr = ++p;
108                         a_path->len = (s + len) - p;
109                         return (s);
110                 }
111         }
112
113         return (NULL);
114 }
115
116 void
117 stop_stream(struct stream *stream)
118 {
119         if (stream->io_class != NULL && stream->io_class->close != NULL)
120                 stream->io_class->close(stream);
121
122         stream->io_class= NULL;
123         stream->flags |= FLAG_CLOSED;
124         stream->flags &= ~(FLAG_R | FLAG_W | FLAG_ALWAYS_READY);
125
126         DBG(("%d %s stopped. %lu of content data, %d now in a buffer",
127             stream->conn->rem.chan.sock, 
128             stream->io_class ? stream->io_class->name : "(null)",
129             (unsigned long) stream->io.total, io_data_len(&stream->io)));
130 }
131
132 /*
133  * Setup listening socket on given port, return socket
134  */
135 static int
136 open_listening_port(int port)
137 {
138         int             sock, on = 1;
139         struct usa      sa;
140
141 #ifdef _WIN32
142         {WSADATA data;  WSAStartup(MAKEWORD(2,2), &data);}
143 #endif /* _WIN32 */
144
145         sa.len                          = sizeof(sa.u.sin);
146         sa.u.sin.sin_family             = AF_INET;
147         sa.u.sin.sin_port               = htons((uint16_t) port);
148         sa.u.sin.sin_addr.s_addr        = htonl(INADDR_ANY);
149
150         if ((sock = socket(PF_INET, SOCK_STREAM, 6)) == -1)
151                 goto fail;
152         if (set_non_blocking_mode(sock) != 0)
153                 goto fail;
154         if (setsockopt(sock, SOL_SOCKET,
155             SO_REUSEADDR,(char *) &on, sizeof(on)) != 0)
156                 goto fail;
157         if (bind(sock, &sa.u.sa, sa.len) < 0)
158                 goto fail;
159         if (listen(sock, 128) != 0)
160                 goto fail;
161
162 #ifndef _WIN32
163         (void) fcntl(sock, F_SETFD, FD_CLOEXEC);
164 #endif /* !_WIN32 */
165
166         return (sock);
167 fail:
168         if (sock != -1)
169                 (void) closesocket(sock);
170         elog(E_LOG, NULL, "open_listening_port(%d): %s", port, strerror(errno));
171         return (-1);
172 }
173
174 /*
175  * Check whether full request is buffered Return headers length, or 0
176  */
177 int
178 get_headers_len(const char *buf, size_t buflen)
179 {
180         const char      *s, *e;
181         int             len = 0;
182
183         for (s = buf, e = s + buflen - 1; len == 0 && s < e; s++)
184                 /* Control characters are not allowed but >=128 is. */
185                 if (!isprint(* (unsigned char *) s) && *s != '\r' &&
186                     *s != '\n' && * (unsigned char *) s < 128)
187                         len = -1;
188                 else if (s[0] == '\n' && s[1] == '\n')
189                         len = s - buf + 2;
190                 else if (s[0] == '\n' && &s[1] < e &&
191                     s[1] == '\r' && s[2] == '\n')
192                         len = s - buf + 3;
193
194         return (len);
195 }
196
197 /*
198  * Send error message back to a client.
199  */
200 void
201 send_server_error(struct conn *c, int status, const char *reason)
202 {
203         struct llhead           *lp;
204         struct error_handler    *e;
205
206         LL_FOREACH(&c->ctx->error_handlers, lp) {
207                 e = LL_ENTRY(lp, struct error_handler, link);
208
209                 if (e->code == status) {
210                         if (c->loc.io_class != NULL &&
211                             c->loc.io_class->close != NULL)
212                                 c->loc.io_class->close(&c->loc);
213                         io_clear(&c->loc.io);
214                         setup_embedded_stream(c, e->callback, e->callback_data);
215                         return;
216                 }
217         }
218
219         io_clear(&c->loc.io);
220         c->loc.io.head = my_snprintf(c->loc.io.buf, c->loc.io.size,
221             "HTTP/1.1 %d %s\r\n"
222             "Content-Type: text/plain\r\n"
223             "Content-Length: 12\r\n"
224             "\r\n"
225             "Error: %03d\r\n",
226             status, reason, status);
227         c->loc.content_len = 10;
228         c->status = status;
229         stop_stream(&c->loc);
230 }
231
232 /*
233  * Convert month to the month number. Return -1 on error, or month number
234  */
235 static int
236 montoi(const char *s)
237 {
238         static const char *ar[] = {
239                 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
240                 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
241         };
242         size_t  i;
243
244         for (i = 0; i < sizeof(ar) / sizeof(ar[0]); i++)
245                 if (!strcmp(s, ar[i]))
246                         return (i);
247
248         return (-1);
249 }
250
251 /*
252  * Parse date-time string, and return the corresponding time_t value
253  */
254 static time_t
255 date_to_epoch(const char *s)
256 {
257         struct tm       tm, *tmp;
258         char            mon[32];
259         int             sec, min, hour, mday, month, year;
260
261         (void) memset(&tm, 0, sizeof(tm));
262         sec = min = hour = mday = month = year = 0;
263
264         if (((sscanf(s, "%d/%3s/%d %d:%d:%d",
265             &mday, mon, &year, &hour, &min, &sec) == 6) ||
266             (sscanf(s, "%d %3s %d %d:%d:%d",
267             &mday, mon, &year, &hour, &min, &sec) == 6) ||
268             (sscanf(s, "%*3s, %d %3s %d %d:%d:%d",
269             &mday, mon, &year, &hour, &min, &sec) == 6) ||
270             (sscanf(s, "%d-%3s-%d %d:%d:%d",
271             &mday, mon, &year, &hour, &min, &sec) == 6)) &&
272             (month = montoi(mon)) != -1) {
273                 tm.tm_mday      = mday;
274                 tm.tm_mon       = month;
275                 tm.tm_year      = year;
276                 tm.tm_hour      = hour;
277                 tm.tm_min       = min;
278                 tm.tm_sec       = sec;
279         }
280
281         if (tm.tm_year > 1900)
282                 tm.tm_year -= 1900;
283         else if (tm.tm_year < 70)
284                 tm.tm_year += 100;
285
286         /* Set Daylight Saving Time field */
287         tmp = localtime(&current_time);
288         tm.tm_isdst = tmp->tm_isdst;
289
290         return (mktime(&tm));
291 }
292
293 static void
294 remove_double_dots(char *s)
295 {
296         char    *p = s;
297
298         while (*s != '\0') {
299                 *p++ = *s++;
300                 if (s[-1] == '/' || s[-1] == '\\')
301                         while (*s == '.' || *s == '/' || *s == '\\')
302                                 s++;
303         }
304         *p = '\0';
305 }
306
307 void
308 parse_headers(const char *s, int len, struct headers *parsed)
309 {
310         const struct http_header        *h;
311         union variant                   *v;
312         const char                      *p, *e = s + len;
313
314         DBG(("parsing headers (len %d): [%.*s]", len, len, s));
315
316         /* Loop through all headers in the request */
317         while (s < e) {
318
319                 /* Find where this header ends */
320                 for (p = s; p < e && *p != '\n'; ) p++;
321
322                 /* Is this header known to us ? */
323                 for (h = http_headers; h->len != 0; h++)
324                         if (e - s > h->len &&
325                             !my_strncasecmp(s, h->name, h->len))
326                                 break;
327
328                 /* If the header is known to us, store its value */
329                 if (h->len != 0) {
330
331                         /* Shift to where value starts */
332                         s += h->len;
333
334                         /* Find place to store the value */
335                         v = (union variant *) ((char *) parsed + h->offset);
336
337                         /* Fetch header value into the connection structure */
338                         if (h->type == HDR_STRING) {
339                                 v->v_vec.ptr = s;
340                                 v->v_vec.len = p - s;
341                                 if (p[-1] == '\r' && v->v_vec.len > 0)
342                                         v->v_vec.len--;
343                         } else if (h->type == HDR_INT) {
344                                 v->v_big_int = strtoul(s, NULL, 10);
345                         } else if (h->type == HDR_DATE) {
346                                 v->v_time = date_to_epoch(s);
347                         }
348                 }
349
350                 s = p + 1;      /* Shift to the next header */
351         }
352 }
353
354 static const struct {
355         const char      *extension;
356         int             ext_len;
357         const char      *mime_type;
358 } builtin_mime_types[] = {
359         {"html",        4,      "text/html"                     },
360         {"htm",         3,      "text/html"                     },
361         {"txt",         3,      "text/plain"                    },
362         {"css",         3,      "text/css"                      },
363         {"ico",         3,      "image/x-icon"                  },
364         {"gif",         3,      "image/gif"                     },
365         {"jpg",         3,      "image/jpeg"                    },
366         {"jpeg",        4,      "image/jpeg"                    },
367         {"png",         3,      "image/png"                     },
368         {"svg",         3,      "image/svg+xml"                 },
369         {"torrent",     7,      "application/x-bittorrent"      },
370         {"wav",         3,      "audio/x-wav"                   },
371         {"mp3",         3,      "audio/x-mp3"                   },
372         {"mid",         3,      "audio/mid"                     },
373         {"m3u",         3,      "audio/x-mpegurl"               },
374         {"ram",         3,      "audio/x-pn-realaudio"          },
375         {"ra",          2,      "audio/x-pn-realaudio"          },
376         {"doc",         3,      "application/msword",           },
377         {"exe",         3,      "application/octet-stream"      },
378         {"zip",         3,      "application/x-zip-compressed"  },
379         {"xls",         3,      "application/excel"             },
380         {"tgz",         3,      "application/x-tar-gz"          },
381         {"tar.gz",      6,      "application/x-tar-gz"          },
382         {"tar",         3,      "application/x-tar"             },
383         {"gz",          2,      "application/x-gunzip"          },
384         {"arj",         3,      "application/x-arj-compressed"  },
385         {"rar",         3,      "application/x-arj-compressed"  },
386         {"rtf",         3,      "application/rtf"               },
387         {"pdf",         3,      "application/pdf"               },
388         {"swf",         3,      "application/x-shockwave-flash" },
389         {"mpg",         3,      "video/mpeg"                    },
390         {"mpeg",        4,      "video/mpeg"                    },
391         {"asf",         3,      "video/x-ms-asf"                },
392         {"avi",         3,      "video/x-msvideo"               },
393         {"bmp",         3,      "image/bmp"                     },
394         {NULL,          0,      NULL                            }
395 };
396
397 void
398 get_mime_type(struct shttpd_ctx *ctx, const char *uri, int len, struct vec *vec)
399 {
400         const char      *eq, *p = ctx->options[OPT_MIME_TYPES];
401         int             i, n, ext_len;
402
403         /* Firt, loop through the custom mime types if any */
404         FOR_EACH_WORD_IN_LIST(p, n) {
405                 if ((eq = memchr(p, '=', n)) == NULL || eq >= p + n || eq == p)
406                         continue;
407                 ext_len = eq - p;
408                 if (len > ext_len && uri[len - ext_len - 1] == '.' &&
409                     !my_strncasecmp(p, &uri[len - ext_len], ext_len)) {
410                         vec->ptr = eq + 1;
411                         vec->len = p + n - vec->ptr;
412                         return;
413                 }
414         }
415
416         /* If no luck, try built-in mime types */
417         for (i = 0; builtin_mime_types[i].extension != NULL; i++) {
418                 ext_len = builtin_mime_types[i].ext_len;
419                 if (len > ext_len && uri[len - ext_len - 1] == '.' &&
420                     !my_strncasecmp(builtin_mime_types[i].extension,
421                             &uri[len - ext_len], ext_len)) {
422                         vec->ptr = builtin_mime_types[i].mime_type;
423                         vec->len = strlen(vec->ptr);
424                         return;
425                 }
426         }
427
428         /* Oops. This extension is unknown to us. Fallback to text/plain */
429         vec->ptr = "text/plain";
430         vec->len = strlen(vec->ptr);
431 }
432
433 /*
434  * For given directory path, substitute it to valid index file.
435  * Return 0 if index file has been found, -1 if not found
436  */
437 static int
438 find_index_file(struct conn *c, char *path, size_t maxpath, struct stat *stp)
439 {
440         char            buf[FILENAME_MAX];
441         const char      *s = c->ctx->options[OPT_INDEX_FILES];
442         size_t          len;
443
444         FOR_EACH_WORD_IN_LIST(s, len) {
445                 my_snprintf(buf, sizeof(buf), "%s%c%.*s",path, DIRSEP, len, s);
446                 if (my_stat(buf, stp) == 0) {
447                         my_strlcpy(path, buf, maxpath);
448                         get_mime_type(c->ctx, s, len, &c->mime_type);
449                         return (0);
450                 }
451         }
452
453         return (-1);
454 }
455
456 /*
457  * Try to open requested file, return 0 if OK, -1 if error.
458  * If the file is given arguments using PATH_INFO mechanism,
459  * initialize pathinfo pointer.
460  */
461 static int
462 get_path_info(struct conn *c, char *path, struct stat *stp)
463 {
464         char    *p, *e;
465
466         if (my_stat(path, stp) == 0)
467                 return (0);
468
469         p = path + strlen(path);
470         e = path + strlen(c->ctx->options[OPT_ROOT]) + 2;
471         
472         /* Strip directory parts of the path one by one */
473         for (; p > e; p--)
474                 if (*p == '/') {
475                         *p = '\0';
476                         if (!my_stat(path, stp) && !S_ISDIR(stp->st_mode)) {
477                                 c->path_info = p + 1;
478                                 return (0);
479                         } else {
480                                 *p = '/';
481                         }
482                 }
483
484         return (-1);
485 }
486
487
488 static void
489 decide_what_to_do(struct conn *c)
490 {
491         char            path[URI_MAX], buf[1024], *root;
492         struct vec      alias_uri, alias_path;
493         struct stat     st;
494         int             rc;
495         struct registered_uri   *ruri;
496
497         DBG(("decide_what_to_do: [%s]", c->uri));
498
499         if ((c->query = strchr(c->uri, '?')) != NULL)
500                 *c->query++ = '\0';
501
502         url_decode(c->uri, strlen(c->uri), c->uri, strlen(c->uri) + 1);
503         remove_double_dots(c->uri);
504         
505         root = c->ctx->options[OPT_ROOT];
506         if (strlen(c->uri) + strlen(root) >= sizeof(path)) {
507                 send_server_error(c, 400, "URI is too long");
508                 return;
509         }
510
511         (void) my_snprintf(path, sizeof(path), "%s%s", root, c->uri);
512
513         /* User may use the aliases - check URI for mount point */
514         if (is_alias(c->ctx, c->uri, &alias_uri, &alias_path) != NULL) {
515                 (void) my_snprintf(path, sizeof(path), "%.*s%s",
516                     alias_path.len, alias_path.ptr, c->uri + alias_uri.len);
517                 DBG(("using alias %.*s -> %.*s", alias_uri.len, alias_uri.ptr,
518                     alias_path.len, alias_path.ptr));
519         }
520
521 #if !defined(NO_AUTH)
522         if (check_authorization(c, path) != 1) {
523                 send_authorization_request(c);
524         } else
525 #endif /* NO_AUTH */
526         if ((ruri = is_registered_uri(c->ctx, c->uri)) != NULL) {
527                 setup_embedded_stream(c, ruri->callback, ruri->callback_data);
528         } else
529         if (strstr(path, HTPASSWD)) {
530                 /* Do not allow to view passwords files */
531                 send_server_error(c, 403, "Forbidden");
532         } else
533 #if !defined(NO_AUTH)
534         if ((c->method == METHOD_PUT || c->method == METHOD_DELETE) &&
535             (c->ctx->options[OPT_AUTH_PUT] == NULL ||
536              !is_authorized_for_put(c))) {
537                 send_authorization_request(c);
538         } else
539 #endif /* NO_AUTH */
540         if (c->method == METHOD_PUT) {
541                 c->status = my_stat(path, &st) == 0 ? 200 : 201;
542
543                 if (c->ch.range.v_vec.len > 0) {
544                         send_server_error(c, 501, "PUT Range Not Implemented");
545                 } else if ((rc = put_dir(path)) == 0) {
546                         send_server_error(c, 200, "OK");
547                 } else if (rc == -1) {
548                         send_server_error(c, 500, "PUT Directory Error");
549                 } else if (c->rem.content_len == 0) {
550                         send_server_error(c, 411, "Length Required");
551                 } else if ((c->loc.chan.fd = my_open(path, O_WRONLY | O_BINARY |
552                     O_CREAT | O_NONBLOCK | O_TRUNC, 0644)) == -1) {
553                         send_server_error(c, 500, "PUT Error");
554                 } else {
555                         DBG(("PUT file [%s]", c->uri));
556                         c->loc.io_class = &io_file;
557                         c->loc.flags |= FLAG_W | FLAG_ALWAYS_READY ;
558                 }
559         } else if (c->method == METHOD_DELETE) {
560                 DBG(("DELETE [%s]", c->uri));
561                 if (my_remove(path) == 0)
562                         send_server_error(c, 200, "OK");
563                 else
564                         send_server_error(c, 500, "DELETE Error");
565         } else if (get_path_info(c, path, &st) != 0) {
566                 send_server_error(c, 404, "Not Found");
567         } else if (S_ISDIR(st.st_mode) && path[strlen(path) - 1] != '/') {
568                 (void) my_snprintf(buf, sizeof(buf),
569                         "Moved Permanently\r\nLocation: %s/", c->uri);
570                 send_server_error(c, 301, buf);
571         } else if (S_ISDIR(st.st_mode) &&
572             find_index_file(c, path, sizeof(path) - 1, &st) == -1 &&
573             !IS_TRUE(c->ctx, OPT_DIR_LIST)) {
574                 send_server_error(c, 403, "Directory Listing Denied");
575         } else if (S_ISDIR(st.st_mode) && IS_TRUE(c->ctx, OPT_DIR_LIST)) {
576                 if ((c->loc.chan.dir.path = my_strdup(path)) != NULL)
577                         get_dir(c);
578                 else
579                         send_server_error(c, 500, "GET Directory Error");
580         } else if (S_ISDIR(st.st_mode) && !IS_TRUE(c->ctx, OPT_DIR_LIST)) {
581                 send_server_error(c, 403, "Directory listing denied");
582 #if !defined(NO_CGI)
583         } else if (match_extension(path, c->ctx->options[OPT_CGI_EXTENSIONS])) {
584                 if (c->method != METHOD_POST && c->method != METHOD_GET) {
585                         send_server_error(c, 501, "Bad method ");
586                 } else if ((run_cgi(c, path)) == -1) {
587                         send_server_error(c, 500, "Cannot exec CGI");
588                 } else {
589                         do_cgi(c);
590                 }
591 #endif /* NO_CGI */
592 #if !defined(NO_SSI)
593         } else if (match_extension(path, c->ctx->options[OPT_SSI_EXTENSIONS])) {
594                 if ((c->loc.chan.fd = my_open(path,
595                     O_RDONLY | O_BINARY, 0644)) == -1) {
596                         send_server_error(c, 500, "SSI open error");
597                 } else {
598                         do_ssi(c);
599                 }
600 #endif /* NO_CGI */
601         } else if (c->ch.ims.v_time && st.st_mtime <= c->ch.ims.v_time) {
602                 send_server_error(c, 304, "Not Modified");
603         } else if ((c->loc.chan.fd = my_open(path,
604             O_RDONLY | O_BINARY, 0644)) != -1) {
605                 get_file(c, &st);
606         } else {
607                 send_server_error(c, 500, "Internal Error");
608         }
609 }
610
611 static int
612 set_request_method(struct conn *c)
613 {
614         const struct vec        *v;
615
616         /* Set the request method */
617         for (v = known_http_methods; v->ptr != NULL; v++)
618                 if (!memcmp(c->rem.io.buf, v->ptr, v->len)) {
619                         c->method = v - known_http_methods;
620                         break;
621                 }
622
623         return (v->ptr == NULL);
624 }
625
626 static void
627 parse_http_request(struct conn *c)
628 {
629         char    *s, *e, *p, *start;
630         int     uri_len, req_len, n;
631
632         s = io_data(&c->rem.io);;
633         req_len = c->rem.headers_len =
634             get_headers_len(s, io_data_len(&c->rem.io));
635
636         if (req_len == 0 && io_space_len(&c->rem.io) == 0) {
637                 io_clear(&c->rem.io);
638                 send_server_error(c, 400, "Request is too big");
639         }
640
641         io_inc_tail(&c->rem.io, req_len);
642
643         if (req_len == 0) {
644                 return;
645         } else if (req_len < 16) {      /* Minimal: "GET / HTTP/1.0\n\n" */
646                 send_server_error(c, 400, "Bad request");
647         } else if (set_request_method(c)) {
648                 send_server_error(c, 501, "Method Not Implemented");
649         } else if ((c->request = my_strndup(s, req_len)) == NULL) {
650                 send_server_error(c, 500, "Cannot allocate request");
651         }
652
653         if (c->loc.flags & FLAG_CLOSED)
654                 return;
655
656         DBG(("Conn %d: parsing request: [%.*s]", c->rem.chan.sock, req_len, s));
657         c->rem.flags |= FLAG_HEADERS_PARSED;
658
659         /* Set headers pointer. Headers follow the request line */
660         c->headers = memchr(c->request, '\n', req_len);
661         assert(c->headers != NULL);
662         assert(c->headers < c->request + req_len);
663         if (c->headers > c->request && c->headers[-1] == '\r')
664                 c->headers[-1] = '\0';
665         *c->headers++ = '\0';
666
667         /*
668          * Now make a copy of the URI, because it will be URL-decoded,
669          * and we need a copy of unmodified URI for the access log.
670          * First, we skip the REQUEST_METHOD and shift to the URI.
671          */
672         for (p = c->request, e = p + req_len; *p != ' ' && p < e; p++);
673         while (p < e && *p == ' ')
674                 p++;
675
676         /* Now remember where URI starts, and shift to the end of URI */
677         for (start = p; p < e && !isspace((unsigned char)*p); ) p++;
678         uri_len = p - start;
679
680         /* Skip space following the URI */
681         while (p < e && *p == ' ')
682                 p++;
683
684         /* Now comes the HTTP-Version in the form HTTP/<major>.<minor> */
685         if (sscanf(p, "HTTP/%lu.%lu%n",
686             &c->major_version, &c->minor_version, &n) != 2 || p[n] != '\0') {
687                 send_server_error(c, 400, "Bad HTTP version");
688         } else if (c->major_version > 1 ||
689             (c->major_version == 1 && c->minor_version > 1)) {
690                 send_server_error(c, 505, "HTTP version not supported");
691         } else if (uri_len <= 0) {
692                 send_server_error(c, 400, "Bad URI");
693         } else if ((c->uri = malloc(uri_len + 1)) == NULL) {
694                 send_server_error(c, 500, "Cannot allocate URI");
695         } else {
696                 my_strlcpy(c->uri, (char *) start, uri_len + 1);
697                 parse_headers(c->headers,
698                     (c->request + req_len) - c->headers, &c->ch);
699
700                 /* Remove the length of request from total, count only data */
701                 assert(c->rem.io.total >= (big_int_t) req_len);
702                 c->rem.io.total -= req_len;
703                 c->rem.content_len = c->ch.cl.v_big_int;
704                 decide_what_to_do(c);
705         }
706 }
707
708 void
709 shttpd_add_socket(struct shttpd_ctx *ctx, int sock, int is_ssl)
710 {
711         struct conn     *c;
712         struct usa      sa;
713         int             l = IS_TRUE(ctx, OPT_INETD) ? E_FATAL : E_LOG;
714 #if !defined(NO_SSL)
715         SSL             *ssl = NULL;
716 #endif /* NO_SSL */
717
718         sa.len = sizeof(sa.u.sin);
719         (void) set_non_blocking_mode(sock);
720
721         if (getpeername(sock, &sa.u.sa, &sa.len)) {
722                 elog(l, NULL, "add_socket: %s", strerror(errno));
723 #if !defined(NO_SSL)
724         } else if (is_ssl && (ssl = SSL_new(ctx->ssl_ctx)) == NULL) {
725                 elog(l, NULL, "add_socket: SSL_new: %s", strerror(ERRNO));
726                 (void) closesocket(sock);
727         } else if (is_ssl && SSL_set_fd(ssl, sock) == 0) {
728                 elog(l, NULL, "add_socket: SSL_set_fd: %s", strerror(ERRNO));
729                 (void) closesocket(sock);
730                 SSL_free(ssl);
731 #endif /* NO_SSL */
732         } else if ((c = calloc(1, sizeof(*c) + 2 * URI_MAX)) == NULL) {
733 #if !defined(NO_SSL)
734                 if (ssl)
735                         SSL_free(ssl);
736 #endif /* NO_SSL */
737                 (void) closesocket(sock);
738                 elog(l, NULL, "add_socket: calloc: %s", strerror(ERRNO));
739         } else {
740                 ctx->nrequests++;
741                 c->rem.conn = c->loc.conn = c;
742                 c->ctx          = ctx;
743                 c->sa           = sa;
744                 c->birth_time   = current_time;
745                 c->expire_time  = current_time + EXPIRE_TIME;
746
747                 (void) getsockname(sock, &sa.u.sa, &sa.len);
748                 c->loc_port = sa.u.sin.sin_port;
749
750                 set_close_on_exec(sock);
751
752                 c->loc.io_class = NULL;
753         
754                 c->rem.io_class = &io_socket;
755                 c->rem.chan.sock = sock;
756
757                 /* Set IO buffers */
758                 c->loc.io.buf   = (char *) (c + 1);
759                 c->rem.io.buf   = c->loc.io.buf + URI_MAX;
760                 c->loc.io.size  = c->rem.io.size = URI_MAX;
761
762 #if !defined(NO_SSL)
763                 if (is_ssl) {
764                         c->rem.io_class = &io_ssl;
765                         c->rem.chan.ssl.sock = sock;
766                         c->rem.chan.ssl.ssl = ssl;
767                         ssl_handshake(&c->rem);
768                 }
769 #endif /* NO_SSL */
770
771                 EnterCriticalSection(&ctx->mutex);
772                 LL_TAIL(&ctx->connections, &c->link);
773                 ctx->nactive++;
774                 LeaveCriticalSection(&ctx->mutex);
775                 
776                 DBG(("%s:%hu connected (socket %d)",
777                     inet_ntoa(* (struct in_addr *) &sa.u.sin.sin_addr.s_addr),
778                     ntohs(sa.u.sin.sin_port), sock));
779         }
780 }
781
782 int
783 shttpd_active(struct shttpd_ctx *ctx)
784 {
785         return (ctx->nactive);
786 }
787
788 /*
789  * Setup a listening socket on given port. Return opened socket or -1
790  */
791 int
792 shttpd_listen(struct shttpd_ctx *ctx, int port, int is_ssl)
793 {
794         struct listener *l;
795         int             sock;
796
797         if ((sock = open_listening_port(port)) == -1) {
798                 elog(E_FATAL, NULL, "cannot open port %d", port);
799         } else if ((l = calloc(1, sizeof(*l))) == NULL) {
800                 (void) closesocket(sock);
801                 elog(E_FATAL, NULL, "cannot allocate listener");
802         } else if (is_ssl && ctx->ssl_ctx == NULL) {
803                 (void) closesocket(sock);
804                 elog(E_FATAL, NULL, "cannot add SSL socket, "
805                     "please specify certificate file");
806         } else {
807                 l->is_ssl = is_ssl;
808                 l->sock = sock;
809                 l->ctx  = ctx;
810                 LL_TAIL(&ctx->listeners, &l->link);
811                 DBG(("shttpd_listen: added socket %d", sock));
812         }
813
814         return (sock);
815 }
816
817 int
818 shttpd_accept(int lsn_sock, int milliseconds)
819 {
820         struct timeval  tv;
821         struct usa      sa;
822         fd_set          read_set;
823         int             sock = -1;
824         
825         tv.tv_sec       = milliseconds / 1000;
826         tv.tv_usec      = milliseconds % 1000;
827         sa.len          = sizeof(sa.u.sin);
828         FD_ZERO(&read_set);
829         FD_SET(lsn_sock, &read_set);
830         
831         if (select(lsn_sock + 1, &read_set, NULL, NULL, &tv) == 1)
832                 sock = accept(lsn_sock, &sa.u.sa, &sa.len);
833
834         return (sock);
835 }
836
837 static void
838 read_stream(struct stream *stream)
839 {
840         int     n, len;
841
842         len = io_space_len(&stream->io);
843         assert(len > 0);
844
845         /* Do not read more that needed */
846         if (stream->content_len > 0 &&
847             stream->io.total + len > stream->content_len)
848                 len = stream->content_len - stream->io.total;
849
850         /* Read from underlying channel */
851         n = stream->nread_last = stream->io_class->read(stream,
852             io_space(&stream->io), len);
853
854         if (n > 0)
855                 io_inc_head(&stream->io, n);
856         else if (n == -1 && (ERRNO == EINTR || ERRNO == EWOULDBLOCK))
857                 n = n;  /* Ignore EINTR and EAGAIN */
858         else if (!(stream->flags & FLAG_DONT_CLOSE))
859                 stop_stream(stream);
860
861         DBG(("read_stream (%d %s): read %d/%d/%lu bytes (errno %d)",
862             stream->conn->rem.chan.sock,
863             stream->io_class ? stream->io_class->name : "(null)",
864             n, len, (unsigned long) stream->io.total, ERRNO));
865
866         /*
867          * Close the local stream if everything was read
868          * XXX We do not close the remote stream though! It may be
869          * a POST data completed transfer, we do not want the socket
870          * to be closed.
871          */
872         if (stream->content_len > 0 && stream == &stream->conn->loc) {
873                 assert(stream->io.total <= stream->content_len);
874                 if (stream->io.total == stream->content_len)
875                         stop_stream(stream);
876         }
877
878         stream->conn->expire_time = current_time + EXPIRE_TIME;
879 }
880
881 static void
882 write_stream(struct stream *from, struct stream *to)
883 {
884         int     n, len;
885
886         len = io_data_len(&from->io);
887         assert(len > 0);
888
889         /* TODO: should be assert on CAN_WRITE flag */
890         n = to->io_class->write(to, io_data(&from->io), len);
891         to->conn->expire_time = current_time + EXPIRE_TIME;
892         DBG(("write_stream (%d %s): written %d/%d bytes (errno %d)",
893             to->conn->rem.chan.sock,
894             to->io_class ? to->io_class->name : "(null)", n, len, ERRNO));
895
896         if (n > 0)
897                 io_inc_tail(&from->io, n);
898         else if (n == -1 && (ERRNO == EINTR || ERRNO == EWOULDBLOCK))
899                 n = n;  /* Ignore EINTR and EAGAIN */
900         else if (!(to->flags & FLAG_DONT_CLOSE))
901                 stop_stream(to);
902 }
903
904
905 static void
906 disconnect(struct llhead *lp)
907 {
908         struct conn             *c = LL_ENTRY(lp, struct conn, link);
909         static const struct vec vec = {"close", 5};
910         int                     do_close;
911
912         DBG(("Disconnecting %d (%.*s)", c->rem.chan.sock,
913             c->ch.connection.v_vec.len, c->ch.connection.v_vec.ptr));
914
915         if (c->request != NULL && c->ctx->access_log != NULL)
916                 log_access(c->ctx->access_log, c);
917
918         /* In inetd mode, exit if request is finished. */
919         if (IS_TRUE(c->ctx, OPT_INETD))
920                 exit(0);
921
922         if (c->loc.io_class != NULL && c->loc.io_class->close != NULL)
923                 c->loc.io_class->close(&c->loc);
924
925         /*
926          * Check the "Connection: " header before we free c->request
927          * If it its 'keep-alive', then do not close the connection
928          */
929         do_close = (c->ch.connection.v_vec.len >= vec.len &&
930             !my_strncasecmp(vec.ptr, c->ch.connection.v_vec.ptr, vec.len)) ||
931             (c->major_version < 1 ||
932             (c->major_version >= 1 && c->minor_version < 1));
933
934         if (c->request)
935                 free(c->request);
936         if (c->uri)
937                 free(c->uri);
938
939         /* Keep the connection open only if we have Content-Length set */
940         if (!do_close && c->loc.content_len > 0) {
941                 c->loc.io_class = NULL;
942                 c->loc.flags = 0;
943                 c->loc.content_len = 0;
944                 c->rem.flags = FLAG_W | FLAG_R;
945                 c->query = c->request = c->uri = c->path_info = NULL;
946                 c->mime_type.len = 0;
947                 (void) memset(&c->ch, 0, sizeof(c->ch));
948                 io_clear(&c->loc.io);
949                 c->birth_time = current_time;
950                 if (io_data_len(&c->rem.io) > 0)
951                         process_connection(c, 0, 0);
952         } else {
953                 if (c->rem.io_class != NULL)
954                         c->rem.io_class->close(&c->rem);
955
956                 EnterCriticalSection(&c->ctx->mutex);
957                 LL_DEL(&c->link);
958                 c->ctx->nactive--;
959                 assert(c->ctx->nactive >= 0);
960                 LeaveCriticalSection(&c->ctx->mutex);
961
962                 free(c);
963         }
964 }
965
966 static int
967 is_allowed(const struct shttpd_ctx *ctx, const struct usa *usa)
968 {
969         const struct acl        *acl;
970         const struct llhead     *lp;
971         int                     allowed = '+';
972         uint32_t                ip;
973
974         LL_FOREACH(&ctx->acl, lp) {
975                 acl = LL_ENTRY(lp, struct acl, link);
976                 (void) memcpy(&ip, &usa->u.sin.sin_addr, sizeof(ip));
977                 if (acl->ip == (ntohl(ip) & acl->mask))
978                         allowed = acl->flag;
979         }
980
981         return (allowed == '+');
982 }
983
984 static void
985 add_to_set(int fd, fd_set *set, int *max_fd)
986 {
987         FD_SET(fd, set);
988         if (fd > *max_fd)
989                 *max_fd = fd;
990 }
991
992 static void
993 process_connection(struct conn *c, int remote_ready, int local_ready)
994 {
995         /* Read from remote end if it is ready */
996         if (remote_ready && io_space_len(&c->rem.io))
997                 read_stream(&c->rem);
998
999         /* If the request is not parsed yet, do so */
1000         if (!(c->rem.flags & FLAG_HEADERS_PARSED))
1001                 parse_http_request(c);
1002
1003         DBG(("loc: %u [%.*s]", io_data_len(&c->loc.io),
1004             io_data_len(&c->loc.io), io_data(&c->loc.io)));
1005         DBG(("rem: %u [%.*s]", io_data_len(&c->rem.io),
1006             io_data_len(&c->rem.io), io_data(&c->rem.io)));
1007
1008         /* Read from the local end if it is ready */
1009         if (local_ready && io_space_len(&c->loc.io))
1010                 read_stream(&c->loc);
1011
1012         if (io_data_len(&c->rem.io) > 0 && (c->loc.flags & FLAG_W) &&
1013             c->loc.io_class != NULL && c->loc.io_class->write != NULL)
1014                 write_stream(&c->rem, &c->loc);
1015
1016         if (io_data_len(&c->loc.io) > 0 && c->rem.io_class != NULL)
1017                 write_stream(&c->loc, &c->rem); 
1018
1019         if (c->rem.nread_last > 0)
1020                 c->ctx->in += c->rem.nread_last;
1021         if (c->loc.nread_last > 0)
1022                 c->ctx->out += c->loc.nread_last;
1023
1024         /* Check whether we should close this connection */
1025         if ((current_time > c->expire_time) ||
1026             (c->rem.flags & FLAG_CLOSED) ||
1027             ((c->loc.flags & FLAG_CLOSED) && !io_data_len(&c->loc.io)))
1028                 disconnect(&c->link);
1029 }
1030
1031 /*
1032  * One iteration of server loop. This is the core of the data exchange.
1033  */
1034 void
1035 shttpd_poll(struct shttpd_ctx *ctx, int milliseconds)
1036 {
1037         struct llhead   *lp, *tmp;
1038         struct listener *l;
1039         struct conn     *c;
1040         struct timeval  tv;                     /* Timeout for select() */
1041         fd_set          read_set, write_set;
1042         int             sock, max_fd = -1, msec = milliseconds;
1043         struct usa      sa;
1044
1045         current_time = time(0);
1046         FD_ZERO(&read_set);
1047         FD_ZERO(&write_set);
1048
1049         /* Add listening sockets to the read set */
1050         LL_FOREACH(&ctx->listeners, lp) {
1051                 l = LL_ENTRY(lp, struct listener, link);
1052                 FD_SET(l->sock, &read_set);
1053                 if (l->sock > max_fd)
1054                         max_fd = l->sock;
1055                 DBG(("FD_SET(%d) (listening)", l->sock));
1056         }
1057
1058         /* Multiplex streams */
1059         LL_FOREACH(&ctx->connections, lp) {
1060                 c = LL_ENTRY(lp, struct conn, link);
1061                 
1062                 /* If there is a space in remote IO, check remote socket */
1063                 if (io_space_len(&c->rem.io))
1064                         add_to_set(c->rem.chan.fd, &read_set, &max_fd);
1065
1066 #if !defined(NO_CGI)
1067                 /*
1068                  * If there is a space in local IO, and local endpoint is
1069                  * CGI, check local socket for read availability
1070                  */
1071                 if (io_space_len(&c->loc.io) && (c->loc.flags & FLAG_R) &&
1072                     c->loc.io_class == &io_cgi)
1073                         add_to_set(c->loc.chan.fd, &read_set, &max_fd);
1074
1075                 /*
1076                  * If there is some data read from remote socket, and
1077                  * local endpoint is CGI, check local for write availability
1078                  */
1079                 if (io_data_len(&c->rem.io) && (c->loc.flags & FLAG_W) &&
1080                     c->loc.io_class == &io_cgi)
1081                         add_to_set(c->loc.chan.fd, &write_set, &max_fd);
1082 #endif /* NO_CGI */
1083
1084                 /*
1085                  * If there is some data read from local endpoint, check the
1086                  * remote socket for write availability
1087                  */
1088                 if (io_data_len(&c->loc.io))
1089                         add_to_set(c->rem.chan.fd, &write_set, &max_fd);
1090
1091                 if (io_space_len(&c->loc.io) && (c->loc.flags & FLAG_R) &&
1092                     (c->loc.flags & FLAG_ALWAYS_READY))
1093                         msec = 0;
1094                 
1095                 if (io_data_len(&c->rem.io) && (c->loc.flags & FLAG_W) &&
1096                     (c->loc.flags & FLAG_ALWAYS_READY))
1097                         msec = 0;
1098         }
1099
1100         tv.tv_sec = msec / 1000;
1101         tv.tv_usec = (msec % 1000) * 1000;
1102
1103         /* Check IO readiness */
1104         if (select(max_fd + 1, &read_set, &write_set, NULL, &tv) < 0) {
1105 #ifdef _WIN32
1106                 /*
1107                  * On windows, if read_set and write_set are empty,
1108                  * select() returns "Invalid parameter" error
1109                  * (at least on my Windows XP Pro). So in this case,
1110                  * we sleep here.
1111                  */
1112                 Sleep(milliseconds);
1113 #endif /* _WIN32 */
1114                 DBG(("select: %d", ERRNO));
1115                 return;
1116         }
1117
1118         /* Check for incoming connections on listener sockets */
1119         LL_FOREACH(&ctx->listeners, lp) {
1120                 l = LL_ENTRY(lp, struct listener, link);
1121                 if (!FD_ISSET(l->sock, &read_set))
1122                         continue;
1123                 do {
1124                         sa.len = sizeof(sa.u.sin);
1125                         if ((sock = accept(l->sock, &sa.u.sa, &sa.len)) != -1) {
1126 #if defined(_WIN32)
1127                                 if (!is_allowed(ctx, &sa)) {
1128                                         elog(E_LOG, NULL, "shttpd_poll: %s "
1129                                             "is not allowed to connect",
1130                                            inet_ntoa(sa.u.sin.sin_addr));
1131                                         (void) closesocket(sock);
1132                                 } else {
1133                                         shttpd_add_socket(ctx, sock, l->is_ssl);
1134                                 }
1135 #else
1136                                 if (sock >= (int) FD_SETSIZE) {
1137                                         elog(E_LOG, NULL,
1138                                            "shttpd_poll: ctx %p: disarding "
1139                                            "socket %d, too busy", ctx, sock);
1140                                         (void) closesocket(sock);
1141                                 } else if (!is_allowed(ctx, &sa)) {
1142                                         elog(E_LOG, NULL, "shttpd_poll: %s "
1143                                             "is not allowed to connect",
1144                                            inet_ntoa(sa.u.sin.sin_addr));
1145                                         (void) closesocket(sock);
1146                                 } else {
1147                                         shttpd_add_socket(ctx, sock, l->is_ssl);
1148                                 }
1149 #endif /* _WIN32 */
1150                         }
1151                 } while (sock != -1);
1152         }
1153
1154         /* Process all connections */
1155         LL_FOREACH_SAFE(&ctx->connections, lp, tmp) {
1156                 c = LL_ENTRY(lp, struct conn, link);
1157                 process_connection(c, FD_ISSET(c->rem.chan.fd, &read_set),
1158                     ((c->loc.flags & FLAG_ALWAYS_READY)
1159 #if !defined(NO_CGI)
1160                     || (c->loc.io_class == &io_cgi &&
1161                      FD_ISSET(c->loc.chan.fd, &read_set))
1162 #endif /* NO_CGI */
1163                     ));
1164         }
1165 }
1166
1167 void
1168 free_list(struct llhead *head, void (*dtor)(struct llhead *))
1169 {
1170         struct llhead   *lp, *tmp;
1171
1172         LL_FOREACH_SAFE(head, lp, tmp) {
1173                 LL_DEL(lp);
1174                 dtor(lp);
1175         }
1176 }
1177
1178 void
1179 listener_destructor(struct llhead *lp)
1180 {
1181         struct listener *listener = LL_ENTRY(lp, struct listener, link);
1182
1183         (void) closesocket(listener->sock);
1184         free(listener);
1185 }
1186
1187 void
1188 registered_uri_destructor(struct llhead *lp)
1189 {
1190         struct registered_uri *ruri = LL_ENTRY(lp, struct registered_uri, link);
1191
1192         free((void *) ruri->uri);
1193         free(ruri);
1194 }
1195
1196 static void
1197 acl_destructor(struct llhead *lp)
1198 {
1199         struct acl      *acl = LL_ENTRY(lp, struct acl, link);
1200         free(acl);
1201 }
1202
1203 /*
1204  * Deallocate shttpd object, free up the resources
1205  */
1206 void
1207 shttpd_fini(struct shttpd_ctx *ctx)
1208 {
1209         size_t  i;
1210
1211         free_list(&ctx->connections, disconnect);
1212         free_list(&ctx->registered_uris, registered_uri_destructor);
1213         free_list(&ctx->acl, acl_destructor);
1214         free_list(&ctx->listeners, listener_destructor);
1215         free_list(&ctx->ssi_funcs, ssi_func_destructor);
1216
1217         for (i = 0; i < NELEMS(ctx->options); i++)
1218                 if (ctx->options[i] != NULL)
1219                         free(ctx->options[i]);
1220
1221         if (ctx->access_log)            (void) fclose(ctx->access_log);
1222         if (ctx->error_log)             (void) fclose(ctx->error_log);
1223
1224         /* TODO: free SSL context */
1225
1226         free(ctx);
1227 }