Mercurial > trustbridge > trustbridge
comparison patches/0002-Add-CURLOPT_PEERCERT-option-to-pin-a-peer-cert.patch @ 1086:93325618ac7b
(issue117) Set verify callback to abort the handshake earlier if the certificate does not match.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Fri, 12 Sep 2014 13:09:02 +0200 |
parents | 0570b1e562c2 |
children |
comparison
equal
deleted
inserted
replaced
1085:84311f4ce89b | 1086:93325618ac7b |
---|---|
1 From c57d951c3bda8b1ca66cac45dfd6270fa34b01d3 Mon Sep 17 00:00:00 2001 | 1 From e5c7feec5151299975fe03184cc322ea51fb45c2 Mon Sep 17 00:00:00 2001 |
2 From: Andre Heinecke <aheinecke@intevation.de> | 2 From: Andre Heinecke <aheinecke@intevation.de> |
3 Date: Mon, 1 Sep 2014 16:55:40 +0200 | 3 Date: Fri, 12 Sep 2014 13:01:07 +0200 |
4 Subject: [PATCH 2/3] Add CURLOPT_PEERCERT option to pin a peer cert | 4 Subject: [PATCH 2/2] Add CURLOPT_PEERCERT option to pin a peer cert |
5 | 5 |
6 Only implemented for a specific usecase with polarssl | 6 This is only implemented for a specific usecase with polarssl |
7 --- | 7 --- |
8 include/curl/curl.h | 3 +++ | 8 include/curl/curl.h | 3 +++ |
9 include/curl/typecheck-gcc.h | 1 + | 9 include/curl/typecheck-gcc.h | 1 + |
10 lib/url.c | 8 ++++++++ | 10 lib/url.c | 8 ++++++++ |
11 lib/urldata.h | 1 + | 11 lib/urldata.h | 1 + |
12 lib/vtls/polarssl.c | 42 ++++++++++++++++++++++++++++++++++++++++-- | 12 lib/vtls/polarssl.c | 41 +++++++++++++++++++++++++++++++++++++++++ |
13 5 files changed, 53 insertions(+), 2 deletions(-) | 13 5 files changed, 54 insertions(+) |
14 | 14 |
15 diff --git a/include/curl/curl.h b/include/curl/curl.h | 15 diff --git a/include/curl/curl.h b/include/curl/curl.h |
16 index d40b2db..20a9d82 100644 | 16 index d40b2db..20a9d82 100644 |
17 --- a/include/curl/curl.h | 17 --- a/include/curl/curl.h |
18 +++ b/include/curl/curl.h | 18 +++ b/include/curl/curl.h |
37 + (option) == CURLOPT_PEERCERT || \ | 37 + (option) == CURLOPT_PEERCERT || \ |
38 (option) == CURLOPT_SOCKS5_GSSAPI_SERVICE || \ | 38 (option) == CURLOPT_SOCKS5_GSSAPI_SERVICE || \ |
39 (option) == CURLOPT_SSH_KNOWNHOSTS || \ | 39 (option) == CURLOPT_SSH_KNOWNHOSTS || \ |
40 (option) == CURLOPT_MAIL_FROM || \ | 40 (option) == CURLOPT_MAIL_FROM || \ |
41 diff --git a/lib/url.c b/lib/url.c | 41 diff --git a/lib/url.c b/lib/url.c |
42 index 89c3fd5..b089cdf 100644 | 42 index 67126ab3..5721ee2 100644 |
43 --- a/lib/url.c | 43 --- a/lib/url.c |
44 +++ b/lib/url.c | 44 +++ b/lib/url.c |
45 @@ -2015,6 +2015,14 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, | 45 @@ -2015,6 +2015,14 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, |
46 result = setstropt(&data->set.str[STRING_SSL_ISSUERCERT], | 46 result = setstropt(&data->set.str[STRING_SSL_ISSUERCERT], |
47 va_arg(param, char *)); | 47 va_arg(param, char *)); |
68 + STRING_SSL_PEERCERT, /* issuer cert file to check certificate */ | 68 + STRING_SSL_PEERCERT, /* issuer cert file to check certificate */ |
69 STRING_USERNAME, /* <username>, if used */ | 69 STRING_USERNAME, /* <username>, if used */ |
70 STRING_PASSWORD, /* <password>, if used */ | 70 STRING_PASSWORD, /* <password>, if used */ |
71 STRING_OPTIONS, /* <options>, if used */ | 71 STRING_OPTIONS, /* <options>, if used */ |
72 diff --git a/lib/vtls/polarssl.c b/lib/vtls/polarssl.c | 72 diff --git a/lib/vtls/polarssl.c b/lib/vtls/polarssl.c |
73 index e18cadf..2c40e36 100644 | 73 index 08dc4c6..8f34901 100644 |
74 --- a/lib/vtls/polarssl.c | 74 --- a/lib/vtls/polarssl.c |
75 +++ b/lib/vtls/polarssl.c | 75 +++ b/lib/vtls/polarssl.c |
76 @@ -360,6 +360,7 @@ polarssl_connect_step2(struct connectdata *conn, | 76 @@ -403,6 +403,44 @@ polarssl_connect_step1(struct connectdata *conn, |
77 #ifdef HAS_ALPN | 77 return CURLE_OK; |
78 const char* next_protocol; | 78 } |
79 #endif | |
80 + const x509_crt *peer_cert = NULL; | |
81 | 79 |
82 char errorbuf[128]; | 80 +static int |
83 memset(errorbuf, 0, sizeof(errorbuf)); | 81 +pinned_verify(void *pinned_cert_file_name, x509_crt *crt, |
84 @@ -419,12 +420,49 @@ polarssl_connect_step2(struct connectdata *conn, | 82 + int depth, int *flags) |
85 return CURLE_PEER_FAILED_VERIFICATION; | 83 +{ |
86 } | 84 + x509_crt pinned_cert; |
85 + x509_crt *leaf = crt; | |
86 + unsigned int i; | |
87 + int ret; | |
88 + | |
89 + if (pinned_cert_file_name == NULL || crt == NULL) { | |
90 + *flags |= BADCERT_NOT_TRUSTED; | |
91 + return *flags; | |
92 + } | |
93 + | |
94 + x509_crt_init(&pinned_cert); | |
95 + ret = x509_crt_parse_file(&pinned_cert, pinned_cert_file_name); | |
96 + | |
97 + if(ret) { | |
98 + x509_crt_free(&pinned_cert); | |
99 + *flags |= BADCERT_NOT_TRUSTED; | |
100 + return *flags; | |
101 + } | |
102 + | |
103 + while (leaf->next) { | |
104 + leaf = leaf->next; | |
105 + } | |
106 + | |
107 + ret = memcmp(pinned_cert.raw.p, leaf->raw.p, pinned_cert.raw.len); | |
108 + x509_crt_free(&pinned_cert); | |
109 + if (ret == 0) { | |
110 + *flags = 0; | |
111 + return 0; | |
112 + } | |
113 + | |
114 + *flags |= BADCERT_NOT_TRUSTED; | |
115 + return *flags; | |
116 +} | |
117 + | |
118 static CURLcode | |
119 polarssl_connect_step2(struct connectdata *conn, | |
120 int sockindex) | |
121 @@ -422,6 +460,9 @@ polarssl_connect_step2(struct connectdata *conn, | |
122 conn->recv[sockindex] = polarssl_recv; | |
123 conn->send[sockindex] = polarssl_send; | |
87 | 124 |
88 - if(ssl_get_peer_cert(&(connssl->ssl))) { | 125 + if(data->set.str[STRING_SSL_PEERCERT]) |
89 + peer_cert = ssl_get_peer_cert(&(connssl->ssl)); | 126 + ssl_set_verify (&connssl->ssl, pinned_verify, data->set.str[STRING_SSL_PEERCERT]); |
90 + if(peer_cert) { | |
91 + if(data->set.str[STRING_SSL_PEERCERT]) { | |
92 + x509_crt pinned_cert; | |
93 + unsigned int i; | |
94 + | 127 + |
95 + /* Handle pinned certificate */ | 128 for(;;) { |
96 + x509_crt_init(&pinned_cert); | 129 if(!(ret = ssl_handshake(&connssl->ssl))) |
97 + ret = x509_crt_parse_file(&pinned_cert, | 130 break; |
98 + data->set.str[STRING_SSL_PEERCERT]); | |
99 + | |
100 + if(ret) { | |
101 +#ifdef POLARSSL_ERROR_C | |
102 + error_strerror(ret, errorbuf, sizeof(errorbuf)); | |
103 +#endif /* POLARSSL_ERROR_C */ | |
104 + failf(data, "Error reading peer cert file %s - PolarSSL: (-0x%04X) %s", | |
105 + data->set.str[STRING_SSL_PEERCERT], -ret, errorbuf); | |
106 + | |
107 + x509_crt_free(&pinned_cert); | |
108 + return CURLE_PEER_FAILED_VERIFICATION; | |
109 + } | |
110 + | |
111 + if (peer_cert->raw.len == 0 || | |
112 + peer_cert->raw.len != pinned_cert.raw.len) { | |
113 + failf(data, "Error validating peer certificate. Size does " | |
114 + "not match the certificate set with PEERCERT option.\n"); | |
115 + x509_crt_free(&pinned_cert); | |
116 + return CURLE_PEER_FAILED_VERIFICATION; | |
117 + } | |
118 + for (i = 0; i < peer_cert->raw.len; i++) { | |
119 + if (peer_cert->raw.p[i] != pinned_cert.raw.p[i]) { | |
120 + failf(data, "Error validating peer certificate. Does " | |
121 + "not match the certificate set with PEERCERT option.\n"); | |
122 + return CURLE_PEER_FAILED_VERIFICATION; | |
123 + } | |
124 + } | |
125 + } | |
126 + | |
127 /* If the session was resumed, there will be no peer certs */ | |
128 memset(buffer, 0, sizeof(buffer)); | |
129 | |
130 if(x509_crt_info(buffer, sizeof(buffer), (char *)"* ", | |
131 - ssl_get_peer_cert(&(connssl->ssl))) != -1) | |
132 + peer_cert) != -1) | |
133 infof(data, "Dumping cert info:\n%s\n", buffer); | |
134 } | |
135 | |
136 -- | 131 -- |
137 1.9.1 | 132 1.9.1 |
138 | 133 |