=== modified file 'helpers/negotiate_auth/SSPI/negotiate_sspi_auth.cc' --- helpers/negotiate_auth/SSPI/negotiate_sspi_auth.cc 2010-07-05 09:59:15 +0000 +++ helpers/negotiate_auth/SSPI/negotiate_sspi_auth.cc 2011-04-30 11:38:02 +0000 @@ -121,9 +121,11 @@ manage_request() { char buf[HELPER_INPUT_BUFFER]; + char decoded[HELPER_INPUT_BUFFER]; + int decodedLen; char helper_command[3]; - char *c, *decoded; - int plen, status; + char *c; + int status; int oversized = 0; char *ErrorMessage; static char cred[SSP_MAX_CRED_LEN + 1]; @@ -148,26 +150,22 @@ } if ((strlen(buf) > 3) && Negotiate_packet_debug_enabled) { - decoded = base64_decode(buf + 3); + decodedLen = base64_decode(decoded, sizeof(decoded), buf+3); strncpy(helper_command, buf, 2); debug("Got '%s' from Squid with data:\n", helper_command); - hex_dump(decoded, ((strlen(buf) - 3) * 3) / 4); + hex_dump(decoded, decodedLen); } else debug("Got '%s' from Squid\n", buf); if (memcmp(buf, "YR ", 3) == 0) { /* refresh-request */ /* figure out what we got */ decoded = base64_decode(buf + 3); - /* Note: we don't need to manage memory at this point, since - * base64_decode returns a pointer to static storage. - */ - if (!decoded) { /* decoding failure, return error */ + if (decodedLen < sizeof(ntlmhdr)) { /* decoding failure, return error */ SEND("NA * Packet format error, couldn't base64-decode"); return 1; } /* Obtain server blob against SSPI */ - plen = (strlen(buf) - 3) * 3 / 4; /* we only need it here. Optimization */ - c = (char *) SSP_MakeNegotiateBlob(decoded, plen, &Done, &status, cred); + c = (char *) SSP_MakeNegotiateBlob(decoded, decodedLen, &Done, &status, cred); if (status == SSP_OK) { if (Done) { @@ -175,10 +173,10 @@ have_serverblob = 0; Done = FALSE; if (Negotiate_packet_debug_enabled) { - decoded = base64_decode(c); + decodedLen = base64_decode(decoded, sizeof(decoded), c); debug("sending 'AF' %s to squid with data:\n", cred); if (c != NULL) - hex_dump(decoded, (strlen(c) * 3) / 4); + hex_dump(decoded, decodedLen); else fprintf(stderr, "No data available.\n"); printf("AF %s %s\n", c, cred); @@ -186,9 +184,9 @@ SEND3("AF %s %s", c, cred); } else { if (Negotiate_packet_debug_enabled) { - decoded = base64_decode(c); + decodedLen = base64_decode(decoded, sizeof(decoded), c); debug("sending 'TT' to squid with data:\n"); - hex_dump(decoded, (strlen(c) * 3) / 4); + hex_dump(decoded, decodedLen); printf("TT %s\n", c); } else { SEND2("TT %s", c); @@ -205,17 +203,13 @@ return 1; } /* figure out what we got */ - decoded = base64_decode(buf + 3); - /* Note: we don't need to manage memory at this point, since - * base64_decode returns a pointer to static storage. - */ - if (!decoded) { /* decoding failure, return error */ + decodedLen = base64_decode(decoded, sizeof(decoded), buf+3); + if (decodedLen < sizeof(ntlmhdr)) { /* decoding failure, return error */ SEND("NA * Packet format error, couldn't base64-decode"); return 1; } /* check against SSPI */ - plen = (strlen(buf) - 3) * 3 / 4; /* we only need it here. Optimization */ - c = (char *) SSP_ValidateNegotiateCredentials(decoded, plen, &Done, &status, cred); + c = (char *) SSP_ValidateNegotiateCredentials(decoded, decodedLen, &Done, &status, cred); if (status == SSP_ERROR) { FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | @@ -239,10 +233,10 @@ have_serverblob = 0; Done = FALSE; if (Negotiate_packet_debug_enabled) { - decoded = base64_decode(c); + decodedLen = base64_decode(decoded, sizeof(decoded), c); debug("sending 'AF' %s to squid with data:\n", cred); if (c != NULL) - hex_dump(decoded, (strlen(c) * 3) / 4); + hex_dump(decoded, decodedLen); else fprintf(stderr, "No data available.\n"); printf("AF %s %s\n", c, cred); @@ -252,9 +246,9 @@ return 1; } else { if (Negotiate_packet_debug_enabled) { - decoded = base64_decode(c); + decodedLen = base64_decode(decoded, sizeof(decoded), c); debug("sending 'TT' to squid with data:\n"); - hex_dump(decoded, (strlen(c) * 3) / 4); + hex_dump(decoded, decodedLen); printf("TT %s\n", c); } else SEND2("TT %s", c); === modified file 'helpers/negotiate_auth/kerberos/Makefile.am' --- helpers/negotiate_auth/kerberos/Makefile.am 2010-08-13 12:05:25 +0000 +++ helpers/negotiate_auth/kerberos/Makefile.am 2011-04-16 15:24:58 +0000 @@ -5,17 +5,22 @@ libexec_PROGRAMS = negotiate_kerberos_auth negotiate_kerberos_auth_test -SOURCE = negotiate_kerberos_auth.cc base64.cc base64.h -SOURCE_test = negotiate_kerberos_auth_test.cc base64.cc base64.h - -negotiate_kerberos_auth_SOURCES = $(SOURCE) AM_CPPFLAGS = $(INCLUDES) -I$(srcdir) -negotiate_kerberos_auth_test_SOURCES = $(SOURCE_test) - - + +negotiate_kerberos_auth_SOURCES = negotiate_kerberos_auth.cc negotiate_kerberos_auth_LDFLAGS = -negotiate_kerberos_auth_LDADD = $(COMPAT_LIB) $(XTRA_LIBS) $(KRB5LIBS) +negotiate_kerberos_auth_LDADD = \ + $(top_builddir)/lib/libmiscencoding.la \ + $(COMPAT_LIB) \ + $(KRB5LIBS) \ + $(XTRA_LIBS) + +negotiate_kerberos_auth_test_SOURCES = negotiate_kerberos_auth_test.cc negotiate_kerberos_auth_test_LDFLAGS = -negotiate_kerberos_auth_test_LDADD = $(COMPAT_LIB) $(XTRA_LIBS) $(KRB5LIBS) +negotiate_kerberos_auth_test_LDADD = \ + $(top_builddir)/lib/libmiscencoding.la \ + $(COMPAT_LIB) \ + $(KRB5LIBS) \ + $(XTRA_LIBS) man_MANS = negotiate_kerberos_auth.8 === removed file 'helpers/negotiate_auth/kerberos/base64.cc' --- helpers/negotiate_auth/kerberos/base64.cc 2010-11-20 11:31:38 +0000 +++ helpers/negotiate_auth/kerberos/base64.cc 1970-01-01 00:00:00 +0000 @@ -1,161 +0,0 @@ -/* - * Markus Moeller has modified the following code from Squid - */ - -#include "config.h" -#include "base64.h" -#include -#include -#include - - -static void ska_base64_init(void); - -static int base64_initialized = 0; -#define BASE64_VALUE_SZ 256 -int base64_value[BASE64_VALUE_SZ]; -const char base64_code[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - -static void -ska_base64_init(void) -{ - int i; - - for (i = 0; i < BASE64_VALUE_SZ; i++) - base64_value[i] = -1; - - for (i = 0; i < 64; i++) - base64_value[(int) base64_code[i]] = i; - base64_value[(int) '='] = 0; - - base64_initialized = 1; -} - -void -ska_base64_decode(char *result, const char *data, int result_size) -{ - int j; - int c; - long val; - if (!data) - return; - if (!base64_initialized) - ska_base64_init(); - val = c = 0; - - for (j = 0; *data; data++) { - unsigned int k = ((unsigned char) *data) % BASE64_VALUE_SZ; - if (base64_value[k] < 0) - continue; - val <<= 6; - val += base64_value[k]; - if (++c < 4) - continue; - /* One quantum of four encoding characters/24 bit */ - if (j >= result_size) - break; - result[j++] = val >> 16; /* High 8 bits */ - if (j >= result_size) - break; - result[j++] = (val >> 8) & 0xff; /* Mid 8 bits */ - if (j >= result_size) - break; - result[j++] = val & 0xff; /* Low 8 bits */ - val = c = 0; - } - return; -} - -/* adopted from http://ftp.sunet.se/pub2/gnu/vm/base64-encode.c with adjustments */ -void -ska_base64_encode(char *result, const char *data, int result_size, - int data_size) -{ - int bits = 0; - int char_count = 0; - int out_cnt = 0; - - if (!data) - return; - - if (!base64_initialized) - ska_base64_init(); - - while (data_size--) { - int c = (unsigned char) *data++; - bits += c; - char_count++; - if (char_count == 3) { - if (out_cnt >= result_size) - break; - result[out_cnt++] = base64_code[bits >> 18]; - if (out_cnt >= result_size) - break; - result[out_cnt++] = base64_code[(bits >> 12) & 0x3f]; - if (out_cnt >= result_size) - break; - result[out_cnt++] = base64_code[(bits >> 6) & 0x3f]; - if (out_cnt >= result_size) - break; - result[out_cnt++] = base64_code[bits & 0x3f]; - bits = 0; - char_count = 0; - } else { - bits <<= 8; - } - } - if (char_count != 0) { - bits <<= 16 - (8 * char_count); - if (out_cnt >= result_size) - goto end; - result[out_cnt++] = base64_code[bits >> 18]; - if (out_cnt >= result_size) - goto end; - result[out_cnt++] = base64_code[(bits >> 12) & 0x3f]; - if (char_count == 1) { - if (out_cnt >= result_size) - goto end; - result[out_cnt++] = '='; - if (out_cnt >= result_size) - goto end; - result[out_cnt++] = '='; - } else { - if (out_cnt >= result_size) - goto end; - result[out_cnt++] = base64_code[(bits >> 6) & 0x3f]; - if (out_cnt >= result_size) - goto end; - result[out_cnt++] = '='; - } - } -end: - if (out_cnt >= result_size) { - result[result_size - 1] = '\0'; /* terminate */ - } else { - result[out_cnt] = '\0'; /* terminate */ - } - return; -} - -int -ska_base64_encode_len(int len) -{ - return ((len + 2) / 3 * 4) + 1; -} - -int -ska_base64_decode_len(const char *data) -{ - int i, j; - - j = 0; - for (i = strlen(data) - 1; i >= 0; i--) { - if (data[i] == '=') - j++; - if (data[i] != '=') - break; - } - return strlen(data) / 4 * 3 - j; -} === removed file 'helpers/negotiate_auth/kerberos/base64.h' --- helpers/negotiate_auth/kerberos/base64.h 2010-08-14 00:12:49 +0000 +++ helpers/negotiate_auth/kerberos/base64.h 1970-01-01 00:00:00 +0000 @@ -1,10 +0,0 @@ -/* - * Markus Moeller has modified the following code from Squid - */ - -void ska_base64_decode(char *result, const char *data, int result_size); -void ska_base64_encode(char *result, const char *data, int result_size, - int data_size); - -int ska_base64_encode_len(int len); -int ska_base64_decode_len(const char *data); === modified file 'helpers/negotiate_auth/kerberos/negotiate_kerberos_auth.cc' --- helpers/negotiate_auth/kerberos/negotiate_kerberos_auth.cc 2011-03-14 06:15:51 +0000 +++ helpers/negotiate_auth/kerberos/negotiate_kerberos_auth.cc 2011-04-30 13:50:39 +0000 @@ -374,13 +374,12 @@ fprintf(stdout, "BH Invalid negotiate request\n"); continue; } - input_token.length = ska_base64_decode_len(buf + 3); + input_token.length = base64_decode_len(buf+3); debug((char *) "%s| %s: DEBUG: Decode '%s' (decoded length: %d).\n", LogTime(), PROGRAM, buf + 3, (int) input_token.length); input_token.value = xmalloc(input_token.length); - ska_base64_decode((char *) input_token.value, buf + 3, input_token.length); - + input_token.length = base64_decode((char *) input_token.value, input_token.length, buf+3); if ((input_token.length >= sizeof ntlmProtocol + 1) && (!memcmp(input_token.value, ntlmProtocol, sizeof ntlmProtocol))) { @@ -427,14 +426,14 @@ if (output_token.length) { spnegoToken = (const unsigned char *) output_token.value; spnegoTokenLength = output_token.length; - token = (char *) xmalloc(ska_base64_encode_len(spnegoTokenLength)); + token = (char *) xmalloc(base64_encode_len(spnegoTokenLength)); if (token == NULL) { debug((char *) "%s| %s: ERROR: Not enough memory\n", LogTime(), PROGRAM); fprintf(stdout, "BH Not enough memory\n"); goto cleanup; } - ska_base64_encode(token, (const char *) spnegoToken, - ska_base64_encode_len(spnegoTokenLength), spnegoTokenLength); + base64_encode_str(token, base64_encode_len(spnegoTokenLength), + (const char *) spnegoToken, spnegoTokenLength); if (check_gss_err(major_status, minor_status, "gss_accept_sec_context()", log)) goto cleanup; === modified file 'helpers/negotiate_auth/kerberos/negotiate_kerberos_auth_test.cc' --- helpers/negotiate_auth/kerberos/negotiate_kerberos_auth_test.cc 2011-03-14 06:15:51 +0000 +++ helpers/negotiate_auth/kerberos/negotiate_kerberos_auth_test.cc 2011-04-30 13:50:07 +0000 @@ -196,9 +196,9 @@ goto cleanup; if (output_token.length) { - token = (char *) xmalloc(ska_base64_encode_len(output_token.length)); - ska_base64_encode(token, (const char *) output_token.value, - ska_base64_encode_len(output_token.length), output_token.length); + token = (char *) xmalloc(base64_encode_len(output_token.length)); + base64_encode_str(token, base64_encode_len(output_token.length), + (const char *) output_token.value, output_token.length); } cleanup: gss_delete_sec_context(&minor_status, &gss_context, NULL); === modified file 'helpers/negotiate_auth/wrapper/Makefile.am' --- helpers/negotiate_auth/wrapper/Makefile.am 2011-04-15 11:51:15 +0000 +++ helpers/negotiate_auth/wrapper/Makefile.am 2011-04-16 04:35:08 +0000 @@ -4,5 +4,8 @@ libexec_PROGRAMS = negotiate_wrapper_auth -negotiate_wrapper_auth_SOURCES = negotiate_wrapper.cc nw_base64.cc nw_base64.h -negotiate_wrapper_auth_LDADD = $(COMPAT_LIB) $(XTRA_LIBS) +negotiate_wrapper_auth_SOURCES = negotiate_wrapper.cc +negotiate_wrapper_auth_LDADD = \ + $(top_builddir)/lib/libmiscencoding.la \ + $(COMPAT_LIB) \ + $(XTRA_LIBS) === modified file 'helpers/negotiate_auth/wrapper/negotiate_wrapper.cc' --- helpers/negotiate_auth/wrapper/negotiate_wrapper.cc 2011-04-19 13:20:31 +0000 +++ helpers/negotiate_auth/wrapper/negotiate_wrapper.cc 2011-04-30 11:31:02 +0000 @@ -26,7 +26,7 @@ */ #include "config.h" -#include "nw_base64.h" +#include "base64.h" #if HAVE_STRING_H #include @@ -346,7 +346,7 @@ fprintf(stdout, "BH Invalid negotiate request\n"); continue; } - length = nw_base64_decode_len(buf + 3); + length = base64_decode_len(buf+3); if (debug) fprintf(stderr, "%s| %s: Decode '%s' (decoded length: %d).\n", LogTime(), PROGRAM, buf + 3, (int) length); @@ -356,7 +356,7 @@ return 1; } - nw_base64_decode(token, buf + 3, length); + length = base64_decode(token, length, buf+3); if ((static_cast(length) >= sizeof(ntlmProtocol) + 1) && (!memcmp(token, ntlmProtocol, sizeof ntlmProtocol))) { === removed file 'helpers/negotiate_auth/wrapper/nw_base64.cc' --- helpers/negotiate_auth/wrapper/nw_base64.cc 2011-04-16 14:43:18 +0000 +++ helpers/negotiate_auth/wrapper/nw_base64.cc 1970-01-01 00:00:00 +0000 @@ -1,83 +0,0 @@ -/* - * Markus Moeller has modified the following code from Squid - */ -#include "config.h" -#include "nw_base64.h" -#include -#include -#include - - -static void nw_base64_init(void); - -static int base64_initialized = 0; -#define BASE64_VALUE_SZ 256 -int base64_value[BASE64_VALUE_SZ]; -const char base64_code[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - -static void -nw_base64_init(void) -{ - int i; - - for (i = 0; i < BASE64_VALUE_SZ; i++) - base64_value[i] = -1; - - for (i = 0; i < 64; i++) - base64_value[(int) base64_code[i]] = i; - base64_value[(int)'='] = 0; - - base64_initialized = 1; -} - -void -nw_base64_decode(char *result, const char *data, int result_size) -{ - int j; - int c; - long val; - if (!data) - return; - if (!base64_initialized) - nw_base64_init(); - val = c = 0; - - for (j = 0; *data; data++) { - unsigned int k = ((unsigned char) *data) % BASE64_VALUE_SZ; - if (base64_value[k] < 0) - continue; - val <<= 6; - val += base64_value[k]; - if (++c < 4) - continue; - /* One quantum of four encoding characters/24 bit */ - if (j >= result_size) - break; - result[j++] = val >> 16; /* High 8 bits */ - if (j >= result_size) - break; - result[j++] = (val >> 8) & 0xff; /* Mid 8 bits */ - if (j >= result_size) - break; - result[j++] = val & 0xff; /* Low 8 bits */ - val = c = 0; - } - return; -} - -int -nw_base64_decode_len(const char *data) -{ - int i, j; - - j = 0; - for (i = strlen(data) - 1; i >= 0; i--) { - if (data[i] == '=') - j++; - if (data[i] != '=') - break; - } - return strlen(data) / 4 * 3 - j; -} === removed file 'helpers/negotiate_auth/wrapper/nw_base64.h' --- helpers/negotiate_auth/wrapper/nw_base64.h 2011-04-15 11:51:15 +0000 +++ helpers/negotiate_auth/wrapper/nw_base64.h 1970-01-01 00:00:00 +0000 @@ -1,11 +0,0 @@ -#ifndef _NW_BASE64_H -#define _NW_BASE64_H - -/* - * Markus Moeller has modified the following code from Squid - */ - -void nw_base64_decode(char *result, const char *data, int result_size); -int nw_base64_decode_len(const char *data); - -#endif === modified file 'helpers/ntlm_auth/SSPI/ntlm_sspi_auth.cc' --- helpers/ntlm_auth/SSPI/ntlm_sspi_auth.cc 2010-07-06 12:44:06 +0000 +++ helpers/ntlm_auth/SSPI/ntlm_sspi_auth.cc 2011-04-30 11:39:10 +0000 @@ -415,9 +415,10 @@ { ntlmhdr *fast_header; char buf[BUFFER_SIZE]; + char decoded[BUFFER_SIZE]; + int decodedLen; char helper_command[3]; - char *c, *decoded, *cred; - int plen; + char *c, *cred; int oversized = 0; char * ErrorMessage; static ntlm_negotiate local_nego; @@ -454,24 +455,22 @@ goto try_again; } if ((strlen(buf) > 3) && NTLM_packet_debug_enabled) { - decoded = base64_decode(buf + 3); + decodedLen = base64_decode(decoded, sizeof(decoded), buf+3); strncpy(helper_command, buf, 2); debug("Got '%s' from Squid with data:\n", helper_command); - hex_dump(decoded, ((strlen(buf) - 3) * 3) / 4); + hex_dump(decoded, decodedLen); } else debug("Got '%s' from Squid\n", buf); if (memcmp(buf, "YR", 2) == 0) { /* refresh-request */ /* figure out what we got */ if (strlen(buf) > 3) - decoded = base64_decode(buf + 3); + decodedLen = base64_decode(decoded, sizeof(decoded), buf+3); else { debug("Negotiate packet not supplied - self generated\n"); - decoded = (char *) &local_nego; + memcpy(decoded, local_lego, sizeof(local_nego)); + decodedLen = sizeof(localnego); } - /* Note: we don't need to manage memory at this point, since - * base64_decode returns a pointer to static storage. - */ - if (!decoded) { /* decoding failure, return error */ + if (decodedLen < sizeof(ntlmhdr)) { /* decoding failure, return error */ SEND("NA Packet format error, couldn't base64-decode"); return 1; } @@ -486,17 +485,13 @@ switch (fast_header->type) { case NTLM_NEGOTIATE: /* Obtain challenge against SSPI */ - if (strlen(buf) > 3) - plen = (strlen(buf) - 3) * 3 / 4; /* we only need it here. Optimization */ - else - plen = sizeof(ntlmhdr) + sizeof uint32_t); /* local_nego only has header and flags set. */ debug("attempting SSPI challenge retrieval\n"); - if ((c = (char *) SSP_MakeChallenge((ntlm_negotiate *) decoded, plen)) != NULL ) { + if ((c = (char *) SSP_MakeChallenge((ntlm_negotiate *) decoded, decodedLen)) != NULL ) { if (NTLM_packet_debug_enabled) { printf("TT %s\n",c); - decoded = base64_decode(c); + decodedLen = base64_decode(decoded, sizeof(decoded), c); debug("sending 'TT' to squid with data:\n"); - hex_dump(decoded, (strlen(c) * 3) / 4); + hex_dump(decoded, decodedLen); if (NTLM_LocalCall) debug("NTLM Local Call detected\n"); } else { @@ -505,6 +500,7 @@ have_challenge = 1; } else helperfail("can't obtain challenge"); + return 1; /* notreached */ case NTLM_CHALLENGE: @@ -527,12 +523,9 @@ return 1; } /* figure out what we got */ - decoded = base64_decode(buf + 3); - /* Note: we don't need to manage memory at this point, since - * base64_decode returns a pointer to static storage. - */ + decodedLen = base64_decode(decoded, sizeof(decoded), buf+3); - if (!decoded) { /* decoding failure, return error */ + if (decodedLen < sizeof(ntlmhdr)) { /* decoding failure, return error */ SEND("NA Packet format error, couldn't base64-decode"); return 1; } @@ -556,8 +549,7 @@ /* notreached */ case NTLM_AUTHENTICATE: /* check against SSPI */ - plen = (strlen(buf) - 3) * 3 / 4; /* we only need it here. Optimization */ - err = ntlm_check_auth((ntlm_authenticate *) decoded, user, domain, plen); + err = ntlm_check_auth((ntlm_authenticate *) decoded, user, domain, decodedLen); have_challenge = 0; if (err != NTLM_ERR_NONE) { #if FAIL_DEBUG === modified file 'helpers/ntlm_auth/fake/ntlm_fake_auth.cc' --- helpers/ntlm_auth/fake/ntlm_fake_auth.cc 2011-01-25 21:30:11 +0000 +++ helpers/ntlm_auth/fake/ntlm_fake_auth.cc 2011-04-30 11:16:56 +0000 @@ -150,6 +150,8 @@ { char buf[HELPER_INPUT_BUFFER]; int buflen = 0; + char decodedBuf[HELPER_INPUT_BUFFER]; + int decodedLen; char user[NTLM_MAX_FIELD_LENGTH], domain[NTLM_MAX_FIELD_LENGTH]; char *p; ntlmhdr *packet = NULL; @@ -173,13 +175,15 @@ if ((p = strchr(buf, '\n')) != NULL) *p = '\0'; /* strip \n */ buflen = strlen(buf); /* keep this so we only scan the buffer for \0 once per loop */ - if (buflen > 3) - packet = (ntlmhdr*)base64_decode(buf + 3); + if (buflen > 3) { + decodedLen = base64_decode(decodedBuf, sizeof(decodedBuf), buf+3); + packet = (ntlmhdr*)decodedBuf; + } if (buflen > 3 && NTLM_packet_debug_enabled) { strncpy(helper_command, buf, 2); helper_command[2] = '\0'; debug("Got '%s' from Squid with data:\n", helper_command); - hex_dump((unsigned char*)packet, ((buflen - 3) * 3) / 4); + hex_dump((unsigned char *)decodedBuf, decodedLen); } else debug("Got '%s' from Squid\n", buf); @@ -208,7 +212,7 @@ if (!packet) { SEND("BH received KK with no data! user="); } else if (ntlm_validate_packet(packet, NTLM_AUTHENTICATE) == NTLM_ERR_NONE) { - if (ntlm_unpack_auth((ntlm_authenticate *)packet, user, domain, (buflen-3)) == NTLM_ERR_NONE) { + if (ntlm_unpack_auth((ntlm_authenticate *)packet, user, domain, decodedLen) == NTLM_ERR_NONE) { lc(user); lc(domain); if (strip_domain_enabled) { === modified file 'helpers/ntlm_auth/smb_lm/ntlm_smb_lm_auth.cc' --- helpers/ntlm_auth/smb_lm/ntlm_smb_lm_auth.cc 2011-04-09 02:37:59 +0000 +++ helpers/ntlm_auth/smb_lm/ntlm_smb_lm_auth.cc 2011-04-30 11:16:35 +0000 @@ -506,9 +506,9 @@ { ntlmhdr *fast_header; char buf[NTLM_BLOB_BUFFER_SIZE]; + char decoded[NTLM_BLOB_BUFFER_SIZE]; const char *ch; - char *ch2, *decoded, *cred = NULL; - int plen; + char *ch2, *cred = NULL; if (fgets(buf, NTLM_BLOB_BUFFER_SIZE, stdin) == NULL) { fprintf(stderr, "fgets() failed! dying..... errno=%d (%s)\n", errno, @@ -525,12 +525,9 @@ if (memcmp(buf, "KK ", 3) == 0) { /* authenticate-request */ /* figure out what we got */ - decoded = base64_decode(buf + 3); - /* Note: we don't need to manage memory at this point, since - * base64_decode returns a pointer to static storage. - */ + int decodedLen = base64_decode(decoded, sizeof(decoded), buf+3); - if (!decoded) { /* decoding failure, return error */ + if (decodedLen < sizeof(ntlmhdr)) { /* decoding failure, return error */ SEND("NA Packet format error, couldn't base64-decode"); return; } @@ -553,10 +550,9 @@ /* notreached */ case NTLM_AUTHENTICATE: /* check against the DC */ - plen = strlen(buf) * 3 / 4; /* we only need it here. Optimization */ signal(SIGALRM, timeout_during_auth); alarm(30); - cred = ntlm_check_auth((ntlm_authenticate *) decoded, plen); + cred = ntlm_check_auth((ntlm_authenticate *) decoded, decodedLen); alarm(0); signal(SIGALRM, SIG_DFL); if (got_timeout != 0) { @@ -585,7 +581,7 @@ * without it.. */ if (nb_error != 0) { /* netbios-level error */ send_bh_or_ld("NetBios error!", - (ntlm_authenticate *) decoded, plen); + (ntlm_authenticate *) decoded, decodedLen); fprintf(stderr, "NetBios error code %d (%s)\n", nb_error, RFCNB_Error_Strings[abs(nb_error)]); return; @@ -596,7 +592,7 @@ SEND("NA Authentication failed"); /* * send_bh_or_ld("SMB success, but no creds. Internal error?", - * (ntlm_authenticate *) decoded, plen); + * (ntlm_authenticate *) decoded, decodedLen); */ return; case SMBC_ERRDOS: @@ -619,7 +615,7 @@ return; default: send_bh_or_ld("DOS Error", - (ntlm_authenticate *) decoded, plen); + (ntlm_authenticate *) decoded, decodedLen); return; } case SMBC_ERRSRV: /* server errors */ @@ -634,16 +630,16 @@ return; default: send_bh_or_ld("Server Error", - (ntlm_authenticate *) decoded, plen); + (ntlm_authenticate *) decoded, decodedLen); return; } case SMBC_ERRHRD: /* hardware errors don't really matter */ send_bh_or_ld("Domain Controller Hardware error", - (ntlm_authenticate *) decoded, plen); + (ntlm_authenticate *) decoded, decodedLen); return; case SMBC_ERRCMD: send_bh_or_ld("Domain Controller Command Error", - (ntlm_authenticate *) decoded, plen); + (ntlm_authenticate *) decoded, decodedLen); return; } SEND("BH unknown internal error."); === modified file 'include/base64.h' --- include/base64.h 2010-11-02 00:12:43 +0000 +++ include/base64.h 2011-04-30 13:52:07 +0000 @@ -5,10 +5,48 @@ extern "C" { #endif - extern char *base64_decode(const char *coded); - extern const char *base64_encode(const char *decoded); + // Decoding functions + + /// Calculate the decoded length of a given nul-terminated encoded string. + /// NULL pointer and empty strings are accepted, result is zero. + /// Any return value <= zero means no decoded result can be produced. + extern int base64_decode_len(const char *encodedData); + + /// Decode a base-64 encoded blob into a provided buffer. + /// Will not terminate the resulting string. + /// In-place decoding overlap is supported if result is equal or earlier that the source pointer. + /// + /// \return number of bytes filled in result. + extern int base64_decode(char *result, unsigned int result_max_size, const char *encoded); + + + // Encoding functions + + /// Calculate the buffer size required to hold the encoded form of + /// a string of length 'decodedLen' including all terminator bytes. + extern int base64_encode_len(int decodedLen); + + /// Base-64 encode a string into a given buffer. + /// Will not terminate the resulting string. + /// \return the number of bytes filled in result. + extern int base64_encode(char *result, int result_max_size, const char *data, int data_size); + + /// Base-64 encode a string into a given buffer. + /// Will terminate the resulting string. + /// \return the number of bytes filled in result. Including the terminator. + extern int base64_encode_str(char *result, int result_max_size, const char *data, int data_size); + + // Old encoder. Now a wrapper for the new. Takes a binary array of known length. + // Output is presented in a static buffer which will only remain valid until next call. + // Ensures a nul-terminated result. Will always return non-NULL. extern const char *base64_encode_bin(const char *data, int len); + // Old encoder. Now a wrapper for the new. + // Output is presented in a static buffer which will only remain valid until next call. + // Ensures a nul-terminated result. Will always return non-NULL. + extern const char *old_base64_encode(const char *decoded); + + #ifdef __cplusplus } #endif === modified file 'lib/base64.c' --- lib/base64.c 2010-11-01 05:44:28 +0000 +++ lib/base64.c 2011-04-30 13:53:15 +0000 @@ -1,5 +1,9 @@ /* * $Id$ + * + * AUTHOR: Markus Moeller + * + * Encoders adopted from http://ftp.sunet.se/pub2/gnu/vm/base64-encode.c with adjustments. */ #include "config.h" @@ -37,19 +41,37 @@ base64_initialized = 1; } -char * -base64_decode(const char *p) -{ - static char result[BASE64_RESULT_SZ]; - int j; +int +base64_decode_len(const char *data) +{ + if (!data || !*data) + return 0; + + int terminatorLen = 0; + int dataLen = strlen(data); + int i; + + for (i = dataLen - 1; i >= 0; i--) { + if (data[i] == '=') + terminatorLen++; + if (data[i] != '=') + break; + } + return dataLen / 4 * 3 - terminatorLen; +} + +int +base64_decode(char *result, unsigned int result_size, const char *p) +{ + int j = 0; int c; long val; - if (!p) - return NULL; + if (!p || !result || result_size == 0) + return j; if (!base64_initialized) base64_init(); val = c = 0; - for (j = 0; *p && j + 4 < BASE64_RESULT_SZ; p++) { + for (; *p; p++) { unsigned int k = ((unsigned char) *p) % BASE64_VALUE_SZ; if (base64_value[k] < 0) continue; @@ -58,85 +80,107 @@ if (++c < 4) continue; /* One quantum of four encoding characters/24 bit */ - result[j++] = (val >> 16) & 0xff; /* High 8 bits */ - result[j++] = (val >> 8) & 0xff; /* Mid 8 bits */ - result[j++] = val & 0xff; /* Low 8 bits */ + if (j+4 <= result_size) { + // Speed optimization: plenty of space, avoid some per-byte checks. + result[j++] = (val >> 16) & 0xff; /* High 8 bits */ + result[j++] = (val >> 8) & 0xff; /* Mid 8 bits */ + result[j++] = val & 0xff; /* Low 8 bits */ + } else { + // part-quantum goes a bit slower with per-byte checks + result[j++] = (val >> 16) & 0xff; /* High 8 bits */ + if (j == result_size) + return j; + result[j++] = (val >> 8) & 0xff; /* Mid 8 bits */ + if (j == result_size) + return j; + result[j++] = val & 0xff; /* Low 8 bits */ + } + if (j == result_size) + return j; val = c = 0; } - result[j] = 0; - return result; -} - -/* adopted from http://ftp.sunet.se/pub2/gnu/vm/base64-encode.c with adjustments */ -const char * -base64_encode(const char *decoded_str) -{ - static char result[BASE64_RESULT_SZ]; - int bits = 0; - int char_count = 0; - int out_cnt = 0; - int c; - - if (!decoded_str) - return decoded_str; - - if (!base64_initialized) - base64_init(); - - while ((c = (unsigned char) *decoded_str++) && out_cnt < sizeof(result) - 5) { - bits += c; - char_count++; - if (char_count == 3) { - result[out_cnt++] = base64_code[bits >> 18]; - result[out_cnt++] = base64_code[(bits >> 12) & 0x3f]; - result[out_cnt++] = base64_code[(bits >> 6) & 0x3f]; - result[out_cnt++] = base64_code[bits & 0x3f]; - bits = 0; - char_count = 0; - } else { - bits <<= 8; - } - } - if (char_count != 0) { - bits <<= 16 - (8 * char_count); - result[out_cnt++] = base64_code[bits >> 18]; - result[out_cnt++] = base64_code[(bits >> 12) & 0x3f]; - if (char_count == 1) { - result[out_cnt++] = '='; - result[out_cnt++] = '='; - } else { - result[out_cnt++] = base64_code[(bits >> 6) & 0x3f]; - result[out_cnt++] = '='; - } - } - result[out_cnt] = '\0'; /* terminate */ - return result; -} - -/* adopted from http://ftp.sunet.se/pub2/gnu/vm/base64-encode.c with adjustments */ -const char * -base64_encode_bin(const char *data, int len) -{ - static char result[BASE64_RESULT_SZ]; - int bits = 0; - int char_count = 0; - int out_cnt = 0; - - if (!data) - return data; - - if (!base64_initialized) - base64_init(); - - while (len-- && out_cnt < sizeof(result) - 5) { + return j; +} + +int +base64_encode_len(int len) +{ + // NP: some magic numbers + potential nil-terminator + return ((len + 2) / 3 * 4) + 1; +} + +const char * +old_base64_encode(const char *decoded_str) +{ + static char result[BASE64_RESULT_SZ]; + base64_encode_str(result, sizeof(result), decoded_str, strlen(decoded_str)); + return result; +} + +const char * +base64_encode_bin(const char *decoded_str, int len) +{ + static char result[BASE64_RESULT_SZ]; + base64_encode_str(result, sizeof(result), decoded_str, len); + return result; +} + +int +base64_encode_str(char *result, int result_max_size, const char *data, int data_size) +{ + if (result_max_size < 1) + return 0; + + int used = base64_encode(result, result_max_size, data, data_size); + /* terminate */ + if (used >= result_max_size) { + result[result_max_size - 1] = '\0'; + return result_max_size; + } else { + result[used++] = '\0'; + } + return used; +} + +/* adopted from http://ftp.sunet.se/pub2/gnu/vm/base64-encode.c with adjustments */ +int +base64_encode(char *result, int result_size, const char *data, int data_size) +{ + int bits = 0; + int char_count = 0; + int out_cnt = 0; + + if (!data || !*data || !result || result_size < 1 || data_size < 1) + return 0; + + if (!base64_initialized) + base64_init(); + + while (data_size--) { int c = (unsigned char) *data++; bits += c; char_count++; if (char_count == 3) { - result[out_cnt++] = base64_code[bits >> 18]; - result[out_cnt++] = base64_code[(bits >> 12) & 0x3f]; - result[out_cnt++] = base64_code[(bits >> 6) & 0x3f]; - result[out_cnt++] = base64_code[bits & 0x3f]; + if (out_cnt >= result_size) + break; + if (out_cnt+4 <= result_size) { + result[out_cnt++] = base64_code[bits >> 18]; + result[out_cnt++] = base64_code[(bits >> 12) & 0x3f]; + result[out_cnt++] = base64_code[(bits >> 6) & 0x3f]; + result[out_cnt++] = base64_code[bits & 0x3f]; + } else { + // part-quantum goes a bit slower with per-byte checks + result[out_cnt++] = base64_code[bits >> 18]; + if (out_cnt >= result_size) + break; + result[out_cnt++] = base64_code[(bits >> 12) & 0x3f]; + if (out_cnt >= result_size) + break; + result[out_cnt++] = base64_code[(bits >> 6) & 0x3f]; + if (out_cnt >= result_size) + break; + result[out_cnt++] = base64_code[bits & 0x3f]; + } bits = 0; char_count = 0; } else { @@ -145,16 +189,27 @@ } if (char_count != 0) { bits <<= 16 - (8 * char_count); + if (out_cnt >= result_size) + return result_size; result[out_cnt++] = base64_code[bits >> 18]; + if (out_cnt >= result_size) + return result_size; result[out_cnt++] = base64_code[(bits >> 12) & 0x3f]; if (char_count == 1) { + if (out_cnt >= result_size) + return result_size; result[out_cnt++] = '='; + if (out_cnt >= result_size) + return result_size; result[out_cnt++] = '='; } else { + if (out_cnt >= result_size) + return result_size; result[out_cnt++] = base64_code[(bits >> 6) & 0x3f]; + if (out_cnt >= result_size) + return result_size; result[out_cnt++] = '='; } } - result[out_cnt] = '\0'; /* terminate */ - return result; + return (out_cnt >= result_size?result_size:out_cnt); } === modified file 'src/HttpHeader.cc' --- src/HttpHeader.cc 2011-03-22 12:23:25 +0000 +++ src/HttpHeader.cc 2011-04-30 11:07:04 +0000 @@ -1414,7 +1414,10 @@ if (!*field) /* no authorization cookie */ return NULL; - return base64_decode(field); + static char decodedAuthToken[8192]; + const int decodedLen = base64_decode(decodedAuthToken, sizeof(decodedAuthToken)-1, field); + decodedAuthToken[decodedLen] = '\0'; + return decodedAuthToken; } ETag === modified file 'src/adaptation/icap/ModXact.cc' --- src/adaptation/icap/ModXact.cc 2011-04-07 12:42:02 +0000 +++ src/adaptation/icap/ModXact.cc 2011-04-29 15:02:09 +0000 @@ -1425,7 +1425,7 @@ if (request->auth_user_request != NULL) { char const *name = request->auth_user_request->username(); if (name) { - const char *value = TheConfig.client_username_encode ? base64_encode(name) : name; + const char *value = TheConfig.client_username_encode ? old_base64_encode(name) : name; buf.Printf("%s: %s\r\n", TheConfig.client_username_header, value); } } === modified file 'src/http.cc' --- src/http.cc 2011-04-06 16:25:36 +0000 +++ src/http.cc 2011-04-29 15:02:35 +0000 @@ -1606,7 +1606,7 @@ snprintf(loginbuf, sizeof(loginbuf), "%s%s", username, orig_request->peer_login + 1); httpHeaderPutStrf(hdr_out, header, "Basic %s", - base64_encode(loginbuf)); + old_base64_encode(loginbuf)); return; } @@ -1619,7 +1619,7 @@ SQUIDSTRINGPRINT(orig_request->extacl_user), SQUIDSTRINGPRINT(orig_request->extacl_passwd)); httpHeaderPutStrf(hdr_out, header, "Basic %s", - base64_encode(loginbuf)); + old_base64_encode(loginbuf)); return; } @@ -1640,7 +1640,7 @@ #endif /* HAVE_KRB5 && HAVE_GSSAPI */ httpHeaderPutStrf(hdr_out, header, "Basic %s", - base64_encode(orig_request->peer_login)); + old_base64_encode(orig_request->peer_login)); return; } @@ -1771,7 +1771,7 @@ if (!hdr_out->has(HDR_AUTHORIZATION)) { if (!request->flags.proxying && *request->login) { httpHeaderPutStrf(hdr_out, HDR_AUTHORIZATION, "Basic %s", - base64_encode(request->login)); + old_base64_encode(request->login)); } } === modified file 'tools/cachemgr.cc' --- tools/cachemgr.cc 2011-04-12 11:33:32 +0000 +++ tools/cachemgr.cc 2011-04-30 13:49:06 +0000 @@ -1053,16 +1053,17 @@ return; /* host | time | user | passwd */ - snprintf(buf, sizeof(buf), "%s|%d|%s|%s", - req->hostname, - (int) now, - req->user_name ? req->user_name : "", - req->passwd); - + const int bufLen = snprintf(buf, sizeof(buf), "%s|%d|%s|%s", + req->hostname, + (int) now, + req->user_name ? req->user_name : "", + req->passwd); debug("cmgr: pre-encoded for pub: %s\n", buf); - debug("cmgr: encoded: '%s'\n", base64_encode(buf)); - req->pub_auth = xstrdup(base64_encode(buf)); + const int encodedLen = base64_encode_len(bufLen); + req->pub_auth = (char *) xmalloc(encodedLen); + base64_encode_str(req->pub_auth, encodedLen, buf, bufLen); + debug("cmgr: encoded: '%s'\n", req->pub_auth); } static void @@ -1080,7 +1081,9 @@ if (!req->pub_auth || strlen(req->pub_auth) < 4 + strlen(safe_str(req->hostname))) return; - buf = xstrdup(base64_decode(req->pub_auth)); + const int decodedLen = base64_decode_len(req->pub_auth); + buf = (char*)xmalloc(decodedLen); + base64_decode(buf, decodedLen, req->pub_auth); debug("cmgr: length ok\n"); @@ -1136,16 +1139,20 @@ { static char buf[1024]; size_t stringLength = 0; - const char *str64; if (!req->passwd) return ""; - snprintf(buf, sizeof(buf), "%s:%s", - req->user_name ? req->user_name : "", - req->passwd); - - str64 = base64_encode(buf); + int bufLen = snprintf(buf, sizeof(buf), "%s:%s", + req->user_name ? req->user_name : "", + req->passwd); + + int encodedLen = base64_encode_len(bufLen); + if (encodedLen <= 0) + return ""; + + char *str64 = static_cast(xmalloc(encodedLen)); + base64_encode_str(str64, encodedLen, buf, bufLen); stringLength += snprintf(buf, sizeof(buf), "Authorization: Basic %s\r\n", str64); === modified file 'tools/squidclient.cc' --- tools/squidclient.cc 2011-02-17 14:57:33 +0000 +++ tools/squidclient.cc 2011-04-30 08:42:27 +0000 @@ -489,7 +489,7 @@ exit(1); } snprintf(buf, BUFSIZ, "%s:%s", user, password); - snprintf(buf, BUFSIZ, "Proxy-Authorization: Basic %s\r\n", base64_encode(buf)); + snprintf(buf, BUFSIZ, "Proxy-Authorization: Basic %s\r\n", old_base64_encode(buf)); strcat(msg, buf); } if (www_user) { @@ -504,7 +504,7 @@ exit(1); } snprintf(buf, BUFSIZ, "%s:%s", user, password); - snprintf(buf, BUFSIZ, "Authorization: Basic %s\r\n", base64_encode(buf)); + snprintf(buf, BUFSIZ, "Authorization: Basic %s\r\n", old_base64_encode(buf)); strcat(msg, buf); } #if HAVE_GSSAPI