2 Unix SMB/CIFS implementation.
6 Copyright (C) 2013 Samuel Cabrero <samuelcabrero@kernevil.me>
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "lib/util/tevent_ntstatus.h"
25 #include "http_internal.h"
26 #include "util/tevent_werror.h"
27 #include "lib/util/dlinklist.h"
32 * Determines if a response should have a body.
33 * @return 1 if the response MUST have a body; 0 if the response MUST NOT have
34 * a body. Returns -1 on error.
36 static int http_response_needs_body(struct http_request
*req
)
38 struct http_header
*h
= NULL
;
42 for (h
= req
->headers
; h
!= NULL
; h
= h
->next
) {
48 cmp
= strcasecmp(h
->key
, "Content-Length");
53 n
= sscanf(h
->value
, "%llu%c", &v
, &c
);
58 req
->remaining_content_length
= v
;
70 struct http_read_response_state
{
71 enum http_parser_state parser_state
;
72 size_t max_headers_size
;
73 uint64_t max_content_length
;
75 struct http_request
*response
;
79 * Parses the HTTP headers
81 static enum http_read_status
http_parse_headers(struct http_read_response_state
*state
)
83 enum http_read_status status
= HTTP_ALL_DATA_READ
;
92 if (!state
|| !state
->response
) {
93 DEBUG(0, ("%s: Invalid Parameter\n", __func__
));
94 return HTTP_DATA_CORRUPTED
;
97 if (state
->buffer
.length
> state
->max_headers_size
) {
98 DEBUG(0, ("%s: Headers too long: %zi, maximum length is %zi\n", __func__
,
99 state
->buffer
.length
, state
->max_headers_size
));
100 return HTTP_DATA_TOO_LONG
;
103 line
= talloc_strndup(state
, (char *)state
->buffer
.data
, state
->buffer
.length
);
105 DEBUG(0, ("%s: Memory error\n", __func__
));
106 return HTTP_DATA_CORRUPTED
;
109 ptr
= strstr(line
, "\r\n");
112 return HTTP_MORE_DATA_EXPECTED
;
115 state
->response
->headers_size
+= state
->buffer
.length
;
117 if (strncmp(line
, "\r\n", 2) == 0) {
118 DEBUG(11,("%s: All headers read\n", __func__
));
120 ret
= http_response_needs_body(state
->response
);
123 if (state
->response
->remaining_content_length
<= state
->max_content_length
) {
124 DEBUG(11, ("%s: Start of read body\n", __func__
));
125 state
->parser_state
= HTTP_READING_BODY
;
130 DEBUG(11, ("%s: Skipping body for code %d\n", __func__
,
131 state
->response
->response_code
));
132 state
->parser_state
= HTTP_READING_DONE
;
135 DEBUG(0, ("%s_: Error in http_response_needs_body\n", __func__
));
137 return HTTP_DATA_CORRUPTED
;
142 return HTTP_ALL_DATA_READ
;
145 n
= sscanf(line
, "%m[^:]: %m[^\r\n]\r\n", &key
, &value
);
147 DEBUG(0, ("%s: Error parsing header '%s'\n", __func__
, line
));
148 status
= HTTP_DATA_CORRUPTED
;
152 if (http_add_header(state
->response
, &state
->response
->headers
, key
, value
) == -1) {
153 DEBUG(0, ("%s: Error adding header\n", __func__
));
154 status
= HTTP_DATA_CORRUPTED
;
166 * Parses the first line of a HTTP response
168 static bool http_parse_response_line(struct http_read_response_state
*state
)
181 DEBUG(0, ("%s: Input parameter is NULL\n", __func__
));
185 line
= talloc_strndup(state
, (char*)state
->buffer
.data
, state
->buffer
.length
);
187 DEBUG(0, ("%s: Memory error\n", __func__
));
191 n
= sscanf(line
, "%m[^/]/%c.%c %d %m[^\r\n]\r\n",
192 &protocol
, &major
, &minor
, &code
, &msg
);
194 DEBUG(11, ("%s: Header parsed(%i): protocol->%s, major->%c, minor->%c, "
195 "code->%d, message->%s\n", __func__
, n
, protocol
, major
, minor
,
199 DEBUG(0, ("%s: Error parsing header\n", __func__
));
205 DEBUG(0, ("%s: Bad HTTP major number '%c'\n", __func__
, major
));
211 DEBUG(0, ("%s: Bad response code '%d'", __func__
, code
));
217 DEBUG(0, ("%s: Error parsing HTTP data\n", __func__
));
222 state
->response
->major
= major
;
223 state
->response
->minor
= minor
;
224 state
->response
->response_code
= code
;
225 state
->response
->response_code_line
= talloc_strndup(state
->response
,
236 * Parses header lines from a request or a response into the specified
237 * request object given a buffer.
240 * HTTP_DATA_CORRUPTED on error
241 * HTTP_MORE_DATA_EXPECTED when we need to read more headers
242 * HTTP_DATA_TOO_LONG on error
243 * HTTP_ALL_DATA_READ when all headers have been read
245 static enum http_read_status
http_parse_firstline(struct http_read_response_state
*state
)
247 enum http_read_status status
= HTTP_ALL_DATA_READ
;
253 DEBUG(0, ("%s: Invalid Parameter\n", __func__
));
254 return HTTP_DATA_CORRUPTED
;
257 if (state
->buffer
.length
> state
->max_headers_size
) {
258 DEBUG(0, ("%s: Headers too long: %zi, maximum length is %zi\n", __func__
,
259 state
->buffer
.length
, state
->max_headers_size
));
260 return HTTP_DATA_TOO_LONG
;
263 line
= talloc_strndup(state
, (char *)state
->buffer
.data
, state
->buffer
.length
);
265 DEBUG(0, ("%s: Not enough memory\n", __func__
));
266 return HTTP_DATA_CORRUPTED
;
269 ptr
= strstr(line
, "\r\n");
272 return HTTP_MORE_DATA_EXPECTED
;
275 state
->response
->headers_size
= state
->buffer
.length
;
276 if (!http_parse_response_line(state
)) {
277 status
= HTTP_DATA_CORRUPTED
;
280 /* Next state, read HTTP headers */
281 state
->parser_state
= HTTP_READING_HEADERS
;
287 static enum http_read_status
http_read_body(struct http_read_response_state
*state
)
289 struct http_request
*resp
= state
->response
;
291 if (state
->buffer
.length
< resp
->remaining_content_length
) {
292 return HTTP_MORE_DATA_EXPECTED
;
295 resp
->body
= state
->buffer
;
296 state
->buffer
= data_blob_null
;
297 talloc_steal(resp
, resp
->body
.data
);
298 resp
->remaining_content_length
= 0;
300 state
->parser_state
= HTTP_READING_DONE
;
301 return HTTP_ALL_DATA_READ
;
304 static enum http_read_status
http_read_trailer(struct http_read_response_state
*state
)
306 enum http_read_status status
= HTTP_DATA_CORRUPTED
;
311 static enum http_read_status
http_parse_buffer(struct http_read_response_state
*state
)
314 DEBUG(0, ("%s: Invalid parameter\n", __func__
));
315 return HTTP_DATA_CORRUPTED
;
318 switch (state
->parser_state
) {
319 case HTTP_READING_FIRSTLINE
:
320 return http_parse_firstline(state
);
321 case HTTP_READING_HEADERS
:
322 return http_parse_headers(state
);
323 case HTTP_READING_BODY
:
324 return http_read_body(state
);
326 case HTTP_READING_TRAILER
:
327 return http_read_trailer(state
);
329 case HTTP_READING_DONE
:
331 return HTTP_ALL_DATA_READ
;
333 DEBUG(0, ("%s: Illegal parser state %d", __func__
,
334 state
->parser_state
));
337 return HTTP_DATA_CORRUPTED
;
340 static int http_header_is_valid_value(const char *value
)
342 const char *p
= NULL
;
346 DEBUG(0, ("%s: Invalid parameter\n", __func__
));
351 while ((p
= strpbrk(p
, "\r\n")) != NULL
) {
352 /* Expect only one new line */
353 p
+= strspn(p
, "\r\n");
354 /* Expect a space or tab for continuation */
355 if (*p
!= ' ' && *p
!= '\t')
361 static int http_add_header_internal(TALLOC_CTX
*mem_ctx
,
362 struct http_header
**headers
,
363 const char *key
, const char *value
,
366 struct http_header
*tail
= NULL
;
367 struct http_header
*h
= NULL
;
370 if (!headers
|| !key
|| !value
) {
371 DEBUG(0, ("Invalid parameter\n"));
378 for (h
= *headers
; h
!= NULL
; h
= h
->next
) {
379 if (strcasecmp(key
, h
->key
) == 0) {
385 /* Replace header value */
387 talloc_free(h
->value
);
389 h
->value
= talloc_strdup(h
, value
);
390 DEBUG(11, ("%s: Replaced HTTP header: key '%s', value '%s'\n",
391 __func__
, h
->key
, h
->value
));
397 h
= talloc(mem_ctx
, struct http_header
);
398 h
->key
= talloc_strdup(h
, key
);
399 h
->value
= talloc_strdup(h
, value
);
400 DLIST_ADD_END(*headers
, h
);
401 tail
= DLIST_TAIL(*headers
);
403 DEBUG(0, ("%s: Error adding header\n", __func__
));
406 DEBUG(11, ("%s: Added HTTP header: key '%s', value '%s'\n",
407 __func__
, h
->key
, h
->value
));
411 int http_add_header(TALLOC_CTX
*mem_ctx
,
412 struct http_header
**headers
,
413 const char *key
, const char *value
)
415 if (strchr(key
, '\r') != NULL
|| strchr(key
, '\n') != NULL
) {
416 DEBUG(0, ("%s: Dropping illegal header key\n", __func__
));
420 if (!http_header_is_valid_value(value
)) {
421 DEBUG(0, ("%s: Dropping illegal header value\n", __func__
));
425 return (http_add_header_internal(mem_ctx
, headers
, key
, value
, false));
428 int http_replace_header(TALLOC_CTX
*mem_ctx
,
429 struct http_header
**headers
,
430 const char *key
, const char *value
)
432 if (strchr(key
, '\r') != NULL
|| strchr(key
, '\n') != NULL
) {
433 DEBUG(0, ("%s: Dropping illegal header key\n", __func__
));
437 if (!http_header_is_valid_value(value
)) {
438 DEBUG(0, ("%s: Dropping illegal header value\n", __func__
));
442 return (http_add_header_internal(mem_ctx
, headers
, key
, value
, true));
446 * Remove a header from the headers list.
448 * Returns 0, if the header was successfully removed.
449 * Returns -1, if the header could not be found.
451 int http_remove_header(struct http_header
**headers
, const char *key
)
453 struct http_header
*header
;
456 if (!headers
|| !key
) {
457 DEBUG(0, ("%s: Invalid parameter\n", __func__
));
461 for(header
= *headers
; header
!= NULL
; header
= header
->next
) {
462 if (strcmp(key
, header
->key
) == 0) {
463 DLIST_REMOVE(*headers
, header
);
470 static int http_read_response_next_vector(struct tstream_context
*stream
,
473 struct iovec
**_vector
,
476 struct http_read_response_state
*state
;
477 struct iovec
*vector
;
480 if (!stream
|| !private_data
|| !_vector
|| !_count
) {
481 DEBUG(0, ("%s: Invalid Parameter\n", __func__
));
485 state
= talloc_get_type_abort(private_data
, struct http_read_response_state
);
486 vector
= talloc_array(mem_ctx
, struct iovec
, 1);
488 DEBUG(0, ("%s: No more memory\n", __func__
));
492 if (state
->buffer
.data
== NULL
) {
493 /* Allocate buffer */
494 state
->buffer
.data
= talloc_zero_array(state
, uint8_t, 1);
495 if (!state
->buffer
.data
) {
496 DEBUG(0, ("%s: No more memory\n", __func__
));
499 state
->buffer
.length
= 1;
501 /* Return now, nothing to parse yet */
502 vector
[0].iov_base
= (void *)(state
->buffer
.data
);
503 vector
[0].iov_len
= 1;
509 switch (http_parse_buffer(state
)) {
510 case HTTP_ALL_DATA_READ
:
511 if (state
->parser_state
== HTTP_READING_DONE
) {
512 /* Full request or response parsed */
516 /* Free current buffer and allocate new one */
517 TALLOC_FREE(state
->buffer
.data
);
518 state
->buffer
.data
= talloc_zero_array(state
, uint8_t, 1);
519 if (!state
->buffer
.data
) {
522 state
->buffer
.length
= 1;
524 vector
[0].iov_base
= (void *)(state
->buffer
.data
);
525 vector
[0].iov_len
= 1;
530 case HTTP_MORE_DATA_EXPECTED
:
531 /* TODO Optimize, allocating byte by byte */
532 state
->buffer
.data
= talloc_realloc(state
, state
->buffer
.data
,
533 uint8_t, state
->buffer
.length
+ 1);
534 if (!state
->buffer
.data
) {
537 state
->buffer
.length
++;
538 vector
[0].iov_base
= (void *)(state
->buffer
.data
+
539 state
->buffer
.length
- 1);
540 vector
[0].iov_len
= 1;
544 case HTTP_DATA_CORRUPTED
:
545 case HTTP_REQUEST_CANCELED
:
546 case HTTP_DATA_TOO_LONG
:
550 DEBUG(0, ("%s: Unexpected status\n", __func__
));
558 * Reads a HTTP response
560 static void http_read_response_done(struct tevent_req
*);
561 struct tevent_req
*http_read_response_send(TALLOC_CTX
*mem_ctx
,
562 struct tevent_context
*ev
,
563 struct http_conn
*http_conn
,
564 size_t max_content_length
)
566 struct tevent_req
*req
;
567 struct tevent_req
*subreq
;
568 struct http_read_response_state
*state
;
570 DEBUG(11, ("%s: Reading HTTP response\n", __func__
));
573 if (ev
== NULL
|| http_conn
== NULL
) {
574 DEBUG(0, ("%s: Invalid parameter\n", __func__
));
578 req
= tevent_req_create(mem_ctx
, &state
, struct http_read_response_state
);
583 state
->max_headers_size
= HTTP_MAX_HEADER_SIZE
;
584 state
->max_content_length
= (uint64_t)max_content_length
;
585 state
->parser_state
= HTTP_READING_FIRSTLINE
;
586 state
->response
= talloc_zero(state
, struct http_request
);
587 if (tevent_req_nomem(state
->response
, req
)) {
588 return tevent_req_post(req
, ev
);
591 subreq
= tstream_readv_pdu_send(state
, ev
, http_conn
->tstreams
.active
,
592 http_read_response_next_vector
,
594 if (tevent_req_nomem(subreq
,req
)) {
595 return tevent_req_post(req
, ev
);
597 tevent_req_set_callback(subreq
, http_read_response_done
, req
);
602 static void http_read_response_done(struct tevent_req
*subreq
)
605 struct tevent_req
*req
;
610 DEBUG(0, ("%s: Invalid parameter\n", __func__
));
614 req
= tevent_req_callback_data(subreq
, struct tevent_req
);
616 ret
= tstream_readv_pdu_recv(subreq
, &sys_errno
);
617 DEBUG(11, ("%s: HTTP response read (%d bytes)\n", __func__
, ret
));
620 status
= map_nt_error_from_unix_common(sys_errno
);
621 DEBUG(0, ("%s: Failed to read HTTP response: %s\n",
622 __func__
, nt_errstr(status
)));
623 tevent_req_nterror(req
, status
);
627 tevent_req_done(req
);
630 NTSTATUS
http_read_response_recv(struct tevent_req
*req
,
632 struct http_request
**response
)
635 struct http_read_response_state
*state
;
637 if (!mem_ctx
|| !response
|| !req
) {
638 DEBUG(0, ("%s: Invalid parameter\n", __func__
));
639 return NT_STATUS_INVALID_PARAMETER
;
641 if (tevent_req_is_nterror(req
, &status
)) {
642 tevent_req_received(req
);
646 state
= tevent_req_data(req
, struct http_read_response_state
);
647 *response
= state
->response
;
648 talloc_steal(mem_ctx
, state
->response
);
650 tevent_req_received(req
);
655 static const char *http_method_str(enum http_cmd_type type
)
663 case HTTP_REQ_RPC_IN_DATA
:
664 method
= "RPC_IN_DATA";
666 case HTTP_REQ_RPC_OUT_DATA
:
667 method
= "RPC_OUT_DATA";
677 static NTSTATUS
http_push_request_line(TALLOC_CTX
*mem_ctx
,
679 const struct http_request
*req
)
685 if (!buffer
|| !req
) {
686 DEBUG(0, ("%s: Invalid parameter\n", __func__
));
687 return NT_STATUS_INVALID_PARAMETER
;
690 method
= http_method_str(req
->type
);
691 if (method
== NULL
) {
692 return NT_STATUS_INVALID_PARAMETER
;
695 str
= talloc_asprintf(mem_ctx
, "%s %s HTTP/%c.%c\r\n", method
,
696 req
->uri
, req
->major
, req
->minor
);
698 return NT_STATUS_NO_MEMORY
;
700 if (!data_blob_append(mem_ctx
, buffer
, str
, strlen(str
))) {
702 return NT_STATUS_NO_MEMORY
;
709 static NTSTATUS
http_push_headers(TALLOC_CTX
*mem_ctx
,
711 struct http_request
*req
)
713 struct http_header
*header
= NULL
;
714 char *header_str
= NULL
;
719 DEBUG(0, ("%s: Invalid parameter\n", __func__
));
720 return NT_STATUS_INVALID_PARAMETER
;
723 for (header
= req
->headers
; header
!= NULL
; header
= header
->next
) {
724 header_str
= talloc_asprintf(mem_ctx
, "%s: %s\r\n",
725 header
->key
, header
->value
);
726 if (header_str
== NULL
) {
727 return NT_STATUS_NO_MEMORY
;
730 len
= strlen(header_str
);
731 if (!data_blob_append(mem_ctx
, blob
, header_str
, len
)) {
732 talloc_free(header_str
);
733 return NT_STATUS_NO_MEMORY
;
735 talloc_free(header_str
);
738 if (!data_blob_append(mem_ctx
, blob
, "\r\n",2)) {
739 return NT_STATUS_NO_MEMORY
;
746 static NTSTATUS
http_push_body(TALLOC_CTX
*mem_ctx
,
748 struct http_request
*req
)
752 DEBUG(0, ("%s: Invalid parameter\n", __func__
));
753 return NT_STATUS_INVALID_PARAMETER
;
756 if (req
->body
.length
) {
757 if (!data_blob_append(mem_ctx
, blob
, req
->body
.data
,
759 return NT_STATUS_NO_MEMORY
;
766 struct http_send_request_state
{
767 struct tevent_context
*ev
;
768 struct loadparm_context
*lp_ctx
;
769 struct cli_credentials
*credentials
;
770 struct http_request
*request
;
778 * Sends and HTTP request
780 static void http_send_request_done(struct tevent_req
*);
781 struct tevent_req
*http_send_request_send(TALLOC_CTX
*mem_ctx
,
782 struct tevent_context
*ev
,
783 struct http_conn
*http_conn
,
784 struct http_request
*request
)
786 struct tevent_req
*req
;
787 struct tevent_req
*subreq
;
788 struct http_send_request_state
*state
= NULL
;
791 DEBUG(11, ("%s: Sending HTTP request\n", __func__
));
794 if (ev
== NULL
|| request
== NULL
|| http_conn
== NULL
) {
795 DEBUG(0, ("%s: Invalid parameter\n", __func__
));
799 req
= tevent_req_create(mem_ctx
, &state
, struct http_send_request_state
);
805 state
->request
= request
;
807 /* Push the request line */
808 status
= http_push_request_line(state
, &state
->buffer
, state
->request
);
809 if (!NT_STATUS_IS_OK(status
)) {
810 tevent_req_nterror(req
, status
);
811 return tevent_req_post(req
, ev
);
814 /* Push the headers */
815 status
= http_push_headers(mem_ctx
, &state
->buffer
, request
);
816 if (!NT_STATUS_IS_OK(status
)) {
817 tevent_req_nterror(req
, status
);
818 return tevent_req_post(req
, ev
);
822 status
= http_push_body(mem_ctx
, &state
->buffer
, request
);
823 if (!NT_STATUS_IS_OK(status
)) {
824 tevent_req_nterror(req
, status
);
825 return tevent_req_post(req
, ev
);
828 state
->iov
.iov_base
= (char *) state
->buffer
.data
;
829 state
->iov
.iov_len
= state
->buffer
.length
;
830 subreq
= tstream_writev_queue_send(state
,
832 http_conn
->tstreams
.active
,
833 http_conn
->send_queue
,
835 if (tevent_req_nomem(subreq
, req
)) {
836 return tevent_req_post(req
, ev
);
838 tevent_req_set_callback(subreq
, http_send_request_done
, req
);
843 static void http_send_request_done(struct tevent_req
*subreq
)
846 struct tevent_req
*req
;
847 struct http_send_request_state
*state
;
849 req
= tevent_req_callback_data(subreq
, struct tevent_req
);
850 state
= tevent_req_data(req
, struct http_send_request_state
);
852 state
->nwritten
= tstream_writev_queue_recv(subreq
, &state
->sys_errno
);
854 if (state
->nwritten
== -1 && state
->sys_errno
!= 0) {
855 status
= map_nt_error_from_unix_common(state
->sys_errno
);
856 DEBUG(0, ("%s: Failed to send HTTP request: %s\n",
857 __func__
, nt_errstr(status
)));
858 tevent_req_nterror(req
, status
);
862 tevent_req_done(req
);
865 NTSTATUS
http_send_request_recv(struct tevent_req
*req
)
870 DEBUG(0, ("%s: Invalid parameter\n", __func__
));
871 return NT_STATUS_INVALID_PARAMETER
;
874 if (tevent_req_is_nterror(req
, &status
)) {
875 tevent_req_received(req
);
879 tevent_req_received(req
);