diff options
-rw-r--r-- | doc/usage/cmd/wget.rst | 2 | ||||
-rw-r--r-- | include/net-common.h | 2 | ||||
-rw-r--r-- | lib/efi_loader/efi_net.c | 2 | ||||
-rw-r--r-- | lib/lwip/lwip/src/apps/altcp_tls/altcp_tls_mbedtls.c | 8 | ||||
-rw-r--r-- | net/lwip/tftp.c | 71 | ||||
-rw-r--r-- | net/lwip/wget.c | 122 | ||||
-rw-r--r-- | net/wget.c | 23 |
7 files changed, 175 insertions, 55 deletions
diff --git a/doc/usage/cmd/wget.rst b/doc/usage/cmd/wget.rst index cc82e495a29..44033aaff39 100644 --- a/doc/usage/cmd/wget.rst +++ b/doc/usage/cmd/wget.rst @@ -141,9 +141,9 @@ https://cacerts.digicert.com/DigiCertTLSRSA4096RootG5.crt. Bytes transferred = 1864 (748 hex) # Another server not signed against Digicert will fail => wget https://www.google.com/ - Certificate verification failed HTTP client error 4 + Certificate verification failed # Disable authentication to allow the command to proceed anyways => wget cacert none => wget https://www.google.com/ diff --git a/include/net-common.h b/include/net-common.h index e536968a92b..7853612b237 100644 --- a/include/net-common.h +++ b/include/net-common.h @@ -570,6 +570,7 @@ enum wget_http_method { * Filled by client. * @hdr_cont_len: content length according to headers. Filled by wget * @headers: buffer for headers. Filled by wget. + * @silent: do not print anything to the console. Filled by client. */ struct wget_http_info { enum wget_http_method method; @@ -580,6 +581,7 @@ struct wget_http_info { bool check_buffer_size; u32 hdr_cont_len; char *headers; + bool silent; }; extern struct wget_http_info default_wget_info; diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c index b3291b4f1d5..9ff0b691ee1 100644 --- a/lib/efi_loader/efi_net.c +++ b/lib/efi_loader/efi_net.c @@ -51,7 +51,7 @@ static int next_dp_entry; static struct wget_http_info efi_wget_info = { .set_bootdev = false, .check_buffer_size = true, - + .silent = true, }; #endif diff --git a/lib/lwip/lwip/src/apps/altcp_tls/altcp_tls_mbedtls.c b/lib/lwip/lwip/src/apps/altcp_tls/altcp_tls_mbedtls.c index ef51a5ac168..7459bfa468f 100644 --- a/lib/lwip/lwip/src/apps/altcp_tls/altcp_tls_mbedtls.c +++ b/lib/lwip/lwip/src/apps/altcp_tls/altcp_tls_mbedtls.c @@ -60,6 +60,8 @@ #if LWIP_ALTCP_TLS && LWIP_ALTCP_TLS_MBEDTLS +#include "lwip/errno.h" + #include "lwip/altcp.h" #include "lwip/altcp_tls.h" #include "lwip/priv/altcp_priv.h" @@ -299,7 +301,8 @@ altcp_mbedtls_lower_recv_process(struct altcp_pcb *conn, altcp_mbedtls_state_t * LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ssl_handshake failed: %d\n", ret)); /* handshake failed, connection has to be closed */ if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) { - printf("Certificate verification failed\n"); + /* provide a cause for why the connection is closed to the called */ + errno = EPERM; } if (conn->err) { conn->err(conn->arg, ERR_CLSD); @@ -844,9 +847,6 @@ altcp_tls_create_config(int is_server, u8_t cert_count, u8_t pkey_count, int hav altcp_mbedtls_free_config(conf); return NULL; } - if (authmode == MBEDTLS_SSL_VERIFY_NONE) { - printf("WARNING: no CA certificates, HTTPS connections not authenticated\n"); - } mbedtls_ssl_conf_authmode(&conf->conf, authmode); mbedtls_ssl_conf_rng(&conf->conf, mbedtls_ctr_drbg_random, &altcp_tls_entropy_rng->ctr_drbg); diff --git a/net/lwip/tftp.c b/net/lwip/tftp.c index 4f9b2049187..fae701bad2e 100644 --- a/net/lwip/tftp.c +++ b/net/lwip/tftp.c @@ -8,6 +8,7 @@ #include <efi_loader.h> #include <image.h> #include <linux/delay.h> +#include <linux/kconfig.h> #include <lwip/apps/tftp_client.h> #include <lwip/timeouts.h> #include <mapmem.h> @@ -15,6 +16,8 @@ #include <time.h> #define PROGRESS_PRINT_STEP_BYTES (10 * 1024) +/* Max time to wait for first data packet from server */ +#define NO_RSP_TIMEOUT_MS 10000 enum done_state { NOT_DONE = 0, @@ -31,6 +34,47 @@ struct tftp_ctx { enum done_state done; }; +/** + * store_block() - copy received data + * + * This function is called by the receive callback to copy a block of data + * into its final location (ctx->daddr). Before doing so, it checks if the copy + * is allowed. + * + * @ctx: the context for the current transfer + * @src: the data received from the TCP stack + * @len: the length of the data + */ +static int store_block(struct tftp_ctx *ctx, void *src, u16_t len) +{ + ulong store_addr = ctx->daddr; + void *ptr; + + if (CONFIG_IS_ENABLED(LMB)) { + if (store_addr + len < store_addr || + lmb_read_check(store_addr, len)) { + puts("\nTFTP error: "); + puts("trying to overwrite reserved memory...\n"); + return -1; + } + } + + ptr = map_sysmem(store_addr, len); + memcpy(ptr, src, len); + unmap_sysmem(ptr); + + ctx->daddr += len; + ctx->size += len; + ctx->block_count++; + if (ctx->block_count % 10 == 0) { + putc('#'); + if (ctx->block_count % (65 * 10) == 0) + puts("\n\t "); + } + + return 0; +} + static void *tftp_open(const char *fname, const char *mode, u8_t is_write) { return NULL; @@ -71,17 +115,9 @@ static int tftp_write(void *handle, struct pbuf *p) struct tftp_ctx *ctx = handle; struct pbuf *q; - for (q = p; q; q = q->next) { - memcpy((void *)ctx->daddr, q->payload, q->len); - ctx->daddr += q->len; - ctx->size += q->len; - ctx->block_count++; - if (ctx->block_count % 10 == 0) { - putc('#'); - if (ctx->block_count % (65 * 10) == 0) - puts("\n\t "); - } - } + for (q = p; q; q = q->next) + if (store_block(ctx, q->payload, q->len) < 0) + return -1; return 0; } @@ -106,6 +142,17 @@ static const struct tftp_context tftp_context = { tftp_error }; +static void no_response(void *arg) +{ + struct tftp_ctx *ctx = (struct tftp_ctx *)arg; + + if (ctx->size) + return; + + printf("Timeout!\n"); + ctx->done = FAILURE; +} + static int tftp_loop(struct udevice *udev, ulong addr, char *fname, ip_addr_t srvip, uint16_t srvport) { @@ -150,6 +197,7 @@ static int tftp_loop(struct udevice *udev, ulong addr, char *fname, return -1; } + sys_timeout(NO_RSP_TIMEOUT_MS, no_response, &ctx); while (!ctx.done) { net_lwip_rx(udev, netif); sys_check_timeouts(); @@ -159,6 +207,7 @@ static int tftp_loop(struct udevice *udev, ulong addr, char *fname, break; } } + sys_untimeout(no_response, (void *)&ctx); tftp_cleanup(); diff --git a/net/lwip/wget.c b/net/lwip/wget.c index a3b82908877..ea1113e18b1 100644 --- a/net/lwip/wget.c +++ b/net/lwip/wget.c @@ -6,8 +6,10 @@ #include <display_options.h> #include <efi_loader.h> #include <image.h> +#include <linux/kconfig.h> #include <lwip/apps/http_client.h> #include "lwip/altcp_tls.h" +#include <lwip/errno.h> #include <lwip/timeouts.h> #include <rng.h> #include <mapmem.h> @@ -201,11 +203,58 @@ static int parse_legacy_arg(char *arg, char *nurl, size_t rem) return 0; } +/** + * store_block() - copy received data + * + * This function is called by the receive callback to copy a block of data + * into its final location (ctx->daddr). Before doing so, it checks if the copy + * is allowed. + * + * @ctx: the context for the current transfer + * @src: the data received from the TCP stack + * @len: the length of the data + */ +static int store_block(struct wget_ctx *ctx, void *src, u16_t len) +{ + ulong store_addr = ctx->daddr; + uchar *ptr; + + /* Avoid overflow */ + if (wget_info->buffer_size && wget_info->buffer_size < ctx->size + len) + return -1; + + if (CONFIG_IS_ENABLED(LMB) && wget_info->set_bootdev) { + if (store_addr + len < store_addr || + lmb_read_check(store_addr, len)) { + if (!wget_info->silent) { + printf("\nwget error: "); + printf("trying to overwrite reserved memory\n"); + } + return -1; + } + } + + ptr = map_sysmem(store_addr, len); + memcpy(ptr, src, len); + unmap_sysmem(ptr); + + ctx->daddr += len; + ctx->size += len; + if (ctx->size - ctx->prevsize > PROGRESS_PRINT_STEP_BYTES) { + if (!wget_info->silent) + printf("#"); + ctx->prevsize = ctx->size; + } + + return 0; +} + static err_t httpc_recv_cb(void *arg, struct altcp_pcb *pcb, struct pbuf *pbuf, err_t err) { struct wget_ctx *ctx = arg; struct pbuf *buf; + err_t ret; if (!pbuf) return ERR_BUF; @@ -214,18 +263,17 @@ static err_t httpc_recv_cb(void *arg, struct altcp_pcb *pcb, struct pbuf *pbuf, ctx->start_time = get_timer(0); for (buf = pbuf; buf; buf = buf->next) { - memcpy((void *)ctx->daddr, buf->payload, buf->len); - ctx->daddr += buf->len; - ctx->size += buf->len; - if (ctx->size - ctx->prevsize > PROGRESS_PRINT_STEP_BYTES) { - printf("#"); - ctx->prevsize = ctx->size; + if (store_block(ctx, buf->payload, buf->len) < 0) { + altcp_abort(pcb); + ret = ERR_BUF; + goto out; } } - altcp_recved(pcb, pbuf->tot_len); + ret = ERR_OK; +out: pbuf_free(pbuf); - return ERR_OK; + return ret; } static void httpc_result_cb(void *arg, httpc_result_t httpc_result, @@ -255,11 +303,15 @@ static void httpc_result_cb(void *arg, httpc_result_t httpc_result, elapsed = get_timer(ctx->start_time); if (!elapsed) elapsed = 1; - if (rx_content_len > PROGRESS_PRINT_STEP_BYTES) - printf("\n"); - printf("%u bytes transferred in %lu ms (", rx_content_len, elapsed); - print_size(rx_content_len / elapsed * 1000, "/s)\n"); - printf("Bytes transferred = %lu (%lx hex)\n", ctx->size, ctx->size); + if (!wget_info->silent) { + if (rx_content_len > PROGRESS_PRINT_STEP_BYTES) + printf("\n"); + printf("%u bytes transferred in %lu ms (", rx_content_len, + elapsed); + print_size(rx_content_len / elapsed * 1000, "/s)\n"); + printf("Bytes transferred = %lu (%lx hex)\n", ctx->size, + ctx->size); + } if (wget_info->set_bootdev) efi_set_bootdev("Http", ctx->server_name, ctx->path, map_sysmem(ctx->saved_daddr, 0), rx_content_len); @@ -339,7 +391,8 @@ static int _set_cacert(const void *addr, size_t sz) mbedtls_x509_crt_init(&crt); ret = mbedtls_x509_crt_parse(&crt, cacert, cacert_size); if (ret) { - printf("Could not parse certificates (%d)\n", ret); + if (!wget_info->silent) + printf("Could not parse certificates (%d)\n", ret); free(cacert); cacert = NULL; cacert_size = 0; @@ -372,13 +425,14 @@ static int set_cacert(char * const saddr, char * const ssz) #endif #endif /* CONFIG_WGET_CACERT || CONFIG_WGET_BUILTIN_CACERT */ -static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri) +int wget_do_request(ulong dst_addr, char *uri) { #if CONFIG_IS_ENABLED(WGET_HTTPS) altcp_allocator_t tls_allocator; #endif httpc_connection_t conn; httpc_state_t *state; + struct udevice *udev; struct netif *netif; struct wget_ctx ctx; char *path; @@ -394,6 +448,14 @@ static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri) if (parse_url(uri, ctx.server_name, &ctx.port, &path, &is_https)) return CMD_RET_USAGE; + if (net_lwip_eth_start() < 0) + return CMD_RET_FAILURE; + + if (!wget_info) + wget_info = &default_wget_info; + + udev = eth_get_dev(); + netif = net_lwip_new_netif(udev); if (!netif) return -1; @@ -413,9 +475,10 @@ static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri) if (cacert_auth_mode == AUTH_REQUIRED) { if (!ca || !ca_sz) { - printf("Error: cacert authentication mode is " - "'required' but no CA certificates " - "given\n"); + if (!wget_info->silent) + printf("Error: cacert authentication " + "mode is 'required' but no CA " + "certificates given\n"); return CMD_RET_FAILURE; } } else if (cacert_auth_mode == AUTH_NONE) { @@ -430,6 +493,10 @@ static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri) */ } + if (!ca && !wget_info->silent) { + printf("WARNING: no CA certificates, "); + printf("HTTPS connections not authenticated\n"); + } tls_allocator.alloc = &altcp_tls_alloc; tls_allocator.arg = altcp_tls_create_config_client(ca, ca_sz, @@ -454,6 +521,8 @@ static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri) return CMD_RET_FAILURE; } + errno = 0; + while (!ctx.done) { net_lwip_rx(udev, netif); sys_check_timeouts(); @@ -466,21 +535,10 @@ static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri) if (ctx.done == SUCCESS) return 0; - return -1; -} - -int wget_do_request(ulong dst_addr, char *uri) -{ - int ret; + if (errno == EPERM && !wget_info->silent) + printf("Certificate verification failed\n"); - ret = net_lwip_eth_start(); - if (ret < 0) - return ret; - - if (!wget_info) - wget_info = &default_wget_info; - - return wget_loop(eth_get_dev(), dst_addr, uri); + return -1; } int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]) diff --git a/net/wget.c b/net/wget.c index c73836cbc9d..3c0fff488eb 100644 --- a/net/wget.c +++ b/net/wget.c @@ -59,8 +59,10 @@ static inline int store_block(uchar *src, unsigned int offset, unsigned int len) if (CONFIG_IS_ENABLED(LMB) && wget_info->set_bootdev) { if (store_addr < image_load_addr || lmb_read_check(store_addr, len)) { - printf("\nwget error: "); - printf("trying to overwrite reserved memory...\n"); + if (!wget_info->silent) { + printf("\nwget error: "); + printf("trying to overwrite reserved memory\n"); + } return -1; } } @@ -76,6 +78,9 @@ static void show_block_marker(u32 packets) { int cnt; + if (wget_info->silent) + return; + if (content_length != -1) { if (net_boot_file_size > content_length) content_length = net_boot_file_size; @@ -101,11 +106,15 @@ static void tcp_stream_on_closed(struct tcp_stream *tcp) net_set_state(wget_loop_state); if (wget_loop_state != NETLOOP_SUCCESS) { net_boot_file_size = 0; - printf("\nwget: Transfer Fail, TCP status - %d\n", tcp->status); + if (!wget_info->silent) + printf("\nwget: Transfer Fail, TCP status - %d\n", + tcp->status); return; } - printf("\nPackets received %d, Transfer Successful\n", tcp->rx_packets); + if (!wget_info->silent) + printf("\nPackets received %d, Transfer Successful\n", + tcp->rx_packets); wget_info->file_size = net_boot_file_size; if (wget_info->method == WGET_HTTP_METHOD_GET && wget_info->set_bootdev) { efi_set_bootdev("Http", NULL, image_url, @@ -139,7 +148,8 @@ static void tcp_stream_on_rcv_nxt_update(struct tcp_stream *tcp, u32 rx_bytes) tcp->state == TCP_ESTABLISHED) goto end; - printf("ERROR: misssed HTTP header\n"); + if (!wget_info->silent) + printf("ERROR: misssed HTTP header\n"); tcp_stream_close(tcp); goto end; } @@ -346,7 +356,8 @@ void wget_start(void) tcp_stream_set_on_create_handler(tcp_stream_on_create); tcp = tcp_stream_connect(web_server_ip, server_port); if (!tcp) { - printf("No free tcp streams\n"); + if (!wget_info->silent) + printf("No free tcp streams\n"); net_set_state(NETLOOP_FAIL); return; } |