schannel: make CURLOPT_CERTINFO support using Issuer chain

Closes #3197
This commit is contained in:
marcosdiazr 2018-10-30 18:06:30 -03:00 committed by Daniel Stenberg
parent 58d04252e1
commit 7f4c358541
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
2 changed files with 65 additions and 9 deletions

View File

@ -70,7 +70,7 @@ if(curl) {
}
.fi
.SH AVAILABILITY
This option is supported by the OpenSSL, GnuTLS, NSS and GSKit backends.
This option is supported by the OpenSSL, GnuTLS, WinSSL, NSS and GSKit backends.
.SH RETURN VALUE
Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not.
.SH "SEE ALSO"

View File

@ -1121,6 +1121,61 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
return CURLE_OK;
}
static bool
valid_cert_encoding(const CERT_CONTEXT *cert_context)
{
return (cert_context != NULL) &&
((cert_context->dwCertEncodingType & X509_ASN_ENCODING) != 0) &&
(cert_context->pbCertEncoded != NULL) &&
(cert_context->cbCertEncoded > 0);
}
typedef bool(*Read_crt_func)(const CERT_CONTEXT *ccert_context, void *arg);
static void
traverse_cert_store(const CERT_CONTEXT *context, Read_crt_func func,
void *arg)
{
const CERT_CONTEXT *current_context = NULL;
bool should_continue = true;
while(should_continue &&
(current_context = CertEnumCertificatesInStore(
context->hCertStore,
current_context)) != NULL)
should_continue = func(current_context, arg);
if(current_context)
CertFreeCertificateContext(current_context);
}
static bool
cert_counter_callback(const CERT_CONTEXT *ccert_context, void *certs_count)
{
if(valid_cert_encoding(ccert_context))
(*(int *)certs_count)++;
return true;
}
struct Adder_args
{
struct connectdata *conn;
CURLcode result;
int idx;
};
static bool
add_cert_to_certinfo(const CERT_CONTEXT *ccert_context, void *raw_arg)
{
struct Adder_args *args = (struct Adder_args*)raw_arg;
args->result = CURLE_OK;
if(valid_cert_encoding(ccert_context)) {
const char *beg = (const char *) ccert_context->pbCertEncoded;
const char *end = beg + ccert_context->cbCertEncoded;
args->result = Curl_extract_certinfo(args->conn, (args->idx)++, beg, end);
}
return args->result == CURLE_OK;
}
static CURLcode
schannel_connect_step3(struct connectdata *conn, int sockindex)
{
@ -1230,6 +1285,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
}
if(data->set.ssl.certinfo) {
int certs_count = 0;
sspi_status = s_pSecFn->QueryContextAttributes(&BACKEND->ctxt->ctxt_handle,
SECPKG_ATTR_REMOTE_CERT_CONTEXT, &ccert_context);
@ -1238,15 +1294,15 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
return CURLE_PEER_FAILED_VERIFICATION;
}
result = Curl_ssl_init_certinfo(data, 1);
if(!result) {
if(((ccert_context->dwCertEncodingType & X509_ASN_ENCODING) != 0) &&
(ccert_context->cbCertEncoded > 0)) {
traverse_cert_store(ccert_context, cert_counter_callback, &certs_count);
const char *beg = (const char *) ccert_context->pbCertEncoded;
const char *end = beg + ccert_context->cbCertEncoded;
result = Curl_extract_certinfo(conn, 0, beg, end);
}
result = Curl_ssl_init_certinfo(data, certs_count);
if(!result) {
struct Adder_args args;
args.conn = conn;
args.idx = 0;
traverse_cert_store(ccert_context, add_cert_to_certinfo, &args);
result = args.result;
}
CertFreeCertificateContext(ccert_context);
if(result)