diff --git a/CMakeLists.txt b/CMakeLists.txt index 8ca40e3..a573048 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -350,6 +350,18 @@ target_include_directories(common_obj PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) add_library(base64_obj OBJECT src/base64.c) target_include_directories(base64_obj PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) +# mdhash object library (MD4/MD5: CAPI on Windows, OpenSSL EVP elsewhere) +add_library(mdhash_obj OBJECT src/mdhash.c) +target_include_directories(mdhash_obj PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) +if(WIN32) + # CAPI lives in advapi32 (already in WINDOWS_LIBS); no extra include needed. +else() + if(OpenSSL_FOUND) + target_include_directories(mdhash_obj PRIVATE ${OPENSSL_INCLUDE_DIR}) + target_compile_definitions(mdhash_obj PRIVATE WITH_SSL) + endif() +endif() + # ============================================================================ # Object libraries for 3proxy (compiled WITHOUT WITHMAIN) # These are used by the main 3proxy executable @@ -411,6 +423,7 @@ add_executable(3proxy $ $ $ + $ $ $ ) @@ -520,6 +533,7 @@ endif() add_executable(3proxy_crypt src/3proxy_crypt.c $ + $ ) target_sources(3proxy_crypt PRIVATE ${MD_SOURCES}) target_compile_definitions(3proxy_crypt PRIVATE WITHMAIN) diff --git a/src/3proxy_crypt.c b/src/3proxy_crypt.c index b936ee7..79ae11d 100644 --- a/src/3proxy_crypt.c +++ b/src/3proxy_crypt.c @@ -6,6 +6,7 @@ */ #include "libs/blake2.h" +#include "mdhash.h" #ifdef WITH_SSL #include #if OPENSSL_VERSION_NUMBER >= 0x30000000L @@ -28,7 +29,7 @@ static unsigned char itoa64[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; -#if defined(WITH_SSL) && OPENSSL_VERSION_NUMBER >= 0x30000000L +#if defined(WITH_SSL) && !defined(_WIN32) && OPENSSL_VERSION_NUMBER >= 0x30000000L EVP_MD *md4_hash = NULL; EVP_MD *md5_hash = NULL; #endif @@ -43,21 +44,14 @@ _crypt_to64(unsigned char *s, unsigned long v, int n) } -#ifdef WITH_SSL +#if defined(WITH_SSL) || defined(_WIN32) unsigned char * ntpwdhash (unsigned char *szHash, const unsigned char *szPassword, int ctohex) { unsigned char szUnicodePass[513]; unsigned int nPasswordLen; - EVP_MD_CTX *ctx; - unsigned int len=sizeof(szUnicodePass); + unsigned int len = 16; unsigned int i; - -#if OPENSSL_VERSION_NUMBER >= 0x30000000L - const EVP_MD *md4 = md4_hash; -#else - const EVP_MD *md4 = EVP_md4(); -#endif - if(md4 == NULL) return NULL; + mdh_ctx *ctx; /* * NT passwords are unicode. Convert plain text password @@ -71,15 +65,14 @@ unsigned char * ntpwdhash (unsigned char *szHash, const unsigned char *szPasswor } /* Encrypt Unicode password to a 16-byte MD4 hash */ - ctx = EVP_MD_CTX_new(); + ctx = mdh_init(MDH_MD4); if(!ctx) return NULL; - if(!EVP_DigestInit_ex(ctx, md4, NULL)){ - EVP_MD_CTX_free(ctx); - return NULL; + mdh_update(ctx, szUnicodePass, (nPasswordLen<<1)); + if(!mdh_final(ctx, szUnicodePass, &len)) { + mdh_free(ctx); + return NULL; } - EVP_DigestUpdate(ctx, szUnicodePass, (nPasswordLen<<1)); - EVP_DigestFinal_ex(ctx, szUnicodePass, &len); - EVP_MD_CTX_free(ctx); + mdh_free(ctx); if (ctohex){ tohex(szUnicodePass, szHash, 16); } @@ -100,57 +93,45 @@ unsigned char * mycrypt(const unsigned char *pw, const unsigned char *salt, unsi int sl; unsigned long l; -#if defined(WITH_SSL) +#if defined(WITH_SSL) || defined(_WIN32) #ifndef WITHMAIN if(salt[0] == '$' && salt[1] == '1' && salt[2] == '$' && (ep = (unsigned char *)strchr((char *)salt+3, '$'))) { - EVP_MD_CTX *ctx, *ctx1; - unsigned int len; + mdh_ctx *ctx, *ctx1; + unsigned int len = MD5_SIZE; int pl, i; -#if OPENSSL_VERSION_NUMBER >= 0x30000000L - const EVP_MD *md5 = md5_hash; -#else - const EVP_MD *md5 = EVP_md5(); -#endif - if(md5 == NULL) { - *passwd = 0; - return NULL; - } - sp = salt +3; sl = (int)(ep - sp); magic = (unsigned char *)"$1$"; - ctx = EVP_MD_CTX_new(); + ctx = mdh_init(MDH_MD5); if(!ctx) { *passwd = 0; return NULL; } - EVP_DigestInit_ex(ctx, md5, NULL); /* The password first, since that is what is most unknown */ - EVP_DigestUpdate(ctx,pw,strlen((char *)pw)); + mdh_update(ctx, pw, (unsigned int)strlen((char *)pw)); /* Then our magic string */ - EVP_DigestUpdate(ctx,magic,strlen((char *)magic)); + mdh_update(ctx, magic, (unsigned int)strlen((char *)magic)); /* Then the raw salt */ - EVP_DigestUpdate(ctx,sp,sl); + mdh_update(ctx, sp, (unsigned int)sl); /* Then just as many unsigned characters of the MD5(pw,salt,pw) */ - ctx1 = EVP_MD_CTX_new(); + ctx1 = mdh_init(MDH_MD5); if(!ctx1) { - EVP_MD_CTX_free(ctx); + mdh_free(ctx); *passwd = 0; return NULL; } - EVP_DigestInit_ex(ctx1, md5, NULL); - EVP_DigestUpdate(ctx1,pw,strlen((char *)pw)); - EVP_DigestUpdate(ctx1,sp,sl); - EVP_DigestUpdate(ctx1,pw,strlen((char *)pw)); - EVP_DigestFinal_ex(ctx1,final,&len); + mdh_update(ctx1, pw, (unsigned int)strlen((char *)pw)); + mdh_update(ctx1, sp, (unsigned int)sl); + mdh_update(ctx1, pw, (unsigned int)strlen((char *)pw)); + mdh_final(ctx1, final, &len); for(pl = (int)strlen((char *)pw); pl > 0; pl -= MD5_SIZE) - EVP_DigestUpdate(ctx,final,pl>MD5_SIZE ? MD5_SIZE : pl); + mdh_update(ctx, final, (unsigned int)(pl>MD5_SIZE ? MD5_SIZE : pl)); /* Don't leave anything around in vm they could use. */ memset(final,0,sizeof final); @@ -158,13 +139,13 @@ unsigned char * mycrypt(const unsigned char *pw, const unsigned char *salt, unsi /* Then something really weird... */ for (i = (int)strlen((char *)pw); i ; i >>= 1) if(i&1) - EVP_DigestUpdate(ctx, final, 1); + mdh_update(ctx, final, 1); else - EVP_DigestUpdate(ctx, pw, 1); + mdh_update(ctx, pw, 1); - EVP_DigestFinal_ex(ctx,final,&len); - EVP_MD_CTX_free(ctx); + mdh_final(ctx, final, &len); + mdh_free(ctx); /* * and now, just to make sure things don't run too fast @@ -172,26 +153,27 @@ unsigned char * mycrypt(const unsigned char *pw, const unsigned char *salt, unsi * need 30 seconds to build a 1000 entry dictionary... */ for(i=0;i<1000;i++) { - EVP_MD_CTX_reset(ctx1); - EVP_DigestInit_ex(ctx1, md5, NULL); + mdh_free(ctx1); + ctx1 = mdh_init(MDH_MD5); + if(!ctx1) { *passwd = 0; return NULL; } if(i & 1) - EVP_DigestUpdate(ctx1,pw,strlen((char *)pw)); + mdh_update(ctx1, pw, (unsigned int)strlen((char *)pw)); else - EVP_DigestUpdate(ctx1,final,MD5_SIZE); + mdh_update(ctx1, final, MD5_SIZE); if(i % 3) - EVP_DigestUpdate(ctx1,sp,sl); + mdh_update(ctx1, sp, (unsigned int)sl); if(i % 7) - EVP_DigestUpdate(ctx1,pw,strlen((char *)pw)); + mdh_update(ctx1, pw, (unsigned int)strlen((char *)pw)); if(i & 1) - EVP_DigestUpdate(ctx1,final,MD5_SIZE); + mdh_update(ctx1, final, MD5_SIZE); else - EVP_DigestUpdate(ctx1,pw,strlen((char *)pw)); - EVP_DigestFinal_ex(ctx1,final,&len); + mdh_update(ctx1, pw, (unsigned int)strlen((char *)pw)); + mdh_final(ctx1, final, &len); } - EVP_MD_CTX_free(ctx1); + mdh_free(ctx1); } else #endif @@ -248,23 +230,23 @@ int main(int argc, char* argv[]){ unsigned i; if(argc < 2 || argc > 3) { fprintf(stderr, "usage: \n" -#ifdef WITH_SSL +#if defined(WITH_SSL) || defined(_WIN32) "\t%s \n" #endif "\t%s \n" -#ifdef WITH_SSL +#if defined(WITH_SSL) || defined(_WIN32) "Performs NT crypt if no salt specified, BLAKE2 crypt with salt\n" #else "Performs BLAKE2 crypt with salt\n" #endif , -#ifdef WITH_SSL +#if defined(WITH_SSL) || defined(_WIN32) argv[0], #endif argv[0]); return 1; } -#if defined(WITH_SSL) && OPENSSL_VERSION_NUMBER >= 0x30000000L +#if defined(WITH_SSL) && !defined(_WIN32) && OPENSSL_VERSION_NUMBER >= 0x30000000L OSSL_PROVIDER_load(NULL, "legacy"); OSSL_PROVIDER_load(NULL, "default"); md4_hash = EVP_MD_fetch(NULL, "MD4", NULL); @@ -273,7 +255,7 @@ int main(int argc, char* argv[]){ } #endif if(argc == 2) { -#ifdef WITH_SSL +#if defined(WITH_SSL) || defined(_WIN32) { unsigned char *nt = ntpwdhash(buf1, (unsigned char *)argv[1], 1); if(nt) printf("NT:%s\n", nt); } #else diff --git a/src/Makefile.inc b/src/Makefile.inc index f949826..8acfc79 100644 --- a/src/Makefile.inc +++ b/src/Makefile.inc @@ -134,7 +134,7 @@ hashtables$(OBJSUFFICS): hashtables.c proxy.h structures.h libs/blake2.h resolve$(OBJSUFFICS): resolve.c proxy.h structures.h $(CC) $(COUT)resolve$(OBJSUFFICS) $(CFLAGS) resolve.c -authradius$(OBJSUFFICS): authradius.c proxy.h structures.h +authradius$(OBJSUFFICS): authradius.c proxy.h structures.h mdhash.h $(CC) $(COUT)authradius$(OBJSUFFICS) $(CFLAGS) authradius.c conf$(OBJSUFFICS): conf.c proxy.h structures.h @@ -146,17 +146,20 @@ log$(OBJSUFFICS): log.c proxy.h structures.h datatypes$(OBJSUFFICS): datatypes.c proxy.h structures.h $(CC) $(COUT)datatypes$(OBJSUFFICS) $(CFLAGS) datatypes.c -3proxy_crypt$(OBJSUFFICS): 3proxy_crypt.c libs/blake2.h +3proxy_crypt$(OBJSUFFICS): 3proxy_crypt.c libs/blake2.h mdhash.h $(CC) $(COUT)3proxy_crypt$(OBJSUFFICS) $(CFLAGS) 3proxy_crypt.c -3proxy_cryptmain$(OBJSUFFICS): 3proxy_crypt.c libs/blake2.h +3proxy_cryptmain$(OBJSUFFICS): 3proxy_crypt.c libs/blake2.h mdhash.h $(CC) $(COUT)3proxy_cryptmain$(OBJSUFFICS) $(CFLAGS) $(DEFINEOPTION)WITHMAIN 3proxy_crypt.c blake2$(OBJSUFFICS): libs/blake2b-ref.c $(CC) $(COUT)blake2$(OBJSUFFICS) $(CFLAGS) libs/blake2b-ref.c -$(BUILDDIR)$(CRYPT_PREFIX)crypt$(EXESUFFICS): blake2$(OBJSUFFICS) 3proxy_cryptmain$(OBJSUFFICS) base64$(OBJSUFFICS) - $(LN) $(LNOUT)$(BUILDDIR)$(CRYPT_PREFIX)crypt$(EXESUFFICS) $(LDFLAGS) blake2$(OBJSUFFICS) base64$(OBJSUFFICS) 3proxy_cryptmain$(OBJSUFFICS) $(LIBS) +mdhash$(OBJSUFFICS): mdhash.c mdhash.h proxy.h structures.h + $(CC) $(COUT)mdhash$(OBJSUFFICS) $(CFLAGS) mdhash.c + +$(BUILDDIR)$(CRYPT_PREFIX)crypt$(EXESUFFICS): blake2$(OBJSUFFICS) 3proxy_cryptmain$(OBJSUFFICS) base64$(OBJSUFFICS) mdhash$(OBJSUFFICS) + $(LN) $(LNOUT)$(BUILDDIR)$(CRYPT_PREFIX)crypt$(EXESUFFICS) $(LDFLAGS) blake2$(OBJSUFFICS) base64$(OBJSUFFICS) mdhash$(OBJSUFFICS) 3proxy_cryptmain$(OBJSUFFICS) $(LIBS) stringtable$(OBJSUFFICS): stringtable.c $(CC) $(COUT)stringtable$(OBJSUFFICS) $(CFLAGS) stringtable.c @@ -170,6 +173,6 @@ ssl$(OBJSUFFICS): ssl.c structures.h proxy.h ssl.h pcre$(OBJSUFFICS): pcre.c structures.h $(CC) $(COUT)pcre$(OBJSUFFICS) $(CFLAGS) $(DEFINEOPTION)WITH_PCRE pcre.c -$(BUILDDIR)3proxy$(EXESUFFICS): 3proxy$(OBJSUFFICS) mainfunc$(OBJSUFFICS) srvproxy$(OBJSUFFICS) srvpop3p$(OBJSUFFICS) srvsmtpp$(OBJSUFFICS) srvftppr$(OBJSUFFICS) srvsocks$(OBJSUFFICS) srvtcppm$(OBJSUFFICS) srvtlspr$(OBJSUFFICS) srvauto$(OBJSUFFICS) srvudppm$(OBJSUFFICS) sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) auth$(OBJSUFFICS) acl$(OBJSUFFICS) limiter$(OBJSUFFICS) redirect$(OBJSUFFICS) authradius$(OBJSUFFICS) hash$(OBJSUFFICS) hashtables$(OBJSUFFICS) resolve$(OBJSUFFICS) sql$(OBJSUFFICS) conf$(OBJSUFFICS) log$(OBJSUFFICS) datatypes$(OBJSUFFICS) blake2$(OBJSUFFICS) 3proxy_crypt$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) stringtable$(OBJSUFFICS) srvwebadmin$(OBJSUFFICS) srvdnspr$(OBJSUFFICS) plugins$(OBJSUFFICS) $(SSL_OBJS) $(PCRE_OBJS) $(COMPATLIBS) $(VERSIONDEP) - $(LN) $(LNOUT)$(BUILDDIR)3proxy$(EXESUFFICS) $(LDFLAGS) $(VERFILE) 3proxy$(OBJSUFFICS) mainfunc$(OBJSUFFICS) auth$(OBJSUFFICS) acl$(OBJSUFFICS) limiter$(OBJSUFFICS) redirect$(OBJSUFFICS) authradius$(OBJSUFFICS) hash$(OBJSUFFICS) hashtables$(OBJSUFFICS) resolve$(OBJSUFFICS) sql$(OBJSUFFICS) conf$(OBJSUFFICS) datatypes$(OBJSUFFICS) srvauto$(OBJSUFFICS) srvproxy$(OBJSUFFICS) srvpop3p$(OBJSUFFICS) srvsmtpp$(OBJSUFFICS) srvftppr$(OBJSUFFICS) srvsocks$(OBJSUFFICS) srvtcppm$(OBJSUFFICS) srvtlspr$(OBJSUFFICS) srvudppm$(OBJSUFFICS) sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) 3proxy_crypt$(OBJSUFFICS) blake2$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) stringtable$(OBJSUFFICS) srvwebadmin$(OBJSUFFICS) srvdnspr$(OBJSUFFICS) plugins$(OBJSUFFICS) $(SSL_OBJS) $(PCRE_OBJS) $(COMPATLIBS) $(LIBS) $(PCRE_LIBS) +$(BUILDDIR)3proxy$(EXESUFFICS): 3proxy$(OBJSUFFICS) mainfunc$(OBJSUFFICS) srvproxy$(OBJSUFFICS) srvpop3p$(OBJSUFFICS) srvsmtpp$(OBJSUFFICS) srvftppr$(OBJSUFFICS) srvsocks$(OBJSUFFICS) srvtcppm$(OBJSUFFICS) srvtlspr$(OBJSUFFICS) srvauto$(OBJSUFFICS) srvudppm$(OBJSUFFICS) sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) auth$(OBJSUFFICS) acl$(OBJSUFFICS) limiter$(OBJSUFFICS) redirect$(OBJSUFFICS) authradius$(OBJSUFFICS) hash$(OBJSUFFICS) hashtables$(OBJSUFFICS) resolve$(OBJSUFFICS) sql$(OBJSUFFICS) conf$(OBJSUFFICS) log$(OBJSUFFICS) datatypes$(OBJSUFFICS) blake2$(OBJSUFFICS) 3proxy_crypt$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) stringtable$(OBJSUFFICS) srvwebadmin$(OBJSUFFICS) srvdnspr$(OBJSUFFICS) plugins$(OBJSUFFICS) mdhash$(OBJSUFFICS) $(SSL_OBJS) $(PCRE_OBJS) $(COMPATLIBS) $(VERSIONDEP) + $(LN) $(LNOUT)$(BUILDDIR)3proxy$(EXESUFFICS) $(LDFLAGS) $(VERFILE) 3proxy$(OBJSUFFICS) mainfunc$(OBJSUFFICS) auth$(OBJSUFFICS) acl$(OBJSUFFICS) limiter$(OBJSUFFICS) redirect$(OBJSUFFICS) authradius$(OBJSUFFICS) hash$(OBJSUFFICS) hashtables$(OBJSUFFICS) resolve$(OBJSUFFICS) sql$(OBJSUFFICS) conf$(OBJSUFFICS) datatypes$(OBJSUFFICS) srvauto$(OBJSUFFICS) srvproxy$(OBJSUFFICS) srvpop3p$(OBJSUFFICS) srvsmtpp$(OBJSUFFICS) srvftppr$(OBJSUFFICS) srvsocks$(OBJSUFFICS) srvtcppm$(OBJSUFFICS) srvtlspr$(OBJSUFFICS) srvudppm$(OBJSUFFICS) sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) 3proxy_crypt$(OBJSUFFICS) blake2$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) stringtable$(OBJSUFFICS) srvwebadmin$(OBJSUFFICS) srvdnspr$(OBJSUFFICS) plugins$(OBJSUFFICS) mdhash$(OBJSUFFICS) $(SSL_OBJS) $(PCRE_OBJS) $(COMPATLIBS) $(LIBS) $(PCRE_LIBS) diff --git a/src/authradius.c b/src/authradius.c index f0d73cb..a784f13 100644 --- a/src/authradius.c +++ b/src/authradius.c @@ -8,6 +8,7 @@ #ifndef NORADIUS #include "proxy.h" +#include "mdhash.h" #include #define AUTH_VECTOR_LEN 16 @@ -185,7 +186,7 @@ char *strNcpy(char *dest, const char *src, int n) return dest; } -#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#if !defined(_WIN32) && OPENSSL_VERSION_NUMBER >= 0x30000000L extern EVP_MD *md4_hash; extern EVP_MD *md5_hash; #endif @@ -194,16 +195,12 @@ extern EVP_MD *md5_hash; void md5_calc(unsigned char *output, unsigned char *input, unsigned int inlen) { - EVP_MD_CTX *ctx = EVP_MD_CTX_new(); - unsigned int len = 0; -#if OPENSSL_VERSION_NUMBER >= 0x30000000L - EVP_DigestInit_ex(ctx, md5_hash, NULL); -#else - EVP_DigestInit_ex(ctx, EVP_md5(), NULL); -#endif - EVP_DigestUpdate(ctx, input, inlen); - EVP_DigestFinal_ex(ctx, output, &len); - EVP_MD_CTX_free(ctx); + mdh_ctx *ctx = mdh_init(MDH_MD5); + unsigned int len = 16; + if(!ctx) return; + mdh_update(ctx, input, inlen); + mdh_final(ctx, output, &len); + mdh_free(ctx); } diff --git a/src/mdhash.c b/src/mdhash.c new file mode 100644 index 0000000..1a00a04 --- /dev/null +++ b/src/mdhash.c @@ -0,0 +1,129 @@ +/* + 3APA3A simplest proxy server + (c) 2002-2026 by Vladimir Dubrovin + + please read License Agreement + + MD4/MD5 hash implementation. + - Windows: CryptoAPI (CAPI). Supports both CALG_MD4 and CALG_MD5. + - Other platforms: OpenSSL EVP (requires WITH_SSL). +*/ +#include "mdhash.h" +#include + +#ifdef _WIN32 + +#define WIN32_LEAN_AND_MEAN +#include +#include + +struct mdh_ctx { + HCRYPTPROV hProv; + HCRYPTHASH hHash; +}; + +mdh_ctx *mdh_init(mdh_alg alg) +{ + mdh_ctx *c; + ALG_ID alg_id; + + c = (mdh_ctx *)malloc(sizeof(mdh_ctx)); + if(!c) return NULL; + c->hProv = 0; + c->hHash = 0; + + if(!CryptAcquireContext(&c->hProv, NULL, NULL, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT)) { + free(c); + return NULL; + } + + alg_id = (alg == MDH_MD4) ? CALG_MD4 : CALG_MD5; + if(!CryptCreateHash(c->hProv, alg_id, 0, 0, &c->hHash)) { + CryptReleaseContext(c->hProv, 0); + free(c); + return NULL; + } + return c; +} + +int mdh_update(mdh_ctx *c, const void *data, unsigned int len) +{ + if(!c || !c->hHash) return 0; + if(len == 0) return 1; + return CryptHashData(c->hHash, (BYTE *)data, len, 0) ? 1 : 0; +} + +int mdh_final(mdh_ctx *c, unsigned char *out, unsigned int *outlen) +{ + DWORD l; + BOOL ok; + + if(!c || !c->hHash || !outlen) return 0; + l = (DWORD)*outlen; + ok = CryptGetHashParam(c->hHash, HP_HASHVAL, out, &l, 0); + if(!ok) return 0; + *outlen = (unsigned int)l; + return 1; +} + +void mdh_free(mdh_ctx *c) +{ + if(!c) return; + if(c->hHash) CryptDestroyHash(c->hHash); + if(c->hProv) CryptReleaseContext(c->hProv, 0); + free(c); +} + +#else /* !_WIN32 */ + +#ifdef WITH_SSL +#include + +struct mdh_ctx { + EVP_MD_CTX *ctx; +}; + +mdh_ctx *mdh_init(mdh_alg alg) +{ + mdh_ctx *c; + const EVP_MD *md; + + c = (mdh_ctx *)malloc(sizeof(mdh_ctx)); + if(!c) return NULL; + c->ctx = EVP_MD_CTX_new(); + if(!c->ctx) { free(c); return NULL; } + md = (alg == MDH_MD4) ? EVP_md4() : EVP_md5(); + if(!EVP_DigestInit_ex(c->ctx, md, NULL)) { + EVP_MD_CTX_free(c->ctx); + free(c); + return NULL; + } + return c; +} + +int mdh_update(mdh_ctx *c, const void *data, unsigned int len) +{ + if(!c || !c->ctx) return 0; + return EVP_DigestUpdate(c->ctx, data, (size_t)len) ? 1 : 0; +} + +int mdh_final(mdh_ctx *c, unsigned char *out, unsigned int *outlen) +{ + unsigned int l = 0; + if(!c || !c->ctx || !outlen) return 0; + if(!EVP_DigestFinal_ex(c->ctx, out, &l)) return 0; + *outlen = l; + return 1; +} + +void mdh_free(mdh_ctx *c) +{ + if(!c) return; + if(c->ctx) EVP_MD_CTX_free(c->ctx); + free(c); +} + +#endif /* WITH_SSL */ + +#endif /* _WIN32 */ diff --git a/src/mdhash.h b/src/mdhash.h new file mode 100644 index 0000000..a48e5c6 --- /dev/null +++ b/src/mdhash.h @@ -0,0 +1,31 @@ +/* + 3APA3A simplest proxy server + (c) 2002-2026 by Vladimir Dubrovin + + please read License Agreement + + Internal MD4/MD5 hash abstraction. + - Windows: CryptoAPI (CAPI) backed, no OpenSSL dependency for these hashes. + - Other platforms: OpenSSL EVP backed (requires WITH_SSL). +*/ +#ifndef _MDHASH_H +#define _MDHASH_H + +typedef enum { MDH_MD4, MDH_MD5 } mdh_alg; + +typedef struct mdh_ctx mdh_ctx; + +/* Returns NULL on failure. */ +mdh_ctx *mdh_init(mdh_alg alg); + +/* Returns 1 on success, 0 on failure. */ +int mdh_update(mdh_ctx *c, const void *data, unsigned int len); + +/* outlen is in/out: caller passes buffer size, receives hash length. + Returns 1 on success, 0 on failure. */ +int mdh_final(mdh_ctx *c, unsigned char *out, unsigned int *outlen); + +/* Safe to call with NULL. */ +void mdh_free(mdh_ctx *c); + +#endif /* _MDHASH_H */ diff --git a/src/proxy.h b/src/proxy.h index e72fb25..a02a205 100644 --- a/src/proxy.h +++ b/src/proxy.h @@ -240,7 +240,7 @@ extern int paused; extern int demon; unsigned char * mycrypt(const unsigned char *key, const unsigned char *salt, unsigned char *buf); -#ifdef WITH_SSL +#if defined(WITH_SSL) || defined(_WIN32) unsigned char * ntpwdhash (unsigned char *szHash, const unsigned char *szPassword, int tohex); #endif int de64 (const unsigned char *in, unsigned char *out, int maxlen); diff --git a/src/ssllib.c b/src/ssllib.c index 8e050d6..d42530f 100644 --- a/src/ssllib.c +++ b/src/ssllib.c @@ -280,7 +280,7 @@ int ssl_file_init = 0; int ssl_init_done = 0; -#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#if !defined(_WIN32) && OPENSSL_VERSION_NUMBER >= 0x30000000L extern EVP_MD *md4_hash; extern EVP_MD *md5_hash; #endif @@ -289,14 +289,14 @@ extern EVP_MD *md5_hash; void ssl_init() { if(!ssl_init_done){ - + ssl_init_done = 1; thread_setup(); SSLeay_add_ssl_algorithms(); SSL_load_error_strings(); _3proxy_mutex_init(&ssl_file_mutex); bio_err=BIO_new_fp(stderr,BIO_NOCLOSE); -#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#if !defined(_WIN32) && OPENSSL_VERSION_NUMBER >= 0x30000000L OSSL_PROVIDER_load(NULL, "legacy"); OSSL_PROVIDER_load(NULL, "default"); md4_hash = EVP_MD_fetch(NULL, "MD4", NULL);