diff options
Diffstat (limited to 'net/lwip/wget.c')
-rw-r--r-- | net/lwip/wget.c | 102 |
1 files changed, 85 insertions, 17 deletions
diff --git a/net/lwip/wget.c b/net/lwip/wget.c index 53c3b169e01..46858cb5dd3 100644 --- a/net/lwip/wget.c +++ b/net/lwip/wget.c @@ -7,19 +7,23 @@ #include <efi_loader.h> #include <image.h> #include <lwip/apps/http_client.h> +#include "lwip/altcp_tls.h" #include <lwip/timeouts.h> +#include <rng.h> #include <mapmem.h> #include <net.h> #include <time.h> +#include <dm/uclass.h> -#define SERVER_NAME_SIZE 200 +#define SERVER_NAME_SIZE 254 #define HTTP_PORT_DEFAULT 80 +#define HTTPS_PORT_DEFAULT 443 #define PROGRESS_PRINT_STEP_BYTES (100 * 1024) enum done_state { - NOT_DONE = 0, - SUCCESS = 1, - FAILURE = 2 + NOT_DONE = 0, + SUCCESS = 1, + FAILURE = 2 }; struct wget_ctx { @@ -46,18 +50,54 @@ static void wget_lwip_set_file_size(u32_t rx_content_len) wget_info->file_size = (ulong)rx_content_len; } -static int parse_url(char *url, char *host, u16 *port, char **path) +bool wget_validate_uri(char *uri); + +int mbedtls_hardware_poll(void *data, unsigned char *output, size_t len, + size_t *olen) +{ + struct udevice *dev; + int ret; + + *olen = 0; + + ret = uclass_get_device(UCLASS_RNG, 0, &dev); + if (ret) { + log_err("Failed to get an rng: %d\n", ret); + return ret; + } + ret = dm_rng_read(dev, output, len); + if (ret) + return ret; + + *olen = len; + + return 0; +} + +static int parse_url(char *url, char *host, u16 *port, char **path, + bool *is_https) { char *p, *pp; long lport; + size_t prefix_len = 0; + if (!wget_validate_uri(url)) { + log_err("Invalid URL. Use http(s)://\n"); + return -EINVAL; + } + + *is_https = false; + *port = HTTP_PORT_DEFAULT; + prefix_len = strlen("http://"); p = strstr(url, "http://"); if (!p) { - log_err("only http:// is supported\n"); - return -EINVAL; + p = strstr(url, "https://"); + prefix_len = strlen("https://"); + *port = HTTPS_PORT_DEFAULT; + *is_https = true; } - p += strlen("http://"); + p += prefix_len; /* Parse hostname */ pp = strchr(p, ':'); @@ -81,9 +121,8 @@ static int parse_url(char *url, char *host, u16 *port, char **path) if (lport > 65535) return -EINVAL; *port = (u16)lport; - } else { - *port = HTTP_PORT_DEFAULT; } + if (*pp != '/') return -EINVAL; *path = pp; @@ -136,7 +175,7 @@ static int parse_legacy_arg(char *arg, char *nurl, size_t rem) if (rem < n) return -1; - strncpy(p, server, n); + strlcpy(p, server, n); p += n; rem -= n; if (rem < 1) @@ -147,7 +186,7 @@ static int parse_legacy_arg(char *arg, char *nurl, size_t rem) n = strlen(path); if (rem < n) return -1; - strncpy(p, path, n); + strlcpy(p, path, n); p += n; rem -= n; if (rem < 1) @@ -244,11 +283,17 @@ static err_t httpc_headers_done_cb(httpc_state_t *connection, void *arg, struct static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri) { + char server_name[SERVER_NAME_SIZE]; +#if defined CONFIG_WGET_HTTPS + altcp_allocator_t tls_allocator; +#endif httpc_connection_t conn; httpc_state_t *state; struct netif *netif; struct wget_ctx ctx; char *path; + u16 port; + bool is_https; ctx.daddr = dst_addr; ctx.saved_daddr = dst_addr; @@ -257,7 +302,7 @@ static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri) ctx.prevsize = 0; ctx.start_time = 0; - if (parse_url(uri, ctx.server_name, &ctx.port, &path)) + if (parse_url(uri, server_name, &port, &path, &is_https)) return CMD_RET_USAGE; netif = net_lwip_new_netif(udev); @@ -265,6 +310,22 @@ static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri) return -1; memset(&conn, 0, sizeof(conn)); +#if defined CONFIG_WGET_HTTPS + if (is_https) { + tls_allocator.alloc = &altcp_tls_alloc; + tls_allocator.arg = + altcp_tls_create_config_client(NULL, 0, server_name); + + if (!tls_allocator.arg) { + log_err("error: Cannot create a TLS connection\n"); + net_lwip_remove_netif(netif); + return -1; + } + + conn.altcp_allocator = &tls_allocator; + } +#endif + conn.result_fn = httpc_result_cb; conn.headers_done_fn = httpc_headers_done_cb; ctx.path = path; @@ -310,7 +371,7 @@ int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]) return CMD_RET_USAGE; dst_addr = hextoul(argv[1], &end); - if (end == (argv[1] + strlen(argv[1]))) { + if (end == (argv[1] + strlen(argv[1]))) { if (argc < 3) return CMD_RET_USAGE; url = argv[2]; @@ -320,7 +381,7 @@ int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]) } if (parse_legacy_arg(url, nurl, sizeof(nurl))) - return CMD_RET_FAILURE; + return CMD_RET_FAILURE; wget_info = &default_wget_info; if (wget_with_dns(dst_addr, nurl)) @@ -354,6 +415,7 @@ bool wget_validate_uri(char *uri) char c; bool ret = true; char *str_copy, *s, *authority; + size_t prefix_len = 0; for (c = 0x1; c < 0x21; c++) { if (strchr(uri, c)) { @@ -361,15 +423,21 @@ bool wget_validate_uri(char *uri) return false; } } + if (strchr(uri, 0x7f)) { log_err("invalid character is used\n"); return false; } - if (strncmp(uri, "http://", 7)) { - log_err("only http:// is supported\n"); + if (!strncmp(uri, "http://", strlen("http://"))) { + prefix_len = strlen("http://"); + } else if (!strncmp(uri, "https://", strlen("https://"))) { + prefix_len = strlen("https://"); + } else { + log_err("only http(s):// is supported\n"); return false; } + str_copy = strdup(uri); if (!str_copy) return false; |