X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=engines%2Fe_capi.c;h=e2a7cb58b0037cf0b31f4b2b75dd12fb749ab900;hb=3081e2ca7311526555954ab10ef094ec90d17b43;hp=95c6aecbb12a7a755a2d4bfdf04b5bda3a395eb9;hpb=1cd504e7bea3c7197e89864f7689b52da497d9a3;p=oweals%2Fopenssl.git diff --git a/engines/e_capi.c b/engines/e_capi.c index 95c6aecbb1..e2a7cb58b0 100644 --- a/engines/e_capi.c +++ b/engines/e_capi.c @@ -56,20 +56,56 @@ #include #include #include -#include #include #ifdef OPENSSL_SYS_WIN32 #ifndef OPENSSL_NO_CAPIENG +#include + #include + +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0400 +#endif + #include +/* + * This module uses several "new" interfaces, among which is + * CertGetCertificateContextProperty. CERT_KEY_PROV_INFO_PROP_ID is + * one of possible values you can pass to function in question. By + * checking if it's defined we can see if wincrypt.h and accompanying + * crypt32.lib are in shape. Yes, it's rather "weak" test and if + * compilation fails, then re-configure with -DOPENSSL_NO_CAPIENG. + */ +#ifdef CERT_KEY_PROV_INFO_PROP_ID +# define __COMPILE_CAPIENG +#endif /* CERT_KEY_PROV_INFO_PROP_ID */ +#endif /* OPENSSL_NO_CAPIENG */ +#endif /* OPENSSL_SYS_WIN32 */ + +#ifdef __COMPILE_CAPIENG + #undef X509_EXTENSIONS #undef X509_CERT_PAIR +/* Definitions which may be missing from earlier version of headers */ +#ifndef CERT_STORE_OPEN_EXISTING_FLAG +#define CERT_STORE_OPEN_EXISTING_FLAG 0x00004000 +#endif + +#ifndef CERT_STORE_CREATE_NEW_FLAG +#define CERT_STORE_CREATE_NEW_FLAG 0x00002000 +#endif + +#ifndef CERT_SYSTEM_STORE_CURRENT_USER +#define CERT_SYSTEM_STORE_CURRENT_USER 0x00010000 +#endif + #include #include +#include #include "e_capi_err.h" #include "e_capi_err.c" @@ -136,19 +172,21 @@ struct CAPI_CTX_st { char *debug_file; /* Parameters to use for container lookup */ DWORD keytype; - LPTSTR cspname; + LPSTR cspname; DWORD csptype; /* Certificate store name to use */ - LPTSTR storename; - LPTSTR ssl_client_store; + LPSTR storename; + LPSTR ssl_client_store; + /* System store flags */ + DWORD store_flags; /* Lookup string meanings in load_private_key */ /* Substring of subject: uses "storename" */ -#define CAPI_LU_SUBSTR 0 +#define CAPI_LU_SUBSTR 1 /* Friendly name: uses storename */ -#define CAPI_LU_FNAME 1 +#define CAPI_LU_FNAME 2 /* Container name: uses cspname, keytype */ -#define CAPI_LU_CONTNAME 2 +#define CAPI_LU_CONTNAME 3 int lookup_method; /* Info to dump with dumpcerts option */ /* Issuer and serial name strings */ @@ -190,6 +228,7 @@ static int capi_ctx_set_provname_idx(CAPI_CTX *ctx, int idx); #define CAPI_CMD_LIST_OPTIONS (ENGINE_CMD_BASE + 10) #define CAPI_CMD_LOOKUP_METHOD (ENGINE_CMD_BASE + 11) #define CAPI_CMD_STORE_NAME (ENGINE_CMD_BASE + 12) +#define CAPI_CMD_STORE_FLAGS (ENGINE_CMD_BASE + 13) static const ENGINE_CMD_DEFN capi_cmd_defns[] = { {CAPI_CMD_LIST_CERTS, @@ -245,6 +284,10 @@ static const ENGINE_CMD_DEFN capi_cmd_defns[] = { "store_name", "certificate store name, default \"MY\"", ENGINE_CMD_FLAG_STRING}, + {CAPI_CMD_STORE_FLAGS, + "store_flags", + "Certificate store flags: 1 = system store", + ENGINE_CMD_FLAG_NUMERIC}, {0, NULL, NULL, 0} }; @@ -291,6 +334,20 @@ static int capi_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void)) CAPI_trace(ctx, "Setting store name to %s\n", p); break; + case CAPI_CMD_STORE_FLAGS: + if (i & 1) + { + ctx->store_flags |= CERT_SYSTEM_STORE_LOCAL_MACHINE; + ctx->store_flags &= ~CERT_SYSTEM_STORE_CURRENT_USER; + } + else + { + ctx->store_flags |= CERT_SYSTEM_STORE_CURRENT_USER; + ctx->store_flags &= ~CERT_SYSTEM_STORE_LOCAL_MACHINE; + } + CAPI_trace(ctx, "Setting flags to %d\n", i); + break; + case CAPI_CMD_DEBUG_LEVEL: ctx->debug_level = (int)i; CAPI_trace(ctx, "Setting debug level to %d\n", ctx->debug_level); @@ -405,13 +462,12 @@ static int capi_init(ENGINE *e) #ifdef OPENSSL_CAPIENG_DIALOG { HMODULE cryptui = LoadLibrary(TEXT("CRYPTUI.DLL")); - HMODULE kernel = LoadLibrary(TEXT("KERNEL32.DLL")); + HMODULE kernel = GetModuleHandle(TEXT("KERNEL32.DLL")); if (cryptui) ctx->certselectdlg = (CERTDLG)GetProcAddress(cryptui, "CryptUIDlgSelectCertificateFromStore"); if (kernel) ctx->getconswindow = (GETCONSWIN)GetProcAddress(kernel, "GetConsoleWindow"); - if (cryptui) -// if (cryptui && !OPENSSL_isservice()) + if (cryptui && !OPENSSL_isservice()) ctx->client_cert_select = cert_select_dialog; } #endif @@ -680,7 +736,7 @@ static EVP_PKEY *capi_get_pkey(ENGINE *eng, CAPI_KEY *key) return ret; memerr: - CAPIerr(CAPI_F_CAPI_LOAD_PRIVKEY, ERR_R_MALLOC_FAILURE); + CAPIerr(CAPI_F_CAPI_GET_PKEY, ERR_R_MALLOC_FAILURE); goto err; } @@ -787,7 +843,7 @@ int capi_rsa_sign(int dtype, const unsigned char *m, unsigned int m_len, /* Finally sign it */ slen = RSA_size(rsa); - if(!CryptSignHash(hash, capi_key->keyspec, NULL, 0, sigret, &slen)) + if(!CryptSignHashA(hash, capi_key->keyspec, NULL, 0, sigret, &slen)) { CAPIerr(CAPI_F_CAPI_RSA_SIGN, CAPI_R_ERROR_SIGNING_HASH); capi_addlasterror(); @@ -925,7 +981,7 @@ static DSA_SIG *capi_dsa_do_sign(const unsigned char *digest, int dlen, /* Finally sign it */ slen = sizeof(csigbuf); - if(!CryptSignHash(hash, capi_key->keyspec, NULL, 0, csigbuf, &slen)) + if(!CryptSignHashA(hash, capi_key->keyspec, NULL, 0, csigbuf, &slen)) { CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_ERROR_SIGNING_HASH); capi_addlasterror(); @@ -1000,15 +1056,29 @@ static void capi_adderror(DWORD err) static char *wide_to_asc(LPWSTR wstr) { char *str; + int len_0,sz; + if (!wstr) return NULL; - str = OPENSSL_malloc(wcslen(wstr) + 1); + len_0 = (int)wcslen(wstr)+1; /* WideCharToMultiByte expects int */ + sz = WideCharToMultiByte(CP_ACP,0,wstr,len_0,NULL,0,NULL,NULL); + if (!sz) + { + CAPIerr(CAPI_F_WIDE_TO_ASC, CAPI_R_WIN32_ERROR); + return NULL; + } + str = OPENSSL_malloc(sz); if (!str) { CAPIerr(CAPI_F_WIDE_TO_ASC, ERR_R_MALLOC_FAILURE); return NULL; } - sprintf(str, "%S", wstr); + if (!WideCharToMultiByte(CP_ACP,0,wstr,len_0,str,sz,NULL,NULL)) + { + OPENSSL_free(str); + CAPIerr(CAPI_F_WIDE_TO_ASC, CAPI_R_WIN32_ERROR); + return NULL; + } return str; } @@ -1017,7 +1087,7 @@ static int capi_get_provname(CAPI_CTX *ctx, LPSTR *pname, DWORD *ptype, DWORD id LPSTR name; DWORD len, err; CAPI_trace(ctx, "capi_get_provname, index=%d\n", idx); - if (!CryptEnumProviders(idx, NULL, 0, ptype, NULL, &len)) + if (!CryptEnumProvidersA(idx, NULL, 0, ptype, NULL, &len)) { err = GetLastError(); if (err == ERROR_NO_MORE_ITEMS) @@ -1027,7 +1097,7 @@ static int capi_get_provname(CAPI_CTX *ctx, LPSTR *pname, DWORD *ptype, DWORD id return 0; } name = OPENSSL_malloc(len); - if (!CryptEnumProviders(idx, NULL, 0, ptype, name, &len)) + if (!CryptEnumProvidersA(idx, NULL, 0, ptype, name, &len)) { err = GetLastError(); if (err == ERROR_NO_MORE_ITEMS) @@ -1046,7 +1116,7 @@ static int capi_list_providers(CAPI_CTX *ctx, BIO *out) { DWORD idx, ptype; int ret; - LPTSTR provname = NULL; + LPSTR provname = NULL; CAPI_trace(ctx, "capi_list_providers\n"); BIO_printf(out, "Available CSPs:\n"); for(idx = 0; ; idx++) @@ -1069,7 +1139,7 @@ static int capi_list_containers(CAPI_CTX *ctx, BIO *out) DWORD err, idx, flags, buflen = 0, clen; LPSTR cname; CAPI_trace(ctx, "Listing containers CSP=%s, type = %d\n", ctx->cspname, ctx->csptype); - if (!CryptAcquireContext(&hprov, NULL, ctx->cspname, ctx->csptype, CRYPT_VERIFYCONTEXT)) + if (!CryptAcquireContextA(&hprov, NULL, ctx->cspname, ctx->csptype, CRYPT_VERIFYCONTEXT)) { CAPIerr(CAPI_F_CAPI_LIST_CONTAINERS, CAPI_R_CRYPTACQUIRECONTEXT_ERROR); capi_addlasterror(); @@ -1255,7 +1325,8 @@ HCERTSTORE capi_open_store(CAPI_CTX *ctx, char *storename) storename = "MY"; CAPI_trace(ctx, "Opening certificate store %s\n", storename); - hstore = CertOpenSystemStore(0, storename); + hstore = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, 0, + ctx->store_flags, storename); if (!hstore) { CAPIerr(CAPI_F_CAPI_OPEN_STORE, CAPI_R_ERROR_OPENING_STORE); @@ -1348,7 +1419,7 @@ static CAPI_KEY *capi_get_key(CAPI_CTX *ctx, const char *contname, char *provnam key = OPENSSL_malloc(sizeof(CAPI_KEY)); CAPI_trace(ctx, "capi_get_key, contname=%s, provname=%s, type=%d\n", contname, provname, ptype); - if (!CryptAcquireContext(&key->hprov, contname, provname, ptype, 0)) + if (!CryptAcquireContextA(&key->hprov, contname, provname, ptype, 0)) { CAPIerr(CAPI_F_CAPI_GET_KEY, CAPI_R_CRYPTACQUIRECONTEXT_ERROR); capi_addlasterror(); @@ -1372,7 +1443,7 @@ static CAPI_KEY *capi_get_key(CAPI_CTX *ctx, const char *contname, char *provnam static CAPI_KEY *capi_get_cert_key(CAPI_CTX *ctx, PCCERT_CONTEXT cert) { - CAPI_KEY *key; + CAPI_KEY *key = NULL; CRYPT_KEY_PROV_INFO *pinfo = NULL; char *provname = NULL, *contname = NULL; pinfo = capi_get_prov_info(ctx, cert); @@ -1381,8 +1452,7 @@ static CAPI_KEY *capi_get_cert_key(CAPI_CTX *ctx, PCCERT_CONTEXT cert) provname = wide_to_asc(pinfo->pwszProvName); contname = wide_to_asc(pinfo->pwszContainerName); if (!provname || !contname) - return 0; - + goto err; key = capi_get_key(ctx, contname, provname, pinfo->dwProvType, pinfo->dwKeySpec); @@ -1455,6 +1525,9 @@ static CAPI_CTX *capi_ctx_new() ctx->keytype = AT_KEYEXCHANGE; ctx->storename = NULL; ctx->ssl_client_store = NULL; + ctx->store_flags = CERT_STORE_OPEN_EXISTING_FLAG | + CERT_STORE_READONLY_FLAG | + CERT_SYSTEM_STORE_CURRENT_USER; ctx->lookup_method = CAPI_LU_SUBSTR; ctx->debug_level = 0; ctx->debug_file = NULL; @@ -1484,7 +1557,7 @@ static int capi_ctx_set_provname(CAPI_CTX *ctx, LPSTR pname, DWORD type, int che if (check) { HCRYPTPROV hprov; - if (!CryptAcquireContext(&hprov, NULL, pname, type, + if (!CryptAcquireContextA(&hprov, NULL, pname, type, CRYPT_VERIFYCONTEXT)) { CAPIerr(CAPI_F_CAPI_CTX_SET_PROVNAME, CAPI_R_CRYPTACQUIRECONTEXT_ERROR); @@ -1563,11 +1636,15 @@ static int capi_load_ssl_client_cert(ENGINE *e, SSL *ssl, CAPI_trace(ctx, "Can't Parse Certificate %d\n", i); continue; } - if (cert_issuer_match(ca_dn, x)) + if (cert_issuer_match(ca_dn, x) + && X509_check_purpose(x, X509_PURPOSE_SSL_CLIENT, 0)) { key = capi_get_cert_key(ctx, cert); if (!key) + { + X509_free(x); continue; + } /* Match found: attach extra data to it so * we can retrieve the key later. */ @@ -1642,8 +1719,14 @@ static int cert_select_simple(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs) * CryptUIDlgSelectCertificateFromStore() to produce a dialog box. */ -#include -#include +/* Definitions which are in cryptuiapi.h but this is not present in older + * versions of headers. + */ + +#ifndef CRYPTUI_SELECT_LOCATION_COLUMN +#define CRYPTUI_SELECT_LOCATION_COLUMN 0x000000010 +#define CRYPTUI_SELECT_INTENDEDUSE_COLUMN 0x000000004 +#endif #define dlg_title L"OpenSSL Application SSL Client Certificate Selection" #define dlg_prompt L"Select a certificate to use for authentication" @@ -1667,7 +1750,7 @@ static int cert_select_dialog(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs) CERT_STORE_CREATE_NEW_FLAG, NULL); if (!dstore) { - CAPIerr(CAPI_F_CLIENT_CERT_SELECT, CAPI_R_ERROR_CREATING_STORE); + CAPIerr(CAPI_F_CERT_SELECT_DIALOG, CAPI_R_ERROR_CREATING_STORE); capi_addlasterror(); goto err; } @@ -1680,13 +1763,15 @@ static int cert_select_dialog(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs) if (!CertAddCertificateContextToStore(dstore, key->pcert, CERT_STORE_ADD_NEW, NULL)) { - CAPIerr(CAPI_F_CLIENT_CERT_SELECT, CAPI_R_ERROR_ADDING_CERT); + CAPIerr(CAPI_F_CERT_SELECT_DIALOG, CAPI_R_ERROR_ADDING_CERT); capi_addlasterror(); goto err; } } - hwnd = GetActiveWindow(); + hwnd = GetForegroundWindow(); + if (!hwnd) + hwnd = GetActiveWindow(); if (!hwnd && ctx->getconswindow) hwnd = ctx->getconswindow(); /* Call dialog to select one */ @@ -1719,5 +1804,13 @@ static int cert_select_dialog(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs) } #endif +#else /* !__COMPILE_CAPIENG */ +#include +#ifndef OPENSSL_NO_DYNAMIC_ENGINE +OPENSSL_EXPORT +int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns) { return 0; } +IMPLEMENT_DYNAMIC_CHECK_FN() +#else +void ENGINE_load_capi(void){} #endif #endif