Avoid use of ex_data free function in Chil ENGINE so it can be safely
[openssl.git] / engines / e_capi.c
index c2e5e6445882347cba4663aa4d0f2453e8289657..e2a7cb58b0037cf0b31f4b2b75dd12fb749ab900 100644 (file)
 #include <string.h>
 #include <openssl/crypto.h>
 #include <openssl/buffer.h>
-#include <openssl/rsa.h>
 #include <openssl/bn.h>
 
 #ifdef OPENSSL_SYS_WIN32
 #ifndef OPENSSL_NO_CAPIENG
 
+#include <openssl/rsa.h>
+
 #include <windows.h>
+
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0400
+#endif
+
 #include <wincrypt.h>
 
+/*
+ * 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 <openssl/engine.h>
 #include <openssl/pem.h>
 #include <openssl/x509v3.h>
@@ -137,21 +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 */
@@ -427,7 +462,7 @@ 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)
@@ -701,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;
 
        }
@@ -808,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();
@@ -946,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();
@@ -1021,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;
        }
 
@@ -1038,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)
@@ -1048,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)
@@ -1067,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++)
@@ -1090,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();
@@ -1370,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();
@@ -1508,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);
@@ -1670,8 +1719,14 @@ static int cert_select_simple(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs)
  * 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"
@@ -1695,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;
                }
@@ -1708,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 */
@@ -1747,5 +1804,13 @@ static int cert_select_dialog(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs)
        }
 #endif
 
+#else /* !__COMPILE_CAPIENG */
+#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()
+#else
+void ENGINE_load_capi(void){}
 #endif
 #endif