v3name_test.cc
Go to the documentation of this file.
1 /*
2  * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
3  * 1999.
4  */
5 /* ====================================================================
6  * Copyright (c) 1999-2004 The OpenSSL Project. All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  * software must display the following acknowledgment:
22  * "This product includes software developed by the OpenSSL Project
23  * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  * endorse or promote products derived from this software without
27  * prior written permission. For written permission, please contact
28  * licensing@OpenSSL.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  * nor may "OpenSSL" appear in their names without prior written
32  * permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  * acknowledgment:
36  * "This product includes software developed by the OpenSSL Project
37  * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  *
53  * This product includes cryptographic software written by Eric Young
54  * (eay@cryptsoft.com). This product includes software written by Tim
55  * Hudson (tjh@cryptsoft.com). */
56 
57 #include <stdarg.h>
58 #include <string.h>
59 
60 #include <gtest/gtest.h>
61 
62 #include <openssl/crypto.h>
63 #include <openssl/mem.h>
64 #include <openssl/x509.h>
65 #include <openssl/x509v3.h>
66 
67 #include "../internal.h"
68 #include "internal.h"
69 
70 
71 static const char *const names[] = {
72  "a", "b", ".", "*", "@",
73  ".a", "a.", ".b", "b.", ".*", "*.", "*@", "@*", "a@", "@a", "b@", "..",
74  "-example.com", "example-.com",
75  "@@", "**", "*.com", "*com", "*.*.com", "*com", "com*", "*example.com",
76  "*@example.com", "test@*.example.com", "example.com", "www.example.com",
77  "test.www.example.com", "*.example.com", "*.www.example.com",
78  "test.*.example.com", "www.*.com",
79  ".www.example.com", "*www.example.com",
80  "example.net", "xn--rger-koa.example.com",
81  "*.xn--rger-koa.example.com", "www.xn--rger-koa.example.com",
82  "*.good--example.com", "www.good--example.com",
83  "*.xn--bar.com", "xn--foo.xn--bar.com",
84  "a.example.com", "b.example.com",
85  "postmaster@example.com", "Postmaster@example.com",
86  "postmaster@EXAMPLE.COM",
87  NULL
88 };
89 
90 static const char *const exceptions[] = {
91  "set CN: host: [*.example.com] matches [a.example.com]",
92  "set CN: host: [*.example.com] matches [b.example.com]",
93  "set CN: host: [*.example.com] matches [www.example.com]",
94  "set CN: host: [*.example.com] matches [xn--rger-koa.example.com]",
95  "set CN: host: [*.www.example.com] matches [test.www.example.com]",
96  "set CN: host: [*.www.example.com] matches [.www.example.com]",
97  "set CN: host: [*www.example.com] matches [www.example.com]",
98  "set CN: host: [test.www.example.com] matches [.www.example.com]",
99  "set CN: host: [*.xn--rger-koa.example.com] matches [www.xn--rger-koa.example.com]",
100  "set CN: host: [*.xn--bar.com] matches [xn--foo.xn--bar.com]",
101  "set CN: host: [*.good--example.com] matches [www.good--example.com]",
102  "set CN: host-no-wildcards: [*.www.example.com] matches [.www.example.com]",
103  "set CN: host-no-wildcards: [test.www.example.com] matches [.www.example.com]",
104  "set emailAddress: email: [postmaster@example.com] does not match [Postmaster@example.com]",
105  "set emailAddress: email: [postmaster@EXAMPLE.COM] does not match [Postmaster@example.com]",
106  "set emailAddress: email: [Postmaster@example.com] does not match [postmaster@example.com]",
107  "set emailAddress: email: [Postmaster@example.com] does not match [postmaster@EXAMPLE.COM]",
108  "set dnsName: host: [*.example.com] matches [www.example.com]",
109  "set dnsName: host: [*.example.com] matches [a.example.com]",
110  "set dnsName: host: [*.example.com] matches [b.example.com]",
111  "set dnsName: host: [*.example.com] matches [xn--rger-koa.example.com]",
112  "set dnsName: host: [*.www.example.com] matches [test.www.example.com]",
113  "set dnsName: host-no-wildcards: [*.www.example.com] matches [.www.example.com]",
114  "set dnsName: host-no-wildcards: [test.www.example.com] matches [.www.example.com]",
115  "set dnsName: host: [*.www.example.com] matches [.www.example.com]",
116  "set dnsName: host: [*www.example.com] matches [www.example.com]",
117  "set dnsName: host: [test.www.example.com] matches [.www.example.com]",
118  "set dnsName: host: [*.xn--rger-koa.example.com] matches [www.xn--rger-koa.example.com]",
119  "set dnsName: host: [*.xn--bar.com] matches [xn--foo.xn--bar.com]",
120  "set dnsName: host: [*.good--example.com] matches [www.good--example.com]",
121  "set rfc822Name: email: [postmaster@example.com] does not match [Postmaster@example.com]",
122  "set rfc822Name: email: [Postmaster@example.com] does not match [postmaster@example.com]",
123  "set rfc822Name: email: [Postmaster@example.com] does not match [postmaster@EXAMPLE.COM]",
124  "set rfc822Name: email: [postmaster@EXAMPLE.COM] does not match [Postmaster@example.com]",
125  NULL
126 };
127 
128 static int is_exception(const char *msg)
129 {
130  const char *const *p;
131  for (p = exceptions; *p; ++p)
132  if (strcmp(msg, *p) == 0)
133  return 1;
134  return 0;
135 }
136 
137 static int set_cn(X509 *crt, ...)
138 {
139  int ret = 0;
140  X509_NAME *n = NULL;
141  va_list ap;
142  va_start(ap, crt);
143  n = X509_NAME_new();
144  if (n == NULL)
145  goto out;
146  while (1) {
147  int nid;
148  const char *name;
149  nid = va_arg(ap, int);
150  if (nid == 0)
151  break;
152  name = va_arg(ap, const char *);
154  (unsigned char *)name, -1, -1, 1))
155  goto out;
156  }
157  if (!X509_set_subject_name(crt, n))
158  goto out;
159  ret = 1;
160  out:
161  X509_NAME_free(n);
162  va_end(ap);
163  return ret;
164 }
165 
166 /*
167  * int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc); X509_EXTENSION
168  * *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex, int nid, int crit,
169  * ASN1_OCTET_STRING *data); int X509_add_ext(X509 *x, X509_EXTENSION *ex,
170  * int loc);
171  */
172 
173 static int set_altname(X509 *crt, ...)
174 {
175  int ret = 0;
176  GENERAL_NAMES *gens = NULL;
177  GENERAL_NAME *gen = NULL;
178  ASN1_IA5STRING *ia5 = NULL;
179  va_list ap;
180  va_start(ap, crt);
181  gens = sk_GENERAL_NAME_new_null();
182  if (gens == NULL)
183  goto out;
184  while (1) {
185  int type;
186  const char *name;
187  type = va_arg(ap, int);
188  if (type == 0)
189  break;
190  name = va_arg(ap, const char *);
191 
192  gen = GENERAL_NAME_new();
193  if (gen == NULL)
194  goto out;
195  ia5 = ASN1_IA5STRING_new();
196  if (ia5 == NULL)
197  goto out;
198  if (!ASN1_STRING_set(ia5, name, -1))
199  goto out;
200  switch (type) {
201  case GEN_EMAIL:
202  case GEN_DNS:
204  ia5 = NULL;
205  break;
206  default:
207  abort();
208  }
209  sk_GENERAL_NAME_push(gens, gen);
210  gen = NULL;
211  }
212  if (!X509_add1_ext_i2d(crt, NID_subject_alt_name, gens, 0, 0))
213  goto out;
214  ret = 1;
215  out:
216  ASN1_IA5STRING_free(ia5);
218  GENERAL_NAMES_free(gens);
219  va_end(ap);
220  return ret;
221 }
222 
223 static int set_cn1(X509 *crt, const char *name)
224 {
225  return set_cn(crt, NID_commonName, name, 0);
226 }
227 
228 static int set_cn_and_email(X509 *crt, const char *name)
229 {
230  return set_cn(crt, NID_commonName, name,
231  NID_pkcs9_emailAddress, "dummy@example.com", 0);
232 }
233 
234 static int set_cn2(X509 *crt, const char *name)
235 {
236  return set_cn(crt, NID_commonName, "dummy value",
237  NID_commonName, name, 0);
238 }
239 
240 static int set_cn3(X509 *crt, const char *name)
241 {
242  return set_cn(crt, NID_commonName, name,
243  NID_commonName, "dummy value", 0);
244 }
245 
246 static int set_email1(X509 *crt, const char *name)
247 {
248  return set_cn(crt, NID_pkcs9_emailAddress, name, 0);
249 }
250 
251 static int set_email2(X509 *crt, const char *name)
252 {
253  return set_cn(crt, NID_pkcs9_emailAddress, "dummy@example.com",
255 }
256 
257 static int set_email3(X509 *crt, const char *name)
258 {
259  return set_cn(crt, NID_pkcs9_emailAddress, name,
260  NID_pkcs9_emailAddress, "dummy@example.com", 0);
261 }
262 
263 static int set_email_and_cn(X509 *crt, const char *name)
264 {
265  return set_cn(crt, NID_pkcs9_emailAddress, name,
266  NID_commonName, "www.example.org", 0);
267 }
268 
269 static int set_altname_dns(X509 *crt, const char *name)
270 {
271  return set_altname(crt, GEN_DNS, name, 0);
272 }
273 
274 static int set_altname_email(X509 *crt, const char *name)
275 {
276  return set_altname(crt, GEN_EMAIL, name, 0);
277 }
278 
279 struct set_name_fn {
280  int (*fn) (X509 *, const char *);
281  const char *name;
282  int host;
283  int email;
284 };
285 
286 static const struct set_name_fn name_fns[] = {
287  {set_cn1, "set CN", 1, 0},
288  {set_cn2, "set CN", 1, 0},
289  {set_cn3, "set CN", 1, 0},
290  {set_cn_and_email, "set CN", 1, 0},
291  {set_email1, "set emailAddress", 0, 1},
292  {set_email2, "set emailAddress", 0, 1},
293  {set_email3, "set emailAddress", 0, 1},
294  {set_email_and_cn, "set emailAddress", 0, 1},
295  {set_altname_dns, "set dnsName", 1, 0},
296  {set_altname_email, "set rfc822Name", 0, 1},
297  {NULL, NULL, 0, 0},
298 };
299 
300 static X509 *make_cert(void)
301 {
302  X509 *ret = NULL;
303  X509 *crt = NULL;
304  X509_NAME *issuer = NULL;
305  crt = X509_new();
306  if (crt == NULL)
307  goto out;
308  if (!X509_set_version(crt, X509_VERSION_3))
309  goto out;
310  ret = crt;
311  crt = NULL;
312  out:
313  X509_NAME_free(issuer);
314  return ret;
315 }
316 
317 static int errors;
318 
319 static void check_message(const struct set_name_fn *fn, const char *op,
320  const char *nameincert, int match, const char *name)
321 {
322  char msg[1024];
323  if (match < 0)
324  return;
325  BIO_snprintf(msg, sizeof(msg), "%s: %s: [%s] %s [%s]",
326  fn->name, op, nameincert,
327  match ? "matches" : "does not match", name);
328  if (is_exception(msg))
329  return;
330  puts(msg);
331  ++errors;
332 }
333 
334 static void run_cert(X509 *crt, const char *nameincert,
335  const struct set_name_fn *fn)
336 {
337  const char *const *pname = names;
338  while (*pname) {
339  int samename = OPENSSL_strcasecmp(nameincert, *pname) == 0;
340  size_t namelen = strlen(*pname);
341  char *name = (char *)malloc(namelen);
342  int match, ret;
343  OPENSSL_memcpy(name, *pname, namelen);
344 
345  ret = X509_check_host(crt, name, namelen, 0, NULL);
346  match = -1;
347  if (ret < 0) {
348  fprintf(stderr, "internal error in X509_check_host\n");
349  ++errors;
350  } else if (fn->host) {
351  if (ret == 1 && !samename)
352  match = 1;
353  if (ret == 0 && samename)
354  match = 0;
355  } else if (ret == 1)
356  match = 1;
357  check_message(fn, "host", nameincert, match, *pname);
358 
359  ret = X509_check_host(crt, name, namelen,
361  match = -1;
362  if (ret < 0) {
363  fprintf(stderr, "internal error in X509_check_host\n");
364  ++errors;
365  } else if (fn->host) {
366  if (ret == 1 && !samename)
367  match = 1;
368  if (ret == 0 && samename)
369  match = 0;
370  } else if (ret == 1)
371  match = 1;
372  check_message(fn, "host-no-wildcards", nameincert, match, *pname);
373 
374  ret = X509_check_email(crt, name, namelen, 0);
375  match = -1;
376  if (fn->email) {
377  if (ret && !samename)
378  match = 1;
379  if (!ret && samename && strchr(nameincert, '@') != NULL)
380  match = 0;
381  } else if (ret)
382  match = 1;
383  check_message(fn, "email", nameincert, match, *pname);
384  ++pname;
385  free(name);
386  }
387 }
388 
389 // TODO(davidben): Convert this test to GTest more thoroughly.
390 TEST(X509V3Test, NameTest) {
391  const struct set_name_fn *pfn = name_fns;
392  while (pfn->name) {
393  const char *const *pname = names;
394  while (*pname) {
395  // The common name fallback requires the name look sufficiently
396  // DNS-like.
397  if (strcmp(pfn->name, "set CN") == 0 &&
399  reinterpret_cast<const unsigned char*>(*pname),
400  strlen(*pname))) {
401  ++pname;
402  continue;
403  }
404  bssl::UniquePtr<X509> crt(make_cert());
405  ASSERT_TRUE(crt);
406  ASSERT_TRUE(pfn->fn(crt.get(), *pname));
407  run_cert(crt.get(), *pname, pfn);
408  ++pname;
409  }
410  ++pfn;
411  }
412  EXPECT_EQ(0, errors);
413 }
NID_pkcs9_emailAddress
#define NID_pkcs9_emailAddress
Definition: nid.h:304
set_cn1
static int set_cn1(X509 *crt, const char *name)
Definition: v3name_test.cc:223
gen_build_yaml.out
dictionary out
Definition: src/benchmark/gen_build_yaml.py:24
GENERAL_NAME_st
Definition: x509v3.h:173
ASN1_IA5STRING_free
OPENSSL_EXPORT void ASN1_IA5STRING_free(ASN1_IA5STRING *str)
set_cn
static int set_cn(X509 *crt,...)
Definition: v3name_test.cc:137
TEST
TEST(X509V3Test, NameTest)
Definition: v3name_test.cc:390
X509_NAME_add_entry_by_NID
#define X509_NAME_add_entry_by_NID
Definition: boringssl_prefix_symbols.h:2373
internal.h
match
unsigned char match[65280+2]
Definition: bloaty/third_party/zlib/examples/gun.c:165
string.h
set_altname
static int set_altname(X509 *crt,...)
Definition: v3name_test.cc:173
x509v3.h
X509_set_subject_name
#define X509_set_subject_name
Definition: boringssl_prefix_symbols.h:2717
setup.name
name
Definition: setup.py:542
set_cn3
static int set_cn3(X509 *crt, const char *name)
Definition: v3name_test.cc:240
errors
static int errors
Definition: v3name_test.cc:317
names
static const char *const names[]
Definition: v3name_test.cc:71
xds_manager.p
p
Definition: xds_manager.py:60
exceptions
static const char *const exceptions[]
Definition: v3name_test.cc:90
X509_NAME_free
#define X509_NAME_free
Definition: boringssl_prefix_symbols.h:2381
x509v3_looks_like_dns_name
#define x509v3_looks_like_dns_name
Definition: boringssl_prefix_symbols.h:3461
python_utils.port_server.stderr
stderr
Definition: port_server.py:51
X509_check_host
#define X509_check_host
Definition: boringssl_prefix_symbols.h:2616
EXPECT_EQ
#define EXPECT_EQ(a, b)
Definition: iomgr/time_averaged_stats_test.cc:27
set_email_and_cn
static int set_email_and_cn(X509 *crt, const char *name)
Definition: v3name_test.cc:263
ASN1_STRING_set
#define ASN1_STRING_set
Definition: boringssl_prefix_symbols.h:688
run_cert
static void run_cert(X509 *crt, const char *nameincert, const struct set_name_fn *fn)
Definition: v3name_test.cc:334
GEN_EMAIL
#define GEN_EMAIL
Definition: x509v3.h:175
GEN_DNS
#define GEN_DNS
Definition: x509v3.h:176
check_message
static void check_message(const struct set_name_fn *fn, const char *op, const char *nameincert, int match, const char *name)
Definition: v3name_test.cc:319
name_fns
static const struct set_name_fn name_fns[]
Definition: v3name_test.cc:286
NID_commonName
#define NID_commonName
Definition: nid.h:148
xds_interop_client.int
int
Definition: xds_interop_client.py:113
generate-asm-lcov.fn
fn
Definition: generate-asm-lcov.py:146
set_name_fn::name
const char * name
Definition: v3name_test.cc:281
GENERAL_NAME_set0_value
OPENSSL_EXPORT void GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, void *value)
OPENSSL_memcpy
static void * OPENSSL_memcpy(void *dst, const void *src, size_t n)
Definition: third_party/boringssl-with-bazel/src/crypto/internal.h:819
set_name_fn::fn
int(* fn)(X509 *, const char *)
Definition: v3name_test.cc:280
crypto.h
set_name_fn
Definition: v3name_test.cc:279
set_name_fn::host
int host
Definition: v3name_test.cc:282
gen
OPENSSL_EXPORT GENERAL_NAME * gen
Definition: x509v3.h:495
GENERAL_NAMES_free
#define GENERAL_NAMES_free
Definition: boringssl_prefix_symbols.h:1764
n
int n
Definition: abseil-cpp/absl/container/btree_test.cc:1080
BIO_snprintf
#define BIO_snprintf
Definition: boringssl_prefix_symbols.h:864
msg
std::string msg
Definition: client_interceptors_end2end_test.cc:372
X509_new
#define X509_new
Definition: boringssl_prefix_symbols.h:2687
nid
int nid
Definition: cipher_extra.c:71
GENERAL_NAME_free
#define GENERAL_NAME_free
Definition: boringssl_prefix_symbols.h:1769
set_email1
static int set_email1(X509 *crt, const char *name)
Definition: v3name_test.cc:246
GENERAL_NAME_new
#define GENERAL_NAME_new
Definition: boringssl_prefix_symbols.h:1773
x509_st
Definition: third_party/boringssl-with-bazel/src/crypto/x509/internal.h:139
set_email3
static int set_email3(X509 *crt, const char *name)
Definition: v3name_test.cc:257
ret
UniquePtr< SSL_SESSION > ret
Definition: ssl_x509.cc:1029
OPENSSL_strcasecmp
#define OPENSSL_strcasecmp
Definition: boringssl_prefix_symbols.h:1890
set_email2
static int set_email2(X509 *crt, const char *name)
Definition: v3name_test.cc:251
ASSERT_TRUE
#define ASSERT_TRUE(condition)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:1973
MBSTRING_ASC
#define MBSTRING_ASC
Definition: asn1.h:723
set_cn_and_email
static int set_cn_and_email(X509 *crt, const char *name)
Definition: v3name_test.cc:228
NID_subject_alt_name
#define NID_subject_alt_name
Definition: nid.h:474
set_altname_email
static int set_altname_email(X509 *crt, const char *name)
Definition: v3name_test.cc:274
X509_CHECK_FLAG_NO_WILDCARDS
#define X509_CHECK_FLAG_NO_WILDCARDS
Definition: x509v3.h:891
X509_add1_ext_i2d
#define X509_add1_ext_i2d
Definition: boringssl_prefix_symbols.h:2605
set_name_fn::email
int email
Definition: v3name_test.cc:283
is_exception
static int is_exception(const char *msg)
Definition: v3name_test.cc:128
set_altname_dns
static int set_altname_dns(X509 *crt, const char *name)
Definition: v3name_test.cc:269
mem.h
ASN1_IA5STRING_new
OPENSSL_EXPORT ASN1_IA5STRING * ASN1_IA5STRING_new(void)
X509_check_email
#define X509_check_email
Definition: boringssl_prefix_symbols.h:2615
asyncio_get_stats.type
type
Definition: asyncio_get_stats.py:37
X509_set_version
#define X509_set_version
Definition: boringssl_prefix_symbols.h:2718
X509_VERSION_3
#define X509_VERSION_3
Definition: x509.h:323
set_cn2
static int set_cn2(X509 *crt, const char *name)
Definition: v3name_test.cc:234
op
static grpc_op * op
Definition: test/core/fling/client.cc:47
X509_NAME_new
#define X509_NAME_new
Definition: boringssl_prefix_symbols.h:2391
X509_name_st
Definition: third_party/boringssl-with-bazel/src/crypto/x509/internal.h:95
asn1_string_st
Definition: asn1.h:543
make_cert
static X509 * make_cert(void)
Definition: v3name_test.cc:300
x509.h


grpc
Author(s):
autogenerated on Fri May 16 2025 03:00:50