=== 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-20 13:46:46 +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); - + base64_decode((char *) input_token.value, buf + 3, input_token.length); 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, (const char *) spnegoToken, + base64_encode_len(spnegoTokenLength), 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-20 13:45:51 +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, (const char *) output_token.value, + base64_encode_len(output_token.length), 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-20 06:11:07 +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); + base64_decode(token, buf + 3, length); 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/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-29 13:02:08 +0000 @@ -149,6 +149,7 @@ main(int argc, char *argv[]) { char buf[HELPER_INPUT_BUFFER]; + char decodedBuf[HELPER_INPUT_BUFFER]; int buflen = 0; char user[NTLM_MAX_FIELD_LENGTH], domain[NTLM_MAX_FIELD_LENGTH]; char *p; @@ -173,13 +174,16 @@ 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, buf+3, sizeof(decodedBuf)); + decodedBuf[decodedLen] = '\0'; + 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); === 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-29 13:06:29 +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 decodeLen = base64_decode(decoded, buf+3, sizeof(decoded), ch-buf+3); - if (!decoded) { /* decoding failure, return error */ + if (!*decoded) { /* 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-29 14:15:21 +0000 @@ -5,9 +5,47 @@ extern "C" { #endif - extern char *base64_decode(const char *coded); + // 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, const char *p, unsigned int result_max_size); + + + // 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, const char *data, int result_max_size, 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, const char *data, int result_max_size, 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 *base64_encode(const char *decoded); - extern const char *base64_encode_bin(const char *data, int len); + #ifdef __cplusplus } === modified file 'lib/base64.c' --- lib/base64.c 2010-11-01 05:44:28 +0000 +++ lib/base64.c 2011-04-29 14:06:07 +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,35 @@ 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); + for (int i = dataLen - 1; i >= 0; i--) { + if (data[i] == '=') + terminatorLen++; + if (data[i] != '=') + break; + } + return dataLen / 4 * 3 - terminatorLen; +} + +int +base64_decode(char *result, const char *p, unsigned int result_size) +{ + 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 +78,104 @@ 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 */ + return j; +} + +int +base64_encode_len(int len) +{ + // NP: some magic numbers + potential nil-terminator + return ((len + 2) / 3 * 4) + 1; +} + const char * -base64_encode(const char *decoded_str) +base64_encode(const char *data) { 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 */ + base64_encode_str(result, decoded_str, sizeof(result), strlen(decoded_str)); 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]; + base64_encode_str(result, decoded_str, sizeof(result), len); + return result; +} + +int +base64_encode_str(char *result, const char *data, int result_size, int data_size) +{ + int used = base64_encode(result, data, result_size, data_size); + /* terminate */ + if (used >= result_size) { + result[result_size - 1] = '\0'; + return result_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, const char *data, int result_size, int data_size) +{ int bits = 0; int char_count = 0; int out_cnt = 0; - if (!data) - return data; + if (!data || !*data || !result || result_size < 1 || data_size < 1) + return 0; if (!base64_initialized) base64_init(); - while (len-- && out_cnt < sizeof(result) - 5) { + 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 +184,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-29 13:13:00 +0000 @@ -1414,7 +1414,10 @@ if (!*field) /* no authorization cookie */ return NULL; - return base64_decode(field); + static char decodedAuthToken[8192]; + int decodedLen = base64_decode(decodedAuthToken, fields, sizeof(decodedAuthToken)); + decodedAuthToken[decodedLen] = '\0'; + return decodedAuthToken; } ETag === modified file 'tools/cachemgr.cc' --- tools/cachemgr.cc 2011-04-12 11:33:32 +0000 +++ tools/cachemgr.cc 2011-04-29 13:37:29 +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); - + 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)); + int encodedLen = base64_encode_len(bufLen); + req->pub_auth = (char *) xmalloc(encodedLen); + base64_encode_str(req->pub_auth, buf, encodedLen, 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, req->pub_auth, decodedLen); debug("cmgr: length ok\n"); @@ -1136,16 +1139,18 @@ { 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); + int bufLen = snprintf(buf, sizeof(buf), "%s:%s", + req->user_name ? req->user_name : "", + req->passwd); - str64 = base64_encode(buf); + int encodedLen = base64_encode_len(bufLen); + char *str64 = static_cast(xmalloc(encodedLen)); + if (base64_encode_str(str64, buf, encodedLen, bufLen) == 0) + return ""; stringLength += snprintf(buf, sizeof(buf), "Authorization: Basic %s\r\n", str64);