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