1 
2 /*
3  * Copyright (C) Igor Sysoev
4  * Copyright (C) NGINX, Inc.
5  */
6 
7 #include <nxt_router.h>
8 #include <nxt_http.h>
9 
10 
11 static nxt_int_t nxt_http_validate_host(nxt_str_t *host, nxt_mp_t *mp);
12 static void nxt_http_request_start(nxt_task_t *task, void *obj, void *data);
13 static nxt_int_t nxt_http_request_client_ip(nxt_task_t *task,
14     nxt_http_request_t *r);
15 static nxt_sockaddr_t *nxt_http_request_client_ip_sockaddr(
16     nxt_http_request_t *r, u_char *start, size_t len);
17 static void nxt_http_request_ready(nxt_task_t *task, void *obj, void *data);
18 static void nxt_http_request_proto_info(nxt_task_t *task,
19     nxt_http_request_t *r);
20 static void nxt_http_request_mem_buf_completion(nxt_task_t *task, void *obj,
21     void *data);
22 static void nxt_http_request_done(nxt_task_t *task, void *obj, void *data);
23 
24 static u_char *nxt_http_date_cache_handler(u_char *buf, nxt_realtime_t *now,
25     struct tm *tm, size_t size, const char *format);
26 
27 
28 static const nxt_http_request_state_t  nxt_http_request_init_state;
29 static const nxt_http_request_state_t  nxt_http_request_body_state;
30 
31 
32 nxt_time_string_t  nxt_http_date_cache = {
33     (nxt_atomic_uint_t) -1,
34     nxt_http_date_cache_handler,
35     NULL,
36     NXT_HTTP_DATE_LEN,
37     NXT_THREAD_TIME_GMT,
38     NXT_THREAD_TIME_SEC,
39 };
40 
41 
42 nxt_int_t
nxt_http_init(nxt_task_t * task)43 nxt_http_init(nxt_task_t *task)
44 {
45     nxt_int_t  ret;
46 
47     ret = nxt_h1p_init(task);
48 
49     if (ret != NXT_OK) {
50         return ret;
51     }
52 
53     return nxt_http_response_hash_init(task);
54 }
55 
56 
57 nxt_int_t
nxt_http_request_host(void * ctx,nxt_http_field_t * field,uintptr_t data)58 nxt_http_request_host(void *ctx, nxt_http_field_t *field, uintptr_t data)
59 {
60     nxt_int_t           ret;
61     nxt_str_t           host;
62     nxt_http_request_t  *r;
63 
64     r = ctx;
65 
66     if (nxt_slow_path(r->host.start != NULL)) {
67         return NXT_HTTP_BAD_REQUEST;
68     }
69 
70     host.length = field->value_length;
71     host.start = field->value;
72 
73     ret = nxt_http_validate_host(&host, r->mem_pool);
74 
75     if (nxt_fast_path(ret == NXT_OK)) {
76         r->host = host;
77     }
78 
79     return ret;
80 }
81 
82 
83 static nxt_int_t
nxt_http_validate_host(nxt_str_t * host,nxt_mp_t * mp)84 nxt_http_validate_host(nxt_str_t *host, nxt_mp_t *mp)
85 {
86     u_char      *h, ch;
87     size_t      i, dot_pos, host_length;
88     nxt_bool_t  lowcase;
89 
90     enum {
91         sw_usual,
92         sw_literal,
93         sw_rest
94     } state;
95 
96     dot_pos = host->length;
97     host_length = host->length;
98 
99     h = host->start;
100 
101     lowcase = 0;
102     state = sw_usual;
103 
104     for (i = 0; i < host->length; i++) {
105         ch = h[i];
106 
107         if (ch > ']') {
108             /* Short path. */
109             continue;
110         }
111 
112         switch (ch) {
113 
114         case '.':
115             if (dot_pos == i - 1) {
116                 return NXT_HTTP_BAD_REQUEST;
117             }
118 
119             dot_pos = i;
120             break;
121 
122         case ':':
123             if (state == sw_usual) {
124                 host_length = i;
125                 state = sw_rest;
126             }
127 
128             break;
129 
130         case '[':
131             if (i == 0) {
132                 state = sw_literal;
133             }
134 
135             break;
136 
137         case ']':
138             if (state == sw_literal) {
139                 host_length = i + 1;
140                 state = sw_rest;
141             }
142 
143             break;
144 
145         case '/':
146             return NXT_HTTP_BAD_REQUEST;
147 
148         default:
149             if (ch >= 'A' && ch <= 'Z') {
150                 lowcase = 1;
151             }
152 
153             break;
154         }
155     }
156 
157     if (dot_pos == host_length - 1) {
158         host_length--;
159     }
160 
161     host->length = host_length;
162 
163     if (lowcase) {
164         host->start = nxt_mp_nget(mp, host_length);
165         if (nxt_slow_path(host->start == NULL)) {
166             return NXT_HTTP_INTERNAL_SERVER_ERROR;
167         }
168 
169         nxt_memcpy_lowcase(host->start, h, host_length);
170     }
171 
172     return NXT_OK;
173 }
174 
175 
176 nxt_int_t
nxt_http_request_field(void * ctx,nxt_http_field_t * field,uintptr_t offset)177 nxt_http_request_field(void *ctx, nxt_http_field_t *field, uintptr_t offset)
178 {
179     nxt_http_request_t  *r;
180 
181     r = ctx;
182 
183     nxt_value_at(nxt_http_field_t *, r, offset) = field;
184 
185     return NXT_OK;
186 }
187 
188 
189 nxt_int_t
nxt_http_request_content_length(void * ctx,nxt_http_field_t * field,uintptr_t data)190 nxt_http_request_content_length(void *ctx, nxt_http_field_t *field,
191     uintptr_t data)
192 {
193     nxt_off_t           n, max_body_size;
194     nxt_http_request_t  *r;
195 
196     r = ctx;
197 
198     if (nxt_fast_path(r->content_length == NULL)) {
199         r->content_length = field;
200 
201         n = nxt_off_t_parse(field->value, field->value_length);
202 
203         if (nxt_fast_path(n >= 0)) {
204             r->content_length_n = n;
205 
206             max_body_size = r->conf->socket_conf->max_body_size;
207 
208             if (nxt_slow_path(n > max_body_size)) {
209                 return NXT_HTTP_PAYLOAD_TOO_LARGE;
210             }
211 
212             return NXT_OK;
213         }
214     }
215 
216     return NXT_HTTP_BAD_REQUEST;
217 }
218 
219 
220 nxt_http_request_t *
nxt_http_request_create(nxt_task_t * task)221 nxt_http_request_create(nxt_task_t *task)
222 {
223     nxt_mp_t            *mp;
224     nxt_buf_t           *last;
225     nxt_http_request_t  *r;
226 
227     mp = nxt_mp_create(4096, 128, 512, 32);
228     if (nxt_slow_path(mp == NULL)) {
229         return NULL;
230     }
231 
232     r = nxt_mp_zget(mp, sizeof(nxt_http_request_t));
233     if (nxt_slow_path(r == NULL)) {
234         goto fail;
235     }
236 
237     r->resp.fields = nxt_list_create(mp, 8, sizeof(nxt_http_field_t));
238     if (nxt_slow_path(r->resp.fields == NULL)) {
239         goto fail;
240     }
241 
242     last = nxt_mp_zget(mp, NXT_BUF_SYNC_SIZE);
243     if (nxt_slow_path(last == NULL)) {
244         goto fail;
245     }
246 
247     nxt_buf_set_sync(last);
248     nxt_buf_set_last(last);
249     last->completion_handler = nxt_http_request_done;
250     last->parent = r;
251     r->last = last;
252 
253     r->mem_pool = mp;
254     r->content_length_n = -1;
255     r->resp.content_length_n = -1;
256     r->state = &nxt_http_request_init_state;
257 
258     return r;
259 
260 fail:
261 
262     nxt_mp_release(mp);
263 
264     return NULL;
265 }
266 
267 
268 static const nxt_http_request_state_t  nxt_http_request_init_state
269     nxt_aligned(64) =
270 {
271     .ready_handler = nxt_http_request_start,
272     .error_handler = nxt_http_request_close_handler,
273 };
274 
275 
276 static void
nxt_http_request_start(nxt_task_t * task,void * obj,void * data)277 nxt_http_request_start(nxt_task_t *task, void *obj, void *data)
278 {
279     nxt_int_t           ret;
280     nxt_http_request_t  *r;
281 
282     r = obj;
283 
284     r->state = &nxt_http_request_body_state;
285 
286     ret = nxt_http_request_client_ip(task, r);
287     if (nxt_slow_path(ret != NXT_OK)) {
288         nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR);
289     }
290 
291     nxt_http_request_read_body(task, r);
292 }
293 
294 
295 static nxt_int_t
nxt_http_request_client_ip(nxt_task_t * task,nxt_http_request_t * r)296 nxt_http_request_client_ip(nxt_task_t *task, nxt_http_request_t *r)
297 {
298     u_char                *start, *p;
299     nxt_int_t             ret, i, len;
300     nxt_str_t             *header;
301     nxt_array_t           *fields_arr;  /* of nxt_http_field_t * */
302     nxt_sockaddr_t        *sa, *prev_sa;
303     nxt_http_field_t      *f, **fields;
304     nxt_http_client_ip_t  *client_ip;
305 
306     client_ip = r->conf->socket_conf->client_ip;
307 
308     if (client_ip == NULL) {
309         return NXT_OK;
310     }
311 
312     ret = nxt_http_route_addr_rule(r, client_ip->source, r->remote);
313     if (ret <= 0) {
314         return NXT_OK;
315     }
316 
317     header = client_ip->header;
318 
319     fields_arr = nxt_array_create(r->mem_pool, 2, sizeof(nxt_http_field_t *));
320     if (nxt_slow_path(fields_arr == NULL)) {
321         return NXT_ERROR;
322     }
323 
324     nxt_list_each(f, r->fields) {
325         if (f->hash == client_ip->header_hash
326             && f->name_length == client_ip->header->length
327             && f->value_length > 0
328             && nxt_memcasecmp(f->name, header->start, header->length) == 0)
329         {
330             fields = nxt_array_add(fields_arr);
331             if (nxt_slow_path(fields == NULL)) {
332                 return NXT_ERROR;
333             }
334 
335             *fields = f;
336         }
337     } nxt_list_loop;
338 
339     prev_sa = r->remote;
340     fields = (nxt_http_field_t **) fields_arr->elts;
341 
342     i = fields_arr->nelts;
343 
344     while (i-- > 0) {
345         f = fields[i];
346         start = f->value;
347         len = f->value_length;
348 
349         do {
350             for (p = start + len - 1; p > start; p--, len--) {
351                 if (*p != ' ' && *p != ',') {
352                     break;
353                 }
354             }
355 
356             for (/* void */; p > start; p--) {
357                 if (*p == ' ' || *p == ',') {
358                     p++;
359                     break;
360                 }
361             }
362 
363             sa = nxt_http_request_client_ip_sockaddr(r, p, len - (p - start));
364             if (nxt_slow_path(sa == NULL)) {
365                 if (prev_sa != NULL) {
366                     r->remote = prev_sa;
367                 }
368 
369                 return NXT_OK;
370             }
371 
372             if (!client_ip->recursive) {
373                 r->remote = sa;
374 
375                 return NXT_OK;
376             }
377 
378             ret = nxt_http_route_addr_rule(r, client_ip->source, sa);
379             if (ret <= 0 || (i == 0 && p == start)) {
380                 r->remote = sa;
381 
382                 return NXT_OK;
383             }
384 
385             prev_sa = sa;
386             len = p - 1 - start;
387 
388         } while (len > 0);
389     }
390 
391     return NXT_OK;
392 }
393 
394 
395 static nxt_sockaddr_t *
nxt_http_request_client_ip_sockaddr(nxt_http_request_t * r,u_char * start,size_t len)396 nxt_http_request_client_ip_sockaddr(nxt_http_request_t *r, u_char *start,
397     size_t len)
398 {
399     nxt_str_t       addr;
400     nxt_sockaddr_t  *sa;
401 
402     addr.start = start;
403     addr.length = len;
404 
405     sa = nxt_sockaddr_parse_optport(r->mem_pool, &addr);
406     if (nxt_slow_path(sa == NULL)) {
407         return NULL;
408     }
409 
410     switch (sa->u.sockaddr.sa_family) {
411         case AF_INET:
412             if (sa->u.sockaddr_in.sin_addr.s_addr == INADDR_ANY) {
413                 return NULL;
414             }
415 
416             break;
417 
418 #if (NXT_INET6)
419         case AF_INET6:
420             if (IN6_IS_ADDR_UNSPECIFIED(&sa->u.sockaddr_in6.sin6_addr)) {
421                 return NULL;
422             }
423 
424             break;
425 #endif /* NXT_INET6 */
426 
427         default:
428             return NULL;
429     }
430 
431     return sa;
432 }
433 
434 
435 static const nxt_http_request_state_t  nxt_http_request_body_state
436     nxt_aligned(64) =
437 {
438     .ready_handler = nxt_http_request_ready,
439     .error_handler = nxt_http_request_close_handler,
440 };
441 
442 
443 static void
nxt_http_request_ready(nxt_task_t * task,void * obj,void * data)444 nxt_http_request_ready(nxt_task_t *task, void *obj, void *data)
445 {
446     nxt_http_action_t   *action;
447     nxt_http_request_t  *r;
448 
449     r = obj;
450     action = r->conf->socket_conf->action;
451 
452     nxt_http_request_action(task, r, action);
453 }
454 
455 
456 void
nxt_http_request_action(nxt_task_t * task,nxt_http_request_t * r,nxt_http_action_t * action)457 nxt_http_request_action(nxt_task_t *task, nxt_http_request_t *r,
458     nxt_http_action_t *action)
459 {
460     if (nxt_fast_path(action != NULL)) {
461 
462         do {
463             action = action->handler(task, r, action);
464 
465             if (action == NULL) {
466                 return;
467             }
468 
469             if (action == NXT_HTTP_ACTION_ERROR) {
470                 break;
471             }
472 
473         } while (r->pass_count++ < 255);
474     }
475 
476     nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR);
477 }
478 
479 
480 nxt_http_action_t *
nxt_http_application_handler(nxt_task_t * task,nxt_http_request_t * r,nxt_http_action_t * action)481 nxt_http_application_handler(nxt_task_t *task, nxt_http_request_t *r,
482     nxt_http_action_t *action)
483 {
484     nxt_debug(task, "http application handler");
485 
486     /*
487      * TODO: need an application flag to get local address
488      * required by "SERVER_ADDR" in Pyhton and PHP. Not used in Go.
489      */
490     nxt_http_request_proto_info(task, r);
491 
492     if (r->host.length != 0) {
493         r->server_name = r->host;
494 
495     } else {
496         nxt_str_set(&r->server_name, "localhost");
497     }
498 
499     nxt_router_process_http_request(task, r, action);
500 
501     return NULL;
502 }
503 
504 
505 static void
nxt_http_request_proto_info(nxt_task_t * task,nxt_http_request_t * r)506 nxt_http_request_proto_info(nxt_task_t *task, nxt_http_request_t *r)
507 {
508     if (nxt_fast_path(r->proto.any != NULL)) {
509         nxt_http_proto[r->protocol].local_addr(task, r);
510     }
511 }
512 
513 
514 void
nxt_http_request_read_body(nxt_task_t * task,nxt_http_request_t * r)515 nxt_http_request_read_body(nxt_task_t *task, nxt_http_request_t *r)
516 {
517     if (nxt_fast_path(r->proto.any != NULL)) {
518         nxt_http_proto[r->protocol].body_read(task, r);
519     }
520 }
521 
522 
523 void
nxt_http_request_header_send(nxt_task_t * task,nxt_http_request_t * r,nxt_work_handler_t body_handler,void * data)524 nxt_http_request_header_send(nxt_task_t *task, nxt_http_request_t *r,
525     nxt_work_handler_t body_handler, void *data)
526 {
527     u_char            *p, *end;
528     nxt_http_field_t  *server, *date, *content_length;
529 
530     /*
531      * TODO: "Server", "Date", and "Content-Length" processing should be moved
532      * to the last header filter.
533      */
534 
535     server = nxt_list_zero_add(r->resp.fields);
536     if (nxt_slow_path(server == NULL)) {
537         goto fail;
538     }
539 
540     nxt_http_field_set(server, "Server", NXT_SERVER);
541 
542     if (r->resp.date == NULL) {
543         date = nxt_list_zero_add(r->resp.fields);
544         if (nxt_slow_path(date == NULL)) {
545             goto fail;
546         }
547 
548         nxt_http_field_name_set(date, "Date");
549 
550         p = nxt_mp_nget(r->mem_pool, nxt_http_date_cache.size);
551         if (nxt_slow_path(p == NULL)) {
552             goto fail;
553         }
554 
555         (void) nxt_thread_time_string(task->thread, &nxt_http_date_cache, p);
556 
557         date->value = p;
558         date->value_length = nxt_http_date_cache.size;
559 
560         r->resp.date = date;
561     }
562 
563     if (r->resp.content_length_n != -1
564         && (r->resp.content_length == NULL || r->resp.content_length->skip))
565     {
566         content_length = nxt_list_zero_add(r->resp.fields);
567         if (nxt_slow_path(content_length == NULL)) {
568             goto fail;
569         }
570 
571         nxt_http_field_name_set(content_length, "Content-Length");
572 
573         p = nxt_mp_nget(r->mem_pool, NXT_OFF_T_LEN);
574         if (nxt_slow_path(p == NULL)) {
575             goto fail;
576         }
577 
578         content_length->value = p;
579         end = nxt_sprintf(p, p + NXT_OFF_T_LEN, "%O", r->resp.content_length_n);
580         content_length->value_length = end - p;
581 
582         r->resp.content_length = content_length;
583     }
584 
585     if (nxt_fast_path(r->proto.any != NULL)) {
586         nxt_http_proto[r->protocol].header_send(task, r, body_handler, data);
587     }
588 
589     return;
590 
591 fail:
592 
593     nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR);
594 }
595 
596 
597 void
nxt_http_request_ws_frame_start(nxt_task_t * task,nxt_http_request_t * r,nxt_buf_t * ws_frame)598 nxt_http_request_ws_frame_start(nxt_task_t *task, nxt_http_request_t *r,
599     nxt_buf_t *ws_frame)
600 {
601     if (r->proto.any != NULL) {
602         nxt_http_proto[r->protocol].ws_frame_start(task, r, ws_frame);
603     }
604 }
605 
606 
607 void
nxt_http_request_send(nxt_task_t * task,nxt_http_request_t * r,nxt_buf_t * out)608 nxt_http_request_send(nxt_task_t *task, nxt_http_request_t *r, nxt_buf_t *out)
609 {
610     if (nxt_fast_path(r->proto.any != NULL)) {
611         nxt_http_proto[r->protocol].send(task, r, out);
612     }
613 }
614 
615 
616 nxt_buf_t *
nxt_http_buf_mem(nxt_task_t * task,nxt_http_request_t * r,size_t size)617 nxt_http_buf_mem(nxt_task_t *task, nxt_http_request_t *r, size_t size)
618 {
619     nxt_buf_t  *b;
620 
621     b = nxt_buf_mem_alloc(r->mem_pool, size, 0);
622     if (nxt_fast_path(b != NULL)) {
623         b->completion_handler = nxt_http_request_mem_buf_completion;
624         b->parent = r;
625         nxt_mp_retain(r->mem_pool);
626 
627     } else {
628         nxt_http_request_error(task, r, NXT_HTTP_INTERNAL_SERVER_ERROR);
629     }
630 
631     return b;
632 }
633 
634 
635 static void
nxt_http_request_mem_buf_completion(nxt_task_t * task,void * obj,void * data)636 nxt_http_request_mem_buf_completion(nxt_task_t *task, void *obj, void *data)
637 {
638     nxt_buf_t           *b, *next;
639     nxt_http_request_t  *r;
640 
641     b = obj;
642     r = data;
643 
644     do {
645         next = b->next;
646 
647         nxt_mp_free(r->mem_pool, b);
648         nxt_mp_release(r->mem_pool);
649 
650         b = next;
651     } while (b != NULL);
652 }
653 
654 
655 nxt_buf_t *
nxt_http_buf_last(nxt_http_request_t * r)656 nxt_http_buf_last(nxt_http_request_t *r)
657 {
658     nxt_buf_t  *last;
659 
660     last = r->last;
661     r->last = NULL;
662 
663     return last;
664 }
665 
666 
667 static void
nxt_http_request_done(nxt_task_t * task,void * obj,void * data)668 nxt_http_request_done(nxt_task_t *task, void *obj, void *data)
669 {
670     nxt_http_request_t  *r;
671 
672     r = data;
673 
674     nxt_debug(task, "http request done");
675 
676     nxt_http_request_close_handler(task, r, r->proto.any);
677 }
678 
679 
680 void
nxt_http_request_error_handler(nxt_task_t * task,void * obj,void * data)681 nxt_http_request_error_handler(nxt_task_t *task, void *obj, void *data)
682 {
683     nxt_http_proto_t    proto;
684     nxt_http_request_t  *r;
685 
686     r = obj;
687     proto.any = data;
688 
689     nxt_debug(task, "http request error handler");
690 
691     r->error = 1;
692 
693     if (nxt_fast_path(proto.any != NULL)) {
694         nxt_http_proto[r->protocol].discard(task, r, nxt_http_buf_last(r));
695     }
696 }
697 
698 
699 void
nxt_http_request_close_handler(nxt_task_t * task,void * obj,void * data)700 nxt_http_request_close_handler(nxt_task_t *task, void *obj, void *data)
701 {
702     nxt_http_proto_t         proto;
703     nxt_http_request_t       *r;
704     nxt_http_protocol_t      protocol;
705     nxt_socket_conf_joint_t  *conf;
706     nxt_router_access_log_t  *access_log;
707 
708     r = obj;
709     proto.any = data;
710 
711     nxt_debug(task, "http request close handler");
712 
713     conf = r->conf;
714 
715     if (!r->logged) {
716         r->logged = 1;
717 
718         access_log = conf->socket_conf->router_conf->access_log;
719 
720         if (access_log != NULL) {
721             access_log->handler(task, r, access_log);
722         }
723     }
724 
725     r->proto.any = NULL;
726 
727     if (r->body != NULL && nxt_buf_is_file(r->body)
728         && r->body->file->fd != -1)
729     {
730         nxt_fd_close(r->body->file->fd);
731 
732         r->body->file->fd = -1;
733     }
734 
735     if (nxt_fast_path(proto.any != NULL)) {
736         protocol = r->protocol;
737 
738         nxt_http_proto[protocol].close(task, proto, conf);
739 
740         nxt_mp_release(r->mem_pool);
741     }
742 }
743 
744 
745 static u_char *
nxt_http_date_cache_handler(u_char * buf,nxt_realtime_t * now,struct tm * tm,size_t size,const char * format)746 nxt_http_date_cache_handler(u_char *buf, nxt_realtime_t *now, struct tm *tm,
747     size_t size, const char *format)
748 {
749     return nxt_http_date(buf, tm);
750 }
751