mirror of
https://github.com/moparisthebest/curl
synced 2024-08-13 17:03:50 -04:00
SSL: Pinned public key hash support
This commit is contained in:
parent
c00b18d540
commit
55b78c5ae9
11
docs/curl.1
11
docs/curl.1
@ -544,9 +544,11 @@ OpenSSL-powered curl to make SSL-connections much more efficiently than using
|
|||||||
|
|
||||||
If this option is set, the default capath value will be ignored, and if it is
|
If this option is set, the default capath value will be ignored, and if it is
|
||||||
used several times, the last one will be used.
|
used several times, the last one will be used.
|
||||||
.IP "--pinnedpubkey <pinned public key>"
|
.IP "--pinnedpubkey <pinned public key (hashes)>"
|
||||||
(SSL) Tells curl to use the specified public key file to verify the peer. The
|
(SSL) Tells curl to use the specified public key file (or hashes) to verify the
|
||||||
file must contain a single public key in PEM or DER format.
|
peer. This can be a path to a file which contains a single public key in PEM or
|
||||||
|
DER format, or any number of base64 encoded sha256 hashes preceded by
|
||||||
|
\'sha256//\' and seperated by \';\'
|
||||||
|
|
||||||
When negotiating a TLS or SSL connection, the server sends a certificate
|
When negotiating a TLS or SSL connection, the server sends a certificate
|
||||||
indicating its identity. A public key is extracted from this certificate and
|
indicating its identity. A public key is extracted from this certificate and
|
||||||
@ -554,7 +556,8 @@ if it does not exactly match the public key provided to this option, curl will
|
|||||||
abort the connection before sending or receiving any data.
|
abort the connection before sending or receiving any data.
|
||||||
|
|
||||||
Added in 7.39.0 for OpenSSL, GnuTLS and GSKit. Added in 7.43.0 for NSS and
|
Added in 7.39.0 for OpenSSL, GnuTLS and GSKit. Added in 7.43.0 for NSS and
|
||||||
wolfSSL/CyaSSL. Other SSL backends not supported.
|
wolfSSL/CyaSSL. sha256 support added in 7.44.0 for OpenSSL,
|
||||||
|
GnuTLS, NSS and wolfSSL/CyaSSL. Other SSL backends not supported.
|
||||||
|
|
||||||
If this option is used several times, the last one will be used.
|
If this option is used several times, the last one will be used.
|
||||||
.IP "--cert-status"
|
.IP "--cert-status"
|
||||||
|
@ -28,8 +28,10 @@ CURLOPT_PINNEDPUBLICKEY \- set pinned public key
|
|||||||
|
|
||||||
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PINNEDPUBLICKEY, char *pinnedpubkey);
|
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PINNEDPUBLICKEY, char *pinnedpubkey);
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
Pass a pointer to a zero terminated string as parameter. The string should be
|
Pass a pointer to a zero terminated string as parameter. The string can be the
|
||||||
the file name of your pinned public key. The format expected is "PEM" or "DER".
|
file name of your pinned public key. The file format expected is "PEM" or "DER".
|
||||||
|
The string can also be any number of base64 encoded sha256 hashes preceded by
|
||||||
|
"sha256//" and seperated by ";"
|
||||||
|
|
||||||
When negotiating a TLS or SSL connection, the server sends a certificate
|
When negotiating a TLS or SSL connection, the server sends a certificate
|
||||||
indicating its identity. A public key is extracted from this certificate and
|
indicating its identity. A public key is extracted from this certificate and
|
||||||
@ -45,6 +47,9 @@ CURL *curl = curl_easy_init();
|
|||||||
if(curl) {
|
if(curl) {
|
||||||
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com");
|
||||||
curl_easy_setopt(curl, CURLOPT_PINNEDPUBLICKEY, "/etc/publickey.der");
|
curl_easy_setopt(curl, CURLOPT_PINNEDPUBLICKEY, "/etc/publickey.der");
|
||||||
|
/* OR
|
||||||
|
curl_easy_setopt(curl, CURLOPT_PINNEDPUBLICKEY, "sha256//YhKJKSzoTt2b5FP18fvpHo7fJYqQCjAa3HWY3tvRMwE=;sha256//t62CeU2tQiqkexU74Gxa2eg7fRbEgoChTociMee9wno=");
|
||||||
|
*/
|
||||||
|
|
||||||
/* Perform the request */
|
/* Perform the request */
|
||||||
curl_easy_perform(curl);
|
curl_easy_perform(curl);
|
||||||
@ -54,9 +59,14 @@ if(curl) {
|
|||||||
If you do not have the server's public key file you can extract it from the
|
If you do not have the server's public key file you can extract it from the
|
||||||
server's certificate.
|
server's certificate.
|
||||||
.nf
|
.nf
|
||||||
|
# extract public key in pem format from certificate
|
||||||
openssl x509 -in www.test.com.pem -pubkey -noout > www.test.com.pubkey.pem
|
openssl x509 -in www.test.com.pem -pubkey -noout > www.test.com.pubkey.pem
|
||||||
|
# convert public key from pem to der
|
||||||
|
openssl asn1parse -noout -inform pem -in www.test.com.pubkey.pem -out www.test.com.pubkey.der
|
||||||
|
# sha256 hash and base64 encode der to string for use
|
||||||
|
openssl dgst -sha256 -binary www.test.com.pubkey.der | openssl base64
|
||||||
.fi
|
.fi
|
||||||
The public key is output in PEM format and contains a header, base64 data and a
|
The public key in PEM format contains a header, base64 data and a
|
||||||
footer:
|
footer:
|
||||||
.nf
|
.nf
|
||||||
-----BEGIN PUBLIC KEY-----
|
-----BEGIN PUBLIC KEY-----
|
||||||
@ -65,7 +75,8 @@ footer:
|
|||||||
.fi
|
.fi
|
||||||
.SH AVAILABILITY
|
.SH AVAILABILITY
|
||||||
Added in 7.39.0 for OpenSSL, GnuTLS and GSKit. Added in 7.43.0 for
|
Added in 7.39.0 for OpenSSL, GnuTLS and GSKit. Added in 7.43.0 for
|
||||||
NSS and wolfSSL/CyaSSL. Other SSL backends not supported.
|
NSS and wolfSSL/CyaSSL. sha256 support added in 7.44.0 for OpenSSL,
|
||||||
|
GnuTLS, NSS and wolfSSL/CyaSSL. Other SSL backends not supported.
|
||||||
.SH RETURN VALUE
|
.SH RETURN VALUE
|
||||||
Returns CURLE_OK if TLS enabled, CURLE_UNKNOWN_OPTION if not, or
|
Returns CURLE_OK if TLS enabled, CURLE_UNKNOWN_OPTION if not, or
|
||||||
CURLE_OUT_OF_MEMORY if there was insufficient heap space.
|
CURLE_OUT_OF_MEMORY if there was insufficient heap space.
|
||||||
|
@ -67,6 +67,7 @@ and that's a problem since options.h hasn't been included yet. */
|
|||||||
#include <cyassl/error.h>
|
#include <cyassl/error.h>
|
||||||
#endif
|
#endif
|
||||||
#include <cyassl/ctaocrypt/random.h>
|
#include <cyassl/ctaocrypt/random.h>
|
||||||
|
#include <cyassl/ctaocrypt/sha256.h>
|
||||||
|
|
||||||
/* The last #include files should be: */
|
/* The last #include files should be: */
|
||||||
#include "curl_memory.h"
|
#include "curl_memory.h"
|
||||||
@ -770,4 +771,16 @@ int Curl_cyassl_random(struct SessionHandle *data,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */
|
||||||
|
size_t tmplen,
|
||||||
|
unsigned char *sha256sum /* output */,
|
||||||
|
size_t unused)
|
||||||
|
{
|
||||||
|
Sha256 SHA256pw;
|
||||||
|
(void)unused;
|
||||||
|
InitSha256(&SHA256pw);
|
||||||
|
Sha256Update(&SHA256pw, tmp, tmplen);
|
||||||
|
Sha256Final(&SHA256pw, sha256sum);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -42,6 +42,10 @@ CURLcode Curl_cyassl_connect_nonblocking(struct connectdata *conn,
|
|||||||
int Curl_cyassl_random(struct SessionHandle *data,
|
int Curl_cyassl_random(struct SessionHandle *data,
|
||||||
unsigned char *entropy,
|
unsigned char *entropy,
|
||||||
size_t length);
|
size_t length);
|
||||||
|
void Curl_cyassl_sha256sum(unsigned char *tmp, /* input */
|
||||||
|
size_t tmplen,
|
||||||
|
unsigned char *sha256sum, /* output */
|
||||||
|
size_t unused);
|
||||||
|
|
||||||
/* Set the API backend definition to Schannel */
|
/* Set the API backend definition to Schannel */
|
||||||
#define CURL_SSL_BACKEND CURLSSLBACKEND_CYASSL
|
#define CURL_SSL_BACKEND CURLSSLBACKEND_CYASSL
|
||||||
@ -65,6 +69,7 @@ int Curl_cyassl_random(struct SessionHandle *data,
|
|||||||
#define curlssl_check_cxn(x) ((void)x, -1)
|
#define curlssl_check_cxn(x) ((void)x, -1)
|
||||||
#define curlssl_data_pending(x,y) Curl_cyassl_data_pending(x,y)
|
#define curlssl_data_pending(x,y) Curl_cyassl_data_pending(x,y)
|
||||||
#define curlssl_random(x,y,z) Curl_cyassl_random(x,y,z)
|
#define curlssl_random(x,y,z) Curl_cyassl_random(x,y,z)
|
||||||
|
#define curlssl_sha256sum(a,b,c,d) Curl_cyassl_sha256sum(a,b,c,d)
|
||||||
|
|
||||||
#endif /* USE_CYASSL */
|
#endif /* USE_CYASSL */
|
||||||
#endif /* HEADER_CURL_CYASSL_H */
|
#endif /* HEADER_CURL_CYASSL_H */
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
#ifdef USE_GNUTLS_NETTLE
|
#ifdef USE_GNUTLS_NETTLE
|
||||||
#include <gnutls/crypto.h>
|
#include <gnutls/crypto.h>
|
||||||
#include <nettle/md5.h>
|
#include <nettle/md5.h>
|
||||||
|
#include <nettle/sha2.h>
|
||||||
#else
|
#else
|
||||||
#include <gcrypt.h>
|
#include <gcrypt.h>
|
||||||
#endif
|
#endif
|
||||||
@ -1557,6 +1558,25 @@ void Curl_gtls_md5sum(unsigned char *tmp, /* input */
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
|
||||||
|
size_t tmplen,
|
||||||
|
unsigned char *sha256sum, /* output */
|
||||||
|
size_t sha256len)
|
||||||
|
{
|
||||||
|
#if defined(USE_GNUTLS_NETTLE)
|
||||||
|
struct sha256_ctx SHA256pw;
|
||||||
|
sha256_init(&SHA256pw);
|
||||||
|
sha256_update(&SHA256pw, (unsigned int)tmplen, tmp);
|
||||||
|
sha256_digest(&SHA256pw, (unsigned int)sha256len, sha256sum);
|
||||||
|
#elif defined(USE_GNUTLS)
|
||||||
|
gcry_md_hd_t SHA256pw;
|
||||||
|
gcry_md_open(&SHA256pw, GCRY_MD_SHA256, 0);
|
||||||
|
gcry_md_write(SHA256pw, tmp, tmplen);
|
||||||
|
memcpy(sha256sum, gcry_md_read (SHA256pw, 0), sha256len);
|
||||||
|
gcry_md_close(SHA256pw);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
bool Curl_gtls_cert_status_request(void)
|
bool Curl_gtls_cert_status_request(void)
|
||||||
{
|
{
|
||||||
#ifdef HAS_OCSP
|
#ifdef HAS_OCSP
|
||||||
|
@ -48,6 +48,10 @@ void Curl_gtls_md5sum(unsigned char *tmp, /* input */
|
|||||||
size_t tmplen,
|
size_t tmplen,
|
||||||
unsigned char *md5sum, /* output */
|
unsigned char *md5sum, /* output */
|
||||||
size_t md5len);
|
size_t md5len);
|
||||||
|
void Curl_gtls_sha256sum(const unsigned char *tmp, /* input */
|
||||||
|
size_t tmplen,
|
||||||
|
unsigned char *sha256sum, /* output */
|
||||||
|
size_t sha256len);
|
||||||
|
|
||||||
bool Curl_gtls_cert_status_request(void);
|
bool Curl_gtls_cert_status_request(void);
|
||||||
|
|
||||||
@ -77,6 +81,7 @@ bool Curl_gtls_cert_status_request(void);
|
|||||||
#define curlssl_data_pending(x,y) ((void)x, (void)y, 0)
|
#define curlssl_data_pending(x,y) ((void)x, (void)y, 0)
|
||||||
#define curlssl_random(x,y,z) Curl_gtls_random(x,y,z)
|
#define curlssl_random(x,y,z) Curl_gtls_random(x,y,z)
|
||||||
#define curlssl_md5sum(a,b,c,d) Curl_gtls_md5sum(a,b,c,d)
|
#define curlssl_md5sum(a,b,c,d) Curl_gtls_md5sum(a,b,c,d)
|
||||||
|
#define curlssl_sha256sum(a,b,c,d) Curl_gtls_sha256sum(a,b,c,d)
|
||||||
#define curlssl_cert_status_request() Curl_gtls_cert_status_request()
|
#define curlssl_cert_status_request() Curl_gtls_cert_status_request()
|
||||||
|
|
||||||
#endif /* USE_GNUTLS */
|
#endif /* USE_GNUTLS */
|
||||||
|
@ -2041,6 +2041,19 @@ void Curl_nss_md5sum(unsigned char *tmp, /* input */
|
|||||||
PK11_DestroyContext(MD5pw, PR_TRUE);
|
PK11_DestroyContext(MD5pw, PR_TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Curl_nss_sha256sum(const unsigned char *tmp, /* input */
|
||||||
|
size_t tmplen,
|
||||||
|
unsigned char *sha256sum, /* output */
|
||||||
|
size_t sha256len)
|
||||||
|
{
|
||||||
|
PK11Context *SHA256pw = PK11_CreateDigestContext(SEC_OID_SHA256);
|
||||||
|
unsigned int SHA256out;
|
||||||
|
|
||||||
|
PK11_DigestOp(SHA256pw, tmp, curlx_uztoui(tmplen));
|
||||||
|
PK11_DigestFinal(SHA256pw, sha256sum, &SHA256out, curlx_uztoui(sha256len));
|
||||||
|
PK11_DestroyContext(SHA256pw, PR_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
bool Curl_nss_cert_status_request(void)
|
bool Curl_nss_cert_status_request(void)
|
||||||
{
|
{
|
||||||
#ifdef SSL_ENABLE_OCSP_STAPLING
|
#ifdef SSL_ENABLE_OCSP_STAPLING
|
||||||
|
@ -56,6 +56,11 @@ void Curl_nss_md5sum(unsigned char *tmp, /* input */
|
|||||||
unsigned char *md5sum, /* output */
|
unsigned char *md5sum, /* output */
|
||||||
size_t md5len);
|
size_t md5len);
|
||||||
|
|
||||||
|
void Curl_nss_sha256sum(const unsigned char *tmp, /* input */
|
||||||
|
size_t tmplen,
|
||||||
|
unsigned char *sha256sum, /* output */
|
||||||
|
size_t sha256len);
|
||||||
|
|
||||||
bool Curl_nss_cert_status_request(void);
|
bool Curl_nss_cert_status_request(void);
|
||||||
|
|
||||||
bool Curl_nss_false_start(void);
|
bool Curl_nss_false_start(void);
|
||||||
@ -89,6 +94,7 @@ bool Curl_nss_false_start(void);
|
|||||||
#define curlssl_data_pending(x,y) ((void)x, (void)y, 0)
|
#define curlssl_data_pending(x,y) ((void)x, (void)y, 0)
|
||||||
#define curlssl_random(x,y,z) Curl_nss_random(x,y,z)
|
#define curlssl_random(x,y,z) Curl_nss_random(x,y,z)
|
||||||
#define curlssl_md5sum(a,b,c,d) Curl_nss_md5sum(a,b,c,d)
|
#define curlssl_md5sum(a,b,c,d) Curl_nss_md5sum(a,b,c,d)
|
||||||
|
#define curlssl_sha256sum(a,b,c,d) Curl_nss_sha256sum(a,b,c,d)
|
||||||
#define curlssl_cert_status_request() Curl_nss_cert_status_request()
|
#define curlssl_cert_status_request() Curl_nss_cert_status_request()
|
||||||
#define curlssl_false_start() Curl_nss_false_start()
|
#define curlssl_false_start() Curl_nss_false_start()
|
||||||
|
|
||||||
|
@ -3183,6 +3183,18 @@ void Curl_ossl_md5sum(unsigned char *tmp, /* input */
|
|||||||
MD5_Final(md5sum, &MD5pw);
|
MD5_Final(md5sum, &MD5pw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Curl_ossl_sha256sum(const unsigned char *tmp, /* input */
|
||||||
|
size_t tmplen,
|
||||||
|
unsigned char *sha256sum /* output */,
|
||||||
|
size_t unused)
|
||||||
|
{
|
||||||
|
SHA256_CTX SHA256pw;
|
||||||
|
(void)unused;
|
||||||
|
SHA256_Init(&SHA256pw);
|
||||||
|
SHA256_Update(&SHA256pw, tmp, tmplen);
|
||||||
|
SHA256_Final(sha256sum, &SHA256pw);
|
||||||
|
}
|
||||||
|
|
||||||
bool Curl_ossl_cert_status_request(void)
|
bool Curl_ossl_cert_status_request(void)
|
||||||
{
|
{
|
||||||
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
|
#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \
|
||||||
|
@ -72,6 +72,10 @@ void Curl_ossl_md5sum(unsigned char *tmp, /* input */
|
|||||||
size_t tmplen,
|
size_t tmplen,
|
||||||
unsigned char *md5sum /* output */,
|
unsigned char *md5sum /* output */,
|
||||||
size_t unused);
|
size_t unused);
|
||||||
|
void Curl_ossl_sha256sum(const unsigned char *tmp, /* input */
|
||||||
|
size_t tmplen,
|
||||||
|
unsigned char *sha256sum /* output */,
|
||||||
|
size_t unused);
|
||||||
|
|
||||||
bool Curl_ossl_cert_status_request(void);
|
bool Curl_ossl_cert_status_request(void);
|
||||||
|
|
||||||
@ -104,6 +108,7 @@ bool Curl_ossl_cert_status_request(void);
|
|||||||
#define curlssl_data_pending(x,y) Curl_ossl_data_pending(x,y)
|
#define curlssl_data_pending(x,y) Curl_ossl_data_pending(x,y)
|
||||||
#define curlssl_random(x,y,z) Curl_ossl_random(x,y,z)
|
#define curlssl_random(x,y,z) Curl_ossl_random(x,y,z)
|
||||||
#define curlssl_md5sum(a,b,c,d) Curl_ossl_md5sum(a,b,c,d)
|
#define curlssl_md5sum(a,b,c,d) Curl_ossl_md5sum(a,b,c,d)
|
||||||
|
#define curlssl_sha256sum(a,b,c,d) Curl_ossl_sha256sum(a,b,c,d)
|
||||||
#define curlssl_cert_status_request() Curl_ossl_cert_status_request()
|
#define curlssl_cert_status_request() Curl_ossl_cert_status_request()
|
||||||
|
|
||||||
#define DEFAULT_CIPHER_SELECTION \
|
#define DEFAULT_CIPHER_SELECTION \
|
||||||
|
@ -774,12 +774,78 @@ CURLcode Curl_pin_peer_pubkey(const char *pinnedpubkey,
|
|||||||
size_t size, pem_len;
|
size_t size, pem_len;
|
||||||
CURLcode pem_read;
|
CURLcode pem_read;
|
||||||
CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
|
CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
|
||||||
|
#ifdef curlssl_sha256sum
|
||||||
|
size_t pinkeylen;
|
||||||
|
char *pinkeycopy, *begin_pos, *end_pos;
|
||||||
|
unsigned char *sha256sumdigest = NULL, *expectedsha256sumdigest = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* if a path wasn't specified, don't pin */
|
/* if a path wasn't specified, don't pin */
|
||||||
if(!pinnedpubkey)
|
if(!pinnedpubkey)
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
if(!pubkey || !pubkeylen)
|
if(!pubkey || !pubkeylen)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
#ifdef curlssl_sha256sum
|
||||||
|
/* only do this if pinnedpubkey starts with "sha256//", length 8 */
|
||||||
|
if(strncmp(pinnedpubkey, "sha256//", 8) == 0) {
|
||||||
|
/* compute sha256sum of public key */
|
||||||
|
sha256sumdigest = malloc(SHA256_DIGEST_LENGTH);
|
||||||
|
if(!sha256sumdigest)
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
curlssl_sha256sum(pubkey, pubkeylen,
|
||||||
|
sha256sumdigest, SHA256_DIGEST_LENGTH);
|
||||||
|
|
||||||
|
/* it starts with sha256//, copy so we can modify it */
|
||||||
|
pinkeylen = strlen(pinnedpubkey) + 1;
|
||||||
|
pinkeycopy = malloc(pinkeylen);
|
||||||
|
if(!pinkeycopy) {
|
||||||
|
Curl_safefree(sha256sumdigest);
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
memcpy(pinkeycopy, pinnedpubkey, pinkeylen);
|
||||||
|
/* point begin_pos to the copy, and start extracting keys */
|
||||||
|
begin_pos = pinkeycopy;
|
||||||
|
do {
|
||||||
|
end_pos = strstr(begin_pos, ";sha256//");
|
||||||
|
/*
|
||||||
|
* if there is an end_pos, null terminate,
|
||||||
|
* otherwise it'll go to the end of the original string
|
||||||
|
*/
|
||||||
|
if(end_pos)
|
||||||
|
end_pos[0] = '\0';
|
||||||
|
|
||||||
|
/* decode base64 pinnedpubkey, 8 is length of "sha256//" */
|
||||||
|
pem_read = Curl_base64_decode(begin_pos + 8,
|
||||||
|
&expectedsha256sumdigest, &size);
|
||||||
|
/* if not valid base64, don't bother comparing or freeing */
|
||||||
|
if(!pem_read) {
|
||||||
|
/* compare sha256 digests directly */
|
||||||
|
if(SHA256_DIGEST_LENGTH == size &&
|
||||||
|
!memcmp(sha256sumdigest, expectedsha256sumdigest,
|
||||||
|
SHA256_DIGEST_LENGTH)) {
|
||||||
|
result = CURLE_OK;
|
||||||
|
Curl_safefree(expectedsha256sumdigest);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Curl_safefree(expectedsha256sumdigest);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* change back the null-terminator we changed earlier,
|
||||||
|
* and look for next begin
|
||||||
|
*/
|
||||||
|
if(end_pos) {
|
||||||
|
end_pos[0] = ';';
|
||||||
|
begin_pos = strstr(end_pos, "sha256//");
|
||||||
|
}
|
||||||
|
} while(end_pos && begin_pos);
|
||||||
|
Curl_safefree(sha256sumdigest);
|
||||||
|
Curl_safefree(pinkeycopy);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
fp = fopen(pinnedpubkey, "rb");
|
fp = fopen(pinnedpubkey, "rb");
|
||||||
if(!fp)
|
if(!fp)
|
||||||
return result;
|
return result;
|
||||||
|
@ -41,6 +41,10 @@
|
|||||||
#define MD5_DIGEST_LENGTH 16 /* fixed size */
|
#define MD5_DIGEST_LENGTH 16 /* fixed size */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef SHA256_DIGEST_LENGTH
|
||||||
|
#define SHA256_DIGEST_LENGTH 32 /* fixed size */
|
||||||
|
#endif
|
||||||
|
|
||||||
/* see http://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-04 */
|
/* see http://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-04 */
|
||||||
#define ALPN_HTTP_1_1_LENGTH 8
|
#define ALPN_HTTP_1_1_LENGTH 8
|
||||||
#define ALPN_HTTP_1_1 "http/1.1"
|
#define ALPN_HTTP_1_1 "http/1.1"
|
||||||
|
@ -156,8 +156,7 @@ static const char *const helptext[] = {
|
|||||||
" -o, --output FILE Write to FILE instead of stdout",
|
" -o, --output FILE Write to FILE instead of stdout",
|
||||||
" --pass PASS Pass phrase for the private key (SSL/SSH)",
|
" --pass PASS Pass phrase for the private key (SSL/SSH)",
|
||||||
" --path-as-is Do not squash .. sequences in URL path",
|
" --path-as-is Do not squash .. sequences in URL path",
|
||||||
" --pinnedpubkey FILE Public key (PEM/DER) to verify peer against "
|
" --pinnedpubkey FILE/HASHES Public key to verify peer against (SSL)",
|
||||||
"(OpenSSL/GnuTLS/NSS/wolfSSL/CyaSSL/GSKit only)",
|
|
||||||
" --post301 "
|
" --post301 "
|
||||||
"Do not switch to GET after following a 301 redirect (H)",
|
"Do not switch to GET after following a 301 redirect (H)",
|
||||||
" --post302 "
|
" --post302 "
|
||||||
|
@ -166,4 +166,4 @@ test2008 test2009 test2010 test2011 test2012 test2013 test2014 test2015 \
|
|||||||
test2016 test2017 test2018 test2019 test2020 test2021 test2022 test2023 \
|
test2016 test2017 test2018 test2019 test2020 test2021 test2022 test2023 \
|
||||||
test2024 test2025 test2026 test2027 test2028 test2029 test2030 test2031 \
|
test2024 test2025 test2026 test2027 test2028 test2029 test2030 test2031 \
|
||||||
test2032 test2033 test2034 test2035 test2036 test2037 test2038 test2039 \
|
test2032 test2033 test2034 test2035 test2036 test2037 test2038 test2039 \
|
||||||
test2040
|
test2040 test2041 test2042
|
||||||
|
58
tests/data/test2041
Normal file
58
tests/data/test2041
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
<testcase>
|
||||||
|
<info>
|
||||||
|
<keywords>
|
||||||
|
HTTPS
|
||||||
|
HTTP GET
|
||||||
|
PEM certificate
|
||||||
|
</keywords>
|
||||||
|
</info>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Server-side
|
||||||
|
<reply>
|
||||||
|
<data>
|
||||||
|
HTTP/1.1 200 OK
|
||||||
|
Date: Thu, 09 Nov 2010 14:49:00 GMT
|
||||||
|
Server: test-server/fake
|
||||||
|
Content-Length: 7
|
||||||
|
|
||||||
|
MooMoo
|
||||||
|
</data>
|
||||||
|
</reply>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Client-side
|
||||||
|
<client>
|
||||||
|
<features>
|
||||||
|
SSL
|
||||||
|
SSLpinning
|
||||||
|
</features>
|
||||||
|
<server>
|
||||||
|
https Server-localhost-sv.pem
|
||||||
|
</server>
|
||||||
|
<name>
|
||||||
|
simple HTTPS GET with base64-sha256 public key pinning
|
||||||
|
</name>
|
||||||
|
<command>
|
||||||
|
--cacert %SRCDIR/certs/EdelCurlRoot-ca.crt --pinnedpubkey sha256//pyh+fICi9M8MFEZvherIT0cs3MN+cXNGoU9Giwyx1so= https://localhost:%HTTPSPORT/2041
|
||||||
|
</command>
|
||||||
|
# Ensure that we're running on localhost because we're checking the host name
|
||||||
|
<precheck>
|
||||||
|
perl -e "print 'Test requires default test server host' if ( '%HOSTIP' ne '127.0.0.1' );"
|
||||||
|
</precheck>
|
||||||
|
</client>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Verify data after the test has been "shot"
|
||||||
|
<verify>
|
||||||
|
<strip>
|
||||||
|
^User-Agent:.*
|
||||||
|
</strip>
|
||||||
|
<protocol>
|
||||||
|
GET /2041 HTTP/1.1
|
||||||
|
Host: localhost:%HTTPSPORT
|
||||||
|
Accept: */*
|
||||||
|
|
||||||
|
</protocol>
|
||||||
|
</verify>
|
||||||
|
</testcase>
|
44
tests/data/test2042
Normal file
44
tests/data/test2042
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<testcase>
|
||||||
|
<info>
|
||||||
|
<keywords>
|
||||||
|
HTTPS
|
||||||
|
HTTP GET
|
||||||
|
PEM certificate
|
||||||
|
</keywords>
|
||||||
|
</info>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Server-side
|
||||||
|
<reply>
|
||||||
|
</reply>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Client-side
|
||||||
|
<client>
|
||||||
|
<features>
|
||||||
|
SSL
|
||||||
|
SSLpinning
|
||||||
|
</features>
|
||||||
|
<server>
|
||||||
|
https Server-localhost-sv.pem
|
||||||
|
</server>
|
||||||
|
<name>
|
||||||
|
HTTPS wrong base64-sha256 pinnedpubkey but right CN
|
||||||
|
</name>
|
||||||
|
<command>
|
||||||
|
--cacert %SRCDIR/certs/EdelCurlRoot-ca.crt --pinnedpubkey sha256//bSIggTf+ikMG0CtmDlpMVBd7yi7H1md4URogRPqerso= https://localhost:%HTTPSPORT/2042
|
||||||
|
</command>
|
||||||
|
# Ensure that we're running on localhost because we're checking the host name
|
||||||
|
<precheck>
|
||||||
|
perl -e "print 'Test requires default test server host' if ( '%HOSTIP' ne '127.0.0.1' );"
|
||||||
|
</precheck>
|
||||||
|
</client>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Verify data after the test has been "shot"
|
||||||
|
<verify>
|
||||||
|
<errorcode>
|
||||||
|
90
|
||||||
|
</errorcode>
|
||||||
|
</verify>
|
||||||
|
</testcase>
|
Loading…
Reference in New Issue
Block a user