mirror of
https://github.com/moparisthebest/curl
synced 2024-12-21 23:58:49 -05:00
NSS: support for CERTINFO feature
This commit is contained in:
parent
2bd72fa61c
commit
f6c335d63f
@ -5,7 +5,7 @@
|
|||||||
.\" * | (__| |_| | _ <| |___
|
.\" * | (__| |_| | _ <| |___
|
||||||
.\" * \___|\___/|_| \_\_____|
|
.\" * \___|\___/|_| \_\_____|
|
||||||
.\" *
|
.\" *
|
||||||
.\" * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
.\" * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
.\" *
|
.\" *
|
||||||
.\" * This software is licensed as described in the file COPYING, which
|
.\" * This software is licensed as described in the file COPYING, which
|
||||||
.\" * you should have received as part of this distribution. The terms
|
.\" * you should have received as part of this distribution. The terms
|
||||||
@ -219,8 +219,8 @@ done. The struct reports how many certs it found and then you can extract info
|
|||||||
for each of those certs by following the linked lists. The info chain is
|
for each of those certs by following the linked lists. The info chain is
|
||||||
provided in a series of data in the format "name:content" where the content is
|
provided in a series of data in the format "name:content" where the content is
|
||||||
for the specific named data. See also the certinfo.c example. NOTE: this
|
for the specific named data. See also the certinfo.c example. NOTE: this
|
||||||
option is only available in libcurl built with OpenSSL support. (Added in
|
option is only available in libcurl built with OpenSSL, NSS, GSKit or QsoSSL
|
||||||
7.19.1)
|
support. (Added in 7.19.1)
|
||||||
.IP CURLINFO_CONDITION_UNMET
|
.IP CURLINFO_CONDITION_UNMET
|
||||||
Pass a pointer to a long to receive the number 1 if the condition provided in
|
Pass a pointer to a long to receive the number 1 if the condition provided in
|
||||||
the previous request didn't match (see \fICURLOPT_TIMECONDITION\fP). Alas, if
|
the previous request didn't match (see \fICURLOPT_TIMECONDITION\fP). Alas, if
|
||||||
|
@ -2549,9 +2549,10 @@ is ignored.
|
|||||||
|
|
||||||
.IP CURLOPT_CERTINFO
|
.IP CURLOPT_CERTINFO
|
||||||
Pass a long set to 1 to enable libcurl's certificate chain info gatherer. With
|
Pass a long set to 1 to enable libcurl's certificate chain info gatherer. With
|
||||||
this enabled, libcurl (if built with OpenSSL) will extract lots of information
|
this enabled, libcurl (if built with OpenSSL, NSS, GSKit or QsoSSL) will
|
||||||
|
extract lots of information
|
||||||
and data about the certificates in the certificate chain used in the SSL
|
and data about the certificates in the certificate chain used in the SSL
|
||||||
connection. This data is then possible to extract after a transfer using
|
connection. This data may then be retrieved after a transfer using
|
||||||
\fIcurl_easy_getinfo(3)\fP and its option \fICURLINFO_CERTINFO\fP. (Added in
|
\fIcurl_easy_getinfo(3)\fP and its option \fICURLINFO_CERTINFO\fP. (Added in
|
||||||
7.19.1)
|
7.19.1)
|
||||||
.IP CURLOPT_RANDOM_FILE
|
.IP CURLOPT_RANDOM_FILE
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
#include "curl_setup.h"
|
#include "curl_setup.h"
|
||||||
|
|
||||||
#if defined(USE_SSLEAY) || defined(USE_AXTLS) || defined(USE_QSOSSL) || \
|
#if defined(USE_SSLEAY) || defined(USE_AXTLS) || defined(USE_QSOSSL) || \
|
||||||
defined(USE_GSKIT)
|
defined(USE_GSKIT) || defined(USE_NSS)
|
||||||
/* these backends use functions from this file */
|
/* these backends use functions from this file */
|
||||||
|
|
||||||
#include "hostcheck.h"
|
#include "hostcheck.h"
|
||||||
@ -94,4 +94,4 @@ int Curl_cert_hostcheck(const char *match_pattern, const char *hostname)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* SSLEAY or AXTLS or QSOSSL or GSKIT */
|
#endif /* SSLEAY or AXTLS or QSOSSL or GSKIT or NSS */
|
||||||
|
46
lib/nss.c
46
lib/nss.c
@ -653,6 +653,10 @@ static void display_conn_info(struct connectdata *conn, PRFileDesc *sock)
|
|||||||
SSLChannelInfo channel;
|
SSLChannelInfo channel;
|
||||||
SSLCipherSuiteInfo suite;
|
SSLCipherSuiteInfo suite;
|
||||||
CERTCertificate *cert;
|
CERTCertificate *cert;
|
||||||
|
CERTCertificate *cert2;
|
||||||
|
CERTCertificate *cert3;
|
||||||
|
PRTime now;
|
||||||
|
int i;
|
||||||
|
|
||||||
if(SSL_GetChannelInfo(sock, &channel, sizeof channel) ==
|
if(SSL_GetChannelInfo(sock, &channel, sizeof channel) ==
|
||||||
SECSuccess && channel.length == sizeof channel &&
|
SECSuccess && channel.length == sizeof channel &&
|
||||||
@ -663,11 +667,45 @@ static void display_conn_info(struct connectdata *conn, PRFileDesc *sock)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
infof(conn->data, "Server certificate:\n");
|
|
||||||
|
|
||||||
cert = SSL_PeerCertificate(sock);
|
cert = SSL_PeerCertificate(sock);
|
||||||
display_cert_info(conn->data, cert);
|
|
||||||
CERT_DestroyCertificate(cert);
|
if(cert) {
|
||||||
|
infof(conn->data, "Server certificate:\n");
|
||||||
|
|
||||||
|
if(!conn->data->set.ssl.certinfo) {
|
||||||
|
display_cert_info(conn->data, cert);
|
||||||
|
CERT_DestroyCertificate(cert);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Count certificates in chain. */
|
||||||
|
now = PR_Now();
|
||||||
|
i = 1;
|
||||||
|
if(!cert->isRoot) {
|
||||||
|
cert2 = CERT_FindCertIssuer(cert, now, certUsageSSLCA);
|
||||||
|
while(cert2) {
|
||||||
|
i++;
|
||||||
|
if(cert2->isRoot) {
|
||||||
|
CERT_DestroyCertificate(cert2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cert3 = CERT_FindCertIssuer(cert2, now, certUsageSSLCA);
|
||||||
|
CERT_DestroyCertificate(cert2);
|
||||||
|
cert2 = cert3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Curl_ssl_init_certinfo(conn->data, i);
|
||||||
|
for(i = 0; cert; cert = cert2) {
|
||||||
|
Curl_extract_certinfo(conn, i++, cert->derCert.data,
|
||||||
|
cert->derCert.data + cert->derCert.len);
|
||||||
|
if(cert->isRoot) {
|
||||||
|
CERT_DestroyCertificate(cert);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cert2 = CERT_FindCertIssuer(cert, now, certUsageSSLCA);
|
||||||
|
CERT_DestroyCertificate(cert);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1926,7 +1926,8 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
|||||||
data->set.ssl.fsslctxp = va_arg(param, void *);
|
data->set.ssl.fsslctxp = va_arg(param, void *);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if defined(USE_SSLEAY) || defined(USE_QSOSSL) || defined(USE_GSKIT)
|
#if defined(USE_SSLEAY) || defined(USE_QSOSSL) || defined(USE_GSKIT) || \
|
||||||
|
defined(USE_NSS)
|
||||||
case CURLOPT_CERTINFO:
|
case CURLOPT_CERTINFO:
|
||||||
data->set.ssl.certinfo = (0 != va_arg(param, long))?TRUE:FALSE;
|
data->set.ssl.certinfo = (0 != va_arg(param, long))?TRUE:FALSE;
|
||||||
break;
|
break;
|
||||||
|
100
lib/x509asn1.c
100
lib/x509asn1.c
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#include "curl_setup.h"
|
#include "curl_setup.h"
|
||||||
|
|
||||||
#if defined(USE_QSOSSL) || defined(USE_GSKIT)
|
#if defined(USE_QSOSSL) || defined(USE_GSKIT) || defined(USE_NSS)
|
||||||
|
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
#include "urldata.h"
|
#include "urldata.h"
|
||||||
@ -803,7 +803,7 @@ static const char * dumpAlgo(curl_asn1Element * param,
|
|||||||
return OID2str(oid.beg, oid.end, TRUE);
|
return OID2str(oid.beg, oid.end, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_pubkey_field(struct SessionHandle *data, int certnum,
|
static void do_pubkey_field(struct SessionHandle * data, int certnum,
|
||||||
const char * label, curl_asn1Element * elem)
|
const char * label, curl_asn1Element * elem)
|
||||||
{
|
{
|
||||||
const char * output;
|
const char * output;
|
||||||
@ -812,8 +812,10 @@ static void do_pubkey_field(struct SessionHandle *data, int certnum,
|
|||||||
|
|
||||||
output = Curl_ASN1tostr(elem, 0);
|
output = Curl_ASN1tostr(elem, 0);
|
||||||
if(output) {
|
if(output) {
|
||||||
Curl_ssl_push_certinfo(data, certnum, label, output);
|
if(data->set.ssl.certinfo)
|
||||||
infof(data, " %s: %s\n", label, output);
|
Curl_ssl_push_certinfo(data, certnum, label, output);
|
||||||
|
if(!certnum)
|
||||||
|
infof(data, " %s: %s\n", label, output);
|
||||||
free((char *) output);
|
free((char *) output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -845,11 +847,14 @@ static void do_pubkey(struct SessionHandle * data, int certnum,
|
|||||||
len--;
|
len--;
|
||||||
if(len > 32)
|
if(len > 32)
|
||||||
elem.beg = q; /* Strip leading zero bytes. */
|
elem.beg = q; /* Strip leading zero bytes. */
|
||||||
infof(data, " RSA Public Key (%lu bits)\n", len);
|
if(!certnum)
|
||||||
q = curl_maprintf("%lu", len);
|
infof(data, " RSA Public Key (%lu bits)\n", len);
|
||||||
if(q) {
|
if(data->set.ssl.certinfo) {
|
||||||
Curl_ssl_push_certinfo(data, certnum, "RSA Public Key", q);
|
q = curl_maprintf("%lu", len);
|
||||||
free((char *) q);
|
if(q) {
|
||||||
|
Curl_ssl_push_certinfo(data, certnum, "RSA Public Key", q);
|
||||||
|
free((char *) q);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* Generate coefficients. */
|
/* Generate coefficients. */
|
||||||
do_pubkey_field(data, certnum, "rsa(n)", &elem);
|
do_pubkey_field(data, certnum, "rsa(n)", &elem);
|
||||||
@ -896,6 +901,10 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn,
|
|||||||
size_t i;
|
size_t i;
|
||||||
size_t j;
|
size_t j;
|
||||||
|
|
||||||
|
if(!data->set.ssl.certinfo)
|
||||||
|
if(certnum)
|
||||||
|
return CURLE_OK;
|
||||||
|
|
||||||
/* Prepare the certificate information for curl_easy_getinfo(). */
|
/* Prepare the certificate information for curl_easy_getinfo(). */
|
||||||
|
|
||||||
/* Extract the certificate ASN.1 elements. */
|
/* Extract the certificate ASN.1 elements. */
|
||||||
@ -905,35 +914,44 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn,
|
|||||||
ccp = Curl_DNtostr(&cert.subject);
|
ccp = Curl_DNtostr(&cert.subject);
|
||||||
if(!ccp)
|
if(!ccp)
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
Curl_ssl_push_certinfo(data, certnum, "Subject", ccp);
|
if(data->set.ssl.certinfo)
|
||||||
infof(data, "%2d Subject: %s\n", certnum, ccp);
|
Curl_ssl_push_certinfo(data, certnum, "Subject", ccp);
|
||||||
|
if(!certnum)
|
||||||
|
infof(data, "%2d Subject: %s\n", certnum, ccp);
|
||||||
free((char *) ccp);
|
free((char *) ccp);
|
||||||
|
|
||||||
/* Issuer. */
|
/* Issuer. */
|
||||||
ccp = Curl_DNtostr(&cert.issuer);
|
ccp = Curl_DNtostr(&cert.issuer);
|
||||||
if(!ccp)
|
if(!ccp)
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
Curl_ssl_push_certinfo(data, certnum, "Issuer", ccp);
|
if(data->set.ssl.certinfo)
|
||||||
infof(data, " Issuer: %s\n", ccp);
|
Curl_ssl_push_certinfo(data, certnum, "Issuer", ccp);
|
||||||
|
if(!certnum)
|
||||||
|
infof(data, " Issuer: %s\n", ccp);
|
||||||
free((char *) ccp);
|
free((char *) ccp);
|
||||||
|
|
||||||
/* Version (always fits in less than 32 bits). */
|
/* Version (always fits in less than 32 bits). */
|
||||||
version = 0;
|
version = 0;
|
||||||
for(ccp = cert.version.beg; ccp < cert.version.end; ccp++)
|
for(ccp = cert.version.beg; ccp < cert.version.end; ccp++)
|
||||||
version = (version << 8) | *(const unsigned char *) ccp;
|
version = (version << 8) | *(const unsigned char *) ccp;
|
||||||
ccp = curl_maprintf("%lx", version);
|
if(data->set.ssl.certinfo) {
|
||||||
if(!ccp)
|
ccp = curl_maprintf("%lx", version);
|
||||||
return CURLE_OUT_OF_MEMORY;
|
if(!ccp)
|
||||||
Curl_ssl_push_certinfo(data, certnum, "Version", ccp);
|
return CURLE_OUT_OF_MEMORY;
|
||||||
free((char *) ccp);
|
Curl_ssl_push_certinfo(data, certnum, "Version", ccp);
|
||||||
infof(data, " Version: %lu (0x%lx)\n", version + 1, version);
|
free((char *) ccp);
|
||||||
|
}
|
||||||
|
if(!certnum)
|
||||||
|
infof(data, " Version: %lu (0x%lx)\n", version + 1, version);
|
||||||
|
|
||||||
/* Serial number. */
|
/* Serial number. */
|
||||||
ccp = Curl_ASN1tostr(&cert.serialNumber, 0);
|
ccp = Curl_ASN1tostr(&cert.serialNumber, 0);
|
||||||
if(!ccp)
|
if(!ccp)
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
Curl_ssl_push_certinfo(data, certnum, "Serial Number", ccp);
|
if(data->set.ssl.certinfo)
|
||||||
infof(data, " Serial Number: %s\n", ccp);
|
Curl_ssl_push_certinfo(data, certnum, "Serial Number", ccp);
|
||||||
|
if(!certnum)
|
||||||
|
infof(data, " Serial Number: %s\n", ccp);
|
||||||
free((char *) ccp);
|
free((char *) ccp);
|
||||||
|
|
||||||
/* Signature algorithm .*/
|
/* Signature algorithm .*/
|
||||||
@ -941,24 +959,30 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn,
|
|||||||
cert.signatureAlgorithm.end);
|
cert.signatureAlgorithm.end);
|
||||||
if(!ccp)
|
if(!ccp)
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
Curl_ssl_push_certinfo(data, certnum, "Signature Algorithm", ccp);
|
if(data->set.ssl.certinfo)
|
||||||
infof(data, " Signature Algorithm: %s\n", ccp);
|
Curl_ssl_push_certinfo(data, certnum, "Signature Algorithm", ccp);
|
||||||
|
if(!certnum)
|
||||||
|
infof(data, " Signature Algorithm: %s\n", ccp);
|
||||||
free((char *) ccp);
|
free((char *) ccp);
|
||||||
|
|
||||||
/* Start Date. */
|
/* Start Date. */
|
||||||
ccp = Curl_ASN1tostr(&cert.notBefore, 0);
|
ccp = Curl_ASN1tostr(&cert.notBefore, 0);
|
||||||
if(!ccp)
|
if(!ccp)
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
Curl_ssl_push_certinfo(data, certnum, "Start Date", ccp);
|
if(data->set.ssl.certinfo)
|
||||||
infof(data, " Start Date: %s\n", ccp);
|
Curl_ssl_push_certinfo(data, certnum, "Start Date", ccp);
|
||||||
|
if(!certnum)
|
||||||
|
infof(data, " Start Date: %s\n", ccp);
|
||||||
free((char *) ccp);
|
free((char *) ccp);
|
||||||
|
|
||||||
/* Expire Date. */
|
/* Expire Date. */
|
||||||
ccp = Curl_ASN1tostr(&cert.notAfter, 0);
|
ccp = Curl_ASN1tostr(&cert.notAfter, 0);
|
||||||
if(!ccp)
|
if(!ccp)
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
Curl_ssl_push_certinfo(data, certnum, "Expire Date", ccp);
|
if(data->set.ssl.certinfo)
|
||||||
infof(data, " Expire Date: %s\n", ccp);
|
Curl_ssl_push_certinfo(data, certnum, "Expire Date", ccp);
|
||||||
|
if(!certnum)
|
||||||
|
infof(data, " Expire Date: %s\n", ccp);
|
||||||
free((char *) ccp);
|
free((char *) ccp);
|
||||||
|
|
||||||
/* Public Key Algorithm. */
|
/* Public Key Algorithm. */
|
||||||
@ -966,8 +990,10 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn,
|
|||||||
cert.subjectPublicKeyAlgorithm.end);
|
cert.subjectPublicKeyAlgorithm.end);
|
||||||
if(!ccp)
|
if(!ccp)
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
Curl_ssl_push_certinfo(data, certnum, "Public Key Algorithm", ccp);
|
if(data->set.ssl.certinfo)
|
||||||
infof(data, " Public Key Algorithm: %s\n", ccp);
|
Curl_ssl_push_certinfo(data, certnum, "Public Key Algorithm", ccp);
|
||||||
|
if(!certnum)
|
||||||
|
infof(data, " Public Key Algorithm: %s\n", ccp);
|
||||||
do_pubkey(data, certnum, ccp, ¶m, &cert.subjectPublicKey);
|
do_pubkey(data, certnum, ccp, ¶m, &cert.subjectPublicKey);
|
||||||
free((char *) ccp);
|
free((char *) ccp);
|
||||||
|
|
||||||
@ -977,8 +1003,10 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn,
|
|||||||
ccp = Curl_ASN1tostr(&cert.signature, 0);
|
ccp = Curl_ASN1tostr(&cert.signature, 0);
|
||||||
if(!ccp)
|
if(!ccp)
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
Curl_ssl_push_certinfo(data, certnum, "Signature", ccp);
|
if(data->set.ssl.certinfo)
|
||||||
infof(data, " Signature: %s\n", ccp);
|
Curl_ssl_push_certinfo(data, certnum, "Signature", ccp);
|
||||||
|
if(!certnum)
|
||||||
|
infof(data, " Signature: %s\n", ccp);
|
||||||
free((char *) ccp);
|
free((char *) ccp);
|
||||||
|
|
||||||
/* Generate PEM certificate. */
|
/* Generate PEM certificate. */
|
||||||
@ -987,7 +1015,7 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn,
|
|||||||
&cp1, &cl1);
|
&cp1, &cl1);
|
||||||
if(cc != CURLE_OK)
|
if(cc != CURLE_OK)
|
||||||
return cc;
|
return cc;
|
||||||
/* Compute the number of charaters in final certificate string. Format is:
|
/* Compute the number of characters in final certificate string. Format is:
|
||||||
-----BEGIN CERTIFICATE-----\n
|
-----BEGIN CERTIFICATE-----\n
|
||||||
<max 64 base64 characters>\n
|
<max 64 base64 characters>\n
|
||||||
.
|
.
|
||||||
@ -1008,8 +1036,10 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn,
|
|||||||
i += copySubstring(cp2 + i, "-----END CERTIFICATE-----");
|
i += copySubstring(cp2 + i, "-----END CERTIFICATE-----");
|
||||||
cp2[i] = '\0';
|
cp2[i] = '\0';
|
||||||
free(cp1);
|
free(cp1);
|
||||||
Curl_ssl_push_certinfo(data, certnum, "Cert", cp2);
|
if(data->set.ssl.certinfo)
|
||||||
infof(data, "%s\n", cp2);
|
Curl_ssl_push_certinfo(data, certnum, "Cert", cp2);
|
||||||
|
if(!certnum)
|
||||||
|
infof(data, "%s\n", cp2);
|
||||||
free(cp2);
|
free(cp2);
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
@ -1148,4 +1178,4 @@ CURLcode Curl_verifyhost(struct connectdata * conn,
|
|||||||
return CURLE_PEER_FAILED_VERIFICATION;
|
return CURLE_PEER_FAILED_VERIFICATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* USE_QSOSSL or USE_GSKIT */
|
#endif /* USE_QSOSSL or USE_GSKIT or USE_NSS */
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
#include "curl_setup.h"
|
#include "curl_setup.h"
|
||||||
|
|
||||||
#if defined(USE_QSOSSL) || defined(USE_GSKIT)
|
#if defined(USE_QSOSSL) || defined(USE_GSKIT) || defined(USE_NSS)
|
||||||
|
|
||||||
#include "urldata.h"
|
#include "urldata.h"
|
||||||
|
|
||||||
@ -125,5 +125,5 @@ CURLcode Curl_extract_certinfo(struct connectdata * conn, int certnum,
|
|||||||
CURLcode Curl_verifyhost(struct connectdata * conn,
|
CURLcode Curl_verifyhost(struct connectdata * conn,
|
||||||
const char * beg, const char * end);
|
const char * beg, const char * end);
|
||||||
|
|
||||||
#endif /* USE_QSOSSL or USE_GSKIT */
|
#endif /* USE_QSOSSL or USE_GSKIT or USE_NSS */
|
||||||
#endif /* HEADER_CURL_X509ASN1_H */
|
#endif /* HEADER_CURL_X509ASN1_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user