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