aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/ext/lb_policy/pick_first/pick_first.c2
-rw-r--r--src/core/ext/transport/chttp2/transport/bin_encoder.c18
-rw-r--r--src/core/lib/http/parser.c13
-rw-r--r--src/core/lib/http/parser.h2
-rw-r--r--src/core/lib/iomgr/udp_server.c3
-rw-r--r--src/core/lib/security/credentials.c27
-rw-r--r--src/core/lib/security/security_connector.c34
-rw-r--r--src/core/lib/security/security_connector.h2
-rw-r--r--src/core/lib/support/log.c33
-rw-r--r--src/core/lib/surface/init.c4
-rw-r--r--src/core/lib/tsi/ssl_transport_security.c54
-rw-r--r--src/core/lib/tsi/ssl_transport_security.h17
-rw-r--r--src/core/lib/tsi/transport_security_interface.h9
13 files changed, 188 insertions, 30 deletions
diff --git a/src/core/ext/lb_policy/pick_first/pick_first.c b/src/core/ext/lb_policy/pick_first/pick_first.c
index 454efd011a..0ffa003946 100644
--- a/src/core/ext/lb_policy/pick_first/pick_first.c
+++ b/src/core/ext/lb_policy/pick_first/pick_first.c
@@ -109,7 +109,7 @@ static void pf_shutdown(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
if (selected != NULL) {
grpc_connected_subchannel_notify_on_state_change(
exec_ctx, selected, NULL, NULL, &p->connectivity_changed);
- } else {
+ } else if (p->num_subchannels > 0) {
grpc_subchannel_notify_on_state_change(
exec_ctx, p->subchannels[p->checking_subchannel], NULL, NULL,
&p->connectivity_changed);
diff --git a/src/core/ext/transport/chttp2/transport/bin_encoder.c b/src/core/ext/transport/chttp2/transport/bin_encoder.c
index db68e750ac..1b43c28be1 100644
--- a/src/core/ext/transport/chttp2/transport/bin_encoder.c
+++ b/src/core/ext/transport/chttp2/transport/bin_encoder.c
@@ -194,9 +194,13 @@ gpr_slice grpc_chttp2_base64_encode_and_huffman_compress_impl(gpr_slice input) {
/* encode full triplets */
for (i = 0; i < input_triplets; i++) {
- enc_add2(&out, in[0] >> 2, (uint8_t)((in[0] & 0x3) << 4) | (in[1] >> 4));
- enc_add2(&out, (uint8_t)((in[1] & 0xf) << 2) | (in[2] >> 6),
- (uint8_t)(in[2] & 0x3f));
+ const uint8_t low_to_high = (uint8_t)((in[0] & 0x3) << 4);
+ const uint8_t high_to_low = in[1] >> 4;
+ enc_add2(&out, in[0] >> 2, low_to_high | high_to_low);
+
+ const uint8_t a = (uint8_t)((in[1] & 0xf) << 2);
+ const uint8_t b = (in[2] >> 6);
+ enc_add2(&out, a | b, in[2] & 0x3f);
in += 3;
}
@@ -208,12 +212,14 @@ gpr_slice grpc_chttp2_base64_encode_and_huffman_compress_impl(gpr_slice input) {
enc_add2(&out, in[0] >> 2, (uint8_t)((in[0] & 0x3) << 4));
in += 1;
break;
- case 2:
- enc_add2(&out, in[0] >> 2,
- (uint8_t)((in[0] & 0x3) << 4) | (uint8_t)(in[1] >> 4));
+ case 2: {
+ const uint8_t low_to_high = (uint8_t)((in[0] & 0x3) << 4);
+ const uint8_t high_to_low = in[1] >> 4;
+ enc_add2(&out, in[0] >> 2, low_to_high | high_to_low);
enc_add1(&out, (uint8_t)((in[1] & 0xf) << 2));
in += 2;
break;
+ }
}
if (out.temp_length) {
diff --git a/src/core/lib/http/parser.c b/src/core/lib/http/parser.c
index 01d17fb623..921c772453 100644
--- a/src/core/lib/http/parser.c
+++ b/src/core/lib/http/parser.c
@@ -39,7 +39,7 @@
#include <grpc/support/log.h>
#include <grpc/support/useful.h>
-extern int grpc_http_trace;
+int grpc_http1_trace = 0;
static char *buf2str(void *buffer, size_t length) {
char *out = gpr_malloc(length + 1);
@@ -74,7 +74,7 @@ static int handle_response_line(grpc_http_parser *parser) {
return 1;
error:
- if (grpc_http_trace) gpr_log(GPR_ERROR, "Failed parsing response line");
+ if (grpc_http1_trace) gpr_log(GPR_ERROR, "Failed parsing response line");
return 0;
}
@@ -127,7 +127,7 @@ static int handle_request_line(grpc_http_parser *parser) {
return 1;
error:
- if (grpc_http_trace) gpr_log(GPR_ERROR, "Failed parsing request line");
+ if (grpc_http1_trace) gpr_log(GPR_ERROR, "Failed parsing request line");
return 0;
}
@@ -152,7 +152,7 @@ static int add_header(grpc_http_parser *parser) {
GPR_ASSERT(cur != end);
if (*cur == ' ' || *cur == '\t') {
- if (grpc_http_trace)
+ if (grpc_http1_trace)
gpr_log(GPR_ERROR, "Continued header lines not supported yet");
goto error;
}
@@ -161,7 +161,8 @@ static int add_header(grpc_http_parser *parser) {
cur++;
}
if (cur == end) {
- if (grpc_http_trace) gpr_log(GPR_ERROR, "Didn't find ':' in header string");
+ if (grpc_http1_trace)
+ gpr_log(GPR_ERROR, "Didn't find ':' in header string");
goto error;
}
GPR_ASSERT(cur >= beg);
@@ -252,7 +253,7 @@ static int addbyte(grpc_http_parser *parser, uint8_t byte) {
case GRPC_HTTP_FIRST_LINE:
case GRPC_HTTP_HEADERS:
if (parser->cur_line_length >= GRPC_HTTP_PARSER_MAX_HEADER_LENGTH) {
- if (grpc_http_trace)
+ if (grpc_http1_trace)
gpr_log(GPR_ERROR, "HTTP client max line length (%d) exceeded",
GRPC_HTTP_PARSER_MAX_HEADER_LENGTH);
return 0;
diff --git a/src/core/lib/http/parser.h b/src/core/lib/http/parser.h
index 8bd73f649a..42fa5181b8 100644
--- a/src/core/lib/http/parser.h
+++ b/src/core/lib/http/parser.h
@@ -113,4 +113,6 @@ void grpc_http_parser_destroy(grpc_http_parser *parser);
int grpc_http_parser_parse(grpc_http_parser *parser, gpr_slice slice);
int grpc_http_parser_eof(grpc_http_parser *parser);
+extern int grpc_http1_trace;
+
#endif /* GRPC_CORE_LIB_HTTP_PARSER_H */
diff --git a/src/core/lib/iomgr/udp_server.c b/src/core/lib/iomgr/udp_server.c
index 24131179af..df6cf956d9 100644
--- a/src/core/lib/iomgr/udp_server.c
+++ b/src/core/lib/iomgr/udp_server.c
@@ -166,7 +166,6 @@ static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_udp_server *s) {
if (s->nports) {
for (i = 0; i < s->nports; i++) {
server_port *sp = &s->ports[i];
- grpc_unlink_if_unix_domain_socket(&sp->addr.sockaddr);
sp->destroyed_closure.cb = destroyed_port;
sp->destroyed_closure.cb_arg = s;
grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure, NULL,
@@ -317,8 +316,6 @@ int grpc_udp_server_add_port(grpc_udp_server *s, const void *addr,
socklen_t sockname_len;
int port;
- grpc_unlink_if_unix_domain_socket((struct sockaddr *)addr);
-
/* Check if this is a wildcard port, and if so, try to keep the port the same
as some previously created listener. */
if (grpc_sockaddr_get_port(addr) == 0) {
diff --git a/src/core/lib/security/credentials.c b/src/core/lib/security/credentials.c
index 4471a16e49..8550649cbf 100644
--- a/src/core/lib/security/credentials.c
+++ b/src/core/lib/security/credentials.c
@@ -338,10 +338,11 @@ static void ssl_build_config(const char *pem_root_certs,
static void ssl_build_server_config(
const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs,
- size_t num_key_cert_pairs, int force_client_auth,
+ size_t num_key_cert_pairs,
+ grpc_ssl_client_certificate_request_type client_certificate_request,
grpc_ssl_server_config *config) {
size_t i;
- config->force_client_auth = force_client_auth;
+ config->client_certificate_request = client_certificate_request;
if (pem_root_certs != NULL) {
ssl_copy_key_material(pem_root_certs, &config->pem_root_certs,
&config->pem_root_certs_size);
@@ -391,21 +392,35 @@ grpc_channel_credentials *grpc_ssl_credentials_create(
grpc_server_credentials *grpc_ssl_server_credentials_create(
const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs,
size_t num_key_cert_pairs, int force_client_auth, void *reserved) {
+ return grpc_ssl_server_credentials_create_ex(
+ pem_root_certs, pem_key_cert_pairs, num_key_cert_pairs,
+ force_client_auth
+ ? GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY
+ : GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE,
+ reserved);
+}
+
+grpc_server_credentials *grpc_ssl_server_credentials_create_ex(
+ const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs,
+ size_t num_key_cert_pairs,
+ grpc_ssl_client_certificate_request_type client_certificate_request,
+ void *reserved) {
grpc_ssl_server_credentials *c =
gpr_malloc(sizeof(grpc_ssl_server_credentials));
GRPC_API_TRACE(
- "grpc_ssl_server_credentials_create("
+ "grpc_ssl_server_credentials_create_ex("
"pem_root_certs=%s, pem_key_cert_pairs=%p, num_key_cert_pairs=%lu, "
- "force_client_auth=%d, reserved=%p)",
+ "client_certificate_request=%d, reserved=%p)",
5, (pem_root_certs, pem_key_cert_pairs, (unsigned long)num_key_cert_pairs,
- force_client_auth, reserved));
+ client_certificate_request, reserved));
GPR_ASSERT(reserved == NULL);
memset(c, 0, sizeof(grpc_ssl_server_credentials));
c->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_SSL;
gpr_ref_init(&c->base.refcount, 1);
c->base.vtable = &ssl_server_vtable;
ssl_build_server_config(pem_root_certs, pem_key_cert_pairs,
- num_key_cert_pairs, force_client_auth, &c->config);
+ num_key_cert_pairs, client_certificate_request,
+ &c->config);
return &c->base;
}
diff --git a/src/core/lib/security/security_connector.c b/src/core/lib/security/security_connector.c
index 59863ba064..2d2023bdf5 100644
--- a/src/core/lib/security/security_connector.c
+++ b/src/core/lib/security/security_connector.c
@@ -668,6 +668,31 @@ gpr_slice grpc_get_default_ssl_roots_for_testing(void) {
return compute_default_pem_root_certs_once();
}
+static tsi_client_certificate_request_type
+get_tsi_client_certificate_request_type(
+ grpc_ssl_client_certificate_request_type grpc_request_type) {
+ switch (grpc_request_type) {
+ case GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE:
+ return TSI_DONT_REQUEST_CLIENT_CERTIFICATE;
+
+ case GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY:
+ return TSI_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY;
+
+ case GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY:
+ return TSI_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY;
+
+ case GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY:
+ return TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY;
+
+ case GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY:
+ return TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY;
+
+ default:
+ // Is this a sane default
+ return TSI_DONT_REQUEST_CLIENT_CERTIFICATE;
+ }
+}
+
size_t grpc_get_default_ssl_roots(const unsigned char **pem_root_certs) {
/* TODO(jboeuf@google.com): Maybe revisit the approach which consists in
loading all the roots once for the lifetime of the process. */
@@ -782,15 +807,16 @@ grpc_security_status grpc_ssl_server_security_connector_create(
gpr_ref_init(&c->base.base.refcount, 1);
c->base.base.url_scheme = GRPC_SSL_URL_SCHEME;
c->base.base.vtable = &ssl_server_vtable;
- result = tsi_create_ssl_server_handshaker_factory(
+ result = tsi_create_ssl_server_handshaker_factory_ex(
(const unsigned char **)config->pem_private_keys,
config->pem_private_keys_sizes,
(const unsigned char **)config->pem_cert_chains,
config->pem_cert_chains_sizes, config->num_key_cert_pairs,
config->pem_root_certs, config->pem_root_certs_size,
- config->force_client_auth, ssl_cipher_suites(), alpn_protocol_strings,
- alpn_protocol_string_lengths, (uint16_t)num_alpn_protocols,
- &c->handshaker_factory);
+ get_tsi_client_certificate_request_type(
+ config->client_certificate_request),
+ ssl_cipher_suites(), alpn_protocol_strings, alpn_protocol_string_lengths,
+ (uint16_t)num_alpn_protocols, &c->handshaker_factory);
if (result != TSI_OK) {
gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.",
tsi_result_to_string(result));
diff --git a/src/core/lib/security/security_connector.h b/src/core/lib/security/security_connector.h
index c9e262b1ad..2c893cd5e9 100644
--- a/src/core/lib/security/security_connector.h
+++ b/src/core/lib/security/security_connector.h
@@ -241,7 +241,7 @@ typedef struct {
size_t num_key_cert_pairs;
unsigned char *pem_root_certs;
size_t pem_root_certs_size;
- int force_client_auth;
+ grpc_ssl_client_certificate_request_type client_certificate_request;
} grpc_ssl_server_config;
/* Creates an SSL server_security_connector.
diff --git a/src/core/lib/support/log.c b/src/core/lib/support/log.c
index 04156a5b1f..882abf673c 100644
--- a/src/core/lib/support/log.c
+++ b/src/core/lib/support/log.c
@@ -31,14 +31,20 @@
*
*/
+#include <grpc/support/alloc.h>
+#include <grpc/support/atm.h>
#include <grpc/support/log.h>
#include <grpc/support/port_platform.h>
+#include "src/core/lib/support/env.h"
+#include "src/core/lib/support/string.h"
+
#include <stdio.h>
#include <string.h>
extern void gpr_default_log(gpr_log_func_args *args);
static gpr_log_func g_log_func = gpr_default_log;
+static gpr_atm g_min_severity_to_print = GPR_LOG_VERBOSITY_UNSET;
const char *gpr_log_severity_string(gpr_log_severity severity) {
switch (severity) {
@@ -54,6 +60,9 @@ const char *gpr_log_severity_string(gpr_log_severity severity) {
void gpr_log_message(const char *file, int line, gpr_log_severity severity,
const char *message) {
+ if ((gpr_atm)severity < gpr_atm_no_barrier_load(&g_min_severity_to_print))
+ return;
+
gpr_log_func_args lfargs;
memset(&lfargs, 0, sizeof(lfargs));
lfargs.file = file;
@@ -63,4 +72,28 @@ void gpr_log_message(const char *file, int line, gpr_log_severity severity,
g_log_func(&lfargs);
}
+void gpr_set_log_verbosity(gpr_log_severity min_severity_to_print) {
+ gpr_atm_no_barrier_store(&g_min_severity_to_print,
+ (gpr_atm)min_severity_to_print);
+}
+
+void gpr_log_verbosity_init() {
+ char *verbosity = gpr_getenv("GRPC_VERBOSITY");
+ if (verbosity == NULL) return;
+
+ gpr_atm min_severity_to_print = GPR_LOG_VERBOSITY_UNSET;
+ if (strcmp(verbosity, "DEBUG") == 0) {
+ min_severity_to_print = (gpr_atm)GPR_LOG_SEVERITY_DEBUG;
+ } else if (strcmp(verbosity, "INFO") == 0) {
+ min_severity_to_print = (gpr_atm)GPR_LOG_SEVERITY_INFO;
+ } else if (strcmp(verbosity, "ERROR") == 0) {
+ min_severity_to_print = (gpr_atm)GPR_LOG_SEVERITY_ERROR;
+ }
+ gpr_free(verbosity);
+ if ((gpr_atm_no_barrier_load(&g_min_severity_to_print)) ==
+ GPR_LOG_VERBOSITY_UNSET) {
+ gpr_atm_no_barrier_store(&g_min_severity_to_print, min_severity_to_print);
+ }
+}
+
void gpr_set_log_function(gpr_log_func f) { g_log_func = f; }
diff --git a/src/core/lib/surface/init.c b/src/core/lib/surface/init.c
index ec75af6e06..03f379aba8 100644
--- a/src/core/lib/surface/init.c
+++ b/src/core/lib/surface/init.c
@@ -38,6 +38,7 @@
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/channel/compress_filter.h"
@@ -45,6 +46,7 @@
#include "src/core/lib/channel/http_client_filter.h"
#include "src/core/lib/channel/http_server_filter.h"
#include "src/core/lib/debug/trace.h"
+#include "src/core/lib/http/parser.h"
#include "src/core/lib/iomgr/executor.h"
#include "src/core/lib/iomgr/iomgr.h"
#include "src/core/lib/profiling/timers.h"
@@ -69,6 +71,7 @@ static gpr_mu g_init_mu;
static int g_initializations;
static void do_basic_init(void) {
+ gpr_log_verbosity_init();
gpr_mu_init(&g_init_mu);
grpc_register_built_in_plugins();
g_initializations = 0;
@@ -160,6 +163,7 @@ void grpc_init(void) {
grpc_register_tracer("connectivity_state", &grpc_connectivity_state_trace);
grpc_register_tracer("channel_stack_builder",
&grpc_trace_channel_stack_builder);
+ grpc_register_tracer("http1", &grpc_http1_trace);
grpc_security_pre_init();
grpc_iomgr_init();
grpc_executor_init();
diff --git a/src/core/lib/tsi/ssl_transport_security.c b/src/core/lib/tsi/ssl_transport_security.c
index 045901cc72..e91c6316e7 100644
--- a/src/core/lib/tsi/ssl_transport_security.c
+++ b/src/core/lib/tsi/ssl_transport_security.c
@@ -718,6 +718,14 @@ static tsi_result build_alpn_protocol_name_list(
return TSI_OK;
}
+// The verification callback is used for clients that don't really care about
+// the server's certificate, but we need to pull it anyway, in case a higher
+// layer wants to look at it. In this case the verification may fail, but
+// we don't really care.
+static int NullVerifyCallback(int preverify_ok, X509_STORE_CTX *ctx) {
+ return 1;
+}
+
/* --- tsi_frame_protector methods implementation. ---*/
static tsi_result ssl_protector_protect(tsi_frame_protector *self,
@@ -1390,6 +1398,26 @@ tsi_result tsi_create_ssl_server_handshaker_factory(
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) {
+ return tsi_create_ssl_server_handshaker_factory_ex(
+ pem_private_keys, pem_private_keys_sizes, pem_cert_chains,
+ pem_cert_chains_sizes, key_cert_pair_count, pem_client_root_certs,
+ pem_client_root_certs_size,
+ force_client_auth ? TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY
+ : TSI_DONT_REQUEST_CLIENT_CERTIFICATE,
+ cipher_list, alpn_protocols, alpn_protocols_lengths, num_alpn_protocols,
+ factory);
+}
+
+tsi_result tsi_create_ssl_server_handshaker_factory_ex(
+ 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,
+ tsi_client_certificate_request_type client_certificate_request,
+ 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;
@@ -1445,7 +1473,6 @@ tsi_result tsi_create_ssl_server_handshaker_factory(
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,
@@ -1455,8 +1482,29 @@ tsi_result tsi_create_ssl_server_handshaker_factory(
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);
+ switch (client_certificate_request) {
+ case TSI_DONT_REQUEST_CLIENT_CERTIFICATE:
+ SSL_CTX_set_verify(impl->ssl_contexts[i], SSL_VERIFY_NONE, NULL);
+ break;
+ case TSI_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY:
+ SSL_CTX_set_verify(impl->ssl_contexts[i], SSL_VERIFY_PEER,
+ NullVerifyCallback);
+ break;
+ case TSI_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY:
+ SSL_CTX_set_verify(impl->ssl_contexts[i], SSL_VERIFY_PEER, NULL);
+ break;
+ case TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY:
+ SSL_CTX_set_verify(
+ impl->ssl_contexts[i],
+ SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
+ NullVerifyCallback);
+ break;
+ case TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY:
+ SSL_CTX_set_verify(
+ impl->ssl_contexts[i],
+ SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
+ break;
+ }
/* TODO(jboeuf): Add revocation verification. */
}
diff --git a/src/core/lib/tsi/ssl_transport_security.h b/src/core/lib/tsi/ssl_transport_security.h
index 211c8f9656..7407246118 100644
--- a/src/core/lib/tsi/ssl_transport_security.h
+++ b/src/core/lib/tsi/ssl_transport_security.h
@@ -142,6 +142,23 @@ tsi_result tsi_create_ssl_server_handshaker_factory(
const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols,
tsi_ssl_handshaker_factory **factory);
+/* Same as tsi_create_ssl_server_handshaker_factory method except uses
+ tsi_client_certificate_request_type to support more ways to handle client
+ certificate authentication.
+ - client_certificate_request, if set to non-zero will force the client to
+ authenticate with an SSL cert. Note that this option is ignored if
+ pem_client_root_certs is NULL or pem_client_roots_certs_size is 0 */
+tsi_result tsi_create_ssl_server_handshaker_factory_ex(
+ 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,
+ tsi_client_certificate_request_type client_certificate_request,
+ const char *cipher_suites, const unsigned char **alpn_protocols,
+ const unsigned char *alpn_protocols_lengths, uint16_t num_alpn_protocols,
+ tsi_ssl_handshaker_factory **factory);
+
/* Creates a handshaker.
- self is the factory from which the handshaker will be created.
- server_name_indication indicates the name of the server the client is
diff --git a/src/core/lib/tsi/transport_security_interface.h b/src/core/lib/tsi/transport_security_interface.h
index d81ec0963a..3e8c9d7ffe 100644
--- a/src/core/lib/tsi/transport_security_interface.h
+++ b/src/core/lib/tsi/transport_security_interface.h
@@ -59,6 +59,15 @@ typedef enum {
TSI_OUT_OF_RESOURCES = 12
} tsi_result;
+typedef enum {
+ // Default option
+ TSI_DONT_REQUEST_CLIENT_CERTIFICATE,
+ TSI_REQUEST_CLIENT_CERTIFICATE_BUT_DONT_VERIFY,
+ TSI_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY,
+ TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_BUT_DONT_VERIFY,
+ TSI_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY,
+} tsi_client_certificate_request_type;
+
const char *tsi_result_to_string(tsi_result result);
/* --- tsi tracing --- */