Implement base64 without openssl

This commit is contained in:
matt335672 2022-01-27 16:23:51 +00:00
parent 8b8cfbe119
commit 4699dced14
8 changed files with 713 additions and 75 deletions

View File

@ -1,5 +1,5 @@
/**
* Copyright (C) 2017 Koichiro Iwao, all xrdp contributors
* Copyright (C) 2022 Matt Burt, all xrdp contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -26,57 +26,229 @@
#include "string_calls.h"
#include <openssl/bio.h>
#include <openssl/evp.h>
#include "base64.h"
size_t
base64_decoded_bytes(const char *src)
/*
* Values for invalid and padding characters, used in the charmap
* for converting base64 to binary
*
* Thse value are specially chosen to make it easy to detect padding or
* invalid characters by or-ing together the values looked up in
* a base64 quantum */
#define E_INVALID 0x40
#define E_PAD 0x80
/* Determine the character set on this platform */
#if ('a' == 0x61 && 'z' == 0x7a ) && \
('A' == 0x41 && 'Z' == 0x5a ) && \
('0' == 0x30 && '9' == 0x39 )
# define PLATFORM_IS_ASCII 1
#else
# error "Unrecognised character set on this platform"
#endif /* character set check */
/*
* Define a table to map the base64 character values to bit values.
*/
#ifdef PLATFORM_IS_ASCII
#define CHARMAP_BASE 0x28
#define E_IV E_INVALID /* For table alignment */
const unsigned char charmap[] =
{
size_t len;
size_t padding;
/* 0x28 */ E_IV, E_IV, E_IV, 0x3e, E_IV, E_IV, E_IV, 0x3f,
/* 0x30 */ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
/* 0x38 */ 0x3c, 0x3d, E_IV, E_IV, E_IV, E_PAD, E_IV, E_IV,
/* 0x40 */ E_IV, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
/* 0x48 */ 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
/* 0x50 */ 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
/* 0x58 */ 0x17, 0x18, 0x19, E_IV, E_IV, E_IV, E_IV, E_IV,
/* 0x60 */ E_IV, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
/* 0x68 */ 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
/* 0x70 */ 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
/* 0x78 */ 0x31, 0x32, 0x33
};
#undef E_IV
#endif /* PLATFORM_IS_ASCII */
len = g_strlen(src);
padding = 0;
if (src[len - 1] == '=')
/**
* Lookup a value in the charmap
*
* @param x - byte to lookup. Only referenced once so can safely have
* side effects.
* @param dest - destination to assign result to.
*/
#define CM_LOOKUP(x,dest) \
{ \
unsigned int t = (unsigned int)(x) - CHARMAP_BASE;\
dest = (t < sizeof(charmap)) ? charmap[t] : E_INVALID; \
}
/*****************************************************************************/
int
base64_decode(const char *src, char *dst, size_t dst_len, size_t *actual_len)
{
*actual_len = 0;
size_t src_len;
size_t src_i = 0;
size_t dst_i = 0;
unsigned int a; /* Four characters of base64 quantum */
unsigned int b;
unsigned int c;
unsigned int d;
unsigned int v;
#define OUTPUT_CHAR(x) \
{ \
if (dst_i < dst_len) \
{ \
dst[dst_i] = (x);\
} \
++dst_i; \
}
src_len = g_strlen(src);
while (src_i < src_len)
{
padding++;
if (src[len - 2] == '=')
if ((src_len - src_i) >= 4)
{
padding++;
/* Usual case - full quantum */
CM_LOOKUP(src[src_i++], a);
CM_LOOKUP(src[src_i++], b);
CM_LOOKUP(src[src_i++], c);
CM_LOOKUP(src[src_i++], d);
}
else
{
/* Add padding on the end to make up the full quantum */
CM_LOOKUP(src[src_i++], a);
b = E_PAD;
c = E_PAD;
d = E_PAD;
if ((src_len - src_i) > 0)
{
CM_LOOKUP(src[src_i++], b);
}
if ((src_len - src_i) > 0)
{
CM_LOOKUP(src[src_i++], c);
}
}
/*
* Bitwise-or the translated quantum values together, so that
* any invalid or padding characters can be detected with a
* single test */
v = a | b | c | d;
if ((v & E_INVALID) != 0)
{
return -1; /* At least one invalid character */
}
if ((v & E_PAD) == 0)
{
/* No padding - a full quantum */
v = (a << 18) | (b << 12) | (c << 6) | d;
OUTPUT_CHAR(v >> 16);
OUTPUT_CHAR((v >> 8) & 0xff);
OUTPUT_CHAR(v & 0xff);
}
else if (((a | b | c) & E_PAD) == 0)
{
/* No padding in the first 3 chars, so the padding must
* be at the end */
v = (a << 10) | (b << 4) | (c >> 2);
OUTPUT_CHAR(v >> 8);
OUTPUT_CHAR(v & 0xff);
}
else if (((a | b) & E_PAD) == 0 && c == d)
{
/* No padding in first two chars, so if the last two chars are
* equal, they must both be padding */
v = (a << 2) | (b >> 4);
OUTPUT_CHAR(v);
}
else
{
/* Illegal padding */
return -1;
}
}
return len * 3 / 4 - padding;
*actual_len = dst_i;
return 0;
#undef OUTPUT_CHAR
}
/*****************************************************************************/
char *
base64_decode(char *dst, const char *src, size_t len)
size_t
base64_encode(const char *src, size_t src_len, char *dst, size_t dst_len)
{
BIO *b64;
BIO *bio;
char *b64str;
size_t estimated_decoded_bytes;
size_t decoded_bytes;
char *p = dst;
size_t src_i = 0;
size_t max_src_len;
unsigned int v;
static const char *b64chr =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/=";
b64str = g_strdup(src);
estimated_decoded_bytes = base64_decoded_bytes(b64str);
dst[estimated_decoded_bytes] = '\0';
b64 = BIO_new(BIO_f_base64());
bio = BIO_new_mem_buf(b64str, len);
bio = BIO_push(b64, bio);
BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
decoded_bytes = BIO_read(bio, dst, len);
BIO_free_all(bio);
/* if input is corrupt, return empty string */
if (estimated_decoded_bytes != decoded_bytes)
/* Each three octets of the source results in four bytes at the output,
* plus we need a terminator. So we can work out the maximum number of
* source octets we can process */
if (dst_len == 0)
{
g_strncpy(dst, "", sizeof(""));
max_src_len = 0;
}
else
{
max_src_len = (dst_len - 1) / 4 * 3;
}
return dst;
if (src_len > max_src_len)
{
src_len = max_src_len;
}
while (src_i < src_len)
{
switch (src_len - src_i)
{
case 1:
v = (unsigned int)(unsigned char)src[src_i++] << 4;
*p++ = b64chr[v >> 6];
*p++ = b64chr[v & 0x3f];
*p++ = b64chr[64];
*p++ = b64chr[64];
break;
case 2:
v = (unsigned int)(unsigned char)src[src_i++] << 10;
v |= (unsigned int)(unsigned char)src[src_i++] << 2;
*p++ = b64chr[v >> 12];
*p++ = b64chr[(v >> 6) & 0x3f];
*p++ = b64chr[v & 0x3f];
*p++ = b64chr[64];
break;
default:
v = (unsigned int)(unsigned char)src[src_i++] << 16;
v |= (unsigned int)(unsigned char)src[src_i++] << 8;
v |= (unsigned int)(unsigned char)src[src_i++];
*p++ = b64chr[v >> 18];
*p++ = b64chr[(v >> 12) & 0x3f];
*p++ = b64chr[(v >> 6) & 0x3f];
*p++ = b64chr[v & 0x3f];
break;
}
}
*p = '\0';
return src_len;
}

