blob: 366dca95077951e20643956b47d34d68041e33f8 [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
Craig Tiller6169d5f2016-03-31 07:46:18 -07003 * Copyright 2015, Google Inc.
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08004 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
murgatroid99dedb9232016-09-26 13:54:04 -070034#include "src/core/lib/tsi/ssl_transport_security.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080035
Paul Querna47d841d2016-03-10 11:19:17 -080036#include <grpc/support/port_platform.h>
37
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080038#include <limits.h>
Julien Boeuf330f4c82015-04-27 10:37:42 -070039#include <string.h>
Paul Querna27df6892016-03-13 13:34:27 -070040
Nicolas "Pixel" Noblee3df5a02016-10-27 00:41:13 +020041/* TODO(jboeuf): refactor inet_ntop into a portability header. */
42/* Note: for whomever reads this and tries to refactor this, this
43 can't be in grpc, it has to be in gpr. */
44#ifdef GPR_WINDOWS
45#include <ws2tcpip.h>
46#else
47#include <arpa/inet.h>
48#endif
49
Nicolas "Pixel" Nobleb29d8cf2016-04-08 01:38:29 +020050#include <grpc/support/alloc.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080051#include <grpc/support/log.h>
nnoble8a23a3d2014-12-16 10:10:29 -080052#include <grpc/support/sync.h>
Julien Boeuf4a0a3942015-02-03 15:04:45 -080053#include <grpc/support/thd.h>
Nicolas "Pixel" Noble213ed912015-01-30 02:11:35 +010054#include <grpc/support/useful.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080055
56#include <openssl/bio.h>
Craig Tillera82950e2015-09-22 12:33:20 -070057#include <openssl/crypto.h> /* For OPENSSL_free */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080058#include <openssl/err.h>
59#include <openssl/ssl.h>
60#include <openssl/x509.h>
61#include <openssl/x509v3.h>
62
Craig Tiller9533d042016-03-25 17:11:06 -070063#include "src/core/lib/tsi/ssl_types.h"
64#include "src/core/lib/tsi/transport_security.h"
Craig Tiller0fe5ee72015-12-22 12:50:36 -080065
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080066/* --- Constants. ---*/
67
68#define TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND 16384
69#define TSI_SSL_MAX_PROTECTED_FRAME_SIZE_LOWER_BOUND 1024
70
Julien Boeuf3e29de12015-06-18 23:29:13 +020071/* Putting a macro like this and littering the source file with #if is really
72 bad practice.
73 TODO(jboeuf): refactor all the #if / #endif in a separate module. */
Julien Boeufd1531322015-06-18 11:05:39 +020074#ifndef TSI_OPENSSL_ALPN_SUPPORT
75#define TSI_OPENSSL_ALPN_SUPPORT 1
76#endif
77
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080078/* TODO(jboeuf): I have not found a way to get this number dynamically from the
Julien Boeuf3e29de12015-06-18 23:29:13 +020079 SSL structure. This is what we would ultimately want though... */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080080#define TSI_SSL_MAX_PROTECTION_OVERHEAD 100
81
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080082/* --- Structure definitions. ---*/
83
Craig Tillera82950e2015-09-22 12:33:20 -070084struct tsi_ssl_handshaker_factory {
85 tsi_result (*create_handshaker)(tsi_ssl_handshaker_factory *self,
86 const char *server_name_indication,
87 tsi_handshaker **handshaker);
88 void (*destroy)(tsi_ssl_handshaker_factory *self);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080089};
90
Craig Tillera82950e2015-09-22 12:33:20 -070091typedef struct {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080092 tsi_ssl_handshaker_factory base;
Craig Tiller45724b32015-09-22 10:42:19 -070093 SSL_CTX *ssl_context;
94 unsigned char *alpn_protocol_list;
Julien Boeufd1531322015-06-18 11:05:39 +020095 size_t alpn_protocol_list_length;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080096} tsi_ssl_client_handshaker_factory;
97
Craig Tillera82950e2015-09-22 12:33:20 -070098typedef struct {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080099 tsi_ssl_handshaker_factory base;
100
101 /* Several contexts to support SNI.
102 The tsi_peer array contains the subject names of the server certificates
103 associated with the contexts at the same index. */
Craig Tiller45724b32015-09-22 10:42:19 -0700104 SSL_CTX **ssl_contexts;
105 tsi_peer *ssl_context_x509_subject_names;
Julien Boeufb222b4d2015-01-15 17:01:39 -0800106 size_t ssl_context_count;
Craig Tiller45724b32015-09-22 10:42:19 -0700107 unsigned char *alpn_protocol_list;
Julien Boeufb222b4d2015-01-15 17:01:39 -0800108 size_t alpn_protocol_list_length;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800109} tsi_ssl_server_handshaker_factory;
110
Craig Tillera82950e2015-09-22 12:33:20 -0700111typedef struct {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800112 tsi_handshaker base;
Craig Tiller45724b32015-09-22 10:42:19 -0700113 SSL *ssl;
114 BIO *into_ssl;
115 BIO *from_ssl;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800116 tsi_result result;
117} tsi_ssl_handshaker;
118
Craig Tillera82950e2015-09-22 12:33:20 -0700119typedef struct {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800120 tsi_frame_protector base;
Craig Tiller45724b32015-09-22 10:42:19 -0700121 SSL *ssl;
122 BIO *into_ssl;
123 BIO *from_ssl;
124 unsigned char *buffer;
Julien Boeufb222b4d2015-01-15 17:01:39 -0800125 size_t buffer_size;
126 size_t buffer_offset;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800127} tsi_ssl_frame_protector;
128
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800129/* --- Library Initialization. ---*/
130
nnoble8a23a3d2014-12-16 10:10:29 -0800131static gpr_once init_openssl_once = GPR_ONCE_INIT;
Craig Tiller45724b32015-09-22 10:42:19 -0700132static gpr_mu *openssl_mutexes = NULL;
Julien Boeuf4a0a3942015-02-03 15:04:45 -0800133
Craig Tillera82950e2015-09-22 12:33:20 -0700134static void openssl_locking_cb(int mode, int type, const char *file, int line) {
135 if (mode & CRYPTO_LOCK) {
136 gpr_mu_lock(&openssl_mutexes[type]);
137 } else {
138 gpr_mu_unlock(&openssl_mutexes[type]);
139 }
Julien Boeuf4a0a3942015-02-03 15:04:45 -0800140}
141
Craig Tillera82950e2015-09-22 12:33:20 -0700142static unsigned long openssl_thread_id_cb(void) {
143 return (unsigned long)gpr_thd_currentid();
Julien Boeuf4a0a3942015-02-03 15:04:45 -0800144}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800145
Craig Tillera82950e2015-09-22 12:33:20 -0700146static void init_openssl(void) {
Julien Boeuf4a0a3942015-02-03 15:04:45 -0800147 int i;
Craig Tiller3121fd42015-09-10 09:56:20 -0700148 int num_locks;
Craig Tillera82950e2015-09-22 12:33:20 -0700149 SSL_library_init();
150 SSL_load_error_strings();
151 OpenSSL_add_all_algorithms();
152 num_locks = CRYPTO_num_locks();
153 GPR_ASSERT(num_locks > 0);
Nicolas "Pixel" Noble7c9a1542016-03-26 01:33:34 +0100154 openssl_mutexes = gpr_malloc((size_t)num_locks * sizeof(gpr_mu));
Craig Tillera82950e2015-09-22 12:33:20 -0700155 for (i = 0; i < CRYPTO_num_locks(); i++) {
156 gpr_mu_init(&openssl_mutexes[i]);
157 }
158 CRYPTO_set_locking_callback(openssl_locking_cb);
159 CRYPTO_set_id_callback(openssl_thread_id_cb);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800160}
161
162/* --- Ssl utils. ---*/
163
Craig Tillera82950e2015-09-22 12:33:20 -0700164static const char *ssl_error_string(int error) {
165 switch (error) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800166 case SSL_ERROR_NONE:
167 return "SSL_ERROR_NONE";
168 case SSL_ERROR_ZERO_RETURN:
169 return "SSL_ERROR_ZERO_RETURN";
170 case SSL_ERROR_WANT_READ:
171 return "SSL_ERROR_WANT_READ";
172 case SSL_ERROR_WANT_WRITE:
173 return "SSL_ERROR_WANT_WRITE";
174 case SSL_ERROR_WANT_CONNECT:
175 return "SSL_ERROR_WANT_CONNECT";
176 case SSL_ERROR_WANT_ACCEPT:
177 return "SSL_ERROR_WANT_ACCEPT";
178 case SSL_ERROR_WANT_X509_LOOKUP:
179 return "SSL_ERROR_WANT_X509_LOOKUP";
180 case SSL_ERROR_SYSCALL:
181 return "SSL_ERROR_SYSCALL";
182 case SSL_ERROR_SSL:
183 return "SSL_ERROR_SSL";
184 default:
185 return "Unknown error";
Craig Tillera82950e2015-09-22 12:33:20 -0700186 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800187}
188
189/* TODO(jboeuf): Remove when we are past the debugging phase with this code. */
Craig Tillera82950e2015-09-22 12:33:20 -0700190static void ssl_log_where_info(const SSL *ssl, int where, int flag,
191 const char *msg) {
192 if ((where & flag) && tsi_tracing_enabled) {
193 gpr_log(GPR_INFO, "%20.20s - %30.30s - %5.10s", msg,
194 SSL_state_string_long(ssl), SSL_state_string(ssl));
195 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800196}
197
198/* Used for debugging. TODO(jboeuf): Remove when code is mature enough. */
Craig Tillera82950e2015-09-22 12:33:20 -0700199static void ssl_info_callback(const SSL *ssl, int where, int ret) {
200 if (ret == 0) {
201 gpr_log(GPR_ERROR, "ssl_info_callback: error occured.\n");
202 return;
203 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800204
Craig Tillera82950e2015-09-22 12:33:20 -0700205 ssl_log_where_info(ssl, where, SSL_CB_LOOP, "LOOP");
206 ssl_log_where_info(ssl, where, SSL_CB_HANDSHAKE_START, "HANDSHAKE START");
207 ssl_log_where_info(ssl, where, SSL_CB_HANDSHAKE_DONE, "HANDSHAKE DONE");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800208}
209
Julien Boeuf0170a6c2015-02-24 18:08:01 -0800210/* Returns 1 if name looks like an IP address, 0 otherwise.
Paul Querna4a9e7c42016-03-13 14:00:11 -0700211 This is a very rough heuristic, and only handles IPv6 in hexadecimal form. */
Craig Tillera82950e2015-09-22 12:33:20 -0700212static int looks_like_ip_address(const char *name) {
Julien Boeuf9fff77e2015-02-24 16:50:35 -0800213 size_t i;
214 size_t dot_count = 0;
215 size_t num_size = 0;
Craig Tillera82950e2015-09-22 12:33:20 -0700216 for (i = 0; i < strlen(name); i++) {
Paul Querna4a9e7c42016-03-13 14:00:11 -0700217 if (name[i] == ':') {
218 /* IPv6 Address in hexadecimal form, : is not allowed in DNS names. */
219 return 1;
220 }
Craig Tillera82950e2015-09-22 12:33:20 -0700221 if (name[i] >= '0' && name[i] <= '9') {
222 if (num_size > 3) return 0;
223 num_size++;
224 } else if (name[i] == '.') {
225 if (dot_count > 3 || num_size == 0) return 0;
226 dot_count++;
227 num_size = 0;
228 } else {
229 return 0;
Julien Boeuf9fff77e2015-02-24 16:50:35 -0800230 }
Craig Tillera82950e2015-09-22 12:33:20 -0700231 }
232 if (dot_count < 3 || num_size == 0) return 0;
Julien Boeuf9fff77e2015-02-24 16:50:35 -0800233 return 1;
234}
235
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800236/* Gets the subject CN from an X509 cert. */
Craig Tillera82950e2015-09-22 12:33:20 -0700237static tsi_result ssl_get_x509_common_name(X509 *cert, unsigned char **utf8,
238 size_t *utf8_size) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800239 int common_name_index = -1;
Craig Tiller45724b32015-09-22 10:42:19 -0700240 X509_NAME_ENTRY *common_name_entry = NULL;
241 ASN1_STRING *common_name_asn1 = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700242 X509_NAME *subject_name = X509_get_subject_name(cert);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800243 int utf8_returned_size = 0;
Craig Tillera82950e2015-09-22 12:33:20 -0700244 if (subject_name == NULL) {
245 gpr_log(GPR_ERROR, "Could not get subject name from certificate.");
246 return TSI_NOT_FOUND;
247 }
248 common_name_index =
249 X509_NAME_get_index_by_NID(subject_name, NID_commonName, -1);
250 if (common_name_index == -1) {
251 gpr_log(GPR_ERROR,
252 "Could not get common name of subject from certificate.");
253 return TSI_NOT_FOUND;
254 }
255 common_name_entry = X509_NAME_get_entry(subject_name, common_name_index);
256 if (common_name_entry == NULL) {
257 gpr_log(GPR_ERROR, "Could not get common name entry from certificate.");
258 return TSI_INTERNAL_ERROR;
259 }
260 common_name_asn1 = X509_NAME_ENTRY_get_data(common_name_entry);
261 if (common_name_asn1 == NULL) {
262 gpr_log(GPR_ERROR,
263 "Could not get common name entry asn1 from certificate.");
264 return TSI_INTERNAL_ERROR;
265 }
266 utf8_returned_size = ASN1_STRING_to_UTF8(utf8, common_name_asn1);
267 if (utf8_returned_size < 0) {
268 gpr_log(GPR_ERROR, "Could not extract utf8 from asn1 string.");
269 return TSI_OUT_OF_RESOURCES;
270 }
271 *utf8_size = (size_t)utf8_returned_size;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800272 return TSI_OK;
273}
274
275/* Gets the subject CN of an X509 cert as a tsi_peer_property. */
Craig Tillera82950e2015-09-22 12:33:20 -0700276static tsi_result peer_property_from_x509_common_name(
277 X509 *cert, tsi_peer_property *property) {
Craig Tiller45724b32015-09-22 10:42:19 -0700278 unsigned char *common_name;
Julien Boeufb222b4d2015-01-15 17:01:39 -0800279 size_t common_name_size;
Craig Tillera82950e2015-09-22 12:33:20 -0700280 tsi_result result =
281 ssl_get_x509_common_name(cert, &common_name, &common_name_size);
282 if (result != TSI_OK) {
283 if (result == TSI_NOT_FOUND) {
284 common_name = NULL;
285 common_name_size = 0;
286 } else {
287 return result;
Julien Boeuf9fff77e2015-02-24 16:50:35 -0800288 }
Craig Tillera82950e2015-09-22 12:33:20 -0700289 }
290 result = tsi_construct_string_peer_property(
291 TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY,
292 common_name == NULL ? "" : (const char *)common_name, common_name_size,
293 property);
294 OPENSSL_free(common_name);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800295 return result;
296}
297
Deepak Lukosee61cbe32016-03-14 14:10:44 -0700298/* Gets the X509 cert in PEM format as a tsi_peer_property. */
299static tsi_result add_pem_certificate(X509 *cert, tsi_peer_property *property) {
300 BIO *bio = BIO_new(BIO_s_mem());
301 if (!PEM_write_bio_X509(bio, cert)) {
302 BIO_free(bio);
303 return TSI_INTERNAL_ERROR;
304 }
305 char *contents;
306 long len = BIO_get_mem_data(bio, &contents);
307 if (len <= 0) {
308 BIO_free(bio);
309 return TSI_INTERNAL_ERROR;
310 }
311 tsi_result result = tsi_construct_string_peer_property(
312 TSI_X509_PEM_CERT_PROPERTY, (const char *)contents, (size_t)len,
313 property);
314 BIO_free(bio);
315 return result;
316}
317
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800318/* Gets the subject SANs from an X509 cert as a tsi_peer_property. */
Craig Tillera82950e2015-09-22 12:33:20 -0700319static tsi_result add_subject_alt_names_properties_to_peer(
320 tsi_peer *peer, GENERAL_NAMES *subject_alt_names,
321 size_t subject_alt_name_count) {
Craig Tiller3121fd42015-09-10 09:56:20 -0700322 size_t i;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800323 tsi_result result = TSI_OK;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800324
325 /* Reset for DNS entries filtering. */
Julien Boeuf77e8c1c2015-05-13 13:50:59 -0700326 peer->property_count -= subject_alt_name_count;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800327
Craig Tillera82950e2015-09-22 12:33:20 -0700328 for (i = 0; i < subject_alt_name_count; i++) {
329 GENERAL_NAME *subject_alt_name =
Craig Tiller0fe5ee72015-12-22 12:50:36 -0800330 sk_GENERAL_NAME_value(subject_alt_names, TSI_SIZE_AS_SIZE(i));
Craig Tillera82950e2015-09-22 12:33:20 -0700331 /* Filter out the non-dns entries names. */
332 if (subject_alt_name->type == GEN_DNS) {
Paul Querna47d841d2016-03-10 11:19:17 -0800333 unsigned char *name = NULL;
334 int name_size;
335 name_size = ASN1_STRING_to_UTF8(&name, subject_alt_name->d.dNSName);
336 if (name_size < 0) {
Craig Tillera82950e2015-09-22 12:33:20 -0700337 gpr_log(GPR_ERROR, "Could not get utf8 from asn1 string.");
338 result = TSI_INTERNAL_ERROR;
339 break;
340 }
341 result = tsi_construct_string_peer_property(
Paul Querna47d841d2016-03-10 11:19:17 -0800342 TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, (const char *)name,
343 (size_t)name_size, &peer->properties[peer->property_count++]);
344 OPENSSL_free(name);
345 } else if (subject_alt_name->type == GEN_IPADD) {
346 char ntop_buf[INET6_ADDRSTRLEN];
347 int af;
348
349 if (subject_alt_name->d.iPAddress->length == 4) {
350 af = AF_INET;
351 } else if (subject_alt_name->d.iPAddress->length == 16) {
352 af = AF_INET6;
353 } else {
354 gpr_log(GPR_ERROR, "SAN IP Address contained invalid IP");
355 result = TSI_INTERNAL_ERROR;
356 break;
357 }
Nicolas "Pixel" Noblee3df5a02016-10-27 00:41:13 +0200358 const char *name = inet_ntop(af, subject_alt_name->d.iPAddress->data,
359 ntop_buf, INET6_ADDRSTRLEN);
Paul Querna47d841d2016-03-10 11:19:17 -0800360 if (name == NULL) {
361 gpr_log(GPR_ERROR, "Could not get IP string from asn1 octet.");
362 result = TSI_INTERNAL_ERROR;
363 break;
364 }
365
366 result = tsi_construct_string_peer_property_from_cstring(
367 TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, name,
Craig Tillera82950e2015-09-22 12:33:20 -0700368 &peer->properties[peer->property_count++]);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800369 }
Paul Querna47d841d2016-03-10 11:19:17 -0800370 if (result != TSI_OK) break;
Craig Tillera82950e2015-09-22 12:33:20 -0700371 }
Julien Boeuf77e8c1c2015-05-13 13:50:59 -0700372 return result;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800373}
374
375/* Gets information about the peer's X509 cert as a tsi_peer object. */
Craig Tillera82950e2015-09-22 12:33:20 -0700376static tsi_result peer_from_x509(X509 *cert, int include_certificate_type,
377 tsi_peer *peer) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800378 /* TODO(jboeuf): Maybe add more properties. */
Craig Tillera82950e2015-09-22 12:33:20 -0700379 GENERAL_NAMES *subject_alt_names =
380 X509_get_ext_d2i(cert, NID_subject_alt_name, 0, 0);
Julien Boeuf01ac4f02015-10-09 16:08:24 -0700381 int subject_alt_name_count = (subject_alt_names != NULL)
382 ? (int)sk_GENERAL_NAME_num(subject_alt_names)
383 : 0;
Craig Tiller3121fd42015-09-10 09:56:20 -0700384 size_t property_count;
385 tsi_result result;
Craig Tillera82950e2015-09-22 12:33:20 -0700386 GPR_ASSERT(subject_alt_name_count >= 0);
387 property_count = (include_certificate_type ? (size_t)1 : 0) +
Deepak Lukosee61cbe32016-03-14 14:10:44 -0700388 2 /* common name, certificate */ +
389 (size_t)subject_alt_name_count;
Craig Tillera82950e2015-09-22 12:33:20 -0700390 result = tsi_construct_peer(property_count, peer);
391 if (result != TSI_OK) return result;
392 do {
393 if (include_certificate_type) {
394 result = tsi_construct_string_peer_property_from_cstring(
395 TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE,
396 &peer->properties[0]);
397 if (result != TSI_OK) break;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800398 }
Craig Tillera82950e2015-09-22 12:33:20 -0700399 result = peer_property_from_x509_common_name(
400 cert, &peer->properties[include_certificate_type ? 1 : 0]);
401 if (result != TSI_OK) break;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800402
Deepak Lukosee61cbe32016-03-14 14:10:44 -0700403 result = add_pem_certificate(
404 cert, &peer->properties[include_certificate_type ? 2 : 1]);
405 if (result != TSI_OK) break;
406
Craig Tillera82950e2015-09-22 12:33:20 -0700407 if (subject_alt_name_count != 0) {
408 result = add_subject_alt_names_properties_to_peer(
409 peer, subject_alt_names, (size_t)subject_alt_name_count);
410 if (result != TSI_OK) break;
Craig Tiller45724b32015-09-22 10:42:19 -0700411 }
Craig Tillera82950e2015-09-22 12:33:20 -0700412 } while (0);
413
414 if (subject_alt_names != NULL) {
415 sk_GENERAL_NAME_pop_free(subject_alt_names, GENERAL_NAME_free);
416 }
417 if (result != TSI_OK) tsi_peer_destruct(peer);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800418 return result;
419}
420
nnoble0c475f02014-12-05 15:37:39 -0800421/* Logs the SSL error stack. */
Craig Tillera82950e2015-09-22 12:33:20 -0700422static void log_ssl_error_stack(void) {
nnoble0c475f02014-12-05 15:37:39 -0800423 unsigned long err;
Craig Tillera82950e2015-09-22 12:33:20 -0700424 while ((err = ERR_get_error()) != 0) {
425 char details[256];
Julien Boeuf01ac4f02015-10-09 16:08:24 -0700426 ERR_error_string_n((uint32_t)err, details, sizeof(details));
Craig Tillera82950e2015-09-22 12:33:20 -0700427 gpr_log(GPR_ERROR, "%s", details);
428 }
nnoble0c475f02014-12-05 15:37:39 -0800429}
430
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800431/* Performs an SSL_read and handle errors. */
Craig Tillera82950e2015-09-22 12:33:20 -0700432static tsi_result do_ssl_read(SSL *ssl, unsigned char *unprotected_bytes,
433 size_t *unprotected_bytes_size) {
Craig Tillerf96dfc32015-09-10 14:43:18 -0700434 int read_from_ssl;
Craig Tillera82950e2015-09-22 12:33:20 -0700435 GPR_ASSERT(*unprotected_bytes_size <= INT_MAX);
436 read_from_ssl =
437 SSL_read(ssl, unprotected_bytes, (int)*unprotected_bytes_size);
438 if (read_from_ssl == 0) {
439 gpr_log(GPR_ERROR, "SSL_read returned 0 unexpectedly.");
440 return TSI_INTERNAL_ERROR;
441 }
442 if (read_from_ssl < 0) {
443 read_from_ssl = SSL_get_error(ssl, read_from_ssl);
444 switch (read_from_ssl) {
445 case SSL_ERROR_WANT_READ:
446 /* We need more data to finish the frame. */
447 *unprotected_bytes_size = 0;
448 return TSI_OK;
449 case SSL_ERROR_WANT_WRITE:
450 gpr_log(
451 GPR_ERROR,
452 "Peer tried to renegotiate SSL connection. This is unsupported.");
453 return TSI_UNIMPLEMENTED;
454 case SSL_ERROR_SSL:
455 gpr_log(GPR_ERROR, "Corruption detected.");
456 log_ssl_error_stack();
457 return TSI_DATA_CORRUPTED;
458 default:
459 gpr_log(GPR_ERROR, "SSL_read failed with error %s.",
460 ssl_error_string(read_from_ssl));
461 return TSI_PROTOCOL_FAILURE;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800462 }
Craig Tillera82950e2015-09-22 12:33:20 -0700463 }
464 *unprotected_bytes_size = (size_t)read_from_ssl;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800465 return TSI_OK;
466}
467
468/* Performs an SSL_write and handle errors. */
Craig Tillera82950e2015-09-22 12:33:20 -0700469static tsi_result do_ssl_write(SSL *ssl, unsigned char *unprotected_bytes,
470 size_t unprotected_bytes_size) {
Craig Tillerf96dfc32015-09-10 14:43:18 -0700471 int ssl_write_result;
Craig Tillera82950e2015-09-22 12:33:20 -0700472 GPR_ASSERT(unprotected_bytes_size <= INT_MAX);
473 ssl_write_result =
474 SSL_write(ssl, unprotected_bytes, (int)unprotected_bytes_size);
475 if (ssl_write_result < 0) {
476 ssl_write_result = SSL_get_error(ssl, ssl_write_result);
477 if (ssl_write_result == SSL_ERROR_WANT_READ) {
478 gpr_log(GPR_ERROR,
479 "Peer tried to renegotiate SSL connection. This is unsupported.");
480 return TSI_UNIMPLEMENTED;
481 } else {
482 gpr_log(GPR_ERROR, "SSL_write failed with error %s.",
483 ssl_error_string(ssl_write_result));
484 return TSI_INTERNAL_ERROR;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800485 }
Craig Tillera82950e2015-09-22 12:33:20 -0700486 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800487 return TSI_OK;
488}
489
490/* Loads an in-memory PEM certificate chain into the SSL context. */
Craig Tillera82950e2015-09-22 12:33:20 -0700491static tsi_result ssl_ctx_use_certificate_chain(
492 SSL_CTX *context, const unsigned char *pem_cert_chain,
493 size_t pem_cert_chain_size) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800494 tsi_result result = TSI_OK;
Craig Tiller45724b32015-09-22 10:42:19 -0700495 X509 *certificate = NULL;
496 BIO *pem;
Craig Tillera82950e2015-09-22 12:33:20 -0700497 GPR_ASSERT(pem_cert_chain_size <= INT_MAX);
498 pem = BIO_new_mem_buf((void *)pem_cert_chain, (int)pem_cert_chain_size);
499 if (pem == NULL) return TSI_OUT_OF_RESOURCES;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800500
Craig Tillera82950e2015-09-22 12:33:20 -0700501 do {
502 certificate = PEM_read_bio_X509_AUX(pem, NULL, NULL, "");
503 if (certificate == NULL) {
504 result = TSI_INVALID_ARGUMENT;
505 break;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800506 }
Craig Tillera82950e2015-09-22 12:33:20 -0700507 if (!SSL_CTX_use_certificate(context, certificate)) {
508 result = TSI_INVALID_ARGUMENT;
509 break;
510 }
511 while (1) {
512 X509 *certificate_authority = PEM_read_bio_X509(pem, NULL, NULL, "");
513 if (certificate_authority == NULL) {
514 ERR_clear_error();
515 break; /* Done reading. */
516 }
517 if (!SSL_CTX_add_extra_chain_cert(context, certificate_authority)) {
518 X509_free(certificate_authority);
519 result = TSI_INVALID_ARGUMENT;
520 break;
521 }
522 /* We don't need to free certificate_authority as its ownership has been
523 transfered to the context. That is not the case for certificate though.
524 */
525 }
526 } while (0);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800527
Craig Tillera82950e2015-09-22 12:33:20 -0700528 if (certificate != NULL) X509_free(certificate);
529 BIO_free(pem);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800530 return result;
531}
532
533/* Loads an in-memory PEM private key into the SSL context. */
Craig Tillera82950e2015-09-22 12:33:20 -0700534static tsi_result ssl_ctx_use_private_key(SSL_CTX *context,
535 const unsigned char *pem_key,
536 size_t pem_key_size) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800537 tsi_result result = TSI_OK;
Craig Tiller45724b32015-09-22 10:42:19 -0700538 EVP_PKEY *private_key = NULL;
539 BIO *pem;
Craig Tillera82950e2015-09-22 12:33:20 -0700540 GPR_ASSERT(pem_key_size <= INT_MAX);
541 pem = BIO_new_mem_buf((void *)pem_key, (int)pem_key_size);
542 if (pem == NULL) return TSI_OUT_OF_RESOURCES;
543 do {
544 private_key = PEM_read_bio_PrivateKey(pem, NULL, NULL, "");
545 if (private_key == NULL) {
546 result = TSI_INVALID_ARGUMENT;
547 break;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800548 }
Craig Tillera82950e2015-09-22 12:33:20 -0700549 if (!SSL_CTX_use_PrivateKey(context, private_key)) {
550 result = TSI_INVALID_ARGUMENT;
551 break;
552 }
553 } while (0);
554 if (private_key != NULL) EVP_PKEY_free(private_key);
555 BIO_free(pem);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800556 return result;
557}
558
559/* Loads in-memory PEM verification certs into the SSL context and optionally
560 returns the verification cert names (root_names can be NULL). */
Craig Tillera82950e2015-09-22 12:33:20 -0700561static tsi_result ssl_ctx_load_verification_certs(
562 SSL_CTX *context, const unsigned char *pem_roots, size_t pem_roots_size,
563 STACK_OF(X509_NAME) * *root_names) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800564 tsi_result result = TSI_OK;
Julien Boeufb222b4d2015-01-15 17:01:39 -0800565 size_t num_roots = 0;
Craig Tiller45724b32015-09-22 10:42:19 -0700566 X509 *root = NULL;
567 X509_NAME *root_name = NULL;
568 BIO *pem;
569 X509_STORE *root_store;
Craig Tillera82950e2015-09-22 12:33:20 -0700570 GPR_ASSERT(pem_roots_size <= INT_MAX);
571 pem = BIO_new_mem_buf((void *)pem_roots, (int)pem_roots_size);
572 root_store = SSL_CTX_get_cert_store(context);
573 if (root_store == NULL) return TSI_INVALID_ARGUMENT;
574 if (pem == NULL) return TSI_OUT_OF_RESOURCES;
575 if (root_names != NULL) {
576 *root_names = sk_X509_NAME_new_null();
577 if (*root_names == NULL) return TSI_OUT_OF_RESOURCES;
578 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800579
Craig Tillera82950e2015-09-22 12:33:20 -0700580 while (1) {
581 root = PEM_read_bio_X509_AUX(pem, NULL, NULL, "");
582 if (root == NULL) {
583 ERR_clear_error();
584 break; /* We're at the end of stream. */
nnoble0c475f02014-12-05 15:37:39 -0800585 }
Craig Tillera82950e2015-09-22 12:33:20 -0700586 if (root_names != NULL) {
587 root_name = X509_get_subject_name(root);
588 if (root_name == NULL) {
589 gpr_log(GPR_ERROR, "Could not get name from root certificate.");
590 result = TSI_INVALID_ARGUMENT;
591 break;
592 }
593 root_name = X509_NAME_dup(root_name);
594 if (root_name == NULL) {
595 result = TSI_OUT_OF_RESOURCES;
596 break;
597 }
598 sk_X509_NAME_push(*root_names, root_name);
599 root_name = NULL;
600 }
601 if (!X509_STORE_add_cert(root_store, root)) {
602 gpr_log(GPR_ERROR, "Could not add root certificate to ssl context.");
603 result = TSI_INTERNAL_ERROR;
604 break;
605 }
606 X509_free(root);
607 num_roots++;
608 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800609
Craig Tillera82950e2015-09-22 12:33:20 -0700610 if (num_roots == 0) {
611 gpr_log(GPR_ERROR, "Could not load any root certificate.");
612 result = TSI_INVALID_ARGUMENT;
613 }
Craig Tiller45724b32015-09-22 10:42:19 -0700614
Craig Tillera82950e2015-09-22 12:33:20 -0700615 if (result != TSI_OK) {
616 if (root != NULL) X509_free(root);
617 if (root_names != NULL) {
618 sk_X509_NAME_pop_free(*root_names, X509_NAME_free);
619 *root_names = NULL;
620 if (root_name != NULL) X509_NAME_free(root_name);
Craig Tiller45724b32015-09-22 10:42:19 -0700621 }
Craig Tillera82950e2015-09-22 12:33:20 -0700622 }
623 BIO_free(pem);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800624 return result;
625}
626
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800627/* Populates the SSL context with a private key and a cert chain, and sets the
628 cipher list and the ephemeral ECDH key. */
Craig Tillera82950e2015-09-22 12:33:20 -0700629static tsi_result populate_ssl_context(
630 SSL_CTX *context, const unsigned char *pem_private_key,
631 size_t pem_private_key_size, const unsigned char *pem_certificate_chain,
632 size_t pem_certificate_chain_size, const char *cipher_list) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800633 tsi_result result = TSI_OK;
Craig Tillera82950e2015-09-22 12:33:20 -0700634 if (pem_certificate_chain != NULL) {
635 result = ssl_ctx_use_certificate_chain(context, pem_certificate_chain,
636 pem_certificate_chain_size);
637 if (result != TSI_OK) {
638 gpr_log(GPR_ERROR, "Invalid cert chain file.");
639 return result;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800640 }
Craig Tillera82950e2015-09-22 12:33:20 -0700641 }
642 if (pem_private_key != NULL) {
643 result =
644 ssl_ctx_use_private_key(context, pem_private_key, pem_private_key_size);
645 if (result != TSI_OK || !SSL_CTX_check_private_key(context)) {
646 gpr_log(GPR_ERROR, "Invalid private key.");
647 return result != TSI_OK ? result : TSI_INVALID_ARGUMENT;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800648 }
Craig Tillera82950e2015-09-22 12:33:20 -0700649 }
650 if ((cipher_list != NULL) && !SSL_CTX_set_cipher_list(context, cipher_list)) {
651 gpr_log(GPR_ERROR, "Invalid cipher list: %s.", cipher_list);
652 return TSI_INVALID_ARGUMENT;
653 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800654 {
Craig Tillera82950e2015-09-22 12:33:20 -0700655 EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
656 if (!SSL_CTX_set_tmp_ecdh(context, ecdh)) {
657 gpr_log(GPR_ERROR, "Could not set ephemeral ECDH key.");
658 EC_KEY_free(ecdh);
659 return TSI_INTERNAL_ERROR;
660 }
661 SSL_CTX_set_options(context, SSL_OP_SINGLE_ECDH_USE);
662 EC_KEY_free(ecdh);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800663 }
664 return TSI_OK;
665}
666
667/* Extracts the CN and the SANs from an X509 cert as a peer object. */
Craig Tillera82950e2015-09-22 12:33:20 -0700668static tsi_result extract_x509_subject_names_from_pem_cert(
669 const unsigned char *pem_cert, size_t pem_cert_size, tsi_peer *peer) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800670 tsi_result result = TSI_OK;
Craig Tiller45724b32015-09-22 10:42:19 -0700671 X509 *cert = NULL;
672 BIO *pem;
Craig Tillera82950e2015-09-22 12:33:20 -0700673 GPR_ASSERT(pem_cert_size <= INT_MAX);
674 pem = BIO_new_mem_buf((void *)pem_cert, (int)pem_cert_size);
675 if (pem == NULL) return TSI_OUT_OF_RESOURCES;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800676
Craig Tillera82950e2015-09-22 12:33:20 -0700677 cert = PEM_read_bio_X509(pem, NULL, NULL, "");
678 if (cert == NULL) {
679 gpr_log(GPR_ERROR, "Invalid certificate");
680 result = TSI_INVALID_ARGUMENT;
681 } else {
682 result = peer_from_x509(cert, 0, peer);
683 }
684 if (cert != NULL) X509_free(cert);
685 BIO_free(pem);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800686 return result;
687}
688
689/* Builds the alpn protocol name list according to rfc 7301. */
Craig Tillera82950e2015-09-22 12:33:20 -0700690static tsi_result build_alpn_protocol_name_list(
691 const unsigned char **alpn_protocols,
692 const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols,
693 unsigned char **protocol_name_list, size_t *protocol_name_list_length) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800694 uint16_t i;
Craig Tiller45724b32015-09-22 10:42:19 -0700695 unsigned char *current;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800696 *protocol_name_list = NULL;
697 *protocol_name_list_length = 0;
Craig Tillera82950e2015-09-22 12:33:20 -0700698 if (num_alpn_protocols == 0) return TSI_INVALID_ARGUMENT;
699 for (i = 0; i < num_alpn_protocols; i++) {
700 if (alpn_protocols_lengths[i] == 0) {
701 gpr_log(GPR_ERROR, "Invalid 0-length protocol name.");
702 return TSI_INVALID_ARGUMENT;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800703 }
Craig Tillera82950e2015-09-22 12:33:20 -0700704 *protocol_name_list_length += (size_t)alpn_protocols_lengths[i] + 1;
705 }
Nicolas "Pixel" Noble7c9a1542016-03-26 01:33:34 +0100706 *protocol_name_list = gpr_malloc(*protocol_name_list_length);
Craig Tillera82950e2015-09-22 12:33:20 -0700707 if (*protocol_name_list == NULL) return TSI_OUT_OF_RESOURCES;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800708 current = *protocol_name_list;
Craig Tillera82950e2015-09-22 12:33:20 -0700709 for (i = 0; i < num_alpn_protocols; i++) {
710 *(current++) = alpn_protocols_lengths[i];
711 memcpy(current, alpn_protocols[i], alpn_protocols_lengths[i]);
712 current += alpn_protocols_lengths[i];
713 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800714 /* Safety check. */
Craig Tillera82950e2015-09-22 12:33:20 -0700715 if ((current < *protocol_name_list) ||
Craig Tiller7536af02015-12-22 13:49:30 -0800716 ((uintptr_t)(current - *protocol_name_list) !=
Craig Tillera82950e2015-09-22 12:33:20 -0700717 *protocol_name_list_length)) {
718 return TSI_INTERNAL_ERROR;
719 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800720 return TSI_OK;
721}
722
Deepak Lukosedba4c5f2016-03-25 12:54:25 -0700723// The verification callback is used for clients that don't really care about
724// the server's certificate, but we need to pull it anyway, in case a higher
725// layer wants to look at it. In this case the verification may fail, but
726// we don't really care.
727static int NullVerifyCallback(int preverify_ok, X509_STORE_CTX *ctx) {
728 return 1;
729}
730
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800731/* --- tsi_frame_protector methods implementation. ---*/
732
Craig Tillera82950e2015-09-22 12:33:20 -0700733static tsi_result ssl_protector_protect(tsi_frame_protector *self,
734 const unsigned char *unprotected_bytes,
735 size_t *unprotected_bytes_size,
736 unsigned char *protected_output_frames,
737 size_t *protected_output_frames_size) {
738 tsi_ssl_frame_protector *impl = (tsi_ssl_frame_protector *)self;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800739 int read_from_ssl;
Julien Boeufb222b4d2015-01-15 17:01:39 -0800740 size_t available;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800741 tsi_result result = TSI_OK;
742
743 /* First see if we have some pending data in the SSL BIO. */
Julien Boeuf01ac4f02015-10-09 16:08:24 -0700744 int pending_in_ssl = (int)BIO_pending(impl->from_ssl);
Craig Tillera82950e2015-09-22 12:33:20 -0700745 if (pending_in_ssl > 0) {
746 *unprotected_bytes_size = 0;
747 GPR_ASSERT(*protected_output_frames_size <= INT_MAX);
748 read_from_ssl = BIO_read(impl->from_ssl, protected_output_frames,
749 (int)*protected_output_frames_size);
750 if (read_from_ssl < 0) {
751 gpr_log(GPR_ERROR,
752 "Could not read from BIO even though some data is pending");
753 return TSI_INTERNAL_ERROR;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800754 }
Craig Tillera82950e2015-09-22 12:33:20 -0700755 *protected_output_frames_size = (size_t)read_from_ssl;
756 return TSI_OK;
757 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800758
759 /* Now see if we can send a complete frame. */
760 available = impl->buffer_size - impl->buffer_offset;
Craig Tillera82950e2015-09-22 12:33:20 -0700761 if (available > *unprotected_bytes_size) {
762 /* If we cannot, just copy the data in our internal buffer. */
763 memcpy(impl->buffer + impl->buffer_offset, unprotected_bytes,
764 *unprotected_bytes_size);
765 impl->buffer_offset += *unprotected_bytes_size;
766 *protected_output_frames_size = 0;
767 return TSI_OK;
768 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800769
770 /* If we can, prepare the buffer, send it to SSL_write and read. */
Craig Tillera82950e2015-09-22 12:33:20 -0700771 memcpy(impl->buffer + impl->buffer_offset, unprotected_bytes, available);
772 result = do_ssl_write(impl->ssl, impl->buffer, impl->buffer_size);
773 if (result != TSI_OK) return result;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800774
Craig Tillera82950e2015-09-22 12:33:20 -0700775 GPR_ASSERT(*protected_output_frames_size <= INT_MAX);
776 read_from_ssl = BIO_read(impl->from_ssl, protected_output_frames,
777 (int)*protected_output_frames_size);
778 if (read_from_ssl < 0) {
779 gpr_log(GPR_ERROR, "Could not read from BIO after SSL_write.");
780 return TSI_INTERNAL_ERROR;
781 }
782 *protected_output_frames_size = (size_t)read_from_ssl;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800783 *unprotected_bytes_size = available;
784 impl->buffer_offset = 0;
785 return TSI_OK;
786}
787
Craig Tillera82950e2015-09-22 12:33:20 -0700788static tsi_result ssl_protector_protect_flush(
789 tsi_frame_protector *self, unsigned char *protected_output_frames,
790 size_t *protected_output_frames_size, size_t *still_pending_size) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800791 tsi_result result = TSI_OK;
Craig Tillera82950e2015-09-22 12:33:20 -0700792 tsi_ssl_frame_protector *impl = (tsi_ssl_frame_protector *)self;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800793 int read_from_ssl = 0;
Craig Tiller3121fd42015-09-10 09:56:20 -0700794 int pending;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800795
Craig Tillera82950e2015-09-22 12:33:20 -0700796 if (impl->buffer_offset != 0) {
797 result = do_ssl_write(impl->ssl, impl->buffer, impl->buffer_offset);
798 if (result != TSI_OK) return result;
799 impl->buffer_offset = 0;
800 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800801
Julien Boeuf01ac4f02015-10-09 16:08:24 -0700802 pending = (int)BIO_pending(impl->from_ssl);
Craig Tillera82950e2015-09-22 12:33:20 -0700803 GPR_ASSERT(pending >= 0);
804 *still_pending_size = (size_t)pending;
805 if (*still_pending_size == 0) return TSI_OK;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800806
Craig Tillera82950e2015-09-22 12:33:20 -0700807 GPR_ASSERT(*protected_output_frames_size <= INT_MAX);
808 read_from_ssl = BIO_read(impl->from_ssl, protected_output_frames,
809 (int)*protected_output_frames_size);
810 if (read_from_ssl <= 0) {
811 gpr_log(GPR_ERROR, "Could not read from BIO after SSL_write.");
812 return TSI_INTERNAL_ERROR;
813 }
814 *protected_output_frames_size = (size_t)read_from_ssl;
Julien Boeuf01ac4f02015-10-09 16:08:24 -0700815 pending = (int)BIO_pending(impl->from_ssl);
Craig Tillera82950e2015-09-22 12:33:20 -0700816 GPR_ASSERT(pending >= 0);
817 *still_pending_size = (size_t)pending;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800818 return TSI_OK;
819}
820
Craig Tillera82950e2015-09-22 12:33:20 -0700821static tsi_result ssl_protector_unprotect(
822 tsi_frame_protector *self, const unsigned char *protected_frames_bytes,
823 size_t *protected_frames_bytes_size, unsigned char *unprotected_bytes,
824 size_t *unprotected_bytes_size) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800825 tsi_result result = TSI_OK;
826 int written_into_ssl = 0;
Julien Boeufb222b4d2015-01-15 17:01:39 -0800827 size_t output_bytes_size = *unprotected_bytes_size;
828 size_t output_bytes_offset = 0;
Craig Tillera82950e2015-09-22 12:33:20 -0700829 tsi_ssl_frame_protector *impl = (tsi_ssl_frame_protector *)self;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800830
831 /* First, try to read remaining data from ssl. */
Craig Tillera82950e2015-09-22 12:33:20 -0700832 result = do_ssl_read(impl->ssl, unprotected_bytes, unprotected_bytes_size);
833 if (result != TSI_OK) return result;
834 if (*unprotected_bytes_size == output_bytes_size) {
835 /* We have read everything we could and cannot process any more input. */
836 *protected_frames_bytes_size = 0;
837 return TSI_OK;
838 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800839 output_bytes_offset = *unprotected_bytes_size;
840 unprotected_bytes += output_bytes_offset;
841 *unprotected_bytes_size = output_bytes_size - output_bytes_offset;
842
843 /* Then, try to write some data to ssl. */
Craig Tillera82950e2015-09-22 12:33:20 -0700844 GPR_ASSERT(*protected_frames_bytes_size <= INT_MAX);
845 written_into_ssl = BIO_write(impl->into_ssl, protected_frames_bytes,
846 (int)*protected_frames_bytes_size);
847 if (written_into_ssl < 0) {
848 gpr_log(GPR_ERROR, "Sending protected frame to ssl failed with %d",
849 written_into_ssl);
850 return TSI_INTERNAL_ERROR;
851 }
852 *protected_frames_bytes_size = (size_t)written_into_ssl;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800853
854 /* Now try to read some data again. */
Craig Tillera82950e2015-09-22 12:33:20 -0700855 result = do_ssl_read(impl->ssl, unprotected_bytes, unprotected_bytes_size);
856 if (result == TSI_OK) {
857 /* Don't forget to output the total number of bytes read. */
858 *unprotected_bytes_size += output_bytes_offset;
859 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800860 return result;
861}
862
Craig Tillera82950e2015-09-22 12:33:20 -0700863static void ssl_protector_destroy(tsi_frame_protector *self) {
864 tsi_ssl_frame_protector *impl = (tsi_ssl_frame_protector *)self;
Nicolas "Pixel" Noble7c9a1542016-03-26 01:33:34 +0100865 if (impl->buffer != NULL) gpr_free(impl->buffer);
Craig Tillera82950e2015-09-22 12:33:20 -0700866 if (impl->ssl != NULL) SSL_free(impl->ssl);
Nicolas "Pixel" Noble7c9a1542016-03-26 01:33:34 +0100867 gpr_free(self);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800868}
869
870static const tsi_frame_protector_vtable frame_protector_vtable = {
Craig Tillera82950e2015-09-22 12:33:20 -0700871 ssl_protector_protect, ssl_protector_protect_flush, ssl_protector_unprotect,
872 ssl_protector_destroy,
Craig Tillerd6c98df2015-08-18 09:33:44 -0700873};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800874
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800875/* --- tsi_handshaker methods implementation. ---*/
876
Craig Tillera82950e2015-09-22 12:33:20 -0700877static tsi_result ssl_handshaker_get_bytes_to_send_to_peer(tsi_handshaker *self,
878 unsigned char *bytes,
879 size_t *bytes_size) {
880 tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800881 int bytes_read_from_ssl = 0;
Craig Tillera82950e2015-09-22 12:33:20 -0700882 if (bytes == NULL || bytes_size == NULL || *bytes_size == 0 ||
883 *bytes_size > INT_MAX) {
884 return TSI_INVALID_ARGUMENT;
885 }
886 GPR_ASSERT(*bytes_size <= INT_MAX);
887 bytes_read_from_ssl = BIO_read(impl->from_ssl, bytes, (int)*bytes_size);
888 if (bytes_read_from_ssl < 0) {
889 *bytes_size = 0;
890 if (!BIO_should_retry(impl->from_ssl)) {
891 impl->result = TSI_INTERNAL_ERROR;
892 return impl->result;
893 } else {
894 return TSI_OK;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800895 }
Craig Tillera82950e2015-09-22 12:33:20 -0700896 }
897 *bytes_size = (size_t)bytes_read_from_ssl;
898 return BIO_pending(impl->from_ssl) == 0 ? TSI_OK : TSI_INCOMPLETE_DATA;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800899}
900
Craig Tillera82950e2015-09-22 12:33:20 -0700901static tsi_result ssl_handshaker_get_result(tsi_handshaker *self) {
902 tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self;
903 if ((impl->result == TSI_HANDSHAKE_IN_PROGRESS) &&
904 SSL_is_init_finished(impl->ssl)) {
905 impl->result = TSI_OK;
906 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800907 return impl->result;
908}
909
Craig Tillera82950e2015-09-22 12:33:20 -0700910static tsi_result ssl_handshaker_process_bytes_from_peer(
911 tsi_handshaker *self, const unsigned char *bytes, size_t *bytes_size) {
912 tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800913 int bytes_written_into_ssl_size = 0;
Craig Tillera82950e2015-09-22 12:33:20 -0700914 if (bytes == NULL || bytes_size == 0 || *bytes_size > INT_MAX) {
915 return TSI_INVALID_ARGUMENT;
916 }
917 GPR_ASSERT(*bytes_size <= INT_MAX);
918 bytes_written_into_ssl_size =
919 BIO_write(impl->into_ssl, bytes, (int)*bytes_size);
920 if (bytes_written_into_ssl_size < 0) {
921 gpr_log(GPR_ERROR, "Could not write to memory BIO.");
922 impl->result = TSI_INTERNAL_ERROR;
923 return impl->result;
924 }
925 *bytes_size = (size_t)bytes_written_into_ssl_size;
Craig Tiller45724b32015-09-22 10:42:19 -0700926
Craig Tillera82950e2015-09-22 12:33:20 -0700927 if (!tsi_handshaker_is_in_progress(self)) {
928 impl->result = TSI_OK;
929 return impl->result;
930 } else {
931 /* Get ready to get some bytes from SSL. */
932 int ssl_result = SSL_do_handshake(impl->ssl);
933 ssl_result = SSL_get_error(impl->ssl, ssl_result);
934 switch (ssl_result) {
935 case SSL_ERROR_WANT_READ:
936 if (BIO_pending(impl->from_ssl) == 0) {
937 /* We need more data. */
938 return TSI_INCOMPLETE_DATA;
939 } else {
940 return TSI_OK;
941 }
942 case SSL_ERROR_NONE:
943 return TSI_OK;
944 default: {
945 char err_str[256];
946 ERR_error_string_n(ERR_get_error(), err_str, sizeof(err_str));
947 gpr_log(GPR_ERROR, "Handshake failed with fatal error %s: %s.",
948 ssl_error_string(ssl_result), err_str);
949 impl->result = TSI_PROTOCOL_FAILURE;
950 return impl->result;
951 }
Craig Tiller45724b32015-09-22 10:42:19 -0700952 }
Craig Tillera82950e2015-09-22 12:33:20 -0700953 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800954}
955
Craig Tillera82950e2015-09-22 12:33:20 -0700956static tsi_result ssl_handshaker_extract_peer(tsi_handshaker *self,
957 tsi_peer *peer) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800958 tsi_result result = TSI_OK;
Craig Tiller45724b32015-09-22 10:42:19 -0700959 const unsigned char *alpn_selected = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800960 unsigned int alpn_selected_len;
Craig Tillera82950e2015-09-22 12:33:20 -0700961 tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self;
962 X509 *peer_cert = SSL_get_peer_certificate(impl->ssl);
963 if (peer_cert != NULL) {
964 result = peer_from_x509(peer_cert, 1, peer);
965 X509_free(peer_cert);
966 if (result != TSI_OK) return result;
967 }
Julien Boeufd1531322015-06-18 11:05:39 +0200968#if TSI_OPENSSL_ALPN_SUPPORT
Craig Tillera82950e2015-09-22 12:33:20 -0700969 SSL_get0_alpn_selected(impl->ssl, &alpn_selected, &alpn_selected_len);
Julien Boeufd1531322015-06-18 11:05:39 +0200970#endif /* TSI_OPENSSL_ALPN_SUPPORT */
Craig Tillera82950e2015-09-22 12:33:20 -0700971 if (alpn_selected == NULL) {
972 /* Try npn. */
973 SSL_get0_next_proto_negotiated(impl->ssl, &alpn_selected,
974 &alpn_selected_len);
975 }
976 if (alpn_selected != NULL) {
977 size_t i;
978 tsi_peer_property *new_properties =
Nicolas "Pixel" Noble7c9a1542016-03-26 01:33:34 +0100979 gpr_malloc(sizeof(*new_properties) * (peer->property_count + 1));
Nicolas "Pixel" Noble5d203f52016-03-26 01:35:33 +0100980 memset(new_properties, 0,
981 sizeof(*new_properties) * (peer->property_count + 1));
Craig Tillera82950e2015-09-22 12:33:20 -0700982 for (i = 0; i < peer->property_count; i++) {
983 new_properties[i] = peer->properties[i];
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800984 }
Craig Tillera82950e2015-09-22 12:33:20 -0700985 result = tsi_construct_string_peer_property(
986 TSI_SSL_ALPN_SELECTED_PROTOCOL, (const char *)alpn_selected,
987 alpn_selected_len, &new_properties[peer->property_count]);
988 if (result != TSI_OK) {
Nicolas "Pixel" Noble7c9a1542016-03-26 01:33:34 +0100989 gpr_free(new_properties);
Craig Tillera82950e2015-09-22 12:33:20 -0700990 return result;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800991 }
Nicolas "Pixel" Noble7c9a1542016-03-26 01:33:34 +0100992 if (peer->properties != NULL) gpr_free(peer->properties);
Craig Tillera82950e2015-09-22 12:33:20 -0700993 peer->property_count++;
994 peer->properties = new_properties;
995 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800996 return result;
997}
998
Craig Tillera82950e2015-09-22 12:33:20 -0700999static tsi_result ssl_handshaker_create_frame_protector(
1000 tsi_handshaker *self, size_t *max_output_protected_frame_size,
1001 tsi_frame_protector **protector) {
1002 size_t actual_max_output_protected_frame_size =
1003 TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND;
1004 tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self;
Nicolas "Pixel" Noble5d203f52016-03-26 01:35:33 +01001005 tsi_ssl_frame_protector *protector_impl = gpr_malloc(sizeof(*protector_impl));
Nicolas "Pixel" Noble7c9a1542016-03-26 01:33:34 +01001006 memset(protector_impl, 0, sizeof(*protector_impl));
Craig Tiller45724b32015-09-22 10:42:19 -07001007
Craig Tillera82950e2015-09-22 12:33:20 -07001008 if (max_output_protected_frame_size != NULL) {
1009 if (*max_output_protected_frame_size >
1010 TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND) {
1011 *max_output_protected_frame_size =
1012 TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND;
1013 } else if (*max_output_protected_frame_size <
1014 TSI_SSL_MAX_PROTECTED_FRAME_SIZE_LOWER_BOUND) {
1015 *max_output_protected_frame_size =
1016 TSI_SSL_MAX_PROTECTED_FRAME_SIZE_LOWER_BOUND;
Craig Tiller45724b32015-09-22 10:42:19 -07001017 }
Craig Tillera82950e2015-09-22 12:33:20 -07001018 actual_max_output_protected_frame_size = *max_output_protected_frame_size;
1019 }
1020 protector_impl->buffer_size =
1021 actual_max_output_protected_frame_size - TSI_SSL_MAX_PROTECTION_OVERHEAD;
Nicolas "Pixel" Noble7c9a1542016-03-26 01:33:34 +01001022 protector_impl->buffer = gpr_malloc(protector_impl->buffer_size);
Craig Tillera82950e2015-09-22 12:33:20 -07001023 if (protector_impl->buffer == NULL) {
1024 gpr_log(GPR_ERROR,
1025 "Could not allocated buffer for tsi_ssl_frame_protector.");
Nicolas "Pixel" Noble7c9a1542016-03-26 01:33:34 +01001026 gpr_free(protector_impl);
Craig Tillera82950e2015-09-22 12:33:20 -07001027 return TSI_INTERNAL_ERROR;
1028 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001029
1030 /* Transfer ownership of ssl to the frame protector. It is OK as the caller
1031 * cannot call anything else but destroy on the handshaker after this call. */
1032 protector_impl->ssl = impl->ssl;
1033 impl->ssl = NULL;
1034 protector_impl->into_ssl = impl->into_ssl;
1035 protector_impl->from_ssl = impl->from_ssl;
1036
1037 protector_impl->base.vtable = &frame_protector_vtable;
1038 *protector = &protector_impl->base;
1039 return TSI_OK;
1040}
1041
Craig Tillera82950e2015-09-22 12:33:20 -07001042static void ssl_handshaker_destroy(tsi_handshaker *self) {
1043 tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *)self;
1044 SSL_free(impl->ssl); /* The BIO objects are owned by ssl */
Nicolas "Pixel" Noble7c9a1542016-03-26 01:33:34 +01001045 gpr_free(impl);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001046}
1047
1048static const tsi_handshaker_vtable handshaker_vtable = {
Craig Tillera82950e2015-09-22 12:33:20 -07001049 ssl_handshaker_get_bytes_to_send_to_peer,
Craig Tillerf40df232016-03-25 13:38:14 -07001050 ssl_handshaker_process_bytes_from_peer,
1051 ssl_handshaker_get_result,
1052 ssl_handshaker_extract_peer,
1053 ssl_handshaker_create_frame_protector,
Craig Tillera82950e2015-09-22 12:33:20 -07001054 ssl_handshaker_destroy,
Craig Tillerd6c98df2015-08-18 09:33:44 -07001055};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001056
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001057/* --- tsi_ssl_handshaker_factory common methods. --- */
1058
Craig Tillera82950e2015-09-22 12:33:20 -07001059tsi_result tsi_ssl_handshaker_factory_create_handshaker(
1060 tsi_ssl_handshaker_factory *self, const char *server_name_indication,
1061 tsi_handshaker **handshaker) {
1062 if (self == NULL || handshaker == NULL) return TSI_INVALID_ARGUMENT;
1063 return self->create_handshaker(self, server_name_indication, handshaker);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001064}
1065
Craig Tillera82950e2015-09-22 12:33:20 -07001066void tsi_ssl_handshaker_factory_destroy(tsi_ssl_handshaker_factory *self) {
1067 if (self == NULL) return;
1068 self->destroy(self);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001069}
1070
Craig Tillera82950e2015-09-22 12:33:20 -07001071static tsi_result create_tsi_ssl_handshaker(SSL_CTX *ctx, int is_client,
1072 const char *server_name_indication,
1073 tsi_handshaker **handshaker) {
1074 SSL *ssl = SSL_new(ctx);
Craig Tiller45724b32015-09-22 10:42:19 -07001075 BIO *into_ssl = NULL;
1076 BIO *from_ssl = NULL;
1077 tsi_ssl_handshaker *impl = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001078 *handshaker = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -07001079 if (ctx == NULL) {
1080 gpr_log(GPR_ERROR, "SSL Context is null. Should never happen.");
1081 return TSI_INTERNAL_ERROR;
1082 }
1083 if (ssl == NULL) {
1084 return TSI_OUT_OF_RESOURCES;
1085 }
1086 SSL_set_info_callback(ssl, ssl_info_callback);
1087
1088 into_ssl = BIO_new(BIO_s_mem());
1089 from_ssl = BIO_new(BIO_s_mem());
1090 if (into_ssl == NULL || from_ssl == NULL) {
1091 gpr_log(GPR_ERROR, "BIO_new failed.");
1092 SSL_free(ssl);
1093 if (into_ssl != NULL) BIO_free(into_ssl);
1094 if (from_ssl != NULL) BIO_free(into_ssl);
1095 return TSI_OUT_OF_RESOURCES;
1096 }
1097 SSL_set_bio(ssl, into_ssl, from_ssl);
1098 if (is_client) {
1099 int ssl_result;
1100 SSL_set_connect_state(ssl);
1101 if (server_name_indication != NULL) {
1102 if (!SSL_set_tlsext_host_name(ssl, server_name_indication)) {
1103 gpr_log(GPR_ERROR, "Invalid server name indication %s.",
1104 server_name_indication);
1105 SSL_free(ssl);
1106 return TSI_INTERNAL_ERROR;
1107 }
1108 }
1109 ssl_result = SSL_do_handshake(ssl);
1110 ssl_result = SSL_get_error(ssl, ssl_result);
1111 if (ssl_result != SSL_ERROR_WANT_READ) {
1112 gpr_log(GPR_ERROR,
1113 "Unexpected error received from first SSL_do_handshake call: %s",
1114 ssl_error_string(ssl_result));
1115 SSL_free(ssl);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001116 return TSI_INTERNAL_ERROR;
1117 }
Craig Tillera82950e2015-09-22 12:33:20 -07001118 } else {
1119 SSL_set_accept_state(ssl);
1120 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001121
Nicolas "Pixel" Noble7c9a1542016-03-26 01:33:34 +01001122 impl = gpr_malloc(sizeof(*impl));
1123 memset(impl, 0, sizeof(*impl));
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001124 impl->ssl = ssl;
1125 impl->into_ssl = into_ssl;
1126 impl->from_ssl = from_ssl;
1127 impl->result = TSI_HANDSHAKE_IN_PROGRESS;
1128 impl->base.vtable = &handshaker_vtable;
1129 *handshaker = &impl->base;
1130 return TSI_OK;
1131}
1132
Craig Tillera82950e2015-09-22 12:33:20 -07001133static int select_protocol_list(const unsigned char **out,
1134 unsigned char *outlen,
1135 const unsigned char *client_list,
1136 size_t client_list_len,
1137 const unsigned char *server_list,
1138 size_t server_list_len) {
Craig Tiller45724b32015-09-22 10:42:19 -07001139 const unsigned char *client_current = client_list;
Craig Tillera82950e2015-09-22 12:33:20 -07001140 while ((unsigned int)(client_current - client_list) < client_list_len) {
1141 unsigned char client_current_len = *(client_current++);
1142 const unsigned char *server_current = server_list;
1143 while ((server_current >= server_list) &&
Craig Tiller7536af02015-12-22 13:49:30 -08001144 (uintptr_t)(server_current - server_list) < server_list_len) {
Craig Tillera82950e2015-09-22 12:33:20 -07001145 unsigned char server_current_len = *(server_current++);
1146 if ((client_current_len == server_current_len) &&
1147 !memcmp(client_current, server_current, server_current_len)) {
1148 *out = server_current;
1149 *outlen = server_current_len;
1150 return SSL_TLSEXT_ERR_OK;
1151 }
1152 server_current += server_current_len;
Julien Boeufd1531322015-06-18 11:05:39 +02001153 }
Craig Tillera82950e2015-09-22 12:33:20 -07001154 client_current += client_current_len;
1155 }
Julien Boeufd1531322015-06-18 11:05:39 +02001156 return SSL_TLSEXT_ERR_NOACK;
1157}
1158
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001159/* --- tsi_ssl__client_handshaker_factory methods implementation. --- */
1160
Craig Tillera82950e2015-09-22 12:33:20 -07001161static tsi_result ssl_client_handshaker_factory_create_handshaker(
1162 tsi_ssl_handshaker_factory *self, const char *server_name_indication,
1163 tsi_handshaker **handshaker) {
1164 tsi_ssl_client_handshaker_factory *impl =
1165 (tsi_ssl_client_handshaker_factory *)self;
1166 return create_tsi_ssl_handshaker(impl->ssl_context, 1, server_name_indication,
1167 handshaker);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001168}
1169
Craig Tillera82950e2015-09-22 12:33:20 -07001170static void ssl_client_handshaker_factory_destroy(
1171 tsi_ssl_handshaker_factory *self) {
1172 tsi_ssl_client_handshaker_factory *impl =
1173 (tsi_ssl_client_handshaker_factory *)self;
1174 if (impl->ssl_context != NULL) SSL_CTX_free(impl->ssl_context);
Nicolas "Pixel" Noble7c9a1542016-03-26 01:33:34 +01001175 if (impl->alpn_protocol_list != NULL) gpr_free(impl->alpn_protocol_list);
1176 gpr_free(impl);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001177}
1178
Craig Tillera82950e2015-09-22 12:33:20 -07001179static int client_handshaker_factory_npn_callback(SSL *ssl, unsigned char **out,
1180 unsigned char *outlen,
1181 const unsigned char *in,
1182 unsigned int inlen,
1183 void *arg) {
1184 tsi_ssl_client_handshaker_factory *factory =
1185 (tsi_ssl_client_handshaker_factory *)arg;
1186 return select_protocol_list((const unsigned char **)out, outlen,
1187 factory->alpn_protocol_list,
1188 factory->alpn_protocol_list_length, in, inlen);
Julien Boeufd1531322015-06-18 11:05:39 +02001189}
1190
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001191/* --- tsi_ssl_server_handshaker_factory methods implementation. --- */
1192
Craig Tillera82950e2015-09-22 12:33:20 -07001193static tsi_result ssl_server_handshaker_factory_create_handshaker(
1194 tsi_ssl_handshaker_factory *self, const char *server_name_indication,
1195 tsi_handshaker **handshaker) {
1196 tsi_ssl_server_handshaker_factory *impl =
1197 (tsi_ssl_server_handshaker_factory *)self;
1198 if (impl->ssl_context_count == 0 || server_name_indication != NULL) {
1199 return TSI_INVALID_ARGUMENT;
1200 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001201 /* Create the handshaker with the first context. We will switch if needed
1202 because of SNI in ssl_server_handshaker_factory_servername_callback. */
Craig Tillera82950e2015-09-22 12:33:20 -07001203 return create_tsi_ssl_handshaker(impl->ssl_contexts[0], 0, NULL, handshaker);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001204}
1205
Craig Tillera82950e2015-09-22 12:33:20 -07001206static void ssl_server_handshaker_factory_destroy(
1207 tsi_ssl_handshaker_factory *self) {
1208 tsi_ssl_server_handshaker_factory *impl =
1209 (tsi_ssl_server_handshaker_factory *)self;
Julien Boeufb222b4d2015-01-15 17:01:39 -08001210 size_t i;
Craig Tillera82950e2015-09-22 12:33:20 -07001211 for (i = 0; i < impl->ssl_context_count; i++) {
1212 if (impl->ssl_contexts[i] != NULL) {
1213 SSL_CTX_free(impl->ssl_contexts[i]);
1214 tsi_peer_destruct(&impl->ssl_context_x509_subject_names[i]);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001215 }
Craig Tillera82950e2015-09-22 12:33:20 -07001216 }
Nicolas "Pixel" Noble7c9a1542016-03-26 01:33:34 +01001217 if (impl->ssl_contexts != NULL) gpr_free(impl->ssl_contexts);
Craig Tillera82950e2015-09-22 12:33:20 -07001218 if (impl->ssl_context_x509_subject_names != NULL) {
Nicolas "Pixel" Noble7c9a1542016-03-26 01:33:34 +01001219 gpr_free(impl->ssl_context_x509_subject_names);
Craig Tillera82950e2015-09-22 12:33:20 -07001220 }
Nicolas "Pixel" Noble7c9a1542016-03-26 01:33:34 +01001221 if (impl->alpn_protocol_list != NULL) gpr_free(impl->alpn_protocol_list);
1222 gpr_free(impl);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001223}
1224
Craig Tillera82950e2015-09-22 12:33:20 -07001225static int does_entry_match_name(const char *entry, size_t entry_length,
1226 const char *name) {
Craig Tiller45724b32015-09-22 10:42:19 -07001227 const char *dot;
1228 const char *name_subdomain = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -07001229 size_t name_length = strlen(name);
Julien Boeuf9fff77e2015-02-24 16:50:35 -08001230 size_t name_subdomain_length;
Craig Tillera82950e2015-09-22 12:33:20 -07001231 if (entry_length == 0) return 0;
Julien Boeuf9fff77e2015-02-24 16:50:35 -08001232
1233 /* Take care of '.' terminations. */
Craig Tillera82950e2015-09-22 12:33:20 -07001234 if (name[name_length - 1] == '.') {
1235 name_length--;
1236 }
1237 if (entry[entry_length - 1] == '.') {
1238 entry_length--;
1239 if (entry_length == 0) return 0;
1240 }
Julien Boeuf9fff77e2015-02-24 16:50:35 -08001241
Craig Tillera82950e2015-09-22 12:33:20 -07001242 if ((name_length == entry_length) &&
1243 strncmp(name, entry, entry_length) == 0) {
1244 return 1; /* Perfect match. */
1245 }
1246 if (entry[0] != '*') return 0;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001247
1248 /* Wildchar subdomain matching. */
Craig Tillera82950e2015-09-22 12:33:20 -07001249 if (entry_length < 3 || entry[1] != '.') { /* At least *.x */
1250 gpr_log(GPR_ERROR, "Invalid wildchar entry.");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001251 return 0;
Craig Tillera82950e2015-09-22 12:33:20 -07001252 }
1253 name_subdomain = strchr(name, '.');
1254 if (name_subdomain == NULL) return 0;
1255 name_subdomain_length = strlen(name_subdomain);
1256 if (name_subdomain_length < 2) return 0;
1257 name_subdomain++; /* Starts after the dot. */
Julien Boeuf0170a6c2015-02-24 18:08:01 -08001258 name_subdomain_length--;
Craig Tillera82950e2015-09-22 12:33:20 -07001259 entry += 2; /* Remove *. */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001260 entry_length -= 2;
Craig Tillera82950e2015-09-22 12:33:20 -07001261 dot = strchr(name_subdomain, '.');
1262 if ((dot == NULL) || (dot == &name_subdomain[name_subdomain_length - 1])) {
1263 gpr_log(GPR_ERROR, "Invalid toplevel subdomain: %s", name_subdomain);
1264 return 0;
1265 }
1266 if (name_subdomain[name_subdomain_length - 1] == '.') {
1267 name_subdomain_length--;
1268 }
1269 return ((entry_length > 0) && (name_subdomain_length == entry_length) &&
1270 strncmp(entry, name_subdomain, entry_length) == 0);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001271}
1272
Craig Tillera82950e2015-09-22 12:33:20 -07001273static int ssl_server_handshaker_factory_servername_callback(SSL *ssl, int *ap,
1274 void *arg) {
1275 tsi_ssl_server_handshaker_factory *impl =
1276 (tsi_ssl_server_handshaker_factory *)arg;
Julien Boeufb222b4d2015-01-15 17:01:39 -08001277 size_t i = 0;
Craig Tillera82950e2015-09-22 12:33:20 -07001278 const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
1279 if (servername == NULL || strlen(servername) == 0) {
1280 return SSL_TLSEXT_ERR_NOACK;
1281 }
Craig Tiller45724b32015-09-22 10:42:19 -07001282
Craig Tillera82950e2015-09-22 12:33:20 -07001283 for (i = 0; i < impl->ssl_context_count; i++) {
1284 if (tsi_ssl_peer_matches_name(&impl->ssl_context_x509_subject_names[i],
1285 servername)) {
1286 SSL_set_SSL_CTX(ssl, impl->ssl_contexts[i]);
1287 return SSL_TLSEXT_ERR_OK;
Craig Tiller45724b32015-09-22 10:42:19 -07001288 }
Craig Tillera82950e2015-09-22 12:33:20 -07001289 }
1290 gpr_log(GPR_ERROR, "No match found for server name: %s.", servername);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001291 return SSL_TLSEXT_ERR_ALERT_WARNING;
1292}
1293
Julien Boeufd1531322015-06-18 11:05:39 +02001294#if TSI_OPENSSL_ALPN_SUPPORT
Craig Tillera82950e2015-09-22 12:33:20 -07001295static int server_handshaker_factory_alpn_callback(
1296 SSL *ssl, const unsigned char **out, unsigned char *outlen,
1297 const unsigned char *in, unsigned int inlen, void *arg) {
1298 tsi_ssl_server_handshaker_factory *factory =
1299 (tsi_ssl_server_handshaker_factory *)arg;
1300 return select_protocol_list(out, outlen, in, inlen,
1301 factory->alpn_protocol_list,
1302 factory->alpn_protocol_list_length);
Julien Boeufd1531322015-06-18 11:05:39 +02001303}
1304#endif /* TSI_OPENSSL_ALPN_SUPPORT */
1305
Craig Tillera82950e2015-09-22 12:33:20 -07001306static int server_handshaker_factory_npn_advertised_callback(
1307 SSL *ssl, const unsigned char **out, unsigned int *outlen, void *arg) {
1308 tsi_ssl_server_handshaker_factory *factory =
1309 (tsi_ssl_server_handshaker_factory *)arg;
Julien Boeufd1531322015-06-18 11:05:39 +02001310 *out = factory->alpn_protocol_list;
Craig Tillera82950e2015-09-22 12:33:20 -07001311 GPR_ASSERT(factory->alpn_protocol_list_length <= UINT_MAX);
1312 *outlen = (unsigned int)factory->alpn_protocol_list_length;
Julien Boeufd1531322015-06-18 11:05:39 +02001313 return SSL_TLSEXT_ERR_OK;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001314}
1315
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001316/* --- tsi_ssl_handshaker_factory constructors. --- */
1317
Craig Tillera82950e2015-09-22 12:33:20 -07001318tsi_result tsi_create_ssl_client_handshaker_factory(
1319 const unsigned char *pem_private_key, size_t pem_private_key_size,
1320 const unsigned char *pem_cert_chain, size_t pem_cert_chain_size,
1321 const unsigned char *pem_root_certs, size_t pem_root_certs_size,
1322 const char *cipher_list, const unsigned char **alpn_protocols,
1323 const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols,
1324 tsi_ssl_handshaker_factory **factory) {
Craig Tiller45724b32015-09-22 10:42:19 -07001325 SSL_CTX *ssl_context = NULL;
1326 tsi_ssl_client_handshaker_factory *impl = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001327 tsi_result result = TSI_OK;
1328
Craig Tillera82950e2015-09-22 12:33:20 -07001329 gpr_once_init(&init_openssl_once, init_openssl);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001330
Craig Tillera82950e2015-09-22 12:33:20 -07001331 if (factory == NULL) return TSI_INVALID_ARGUMENT;
Craig Tiller45724b32015-09-22 10:42:19 -07001332 *factory = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -07001333 if (pem_root_certs == NULL) return TSI_INVALID_ARGUMENT;
1334
1335 ssl_context = SSL_CTX_new(TLSv1_2_method());
1336 if (ssl_context == NULL) {
1337 gpr_log(GPR_ERROR, "Could not create ssl context.");
Craig Tiller45724b32015-09-22 10:42:19 -07001338 return TSI_INVALID_ARGUMENT;
Craig Tillera82950e2015-09-22 12:33:20 -07001339 }
Julien Boeufd1531322015-06-18 11:05:39 +02001340
Nicolas "Pixel" Noble7c9a1542016-03-26 01:33:34 +01001341 impl = gpr_malloc(sizeof(*impl));
1342 memset(impl, 0, sizeof(*impl));
Julien Boeufd1531322015-06-18 11:05:39 +02001343 impl->ssl_context = ssl_context;
1344
Craig Tillera82950e2015-09-22 12:33:20 -07001345 do {
1346 result =
1347 populate_ssl_context(ssl_context, pem_private_key, pem_private_key_size,
1348 pem_cert_chain, pem_cert_chain_size, cipher_list);
1349 if (result != TSI_OK) break;
1350 result = ssl_ctx_load_verification_certs(ssl_context, pem_root_certs,
1351 pem_root_certs_size, NULL);
1352 if (result != TSI_OK) {
1353 gpr_log(GPR_ERROR, "Cannot load server root certificates.");
1354 break;
1355 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001356
Craig Tillera82950e2015-09-22 12:33:20 -07001357 if (num_alpn_protocols != 0) {
1358 result = build_alpn_protocol_name_list(
1359 alpn_protocols, alpn_protocols_lengths, num_alpn_protocols,
1360 &impl->alpn_protocol_list, &impl->alpn_protocol_list_length);
1361 if (result != TSI_OK) {
1362 gpr_log(GPR_ERROR, "Building alpn list failed with error %s.",
1363 tsi_result_to_string(result));
1364 break;
1365 }
Julien Boeufd1531322015-06-18 11:05:39 +02001366#if TSI_OPENSSL_ALPN_SUPPORT
Craig Tillera82950e2015-09-22 12:33:20 -07001367 GPR_ASSERT(impl->alpn_protocol_list_length < UINT_MAX);
1368 if (SSL_CTX_set_alpn_protos(
1369 ssl_context, impl->alpn_protocol_list,
1370 (unsigned int)impl->alpn_protocol_list_length)) {
1371 gpr_log(GPR_ERROR, "Could not set alpn protocol list to context.");
1372 result = TSI_INVALID_ARGUMENT;
1373 break;
1374 }
Julien Boeufd1531322015-06-18 11:05:39 +02001375#endif /* TSI_OPENSSL_ALPN_SUPPORT */
Craig Tillera82950e2015-09-22 12:33:20 -07001376 SSL_CTX_set_next_proto_select_cb(
1377 ssl_context, client_handshaker_factory_npn_callback, impl);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001378 }
Craig Tillera82950e2015-09-22 12:33:20 -07001379 } while (0);
1380 if (result != TSI_OK) {
1381 ssl_client_handshaker_factory_destroy(&impl->base);
1382 return result;
1383 }
1384 SSL_CTX_set_verify(ssl_context, SSL_VERIFY_PEER, NULL);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001385 /* TODO(jboeuf): Add revocation verification. */
1386
Craig Tillera82950e2015-09-22 12:33:20 -07001387 impl->base.create_handshaker =
1388 ssl_client_handshaker_factory_create_handshaker;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001389 impl->base.destroy = ssl_client_handshaker_factory_destroy;
1390 *factory = &impl->base;
1391 return TSI_OK;
1392}
1393
Craig Tillera82950e2015-09-22 12:33:20 -07001394tsi_result tsi_create_ssl_server_handshaker_factory(
1395 const unsigned char **pem_private_keys,
1396 const size_t *pem_private_keys_sizes, const unsigned char **pem_cert_chains,
1397 const size_t *pem_cert_chains_sizes, size_t key_cert_pair_count,
1398 const unsigned char *pem_client_root_certs,
1399 size_t pem_client_root_certs_size, int force_client_auth,
1400 const char *cipher_list, const unsigned char **alpn_protocols,
1401 const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols,
1402 tsi_ssl_handshaker_factory **factory) {
Deepak Lukosedba4c5f2016-03-25 12:54:25 -07001403 return tsi_create_ssl_server_handshaker_factory_ex(
1404 pem_private_keys, pem_private_keys_sizes, pem_cert_chains,
1405 pem_cert_chains_sizes, key_cert_pair_count, pem_client_root_certs,
1406 pem_client_root_certs_size,
1407 force_client_auth ? TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY
1408 : TSI_DONT_REQUEST_CLIENT_CERTIFICATE,
1409 cipher_list, alpn_protocols, alpn_protocols_lengths, num_alpn_protocols,
1410 factory);
1411}
1412
1413tsi_result tsi_create_ssl_server_handshaker_factory_ex(
1414 const unsigned char **pem_private_keys,
1415 const size_t *pem_private_keys_sizes, const unsigned char **pem_cert_chains,
1416 const size_t *pem_cert_chains_sizes, size_t key_cert_pair_count,
1417 const unsigned char *pem_client_root_certs,
1418 size_t pem_client_root_certs_size,
1419 tsi_client_certificate_request_type client_certificate_request,
1420 const char *cipher_list, const unsigned char **alpn_protocols,
1421 const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols,
1422 tsi_ssl_handshaker_factory **factory) {
Craig Tiller45724b32015-09-22 10:42:19 -07001423 tsi_ssl_server_handshaker_factory *impl = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001424 tsi_result result = TSI_OK;
Julien Boeufb222b4d2015-01-15 17:01:39 -08001425 size_t i = 0;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001426
Craig Tillera82950e2015-09-22 12:33:20 -07001427 gpr_once_init(&init_openssl_once, init_openssl);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001428
Craig Tillera82950e2015-09-22 12:33:20 -07001429 if (factory == NULL) return TSI_INVALID_ARGUMENT;
Craig Tiller45724b32015-09-22 10:42:19 -07001430 *factory = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -07001431 if (key_cert_pair_count == 0 || pem_private_keys == NULL ||
1432 pem_cert_chains == NULL) {
1433 return TSI_INVALID_ARGUMENT;
1434 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001435
Nicolas "Pixel" Noble7c9a1542016-03-26 01:33:34 +01001436 impl = gpr_malloc(sizeof(*impl));
1437 memset(impl, 0, sizeof(*impl));
Craig Tillera82950e2015-09-22 12:33:20 -07001438 impl->base.create_handshaker =
1439 ssl_server_handshaker_factory_create_handshaker;
Craig Tiller45724b32015-09-22 10:42:19 -07001440 impl->base.destroy = ssl_server_handshaker_factory_destroy;
Nicolas "Pixel" Noble7c9a1542016-03-26 01:33:34 +01001441 impl->ssl_contexts = gpr_malloc(key_cert_pair_count * sizeof(SSL_CTX *));
1442 memset(impl->ssl_contexts, 0, key_cert_pair_count * sizeof(SSL_CTX *));
Craig Tillera82950e2015-09-22 12:33:20 -07001443 impl->ssl_context_x509_subject_names =
Nicolas "Pixel" Noble7c9a1542016-03-26 01:33:34 +01001444 gpr_malloc(key_cert_pair_count * sizeof(tsi_peer));
Nicolas "Pixel" Noble5d203f52016-03-26 01:35:33 +01001445 memset(impl->ssl_context_x509_subject_names, 0,
1446 key_cert_pair_count * sizeof(tsi_peer));
Craig Tillera82950e2015-09-22 12:33:20 -07001447 if (impl->ssl_contexts == NULL ||
1448 impl->ssl_context_x509_subject_names == NULL) {
1449 tsi_ssl_handshaker_factory_destroy(&impl->base);
1450 return TSI_OUT_OF_RESOURCES;
1451 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001452 impl->ssl_context_count = key_cert_pair_count;
1453
Craig Tillera82950e2015-09-22 12:33:20 -07001454 if (num_alpn_protocols > 0) {
1455 result = build_alpn_protocol_name_list(
1456 alpn_protocols, alpn_protocols_lengths, num_alpn_protocols,
1457 &impl->alpn_protocol_list, &impl->alpn_protocol_list_length);
1458 if (result != TSI_OK) {
1459 tsi_ssl_handshaker_factory_destroy(&impl->base);
1460 return result;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001461 }
Craig Tillera82950e2015-09-22 12:33:20 -07001462 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001463
Craig Tillera82950e2015-09-22 12:33:20 -07001464 for (i = 0; i < key_cert_pair_count; i++) {
1465 do {
1466 impl->ssl_contexts[i] = SSL_CTX_new(TLSv1_2_method());
1467 if (impl->ssl_contexts[i] == NULL) {
1468 gpr_log(GPR_ERROR, "Could not create ssl context.");
1469 result = TSI_OUT_OF_RESOURCES;
1470 break;
1471 }
1472 result = populate_ssl_context(
1473 impl->ssl_contexts[i], pem_private_keys[i], pem_private_keys_sizes[i],
1474 pem_cert_chains[i], pem_cert_chains_sizes[i], cipher_list);
1475 if (result != TSI_OK) break;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001476
Craig Tillera82950e2015-09-22 12:33:20 -07001477 if (pem_client_root_certs != NULL) {
Craig Tillera82950e2015-09-22 12:33:20 -07001478 STACK_OF(X509_NAME) *root_names = NULL;
1479 result = ssl_ctx_load_verification_certs(
1480 impl->ssl_contexts[i], pem_client_root_certs,
1481 pem_client_root_certs_size, &root_names);
1482 if (result != TSI_OK) {
1483 gpr_log(GPR_ERROR, "Invalid verification certs.");
1484 break;
1485 }
1486 SSL_CTX_set_client_CA_list(impl->ssl_contexts[i], root_names);
Deepak Lukosedba4c5f2016-03-25 12:54:25 -07001487 switch (client_certificate_request) {
1488 case TSI_DONT_REQUEST_CLIENT_CERTIFICATE:
1489 SSL_CTX_set_verify(impl->ssl_contexts[i], SSL_VERIFY_NONE, NULL);
1490 break;
1491 case TSI_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY:
1492 SSL_CTX_set_verify(impl->ssl_contexts[i], SSL_VERIFY_PEER,
1493 NullVerifyCallback);
1494 break;
1495 case TSI_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY:
1496 SSL_CTX_set_verify(impl->ssl_contexts[i], SSL_VERIFY_PEER, NULL);
1497 break;
1498 case TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY:
1499 SSL_CTX_set_verify(
1500 impl->ssl_contexts[i],
1501 SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
1502 NullVerifyCallback);
1503 break;
1504 case TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY:
1505 SSL_CTX_set_verify(
1506 impl->ssl_contexts[i],
1507 SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
1508 break;
1509 }
Craig Tillera82950e2015-09-22 12:33:20 -07001510 /* TODO(jboeuf): Add revocation verification. */
1511 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001512
Craig Tillera82950e2015-09-22 12:33:20 -07001513 result = extract_x509_subject_names_from_pem_cert(
1514 pem_cert_chains[i], pem_cert_chains_sizes[i],
1515 &impl->ssl_context_x509_subject_names[i]);
1516 if (result != TSI_OK) break;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001517
Craig Tillera82950e2015-09-22 12:33:20 -07001518 SSL_CTX_set_tlsext_servername_callback(
1519 impl->ssl_contexts[i],
1520 ssl_server_handshaker_factory_servername_callback);
1521 SSL_CTX_set_tlsext_servername_arg(impl->ssl_contexts[i], impl);
Julien Boeufd1531322015-06-18 11:05:39 +02001522#if TSI_OPENSSL_ALPN_SUPPORT
Craig Tillera82950e2015-09-22 12:33:20 -07001523 SSL_CTX_set_alpn_select_cb(impl->ssl_contexts[i],
1524 server_handshaker_factory_alpn_callback, impl);
Julien Boeufd1531322015-06-18 11:05:39 +02001525#endif /* TSI_OPENSSL_ALPN_SUPPORT */
Craig Tillera82950e2015-09-22 12:33:20 -07001526 SSL_CTX_set_next_protos_advertised_cb(
1527 impl->ssl_contexts[i],
1528 server_handshaker_factory_npn_advertised_callback, impl);
1529 } while (0);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001530
Craig Tillera82950e2015-09-22 12:33:20 -07001531 if (result != TSI_OK) {
1532 tsi_ssl_handshaker_factory_destroy(&impl->base);
1533 return result;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001534 }
Craig Tillera82950e2015-09-22 12:33:20 -07001535 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001536 *factory = &impl->base;
1537 return TSI_OK;
1538}
1539
1540/* --- tsi_ssl utils. --- */
1541
Craig Tillera82950e2015-09-22 12:33:20 -07001542int tsi_ssl_peer_matches_name(const tsi_peer *peer, const char *name) {
Julien Boeufb222b4d2015-01-15 17:01:39 -08001543 size_t i = 0;
Julien Boeuf597a4f22015-02-23 15:57:14 -08001544 size_t san_count = 0;
Craig Tiller45724b32015-09-22 10:42:19 -07001545 const tsi_peer_property *cn_property = NULL;
Paul Querna47d841d2016-03-10 11:19:17 -08001546 int like_ip = looks_like_ip_address(name);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001547
Julien Boeuf597a4f22015-02-23 15:57:14 -08001548 /* Check the SAN first. */
Craig Tillera82950e2015-09-22 12:33:20 -07001549 for (i = 0; i < peer->property_count; i++) {
1550 const tsi_peer_property *property = &peer->properties[i];
1551 if (property->name == NULL) continue;
1552 if (strcmp(property->name,
1553 TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) == 0) {
1554 san_count++;
Paul Querna47d841d2016-03-10 11:19:17 -08001555
1556 if (!like_ip && does_entry_match_name(property->value.data,
1557 property->value.length, name)) {
1558 return 1;
1559 } else if (like_ip &&
1560 strncmp(name, property->value.data, property->value.length) ==
1561 0 &&
1562 strlen(name) == property->value.length) {
1563 /* IP Addresses are exact matches only. */
Craig Tillera82950e2015-09-22 12:33:20 -07001564 return 1;
1565 }
1566 } else if (strcmp(property->name,
1567 TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY) == 0) {
1568 cn_property = property;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001569 }
Craig Tillera82950e2015-09-22 12:33:20 -07001570 }
Julien Boeuf597a4f22015-02-23 15:57:14 -08001571
Paul Querna47d841d2016-03-10 11:19:17 -08001572 /* If there's no SAN, try the CN, but only if its not like an IP Address */
1573 if (san_count == 0 && cn_property != NULL && !like_ip) {
Craig Tillera82950e2015-09-22 12:33:20 -07001574 if (does_entry_match_name(cn_property->value.data,
1575 cn_property->value.length, name)) {
1576 return 1;
Julien Boeuf597a4f22015-02-23 15:57:14 -08001577 }
Craig Tillera82950e2015-09-22 12:33:20 -07001578 }
Julien Boeuf597a4f22015-02-23 15:57:14 -08001579
Craig Tillera82950e2015-09-22 12:33:20 -07001580 return 0; /* Not found. */
Craig Tiller190d3602015-02-18 09:23:38 -08001581}