Commit 1b77bac5 authored by Robert Dubner's avatar Robert Dubner
Browse files

Sanitized md4 and utf8_to_ucs2 in radiusov

parent 03f4554e
/* md4.c */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2021 The OpenLDAP Foundation.
* Portions Copyright 2021 Robert Dubner, Symas Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -13,7 +11,7 @@
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*
* The code in this module is largely derived from a public domain source.
* As noted below, portions of this code were derived from public-domain sources
*
*/
......@@ -21,69 +19,6 @@
#include "lber-int.h"
#include "md4.h"
/** Convert UTF8 string to UCS2 encoding
*
* @note Borrowed from src/crypto/ms_funcs.c of wpa_supplicant project (http://hostap.epitest.fi/wpa_supplicant/)
*
* @param[out] out Where to write the ucs2 string.
* @param[in] outlen Size of output buffer.
* @param[in] in UTF8 string to convert.
* @param[in] inlen length of UTF8 string.
* @return the size of the UCS2 string written to the output buffer (in bytes).
*/
ssize_t
utf8_to_ucs2(uint8_t *out, size_t outlen, char const *in, size_t inlen)
{
size_t i;
uint8_t *start = out;
for (i = 0; i < inlen; i++)
{
uint8_t c, c2, c3;
c = in[i];
if ((size_t)(out - start) >= outlen)
{
/* input too long */
return -1;
}
/* One-byte encoding */
if (c <= 0x7f)
{
PUT_LE16(out, c);
out += 2;
continue;
}
else if ((i == (inlen - 1)) || ((size_t)(out - start) >= (outlen - 1)))
{
/* Incomplete surrogate */
return -1;
}
c2 = in[++i];
/* Two-byte encoding */
if ((c & 0xe0) == 0xc0)
{
PUT_LE16(out, ((c & 0x1f) << 6) | (c2 & 0x3f));
out += 2;
continue;
}
if ((i == inlen) || ((size_t)(out - start) >= (outlen - 1)))
{
/* Incomplete surrogate */
return -1;
}
/* Three-byte encoding */
c3 = in[++i];
PUT_LE16(out, ((c & 0xf) << 12) | ((c2 & 0x3f) << 6) | (c3 & 0x3f));
out += 2;
}
return out - start;
}
/** Calculate the MD4 hash of the contents of a buffer
*
* @param[out] out Where to write the MD4 digest. Must be a minimum of MD4_DIGEST_LENGTH.
......
/* md4.h */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2021 The OpenLDAP Foundation.
* Portions Copyright 2021 Robert Dubner, Symas Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
......@@ -13,12 +11,12 @@
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*
* The code in this module is largely derived from a public domain source.
* As noted below, portions of this code were derived from public-domain sources
*
*/
#ifndef _MD4_H
#define _MD4_H
#ifndef _h_MD4_H
#define _h_MD4_H
#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
......@@ -34,10 +32,6 @@
#include <string.h>
#ifdef HAVE_OPENSSL_MD4_H
# include <openssl/md4.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
......@@ -64,8 +58,6 @@ extern "C" {
# define MD4_BLOCK_LENGTH 64
# define MD4_DIGEST_STRING_LENGTH (MD4_DIGEST_LENGTH * 2 + 1)
ssize_t utf8_to_ucs2(uint8_t *out, size_t outlen, char const *in, size_t inlen);
typedef struct MD4Context
{
uint32_t state[4]; //!< State.
......@@ -80,12 +72,6 @@ void md4_transform(uint32_t buf[4], uint8_t const inc[MD4_BLOCK_LENGTH]);
void md4_calc(uint8_t out[MD4_DIGEST_LENGTH], uint8_t const *in, size_t inlen);
#define PUT_LE16(a, val)\
do {\
a[1] = ((uint16_t) (val)) >> 8;\
a[0] = ((uint16_t) (val)) & 0xff;\
} while (0)
#ifdef __cplusplus
}
#endif
......
......@@ -162,7 +162,7 @@ md5_final(uint8_t out[MD5_DIGEST_LENGTH], MD5_CTX *ctx)
for (i = 0; i < 4; i++)
PUT_32BIT_LE(out + i * 4, ctx->state[i]);
}
memset(ctx, 0, sizeof(*ctx)); /* in case it's sensitive */
bzero(ctx, sizeof(MD5_CTX)); /* in case it's sensitive */
}
/* The four core functions - F1 is optimized somewhat */
......
......@@ -43,7 +43,7 @@ SendThePacket( RADIUS_PACKET *response,
GV_packet_count += 1;
Debug( LDAP_DEBUG_ARGS | LDAP_DEBUG_PACKETS | LDAP_DEBUG_CONNS,
DPREFIX "%s(): sending %ld bytes (nominal packet #%d)\n",
DPREFIX "%s(): sending %ld bytes *************************** Nominal packet #%d\n",
__func__,
length,
GV_packet_count);
......@@ -840,6 +840,78 @@ encrypt_and_send_response( STATE *state,
return rc;
}
#define PUT_LE16(a, val)\
do {\
a[1] = ((uint16_t) (val)) >> 8;\
a[0] = ((uint16_t) (val)) & 0xff;\
} while (0)
static ssize_t
utf8_to_ucs2(uint8_t *out, size_t outlen, char const *in, size_t inlen)
{
// We always output UCS2 characters two bytes at a time, so make sure
// our caller called us with an even number as the outlen
outlen &= ~1;
// Converts a UTF8 string into a UCS2 string
size_t i = 0;
uint8_t *start = out;
while(i < inlen)
{
uint8_t c;
uint8_t c2;
uint8_t c3;
if ((size_t)(out - start) >= outlen)
{
// We ran out of room in the destination
return -1;
}
c = in[i++];
if (c <= 0x7f)
{
// This is a single-byte character, just output it as a
// 16-bit little-endian character
PUT_LE16(out, c);
out += 2;
continue;
}
if( i >= inlen )
{
// Odd. We need at least one more character, but the input
// buffer ran out
return -1;
}
c2 = in[i++];
if ((c & 0xe0) == 0xc0)
{
// This is a two-byte character.
PUT_LE16(out, ((c & 0x1f) << 6) | (c2 & 0x3f));
out += 2;
continue;
}
if( i >= inlen )
{
// We need a third character, but we fell off the edge of the input
return -1;
}
/* Three-byte encoding */
c3 = in[i++];
PUT_LE16(out, ((c & 0xf) << 12) | ((c2 & 0x3f) << 6) | (c3 & 0x3f));
out += 2;
}
//ssize_t retval = out - start;
// Return the length, in bytes, of the UCS2-encoded string
return out - start;
}
static int
process_mschap_response(STATE *state)
{
......@@ -976,11 +1048,24 @@ process_mschap_response(STATE *state)
// convert the password to 16-bit Unicode, as required by MS-CHAP:
uint8_t ucs2_password[(MAXIMUM_PASSWORD_CHARACTERS+1)*2];
ssize_t unicode_password_length = utf8_to_ucs2( ucs2_password,
ssize_t unicode_password_length = utf8_to_ucs2(ucs2_password,
sizeof(ucs2_password),
password,
strlen(password));
if( LogTest(LDAP_DEBUG_ARGS) )
{
Debug( LDAP_DEBUG_ARGS,
"%s() password \"%s\" becomes UCS2_PASSWORD length is %ld\n",
__func__,
password,
unicode_password_length);
ber_log_bprint( LDAP_DEBUG_ARGS,
LDAP_DEBUG_ARGS,
(const char *)ucs2_password,
unicode_password_length);
}
// Wipe the cleartext password; we are done with it:
memset( password, 0x00, sizeof(password) );
if( unicode_password_length < 0 )
......
......@@ -498,11 +498,6 @@ radiusov_acceptconn(void *ctx, void *arg)
// }
// fprintf(ltiming, "accept\t%ld\n", Nanoseconds());
DENTER;
GV_packet_count += 1;
Debug( LDAP_DEBUG_ARGS | LDAP_DEBUG_CONNS | LDAP_DEBUG_PACKETS,
DPREFIX "%s(): nominal packet #%d **************************************\n",
__func__,
GV_packet_count);
RADIUS_INFO *radius_info = arg;
......@@ -608,6 +603,12 @@ radiusov_acceptconn(void *ctx, void *arg)
search_method = TEST_AND_DEVELOPMENT;
}
GV_packet_count += 1;
Debug( LDAP_DEBUG_ARGS | LDAP_DEBUG_CONNS | LDAP_DEBUG_PACKETS,
DPREFIX "%s(): ************************************** Nominal packet #%d \n",
__func__,
GV_packet_count);
#if 0
ber_log_bprint( LDAP_DEBUG_ANY,
LDAP_DEBUG_ANY,
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment