From 27f0f7b2255804f0bc4fef9b4c851f9742690051 Mon Sep 17 00:00:00 2001 From: Amos Jeffries Date: Sun, 9 Nov 2025 23:42:28 +1300 Subject: [PATCH 1/4] Update for Nettle 4.0 base64 API --- src/HttpHeader.cc | 2 +- src/auth/basic/Config.cc | 2 +- src/auth/negotiate/SSPI/negotiate_sspi_auth.cc | 2 ++ src/auth/negotiate/kerberos/negotiate_kerberos_auth.cc | 2 +- src/auth/negotiate/wrapper/negotiate_wrapper.cc | 2 +- src/auth/ntlm/fake/ntlm_fake_auth.cc | 2 +- 6 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/HttpHeader.cc b/src/HttpHeader.cc index 31d06fcb602..ab056105320 100644 --- a/src/HttpHeader.cc +++ b/src/HttpHeader.cc @@ -1437,7 +1437,7 @@ HttpHeader::getAuthToken(Http::HdrType id, const char *auth_scheme) const char *decodedAuthToken = result.rawAppendStart(BASE64_DECODE_LENGTH(fieldLen)); struct base64_decode_ctx ctx; base64_decode_init(&ctx); - size_t decodedLen = 0; + size_t decodedLen = BASE64_DECODE_LENGTH(fieldLen); if (!base64_decode_update(&ctx, &decodedLen, reinterpret_cast(decodedAuthToken), fieldLen, field) || !base64_decode_final(&ctx)) { return nil; diff --git a/src/auth/basic/Config.cc b/src/auth/basic/Config.cc index 2b9f7c28f21..a3326c4f670 100644 --- a/src/auth/basic/Config.cc +++ b/src/auth/basic/Config.cc @@ -170,7 +170,7 @@ Auth::Basic::Config::decodeCleartext(const char *httpAuthHeader, const HttpReque struct base64_decode_ctx ctx; base64_decode_init(&ctx); - size_t dstLen = 0; + size_t dstLen = sizeof(cleartext); if (base64_decode_update(&ctx, &dstLen, reinterpret_cast(cleartext), srcLen, eek) && base64_decode_final(&ctx)) { cleartext[dstLen] = '\0'; diff --git a/src/auth/negotiate/SSPI/negotiate_sspi_auth.cc b/src/auth/negotiate/SSPI/negotiate_sspi_auth.cc index 8d5924d93b5..e286241b9b2 100644 --- a/src/auth/negotiate/SSPI/negotiate_sspi_auth.cc +++ b/src/auth/negotiate/SSPI/negotiate_sspi_auth.cc @@ -124,10 +124,12 @@ token_decode(size_t *decodedLen, uint8_t decoded[], const char *buf) { struct base64_decode_ctx ctx; base64_decode_init(&ctx); + decodedLen = sizeof(decoded); if (!base64_decode_update(&ctx, decodedLen, decoded, strlen(buf), buf) || !base64_decode_final(&ctx)) { SEND("BH base64 decode failed"); fprintf(stderr, "ERROR: base64 decoding failed for: '%s'\n", buf); + decodedLen = 0; return false; } return true; diff --git a/src/auth/negotiate/kerberos/negotiate_kerberos_auth.cc b/src/auth/negotiate/kerberos/negotiate_kerberos_auth.cc index acce0b0ee28..703bd454cde 100644 --- a/src/auth/negotiate/kerberos/negotiate_kerberos_auth.cc +++ b/src/auth/negotiate/kerberos/negotiate_kerberos_auth.cc @@ -658,7 +658,7 @@ main(int argc, char *const argv[]) struct base64_decode_ctx ctx; base64_decode_init(&ctx); - size_t dstLen = 0; + size_t dstLen = sizeof(input_token.value); if (!base64_decode_update(&ctx, &dstLen, static_cast(input_token.value), srcLen, b64Token) || !base64_decode_final(&ctx)) { debug((char *) "%s| %s: ERROR: Invalid base64 token [%s]\n", LogTime(), PROGRAM, b64Token); diff --git a/src/auth/negotiate/wrapper/negotiate_wrapper.cc b/src/auth/negotiate/wrapper/negotiate_wrapper.cc index 425434d22f0..9a46bc64614 100644 --- a/src/auth/negotiate/wrapper/negotiate_wrapper.cc +++ b/src/auth/negotiate/wrapper/negotiate_wrapper.cc @@ -189,7 +189,7 @@ processingLoop(FILE *FDKIN, FILE *FDKOUT, FILE *FDNIN, FILE *FDNOUT) struct base64_decode_ctx ctx; base64_decode_init(&ctx); - size_t dstLen = 0; + size_t dstLen = sizeof(token); if (!base64_decode_update(&ctx, &dstLen, token, strlen(buf+3), buf+3) || !base64_decode_final(&ctx)) { if (debug_enabled) diff --git a/src/auth/ntlm/fake/ntlm_fake_auth.cc b/src/auth/ntlm/fake/ntlm_fake_auth.cc index bb3df8d3bb2..25d51fe7ce2 100644 --- a/src/auth/ntlm/fake/ntlm_fake_auth.cc +++ b/src/auth/ntlm/fake/ntlm_fake_auth.cc @@ -164,7 +164,7 @@ main(int argc, char *argv[]) ntlmhdr *packet; struct base64_decode_ctx ctx; base64_decode_init(&ctx); - size_t dstLen = 0; + size_t dstLen = sizeof(decodedBuf); if (buflen > 3 && base64_decode_update(&ctx, &dstLen, decodedBuf, buflen-3, buf+3) && base64_decode_final(&ctx)) { From 460dc505c2a5432b01bf1a252a3c46751991f432 Mon Sep 17 00:00:00 2001 From: Amos Jeffries Date: Thu, 13 Nov 2025 21:02:40 +1300 Subject: [PATCH 2/4] Reviewer requested change --- src/HttpHeader.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/HttpHeader.cc b/src/HttpHeader.cc index ab056105320..b412775effb 100644 --- a/src/HttpHeader.cc +++ b/src/HttpHeader.cc @@ -1434,10 +1434,10 @@ HttpHeader::getAuthToken(Http::HdrType id, const char *auth_scheme) const const auto fieldLen = strlen(field); SBuf result; - char *decodedAuthToken = result.rawAppendStart(BASE64_DECODE_LENGTH(fieldLen)); struct base64_decode_ctx ctx; base64_decode_init(&ctx); size_t decodedLen = BASE64_DECODE_LENGTH(fieldLen); + char *decodedAuthToken = result.rawAppendStart(decodedLen); if (!base64_decode_update(&ctx, &decodedLen, reinterpret_cast(decodedAuthToken), fieldLen, field) || !base64_decode_final(&ctx)) { return nil; From 93547be4d3dfd43256542e5f0759f9b9e32f2e27 Mon Sep 17 00:00:00 2001 From: Amos Jeffries Date: Thu, 13 Nov 2025 22:25:02 +1300 Subject: [PATCH 3/4] Import latest Base64 implementation from libnettle 4.0 --- CREDITS | 2 +- include/base64.h | 21 +++++----- lib/base64.c | 106 +++++++++++++++++++---------------------------- 3 files changed, 54 insertions(+), 75 deletions(-) diff --git a/CREDITS b/CREDITS index 4ccb7162bf1..c15f71b0ac5 100644 --- a/CREDITS +++ b/CREDITS @@ -504,7 +504,7 @@ include/base64.h: lib/base64.c: /* - Copyright (C) 2002 Niels Möller, Dan Egnor + Copyright (C) 2002 Niels Möller This file is part of GNU Nettle. diff --git a/include/base64.h b/include/base64.h index 08d9f07cd1a..8a2e4b8444a 100644 --- a/include/base64.h +++ b/include/base64.h @@ -12,7 +12,7 @@ #if HAVE_NETTLE_BASE64_H #include -#else /* Base64 functions copied from Nettle 3.4 under GPLv2, with adjustments */ +#else /* Base64 functions copied from Nettle 4.0 under GPLv2, with adjustments */ /* base64.h @@ -51,6 +51,9 @@ extern "C" { #endif +#define BASE64_BINARY_BLOCK_SIZE 3 +#define BASE64_TEXT_BLOCK_SIZE 4 + /* Base64 encoding */ /* Maximum length of output for base64_encode_update. NOTE: Doesn't @@ -104,15 +107,12 @@ base64_encode_final(struct base64_encode_ctx *ctx, /* Encodes a string in one go, including any padding at the end. * Generates exactly BASE64_ENCODE_RAW_LENGTH(length) bytes of output. - * Supports overlapped operation, if src <= dst. - * TODO: Use of overlap is deprecated, if needed there should be a separate public function + * Supports overlapped operation, if src <= dst. FIXME: Use of overlap + * is deprecated, if needed there should be a separate public fucntion * to do that.*/ void base64_encode_raw(char *dst, size_t length, const uint8_t *src); -void -base64_encode_group(char *dst, uint32_t group); - /* Base64 decoding */ /* Maximum length of output for base64_decode_update. */ @@ -145,8 +145,10 @@ base64_decode_single(struct base64_decode_ctx *ctx, char src); /* Returns 1 on success, 0 on error. DST should point to an area of - * size at least BASE64_DECODE_LENGTH(length). The amount of data - * generated is returned in *DST_LENGTH. */ + * size *DST_LENGTH. Decoding returns failure it output would exceed + * this size. BASE64_DECODE_LENGTH(length) is always sufficient. + * *DST_LENGTH is updated to reflect the amount of data actually + * generated. */ int base64_decode_update(struct base64_decode_ctx *ctx, size_t *dst_length, @@ -165,8 +167,7 @@ base64_decode_final(struct base64_decode_ctx *ctx); #endif /* HAVE_NETTLE_BASE64_H */ /// Calculate the buffer size required to hold the encoded form of -/// a string of length 'decodedLen' including all terminator bytes. +/// a string of length bytes, including all terminator bytes. #define base64_encode_len(length) (BASE64_ENCODE_LENGTH(length)+BASE64_ENCODE_FINAL_LENGTH+1) #endif /* SQUID_INCLUDE_BASE64_H */ - diff --git a/lib/base64.c b/lib/base64.c index 3b411d66790..b788c6143d6 100644 --- a/lib/base64.c +++ b/lib/base64.c @@ -7,7 +7,7 @@ */ /* - * Copied from Nettle 3.4 under GPLv2, with adjustments + * Copied from Nettle 4.0 under GPLv2, with adjustments */ #include "squid.h" @@ -15,8 +15,7 @@ #if !HAVE_NETTLE_BASE64_H -/* base64-encode.c - +/* Copyright (C) 2002 Niels Möller This file is part of GNU Nettle. @@ -46,6 +45,8 @@ not, see http://www.gnu.org/licenses/. */ +/* base64-decode.c */ + #define TABLE_INVALID -1 #define TABLE_SPACE -2 #define TABLE_END -3 @@ -83,46 +84,9 @@ base64_decode_single(struct base64_decode_ctx *ctx, uint8_t *dst, char src) { - int data = ctx->table[(uint8_t) src]; - - switch(data) - { - default: - assert(data >= 0 && data < 0x40); - - if (ctx->padding) - return -1; - - ctx->word = ctx->word << 6 | data; - ctx->bits += 6; - - if (ctx->bits >= 8) - { - ctx->bits -= 8; - dst[0] = ctx->word >> ctx->bits; - return 1; - } - else return 0; - - case TABLE_INVALID: - return -1; - - case TABLE_SPACE: - return 0; - - case TABLE_END: - /* There can be at most two padding characters. */ - if (!ctx->bits || ctx->padding > 2) - return -1; - - if (ctx->word & ( (1<bits) - 1)) - /* We shouldn't have any leftover bits */ - return -1; - - ctx->padding++; - ctx->bits -= 2; - return 0; - } + size_t dst_length = 1; + return base64_decode_update (ctx, &dst_length, dst, 1, &src) + ? dst_length : -1; } int @@ -135,20 +99,44 @@ base64_decode_update(struct base64_decode_ctx *ctx, size_t done; size_t i; - for (i = 0, done = 0; itable[(uint8_t) src[i]]; + switch (data) { - case -1: - return 0; - case 1: - done++; - /* Fall through */ - case 0: - break; default: - abort(); - } + assert(data >= 0 && data < 0x40); + + if (ctx->padding || (done >= *dst_length)) + return -1; + ctx->word = ctx->word << 6 | data; + ctx->bits += 6; + + if (ctx->bits >= 8) + { + ctx->bits -= 8; + dst[done++] = ctx->word >> ctx->bits; + } + break; + case TABLE_INVALID: + return -1; + case TABLE_SPACE: + continue; + case TABLE_END: + /* There can be at most two padding characters. */ + if (!ctx->bits || ctx->padding > 2) + return -1; + + if (ctx->word & ( (1<bits) - 1)) + /* We shouldn't have any leftover bits */ + return -1; + + ctx->padding++; + ctx->bits -= 2; + break; + } + } assert(done <= BASE64_DECODE_LENGTH(src_length)); *dst_length = done; @@ -219,15 +207,6 @@ base64_encode_raw(char *dst, size_t length, const uint8_t *src) encode_raw(base64_encode_table, dst, length, src); } -void -base64_encode_group(char *dst, uint32_t group) -{ - *dst++ = ENCODE(base64_encode_table, (group >> 18)); - *dst++ = ENCODE(base64_encode_table, (group >> 12)); - *dst++ = ENCODE(base64_encode_table, (group >> 6)); - *dst++ = ENCODE(base64_encode_table, group); -} - void base64_encode_init(struct base64_encode_ctx *ctx) { @@ -325,4 +304,3 @@ base64_encode_final(struct base64_encode_ctx *ctx, } #endif /* !HAVE_NETTLE_BASE64_H */ - From 8dc854bd3113e9832ce5da72d95df76d4e419ac6 Mon Sep 17 00:00:00 2001 From: Amos Jeffries Date: Sat, 15 Nov 2025 16:57:28 +1300 Subject: [PATCH 4/4] Spelling mistake upstream --- include/base64.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/base64.h b/include/base64.h index 8a2e4b8444a..d6d40648530 100644 --- a/include/base64.h +++ b/include/base64.h @@ -108,7 +108,7 @@ base64_encode_final(struct base64_encode_ctx *ctx, /* Encodes a string in one go, including any padding at the end. * Generates exactly BASE64_ENCODE_RAW_LENGTH(length) bytes of output. * Supports overlapped operation, if src <= dst. FIXME: Use of overlap - * is deprecated, if needed there should be a separate public fucntion + * is deprecated, if needed there should be a separate public function * to do that.*/ void base64_encode_raw(char *dst, size_t length, const uint8_t *src);