static int capi_idx = -1;
static int rsa_capi_idx = -1;
static int dsa_capi_idx = -1;
+static int cert_capi_idx = -1;
static int capi_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
{
const RSA_METHOD *ossl_rsa_meth;
const DSA_METHOD *ossl_dsa_meth;
capi_idx = ENGINE_get_ex_new_index(0, NULL, NULL, NULL, 0);
+ cert_capi_idx = X509_get_ex_new_index(0, NULL, NULL, NULL, 0);
ctx = capi_ctx_new();
if (!ctx || (capi_idx < 0))
struct CAPI_KEY_st
{
+ /* Associated certificate context (if any) */
+ PCERT_CONTEXT pcert;
HCRYPTPROV hprov;
HCRYPTKEY key;
DWORD keyspec;
goto err;
}
key->keyspec = keyspec;
+ key->pcert = NULL;
return key;
err:
return;
CryptDestroyKey(key->key);
CryptReleaseContext(key->hprov, 0);
+ if (key->pcert)
+ CertFreeCertificateContext(key->pcert);
OPENSSL_free(key);
}
return 0;
}
+static int client_cert_select(ENGINE *e, SSL *ssl, STACK_OF(X509) *certs)
+ {
+fprintf(stderr, "%d certificates\n", sk_X509_num(certs));
+ return 0;
+ }
+
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)
{
-#if 0
- /* For now just one matching key/cert */
STACK_OF(X509) *certs = NULL;
- STACK_OF(EVP_PKEY) *keys = NULL;
-#endif
X509 *x;
- EVP_PKEY *pk;
char *storename;
const char *p;
- int i;
+ int i, client_cert_idx;
HCERTSTORE hstore;
- PCCERT_CONTEXT cert = NULL;
+ PCCERT_CONTEXT cert = NULL, excert = NULL;
CAPI_CTX *ctx;
+ CAPI_KEY *key;
ctx = ENGINE_get_ex_data(e, capi_idx);
*pcert = NULL;
if (!hstore)
return 0;
/* Enumerate all certificates looking for a match */
- for(i = 0;!*pcert;i++)
+ for(i = 0;;i++)
{
cert = CertEnumCertificatesInStore(hstore, cert);
if (!cert)
}
if (cert_issuer_match(ca_dn, x))
{
- CAPI_KEY *key = capi_get_cert_key(ctx, cert);
+ key = capi_get_cert_key(ctx, cert);
if (!key)
continue;
+ excert = CertDuplicateCertificateContext(cert);
+ X509_set_ex_data(x, cert_capi_idx, key);
+
+ if (!certs)
+ certs = sk_X509_new_null();
+
+ sk_X509_push(certs, x);
+#if 0
pk = capi_get_pkey(e, key);
if (!pk)
{
}
*pcert = x;
*pkey = pk;
+#endif
}
else
X509_free(x);
if (cert)
CertFreeCertificateContext(cert);
- if (*pcert)
- return 1;
- else
+ if (!certs)
return 0;
+ client_cert_idx = client_cert_select(e, ssl, certs);
+
+ for(i = 0; i < sk_X509_num(certs); i++)
+ {
+ x = sk_X509_value(certs, i);
+ if (i == client_cert_idx)
+ *pcert = x;
+ else
+ {
+ key = X509_get_ex_data(x, cert_capi_idx);
+ capi_free_key(key);
+ X509_free(x);
+ }
+ }
+
+ sk_X509_free(certs);
+
+ if (!*pcert)
+ return 0;
+
+ key = X509_get_ex_data(*pcert, cert_capi_idx);
+ *pkey = capi_get_pkey(e, key);
+ X509_set_ex_data(*pcert, cert_capi_idx, NULL);
+
+ return 1;
+
}
#endif