X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=engines%2Fe_capi.c;h=e98946c85a0a288c8ac925db665785f980bc32fe;hb=c60dca1f95457a9cb6deca7a4c3f81f99fe05b11;hp=f2e45c9e50bcc1315f4a94cffdbf87e7af756c47;hpb=bca68e90ccb4bca4699a8ae7183ac4d26fd7c60a;p=oweals%2Fopenssl.git diff --git a/engines/e_capi.c b/engines/e_capi.c index f2e45c9e50..e98946c85a 100644 --- a/engines/e_capi.c +++ b/engines/e_capi.c @@ -56,22 +56,36 @@ #include #include #include -#include #include #include -#include #ifdef OPENSSL_SYS_WIN32 #ifndef OPENSSL_NO_CAPIENG + +#include + #ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x400 +#define _WIN32_WINNT 0x0400 #endif -#include #include -#undef X509_NAME +#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 + +#include +#include +#include #include "e_capi_err.h" #include "e_capi_err.c" @@ -92,7 +106,6 @@ static int capi_list_providers(CAPI_CTX *ctx, BIO *out); static int capi_list_containers(CAPI_CTX *ctx, BIO *out); int capi_list_certs(CAPI_CTX *ctx, BIO *out, char *storename); void capi_free_key(CAPI_KEY *key); -static int client_cert_select(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs); static PCCERT_CONTEXT capi_find_cert(CAPI_CTX *ctx, const char *id, HCERTSTORE hstore); @@ -115,7 +128,17 @@ static int capi_dsa_free(DSA *dsa); static int capi_load_ssl_client_cert(ENGINE *e, SSL *ssl, STACK_OF(X509_NAME) *ca_dn, X509 **pcert, EVP_PKEY **pkey, STACK_OF(X509) **pother, UI_METHOD *ui_method, void *callback_data); - + +static int cert_select_simple(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs); +#ifdef OPENSSL_CAPIENG_DIALOG +static int cert_select_dialog(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs); +#endif + +typedef PCCERT_CONTEXT (WINAPI *CERTDLG)(HCERTSTORE, HWND, LPCWSTR, + LPCWSTR, DWORD, DWORD, + void *); +typedef HWND (WINAPI *GETCONSWIN)(void); + /* This structure contains CAPI ENGINE specific data: * it contains various global options and affects how * other functions behave. @@ -134,6 +157,8 @@ struct CAPI_CTX_st { /* Certificate store name to use */ LPTSTR storename; LPTSTR ssl_client_store; + /* System store flags */ + DWORD store_flags; /* Lookup string meanings in load_private_key */ /* Substring of subject: uses "storename" */ @@ -158,6 +183,10 @@ struct CAPI_CTX_st { #define CAPI_DMP_PKEYINFO 0x20 DWORD dump_flags; + int (*client_cert_select)(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs); + + CERTDLG certselectdlg; + GETCONSWIN getconswindow; }; @@ -179,6 +208,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, @@ -234,6 +264,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} }; @@ -280,6 +314,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); @@ -391,6 +439,20 @@ static int capi_init(ENGINE *e) capi_dsa_method.dsa_mod_exp = ossl_dsa_meth->dsa_mod_exp; capi_dsa_method.bn_mod_exp = ossl_dsa_meth->bn_mod_exp; +#ifdef OPENSSL_CAPIENG_DIALOG + { + HMODULE cryptui = LoadLibrary(TEXT("CRYPTUI.DLL")); + HMODULE kernel = LoadLibrary(TEXT("KERNEL32.DLL")); + if (cryptui) + ctx->certselectdlg = (CERTDLG)GetProcAddress(cryptui, "CryptUIDlgSelectCertificateFromStore"); + if (kernel) + ctx->getconswindow = (GETCONSWIN)GetProcAddress(kernel, "GetConsoleWindow"); + if (cryptui && !OPENSSL_isservice()) + ctx->client_cert_select = cert_select_dialog; + } +#endif + + return 1; memerr: @@ -654,7 +716,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; } @@ -1229,7 +1291,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); @@ -1346,7 +1409,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); @@ -1355,8 +1418,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); @@ -1429,9 +1491,13 @@ 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; + ctx->client_cert_select = cert_select_simple; return ctx; } @@ -1536,11 +1602,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. */ @@ -1569,7 +1639,7 @@ static int capi_load_ssl_client_cert(ENGINE *e, SSL *ssl, /* Select the appropriate certificate */ - client_cert_idx = client_cert_select(e, ssl, certs); + client_cert_idx = ctx->client_cert_select(e, ssl, certs); /* Set the selected certificate and free the rest */ @@ -1601,29 +1671,35 @@ static int capi_load_ssl_client_cert(ENGINE *e, SSL *ssl, } -#ifndef OPENSSL_CAPIENG_DIALOG /* Simple client cert selection function: always select first */ -static int client_cert_select(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs) +static int cert_select_simple(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs) { return 0; } -#else +#ifdef OPENSSL_CAPIENG_DIALOG /* More complex cert selection function, using standard function * CryptUIDlgSelectCertificateFromStore() to produce a dialog box. */ -#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" #define dlg_columns CRYPTUI_SELECT_LOCATION_COLUMN \ |CRYPTUI_SELECT_INTENDEDUSE_COLUMN -static int client_cert_select(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs) +static int cert_select_dialog(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs) { X509 *x; HCERTSTORE dstore; @@ -1640,7 +1716,7 @@ static int client_cert_select(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; } @@ -1653,19 +1729,20 @@ static int client_cert_select(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 = GetConsoleWindow(); + hwnd = GetActiveWindow(); + if (!hwnd && ctx->getconswindow) + hwnd = ctx->getconswindow(); /* Call dialog to select one */ - cert = CryptUIDlgSelectCertificateFromStore(dstore, hwnd, - dlg_title, dlg_prompt, - dlg_columns, 0, NULL); + cert = ctx->certselectdlg(dstore, hwnd, dlg_title, dlg_prompt, + dlg_columns, 0, NULL); /* Find matching cert from list */ if (cert) @@ -1693,5 +1770,12 @@ static int client_cert_select(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs) } #endif +#endif +#else /* !WIN32 */ +#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() #endif #endif