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