496f064439c7b204c0dcf4328b7588a11e5a93b0
[platform/upstream/grpc.git] / test / core / security / security_connector_test.cc
1 /*
2  *
3  * Copyright 2015 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18
19 #include <stdio.h>
20 #include <string.h>
21
22 #include <grpc/grpc_security.h>
23 #include <grpc/support/alloc.h>
24 #include <grpc/support/log.h>
25 #include <grpc/support/string_util.h>
26
27 #include "src/core/lib/gpr/env.h"
28 #include "src/core/lib/gpr/string.h"
29 #include "src/core/lib/gpr/tmpfile.h"
30 #include "src/core/lib/gprpp/ref_counted_ptr.h"
31 #include "src/core/lib/security/context/security_context.h"
32 #include "src/core/lib/security/security_connector/security_connector.h"
33 #include "src/core/lib/security/security_connector/ssl_utils.h"
34 #include "src/core/lib/slice/slice_string_helpers.h"
35 #include "src/core/tsi/ssl_transport_security.h"
36 #include "src/core/tsi/transport_security.h"
37 #include "test/core/util/test_config.h"
38
39 #ifndef TSI_OPENSSL_ALPN_SUPPORT
40 #define TSI_OPENSSL_ALPN_SUPPORT 1
41 #endif
42
43 static int check_transport_security_type(const grpc_auth_context* ctx) {
44   grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name(
45       ctx, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME);
46   const grpc_auth_property* prop = grpc_auth_property_iterator_next(&it);
47   if (prop == nullptr) return 0;
48   if (strncmp(prop->value, GRPC_SSL_TRANSPORT_SECURITY_TYPE,
49               prop->value_length) != 0) {
50     return 0;
51   }
52   /* Check that we have only one property with this name. */
53   if (grpc_auth_property_iterator_next(&it) != nullptr) return 0;
54   return 1;
55 }
56
57 static int check_peer_property(const tsi_peer* peer,
58                                const tsi_peer_property* expected) {
59   size_t i;
60   for (i = 0; i < peer->property_count; i++) {
61     const tsi_peer_property* prop = &peer->properties[i];
62     if ((strcmp(prop->name, expected->name) == 0) &&
63         (prop->value.length == expected->value.length) &&
64         (memcmp(prop->value.data, expected->value.data,
65                 expected->value.length) == 0)) {
66       return 1;
67     }
68   }
69   return 0; /* Not found... */
70 }
71
72 static int check_ssl_peer_equivalence(const tsi_peer* original,
73                                       const tsi_peer* reconstructed) {
74   /* The reconstructed peer only has CN, SAN and pem cert properties. */
75   size_t i;
76   for (i = 0; i < original->property_count; i++) {
77     const tsi_peer_property* prop = &original->properties[i];
78     if ((strcmp(prop->name, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY) == 0) ||
79         (strcmp(prop->name, TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) ==
80          0) ||
81         (strcmp(prop->name, TSI_X509_PEM_CERT_PROPERTY) == 0)) {
82       if (!check_peer_property(reconstructed, prop)) return 0;
83     }
84   }
85   return 1;
86 }
87
88 static void test_unauthenticated_ssl_peer(void) {
89   tsi_peer peer;
90   tsi_peer rpeer;
91   GPR_ASSERT(tsi_construct_peer(1, &peer) == TSI_OK);
92   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
93                  TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE,
94                  &peer.properties[0]) == TSI_OK);
95   grpc_core::RefCountedPtr<grpc_auth_context> ctx =
96       grpc_ssl_peer_to_auth_context(&peer);
97   GPR_ASSERT(ctx != nullptr);
98   GPR_ASSERT(!grpc_auth_context_peer_is_authenticated(ctx.get()));
99   GPR_ASSERT(check_transport_security_type(ctx.get()));
100
101   rpeer = grpc_shallow_peer_from_ssl_auth_context(ctx.get());
102   GPR_ASSERT(check_ssl_peer_equivalence(&peer, &rpeer));
103
104   grpc_shallow_peer_destruct(&rpeer);
105   tsi_peer_destruct(&peer);
106   ctx.reset(DEBUG_LOCATION, "test");
107 }
108
109 static int check_identity(const grpc_auth_context* ctx,
110                           const char* expected_property_name,
111                           const char** expected_identities,
112                           size_t num_identities) {
113   grpc_auth_property_iterator it;
114   const grpc_auth_property* prop;
115   size_t i;
116   GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx));
117   it = grpc_auth_context_peer_identity(ctx);
118   for (i = 0; i < num_identities; i++) {
119     prop = grpc_auth_property_iterator_next(&it);
120     if (prop == nullptr) {
121       gpr_log(GPR_ERROR, "Expected identity value %s not found.",
122               expected_identities[i]);
123       return 0;
124     }
125     if (strcmp(prop->name, expected_property_name) != 0) {
126       gpr_log(GPR_ERROR, "Expected peer identity property name %s and got %s.",
127               expected_property_name, prop->name);
128       return 0;
129     }
130     if (strncmp(prop->value, expected_identities[i], prop->value_length) != 0) {
131       gpr_log(GPR_ERROR, "Expected peer identity %s and got %s.",
132               expected_identities[i], prop->value);
133       return 0;
134     }
135   }
136   return 1;
137 }
138
139 static int check_x509_cn(const grpc_auth_context* ctx,
140                          const char* expected_cn) {
141   grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name(
142       ctx, GRPC_X509_CN_PROPERTY_NAME);
143   const grpc_auth_property* prop = grpc_auth_property_iterator_next(&it);
144   if (prop == nullptr) {
145     gpr_log(GPR_ERROR, "CN property not found.");
146     return 0;
147   }
148   if (strncmp(prop->value, expected_cn, prop->value_length) != 0) {
149     gpr_log(GPR_ERROR, "Expected CN %s and got %s", expected_cn, prop->value);
150     return 0;
151   }
152   if (grpc_auth_property_iterator_next(&it) != nullptr) {
153     gpr_log(GPR_ERROR, "Expected only one property for CN.");
154     return 0;
155   }
156   return 1;
157 }
158
159 static int check_x509_pem_cert(const grpc_auth_context* ctx,
160                                const char* expected_pem_cert) {
161   grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name(
162       ctx, GRPC_X509_PEM_CERT_PROPERTY_NAME);
163   const grpc_auth_property* prop = grpc_auth_property_iterator_next(&it);
164   if (prop == nullptr) {
165     gpr_log(GPR_ERROR, "Pem certificate property not found.");
166     return 0;
167   }
168   if (strncmp(prop->value, expected_pem_cert, prop->value_length) != 0) {
169     gpr_log(GPR_ERROR, "Expected pem cert %s and got %s", expected_pem_cert,
170             prop->value);
171     return 0;
172   }
173   if (grpc_auth_property_iterator_next(&it) != nullptr) {
174     gpr_log(GPR_ERROR, "Expected only one property for pem cert.");
175     return 0;
176   }
177   return 1;
178 }
179
180 static void test_cn_only_ssl_peer_to_auth_context(void) {
181   tsi_peer peer;
182   tsi_peer rpeer;
183   const char* expected_cn = "cn1";
184   const char* expected_pem_cert = "pem_cert1";
185   GPR_ASSERT(tsi_construct_peer(3, &peer) == TSI_OK);
186   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
187                  TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE,
188                  &peer.properties[0]) == TSI_OK);
189   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
190                  TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, expected_cn,
191                  &peer.properties[1]) == TSI_OK);
192   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
193                  TSI_X509_PEM_CERT_PROPERTY, expected_pem_cert,
194                  &peer.properties[2]) == TSI_OK);
195   grpc_core::RefCountedPtr<grpc_auth_context> ctx =
196       grpc_ssl_peer_to_auth_context(&peer);
197   GPR_ASSERT(ctx != nullptr);
198   GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx.get()));
199   GPR_ASSERT(
200       check_identity(ctx.get(), GRPC_X509_CN_PROPERTY_NAME, &expected_cn, 1));
201   GPR_ASSERT(check_transport_security_type(ctx.get()));
202   GPR_ASSERT(check_x509_cn(ctx.get(), expected_cn));
203   GPR_ASSERT(check_x509_pem_cert(ctx.get(), expected_pem_cert));
204
205   rpeer = grpc_shallow_peer_from_ssl_auth_context(ctx.get());
206   GPR_ASSERT(check_ssl_peer_equivalence(&peer, &rpeer));
207
208   grpc_shallow_peer_destruct(&rpeer);
209   tsi_peer_destruct(&peer);
210   ctx.reset(DEBUG_LOCATION, "test");
211 }
212
213 static void test_cn_and_one_san_ssl_peer_to_auth_context(void) {
214   tsi_peer peer;
215   tsi_peer rpeer;
216   const char* expected_cn = "cn1";
217   const char* expected_san = "san1";
218   const char* expected_pem_cert = "pem_cert1";
219   GPR_ASSERT(tsi_construct_peer(4, &peer) == TSI_OK);
220   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
221                  TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE,
222                  &peer.properties[0]) == TSI_OK);
223   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
224                  TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, expected_cn,
225                  &peer.properties[1]) == TSI_OK);
226   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
227                  TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, expected_san,
228                  &peer.properties[2]) == TSI_OK);
229   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
230                  TSI_X509_PEM_CERT_PROPERTY, expected_pem_cert,
231                  &peer.properties[3]) == TSI_OK);
232
233   grpc_core::RefCountedPtr<grpc_auth_context> ctx =
234       grpc_ssl_peer_to_auth_context(&peer);
235   GPR_ASSERT(ctx != nullptr);
236   GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx.get()));
237   GPR_ASSERT(
238       check_identity(ctx.get(), GRPC_X509_SAN_PROPERTY_NAME, &expected_san, 1));
239   GPR_ASSERT(check_transport_security_type(ctx.get()));
240   GPR_ASSERT(check_x509_cn(ctx.get(), expected_cn));
241   GPR_ASSERT(check_x509_pem_cert(ctx.get(), expected_pem_cert));
242
243   rpeer = grpc_shallow_peer_from_ssl_auth_context(ctx.get());
244   GPR_ASSERT(check_ssl_peer_equivalence(&peer, &rpeer));
245
246   grpc_shallow_peer_destruct(&rpeer);
247   tsi_peer_destruct(&peer);
248   ctx.reset(DEBUG_LOCATION, "test");
249 }
250
251 static void test_cn_and_multiple_sans_ssl_peer_to_auth_context(void) {
252   tsi_peer peer;
253   tsi_peer rpeer;
254   const char* expected_cn = "cn1";
255   const char* expected_sans[] = {"san1", "san2", "san3"};
256   const char* expected_pem_cert = "pem_cert1";
257   size_t i;
258   GPR_ASSERT(tsi_construct_peer(3 + GPR_ARRAY_SIZE(expected_sans), &peer) ==
259              TSI_OK);
260   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
261                  TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE,
262                  &peer.properties[0]) == TSI_OK);
263   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
264                  TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, expected_cn,
265                  &peer.properties[1]) == TSI_OK);
266   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
267                  TSI_X509_PEM_CERT_PROPERTY, expected_pem_cert,
268                  &peer.properties[2]) == TSI_OK);
269   for (i = 0; i < GPR_ARRAY_SIZE(expected_sans); i++) {
270     GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
271                    TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY,
272                    expected_sans[i], &peer.properties[3 + i]) == TSI_OK);
273   }
274   grpc_core::RefCountedPtr<grpc_auth_context> ctx =
275       grpc_ssl_peer_to_auth_context(&peer);
276   GPR_ASSERT(ctx != nullptr);
277   GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx.get()));
278   GPR_ASSERT(check_identity(ctx.get(), GRPC_X509_SAN_PROPERTY_NAME,
279                             expected_sans, GPR_ARRAY_SIZE(expected_sans)));
280   GPR_ASSERT(check_transport_security_type(ctx.get()));
281   GPR_ASSERT(check_x509_cn(ctx.get(), expected_cn));
282   GPR_ASSERT(check_x509_pem_cert(ctx.get(), expected_pem_cert));
283
284   rpeer = grpc_shallow_peer_from_ssl_auth_context(ctx.get());
285   GPR_ASSERT(check_ssl_peer_equivalence(&peer, &rpeer));
286
287   grpc_shallow_peer_destruct(&rpeer);
288   tsi_peer_destruct(&peer);
289   ctx.reset(DEBUG_LOCATION, "test");
290 }
291
292 static void test_cn_and_multiple_sans_and_others_ssl_peer_to_auth_context(
293     void) {
294   tsi_peer peer;
295   tsi_peer rpeer;
296   const char* expected_cn = "cn1";
297   const char* expected_pem_cert = "pem_cert1";
298   const char* expected_sans[] = {"san1", "san2", "san3"};
299   size_t i;
300   GPR_ASSERT(tsi_construct_peer(5 + GPR_ARRAY_SIZE(expected_sans), &peer) ==
301              TSI_OK);
302   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
303                  TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE,
304                  &peer.properties[0]) == TSI_OK);
305   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
306                  "foo", "bar", &peer.properties[1]) == TSI_OK);
307   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
308                  TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, expected_cn,
309                  &peer.properties[2]) == TSI_OK);
310   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
311                  "chapi", "chapo", &peer.properties[3]) == TSI_OK);
312   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
313                  TSI_X509_PEM_CERT_PROPERTY, expected_pem_cert,
314                  &peer.properties[4]) == TSI_OK);
315   for (i = 0; i < GPR_ARRAY_SIZE(expected_sans); i++) {
316     GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
317                    TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY,
318                    expected_sans[i], &peer.properties[5 + i]) == TSI_OK);
319   }
320   grpc_core::RefCountedPtr<grpc_auth_context> ctx =
321       grpc_ssl_peer_to_auth_context(&peer);
322   GPR_ASSERT(ctx != nullptr);
323   GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx.get()));
324   GPR_ASSERT(check_identity(ctx.get(), GRPC_X509_SAN_PROPERTY_NAME,
325                             expected_sans, GPR_ARRAY_SIZE(expected_sans)));
326   GPR_ASSERT(check_transport_security_type(ctx.get()));
327   GPR_ASSERT(check_x509_cn(ctx.get(), expected_cn));
328   GPR_ASSERT(check_x509_pem_cert(ctx.get(), expected_pem_cert));
329
330   rpeer = grpc_shallow_peer_from_ssl_auth_context(ctx.get());
331   GPR_ASSERT(check_ssl_peer_equivalence(&peer, &rpeer));
332
333   grpc_shallow_peer_destruct(&rpeer);
334   tsi_peer_destruct(&peer);
335   ctx.reset(DEBUG_LOCATION, "test");
336 }
337
338 static const char* roots_for_override_api = "roots for override api";
339
340 static grpc_ssl_roots_override_result override_roots_success(
341     char** pem_root_certs) {
342   *pem_root_certs = gpr_strdup(roots_for_override_api);
343   return GRPC_SSL_ROOTS_OVERRIDE_OK;
344 }
345
346 static grpc_ssl_roots_override_result override_roots_permanent_failure(
347     char** pem_root_certs) {
348   return GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY;
349 }
350
351 static void test_ipv6_address_san(void) {
352   const char* addresses[] = {
353       "2001:db8::1",     "fe80::abcd:ef65:4321%em0", "fd11:feed:beef:0:cafe::4",
354       "128.10.0.1:8888", "[2001:db8::1]:8080",       "[2001:db8::1%em1]:8080",
355   };
356   const char* san_ips[] = {
357       "2001:db8::1", "fe80::abcd:ef65:4321", "fd11:feed:beef:0:cafe::4",
358       "128.10.0.1",  "2001:db8::1",          "2001:db8::1",
359   };
360   tsi_peer peer;
361   GPR_ASSERT(tsi_construct_peer(1, &peer) == TSI_OK);
362   for (size_t i = 0; i < GPR_ARRAY_SIZE(addresses); i++) {
363     GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
364                    TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, san_ips[i],
365                    &peer.properties[0]) == TSI_OK);
366     GPR_ASSERT(grpc_ssl_host_matches_name(&peer, addresses[i]));
367     tsi_peer_property_destruct(&peer.properties[0]);
368   }
369   tsi_peer_destruct(&peer);
370 }
371 namespace grpc_core {
372 namespace {
373
374 class TestDefaultSslRootStore : public DefaultSslRootStore {
375  public:
376   static grpc_slice ComputePemRootCertsForTesting() {
377     return ComputePemRootCerts();
378   }
379 };
380
381 }  // namespace
382 }  // namespace grpc_core
383
384 // TODO: Convert this test to C++ test when security_connector implementation
385 // is converted to C++.
386 static void test_default_ssl_roots(void) {
387   const char* roots_for_env_var = "roots for env var";
388
389   char* roots_env_var_file_path;
390   FILE* roots_env_var_file =
391       gpr_tmpfile("test_roots_for_env_var", &roots_env_var_file_path);
392   fwrite(roots_for_env_var, 1, strlen(roots_for_env_var), roots_env_var_file);
393   fclose(roots_env_var_file);
394
395   /* First let's get the root through the override: set the env to an invalid
396      value. */
397   gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, "");
398   grpc_set_ssl_roots_override_callback(override_roots_success);
399   grpc_slice roots =
400       grpc_core::TestDefaultSslRootStore::ComputePemRootCertsForTesting();
401   char* roots_contents = grpc_slice_to_c_string(roots);
402   grpc_slice_unref(roots);
403   GPR_ASSERT(strcmp(roots_contents, roots_for_override_api) == 0);
404   gpr_free(roots_contents);
405
406   /* Now let's set the env var: We should get the contents pointed value
407      instead. */
408   gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, roots_env_var_file_path);
409   roots = grpc_core::TestDefaultSslRootStore::ComputePemRootCertsForTesting();
410   roots_contents = grpc_slice_to_c_string(roots);
411   grpc_slice_unref(roots);
412   GPR_ASSERT(strcmp(roots_contents, roots_for_env_var) == 0);
413   gpr_free(roots_contents);
414
415   /* Now reset the env var. We should fall back to the value overridden using
416      the api. */
417   gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, "");
418   roots = grpc_core::TestDefaultSslRootStore::ComputePemRootCertsForTesting();
419   roots_contents = grpc_slice_to_c_string(roots);
420   grpc_slice_unref(roots);
421   GPR_ASSERT(strcmp(roots_contents, roots_for_override_api) == 0);
422   gpr_free(roots_contents);
423
424   /* Now setup a permanent failure for the overridden roots and we should get
425      an empty slice. */
426   gpr_setenv("GRPC_NOT_USE_SYSTEM_SSL_ROOTS", "true");
427   grpc_set_ssl_roots_override_callback(override_roots_permanent_failure);
428   roots = grpc_core::TestDefaultSslRootStore::ComputePemRootCertsForTesting();
429   GPR_ASSERT(GRPC_SLICE_IS_EMPTY(roots));
430   const tsi_ssl_root_certs_store* root_store =
431       grpc_core::TestDefaultSslRootStore::GetRootStore();
432   GPR_ASSERT(root_store == nullptr);
433
434   /* Cleanup. */
435   remove(roots_env_var_file_path);
436   gpr_free(roots_env_var_file_path);
437 }
438
439 static void test_peer_alpn_check(void) {
440 #if TSI_OPENSSL_ALPN_SUPPORT
441   tsi_peer peer;
442   const char* alpn = "grpc";
443   const char* wrong_alpn = "wrong";
444   // peer does not have a TSI_SSL_ALPN_SELECTED_PROTOCOL property.
445   GPR_ASSERT(tsi_construct_peer(1, &peer) == TSI_OK);
446   GPR_ASSERT(tsi_construct_string_peer_property("wrong peer property name",
447                                                 alpn, strlen(alpn),
448                                                 &peer.properties[0]) == TSI_OK);
449   grpc_error* error = grpc_ssl_check_alpn(&peer);
450   GPR_ASSERT(error != GRPC_ERROR_NONE);
451   tsi_peer_destruct(&peer);
452   GRPC_ERROR_UNREF(error);
453   // peer has a TSI_SSL_ALPN_SELECTED_PROTOCOL property but with an incorrect
454   // property value.
455   GPR_ASSERT(tsi_construct_peer(1, &peer) == TSI_OK);
456   GPR_ASSERT(tsi_construct_string_peer_property(TSI_SSL_ALPN_SELECTED_PROTOCOL,
457                                                 wrong_alpn, strlen(wrong_alpn),
458                                                 &peer.properties[0]) == TSI_OK);
459   error = grpc_ssl_check_alpn(&peer);
460   GPR_ASSERT(error != GRPC_ERROR_NONE);
461   tsi_peer_destruct(&peer);
462   GRPC_ERROR_UNREF(error);
463   // peer has a TSI_SSL_ALPN_SELECTED_PROTOCOL property with a correct property
464   // value.
465   GPR_ASSERT(tsi_construct_peer(1, &peer) == TSI_OK);
466   GPR_ASSERT(tsi_construct_string_peer_property(TSI_SSL_ALPN_SELECTED_PROTOCOL,
467                                                 alpn, strlen(alpn),
468                                                 &peer.properties[0]) == TSI_OK);
469   GPR_ASSERT(grpc_ssl_check_alpn(&peer) == GRPC_ERROR_NONE);
470   tsi_peer_destruct(&peer);
471 #else
472   GPR_ASSERT(grpc_ssl_check_alpn(nullptr) == GRPC_ERROR_NONE);
473 #endif
474 }
475
476 int main(int argc, char** argv) {
477   grpc::testing::TestEnvironment env(argc, argv);
478   grpc_init();
479
480   test_unauthenticated_ssl_peer();
481   test_cn_only_ssl_peer_to_auth_context();
482   test_cn_and_one_san_ssl_peer_to_auth_context();
483   test_cn_and_multiple_sans_ssl_peer_to_auth_context();
484   test_cn_and_multiple_sans_and_others_ssl_peer_to_auth_context();
485   test_ipv6_address_san();
486   test_default_ssl_roots();
487   test_peer_alpn_check();
488   grpc_shutdown();
489   return 0;
490 }