1 #include "uwsgi.h"
2
3 extern struct uwsgi_server uwsgi;
4
5 // this is like uwsgi_str_num but with security checks
get_content_length(char * buf,uint16_t size)6 static size_t get_content_length(char *buf, uint16_t size) {
7 int i;
8 size_t val = 0;
9 for (i = 0; i < size; i++) {
10 if (buf[i] >= '0' && buf[i] <= '9') {
11 val = (val * 10) + (buf[i] - '0');
12 continue;
13 }
14 break;
15 }
16
17 return val;
18 }
19
20
uwsgi_read_response(int fd,struct uwsgi_header * uh,int timeout,char ** buf)21 int uwsgi_read_response(int fd, struct uwsgi_header *uh, int timeout, char **buf) {
22
23 char *ptr = (char *) uh;
24 size_t remains = 4;
25 int ret = -1;
26 int rlen;
27 ssize_t len;
28
29 while (remains > 0) {
30 rlen = uwsgi_waitfd(fd, timeout);
31 if (rlen > 0) {
32 len = read(fd, ptr, remains);
33 if (len <= 0)
34 break;
35 remains -= len;
36 ptr += len;
37 if (remains == 0) {
38 ret = uh->modifier2;
39 break;
40 }
41 continue;
42 }
43 // timed out ?
44 else if (ret == 0)
45 ret = -2;
46 break;
47 }
48
49 if (buf && uh->pktsize > 0) {
50 if (*buf == NULL)
51 *buf = uwsgi_malloc(uh->pktsize);
52 remains = uh->pktsize;
53 ptr = *buf;
54 ret = -1;
55 while (remains > 0) {
56 rlen = uwsgi_waitfd(fd, timeout);
57 if (rlen > 0) {
58 len = read(fd, ptr, remains);
59 if (len <= 0)
60 break;
61 remains -= len;
62 ptr += len;
63 if (remains == 0) {
64 ret = uh->modifier2;
65 break;
66 }
67 continue;
68 }
69 // timed out ?
70 else if (ret == 0)
71 ret = -2;
72 break;
73 }
74 }
75
76 return ret;
77 }
78
uwsgi_parse_array(char * buffer,uint16_t size,char ** argv,uint16_t argvs[],uint8_t * argc)79 int uwsgi_parse_array(char *buffer, uint16_t size, char **argv, uint16_t argvs[], uint8_t * argc) {
80
81 char *ptrbuf, *bufferend;
82 uint16_t strsize = 0;
83
84 uint8_t max = *argc;
85 *argc = 0;
86
87 ptrbuf = buffer;
88 bufferend = ptrbuf + size;
89
90 while (ptrbuf < bufferend && *argc < max) {
91 if (ptrbuf + 2 < bufferend) {
92 memcpy(&strsize, ptrbuf, 2);
93 #ifdef __BIG_ENDIAN__
94 strsize = uwsgi_swap16(strsize);
95 #endif
96
97 ptrbuf += 2;
98 /* item cannot be null */
99 if (!strsize)
100 continue;
101
102 if (ptrbuf + strsize <= bufferend) {
103 // item
104 argv[*argc] = uwsgi_cheap_string(ptrbuf, strsize);
105 argvs[*argc] = strsize;
106 #ifdef UWSGI_DEBUG
107 uwsgi_log("arg %s\n", argv[*argc]);
108 #endif
109 ptrbuf += strsize;
110 *argc = *argc + 1;
111 }
112 else {
113 uwsgi_log("invalid uwsgi array. skip this var.\n");
114 return -1;
115 }
116 }
117 else {
118 uwsgi_log("invalid uwsgi array. skip this request.\n");
119 return -1;
120 }
121 }
122
123
124 return 0;
125 }
126
uwsgi_simple_parse_vars(struct wsgi_request * wsgi_req,char * ptrbuf,char * bufferend)127 int uwsgi_simple_parse_vars(struct wsgi_request *wsgi_req, char *ptrbuf, char *bufferend) {
128
129 uint16_t strsize;
130
131 while (ptrbuf < bufferend) {
132 if (ptrbuf + 2 < bufferend) {
133 memcpy(&strsize, ptrbuf, 2);
134 #ifdef __BIG_ENDIAN__
135 strsize = uwsgi_swap16(strsize);
136 #endif
137 /* key cannot be null */
138 if (!strsize) {
139 uwsgi_log("uwsgi key cannot be null. skip this request.\n");
140 return -1;
141 }
142
143 ptrbuf += 2;
144 if (ptrbuf + strsize < bufferend) {
145 // var key
146 wsgi_req->hvec[wsgi_req->var_cnt].iov_base = ptrbuf;
147 wsgi_req->hvec[wsgi_req->var_cnt].iov_len = strsize;
148 ptrbuf += strsize;
149 // value can be null (even at the end) so use <=
150 if (ptrbuf + 2 <= bufferend) {
151 memcpy(&strsize, ptrbuf, 2);
152 #ifdef __BIG_ENDIAN__
153 strsize = uwsgi_swap16(strsize);
154 #endif
155 ptrbuf += 2;
156 if (ptrbuf + strsize <= bufferend) {
157
158 if (wsgi_req->var_cnt < uwsgi.vec_size - (4 + 1)) {
159 wsgi_req->var_cnt++;
160 }
161 else {
162 uwsgi_log("max vec size reached. skip this header.\n");
163 return -1;
164 }
165 // var value
166 wsgi_req->hvec[wsgi_req->var_cnt].iov_base = ptrbuf;
167 wsgi_req->hvec[wsgi_req->var_cnt].iov_len = strsize;
168
169 if (wsgi_req->var_cnt < uwsgi.vec_size - (4 + 1)) {
170 wsgi_req->var_cnt++;
171 }
172 else {
173 uwsgi_log("max vec size reached. skip this var.\n");
174 return -1;
175 }
176 ptrbuf += strsize;
177 }
178 else {
179 uwsgi_log("invalid uwsgi request (current strsize: %d). skip.\n", strsize);
180 return -1;
181 }
182 }
183 else {
184 uwsgi_log("invalid uwsgi request (current strsize: %d). skip.\n", strsize);
185 return -1;
186 }
187 }
188 }
189 }
190
191 return 0;
192 }
193
194 #define uwsgi_proto_key(x, y) memcmp(x, key, y)
195
uwsgi_proto_check_5(struct wsgi_request * wsgi_req,char * key,char * buf,uint16_t len)196 static int uwsgi_proto_check_5(struct wsgi_request *wsgi_req, char *key, char *buf, uint16_t len) {
197
198 if (!uwsgi_proto_key("HTTPS", 5)) {
199 wsgi_req->https = buf;
200 wsgi_req->https_len = len;
201 return 0;
202 }
203
204 return 0;
205 }
206
uwsgi_proto_check_9(struct wsgi_request * wsgi_req,char * key,char * buf,uint16_t len)207 static int uwsgi_proto_check_9(struct wsgi_request *wsgi_req, char *key, char *buf, uint16_t len) {
208
209 if (!uwsgi_proto_key("PATH_INFO", 9)) {
210 wsgi_req->path_info = buf;
211 wsgi_req->path_info_len = len;
212 wsgi_req->path_info_pos = wsgi_req->var_cnt + 1;
213 #ifdef UWSGI_DEBUG
214 uwsgi_debug("PATH_INFO=%.*s\n", wsgi_req->path_info_len, wsgi_req->path_info);
215 #endif
216 return 0;
217 }
218
219 if (!uwsgi_proto_key("HTTP_HOST", 9)) {
220 wsgi_req->host = buf;
221 wsgi_req->host_len = len;
222 #ifdef UWSGI_DEBUG
223 uwsgi_debug("HTTP_HOST=%.*s\n", wsgi_req->host_len, wsgi_req->host);
224 #endif
225 return 0;
226 }
227
228 return 0;
229 }
230
uwsgi_parse_http_range(char * buf,uint16_t len,enum uwsgi_range * parsed,int64_t * from,int64_t * to)231 static void uwsgi_parse_http_range(char *buf, uint16_t len, enum uwsgi_range *parsed, int64_t *from, int64_t *to) {
232 *parsed = UWSGI_RANGE_INVALID;
233 *from = 0;
234 *to = 0;
235 uint16_t rlen = 0;
236 uint16_t i;
237 for(i=0;i<len;i++) {
238 if (buf[i] == ',') break;
239 rlen++;
240 }
241
242 // bytes=X-
243 if (rlen < 8) return;
244 char *equal = memchr(buf, '=', rlen);
245 if (!equal) return;
246 if (equal-buf != 5) return;
247 if (memcmp(buf, "bytes", 5)) return;
248 char *range = equal+1;
249 rlen -= 6;
250 char *dash = memchr(range, '-', rlen);
251 if (!dash) return;
252 if (dash != range) {
253 *from = uwsgi_str_num(range, dash-range);
254 if (dash == range+(rlen-1)) {
255 /* RFC7233 prefix range
256 * `bytes=start-` is a same as `byte=start-0x7ffffffffffffff`
257 */
258 *to = INT64_MAX;
259 } else {
260 *to = uwsgi_str_num(dash+1, rlen - ((dash+1)-range));
261 }
262 if (*to >= *from) {
263 *parsed = UWSGI_RANGE_PARSED;
264 } else {
265 *from = 0;
266 *to = 0;
267 }
268 } else {
269 /* RFC7233 suffix-byte-range-spec: `bytes=-500` */
270 *from = -(int64_t)uwsgi_str_num(dash+1, rlen - ((dash+1)-range));
271 if (*from < 0) {
272 *to = INT64_MAX;
273 *parsed = UWSGI_RANGE_PARSED;
274 }
275 }
276 }
277
uwsgi_proto_check_10(struct wsgi_request * wsgi_req,char * key,char * buf,uint16_t len)278 static int uwsgi_proto_check_10(struct wsgi_request *wsgi_req, char *key, char *buf, uint16_t len) {
279
280 if (uwsgi.honour_range && !uwsgi_proto_key("HTTP_IF_RANGE", 13)) {
281 wsgi_req->if_range = buf;
282 wsgi_req->if_range_len = len;
283 }
284
285 if (uwsgi.honour_range && !uwsgi_proto_key("HTTP_RANGE", 10)) {
286 uwsgi_parse_http_range(buf, len, &wsgi_req->range_parsed,
287 &wsgi_req->range_from, &wsgi_req->range_to);
288 // set deprecated fields for binary compatibility
289 wsgi_req->__range_from = (size_t)wsgi_req->range_from;
290 wsgi_req->__range_to = (size_t)wsgi_req->range_to;
291 return 0;
292 }
293
294 if (!uwsgi_proto_key("UWSGI_FILE", 10)) {
295 wsgi_req->file = buf;
296 wsgi_req->file_len = len;
297 wsgi_req->dynamic = 1;
298 return 0;
299 }
300
301 if (!uwsgi_proto_key("UWSGI_HOME", 10)) {
302 wsgi_req->home = buf;
303 wsgi_req->home_len = len;
304 return 0;
305 }
306
307 return 0;
308 }
309
uwsgi_proto_check_11(struct wsgi_request * wsgi_req,char * key,char * buf,uint16_t len)310 static int uwsgi_proto_check_11(struct wsgi_request *wsgi_req, char *key, char *buf, uint16_t len) {
311
312 if (!uwsgi_proto_key("SCRIPT_NAME", 11)) {
313 wsgi_req->script_name = buf;
314 wsgi_req->script_name_len = len;
315 wsgi_req->script_name_pos = wsgi_req->var_cnt + 1;
316 #ifdef UWSGI_DEBUG
317 uwsgi_debug("SCRIPT_NAME=%.*s\n", wsgi_req->script_name_len, wsgi_req->script_name);
318 #endif
319 return 0;
320 }
321
322 if (!uwsgi_proto_key("REQUEST_URI", 11)) {
323 wsgi_req->uri = buf;
324 wsgi_req->uri_len = len;
325 return 0;
326 }
327
328 if (!uwsgi_proto_key("REMOTE_USER", 11)) {
329 wsgi_req->remote_user = buf;
330 wsgi_req->remote_user_len = len;
331 return 0;
332 }
333
334 if (wsgi_req->host_len == 0 && !uwsgi_proto_key("SERVER_NAME", 11)) {
335 wsgi_req->host = buf;
336 wsgi_req->host_len = len;
337 #ifdef UWSGI_DEBUG
338 uwsgi_debug("SERVER_NAME=%.*s\n", wsgi_req->host_len, wsgi_req->host);
339 #endif
340 return 0;
341 }
342
343 if (wsgi_req->remote_addr_len == 0 && !uwsgi_proto_key("REMOTE_ADDR", 11)) {
344 wsgi_req->remote_addr = buf;
345 wsgi_req->remote_addr_len = len;
346 return 0;
347 }
348
349 if (!uwsgi_proto_key("HTTP_COOKIE", 11)) {
350 wsgi_req->cookie = buf;
351 wsgi_req->cookie_len = len;
352 return 0;
353 }
354
355
356 if (!uwsgi_proto_key("UWSGI_APPID", 11)) {
357 wsgi_req->appid = buf;
358 wsgi_req->appid_len = len;
359 return 0;
360 }
361
362 if (!uwsgi_proto_key("UWSGI_CHDIR", 11)) {
363 wsgi_req->chdir = buf;
364 wsgi_req->chdir_len = len;
365 return 0;
366 }
367
368 if (!uwsgi_proto_key("HTTP_ORIGIN", 11)) {
369 wsgi_req->http_origin = buf;
370 wsgi_req->http_origin_len = len;
371 return 0;
372 }
373
374 return 0;
375 }
376
uwsgi_proto_check_12(struct wsgi_request * wsgi_req,char * key,char * buf,uint16_t len)377 static int uwsgi_proto_check_12(struct wsgi_request *wsgi_req, char *key, char *buf, uint16_t len) {
378 if (!uwsgi_proto_key("QUERY_STRING", 12)) {
379 wsgi_req->query_string = buf;
380 wsgi_req->query_string_len = len;
381 return 0;
382 }
383
384 if (!uwsgi_proto_key("CONTENT_TYPE", 12)) {
385 wsgi_req->content_type = buf;
386 wsgi_req->content_type_len = len;
387 return 0;
388 }
389
390 if (!uwsgi_proto_key("HTTP_REFERER", 12)) {
391 wsgi_req->referer = buf;
392 wsgi_req->referer_len = len;
393 return 0;
394 }
395
396 if (!uwsgi_proto_key("UWSGI_SCHEME", 12)) {
397 wsgi_req->scheme = buf;
398 wsgi_req->scheme_len = len;
399 return 0;
400 }
401
402 if (!uwsgi_proto_key("UWSGI_SCRIPT", 12)) {
403 wsgi_req->script = buf;
404 wsgi_req->script_len = len;
405 wsgi_req->dynamic = 1;
406 return 0;
407 }
408
409 if (!uwsgi_proto_key("UWSGI_MODULE", 12)) {
410 wsgi_req->module = buf;
411 wsgi_req->module_len = len;
412 wsgi_req->dynamic = 1;
413 return 0;
414 }
415
416 if (!uwsgi_proto_key("UWSGI_PYHOME", 12)) {
417 wsgi_req->home = buf;
418 wsgi_req->home_len = len;
419 return 0;
420 }
421
422 if (!uwsgi_proto_key("UWSGI_SETENV", 12)) {
423 char *env_value = memchr(buf, '=', len);
424 if (env_value) {
425 env_value[0] = 0;
426 env_value = uwsgi_concat2n(env_value + 1, len - ((env_value + 1) - buf), "", 0);
427 if (setenv(buf, env_value, 1)) {
428 uwsgi_error("setenv()");
429 }
430 free(env_value);
431 }
432 return 0;
433 }
434 return 0;
435 }
436
uwsgi_proto_check_13(struct wsgi_request * wsgi_req,char * key,char * buf,uint16_t len)437 static int uwsgi_proto_check_13(struct wsgi_request *wsgi_req, char *key, char *buf, uint16_t len) {
438 if (!uwsgi_proto_key("DOCUMENT_ROOT", 13)) {
439 wsgi_req->document_root = buf;
440 wsgi_req->document_root_len = len;
441 return 0;
442 }
443 return 0;
444 }
445
uwsgi_proto_check_14(struct wsgi_request * wsgi_req,char * key,char * buf,uint16_t len)446 static int uwsgi_proto_check_14(struct wsgi_request *wsgi_req, char *key, char *buf, uint16_t len) {
447 if (!uwsgi_proto_key("REQUEST_METHOD", 14)) {
448 wsgi_req->method = buf;
449 wsgi_req->method_len = len;
450 return 0;
451 }
452
453 if (!uwsgi_proto_key("CONTENT_LENGTH", 14)) {
454 wsgi_req->post_cl = get_content_length(buf, len);
455 if (uwsgi.limit_post) {
456 if (wsgi_req->post_cl > uwsgi.limit_post) {
457 uwsgi_log("Invalid (too big) CONTENT_LENGTH. skip.\n");
458 return -1;
459 }
460 }
461 return 0;
462 }
463
464 if (!uwsgi_proto_key("UWSGI_POSTFILE", 14)) {
465 char *postfile = uwsgi_concat2n(buf, len, "", 0);
466 wsgi_req->post_file = fopen(postfile, "r");
467 if (!wsgi_req->post_file) {
468 uwsgi_error_open(postfile);
469 }
470 free(postfile);
471 return 0;
472 }
473
474 if (!uwsgi_proto_key("UWSGI_CALLABLE", 14)) {
475 wsgi_req->callable = buf;
476 wsgi_req->callable_len = len;
477 wsgi_req->dynamic = 1;
478 return 0;
479 }
480
481 return 0;
482 }
483
484
uwsgi_proto_check_15(struct wsgi_request * wsgi_req,char * key,char * buf,uint16_t len)485 static int uwsgi_proto_check_15(struct wsgi_request *wsgi_req, char *key, char *buf, uint16_t len) {
486 if (!uwsgi_proto_key("SERVER_PROTOCOL", 15)) {
487 wsgi_req->protocol = buf;
488 wsgi_req->protocol_len = len;
489 return 0;
490 }
491
492 if (!uwsgi_proto_key("HTTP_USER_AGENT", 15)) {
493 wsgi_req->user_agent = buf;
494 wsgi_req->user_agent_len = len;
495 return 0;
496 }
497
498 if (uwsgi.caches && !uwsgi_proto_key("UWSGI_CACHE_GET", 15)) {
499 wsgi_req->cache_get = buf;
500 wsgi_req->cache_get_len = len;
501 return 0;
502 }
503
504 return 0;
505 }
506
uwsgi_proto_check_18(struct wsgi_request * wsgi_req,char * key,char * buf,uint16_t len)507 static int uwsgi_proto_check_18(struct wsgi_request *wsgi_req, char *key, char *buf, uint16_t len) {
508 if (!uwsgi_proto_key("HTTP_AUTHORIZATION", 18)) {
509 wsgi_req->authorization = buf;
510 wsgi_req->authorization_len = len;
511 return 0;
512 }
513
514 if (!uwsgi_proto_key("UWSGI_TOUCH_RELOAD", 18)) {
515 wsgi_req->touch_reload = buf;
516 wsgi_req->touch_reload_len = len;
517 return 0;
518 }
519
520 return 0;
521 }
522
523
uwsgi_proto_check_20(struct wsgi_request * wsgi_req,char * key,char * buf,uint16_t len)524 static int uwsgi_proto_check_20(struct wsgi_request *wsgi_req, char *key, char *buf, uint16_t len) {
525 if (uwsgi.logging_options.log_x_forwarded_for && !uwsgi_proto_key("HTTP_X_FORWARDED_FOR", 20)) {
526 wsgi_req->remote_addr = buf;
527 wsgi_req->remote_addr_len = len;
528 return 0;
529 }
530
531 if (!uwsgi_proto_key("HTTP_X_FORWARDED_SSL", 20)) {
532 wsgi_req->https = buf;
533 wsgi_req->https_len = len;
534 }
535
536 if (!uwsgi_proto_key("HTTP_ACCEPT_ENCODING", 20)) {
537 wsgi_req->encoding = buf;
538 wsgi_req->encoding_len = len;
539 return 0;
540 }
541
542 return 0;
543 }
544
uwsgi_proto_check_22(struct wsgi_request * wsgi_req,char * key,char * buf,uint16_t len)545 static int uwsgi_proto_check_22(struct wsgi_request *wsgi_req, char *key, char *buf, uint16_t len) {
546 if (!uwsgi_proto_key("HTTP_IF_MODIFIED_SINCE", 22)) {
547 wsgi_req->if_modified_since = buf;
548 wsgi_req->if_modified_since_len = len;
549 return 0;
550 }
551
552 if (!uwsgi_proto_key("HTTP_SEC_WEBSOCKET_KEY", 22)) {
553 wsgi_req->http_sec_websocket_key = buf;
554 wsgi_req->http_sec_websocket_key_len = len;
555 return 0;
556 }
557
558 if (!uwsgi_proto_key("HTTP_X_FORWARDED_PROTO", 22)) {
559 wsgi_req->scheme = buf;
560 wsgi_req->scheme_len = len;
561 }
562
563 return 0;
564 }
565
uwsgi_proto_check_27(struct wsgi_request * wsgi_req,char * key,char * buf,uint16_t len)566 static int uwsgi_proto_check_27(struct wsgi_request *wsgi_req, char *key, char *buf, uint16_t len) {
567
568 if (!uwsgi_proto_key("HTTP_SEC_WEBSOCKET_PROTOCOL", 27)) {
569 wsgi_req->http_sec_websocket_protocol = buf;
570 wsgi_req->http_sec_websocket_protocol_len = len;
571 return 0;
572 }
573
574 return 0;
575 }
576
577
uwsgi_proto_hooks_setup()578 void uwsgi_proto_hooks_setup() {
579 int i = 0;
580 for(i=0;i<UWSGI_PROTO_MAX_CHECK;i++) {
581 uwsgi.proto_hooks[i] = NULL;
582 }
583
584 uwsgi.proto_hooks[5] = uwsgi_proto_check_5;
585 uwsgi.proto_hooks[9] = uwsgi_proto_check_9;
586 uwsgi.proto_hooks[10] = uwsgi_proto_check_10;
587 uwsgi.proto_hooks[11] = uwsgi_proto_check_11;
588 uwsgi.proto_hooks[12] = uwsgi_proto_check_12;
589 uwsgi.proto_hooks[13] = uwsgi_proto_check_13;
590 uwsgi.proto_hooks[14] = uwsgi_proto_check_14;
591 uwsgi.proto_hooks[15] = uwsgi_proto_check_15;
592 uwsgi.proto_hooks[18] = uwsgi_proto_check_18;
593 uwsgi.proto_hooks[20] = uwsgi_proto_check_20;
594 uwsgi.proto_hooks[22] = uwsgi_proto_check_22;
595 uwsgi.proto_hooks[27] = uwsgi_proto_check_27;
596 }
597
598
uwsgi_parse_vars(struct wsgi_request * wsgi_req)599 int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
600
601 char *buffer = wsgi_req->buffer;
602
603 char *ptrbuf, *bufferend;
604
605 uint16_t strsize = 0;
606 struct uwsgi_dyn_dict *udd;
607
608 ptrbuf = buffer;
609 bufferend = ptrbuf + wsgi_req->uh->pktsize;
610 int i;
611
612 /* set an HTTP 500 status as default */
613 wsgi_req->status = 500;
614
615 // skip if already parsed
616 if (wsgi_req->parsed)
617 return 0;
618
619 // has the protocol already parsed the request ?
620 if (wsgi_req->uri_len > 0) {
621 wsgi_req->parsed = 1;
622 i = uwsgi_simple_parse_vars(wsgi_req, ptrbuf, bufferend);
623 if (i == 0)
624 goto next;
625 return i;
626 }
627
628 wsgi_req->parsed = 1;
629 wsgi_req->script_name_pos = -1;
630 wsgi_req->path_info_pos = -1;
631
632 while (ptrbuf < bufferend) {
633 if (ptrbuf + 2 < bufferend) {
634 memcpy(&strsize, ptrbuf, 2);
635 #ifdef __BIG_ENDIAN__
636 strsize = uwsgi_swap16(strsize);
637 #endif
638 /* key cannot be null */
639 if (!strsize) {
640 uwsgi_log("uwsgi key cannot be null. skip this var.\n");
641 return -1;
642 }
643
644 ptrbuf += 2;
645 if (ptrbuf + strsize < bufferend) {
646 // var key
647 wsgi_req->hvec[wsgi_req->var_cnt].iov_base = ptrbuf;
648 wsgi_req->hvec[wsgi_req->var_cnt].iov_len = strsize;
649 ptrbuf += strsize;
650 // value can be null (even at the end) so use <=
651 if (ptrbuf + 2 <= bufferend) {
652 memcpy(&strsize, ptrbuf, 2);
653 #ifdef __BIG_ENDIAN__
654 strsize = uwsgi_swap16(strsize);
655 #endif
656 ptrbuf += 2;
657 if (ptrbuf + strsize <= bufferend) {
658 if (wsgi_req->hvec[wsgi_req->var_cnt].iov_len > UWSGI_PROTO_MIN_CHECK &&
659 wsgi_req->hvec[wsgi_req->var_cnt].iov_len < UWSGI_PROTO_MAX_CHECK &&
660 uwsgi.proto_hooks[wsgi_req->hvec[wsgi_req->var_cnt].iov_len]) {
661 if (uwsgi.proto_hooks[wsgi_req->hvec[wsgi_req->var_cnt].iov_len](wsgi_req, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, ptrbuf, strsize)) {
662 return -1;
663 }
664 }
665 //uwsgi_log("uwsgi %.*s = %.*s\n", wsgi_req->hvec[wsgi_req->var_cnt].iov_len, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, strsize, ptrbuf);
666
667 if (wsgi_req->var_cnt < uwsgi.vec_size - (4 + 1)) {
668 wsgi_req->var_cnt++;
669 }
670 else {
671 uwsgi_log("max vec size reached. skip this var.\n");
672 return -1;
673 }
674 // var value
675 wsgi_req->hvec[wsgi_req->var_cnt].iov_base = ptrbuf;
676 wsgi_req->hvec[wsgi_req->var_cnt].iov_len = strsize;
677 //uwsgi_log("%.*s = %.*s\n", wsgi_req->hvec[wsgi_req->var_cnt-1].iov_len, wsgi_req->hvec[wsgi_req->var_cnt-1].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len, wsgi_req->hvec[wsgi_req->var_cnt].iov_base);
678 if (wsgi_req->var_cnt < uwsgi.vec_size - (4 + 1)) {
679 wsgi_req->var_cnt++;
680 }
681 else {
682 uwsgi_log("max vec size reached. skip this var.\n");
683 return -1;
684 }
685 ptrbuf += strsize;
686 }
687 else {
688 uwsgi_log("invalid uwsgi request (current strsize: %d). skip.\n", strsize);
689 return -1;
690 }
691 }
692 else {
693 uwsgi_log("invalid uwsgi request (current strsize: %d). skip.\n", strsize);
694 return -1;
695 }
696 }
697 }
698 else {
699 uwsgi_log("invalid uwsgi request (current strsize: %d). skip.\n", strsize);
700 return -1;
701 }
702 }
703
704 next:
705
706 // manage post buffering (if needed as post_file could be created before)
707 if (uwsgi.post_buffering > 0 && !wsgi_req->post_file) {
708 // read to disk if post_cl > post_buffering (it will eventually do upload progress...)
709 if (wsgi_req->post_cl >= uwsgi.post_buffering) {
710 if (uwsgi_postbuffer_do_in_disk(wsgi_req)) {
711 return -1;
712 }
713 }
714 // on tiny post use memory
715 else {
716 if (uwsgi_postbuffer_do_in_mem(wsgi_req)) {
717 return -1;
718 }
719 }
720 }
721
722
723 // check if data are available in the local cache
724 if (wsgi_req->cache_get_len > 0) {
725 uint64_t cache_value_size;
726 char *cache_value = uwsgi_cache_magic_get(wsgi_req->cache_get, wsgi_req->cache_get_len, &cache_value_size, NULL, NULL);
727 if (cache_value && cache_value_size > 0) {
728 uwsgi_response_write_body_do(wsgi_req, cache_value, cache_value_size);
729 free(cache_value);
730 return -1;
731 }
732 }
733
734 if (uwsgi.check_cache && wsgi_req->uri_len && wsgi_req->method_len == 3 && wsgi_req->method[0] == 'G' && wsgi_req->method[1] == 'E' && wsgi_req->method[2] == 'T') {
735
736 uint64_t cache_value_size;
737 char *cache_value = uwsgi_cache_magic_get(wsgi_req->uri, wsgi_req->uri_len, &cache_value_size, NULL, NULL);
738 if (cache_value && cache_value_size > 0) {
739 uwsgi_response_write_body_do(wsgi_req, cache_value, cache_value_size);
740 free(cache_value);
741 return -1;
742 }
743 }
744
745 if (uwsgi.manage_script_name) {
746 if (uwsgi_apps_cnt > 0 && wsgi_req->path_info_len > 1 && wsgi_req->path_info_pos != -1) {
747 // starts with 1 as the 0 app is the default (/) one
748 int best_found = 0;
749 char *orig_path_info = wsgi_req->path_info;
750 int orig_path_info_len = wsgi_req->path_info_len;
751 // if SCRIPT_NAME is not allocated, add a slot for it
752 if (wsgi_req->script_name_pos == -1) {
753 if (wsgi_req->var_cnt >= uwsgi.vec_size - (4 + 2)) {
754 uwsgi_log("max vec size reached. skip this var.\n");
755 return -1;
756 }
757 wsgi_req->hvec[wsgi_req->var_cnt].iov_base = "SCRIPT_NAME";
758 wsgi_req->hvec[wsgi_req->var_cnt].iov_len = 11;
759 wsgi_req->var_cnt++;
760 wsgi_req->script_name_pos = wsgi_req->var_cnt;
761 wsgi_req->hvec[wsgi_req->script_name_pos].iov_base = "";
762 wsgi_req->hvec[wsgi_req->script_name_pos].iov_len = 0;
763 wsgi_req->var_cnt++;
764 }
765
766 for (i = 0; i < uwsgi_apps_cnt; i++) {
767 char* mountpoint = uwsgi_apps[i].mountpoint;
768 int mountpoint_len = uwsgi_apps[i].mountpoint_len;
769
770 // Ignore trailing mountpoint slashes
771 if (mountpoint_len > 0 && mountpoint[mountpoint_len - 1] == '/') {
772 mountpoint_len -= 1;
773 }
774
775 //uwsgi_log("app mountpoint = %.*s\n", uwsgi_apps[i].mountpoint_len, uwsgi_apps[i].mountpoint);
776
777 // Check if mountpoint could be a possible candidate
778 if (orig_path_info_len < mountpoint_len || // it should be shorter than or equal to path_info
779 mountpoint_len <= best_found || // it should be better than the previous found
780 // should have the same prefix of path_info
781 uwsgi_startswith(orig_path_info, mountpoint, mountpoint_len) ||
782 // and should not be "misleading"
783 (orig_path_info_len > mountpoint_len && orig_path_info[mountpoint_len] != '/' )) {
784 continue;
785 }
786
787 best_found = mountpoint_len;
788 wsgi_req->script_name = uwsgi_apps[i].mountpoint;
789 wsgi_req->script_name_len = uwsgi_apps[i].mountpoint_len;
790 wsgi_req->path_info = orig_path_info + wsgi_req->script_name_len;
791 wsgi_req->path_info_len = orig_path_info_len - wsgi_req->script_name_len;
792
793 wsgi_req->hvec[wsgi_req->script_name_pos].iov_base = wsgi_req->script_name;
794 wsgi_req->hvec[wsgi_req->script_name_pos].iov_len = wsgi_req->script_name_len;
795
796 wsgi_req->hvec[wsgi_req->path_info_pos].iov_base = wsgi_req->path_info;
797 wsgi_req->hvec[wsgi_req->path_info_pos].iov_len = wsgi_req->path_info_len;
798 #ifdef UWSGI_DEBUG
799 uwsgi_log("managed SCRIPT_NAME = %.*s PATH_INFO = %.*s\n", wsgi_req->script_name_len, wsgi_req->script_name, wsgi_req->path_info_len, wsgi_req->path_info);
800 #endif
801 }
802 }
803 }
804
805
806 /* CHECK FOR STATIC FILES */
807
808 // skip extensions
809 struct uwsgi_string_list *sse = uwsgi.static_skip_ext;
810 while (sse) {
811 if (wsgi_req->path_info_len >= sse->len) {
812 if (!uwsgi_strncmp(wsgi_req->path_info + (wsgi_req->path_info_len - sse->len), sse->len, sse->value, sse->len)) {
813 return 0;
814 }
815 }
816 sse = sse->next;
817 }
818
819 // check if a file named uwsgi.check_static+env['PATH_INFO'] exists
820 udd = uwsgi.check_static;
821 while (udd) {
822 // need to build the path ?
823 if (udd->value == NULL) {
824 if (uwsgi.threads > 1)
825 pthread_mutex_lock(&uwsgi.lock_static);
826 udd->value = uwsgi_malloc(PATH_MAX + 1);
827 if (!realpath(udd->key, udd->value)) {
828 free(udd->value);
829 udd->value = NULL;
830 }
831 if (uwsgi.threads > 1)
832 pthread_mutex_unlock(&uwsgi.lock_static);
833 if (!udd->value)
834 goto nextcs;
835 udd->vallen = strlen(udd->value);
836 }
837
838 if (!uwsgi_file_serve(wsgi_req, udd->value, udd->vallen, wsgi_req->path_info, wsgi_req->path_info_len, 0)) {
839 return -1;
840 }
841 nextcs:
842 udd = udd->next;
843 }
844
845 // check static-map
846 udd = uwsgi.static_maps;
847 while (udd) {
848 #ifdef UWSGI_DEBUG
849 uwsgi_log("checking for %.*s <-> %.*s %.*s\n", (int)wsgi_req->path_info_len, wsgi_req->path_info, (int)udd->keylen, udd->key, (int) udd->vallen, udd->value);
850 #endif
851 if (udd->status == 0) {
852 if (uwsgi.threads > 1)
853 pthread_mutex_lock(&uwsgi.lock_static);
854 char *real_docroot = uwsgi_malloc(PATH_MAX + 1);
855 if (!realpath(udd->value, real_docroot)) {
856 free(real_docroot);
857 real_docroot = NULL;
858 udd->value = NULL;
859 }
860 if (uwsgi.threads > 1)
861 pthread_mutex_unlock(&uwsgi.lock_static);
862 if (!real_docroot)
863 goto nextsm;
864 udd->value = real_docroot;
865 udd->vallen = strlen(udd->value);
866 udd->status = 1 + uwsgi_is_file(real_docroot);
867 }
868
869 if (!uwsgi_starts_with(wsgi_req->path_info, wsgi_req->path_info_len, udd->key, udd->keylen)) {
870 if (!uwsgi_file_serve(wsgi_req, udd->value, udd->vallen, wsgi_req->path_info + udd->keylen, wsgi_req->path_info_len - udd->keylen, udd->status - 1)) {
871 return -1;
872 }
873 }
874 nextsm:
875 udd = udd->next;
876 }
877
878 // check for static_maps in append mode
879 udd = uwsgi.static_maps2;
880 while (udd) {
881 #ifdef UWSGI_DEBUG
882 uwsgi_log("checking for %.*s <-> %.*s\n", wsgi_req->path_info_len, wsgi_req->path_info, udd->keylen, udd->key);
883 #endif
884 if (udd->status == 0) {
885 if (uwsgi.threads > 1)
886 pthread_mutex_lock(&uwsgi.lock_static);
887 char *real_docroot = uwsgi_malloc(PATH_MAX + 1);
888 if (!realpath(udd->value, real_docroot)) {
889 free(real_docroot);
890 real_docroot = NULL;
891 udd->value = NULL;
892 }
893 if (uwsgi.threads > 1)
894 pthread_mutex_unlock(&uwsgi.lock_static);
895 if (!real_docroot)
896 goto nextsm2;
897 udd->value = real_docroot;
898 udd->vallen = strlen(udd->value);
899 udd->status = 1 + uwsgi_is_file(real_docroot);
900 }
901
902 if (!uwsgi_starts_with(wsgi_req->path_info, wsgi_req->path_info_len, udd->key, udd->keylen)) {
903 if (!uwsgi_file_serve(wsgi_req, udd->value, udd->vallen, wsgi_req->path_info, wsgi_req->path_info_len, udd->status - 1)) {
904 return -1;
905 }
906 }
907 nextsm2:
908 udd = udd->next;
909 }
910
911
912 // finally check for docroot
913 if (uwsgi.check_static_docroot && wsgi_req->document_root_len > 0) {
914 char *real_docroot = uwsgi_expand_path(wsgi_req->document_root, wsgi_req->document_root_len, NULL);
915 if (!real_docroot) {
916 return -1;
917 }
918 if (!uwsgi_file_serve(wsgi_req, real_docroot, strlen(real_docroot), wsgi_req->path_info, wsgi_req->path_info_len, 0)) {
919 free(real_docroot);
920 return -1;
921 }
922 free(real_docroot);
923 }
924
925 return 0;
926 }
927
uwsgi_hooked_parse(char * buffer,size_t len,void (* hook)(char *,uint16_t,char *,uint16_t,void *),void * data)928 int uwsgi_hooked_parse(char *buffer, size_t len, void (*hook) (char *, uint16_t, char *, uint16_t, void *), void *data) {
929
930 char *ptrbuf, *bufferend;
931 uint16_t keysize = 0, valsize = 0;
932 char *key;
933
934 ptrbuf = buffer;
935 bufferend = buffer + len;
936
937 while (ptrbuf < bufferend) {
938 if (ptrbuf + 2 >= bufferend)
939 return -1;
940 memcpy(&keysize, ptrbuf, 2);
941 #ifdef __BIG_ENDIAN__
942 keysize = uwsgi_swap16(keysize);
943 #endif
944 /* key cannot be null */
945 if (!keysize)
946 return -1;
947
948 ptrbuf += 2;
949 if (ptrbuf + keysize > bufferend)
950 return -1;
951
952 // key
953 key = ptrbuf;
954 ptrbuf += keysize;
955 // value can be null
956 if (ptrbuf + 2 > bufferend)
957 return -1;
958
959 memcpy(&valsize, ptrbuf, 2);
960 #ifdef __BIG_ENDIAN__
961 valsize = uwsgi_swap16(valsize);
962 #endif
963 ptrbuf += 2;
964 if (ptrbuf + valsize > bufferend)
965 return -1;
966
967 // now call the hook
968 hook(key, keysize, ptrbuf, valsize, data);
969 ptrbuf += valsize;
970 }
971
972 return 0;
973
974 }
975
uwsgi_hooked_parse_array(char * buffer,size_t len,void (* hook)(uint16_t,char *,uint16_t,void *),void * data)976 int uwsgi_hooked_parse_array(char *buffer, size_t len, void (*hook) (uint16_t, char *, uint16_t, void *), void *data) {
977
978 char *ptrbuf, *bufferend;
979 uint16_t valsize = 0;
980 char *value;
981 uint16_t pos = 0;
982
983 ptrbuf = buffer;
984 bufferend = buffer + len;
985
986 while (ptrbuf < bufferend) {
987 if (ptrbuf + 2 > bufferend)
988 return -1;
989 memcpy(&valsize, ptrbuf, 2);
990 #ifdef __BIG_ENDIAN__
991 valsize = uwsgi_swap16(valsize);
992 #endif
993 ptrbuf += 2;
994 if (ptrbuf + valsize > bufferend)
995 return -1;
996
997 // key
998 value = ptrbuf;
999 // now call the hook
1000 hook(pos, value, valsize, data);
1001 ptrbuf += valsize;
1002 pos++;
1003 }
1004
1005 return 0;
1006
1007 }
1008
1009
1010 // this functions transform a raw HTTP response to a uWSGI-managed response
uwsgi_blob_to_response(struct wsgi_request * wsgi_req,char * body,size_t len)1011 int uwsgi_blob_to_response(struct wsgi_request *wsgi_req, char *body, size_t len) {
1012 char *line = body;
1013 size_t line_len = 0;
1014 size_t i;
1015 int status_managed = 0;
1016 for(i=0;i<len;i++) {
1017 if (body[i] == '\n') {
1018 // invalid line
1019 if (line_len < 1) {
1020 return -1;
1021 }
1022 if (line[line_len-1] != '\r') {
1023 return -1;
1024 }
1025 // end of the headers
1026 if (line_len == 1) {
1027 break;
1028 }
1029
1030 if (status_managed) {
1031 char *colon = memchr(line, ':', line_len-1);
1032 if (!colon) return -1;
1033 if (colon[1] != ' ') return -1;
1034 if (uwsgi_response_add_header(wsgi_req, line, colon-line, colon+2, (line_len-1) - ((colon+2)-line))) return -1;
1035 }
1036 else {
1037 char *space = memchr(line, ' ', line_len-1);
1038 if (!space) return -1;
1039 if ((line_len-1) - ((space+1)-line) < 3) return -1;
1040 if (uwsgi_response_prepare_headers(wsgi_req, space+1, (line_len-1) - ((space+1)-line))) return -1;
1041 status_managed = 1;
1042 }
1043 line = NULL;
1044 line_len = 0;
1045 }
1046 else {
1047 if (!line) {
1048 line = body + i;
1049 }
1050 line_len++;
1051 }
1052 }
1053
1054 if ((i+1) < len) {
1055 if (uwsgi_response_write_body_do(wsgi_req, body + (i + 1), len-(i+1))) {
1056 return -1;
1057 }
1058 }
1059
1060 return 0;
1061 }
1062
1063 /*
1064
1065 the following functions need to take in account that POST data could be already available in wsgi_req->buffer (generally when uwsgi protocol is in use)
1066
1067 In such a case, allocate a proto_parser_buf and move data there
1068
1069 */
1070
uwsgi_req_append(struct wsgi_request * wsgi_req,char * key,uint16_t keylen,char * val,uint16_t vallen)1071 char *uwsgi_req_append(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, char *val, uint16_t vallen) {
1072
1073 if (!wsgi_req->proto_parser_buf) {
1074 if (wsgi_req->proto_parser_remains > 0) {
1075 wsgi_req->proto_parser_buf = uwsgi_malloc(wsgi_req->proto_parser_remains);
1076 memcpy(wsgi_req->proto_parser_buf, wsgi_req->proto_parser_remains_buf, wsgi_req->proto_parser_remains);
1077 wsgi_req->proto_parser_remains_buf = wsgi_req->proto_parser_buf;
1078 }
1079 }
1080
1081 if ((wsgi_req->uh->pktsize + (2 + keylen + 2 + vallen)) > uwsgi.buffer_size) {
1082 uwsgi_log("not enough buffer space to add %.*s variable, consider increasing it with the --buffer-size option\n", keylen, key);
1083 return NULL;
1084 }
1085
1086 if (wsgi_req->var_cnt >= uwsgi.vec_size - (4 + 2)) {
1087 uwsgi_log("max vec size reached. skip this header.\n");
1088 return NULL;
1089 }
1090
1091 char *ptr = wsgi_req->buffer + wsgi_req->uh->pktsize;
1092
1093 *ptr++ = (uint8_t) (keylen & 0xff);
1094 *ptr++ = (uint8_t) ((keylen >> 8) & 0xff);
1095
1096 memcpy(ptr, key, keylen);
1097 wsgi_req->hvec[wsgi_req->var_cnt].iov_base = ptr;
1098 wsgi_req->hvec[wsgi_req->var_cnt].iov_len = keylen;
1099 wsgi_req->var_cnt++;
1100 ptr += keylen;
1101
1102
1103
1104 *ptr++ = (uint8_t) (vallen & 0xff);
1105 *ptr++ = (uint8_t) ((vallen >> 8) & 0xff);
1106
1107 memcpy(ptr, val, vallen);
1108 wsgi_req->hvec[wsgi_req->var_cnt].iov_base = ptr;
1109 wsgi_req->hvec[wsgi_req->var_cnt].iov_len = vallen;
1110 wsgi_req->var_cnt++;
1111
1112 wsgi_req->uh->pktsize += (2 + keylen + 2 + vallen);
1113
1114 return ptr;
1115 }
1116
uwsgi_req_append_path_info_with_index(struct wsgi_request * wsgi_req,char * index,uint16_t index_len)1117 int uwsgi_req_append_path_info_with_index(struct wsgi_request *wsgi_req, char *index, uint16_t index_len) {
1118
1119 if (!wsgi_req->proto_parser_buf) {
1120 if (wsgi_req->proto_parser_remains > 0) {
1121 wsgi_req->proto_parser_buf = uwsgi_malloc(wsgi_req->proto_parser_remains);
1122 memcpy(wsgi_req->proto_parser_buf, wsgi_req->proto_parser_remains_buf, wsgi_req->proto_parser_remains);
1123 wsgi_req->proto_parser_remains_buf = wsgi_req->proto_parser_buf;
1124 }
1125 }
1126
1127 uint8_t need_slash = 0;
1128 if (wsgi_req->path_info_len > 0) {
1129 if (wsgi_req->path_info[wsgi_req->path_info_len-1] != '/') {
1130 need_slash = 1;
1131 }
1132 }
1133
1134 wsgi_req->path_info_len += need_slash + index_len;
1135
1136 // 2 + 9 + 2
1137 if ((wsgi_req->uh->pktsize + (13 + wsgi_req->path_info_len)) > uwsgi.buffer_size) {
1138 uwsgi_log("not enough buffer space to transform the PATH_INFO variable, consider increasing it with the --buffer-size option\n");
1139 return -1;
1140 }
1141
1142 if (wsgi_req->var_cnt >= uwsgi.vec_size - (4 + 2)) {
1143 uwsgi_log("max vec size reached for PATH_INFO + index. skip this request.\n");
1144 return -1;
1145 }
1146
1147 uint16_t keylen = 9;
1148 char *ptr = wsgi_req->buffer + wsgi_req->uh->pktsize;
1149 *ptr++ = (uint8_t) (keylen & 0xff);
1150 *ptr++ = (uint8_t) ((keylen >> 8) & 0xff);
1151
1152 memcpy(ptr, "PATH_INFO", keylen);
1153 wsgi_req->hvec[wsgi_req->var_cnt].iov_base = ptr;
1154 wsgi_req->hvec[wsgi_req->var_cnt].iov_len = keylen;
1155 wsgi_req->var_cnt++;
1156 ptr += keylen;
1157
1158 *ptr++ = (uint8_t) (wsgi_req->path_info_len & 0xff);
1159 *ptr++ = (uint8_t) ((wsgi_req->path_info_len >> 8) & 0xff);
1160
1161 char *new_path_info = ptr;
1162
1163 memcpy(ptr, wsgi_req->path_info, wsgi_req->path_info_len - (need_slash + index_len));
1164 ptr+=wsgi_req->path_info_len - (need_slash + index_len);
1165 if (need_slash) {
1166 *ptr ++= '/';
1167 }
1168 memcpy(ptr, index, index_len);
1169
1170 wsgi_req->hvec[wsgi_req->var_cnt].iov_base = new_path_info;
1171 wsgi_req->hvec[wsgi_req->var_cnt].iov_len = wsgi_req->path_info_len;
1172 wsgi_req->var_cnt++;
1173
1174 wsgi_req->uh->pktsize += 13 + wsgi_req->path_info_len;
1175 wsgi_req->path_info = new_path_info;
1176
1177 return 0;
1178 }
1179