1 /* This program is free software; you can redistribute it and/or modify
2 * it under the terms of the GNU General Public License as published by
3 * the Free Software Foundation; version 2 of the License. For a copy,
4 * see http://www.gnu.org/licenses/gpl-2.0.html.
5 *
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
10 */
11
12 #include "config.h"
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <sys/socket.h>
17 #include "global.h"
18 #include "libstr.h"
19 #include "liblist.h"
20 #include "memdbg.h"
21
22 /*---< headerlist >-----------------------------------------------------------*/
23
24 /* Parse the HTTP http_headers from the received request.
25 */
parse_http_headers(char * line)26 t_http_header *parse_http_headers(char *line) {
27 t_http_header *first, *http_header;
28 char *value;
29
30 if (empty_string(line)) {
31 return NULL;
32 } else if (*line == '\0') {
33 return NULL;
34 }
35
36 if ((first = http_header = (t_http_header*)malloc(sizeof(t_http_header))) == NULL) {
37 return NULL;
38 }
39 http_header->data = line;
40 http_header->length = 0;
41 http_header->next = NULL;
42 while (*line != '\0') {
43 if (*line == '\r') {
44 *line = '\0';
45 http_header->length = strlen(http_header->data);
46 if (*(line + 1) == '\n') {
47 if ((*(line + 2) != '\r') && (*(line + 2) != '\0')) {
48 if ((http_header->next = (t_http_header*)malloc(sizeof(t_http_header))) == NULL) {
49 return first;
50 }
51 http_header = http_header->next;
52 http_header->next = NULL;
53 http_header->data = line + 2;
54 http_header->length = 0;
55 } else {
56 break;
57 }
58 } else {
59 http_header->data = line + 1;
60 }
61 }
62 line++;
63 }
64
65 if (first->length == 0) {
66 free(first);
67 return NULL;
68 }
69
70 if (http_header->length == 0) {
71 http_header->length = strlen(http_header->data);
72 }
73
74 http_header = first;
75 while (http_header != NULL) {
76 if ((value = strchr(http_header->data, ':')) != NULL) {
77 do {
78 value++;
79 } while (*value == ' ');
80 http_header->value_offset = (value - http_header->data);
81 } else {
82 http_header->value_offset = 0;
83 }
84 http_header = http_header->next;
85 }
86
87 return first;
88 }
89
90 /* Search for a http_header and return its value.
91 */
get_http_header(char * key,t_http_header * http_headers)92 char *get_http_header(char *key, t_http_header *http_headers) {
93 int len;
94
95 if ((key == NULL) || (http_headers == NULL)) {
96 return NULL;
97 }
98
99 len = strlen(key);
100 while (http_headers != NULL) {
101 if (strncasecmp(http_headers->data, key, len) == 0) {
102 return http_headers->data + http_headers->value_offset;
103 }
104 http_headers = http_headers->next;
105 }
106
107 return NULL;
108 }
109
110 /* Return the HTTP Origin or Referer header
111 */
get_referer_header(t_http_header * http_headers)112 char *get_referer_header(t_http_header *http_headers) {
113 char *referer;
114
115 if ((referer = get_http_header("Origin:", http_headers)) == NULL) {
116 referer = get_http_header("Referer:", http_headers);
117 }
118
119 return referer;
120 }
121
122 /* free() a list of http_headers.
123 */
remove_http_headers(t_http_header * http_headers)124 t_http_header *remove_http_headers(t_http_header *http_headers) {
125 t_http_header *remove;
126
127 while (http_headers != NULL) {
128 remove = http_headers;
129 http_headers = http_headers->next;
130
131 free(remove);
132 }
133
134 return NULL;
135 }
136
137 /*---< charlist >-------------------------------------------------------------*/
138
init_charlist(t_charlist * list)139 void init_charlist(t_charlist *list) {
140 if (list != NULL) {
141 list->size = 0;
142 list->item = NULL;
143 }
144 }
145
parse_charlist(char * value,t_charlist * list)146 int parse_charlist(char *value, t_charlist *list) {
147 char *scan, **new;
148 int add = 1, i;
149
150 if (list == NULL) {
151 return -1;
152 } else if (empty_string(value)) {
153 return -1;
154 }
155
156 scan = value;
157 while (*scan != '\0') {
158 if (*scan == ',') {
159 *scan = '\0';
160 add++;
161 }
162 scan++;
163 }
164
165 if ((new = (char**)realloc(list->item, (list->size + add) * sizeof(char*))) == NULL) {
166 return -1;
167 }
168 list->item = new;
169
170 for (i = 0; i < add; i++) {
171 *(list->item + list->size + i) = NULL;
172 }
173
174 for (i = 0; i < add; i++) {
175 if ((*(list->item + list->size + i) = strdup(remove_spaces(value))) == NULL) {
176 remove_charlist(list);
177 init_charlist(list);
178 return -1;
179 }
180 value = value + strlen(value) + 1;
181 }
182
183 list->size += add;
184
185 return 0;
186 }
187
copy_charlist(t_charlist * dest,t_charlist * src)188 void copy_charlist(t_charlist *dest, t_charlist *src) {
189 if ((dest != NULL) && (src != NULL)) {
190 dest->size = src->size;
191 dest->item = src->item;
192 }
193 }
194
in_charlist(char * item,t_charlist * list)195 bool in_charlist(char *item, t_charlist *list) {
196 int i;
197
198 if ((item == NULL) || (list == NULL)) {
199 return false;
200 }
201
202 i = list->size;
203 while (i-- > 0) {
204 if (strcmp(*(list->item + i), item) == 0) {
205 return true;
206 }
207 }
208
209 return false;
210 }
211
matches_charlist(char * item,t_charlist * list)212 bool matches_charlist(char *item, t_charlist *list) {
213 int i;
214 size_t n;
215
216 if ((item == NULL) || (list == NULL)) {
217 return false;
218 }
219
220 n = strlen(item);
221
222 i = list->size;
223 while (i-- > 0) {
224 if (strncmp(*(list->item + i), item, n) == 0) {
225 return true;
226 }
227 }
228
229 return false;
230 }
231
remove_charlist(t_charlist * list)232 void remove_charlist(t_charlist *list) {
233 if (list != NULL) {
234 if (list->size > 0) {
235 do {
236 list->size--;
237 check_free(*(list->item + list->size));
238 } while (list->size > 0);
239 check_free(list->item);
240 list->item = NULL;
241 }
242 }
243 }
244
245 /*---< accesslist >-----------------------------------------------------------*/
246
247 /* Parse a list of access levels.
248 */
parse_accesslist(char * line,bool pwd_allowed,t_accesslist * list)249 t_accesslist *parse_accesslist(char *line, bool pwd_allowed, t_accesslist *list) {
250 t_accesslist *new = NULL;
251 char *rule, *ip, *mask;
252 bool error = false;
253
254 if (empty_string(line)) {
255 return remove_accesslist(list);
256 }
257
258 if (list != NULL) {
259 new = list;
260 while (new->next != NULL) {
261 new = new->next;
262 }
263 }
264
265 while (line != NULL) {
266 split_string(line, &ip, &line, ',');
267 if (split_string(ip, &rule, &ip, ' ') == 0) {
268 if (list == NULL) {
269 if ((list = new = (t_accesslist*)malloc(sizeof(t_accesslist))) == NULL) {
270 break;
271 }
272 } else {
273 if ((new->next = (t_accesslist*)malloc(sizeof(t_accesslist))) == NULL) {
274 error = true;
275 break;
276 }
277 new = new->next;
278 }
279 new->next = NULL;
280
281 if (strcasecmp(rule, "allow") == 0) {
282 new->access = allow;
283 } else if (strcasecmp(rule, "deny") == 0) {
284 new->access = deny;
285 } else if (pwd_allowed && (strcasecmp(rule, "pwd") == 0)) {
286 new->access = pwd;
287 } else {
288 error = true;
289 break;
290 }
291 if (strcasecmp(ip, "all") == 0) {
292 default_ipv4(&(new->ip));
293 new->netmask = 0;
294 new->all_ip = true;
295 } else {
296 new->all_ip = false;
297 if (split_string(ip, &ip, &mask, '/') == 0) {
298 if ((new->netmask = str_to_int(mask)) == -1) {
299 error = true;
300 break;
301 }
302 } else {
303 new->netmask = -1;
304 }
305 if (parse_ip(ip, &(new->ip)) == -1) {
306 error = true;
307 break;
308 }
309
310 if (new->netmask == -1) {
311 /* Set netmask
312 */
313 if (new->ip.family == AF_INET) {
314 new->netmask = 8 * IPv4_LEN;
315 } else if (new->ip.family == AF_INET6) {
316 new->netmask = 8 * IPv6_LEN;
317 } else {
318 error = true;
319 break;
320 }
321 } else {
322 /* Check netmask
323 */
324 if (new->ip.family == AF_INET) {
325 if ((unsigned int)new->netmask > 8 * IPv4_LEN) {
326 error = true;
327 break;
328 }
329 } else if (new->ip.family == AF_INET6) {
330 if ((unsigned int)new->netmask > 8 * IPv6_LEN) {
331 error = true;
332 break;
333 }
334 } else {
335 error = true;
336 break;
337 }
338 }
339
340 /* Apply subnetmask
341 */
342 if (apply_netmask(&(new->ip), new->netmask) == -1) {
343 error = true;
344 break;
345 }
346 }
347 } else {
348 error = true;
349 break;
350 }
351 }
352
353 if (error) {
354 list = remove_accesslist(list);
355 }
356
357 return list;
358 }
359
360 /* Remove an accesslist.
361 */
remove_accesslist(t_accesslist * list)362 t_accesslist *remove_accesslist(t_accesslist *list) {
363 t_accesslist *item;
364
365 while (list != NULL) {
366 item = list;
367 list = list->next;
368
369 free(item);
370 }
371
372 return NULL;
373 }
374
375 /* Return the access status of an IP address.
376 */
ip_allowed(t_ip_addr * ip,t_accesslist * list)377 t_access ip_allowed(t_ip_addr *ip, t_accesslist *list) {
378 while (list != NULL) {
379 if (list->all_ip) {
380 return list->access;
381 } else if (ip_in_subnet(ip, &(list->ip), list->netmask)) {
382 return list->access;
383 }
384 list = list->next;
385 }
386
387 return unspecified;
388 }
389
390 /*---< key/value >-----------------------------------------------------------*/
391
392 /* Parse a key/value combination.
393 */
parse_keyvalue(char * line,t_keyvalue ** kvlist,char * delimiter)394 int parse_keyvalue(char *line, t_keyvalue **kvlist, char *delimiter) {
395 char *value;
396 t_keyvalue *prev;
397
398 if ((kvlist == NULL) || (delimiter == NULL)) {
399 return -1;
400 } else if (empty_string(line)) {
401 return -1;
402 }
403
404 if ((value = strstr(line, delimiter)) == NULL) {
405 return -1;
406 }
407
408 *value = '\0';
409 value += strlen(delimiter);
410
411 prev = *kvlist;
412 if ((*kvlist = (t_keyvalue*)malloc(sizeof(t_keyvalue))) == NULL) {
413 return -1;
414 }
415 (*kvlist)->next = prev;
416
417 (*kvlist)->value = NULL;
418 if (((*kvlist)->key = strdup(remove_spaces(line))) == NULL) {
419 free(*kvlist);
420 return -1;
421 }
422 (*kvlist)->key_len = strlen((*kvlist)->key);
423
424 if (((*kvlist)->value = strdup(remove_spaces(value))) == NULL) {
425 free((*kvlist)->key);
426 free(*kvlist);
427 return -1;
428 }
429 (*kvlist)->value_len = strlen((*kvlist)->value);
430
431 return 0;
432 }
433
remove_keyvaluelist(t_keyvalue * list)434 t_keyvalue *remove_keyvaluelist(t_keyvalue *list) {
435 t_keyvalue *remove;
436
437 while (list != NULL) {
438 remove = list;
439 list = list->next;
440
441 check_free(remove->key);
442 check_free(remove->value);
443 free(remove);
444 }
445
446 return NULL;
447 }
448
449 /*---< error handlers >------------------------------------------------------*/
450
parse_error_handler(char * line,t_error_handler ** handlers)451 int parse_error_handler(char *line, t_error_handler **handlers) {
452 t_error_handler *handler;
453 char *param;
454 int code;
455
456 if (empty_string(line)) {
457 return -1;
458 } else if ((handler = (t_error_handler*)malloc(sizeof(t_error_handler))) == NULL) {
459 return -1;
460 }
461
462 if (split_string(line, ¶m, &line, ':') != 0) {
463 free(handler);
464 return -1;
465 }
466
467 switch (code = str_to_int(param)) {
468 case 401:
469 case 403:
470 case 404:
471 case 501:
472 case 503:
473 handler->code = code;
474 break;
475 default:
476 free(handler);
477 return -1;
478 }
479
480 if ((strlen(line) > 128) || (*line != '/')) {
481 free(handler);
482 return -1;
483 } else if ((handler->handler = strdup(line)) == NULL) {
484 free(handler);
485 return -1;
486 }
487
488 if ((param = strchr(handler->handler, '?')) != NULL) {
489 *param = '\0';
490 handler->parameters = param + 1;
491 } else {
492 handler->parameters = NULL;
493 }
494
495 handler->next = *handlers;
496 *handlers = handler;
497
498 return 0;
499 }
500
remove_error_handler(t_error_handler * handler)501 void remove_error_handler(t_error_handler *handler) {
502 if (handler != NULL) {
503 free(handler->handler);
504 free(handler);
505 }
506 }
507
508 /*---< temporary data >------------------------------------------------------*/
509
register_tempdata(t_tempdata ** tempdata,void * data,t_tempdata_type type)510 int register_tempdata(t_tempdata **tempdata, void *data, t_tempdata_type type) {
511 t_tempdata *tdata;
512
513 if (tempdata == NULL) {
514 return 0;
515 } else if (data == NULL) {
516 return -1;
517 } else if ((tdata = (t_tempdata*)malloc(sizeof(t_tempdata))) == NULL) {
518 return -1;
519 }
520
521 tdata->content = data;
522 tdata->type = type;
523 tdata->next = *tempdata;
524 *tempdata = tdata;
525
526 return 0;
527 }
528
remove_tempdata(t_tempdata * tempdata)529 void remove_tempdata(t_tempdata *tempdata) {
530 t_tempdata *tdata;
531
532 while (tempdata != NULL) {
533 tdata = tempdata;
534 tempdata = tempdata->next;
535
536 switch (tdata->type) {
537 case tc_data:
538 check_free(tdata->content);
539 break;
540 case tc_accesslist:
541 remove_accesslist((t_accesslist*)tdata->content);
542 break;
543 case tc_keyvalue:
544 free(((t_keyvalue*)(tdata->content))->key);
545 free(((t_keyvalue*)(tdata->content))->value);
546 free(tdata->content);
547 break;
548 case tc_charlist:
549 remove_charlist((t_charlist*)tdata->content);
550 break;
551 case tc_errorhandler:
552 remove_error_handler((t_error_handler*)tdata->content);
553 break;
554 }
555
556 free(tdata);
557 }
558 }
559