6 #include <libubox/ustream.h>
7 #include <libubox/ustream-ssl.h>
8 #include <libubox/usock.h>
9 #include <libubox/blobmsg.h>
12 #include "uclient-utils.h"
13 #include "uclient-backend.h"
15 static struct ustream_ssl_ctx *ssl_ctx;
34 HTTP_STATE_HEADERS_SENT,
35 HTTP_STATE_REQUEST_DONE,
36 HTTP_STATE_RECV_HEADERS,
41 static const char * const request_types[__REQ_MAX] = {
52 struct ustream_fd ufd;
53 struct ustream_ssl ussl;
57 bool connection_close;
58 enum request_type req_type;
59 enum http_state state;
61 enum auth_type auth_type;
67 struct blob_buf headers;
77 static const char * const uclient_http_prefix[] = {
78 [PREFIX_HTTP] = "http://",
79 [PREFIX_HTTPS] = "https://",
83 static int uclient_do_connect(struct uclient_http *uh, const char *port)
88 port = uh->uc.url->port;
90 fd = usock(USOCK_TCP | USOCK_NONBLOCK, uh->uc.url->host, port);
94 ustream_fd_init(&uh->ufd, fd);
98 static void uclient_http_disconnect(struct uclient_http *uh)
104 ustream_free(&uh->ussl.stream);
105 ustream_free(&uh->ufd.stream);
106 close(uh->ufd.fd.fd);
110 static void uclient_http_free_url_state(struct uclient *cl)
112 struct uclient_http *uh = container_of(cl, struct uclient_http, uc);
114 uh->auth_type = AUTH_TYPE_UNKNOWN;
117 uclient_http_disconnect(uh);
120 static void uclient_notify_eof(struct uclient_http *uh)
122 struct ustream *us = uh->us;
125 if (!us->eof && !us->write_error)
128 if (ustream_pending_data(us, false))
132 uclient_backend_set_eof(&uh->uc);
134 if (uh->connection_close)
135 uclient_http_disconnect(uh);
138 static void uclient_http_reset_state(struct uclient_http *uh)
140 uclient_backend_reset_state(&uh->uc);
141 uh->read_chunked = -1;
142 uh->content_length = -1;
144 uh->connection_close = false;
145 uh->state = HTTP_STATE_INIT;
147 if (uh->auth_type == AUTH_TYPE_UNKNOWN && !uh->uc.url->auth)
148 uh->auth_type = AUTH_TYPE_NONE;
151 static void uclient_http_init_request(struct uclient_http *uh)
153 uclient_http_reset_state(uh);
154 blob_buf_init(&uh->meta, 0);
157 static enum auth_type
158 uclient_http_update_auth_type(struct uclient_http *uh)
161 return AUTH_TYPE_NONE;
163 if (!strncasecmp(uh->auth_str, "basic", 5))
164 return AUTH_TYPE_BASIC;
166 if (!strncasecmp(uh->auth_str, "digest", 6))
167 return AUTH_TYPE_DIGEST;
169 return AUTH_TYPE_NONE;
172 static void uclient_http_process_headers(struct uclient_http *uh)
175 HTTP_HDR_TRANSFER_ENCODING,
177 HTTP_HDR_CONTENT_LENGTH,
181 static const struct blobmsg_policy hdr_policy[__HTTP_HDR_MAX] = {
182 #define hdr(_name) { .name = _name, .type = BLOBMSG_TYPE_STRING }
183 [HTTP_HDR_TRANSFER_ENCODING] = hdr("transfer-encoding"),
184 [HTTP_HDR_CONNECTION] = hdr("connection"),
185 [HTTP_HDR_CONTENT_LENGTH] = hdr("content-length"),
186 [HTTP_HDR_AUTH] = hdr("www-authenticate"),
189 struct blob_attr *tb[__HTTP_HDR_MAX];
190 struct blob_attr *cur;
192 blobmsg_parse(hdr_policy, __HTTP_HDR_MAX, tb, blob_data(uh->meta.head), blob_len(uh->meta.head));
194 cur = tb[HTTP_HDR_TRANSFER_ENCODING];
195 if (cur && strstr(blobmsg_data(cur), "chunked"))
196 uh->read_chunked = 0;
198 cur = tb[HTTP_HDR_CONNECTION];
199 if (cur && strstr(blobmsg_data(cur), "close"))
200 uh->connection_close = true;
202 cur = tb[HTTP_HDR_CONTENT_LENGTH];
204 uh->content_length = strtoul(blobmsg_data(cur), NULL, 10);
206 cur = tb[HTTP_HDR_AUTH];
209 uh->auth_str = strdup(blobmsg_data(cur));
212 uh->auth_type = uclient_http_update_auth_type(uh);
216 uclient_http_add_auth_basic(struct uclient_http *uh)
218 struct uclient_url *url = uh->uc.url;
219 int auth_len = strlen(url->auth);
225 auth_buf = alloca(base64_len(auth_len) + 1);
226 base64_encode(url->auth, auth_len, auth_buf);
227 ustream_printf(uh->us, "Authorization: Basic %s\r\n", auth_buf);
230 static char *digest_unquote_sep(char **str)
232 char *cur = *str + 1;
264 static bool strmatch(char **str, const char *prefix)
266 int len = strlen(prefix);
268 if (strncmp(*str, prefix, len) != 0 || (*str)[len] != '=')
276 get_cnonce(char *dest)
281 f = fopen("/dev/urandom", "r");
283 fread(&val, sizeof(val), 1, f);
287 bin_to_hex(dest, &val, sizeof(val));
290 static void add_field(char **buf, int *ofs, int *len, const char *name, const char *val)
292 int available = *len - *ofs;
300 required = strlen(name) + 4 + strlen(val) * 2;
301 if (required > available)
302 *len += required - available + 64;
304 *buf = realloc(*buf, *len);
309 cur += sprintf(cur, ", %s=\"", name);
311 while ((next = strchr(val, '"'))) {
313 memcpy(cur, val, next - val);
317 cur += sprintf(cur, "\\\"");
321 cur += sprintf(cur, "%s\"", val);
326 uclient_http_add_auth_digest(struct uclient_http *uh)
328 struct uclient_url *url = uh->uc.url;
329 const char *realm = NULL, *opaque = NULL;
330 const char *user, *password;
339 struct http_digest_data data = {
341 .cnonce = cnonce_str,
345 len = strlen(uh->auth_str) + 1;
350 strcpy(buf, uh->auth_str);
357 const char **dest = NULL;
359 while (isspace(*next))
362 if (strmatch(&next, "realm"))
364 else if (strmatch(&next, "qop"))
366 else if (strmatch(&next, "nonce"))
368 else if (strmatch(&next, "opaque"))
373 *dest = digest_unquote_sep(&next);
376 if (!realm || !data.qop || !data.nonce)
379 sprintf(nc_str, "%08x", nc++);
380 get_cnonce(cnonce_str);
383 data.uri = url->location;
384 data.method = request_types[uh->req_type];
386 password = strchr(url->auth, ':');
390 len = password - url->auth;
394 user_buf = alloca(len + 1);
395 strncpy(user_buf, url->auth, len);
404 http_digest_calculate_auth_hash(ahash, user, realm, password);
405 http_digest_calculate_response(hash, &data);
411 add_field(&buf, &ofs, &len, "username", user);
412 add_field(&buf, &ofs, &len, "realm", realm);
413 add_field(&buf, &ofs, &len, "nonce", data.nonce);
414 add_field(&buf, &ofs, &len, "uri", data.uri);
415 add_field(&buf, &ofs, &len, "cnonce", data.cnonce);
416 add_field(&buf, &ofs, &len, "response", hash);
418 add_field(&buf, &ofs, &len, "opaque", opaque);
420 ustream_printf(uh->us, "Authorization: Digest nc=%s, qop=%s%s\r\n", data.nc, data.qop, buf);
425 uclient_http_add_auth_header(struct uclient_http *uh)
427 if (!uh->uc.url->auth)
430 switch (uh->auth_type) {
431 case AUTH_TYPE_UNKNOWN:
434 case AUTH_TYPE_BASIC:
435 uclient_http_add_auth_basic(uh);
437 case AUTH_TYPE_DIGEST:
438 uclient_http_add_auth_digest(uh);
444 uclient_http_send_headers(struct uclient_http *uh)
446 struct uclient_url *url = uh->uc.url;
447 struct blob_attr *cur;
448 enum request_type req_type = uh->req_type;
451 if (uh->state >= HTTP_STATE_HEADERS_SENT)
454 if (uh->auth_type == AUTH_TYPE_UNKNOWN)
457 ustream_printf(uh->us,
460 request_types[req_type],
461 url->location, url->host);
463 blobmsg_for_each_attr(cur, uh->headers.head, rem)
464 ustream_printf(uh->us, "%s: %s\n", blobmsg_name(cur), (char *) blobmsg_data(cur));
466 if (uh->req_type == REQ_POST)
467 ustream_printf(uh->us, "Transfer-Encoding: chunked\r\n");
469 uclient_http_add_auth_header(uh);
471 ustream_printf(uh->us, "\r\n");
474 static void uclient_http_headers_complete(struct uclient_http *uh)
476 enum auth_type auth_type = uh->auth_type;
478 uh->state = HTTP_STATE_RECV_DATA;
479 uh->uc.meta = uh->meta.head;
480 uclient_http_process_headers(uh);
482 if (auth_type == AUTH_TYPE_UNKNOWN) {
483 uclient_http_init_request(uh);
484 uclient_http_send_headers(uh);
485 uh->state = HTTP_STATE_REQUEST_DONE;
489 if (uh->uc.cb->header_done)
490 uh->uc.cb->header_done(&uh->uc);
492 if (uh->req_type == REQ_HEAD) {
494 uclient_notify_eof(uh);
498 static void uclient_parse_http_line(struct uclient_http *uh, char *data)
503 if (uh->state == HTTP_STATE_REQUEST_DONE) {
504 uh->state = HTTP_STATE_RECV_HEADERS;
509 uclient_http_headers_complete(uh);
513 sep = strchr(data, ':');
519 for (name = data; *name; name++)
520 *name = tolower(*name);
523 while (isspace(*sep))
526 blobmsg_add_string(&uh->meta, name, sep);
529 static void __uclient_notify_read(struct uclient_http *uh)
531 struct uclient *uc = &uh->uc;
535 if (uh->state < HTTP_STATE_REQUEST_DONE)
538 data = ustream_get_read_buf(uh->us, &len);
542 if (uh->state < HTTP_STATE_RECV_DATA) {
547 sep = strstr(data, "\r\n");
551 /* Check for multi-line HTTP headers */
556 if (isspace(sep[2]) && sep[2] != '\r') {
564 cur_len = sep + 2 - data;
565 uclient_parse_http_line(uh, data);
566 ustream_consume(uh->us, cur_len);
569 data = ustream_get_read_buf(uh->us, &len);
570 } while (data && uh->state < HTTP_STATE_RECV_DATA);
576 if (uh->state == HTTP_STATE_RECV_DATA && uc->cb->data_read)
577 uc->cb->data_read(uc);
580 static void uclient_notify_read(struct ustream *us, int bytes)
582 struct uclient_http *uh = container_of(us, struct uclient_http, ufd.stream);
584 __uclient_notify_read(uh);
587 static void uclient_notify_state(struct ustream *us)
589 struct uclient_http *uh = container_of(us, struct uclient_http, ufd.stream);
591 uclient_notify_eof(uh);
594 static int uclient_setup_http(struct uclient_http *uh)
596 struct ustream *us = &uh->ufd.stream;
600 us->string_data = true;
601 us->notify_state = uclient_notify_state;
602 us->notify_read = uclient_notify_read;
604 ret = uclient_do_connect(uh, "80");
611 static void uclient_ssl_notify_read(struct ustream *us, int bytes)
613 struct uclient_http *uh = container_of(us, struct uclient_http, ussl.stream);
615 __uclient_notify_read(uh);
618 static void uclient_ssl_notify_state(struct ustream *us)
620 struct uclient_http *uh = container_of(us, struct uclient_http, ussl.stream);
622 uclient_notify_eof(uh);
625 static int uclient_setup_https(struct uclient_http *uh)
627 struct ustream *us = &uh->ussl.stream;
633 ret = uclient_do_connect(uh, "443");
638 ssl_ctx = ustream_ssl_context_new(false);
640 us->string_data = true;
641 us->notify_state = uclient_ssl_notify_state;
642 us->notify_read = uclient_ssl_notify_read;
643 ustream_ssl_init(&uh->ussl, &uh->ufd.stream, ssl_ctx, false);
648 static int uclient_http_connect(struct uclient *cl)
650 struct uclient_http *uh = container_of(cl, struct uclient_http, uc);
652 uclient_http_init_request(uh);
657 uh->ssl = cl->url->prefix == PREFIX_HTTPS;
660 return uclient_setup_https(uh);
662 return uclient_setup_http(uh);
665 static struct uclient *uclient_http_alloc(void)
667 struct uclient_http *uh;
669 uh = calloc_a(sizeof(*uh));
670 blob_buf_init(&uh->headers, 0);
675 static void uclient_http_free(struct uclient *cl)
677 struct uclient_http *uh = container_of(cl, struct uclient_http, uc);
679 uclient_http_free_url_state(cl);
680 blob_buf_free(&uh->headers);
681 blob_buf_free(&uh->meta);
686 uclient_http_set_request_type(struct uclient *cl, const char *type)
688 struct uclient_http *uh = container_of(cl, struct uclient_http, uc);
691 if (cl->backend != &uclient_backend_http)
694 if (uh->state > HTTP_STATE_INIT)
697 for (i = 0; i < ARRAY_SIZE(request_types); i++) {
698 if (strcmp(request_types[i], type) != 0)
709 uclient_http_reset_headers(struct uclient *cl, const char *name, const char *value)
711 struct uclient_http *uh = container_of(cl, struct uclient_http, uc);
713 blob_buf_init(&uh->headers, 0);
719 uclient_http_set_header(struct uclient *cl, const char *name, const char *value)
721 struct uclient_http *uh = container_of(cl, struct uclient_http, uc);
723 if (cl->backend != &uclient_backend_http)
726 if (uh->state > HTTP_STATE_INIT)
729 blobmsg_add_string(&uh->headers, name, value);
734 uclient_http_send_data(struct uclient *cl, char *buf, unsigned int len)
736 struct uclient_http *uh = container_of(cl, struct uclient_http, uc);
738 if (uh->state >= HTTP_STATE_REQUEST_DONE)
741 uclient_http_send_headers(uh);
743 ustream_printf(uh->us, "%X\r\n", len);
744 ustream_write(uh->us, buf, len, false);
745 ustream_printf(uh->us, "\r\n");
751 uclient_http_request_done(struct uclient *cl)
753 struct uclient_http *uh = container_of(cl, struct uclient_http, uc);
755 if (uh->state >= HTTP_STATE_REQUEST_DONE)
758 uclient_http_send_headers(uh);
759 uh->state = HTTP_STATE_REQUEST_DONE;
765 uclient_http_read(struct uclient *cl, char *buf, unsigned int len)
767 struct uclient_http *uh = container_of(cl, struct uclient_http, uc);
769 char *data, *data_end;
771 if (uh->state < HTTP_STATE_RECV_DATA || !uh->us)
774 data = ustream_get_read_buf(uh->us, &read_len);
775 if (!data || !read_len)
778 data_end = data + read_len;
781 if (uh->read_chunked == 0) {
784 if (data[0] == '\r' && data[1] == '\n') {
789 sep = strstr(data, "\r\n");
794 uh->read_chunked = strtoul(data, NULL, 16);
796 read_len += sep + 2 - data;
799 if (!uh->read_chunked)
803 if (len > data_end - data)
804 len = data_end - data;
806 if (uh->read_chunked >= 0) {
807 if (len > uh->read_chunked)
808 len = uh->read_chunked;
810 uh->read_chunked -= len;
811 } else if (uh->content_length >= 0) {
812 if (len > uh->content_length)
813 len = uh->content_length;
815 uh->content_length -= len;
816 if (!uh->content_length)
822 memcpy(buf, data, len);
826 ustream_consume(uh->us, read_len);
828 uclient_notify_eof(uh);
833 const struct uclient_backend uclient_backend_http __hidden = {
834 .prefix = uclient_http_prefix,
836 .alloc = uclient_http_alloc,
837 .free = uclient_http_free,
838 .connect = uclient_http_connect,
839 .update_url = uclient_http_free_url_state,
841 .read = uclient_http_read,
842 .write = uclient_http_send_data,
843 .request = uclient_http_request_done,