View File

@ -1,5 +1,5 @@
/**
* Copyright (C) 2017 Koichiro Iwao, all xrdp contributors
* Copyright (C) 2021 Koichiro Iwao, all xrdp contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -17,16 +17,66 @@
/**
* @file common/base64.h
* @brief Base64 encoder / decoder
*
* Base-64 is described in RFC4648. The following notes apply to this
* implementation:-
* - The only supported characters are [A-Za-z0-9+/=]. At present,
* embedded linefeeds and URL encodings are not supported.
*
*/
#if !defined(SSL_CALLS_H)
#define SSL_CALLS_H
#if !defined(BASE64_CALLS_H)
#define BASE64_CALLS_H
#include "arch.h"
size_t
base64_decoded_bytes(const char *src);
char *
base64_decode(char *dst, const char *src, size_t len);
/*
* Decodes a base64 string
*
* @param src Pointer to null-terminated source
* @param dst Pointer to output buffer
* @param dst_len Length of above. No more than this is written to the
* output buffer
* @param actual_len Pointer to value to receive actual length of decoded data
* @return 0 for success, 1 for an invalid input string
*
* The following notes apply to this implementation:-
* - Embedded padding is supported, provided it only occurs at the end
* of a quantum as described in RFC4648(4). This allows concatenated
* encodings to be fed into the decoder.
* - Padding of the last quantum is assumed if not provided.
* - Excess padding of the last quantum is ignored.
*
* Only dst_len bytes at most are written to the output. The length
* returned in actual_len however represents how much buffer is needed for
* a correct result. This may be more than dst_len, and enables the caller
* to detect a potential buffer overflow
*/
int
base64_decode(const char *src, char *dst, size_t dst_len, size_t *actual_len);
#endif
/*
* Encodes a buffer as base64
*
* @param src Pointer to source
* @param src_len Length of above.
* @param dst Pointer to output buffer for null-terminated string
* @param dst_len Length of above. No more than this is written to the
* output buffer
* @return Number of source characters processed
*
* The following notes apply to this implementation:-
* - Padding of the last quantum is always written if the number of
* source bytes is not divisible by 3.
*
* The number of source characters processed is always returned. If
* the destination buffer is too small for all the output plus a
* terminator, the returned value from this procedure will be less than
* src_len. In this case no padding characters will have been written,
* and the remaining characters can be converted with more calls to
* this procedure.
*/
size_t
base64_encode(const char *src, size_t src_len, char *dst, size_t dst_len);
#endif /* BASE64_CALLS_H */

