diff --git a/dlls/crypt32/Makefile.in b/dlls/crypt32/Makefile.in index 9fe651ce846..996044bbc37 100644 --- a/dlls/crypt32/Makefile.in +++ b/dlls/crypt32/Makefile.in @@ -1,5 +1,6 @@ EXTRADEFS = -D_CRYPT32_ MODULE = crypt32.dll +UNIXLIB = crypt32.so IMPORTLIB = crypt32 IMPORTS = user32 advapi32 bcrypt DELAYIMPORTS = cryptnet diff --git a/dlls/crypt32/crypt32_private.h b/dlls/crypt32/crypt32_private.h index 49ef40052e0..7fed1665d56 100644 --- a/dlls/crypt32/crypt32_private.h +++ b/dlls/crypt32/crypt32_private.h @@ -20,6 +20,7 @@ #define __CRYPT32_PRIVATE_H__ #include "wine/list.h" +#include "wine/unixlib.h" BOOL CNG_ImportPubKey(CERT_PUBLIC_KEY_INFO *pubKeyInfo, BCRYPT_KEY_HANDLE *key) DECLSPEC_HIDDEN; @@ -462,17 +463,53 @@ void init_empty_store(void) DECLSPEC_HIDDEN; struct cert_store_data; -struct unix_funcs +struct open_cert_store_params { - BOOL (WINAPI *enum_root_certs)( void *buffer, SIZE_T size, SIZE_T *needed ); - BOOL (WINAPI *open_cert_store)( CRYPT_DATA_BLOB *pfx, const WCHAR *password, - struct cert_store_data **data_ret ); - NTSTATUS (WINAPI *import_store_key)( struct cert_store_data *data, void *buf, DWORD *buf_size ); - NTSTATUS (WINAPI *import_store_cert)( struct cert_store_data *data, unsigned int index, - void *buf, DWORD *buf_size ); - void (WINAPI *close_cert_store)( struct cert_store_data *data ); + CRYPT_DATA_BLOB *pfx; + const WCHAR *password; + struct cert_store_data **data_ret; }; -extern const struct unix_funcs *unix_funcs DECLSPEC_HIDDEN; +struct import_store_key_params +{ + struct cert_store_data *data; + void *buf; + DWORD *buf_size; +}; + +struct import_store_cert_params +{ + struct cert_store_data *data; + unsigned int index; + void *buf; + DWORD *buf_size; +}; + +struct close_cert_store_params +{ + struct cert_store_data *data; +}; + +struct enum_root_certs_params +{ + void *buffer; + DWORD size; + DWORD *needed; +}; + +enum unix_funcs +{ + unix_process_attach, + unix_process_detach, + unix_open_cert_store, + unix_import_store_key, + unix_import_store_cert, + unix_close_cert_store, + unix_enum_root_certs, +}; + +extern unixlib_handle_t crypt32_handle; + +#define CRYPT32_CALL( func, params ) __wine_unix_call( crypt32_handle, unix_ ## func, params ) #endif diff --git a/dlls/crypt32/main.c b/dlls/crypt32/main.c index 4189da5a505..94dabbe6fc7 100644 --- a/dlls/crypt32/main.c +++ b/dlls/crypt32/main.c @@ -34,7 +34,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(crypt); static HCRYPTPROV hDefProv; HINSTANCE hInstance; -const struct unix_funcs *unix_funcs = NULL; +unixlib_handle_t crypt32_handle = 0; static CRITICAL_SECTION prov_param_cs; static CRITICAL_SECTION_DEBUG prov_param_cs_debug = @@ -55,7 +55,10 @@ BOOL WINAPI DllMain(HINSTANCE hInst, DWORD reason, PVOID pvReserved) DisableThreadLibraryCalls(hInst); init_empty_store(); crypt_oid_init(); - __wine_init_unix_lib( hInst, reason, NULL, &unix_funcs ); + if (NtQueryVirtualMemory( GetCurrentProcess(), hInst, MemoryWineUnixFuncs, + &crypt32_handle, sizeof(crypt32_handle), NULL )) + return FALSE; + CRYPT32_CALL( process_attach, NULL ); break; case DLL_PROCESS_DETACH: if (pvReserved) break; @@ -63,7 +66,7 @@ BOOL WINAPI DllMain(HINSTANCE hInst, DWORD reason, PVOID pvReserved) crypt_sip_free(); default_chain_engine_free(); if (hDefProv) CryptReleaseContext(hDefProv, 0); - __wine_init_unix_lib( hInst, reason, NULL, NULL ); + CRYPT32_CALL( process_detach, NULL ); break; } return TRUE; diff --git a/dlls/crypt32/pfx.c b/dlls/crypt32/pfx.c index eca4c788784..1dd048c2b67 100644 --- a/dlls/crypt32/pfx.c +++ b/dlls/crypt32/pfx.c @@ -38,8 +38,9 @@ static HCRYPTPROV import_key( struct cert_store_data *data, DWORD flags ) HCRYPTKEY cryptkey; DWORD size, acquire_flags; void *key; + struct import_store_key_params params = { data, NULL, &size }; - if (unix_funcs->import_store_key( data, NULL, &size ) != STATUS_BUFFER_TOO_SMALL) return 0; + if (CRYPT32_CALL( import_store_key, ¶ms ) != STATUS_BUFFER_TOO_SMALL) return 0; acquire_flags = (flags & CRYPT_MACHINE_KEYSET) | CRYPT_NEWKEYSET; if (!CryptAcquireContextW( &prov, NULL, MS_ENHANCED_PROV_W, PROV_RSA_FULL, acquire_flags )) @@ -54,8 +55,8 @@ static HCRYPTPROV import_key( struct cert_store_data *data, DWORD flags ) } } - key = malloc( size ); - if (unix_funcs->import_store_key( data, key, &size ) || + params.buf = key = malloc( size ); + if (CRYPT32_CALL( import_store_key, ¶ms ) || !CryptImportKey( prov, key, size, 0, flags & CRYPT_EXPORTABLE, &cryptkey )) { WARN( "CryptImportKey failed %08x\n", GetLastError() ); @@ -145,6 +146,8 @@ HCERTSTORE WINAPI PFXImportCertStore( CRYPT_DATA_BLOB *pfx, const WCHAR *passwor HCERTSTORE store = NULL; HCRYPTPROV prov = 0; struct cert_store_data *data = NULL; + struct open_cert_store_params open_params = { pfx, password, &data }; + struct close_cert_store_params close_params; if (!pfx) { @@ -156,12 +159,7 @@ HCERTSTORE WINAPI PFXImportCertStore( CRYPT_DATA_BLOB *pfx, const WCHAR *passwor FIXME( "flags %08x not supported\n", flags ); return NULL; } - if (!unix_funcs->open_cert_store) - { - FIXME( "(%p, %p, %08x)\n", pfx, password, flags ); - return NULL; - } - if (!unix_funcs->open_cert_store( pfx, password, &data )) return NULL; + if (CRYPT32_CALL( open_cert_store, &open_params )) return NULL; prov = import_key( data, flags ); if (!prov) goto error; @@ -176,10 +174,11 @@ HCERTSTORE WINAPI PFXImportCertStore( CRYPT_DATA_BLOB *pfx, const WCHAR *passwor { const void *ctx = NULL; void *cert; + struct import_store_cert_params import_params = { data, i, NULL, &size }; - if (unix_funcs->import_store_cert( data, i, NULL, &size ) != STATUS_BUFFER_TOO_SMALL) break; - cert = malloc( size ); - if (!unix_funcs->import_store_cert( data, i++, cert, &size )) + if (CRYPT32_CALL( import_store_cert, &import_params ) != STATUS_BUFFER_TOO_SMALL) break; + import_params.buf = cert = malloc( size ); + if (!CRYPT32_CALL( import_store_cert, &import_params )) ctx = CertCreateContext( CERT_STORE_CERTIFICATE_CONTEXT, X509_ASN_ENCODING, cert, size, 0, NULL ); free( cert ); if (!ctx) @@ -209,14 +208,17 @@ HCERTSTORE WINAPI PFXImportCertStore( CRYPT_DATA_BLOB *pfx, const WCHAR *passwor goto error; } CertFreeCertificateContext( ctx ); + i++; } - unix_funcs->close_cert_store( data ); + close_params.data = data; + CRYPT32_CALL( close_cert_store, &close_params ); return store; error: CryptReleaseContext( prov, 0 ); CertCloseStore( store, 0 ); - if (data) unix_funcs->close_cert_store( data ); + close_params.data = data; + CRYPT32_CALL( close_cert_store, &close_params ); return NULL; } diff --git a/dlls/crypt32/rootstore.c b/dlls/crypt32/rootstore.c index d93de8fb37a..82620428397 100644 --- a/dlls/crypt32/rootstore.c +++ b/dlls/crypt32/rootstore.c @@ -18,6 +18,8 @@ #include #include +#include + #include "ntstatus.h" #define WIN32_NO_STATUS #include "windef.h" @@ -615,24 +617,24 @@ static void read_trusted_roots_from_known_locations(HCERTSTORE store) { HCERTSTORE from = CertOpenStore(CERT_STORE_PROV_MEMORY, X509_ASN_ENCODING, 0, CERT_STORE_CREATE_NEW_FLAG, NULL); - SIZE_T needed, size = 2048; - void *buffer; + DWORD needed; + struct enum_root_certs_params params = { NULL, 2048, &needed }; if (from) { - buffer = HeapAlloc( GetProcessHeap(), 0, size ); - while (unix_funcs->enum_root_certs( buffer, size, &needed )) + params.buffer = malloc( params.size ); + while (!CRYPT32_CALL( enum_root_certs, ¶ms )) { - if (needed > size) + if (needed > params.size) { - HeapFree( GetProcessHeap(), 0, buffer ); - buffer = HeapAlloc( GetProcessHeap(), 0, needed ); - size = needed; + free( params.buffer ); + params.buffer = malloc( needed ); + params.size = needed; } - else CertAddEncodedCertificateToStore( from, X509_ASN_ENCODING, buffer, needed, + else CertAddEncodedCertificateToStore( from, X509_ASN_ENCODING, params.buffer, needed, CERT_STORE_ADD_NEW, NULL ); } - HeapFree( GetProcessHeap(), 0, buffer ); + free( params.buffer ); check_and_store_certs(from, store); } CertCloseStore(from, 0); diff --git a/dlls/crypt32/unixlib.c b/dlls/crypt32/unixlib.c index b3cfd95771c..7cb521eb98b 100644 --- a/dlls/crypt32/unixlib.c +++ b/dlls/crypt32/unixlib.c @@ -21,15 +21,14 @@ #endif #include "config.h" -#include "wine/port.h" #include +#include #include #include #include -#ifdef HAVE_SYS_STAT_H +#include #include -#endif #ifdef HAVE_SECURITY_SECURITY_H #include #endif @@ -43,11 +42,8 @@ #include "winbase.h" #include "winternl.h" #include "wincrypt.h" -#include "snmp.h" #include "crypt32_private.h" - #include "wine/debug.h" -#include "wine/heap.h" WINE_DEFAULT_DEBUG_CHANNEL(crypt); @@ -84,7 +80,7 @@ static void gnutls_log( int level, const char *msg ) TRACE( "<%d> %s", level, msg ); } -static BOOL gnutls_initialize(void) +static NTSTATUS process_attach( void *args ) { const char *env_str; int ret; @@ -102,7 +98,7 @@ static BOOL gnutls_initialize(void) if (!(libgnutls_handle = dlopen( SONAME_LIBGNUTLS, RTLD_NOW ))) { ERR_(winediag)( "failed to load libgnutls, no support for pfx import/export\n" ); - return FALSE; + return STATUS_DLL_NOT_FOUND; } #define LOAD_FUNCPTR(f) \ @@ -143,14 +139,15 @@ static BOOL gnutls_initialize(void) fail: dlclose( libgnutls_handle ); libgnutls_handle = NULL; - return FALSE; + return STATUS_DLL_INIT_FAILED; } -static void gnutls_uninitialize(void) +static NTSTATUS process_detach( void *args ) { pgnutls_global_deinit(); dlclose( libgnutls_handle ); libgnutls_handle = NULL; + return STATUS_SUCCESS; } #define RSA_MAGIC_KEY ('R' | ('S' << 8) | ('A' << 16) | ('2' << 24)) #define RSA_PUBEXP 65537 @@ -164,8 +161,10 @@ struct cert_store_data unsigned int chain_len; }; -static NTSTATUS WINAPI import_store_key( struct cert_store_data *data, void *buf, DWORD *buf_size ) +static NTSTATUS import_store_key( void *args ) { + struct import_store_key_params *params = args; + struct cert_store_data *data = params->data; int i, ret; unsigned int bitlen = data->key_bitlen; gnutls_datum_t m, e, d, p, q, u, e1, e2; @@ -175,9 +174,9 @@ static NTSTATUS WINAPI import_store_key( struct cert_store_data *data, void *buf DWORD size; size = sizeof(*hdr) + sizeof(*rsakey) + (bitlen * 9 / 16); - if (!buf || *buf_size < size) + if (!params->buf || *params->buf_size < size) { - *buf_size = size; + *params->buf_size = size; return STATUS_BUFFER_TOO_SMALL; } @@ -187,7 +186,7 @@ static NTSTATUS WINAPI import_store_key( struct cert_store_data *data, void *buf return STATUS_INVALID_PARAMETER; } - hdr = (BLOBHEADER *)buf; + hdr = params->buf; hdr->bType = PRIVATEKEYBLOB; hdr->bVersion = CUR_BLOB_VERSION; hdr->reserved = 0; @@ -261,9 +260,9 @@ static char *password_to_ascii( const WCHAR *str ) return ret; } -static BOOL WINAPI open_cert_store( CRYPT_DATA_BLOB *pfx, const WCHAR *password, - struct cert_store_data **data_ret ) +static NTSTATUS open_cert_store( void *args ) { + struct open_cert_store_params *params = args; gnutls_pkcs12_t p12; gnutls_datum_t pfx_data; gnutls_x509_privkey_t key; @@ -274,12 +273,13 @@ static BOOL WINAPI open_cert_store( CRYPT_DATA_BLOB *pfx, const WCHAR *password, int ret; struct cert_store_data *store_data; - if (password && !(pwd = password_to_ascii( password ))) return FALSE; + if (!libgnutls_handle) return STATUS_DLL_NOT_FOUND; + if (params->password && !(pwd = password_to_ascii( params->password ))) return STATUS_NO_MEMORY; if ((ret = pgnutls_pkcs12_init( &p12 )) < 0) goto error; - pfx_data.data = pfx->pbData; - pfx_data.size = pfx->cbData; + pfx_data.data = params->pfx->pbData; + pfx_data.size = params->pfx->cbData; if ((ret = pgnutls_pkcs12_import( p12, &pfx_data, GNUTLS_X509_FMT_DER, 0 )) < 0) goto error; if ((ret = pgnutls_pkcs12_simple_parse( p12, pwd ? pwd : "", &key, &chain, &chain_len, NULL, NULL, NULL, 0 )) < 0) @@ -294,7 +294,7 @@ static BOOL WINAPI open_cert_store( CRYPT_DATA_BLOB *pfx, const WCHAR *password, { FIXME( "key algorithm %u not supported\n", ret ); pgnutls_pkcs12_deinit( p12 ); - return FALSE; + return STATUS_INVALID_PARAMETER; } store_data = malloc( sizeof(*store_data) ); @@ -303,44 +303,60 @@ static BOOL WINAPI open_cert_store( CRYPT_DATA_BLOB *pfx, const WCHAR *password, store_data->chain = chain; store_data->key_bitlen = bitlen; store_data->chain_len = chain_len; - *data_ret = store_data; - return TRUE; + *params->data_ret = store_data; + return STATUS_SUCCESS; error: pgnutls_perror( ret ); pgnutls_pkcs12_deinit( p12 ); free( pwd ); - return FALSE; + return STATUS_INVALID_PARAMETER; } -static NTSTATUS WINAPI import_store_cert( struct cert_store_data *data, unsigned int index, - void *buf, DWORD *buf_size ) +static NTSTATUS import_store_cert( void *args ) { + struct import_store_cert_params *params = args; + struct cert_store_data *data = params->data; size_t size = 0; int ret; - if (index >= data->chain_len) return STATUS_NO_MORE_ENTRIES; + if (params->index >= data->chain_len) return STATUS_NO_MORE_ENTRIES; - if ((ret = pgnutls_x509_crt_export( data->chain[index], GNUTLS_X509_FMT_DER, NULL, &size )) != GNUTLS_E_SHORT_MEMORY_BUFFER) + if ((ret = pgnutls_x509_crt_export( data->chain[params->index], GNUTLS_X509_FMT_DER, NULL, &size )) != GNUTLS_E_SHORT_MEMORY_BUFFER) return STATUS_INVALID_PARAMETER; - if (!buf || *buf_size < size) + if (!params->buf || *params->buf_size < size) { - *buf_size = size; + *params->buf_size = size; return STATUS_BUFFER_TOO_SMALL; } - if ((ret = pgnutls_x509_crt_export( data->chain[index], GNUTLS_X509_FMT_DER, buf, &size )) < 0) + if ((ret = pgnutls_x509_crt_export( data->chain[params->index], GNUTLS_X509_FMT_DER, params->buf, &size )) < 0) return STATUS_INVALID_PARAMETER; return STATUS_SUCCESS; } -static void WINAPI close_cert_store( struct cert_store_data *data ) +static NTSTATUS close_cert_store( void *args ) { - pgnutls_pkcs12_deinit( data->p12 ); - free( data ); + struct close_cert_store_params *params = args; + + if (params->data) + { + pgnutls_pkcs12_deinit( params->data->p12 ); + free( params->data ); + } + return STATUS_SUCCESS; } +#else /* SONAME_LIBGNUTLS */ + +static NTSTATUS process_attach( void *args ) { return STATUS_SUCCESS; } +static NTSTATUS process_detach( void *args ) { return STATUS_SUCCESS; } +static NTSTATUS open_cert_store( void *args ) { return STATUS_DLL_NOT_FOUND; } +static NTSTATUS import_store_key( void *args ) { return STATUS_DLL_NOT_FOUND; } +static NTSTATUS import_store_cert( void *args ) { return STATUS_DLL_NOT_FOUND; } +static NTSTATUS close_cert_store( void *args ) { return STATUS_DLL_NOT_FOUND; } + #endif /* SONAME_LIBGNUTLS */ struct root_cert @@ -640,8 +656,9 @@ static void load_root_certs(void) import_certs_from_path( CRYPT_knownLocations[i], TRUE ); } -static BOOL WINAPI enum_root_certs( void *buffer, SIZE_T size, SIZE_T *needed ) +static NTSTATUS enum_root_certs( void *args ) { + struct enum_root_certs_params *params = args; static BOOL loaded; struct list *ptr; struct root_cert *cert; @@ -649,45 +666,25 @@ static BOOL WINAPI enum_root_certs( void *buffer, SIZE_T size, SIZE_T *needed ) if (!loaded) load_root_certs(); loaded = TRUE; - if (!(ptr = list_head( &root_cert_list ))) return FALSE; + if (!(ptr = list_head( &root_cert_list ))) return STATUS_NO_MORE_ENTRIES; cert = LIST_ENTRY( ptr, struct root_cert, entry ); - *needed = cert->size; - if (cert->size <= size) + *params->needed = cert->size; + if (cert->size <= params->size) { - memcpy( buffer, cert->data, cert->size ); + memcpy( params->buffer, cert->data, cert->size ); list_remove( &cert->entry ); free( cert ); } - return TRUE; -} - -static struct unix_funcs funcs = -{ - enum_root_certs, - NULL -}; - -NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out ) -{ - switch (reason) - { - case DLL_PROCESS_ATTACH: -#ifdef SONAME_LIBGNUTLS - if (gnutls_initialize()) - { - funcs.open_cert_store = open_cert_store; - funcs.import_store_key = import_store_key; - funcs.import_store_cert = import_store_cert; - funcs.close_cert_store = close_cert_store; - } -#endif - *(const struct unix_funcs **)ptr_out = &funcs; - break; - case DLL_PROCESS_DETACH: -#ifdef SONAME_LIBGNUTLS - if (libgnutls_handle) gnutls_uninitialize(); -#endif - break; - } return STATUS_SUCCESS; } + +unixlib_entry_t __wine_unix_call_funcs[] = +{ + process_attach, + process_detach, + open_cert_store, + import_store_key, + import_store_cert, + close_cert_store, + enum_root_certs, +};