#ifdef OPENSSL_SYS_WIN32
#ifndef OPENSSL_NO_CAPIENG
-#if _WIN32_WINNT < 0x0500
-#define _WIN32_WINNT 0x0500
-#endif
#include <windows.h>
+
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0400
+#endif
+
#include <wincrypt.h>
#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 <openssl/engine.h>
#include <openssl/pem.h>
+#include <openssl/x509v3.h>
#include "e_capi_err.h"
#include "e_capi_err.c"
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);
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.
/* 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" */
#define CAPI_DMP_PKEYINFO 0x20
DWORD dump_flags;
+ int (*client_cert_select)(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs);
+
+ CERTDLG certselectdlg;
+ GETCONSWIN getconswindow;
};
#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,
"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}
};
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);
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:
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;
}
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);
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);
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);
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;
}
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.
*/
/* 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 */
}
-#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 <PrSht.h>
-#include <cryptuiapi.h>
+/* 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;
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;
}
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)
}
#endif
+#endif
+#else /* !WIN32 */
+#include <openssl/engine.h>
+#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