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];
}
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 ((size_t)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) {
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);
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);
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 ((size_t)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 |
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);
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);
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
+++ /dev/null
-/*
- * Markus Moeller has modified the following code from Squid
- */
-
-#include "config.h"
-#include "base64.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-
-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;
-}
+++ /dev/null
-/*
- * 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);
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))) {
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;
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);
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)
*/
#include "config.h"
-#include "nw_base64.h"
+#include "base64.h"
#if HAVE_STRING_H
#include <string.h>
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);
return 1;
}
- nw_base64_decode(token, buf + 3, length);
+ length = base64_decode(token, length, buf+3);
if ((static_cast<size_t>(length) >= sizeof(ntlmProtocol) + 1) &&
(!memcmp(token, ntlmProtocol, sizeof ntlmProtocol))) {
+++ /dev/null
-/*
- * Markus Moeller has modified the following code from Squid
- */
-#include "config.h"
-#include "nw_base64.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-
-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;
-}
+++ /dev/null
-#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
{
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;
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 ((size_t)decodedLen < sizeof(ntlmhdr)) { /* decoding failure, return error */
SEND("NA Packet format error, couldn't base64-decode");
return 1;
}
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 {
have_challenge = 1;
} else
helperfail("can't obtain challenge");
+
return 1;
/* notreached */
case NTLM_CHALLENGE:
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 ((size_t)decodedLen < sizeof(ntlmhdr)) { /* decoding failure, return error */
SEND("NA Packet format error, couldn't base64-decode");
return 1;
}
/* 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
{
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;
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;
+ } else {
+ packet = NULL;
+ decodeLen = 0;
+ }
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);
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) {
{
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,
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 ((size_t)decodedLen < sizeof(ntlmhdr)) { /* decoding failure, return error */
SEND("NA Packet format error, couldn't base64-decode");
return;
}
/* 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) {
* 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;
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:
return;
default:
send_bh_or_ld("DOS Error",
- (ntlm_authenticate *) decoded, plen);
+ (ntlm_authenticate *) decoded, decodedLen);
return;
}
case SMBC_ERRSRV: /* server errors */
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.");
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
/*
* $Id$
+ *
+ * AUTHOR: Markus Moeller
+ *
+ * Encoders adopted from http://ftp.sunet.se/pub2/gnu/vm/base64-encode.c with adjustments.
*/
#include "config.h"
base64_initialized = 1;
}
-char *
-base64_decode(const char *p)
+int
+base64_decode_len(const char *data)
{
- static char result[BASE64_RESULT_SZ];
- int j;
+ 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;
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;
+ return j;
+}
+
+int
+base64_encode_len(int len)
+{
+ // NP: some magic numbers + potential nil-terminator
+ return ((len + 2) / 3 * 4) + 1;
}
-/* adopted from http://ftp.sunet.se/pub2/gnu/vm/base64-encode.c with adjustments */
const char *
-base64_encode(const char *decoded_str)
+old_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;
+ base64_encode_str(result, sizeof(result), decoded_str, strlen(decoded_str));
+ return result;
+}
- if (!base64_initialized)
- base64_init();
+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;
+}
- 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++] = '=';
- }
+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';
}
- result[out_cnt] = '\0'; /* terminate */
- return result;
+ return used;
}
/* adopted from http://ftp.sunet.se/pub2/gnu/vm/base64-encode.c with adjustments */
-const char *
-base64_encode_bin(const char *data, int len)
+int
+base64_encode(char *result, int result_size, const char *data, int data_size)
{
- static char result[BASE64_RESULT_SZ];
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 {
}
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);
}
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
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);
}
}
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;
}
SQUIDSTRINGPRINT(orig_request->extacl_user),
SQUIDSTRINGPRINT(orig_request->extacl_passwd));
httpHeaderPutStrf(hdr_out, header, "Basic %s",
- base64_encode(loginbuf));
+ old_base64_encode(loginbuf));
return;
}
#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;
}
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));
}
}
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
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");
{
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);
+
+ int encodedLen = base64_encode_len(bufLen);
+ if (encodedLen <= 0)
+ return "";
- str64 = base64_encode(buf);
+ char *str64 = static_cast<char*>(xmalloc(encodedLen));
+ base64_encode_str(str64, encodedLen, buf, bufLen);
stringLength += snprintf(buf, sizeof(buf), "Authorization: Basic %s\r\n", str64);
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) {
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