aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/tsi/ssl_transport_security.c
diff options
context:
space:
mode:
authorGravatar Craig Tiller <ctiller@google.com>2015-09-22 10:42:19 -0700
committerGravatar Craig Tiller <ctiller@google.com>2015-09-22 10:42:19 -0700
commit45724b35e411fef7c5da66a74c78428c11d56843 (patch)
tree9264034aca675c89444e02f72ef58e67d7043604 /src/core/tsi/ssl_transport_security.c
parent298751c1195523ef6228595043b583c3a6270e08 (diff)
indent pass to get logical source lines on one physical line
Diffstat (limited to 'src/core/tsi/ssl_transport_security.c')
-rw-r--r--src/core/tsi/ssl_transport_security.c2176
1 files changed, 1153 insertions, 1023 deletions
diff --git a/src/core/tsi/ssl_transport_security.c b/src/core/tsi/ssl_transport_security.c
index 99ce7ecadf..a4e3503a96 100644
--- a/src/core/tsi/ssl_transport_security.c
+++ b/src/core/tsi/ssl_transport_security.c
@@ -43,7 +43,7 @@
#include "src/core/tsi/transport_security.h"
#include <openssl/bio.h>
-#include <openssl/crypto.h> /* For OPENSSL_free */
+#include <openssl/crypto.h> /* For OPENSSL_free */
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <openssl/x509.h>
@@ -67,47 +67,50 @@
/* --- Structure definitions. ---*/
-struct tsi_ssl_handshaker_factory {
- tsi_result (*create_handshaker)(tsi_ssl_handshaker_factory* self,
- const char* server_name_indication,
- tsi_handshaker** handshaker);
- void (*destroy)(tsi_ssl_handshaker_factory* self);
+struct tsi_ssl_handshaker_factory
+{
+ tsi_result (*create_handshaker) (tsi_ssl_handshaker_factory * self, const char *server_name_indication, tsi_handshaker ** handshaker);
+ void (*destroy) (tsi_ssl_handshaker_factory * self);
};
-typedef struct {
+typedef struct
+{
tsi_ssl_handshaker_factory base;
- SSL_CTX* ssl_context;
- unsigned char* alpn_protocol_list;
+ SSL_CTX *ssl_context;
+ unsigned char *alpn_protocol_list;
size_t alpn_protocol_list_length;
} tsi_ssl_client_handshaker_factory;
-typedef struct {
+typedef struct
+{
tsi_ssl_handshaker_factory base;
/* Several contexts to support SNI.
The tsi_peer array contains the subject names of the server certificates
associated with the contexts at the same index. */
- SSL_CTX** ssl_contexts;
- tsi_peer* ssl_context_x509_subject_names;
+ SSL_CTX **ssl_contexts;
+ tsi_peer *ssl_context_x509_subject_names;
size_t ssl_context_count;
- unsigned char* alpn_protocol_list;
+ unsigned char *alpn_protocol_list;
size_t alpn_protocol_list_length;
} tsi_ssl_server_handshaker_factory;
-typedef struct {
+typedef struct
+{
tsi_handshaker base;
- SSL* ssl;
- BIO* into_ssl;
- BIO* from_ssl;
+ SSL *ssl;
+ BIO *into_ssl;
+ BIO *from_ssl;
tsi_result result;
} tsi_ssl_handshaker;
-typedef struct {
+typedef struct
+{
tsi_frame_protector base;
- SSL* ssl;
- BIO* into_ssl;
- BIO* from_ssl;
- unsigned char* buffer;
+ SSL *ssl;
+ BIO *into_ssl;
+ BIO *from_ssl;
+ unsigned char *buffer;
size_t buffer_size;
size_t buffer_offset;
} tsi_ssl_frame_protector;
@@ -115,41 +118,54 @@ typedef struct {
/* --- Library Initialization. ---*/
static gpr_once init_openssl_once = GPR_ONCE_INIT;
-static gpr_mu* openssl_mutexes = NULL;
-
-static void openssl_locking_cb(int mode, int type, const char* file, int line) {
- if (mode & CRYPTO_LOCK) {
- gpr_mu_lock(&openssl_mutexes[type]);
- } else {
- gpr_mu_unlock(&openssl_mutexes[type]);
- }
+static gpr_mu *openssl_mutexes = NULL;
+
+static void
+openssl_locking_cb (int mode, int type, const char *file, int line)
+{
+ if (mode & CRYPTO_LOCK)
+ {
+ gpr_mu_lock (&openssl_mutexes[type]);
+ }
+ else
+ {
+ gpr_mu_unlock (&openssl_mutexes[type]);
+ }
}
-static unsigned long openssl_thread_id_cb(void) {
- return (unsigned long)gpr_thd_currentid();
+static unsigned long
+openssl_thread_id_cb (void)
+{
+ return (unsigned long) gpr_thd_currentid ();
}
-static void init_openssl(void) {
+static void
+init_openssl (void)
+{
int i;
int num_locks;
- SSL_library_init();
- SSL_load_error_strings();
- OpenSSL_add_all_algorithms();
- num_locks = CRYPTO_num_locks();
- GPR_ASSERT(num_locks > 0);
- openssl_mutexes = malloc((size_t)num_locks * sizeof(gpr_mu));
- GPR_ASSERT(openssl_mutexes != NULL);
- for (i = 0; i < CRYPTO_num_locks(); i++) {
- gpr_mu_init(&openssl_mutexes[i]);
- }
- CRYPTO_set_locking_callback(openssl_locking_cb);
- CRYPTO_set_id_callback(openssl_thread_id_cb);
+ SSL_library_init ();
+ SSL_load_error_strings ();
+ OpenSSL_add_all_algorithms ();
+ num_locks = CRYPTO_num_locks ();
+ GPR_ASSERT (num_locks > 0);
+ openssl_mutexes = malloc ((size_t) num_locks * sizeof (gpr_mu));
+ GPR_ASSERT (openssl_mutexes != NULL);
+ for (i = 0; i < CRYPTO_num_locks (); i++)
+ {
+ gpr_mu_init (&openssl_mutexes[i]);
+ }
+ CRYPTO_set_locking_callback (openssl_locking_cb);
+ CRYPTO_set_id_callback (openssl_thread_id_cb);
}
/* --- Ssl utils. ---*/
-static const char* ssl_error_string(int error) {
- switch (error) {
+static const char *
+ssl_error_string (int error)
+{
+ switch (error)
+ {
case SSL_ERROR_NONE:
return "SSL_ERROR_NONE";
case SSL_ERROR_ZERO_RETURN:
@@ -170,791 +186,885 @@ static const char* ssl_error_string(int error) {
return "SSL_ERROR_SSL";
default:
return "Unknown error";
- }
+ }
}
/* TODO(jboeuf): Remove when we are past the debugging phase with this code. */
-static void ssl_log_where_info(const SSL* ssl, int where, int flag,
- const char* msg) {
- if ((where & flag) && tsi_tracing_enabled) {
- gpr_log(GPR_INFO, "%20.20s - %30.30s - %5.10s", msg,
- SSL_state_string_long(ssl), SSL_state_string(ssl));
- }
+static void
+ssl_log_where_info (const SSL * ssl, int where, int flag, const char *msg)
+{
+ if ((where & flag) && tsi_tracing_enabled)
+ {
+ gpr_log (GPR_INFO, "%20.20s - %30.30s - %5.10s", msg, SSL_state_string_long (ssl), SSL_state_string (ssl));
+ }
}
/* Used for debugging. TODO(jboeuf): Remove when code is mature enough. */
-static void ssl_info_callback(const SSL* ssl, int where, int ret) {
- if (ret == 0) {
- gpr_log(GPR_ERROR, "ssl_info_callback: error occured.\n");
- return;
- }
+static void
+ssl_info_callback (const SSL * ssl, int where, int ret)
+{
+ if (ret == 0)
+ {
+ gpr_log (GPR_ERROR, "ssl_info_callback: error occured.\n");
+ return;
+ }
- ssl_log_where_info(ssl, where, SSL_CB_LOOP, "LOOP");
- ssl_log_where_info(ssl, where, SSL_CB_HANDSHAKE_START, "HANDSHAKE START");
- ssl_log_where_info(ssl, where, SSL_CB_HANDSHAKE_DONE, "HANDSHAKE DONE");
+ ssl_log_where_info (ssl, where, SSL_CB_LOOP, "LOOP");
+ ssl_log_where_info (ssl, where, SSL_CB_HANDSHAKE_START, "HANDSHAKE START");
+ ssl_log_where_info (ssl, where, SSL_CB_HANDSHAKE_DONE, "HANDSHAKE DONE");
}
/* Returns 1 if name looks like an IP address, 0 otherwise.
This is a very rough heuristic as it does not handle IPV6 or things like:
0300.0250.00.01, 0xC0.0Xa8.0x0.0x1, 000030052000001, 0xc0.052000001 */
-static int looks_like_ip_address(const char* name) {
+static int
+looks_like_ip_address (const char *name)
+{
size_t i;
size_t dot_count = 0;
size_t num_size = 0;
- for (i = 0; i < strlen(name); i++) {
- if (name[i] >= '0' && name[i] <= '9') {
- if (num_size > 3) return 0;
- num_size++;
- } else if (name[i] == '.') {
- if (dot_count > 3 || num_size == 0) return 0;
- dot_count++;
- num_size = 0;
- } else {
- return 0;
+ for (i = 0; i < strlen (name); i++)
+ {
+ if (name[i] >= '0' && name[i] <= '9')
+ {
+ if (num_size > 3)
+ return 0;
+ num_size++;
+ }
+ else if (name[i] == '.')
+ {
+ if (dot_count > 3 || num_size == 0)
+ return 0;
+ dot_count++;
+ num_size = 0;
+ }
+ else
+ {
+ return 0;
+ }
}
- }
- if (dot_count < 3 || num_size == 0) return 0;
+ if (dot_count < 3 || num_size == 0)
+ return 0;
return 1;
}
/* Gets the subject CN from an X509 cert. */
-static tsi_result ssl_get_x509_common_name(X509* cert, unsigned char** utf8,
- size_t* utf8_size) {
+static tsi_result
+ssl_get_x509_common_name (X509 * cert, unsigned char **utf8, size_t * utf8_size)
+{
int common_name_index = -1;
- X509_NAME_ENTRY* common_name_entry = NULL;
- ASN1_STRING* common_name_asn1 = NULL;
- X509_NAME* subject_name = X509_get_subject_name(cert);
+ X509_NAME_ENTRY *common_name_entry = NULL;
+ ASN1_STRING *common_name_asn1 = NULL;
+ X509_NAME *subject_name = X509_get_subject_name (cert);
int utf8_returned_size = 0;
- if (subject_name == NULL) {
- gpr_log(GPR_ERROR, "Could not get subject name from certificate.");
- return TSI_NOT_FOUND;
- }
- common_name_index =
- X509_NAME_get_index_by_NID(subject_name, NID_commonName, -1);
- if (common_name_index == -1) {
- gpr_log(GPR_ERROR,
- "Could not get common name of subject from certificate.");
- return TSI_NOT_FOUND;
- }
- common_name_entry = X509_NAME_get_entry(subject_name, common_name_index);
- if (common_name_entry == NULL) {
- gpr_log(GPR_ERROR, "Could not get common name entry from certificate.");
- return TSI_INTERNAL_ERROR;
- }
- common_name_asn1 = X509_NAME_ENTRY_get_data(common_name_entry);
- if (common_name_asn1 == NULL) {
- gpr_log(GPR_ERROR,
- "Could not get common name entry asn1 from certificate.");
- return TSI_INTERNAL_ERROR;
- }
- utf8_returned_size = ASN1_STRING_to_UTF8(utf8, common_name_asn1);
- if (utf8_returned_size < 0) {
- gpr_log(GPR_ERROR, "Could not extract utf8 from asn1 string.");
- return TSI_OUT_OF_RESOURCES;
- }
- *utf8_size = (size_t)utf8_returned_size;
+ if (subject_name == NULL)
+ {
+ gpr_log (GPR_ERROR, "Could not get subject name from certificate.");
+ return TSI_NOT_FOUND;
+ }
+ common_name_index = X509_NAME_get_index_by_NID (subject_name, NID_commonName, -1);
+ if (common_name_index == -1)
+ {
+ gpr_log (GPR_ERROR, "Could not get common name of subject from certificate.");
+ return TSI_NOT_FOUND;
+ }
+ common_name_entry = X509_NAME_get_entry (subject_name, common_name_index);
+ if (common_name_entry == NULL)
+ {
+ gpr_log (GPR_ERROR, "Could not get common name entry from certificate.");
+ return TSI_INTERNAL_ERROR;
+ }
+ common_name_asn1 = X509_NAME_ENTRY_get_data (common_name_entry);
+ if (common_name_asn1 == NULL)
+ {
+ gpr_log (GPR_ERROR, "Could not get common name entry asn1 from certificate.");
+ return TSI_INTERNAL_ERROR;
+ }
+ utf8_returned_size = ASN1_STRING_to_UTF8 (utf8, common_name_asn1);
+ if (utf8_returned_size < 0)
+ {
+ gpr_log (GPR_ERROR, "Could not extract utf8 from asn1 string.");
+ return TSI_OUT_OF_RESOURCES;
+ }
+ *utf8_size = (size_t) utf8_returned_size;
return TSI_OK;
}
/* Gets the subject CN of an X509 cert as a tsi_peer_property. */
-static tsi_result peer_property_from_x509_common_name(
- X509* cert, tsi_peer_property* property) {
- unsigned char* common_name;
+static tsi_result
+peer_property_from_x509_common_name (X509 * cert, tsi_peer_property * property)
+{
+ unsigned char *common_name;
size_t common_name_size;
- tsi_result result =
- ssl_get_x509_common_name(cert, &common_name, &common_name_size);
- if (result != TSI_OK) {
- if (result == TSI_NOT_FOUND) {
- common_name = NULL;
- common_name_size = 0;
- } else {
- return result;
+ tsi_result result = ssl_get_x509_common_name (cert, &common_name, &common_name_size);
+ if (result != TSI_OK)
+ {
+ if (result == TSI_NOT_FOUND)
+ {
+ common_name = NULL;
+ common_name_size = 0;
+ }
+ else
+ {
+ return result;
+ }
}
- }
- result = tsi_construct_string_peer_property(
- TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY,
- common_name == NULL ? "" : (const char*)common_name, common_name_size,
- property);
- OPENSSL_free(common_name);
+ result = tsi_construct_string_peer_property (TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, common_name == NULL ? "" : (const char *) common_name, common_name_size, property);
+ OPENSSL_free (common_name);
return result;
}
/* Gets the subject SANs from an X509 cert as a tsi_peer_property. */
-static tsi_result add_subject_alt_names_properties_to_peer(
- tsi_peer* peer, GENERAL_NAMES* subject_alt_names,
- size_t subject_alt_name_count) {
+static tsi_result
+add_subject_alt_names_properties_to_peer (tsi_peer * peer, GENERAL_NAMES * subject_alt_names, size_t subject_alt_name_count)
+{
size_t i;
tsi_result result = TSI_OK;
/* Reset for DNS entries filtering. */
peer->property_count -= subject_alt_name_count;
- for (i = 0; i < subject_alt_name_count; i++) {
- GENERAL_NAME* subject_alt_name =
- sk_GENERAL_NAME_value(subject_alt_names, (int)i);
- /* Filter out the non-dns entries names. */
- if (subject_alt_name->type == GEN_DNS) {
- unsigned char* dns_name = NULL;
- int dns_name_size =
- ASN1_STRING_to_UTF8(&dns_name, subject_alt_name->d.dNSName);
- if (dns_name_size < 0) {
- gpr_log(GPR_ERROR, "Could not get utf8 from asn1 string.");
- result = TSI_INTERNAL_ERROR;
- break;
- }
- result = tsi_construct_string_peer_property(
- TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY,
- (const char*)dns_name, (size_t)dns_name_size,
- &peer->properties[peer->property_count++]);
- OPENSSL_free(dns_name);
- if (result != TSI_OK) break;
+ for (i = 0; i < subject_alt_name_count; i++)
+ {
+ GENERAL_NAME *subject_alt_name = sk_GENERAL_NAME_value (subject_alt_names, (int) i);
+ /* Filter out the non-dns entries names. */
+ if (subject_alt_name->type == GEN_DNS)
+ {
+ unsigned char *dns_name = NULL;
+ int dns_name_size = ASN1_STRING_to_UTF8 (&dns_name, subject_alt_name->d.dNSName);
+ if (dns_name_size < 0)
+ {
+ gpr_log (GPR_ERROR, "Could not get utf8 from asn1 string.");
+ result = TSI_INTERNAL_ERROR;
+ break;
+ }
+ result = tsi_construct_string_peer_property (TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, (const char *) dns_name, (size_t) dns_name_size, &peer->properties[peer->property_count++]);
+ OPENSSL_free (dns_name);
+ if (result != TSI_OK)
+ break;
+ }
}
- }
return result;
}
/* Gets information about the peer's X509 cert as a tsi_peer object. */
-static tsi_result peer_from_x509(X509* cert, int include_certificate_type,
- tsi_peer* peer) {
+static tsi_result
+peer_from_x509 (X509 * cert, int include_certificate_type, tsi_peer * peer)
+{
/* TODO(jboeuf): Maybe add more properties. */
- GENERAL_NAMES* subject_alt_names =
- X509_get_ext_d2i(cert, NID_subject_alt_name, 0, 0);
- int subject_alt_name_count =
- (subject_alt_names != NULL) ? sk_GENERAL_NAME_num(subject_alt_names) : 0;
+ GENERAL_NAMES *subject_alt_names = X509_get_ext_d2i (cert, NID_subject_alt_name, 0, 0);
+ int subject_alt_name_count = (subject_alt_names != NULL) ? sk_GENERAL_NAME_num (subject_alt_names) : 0;
size_t property_count;
tsi_result result;
- GPR_ASSERT(subject_alt_name_count >= 0);
- property_count = (include_certificate_type ? (size_t)1 : 0) +
- 1 /* common name */ + (size_t)subject_alt_name_count;
- result = tsi_construct_peer(property_count, peer);
- if (result != TSI_OK) return result;
- do {
- if (include_certificate_type) {
- result = tsi_construct_string_peer_property_from_cstring(
- TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE,
- &peer->properties[0]);
- if (result != TSI_OK) break;
- }
- result = peer_property_from_x509_common_name(
- cert, &peer->properties[include_certificate_type ? 1 : 0]);
- if (result != TSI_OK) break;
-
- if (subject_alt_name_count != 0) {
- result = add_subject_alt_names_properties_to_peer(
- peer, subject_alt_names, (size_t)subject_alt_name_count);
- if (result != TSI_OK) break;
- }
- } while (0);
-
- if (subject_alt_names != NULL) {
- sk_GENERAL_NAME_pop_free(subject_alt_names, GENERAL_NAME_free);
- }
- if (result != TSI_OK) tsi_peer_destruct(peer);
+ GPR_ASSERT (subject_alt_name_count >= 0);
+ property_count = (include_certificate_type ? (size_t) 1 : 0) + 1 /* common name */ + (size_t) subject_alt_name_count;
+ result = tsi_construct_peer (property_count, peer);
+ if (result != TSI_OK)
+ return result;
+ do
+ {
+ if (include_certificate_type)
+ {
+ result = tsi_construct_string_peer_property_from_cstring (TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE, &peer->properties[0]);
+ if (result != TSI_OK)
+ break;
+ }
+ result = peer_property_from_x509_common_name (cert, &peer->properties[include_certificate_type ? 1 : 0]);
+ if (result != TSI_OK)
+ break;
+
+ if (subject_alt_name_count != 0)
+ {
+ result = add_subject_alt_names_properties_to_peer (peer, subject_alt_names, (size_t) subject_alt_name_count);
+ if (result != TSI_OK)
+ break;
+ }
+ }
+ while (0);
+
+ if (subject_alt_names != NULL)
+ {
+ sk_GENERAL_NAME_pop_free (subject_alt_names, GENERAL_NAME_free);
+ }
+ if (result != TSI_OK)
+ tsi_peer_destruct (peer);
return result;
}
/* Logs the SSL error stack. */
-static void log_ssl_error_stack(void) {
+static void
+log_ssl_error_stack (void)
+{
unsigned long err;
- while ((err = ERR_get_error()) != 0) {
- char details[256];
- ERR_error_string_n(err, details, sizeof(details));
- gpr_log(GPR_ERROR, "%s", details);
- }
+ while ((err = ERR_get_error ()) != 0)
+ {
+ char details[256];
+ ERR_error_string_n (err, details, sizeof (details));
+ gpr_log (GPR_ERROR, "%s", details);
+ }
}
/* Performs an SSL_read and handle errors. */
-static tsi_result do_ssl_read(SSL* ssl, unsigned char* unprotected_bytes,
- size_t* unprotected_bytes_size) {
+static tsi_result
+do_ssl_read (SSL * ssl, unsigned char *unprotected_bytes, size_t * unprotected_bytes_size)
+{
int read_from_ssl;
- GPR_ASSERT(*unprotected_bytes_size <= INT_MAX);
- read_from_ssl =
- SSL_read(ssl, unprotected_bytes, (int)*unprotected_bytes_size);
- if (read_from_ssl == 0) {
- gpr_log(GPR_ERROR, "SSL_read returned 0 unexpectedly.");
- return TSI_INTERNAL_ERROR;
- }
- if (read_from_ssl < 0) {
- read_from_ssl = SSL_get_error(ssl, read_from_ssl);
- switch (read_from_ssl) {
- case SSL_ERROR_WANT_READ:
- /* We need more data to finish the frame. */
- *unprotected_bytes_size = 0;
- return TSI_OK;
- case SSL_ERROR_WANT_WRITE:
- gpr_log(
- GPR_ERROR,
- "Peer tried to renegotiate SSL connection. This is unsupported.");
- return TSI_UNIMPLEMENTED;
- case SSL_ERROR_SSL:
- gpr_log(GPR_ERROR, "Corruption detected.");
- log_ssl_error_stack();
- return TSI_DATA_CORRUPTED;
- default:
- gpr_log(GPR_ERROR, "SSL_read failed with error %s.",
- ssl_error_string(read_from_ssl));
- return TSI_PROTOCOL_FAILURE;
+ GPR_ASSERT (*unprotected_bytes_size <= INT_MAX);
+ read_from_ssl = SSL_read (ssl, unprotected_bytes, (int) *unprotected_bytes_size);
+ if (read_from_ssl == 0)
+ {
+ gpr_log (GPR_ERROR, "SSL_read returned 0 unexpectedly.");
+ return TSI_INTERNAL_ERROR;
}
- }
- *unprotected_bytes_size = (size_t)read_from_ssl;
+ if (read_from_ssl < 0)
+ {
+ read_from_ssl = SSL_get_error (ssl, read_from_ssl);
+ switch (read_from_ssl)
+ {
+ case SSL_ERROR_WANT_READ:
+ /* We need more data to finish the frame. */
+ *unprotected_bytes_size = 0;
+ return TSI_OK;
+ case SSL_ERROR_WANT_WRITE:
+ gpr_log (GPR_ERROR, "Peer tried to renegotiate SSL connection. This is unsupported.");
+ return TSI_UNIMPLEMENTED;
+ case SSL_ERROR_SSL:
+ gpr_log (GPR_ERROR, "Corruption detected.");
+ log_ssl_error_stack ();
+ return TSI_DATA_CORRUPTED;
+ default:
+ gpr_log (GPR_ERROR, "SSL_read failed with error %s.", ssl_error_string (read_from_ssl));
+ return TSI_PROTOCOL_FAILURE;
+ }
+ }
+ *unprotected_bytes_size = (size_t) read_from_ssl;
return TSI_OK;
}
/* Performs an SSL_write and handle errors. */
-static tsi_result do_ssl_write(SSL* ssl, unsigned char* unprotected_bytes,
- size_t unprotected_bytes_size) {
+static tsi_result
+do_ssl_write (SSL * ssl, unsigned char *unprotected_bytes, size_t unprotected_bytes_size)
+{
int ssl_write_result;
- GPR_ASSERT(unprotected_bytes_size <= INT_MAX);
- ssl_write_result =
- SSL_write(ssl, unprotected_bytes, (int)unprotected_bytes_size);
- if (ssl_write_result < 0) {
- ssl_write_result = SSL_get_error(ssl, ssl_write_result);
- if (ssl_write_result == SSL_ERROR_WANT_READ) {
- gpr_log(GPR_ERROR,
- "Peer tried to renegotiate SSL connection. This is unsupported.");
- return TSI_UNIMPLEMENTED;
- } else {
- gpr_log(GPR_ERROR, "SSL_write failed with error %s.",
- ssl_error_string(ssl_write_result));
- return TSI_INTERNAL_ERROR;
+ GPR_ASSERT (unprotected_bytes_size <= INT_MAX);
+ ssl_write_result = SSL_write (ssl, unprotected_bytes, (int) unprotected_bytes_size);
+ if (ssl_write_result < 0)
+ {
+ ssl_write_result = SSL_get_error (ssl, ssl_write_result);
+ if (ssl_write_result == SSL_ERROR_WANT_READ)
+ {
+ gpr_log (GPR_ERROR, "Peer tried to renegotiate SSL connection. This is unsupported.");
+ return TSI_UNIMPLEMENTED;
+ }
+ else
+ {
+ gpr_log (GPR_ERROR, "SSL_write failed with error %s.", ssl_error_string (ssl_write_result));
+ return TSI_INTERNAL_ERROR;
+ }
}
- }
return TSI_OK;
}
/* Loads an in-memory PEM certificate chain into the SSL context. */
-static tsi_result ssl_ctx_use_certificate_chain(
- SSL_CTX* context, const unsigned char* pem_cert_chain,
- size_t pem_cert_chain_size) {
+static tsi_result
+ssl_ctx_use_certificate_chain (SSL_CTX * context, const unsigned char *pem_cert_chain, size_t pem_cert_chain_size)
+{
tsi_result result = TSI_OK;
- X509* certificate = NULL;
- BIO* pem;
- GPR_ASSERT(pem_cert_chain_size <= INT_MAX);
- pem = BIO_new_mem_buf((void*)pem_cert_chain, (int)pem_cert_chain_size);
- if (pem == NULL) return TSI_OUT_OF_RESOURCES;
-
- do {
- certificate = PEM_read_bio_X509_AUX(pem, NULL, NULL, "");
- if (certificate == NULL) {
- result = TSI_INVALID_ARGUMENT;
- break;
- }
- if (!SSL_CTX_use_certificate(context, certificate)) {
- result = TSI_INVALID_ARGUMENT;
- break;
- }
- while (1) {
- X509* certificate_authority = PEM_read_bio_X509(pem, NULL, NULL, "");
- if (certificate_authority == NULL) {
- ERR_clear_error();
- break; /* Done reading. */
- }
- if (!SSL_CTX_add_extra_chain_cert(context, certificate_authority)) {
- X509_free(certificate_authority);
- result = TSI_INVALID_ARGUMENT;
- break;
- }
- /* We don't need to free certificate_authority as its ownership has been
- transfered to the context. That is not the case for certificate though.
- */
+ X509 *certificate = NULL;
+ BIO *pem;
+ GPR_ASSERT (pem_cert_chain_size <= INT_MAX);
+ pem = BIO_new_mem_buf ((void *) pem_cert_chain, (int) pem_cert_chain_size);
+ if (pem == NULL)
+ return TSI_OUT_OF_RESOURCES;
+
+ do
+ {
+ certificate = PEM_read_bio_X509_AUX (pem, NULL, NULL, "");
+ if (certificate == NULL)
+ {
+ result = TSI_INVALID_ARGUMENT;
+ break;
+ }
+ if (!SSL_CTX_use_certificate (context, certificate))
+ {
+ result = TSI_INVALID_ARGUMENT;
+ break;
+ }
+ while (1)
+ {
+ X509 *certificate_authority = PEM_read_bio_X509 (pem, NULL, NULL, "");
+ if (certificate_authority == NULL)
+ {
+ ERR_clear_error ();
+ break; /* Done reading. */
+ }
+ if (!SSL_CTX_add_extra_chain_cert (context, certificate_authority))
+ {
+ X509_free (certificate_authority);
+ result = TSI_INVALID_ARGUMENT;
+ break;
+ }
+ /* We don't need to free certificate_authority as its ownership has been
+ transfered to the context. That is not the case for certificate though.
+ */
+ }
}
- } while (0);
+ while (0);
- if (certificate != NULL) X509_free(certificate);
- BIO_free(pem);
+ if (certificate != NULL)
+ X509_free (certificate);
+ BIO_free (pem);
return result;
}
/* Loads an in-memory PEM private key into the SSL context. */
-static tsi_result ssl_ctx_use_private_key(SSL_CTX* context,
- const unsigned char* pem_key,
- size_t pem_key_size) {
+static tsi_result
+ssl_ctx_use_private_key (SSL_CTX * context, const unsigned char *pem_key, size_t pem_key_size)
+{
tsi_result result = TSI_OK;
- EVP_PKEY* private_key = NULL;
- BIO* pem;
- GPR_ASSERT(pem_key_size <= INT_MAX);
- pem = BIO_new_mem_buf((void*)pem_key, (int)pem_key_size);
- if (pem == NULL) return TSI_OUT_OF_RESOURCES;
- do {
- private_key = PEM_read_bio_PrivateKey(pem, NULL, NULL, "");
- if (private_key == NULL) {
- result = TSI_INVALID_ARGUMENT;
- break;
- }
- if (!SSL_CTX_use_PrivateKey(context, private_key)) {
- result = TSI_INVALID_ARGUMENT;
- break;
+ EVP_PKEY *private_key = NULL;
+ BIO *pem;
+ GPR_ASSERT (pem_key_size <= INT_MAX);
+ pem = BIO_new_mem_buf ((void *) pem_key, (int) pem_key_size);
+ if (pem == NULL)
+ return TSI_OUT_OF_RESOURCES;
+ do
+ {
+ private_key = PEM_read_bio_PrivateKey (pem, NULL, NULL, "");
+ if (private_key == NULL)
+ {
+ result = TSI_INVALID_ARGUMENT;
+ break;
+ }
+ if (!SSL_CTX_use_PrivateKey (context, private_key))
+ {
+ result = TSI_INVALID_ARGUMENT;
+ break;
+ }
}
- } while (0);
- if (private_key != NULL) EVP_PKEY_free(private_key);
- BIO_free(pem);
+ while (0);
+ if (private_key != NULL)
+ EVP_PKEY_free (private_key);
+ BIO_free (pem);
return result;
}
/* Loads in-memory PEM verification certs into the SSL context and optionally
returns the verification cert names (root_names can be NULL). */
-static tsi_result ssl_ctx_load_verification_certs(
- SSL_CTX* context, const unsigned char* pem_roots, size_t pem_roots_size,
- STACK_OF(X509_NAME) * *root_names) {
+static tsi_result
+ssl_ctx_load_verification_certs (SSL_CTX * context, const unsigned char *pem_roots, size_t pem_roots_size, STACK_OF (X509_NAME) * *root_names)
+{
tsi_result result = TSI_OK;
size_t num_roots = 0;
- X509* root = NULL;
- X509_NAME* root_name = NULL;
- BIO* pem;
- X509_STORE* root_store;
- GPR_ASSERT(pem_roots_size <= INT_MAX);
- pem = BIO_new_mem_buf((void*)pem_roots, (int)pem_roots_size);
- root_store = SSL_CTX_get_cert_store(context);
- if (root_store == NULL) return TSI_INVALID_ARGUMENT;
- if (pem == NULL) return TSI_OUT_OF_RESOURCES;
- if (root_names != NULL) {
- *root_names = sk_X509_NAME_new_null();
- if (*root_names == NULL) return TSI_OUT_OF_RESOURCES;
- }
-
- while (1) {
- root = PEM_read_bio_X509_AUX(pem, NULL, NULL, "");
- if (root == NULL) {
- ERR_clear_error();
- break; /* We're at the end of stream. */
- }
- if (root_names != NULL) {
- root_name = X509_get_subject_name(root);
- if (root_name == NULL) {
- gpr_log(GPR_ERROR, "Could not get name from root certificate.");
- result = TSI_INVALID_ARGUMENT;
- break;
- }
- root_name = X509_NAME_dup(root_name);
- if (root_name == NULL) {
- result = TSI_OUT_OF_RESOURCES;
- break;
- }
- sk_X509_NAME_push(*root_names, root_name);
- root_name = NULL;
+ X509 *root = NULL;
+ X509_NAME *root_name = NULL;
+ BIO *pem;
+ X509_STORE *root_store;
+ GPR_ASSERT (pem_roots_size <= INT_MAX);
+ pem = BIO_new_mem_buf ((void *) pem_roots, (int) pem_roots_size);
+ root_store = SSL_CTX_get_cert_store (context);
+ if (root_store == NULL)
+ return TSI_INVALID_ARGUMENT;
+ if (pem == NULL)
+ return TSI_OUT_OF_RESOURCES;
+ if (root_names != NULL)
+ {
+ *root_names = sk_X509_NAME_new_null ();
+ if (*root_names == NULL)
+ return TSI_OUT_OF_RESOURCES;
}
- if (!X509_STORE_add_cert(root_store, root)) {
- gpr_log(GPR_ERROR, "Could not add root certificate to ssl context.");
- result = TSI_INTERNAL_ERROR;
- break;
+
+ while (1)
+ {
+ root = PEM_read_bio_X509_AUX (pem, NULL, NULL, "");
+ if (root == NULL)
+ {
+ ERR_clear_error ();
+ break; /* We're at the end of stream. */
+ }
+ if (root_names != NULL)
+ {
+ root_name = X509_get_subject_name (root);
+ if (root_name == NULL)
+ {
+ gpr_log (GPR_ERROR, "Could not get name from root certificate.");
+ result = TSI_INVALID_ARGUMENT;
+ break;
+ }
+ root_name = X509_NAME_dup (root_name);
+ if (root_name == NULL)
+ {
+ result = TSI_OUT_OF_RESOURCES;
+ break;
+ }
+ sk_X509_NAME_push (*root_names, root_name);
+ root_name = NULL;
+ }
+ if (!X509_STORE_add_cert (root_store, root))
+ {
+ gpr_log (GPR_ERROR, "Could not add root certificate to ssl context.");
+ result = TSI_INTERNAL_ERROR;
+ break;
+ }
+ X509_free (root);
+ num_roots++;
}
- X509_free(root);
- num_roots++;
- }
- if (num_roots == 0) {
- gpr_log(GPR_ERROR, "Could not load any root certificate.");
- result = TSI_INVALID_ARGUMENT;
- }
+ if (num_roots == 0)
+ {
+ gpr_log (GPR_ERROR, "Could not load any root certificate.");
+ result = TSI_INVALID_ARGUMENT;
+ }
- if (result != TSI_OK) {
- if (root != NULL) X509_free(root);
- if (root_names != NULL) {
- sk_X509_NAME_pop_free(*root_names, X509_NAME_free);
- *root_names = NULL;
- if (root_name != NULL) X509_NAME_free(root_name);
+ if (result != TSI_OK)
+ {
+ if (root != NULL)
+ X509_free (root);
+ if (root_names != NULL)
+ {
+ sk_X509_NAME_pop_free (*root_names, X509_NAME_free);
+ *root_names = NULL;
+ if (root_name != NULL)
+ X509_NAME_free (root_name);
+ }
}
- }
- BIO_free(pem);
+ BIO_free (pem);
return result;
}
/* Populates the SSL context with a private key and a cert chain, and sets the
cipher list and the ephemeral ECDH key. */
-static tsi_result populate_ssl_context(
- SSL_CTX* context, const unsigned char* pem_private_key,
- size_t pem_private_key_size, const unsigned char* pem_certificate_chain,
- size_t pem_certificate_chain_size, const char* cipher_list) {
+static tsi_result
+populate_ssl_context (SSL_CTX * context, const unsigned char *pem_private_key, size_t pem_private_key_size, const unsigned char *pem_certificate_chain, size_t pem_certificate_chain_size, const char *cipher_list)
+{
tsi_result result = TSI_OK;
- if (pem_certificate_chain != NULL) {
- result = ssl_ctx_use_certificate_chain(context, pem_certificate_chain,
- pem_certificate_chain_size);
- if (result != TSI_OK) {
- gpr_log(GPR_ERROR, "Invalid cert chain file.");
- return result;
+ if (pem_certificate_chain != NULL)
+ {
+ result = ssl_ctx_use_certificate_chain (context, pem_certificate_chain, pem_certificate_chain_size);
+ if (result != TSI_OK)
+ {
+ gpr_log (GPR_ERROR, "Invalid cert chain file.");
+ return result;
+ }
}
- }
- if (pem_private_key != NULL) {
- result =
- ssl_ctx_use_private_key(context, pem_private_key, pem_private_key_size);
- if (result != TSI_OK || !SSL_CTX_check_private_key(context)) {
- gpr_log(GPR_ERROR, "Invalid private key.");
- return result != TSI_OK ? result : TSI_INVALID_ARGUMENT;
+ if (pem_private_key != NULL)
+ {
+ result = ssl_ctx_use_private_key (context, pem_private_key, pem_private_key_size);
+ if (result != TSI_OK || !SSL_CTX_check_private_key (context))
+ {
+ gpr_log (GPR_ERROR, "Invalid private key.");
+ return result != TSI_OK ? result : TSI_INVALID_ARGUMENT;
+ }
}
- }
- if ((cipher_list != NULL) && !SSL_CTX_set_cipher_list(context, cipher_list)) {
- gpr_log(GPR_ERROR, "Invalid cipher list: %s.", cipher_list);
- return TSI_INVALID_ARGUMENT;
- }
- {
- EC_KEY* ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
- if (!SSL_CTX_set_tmp_ecdh(context, ecdh)) {
- gpr_log(GPR_ERROR, "Could not set ephemeral ECDH key.");
- EC_KEY_free(ecdh);
- return TSI_INTERNAL_ERROR;
+ if ((cipher_list != NULL) && !SSL_CTX_set_cipher_list (context, cipher_list))
+ {
+ gpr_log (GPR_ERROR, "Invalid cipher list: %s.", cipher_list);
+ return TSI_INVALID_ARGUMENT;
}
- SSL_CTX_set_options(context, SSL_OP_SINGLE_ECDH_USE);
- EC_KEY_free(ecdh);
+ {
+ EC_KEY *ecdh = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1);
+ if (!SSL_CTX_set_tmp_ecdh (context, ecdh))
+ {
+ gpr_log (GPR_ERROR, "Could not set ephemeral ECDH key.");
+ EC_KEY_free (ecdh);
+ return TSI_INTERNAL_ERROR;
+ }
+ SSL_CTX_set_options (context, SSL_OP_SINGLE_ECDH_USE);
+ EC_KEY_free (ecdh);
}
return TSI_OK;
}
/* Extracts the CN and the SANs from an X509 cert as a peer object. */
-static tsi_result extract_x509_subject_names_from_pem_cert(
- const unsigned char* pem_cert, size_t pem_cert_size, tsi_peer* peer) {
+static tsi_result
+extract_x509_subject_names_from_pem_cert (const unsigned char *pem_cert, size_t pem_cert_size, tsi_peer * peer)
+{
tsi_result result = TSI_OK;
- X509* cert = NULL;
- BIO* pem;
- GPR_ASSERT(pem_cert_size <= INT_MAX);
- pem = BIO_new_mem_buf((void*)pem_cert, (int)pem_cert_size);
- if (pem == NULL) return TSI_OUT_OF_RESOURCES;
-
- cert = PEM_read_bio_X509(pem, NULL, NULL, "");
- if (cert == NULL) {
- gpr_log(GPR_ERROR, "Invalid certificate");
- result = TSI_INVALID_ARGUMENT;
- } else {
- result = peer_from_x509(cert, 0, peer);
- }
- if (cert != NULL) X509_free(cert);
- BIO_free(pem);
+ X509 *cert = NULL;
+ BIO *pem;
+ GPR_ASSERT (pem_cert_size <= INT_MAX);
+ pem = BIO_new_mem_buf ((void *) pem_cert, (int) pem_cert_size);
+ if (pem == NULL)
+ return TSI_OUT_OF_RESOURCES;
+
+ cert = PEM_read_bio_X509 (pem, NULL, NULL, "");
+ if (cert == NULL)
+ {
+ gpr_log (GPR_ERROR, "Invalid certificate");
+ result = TSI_INVALID_ARGUMENT;
+ }
+ else
+ {
+ result = peer_from_x509 (cert, 0, peer);
+ }
+ if (cert != NULL)
+ X509_free (cert);
+ BIO_free (pem);
return result;
}
/* Builds the alpn protocol name list according to rfc 7301. */
-static tsi_result build_alpn_protocol_name_list(
- const unsigned char** alpn_protocols,
- const unsigned char* alpn_protocols_lengths, uint16_t num_alpn_protocols,
- unsigned char** protocol_name_list, size_t* protocol_name_list_length) {
+static tsi_result
+build_alpn_protocol_name_list (const unsigned char **alpn_protocols, const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols, unsigned char **protocol_name_list, size_t * protocol_name_list_length)
+{
uint16_t i;
- unsigned char* current;
+ unsigned char *current;
*protocol_name_list = NULL;
*protocol_name_list_length = 0;
- if (num_alpn_protocols == 0) return TSI_INVALID_ARGUMENT;
- for (i = 0; i < num_alpn_protocols; i++) {
- if (alpn_protocols_lengths[i] == 0) {
- gpr_log(GPR_ERROR, "Invalid 0-length protocol name.");
- return TSI_INVALID_ARGUMENT;
+ if (num_alpn_protocols == 0)
+ return TSI_INVALID_ARGUMENT;
+ for (i = 0; i < num_alpn_protocols; i++)
+ {
+ if (alpn_protocols_lengths[i] == 0)
+ {
+ gpr_log (GPR_ERROR, "Invalid 0-length protocol name.");
+ return TSI_INVALID_ARGUMENT;
+ }
+ *protocol_name_list_length += (size_t) alpn_protocols_lengths[i] + 1;
}
- *protocol_name_list_length += (size_t)alpn_protocols_lengths[i] + 1;
- }
- *protocol_name_list = malloc(*protocol_name_list_length);
- if (*protocol_name_list == NULL) return TSI_OUT_OF_RESOURCES;
+ *protocol_name_list = malloc (*protocol_name_list_length);
+ if (*protocol_name_list == NULL)
+ return TSI_OUT_OF_RESOURCES;
current = *protocol_name_list;
- for (i = 0; i < num_alpn_protocols; i++) {
- *(current++) = alpn_protocols_lengths[i];
- memcpy(current, alpn_protocols[i], alpn_protocols_lengths[i]);
- current += alpn_protocols_lengths[i];
- }
+ for (i = 0; i < num_alpn_protocols; i++)
+ {
+ *(current++) = alpn_protocols_lengths[i];
+ memcpy (current, alpn_protocols[i], alpn_protocols_lengths[i]);
+ current += alpn_protocols_lengths[i];
+ }
/* Safety check. */
- if ((current < *protocol_name_list) ||
- ((gpr_uintptr)(current - *protocol_name_list) !=
- *protocol_name_list_length)) {
- return TSI_INTERNAL_ERROR;
- }
+ if ((current < *protocol_name_list) || ((gpr_uintptr) (current - *protocol_name_list) != *protocol_name_list_length))
+ {
+ return TSI_INTERNAL_ERROR;
+ }
return TSI_OK;
}
/* --- tsi_frame_protector methods implementation. ---*/
-static tsi_result ssl_protector_protect(tsi_frame_protector* self,
- const unsigned char* unprotected_bytes,
- size_t* unprotected_bytes_size,
- unsigned char* protected_output_frames,
- size_t* protected_output_frames_size) {
- tsi_ssl_frame_protector* impl = (tsi_ssl_frame_protector*)self;
+static tsi_result
+ssl_protector_protect (tsi_frame_protector * self, const unsigned char *unprotected_bytes, size_t * unprotected_bytes_size, unsigned char *protected_output_frames, size_t * protected_output_frames_size)
+{
+ tsi_ssl_frame_protector *impl = (tsi_ssl_frame_protector *) self;
int read_from_ssl;
size_t available;
tsi_result result = TSI_OK;
/* First see if we have some pending data in the SSL BIO. */
- int pending_in_ssl = BIO_pending(impl->from_ssl);
- if (pending_in_ssl > 0) {
- *unprotected_bytes_size = 0;
- GPR_ASSERT(*protected_output_frames_size <= INT_MAX);
- read_from_ssl = BIO_read(impl->from_ssl, protected_output_frames,
- (int)*protected_output_frames_size);
- if (read_from_ssl < 0) {
- gpr_log(GPR_ERROR,
- "Could not read from BIO even though some data is pending");
- return TSI_INTERNAL_ERROR;
+ int pending_in_ssl = BIO_pending (impl->from_ssl);
+ if (pending_in_ssl > 0)
+ {
+ *unprotected_bytes_size = 0;
+ GPR_ASSERT (*protected_output_frames_size <= INT_MAX);
+ read_from_ssl = BIO_read (impl->from_ssl, protected_output_frames, (int) *protected_output_frames_size);
+ if (read_from_ssl < 0)
+ {
+ gpr_log (GPR_ERROR, "Could not read from BIO even though some data is pending");
+ return TSI_INTERNAL_ERROR;
+ }
+ *protected_output_frames_size = (size_t) read_from_ssl;
+ return TSI_OK;
}
- *protected_output_frames_size = (size_t)read_from_ssl;
- return TSI_OK;
- }
/* Now see if we can send a complete frame. */
available = impl->buffer_size - impl->buffer_offset;
- if (available > *unprotected_bytes_size) {
- /* If we cannot, just copy the data in our internal buffer. */
- memcpy(impl->buffer + impl->buffer_offset, unprotected_bytes,
- *unprotected_bytes_size);
- impl->buffer_offset += *unprotected_bytes_size;
- *protected_output_frames_size = 0;
- return TSI_OK;
- }
+ if (available > *unprotected_bytes_size)
+ {
+ /* If we cannot, just copy the data in our internal buffer. */
+ memcpy (impl->buffer + impl->buffer_offset, unprotected_bytes, *unprotected_bytes_size);
+ impl->buffer_offset += *unprotected_bytes_size;
+ *protected_output_frames_size = 0;
+ return TSI_OK;
+ }
/* If we can, prepare the buffer, send it to SSL_write and read. */
- memcpy(impl->buffer + impl->buffer_offset, unprotected_bytes, available);
- result = do_ssl_write(impl->ssl, impl->buffer, impl->buffer_size);
- if (result != TSI_OK) return result;
-
- GPR_ASSERT(*protected_output_frames_size <= INT_MAX);
- read_from_ssl = BIO_read(impl->from_ssl, protected_output_frames,
- (int)*protected_output_frames_size);
- if (read_from_ssl < 0) {
- gpr_log(GPR_ERROR, "Could not read from BIO after SSL_write.");
- return TSI_INTERNAL_ERROR;
- }
- *protected_output_frames_size = (size_t)read_from_ssl;
+ memcpy (impl->buffer + impl->buffer_offset, unprotected_bytes, available);
+ result = do_ssl_write (impl->ssl, impl->buffer, impl->buffer_size);
+ if (result != TSI_OK)
+ return result;
+
+ GPR_ASSERT (*protected_output_frames_size <= INT_MAX);
+ read_from_ssl = BIO_read (impl->from_ssl, protected_output_frames, (int) *protected_output_frames_size);
+ if (read_from_ssl < 0)
+ {
+ gpr_log (GPR_ERROR, "Could not read from BIO after SSL_write.");
+ return TSI_INTERNAL_ERROR;
+ }
+ *protected_output_frames_size = (size_t) read_from_ssl;
*unprotected_bytes_size = available;
impl->buffer_offset = 0;
return TSI_OK;
}
-static tsi_result ssl_protector_protect_flush(
- tsi_frame_protector* self, unsigned char* protected_output_frames,
- size_t* protected_output_frames_size, size_t* still_pending_size) {
+static tsi_result
+ssl_protector_protect_flush (tsi_frame_protector * self, unsigned char *protected_output_frames, size_t * protected_output_frames_size, size_t * still_pending_size)
+{
tsi_result result = TSI_OK;
- tsi_ssl_frame_protector* impl = (tsi_ssl_frame_protector*)self;
+ tsi_ssl_frame_protector *impl = (tsi_ssl_frame_protector *) self;
int read_from_ssl = 0;
int pending;
- if (impl->buffer_offset != 0) {
- result = do_ssl_write(impl->ssl, impl->buffer, impl->buffer_offset);
- if (result != TSI_OK) return result;
- impl->buffer_offset = 0;
- }
+ if (impl->buffer_offset != 0)
+ {
+ result = do_ssl_write (impl->ssl, impl->buffer, impl->buffer_offset);
+ if (result != TSI_OK)
+ return result;
+ impl->buffer_offset = 0;
+ }
- pending = BIO_pending(impl->from_ssl);
- GPR_ASSERT(pending >= 0);
- *still_pending_size = (size_t)pending;
- if (*still_pending_size == 0) return TSI_OK;
-
- GPR_ASSERT(*protected_output_frames_size <= INT_MAX);
- read_from_ssl = BIO_read(impl->from_ssl, protected_output_frames,
- (int)*protected_output_frames_size);
- if (read_from_ssl <= 0) {
- gpr_log(GPR_ERROR, "Could not read from BIO after SSL_write.");
- return TSI_INTERNAL_ERROR;
- }
- *protected_output_frames_size = (size_t)read_from_ssl;
- pending = BIO_pending(impl->from_ssl);
- GPR_ASSERT(pending >= 0);
- *still_pending_size = (size_t)pending;
+ pending = BIO_pending (impl->from_ssl);
+ GPR_ASSERT (pending >= 0);
+ *still_pending_size = (size_t) pending;
+ if (*still_pending_size == 0)
+ return TSI_OK;
+
+ GPR_ASSERT (*protected_output_frames_size <= INT_MAX);
+ read_from_ssl = BIO_read (impl->from_ssl, protected_output_frames, (int) *protected_output_frames_size);
+ if (read_from_ssl <= 0)
+ {
+ gpr_log (GPR_ERROR, "Could not read from BIO after SSL_write.");
+ return TSI_INTERNAL_ERROR;
+ }
+ *protected_output_frames_size = (size_t) read_from_ssl;
+ pending = BIO_pending (impl->from_ssl);
+ GPR_ASSERT (pending >= 0);
+ *still_pending_size = (size_t) pending;
return TSI_OK;
}
-static tsi_result ssl_protector_unprotect(
- tsi_frame_protector* self, const unsigned char* protected_frames_bytes,
- size_t* protected_frames_bytes_size, unsigned char* unprotected_bytes,
- size_t* unprotected_bytes_size) {
+static tsi_result
+ssl_protector_unprotect (tsi_frame_protector * self, const unsigned char *protected_frames_bytes, size_t * protected_frames_bytes_size, unsigned char *unprotected_bytes, size_t * unprotected_bytes_size)
+{
tsi_result result = TSI_OK;
int written_into_ssl = 0;
size_t output_bytes_size = *unprotected_bytes_size;
size_t output_bytes_offset = 0;
- tsi_ssl_frame_protector* impl = (tsi_ssl_frame_protector*)self;
+ tsi_ssl_frame_protector *impl = (tsi_ssl_frame_protector *) self;
/* First, try to read remaining data from ssl. */
- result = do_ssl_read(impl->ssl, unprotected_bytes, unprotected_bytes_size);
- if (result != TSI_OK) return result;
- if (*unprotected_bytes_size == output_bytes_size) {
- /* We have read everything we could and cannot process any more input. */
- *protected_frames_bytes_size = 0;
- return TSI_OK;
- }
+ result = do_ssl_read (impl->ssl, unprotected_bytes, unprotected_bytes_size);
+ if (result != TSI_OK)
+ return result;
+ if (*unprotected_bytes_size == output_bytes_size)
+ {
+ /* We have read everything we could and cannot process any more input. */
+ *protected_frames_bytes_size = 0;
+ return TSI_OK;
+ }
output_bytes_offset = *unprotected_bytes_size;
unprotected_bytes += output_bytes_offset;
*unprotected_bytes_size = output_bytes_size - output_bytes_offset;
/* Then, try to write some data to ssl. */
- GPR_ASSERT(*protected_frames_bytes_size <= INT_MAX);
- written_into_ssl = BIO_write(impl->into_ssl, protected_frames_bytes,
- (int)*protected_frames_bytes_size);
- if (written_into_ssl < 0) {
- gpr_log(GPR_ERROR, "Sending protected frame to ssl failed with %d",
- written_into_ssl);
- return TSI_INTERNAL_ERROR;
- }
- *protected_frames_bytes_size = (size_t)written_into_ssl;
+ GPR_ASSERT (*protected_frames_bytes_size <= INT_MAX);
+ written_into_ssl = BIO_write (impl->into_ssl, protected_frames_bytes, (int) *protected_frames_bytes_size);
+ if (written_into_ssl < 0)
+ {
+ gpr_log (GPR_ERROR, "Sending protected frame to ssl failed with %d", written_into_ssl);
+ return TSI_INTERNAL_ERROR;
+ }
+ *protected_frames_bytes_size = (size_t) written_into_ssl;
/* Now try to read some data again. */
- result = do_ssl_read(impl->ssl, unprotected_bytes, unprotected_bytes_size);
- if (result == TSI_OK) {
- /* Don't forget to output the total number of bytes read. */
- *unprotected_bytes_size += output_bytes_offset;
- }
+ result = do_ssl_read (impl->ssl, unprotected_bytes, unprotected_bytes_size);
+ if (result == TSI_OK)
+ {
+ /* Don't forget to output the total number of bytes read. */
+ *unprotected_bytes_size += output_bytes_offset;
+ }
return result;
}
-static void ssl_protector_destroy(tsi_frame_protector* self) {
- tsi_ssl_frame_protector* impl = (tsi_ssl_frame_protector*)self;
- if (impl->buffer != NULL) free(impl->buffer);
- if (impl->ssl != NULL) SSL_free(impl->ssl);
- free(self);
+static void
+ssl_protector_destroy (tsi_frame_protector * self)
+{
+ tsi_ssl_frame_protector *impl = (tsi_ssl_frame_protector *) self;
+ if (impl->buffer != NULL)
+ free (impl->buffer);
+ if (impl->ssl != NULL)
+ SSL_free (impl->ssl);
+ free (self);
}
static const tsi_frame_protector_vtable frame_protector_vtable = {
- ssl_protector_protect, ssl_protector_protect_flush, ssl_protector_unprotect,
- ssl_protector_destroy,
+ ssl_protector_protect, ssl_protector_protect_flush, ssl_protector_unprotect,
+ ssl_protector_destroy,
};
/* --- tsi_handshaker methods implementation. ---*/
-static tsi_result ssl_handshaker_get_bytes_to_send_to_peer(tsi_handshaker* self,
- unsigned char* bytes,
- size_t* bytes_size) {
- tsi_ssl_handshaker* impl = (tsi_ssl_handshaker*)self;
+static tsi_result
+ssl_handshaker_get_bytes_to_send_to_peer (tsi_handshaker * self, unsigned char *bytes, size_t * bytes_size)
+{
+ tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *) self;
int bytes_read_from_ssl = 0;
- if (bytes == NULL || bytes_size == NULL || *bytes_size == 0 ||
- *bytes_size > INT_MAX) {
- return TSI_INVALID_ARGUMENT;
- }
- GPR_ASSERT(*bytes_size <= INT_MAX);
- bytes_read_from_ssl = BIO_read(impl->from_ssl, bytes, (int)*bytes_size);
- if (bytes_read_from_ssl < 0) {
- *bytes_size = 0;
- if (!BIO_should_retry(impl->from_ssl)) {
- impl->result = TSI_INTERNAL_ERROR;
- return impl->result;
- } else {
- return TSI_OK;
+ if (bytes == NULL || bytes_size == NULL || *bytes_size == 0 || *bytes_size > INT_MAX)
+ {
+ return TSI_INVALID_ARGUMENT;
}
- }
- *bytes_size = (size_t)bytes_read_from_ssl;
- return BIO_pending(impl->from_ssl) == 0 ? TSI_OK : TSI_INCOMPLETE_DATA;
+ GPR_ASSERT (*bytes_size <= INT_MAX);
+ bytes_read_from_ssl = BIO_read (impl->from_ssl, bytes, (int) *bytes_size);
+ if (bytes_read_from_ssl < 0)
+ {
+ *bytes_size = 0;
+ if (!BIO_should_retry (impl->from_ssl))
+ {
+ impl->result = TSI_INTERNAL_ERROR;
+ return impl->result;
+ }
+ else
+ {
+ return TSI_OK;
+ }
+ }
+ *bytes_size = (size_t) bytes_read_from_ssl;
+ return BIO_pending (impl->from_ssl) == 0 ? TSI_OK : TSI_INCOMPLETE_DATA;
}
-static tsi_result ssl_handshaker_get_result(tsi_handshaker* self) {
- tsi_ssl_handshaker* impl = (tsi_ssl_handshaker*)self;
- if ((impl->result == TSI_HANDSHAKE_IN_PROGRESS) &&
- SSL_is_init_finished(impl->ssl)) {
- impl->result = TSI_OK;
- }
+static tsi_result
+ssl_handshaker_get_result (tsi_handshaker * self)
+{
+ tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *) self;
+ if ((impl->result == TSI_HANDSHAKE_IN_PROGRESS) && SSL_is_init_finished (impl->ssl))
+ {
+ impl->result = TSI_OK;
+ }
return impl->result;
}
-static tsi_result ssl_handshaker_process_bytes_from_peer(
- tsi_handshaker* self, const unsigned char* bytes, size_t* bytes_size) {
- tsi_ssl_handshaker* impl = (tsi_ssl_handshaker*)self;
+static tsi_result
+ssl_handshaker_process_bytes_from_peer (tsi_handshaker * self, const unsigned char *bytes, size_t * bytes_size)
+{
+ tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *) self;
int bytes_written_into_ssl_size = 0;
- if (bytes == NULL || bytes_size == 0 || *bytes_size > INT_MAX) {
- return TSI_INVALID_ARGUMENT;
- }
- GPR_ASSERT(*bytes_size <= INT_MAX);
- bytes_written_into_ssl_size =
- BIO_write(impl->into_ssl, bytes, (int)*bytes_size);
- if (bytes_written_into_ssl_size < 0) {
- gpr_log(GPR_ERROR, "Could not write to memory BIO.");
- impl->result = TSI_INTERNAL_ERROR;
- return impl->result;
- }
- *bytes_size = (size_t)bytes_written_into_ssl_size;
-
- if (!tsi_handshaker_is_in_progress(self)) {
- impl->result = TSI_OK;
- return impl->result;
- } else {
- /* Get ready to get some bytes from SSL. */
- int ssl_result = SSL_do_handshake(impl->ssl);
- ssl_result = SSL_get_error(impl->ssl, ssl_result);
- switch (ssl_result) {
- case SSL_ERROR_WANT_READ:
- if (BIO_pending(impl->from_ssl) == 0) {
- /* We need more data. */
- return TSI_INCOMPLETE_DATA;
- } else {
- return TSI_OK;
- }
- case SSL_ERROR_NONE:
- return TSI_OK;
- default: {
- char err_str[256];
- ERR_error_string_n(ERR_get_error(), err_str, sizeof(err_str));
- gpr_log(GPR_ERROR, "Handshake failed with fatal error %s: %s.",
- ssl_error_string(ssl_result), err_str);
- impl->result = TSI_PROTOCOL_FAILURE;
- return impl->result;
- }
+ if (bytes == NULL || bytes_size == 0 || *bytes_size > INT_MAX)
+ {
+ return TSI_INVALID_ARGUMENT;
+ }
+ GPR_ASSERT (*bytes_size <= INT_MAX);
+ bytes_written_into_ssl_size = BIO_write (impl->into_ssl, bytes, (int) *bytes_size);
+ if (bytes_written_into_ssl_size < 0)
+ {
+ gpr_log (GPR_ERROR, "Could not write to memory BIO.");
+ impl->result = TSI_INTERNAL_ERROR;
+ return impl->result;
+ }
+ *bytes_size = (size_t) bytes_written_into_ssl_size;
+
+ if (!tsi_handshaker_is_in_progress (self))
+ {
+ impl->result = TSI_OK;
+ return impl->result;
+ }
+ else
+ {
+ /* Get ready to get some bytes from SSL. */
+ int ssl_result = SSL_do_handshake (impl->ssl);
+ ssl_result = SSL_get_error (impl->ssl, ssl_result);
+ switch (ssl_result)
+ {
+ case SSL_ERROR_WANT_READ:
+ if (BIO_pending (impl->from_ssl) == 0)
+ {
+ /* We need more data. */
+ return TSI_INCOMPLETE_DATA;
+ }
+ else
+ {
+ return TSI_OK;
+ }
+ case SSL_ERROR_NONE:
+ return TSI_OK;
+ default:
+ {
+ char err_str[256];
+ ERR_error_string_n (ERR_get_error (), err_str, sizeof (err_str));
+ gpr_log (GPR_ERROR, "Handshake failed with fatal error %s: %s.", ssl_error_string (ssl_result), err_str);
+ impl->result = TSI_PROTOCOL_FAILURE;
+ return impl->result;
+ }
+ }
}
- }
}
-static tsi_result ssl_handshaker_extract_peer(tsi_handshaker* self,
- tsi_peer* peer) {
+static tsi_result
+ssl_handshaker_extract_peer (tsi_handshaker * self, tsi_peer * peer)
+{
tsi_result result = TSI_OK;
- const unsigned char* alpn_selected = NULL;
+ const unsigned char *alpn_selected = NULL;
unsigned int alpn_selected_len;
- tsi_ssl_handshaker* impl = (tsi_ssl_handshaker*)self;
- X509* peer_cert = SSL_get_peer_certificate(impl->ssl);
- if (peer_cert != NULL) {
- result = peer_from_x509(peer_cert, 1, peer);
- X509_free(peer_cert);
- if (result != TSI_OK) return result;
- }
+ tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *) self;
+ X509 *peer_cert = SSL_get_peer_certificate (impl->ssl);
+ if (peer_cert != NULL)
+ {
+ result = peer_from_x509 (peer_cert, 1, peer);
+ X509_free (peer_cert);
+ if (result != TSI_OK)
+ return result;
+ }
#if TSI_OPENSSL_ALPN_SUPPORT
- SSL_get0_alpn_selected(impl->ssl, &alpn_selected, &alpn_selected_len);
+ SSL_get0_alpn_selected (impl->ssl, &alpn_selected, &alpn_selected_len);
#endif /* TSI_OPENSSL_ALPN_SUPPORT */
- if (alpn_selected == NULL) {
- /* Try npn. */
- SSL_get0_next_proto_negotiated(impl->ssl, &alpn_selected,
- &alpn_selected_len);
- }
- if (alpn_selected != NULL) {
- size_t i;
- tsi_peer_property* new_properties =
- calloc(1, sizeof(tsi_peer_property) * (peer->property_count + 1));
- if (new_properties == NULL) return TSI_OUT_OF_RESOURCES;
- for (i = 0; i < peer->property_count; i++) {
- new_properties[i] = peer->properties[i];
- }
- result = tsi_construct_string_peer_property(
- TSI_SSL_ALPN_SELECTED_PROTOCOL, (const char*)alpn_selected,
- alpn_selected_len, &new_properties[peer->property_count]);
- if (result != TSI_OK) {
- free(new_properties);
- return result;
+ if (alpn_selected == NULL)
+ {
+ /* Try npn. */
+ SSL_get0_next_proto_negotiated (impl->ssl, &alpn_selected, &alpn_selected_len);
+ }
+ if (alpn_selected != NULL)
+ {
+ size_t i;
+ tsi_peer_property *new_properties = calloc (1, sizeof (tsi_peer_property) * (peer->property_count + 1));
+ if (new_properties == NULL)
+ return TSI_OUT_OF_RESOURCES;
+ for (i = 0; i < peer->property_count; i++)
+ {
+ new_properties[i] = peer->properties[i];
+ }
+ result = tsi_construct_string_peer_property (TSI_SSL_ALPN_SELECTED_PROTOCOL, (const char *) alpn_selected, alpn_selected_len, &new_properties[peer->property_count]);
+ if (result != TSI_OK)
+ {
+ free (new_properties);
+ return result;
+ }
+ if (peer->properties != NULL)
+ free (peer->properties);
+ peer->property_count++;
+ peer->properties = new_properties;
}
- if (peer->properties != NULL) free(peer->properties);
- peer->property_count++;
- peer->properties = new_properties;
- }
return result;
}
-static tsi_result ssl_handshaker_create_frame_protector(
- tsi_handshaker* self, size_t* max_output_protected_frame_size,
- tsi_frame_protector** protector) {
- size_t actual_max_output_protected_frame_size =
- TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND;
- tsi_ssl_handshaker* impl = (tsi_ssl_handshaker*)self;
- tsi_ssl_frame_protector* protector_impl =
- calloc(1, sizeof(tsi_ssl_frame_protector));
- if (protector_impl == NULL) {
- return TSI_OUT_OF_RESOURCES;
- }
+static tsi_result
+ssl_handshaker_create_frame_protector (tsi_handshaker * self, size_t * max_output_protected_frame_size, tsi_frame_protector ** protector)
+{
+ size_t actual_max_output_protected_frame_size = TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND;
+ tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *) self;
+ tsi_ssl_frame_protector *protector_impl = calloc (1, sizeof (tsi_ssl_frame_protector));
+ if (protector_impl == NULL)
+ {
+ return TSI_OUT_OF_RESOURCES;
+ }
- if (max_output_protected_frame_size != NULL) {
- if (*max_output_protected_frame_size >
- TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND) {
- *max_output_protected_frame_size =
- TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND;
- } else if (*max_output_protected_frame_size <
- TSI_SSL_MAX_PROTECTED_FRAME_SIZE_LOWER_BOUND) {
- *max_output_protected_frame_size =
- TSI_SSL_MAX_PROTECTED_FRAME_SIZE_LOWER_BOUND;
- }
- actual_max_output_protected_frame_size = *max_output_protected_frame_size;
- }
- protector_impl->buffer_size =
- actual_max_output_protected_frame_size - TSI_SSL_MAX_PROTECTION_OVERHEAD;
- protector_impl->buffer = malloc(protector_impl->buffer_size);
- if (protector_impl->buffer == NULL) {
- gpr_log(GPR_ERROR,
- "Could not allocated buffer for tsi_ssl_frame_protector.");
- free(protector_impl);
- return TSI_INTERNAL_ERROR;
- }
+ if (max_output_protected_frame_size != NULL)
+ {
+ if (*max_output_protected_frame_size > TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND)
+ {
+ *max_output_protected_frame_size = TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND;
+ }
+ else if (*max_output_protected_frame_size < TSI_SSL_MAX_PROTECTED_FRAME_SIZE_LOWER_BOUND)
+ {
+ *max_output_protected_frame_size = TSI_SSL_MAX_PROTECTED_FRAME_SIZE_LOWER_BOUND;
+ }
+ actual_max_output_protected_frame_size = *max_output_protected_frame_size;
+ }
+ protector_impl->buffer_size = actual_max_output_protected_frame_size - TSI_SSL_MAX_PROTECTION_OVERHEAD;
+ protector_impl->buffer = malloc (protector_impl->buffer_size);
+ if (protector_impl->buffer == NULL)
+ {
+ gpr_log (GPR_ERROR, "Could not allocated buffer for tsi_ssl_frame_protector.");
+ free (protector_impl);
+ return TSI_INTERNAL_ERROR;
+ }
/* Transfer ownership of ssl to the frame protector. It is OK as the caller
* cannot call anything else but destroy on the handshaker after this call. */
@@ -968,91 +1078,106 @@ static tsi_result ssl_handshaker_create_frame_protector(
return TSI_OK;
}
-static void ssl_handshaker_destroy(tsi_handshaker* self) {
- tsi_ssl_handshaker* impl = (tsi_ssl_handshaker*)self;
- SSL_free(impl->ssl); /* The BIO objects are owned by ssl */
- free(impl);
+static void
+ssl_handshaker_destroy (tsi_handshaker * self)
+{
+ tsi_ssl_handshaker *impl = (tsi_ssl_handshaker *) self;
+ SSL_free (impl->ssl); /* The BIO objects are owned by ssl */
+ free (impl);
}
static const tsi_handshaker_vtable handshaker_vtable = {
- ssl_handshaker_get_bytes_to_send_to_peer,
- ssl_handshaker_process_bytes_from_peer,
- ssl_handshaker_get_result,
- ssl_handshaker_extract_peer,
- ssl_handshaker_create_frame_protector,
- ssl_handshaker_destroy,
+ ssl_handshaker_get_bytes_to_send_to_peer,
+ ssl_handshaker_process_bytes_from_peer,
+ ssl_handshaker_get_result,
+ ssl_handshaker_extract_peer,
+ ssl_handshaker_create_frame_protector,
+ ssl_handshaker_destroy,
};
/* --- tsi_ssl_handshaker_factory common methods. --- */
-tsi_result tsi_ssl_handshaker_factory_create_handshaker(
- tsi_ssl_handshaker_factory* self, const char* server_name_indication,
- tsi_handshaker** handshaker) {
- if (self == NULL || handshaker == NULL) return TSI_INVALID_ARGUMENT;
- return self->create_handshaker(self, server_name_indication, handshaker);
+tsi_result
+tsi_ssl_handshaker_factory_create_handshaker (tsi_ssl_handshaker_factory * self, const char *server_name_indication, tsi_handshaker ** handshaker)
+{
+ if (self == NULL || handshaker == NULL)
+ return TSI_INVALID_ARGUMENT;
+ return self->create_handshaker (self, server_name_indication, handshaker);
}
-void tsi_ssl_handshaker_factory_destroy(tsi_ssl_handshaker_factory* self) {
- if (self == NULL) return;
- self->destroy(self);
+void
+tsi_ssl_handshaker_factory_destroy (tsi_ssl_handshaker_factory * self)
+{
+ if (self == NULL)
+ return;
+ self->destroy (self);
}
-static tsi_result create_tsi_ssl_handshaker(SSL_CTX* ctx, int is_client,
- const char* server_name_indication,
- tsi_handshaker** handshaker) {
- SSL* ssl = SSL_new(ctx);
- BIO* into_ssl = NULL;
- BIO* from_ssl = NULL;
- tsi_ssl_handshaker* impl = NULL;
+static tsi_result
+create_tsi_ssl_handshaker (SSL_CTX * ctx, int is_client, const char *server_name_indication, tsi_handshaker ** handshaker)
+{
+ SSL *ssl = SSL_new (ctx);
+ BIO *into_ssl = NULL;
+ BIO *from_ssl = NULL;
+ tsi_ssl_handshaker *impl = NULL;
*handshaker = NULL;
- if (ctx == NULL) {
- gpr_log(GPR_ERROR, "SSL Context is null. Should never happen.");
- return TSI_INTERNAL_ERROR;
- }
- if (ssl == NULL) {
- return TSI_OUT_OF_RESOURCES;
- }
- SSL_set_info_callback(ssl, ssl_info_callback);
-
- into_ssl = BIO_new(BIO_s_mem());
- from_ssl = BIO_new(BIO_s_mem());
- if (into_ssl == NULL || from_ssl == NULL) {
- gpr_log(GPR_ERROR, "BIO_new failed.");
- SSL_free(ssl);
- if (into_ssl != NULL) BIO_free(into_ssl);
- if (from_ssl != NULL) BIO_free(into_ssl);
- return TSI_OUT_OF_RESOURCES;
- }
- SSL_set_bio(ssl, into_ssl, from_ssl);
- if (is_client) {
- int ssl_result;
- SSL_set_connect_state(ssl);
- if (server_name_indication != NULL) {
- if (!SSL_set_tlsext_host_name(ssl, server_name_indication)) {
- gpr_log(GPR_ERROR, "Invalid server name indication %s.",
- server_name_indication);
- SSL_free(ssl);
- return TSI_INTERNAL_ERROR;
- }
- }
- ssl_result = SSL_do_handshake(ssl);
- ssl_result = SSL_get_error(ssl, ssl_result);
- if (ssl_result != SSL_ERROR_WANT_READ) {
- gpr_log(GPR_ERROR,
- "Unexpected error received from first SSL_do_handshake call: %s",
- ssl_error_string(ssl_result));
- SSL_free(ssl);
+ if (ctx == NULL)
+ {
+ gpr_log (GPR_ERROR, "SSL Context is null. Should never happen.");
return TSI_INTERNAL_ERROR;
}
- } else {
- SSL_set_accept_state(ssl);
- }
+ if (ssl == NULL)
+ {
+ return TSI_OUT_OF_RESOURCES;
+ }
+ SSL_set_info_callback (ssl, ssl_info_callback);
+
+ into_ssl = BIO_new (BIO_s_mem ());
+ from_ssl = BIO_new (BIO_s_mem ());
+ if (into_ssl == NULL || from_ssl == NULL)
+ {
+ gpr_log (GPR_ERROR, "BIO_new failed.");
+ SSL_free (ssl);
+ if (into_ssl != NULL)
+ BIO_free (into_ssl);
+ if (from_ssl != NULL)
+ BIO_free (into_ssl);
+ return TSI_OUT_OF_RESOURCES;
+ }
+ SSL_set_bio (ssl, into_ssl, from_ssl);
+ if (is_client)
+ {
+ int ssl_result;
+ SSL_set_connect_state (ssl);
+ if (server_name_indication != NULL)
+ {
+ if (!SSL_set_tlsext_host_name (ssl, server_name_indication))
+ {
+ gpr_log (GPR_ERROR, "Invalid server name indication %s.", server_name_indication);
+ SSL_free (ssl);
+ return TSI_INTERNAL_ERROR;
+ }
+ }
+ ssl_result = SSL_do_handshake (ssl);
+ ssl_result = SSL_get_error (ssl, ssl_result);
+ if (ssl_result != SSL_ERROR_WANT_READ)
+ {
+ gpr_log (GPR_ERROR, "Unexpected error received from first SSL_do_handshake call: %s", ssl_error_string (ssl_result));
+ SSL_free (ssl);
+ return TSI_INTERNAL_ERROR;
+ }
+ }
+ else
+ {
+ SSL_set_accept_state (ssl);
+ }
- impl = calloc(1, sizeof(tsi_ssl_handshaker));
- if (impl == NULL) {
- SSL_free(ssl);
- return TSI_OUT_OF_RESOURCES;
- }
+ impl = calloc (1, sizeof (tsi_ssl_handshaker));
+ if (impl == NULL)
+ {
+ SSL_free (ssl);
+ return TSI_OUT_OF_RESOURCES;
+ }
impl->ssl = ssl;
impl->into_ssl = into_ssl;
impl->from_ssl = from_ssl;
@@ -1062,407 +1187,412 @@ static tsi_result create_tsi_ssl_handshaker(SSL_CTX* ctx, int is_client,
return TSI_OK;
}
-static int select_protocol_list(const unsigned char** out,
- unsigned char* outlen,
- const unsigned char* client_list,
- size_t client_list_len,
- const unsigned char* server_list,
- size_t server_list_len) {
- const unsigned char* client_current = client_list;
- while ((unsigned int)(client_current - client_list) < client_list_len) {
- unsigned char client_current_len = *(client_current++);
- const unsigned char* server_current = server_list;
- while ((server_current >= server_list) &&
- (gpr_uintptr)(server_current - server_list) < server_list_len) {
- unsigned char server_current_len = *(server_current++);
- if ((client_current_len == server_current_len) &&
- !memcmp(client_current, server_current, server_current_len)) {
- *out = server_current;
- *outlen = server_current_len;
- return SSL_TLSEXT_ERR_OK;
- }
- server_current += server_current_len;
+static int
+select_protocol_list (const unsigned char **out, unsigned char *outlen, const unsigned char *client_list, size_t client_list_len, const unsigned char *server_list, size_t server_list_len)
+{
+ const unsigned char *client_current = client_list;
+ while ((unsigned int) (client_current - client_list) < client_list_len)
+ {
+ unsigned char client_current_len = *(client_current++);
+ const unsigned char *server_current = server_list;
+ while ((server_current >= server_list) && (gpr_uintptr) (server_current - server_list) < server_list_len)
+ {
+ unsigned char server_current_len = *(server_current++);
+ if ((client_current_len == server_current_len) && !memcmp (client_current, server_current, server_current_len))
+ {
+ *out = server_current;
+ *outlen = server_current_len;
+ return SSL_TLSEXT_ERR_OK;
+ }
+ server_current += server_current_len;
+ }
+ client_current += client_current_len;
}
- client_current += client_current_len;
- }
return SSL_TLSEXT_ERR_NOACK;
}
/* --- tsi_ssl__client_handshaker_factory methods implementation. --- */
-static tsi_result ssl_client_handshaker_factory_create_handshaker(
- tsi_ssl_handshaker_factory* self, const char* server_name_indication,
- tsi_handshaker** handshaker) {
- tsi_ssl_client_handshaker_factory* impl =
- (tsi_ssl_client_handshaker_factory*)self;
- return create_tsi_ssl_handshaker(impl->ssl_context, 1, server_name_indication,
- handshaker);
+static tsi_result
+ssl_client_handshaker_factory_create_handshaker (tsi_ssl_handshaker_factory * self, const char *server_name_indication, tsi_handshaker ** handshaker)
+{
+ tsi_ssl_client_handshaker_factory *impl = (tsi_ssl_client_handshaker_factory *) self;
+ return create_tsi_ssl_handshaker (impl->ssl_context, 1, server_name_indication, handshaker);
}
-static void ssl_client_handshaker_factory_destroy(
- tsi_ssl_handshaker_factory* self) {
- tsi_ssl_client_handshaker_factory* impl =
- (tsi_ssl_client_handshaker_factory*)self;
- if (impl->ssl_context != NULL) SSL_CTX_free(impl->ssl_context);
- if (impl->alpn_protocol_list != NULL) free(impl->alpn_protocol_list);
- free(impl);
+static void
+ssl_client_handshaker_factory_destroy (tsi_ssl_handshaker_factory * self)
+{
+ tsi_ssl_client_handshaker_factory *impl = (tsi_ssl_client_handshaker_factory *) self;
+ if (impl->ssl_context != NULL)
+ SSL_CTX_free (impl->ssl_context);
+ if (impl->alpn_protocol_list != NULL)
+ free (impl->alpn_protocol_list);
+ free (impl);
}
-static int client_handshaker_factory_npn_callback(SSL* ssl, unsigned char** out,
- unsigned char* outlen,
- const unsigned char* in,
- unsigned int inlen,
- void* arg) {
- tsi_ssl_client_handshaker_factory* factory =
- (tsi_ssl_client_handshaker_factory*)arg;
- return select_protocol_list((const unsigned char**)out, outlen,
- factory->alpn_protocol_list,
- factory->alpn_protocol_list_length, in, inlen);
+static int
+client_handshaker_factory_npn_callback (SSL * ssl, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
+{
+ tsi_ssl_client_handshaker_factory *factory = (tsi_ssl_client_handshaker_factory *) arg;
+ return select_protocol_list ((const unsigned char **) out, outlen, factory->alpn_protocol_list, factory->alpn_protocol_list_length, in, inlen);
}
/* --- tsi_ssl_server_handshaker_factory methods implementation. --- */
-static tsi_result ssl_server_handshaker_factory_create_handshaker(
- tsi_ssl_handshaker_factory* self, const char* server_name_indication,
- tsi_handshaker** handshaker) {
- tsi_ssl_server_handshaker_factory* impl =
- (tsi_ssl_server_handshaker_factory*)self;
- if (impl->ssl_context_count == 0 || server_name_indication != NULL) {
- return TSI_INVALID_ARGUMENT;
- }
+static tsi_result
+ssl_server_handshaker_factory_create_handshaker (tsi_ssl_handshaker_factory * self, const char *server_name_indication, tsi_handshaker ** handshaker)
+{
+ tsi_ssl_server_handshaker_factory *impl = (tsi_ssl_server_handshaker_factory *) self;
+ if (impl->ssl_context_count == 0 || server_name_indication != NULL)
+ {
+ return TSI_INVALID_ARGUMENT;
+ }
/* Create the handshaker with the first context. We will switch if needed
because of SNI in ssl_server_handshaker_factory_servername_callback. */
- return create_tsi_ssl_handshaker(impl->ssl_contexts[0], 0, NULL, handshaker);
+ return create_tsi_ssl_handshaker (impl->ssl_contexts[0], 0, NULL, handshaker);
}
-static void ssl_server_handshaker_factory_destroy(
- tsi_ssl_handshaker_factory* self) {
- tsi_ssl_server_handshaker_factory* impl =
- (tsi_ssl_server_handshaker_factory*)self;
+static void
+ssl_server_handshaker_factory_destroy (tsi_ssl_handshaker_factory * self)
+{
+ tsi_ssl_server_handshaker_factory *impl = (tsi_ssl_server_handshaker_factory *) self;
size_t i;
- for (i = 0; i < impl->ssl_context_count; i++) {
- if (impl->ssl_contexts[i] != NULL) {
- SSL_CTX_free(impl->ssl_contexts[i]);
- tsi_peer_destruct(&impl->ssl_context_x509_subject_names[i]);
+ for (i = 0; i < impl->ssl_context_count; i++)
+ {
+ if (impl->ssl_contexts[i] != NULL)
+ {
+ SSL_CTX_free (impl->ssl_contexts[i]);
+ tsi_peer_destruct (&impl->ssl_context_x509_subject_names[i]);
+ }
}
- }
- if (impl->ssl_contexts != NULL) free(impl->ssl_contexts);
- if (impl->ssl_context_x509_subject_names != NULL) {
- free(impl->ssl_context_x509_subject_names);
- }
- if (impl->alpn_protocol_list != NULL) free(impl->alpn_protocol_list);
- free(impl);
+ if (impl->ssl_contexts != NULL)
+ free (impl->ssl_contexts);
+ if (impl->ssl_context_x509_subject_names != NULL)
+ {
+ free (impl->ssl_context_x509_subject_names);
+ }
+ if (impl->alpn_protocol_list != NULL)
+ free (impl->alpn_protocol_list);
+ free (impl);
}
-static int does_entry_match_name(const char* entry, size_t entry_length,
- const char* name) {
- const char* dot;
- const char* name_subdomain = NULL;
- size_t name_length = strlen(name);
+static int
+does_entry_match_name (const char *entry, size_t entry_length, const char *name)
+{
+ const char *dot;
+ const char *name_subdomain = NULL;
+ size_t name_length = strlen (name);
size_t name_subdomain_length;
- if (entry_length == 0) return 0;
+ if (entry_length == 0)
+ return 0;
/* Take care of '.' terminations. */
- if (name[name_length - 1] == '.') {
- name_length--;
- }
- if (entry[entry_length - 1] == '.') {
- entry_length--;
- if (entry_length == 0) return 0;
- }
+ if (name[name_length - 1] == '.')
+ {
+ name_length--;
+ }
+ if (entry[entry_length - 1] == '.')
+ {
+ entry_length--;
+ if (entry_length == 0)
+ return 0;
+ }
- if ((name_length == entry_length) &&
- strncmp(name, entry, entry_length) == 0) {
- return 1; /* Perfect match. */
- }
- if (entry[0] != '*') return 0;
+ if ((name_length == entry_length) && strncmp (name, entry, entry_length) == 0)
+ {
+ return 1; /* Perfect match. */
+ }
+ if (entry[0] != '*')
+ return 0;
/* Wildchar subdomain matching. */
- if (entry_length < 3 || entry[1] != '.') { /* At least *.x */
- gpr_log(GPR_ERROR, "Invalid wildchar entry.");
+ if (entry_length < 3 || entry[1] != '.')
+ { /* At least *.x */
+ gpr_log (GPR_ERROR, "Invalid wildchar entry.");
+ return 0;
+ }
+ name_subdomain = strchr (name, '.');
+ if (name_subdomain == NULL)
return 0;
- }
- name_subdomain = strchr(name, '.');
- if (name_subdomain == NULL) return 0;
- name_subdomain_length = strlen(name_subdomain);
- if (name_subdomain_length < 2) return 0;
- name_subdomain++; /* Starts after the dot. */
+ name_subdomain_length = strlen (name_subdomain);
+ if (name_subdomain_length < 2)
+ return 0;
+ name_subdomain++; /* Starts after the dot. */
name_subdomain_length--;
- entry += 2; /* Remove *. */
+ entry += 2; /* Remove *. */
entry_length -= 2;
- dot = strchr(name_subdomain, '.');
- if ((dot == NULL) || (dot == &name_subdomain[name_subdomain_length - 1])) {
- gpr_log(GPR_ERROR, "Invalid toplevel subdomain: %s", name_subdomain);
- return 0;
- }
- if (name_subdomain[name_subdomain_length - 1] == '.') {
- name_subdomain_length--;
- }
- return ((entry_length > 0) && (name_subdomain_length == entry_length) &&
- strncmp(entry, name_subdomain, entry_length) == 0);
+ dot = strchr (name_subdomain, '.');
+ if ((dot == NULL) || (dot == &name_subdomain[name_subdomain_length - 1]))
+ {
+ gpr_log (GPR_ERROR, "Invalid toplevel subdomain: %s", name_subdomain);
+ return 0;
+ }
+ if (name_subdomain[name_subdomain_length - 1] == '.')
+ {
+ name_subdomain_length--;
+ }
+ return ((entry_length > 0) && (name_subdomain_length == entry_length) && strncmp (entry, name_subdomain, entry_length) == 0);
}
-static int ssl_server_handshaker_factory_servername_callback(SSL* ssl, int* ap,
- void* arg) {
- tsi_ssl_server_handshaker_factory* impl =
- (tsi_ssl_server_handshaker_factory*)arg;
+static int
+ssl_server_handshaker_factory_servername_callback (SSL * ssl, int *ap, void *arg)
+{
+ tsi_ssl_server_handshaker_factory *impl = (tsi_ssl_server_handshaker_factory *) arg;
size_t i = 0;
- const char* servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
- if (servername == NULL || strlen(servername) == 0) {
- return SSL_TLSEXT_ERR_NOACK;
- }
+ const char *servername = SSL_get_servername (ssl, TLSEXT_NAMETYPE_host_name);
+ if (servername == NULL || strlen (servername) == 0)
+ {
+ return SSL_TLSEXT_ERR_NOACK;
+ }
- for (i = 0; i < impl->ssl_context_count; i++) {
- if (tsi_ssl_peer_matches_name(&impl->ssl_context_x509_subject_names[i],
- servername)) {
- SSL_set_SSL_CTX(ssl, impl->ssl_contexts[i]);
- return SSL_TLSEXT_ERR_OK;
+ for (i = 0; i < impl->ssl_context_count; i++)
+ {
+ if (tsi_ssl_peer_matches_name (&impl->ssl_context_x509_subject_names[i], servername))
+ {
+ SSL_set_SSL_CTX (ssl, impl->ssl_contexts[i]);
+ return SSL_TLSEXT_ERR_OK;
+ }
}
- }
- gpr_log(GPR_ERROR, "No match found for server name: %s.", servername);
+ gpr_log (GPR_ERROR, "No match found for server name: %s.", servername);
return SSL_TLSEXT_ERR_ALERT_WARNING;
}
#if TSI_OPENSSL_ALPN_SUPPORT
-static int server_handshaker_factory_alpn_callback(
- SSL* ssl, const unsigned char** out, unsigned char* outlen,
- const unsigned char* in, unsigned int inlen, void* arg) {
- tsi_ssl_server_handshaker_factory* factory =
- (tsi_ssl_server_handshaker_factory*)arg;
- return select_protocol_list(out, outlen, in, inlen,
- factory->alpn_protocol_list,
- factory->alpn_protocol_list_length);
+static int
+server_handshaker_factory_alpn_callback (SSL * ssl, const unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
+{
+ tsi_ssl_server_handshaker_factory *factory = (tsi_ssl_server_handshaker_factory *) arg;
+ return select_protocol_list (out, outlen, in, inlen, factory->alpn_protocol_list, factory->alpn_protocol_list_length);
}
#endif /* TSI_OPENSSL_ALPN_SUPPORT */
-static int server_handshaker_factory_npn_advertised_callback(
- SSL* ssl, const unsigned char** out, unsigned int* outlen, void* arg) {
- tsi_ssl_server_handshaker_factory* factory =
- (tsi_ssl_server_handshaker_factory*)arg;
+static int
+server_handshaker_factory_npn_advertised_callback (SSL * ssl, const unsigned char **out, unsigned int *outlen, void *arg)
+{
+ tsi_ssl_server_handshaker_factory *factory = (tsi_ssl_server_handshaker_factory *) arg;
*out = factory->alpn_protocol_list;
- GPR_ASSERT(factory->alpn_protocol_list_length <= UINT_MAX);
- *outlen = (unsigned int)factory->alpn_protocol_list_length;
+ GPR_ASSERT (factory->alpn_protocol_list_length <= UINT_MAX);
+ *outlen = (unsigned int) factory->alpn_protocol_list_length;
return SSL_TLSEXT_ERR_OK;
}
/* --- tsi_ssl_handshaker_factory constructors. --- */
-tsi_result tsi_create_ssl_client_handshaker_factory(
- const unsigned char* pem_private_key, size_t pem_private_key_size,
- const unsigned char* pem_cert_chain, size_t pem_cert_chain_size,
- const unsigned char* pem_root_certs, size_t pem_root_certs_size,
- const char* cipher_list, const unsigned char** alpn_protocols,
- const unsigned char* alpn_protocols_lengths, uint16_t num_alpn_protocols,
- tsi_ssl_handshaker_factory** factory) {
- SSL_CTX* ssl_context = NULL;
- tsi_ssl_client_handshaker_factory* impl = NULL;
+tsi_result
+tsi_create_ssl_client_handshaker_factory (const unsigned char *pem_private_key, size_t pem_private_key_size, const unsigned char *pem_cert_chain, size_t pem_cert_chain_size, const unsigned char *pem_root_certs, size_t pem_root_certs_size, const char *cipher_list, const unsigned char **alpn_protocols, const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols, tsi_ssl_handshaker_factory ** factory)
+{
+ SSL_CTX *ssl_context = NULL;
+ tsi_ssl_client_handshaker_factory *impl = NULL;
tsi_result result = TSI_OK;
- gpr_once_init(&init_openssl_once, init_openssl);
+ gpr_once_init (&init_openssl_once, init_openssl);
- if (factory == NULL) return TSI_INVALID_ARGUMENT;
+ if (factory == NULL)
+ return TSI_INVALID_ARGUMENT;
*factory = NULL;
- if (pem_root_certs == NULL) return TSI_INVALID_ARGUMENT;
-
- ssl_context = SSL_CTX_new(TLSv1_2_method());
- if (ssl_context == NULL) {
- gpr_log(GPR_ERROR, "Could not create ssl context.");
+ if (pem_root_certs == NULL)
return TSI_INVALID_ARGUMENT;
- }
- impl = calloc(1, sizeof(tsi_ssl_client_handshaker_factory));
- if (impl == NULL) {
- SSL_CTX_free(ssl_context);
- return TSI_OUT_OF_RESOURCES;
- }
+ ssl_context = SSL_CTX_new (TLSv1_2_method ());
+ if (ssl_context == NULL)
+ {
+ gpr_log (GPR_ERROR, "Could not create ssl context.");
+ return TSI_INVALID_ARGUMENT;
+ }
+
+ impl = calloc (1, sizeof (tsi_ssl_client_handshaker_factory));
+ if (impl == NULL)
+ {
+ SSL_CTX_free (ssl_context);
+ return TSI_OUT_OF_RESOURCES;
+ }
impl->ssl_context = ssl_context;
- do {
- result =
- populate_ssl_context(ssl_context, pem_private_key, pem_private_key_size,
- pem_cert_chain, pem_cert_chain_size, cipher_list);
- if (result != TSI_OK) break;
- result = ssl_ctx_load_verification_certs(ssl_context, pem_root_certs,
- pem_root_certs_size, NULL);
- if (result != TSI_OK) {
- gpr_log(GPR_ERROR, "Cannot load server root certificates.");
- break;
- }
-
- if (num_alpn_protocols != 0) {
- result = build_alpn_protocol_name_list(
- alpn_protocols, alpn_protocols_lengths, num_alpn_protocols,
- &impl->alpn_protocol_list, &impl->alpn_protocol_list_length);
- if (result != TSI_OK) {
- gpr_log(GPR_ERROR, "Building alpn list failed with error %s.",
- tsi_result_to_string(result));
- break;
- }
+ do
+ {
+ result = populate_ssl_context (ssl_context, pem_private_key, pem_private_key_size, pem_cert_chain, pem_cert_chain_size, cipher_list);
+ if (result != TSI_OK)
+ break;
+ result = ssl_ctx_load_verification_certs (ssl_context, pem_root_certs, pem_root_certs_size, NULL);
+ if (result != TSI_OK)
+ {
+ gpr_log (GPR_ERROR, "Cannot load server root certificates.");
+ break;
+ }
+
+ if (num_alpn_protocols != 0)
+ {
+ result = build_alpn_protocol_name_list (alpn_protocols, alpn_protocols_lengths, num_alpn_protocols, &impl->alpn_protocol_list, &impl->alpn_protocol_list_length);
+ if (result != TSI_OK)
+ {
+ gpr_log (GPR_ERROR, "Building alpn list failed with error %s.", tsi_result_to_string (result));
+ break;
+ }
#if TSI_OPENSSL_ALPN_SUPPORT
- GPR_ASSERT(impl->alpn_protocol_list_length < UINT_MAX);
- if (SSL_CTX_set_alpn_protos(
- ssl_context, impl->alpn_protocol_list,
- (unsigned int)impl->alpn_protocol_list_length)) {
- gpr_log(GPR_ERROR, "Could not set alpn protocol list to context.");
- result = TSI_INVALID_ARGUMENT;
- break;
- }
+ GPR_ASSERT (impl->alpn_protocol_list_length < UINT_MAX);
+ if (SSL_CTX_set_alpn_protos (ssl_context, impl->alpn_protocol_list, (unsigned int) impl->alpn_protocol_list_length))
+ {
+ gpr_log (GPR_ERROR, "Could not set alpn protocol list to context.");
+ result = TSI_INVALID_ARGUMENT;
+ break;
+ }
#endif /* TSI_OPENSSL_ALPN_SUPPORT */
- SSL_CTX_set_next_proto_select_cb(
- ssl_context, client_handshaker_factory_npn_callback, impl);
+ SSL_CTX_set_next_proto_select_cb (ssl_context, client_handshaker_factory_npn_callback, impl);
+ }
}
- } while (0);
- if (result != TSI_OK) {
- ssl_client_handshaker_factory_destroy(&impl->base);
- return result;
- }
- SSL_CTX_set_verify(ssl_context, SSL_VERIFY_PEER, NULL);
+ while (0);
+ if (result != TSI_OK)
+ {
+ ssl_client_handshaker_factory_destroy (&impl->base);
+ return result;
+ }
+ SSL_CTX_set_verify (ssl_context, SSL_VERIFY_PEER, NULL);
/* TODO(jboeuf): Add revocation verification. */
- impl->base.create_handshaker =
- ssl_client_handshaker_factory_create_handshaker;
+ impl->base.create_handshaker = ssl_client_handshaker_factory_create_handshaker;
impl->base.destroy = ssl_client_handshaker_factory_destroy;
*factory = &impl->base;
return TSI_OK;
}
-tsi_result tsi_create_ssl_server_handshaker_factory(
- const unsigned char** pem_private_keys,
- const size_t* pem_private_keys_sizes, const unsigned char** pem_cert_chains,
- const size_t* pem_cert_chains_sizes, size_t key_cert_pair_count,
- const unsigned char* pem_client_root_certs,
- size_t pem_client_root_certs_size, int force_client_auth,
- const char* cipher_list, const unsigned char** alpn_protocols,
- const unsigned char* alpn_protocols_lengths, uint16_t num_alpn_protocols,
- tsi_ssl_handshaker_factory** factory) {
- tsi_ssl_server_handshaker_factory* impl = NULL;
+tsi_result
+tsi_create_ssl_server_handshaker_factory (const unsigned char **pem_private_keys, const size_t * pem_private_keys_sizes, const unsigned char **pem_cert_chains, const size_t * pem_cert_chains_sizes, size_t key_cert_pair_count, const unsigned char *pem_client_root_certs, size_t pem_client_root_certs_size, int force_client_auth, const char *cipher_list, const unsigned char **alpn_protocols, const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols, tsi_ssl_handshaker_factory ** factory)
+{
+ tsi_ssl_server_handshaker_factory *impl = NULL;
tsi_result result = TSI_OK;
size_t i = 0;
- gpr_once_init(&init_openssl_once, init_openssl);
+ gpr_once_init (&init_openssl_once, init_openssl);
- if (factory == NULL) return TSI_INVALID_ARGUMENT;
- *factory = NULL;
- if (key_cert_pair_count == 0 || pem_private_keys == NULL ||
- pem_cert_chains == NULL) {
+ if (factory == NULL)
return TSI_INVALID_ARGUMENT;
- }
+ *factory = NULL;
+ if (key_cert_pair_count == 0 || pem_private_keys == NULL || pem_cert_chains == NULL)
+ {
+ return TSI_INVALID_ARGUMENT;
+ }
- impl = calloc(1, sizeof(tsi_ssl_server_handshaker_factory));
- if (impl == NULL) return TSI_OUT_OF_RESOURCES;
- impl->base.create_handshaker =
- ssl_server_handshaker_factory_create_handshaker;
- impl->base.destroy = ssl_server_handshaker_factory_destroy;
- impl->ssl_contexts = calloc(key_cert_pair_count, sizeof(SSL_CTX*));
- impl->ssl_context_x509_subject_names =
- calloc(key_cert_pair_count, sizeof(tsi_peer));
- if (impl->ssl_contexts == NULL ||
- impl->ssl_context_x509_subject_names == NULL) {
- tsi_ssl_handshaker_factory_destroy(&impl->base);
+ impl = calloc (1, sizeof (tsi_ssl_server_handshaker_factory));
+ if (impl == NULL)
return TSI_OUT_OF_RESOURCES;
- }
+ impl->base.create_handshaker = ssl_server_handshaker_factory_create_handshaker;
+ impl->base.destroy = ssl_server_handshaker_factory_destroy;
+ impl->ssl_contexts = calloc (key_cert_pair_count, sizeof (SSL_CTX *));
+ impl->ssl_context_x509_subject_names = calloc (key_cert_pair_count, sizeof (tsi_peer));
+ if (impl->ssl_contexts == NULL || impl->ssl_context_x509_subject_names == NULL)
+ {
+ tsi_ssl_handshaker_factory_destroy (&impl->base);
+ return TSI_OUT_OF_RESOURCES;
+ }
impl->ssl_context_count = key_cert_pair_count;
- if (num_alpn_protocols > 0) {
- result = build_alpn_protocol_name_list(
- alpn_protocols, alpn_protocols_lengths, num_alpn_protocols,
- &impl->alpn_protocol_list, &impl->alpn_protocol_list_length);
- if (result != TSI_OK) {
- tsi_ssl_handshaker_factory_destroy(&impl->base);
- return result;
+ if (num_alpn_protocols > 0)
+ {
+ result = build_alpn_protocol_name_list (alpn_protocols, alpn_protocols_lengths, num_alpn_protocols, &impl->alpn_protocol_list, &impl->alpn_protocol_list_length);
+ if (result != TSI_OK)
+ {
+ tsi_ssl_handshaker_factory_destroy (&impl->base);
+ return result;
+ }
}
- }
-
- for (i = 0; i < key_cert_pair_count; i++) {
- do {
- impl->ssl_contexts[i] = SSL_CTX_new(TLSv1_2_method());
- if (impl->ssl_contexts[i] == NULL) {
- gpr_log(GPR_ERROR, "Could not create ssl context.");
- result = TSI_OUT_OF_RESOURCES;
- break;
- }
- result = populate_ssl_context(
- impl->ssl_contexts[i], pem_private_keys[i], pem_private_keys_sizes[i],
- pem_cert_chains[i], pem_cert_chains_sizes[i], cipher_list);
- if (result != TSI_OK) break;
-
- if (pem_client_root_certs != NULL) {
- int flags = SSL_VERIFY_PEER;
- STACK_OF(X509_NAME)* root_names = NULL;
- result = ssl_ctx_load_verification_certs(
- impl->ssl_contexts[i], pem_client_root_certs,
- pem_client_root_certs_size, &root_names);
- if (result != TSI_OK) {
- gpr_log(GPR_ERROR, "Invalid verification certs.");
- break;
- }
- SSL_CTX_set_client_CA_list(impl->ssl_contexts[i], root_names);
- if (force_client_auth) flags |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
- SSL_CTX_set_verify(impl->ssl_contexts[i], flags, NULL);
- /* TODO(jboeuf): Add revocation verification. */
- }
-
- result = extract_x509_subject_names_from_pem_cert(
- pem_cert_chains[i], pem_cert_chains_sizes[i],
- &impl->ssl_context_x509_subject_names[i]);
- if (result != TSI_OK) break;
- SSL_CTX_set_tlsext_servername_callback(
- impl->ssl_contexts[i],
- ssl_server_handshaker_factory_servername_callback);
- SSL_CTX_set_tlsext_servername_arg(impl->ssl_contexts[i], impl);
+ for (i = 0; i < key_cert_pair_count; i++)
+ {
+ do
+ {
+ impl->ssl_contexts[i] = SSL_CTX_new (TLSv1_2_method ());
+ if (impl->ssl_contexts[i] == NULL)
+ {
+ gpr_log (GPR_ERROR, "Could not create ssl context.");
+ result = TSI_OUT_OF_RESOURCES;
+ break;
+ }
+ result = populate_ssl_context (impl->ssl_contexts[i], pem_private_keys[i], pem_private_keys_sizes[i], pem_cert_chains[i], pem_cert_chains_sizes[i], cipher_list);
+ if (result != TSI_OK)
+ break;
+
+ if (pem_client_root_certs != NULL)
+ {
+ int flags = SSL_VERIFY_PEER;
+ STACK_OF (X509_NAME) * root_names = NULL;
+ result = ssl_ctx_load_verification_certs (impl->ssl_contexts[i], pem_client_root_certs, pem_client_root_certs_size, &root_names);
+ if (result != TSI_OK)
+ {
+ gpr_log (GPR_ERROR, "Invalid verification certs.");
+ break;
+ }
+ SSL_CTX_set_client_CA_list (impl->ssl_contexts[i], root_names);
+ if (force_client_auth)
+ flags |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
+ SSL_CTX_set_verify (impl->ssl_contexts[i], flags, NULL);
+ /* TODO(jboeuf): Add revocation verification. */
+ }
+
+ result = extract_x509_subject_names_from_pem_cert (pem_cert_chains[i], pem_cert_chains_sizes[i], &impl->ssl_context_x509_subject_names[i]);
+ if (result != TSI_OK)
+ break;
+
+ SSL_CTX_set_tlsext_servername_callback (impl->ssl_contexts[i], ssl_server_handshaker_factory_servername_callback);
+ SSL_CTX_set_tlsext_servername_arg (impl->ssl_contexts[i], impl);
#if TSI_OPENSSL_ALPN_SUPPORT
- SSL_CTX_set_alpn_select_cb(impl->ssl_contexts[i],
- server_handshaker_factory_alpn_callback, impl);
+ SSL_CTX_set_alpn_select_cb (impl->ssl_contexts[i], server_handshaker_factory_alpn_callback, impl);
#endif /* TSI_OPENSSL_ALPN_SUPPORT */
- SSL_CTX_set_next_protos_advertised_cb(
- impl->ssl_contexts[i],
- server_handshaker_factory_npn_advertised_callback, impl);
- } while (0);
-
- if (result != TSI_OK) {
- tsi_ssl_handshaker_factory_destroy(&impl->base);
- return result;
+ SSL_CTX_set_next_protos_advertised_cb (impl->ssl_contexts[i], server_handshaker_factory_npn_advertised_callback, impl);
+ }
+ while (0);
+
+ if (result != TSI_OK)
+ {
+ tsi_ssl_handshaker_factory_destroy (&impl->base);
+ return result;
+ }
}
- }
*factory = &impl->base;
return TSI_OK;
}
/* --- tsi_ssl utils. --- */
-int tsi_ssl_peer_matches_name(const tsi_peer* peer, const char* name) {
+int
+tsi_ssl_peer_matches_name (const tsi_peer * peer, const char *name)
+{
size_t i = 0;
size_t san_count = 0;
- const tsi_peer_property* cn_property = NULL;
+ const tsi_peer_property *cn_property = NULL;
/* For now reject what looks like an IP address. */
- if (looks_like_ip_address(name)) return 0;
+ if (looks_like_ip_address (name))
+ return 0;
/* Check the SAN first. */
- for (i = 0; i < peer->property_count; i++) {
- const tsi_peer_property* property = &peer->properties[i];
- if (property->name == NULL) continue;
- if (strcmp(property->name,
- TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) == 0) {
- san_count++;
- if (does_entry_match_name(property->value.data, property->value.length,
- name)) {
- return 1;
- }
- } else if (strcmp(property->name,
- TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY) == 0) {
- cn_property = property;
+ for (i = 0; i < peer->property_count; i++)
+ {
+ const tsi_peer_property *property = &peer->properties[i];
+ if (property->name == NULL)
+ continue;
+ if (strcmp (property->name, TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) == 0)
+ {
+ san_count++;
+ if (does_entry_match_name (property->value.data, property->value.length, name))
+ {
+ return 1;
+ }
+ }
+ else if (strcmp (property->name, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY) == 0)
+ {
+ cn_property = property;
+ }
}
- }
/* If there's no SAN, try the CN. */
- if (san_count == 0 && cn_property != NULL) {
- if (does_entry_match_name(cn_property->value.data,
- cn_property->value.length, name)) {
- return 1;
+ if (san_count == 0 && cn_property != NULL)
+ {
+ if (does_entry_match_name (cn_property->value.data, cn_property->value.length, name))
+ {
+ return 1;
+ }
}
- }
- return 0; /* Not found. */
+ return 0; /* Not found. */
}