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