Add initial support for multiple SSL client certifcate selection in
CryptoAPI ENGINE.
This commit is contained in:
parent
ca89fc1fb4
commit
7d537d4fc7
@ -238,6 +238,7 @@ static const ENGINE_CMD_DEFN capi_cmd_defns[] = {
|
|||||||
static int capi_idx = -1;
|
static int capi_idx = -1;
|
||||||
static int rsa_capi_idx = -1;
|
static int rsa_capi_idx = -1;
|
||||||
static int dsa_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))
|
static int capi_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
|
||||||
{
|
{
|
||||||
@ -365,6 +366,7 @@ static int capi_init(ENGINE *e)
|
|||||||
const RSA_METHOD *ossl_rsa_meth;
|
const RSA_METHOD *ossl_rsa_meth;
|
||||||
const DSA_METHOD *ossl_dsa_meth;
|
const DSA_METHOD *ossl_dsa_meth;
|
||||||
capi_idx = ENGINE_get_ex_new_index(0, NULL, NULL, NULL, 0);
|
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();
|
ctx = capi_ctx_new();
|
||||||
if (!ctx || (capi_idx < 0))
|
if (!ctx || (capi_idx < 0))
|
||||||
@ -418,6 +420,8 @@ static int capi_finish(ENGINE *e)
|
|||||||
|
|
||||||
struct CAPI_KEY_st
|
struct CAPI_KEY_st
|
||||||
{
|
{
|
||||||
|
/* Associated certificate context (if any) */
|
||||||
|
PCERT_CONTEXT pcert;
|
||||||
HCRYPTPROV hprov;
|
HCRYPTPROV hprov;
|
||||||
HCRYPTKEY key;
|
HCRYPTKEY key;
|
||||||
DWORD keyspec;
|
DWORD keyspec;
|
||||||
@ -1329,6 +1333,7 @@ static CAPI_KEY *capi_get_key(CAPI_CTX *ctx, const char *contname, char *provnam
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
key->keyspec = keyspec;
|
key->keyspec = keyspec;
|
||||||
|
key->pcert = NULL;
|
||||||
return key;
|
return key;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
@ -1398,6 +1403,8 @@ void capi_free_key(CAPI_KEY *key)
|
|||||||
return;
|
return;
|
||||||
CryptDestroyKey(key->key);
|
CryptDestroyKey(key->key);
|
||||||
CryptReleaseContext(key->hprov, 0);
|
CryptReleaseContext(key->hprov, 0);
|
||||||
|
if (key->pcert)
|
||||||
|
CertFreeCertificateContext(key->pcert);
|
||||||
OPENSSL_free(key);
|
OPENSSL_free(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1486,23 +1493,25 @@ static int cert_issuer_match(STACK_OF(X509_NAME) *ca_dn, X509 *x)
|
|||||||
return 0;
|
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,
|
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_NAME) *ca_dn, X509 **pcert, EVP_PKEY **pkey,
|
||||||
STACK_OF(X509) **pother, UI_METHOD *ui_method, void *callback_data)
|
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(X509) *certs = NULL;
|
||||||
STACK_OF(EVP_PKEY) *keys = NULL;
|
|
||||||
#endif
|
|
||||||
X509 *x;
|
X509 *x;
|
||||||
EVP_PKEY *pk;
|
|
||||||
char *storename;
|
char *storename;
|
||||||
const char *p;
|
const char *p;
|
||||||
int i;
|
int i, client_cert_idx;
|
||||||
HCERTSTORE hstore;
|
HCERTSTORE hstore;
|
||||||
PCCERT_CONTEXT cert = NULL;
|
PCCERT_CONTEXT cert = NULL, excert = NULL;
|
||||||
CAPI_CTX *ctx;
|
CAPI_CTX *ctx;
|
||||||
|
CAPI_KEY *key;
|
||||||
ctx = ENGINE_get_ex_data(e, capi_idx);
|
ctx = ENGINE_get_ex_data(e, capi_idx);
|
||||||
|
|
||||||
*pcert = NULL;
|
*pcert = NULL;
|
||||||
@ -1516,7 +1525,7 @@ static int capi_load_ssl_client_cert(ENGINE *e, SSL *ssl,
|
|||||||
if (!hstore)
|
if (!hstore)
|
||||||
return 0;
|
return 0;
|
||||||
/* Enumerate all certificates looking for a match */
|
/* Enumerate all certificates looking for a match */
|
||||||
for(i = 0;!*pcert;i++)
|
for(i = 0;;i++)
|
||||||
{
|
{
|
||||||
cert = CertEnumCertificatesInStore(hstore, cert);
|
cert = CertEnumCertificatesInStore(hstore, cert);
|
||||||
if (!cert)
|
if (!cert)
|
||||||
@ -1530,9 +1539,17 @@ static int capi_load_ssl_client_cert(ENGINE *e, SSL *ssl,
|
|||||||
}
|
}
|
||||||
if (cert_issuer_match(ca_dn, x))
|
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)
|
if (!key)
|
||||||
continue;
|
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);
|
pk = capi_get_pkey(e, key);
|
||||||
if (!pk)
|
if (!pk)
|
||||||
{
|
{
|
||||||
@ -1541,6 +1558,7 @@ static int capi_load_ssl_client_cert(ENGINE *e, SSL *ssl,
|
|||||||
}
|
}
|
||||||
*pcert = x;
|
*pcert = x;
|
||||||
*pkey = pk;
|
*pkey = pk;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
X509_free(x);
|
X509_free(x);
|
||||||
@ -1550,11 +1568,35 @@ static int capi_load_ssl_client_cert(ENGINE *e, SSL *ssl,
|
|||||||
if (cert)
|
if (cert)
|
||||||
CertFreeCertificateContext(cert);
|
CertFreeCertificateContext(cert);
|
||||||
|
|
||||||
if (*pcert)
|
if (!certs)
|
||||||
return 1;
|
|
||||||
else
|
|
||||||
return 0;
|
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
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user