diff --git a/src/http-ntlm.c b/src/http-ntlm.c index 87f5a37c..72f6fcd5 100644 --- a/src/http-ntlm.c +++ b/src/http-ntlm.c @@ -122,7 +122,7 @@ ntlm_input (struct ntlmdata *ntlm, const char *header) DEBUGP (("Received a type-2 NTLM message.\n")); - size = wget_base64_decode (header, buffer); + size = wget_base64_decode (header, buffer, strlen (header)); if (size < 0) return false; /* malformed base64 from server */ diff --git a/src/http.c b/src/http.c index 323f5595..da6552e2 100644 --- a/src/http.c +++ b/src/http.c @@ -2998,7 +2998,7 @@ skip_content_type: char *bin_hash = alloca (dig_hash_str_len * 3 / 4 + 1); ssize_t hash_bin_len; - hash_bin_len = wget_base64_decode (dig_hash, bin_hash); + hash_bin_len = wget_base64_decode (dig_hash, bin_hash, dig_hash_str_len * 3 / 4 + 1); /* Detect malformed base64 input. */ if (hash_bin_len < 0) diff --git a/src/utils.c b/src/utils.c index 3a57e6c7..81f28010 100644 --- a/src/utils.c +++ b/src/utils.c @@ -2346,7 +2346,7 @@ wget_base64_encode (const void *data, size_t length, char *dest) This function originates from Free Recode. */ ssize_t -wget_base64_decode (const char *base64, void *dest) +wget_base64_decode (const char *base64, void *dest, size_t size) { /* Table of base64 values for first 128 characters. Note that this assumes ASCII (but so does Wget in other places). */ @@ -2370,7 +2370,8 @@ wget_base64_decode (const char *base64, void *dest) #define IS_BASE64(c) ((IS_ASCII (c) && BASE64_CHAR_TO_VALUE (c) >= 0) || c == '=') const char *p = base64; - char *q = dest; + unsigned char *q = dest; + ssize_t n = 0; while (1) { @@ -2392,7 +2393,12 @@ wget_base64_decode (const char *base64, void *dest) if (c == '=' || !IS_BASE64 (c)) return -1; /* illegal char while decoding base64 */ value |= BASE64_CHAR_TO_VALUE (c) << 12; - *q++ = value >> 16; + if (size) + { + *q++ = value >> 16; + size--; + } + n++; /* Process third byte of a quadruplet. */ NEXT_CHAR (c, p); @@ -2412,7 +2418,12 @@ wget_base64_decode (const char *base64, void *dest) } value |= BASE64_CHAR_TO_VALUE (c) << 6; - *q++ = 0xff & value >> 8; + if (size) + { + *q++ = 0xff & value >> 8; + size--; + } + n++; /* Process fourth byte of a quadruplet. */ NEXT_CHAR (c, p); @@ -2424,12 +2435,17 @@ wget_base64_decode (const char *base64, void *dest) return -1; /* illegal char while decoding base64 */ value |= BASE64_CHAR_TO_VALUE (c); - *q++ = 0xff & value; + if (size) + { + *q++ = 0xff & value; + size--; + } + n++; } #undef IS_BASE64 #undef BASE64_CHAR_TO_VALUE - return q - (char *) dest; + return n; } #ifdef HAVE_LIBPCRE @@ -2726,7 +2742,7 @@ wg_pubkey_pem_to_der (const char *pem, unsigned char **der, size_t *der_len) base64data = xmalloc (BASE64_LENGTH(stripped_pem_count)); - size = wget_base64_decode (stripped_pem, base64data); + size = wget_base64_decode (stripped_pem, base64data, BASE64_LENGTH(stripped_pem_count)); if (size < 0) { xfree (base64data); /* malformed base64 from server */ @@ -2765,54 +2781,65 @@ wg_pin_peer_pubkey (const char *pinnedpubkey, const char *pubkey, size_t pubkeyl return result; /* only do this if pinnedpubkey starts with "sha256//", length 8 */ - if (strncmp (pinnedpubkey, "sha256//", 8) == 0) { - /* compute sha256sum of public key */ - sha256sumdigest = xmalloc (SHA256_DIGEST_SIZE); - sha256_buffer (pubkey, pubkeylen, sha256sumdigest); - expectedsha256sumdigest = xmalloc (SHA256_DIGEST_SIZE + 1); + if (strncmp (pinnedpubkey, "sha256//", 8) == 0) + { + /* compute sha256sum of public key */ + sha256sumdigest = xmalloc (SHA256_DIGEST_SIZE); + sha256_buffer (pubkey, pubkeylen, sha256sumdigest); + expectedsha256sumdigest = xmalloc (SHA256_DIGEST_SIZE); - /* it starts with sha256//, copy so we can modify it */ - pinkeylen = strlen (pinnedpubkey) + 1; - pinkeycopy = xmalloc (pinkeylen); - memcpy (pinkeycopy, pinnedpubkey, pinkeylen); + /* it starts with sha256//, copy so we can modify it */ + pinkeylen = strlen (pinnedpubkey) + 1; + pinkeycopy = xmalloc (pinkeylen); + memcpy (pinkeycopy, pinnedpubkey, pinkeylen); - /* point begin_pos to the copy, and start extracting keys */ - begin_pos = pinkeycopy; - do - { - end_pos = strstr (begin_pos, ";sha256//"); - /* - * if there is an end_pos, null terminate, - * otherwise it'll go to the end of the original string - */ - if (end_pos) - end_pos[0] = '\0'; + /* point begin_pos to the copy, and start extracting keys */ + begin_pos = pinkeycopy; + do + { + end_pos = strstr (begin_pos, ";sha256//"); + /* + * if there is an end_pos, null terminate, + * otherwise it'll go to the end of the original string + */ + if (end_pos) + end_pos[0] = '\0'; - /* decode base64 pinnedpubkey, 8 is length of "sha256//" */ - decoded_hash_length = wget_base64_decode (begin_pos + 8, expectedsha256sumdigest); - /* if valid base64, compare sha256 digests directly */ - if (SHA256_DIGEST_SIZE == decoded_hash_length && - !memcmp (sha256sumdigest, expectedsha256sumdigest, SHA256_DIGEST_SIZE)) { - result = true; - break; + /* decode base64 pinnedpubkey, 8 is length of "sha256//" */ + decoded_hash_length = wget_base64_decode (begin_pos + 8, expectedsha256sumdigest, SHA256_DIGEST_SIZE); + + /* if valid base64, compare sha256 digests directly */ + if (SHA256_DIGEST_SIZE == decoded_hash_length) + { + if (!memcmp (sha256sumdigest, expectedsha256sumdigest, SHA256_DIGEST_SIZE)) + { + result = true; + break; + } + } + else + logprintf (LOG_VERBOSE, _ ("Skipping key with wrong size (%d/%d): %s\n"), + (strlen (begin_pos + 8) * 3) / 4, SHA256_DIGEST_SIZE, + quote (begin_pos + 8)); + + /* + * change back the null-terminator we changed earlier, + * and look for next begin + */ + if (end_pos) + { + end_pos[0] = ';'; + begin_pos = strstr (end_pos, "sha256//"); + } } + while (end_pos && begin_pos); - /* - * change back the null-terminator we changed earlier, - * and look for next begin - */ - if (end_pos) { - end_pos[0] = ';'; - begin_pos = strstr (end_pos, "sha256//"); - } - } while (end_pos && begin_pos); + xfree (sha256sumdigest); + xfree (expectedsha256sumdigest); + xfree (pinkeycopy); - xfree (sha256sumdigest); - xfree (expectedsha256sumdigest); - xfree (pinkeycopy); - - return result; - } + return result; + } /* fall back to assuming this is a file path */ fm = wget_read_file (pinnedpubkey); @@ -2832,11 +2859,12 @@ wg_pin_peer_pubkey (const char *pinnedpubkey, const char *pubkey, size_t pubkeyl goto cleanup; /* If the sizes are the same, it can't be base64 encoded, must be der */ - if (pubkeylen == size) { - if (!memcmp (pubkey, fm->content, pubkeylen)) - result = true; - goto cleanup; - } + if (pubkeylen == size) + { + if (!memcmp (pubkey, fm->content, pubkeylen)) + result = true; + goto cleanup; + } /* * Otherwise we will assume it's PEM and try to decode it @@ -2858,7 +2886,7 @@ wg_pin_peer_pubkey (const char *pinnedpubkey, const char *pubkey, size_t pubkeyl if (pubkeylen == pem_len && !memcmp (pubkey, pem_ptr, pubkeylen)) result = true; - cleanup: +cleanup: xfree (buf); xfree (pem_ptr); wget_read_file_free (fm); diff --git a/src/utils.h b/src/utils.h index 8acb2589..9936d97c 100644 --- a/src/utils.h +++ b/src/utils.h @@ -149,7 +149,7 @@ void xsleep (double); #define BASE64_LENGTH(len) (4 * (((len) + 2) / 3)) size_t wget_base64_encode (const void *, size_t, char *); -ssize_t wget_base64_decode (const char *, void *); +ssize_t wget_base64_decode (const char *, void *, size_t); #ifdef HAVE_LIBPCRE void *compile_pcre_regex (const char *);