Commit a7f65f03 by Edward Thomson

ntlm: add ntlmclient as a dependency

Include https://github.com/ethomson/ntlmclient as a dependency.
parent 79fc8281
...@@ -67,6 +67,10 @@ OPTION(USE_BUNDLED_ZLIB "Use the bundled version of zlib" OFF) ...@@ -67,6 +67,10 @@ OPTION(USE_BUNDLED_ZLIB "Use the bundled version of zlib" OFF)
OPTION(DEPRECATE_HARD "Do not include deprecated functions in the library" OFF) OPTION(DEPRECATE_HARD "Do not include deprecated functions in the library" OFF)
SET(REGEX_BACKEND "" CACHE STRING "Regular expression implementation. One of regcomp_l, pcre2, pcre, regcomp, or builtin.") SET(REGEX_BACKEND "" CACHE STRING "Regular expression implementation. One of regcomp_l, pcre2, pcre, regcomp, or builtin.")
IF (UNIX)
OPTION(USE_NTLMCLIENT "Enable NTLM support on Unix." ON )
ENDIF()
IF (UNIX AND NOT APPLE) IF (UNIX AND NOT APPLE)
OPTION(ENABLE_REPRODUCIBLE_BUILDS "Enable reproducible builds" OFF) OPTION(ENABLE_REPRODUCIBLE_BUILDS "Enable reproducible builds" OFF)
ENDIF() ENDIF()
......
FILE(GLOB SRC_NTLMCLIENT "ntlm.c" "unicode_builtin.c" "util.c")
ADD_DEFINITIONS(-DNTLM_STATIC=1)
IF (HTTPS_BACKEND STREQUAL "SecureTransport")
ADD_DEFINITIONS(-DCRYPT_COMMONCRYPTO)
SET(SRC_NTLMCLIENT_CRYPTO "crypt_commoncrypto.c")
ELSEIF (HTTPS_BACKEND STREQUAL "OpenSSL")
ADD_DEFINITIONS(-DCRYPT_OPENSSL)
SET(SRC_NTLMCLIENT_CRYPTO "crypt_openssl.c")
ELSEIF (HTTPS_BACKEND STREQUAL "mbedTLS")
ADD_DEFINITIONS(-DCRYPT_MBEDTLS)
SET(SRC_NTLMCLIENT_CRYPTO "crypt_mbedtls.c")
ELSE ()
MESSAGE(FATAL_ERROR "Unable to use libgit2's HTTPS backend (${HTTPS_BACKEND}) for NTLM crypto")
ENDIF()
ADD_LIBRARY(ntlmclient OBJECT ${SRC_NTLMCLIENT} ${SRC_NTLMCLIENT_CRYPTO})
/*
* Copyright (c) Edward Thomson. All rights reserved.
*
* This file is part of ntlmclient, distributed under the MIT license.
* For full terms and copyright information, and for third-party
* copyright information, see the included LICENSE.txt file.
*/
#ifndef PRIVATE_COMPAT_H__
#define PRIVATE_COMPAT_H__
#if defined (_MSC_VER)
typedef unsigned char bool;
# ifndef true
# define true 1
# endif
# ifndef false
# define false 0
# endif
#else
# include <stdbool.h>
#endif
#ifdef __linux__
# include <endian.h>
# define htonll htobe64
#endif
#ifndef MIN
# define MIN(x, y) (((x) < (y)) ? (x) : (y))
#endif
#endif /* PRIVATE_COMPAT_H__ */
/*
* Copyright (c) Edward Thomson. All rights reserved.
*
* This file is part of ntlmclient, distributed under the MIT license.
* For full terms and copyright information, and for third-party
* copyright information, see the included LICENSE.txt file.
*/
#ifndef PRIVATE_CRYPT_COMMON_H__
#define PRIVATE_CRYPT_COMMON_H__
#if defined(CRYPT_OPENSSL)
# include "crypt_openssl.h"
#elif defined(CRYPT_MBEDTLS)
# include "crypt_mbedtls.h"
#elif defined(CRYPT_COMMONCRYPTO)
# include "crypt_commoncrypto.h"
#else
# error "no crypto support"
#endif
#define CRYPT_DES_BLOCKSIZE 8
#define CRYPT_MD4_DIGESTSIZE 16
#define CRYPT_MD5_DIGESTSIZE 16
typedef unsigned char ntlm_des_block[CRYPT_DES_BLOCKSIZE];
extern bool ntlm_random_bytes(
ntlm_client *ntlm,
unsigned char *out,
size_t len);
extern bool ntlm_des_encrypt(
ntlm_des_block *out,
ntlm_des_block *plaintext,
ntlm_des_block *key);
extern bool ntlm_md4_digest(
unsigned char out[CRYPT_MD4_DIGESTSIZE],
const unsigned char *in,
size_t in_len);
extern ntlm_hmac_ctx *ntlm_hmac_ctx_init(void);
extern bool ntlm_hmac_ctx_reset(ntlm_hmac_ctx *ctx);
extern bool ntlm_hmac_md5_init(
ntlm_hmac_ctx *ctx,
const unsigned char *key,
size_t key_len);
extern bool ntlm_hmac_md5_update(
ntlm_hmac_ctx *ctx,
const unsigned char *data,
size_t data_len);
extern bool ntlm_hmac_md5_final(
unsigned char *out,
size_t *out_len,
ntlm_hmac_ctx *ctx);
extern void ntlm_hmac_ctx_free(ntlm_hmac_ctx *ctx);
#endif /* PRIVATE_CRYPT_COMMON_H__ */
/*
* Copyright (c) Edward Thomson. All rights reserved.
*
* This file is part of ntlmclient, distributed under the MIT license.
* For full terms and copyright information, and for third-party
* copyright information, see the included LICENSE.txt file.
*/
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <CommonCrypto/CommonCrypto.h>
#include "ntlm.h"
#include "crypt.h"
bool ntlm_random_bytes(
ntlm_client *ntlm,
unsigned char *out,
size_t len)
{
int fd, ret;
size_t total = 0;
if ((fd = open("/dev/urandom", O_RDONLY)) < 0) {
ntlm_client_set_errmsg(ntlm, strerror(errno));
return false;
}
while (total < len) {
if ((ret = read(fd, out, (len - total))) < 0) {
ntlm_client_set_errmsg(ntlm, strerror(errno));
return false;
} else if (ret == 0) {
ntlm_client_set_errmsg(ntlm, "unexpected eof on random device");
return false;
}
total += ret;
}
close(fd);
return true;
}
bool ntlm_des_encrypt(
ntlm_des_block *out,
ntlm_des_block *plaintext,
ntlm_des_block *key)
{
size_t written;
CCCryptorStatus result = CCCrypt(kCCEncrypt,
kCCAlgorithmDES, kCCOptionECBMode,
key, sizeof(ntlm_des_block), NULL,
plaintext, sizeof(ntlm_des_block),
out, sizeof(ntlm_des_block), &written);
return (result == kCCSuccess) ? true : false;
}
bool ntlm_md4_digest(
unsigned char out[CRYPT_MD4_DIGESTSIZE],
const unsigned char *in,
size_t in_len)
{
return !!CC_MD4(in, in_len, out);
}
ntlm_hmac_ctx *ntlm_hmac_ctx_init(void)
{
return calloc(1, sizeof(ntlm_hmac_ctx));
}
bool ntlm_hmac_ctx_reset(ntlm_hmac_ctx *ctx)
{
memset(ctx, 0, sizeof(ntlm_hmac_ctx));
return true;
}
bool ntlm_hmac_md5_init(
ntlm_hmac_ctx *ctx,
const unsigned char *key,
size_t key_len)
{
CCHmacInit(&ctx->native, kCCHmacAlgMD5, key, key_len);
return true;
}
bool ntlm_hmac_md5_update(
ntlm_hmac_ctx *ctx,
const unsigned char *data,
size_t data_len)
{
CCHmacUpdate(&ctx->native, data, data_len);
return true;
}
bool ntlm_hmac_md5_final(
unsigned char *out,
size_t *out_len,
ntlm_hmac_ctx *ctx)
{
if (*out_len < CRYPT_MD5_DIGESTSIZE)
return false;
CCHmacFinal(&ctx->native, out);
*out_len = CRYPT_MD5_DIGESTSIZE;
return true;
}
void ntlm_hmac_ctx_free(ntlm_hmac_ctx *ctx)
{
free(ctx);
}
/*
* Copyright (c) Edward Thomson. All rights reserved.
*
* This file is part of ntlmclient, distributed under the MIT license.
* For full terms and copyright information, and for third-party
* copyright information, see the included LICENSE.txt file.
*/
#ifndef PRIVATE_CRYPT_COMMONCRYPTO_H__
#define PRIVATE_CRYPT_COMMONCRYPTO_H__
#include <CommonCrypto/CommonCrypto.h>
typedef struct {
CCHmacContext native;
} ntlm_hmac_ctx;
#endif /* PRIVATE_CRYPT_COMMONCRYPTO_H__ */
/*
* Copyright (c) Edward Thomson. All rights reserved.
*
* This file is part of ntlmclient, distributed under the MIT license.
* For full terms and copyright information, and for third-party
* copyright information, see the included LICENSE.txt file.
*/
#include <stdlib.h>
#include <string.h>
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/des.h"
#include "mbedtls/entropy.h"
#include "mbedtls/md4.h"
#include "ntlm.h"
#include "crypt.h"
bool ntlm_random_bytes(
ntlm_client *ntlm,
unsigned char *out,
size_t len)
{
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_entropy_context entropy;
bool ret = true;
const unsigned char personalization[] = {
0xec, 0xb5, 0xd1, 0x0b, 0x8f, 0x15, 0x1f, 0xc2,
0xe4, 0x8e, 0xec, 0x36, 0xf7, 0x0a, 0x45, 0x9a,
0x1f, 0xe1, 0x35, 0x58, 0xb1, 0xcb, 0xfd, 0x8a,
0x57, 0x5c, 0x75, 0x7d, 0x2f, 0xc9, 0x70, 0xac
};
mbedtls_ctr_drbg_init(&ctr_drbg);
mbedtls_entropy_init(&entropy);
if (mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func,
&entropy, personalization, sizeof(personalization)) ||
mbedtls_ctr_drbg_random(&ctr_drbg, out, len)) {
ntlm_client_set_errmsg(ntlm, "random generation failed");
ret = false;
}
mbedtls_entropy_free(&entropy);
mbedtls_ctr_drbg_free(&ctr_drbg);
return ret;
}
bool ntlm_des_encrypt(
ntlm_des_block *out,
ntlm_des_block *plaintext,
ntlm_des_block *key)
{
mbedtls_des_context ctx;
bool success = false;
mbedtls_des_init(&ctx);
if (mbedtls_des_setkey_enc(&ctx, *key) ||
mbedtls_des_crypt_ecb(&ctx, *plaintext, *out))
goto done;
success = true;
done:
mbedtls_des_free(&ctx);
return success;
}
bool ntlm_md4_digest(
unsigned char out[CRYPT_MD4_DIGESTSIZE],
const unsigned char *in,
size_t in_len)
{
mbedtls_md4_context ctx;
mbedtls_md4_init(&ctx);
mbedtls_md4_starts(&ctx);
mbedtls_md4_update(&ctx, in, in_len);
mbedtls_md4_finish(&ctx, out);
mbedtls_md4_free(&ctx);
return true;
}
ntlm_hmac_ctx *ntlm_hmac_ctx_init(void)
{
ntlm_hmac_ctx *ctx;
const mbedtls_md_info_t *info = mbedtls_md_info_from_type(MBEDTLS_MD_MD5);
if ((ctx = calloc(1, sizeof(ntlm_hmac_ctx))) == NULL)
return NULL;
mbedtls_md_init(&ctx->mbed);
if (mbedtls_md_setup(&ctx->mbed, info, 1) != 0) {
free(ctx);
return false;
}
return ctx;
}
bool ntlm_hmac_ctx_reset(ntlm_hmac_ctx *ctx)
{
return !mbedtls_md_hmac_reset(&ctx->mbed);
}
bool ntlm_hmac_md5_init(
ntlm_hmac_ctx *ctx,
const unsigned char *key,
size_t key_len)
{
return !mbedtls_md_hmac_starts(&ctx->mbed, key, key_len);
}
bool ntlm_hmac_md5_update(
ntlm_hmac_ctx *ctx,
const unsigned char *in,
size_t in_len)
{
return !mbedtls_md_hmac_update(&ctx->mbed, in, in_len);
}
bool ntlm_hmac_md5_final(
unsigned char *out,
size_t *out_len,
ntlm_hmac_ctx *ctx)
{
if (*out_len < CRYPT_MD5_DIGESTSIZE)
return false;
return !mbedtls_md_hmac_finish(&ctx->mbed, out);
}
void ntlm_hmac_ctx_free(ntlm_hmac_ctx *ctx)
{
if (ctx) {
mbedtls_md_free(&ctx->mbed);
free(ctx);
}
}
/*
* Copyright (c) Edward Thomson. All rights reserved.
*
* This file is part of ntlmclient, distributed under the MIT license.
* For full terms and copyright information, and for third-party
* copyright information, see the included LICENSE.txt file.
*/
#ifndef PRIVATE_CRYPT_MBEDTLS_H__
#define PRIVATE_CRYPT_MBEDTLS_H__
#include "mbedtls/md.h"
typedef struct {
mbedtls_md_context_t mbed;
} ntlm_hmac_ctx;
#endif /* PRIVATE_CRYPT_MBEDTLS_H__ */
/*
* Copyright (c) Edward Thomson. All rights reserved.
*
* This file is part of ntlmclient, distributed under the MIT license.
* For full terms and copyright information, and for third-party
* copyright information, see the included LICENSE.txt file.
*/
#include <stdlib.h>
#include <string.h>
#include <openssl/rand.h>
#include <openssl/des.h>
#include <openssl/md4.h>
#include <openssl/hmac.h>
#include <openssl/err.h>
#include "ntlm.h"
#include "compat.h"
#include "util.h"
#include "crypt.h"
bool ntlm_random_bytes(
ntlm_client *ntlm,
unsigned char *out,
size_t len)
{
int rc = RAND_bytes(out, len);
if (rc != 1) {
ntlm_client_set_errmsg(ntlm, ERR_lib_error_string(ERR_get_error()));
return false;
}
return true;
}
bool ntlm_des_encrypt(
ntlm_des_block *out,
ntlm_des_block *plaintext,
ntlm_des_block *key)
{
DES_key_schedule keysched;
memset(out, 0, sizeof(ntlm_des_block));
DES_set_key(key, &keysched);
DES_ecb_encrypt(plaintext, out, &keysched, DES_ENCRYPT);
return true;
}
bool ntlm_md4_digest(
unsigned char out[CRYPT_MD4_DIGESTSIZE],
const unsigned char *in,
size_t in_len)
{
MD4(in, in_len, out);
return true;
}
#if OPENSSL_VERSION_NUMBER < 0x10100000L
static inline void HMAC_CTX_free(HMAC_CTX *ctx)
{
if (ctx)
HMAC_CTX_cleanup(ctx);
free(ctx);
}
static inline int HMAC_CTX_reset(HMAC_CTX *ctx)
{
HMAC_CTX_cleanup(ctx);
memzero(ctx, sizeof(HMAC_CTX));
return 1;
}
static inline HMAC_CTX *HMAC_CTX_new(void)
{
return calloc(1, sizeof(HMAC_CTX));
}
#endif
ntlm_hmac_ctx *ntlm_hmac_ctx_init(void)
{
return HMAC_CTX_new();
}
bool ntlm_hmac_ctx_reset(ntlm_hmac_ctx *ctx)
{
return HMAC_CTX_reset(ctx);
}
bool ntlm_hmac_md5_init(
ntlm_hmac_ctx *ctx,
const unsigned char *key,
size_t key_len)
{
return HMAC_Init_ex(ctx, key, key_len, EVP_md5(), NULL);
}
bool ntlm_hmac_md5_update(
ntlm_hmac_ctx *ctx,
const unsigned char *in,
size_t in_len)
{
return HMAC_Update(ctx, in, in_len);
}
bool ntlm_hmac_md5_final(
unsigned char *out,
size_t *out_len,
ntlm_hmac_ctx *ctx)
{
unsigned int len;
if (*out_len < CRYPT_MD5_DIGESTSIZE)
return false;
if (!HMAC_Final(ctx, out, &len))
return false;
*out_len = len;
return true;
}
void ntlm_hmac_ctx_free(ntlm_hmac_ctx *ctx)
{
HMAC_CTX_free(ctx);
}
/*
* Copyright (c) Edward Thomson. All rights reserved.
*
* This file is part of ntlmclient, distributed under the MIT license.
* For full terms and copyright information, and for third-party
* copyright information, see the included LICENSE.txt file.
*/
#ifndef PRIVATE_CRYPT_OPENSSL_H__
#define PRIVATE_CRYPT_OPENSSL_H__
#include <openssl/hmac.h>
/* OpenSSL 1.1.0 uses opaque structs, we'll reuse these. */
#if OPENSSL_VERSION_NUMBER < 0x10100000L
typedef struct hmac_ctx_st ntlm_hmac_ctx;
#else
# define ntlm_hmac_ctx HMAC_CTX
#endif
#endif /* PRIVATE_CRYPT_OPENSSL_H__ */
/*
* Copyright (c) Edward Thomson. All rights reserved.
*
* This file is part of ntlmclient, distributed under the MIT license.
* For full terms and copyright information, and for third-party
* copyright information, see the included LICENSE.txt file.
*/
#ifndef PRIVATE_NTLM_H__
#define PRIVATE_NTLM_H__
#include "ntlmclient.h"
#include "unicode.h"
#include "crypt.h"
#include "compat.h"
#define NTLM_LM_RESPONSE_LEN 24
#define NTLM_NTLM_RESPONSE_LEN 24
#define NTLM_NTLM_HASH_LEN 16
#define NTLM_NTLM2_HASH_LEN 16
#define NTLM_SIGNATURE { 'N', 'T', 'L', 'M', 'S', 'S', 'P', 0x00 }
#define NTLM_LM_PLAINTEXT { 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 }
typedef enum {
NTLM_STATE_NEGOTIATE = 0,
NTLM_STATE_CHALLENGE = 1,
NTLM_STATE_RESPONSE = 2,
NTLM_STATE_ERROR = 3,
NTLM_STATE_COMPLETE = 4,
} ntlm_state;
typedef struct {
unsigned char *buf;
size_t pos;
size_t len;
} ntlm_buf;
typedef struct {
uint8_t major;
uint8_t minor;
uint16_t build;
uint32_t reserved;
} ntlm_version;
typedef struct {
uint32_t flags;
uint64_t nonce;
ntlm_version target_version;
/* The unparsed target information from the server */
unsigned char *target_info;
size_t target_info_len;
/* The target information parsed into usable strings */
char *target;
char *target_server;
char *target_domain;
char *target_server_dns;
char *target_domain_dns;
} ntlm_challenge;
struct ntlm_client {
ntlm_client_flags flags;
ntlm_state state;
/* crypto contexts */
ntlm_hmac_ctx *hmac_ctx;
ntlm_unicode_ctx *unicode_ctx;
/* error message as set by the library */
const char *errmsg;
char *hostname;
char *hostdomain;
ntlm_version host_version;
char *target;
char *username;
char *username_upper;
char *userdomain;
char *password;
/* strings as converted to utf16 */
char *target_utf16;
char *username_utf16;
char *username_upper_utf16;
char *userdomain_utf16;
char *hostname_utf16;
char *password_utf16;
/* timestamp and nonce; only for debugging */
uint64_t nonce;
uint64_t timestamp;
size_t username_utf16_len;
size_t username_upper_utf16_len;
size_t userdomain_utf16_len;
size_t hostname_utf16_len;
size_t password_utf16_len;
size_t target_utf16_len;
unsigned char lm_response[NTLM_LM_RESPONSE_LEN];
size_t lm_response_len;
unsigned char ntlm_response[NTLM_NTLM_RESPONSE_LEN];
size_t ntlm_response_len;
unsigned char *ntlm2_response;
size_t ntlm2_response_len;
ntlm_buf negotiate;
ntlm_challenge challenge;
ntlm_buf response;
};
typedef enum {
NTLM_ENABLE_HOSTVERSION = (1 << 31),
} ntlm_client_internal_flags;
typedef enum {
NTLM_TARGET_INFO_END = 0,
NTLM_TARGET_INFO_SERVER = 1,
NTLM_TARGET_INFO_DOMAIN = 2,
NTLM_TARGET_INFO_SERVER_DNS = 3,
NTLM_TARGET_INFO_DOMAIN_DNS = 4,
} ntlm_target_info_type_t;
typedef enum {
/* Unicode strings are supported in security buffers */
NTLM_NEGOTIATE_UNICODE = 0x00000001,
/* OEM (ANSI) strings are supported in security buffers */
NTLM_NEGOTIATE_OEM = 0x00000002,
/* Request the target realm from the server */
NTLM_NEGOTIATE_REQUEST_TARGET = 0x00000004,
/* NTLM authentication is supported */
NTLM_NEGOTIATE_NTLM = 0x00000200,
/* Negotiate domain name */
NTLM_NEGOTIATE_DOMAIN_SUPPLIED = 0x00001000,
/* Negotiate workstation (client) name */
NTLM_NEGOTIATE_WORKSTATION_SUPPLIED = 0x00002000,
/* Indicates that a local context is available */
NTLM_NEGOTIATE_LOCAL_CALL = 0x00004000,
/* Request a dummy signature */
NTLM_NEGOTIATE_ALWAYS_SIGN = 0x00008000,
/* Target (server) is a domain */
NTLM_NEGOTIATE_TYPE_DOMAIN = 0x00010000,
/* NTLM2 signing and sealing is supported */
NTLM_NEGOTIATE_NTLM2_SIGN_AND_SEAL = 0x00080000,
/* A target information block is included */
NTLM_NEGOTIATE_TARGET_INFO = 0x00800000,
/* Version information should be provided */
NTLM_NEGOTIATE_VERSION = 0x01000000,
} ntlm_negotiate_t;
extern int ntlm_client_set_nonce(ntlm_client *ntlm, uint64_t nonce);
extern int ntlm_client_set_timestamp(ntlm_client *ntlm, uint64_t timestamp);
extern void ntlm_client_set_errmsg(ntlm_client *ntlm, const char *errmsg);
#endif /* PRIVATE_NTLM_H__ */
/*
* Copyright (c) Edward Thomson. All rights reserved.
*
* This file is part of ntlmclient, distributed under the MIT license.
* For full terms and copyright information, and for third-party
* copyright information, see the included LICENSE.txt file.
*/
#ifndef PRIVATE_UNICODE_H__
#define PRIVATE_UNICODE_H__
#include "compat.h"
#define NTLM_UNICODE_MAX_LEN 2048
typedef struct ntlm_unicode_ctx ntlm_unicode_ctx;
extern ntlm_unicode_ctx *ntlm_unicode_ctx_init(ntlm_client *ntlm);
bool ntlm_unicode_utf8_to_16(
char **converted,
size_t *converted_len,
ntlm_unicode_ctx *ctx,
const char *string,
size_t string_len);
bool ntlm_unicode_utf16_to_8(
char **converted,
size_t *converted_len,
ntlm_unicode_ctx *ctx,
const char *string,
size_t string_len);
extern void ntlm_unicode_ctx_free(ntlm_unicode_ctx *ctx);
#endif /* PRIVATE_UNICODE_H__ */
/*
* Copyright (c) Edward Thomson. All rights reserved.
*
* This file is part of ntlmclient, distributed under the MIT license.
* For full terms and copyright information, and for third-party
* copyright information, see the included LICENSE.txt file.
*/
#include <locale.h>
#include <iconv.h>
#include <string.h>
#include <errno.h>
#include "ntlmclient.h"
#include "unicode.h"
#include "ntlm.h"
#include "compat.h"
struct ntlm_unicode_ctx {
ntlm_client *ntlm;
iconv_t utf8_to_16;
iconv_t utf16_to_8;
};
ntlm_unicode_ctx *ntlm_unicode_ctx_init(ntlm_client *ntlm)
{
ntlm_unicode_ctx *ctx;
if ((ctx = calloc(1, sizeof(ntlm_unicode_ctx))) == NULL)
return NULL;
ctx->ntlm = ntlm;
ctx->utf8_to_16 = (iconv_t)-1;
ctx->utf16_to_8 = (iconv_t)-1;
return ctx;
}
typedef enum {
unicode_iconv_utf8_to_16,
unicode_iconv_utf16_to_8
} unicode_iconv_encoding_direction;
static inline bool unicode_iconv_init(ntlm_unicode_ctx *ctx)
{
if (ctx->utf8_to_16 != (iconv_t)-1 || ctx->utf16_to_8 != (iconv_t)-1)
return true;
if ((ctx->utf8_to_16 = iconv_open("UTF-16LE", "UTF-8")) == (iconv_t)-1 ||
(ctx->utf16_to_8 = iconv_open("UTF-8", "UTF-16LE")) == (iconv_t)-1) {
if (errno == EINVAL)
ntlm_client_set_errmsg(ctx->ntlm,
"iconv does not support UTF8 <-> UTF16 conversion");
else
ntlm_client_set_errmsg(ctx->ntlm, strerror(errno));
return false;
}
return true;
}
static inline bool unicode_iconv_encoding_convert(
char **converted,
size_t *converted_len,
ntlm_unicode_ctx *ctx,
const char *string,
size_t string_len,
unicode_iconv_encoding_direction direction)
{
char *in_start, *out_start, *out, *new_out;
size_t in_start_len, out_start_len, out_size, nul_size, ret, written = 0;
iconv_t converter;
*converted = NULL;
*converted_len = 0;
if (!unicode_iconv_init(ctx))
return false;
/*
* When translating UTF8 to UTF16, these strings are only used
* internally, and we obey the given length, so we can simply
* use a buffer that is 2x the size. When translating from UTF16
* to UTF8, we may need to return to callers, so we need to NUL
* terminate and expect an extra byte for UTF8, two for UTF16.
*/
if (direction == unicode_iconv_utf8_to_16) {
converter = ctx->utf8_to_16;
out_size = (string_len * 2) + 2;
nul_size = 2;
} else {
converter = ctx->utf16_to_8;
out_size = (string_len / 2) + 1;
nul_size = 1;
}
/* Round to the nearest multiple of 8 */
out_size = (out_size + 7) & ~7;
if ((out = malloc(out_size)) == NULL) {
ntlm_client_set_errmsg(ctx->ntlm, "out of memory");
return false;
}
in_start = (char *)string;
in_start_len = string_len;
while (true) {
out_start = out + written;
out_start_len = (out_size - nul_size) - written;
ret = iconv(converter, &in_start, &in_start_len, &out_start, &out_start_len);
written = (out_size - nul_size) - out_start_len;
if (ret == 0)
break;
if (ret == (size_t)-1 && errno != E2BIG) {
ntlm_client_set_errmsg(ctx->ntlm, strerror(errno));
goto on_error;
}
/* Grow buffer size by 1.5 (rounded up to a multiple of 8) */
out_size = ((((out_size << 1) - (out_size >> 1)) + 7) & ~7);
if (out_size > NTLM_UNICODE_MAX_LEN) {
ntlm_client_set_errmsg(ctx->ntlm,
"unicode conversion too large");
goto on_error;
}
if ((new_out = realloc(out, out_size)) == NULL) {
ntlm_client_set_errmsg(ctx->ntlm, "out of memory");
goto on_error;
}
out = new_out;
}
if (in_start_len != 0) {
ntlm_client_set_errmsg(ctx->ntlm,
"invalid unicode string; trailing data remains");
goto on_error;
}
/* NUL terminate */
out[written] = '\0';
if (direction == unicode_iconv_utf8_to_16)
out[written + 1] = '\0';
*converted = out;
if (converted_len)
*converted_len = written;
return true;
on_error:
free(out);
return false;
}
bool ntlm_unicode_utf8_to_16(
char **converted,
size_t *converted_len,
ntlm_unicode_ctx *ctx,
const char *string,
size_t string_len)
{
return unicode_iconv_encoding_convert(
converted, converted_len, ctx, string, string_len,
unicode_iconv_utf8_to_16);
}
bool ntlm_unicode_utf16_to_8(
char **converted,
size_t *converted_len,
ntlm_unicode_ctx *ctx,
const char *string,
size_t string_len)
{
return unicode_iconv_encoding_convert(
converted, converted_len, ctx, string, string_len,
unicode_iconv_utf16_to_8);
}
void ntlm_unicode_ctx_free(ntlm_unicode_ctx *ctx)
{
if (!ctx)
return;
if (ctx->utf16_to_8 != (iconv_t)-1)
iconv_close(ctx->utf16_to_8);
if (ctx->utf8_to_16 != (iconv_t)-1)
iconv_close(ctx->utf8_to_16);
free(ctx);
}
/*
* Copyright (c) Edward Thomson. All rights reserved.
*
* This file is part of ntlmclient, distributed under the MIT license.
* For full terms and copyright information, and for third-party
* copyright information, see the included LICENSE.txt file.
*/
#include <stdlib.h>
#include <stdint.h>
#include "compat.h"
#include "util.h"
void memzero(void *data, size_t size)
{
volatile uint8_t *scan = (volatile uint8_t *)data;
while (size--)
*scan++ = 0x0;
}
/*
* Copyright (c) Edward Thomson. All rights reserved.
*
* This file is part of ntlmclient, distributed under the MIT license.
* For full terms and copyright information, and for third-party
* copyright information, see the included LICENSE.txt file.
*/
#ifndef PRIVATE_UTIL_H__
#define PRIVATE_UTIL_H__
extern void memzero(void *data, size_t size);
#endif /* PRIVATE_UTIL_H__ */
...@@ -396,6 +396,15 @@ ELSE() ...@@ -396,6 +396,15 @@ ELSE()
ENDIF() ENDIF()
ADD_FEATURE_INFO(SSH GIT_SSH "SSH transport support") ADD_FEATURE_INFO(SSH GIT_SSH "SSH transport support")
# Optional external dependency: ntlmclient
IF (USE_NTLMCLIENT)
SET(GIT_NTLM 1)
ADD_SUBDIRECTORY("${libgit2_SOURCE_DIR}/deps/ntlmclient" "${libgit2_BINARY_DIR}/deps/ntlmclient")
LIST(APPEND LIBGIT2_INCLUDES "${libgit2_SOURCE_DIR}/deps/ntlmclient")
LIST(APPEND LIBGIT2_OBJECTS "$<TARGET_OBJECTS:ntlmclient>")
ENDIF()
ADD_FEATURE_INFO(ntlmclient GIT_NTLM "NTLM authentication support for Unix")
# Optional external dependency: libgssapi # Optional external dependency: libgssapi
IF (USE_GSSAPI) IF (USE_GSSAPI)
FIND_PACKAGE(GSSAPI) FIND_PACKAGE(GSSAPI)
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#cmakedefine GIT_GSSAPI 1 #cmakedefine GIT_GSSAPI 1
#cmakedefine GIT_WINHTTP 1 #cmakedefine GIT_WINHTTP 1
#cmakedefine GIT_NTLM 1
#cmakedefine GIT_HTTPS 1 #cmakedefine GIT_HTTPS 1
#cmakedefine GIT_OPENSSL 1 #cmakedefine GIT_OPENSSL 1
......
Markdown is supported
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