mirror of
https://github.com/mirror/wget.git
synced 2025-01-27 12:50:13 +08:00
Bugfix: Detect malformed base64 Metalink/HTTP Digest header
* src/http.c (metalink_from_http): Fix hash_bin_len type. Use ssize_t instead than size_t. Reject -1 as base64_decode() return value * testenv/Makefile.am: Add new file * testenv/Test-metalink-http-baddigest.py: New file. Metalink/HTTP malformed base64 Digest header tests On malformed base64 input, ssize_t base64_decode() returns -1. Such value is too big for a size_t variable, and used as xmalloc() value will exaust all the memory.
This commit is contained in:
parent
0538e791fb
commit
5dccb2a9ce
14
src/http.c
14
src/http.c
@ -2894,10 +2894,18 @@ metalink_from_http (const struct response *resp, const struct http_stat *hs,
|
|||||||
Therefore we convert: base64 -> binary -> hex. */
|
Therefore we convert: base64 -> binary -> hex. */
|
||||||
const size_t dig_hash_str_len = strlen (dig_hash);
|
const size_t dig_hash_str_len = strlen (dig_hash);
|
||||||
char *bin_hash = alloca (dig_hash_str_len * 3 / 4 + 1);
|
char *bin_hash = alloca (dig_hash_str_len * 3 / 4 + 1);
|
||||||
size_t hash_bin_len;
|
ssize_t hash_bin_len;
|
||||||
|
|
||||||
hash_bin_len = base64_decode (dig_hash, bin_hash);
|
hash_bin_len = base64_decode (dig_hash, bin_hash);
|
||||||
|
|
||||||
|
/* Detect malformed base64 input. */
|
||||||
|
if (hash_bin_len < 0)
|
||||||
|
{
|
||||||
|
xfree (dig_type);
|
||||||
|
xfree (dig_hash);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* One slot for me, one for zero-termination. */
|
/* One slot for me, one for zero-termination. */
|
||||||
mfile->checksums =
|
mfile->checksums =
|
||||||
xrealloc (mfile->checksums,
|
xrealloc (mfile->checksums,
|
||||||
@ -2905,8 +2913,8 @@ metalink_from_http (const struct response *resp, const struct http_stat *hs,
|
|||||||
mfile->checksums[hash_count] = xnew (metalink_checksum_t);
|
mfile->checksums[hash_count] = xnew (metalink_checksum_t);
|
||||||
mfile->checksums[hash_count]->type = dig_type;
|
mfile->checksums[hash_count]->type = dig_type;
|
||||||
|
|
||||||
mfile->checksums[hash_count]->hash = xmalloc (hash_bin_len * 2 + 1);
|
mfile->checksums[hash_count]->hash = xmalloc ((size_t)hash_bin_len * 2 + 1);
|
||||||
wg_hex_to_string (mfile->checksums[hash_count]->hash, bin_hash, hash_bin_len);
|
wg_hex_to_string (mfile->checksums[hash_count]->hash, bin_hash, (size_t)hash_bin_len);
|
||||||
|
|
||||||
xfree (dig_hash);
|
xfree (dig_hash);
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
if METALINK_IS_ENABLED
|
if METALINK_IS_ENABLED
|
||||||
METALINK_TESTS = Test-metalink-http.py \
|
METALINK_TESTS = Test-metalink-http.py \
|
||||||
Test-metalink-http-quoted.py \
|
Test-metalink-http-quoted.py \
|
||||||
|
Test-metalink-http-baddigest.py \
|
||||||
Test-metalink-http-xml.py \
|
Test-metalink-http-xml.py \
|
||||||
Test-metalink-http-xml-trust.py \
|
Test-metalink-http-xml-trust.py \
|
||||||
Test-metalink-xml.py \
|
Test-metalink-xml.py \
|
||||||
|
93
testenv/Test-metalink-http-baddigest.py
Executable file
93
testenv/Test-metalink-http-baddigest.py
Executable file
@ -0,0 +1,93 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
from sys import exit
|
||||||
|
from test.http_test import HTTPTest
|
||||||
|
from misc.wget_file import WgetFile
|
||||||
|
import hashlib
|
||||||
|
from base64 import b64encode
|
||||||
|
|
||||||
|
"""
|
||||||
|
This is to test Metalink/HTTP with a malformed base64 Digest header.
|
||||||
|
|
||||||
|
With --trust-server-names, trust the metalink:file names.
|
||||||
|
|
||||||
|
Without --trust-server-names, don't trust the metalink:file names:
|
||||||
|
use the basename of --input-metalink, and add a sequential number
|
||||||
|
(e.g. .#1, .#2, etc.).
|
||||||
|
|
||||||
|
Strip the directory from unsafe paths.
|
||||||
|
"""
|
||||||
|
|
||||||
|
############# File Definitions ###############################################
|
||||||
|
bad = "Ouch!"
|
||||||
|
bad_sha256 = b64encode (hashlib.sha256 (bad.encode ('UTF-8')).digest ()).decode ('ascii')
|
||||||
|
|
||||||
|
LinkHeaders = ["<http://{{SRV_HOST}}:{{SRV_PORT}}/wrong_file>; rel=duplicate; pri=1"]
|
||||||
|
DigestHeader = "SHA-256=bad_base64,SHA-256={{BAD_HASH}}"
|
||||||
|
|
||||||
|
# This will be filled as soon as we know server hostname and port
|
||||||
|
MetaHTTPRules = {'SendHeader' : {}}
|
||||||
|
|
||||||
|
MetaHTTP = WgetFile ("main.metalink", rules=MetaHTTPRules)
|
||||||
|
|
||||||
|
wrong_file = WgetFile ("wrong_file", bad)
|
||||||
|
wrong_file_down = WgetFile ("main.metalink", bad)
|
||||||
|
|
||||||
|
WGET_OPTIONS = "--metalink-over-http"
|
||||||
|
WGET_URLS = [["main.metalink"]]
|
||||||
|
|
||||||
|
RequestList = [[
|
||||||
|
"HEAD /main.metalink",
|
||||||
|
"GET /wrong_file"
|
||||||
|
]]
|
||||||
|
|
||||||
|
Files = [[
|
||||||
|
MetaHTTP,
|
||||||
|
wrong_file
|
||||||
|
]]
|
||||||
|
Existing_Files = []
|
||||||
|
|
||||||
|
ExpectedReturnCode = 0
|
||||||
|
ExpectedDownloadedFiles = [wrong_file_down]
|
||||||
|
|
||||||
|
################ Pre and Post Test Hooks #####################################
|
||||||
|
pre_test = {
|
||||||
|
"ServerFiles" : Files,
|
||||||
|
"LocalFiles" : Existing_Files
|
||||||
|
}
|
||||||
|
test_options = {
|
||||||
|
"WgetCommands" : WGET_OPTIONS,
|
||||||
|
"Urls" : WGET_URLS
|
||||||
|
}
|
||||||
|
post_test = {
|
||||||
|
"ExpectedFiles" : ExpectedDownloadedFiles,
|
||||||
|
"ExpectedRetcode" : ExpectedReturnCode,
|
||||||
|
"FilesCrawled" : RequestList
|
||||||
|
}
|
||||||
|
|
||||||
|
http_test = HTTPTest (
|
||||||
|
pre_hook=pre_test,
|
||||||
|
test_params=test_options,
|
||||||
|
post_hook=post_test
|
||||||
|
)
|
||||||
|
|
||||||
|
http_test.server_setup()
|
||||||
|
### Get and use dynamic server sockname
|
||||||
|
srv_host, srv_port = http_test.servers[0].server_inst.socket.getsockname ()
|
||||||
|
|
||||||
|
DigestHeader = DigestHeader.replace('{{BAD_HASH}}', bad_sha256)
|
||||||
|
|
||||||
|
# Helper function for hostname, port and digest substitution
|
||||||
|
def SubstituteServerInfo (text, host, port):
|
||||||
|
text = text.replace('{{SRV_HOST}}', host)
|
||||||
|
text = text.replace('{{SRV_PORT}}', str (port))
|
||||||
|
return text
|
||||||
|
|
||||||
|
MetaHTTPRules["SendHeader"] = {
|
||||||
|
'Link': [ SubstituteServerInfo (LinkHeader, srv_host, srv_port)
|
||||||
|
for LinkHeader in LinkHeaders ],
|
||||||
|
'Digest': DigestHeader
|
||||||
|
}
|
||||||
|
|
||||||
|
err = http_test.begin ()
|
||||||
|
|
||||||
|
exit (err)
|
Loading…
Reference in New Issue
Block a user