Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -2573,6 +2573,7 @@ AC_CONFIG_FILES([
src/parser/Makefile
src/proxyp/Makefile
src/repl/Makefile
src/base64/Makefile
src/sbuf/Makefile
src/security/Makefile
src/security/cert_generators/Makefile
Expand Down
6 changes: 0 additions & 6 deletions include/base64.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,6 @@ base64_encode_init(struct base64_encode_ctx *ctx);
void
base64url_encode_init(struct base64_encode_ctx *ctx);

/* Encodes a single byte. Returns amount of output (always 1 or 2). */
size_t
base64_encode_single(struct base64_encode_ctx *ctx,
char *dst,
uint8_t src);

/* Returns the number of output characters. DST should point to an
* area of size at least BASE64_ENCODE_LENGTH(length). */
size_t
Expand Down
2 changes: 1 addition & 1 deletion lib/base64.cc
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ base64_encode_init(struct base64_encode_ctx *ctx)
}

/* Encodes a single byte. */
size_t
static size_t
base64_encode_single(struct base64_encode_ctx *ctx,
char *dst,
uint8_t src)
Expand Down
19 changes: 19 additions & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ SUBDIRS = \
time \
debug \
base \
base64 \
anyp \
helper \
dns \
Expand Down Expand Up @@ -510,6 +511,7 @@ squid_LDADD = \
http/libhttp.la \
dns/libdns.la \
base/libbase.la \
base64/libbase64.la \
libsquid.la \
fs/libfs.la \
DiskIO/libdiskio.la \
Expand Down Expand Up @@ -982,6 +984,22 @@ tests_testSBufList_LDADD = \
$(XTRA_LIBS)
tests_testSBufList_LDFLAGS = $(LIBADD_DL)

check_PROGRAMS += tests/testBase64Encoder
tests_testBase64Encoder_SOURCES = \
tests/testBase64Encoder.cc
nodist_tests_testBase64Encoder_SOURCES = \
tests/stub_debug.cc \
tests/stub_libmem.cc
tests_testBase64Encoder_LDADD = \
sbuf/libsbuf.la \
base/libbase.la \
base64/libbase64.la \
$(LIBCPPUNIT_LIBS) \
$(COMPAT_LIB) \
$(XTRA_LIBS) \
$(LIBNETTLE_LIBS)
tests_testBase64Encoder_LDFLAGS = $(LIBADD_DL)

check_PROGRAMS += tests/testString
tests_testString_SOURCES = \
tests/testString.cc
Expand Down Expand Up @@ -2261,6 +2279,7 @@ tests_testCacheManager_LDADD = \
eui/libeui.la \
icmp/libicmp.la \
log/liblog.la \
base64/libbase64.la \
format/libformat.la \
$(REPL_OBJS) \
$(ADAPTATION_LIBS) \
Expand Down
26 changes: 26 additions & 0 deletions src/base64/Base64Encoder.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright (C) 1996-2026 The Squid Software Foundation and contributors
*
* Squid software is distributed under GPLv2+ license and includes
* contributions from numerous individuals and organizations.
* Please see the COPYING and CONTRIBUTORS files for details.
*/

#include "squid.h"
#include "base64.h"
#include "base64/Base64Encoder.h"

SBuf Base64Encode(const char *input, size_t length)
{
SBuf result;
const auto encodedLength = BASE64_ENCODE_RAW_LENGTH(length);
char *buf = result.rawAppendStart(encodedLength);
base64_encode_raw(buf, length, reinterpret_cast<const uint8_t *>(input));
result.rawAppendFinish(buf, encodedLength);
return result;
}

SBuf Base64Encode(const SBuf &input)
{
return Base64Encode(input.rawContent(), input.length());
}
17 changes: 17 additions & 0 deletions src/base64/Base64Encoder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* Copyright (C) 1996-2026 The Squid Software Foundation and contributors
*
* Squid software is distributed under GPLv2+ license and includes
* contributions from numerous individuals and organizations.
* Please see the COPYING and CONTRIBUTORS files for details.
*/

#ifndef SQUID_SRC_BASE64_BASE64ENCODER_H
#define SQUID_SRC_BASE64_BASE64ENCODER_H

#include "sbuf/SBuf.h"

SBuf Base64Encode(const char *input, size_t length);
SBuf Base64Encode(const SBuf &input);

#endif /* SQUID_SRC_BASE64_BASE64ENCODER_H */
20 changes: 20 additions & 0 deletions src/base64/Makefile.am
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
## Copyright (C) 1996-2026 The Squid Software Foundation and contributors
##
## Squid software is distributed under GPLv2+ license and includes
## contributions from numerous individuals and organizations.
## Please see the COPYING and CONTRIBUTORS files for details.
##

include $(top_srcdir)/src/Common.am

noinst_LTLIBRARIES = libbase64.la

libbase64_la_SOURCES = \
Base64Encoder.cc \
Base64Encoder.h

libbase64_la_LIBADD = \
$(top_builddir)/lib/libmiscencoding.la \
$(COMPAT_LIB) \
$(LIBNETTLE_LIBS) \
$(XTRA_LIBS)
14 changes: 3 additions & 11 deletions src/format/Format.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

#include "squid.h"
#include "AccessLogEntry.h"
#include "base64.h"
#include "base64/Base64Encoder.h"
#include "client_side.h"
#include "comm/Connection.h"
#include "error/Detail.h"
Expand Down Expand Up @@ -556,16 +556,8 @@ Format::Format::assemble(MemBuf &mb, const AccessLogEntry::Pointer &al, int logS
case LFT_CLIENT_HANDSHAKE:
if (al->request && al->request->clientConnectionManager.valid()) {
const auto &handshake = al->request->clientConnectionManager->preservedClientData;
if (const auto rawLength = handshake.length()) {
// add 1 byte to optimize the c_str() conversion below
char *buf = sb.rawAppendStart(base64_encode_len(rawLength) + 1);

struct base64_encode_ctx ctx;
base64_encode_init(&ctx);
auto encLength = base64_encode_update(&ctx, buf, rawLength, reinterpret_cast<const uint8_t*>(handshake.rawContent()));
encLength += base64_encode_final(&ctx, buf + encLength);

sb.rawAppendFinish(buf, encLength);
if (!handshake.isEmpty()) {
sb = Base64Encode(handshake);
out = sb.c_str();
}
}
Expand Down
46 changes: 19 additions & 27 deletions src/http.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
#include "base/DelayedAsyncCalls.h"
#include "base/Raw.h"
#include "base/TextException.h"
#include "base64.h"
#include "base64/Base64Encoder.h"
#include "CachePeer.h"
#include "client_side.h"
#include "comm/Connection.h"
Expand Down Expand Up @@ -1834,11 +1834,6 @@ httpFixupAuthentication(HttpRequest * request, const HttpHeader * hdr_in, HttpHe
}
}

char loginbuf[base64_encode_len(MAX_LOGIN_SZ)];
size_t blen;
struct base64_encode_ctx ctx;
base64_encode_init(&ctx);

/* Special mode to pass the username to the upstream cache */
if (*request->peer_login == '*') {
const char *username = "-";
Expand All @@ -1850,10 +1845,10 @@ httpFixupAuthentication(HttpRequest * request, const HttpHeader * hdr_in, HttpHe
username = request->auth_user_request->username();
#endif

blen = base64_encode_update(&ctx, loginbuf, strlen(username), reinterpret_cast<const uint8_t*>(username));
blen += base64_encode_update(&ctx, loginbuf+blen, strlen(request->peer_login +1), reinterpret_cast<const uint8_t*>(request->peer_login +1));
blen += base64_encode_final(&ctx, loginbuf+blen);
httpHeaderPutStrf(hdr_out, header, "Basic %.*s", (int)blen, loginbuf);
SBuf toEncode(username);
toEncode.append(request->peer_login + 1);
SBuf encoded = Base64Encode(toEncode);
httpHeaderPutStrf(hdr_out, header, "Basic %.*s", (int)encoded.length(), encoded.rawContent());
return;
}

Expand All @@ -1862,11 +1857,12 @@ httpFixupAuthentication(HttpRequest * request, const HttpHeader * hdr_in, HttpHe
(strcmp(request->peer_login, "PASS") == 0 ||
strcmp(request->peer_login, "PROXYPASS") == 0)) {

blen = base64_encode_update(&ctx, loginbuf, request->extacl_user.size(), reinterpret_cast<const uint8_t*>(request->extacl_user.rawBuf()));
blen += base64_encode_update(&ctx, loginbuf+blen, 1, reinterpret_cast<const uint8_t*>(":"));
blen += base64_encode_update(&ctx, loginbuf+blen, request->extacl_passwd.size(), reinterpret_cast<const uint8_t*>(request->extacl_passwd.rawBuf()));
blen += base64_encode_final(&ctx, loginbuf+blen);
httpHeaderPutStrf(hdr_out, header, "Basic %.*s", (int)blen, loginbuf);
SBuf toEncode;
toEncode.append(request->extacl_user.rawBuf(), request->extacl_user.size());
toEncode.append(':');
toEncode.append(request->extacl_passwd.rawBuf(), request->extacl_passwd.size());
SBuf encoded = Base64Encode(toEncode);
httpHeaderPutStrf(hdr_out, header, "Basic %.*s", (int)encoded.length(), encoded.rawContent());
return;
}
// if no external user credentials are available to fake authentication with PASS acts like PASSTHRU
Expand Down Expand Up @@ -1894,10 +1890,11 @@ httpFixupAuthentication(HttpRequest * request, const HttpHeader * hdr_in, HttpHe
}
#endif /* HAVE_KRB5 && HAVE_GSSAPI */

blen = base64_encode_update(&ctx, loginbuf, strlen(request->peer_login), reinterpret_cast<const uint8_t*>(request->peer_login));
blen += base64_encode_final(&ctx, loginbuf+blen);
httpHeaderPutStrf(hdr_out, header, "Basic %.*s", (int)blen, loginbuf);
return;
{
SBuf encoded = Base64Encode(SBuf(request->peer_login));
httpHeaderPutStrf(hdr_out, header, "Basic %.*s", (int)encoded.length(), encoded.rawContent());
return;
}
}

/*
Expand Down Expand Up @@ -2018,14 +2015,9 @@ HttpStateData::httpBuildRequestHeader(HttpRequest * request,
/* append Authorization if known in URL, not in header and going direct */
if (!hdr_out->has(Http::HdrType::AUTHORIZATION)) {
if (flags.toOrigin && !request->url.userInfo().isEmpty()) {
static char result[base64_encode_len(MAX_URL*2)]; // should be big enough for a single URI segment
struct base64_encode_ctx ctx;
base64_encode_init(&ctx);
size_t blen = base64_encode_update(&ctx, result, request->url.userInfo().length(), reinterpret_cast<const uint8_t*>(request->url.userInfo().rawContent()));
blen += base64_encode_final(&ctx, result+blen);
result[blen] = '\0';
if (blen)
httpHeaderPutStrf(hdr_out, Http::HdrType::AUTHORIZATION, "Basic %.*s", (int)blen, result);
auto encoded = Base64Encode(request->url.userInfo());
if (!encoded.isEmpty())
httpHeaderPutStrf(hdr_out, Http::HdrType::AUTHORIZATION, "Basic %.*s", (int)encoded.length(), encoded.rawContent());
}
}

Expand Down
65 changes: 65 additions & 0 deletions src/tests/testBase64Encoder.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright (C) 1996-2026 The Squid Software Foundation and contributors
*
* Squid software is distributed under GPLv2+ license and includes
* contributions from numerous individuals and organizations.
* Please see the COPYING and CONTRIBUTORS files for details.
*/

#include "squid.h"
#include "base64/Base64Encoder.h"
#include "compat/cppunit.h"
#include "unitTestMain.h"

class TestBase64Encode : public CPPUNIT_NS::TestFixture
{
CPPUNIT_TEST_SUITE(TestBase64Encode);
CPPUNIT_TEST(testBase64EncodeFunction);
CPPUNIT_TEST(testBase64EncodeFunctionEmpty);
CPPUNIT_TEST(testBase64EncodeFunctionLargeInput);
CPPUNIT_TEST_SUITE_END();

protected:
void testBase64EncodeFunction();
void testBase64EncodeFunctionEmpty();
void testBase64EncodeFunctionLargeInput();
};
CPPUNIT_TEST_SUITE_REGISTRATION( TestBase64Encode );

void
TestBase64Encode::testBase64EncodeFunction()
{
SBuf input("Hello");
SBuf result = Base64Encode(input);
CPPUNIT_ASSERT_EQUAL(SBuf("SGVsbG8="), result);
}

void
TestBase64Encode::testBase64EncodeFunctionEmpty()
{
SBuf input("");
SBuf result = Base64Encode(input);
CPPUNIT_ASSERT_EQUAL(SBuf(""), result);
}

void
TestBase64Encode::testBase64EncodeFunctionLargeInput()
{
std::string largeInput(5000, 'A');
SBuf input(largeInput.c_str(), largeInput.size());
SBuf result = Base64Encode(input);

CPPUNIT_ASSERT_EQUAL(static_cast<SBuf::size_type>(6668), result.length());
CPPUNIT_ASSERT_EQUAL(static_cast<char>('Q'), result[0]);
CPPUNIT_ASSERT_EQUAL(static_cast<char>('U'), result[1]);
CPPUNIT_ASSERT_EQUAL(static_cast<char>('F'), result[2]);
CPPUNIT_ASSERT_EQUAL(static_cast<char>('B'), result[3]);
CPPUNIT_ASSERT_EQUAL(static_cast<char>('='), result[result.length() - 1]);
CPPUNIT_ASSERT_EQUAL(static_cast<char>('E'), result[result.length() - 2]);
}

int
main(int argc, char *argv[])
{
return TestProgram().run(argc, argv);
}
Loading