• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/uclient/uclient-http.c

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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt