summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHauke Mehrtens2026-05-31 15:23:54 +0000
committerHauke Mehrtens2026-06-07 11:24:17 +0000
commit391dacd10d31dfec2fd32af5c74841cf07f89c28 (patch)
treec9500b3f31ef5e4db9b0516a1ae6cdba5155b856
parentec47f4176b1ea3c8916ed668a8935cb8636f9317 (diff)
downloaduclient-391dacd10d31dfec2fd32af5c74841cf07f89c28.tar.gz
uclient-http: fail digest auth when the cnonce cannot be randomized
get_cnonce() returned early when fread() from /dev/urandom failed, leaving the caller's cnonce_str[9] buffer uninitialized. That garbage stack memory was then hashed into the digest response, embedded into the Authorization header sent to the server (a stack information leak), and passed to strlen()/strchr() in add_field(), which could read out of bounds if the 9 bytes contained no NUL. Rather than fall back to a fixed value such as a zeroed cnonce, which would weaken digest authentication by making the client nonce predictable, give get_cnonce() a return value and fail when no random data can be obtained. On a failed open or read it returns -EIO and writes nothing; the caller propagates the error and aborts the request before the cnonce buffer is used, so it is neither leaked nor read while uninitialized. Assisted-by: Claude:claude-opus-4-8 Link: https://github.com/openwrt/uclient/pull/16 Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
-rw-r--r--uclient-http.c20
1 files changed, 13 insertions, 7 deletions
diff --git a/uclient-http.c b/uclient-http.c
index 7b25e89..aa048c5 100644
--- a/uclient-http.c
+++ b/uclient-http.c
@@ -431,22 +431,26 @@ static bool strmatch(char **str, const char *prefix)
return true;
}
-static void
+static int
get_cnonce(char *dest)
{
uint32_t val = 0;
FILE *f;
- size_t n;
f = fopen("/dev/urandom", "r");
- if (f) {
- n = fread(&val, sizeof(val), 1, f);
+ if (!f)
+ return -EIO;
+
+ if (fread(&val, sizeof(val), 1, f) != 1) {
fclose(f);
- if (n != 1)
- return;
+ return -EIO;
}
+ fclose(f);
+
bin_to_hex(dest, &val, sizeof(val));
+
+ return 0;
}
static void add_field(char **buf, int *ofs, int *len, const char *name, const char *val)
@@ -564,7 +568,9 @@ uclient_http_add_auth_digest(struct uclient_http *uh)
}
sprintf(nc_str, "%08x", uh->nc++);
- get_cnonce(cnonce_str);
+ err = get_cnonce(cnonce_str);
+ if (err)
+ goto fail;
data.qop = "auth";
data.uri = url->location;