Merge pull request #2130 from matt335672/ssl3_fixes

OpenSSL3 fixes (#2130)
This commit is contained in:
matt335672 2022-01-31 09:39:20 +00:00 committed by GitHub
commit 934a91fc29
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 1550 additions and 118 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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -26,57 +26,229 @@
#include "string_calls.h" #include "string_calls.h"
#include <openssl/bio.h> #include "base64.h"
#include <openssl/evp.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; /* 0x28 */ E_IV, E_IV, E_IV, 0x3e, E_IV, E_IV, E_IV, 0x3f,
size_t padding; /* 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 - src_i) >= 4)
if (src[len - 2] == '=')
{ {
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 * size_t
base64_decode(char *dst, const char *src, size_t len) base64_encode(const char *src, size_t src_len, char *dst, size_t dst_len)
{ {
BIO *b64; char *p = dst;
BIO *bio; size_t src_i = 0;
char *b64str; size_t max_src_len;
size_t estimated_decoded_bytes; unsigned int v;
size_t decoded_bytes; static const char *b64chr =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/=";
b64str = g_strdup(src); /* Each three octets of the source results in four bytes at the output,
estimated_decoded_bytes = base64_decoded_bytes(b64str); * plus we need a terminator. So we can work out the maximum number of
dst[estimated_decoded_bytes] = '\0'; * source octets we can process */
if (dst_len == 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)
{ {
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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -17,16 +17,66 @@
/** /**
* @file common/base64.h * @file common/base64.h
* @brief Base64 encoder / decoder * @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) #if !defined(BASE64_CALLS_H)
#define SSL_CALLS_H #define BASE64_CALLS_H
#include "arch.h" #include "arch.h"
size_t /*
base64_decoded_bytes(const char *src); * Decodes a base64 string
char * *
base64_decode(char *dst, const char *src, size_t len); * @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

@ -44,6 +44,27 @@
#define SSL_WANT_READ_WRITE_TIMEOUT 100 #define SSL_WANT_READ_WRITE_TIMEOUT 100
/*
* Globals used by openssl 3 and later */
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
static EVP_MD *g_md_md5; /* MD5 message digest */
static EVP_MD *g_md_sha1; /* SHA1 message digest */
static EVP_CIPHER *g_cipher_des_ede3_cbc; /* DES3 CBC cipher */
static EVP_MAC *g_mac_hmac; /* HMAC MAC */
#endif
/* definition of ssl_tls */
struct ssl_tls
{
SSL *ssl; /* SSL * */
SSL_CTX *ctx; /* SSL_CTX * */
char *cert;
char *key;
struct trans *trans;
tintptr rwo; /* wait obj */
int error_logged; /* Error has already been logged */
};
#if OPENSSL_VERSION_NUMBER < 0x10100000L #if OPENSSL_VERSION_NUMBER < 0x10100000L
static inline HMAC_CTX * static inline HMAC_CTX *
HMAC_CTX_new(void) HMAC_CTX_new(void)
@ -106,12 +127,41 @@ DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
#endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */ #endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
/*****************************************************************************/
static void
dump_error_stack(const char *prefix)
{
/* Dump the error stack from the SSL library */
unsigned long code;
char buff[256];
while ((code = ERR_get_error()) != 0L)
{
ERR_error_string_n(code, buff, sizeof(buff));
LOG(LOG_LEVEL_ERROR, "%s: %s", prefix, buff);
}
}
/*****************************************************************************/
/* As above, but used for TLS connection errors where only the first
error is logged */
static void
dump_ssl_error_stack(struct ssl_tls *self)
{
if (!self->error_logged)
{
dump_error_stack("SSL");
self->error_logged = 1;
}
}
/*****************************************************************************/ /*****************************************************************************/
int int
ssl_init(void) ssl_init(void)
{ {
SSL_load_error_strings(); SSL_load_error_strings();
SSL_library_init(); SSL_library_init();
return 0; return 0;
} }
@ -119,16 +169,44 @@ ssl_init(void)
int int
ssl_finish(void) ssl_finish(void)
{ {
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
/* De-allocate any allocated globals
* For OpenSSL 3, these can all safely be passed a NULL pointer */
EVP_MD_free(g_md_md5);
EVP_MD_free(g_md_sha1);
EVP_CIPHER_free(g_cipher_des_ede3_cbc);
EVP_MAC_free(g_mac_hmac);
#endif
return 0; return 0;
} }
/* rc4 stuff */ /* rc4 stuff
*
* For OpenSSL 3.0, the rc4 encryption algorithm is only provided by the
* legacy provider (see crypto(7)). Since RC4 is so simple, we can implement
* it directly rather than having to load the legacy provider. This will
* avoids problems if running on a system where openssl has been built
* without the legacy provider */
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
struct rc4_data
{
/* See https://en.wikipedia.org/wiki/RC4 */
unsigned char S[256];
int i;
int j;
};
#endif
/*****************************************************************************/ /*****************************************************************************/
void * void *
ssl_rc4_info_create(void) ssl_rc4_info_create(void)
{ {
#if OPENSSL_VERSION_NUMBER < 0x30000000L
return g_malloc(sizeof(RC4_KEY), 1); return g_malloc(sizeof(RC4_KEY), 1);
#else
return g_malloc(sizeof(struct rc4_data), 1);
#endif
} }
/*****************************************************************************/ /*****************************************************************************/
@ -140,16 +218,77 @@ ssl_rc4_info_delete(void *rc4_info)
/*****************************************************************************/ /*****************************************************************************/
void void
ssl_rc4_set_key(void *rc4_info, char *key, int len) ssl_rc4_set_key(void *rc4_info, const char *key, int len)
{ {
#if OPENSSL_VERSION_NUMBER < 0x30000000L
RC4_set_key((RC4_KEY *)rc4_info, len, (tui8 *)key); RC4_set_key((RC4_KEY *)rc4_info, len, (tui8 *)key);
#else
unsigned char *S = ((struct rc4_data *)rc4_info)->S;
int i;
int j = 0;
unsigned char t;
for (i = 0 ; i < 256; ++i)
{
S[i] = i;
}
for (i = 0 ; i < 256; ++i)
{
j = (j + S[i] + key[i % len]) & 0xff;
t = S[i];
S[i] = S[j];
S[j] = t;
}
((struct rc4_data *)rc4_info)->i = 0;
((struct rc4_data *)rc4_info)->j = 0;
#endif
} }
/*****************************************************************************/ /*****************************************************************************/
void void
ssl_rc4_crypt(void *rc4_info, char *data, int len) ssl_rc4_crypt(void *rc4_info, char *data, int len)
{ {
#if OPENSSL_VERSION_NUMBER < 0x30000000L
RC4((RC4_KEY *)rc4_info, len, (tui8 *)data, (tui8 *)data); RC4((RC4_KEY *)rc4_info, len, (tui8 *)data, (tui8 *)data);
#else
unsigned char *S = ((struct rc4_data *)rc4_info)->S;
int i = ((struct rc4_data *)rc4_info)->i;
int j = ((struct rc4_data *)rc4_info)->j;
unsigned char *p = (unsigned char *)data;
unsigned char t;
unsigned char k;
/*
* Do some loop-unrolling for performance. Here are the steps
* for each byte */
#define RC4_ROUND \
i = (i + 1) & 0xff; \
j = (j + S[i]) & 0xff; \
t = S[i]; \
S[i] = S[j]; \
S[j] = t; \
k = S[(S[i] + S[j]) & 0xff]; \
*p++ ^= k
while (len >= 8)
{
RC4_ROUND;
RC4_ROUND;
RC4_ROUND;
RC4_ROUND;
RC4_ROUND;
RC4_ROUND;
RC4_ROUND;
RC4_ROUND;
len -= 8;
}
while (len-- > 0)
{
RC4_ROUND;
}
((struct rc4_data *)rc4_info)->i = i;
((struct rc4_data *)rc4_info)->j = j;
#endif
} }
/* sha1 stuff */ /* sha1 stuff */
@ -158,35 +297,78 @@ ssl_rc4_crypt(void *rc4_info, char *data, int len)
void * void *
ssl_sha1_info_create(void) ssl_sha1_info_create(void)
{ {
#if OPENSSL_VERSION_NUMBER < 0x30000000L
return g_malloc(sizeof(SHA_CTX), 1); return g_malloc(sizeof(SHA_CTX), 1);
#else
/*
* If we can't get the digest loaded, there's a problem with the
* library providers, so there's no point in us returning anything useful.
* If we do load the digest, it's used later */
if (g_md_sha1 == NULL)
{
if ((g_md_sha1 = EVP_MD_fetch(NULL, "sha1", NULL)) == NULL)
{
dump_error_stack("sha1");
return NULL;
}
}
return (void *)EVP_MD_CTX_new();
#endif
} }
/*****************************************************************************/ /*****************************************************************************/
void void
ssl_sha1_info_delete(void *sha1_info) ssl_sha1_info_delete(void *sha1_info)
{ {
#if OPENSSL_VERSION_NUMBER < 0x30000000L
g_free(sha1_info); g_free(sha1_info);
#else
EVP_MD_CTX_free((EVP_MD_CTX *)sha1_info);
#endif
} }
/*****************************************************************************/ /*****************************************************************************/
void void
ssl_sha1_clear(void *sha1_info) ssl_sha1_clear(void *sha1_info)
{ {
#if OPENSSL_VERSION_NUMBER < 0x30000000L
SHA1_Init((SHA_CTX *)sha1_info); SHA1_Init((SHA_CTX *)sha1_info);
#else
if (sha1_info != NULL)
{
EVP_DigestInit_ex(sha1_info, g_md_sha1, NULL);
}
#endif
} }
/*****************************************************************************/ /*****************************************************************************/
void void
ssl_sha1_transform(void *sha1_info, const char *data, int len) ssl_sha1_transform(void *sha1_info, const char *data, int len)
{ {
#if OPENSSL_VERSION_NUMBER < 0x30000000L
SHA1_Update((SHA_CTX *)sha1_info, data, len); SHA1_Update((SHA_CTX *)sha1_info, data, len);
#else
if (sha1_info != NULL)
{
EVP_DigestUpdate((EVP_MD_CTX *)sha1_info, data, len);
}
#endif
} }
/*****************************************************************************/ /*****************************************************************************/
void void
ssl_sha1_complete(void *sha1_info, char *data) ssl_sha1_complete(void *sha1_info, char *data)
{ {
#if OPENSSL_VERSION_NUMBER < 0x30000000L
SHA1_Final((tui8 *)data, (SHA_CTX *)sha1_info); SHA1_Final((tui8 *)data, (SHA_CTX *)sha1_info);
#else
if (sha1_info != NULL)
{
EVP_DigestFinal_ex((EVP_MD_CTX *)sha1_info, (unsigned char *)data,
NULL);
}
#endif
} }
/* md5 stuff */ /* md5 stuff */
@ -195,35 +377,77 @@ ssl_sha1_complete(void *sha1_info, char *data)
void * void *
ssl_md5_info_create(void) ssl_md5_info_create(void)
{ {
#if OPENSSL_VERSION_NUMBER < 0x30000000L
return g_malloc(sizeof(MD5_CTX), 1); return g_malloc(sizeof(MD5_CTX), 1);
#else
/*
* If we can't get the digest loaded, there's a problem with the
* library providers, so there's no point in us returning anything useful.
* If we do load the digest, it's used later */
if (g_md_md5 == NULL)
{
if ((g_md_md5 = EVP_MD_fetch(NULL, "md5", NULL)) == NULL)
{
dump_error_stack("md5");
return NULL;
}
}
return (void *)EVP_MD_CTX_new();
#endif
} }
/*****************************************************************************/ /*****************************************************************************/
void void
ssl_md5_info_delete(void *md5_info) ssl_md5_info_delete(void *md5_info)
{ {
#if OPENSSL_VERSION_NUMBER < 0x30000000L
g_free(md5_info); g_free(md5_info);
#else
EVP_MD_CTX_free((EVP_MD_CTX *)md5_info);
#endif
} }
/*****************************************************************************/ /*****************************************************************************/
void void
ssl_md5_clear(void *md5_info) ssl_md5_clear(void *md5_info)
{ {
#if OPENSSL_VERSION_NUMBER < 0x30000000L
MD5_Init((MD5_CTX *)md5_info); MD5_Init((MD5_CTX *)md5_info);
#else
if (md5_info != NULL)
{
EVP_DigestInit_ex(md5_info, g_md_md5, NULL);
}
#endif
} }
/*****************************************************************************/ /*****************************************************************************/
void void
ssl_md5_transform(void *md5_info, char *data, int len) ssl_md5_transform(void *md5_info, const char *data, int len)
{ {
#if OPENSSL_VERSION_NUMBER < 0x30000000L
MD5_Update((MD5_CTX *)md5_info, data, len); MD5_Update((MD5_CTX *)md5_info, data, len);
#else
if (md5_info != NULL)
{
EVP_DigestUpdate((EVP_MD_CTX *)md5_info, data, len);
}
#endif
} }
/*****************************************************************************/ /*****************************************************************************/
void void
ssl_md5_complete(void *md5_info, char *data) ssl_md5_complete(void *md5_info, char *data)
{ {
#if OPENSSL_VERSION_NUMBER < 0x30000000L
MD5_Final((tui8 *)data, (MD5_CTX *)md5_info); MD5_Final((tui8 *)data, (MD5_CTX *)md5_info);
#else
if (md5_info != NULL)
{
EVP_DigestFinal_ex((EVP_MD_CTX *)md5_info, (unsigned char *)data, NULL);
}
#endif
} }
/* FIPS stuff */ /* FIPS stuff */
@ -236,10 +460,30 @@ ssl_des3_encrypt_info_create(const char *key, const char *ivec)
const tui8 *lkey; const tui8 *lkey;
const tui8 *livec; const tui8 *livec;
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
/*
* For these versions of OpenSSL, there are no long-term guarantees the
* DES3 cipher will be available. We'll try to load it here so we
* can log any errors */
if (g_cipher_des_ede3_cbc == NULL)
{
g_cipher_des_ede3_cbc = EVP_CIPHER_fetch(NULL, "des-ede3-cbc", NULL);
if (g_cipher_des_ede3_cbc == NULL)
{
dump_error_stack("DES-EDE3-CBC");
return NULL;
}
}
#endif
des3_ctx = EVP_CIPHER_CTX_new(); des3_ctx = EVP_CIPHER_CTX_new();
lkey = (const tui8 *) key; lkey = (const tui8 *) key;
livec = (const tui8 *) ivec; livec = (const tui8 *) ivec;
#if OPENSSL_VERSION_NUMBER < 0x30000000L
EVP_EncryptInit_ex(des3_ctx, EVP_des_ede3_cbc(), NULL, lkey, livec); EVP_EncryptInit_ex(des3_ctx, EVP_des_ede3_cbc(), NULL, lkey, livec);
#else
EVP_EncryptInit_ex(des3_ctx, g_cipher_des_ede3_cbc, NULL, lkey, livec);
#endif
EVP_CIPHER_CTX_set_padding(des3_ctx, 0); EVP_CIPHER_CTX_set_padding(des3_ctx, 0);
return des3_ctx; return des3_ctx;
} }
@ -252,10 +496,30 @@ ssl_des3_decrypt_info_create(const char *key, const char *ivec)
const tui8 *lkey; const tui8 *lkey;
const tui8 *livec; const tui8 *livec;
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
/*
* For these versions of OpenSSL, there are no long-term guarantees the
* DES3 cipher will be available. We'll try to load it here so we
* can log any errors */
if (g_cipher_des_ede3_cbc == NULL)
{
g_cipher_des_ede3_cbc = EVP_CIPHER_fetch(NULL, "des-ede3-cbc", NULL);
if (g_cipher_des_ede3_cbc == NULL)
{
dump_error_stack("DES-EDE3-CBC");
return NULL;
}
}
#endif
des3_ctx = EVP_CIPHER_CTX_new(); des3_ctx = EVP_CIPHER_CTX_new();
lkey = (const tui8 *) key; lkey = (const tui8 *) key;
livec = (const tui8 *) ivec; livec = (const tui8 *) ivec;
#if OPENSSL_VERSION_NUMBER < 0x30000000L
EVP_DecryptInit_ex(des3_ctx, EVP_des_ede3_cbc(), NULL, lkey, livec); EVP_DecryptInit_ex(des3_ctx, EVP_des_ede3_cbc(), NULL, lkey, livec);
#else
EVP_DecryptInit_ex(des3_ctx, g_cipher_des_ede3_cbc, NULL, lkey, livec);
#endif
EVP_CIPHER_CTX_set_padding(des3_ctx, 0); EVP_CIPHER_CTX_set_padding(des3_ctx, 0);
return des3_ctx; return des3_ctx;
} }
@ -283,10 +547,13 @@ ssl_des3_encrypt(void *des3, int length, const char *in_data, char *out_data)
tui8 *lout_data; tui8 *lout_data;
des3_ctx = (EVP_CIPHER_CTX *) des3; des3_ctx = (EVP_CIPHER_CTX *) des3;
lin_data = (const tui8 *) in_data; if (des3_ctx != NULL)
lout_data = (tui8 *) out_data; {
len = 0; lin_data = (const tui8 *) in_data;
EVP_EncryptUpdate(des3_ctx, lout_data, &len, lin_data, length); lout_data = (tui8 *) out_data;
len = 0;
EVP_EncryptUpdate(des3_ctx, lout_data, &len, lin_data, length);
}
return 0; return 0;
} }
@ -300,10 +567,13 @@ ssl_des3_decrypt(void *des3, int length, const char *in_data, char *out_data)
tui8 *lout_data; tui8 *lout_data;
des3_ctx = (EVP_CIPHER_CTX *) des3; des3_ctx = (EVP_CIPHER_CTX *) des3;
lin_data = (const tui8 *) in_data; if (des3_ctx != NULL)
lout_data = (tui8 *) out_data; {
len = 0; lin_data = (const tui8 *) in_data;
EVP_DecryptUpdate(des3_ctx, lout_data, &len, lin_data, length); lout_data = (tui8 *) out_data;
len = 0;
EVP_DecryptUpdate(des3_ctx, lout_data, &len, lin_data, length);
}
return 0; return 0;
} }
@ -311,16 +581,28 @@ ssl_des3_decrypt(void *des3, int length, const char *in_data, char *out_data)
void * void *
ssl_hmac_info_create(void) ssl_hmac_info_create(void)
{ {
HMAC_CTX *hmac_ctx; #if OPENSSL_VERSION_NUMBER < 0x30000000L
return (HMAC_CTX *)HMAC_CTX_new();
#else
/* Need a MAC algorithm loaded */
if (g_mac_hmac == NULL)
{
if ((g_mac_hmac = EVP_MAC_fetch(NULL, "hmac", NULL)) == NULL)
{
dump_error_stack("hmac");
return NULL;
}
}
hmac_ctx = HMAC_CTX_new(); return (void *)EVP_MAC_CTX_new(g_mac_hmac);
return hmac_ctx; #endif
} }
/*****************************************************************************/ /*****************************************************************************/
void void
ssl_hmac_info_delete(void *hmac) ssl_hmac_info_delete(void *hmac)
{ {
#if OPENSSL_VERSION_NUMBER < 0x30000000L
HMAC_CTX *hmac_ctx; HMAC_CTX *hmac_ctx;
hmac_ctx = (HMAC_CTX *) hmac; hmac_ctx = (HMAC_CTX *) hmac;
@ -328,34 +610,61 @@ ssl_hmac_info_delete(void *hmac)
{ {
HMAC_CTX_free(hmac_ctx); HMAC_CTX_free(hmac_ctx);
} }
#else
EVP_MAC_CTX_free((EVP_MAC_CTX *)hmac);
#endif
} }
/*****************************************************************************/ /*****************************************************************************/
void void
ssl_hmac_sha1_init(void *hmac, const char *data, int len) ssl_hmac_sha1_init(void *hmac, const char *data, int len)
{ {
#if OPENSSL_VERSION_NUMBER < 0x30000000L
HMAC_CTX *hmac_ctx; HMAC_CTX *hmac_ctx;
hmac_ctx = (HMAC_CTX *) hmac; hmac_ctx = (HMAC_CTX *) hmac;
HMAC_Init_ex(hmac_ctx, data, len, EVP_sha1(), NULL); HMAC_Init_ex(hmac_ctx, data, len, EVP_sha1(), NULL);
#else
if (hmac != NULL)
{
char digest[] = "sha1";
OSSL_PARAM params[3];
size_t n = 0;
params[n++] = OSSL_PARAM_construct_utf8_string("digest", digest, 0);
params[n++] = OSSL_PARAM_construct_end();
if (EVP_MAC_init((EVP_MAC_CTX *)hmac, (unsigned char *)data,
len, params) == 0)
{
dump_error_stack("hmac-sha1");
}
}
#endif
} }
/*****************************************************************************/ /*****************************************************************************/
void void
ssl_hmac_transform(void *hmac, const char *data, int len) ssl_hmac_transform(void *hmac, const char *data, int len)
{ {
#if OPENSSL_VERSION_NUMBER < 0x30000000L
HMAC_CTX *hmac_ctx; HMAC_CTX *hmac_ctx;
const tui8 *ldata; const tui8 *ldata;
hmac_ctx = (HMAC_CTX *) hmac; hmac_ctx = (HMAC_CTX *) hmac;
ldata = (const tui8 *) data; ldata = (const tui8 *) data;
HMAC_Update(hmac_ctx, ldata, len); HMAC_Update(hmac_ctx, ldata, len);
#else
if (hmac != NULL)
{
EVP_MAC_update((EVP_MAC_CTX *)hmac, (unsigned char *)data, len);
}
#endif
} }
/*****************************************************************************/ /*****************************************************************************/
void void
ssl_hmac_complete(void *hmac, char *data, int len) ssl_hmac_complete(void *hmac, char *data, int len)
{ {
#if OPENSSL_VERSION_NUMBER < 0x30000000L
HMAC_CTX *hmac_ctx; HMAC_CTX *hmac_ctx;
tui8 *ldata; tui8 *ldata;
tui32 llen; tui32 llen;
@ -364,6 +673,12 @@ ssl_hmac_complete(void *hmac, char *data, int len)
ldata = (tui8 *) data; ldata = (tui8 *) data;
llen = len; llen = len;
HMAC_Final(hmac_ctx, ldata, &llen); HMAC_Final(hmac_ctx, ldata, &llen);
#else
if (hmac != NULL)
{
EVP_MAC_final((EVP_MAC_CTX *)hmac, (unsigned char *)data, NULL, len);
}
#endif
} }
/*****************************************************************************/ /*****************************************************************************/
@ -455,7 +770,6 @@ ssl_gen_key_xrdp1(int key_size_in_bits, const char *exp, int exp_len,
char *mod, int mod_len, char *pri, int pri_len) char *mod, int mod_len, char *pri, int pri_len)
{ {
BIGNUM *my_e; BIGNUM *my_e;
RSA *my_key;
char *lexp; char *lexp;
char *lmod; char *lmod;
char *lpri; char *lpri;
@ -477,12 +791,44 @@ ssl_gen_key_xrdp1(int key_size_in_bits, const char *exp, int exp_len,
ssl_reverse_it(lexp, exp_len); ssl_reverse_it(lexp, exp_len);
my_e = BN_new(); my_e = BN_new();
BN_bin2bn((tui8 *)lexp, exp_len, my_e); BN_bin2bn((tui8 *)lexp, exp_len, my_e);
my_key = RSA_new();
#if OPENSSL_VERSION_NUMBER < 0x30000000L
const BIGNUM *n = NULL;
const BIGNUM *d = NULL;
RSA *my_key = RSA_new();
error = RSA_generate_key_ex(my_key, key_size_in_bits, my_e, 0) == 0; error = RSA_generate_key_ex(my_key, key_size_in_bits, my_e, 0) == 0;
const BIGNUM *n; /* After this call, n and d point directly into my_key, and are valid
const BIGNUM *d; * until my_key is free'd */
RSA_get0_key(my_key, &n, NULL, &d); RSA_get0_key(my_key, &n, NULL, &d);
#else
BIGNUM *n = NULL;
BIGNUM *d = NULL;
OSSL_PARAM params[] =
{
OSSL_PARAM_construct_int("bits", &key_size_in_bits),
OSSL_PARAM_construct_end()
};
EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL);
EVP_PKEY *pkey = NULL;
if (pctx != NULL &&
EVP_PKEY_keygen_init(pctx) > 0 &&
EVP_PKEY_CTX_set_params(pctx, params) > 0 &&
EVP_PKEY_generate(pctx, &pkey) > 0 &&
EVP_PKEY_get_bn_param(pkey, "n", &n) > 0 &&
EVP_PKEY_get_bn_param(pkey, "d", &d) > 0)
{
error = 0;
}
else
{
error = 1;
}
EVP_PKEY_CTX_free(pctx);
EVP_PKEY_free(pkey);
#endif
if (error == 0) if (error == 0)
{ {
@ -517,7 +863,12 @@ ssl_gen_key_xrdp1(int key_size_in_bits, const char *exp, int exp_len,
} }
BN_free(my_e); BN_free(my_e);
#if OPENSSL_VERSION_NUMBER < 0x30000000L
RSA_free(my_key); RSA_free(my_key);
#else
BN_free(n);
BN_clear_free(d);
#endif
g_free(lexp); g_free(lexp);
g_free(lmod); g_free(lmod);
g_free(lpri); g_free(lpri);
@ -529,7 +880,11 @@ ssl_gen_key_xrdp1(int key_size_in_bits, const char *exp, int exp_len,
see also see also
* https://wiki.openssl.org/index.php/Diffie-Hellman_parameters * https://wiki.openssl.org/index.php/Diffie-Hellman_parameters
* https://wiki.openssl.org/index.php/Manual:SSL_CTX_set_tmp_dh_callback(3) * https://wiki.openssl.org/index.php/Manual:SSL_CTX_set_tmp_dh_callback(3)
*
* We dont do this for OpenSSL 3 - we use SSL_CTX_set_dh_auto() instead, as this
* can cater for different key sizes on the certificate
*/ */
#if OPENSSL_VERSION_NUMBER < 0x30000000L
static DH *ssl_get_dh2236() static DH *ssl_get_dh2236()
{ {
static unsigned char dh2236_p[] = static unsigned char dh2236_p[] =
@ -591,6 +946,7 @@ static DH *ssl_get_dh2236()
return dh; return dh;
} }
#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L */
/*****************************************************************************/ /*****************************************************************************/
struct ssl_tls * struct ssl_tls *
@ -613,25 +969,6 @@ ssl_tls_create(struct trans *trans, const char *key, const char *cert)
return self; return self;
} }
/*****************************************************************************/
static void
dump_ssl_error_stack(struct ssl_tls *self)
{
if (!self->error_logged)
{
/* Dump the error stack from the SSL library */
unsigned long code;
char buff[256];
while ((code = ERR_get_error()) != 0L)
{
ERR_error_string_n(code, buff, sizeof(buff));
LOG(LOG_LEVEL_ERROR, "SSL: %s", buff);
}
self->error_logged = 1;
}
}
/*****************************************************************************/ /*****************************************************************************/
static int static int
ssl_tls_log_error(struct ssl_tls *self, const char *func, int value) ssl_tls_log_error(struct ssl_tls *self, const char *func, int value)
@ -752,6 +1089,7 @@ ssl_tls_accept(struct ssl_tls *self, long ssl_protocols,
SSL_CTX_set_options(self->ctx, options); SSL_CTX_set_options(self->ctx, options);
/* set DH parameters */ /* set DH parameters */
#if OPENSSL_VERSION_NUMBER < 0x30000000L
DH *dh = ssl_get_dh2236(); DH *dh = ssl_get_dh2236();
if (dh == NULL) if (dh == NULL)
{ {
@ -766,7 +1104,14 @@ ssl_tls_accept(struct ssl_tls *self, long ssl_protocols,
return 1; return 1;
} }
DH_free(dh); // ok to free, copied into ctx by SSL_CTX_set_tmp_dh() DH_free(dh); // ok to free, copied into ctx by SSL_CTX_set_tmp_dh()
#else
if (!SSL_CTX_set_dh_auto(self->ctx, 1))
{
LOG(LOG_LEVEL_ERROR, "TLS DHE auto failed to be enabled");
dump_ssl_error_stack(self);
return 1;
}
#endif
#if defined(SSL_CTX_set_ecdh_auto) #if defined(SSL_CTX_set_ecdh_auto)
if (!SSL_CTX_set_ecdh_auto(self->ctx, 1)) if (!SSL_CTX_set_ecdh_auto(self->ctx, 1))
{ {
@ -1058,16 +1403,23 @@ ssl_tls_can_recv(struct ssl_tls *tls, int sck, int millis)
/*****************************************************************************/ /*****************************************************************************/
const char * const char *
ssl_get_version(const struct ssl_st *ssl) ssl_get_version(const struct ssl_tls *ssl)
{ {
return SSL_get_version(ssl); return SSL_get_version(ssl->ssl);
} }
/*****************************************************************************/ /*****************************************************************************/
const char * const char *
ssl_get_cipher_name(const struct ssl_st *ssl) ssl_get_cipher_name(const struct ssl_tls *ssl)
{ {
return SSL_get_cipher_name(ssl); return SSL_get_cipher_name(ssl->ssl);
}
/*****************************************************************************/
tintptr
ssl_get_rwo(const struct ssl_tls *ssl)
{
return ssl->rwo;
} }
/*****************************************************************************/ /*****************************************************************************/

View File

@ -22,6 +22,10 @@
#include "arch.h" #include "arch.h"
/* Incomplete types */
struct ssl_tls;
struct trans;
int int
ssl_init(void); ssl_init(void);
int int
@ -31,7 +35,7 @@ ssl_rc4_info_create(void);
void void
ssl_rc4_info_delete(void *rc4_info); ssl_rc4_info_delete(void *rc4_info);
void void
ssl_rc4_set_key(void *rc4_info, char *key, int len); ssl_rc4_set_key(void *rc4_info, const char *key, int len);
void void
ssl_rc4_crypt(void *rc4_info, char *data, int len); ssl_rc4_crypt(void *rc4_info, char *data, int len);
void * void *
@ -51,7 +55,7 @@ ssl_md5_info_delete(void *md5_info);
void void
ssl_md5_clear(void *md5_info); ssl_md5_clear(void *md5_info);
void void
ssl_md5_transform(void *md5_info, char *data, int len); ssl_md5_transform(void *md5_info, const char *data, int len);
void void
ssl_md5_complete(void *md5_info, char *data); ssl_md5_complete(void *md5_info, char *data);
void * void *
@ -81,18 +85,6 @@ int
ssl_gen_key_xrdp1(int key_size_in_bits, const char *exp, int exp_len, ssl_gen_key_xrdp1(int key_size_in_bits, const char *exp, int exp_len,
char *mod, int mod_len, char *pri, int pri_len); char *mod, int mod_len, char *pri, int pri_len);
/* ssl_tls */
struct ssl_tls
{
struct ssl_st *ssl; /* SSL * */
struct ssl_ctx_st *ctx; /* SSL_CTX * */
char *cert;
char *key;
struct trans *trans;
tintptr rwo; /* wait obj */
int error_logged; /* Error has already been logged */
};
/* xrdp_tls.c */ /* xrdp_tls.c */
struct ssl_tls * struct ssl_tls *
ssl_tls_create(struct trans *trans, const char *key, const char *cert); ssl_tls_create(struct trans *trans, const char *key, const char *cert);
@ -110,12 +102,14 @@ ssl_tls_write(struct ssl_tls *tls, const char *data, int length);
int int
ssl_tls_can_recv(struct ssl_tls *tls, int sck, int millis); ssl_tls_can_recv(struct ssl_tls *tls, int sck, int millis);
const char * const char *
ssl_get_version(const struct ssl_st *ssl); ssl_get_version(const struct ssl_tls *ssl);
const char * const char *
ssl_get_cipher_name(const struct ssl_st *ssl); ssl_get_cipher_name(const struct ssl_tls *ssl);
int int
ssl_get_protocols_from_string(const char *str, long *ssl_protocols); ssl_get_protocols_from_string(const char *str, long *ssl_protocols);
const char * const char *
get_openssl_version(); get_openssl_version();
tintptr
ssl_get_rwo(const struct ssl_tls *ssl);
#endif #endif

View File

@ -179,13 +179,9 @@ trans_get_wait_objs(struct trans *self, tbus *objs, int *count)
objs[*count] = self->sck; objs[*count] = self->sck;
(*count)++; (*count)++;
if (self->tls != 0) if (self->tls != NULL && (objs[*count] = ssl_get_rwo(self->tls)) != 0)
{ {
if (self->tls->rwo != 0) (*count)++;
{
objs[*count] = self->tls->rwo;
(*count)++;
}
} }
return 0; return 0;
@ -995,8 +991,8 @@ trans_set_tls_mode(struct trans *self, const char *key, const char *cert,
self->trans_send = trans_tls_send; self->trans_send = trans_tls_send;
self->trans_can_recv = trans_tls_can_recv; self->trans_can_recv = trans_tls_can_recv;
self->ssl_protocol = ssl_get_version(self->tls->ssl); self->ssl_protocol = ssl_get_version(self->tls);
self->cipher_name = ssl_get_cipher_name(self->tls->ssl); self->cipher_name = ssl_get_cipher_name(self->tls);
return 0; return 0;
} }

View File

@ -942,11 +942,21 @@ xrdp_rdp_incoming(struct xrdp_rdp *self)
/* log non-TLS connections */ /* log non-TLS connections */
else else
{ {
int crypt_level = self->sec_layer->crypt_level;
const char *security_level =
(crypt_level == CRYPT_LEVEL_NONE) ? "none" :
(crypt_level == CRYPT_LEVEL_LOW) ? "low" :
(crypt_level == CRYPT_LEVEL_CLIENT_COMPATIBLE) ? "medium" :
(crypt_level == CRYPT_LEVEL_HIGH) ? "high" :
(crypt_level == CRYPT_LEVEL_FIPS) ? "fips" :
/* default */ "unknown";
LOG(LOG_LEVEL_INFO, LOG(LOG_LEVEL_INFO,
"Non-TLS connection established from %s port %s: " "Non-TLS connection established from %s port %s: "
"encrypted with standard RDP security", "with security level : %s",
self->client_info.client_addr, self->client_info.client_addr,
self->client_info.client_port); self->client_info.client_port,
security_level);
} }
return 0; return 0;

View File

@ -55,6 +55,7 @@ env_check_password_file(const char *filename, const char *passwd)
/* create password hash from password */ /* create password hash from password */
passwd_bytes = g_strlen(passwd); passwd_bytes = g_strlen(passwd);
sha1 = ssl_sha1_info_create(); sha1 = ssl_sha1_info_create();
ssl_sha1_clear(sha1);
ssl_sha1_transform(sha1, "xrdp_vnc", 8); ssl_sha1_transform(sha1, "xrdp_vnc", 8);
ssl_sha1_transform(sha1, passwd, passwd_bytes); ssl_sha1_transform(sha1, passwd, passwd_bytes);
ssl_sha1_transform(sha1, passwd, passwd_bytes); ssl_sha1_transform(sha1, passwd, passwd_bytes);

View File

@ -6,6 +6,8 @@ AM_CPPFLAGS = \
LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \ LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \
$(top_srcdir)/tap-driver.sh $(top_srcdir)/tap-driver.sh
PACKAGE_STRING = "libcommon"
TESTS = test_common TESTS = test_common
check_PROGRAMS = test_common check_PROGRAMS = test_common
@ -13,7 +15,9 @@ test_common_SOURCES = \
test_common.h \ test_common.h \
test_common_main.c \ test_common_main.c \
test_string_calls.c \ test_string_calls.c \
test_os_calls.c test_os_calls.c \
test_ssl_calls.c \
test_base64.c
test_common_CFLAGS = \ test_common_CFLAGS = \
@CHECK_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,7 +4,12 @@
#include <check.h> #include <check.h>
char *
bin_to_hex(const char *input, int length);
Suite *make_suite_test_string(void); Suite *make_suite_test_string(void);
Suite *make_suite_test_os_calls(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 */ #endif /* TEST_COMMON_H */

View File

@ -4,9 +4,42 @@
#endif #endif
#include <stdlib.h> #include <stdlib.h>
#include <check.h>
#include "log.h"
#include "ssl_calls.h"
#include "test_common.h" #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 main (void)
{ {
int number_failed; int number_failed;
@ -14,11 +47,25 @@ int main (void)
sr = srunner_create (make_suite_test_string()); sr = srunner_create (make_suite_test_string());
srunner_add_suite(sr, make_suite_test_os_calls()); 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_add_suite(sr, make_list_suite());
srunner_set_tap(sr, "-"); srunner_set_tap(sr, "-");
/*
* Set up console logging */
struct log_config *lc = log_config_init_for_console(LOG_LEVEL_INFO, NULL);
log_start_from_param(lc);
log_config_free(lc);
/* Initialise the ssl module */
ssl_init();
srunner_run_all (sr, CK_ENV); srunner_run_all (sr, CK_ENV);
number_failed = srunner_ntests_failed(sr); number_failed = srunner_ntests_failed(sr);
srunner_free(sr); srunner_free(sr);
ssl_finish();
log_end();
return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
} }

View File

@ -0,0 +1,391 @@
#if defined(HAVE_CONFIG_H)
#include "config_ac.h"
#endif
#include "os_calls.h"
#include "string_calls.h"
#include "ssl_calls.h"
#include "test_common.h"
START_TEST(test_rc4_enc_ok)
{
const char *key = "16_byte_key-----";
char text[] = "xrdp-test-suite-rc4-encryption";
char *result;
void *info = ssl_rc4_info_create();
ssl_rc4_set_key(info, key, g_strlen(key));
ssl_rc4_crypt(info, text, sizeof(text) - 1);
ssl_rc4_info_delete(info);
result = bin_to_hex(text, sizeof(text) - 1);
ck_assert(result != NULL);
/* Result should be the same as
* echo -n '<text>' | \
* openssl rc4 -K <hex-key> -e [-provider legacy] | \
* xxd -g0
*
* where <hex-key> is the string above in hexadecimal */
ck_assert_str_eq(result, "c080f175b2d85802dbf1042f07180ddc4be1d9bd4a44158f0aebf11c961b");
g_free(result);
}
END_TEST
START_TEST(test_rc4_enc_tv0_ok)
{
/*
* This is one of the 5 original RC4 test vectors posted in response to
* the 'RC4 Algorithm revealed' sci.crypt usenet posting */
unsigned char key[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef};
unsigned char text[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef};
const char *expected = "75b7878099e0c596";
char *result;
void *info = ssl_rc4_info_create();
ssl_rc4_set_key(info, (char *)key, sizeof(key));
ssl_rc4_crypt(info, (char *)text, sizeof(text));
ssl_rc4_info_delete(info);
result = bin_to_hex((char *)text, sizeof(text));
ck_assert(result != NULL);
ck_assert_str_eq(result, expected);
g_free(result);
}
END_TEST
START_TEST(test_rc4_enc_tv1_ok)
{
/*
* This is one of the 5 original RC4 test vectors posted in response to
* the 'RC4 Algorithm revealed' sci.crypt usenet posting */
unsigned char key[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef};
unsigned char text[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const char *expected = "7494c2e7104b0879";
char *result;
void *info = ssl_rc4_info_create();
ssl_rc4_set_key(info, (char *)key, sizeof(key));
ssl_rc4_crypt(info, (char *)text, sizeof(text));
ssl_rc4_info_delete(info);
result = bin_to_hex((char *)text, sizeof(text));
ck_assert(result != NULL);
ck_assert_str_eq(result, expected);
g_free(result);
}
END_TEST
START_TEST(test_rc4_enc_tv2_ok)
{
/*
* This is one of the 5 original RC4 test vectors posted in response to
* the 'RC4 Algorithm revealed' sci.crypt usenet posting */
unsigned char key[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
unsigned char text[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const char *expected = "de188941a3375d3a";
char *result;
void *info = ssl_rc4_info_create();
ssl_rc4_set_key(info, (char *)key, sizeof(key));
ssl_rc4_crypt(info, (char *)text, sizeof(text));
ssl_rc4_info_delete(info);
result = bin_to_hex((char *)text, sizeof(text));
ck_assert(result != NULL);
ck_assert_str_eq(result, expected);
g_free(result);
}
END_TEST
START_TEST(test_rc4_enc_tv3_ok)
{
/*
* This is one of the 5 original RC4 test vectors posted in response to
* the 'RC4 Algorithm revealed' sci.crypt usenet posting */
unsigned char key[] = {0xef, 0x01, 0x23, 0x45};
unsigned char text[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const char *expected = "d6a141a7ec3c38dfbd61";
char *result;
void *info = ssl_rc4_info_create();
ssl_rc4_set_key(info, (char *)key, sizeof(key));
ssl_rc4_crypt(info, (char *)text, sizeof(text));
ssl_rc4_info_delete(info);
result = bin_to_hex((char *)text, sizeof(text));
ck_assert(result != NULL);
ck_assert_str_eq(result, expected);
g_free(result);
}
END_TEST
START_TEST(test_rc4_enc_tv4_ok)
{
/*
* This is one of the 5 original RC4 test vectors posted in response to
* the 'RC4 Algorithm revealed' sci.crypt usenet posting */
unsigned char key[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef};
unsigned char text[] =
{
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01
};
const char *expected =
"7595c3e6114a09780c4ad452338e1ffd9a1be9498f813d76533449b6778dca"
"d8c78a8d2ba9ac66085d0e53d59c26c2d1c490c1ebbe0ce66d1b6b1b13b6"
"b919b847c25a91447a95e75e4ef16779cde8bf0a95850e32af9689444fd3"
"77108f98fdcbd4e726567500990bcc7e0ca3c4aaa304a387d20f3b8fbbcd"
"42a1bd311d7a4303dda5ab078896ae80c18b0af66dff319616eb784e495a"
"d2ce90d7f772a81747b65f62093b1e0db9e5ba532fafec47508323e67132"
"7df9444432cb7367cec82f5d44c0d00b67d650a075cd4b70dedd77eb9b10"
"231b6b5b741347396d62897421d43df9b42e446e358e9c11a9b2184ecbef"
"0cd8e7a877ef968f1390ec9b3d35a5585cb009290e2fcde7b5ec66d9084b"
"e44055a619d9dd7fc3166f9487f7cb272912426445998514c15d53a18c86"
"4ce3a2b7555793988126520eacf2e3066e230c91bee4dd5304f5fd0405b3"
"5bd99c73135d3d9bc335ee049ef69b3867bf2d7bd1eaa595d8bfc0066ff8"
"d31509eb0c6caa006c807a623ef84c3d33c195d23ee320c40de0558157c8"
"22d4b8c569d849aed59d4e0fd7f379586b4b7ff684ed6a189f7486d49b9c"
"4bad9ba24b96abf924372c8a8fffb10d55354900a77a3db5f205e1b99fcd"
"8660863a159ad4abe40fa48934163ddde542a6585540fd683cbfd8c00f12"
"129a284deacc4cdefe58be7137541c047126c8d49e2755ab181ab7e940b0c0";
char *result;
void *info = ssl_rc4_info_create();
ssl_rc4_set_key(info, (char *)key, sizeof(key));
ssl_rc4_crypt(info, (char *)text, sizeof(text));
ssl_rc4_info_delete(info);
result = bin_to_hex((char *)text, sizeof(text));
ck_assert(result != NULL);
ck_assert_str_eq(result, expected);
g_free(result);
}
END_TEST
START_TEST(test_sha1_hash_ok)
{
const char *hash_string = "xrdp-test-suite-sha1-hash";
char digest[20];
char *result1;
char *result2;
void *info = ssl_sha1_info_create();
ssl_sha1_clear(info);
ssl_sha1_transform(info, hash_string, g_strlen(hash_string));
ssl_sha1_complete(info, digest);
result1 = bin_to_hex(digest, sizeof(digest));
ck_assert(result1 != NULL);
/* Check result with echo -n '<hash_string>' | sha1sum */
ck_assert_str_eq(result1, "3ea0ae84e97e6262c7cfe79ccd7ad2094c06885d");
/* Check a clear has the desired effect */
ssl_sha1_clear(info);
ssl_sha1_transform(info, hash_string, g_strlen(hash_string));
ssl_sha1_complete(info, digest);
result2 = bin_to_hex(digest, sizeof(digest));
ck_assert(result2 != NULL);
ck_assert_str_eq(result1, result2);
ssl_sha1_info_delete(info);
g_free(result1);
g_free(result2);
}
END_TEST
START_TEST(test_md5_hash_ok)
{
const char *hash_string = "xrdp-test-suite-md5-hash";
char digest[16];
char *result1;
char *result2;
void *info = ssl_md5_info_create();
ssl_md5_clear(info);
ssl_md5_transform(info, hash_string, g_strlen(hash_string));
ssl_md5_complete(info, digest);
result1 = bin_to_hex(digest, sizeof(digest));
ck_assert(result1 != NULL);
/* Check result with echo -n '<hash_string>' | md5sum */
ck_assert_str_eq(result1, "ddc599dc7ec62b8f78760b071704c007");
/* Check a clear has the desired effect */
ssl_md5_clear(info);
ssl_md5_transform(info, hash_string, g_strlen(hash_string));
ssl_md5_complete(info, digest);
result2 = bin_to_hex(digest, sizeof(digest));
ck_assert(result2 != NULL);
ck_assert_str_eq(result1, result2);
ssl_md5_info_delete(info);
g_free(result1);
g_free(result2);
}
END_TEST
START_TEST(test_des3_enc_ok)
{
const char *key = "24_byte_key-------------";
char plaintext[] = "xrdp-test-suite-des3-encryption-must-be-multiple-of-8-chars-long--------";
char ciphertext[sizeof(plaintext) - 1]; /* No terminator needed */
char plaintext2[sizeof(plaintext)];
char *result;
void *info = ssl_des3_encrypt_info_create(key, 0);
ssl_des3_encrypt(info, sizeof(plaintext) - 1, plaintext, ciphertext);
ssl_des3_info_delete(info);
result = bin_to_hex(ciphertext, sizeof(ciphertext));
ck_assert(result != NULL);
/* Result should be the same as
* echo -n '<text>' | \
* openssl des3 -iv 0000000000000000 -K <hex-key> -e -nopad | \
* od -t x1
*
* where <hex-key> is the string above in hexadecimal */
ck_assert_str_eq(result,
"856d70861827365e188781616e4f9dcc3009b2c5dc7785edcbc05fa825a4ea5e10b23735c0e971ca20f895f455b8845418963af6dd8e649719790eed6cbcee0fb97b743c60e32e8b");
g_free(result);
/* Let's go back again */
info = ssl_des3_decrypt_info_create(key, 0);
ssl_des3_decrypt(info, sizeof(ciphertext), ciphertext, plaintext2);
ssl_des3_info_delete(info);
plaintext2[sizeof(plaintext2) - 1] = '\0';
ck_assert_str_eq(plaintext, plaintext2);
}
END_TEST
START_TEST(test_hmac_sha1_dgst_ok)
{
const char *key = "20_byte_key---------";
const char *hash_string = "xrdp-test-suite-hmac-sha1-dgst";
char hmac[20];
char *result;
void *info = ssl_hmac_info_create();
ssl_hmac_sha1_init(info, key, g_strlen(key));
ssl_hmac_transform(info, hash_string, g_strlen(hash_string));
ssl_hmac_complete(info, hmac, sizeof(hmac));
ssl_hmac_info_delete(info);
result = bin_to_hex(hmac, sizeof(hmac));
ck_assert(result != NULL);
/* Result should be the same as
* echo -n '<text>' | openssl dgst -sha1 -hmac '<key>'
*
* or:-
*
* echo -n '<text>' | openssl mac -digest sha1 -macopt key:'<key>' hmac
*/
ck_assert_str_eq(result, "af8c04e609e9f3cba53ad7815b60160dc69a9936");
g_free(result);
}
END_TEST
START_TEST(test_gen_key_xrdp1)
{
#define RSA_TEST_BITS 2048
char modulus[RSA_TEST_BITS / 8] = {0};
char private_key[RSA_TEST_BITS / 8] = {0};
unsigned char exponent[4] =
{
0x01, 0x00, 0x01, 0x00 /* 65537 in little-endian format */
};
/*
* We can't do much here because of the nature of the call, but we can
* at least check it completes without error */
int error;
error = ssl_gen_key_xrdp1(RSA_TEST_BITS,
(const char *)exponent, sizeof(exponent),
modulus, sizeof(modulus),
private_key, sizeof(private_key));
ck_assert(error == 0);
/* Both the modulus and the privatekey should be odd */
ck_assert((modulus[0] & 1) == 1);
ck_assert((private_key[0] & 1) == 1);
#undef RSA_TEST_BITS
}
END_TEST
/******************************************************************************/
Suite *
make_suite_test_ssl_calls(void)
{
Suite *s;
TCase *tc_ssl_calls;
s = suite_create("SSL-Calls");
tc_ssl_calls = tcase_create("ssl_calls");
suite_add_tcase(s, tc_ssl_calls);
tcase_add_test(tc_ssl_calls, test_rc4_enc_ok);
tcase_add_test(tc_ssl_calls, test_rc4_enc_tv0_ok);
tcase_add_test(tc_ssl_calls, test_rc4_enc_tv1_ok);
tcase_add_test(tc_ssl_calls, test_rc4_enc_tv2_ok);
tcase_add_test(tc_ssl_calls, test_rc4_enc_tv3_ok);
tcase_add_test(tc_ssl_calls, test_rc4_enc_tv4_ok);
tcase_add_test(tc_ssl_calls, test_sha1_hash_ok);
tcase_add_test(tc_ssl_calls, test_md5_hash_ok);
tcase_add_test(tc_ssl_calls, test_des3_enc_ok);
tcase_add_test(tc_ssl_calls, test_hmac_sha1_dgst_ok);
tcase_add_test(tc_ssl_calls, test_gen_key_xrdp1);
return s;
}

View File

@ -6,6 +6,8 @@ AM_CPPFLAGS = \
LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \ LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \
$(top_srcdir)/tap-driver.sh $(top_srcdir)/tap-driver.sh
PACKAGE_STRING = "libxrdp"
TESTS = test_libxrdp TESTS = test_libxrdp
check_PROGRAMS = test_libxrdp check_PROGRAMS = test_libxrdp

View File

@ -2,6 +2,8 @@
AM_CPPFLAGS = \ AM_CPPFLAGS = \
-I$(top_srcdir)/common -I$(top_srcdir)/common
PACKAGE_STRING = "memtest"
check_PROGRAMS = \ check_PROGRAMS = \
memtest memtest

View File

@ -94,6 +94,7 @@ rfbHashEncryptBytes(char *bytes, const char *passwd)
/* create password hash from password */ /* create password hash from password */
passwd_bytes = g_strlen(passwd); passwd_bytes = g_strlen(passwd);
sha1 = ssl_sha1_info_create(); sha1 = ssl_sha1_info_create();
ssl_sha1_clear(sha1);
ssl_sha1_transform(sha1, "xrdp_vnc", 8); ssl_sha1_transform(sha1, "xrdp_vnc", 8);
ssl_sha1_transform(sha1, passwd, passwd_bytes); ssl_sha1_transform(sha1, passwd, passwd_bytes);
ssl_sha1_transform(sha1, passwd, passwd_bytes); ssl_sha1_transform(sha1, passwd, passwd_bytes);

View File

@ -174,6 +174,7 @@ xrdp_bitmap_hash_crc(struct xrdp_bitmap *self)
return 1; return 1;
} }
hash = ssl_md5_info_create(); hash = ssl_md5_info_create();
ssl_md5_clear(hash);
ssl_md5_transform(hash, self->data, bytes); ssl_md5_transform(hash, self->data, bytes);
ssl_md5_complete(hash, hash_data); ssl_md5_complete(hash, hash_data);
ssl_md5_info_delete(hash); ssl_md5_info_delete(hash);

View File

@ -346,6 +346,7 @@ xrdp_wm_show_edits(struct xrdp_wm *self, struct xrdp_bitmap *combo)
struct xrdp_cfg_globals *globals; struct xrdp_cfg_globals *globals;
char resultIP[256]; char resultIP[256];
char *plain; /* base64 decoded string */ char *plain; /* base64 decoded string */
size_t plain_length; /* length of decoded base64 string */
size_t base64_length; /* length of base64 string */ size_t base64_length; /* length of base64 string */
globals = &self->xrdp_config->cfg_globals; 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); base64_length = g_strlen(value + BASE64PREFIX_LEN);
plain = (char *)g_malloc(base64_length, 0); plain = (char *)g_malloc(base64_length, 0);
base64_decode(plain, value + BASE64PREFIX_LEN, base64_length); base64_decode(value + BASE64PREFIX_LEN,
g_strncpy(value, plain, g_strlen(plain)); plain, base64_length, &plain_length);
g_strncpy(value, plain, plain_length);
g_free(plain); g_free(plain);
} }
else if (g_strncmp(ASK, value, ASK_LEN) == 0) 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); base64_length = g_strlen(value + ASK_LEN + BASE64PREFIX_LEN);
plain = (char *)g_malloc(base64_length, 0); 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_strncpy(b->caption1, plain, 255);
g_free(plain); g_free(plain);
} }