1 /* 2 * uclient - ustream based protocol client library 3 * 4 * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org> 5 * 6 * Permission to use, copy, modify, and/or distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 #include <sys/socket.h> 19 #include <stdio.h> 20 #include <ctype.h> 21 #include <unistd.h> 22 #include <stdint.h> 23 #include <string.h> 24 #include <fcntl.h> 25 26 #include <libubox/ustream.h> 27 #include <libubox/ustream-ssl.h> 28 #include <libubox/usock.h> 29 #include <libubox/blobmsg.h> 30 31 #include "uclient.h" 32 #include "uclient-utils.h" 33 #include "uclient-backend.h" 34 35 enum auth_type { 36 AUTH_TYPE_UNKNOWN, 37 AUTH_TYPE_NONE, 38 AUTH_TYPE_BASIC, 39 AUTH_TYPE_DIGEST, 40 }; 41 42 enum request_type { 43 REQ_GET, 44 REQ_HEAD, 45 REQ_POST, 46 REQ_PUT, 47 REQ_DELETE, 48 __REQ_MAX 49 }; 50 51 enum http_state { 52 HTTP_STATE_INIT, 53 HTTP_STATE_HEADERS_SENT, 54 HTTP_STATE_REQUEST_DONE, 55 HTTP_STATE_RECV_HEADERS, 56 HTTP_STATE_RECV_DATA, 57 HTTP_STATE_ERROR, 58 }; 59 60 static const char * const request_types[__REQ_MAX] = { 61 [REQ_GET] = "GET", 62 [REQ_HEAD] = "HEAD", 63 [REQ_POST] = "POST", 64 [REQ_PUT] = "PUT", 65 [REQ_DELETE] = "DELETE", 66 }; 67 68 struct uclient_http { 69 struct uclient uc; 70 71 const struct ustream_ssl_ops *ssl_ops; 72 struct ustream_ssl_ctx *ssl_ctx; 73 struct ustream *us; 74 75 struct ustream_fd ufd; 76 struct ustream_ssl ussl; 77 78 struct uloop_timeout disconnect_t; 79 unsigned int seq; 80 81 bool ssl_require_validation; 82 bool ssl; 83 bool eof; 84 bool connection_close; 85 bool disconnect; 86 enum request_type req_type; 87 enum http_state state; 88 89 enum auth_type auth_type; 90 char *auth_str; 91 92 long read_chunked; 93 long content_length; 94 95 int usock_flags; 96 97 uint32_t nc; 98 99 struct blob_buf headers; 100 struct blob_buf meta; 101 }; 102 103 enum { 104 PREFIX_HTTP, 105 PREFIX_HTTPS, 106 __PREFIX_MAX, 107 }; 108 109 static const char * const uclient_http_prefix[] = { 110 [PREFIX_HTTP] = "http://", 111 [PREFIX_HTTPS] = "https://", 112 [__PREFIX_MAX] = NULL 113 }; 114 115 static int uclient_http_connect(struct uclient *cl); 116 117 static int uclient_do_connect(struct uclient_http *uh, const char *port) 118 { 119 socklen_t sl; 120 int fd; 121 122 if (uh->uc.url->port) 123 port = uh->uc.url->port; 124 125 memset(&uh->uc.remote_addr, 0, sizeof(uh->uc.remote_addr)); 126 127 fd = usock_inet_timeout(USOCK_TCP | USOCK_NONBLOCK | uh->usock_flags, 128 uh->uc.url->host, port, &uh->uc.remote_addr, 129 uh->uc.timeout_msecs); 130 if (fd < 0) 131 return -1; 132 133 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); 134 ustream_fd_init(&uh->ufd, fd); 135 136 sl = sizeof(uh->uc.local_addr); 137 memset(&uh->uc.local_addr, 0, sl); 138 getsockname(fd, &uh->uc.local_addr.sa, &sl); 139 140 return 0; 141 } 142 143 static void uclient_http_disconnect(struct uclient_http *uh) 144 { 145 uloop_timeout_cancel(&uh->disconnect_t); 146 if (!uh->us) 147 return; 148 149 if (uh->ssl) 150 ustream_free(&uh->ussl.stream); 151 ustream_free(&uh->ufd.stream); 152 if(uh->ufd.fd.fd) 153 close(uh->ufd.fd.fd); 154 uh->us = NULL; 155 } 156 157 static void uclient_http_free_url_state(struct uclient *cl) 158 { 159 struct uclient_http *uh = container_of(cl, struct uclient_http, uc); 160 161 uh->auth_type = AUTH_TYPE_UNKNOWN; 162 free(uh->auth_str); 163 uh->auth_str = NULL; 164 uclient_http_disconnect(uh); 165 } 166 167 static void uclient_http_error(struct uclient_http *uh, int code) 168 { 169 uh->state = HTTP_STATE_ERROR; 170 uh->us->eof = true; 171 ustream_state_change(uh->us); 172 uclient_backend_set_error(&uh->uc, code); 173 } 174 175 static void uclient_http_request_disconnect(struct uclient *cl) 176 { 177 struct uclient_http *uh = container_of(cl, struct uclient_http, uc); 178 179 if (!uh->us) 180 return; 181 182 uh->eof = true; 183 uh->disconnect = true; 184 uloop_timeout_set(&uh->disconnect_t, 1); 185 } 186 187 static void uclient_notify_eof(struct uclient_http *uh) 188 { 189 struct ustream *us = uh->us; 190 191 if (uh->disconnect) 192 return; 193 194 if (!uh->eof) { 195 if (!us->eof && !us->write_error) 196 return; 197 198 if (ustream_pending_data(us, false)) 199 return; 200 } 201 202 if ((uh->content_length < 0 && uh->read_chunked >= 0) || 203 uh->content_length == 0) 204 uh->uc.data_eof = true; 205 206 uclient_backend_set_eof(&uh->uc); 207 208 if (uh->connection_close) 209 uclient_http_request_disconnect(&uh->uc); 210 } 211 212 static void uclient_http_reset_state(struct uclient_http *uh) 213 { 214 uh->seq++; 215 uclient_backend_reset_state(&uh->uc); 216 uh->read_chunked = -1; 217 uh->content_length = -1; 218 uh->eof = false; 219 uh->disconnect = false; 220 uh->connection_close = false; 221 uh->state = HTTP_STATE_INIT; 222 223 if (uh->auth_type == AUTH_TYPE_UNKNOWN && !uh->uc.url->auth) 224 uh->auth_type = AUTH_TYPE_NONE; 225 } 226 227 static void uclient_http_init_request(struct uclient_http *uh) 228 { 229 uh->seq++; 230 uclient_http_reset_state(uh); 231 blob_buf_init(&uh->meta, 0); 232 } 233 234 static enum auth_type 235 uclient_http_update_auth_type(struct uclient_http *uh) 236 { 237 if (!uh->auth_str) 238 return AUTH_TYPE_NONE; 239 240 if (!strncasecmp(uh->auth_str, "basic", 5)) 241 return AUTH_TYPE_BASIC; 242 243 if (!strncasecmp(uh->auth_str, "digest", 6)) 244 return AUTH_TYPE_DIGEST; 245 246 return AUTH_TYPE_NONE; 247 } 248 249 static void uclient_http_process_headers(struct uclient_http *uh) 250 { 251 enum { 252 HTTP_HDR_TRANSFER_ENCODING, 253 HTTP_HDR_CONNECTION, 254 HTTP_HDR_CONTENT_LENGTH, 255 HTTP_HDR_AUTH, 256 __HTTP_HDR_MAX, 257 }; 258 static const struct blobmsg_policy hdr_policy[__HTTP_HDR_MAX] = { 259 #define hdr(_name) { .name = _name, .type = BLOBMSG_TYPE_STRING } 260 [HTTP_HDR_TRANSFER_ENCODING] = hdr("transfer-encoding"), 261 [HTTP_HDR_CONNECTION] = hdr("connection"), 262 [HTTP_HDR_CONTENT_LENGTH] = hdr("content-length"), 263 [HTTP_HDR_AUTH] = hdr("www-authenticate"), 264 #undef hdr 265 }; 266 struct blob_attr *tb[__HTTP_HDR_MAX]; 267 struct blob_attr *cur; 268 269 blobmsg_parse(hdr_policy, __HTTP_HDR_MAX, tb, blob_data(uh->meta.head), blob_len(uh->meta.head)); 270 271 cur = tb[HTTP_HDR_TRANSFER_ENCODING]; 272 if (cur && strstr(blobmsg_data(cur), "chunked")) 273 uh->read_chunked = 0; 274 275 cur = tb[HTTP_HDR_CONNECTION]; 276 if (cur && strstr(blobmsg_data(cur), "close")) 277 uh->connection_close = true; 278 279 cur = tb[HTTP_HDR_CONTENT_LENGTH]; 280 if (cur) 281 uh->content_length = strtoul(blobmsg_data(cur), NULL, 10); 282 283 cur = tb[HTTP_HDR_AUTH]; 284 if (cur) { 285 free(uh->auth_str); 286 uh->auth_str = strdup(blobmsg_data(cur)); 287 } 288 289 uh->auth_type = uclient_http_update_auth_type(uh); 290 } 291 292 static bool uclient_request_supports_body(enum request_type req_type) 293 { 294 switch (req_type) { 295 case REQ_POST: 296 case REQ_PUT: 297 case REQ_DELETE: 298 return true; 299 default: 300 return false; 301 } 302 } 303 304 static int 305 uclient_http_add_auth_basic(struct uclient_http *uh) 306 { 307 struct uclient_url *url = uh->uc.url; 308 int auth_len = strlen(url->auth); 309 char *auth_buf; 310 311 if (auth_len > 512) 312 return -EINVAL; 313 314 auth_buf = alloca(base64_len(auth_len) + 1); 315 if (!auth_buf) 316 return -ENOMEM; 317 318 base64_encode(url->auth, auth_len, auth_buf); 319 ustream_printf(uh->us, "Authorization: Basic %s\r\n", auth_buf); 320 321 return 0; 322 } 323 324 static char *digest_unquote_sep(char **str) 325 { 326 char *cur = *str + 1; 327 char *start = cur; 328 char *out; 329 330 if (**str != '"') 331 return NULL; 332 333 out = cur; 334 while (1) { 335 if (!*cur) 336 return NULL; 337 338 if (*cur == '"') { 339 cur++; 340 break; 341 } 342 343 if (*cur == '\\') 344 cur++; 345 346 *(out++) = *(cur++); 347 } 348 349 if (*cur == ',') 350 cur++; 351 352 *out = 0; 353 *str = cur; 354 355 return start; 356 } 357 358 static char *digest_sep(char **str) 359 { 360 char *cur, *next; 361 362 cur = *str; 363 next = strchr(*str, ','); 364 if (next) { 365 *str = next + 1; 366 *next = 0; 367 } else { 368 *str += strlen(*str); 369 } 370 371 return cur; 372 } 373 374 static bool strmatch(char **str, const char *prefix) 375 { 376 int len = strlen(prefix); 377 378 if (strncmp(*str, prefix, len) != 0 || (*str)[len] != '=') 379 return false; 380 381 *str += len + 1; 382 return true; 383 } 384 385 static void 386 get_cnonce(char *dest) 387 { 388 uint32_t val = 0; 389 FILE *f; 390 size_t n; 391 392 f = fopen("/dev/urandom", "r"); 393 if (f) { 394 n = fread(&val, sizeof(val), 1, f); 395 fclose(f); 396 if (n != 1) 397 return; 398 } 399 400 bin_to_hex(dest, &val, sizeof(val)); 401 } 402 403 static void add_field(char **buf, int *ofs, int *len, const char *name, const char *val) 404 { 405 int available = *len - *ofs; 406 int required; 407 const char *next; 408 char *cur; 409 410 if (*len && !*buf) 411 return; 412 413 required = strlen(name) + 4 + strlen(val) * 2; 414 if (required > available) 415 *len += required - available + 64; 416 417 *buf = realloc(*buf, *len); 418 if (!*buf) 419 return; 420 421 cur = *buf + *ofs; 422 cur += sprintf(cur, ", %s=\"", name); 423 424 while ((next = strchr(val, '"'))) { 425 if (next > val) { 426 memcpy(cur, val, next - val); 427 cur += next - val; 428 } 429 430 cur += sprintf(cur, "\\\""); 431 val = next + 1; 432 } 433 434 cur += sprintf(cur, "%s\"", val); 435 *ofs = cur - *buf; 436 } 437 438 static int 439 uclient_http_add_auth_digest(struct uclient_http *uh) 440 { 441 struct uclient_url *url = uh->uc.url; 442 const char *realm = NULL, *opaque = NULL; 443 const char *user, *password; 444 char *buf, *next; 445 int len, ofs; 446 int err = 0; 447 448 char cnonce_str[9]; 449 char nc_str[9]; 450 char ahash[33]; 451 char hash[33]; 452 453 struct http_digest_data data = { 454 .nc = nc_str, 455 .cnonce = cnonce_str, 456 .auth_hash = ahash, 457 }; 458 459 len = strlen(uh->auth_str) + 1; 460 if (len > 512) { 461 err = -EINVAL; 462 goto fail; 463 } 464 465 buf = alloca(len); 466 if (!buf) { 467 err = -ENOMEM; 468 goto fail; 469 } 470 471 strcpy(buf, uh->auth_str); 472 473 /* skip auth type */ 474 strsep(&buf, " "); 475 476 next = buf; 477 while (*next) { 478 const char **dest = NULL; 479 const char *tmp; 480 481 while (*next && isspace(*next)) 482 next++; 483 484 if (strmatch(&next, "realm")) 485 dest = &realm; 486 else if (strmatch(&next, "qop")) 487 dest = &data.qop; 488 else if (strmatch(&next, "nonce")) 489 dest = &data.nonce; 490 else if (strmatch(&next, "opaque")) 491 dest = &opaque; 492 else if (strmatch(&next, "stale") || 493 strmatch(&next, "algorithm") || 494 strmatch(&next, "auth-param")) { 495 digest_sep(&next); 496 continue; 497 } else if (strmatch(&next, "domain") || 498 strmatch(&next, "qop-options")) 499 dest = &tmp; 500 else { 501 digest_sep(&next); 502 continue; 503 } 504 505 *dest = digest_unquote_sep(&next); 506 } 507 508 if (!realm || !data.qop || !data.nonce) { 509 err = -EINVAL; 510 goto fail; 511 } 512 513 sprintf(nc_str, "%08x", uh->nc++); 514 get_cnonce(cnonce_str); 515 516 data.qop = "auth"; 517 data.uri = url->location; 518 data.method = request_types[uh->req_type]; 519 520 password = strchr(url->auth, ':'); 521 if (password) { 522 char *user_buf; 523 524 len = password - url->auth; 525 if (len > 256) { 526 err = -EINVAL; 527 goto fail; 528 } 529 530 user_buf = alloca(len + 1); 531 if (!user_buf) { 532 err = -ENOMEM; 533 goto fail; 534 } 535 536 strncpy(user_buf, url->auth, len); 537 user_buf[len] = 0; 538 user = user_buf; 539 password++; 540 } else { 541 user = url->auth; 542 password = ""; 543 } 544 545 http_digest_calculate_auth_hash(ahash, user, realm, password); 546 http_digest_calculate_response(hash, &data); 547 548 buf = NULL; 549 len = 0; 550 ofs = 0; 551 552 add_field(&buf, &ofs, &len, "username", user); 553 add_field(&buf, &ofs, &len, "realm", realm); 554 add_field(&buf, &ofs, &len, "nonce", data.nonce); 555 add_field(&buf, &ofs, &len, "uri", data.uri); 556 add_field(&buf, &ofs, &len, "cnonce", data.cnonce); 557 add_field(&buf, &ofs, &len, "response", hash); 558 if (opaque) 559 add_field(&buf, &ofs, &len, "opaque", opaque); 560 561 ustream_printf(uh->us, "Authorization: Digest nc=%s, qop=%s%s\r\n", data.nc, data.qop, buf); 562 563 free(buf); 564 565 return 0; 566 567 fail: 568 return err; 569 } 570 571 static int 572 uclient_http_add_auth_header(struct uclient_http *uh) 573 { 574 if (!uh->uc.url->auth) 575 return 0; 576 577 switch (uh->auth_type) { 578 case AUTH_TYPE_UNKNOWN: 579 case AUTH_TYPE_NONE: 580 break; 581 case AUTH_TYPE_BASIC: 582 return uclient_http_add_auth_basic(uh); 583 case AUTH_TYPE_DIGEST: 584 return uclient_http_add_auth_digest(uh); 585 } 586 587 return 0; 588 } 589 590 static int 591 uclient_http_send_headers(struct uclient_http *uh) 592 { 593 struct uclient_url *url = uh->uc.url; 594 struct blob_attr *cur; 595 enum request_type req_type = uh->req_type; 596 bool literal_ipv6; 597 int err; 598 size_t rem; 599 600 if (uh->state >= HTTP_STATE_HEADERS_SENT) 601 return 0; 602 603 if (uh->uc.proxy_url) 604 url = uh->uc.proxy_url; 605 606 literal_ipv6 = strchr(url->host, ':'); 607 608 ustream_printf(uh->us, 609 "%s %s HTTP/1.1\r\n" 610 "Host: %s%s%s%s%s\r\n", 611 request_types[req_type], url->location, 612 literal_ipv6 ? "[" : "", 613 url->host, 614 literal_ipv6 ? "]" : "", 615 url->port ? ":" : "", 616 url->port ? url->port : ""); 617 618 blobmsg_for_each_attr(cur, uh->headers.head, rem) 619 ustream_printf(uh->us, "%s: %s\r\n", blobmsg_name(cur), (char *) blobmsg_data(cur)); 620 621 if (uclient_request_supports_body(uh->req_type)) 622 ustream_printf(uh->us, "Transfer-Encoding: chunked\r\n"); 623 624 err = uclient_http_add_auth_header(uh); 625 if (err) 626 return err; 627 628 ustream_printf(uh->us, "\r\n"); 629 630 uh->state = HTTP_STATE_HEADERS_SENT; 631 632 return 0; 633 } 634 635 static void uclient_http_headers_complete(struct uclient_http *uh) 636 { 637 enum auth_type auth_type = uh->auth_type; 638 int seq = uh->uc.seq; 639 640 uh->state = HTTP_STATE_RECV_DATA; 641 uh->uc.meta = uh->meta.head; 642 uclient_http_process_headers(uh); 643 644 if (auth_type == AUTH_TYPE_UNKNOWN && uh->uc.status_code == 401 && 645 (uh->req_type == REQ_HEAD || uh->req_type == REQ_GET)) { 646 uclient_http_connect(&uh->uc); 647 uclient_http_send_headers(uh); 648 uh->state = HTTP_STATE_REQUEST_DONE; 649 return; 650 } 651 652 if (uh->uc.cb->header_done) 653 uh->uc.cb->header_done(&uh->uc); 654 655 if (uh->eof || seq != uh->uc.seq) 656 return; 657 658 if (uh->req_type == REQ_HEAD || uh->uc.status_code == 204 || 659 uh->content_length == 0) { 660 uh->eof = true; 661 uclient_notify_eof(uh); 662 } 663 } 664 665 static void uclient_parse_http_line(struct uclient_http *uh, char *data) 666 { 667 char *name; 668 char *sep; 669 670 if (uh->state == HTTP_STATE_REQUEST_DONE) { 671 char *code; 672 673 if (!strlen(data)) 674 return; 675 676 /* HTTP/1.1 */ 677 strsep(&data, " "); 678 679 code = strsep(&data, " "); 680 if (!code) 681 goto error; 682 683 uh->uc.status_code = strtoul(code, &sep, 10); 684 if (sep && *sep) 685 goto error; 686 687 uh->state = HTTP_STATE_RECV_HEADERS; 688 return; 689 } 690 691 if (!*data) { 692 uclient_http_headers_complete(uh); 693 return; 694 } 695 696 sep = strchr(data, ':'); 697 if (!sep) 698 return; 699 700 *(sep++) = 0; 701 702 for (name = data; *name; name++) 703 *name = tolower(*name); 704 705 name = data; 706 while (isspace(*sep)) 707 sep++; 708 709 blobmsg_add_string(&uh->meta, name, sep); 710 return; 711 712 error: 713 uh->uc.status_code = 400; 714 uh->eof = true; 715 uclient_notify_eof(uh); 716 } 717 718 static void __uclient_notify_read(struct uclient_http *uh) 719 { 720 struct uclient *uc = &uh->uc; 721 unsigned int seq = uh->seq; 722 char *data; 723 int len; 724 725 if (uh->state < HTTP_STATE_REQUEST_DONE || uh->state == HTTP_STATE_ERROR) 726 return; 727 728 data = ustream_get_read_buf(uh->us, &len); 729 if (!data || !len) 730 return; 731 732 if (uh->state < HTTP_STATE_RECV_DATA) { 733 char *sep, *next; 734 int cur_len; 735 736 do { 737 sep = strchr(data, '\n'); 738 if (!sep) 739 break; 740 741 next = sep + 1; 742 if (sep > data && sep[-1] == '\r') 743 sep--; 744 745 /* Check for multi-line HTTP headers */ 746 if (sep > data) { 747 if (!*next) 748 return; 749 750 if (isspace(*next) && *next != '\r' && *next != '\n') { 751 sep[0] = ' '; 752 if (sep + 1 < next) 753 sep[1] = ' '; 754 continue; 755 } 756 } 757 758 *sep = 0; 759 cur_len = next - data; 760 uclient_parse_http_line(uh, data); 761 if (seq != uh->seq) 762 return; 763 764 ustream_consume(uh->us, cur_len); 765 len -= cur_len; 766 767 if (uh->eof) 768 return; 769 770 data = ustream_get_read_buf(uh->us, &len); 771 } while (data && uh->state < HTTP_STATE_RECV_DATA); 772 773 if (!len) 774 return; 775 } 776 777 if (uh->eof) 778 return; 779 780 if (uh->state == HTTP_STATE_RECV_DATA) { 781 /* Now it's uclient user turn to read some data */ 782 uloop_timeout_cancel(&uc->connection_timeout); 783 784 if (uc->cb->data_read) 785 uc->cb->data_read(uc); 786 } 787 } 788 789 static void __uclient_notify_write(struct uclient_http *uh) 790 { 791 struct uclient *uc = &uh->uc; 792 793 if (uc->cb->data_sent) 794 uc->cb->data_sent(uc); 795 } 796 797 static void uclient_notify_read(struct ustream *us, int bytes) 798 { 799 struct uclient_http *uh = container_of(us, struct uclient_http, ufd.stream); 800 801 __uclient_notify_read(uh); 802 } 803 804 static void uclient_notify_write(struct ustream *us, int bytes) 805 { 806 struct uclient_http *uh = container_of(us, struct uclient_http, ufd.stream); 807 808 __uclient_notify_write(uh); 809 } 810 811 static void uclient_notify_state(struct ustream *us) 812 { 813 struct uclient_http *uh = container_of(us, struct uclient_http, ufd.stream); 814 815 if (uh->ufd.stream.write_error) { 816 uclient_http_error(uh, UCLIENT_ERROR_CONNECT); 817 return; 818 } 819 uclient_notify_eof(uh); 820 } 821 822 static int uclient_setup_http(struct uclient_http *uh) 823 { 824 struct ustream *us = &uh->ufd.stream; 825 int ret; 826 827 uh->us = us; 828 uh->ssl = false; 829 830 us->string_data = true; 831 us->notify_state = uclient_notify_state; 832 us->notify_read = uclient_notify_read; 833 us->notify_write = uclient_notify_write; 834 835 ret = uclient_do_connect(uh, "80"); 836 if (ret) 837 return UCLIENT_ERROR_CONNECT; 838 839 return 0; 840 } 841 842 static void uclient_ssl_notify_read(struct ustream *us, int bytes) 843 { 844 struct uclient_http *uh = container_of(us, struct uclient_http, ussl.stream); 845 846 __uclient_notify_read(uh); 847 } 848 849 static void uclient_ssl_notify_write(struct ustream *us, int bytes) 850 { 851 struct uclient_http *uh = container_of(us, struct uclient_http, ussl.stream); 852 853 __uclient_notify_write(uh); 854 } 855 856 static void uclient_ssl_notify_state(struct ustream *us) 857 { 858 struct uclient_http *uh = container_of(us, struct uclient_http, ussl.stream); 859 860 uclient_notify_eof(uh); 861 } 862 863 static void uclient_ssl_notify_error(struct ustream_ssl *ssl, int error, const char *str) 864 { 865 struct uclient_http *uh = container_of(ssl, struct uclient_http, ussl); 866 867 uclient_http_error(uh, UCLIENT_ERROR_CONNECT); 868 } 869 870 static void uclient_ssl_notify_verify_error(struct ustream_ssl *ssl, int error, const char *str) 871 { 872 struct uclient_http *uh = container_of(ssl, struct uclient_http, ussl); 873 874 if (!uh->ssl_require_validation) 875 return; 876 877 uclient_http_error(uh, UCLIENT_ERROR_SSL_INVALID_CERT); 878 } 879 880 static void uclient_ssl_notify_connected(struct ustream_ssl *ssl) 881 { 882 struct uclient_http *uh = container_of(ssl, struct uclient_http, ussl); 883 884 if (!uh->ssl_require_validation) 885 return; 886 887 if (!uh->ussl.valid_cn) 888 uclient_http_error(uh, UCLIENT_ERROR_SSL_CN_MISMATCH); 889 } 890 891 static int uclient_setup_https(struct uclient_http *uh) 892 { 893 struct ustream *us = &uh->ussl.stream; 894 int ret; 895 896 uh->ssl = true; 897 uh->us = us; 898 899 if (!uh->ssl_ctx) 900 return UCLIENT_ERROR_MISSING_SSL_CONTEXT; 901 902 ret = uclient_do_connect(uh, "443"); 903 if (ret) 904 return UCLIENT_ERROR_CONNECT; 905 906 us->string_data = true; 907 us->notify_state = uclient_ssl_notify_state; 908 us->notify_read = uclient_ssl_notify_read; 909 us->notify_write = uclient_ssl_notify_write; 910 uh->ussl.notify_error = uclient_ssl_notify_error; 911 uh->ussl.notify_verify_error = uclient_ssl_notify_verify_error; 912 uh->ussl.notify_connected = uclient_ssl_notify_connected; 913 uh->ussl.server_name = uh->uc.url->host; 914 uh->ssl_ops->init(&uh->ussl, &uh->ufd.stream, uh->ssl_ctx, false); 915 uh->ssl_ops->set_peer_cn(&uh->ussl, uh->uc.url->host); 916 917 return 0; 918 } 919 920 static int uclient_http_connect(struct uclient *cl) 921 { 922 struct uclient_http *uh = container_of(cl, struct uclient_http, uc); 923 int ret; 924 925 if (!cl->eof || uh->disconnect || uh->connection_close) 926 uclient_http_disconnect(uh); 927 928 uclient_http_init_request(uh); 929 930 if (uh->us) 931 return 0; 932 933 uh->ssl = cl->url->prefix == PREFIX_HTTPS; 934 935 if (uh->ssl) 936 ret = uclient_setup_https(uh); 937 else 938 ret = uclient_setup_http(uh); 939 940 return ret; 941 } 942 943 static void uclient_http_disconnect_cb(struct uloop_timeout *timeout) 944 { 945 struct uclient_http *uh = container_of(timeout, struct uclient_http, disconnect_t); 946 947 uclient_http_disconnect(uh); 948 } 949 950 static struct uclient *uclient_http_alloc(void) 951 { 952 struct uclient_http *uh; 953 954 uh = calloc_a(sizeof(*uh)); 955 if (!uh) 956 return NULL; 957 958 uh->disconnect_t.cb = uclient_http_disconnect_cb; 959 blob_buf_init(&uh->headers, 0); 960 961 return &uh->uc; 962 } 963 964 static void uclient_http_free_ssl_ctx(struct uclient_http *uh) 965 { 966 uh->ssl_ops = NULL; 967 uh->ssl_ctx = NULL; 968 } 969 970 static void uclient_http_free(struct uclient *cl) 971 { 972 struct uclient_http *uh = container_of(cl, struct uclient_http, uc); 973 974 uclient_http_free_url_state(cl); 975 uclient_http_free_ssl_ctx(uh); 976 blob_buf_free(&uh->headers); 977 blob_buf_free(&uh->meta); 978 free(uh); 979 } 980 981 int 982 uclient_http_set_request_type(struct uclient *cl, const char *type) 983 { 984 struct uclient_http *uh = container_of(cl, struct uclient_http, uc); 985 unsigned int i; 986 987 if (cl->backend != &uclient_backend_http) 988 return -1; 989 990 if (uh->state > HTTP_STATE_INIT) 991 return -1; 992 993 for (i = 0; i < ARRAY_SIZE(request_types); i++) { 994 if (strcmp(request_types[i], type) != 0) 995 continue; 996 997 uh->req_type = i; 998 return 0; 999 } 1000 1001 return -1; 1002 } 1003 1004 int 1005 uclient_http_reset_headers(struct uclient *cl) 1006 { 1007 struct uclient_http *uh = container_of(cl, struct uclient_http, uc); 1008 1009 blob_buf_init(&uh->headers, 0); 1010 1011 return 0; 1012 } 1013 1014 int 1015 uclient_http_set_header(struct uclient *cl, const char *name, const char *value) 1016 { 1017 struct uclient_http *uh = container_of(cl, struct uclient_http, uc); 1018 1019 if (cl->backend != &uclient_backend_http) 1020 return -1; 1021 1022 if (uh->state > HTTP_STATE_INIT) 1023 return -1; 1024 1025 blobmsg_add_string(&uh->headers, name, value); 1026 return 0; 1027 } 1028 1029 static int 1030 uclient_http_send_data(struct uclient *cl, const char *buf, unsigned int len) 1031 { 1032 struct uclient_http *uh = container_of(cl, struct uclient_http, uc); 1033 int err; 1034 1035 if (uh->state >= HTTP_STATE_REQUEST_DONE) 1036 return -1; 1037 1038 err = uclient_http_send_headers(uh); 1039 if (err) 1040 return err; 1041 1042 if (len > 0) { 1043 ustream_printf(uh->us, "%X\r\n", len); 1044 ustream_write(uh->us, buf, len, false); 1045 ustream_printf(uh->us, "\r\n"); 1046 } 1047 1048 return len; 1049 } 1050 1051 static int 1052 uclient_http_request_done(struct uclient *cl) 1053 { 1054 struct uclient_http *uh = container_of(cl, struct uclient_http, uc); 1055 int err; 1056 1057 if (uh->state >= HTTP_STATE_REQUEST_DONE) 1058 return -1; 1059 1060 err = uclient_http_send_headers(uh); 1061 if (err) 1062 return err; 1063 1064 if (uclient_request_supports_body(uh->req_type)) 1065 ustream_printf(uh->us, "\r\n\r\n"); 1066 uh->state = HTTP_STATE_REQUEST_DONE; 1067 1068 return 0; 1069 } 1070 1071 static int 1072 uclient_http_read(struct uclient *cl, char *buf, unsigned int len) 1073 { 1074 struct uclient_http *uh = container_of(cl, struct uclient_http, uc); 1075 int read_len = 0; 1076 char *data, *data_end; 1077 1078 if (uh->state < HTTP_STATE_RECV_DATA || !uh->us) 1079 return 0; 1080 1081 data = ustream_get_read_buf(uh->us, &read_len); 1082 if (!data || !read_len) 1083 return 0; 1084 1085 data_end = data + read_len; 1086 read_len = 0; 1087 1088 if (uh->read_chunked == 0) { 1089 char *sep; 1090 1091 if (data[0] == '\r' && data[1] == '\n') { 1092 data += 2; 1093 read_len += 2; 1094 } 1095 1096 sep = strstr(data, "\r\n"); 1097 if (!sep) 1098 return 0; 1099 1100 *sep = 0; 1101 uh->read_chunked = strtoul(data, NULL, 16); 1102 1103 read_len += sep + 2 - data; 1104 data = sep + 2; 1105 1106 if (!uh->read_chunked) { 1107 uh->eof = true; 1108 uh->uc.data_eof = true; 1109 } 1110 } 1111 1112 unsigned int diff = data_end - data; 1113 if (len > diff) 1114 len = diff; 1115 1116 if (uh->read_chunked >= 0) { 1117 if (len > (unsigned long) uh->read_chunked) 1118 len = uh->read_chunked; 1119 1120 uh->read_chunked -= len; 1121 } else if (uh->content_length >= 0) { 1122 if (len > (unsigned long) uh->content_length) 1123 len = uh->content_length; 1124 1125 uh->content_length -= len; 1126 if (!uh->content_length) { 1127 uh->eof = true; 1128 uh->uc.data_eof = true; 1129 } 1130 } 1131 1132 if (len > 0) { 1133 read_len += len; 1134 memcpy(buf, data, len); 1135 } 1136 1137 if (read_len > 0) 1138 ustream_consume(uh->us, read_len); 1139 1140 uclient_notify_eof(uh); 1141 1142 /* Now that we consumed something and if this isn't EOF, start timer again */ 1143 if (!uh->uc.eof && !cl->connection_timeout.pending) 1144 uloop_timeout_set(&cl->connection_timeout, cl->timeout_msecs); 1145 1146 return len; 1147 } 1148 1149 int uclient_http_redirect(struct uclient *cl) 1150 { 1151 struct uclient_http *uh = container_of(cl, struct uclient_http, uc); 1152 struct blobmsg_policy location = { 1153 .name = "location", 1154 .type = BLOBMSG_TYPE_STRING, 1155 }; 1156 struct uclient_url *url = cl->url; 1157 struct blob_attr *tb; 1158 1159 if (cl->backend != &uclient_backend_http) 1160 return false; 1161 1162 switch (cl->status_code) { 1163 case 301: 1164 case 302: 1165 case 307: 1166 break; 1167 default: 1168 return false; 1169 } 1170 1171 blobmsg_parse(&location, 1, &tb, blob_data(uh->meta.head), blob_len(uh->meta.head)); 1172 if (!tb) 1173 return false; 1174 1175 url = uclient_get_url_location(url, blobmsg_data(tb)); 1176 if (!url) 1177 return false; 1178 1179 if (cl->proxy_url) { 1180 free(cl->proxy_url); 1181 cl->proxy_url = url; 1182 } 1183 else { 1184 free(cl->url); 1185 cl->url = url; 1186 } 1187 1188 if (uclient_http_connect(cl)) 1189 return -1; 1190 1191 uclient_http_request_done(cl); 1192 1193 return true; 1194 } 1195 1196 int uclient_http_set_ssl_ctx(struct uclient *cl, const struct ustream_ssl_ops *ops, 1197 struct ustream_ssl_ctx *ctx, bool require_validation) 1198 { 1199 struct uclient_http *uh = container_of(cl, struct uclient_http, uc); 1200 1201 if (cl->backend != &uclient_backend_http) 1202 return -1; 1203 1204 uclient_http_free_url_state(cl); 1205 1206 uclient_http_free_ssl_ctx(uh); 1207 uh->ssl_ops = ops; 1208 uh->ssl_ctx = ctx; 1209 uh->ssl_require_validation = !!ctx && require_validation; 1210 1211 return 0; 1212 } 1213 1214 int uclient_http_set_address_family(struct uclient *cl, int af) 1215 { 1216 struct uclient_http *uh = container_of(cl, struct uclient_http, uc); 1217 1218 if (cl->backend != &uclient_backend_http) 1219 return -1; 1220 1221 switch (af) { 1222 case AF_INET: 1223 uh->usock_flags = USOCK_IPV4ONLY; 1224 break; 1225 case AF_INET6: 1226 uh->usock_flags = USOCK_IPV6ONLY; 1227 break; 1228 default: 1229 uh->usock_flags = 0; 1230 break; 1231 } 1232 1233 return 0; 1234 } 1235 1236 const struct uclient_backend uclient_backend_http = { 1237 .prefix = uclient_http_prefix, 1238 1239 .alloc = uclient_http_alloc, 1240 .free = uclient_http_free, 1241 .connect = uclient_http_connect, 1242 .disconnect = uclient_http_request_disconnect, 1243 .update_url = uclient_http_free_url_state, 1244 .update_proxy_url = uclient_http_free_url_state, 1245 1246 .read = uclient_http_read, 1247 .write = uclient_http_send_data, 1248 .request = uclient_http_request_done, 1249 }; 1250
This page was automatically generated by LXR 0.3.1. • OpenWrt