From 5158b0b70ade89268b22b7c388802b5f5b6debce Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Tue, 24 Aug 2021 11:56:22 -0400 Subject: ntlmclient: update to ntlmclient 0.9.1 The ntlmclient dependency can now dynamically load OpenSSL. --- deps/ntlmclient/CMakeLists.txt | 22 ++- deps/ntlmclient/crypt.h | 23 +-- deps/ntlmclient/crypt_commoncrypto.c | 40 +++--- deps/ntlmclient/crypt_commoncrypto.h | 6 +- deps/ntlmclient/crypt_mbedtls.c | 73 +++++----- deps/ntlmclient/crypt_mbedtls.h | 7 +- deps/ntlmclient/crypt_openssl.c | 229 +++++++++++++++++++++++------- deps/ntlmclient/crypt_openssl.h | 79 ++++++++++- deps/ntlmclient/ntlm.c | 268 ++++++++++++++++++++--------------- deps/ntlmclient/ntlm.h | 22 +-- deps/ntlmclient/ntlmclient.h | 19 ++- deps/ntlmclient/unicode.h | 14 +- deps/ntlmclient/unicode_builtin.c | 43 +++--- deps/ntlmclient/unicode_builtin.h | 20 +++ deps/ntlmclient/unicode_iconv.c | 80 ++++------- deps/ntlmclient/unicode_iconv.h | 22 +++ 16 files changed, 622 insertions(+), 345 deletions(-) create mode 100644 deps/ntlmclient/unicode_builtin.h create mode 100644 deps/ntlmclient/unicode_iconv.h (limited to 'deps') diff --git a/deps/ntlmclient/CMakeLists.txt b/deps/ntlmclient/CMakeLists.txt index d933f4919..3e0d2c817 100644 --- a/deps/ntlmclient/CMakeLists.txt +++ b/deps/ntlmclient/CMakeLists.txt @@ -1,25 +1,37 @@ -FILE(GLOB SRC_NTLMCLIENT "ntlm.c" "unicode_builtin.c" "util.c") +FILE(GLOB SRC_NTLMCLIENT "ntlm.c" "ntlm.h" "util.c" "util.h") LIST(SORT SRC_NTLMCLIENT) ADD_DEFINITIONS(-DNTLM_STATIC=1) DISABLE_WARNINGS(implicit-fallthrough) +IF(USE_ICONV) + ADD_DEFINITIONS(-DUNICODE_ICONV=1) + FILE(GLOB SRC_NTLMCLIENT_UNICODE "unicode_iconv.c" "unicode_iconv.h") +ELSE() + ADD_DEFINITIONS(-DUNICODE_BUILTIN=1) + FILE(GLOB SRC_NTLMCLIENT_UNICODE "unicode_builtin.c" "unicode_builtin.h") +ENDIF() + IF(USE_HTTPS STREQUAL "SecureTransport") ADD_DEFINITIONS(-DCRYPT_COMMONCRYPTO) - SET(SRC_NTLMCLIENT_CRYPTO "crypt_commoncrypto.c") + SET(SRC_NTLMCLIENT_CRYPTO "crypt_commoncrypto.c" "crypt_commoncrypto.h") # CC_MD4 has been deprecated in macOS 10.15. SET_SOURCE_FILES_PROPERTIES("crypt_commoncrypto.c" COMPILE_FLAGS "-Wno-deprecated") ELSEIF(USE_HTTPS STREQUAL "OpenSSL") ADD_DEFINITIONS(-DCRYPT_OPENSSL) INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR}) - SET(SRC_NTLMCLIENT_CRYPTO "crypt_openssl.c") + SET(SRC_NTLMCLIENT_CRYPTO "crypt_openssl.c" "crypt_openssl.h") +ELSEIF(USE_HTTPS STREQUAL "OpenSSL-Dynamic") + ADD_DEFINITIONS(-DCRYPT_OPENSSL) + ADD_DEFINITIONS(-DCRYPT_OPENSSL_DYNAMIC) + SET(SRC_NTLMCLIENT_CRYPTO "crypt_openssl.c" "crypt_openssl.h") ELSEIF(USE_HTTPS STREQUAL "mbedTLS") ADD_DEFINITIONS(-DCRYPT_MBEDTLS) INCLUDE_DIRECTORIES(${MBEDTLS_INCLUDE_DIR}) - SET(SRC_NTLMCLIENT_CRYPTO "crypt_mbedtls.c") + SET(SRC_NTLMCLIENT_CRYPTO "crypt_mbedtls.c" "crypt_mbedtls.h") ELSE() MESSAGE(FATAL_ERROR "Unable to use libgit2's HTTPS backend (${USE_HTTPS}) for NTLM crypto") ENDIF() -ADD_LIBRARY(ntlmclient OBJECT ${SRC_NTLMCLIENT} ${SRC_NTLMCLIENT_CRYPTO}) +ADD_LIBRARY(ntlmclient OBJECT ${SRC_NTLMCLIENT} ${SRC_NTLMCLIENT_UNICODE} ${SRC_NTLMCLIENT_CRYPTO}) diff --git a/deps/ntlmclient/crypt.h b/deps/ntlmclient/crypt.h index 48be39946..4ad543ef7 100644 --- a/deps/ntlmclient/crypt.h +++ b/deps/ntlmclient/crypt.h @@ -9,6 +9,9 @@ #ifndef PRIVATE_CRYPT_COMMON_H__ #define PRIVATE_CRYPT_COMMON_H__ +#include "ntlmclient.h" +#include "ntlm.h" + #if defined(CRYPT_OPENSSL) # include "crypt_openssl.h" #elif defined(CRYPT_MBEDTLS) @@ -25,40 +28,42 @@ typedef unsigned char ntlm_des_block[CRYPT_DES_BLOCKSIZE]; +typedef struct ntlm_crypt_ctx ntlm_crypt_ctx; + +extern bool ntlm_crypt_init(ntlm_client *ntlm); + extern bool ntlm_random_bytes( - ntlm_client *ntlm, unsigned char *out, + ntlm_client *ntlm, size_t len); extern bool ntlm_des_encrypt( ntlm_des_block *out, + ntlm_client *ntlm, ntlm_des_block *plaintext, ntlm_des_block *key); extern bool ntlm_md4_digest( unsigned char out[CRYPT_MD4_DIGESTSIZE], + ntlm_client *ntlm, 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, + ntlm_client *ntlm, const unsigned char *key, size_t key_len); extern bool ntlm_hmac_md5_update( - ntlm_hmac_ctx *ctx, + ntlm_client *ntlm, 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); + ntlm_client *ntlm); -extern void ntlm_hmac_ctx_free(ntlm_hmac_ctx *ctx); +extern void ntlm_crypt_shutdown(ntlm_client *ntlm); #endif /* PRIVATE_CRYPT_COMMON_H__ */ diff --git a/deps/ntlmclient/crypt_commoncrypto.c b/deps/ntlmclient/crypt_commoncrypto.c index 54a0f097b..4ff57edd2 100644 --- a/deps/ntlmclient/crypt_commoncrypto.c +++ b/deps/ntlmclient/crypt_commoncrypto.c @@ -18,9 +18,15 @@ #include "ntlm.h" #include "crypt.h" +bool ntlm_crypt_init(ntlm_client *ntlm) +{ + memset(&ntlm->crypt_ctx, 0, sizeof(ntlm_crypt_ctx)); + return true; +} + bool ntlm_random_bytes( - ntlm_client *ntlm, unsigned char *out, + ntlm_client *ntlm, size_t len) { int fd, ret; @@ -49,11 +55,14 @@ bool ntlm_random_bytes( bool ntlm_des_encrypt( ntlm_des_block *out, + ntlm_client *ntlm, ntlm_des_block *plaintext, ntlm_des_block *key) { size_t written; + NTLM_UNUSED(ntlm); + CCCryptorStatus result = CCCrypt(kCCEncrypt, kCCAlgorithmDES, kCCOptionECBMode, key, sizeof(ntlm_des_block), NULL, @@ -65,56 +74,47 @@ bool ntlm_des_encrypt( bool ntlm_md4_digest( unsigned char out[CRYPT_MD4_DIGESTSIZE], + ntlm_client *ntlm, const unsigned char *in, size_t in_len) { + NTLM_UNUSED(ntlm); 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, + ntlm_client *ntlm, const unsigned char *key, size_t key_len) { - CCHmacInit(&ctx->native, kCCHmacAlgMD5, key, key_len); + CCHmacInit(&ntlm->crypt_ctx.hmac, kCCHmacAlgMD5, key, key_len); return true; } bool ntlm_hmac_md5_update( - ntlm_hmac_ctx *ctx, + ntlm_client *ntlm, const unsigned char *data, size_t data_len) { - CCHmacUpdate(&ctx->native, data, data_len); + CCHmacUpdate(&ntlm->crypt_ctx.hmac, data, data_len); return true; } bool ntlm_hmac_md5_final( unsigned char *out, size_t *out_len, - ntlm_hmac_ctx *ctx) + ntlm_client *ntlm) { if (*out_len < CRYPT_MD5_DIGESTSIZE) return false; - CCHmacFinal(&ctx->native, out); + CCHmacFinal(&ntlm->crypt_ctx.hmac, out); *out_len = CRYPT_MD5_DIGESTSIZE; return true; } -void ntlm_hmac_ctx_free(ntlm_hmac_ctx *ctx) +void ntlm_crypt_shutdown(ntlm_client *ntlm) { - free(ctx); + NTLM_UNUSED(ntlm); } diff --git a/deps/ntlmclient/crypt_commoncrypto.h b/deps/ntlmclient/crypt_commoncrypto.h index e4075c9f6..e4df91d29 100644 --- a/deps/ntlmclient/crypt_commoncrypto.h +++ b/deps/ntlmclient/crypt_commoncrypto.h @@ -11,8 +11,8 @@ #include -typedef struct { - CCHmacContext native; -} ntlm_hmac_ctx; +struct ntlm_crypt_ctx { + CCHmacContext hmac; +}; #endif /* PRIVATE_CRYPT_COMMONCRYPTO_H__ */ diff --git a/deps/ntlmclient/crypt_mbedtls.c b/deps/ntlmclient/crypt_mbedtls.c index bbab02d7d..6283c3eec 100644 --- a/deps/ntlmclient/crypt_mbedtls.c +++ b/deps/ntlmclient/crypt_mbedtls.c @@ -17,9 +17,24 @@ #include "ntlm.h" #include "crypt.h" +bool ntlm_crypt_init(ntlm_client *ntlm) +{ + const mbedtls_md_info_t *info = mbedtls_md_info_from_type(MBEDTLS_MD_MD5); + + mbedtls_md_init(&ntlm->crypt_ctx.hmac); + + if (mbedtls_md_setup(&ntlm->crypt_ctx.hmac, info, 1) != 0) { + ntlm_client_set_errmsg(ntlm, "could not setup mbedtls digest"); + return false; + } + + return true; +} + + bool ntlm_random_bytes( - ntlm_client *ntlm, unsigned char *out, + ntlm_client *ntlm, size_t len) { mbedtls_ctr_drbg_context ctr_drbg; @@ -51,6 +66,7 @@ bool ntlm_random_bytes( bool ntlm_des_encrypt( ntlm_des_block *out, + ntlm_client *ntlm, ntlm_des_block *plaintext, ntlm_des_block *key) { @@ -60,8 +76,10 @@ bool ntlm_des_encrypt( mbedtls_des_init(&ctx); if (mbedtls_des_setkey_enc(&ctx, *key) || - mbedtls_des_crypt_ecb(&ctx, *plaintext, *out)) + mbedtls_des_crypt_ecb(&ctx, *plaintext, *out)) { + ntlm_client_set_errmsg(ntlm, "DES encryption failed"); goto done; + } success = true; @@ -72,11 +90,14 @@ done: bool ntlm_md4_digest( unsigned char out[CRYPT_MD4_DIGESTSIZE], + ntlm_client *ntlm, const unsigned char *in, size_t in_len) { mbedtls_md4_context ctx; + NTLM_UNUSED(ntlm); + mbedtls_md4_init(&ctx); mbedtls_md4_starts(&ctx); mbedtls_md4_update(&ctx, in, in_len); @@ -86,60 +107,40 @@ bool ntlm_md4_digest( 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, + ntlm_client *ntlm, const unsigned char *key, size_t key_len) { - return !mbedtls_md_hmac_starts(&ctx->mbed, key, key_len); + if (ntlm->crypt_ctx.hmac_initialized) { + if (mbedtls_md_hmac_reset(&ntlm->crypt_ctx.hmac)) + return false; + } + + ntlm->crypt_ctx.hmac_initialized = !mbedtls_md_hmac_starts(&ntlm->crypt_ctx.hmac, key, key_len); + return ntlm->crypt_ctx.hmac_initialized; } bool ntlm_hmac_md5_update( - ntlm_hmac_ctx *ctx, + ntlm_client *ntlm, const unsigned char *in, size_t in_len) { - return !mbedtls_md_hmac_update(&ctx->mbed, in, in_len); + return !mbedtls_md_hmac_update(&ntlm->crypt_ctx.hmac, in, in_len); } bool ntlm_hmac_md5_final( unsigned char *out, size_t *out_len, - ntlm_hmac_ctx *ctx) + ntlm_client *ntlm) { if (*out_len < CRYPT_MD5_DIGESTSIZE) return false; - return !mbedtls_md_hmac_finish(&ctx->mbed, out); + return !mbedtls_md_hmac_finish(&ntlm->crypt_ctx.hmac, out); } -void ntlm_hmac_ctx_free(ntlm_hmac_ctx *ctx) +void ntlm_crypt_shutdown(ntlm_client *ntlm) { - if (ctx) { - mbedtls_md_free(&ctx->mbed); - free(ctx); - } + mbedtls_md_free(&ntlm->crypt_ctx.hmac); } diff --git a/deps/ntlmclient/crypt_mbedtls.h b/deps/ntlmclient/crypt_mbedtls.h index eb49a4596..2fc85035d 100644 --- a/deps/ntlmclient/crypt_mbedtls.h +++ b/deps/ntlmclient/crypt_mbedtls.h @@ -11,8 +11,9 @@ #include "mbedtls/md.h" -typedef struct { - mbedtls_md_context_t mbed; -} ntlm_hmac_ctx; +struct ntlm_crypt_ctx { + mbedtls_md_context_t hmac; + unsigned int hmac_initialized : 1; +}; #endif /* PRIVATE_CRYPT_MBEDTLS_H__ */ diff --git a/deps/ntlmclient/crypt_openssl.c b/deps/ntlmclient/crypt_openssl.c index c0d36d891..463eae4f8 100644 --- a/deps/ntlmclient/crypt_openssl.c +++ b/deps/ntlmclient/crypt_openssl.c @@ -9,26 +9,166 @@ #include #include -#include -#include -#include -#include -#include +#ifdef CRYPT_OPENSSL_DYNAMIC +# include +#else +# include +# include +# include +# include +# include +#endif #include "ntlm.h" #include "compat.h" #include "util.h" #include "crypt.h" +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(CRYPT_OPENSSL_DYNAMIC) + +static inline HMAC_CTX *HMAC_CTX_new(void) +{ + return calloc(1, sizeof(HMAC_CTX)); +} + +static inline int HMAC_CTX_reset(HMAC_CTX *ctx) +{ + ntlm_memzero(ctx, sizeof(HMAC_CTX)); + return 1; +} + +static inline void HMAC_CTX_free(HMAC_CTX *ctx) +{ + free(ctx); +} + +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(CRYPT_OPENSSL_DYNAMIC) + +static inline void HMAC_CTX_cleanup(HMAC_CTX *ctx) +{ + NTLM_UNUSED(ctx); +} + +#endif + + +#ifdef CRYPT_OPENSSL_DYNAMIC + +static bool ntlm_crypt_init_functions(ntlm_client *ntlm) +{ + void *handle; + + if ((handle = dlopen("libssl.so.1.1", RTLD_NOW)) == NULL && + (handle = dlopen("libssl.1.1.dylib", RTLD_NOW)) == NULL && + (handle = dlopen("libssl.so.1.0.0", RTLD_NOW)) == NULL && + (handle = dlopen("libssl.1.0.0.dylib", RTLD_NOW)) == NULL && + (handle = dlopen("libssl.so.10", RTLD_NOW)) == NULL) { + ntlm_client_set_errmsg(ntlm, "could not open libssl"); + return false; + } + + ntlm->crypt_ctx.des_set_key_fn = dlsym(handle, "DES_set_key"); + ntlm->crypt_ctx.des_ecb_encrypt_fn = dlsym(handle, "DES_ecb_encrypt"); + ntlm->crypt_ctx.err_get_error_fn = dlsym(handle, "ERR_get_error"); + ntlm->crypt_ctx.err_lib_error_string_fn = dlsym(handle, "ERR_lib_error_string"); + ntlm->crypt_ctx.evp_md5_fn = dlsym(handle, "EVP_md5"); + ntlm->crypt_ctx.hmac_ctx_new_fn = dlsym(handle, "HMAC_CTX_new"); + ntlm->crypt_ctx.hmac_ctx_free_fn = dlsym(handle, "HMAC_CTX_free"); + ntlm->crypt_ctx.hmac_ctx_reset_fn = dlsym(handle, "HMAC_CTX_reset"); + ntlm->crypt_ctx.hmac_init_ex_fn = dlsym(handle, "HMAC_Init_ex"); + ntlm->crypt_ctx.hmac_update_fn = dlsym(handle, "HMAC_Update"); + ntlm->crypt_ctx.hmac_final_fn = dlsym(handle, "HMAC_Final"); + ntlm->crypt_ctx.md4_fn = dlsym(handle, "MD4"); + ntlm->crypt_ctx.rand_bytes_fn = dlsym(handle, "RAND_bytes"); + + if (!ntlm->crypt_ctx.des_set_key_fn || + !ntlm->crypt_ctx.des_ecb_encrypt_fn || + !ntlm->crypt_ctx.err_get_error_fn || + !ntlm->crypt_ctx.err_lib_error_string_fn || + !ntlm->crypt_ctx.evp_md5_fn || + !ntlm->crypt_ctx.hmac_init_ex_fn || + !ntlm->crypt_ctx.hmac_update_fn || + !ntlm->crypt_ctx.hmac_final_fn || + !ntlm->crypt_ctx.md4_fn || + !ntlm->crypt_ctx.rand_bytes_fn) { + ntlm_client_set_errmsg(ntlm, "could not load libssl functions"); + dlclose(handle); + return false; + } + + /* Toggle legacy HMAC context functions */ + if (ntlm->crypt_ctx.hmac_ctx_new_fn && + ntlm->crypt_ctx.hmac_ctx_free_fn && + ntlm->crypt_ctx.hmac_ctx_reset_fn) { + ntlm->crypt_ctx.hmac_ctx_cleanup_fn = HMAC_CTX_cleanup; + } else { + ntlm->crypt_ctx.hmac_ctx_cleanup_fn = dlsym(handle, "HMAC_CTX_cleanup"); + + if (!ntlm->crypt_ctx.hmac_ctx_cleanup_fn) { + ntlm_client_set_errmsg(ntlm, "could not load legacy libssl functions"); + dlclose(handle); + return false; + } + + ntlm->crypt_ctx.hmac_ctx_new_fn = HMAC_CTX_new; + ntlm->crypt_ctx.hmac_ctx_free_fn = HMAC_CTX_free; + ntlm->crypt_ctx.hmac_ctx_reset_fn = HMAC_CTX_reset; + } + + ntlm->crypt_ctx.openssl_handle = handle; + return true; +} + +#else /* CRYPT_OPENSSL_DYNAMIC */ + +static bool ntlm_crypt_init_functions(ntlm_client *ntlm) +{ + ntlm->crypt_ctx.des_set_key_fn = DES_set_key; + ntlm->crypt_ctx.des_ecb_encrypt_fn = DES_ecb_encrypt; + ntlm->crypt_ctx.err_get_error_fn = ERR_get_error; + ntlm->crypt_ctx.err_lib_error_string_fn = ERR_lib_error_string; + ntlm->crypt_ctx.evp_md5_fn = EVP_md5; + ntlm->crypt_ctx.hmac_ctx_new_fn = HMAC_CTX_new; + ntlm->crypt_ctx.hmac_ctx_free_fn = HMAC_CTX_free; + ntlm->crypt_ctx.hmac_ctx_reset_fn = HMAC_CTX_reset; + ntlm->crypt_ctx.hmac_ctx_cleanup_fn = HMAC_CTX_cleanup; + ntlm->crypt_ctx.hmac_init_ex_fn = HMAC_Init_ex; + ntlm->crypt_ctx.hmac_update_fn = HMAC_Update; + ntlm->crypt_ctx.hmac_final_fn = HMAC_Final; + ntlm->crypt_ctx.md4_fn = MD4; + ntlm->crypt_ctx.rand_bytes_fn = RAND_bytes; + + return true; +} + +#endif /* CRYPT_OPENSSL_DYNAMIC */ + +bool ntlm_crypt_init(ntlm_client *ntlm) +{ + if (!ntlm_crypt_init_functions(ntlm)) + return false; + + ntlm->crypt_ctx.hmac = ntlm->crypt_ctx.hmac_ctx_new_fn(); + + if (ntlm->crypt_ctx.hmac == NULL) { + ntlm_client_set_errmsg(ntlm, "out of memory"); + return false; + } + + return true; +} + bool ntlm_random_bytes( - ntlm_client *ntlm, unsigned char *out, + ntlm_client *ntlm, size_t len) { - int rc = RAND_bytes(out, len); + int rc = ntlm->crypt_ctx.rand_bytes_fn(out, len); if (rc != 1) { - ntlm_client_set_errmsg(ntlm, ERR_lib_error_string(ERR_get_error())); + ntlm_client_set_errmsg(ntlm, ntlm->crypt_ctx.err_lib_error_string_fn(ntlm->crypt_ctx.err_get_error_fn())); return false; } @@ -37,94 +177,81 @@ bool ntlm_random_bytes( bool ntlm_des_encrypt( ntlm_des_block *out, + ntlm_client *ntlm, ntlm_des_block *plaintext, ntlm_des_block *key) { DES_key_schedule keysched; + NTLM_UNUSED(ntlm); + memset(out, 0, sizeof(ntlm_des_block)); - DES_set_key(key, &keysched); - DES_ecb_encrypt(plaintext, out, &keysched, DES_ENCRYPT); + ntlm->crypt_ctx.des_set_key_fn(key, &keysched); + ntlm->crypt_ctx.des_ecb_encrypt_fn(plaintext, out, &keysched, DES_ENCRYPT); return true; } bool ntlm_md4_digest( unsigned char out[CRYPT_MD4_DIGESTSIZE], + ntlm_client *ntlm, const unsigned char *in, size_t in_len) { - MD4(in, in_len, out); + ntlm->crypt_ctx.md4_fn(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); - ntlm_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, + ntlm_client *ntlm, const unsigned char *key, size_t key_len) { - return HMAC_Init_ex(ctx, key, key_len, EVP_md5(), NULL); + const EVP_MD *md5 = ntlm->crypt_ctx.evp_md5_fn(); + + ntlm->crypt_ctx.hmac_ctx_cleanup_fn(ntlm->crypt_ctx.hmac); + + return ntlm->crypt_ctx.hmac_ctx_reset_fn(ntlm->crypt_ctx.hmac) && + ntlm->crypt_ctx.hmac_init_ex_fn(ntlm->crypt_ctx.hmac, key, key_len, md5, NULL); } bool ntlm_hmac_md5_update( - ntlm_hmac_ctx *ctx, + ntlm_client *ntlm, const unsigned char *in, size_t in_len) { - return HMAC_Update(ctx, in, in_len); + return ntlm->crypt_ctx.hmac_update_fn(ntlm->crypt_ctx.hmac, in, in_len); } bool ntlm_hmac_md5_final( unsigned char *out, size_t *out_len, - ntlm_hmac_ctx *ctx) + ntlm_client *ntlm) { unsigned int len; if (*out_len < CRYPT_MD5_DIGESTSIZE) return false; - if (!HMAC_Final(ctx, out, &len)) + if (!ntlm->crypt_ctx.hmac_final_fn(ntlm->crypt_ctx.hmac, out, &len)) return false; *out_len = len; return true; } -void ntlm_hmac_ctx_free(ntlm_hmac_ctx *ctx) +void ntlm_crypt_shutdown(ntlm_client *ntlm) { - HMAC_CTX_free(ctx); + if (ntlm->crypt_ctx.hmac) { + ntlm->crypt_ctx.hmac_ctx_cleanup_fn(ntlm->crypt_ctx.hmac); + ntlm->crypt_ctx.hmac_ctx_free_fn(ntlm->crypt_ctx.hmac); + } + +#ifdef CRYPT_OPENSSL_DYNAMIC + if (ntlm->crypt_ctx.openssl_handle) + dlclose(ntlm->crypt_ctx.openssl_handle); +#endif + + memset(&ntlm->crypt_ctx, 0, sizeof(ntlm_crypt_ctx)); } diff --git a/deps/ntlmclient/crypt_openssl.h b/deps/ntlmclient/crypt_openssl.h index 4195db9a5..8654027db 100644 --- a/deps/ntlmclient/crypt_openssl.h +++ b/deps/ntlmclient/crypt_openssl.h @@ -9,13 +9,82 @@ #ifndef PRIVATE_CRYPT_OPENSSL_H__ #define PRIVATE_CRYPT_OPENSSL_H__ -#include +#ifndef CRYPT_OPENSSL_DYNAMIC +# include +# include +#endif /* 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 +#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10100000L +# define HMAC_CTX struct hmac_ctx_st +#endif + +#ifdef CRYPT_OPENSSL_DYNAMIC +typedef unsigned char DES_cblock[8]; +typedef unsigned char const_DES_cblock[8]; + +typedef unsigned long DES_LONG; + +typedef struct DES_ks { + union { + DES_cblock cblock; + DES_LONG deslong[2]; + } ks[16]; +} DES_key_schedule; + +#define DES_ENCRYPT 1 + +typedef void EVP_MD; +typedef void ENGINE; +typedef void EVP_PKEY_CTX; + +#define HMAC_MAX_MD_CBLOCK 128 + +typedef struct env_md_ctx_st EVP_MD_CTX; +struct env_md_ctx_st { + const EVP_MD *digest; + ENGINE *engine; + unsigned long flags; + void *md_data; + EVP_PKEY_CTX *pctx; + int (*update) (EVP_MD_CTX *ctx, const void *data, size_t count); +}; + +typedef struct hmac_ctx_st { + const EVP_MD *md; + EVP_MD_CTX md_ctx; + EVP_MD_CTX i_ctx; + EVP_MD_CTX o_ctx; + unsigned int key_length; + unsigned char key[HMAC_MAX_MD_CBLOCK]; +} HMAC_CTX; #endif +struct ntlm_crypt_ctx { + HMAC_CTX *hmac; + + void *openssl_handle; + + void (*des_ecb_encrypt_fn)(const_DES_cblock *input, DES_cblock *output, DES_key_schedule *ks, int enc); + int (*des_set_key_fn)(const_DES_cblock *key, DES_key_schedule *schedule); + + unsigned long (*err_get_error_fn)(void); + const char *(*err_lib_error_string_fn)(unsigned long e); + + const EVP_MD *(*evp_md5_fn)(void); + + HMAC_CTX *(*hmac_ctx_new_fn)(void); + int (*hmac_ctx_reset_fn)(HMAC_CTX *ctx); + void (*hmac_ctx_free_fn)(HMAC_CTX *ctx); + void (*hmac_ctx_cleanup_fn)(HMAC_CTX *ctx); + + int (*hmac_init_ex_fn)(HMAC_CTX *ctx, const void *key, int key_len, const EVP_MD *md, ENGINE *impl); + int (*hmac_update_fn)(HMAC_CTX *ctx, const unsigned char *data, size_t len); + int (*hmac_final_fn)(HMAC_CTX *ctx, unsigned char *md, unsigned int *len); + + unsigned char *(*md4_fn)(const unsigned char *d, size_t n, unsigned char *md); + + int (*rand_bytes_fn)(unsigned char *buf, int num); +}; + #endif /* PRIVATE_CRYPT_OPENSSL_H__ */ diff --git a/deps/ntlmclient/ntlm.c b/deps/ntlmclient/ntlm.c index 470a90143..3393be915 100644 --- a/deps/ntlmclient/ntlm.c +++ b/deps/ntlmclient/ntlm.c @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -24,6 +23,18 @@ #include "compat.h" #include "util.h" +#define NTLM_ASSERT_ARG(expr) do { \ + if (!(expr)) \ + return NTLM_CLIENT_ERROR_INVALID_INPUT; \ + } while(0) + +#define NTLM_ASSERT(ntlm, expr) do { \ + if (!(expr)) { \ + ntlm_client_set_errmsg(ntlm, "internal error: " #expr); \ + return -1; \ + } \ + } while(0) + unsigned char ntlm_client_signature[] = NTLM_SIGNATURE; static bool supports_unicode(ntlm_client *ntlm) @@ -52,17 +63,20 @@ ntlm_client *ntlm_client_init(ntlm_client_flags flags) ntlm->flags = flags; - if ((ntlm->hmac_ctx = ntlm_hmac_ctx_init()) == NULL || - (ntlm->unicode_ctx = ntlm_unicode_ctx_init(ntlm)) == NULL) { - ntlm_hmac_ctx_free(ntlm->hmac_ctx); - ntlm_unicode_ctx_free(ntlm->unicode_ctx); - free(ntlm); - return NULL; - } - return ntlm; } +#define ENSURE_INITIALIZED(ntlm) \ + do { \ + if (!(ntlm)->unicode_initialized) \ + (ntlm)->unicode_initialized = ntlm_unicode_init((ntlm)); \ + if (!(ntlm)->crypt_initialized) \ + (ntlm)->crypt_initialized = ntlm_crypt_init((ntlm)); \ + if (!(ntlm)->unicode_initialized || \ + !(ntlm)->crypt_initialized) \ + return -1; \ + } while(0) + void ntlm_client_set_errmsg(ntlm_client *ntlm, const char *errmsg) { ntlm->state = NTLM_STATE_ERROR; @@ -71,7 +85,9 @@ void ntlm_client_set_errmsg(ntlm_client *ntlm, const char *errmsg) const char *ntlm_client_errmsg(ntlm_client *ntlm) { - assert(ntlm); + if (!ntlm) + return "internal error"; + return ntlm->errmsg ? ntlm->errmsg : "no error"; } @@ -81,7 +97,7 @@ int ntlm_client_set_version( uint8_t minor, uint16_t build) { - assert(ntlm); + NTLM_ASSERT_ARG(ntlm); ntlm->host_version.major = major; ntlm->host_version.minor = minor; @@ -93,20 +109,25 @@ int ntlm_client_set_version( return 0; } +#define reset(ptr) do { free(ptr); ptr = NULL; } while(0) + +static void free_hostname(ntlm_client *ntlm) +{ + reset(ntlm->hostname); + reset(ntlm->hostdomain); + reset(ntlm->hostname_utf16); + ntlm->hostname_utf16_len = 0; +} + int ntlm_client_set_hostname( ntlm_client *ntlm, const char *hostname, const char *domain) { - assert(ntlm); + NTLM_ASSERT_ARG(ntlm); + ENSURE_INITIALIZED(ntlm); - free(ntlm->hostname); - free(ntlm->hostdomain); - free(ntlm->hostname_utf16); - - ntlm->hostname = NULL; - ntlm->hostdomain = NULL; - ntlm->hostname_utf16 = NULL; + free_hostname(ntlm); if (hostname && (ntlm->hostname = strdup(hostname)) == NULL) { ntlm_client_set_errmsg(ntlm, "out of memory"); @@ -121,7 +142,7 @@ int ntlm_client_set_hostname( if (hostname && supports_unicode(ntlm) && !ntlm_unicode_utf8_to_16( &ntlm->hostname_utf16, &ntlm->hostname_utf16_len, - ntlm->unicode_ctx, + ntlm, hostname, strlen(hostname))) return -1; @@ -137,25 +158,20 @@ static void free_credentials(ntlm_client *ntlm) if (ntlm->password_utf16) ntlm_memzero(ntlm->password_utf16, ntlm->password_utf16_len); - free(ntlm->username); - free(ntlm->username_upper); - free(ntlm->userdomain); - free(ntlm->password); - - free(ntlm->username_utf16); - free(ntlm->username_upper_utf16); - free(ntlm->userdomain_utf16); - free(ntlm->password_utf16); - - ntlm->username = NULL; - ntlm->username_upper = NULL; - ntlm->userdomain = NULL; - ntlm->password = NULL; - - ntlm->username_utf16 = NULL; - ntlm->username_upper_utf16 = NULL; - ntlm->userdomain_utf16 = NULL; - ntlm->password_utf16 = NULL; + reset(ntlm->username); + reset(ntlm->username_upper); + reset(ntlm->userdomain); + reset(ntlm->password); + + reset(ntlm->username_utf16); + reset(ntlm->username_upper_utf16); + reset(ntlm->userdomain_utf16); + reset(ntlm->password_utf16); + + ntlm->username_utf16_len = 0; + ntlm->username_upper_utf16_len = 0; + ntlm->userdomain_utf16_len = 0; + ntlm->password_utf16_len = 0; } int ntlm_client_set_credentials( @@ -164,7 +180,8 @@ int ntlm_client_set_credentials( const char *domain, const char *password) { - assert(ntlm); + NTLM_ASSERT_ARG(ntlm); + ENSURE_INITIALIZED(ntlm); free_credentials(ntlm); @@ -185,7 +202,7 @@ int ntlm_client_set_credentials( if (!ntlm_unicode_utf8_to_16( &ntlm->username_utf16, &ntlm->username_utf16_len, - ntlm->unicode_ctx, + ntlm, ntlm->username, strlen(ntlm->username))) return -1; @@ -193,7 +210,7 @@ int ntlm_client_set_credentials( if (!ntlm_unicode_utf8_to_16( &ntlm->username_upper_utf16, &ntlm->username_upper_utf16_len, - ntlm->unicode_ctx, + ntlm, ntlm->username_upper, strlen(ntlm->username_upper))) return -1; @@ -202,7 +219,7 @@ int ntlm_client_set_credentials( if (domain && supports_unicode(ntlm) && !ntlm_unicode_utf8_to_16( &ntlm->userdomain_utf16, &ntlm->userdomain_utf16_len, - ntlm->unicode_ctx, + ntlm, ntlm->userdomain, strlen(ntlm->userdomain))) return -1; @@ -212,7 +229,8 @@ int ntlm_client_set_credentials( int ntlm_client_set_target(ntlm_client *ntlm, const char *target) { - assert(ntlm); + NTLM_ASSERT_ARG(ntlm); + ENSURE_INITIALIZED(ntlm); free(ntlm->target); free(ntlm->target_utf16); @@ -229,7 +247,7 @@ int ntlm_client_set_target(ntlm_client *ntlm, const char *target) if (supports_unicode(ntlm) && !ntlm_unicode_utf8_to_16( &ntlm->target_utf16, &ntlm->target_utf16_len, - ntlm->unicode_ctx, + ntlm, ntlm->target, strlen(ntlm->target))) return -1; @@ -240,14 +258,16 @@ int ntlm_client_set_target(ntlm_client *ntlm, const char *target) int ntlm_client_set_nonce(ntlm_client *ntlm, uint64_t nonce) { - assert(ntlm); + NTLM_ASSERT_ARG(ntlm); + ntlm->nonce = nonce; return 0; } int ntlm_client_set_timestamp(ntlm_client *ntlm, uint64_t timestamp) { - assert(ntlm); + NTLM_ASSERT_ARG(ntlm); + ntlm->timestamp = timestamp; return 0; } @@ -475,7 +495,7 @@ static inline bool read_string_unicode( size_t out_len; int ret = ntlm_unicode_utf16_to_8(out, &out_len, - ntlm->unicode_ctx, + ntlm, (char *)&message->buf[message->pos], string_len); @@ -593,7 +613,9 @@ int ntlm_client_negotiate( size_t hostname_offset = 0; uint32_t flags = 0; - assert(out && out_len && ntlm); + NTLM_ASSERT_ARG(out); + NTLM_ASSERT_ARG(out_len); + NTLM_ASSERT_ARG(ntlm); *out = NULL; *out_len = 0; @@ -676,20 +698,22 @@ int ntlm_client_negotiate( return -1; if (hostname_len > 0) { - assert(hostname_offset == ntlm->negotiate.pos); + NTLM_ASSERT(ntlm, hostname_offset == ntlm->negotiate.pos); + if (!write_buf(ntlm, &ntlm->negotiate, (const unsigned char *)ntlm->hostname, hostname_len)) return -1; } if (domain_len > 0) { - assert(domain_offset == ntlm->negotiate.pos); + NTLM_ASSERT(ntlm, domain_offset == ntlm->negotiate.pos); + if (!write_buf(ntlm, &ntlm->negotiate, (const unsigned char *)ntlm->hostdomain, domain_len)) return -1; } - assert(ntlm->negotiate.pos == ntlm->negotiate.len); + NTLM_ASSERT(ntlm, ntlm->negotiate.pos == ntlm->negotiate.len); ntlm->state = NTLM_STATE_CHALLENGE; @@ -711,7 +735,10 @@ int ntlm_client_set_challenge( uint32_t name_offset, info_offset = 0; bool unicode, has_target_info = false; - assert(ntlm && (challenge_msg || !challenge_msg_len)); + NTLM_ASSERT_ARG(ntlm); + NTLM_ASSERT_ARG(challenge_msg || !challenge_msg_len); + + ENSURE_INITIALIZED(ntlm); if (ntlm->state != NTLM_STATE_NEGOTIATE && ntlm->state != NTLM_STATE_CHALLENGE) { @@ -940,6 +967,7 @@ static void des_key_from_password( static inline bool generate_lm_hash( ntlm_des_block out[2], + ntlm_client *ntlm, const char *password) { /* LM encrypts this known plaintext using the password as a key */ @@ -968,8 +996,8 @@ static inline bool generate_lm_hash( des_key_from_password(&key1, keystr1, keystr1_len); des_key_from_password(&key2, keystr2, keystr2_len); - return ntlm_des_encrypt(&out[0], &plaintext, &key1) && - ntlm_des_encrypt(&out[1], &plaintext, &key2); + return ntlm_des_encrypt(&out[0], ntlm, &plaintext, &key1) && + ntlm_des_encrypt(&out[1], ntlm, &plaintext, &key2); } static void des_keys_from_lm_hash(ntlm_des_block out[3], ntlm_des_block lm_hash[2]) @@ -994,16 +1022,16 @@ static bool generate_lm_response(ntlm_client *ntlm) ntlm_des_block *challenge = (ntlm_des_block *)&ntlm->challenge.nonce; /* Generate the LM hash from the password */ - if (!generate_lm_hash(lm_hash, ntlm->password)) + if (!generate_lm_hash(lm_hash, ntlm, ntlm->password)) return false; /* Convert that LM hash to three DES keys */ des_keys_from_lm_hash(key, lm_hash); /* Finally, encrypt the challenge with each of these keys */ - if (!ntlm_des_encrypt(&lm_response[0], challenge, &key[0]) || - !ntlm_des_encrypt(&lm_response[1], challenge, &key[1]) || - !ntlm_des_encrypt(&lm_response[2], challenge, &key[2])) + if (!ntlm_des_encrypt(&lm_response[0], ntlm, challenge, &key[0]) || + !ntlm_des_encrypt(&lm_response[1], ntlm, challenge, &key[1]) || + !ntlm_des_encrypt(&lm_response[2], ntlm, challenge, &key[2])) return false; memcpy(&ntlm->lm_response[0], lm_response[0], 8); @@ -1022,12 +1050,13 @@ static bool generate_ntlm_hash( if (ntlm->password && !ntlm_unicode_utf8_to_16( &ntlm->password_utf16, &ntlm->password_utf16_len, - ntlm->unicode_ctx, + ntlm, ntlm->password, strlen(ntlm->password))) return false; return ntlm_md4_digest(out, + ntlm, (const unsigned char *)ntlm->password_utf16, ntlm->password_utf16_len); } @@ -1048,9 +1077,9 @@ static bool generate_ntlm_response(ntlm_client *ntlm) des_key_from_password(&key[2], &ntlm_hash[14], 2); /* Finally, encrypt the challenge with each of these keys */ - if (!ntlm_des_encrypt(&ntlm_response[0], challenge, &key[0]) || - !ntlm_des_encrypt(&ntlm_response[1], challenge, &key[1]) || - !ntlm_des_encrypt(&ntlm_response[2], challenge, &key[2])) + if (!ntlm_des_encrypt(&ntlm_response[0], ntlm, challenge, &key[0]) || + !ntlm_des_encrypt(&ntlm_response[1], ntlm, challenge, &key[1]) || + !ntlm_des_encrypt(&ntlm_response[2], ntlm, challenge, &key[2])) return false; memcpy(&ntlm->ntlm_response[0], ntlm_response[0], 8); @@ -1081,16 +1110,15 @@ static bool generate_ntlm2_hash( target_len = ntlm->target_utf16_len; } - if (!ntlm_hmac_ctx_reset(ntlm->hmac_ctx) || - !ntlm_hmac_md5_init(ntlm->hmac_ctx, ntlm_hash, sizeof(ntlm_hash)) || - !ntlm_hmac_md5_update(ntlm->hmac_ctx, username, username_len) || - !ntlm_hmac_md5_update(ntlm->hmac_ctx, target, target_len) || - !ntlm_hmac_md5_final(out, &out_len, ntlm->hmac_ctx)) { + if (!ntlm_hmac_md5_init(ntlm, ntlm_hash, sizeof(ntlm_hash)) || + !ntlm_hmac_md5_update(ntlm, username, username_len) || + !ntlm_hmac_md5_update(ntlm, target, target_len) || + !ntlm_hmac_md5_final(out, &out_len, ntlm)) { ntlm_client_set_errmsg(ntlm, "failed to create HMAC-MD5"); return false; } - assert(out_len == NTLM_NTLM2_HASH_LEN); + NTLM_ASSERT(ntlm, out_len == NTLM_NTLM2_HASH_LEN); return true; } @@ -1103,18 +1131,15 @@ static bool generate_ntlm2_challengehash( { size_t out_len = 16; - if (!ntlm_hmac_ctx_reset(ntlm->hmac_ctx) || - !ntlm_hmac_md5_init(ntlm->hmac_ctx, - ntlm2_hash, NTLM_NTLM2_HASH_LEN) || - !ntlm_hmac_md5_update(ntlm->hmac_ctx, - (const unsigned char *)&ntlm->challenge.nonce, 8) || - !ntlm_hmac_md5_update(ntlm->hmac_ctx, blob, blob_len) || - !ntlm_hmac_md5_final(out, &out_len, ntlm->hmac_ctx)) { + if (!ntlm_hmac_md5_init(ntlm, ntlm2_hash, NTLM_NTLM2_HASH_LEN) || + !ntlm_hmac_md5_update(ntlm, (const unsigned char *)&ntlm->challenge.nonce, 8) || + !ntlm_hmac_md5_update(ntlm, blob, blob_len) || + !ntlm_hmac_md5_final(out, &out_len, ntlm)) { ntlm_client_set_errmsg(ntlm, "failed to create HMAC-MD5"); return false; } - assert(out_len == 16); + NTLM_ASSERT(ntlm, out_len == 16); return true; } @@ -1127,19 +1152,15 @@ static bool generate_lm2_response(ntlm_client *ntlm, local_nonce = ntlm_htonll(ntlm->nonce); - if (!ntlm_hmac_ctx_reset(ntlm->hmac_ctx) || - !ntlm_hmac_md5_init(ntlm->hmac_ctx, - ntlm2_hash, NTLM_NTLM2_HASH_LEN) || - !ntlm_hmac_md5_update(ntlm->hmac_ctx, - (const unsigned char *)&ntlm->challenge.nonce, 8) || - !ntlm_hmac_md5_update(ntlm->hmac_ctx, - (const unsigned char *)&local_nonce, 8) || - !ntlm_hmac_md5_final(lm2_challengehash, &lm2_len, ntlm->hmac_ctx)) { + if (!ntlm_hmac_md5_init(ntlm, ntlm2_hash, NTLM_NTLM2_HASH_LEN) || + !ntlm_hmac_md5_update(ntlm, (const unsigned char *)&ntlm->challenge.nonce, 8) || + !ntlm_hmac_md5_update(ntlm, (const unsigned char *)&local_nonce, 8) || + !ntlm_hmac_md5_final(lm2_challengehash, &lm2_len, ntlm)) { ntlm_client_set_errmsg(ntlm, "failed to create HMAC-MD5"); return false; } - assert(lm2_len == 16); + NTLM_ASSERT(ntlm, lm2_len == 16); memcpy(&ntlm->lm_response[0], lm2_challengehash, 16); memcpy(&ntlm->lm_response[16], &local_nonce, 8); @@ -1163,7 +1184,7 @@ static bool generate_nonce(ntlm_client *ntlm) if (ntlm->nonce) return true; - if (!ntlm_random_bytes(ntlm, buf, 8)) + if (!ntlm_random_bytes(buf, ntlm, 8)) return false; memcpy(&ntlm->nonce, buf, sizeof(uint64_t)); @@ -1233,7 +1254,11 @@ int ntlm_client_response( uint32_t flags = 0; bool unicode; - assert(out && out_len && ntlm); + NTLM_ASSERT_ARG(out); + NTLM_ASSERT_ARG(out_len); + NTLM_ASSERT_ARG(ntlm); + + ENSURE_INITIALIZED(ntlm); *out = NULL; *out_len = 0; @@ -1356,7 +1381,7 @@ int ntlm_client_response( !write_buf(ntlm, &ntlm->response, session, session_len)) return -1; - assert(ntlm->response.pos == ntlm->response.len); + NTLM_ASSERT(ntlm, ntlm->response.pos == ntlm->response.len); ntlm->state = NTLM_STATE_COMPLETE; @@ -1368,41 +1393,48 @@ int ntlm_client_response( void ntlm_client_reset(ntlm_client *ntlm) { - ntlm_client_flags flags; - ntlm_hmac_ctx *hmac_ctx; - ntlm_unicode_ctx *unicode_ctx; - - assert(ntlm); + if (!ntlm) + return; - free(ntlm->negotiate.buf); - free(ntlm->challenge.target_info); - free(ntlm->challenge.target); - free(ntlm->challenge.target_domain); - free(ntlm->challenge.target_domain_dns); - free(ntlm->challenge.target_server); - free(ntlm->challenge.target_server_dns); - free(ntlm->response.buf); + ntlm->state = NTLM_STATE_NEGOTIATE; - free(ntlm->hostname); - free(ntlm->hostname_utf16); - free(ntlm->hostdomain); + free_hostname(ntlm); - free(ntlm->target); - free(ntlm->target_utf16); + memset(&ntlm->host_version, 0, sizeof(ntlm_version)); - free(ntlm->ntlm2_response); + reset(ntlm->target); + reset(ntlm->target_utf16); + ntlm->target_utf16_len = 0; free_credentials(ntlm); - flags = ntlm->flags; - hmac_ctx = ntlm->hmac_ctx; - unicode_ctx = ntlm->unicode_ctx; + ntlm->nonce = 0; + ntlm->timestamp = 0; - memset(ntlm, 0, sizeof(struct ntlm_client)); + memset(ntlm->lm_response, 0, NTLM_LM_RESPONSE_LEN); + ntlm->lm_response_len = 0; - ntlm->flags = flags; - ntlm->hmac_ctx = hmac_ctx; - ntlm->unicode_ctx = unicode_ctx; + memset(ntlm->ntlm_response, 0, NTLM_NTLM_RESPONSE_LEN); + ntlm->ntlm_response_len = 0; + + reset(ntlm->ntlm2_response); + ntlm->ntlm2_response_len = 0; + + reset(ntlm->negotiate.buf); + ntlm->negotiate.pos = 0; + ntlm->negotiate.len = 0; + + reset(ntlm->response.buf); + ntlm->response.pos = 0; + ntlm->response.len = 0; + + free(ntlm->challenge.target_info); + free(ntlm->challenge.target); + free(ntlm->challenge.target_domain); + free(ntlm->challenge.target_domain_dns); + free(ntlm->challenge.target_server); + free(ntlm->challenge.target_server_dns); + memset(&ntlm->challenge, 0, sizeof(ntlm_challenge)); } void ntlm_client_free(ntlm_client *ntlm) @@ -1410,10 +1442,10 @@ void ntlm_client_free(ntlm_client *ntlm) if (!ntlm) return; - ntlm_client_reset(ntlm); + ntlm_crypt_shutdown(ntlm); + ntlm_unicode_shutdown(ntlm); - ntlm_hmac_ctx_free(ntlm->hmac_ctx); - ntlm_unicode_ctx_free(ntlm->unicode_ctx); + ntlm_client_reset(ntlm); free(ntlm); } diff --git a/deps/ntlmclient/ntlm.h b/deps/ntlmclient/ntlm.h index 0dad91ec0..227f5bcba 100644 --- a/deps/ntlmclient/ntlm.h +++ b/deps/ntlmclient/ntlm.h @@ -14,6 +14,8 @@ #include "crypt.h" #include "compat.h" +#define NTLM_UNUSED(x) ((void)(x)) + #define NTLM_LM_RESPONSE_LEN 24 #define NTLM_NTLM_RESPONSE_LEN 24 #define NTLM_NTLM_HASH_LEN 16 @@ -66,9 +68,11 @@ struct ntlm_client { ntlm_state state; - /* crypto contexts */ - ntlm_hmac_ctx *hmac_ctx; - ntlm_unicode_ctx *unicode_ctx; + /* subsystem contexts */ + ntlm_crypt_ctx crypt_ctx; + ntlm_unicode_ctx unicode_ctx; + int crypt_initialized : 1, + unicode_initialized : 1; /* error message as set by the library */ const char *errmsg; @@ -85,24 +89,24 @@ struct ntlm_client { char *password; /* strings as converted to utf16 */ + char *hostname_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 hostname_utf16_len; 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; + /* timestamp and nonce; only for debugging */ + uint64_t nonce; + uint64_t timestamp; + unsigned char lm_response[NTLM_LM_RESPONSE_LEN]; size_t lm_response_len; diff --git a/deps/ntlmclient/ntlmclient.h b/deps/ntlmclient/ntlmclient.h index d109a5c89..bf57b17c6 100644 --- a/deps/ntlmclient/ntlmclient.h +++ b/deps/ntlmclient/ntlmclient.h @@ -15,13 +15,26 @@ extern "C" { #endif -#define NTLM_CLIENT_VERSION "0.0.1" +#define NTLM_CLIENT_VERSION "0.9.0" #define NTLM_CLIENT_VERSION_MAJOR 0 -#define NTLM_CLIENT_VERSION_MINOR 0 -#define NTLM_CLIENT_VERSION_TEENY 1 +#define NTLM_CLIENT_VERSION_MINOR 9 +#define NTLM_CLIENT_VERSION_TEENY 0 typedef struct ntlm_client ntlm_client; +typedef enum { + /** + * An error occurred; more details are available by querying + * `ntlm_client_errmsg`. + */ + NTLM_CLIENT_ERROR = -1, + + /** + * The input provided to the function is missing or invalid. + */ + NTLM_CLIENT_ERROR_INVALID_INPUT = -2, +} ntlm_error_code; + /* * Flags for initializing the `ntlm_client` context. A combination of * these flags can be provided to `ntlm_client_init`. diff --git a/deps/ntlmclient/unicode.h b/deps/ntlmclient/unicode.h index e3b17bcf7..b7c63f2ed 100644 --- a/deps/ntlmclient/unicode.h +++ b/deps/ntlmclient/unicode.h @@ -11,26 +11,32 @@ #include "compat.h" +#ifdef UNICODE_ICONV +# include "unicode_iconv.h" +#elif UNICODE_BUILTIN +# include "unicode_builtin.h" +#endif + #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); +extern bool ntlm_unicode_init(ntlm_client *ntlm); bool ntlm_unicode_utf8_to_16( char **converted, size_t *converted_len, - ntlm_unicode_ctx *ctx, + ntlm_client *ntlm, const char *string, size_t string_len); bool ntlm_unicode_utf16_to_8( char **converted, size_t *converted_len, - ntlm_unicode_ctx *ctx, + ntlm_client *ntlm, const char *string, size_t string_len); -extern void ntlm_unicode_ctx_free(ntlm_unicode_ctx *ctx); +extern void ntlm_unicode_shutdown(ntlm_client *ntlm); #endif /* PRIVATE_UNICODE_H__ */ diff --git a/deps/ntlmclient/unicode_builtin.c b/deps/ntlmclient/unicode_builtin.c index e1856cca9..e2ee0abf7 100644 --- a/deps/ntlmclient/unicode_builtin.c +++ b/deps/ntlmclient/unicode_builtin.c @@ -13,10 +13,6 @@ #include "unicode.h" #include "compat.h" -struct ntlm_unicode_ctx { - ntlm_client *ntlm; -}; - typedef unsigned int UTF32; /* at least 32 bits */ typedef unsigned short UTF16; /* at least 16 bits */ typedef unsigned char UTF8; /* typically 8 bits */ @@ -281,15 +277,10 @@ static ConversionResult ConvertUTF8toUTF16 ( } -ntlm_unicode_ctx *ntlm_unicode_ctx_init(ntlm_client *ntlm) +bool ntlm_unicode_init(ntlm_client *ntlm) { - ntlm_unicode_ctx *ctx; - - if ((ctx = malloc(sizeof(ntlm_unicode_ctx))) == NULL) - return NULL; - - ctx->ntlm = ntlm; - return ctx; + NTLM_UNUSED(ntlm); + return true; } typedef enum { @@ -300,7 +291,7 @@ typedef enum { static inline bool unicode_builtin_encoding_convert( char **converted, size_t *converted_len, - ntlm_unicode_ctx *ctx, + ntlm_client *ntlm, const char *string, size_t string_len, unicode_builtin_encoding_direction direction) @@ -332,7 +323,7 @@ static inline bool unicode_builtin_encoding_convert( out_size = (out_size + 7) & ~7; if ((out = malloc(out_size)) == NULL) { - ntlm_client_set_errmsg(ctx->ntlm, "out of memory"); + ntlm_client_set_errmsg(ntlm, "out of memory"); return false; } @@ -358,17 +349,17 @@ static inline bool unicode_builtin_encoding_convert( success = true; goto done; case sourceExhausted: - ntlm_client_set_errmsg(ctx->ntlm, + ntlm_client_set_errmsg(ntlm, "invalid unicode string; trailing data remains"); goto done; case targetExhausted: break; case sourceIllegal: - ntlm_client_set_errmsg(ctx->ntlm, + ntlm_client_set_errmsg(ntlm, "invalid unicode string; trailing data remains"); goto done; default: - ntlm_client_set_errmsg(ctx->ntlm, + ntlm_client_set_errmsg(ntlm, "unknown unicode conversion failure"); goto done; } @@ -377,13 +368,12 @@ static inline bool unicode_builtin_encoding_convert( 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"); + ntlm_client_set_errmsg(ntlm, "unicode conversion too large"); goto done; } if ((new_out = realloc(out, out_size)) == NULL) { - ntlm_client_set_errmsg(ctx->ntlm, "out of memory"); + ntlm_client_set_errmsg(ntlm, "out of memory"); goto done; } @@ -419,27 +409,26 @@ done: bool ntlm_unicode_utf8_to_16( char **converted, size_t *converted_len, - ntlm_unicode_ctx *ctx, + ntlm_client *client, const char *string, size_t string_len) { return unicode_builtin_encoding_convert(converted, converted_len, - ctx, string, string_len, unicode_builtin_utf8_to_16); + client, string, string_len, unicode_builtin_utf8_to_16); } bool ntlm_unicode_utf16_to_8( char **converted, size_t *converted_len, - ntlm_unicode_ctx *ctx, + ntlm_client *client, const char *string, size_t string_len) { return unicode_builtin_encoding_convert(converted, converted_len, - ctx, string, string_len, unicode_builtin_utf16_to_8); + client, string, string_len, unicode_builtin_utf16_to_8); } -void ntlm_unicode_ctx_free(ntlm_unicode_ctx *ctx) +void ntlm_unicode_shutdown(ntlm_client *ntlm) { - if (ctx) - free(ctx); + NTLM_UNUSED(ntlm); } diff --git a/deps/ntlmclient/unicode_builtin.h b/deps/ntlmclient/unicode_builtin.h new file mode 100644 index 000000000..eabec40bf --- /dev/null +++ b/deps/ntlmclient/unicode_builtin.h @@ -0,0 +1,20 @@ +/* + * 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_BUILTIN_H__ +#define PRIVATE_UNICODE_BUILTIN_H__ + +#include +#include + +#include "ntlmclient.h" + +struct ntlm_unicode_ctx { +}; + +#endif /* PRIVATE_UNICODE_BUILTIN_H__ */ diff --git a/deps/ntlmclient/unicode_iconv.c b/deps/ntlmclient/unicode_iconv.c index d1fe07e26..e14da21f5 100644 --- a/deps/ntlmclient/unicode_iconv.c +++ b/deps/ntlmclient/unicode_iconv.c @@ -16,43 +16,23 @@ #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) +bool ntlm_unicode_init(ntlm_client *ntlm) { - if (ctx->utf8_to_16 != (iconv_t)-1 || ctx->utf16_to_8 != (iconv_t)-1) - return true; + ntlm->unicode_ctx.utf8_to_16 = iconv_open("UTF-16LE", "UTF-8"); + ntlm->unicode_ctx.utf16_to_8 = iconv_open("UTF-8", "UTF-16LE"); - 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 (ntlm->unicode_ctx.utf8_to_16 == (iconv_t)-1 || + ntlm->unicode_ctx.utf16_to_8 == (iconv_t)-1) { if (errno == EINVAL) - ntlm_client_set_errmsg(ctx->ntlm, + ntlm_client_set_errmsg(ntlm, "iconv does not support UTF8 <-> UTF16 conversion"); else - ntlm_client_set_errmsg(ctx->ntlm, strerror(errno)); + ntlm_client_set_errmsg(ntlm, strerror(errno)); return false; } @@ -63,7 +43,7 @@ static inline bool unicode_iconv_init(ntlm_unicode_ctx *ctx) static inline bool unicode_iconv_encoding_convert( char **converted, size_t *converted_len, - ntlm_unicode_ctx *ctx, + ntlm_client *ntlm, const char *string, size_t string_len, unicode_iconv_encoding_direction direction) @@ -75,9 +55,6 @@ static inline bool unicode_iconv_encoding_convert( *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 @@ -86,11 +63,11 @@ static inline bool unicode_iconv_encoding_convert( * terminate and expect an extra byte for UTF8, two for UTF16. */ if (direction == unicode_iconv_utf8_to_16) { - converter = ctx->utf8_to_16; + converter = ntlm->unicode_ctx.utf8_to_16; out_size = (string_len * 2) + 2; nul_size = 2; } else { - converter = ctx->utf16_to_8; + converter = ntlm->unicode_ctx.utf16_to_8; out_size = (string_len / 2) + 1; nul_size = 1; } @@ -99,7 +76,7 @@ static inline bool unicode_iconv_encoding_convert( out_size = (out_size + 7) & ~7; if ((out = malloc(out_size)) == NULL) { - ntlm_client_set_errmsg(ctx->ntlm, "out of memory"); + ntlm_client_set_errmsg(ntlm, "out of memory"); return false; } @@ -117,7 +94,7 @@ static inline bool unicode_iconv_encoding_convert( break; if (ret == (size_t)-1 && errno != E2BIG) { - ntlm_client_set_errmsg(ctx->ntlm, strerror(errno)); + ntlm_client_set_errmsg(ntlm, strerror(errno)); goto on_error; } @@ -125,13 +102,12 @@ static inline bool unicode_iconv_encoding_convert( 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"); + ntlm_client_set_errmsg(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"); + ntlm_client_set_errmsg(ntlm, "out of memory"); goto on_error; } @@ -139,7 +115,7 @@ static inline bool unicode_iconv_encoding_convert( } if (in_start_len != 0) { - ntlm_client_set_errmsg(ctx->ntlm, + ntlm_client_set_errmsg(ntlm, "invalid unicode string; trailing data remains"); goto on_error; } @@ -165,37 +141,37 @@ on_error: bool ntlm_unicode_utf8_to_16( char **converted, size_t *converted_len, - ntlm_unicode_ctx *ctx, + ntlm_client *ntlm, const char *string, size_t string_len) { return unicode_iconv_encoding_convert( - converted, converted_len, ctx, string, string_len, + converted, converted_len, ntlm, string, string_len, unicode_iconv_utf8_to_16); } bool ntlm_unicode_utf16_to_8( char **converted, size_t *converted_len, - ntlm_unicode_ctx *ctx, + ntlm_client *ntlm, const char *string, size_t string_len) { return unicode_iconv_encoding_convert( - converted, converted_len, ctx, string, string_len, + converted, converted_len, ntlm, string, string_len, unicode_iconv_utf16_to_8); } -void ntlm_unicode_ctx_free(ntlm_unicode_ctx *ctx) +void ntlm_unicode_shutdown(ntlm_client *ntlm) { - if (!ctx) - return; - - if (ctx->utf16_to_8 != (iconv_t)-1) - iconv_close(ctx->utf16_to_8); + if (ntlm->unicode_ctx.utf16_to_8 != (iconv_t)0 && + ntlm->unicode_ctx.utf16_to_8 != (iconv_t)-1) + iconv_close(ntlm->unicode_ctx.utf16_to_8); - if (ctx->utf8_to_16 != (iconv_t)-1) - iconv_close(ctx->utf8_to_16); + if (ntlm->unicode_ctx.utf8_to_16 != (iconv_t)0 && + ntlm->unicode_ctx.utf8_to_16 != (iconv_t)-1) + iconv_close(ntlm->unicode_ctx.utf8_to_16); - free(ctx); + ntlm->unicode_ctx.utf8_to_16 = (iconv_t)-1; + ntlm->unicode_ctx.utf16_to_8 = (iconv_t)-1; } diff --git a/deps/ntlmclient/unicode_iconv.h b/deps/ntlmclient/unicode_iconv.h new file mode 100644 index 000000000..87a96a67d --- /dev/null +++ b/deps/ntlmclient/unicode_iconv.h @@ -0,0 +1,22 @@ +/* + * 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_ICONV_H__ +#define PRIVATE_UNICODE_ICONV_H__ + +#include +#include + +#include "ntlmclient.h" + +struct ntlm_unicode_ctx { + iconv_t utf8_to_16; + iconv_t utf16_to_8; +}; + +#endif /* PRIVATE_UNICODE_ICONV_H__ */ -- cgit v1.2.1