View File

@ -6,6 +6,8 @@ AM_CPPFLAGS = \
LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \
$(top_srcdir)/tap-driver.sh
PACKAGE_STRING = "libcommon"
TESTS = test_common
check_PROGRAMS = test_common
@ -14,7 +16,8 @@ test_common_SOURCES = \
test_common_main.c \
test_string_calls.c \
test_os_calls.c \
test_ssl_calls.c
test_ssl_calls.c \
test_base64.c
test_common_CFLAGS = \
@CHECK_CFLAGS@ \

400
tests/common/test_base64.c Normal file
View File

@ -0,0 +1,400 @@
#if defined(HAVE_CONFIG_H)
#include "config_ac.h"
#endif
#include "os_calls.h"
#include "string_calls.h"
#include "base64.h"
#include "test_common.h"
/*
* These are the example test strings in RFC4648(10)
*/
static const char *rfc4648_ex1_text = "";
static const char *rfc4648_ex1_b64 = "";
static const char *rfc4648_ex2_text = "f";
static const char *rfc4648_ex2_b64 = "Zg==";
static const char *rfc4648_ex3_text = "fo";
static const char *rfc4648_ex3_b64 = "Zm8=";
static const char *rfc4648_ex4_text = "foo";
static const char *rfc4648_ex4_b64 = "Zm9v";
static const char *rfc4648_ex5_text = "foob";
static const char *rfc4648_ex5_b64 = "Zm9vYg==";
static const char *rfc4648_ex6_text = "fooba";
static const char *rfc4648_ex6_b64 = "Zm9vYmE=";
static const char *rfc4648_ex7_text = "foobar";
static const char *rfc4648_ex7_b64 = "Zm9vYmFy";
/* Every single valid base64 character, except padding */
static const char *all_b64 =
"ABCDEFGHIJKL"
"MNOPQRSTUVWX"
"YZabcdefghij"
"klmnopqrstuv"
"wxyz01234567"
"89+/";
/* What we should get as binary if we decode this */
static const char all_b64_decoded[] =
{
'\x00', '\x10', '\x83', '\x10', '\x51', '\x87', '\x20', '\x92', '\x8b',
'\x30', '\xd3', '\x8f', '\x41', '\x14', '\x93', '\x51', '\x55', '\x97',
'\x61', '\x96', '\x9b', '\x71', '\xd7', '\x9f', '\x82', '\x18', '\xa3',
'\x92', '\x59', '\xa7', '\xa2', '\x9a', '\xab', '\xb2', '\xdb', '\xaf',
'\xc3', '\x1c', '\xb3', '\xd3', '\x5d', '\xb7', '\xe3', '\x9e', '\xbb',
'\xf3', '\xdf', '\xbf'
};
static void
test_rfc4648_to_b64(const char *plaintext, size_t len, const char *b64)
{
char buff[256];
size_t result;
result = base64_encode(plaintext, len, buff, sizeof(buff));
ck_assert_int_eq(result, len);
ck_assert_str_eq(buff, b64);
}
/* Text-only encoder wrapper */
static void
test_rfc4648_to_b64_text(const char *plaintext, const char *b64)
{
test_rfc4648_to_b64(plaintext, g_strlen(plaintext), b64);
}
/* Text-only decoder wrapper for valid base64 */
static void
test_rfc4648_from_b64_text(const char *b64, const char *text)
{
char buff[256];
size_t actual_len;
int result;
result = base64_decode(b64, buff, sizeof(buff), &actual_len);
ck_assert_int_eq(result, 0);
ck_assert_int_lt(actual_len, sizeof(buff));
buff[actual_len] = '\0';
ck_assert_str_eq(buff, text);
}
/******************************************************************************/
START_TEST(test_b64_rfc4648_ex1_to)
{
test_rfc4648_to_b64_text(rfc4648_ex1_text, rfc4648_ex1_b64);
}
END_TEST
/******************************************************************************/
START_TEST(test_b64_rfc4648_ex1_from)
{
test_rfc4648_from_b64_text(rfc4648_ex1_b64, rfc4648_ex1_text);
}
END_TEST
/******************************************************************************/
START_TEST(test_b64_rfc4648_ex2_to)
{
test_rfc4648_to_b64_text(rfc4648_ex2_text, rfc4648_ex2_b64);
}
END_TEST
/******************************************************************************/
START_TEST(test_b64_rfc4648_ex2_from)
{
test_rfc4648_from_b64_text(rfc4648_ex2_b64, rfc4648_ex2_text);
}
END_TEST
/******************************************************************************/
START_TEST(test_b64_rfc4648_ex3_to)
{
test_rfc4648_to_b64_text(rfc4648_ex3_text, rfc4648_ex3_b64);
}
END_TEST
/******************************************************************************/
START_TEST(test_b64_rfc4648_ex3_from)
{
test_rfc4648_from_b64_text(rfc4648_ex3_b64, rfc4648_ex3_text);
}
END_TEST
/******************************************************************************/
START_TEST(test_b64_rfc4648_ex4_to)
{
test_rfc4648_to_b64_text(rfc4648_ex4_text, rfc4648_ex4_b64);
}
END_TEST
/******************************************************************************/
START_TEST(test_b64_rfc4648_ex4_from)
{
test_rfc4648_from_b64_text(rfc4648_ex4_b64, rfc4648_ex4_text);
}
END_TEST
/******************************************************************************/
START_TEST(test_b64_rfc4648_ex5_to)
{
test_rfc4648_to_b64_text(rfc4648_ex5_text, rfc4648_ex5_b64);
}
END_TEST
/******************************************************************************/
START_TEST(test_b64_rfc4648_ex5_from)
{
test_rfc4648_from_b64_text(rfc4648_ex5_b64, rfc4648_ex5_text);
}
END_TEST
/******************************************************************************/
START_TEST(test_b64_rfc4648_ex6_to)
{
test_rfc4648_to_b64_text(rfc4648_ex6_text, rfc4648_ex6_b64);
}
END_TEST
/******************************************************************************/
START_TEST(test_b64_rfc4648_ex6_from)
{
test_rfc4648_from_b64_text(rfc4648_ex6_b64, rfc4648_ex6_text);
}
END_TEST
/******************************************************************************/
START_TEST(test_b64_rfc4648_ex7_to)
{
test_rfc4648_to_b64_text(rfc4648_ex7_text, rfc4648_ex7_b64);
}
END_TEST
/******************************************************************************/
START_TEST(test_b64_rfc4648_ex7_from)
{
test_rfc4648_from_b64_text(rfc4648_ex7_b64, rfc4648_ex7_text);
}
END_TEST
/******************************************************************************/
START_TEST(test_b64_all_valid_from)
{
char buff[256];
size_t actual_len;
int result;
char *str_result;
char *str_expected;
result = base64_decode(all_b64, buff, sizeof(buff), &actual_len);
ck_assert_int_eq(result, 0);
ck_assert_int_eq(actual_len, sizeof(all_b64_decoded));
str_result = bin_to_hex(buff, actual_len);
str_expected = bin_to_hex(all_b64_decoded, sizeof(all_b64_decoded));
ck_assert_str_eq(str_result, str_expected);
free(str_result);
free(str_expected);
}
END_TEST
/******************************************************************************/
START_TEST(test_b64_all_valid_to)
{
char buff[256];
size_t result;
result = base64_encode(all_b64_decoded, sizeof(all_b64_decoded),
buff, sizeof(buff));
ck_assert_int_eq(result, sizeof(all_b64_decoded));
ck_assert_str_eq(buff, all_b64);
}
END_TEST
/******************************************************************************/
START_TEST(test_b64_all_invalid)
{
char buff[256];
size_t actual_len;
char valid[256] = {0};
char encoded[5] = { "T0sh" }; /* Decodes to 'OK!' */
int result;
/* Make a note of all the valid b64 characters */
unsigned int i = 0;
unsigned char c;
while ((c = all_b64[i]) != '\0')
{
valid[c] = 1;
++i;
}
/* Check the decoder's working on a simple string...*/
result = base64_decode(encoded, buff, sizeof(buff), &actual_len);
ck_assert_int_eq(result, 0);
ck_assert_int_eq(actual_len, 3);
buff[actual_len] = '\0';
ck_assert_str_eq(buff, "OK!");
/* Now replace the 1st character with all invalid characters in turn,
* and check they're rejected */
for (i = 0 ; i < 256; ++i)
{
if (i != '\0' && !valid[i]) /* Don't try the string terminator char! */
{
encoded[0] = i;
result = base64_decode(encoded, buff, sizeof(buff), &actual_len);
if (result == 0)
{
ck_abort_msg("Character 0x%02x was not rejected", i);
}
}
}
}
END_TEST
/******************************************************************************/
START_TEST(test_b64_small_buffer_encode)
{
char buff[10 * 4 + 1]; /* Enough space for 10 quanta */
size_t result;
result = base64_encode(all_b64_decoded, sizeof(all_b64_decoded),
buff, sizeof(buff));
/* Should have read 10 lots of 24 bits from the input */
ck_assert_int_eq(result, 10 * 3);
ck_assert_str_eq(buff, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn");
}
END_TEST
/******************************************************************************/
START_TEST(test_b64_small_buffer_decode)
{
char buff[10]; /* Enough space for 10 chars */
size_t actual_len;
int result;
char *str_result;
char *str_expected;
result = base64_decode(all_b64, buff, sizeof(buff), &actual_len);
ck_assert_int_eq(result, 0);
ck_assert_int_eq(actual_len, sizeof(all_b64_decoded));
str_result = bin_to_hex(buff, sizeof(buff));
str_expected = bin_to_hex(all_b64_decoded, sizeof(buff));
ck_assert_str_eq(str_result, str_expected);
free(str_result);
free(str_expected);
}
END_TEST
/******************************************************************************/
START_TEST(test_b64_add_pad_one)
{
/* Check that a missing trailing '=' is added when decoding */
test_rfc4648_from_b64_text("Zm8", "fo"); /* RFC4648 example 3 */
}
END_TEST
/******************************************************************************/
START_TEST(test_b64_add_pad_two)
{
/* Check that two missing trailing '=' chars are added when decoding */
test_rfc4648_from_b64_text("Zg", "f"); /* RFC4648 example 2 */
}
END_TEST
/******************************************************************************/
START_TEST(test_b64_bad_pad)
{
char buff[16];
size_t actual_len;
/* Check all bad quanta with padding chars */
static const char *bad_pad[] =
{
"=AAA",
"A=AA",
"AA=A",
"==AA",
"=A=A",
"=AA=",
"A==A",
"A=A=",
"===A",
"A===",
NULL
};
const char **p;
for (p = bad_pad ; *p != NULL ; ++p)
{
int result = base64_decode(*p, buff, sizeof(buff), &actual_len);
if (result == 0)
{
ck_abort_msg("Padding '%s' was not rejected", *p);
}
}
}
END_TEST
/******************************************************************************/
START_TEST(test_b64_concat_pad)
{
const char *src =
"VGVzdA==" /* Test */
"IA==" /* <space> */
"Y29uY2F0ZW5hdGVk" /* concatenated */
"IA==" /* <space> */
"cGFkZGluZw=="; /*padding */
const char *expected = "Test concatenated padding";
char buff[64];
size_t actual_len;
int result;
result = base64_decode(src, buff, sizeof(buff), &actual_len);
ck_assert_int_eq(result, 0);
ck_assert_int_eq(actual_len, g_strlen(expected));
buff[actual_len] = '\0';
ck_assert_str_eq(buff, expected);
}
END_TEST
/******************************************************************************/
Suite *
make_suite_test_base64(void)
{
Suite *s;
TCase *tc_b64;
s = suite_create("base64");
tc_b64 = tcase_create("base64");
suite_add_tcase(s, tc_b64);
tcase_add_test(tc_b64, test_b64_rfc4648_ex1_to);
tcase_add_test(tc_b64, test_b64_rfc4648_ex1_from);
tcase_add_test(tc_b64, test_b64_rfc4648_ex2_to);
tcase_add_test(tc_b64, test_b64_rfc4648_ex2_from);
tcase_add_test(tc_b64, test_b64_rfc4648_ex3_to);
tcase_add_test(tc_b64, test_b64_rfc4648_ex3_from);
tcase_add_test(tc_b64, test_b64_rfc4648_ex4_to);
tcase_add_test(tc_b64, test_b64_rfc4648_ex4_from);
tcase_add_test(tc_b64, test_b64_rfc4648_ex5_to);
tcase_add_test(tc_b64, test_b64_rfc4648_ex5_from);
tcase_add_test(tc_b64, test_b64_rfc4648_ex6_to);
tcase_add_test(tc_b64, test_b64_rfc4648_ex6_from);
tcase_add_test(tc_b64, test_b64_rfc4648_ex7_to);
tcase_add_test(tc_b64, test_b64_rfc4648_ex7_from);
tcase_add_test(tc_b64, test_b64_all_valid_from);
tcase_add_test(tc_b64, test_b64_all_valid_to);
tcase_add_test(tc_b64, test_b64_all_invalid);
tcase_add_test(tc_b64, test_b64_small_buffer_encode);
tcase_add_test(tc_b64, test_b64_small_buffer_decode);
tcase_add_test(tc_b64, test_b64_add_pad_one);
tcase_add_test(tc_b64, test_b64_add_pad_two);
tcase_add_test(tc_b64, test_b64_bad_pad);
tcase_add_test(tc_b64, test_b64_concat_pad);
return s;
}

View File

@ -4,8 +4,12 @@
#include <check.h>
char *
bin_to_hex(const char *input, int length);
Suite *make_suite_test_string(void);
Suite *make_suite_test_os_calls(void);
Suite *make_suite_test_ssl_calls(void);
Suite *make_suite_test_base64(void);
#endif /* TEST_COMMON_H */

View File

@ -10,6 +10,36 @@
#include "test_common.h"
/**
* Converts a binary buffer to a hexadecimal representation
*
* Result must be free'd after use
*/
char *
bin_to_hex(const char *input, int length)
{
int i;
char *result = (char *)malloc(length * 2 + 1);
if (result != NULL)
{
char *p = result;
const char *hexdigit = "0123456789abcdef";
for (i = 0 ; i < length ; ++i)
{
int c = input[i];
if (c < 0)
{
c += 256;
}
*p++ = hexdigit[ c / 16];
*p++ = hexdigit[ c % 16];
}
*p = '\0';
}
return result;
}
int main (void)
{
int number_failed;
@ -18,6 +48,7 @@ int main (void)
sr = srunner_create (make_suite_test_string());
srunner_add_suite(sr, make_suite_test_os_calls());
srunner_add_suite(sr, make_suite_test_ssl_calls());
srunner_add_suite(sr, make_suite_test_base64());
// srunner_add_suite(sr, make_list_suite());
srunner_set_tap(sr, "-");

View File

@ -9,32 +9,6 @@
#include "test_common.h"
static
char *bin_to_hex(const char *input, int length)
{
int i;
char *result = (char *)g_malloc(length * 2 + 1, 0);
if (result != NULL)
{
char *p = result;
const char *hexdigit = "0123456789abcdef";
for (i = 0 ; i < length ; ++i)
{
int c = input[i];
if (c < 0)
{
c += 256;
}
*p++ = hexdigit[ c / 16];
*p++ = hexdigit[ c % 16];
}
*p = '\0';
}
return result;
}
START_TEST(test_rc4_enc_ok)
{
const char *key = "16_byte_key-----";

View File

@ -346,6 +346,7 @@ xrdp_wm_show_edits(struct xrdp_wm *self, struct xrdp_bitmap *combo)
struct xrdp_cfg_globals *globals;
char resultIP[256];
char *plain; /* base64 decoded string */
size_t plain_length; /* length of decoded base64 string */
size_t base64_length; /* length of base64 string */
globals = &self->xrdp_config->cfg_globals;
@ -379,8 +380,9 @@ xrdp_wm_show_edits(struct xrdp_wm *self, struct xrdp_bitmap *combo)
{
base64_length = g_strlen(value + BASE64PREFIX_LEN);
plain = (char *)g_malloc(base64_length, 0);
base64_decode(plain, value + BASE64PREFIX_LEN, base64_length);
g_strncpy(value, plain, g_strlen(plain));
base64_decode(value + BASE64PREFIX_LEN,
plain, base64_length, &plain_length);
g_strncpy(value, plain, plain_length);
g_free(plain);
}
else if (g_strncmp(ASK, value, ASK_LEN) == 0)
@ -421,7 +423,9 @@ xrdp_wm_show_edits(struct xrdp_wm *self, struct xrdp_bitmap *combo)
{
base64_length = g_strlen(value + ASK_LEN + BASE64PREFIX_LEN);
plain = (char *)g_malloc(base64_length, 0);
base64_decode(plain, value + ASK_LEN + BASE64PREFIX_LEN, base64_length);
base64_decode(value + ASK_LEN + BASE64PREFIX_LEN,
plain, base64_length, &plain_length);
plain[plain_length] = '\0';
g_strncpy(b->caption1, plain, 255);
g_free(plain);
}