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