• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "src/core/lib/security/security_connector/security_connector.h"
20 
21 #include <grpc/grpc_security.h>
22 #include <grpc/support/alloc.h>
23 #include <grpc/support/log.h>
24 #include <grpc/support/string_util.h>
25 #include <stdio.h>
26 #include <string.h>
27 
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/ssl_utils.h"
33 #include "src/core/lib/slice/slice_string_helpers.h"
34 #include "src/core/tsi/ssl_transport_security.h"
35 #include "src/core/tsi/transport_security.h"
36 #include "test/core/util/test_config.h"
37 
38 #ifndef TSI_OPENSSL_ALPN_SUPPORT
39 #define TSI_OPENSSL_ALPN_SUPPORT 1
40 #endif
41 
check_transport_security_type(const grpc_auth_context * ctx)42 static int check_transport_security_type(const grpc_auth_context* ctx) {
43   grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name(
44       ctx, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME);
45   const grpc_auth_property* prop = grpc_auth_property_iterator_next(&it);
46   if (prop == nullptr) return 0;
47   if (strncmp(prop->value, GRPC_SSL_TRANSPORT_SECURITY_TYPE,
48               prop->value_length) != 0) {
49     return 0;
50   }
51   /* Check that we have only one property with this name. */
52   if (grpc_auth_property_iterator_next(&it) != nullptr) return 0;
53   return 1;
54 }
55 
check_peer_property(const tsi_peer * peer,const tsi_peer_property * expected)56 static int check_peer_property(const tsi_peer* peer,
57                                const tsi_peer_property* expected) {
58   size_t i;
59   for (i = 0; i < peer->property_count; i++) {
60     const tsi_peer_property* prop = &peer->properties[i];
61     if ((strcmp(prop->name, expected->name) == 0) &&
62         (prop->value.length == expected->value.length) &&
63         (memcmp(prop->value.data, expected->value.data,
64                 expected->value.length) == 0)) {
65       return 1;
66     }
67   }
68   return 0; /* Not found... */
69 }
70 
check_ssl_peer_equivalence(const tsi_peer * original,const tsi_peer * reconstructed)71 static int check_ssl_peer_equivalence(const tsi_peer* original,
72                                       const tsi_peer* reconstructed) {
73   /* The reconstructed peer only has CN, SAN and pem cert properties. */
74   size_t i;
75   for (i = 0; i < original->property_count; i++) {
76     const tsi_peer_property* prop = &original->properties[i];
77     if ((strcmp(prop->name, TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY) == 0) ||
78         (strcmp(prop->name, TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) ==
79          0) ||
80         (strcmp(prop->name, TSI_X509_PEM_CERT_PROPERTY) == 0)) {
81       if (!check_peer_property(reconstructed, prop)) return 0;
82     }
83   }
84   return 1;
85 }
86 
test_check_security_level()87 static void test_check_security_level() {
88   GPR_ASSERT(grpc_check_security_level(GRPC_PRIVACY_AND_INTEGRITY,
89                                        GRPC_PRIVACY_AND_INTEGRITY) == true);
90   GPR_ASSERT(grpc_check_security_level(GRPC_PRIVACY_AND_INTEGRITY,
91                                        GRPC_INTEGRITY_ONLY) == true);
92   GPR_ASSERT(grpc_check_security_level(GRPC_PRIVACY_AND_INTEGRITY,
93                                        GRPC_SECURITY_NONE) == true);
94   GPR_ASSERT(grpc_check_security_level(GRPC_INTEGRITY_ONLY,
95                                        GRPC_PRIVACY_AND_INTEGRITY) == false);
96   GPR_ASSERT(grpc_check_security_level(GRPC_INTEGRITY_ONLY,
97                                        GRPC_INTEGRITY_ONLY) == true);
98   GPR_ASSERT(grpc_check_security_level(GRPC_INTEGRITY_ONLY,
99                                        GRPC_SECURITY_NONE) == true);
100   GPR_ASSERT(grpc_check_security_level(GRPC_SECURITY_NONE,
101                                        GRPC_PRIVACY_AND_INTEGRITY) == false);
102   GPR_ASSERT(grpc_check_security_level(GRPC_SECURITY_NONE,
103                                        GRPC_INTEGRITY_ONLY) == false);
104   GPR_ASSERT(grpc_check_security_level(GRPC_SECURITY_NONE,
105                                        GRPC_SECURITY_NONE) == true);
106 }
107 
test_unauthenticated_ssl_peer(void)108 static void test_unauthenticated_ssl_peer(void) {
109   tsi_peer peer;
110   tsi_peer rpeer;
111   GPR_ASSERT(tsi_construct_peer(2, &peer) == TSI_OK);
112   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
113                  TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE,
114                  &peer.properties[0]) == TSI_OK);
115   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
116                  TSI_SECURITY_LEVEL_PEER_PROPERTY,
117                  tsi_security_level_to_string(TSI_PRIVACY_AND_INTEGRITY),
118                  &peer.properties[1]) == TSI_OK);
119   grpc_core::RefCountedPtr<grpc_auth_context> ctx =
120       grpc_ssl_peer_to_auth_context(&peer, GRPC_SSL_TRANSPORT_SECURITY_TYPE);
121   GPR_ASSERT(ctx != nullptr);
122   GPR_ASSERT(!grpc_auth_context_peer_is_authenticated(ctx.get()));
123   GPR_ASSERT(check_transport_security_type(ctx.get()));
124 
125   rpeer = grpc_shallow_peer_from_ssl_auth_context(ctx.get());
126   GPR_ASSERT(check_ssl_peer_equivalence(&peer, &rpeer));
127 
128   grpc_shallow_peer_destruct(&rpeer);
129   tsi_peer_destruct(&peer);
130   ctx.reset(DEBUG_LOCATION, "test");
131 }
132 
check_identity(const grpc_auth_context * ctx,const char * expected_property_name,const char ** expected_identities,size_t num_identities)133 static int check_identity(const grpc_auth_context* ctx,
134                           const char* expected_property_name,
135                           const char** expected_identities,
136                           size_t num_identities) {
137   grpc_auth_property_iterator it;
138   const grpc_auth_property* prop;
139   size_t i;
140   GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx));
141   it = grpc_auth_context_peer_identity(ctx);
142   for (i = 0; i < num_identities; i++) {
143     prop = grpc_auth_property_iterator_next(&it);
144     if (prop == nullptr) {
145       gpr_log(GPR_ERROR, "Expected identity value %s not found.",
146               expected_identities[i]);
147       return 0;
148     }
149     if (strcmp(prop->name, expected_property_name) != 0) {
150       gpr_log(GPR_ERROR, "Expected peer identity property name %s and got %s.",
151               expected_property_name, prop->name);
152       return 0;
153     }
154     if (strncmp(prop->value, expected_identities[i], prop->value_length) != 0) {
155       gpr_log(GPR_ERROR, "Expected peer identity %s and got %s.",
156               expected_identities[i], prop->value);
157       return 0;
158     }
159   }
160   return 1;
161 }
162 
check_x509_cn(const grpc_auth_context * ctx,const char * expected_cn)163 static int check_x509_cn(const grpc_auth_context* ctx,
164                          const char* expected_cn) {
165   grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name(
166       ctx, GRPC_X509_CN_PROPERTY_NAME);
167   const grpc_auth_property* prop = grpc_auth_property_iterator_next(&it);
168   if (prop == nullptr) {
169     gpr_log(GPR_ERROR, "CN property not found.");
170     return 0;
171   }
172   if (strncmp(prop->value, expected_cn, prop->value_length) != 0) {
173     gpr_log(GPR_ERROR, "Expected CN %s and got %s", expected_cn, prop->value);
174     return 0;
175   }
176   if (grpc_auth_property_iterator_next(&it) != nullptr) {
177     gpr_log(GPR_ERROR, "Expected only one property for CN.");
178     return 0;
179   }
180   return 1;
181 }
182 
check_x509_pem_cert(const grpc_auth_context * ctx,const char * expected_pem_cert)183 static int check_x509_pem_cert(const grpc_auth_context* ctx,
184                                const char* expected_pem_cert) {
185   grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name(
186       ctx, GRPC_X509_PEM_CERT_PROPERTY_NAME);
187   const grpc_auth_property* prop = grpc_auth_property_iterator_next(&it);
188   if (prop == nullptr) {
189     gpr_log(GPR_ERROR, "Pem certificate property not found.");
190     return 0;
191   }
192   if (strncmp(prop->value, expected_pem_cert, prop->value_length) != 0) {
193     gpr_log(GPR_ERROR, "Expected pem cert %s and got %s", expected_pem_cert,
194             prop->value);
195     return 0;
196   }
197   if (grpc_auth_property_iterator_next(&it) != nullptr) {
198     gpr_log(GPR_ERROR, "Expected only one property for pem cert.");
199     return 0;
200   }
201   return 1;
202 }
203 
check_x509_pem_cert_chain(const grpc_auth_context * ctx,const char * expected_pem_cert_chain)204 static int check_x509_pem_cert_chain(const grpc_auth_context* ctx,
205                                      const char* expected_pem_cert_chain) {
206   grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name(
207       ctx, GRPC_X509_PEM_CERT_CHAIN_PROPERTY_NAME);
208   const grpc_auth_property* prop = grpc_auth_property_iterator_next(&it);
209   if (prop == nullptr) {
210     gpr_log(GPR_ERROR, "Pem certificate chain property not found.");
211     return 0;
212   }
213   if (strncmp(prop->value, expected_pem_cert_chain, prop->value_length) != 0) {
214     gpr_log(GPR_ERROR, "Expected pem cert chain %s and got %s",
215             expected_pem_cert_chain, prop->value);
216     return 0;
217   }
218   if (grpc_auth_property_iterator_next(&it) != nullptr) {
219     gpr_log(GPR_ERROR, "Expected only one property for pem cert chain.");
220     return 0;
221   }
222   return 1;
223 }
224 
check_spiffe_id(const grpc_auth_context * ctx,const char * expected_spiffe_id,bool expect_spiffe_id)225 static int check_spiffe_id(const grpc_auth_context* ctx,
226                            const char* expected_spiffe_id,
227                            bool expect_spiffe_id) {
228   grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name(
229       ctx, GRPC_PEER_SPIFFE_ID_PROPERTY_NAME);
230   const grpc_auth_property* prop = grpc_auth_property_iterator_next(&it);
231   if (prop == nullptr && !expect_spiffe_id) {
232     return 1;
233   }
234   if (prop != nullptr && !expect_spiffe_id) {
235     gpr_log(GPR_ERROR, "SPIFFE ID not expected, but got %s.", prop->value);
236     return 0;
237   }
238   if (prop == nullptr && expect_spiffe_id) {
239     gpr_log(GPR_ERROR, "SPIFFE ID expected, but got nullptr.");
240     return 0;
241   }
242   if (strncmp(prop->value, expected_spiffe_id, prop->value_length) != 0) {
243     gpr_log(GPR_ERROR, "Expected SPIFFE ID %s but got %s.", expected_spiffe_id,
244             prop->value);
245     return 0;
246   }
247   if (grpc_auth_property_iterator_next(&it) != nullptr) {
248     gpr_log(GPR_ERROR, "Expected only one property for SPIFFE ID.");
249     return 0;
250   }
251   return 1;
252 }
253 
test_cn_only_ssl_peer_to_auth_context(void)254 static void test_cn_only_ssl_peer_to_auth_context(void) {
255   tsi_peer peer;
256   tsi_peer rpeer;
257   const char* expected_cn = "cn1";
258   const char* expected_pem_cert = "pem_cert1";
259   const char* expected_pem_cert_chain = "pem_cert1_chain";
260   GPR_ASSERT(tsi_construct_peer(5, &peer) == TSI_OK);
261   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
262                  TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE,
263                  &peer.properties[0]) == TSI_OK);
264   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
265                  TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, expected_cn,
266                  &peer.properties[1]) == TSI_OK);
267   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
268                  TSI_X509_PEM_CERT_PROPERTY, expected_pem_cert,
269                  &peer.properties[2]) == TSI_OK);
270   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
271                  TSI_SECURITY_LEVEL_PEER_PROPERTY,
272                  tsi_security_level_to_string(TSI_PRIVACY_AND_INTEGRITY),
273                  &peer.properties[3]) == TSI_OK);
274   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
275                  TSI_X509_PEM_CERT_CHAIN_PROPERTY, expected_pem_cert_chain,
276                  &peer.properties[4]) == TSI_OK);
277   grpc_core::RefCountedPtr<grpc_auth_context> ctx =
278       grpc_ssl_peer_to_auth_context(&peer, GRPC_SSL_TRANSPORT_SECURITY_TYPE);
279   GPR_ASSERT(ctx != nullptr);
280   GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx.get()));
281   GPR_ASSERT(
282       check_identity(ctx.get(), GRPC_X509_CN_PROPERTY_NAME, &expected_cn, 1));
283   GPR_ASSERT(check_transport_security_type(ctx.get()));
284   GPR_ASSERT(check_x509_cn(ctx.get(), expected_cn));
285   GPR_ASSERT(check_x509_pem_cert(ctx.get(), expected_pem_cert));
286   GPR_ASSERT(check_x509_pem_cert_chain(ctx.get(), expected_pem_cert_chain));
287 
288   rpeer = grpc_shallow_peer_from_ssl_auth_context(ctx.get());
289   GPR_ASSERT(check_ssl_peer_equivalence(&peer, &rpeer));
290 
291   grpc_shallow_peer_destruct(&rpeer);
292   tsi_peer_destruct(&peer);
293   ctx.reset(DEBUG_LOCATION, "test");
294 }
295 
test_cn_and_one_san_ssl_peer_to_auth_context(void)296 static void test_cn_and_one_san_ssl_peer_to_auth_context(void) {
297   tsi_peer peer;
298   tsi_peer rpeer;
299   const char* expected_cn = "cn1";
300   const char* expected_san = "san1";
301   const char* expected_pem_cert = "pem_cert1";
302   const char* expected_pem_cert_chain = "pem_cert1_chain";
303   GPR_ASSERT(tsi_construct_peer(6, &peer) == TSI_OK);
304   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
305                  TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE,
306                  &peer.properties[0]) == 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[1]) == TSI_OK);
310   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
311                  TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, expected_san,
312                  &peer.properties[2]) == TSI_OK);
313   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
314                  TSI_X509_PEM_CERT_PROPERTY, expected_pem_cert,
315                  &peer.properties[3]) == TSI_OK);
316   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
317                  TSI_SECURITY_LEVEL_PEER_PROPERTY,
318                  tsi_security_level_to_string(TSI_PRIVACY_AND_INTEGRITY),
319                  &peer.properties[4]) == TSI_OK);
320   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
321                  TSI_X509_PEM_CERT_CHAIN_PROPERTY, expected_pem_cert_chain,
322                  &peer.properties[5]) == TSI_OK);
323   grpc_core::RefCountedPtr<grpc_auth_context> ctx =
324       grpc_ssl_peer_to_auth_context(&peer, GRPC_SSL_TRANSPORT_SECURITY_TYPE);
325   GPR_ASSERT(ctx != nullptr);
326   GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx.get()));
327   GPR_ASSERT(
328       check_identity(ctx.get(), GRPC_X509_SAN_PROPERTY_NAME, &expected_san, 1));
329   GPR_ASSERT(check_transport_security_type(ctx.get()));
330   GPR_ASSERT(check_x509_cn(ctx.get(), expected_cn));
331   GPR_ASSERT(check_x509_pem_cert(ctx.get(), expected_pem_cert));
332   GPR_ASSERT(check_x509_pem_cert_chain(ctx.get(), expected_pem_cert_chain));
333 
334   rpeer = grpc_shallow_peer_from_ssl_auth_context(ctx.get());
335   GPR_ASSERT(check_ssl_peer_equivalence(&peer, &rpeer));
336 
337   grpc_shallow_peer_destruct(&rpeer);
338   tsi_peer_destruct(&peer);
339   ctx.reset(DEBUG_LOCATION, "test");
340 }
341 
test_cn_and_multiple_sans_ssl_peer_to_auth_context(void)342 static void test_cn_and_multiple_sans_ssl_peer_to_auth_context(void) {
343   tsi_peer peer;
344   tsi_peer rpeer;
345   const char* expected_cn = "cn1";
346   const char* expected_sans[] = {"san1", "san2", "san3"};
347   const char* expected_pem_cert = "pem_cert1";
348   const char* expected_pem_cert_chain = "pem_cert1_chain";
349   size_t i;
350   GPR_ASSERT(tsi_construct_peer(5 + GPR_ARRAY_SIZE(expected_sans), &peer) ==
351              TSI_OK);
352   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
353                  TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE,
354                  &peer.properties[0]) == TSI_OK);
355   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
356                  TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, expected_cn,
357                  &peer.properties[1]) == TSI_OK);
358   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
359                  TSI_X509_PEM_CERT_PROPERTY, expected_pem_cert,
360                  &peer.properties[2]) == TSI_OK);
361   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
362                  TSI_SECURITY_LEVEL_PEER_PROPERTY,
363                  tsi_security_level_to_string(TSI_PRIVACY_AND_INTEGRITY),
364                  &peer.properties[3]) == TSI_OK);
365   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
366                  TSI_X509_PEM_CERT_CHAIN_PROPERTY, expected_pem_cert_chain,
367                  &peer.properties[4]) == TSI_OK);
368   for (i = 0; i < GPR_ARRAY_SIZE(expected_sans); i++) {
369     GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
370                    TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY,
371                    expected_sans[i], &peer.properties[5 + i]) == TSI_OK);
372   }
373   grpc_core::RefCountedPtr<grpc_auth_context> ctx =
374       grpc_ssl_peer_to_auth_context(&peer, GRPC_SSL_TRANSPORT_SECURITY_TYPE);
375   GPR_ASSERT(ctx != nullptr);
376   GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx.get()));
377   GPR_ASSERT(check_identity(ctx.get(), GRPC_X509_SAN_PROPERTY_NAME,
378                             expected_sans, GPR_ARRAY_SIZE(expected_sans)));
379   GPR_ASSERT(check_transport_security_type(ctx.get()));
380   GPR_ASSERT(check_x509_cn(ctx.get(), expected_cn));
381   GPR_ASSERT(check_x509_pem_cert(ctx.get(), expected_pem_cert));
382   GPR_ASSERT(check_x509_pem_cert_chain(ctx.get(), expected_pem_cert_chain));
383 
384   rpeer = grpc_shallow_peer_from_ssl_auth_context(ctx.get());
385   GPR_ASSERT(check_ssl_peer_equivalence(&peer, &rpeer));
386 
387   grpc_shallow_peer_destruct(&rpeer);
388   tsi_peer_destruct(&peer);
389   ctx.reset(DEBUG_LOCATION, "test");
390 }
391 
test_cn_and_multiple_sans_and_others_ssl_peer_to_auth_context(void)392 static void test_cn_and_multiple_sans_and_others_ssl_peer_to_auth_context(
393     void) {
394   tsi_peer peer;
395   tsi_peer rpeer;
396   const char* expected_cn = "cn1";
397   const char* expected_pem_cert = "pem_cert1";
398   const char* expected_pem_cert_chain = "pem_cert1_chain";
399   const char* expected_sans[] = {"san1", "san2", "san3"};
400   size_t i;
401   GPR_ASSERT(tsi_construct_peer(7 + GPR_ARRAY_SIZE(expected_sans), &peer) ==
402              TSI_OK);
403   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
404                  TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE,
405                  &peer.properties[0]) == TSI_OK);
406   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
407                  "foo", "bar", &peer.properties[1]) == TSI_OK);
408   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
409                  TSI_X509_SUBJECT_COMMON_NAME_PEER_PROPERTY, expected_cn,
410                  &peer.properties[2]) == TSI_OK);
411   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
412                  "chapi", "chapo", &peer.properties[3]) == TSI_OK);
413   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
414                  TSI_X509_PEM_CERT_PROPERTY, expected_pem_cert,
415                  &peer.properties[4]) == TSI_OK);
416   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
417                  TSI_SECURITY_LEVEL_PEER_PROPERTY,
418                  tsi_security_level_to_string(TSI_PRIVACY_AND_INTEGRITY),
419                  &peer.properties[5]) == TSI_OK);
420   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
421                  TSI_X509_PEM_CERT_CHAIN_PROPERTY, expected_pem_cert_chain,
422                  &peer.properties[6]) == TSI_OK);
423   for (i = 0; i < GPR_ARRAY_SIZE(expected_sans); i++) {
424     GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
425                    TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY,
426                    expected_sans[i], &peer.properties[7 + i]) == TSI_OK);
427   }
428   grpc_core::RefCountedPtr<grpc_auth_context> ctx =
429       grpc_ssl_peer_to_auth_context(&peer, GRPC_SSL_TRANSPORT_SECURITY_TYPE);
430   GPR_ASSERT(ctx != nullptr);
431   GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx.get()));
432   GPR_ASSERT(check_identity(ctx.get(), GRPC_X509_SAN_PROPERTY_NAME,
433                             expected_sans, GPR_ARRAY_SIZE(expected_sans)));
434   GPR_ASSERT(check_transport_security_type(ctx.get()));
435   GPR_ASSERT(check_x509_cn(ctx.get(), expected_cn));
436   GPR_ASSERT(check_x509_pem_cert(ctx.get(), expected_pem_cert));
437   GPR_ASSERT(check_x509_pem_cert_chain(ctx.get(), expected_pem_cert_chain));
438 
439   rpeer = grpc_shallow_peer_from_ssl_auth_context(ctx.get());
440   GPR_ASSERT(check_ssl_peer_equivalence(&peer, &rpeer));
441 
442   grpc_shallow_peer_destruct(&rpeer);
443   tsi_peer_destruct(&peer);
444   ctx.reset(DEBUG_LOCATION, "test");
445 }
446 
test_spiffe_id_peer_to_auth_context(void)447 static void test_spiffe_id_peer_to_auth_context(void) {
448   // Invalid SPIFFE IDs should not be plumbed.
449   std::string long_id(2050, 'x');
450   std::string long_domain(256, 'x');
451   tsi_peer invalid_peer;
452   std::vector<std::string> invalid_spiffe_id = {
453       "",
454       "spi://",
455       "sfiffe://domain/wl",
456       "spiffe://domain",
457       "spiffe://domain/",
458       long_id,
459       "spiffe://" + long_domain + "/wl"};
460   size_t i;
461   GPR_ASSERT(tsi_construct_peer(invalid_spiffe_id.size(), &invalid_peer) ==
462              TSI_OK);
463   for (i = 0; i < invalid_spiffe_id.size(); i++) {
464     GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
465                    TSI_X509_URI_PEER_PROPERTY, invalid_spiffe_id[i].c_str(),
466                    &invalid_peer.properties[i]) == TSI_OK);
467   }
468   grpc_core::RefCountedPtr<grpc_auth_context> invalid_ctx =
469       grpc_ssl_peer_to_auth_context(&invalid_peer,
470                                     GRPC_SSL_TRANSPORT_SECURITY_TYPE);
471   GPR_ASSERT(invalid_ctx != nullptr);
472   GPR_ASSERT(check_spiffe_id(invalid_ctx.get(), nullptr, false));
473   tsi_peer_destruct(&invalid_peer);
474   invalid_ctx.reset(DEBUG_LOCATION, "test");
475   // A valid SPIFFE ID should be plumbed.
476   tsi_peer valid_peer;
477   std::string valid_spiffe_id = "spiffe://foo.bar.com/wl";
478   GPR_ASSERT(tsi_construct_peer(1, &valid_peer) == TSI_OK);
479   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
480                  TSI_X509_URI_PEER_PROPERTY, valid_spiffe_id.c_str(),
481                  &valid_peer.properties[0]) == TSI_OK);
482   grpc_core::RefCountedPtr<grpc_auth_context> valid_ctx =
483       grpc_ssl_peer_to_auth_context(&valid_peer,
484                                     GRPC_SSL_TRANSPORT_SECURITY_TYPE);
485   GPR_ASSERT(valid_ctx != nullptr);
486   GPR_ASSERT(check_spiffe_id(valid_ctx.get(), "spiffe://foo.bar.com/wl", true));
487   tsi_peer_destruct(&valid_peer);
488   valid_ctx.reset(DEBUG_LOCATION, "test");
489   // Multiple SPIFFE IDs should not be plumbed.
490   tsi_peer multiple_peer;
491   std::vector<std::string> multiple_spiffe_id = {
492       "spiffe://foo.bar.com/wl", "https://xyz", "spiffe://foo.bar.com/wl2"};
493   GPR_ASSERT(tsi_construct_peer(multiple_spiffe_id.size(), &multiple_peer) ==
494              TSI_OK);
495   for (i = 0; i < multiple_spiffe_id.size(); i++) {
496     GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
497                    TSI_X509_URI_PEER_PROPERTY, multiple_spiffe_id[i].c_str(),
498                    &multiple_peer.properties[i]) == TSI_OK);
499   }
500   grpc_core::RefCountedPtr<grpc_auth_context> multiple_ctx =
501       grpc_ssl_peer_to_auth_context(&multiple_peer,
502                                     GRPC_SSL_TRANSPORT_SECURITY_TYPE);
503   GPR_ASSERT(multiple_ctx != nullptr);
504   GPR_ASSERT(check_spiffe_id(multiple_ctx.get(), nullptr, false));
505   tsi_peer_destruct(&multiple_peer);
506   multiple_ctx.reset(DEBUG_LOCATION, "test");
507   // A valid SPIFFE certificate should only has one URI SAN field.
508   // SPIFFE ID should not be plumbed if there are multiple URIs.
509   tsi_peer multiple_uri_peer;
510   std::vector<std::string> multiple_uri = {"spiffe://foo.bar.com/wl",
511                                            "https://xyz", "ssh://foo.bar.com/"};
512   GPR_ASSERT(tsi_construct_peer(multiple_uri.size(), &multiple_uri_peer) ==
513              TSI_OK);
514   for (i = 0; i < multiple_spiffe_id.size(); i++) {
515     GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
516                    TSI_X509_URI_PEER_PROPERTY, multiple_uri[i].c_str(),
517                    &multiple_uri_peer.properties[i]) == TSI_OK);
518   }
519   grpc_core::RefCountedPtr<grpc_auth_context> multiple_uri_ctx =
520       grpc_ssl_peer_to_auth_context(&multiple_uri_peer,
521                                     GRPC_SSL_TRANSPORT_SECURITY_TYPE);
522   GPR_ASSERT(multiple_uri_ctx != nullptr);
523   GPR_ASSERT(check_spiffe_id(multiple_uri_ctx.get(), nullptr, false));
524   tsi_peer_destruct(&multiple_uri_peer);
525   multiple_uri_ctx.reset(DEBUG_LOCATION, "test");
526 }
527 
528 static const char* roots_for_override_api = "roots for override api";
529 
override_roots_success(char ** pem_root_certs)530 static grpc_ssl_roots_override_result override_roots_success(
531     char** pem_root_certs) {
532   *pem_root_certs = gpr_strdup(roots_for_override_api);
533   return GRPC_SSL_ROOTS_OVERRIDE_OK;
534 }
535 
override_roots_permanent_failure(char **)536 static grpc_ssl_roots_override_result override_roots_permanent_failure(
537     char** /*pem_root_certs*/) {
538   return GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY;
539 }
540 
test_ipv6_address_san(void)541 static void test_ipv6_address_san(void) {
542   const char* addresses[] = {
543       "2001:db8::1",     "fe80::abcd:ef65:4321%em0", "fd11:feed:beef:0:cafe::4",
544       "128.10.0.1:8888", "[2001:db8::1]:8080",       "[2001:db8::1%em1]:8080",
545   };
546   const char* san_ips[] = {
547       "2001:db8::1", "fe80::abcd:ef65:4321", "fd11:feed:beef:0:cafe::4",
548       "128.10.0.1",  "2001:db8::1",          "2001:db8::1",
549   };
550   tsi_peer peer;
551   GPR_ASSERT(tsi_construct_peer(1, &peer) == TSI_OK);
552   for (size_t i = 0; i < GPR_ARRAY_SIZE(addresses); i++) {
553     GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
554                    TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, san_ips[i],
555                    &peer.properties[0]) == TSI_OK);
556     GPR_ASSERT(grpc_ssl_host_matches_name(&peer, addresses[i]));
557     tsi_peer_property_destruct(&peer.properties[0]);
558   }
559   tsi_peer_destruct(&peer);
560 }
561 namespace grpc_core {
562 namespace {
563 
564 class TestDefaultSslRootStore : public DefaultSslRootStore {
565  public:
ComputePemRootCertsForTesting()566   static grpc_slice ComputePemRootCertsForTesting() {
567     return ComputePemRootCerts();
568   }
569 };
570 
571 }  // namespace
572 }  // namespace grpc_core
573 
574 // TODO: Convert this test to C++ test when security_connector implementation
575 // is converted to C++.
test_default_ssl_roots(void)576 static void test_default_ssl_roots(void) {
577   const char* roots_for_env_var = "roots for env var";
578 
579   char* roots_env_var_file_path;
580   FILE* roots_env_var_file =
581       gpr_tmpfile("test_roots_for_env_var", &roots_env_var_file_path);
582   fwrite(roots_for_env_var, 1, strlen(roots_for_env_var), roots_env_var_file);
583   fclose(roots_env_var_file);
584 
585   /* First let's get the root through the override: set the env to an invalid
586      value. */
587   GPR_GLOBAL_CONFIG_SET(grpc_default_ssl_roots_file_path, "");
588   grpc_set_ssl_roots_override_callback(override_roots_success);
589   grpc_slice roots =
590       grpc_core::TestDefaultSslRootStore::ComputePemRootCertsForTesting();
591   char* roots_contents = grpc_slice_to_c_string(roots);
592   grpc_slice_unref(roots);
593   GPR_ASSERT(strcmp(roots_contents, roots_for_override_api) == 0);
594   gpr_free(roots_contents);
595 
596   /* Now let's set the env var: We should get the contents pointed value
597      instead. */
598   GPR_GLOBAL_CONFIG_SET(grpc_default_ssl_roots_file_path,
599                         roots_env_var_file_path);
600   roots = grpc_core::TestDefaultSslRootStore::ComputePemRootCertsForTesting();
601   roots_contents = grpc_slice_to_c_string(roots);
602   grpc_slice_unref(roots);
603   GPR_ASSERT(strcmp(roots_contents, roots_for_env_var) == 0);
604   gpr_free(roots_contents);
605 
606   /* Now reset the env var. We should fall back to the value overridden using
607      the api. */
608   GPR_GLOBAL_CONFIG_SET(grpc_default_ssl_roots_file_path, "");
609   roots = grpc_core::TestDefaultSslRootStore::ComputePemRootCertsForTesting();
610   roots_contents = grpc_slice_to_c_string(roots);
611   grpc_slice_unref(roots);
612   GPR_ASSERT(strcmp(roots_contents, roots_for_override_api) == 0);
613   gpr_free(roots_contents);
614 
615   /* Now setup a permanent failure for the overridden roots and we should get
616      an empty slice. */
617   GPR_GLOBAL_CONFIG_SET(grpc_not_use_system_ssl_roots, true);
618   grpc_set_ssl_roots_override_callback(override_roots_permanent_failure);
619   roots = grpc_core::TestDefaultSslRootStore::ComputePemRootCertsForTesting();
620   GPR_ASSERT(GRPC_SLICE_IS_EMPTY(roots));
621   const tsi_ssl_root_certs_store* root_store =
622       grpc_core::TestDefaultSslRootStore::GetRootStore();
623   GPR_ASSERT(root_store == nullptr);
624 
625   /* Cleanup. */
626   remove(roots_env_var_file_path);
627   gpr_free(roots_env_var_file_path);
628 }
629 
test_peer_alpn_check(void)630 static void test_peer_alpn_check(void) {
631 #if TSI_OPENSSL_ALPN_SUPPORT
632   tsi_peer peer;
633   const char* alpn = "grpc";
634   const char* wrong_alpn = "wrong";
635   // peer does not have a TSI_SSL_ALPN_SELECTED_PROTOCOL property.
636   GPR_ASSERT(tsi_construct_peer(1, &peer) == TSI_OK);
637   GPR_ASSERT(tsi_construct_string_peer_property("wrong peer property name",
638                                                 alpn, strlen(alpn),
639                                                 &peer.properties[0]) == TSI_OK);
640   grpc_error* error = grpc_ssl_check_alpn(&peer);
641   GPR_ASSERT(error != GRPC_ERROR_NONE);
642   tsi_peer_destruct(&peer);
643   GRPC_ERROR_UNREF(error);
644   // peer has a TSI_SSL_ALPN_SELECTED_PROTOCOL property but with an incorrect
645   // property value.
646   GPR_ASSERT(tsi_construct_peer(1, &peer) == TSI_OK);
647   GPR_ASSERT(tsi_construct_string_peer_property(TSI_SSL_ALPN_SELECTED_PROTOCOL,
648                                                 wrong_alpn, strlen(wrong_alpn),
649                                                 &peer.properties[0]) == TSI_OK);
650   error = grpc_ssl_check_alpn(&peer);
651   GPR_ASSERT(error != GRPC_ERROR_NONE);
652   tsi_peer_destruct(&peer);
653   GRPC_ERROR_UNREF(error);
654   // peer has a TSI_SSL_ALPN_SELECTED_PROTOCOL property with a correct property
655   // value.
656   GPR_ASSERT(tsi_construct_peer(1, &peer) == TSI_OK);
657   GPR_ASSERT(tsi_construct_string_peer_property(TSI_SSL_ALPN_SELECTED_PROTOCOL,
658                                                 alpn, strlen(alpn),
659                                                 &peer.properties[0]) == TSI_OK);
660   GPR_ASSERT(grpc_ssl_check_alpn(&peer) == GRPC_ERROR_NONE);
661   tsi_peer_destruct(&peer);
662 #else
663   GPR_ASSERT(grpc_ssl_check_alpn(nullptr) == GRPC_ERROR_NONE);
664 #endif
665 }
666 
main(int argc,char ** argv)667 int main(int argc, char** argv) {
668   grpc::testing::TestEnvironment env(argc, argv);
669   grpc_init();
670   test_unauthenticated_ssl_peer();
671   test_cn_only_ssl_peer_to_auth_context();
672   test_cn_and_one_san_ssl_peer_to_auth_context();
673   test_cn_and_multiple_sans_ssl_peer_to_auth_context();
674   test_cn_and_multiple_sans_and_others_ssl_peer_to_auth_context();
675   test_spiffe_id_peer_to_auth_context();
676   test_ipv6_address_san();
677   test_default_ssl_roots();
678   test_peer_alpn_check();
679   test_check_security_level();
680   grpc_shutdown();
681   return 0;
682 }
683