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

http://wald.intevation.org/projects/trustbridge/