github.com/ltltlt/go-source-code@v0.0.0-20190830023027-95be009773aa/crypto/x509/name_constraints_test.go (about)

     1  // Copyright 2017 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package x509
     6  
     7  import (
     8  	"bytes"
     9  	"crypto/ecdsa"
    10  	"crypto/elliptic"
    11  	"crypto/rand"
    12  	"crypto/x509/pkix"
    13  	"encoding/asn1"
    14  	"encoding/hex"
    15  	"encoding/pem"
    16  	"fmt"
    17  	"io/ioutil"
    18  	"math/big"
    19  	"net"
    20  	"net/url"
    21  	"os"
    22  	"os/exec"
    23  	"strconv"
    24  	"strings"
    25  	"sync"
    26  	"testing"
    27  	"time"
    28  )
    29  
    30  const (
    31  	// testNameConstraintsAgainstOpenSSL can be set to true to run tests
    32  	// against the system OpenSSL. This is disabled by default because Go
    33  	// cannot depend on having OpenSSL installed at testing time.
    34  	testNameConstraintsAgainstOpenSSL = false
    35  
    36  	// debugOpenSSLFailure can be set to true, when
    37  	// testNameConstraintsAgainstOpenSSL is also true, to cause
    38  	// intermediate files to be preserved for debugging.
    39  	debugOpenSSLFailure = false
    40  )
    41  
    42  type nameConstraintsTest struct {
    43  	roots         []constraintsSpec
    44  	intermediates [][]constraintsSpec
    45  	leaf          leafSpec
    46  	requestedEKUs []ExtKeyUsage
    47  	expectedError string
    48  	noOpenSSL     bool
    49  }
    50  
    51  type constraintsSpec struct {
    52  	ok   []string
    53  	bad  []string
    54  	ekus []string
    55  }
    56  
    57  type leafSpec struct {
    58  	sans []string
    59  	ekus []string
    60  }
    61  
    62  var nameConstraintsTests = []nameConstraintsTest{
    63  	// #0: dummy test for the certificate generation process itself.
    64  	nameConstraintsTest{
    65  		roots: []constraintsSpec{
    66  			constraintsSpec{},
    67  		},
    68  		leaf: leafSpec{
    69  			sans: []string{"dns:example.com"},
    70  		},
    71  	},
    72  
    73  	// #1: dummy test for the certificate generation process itself: single
    74  	// level of intermediate.
    75  	nameConstraintsTest{
    76  		roots: []constraintsSpec{
    77  			constraintsSpec{},
    78  		},
    79  		intermediates: [][]constraintsSpec{
    80  			[]constraintsSpec{
    81  				constraintsSpec{},
    82  			},
    83  		},
    84  		leaf: leafSpec{
    85  			sans: []string{"dns:example.com"},
    86  		},
    87  	},
    88  
    89  	// #2: dummy test for the certificate generation process itself: two
    90  	// levels of intermediates.
    91  	nameConstraintsTest{
    92  		roots: []constraintsSpec{
    93  			constraintsSpec{},
    94  		},
    95  		intermediates: [][]constraintsSpec{
    96  			[]constraintsSpec{
    97  				constraintsSpec{},
    98  			},
    99  			[]constraintsSpec{
   100  				constraintsSpec{},
   101  			},
   102  		},
   103  		leaf: leafSpec{
   104  			sans: []string{"dns:example.com"},
   105  		},
   106  	},
   107  
   108  	// #3: matching DNS constraint in root
   109  	nameConstraintsTest{
   110  		roots: []constraintsSpec{
   111  			constraintsSpec{
   112  				ok: []string{"dns:example.com"},
   113  			},
   114  		},
   115  		intermediates: [][]constraintsSpec{
   116  			[]constraintsSpec{
   117  				constraintsSpec{},
   118  			},
   119  		},
   120  		leaf: leafSpec{
   121  			sans: []string{"dns:example.com"},
   122  		},
   123  	},
   124  
   125  	// #4: matching DNS constraint in intermediate.
   126  	nameConstraintsTest{
   127  		roots: []constraintsSpec{
   128  			constraintsSpec{},
   129  		},
   130  		intermediates: [][]constraintsSpec{
   131  			[]constraintsSpec{
   132  				constraintsSpec{
   133  					ok: []string{"dns:example.com"},
   134  				},
   135  			},
   136  		},
   137  		leaf: leafSpec{
   138  			sans: []string{"dns:example.com"},
   139  		},
   140  	},
   141  
   142  	// #5: .example.com only matches subdomains.
   143  	nameConstraintsTest{
   144  		roots: []constraintsSpec{
   145  			constraintsSpec{
   146  				ok: []string{"dns:.example.com"},
   147  			},
   148  		},
   149  		intermediates: [][]constraintsSpec{
   150  			[]constraintsSpec{
   151  				constraintsSpec{},
   152  			},
   153  		},
   154  		leaf: leafSpec{
   155  			sans: []string{"dns:example.com"},
   156  		},
   157  		expectedError: "\"example.com\" is not permitted",
   158  	},
   159  
   160  	// #6: .example.com matches subdomains.
   161  	nameConstraintsTest{
   162  		roots: []constraintsSpec{
   163  			constraintsSpec{},
   164  		},
   165  		intermediates: [][]constraintsSpec{
   166  			[]constraintsSpec{
   167  				constraintsSpec{
   168  					ok: []string{"dns:.example.com"},
   169  				},
   170  			},
   171  		},
   172  		leaf: leafSpec{
   173  			sans: []string{"dns:foo.example.com"},
   174  		},
   175  	},
   176  
   177  	// #7: .example.com matches multiple levels of subdomains
   178  	nameConstraintsTest{
   179  		roots: []constraintsSpec{
   180  			constraintsSpec{
   181  				ok: []string{"dns:.example.com"},
   182  			},
   183  		},
   184  		intermediates: [][]constraintsSpec{
   185  			[]constraintsSpec{
   186  				constraintsSpec{},
   187  			},
   188  		},
   189  		leaf: leafSpec{
   190  			sans: []string{"dns:foo.bar.example.com"},
   191  		},
   192  	},
   193  
   194  	// #8: specifying a permitted list of names does not exclude other name
   195  	// types
   196  	nameConstraintsTest{
   197  		roots: []constraintsSpec{
   198  			constraintsSpec{
   199  				ok: []string{"dns:.example.com"},
   200  			},
   201  		},
   202  		intermediates: [][]constraintsSpec{
   203  			[]constraintsSpec{
   204  				constraintsSpec{},
   205  			},
   206  		},
   207  		leaf: leafSpec{
   208  			sans: []string{"ip:10.1.1.1"},
   209  		},
   210  	},
   211  
   212  	// #9: specifying a permitted list of names does not exclude other name
   213  	// types
   214  	nameConstraintsTest{
   215  		roots: []constraintsSpec{
   216  			constraintsSpec{
   217  				ok: []string{"ip:10.0.0.0/8"},
   218  			},
   219  		},
   220  		intermediates: [][]constraintsSpec{
   221  			[]constraintsSpec{
   222  				constraintsSpec{},
   223  			},
   224  		},
   225  		leaf: leafSpec{
   226  			sans: []string{"dns:example.com"},
   227  		},
   228  	},
   229  
   230  	// #10: intermediates can try to permit other names, which isn't
   231  	// forbidden if the leaf doesn't mention them. I.e. name constraints
   232  	// apply to names, not constraints themselves.
   233  	nameConstraintsTest{
   234  		roots: []constraintsSpec{
   235  			constraintsSpec{
   236  				ok: []string{"dns:example.com"},
   237  			},
   238  		},
   239  		intermediates: [][]constraintsSpec{
   240  			[]constraintsSpec{
   241  				constraintsSpec{
   242  					ok: []string{"dns:example.com", "dns:foo.com"},
   243  				},
   244  			},
   245  		},
   246  		leaf: leafSpec{
   247  			sans: []string{"dns:example.com"},
   248  		},
   249  	},
   250  
   251  	// #11: intermediates cannot add permitted names that the root doesn't
   252  	// grant them.
   253  	nameConstraintsTest{
   254  		roots: []constraintsSpec{
   255  			constraintsSpec{
   256  				ok: []string{"dns:example.com"},
   257  			},
   258  		},
   259  		intermediates: [][]constraintsSpec{
   260  			[]constraintsSpec{
   261  				constraintsSpec{
   262  					ok: []string{"dns:example.com", "dns:foo.com"},
   263  				},
   264  			},
   265  		},
   266  		leaf: leafSpec{
   267  			sans: []string{"dns:foo.com"},
   268  		},
   269  		expectedError: "\"foo.com\" is not permitted",
   270  	},
   271  
   272  	// #12: intermediates can further limit their scope if they wish.
   273  	nameConstraintsTest{
   274  		roots: []constraintsSpec{
   275  			constraintsSpec{
   276  				ok: []string{"dns:.example.com"},
   277  			},
   278  		},
   279  		intermediates: [][]constraintsSpec{
   280  			[]constraintsSpec{
   281  				constraintsSpec{
   282  					ok: []string{"dns:.bar.example.com"},
   283  				},
   284  			},
   285  		},
   286  		leaf: leafSpec{
   287  			sans: []string{"dns:foo.bar.example.com"},
   288  		},
   289  	},
   290  
   291  	// #13: intermediates can further limit their scope and that limitation
   292  	// is effective
   293  	nameConstraintsTest{
   294  		roots: []constraintsSpec{
   295  			constraintsSpec{
   296  				ok: []string{"dns:.example.com"},
   297  			},
   298  		},
   299  		intermediates: [][]constraintsSpec{
   300  			[]constraintsSpec{
   301  				constraintsSpec{
   302  					ok: []string{"dns:.bar.example.com"},
   303  				},
   304  			},
   305  		},
   306  		leaf: leafSpec{
   307  			sans: []string{"dns:foo.notbar.example.com"},
   308  		},
   309  		expectedError: "\"foo.notbar.example.com\" is not permitted",
   310  	},
   311  
   312  	// #14: roots can exclude subtrees and that doesn't affect other names.
   313  	nameConstraintsTest{
   314  		roots: []constraintsSpec{
   315  			constraintsSpec{
   316  				bad: []string{"dns:.example.com"},
   317  			},
   318  		},
   319  		intermediates: [][]constraintsSpec{
   320  			[]constraintsSpec{
   321  				constraintsSpec{},
   322  			},
   323  		},
   324  		leaf: leafSpec{
   325  			sans: []string{"dns:foo.com"},
   326  		},
   327  	},
   328  
   329  	// #15: roots exclusions are effective.
   330  	nameConstraintsTest{
   331  		roots: []constraintsSpec{
   332  			constraintsSpec{
   333  				bad: []string{"dns:.example.com"},
   334  			},
   335  		},
   336  		intermediates: [][]constraintsSpec{
   337  			[]constraintsSpec{
   338  				constraintsSpec{},
   339  			},
   340  		},
   341  		leaf: leafSpec{
   342  			sans: []string{"dns:foo.example.com"},
   343  		},
   344  		expectedError: "\"foo.example.com\" is excluded",
   345  	},
   346  
   347  	// #16: intermediates can also exclude names and that doesn't affect
   348  	// other names.
   349  	nameConstraintsTest{
   350  		roots: []constraintsSpec{
   351  			constraintsSpec{},
   352  		},
   353  		intermediates: [][]constraintsSpec{
   354  			[]constraintsSpec{
   355  				constraintsSpec{
   356  					bad: []string{"dns:.example.com"},
   357  				},
   358  			},
   359  		},
   360  		leaf: leafSpec{
   361  			sans: []string{"dns:foo.com"},
   362  		},
   363  	},
   364  
   365  	// #17: intermediate exclusions are effective.
   366  	nameConstraintsTest{
   367  		roots: []constraintsSpec{
   368  			constraintsSpec{},
   369  		},
   370  		intermediates: [][]constraintsSpec{
   371  			[]constraintsSpec{
   372  				constraintsSpec{
   373  					bad: []string{"dns:.example.com"},
   374  				},
   375  			},
   376  		},
   377  		leaf: leafSpec{
   378  			sans: []string{"dns:foo.example.com"},
   379  		},
   380  		expectedError: "\"foo.example.com\" is excluded",
   381  	},
   382  
   383  	// #18: having an exclusion doesn't prohibit other types of names.
   384  	nameConstraintsTest{
   385  		roots: []constraintsSpec{
   386  			constraintsSpec{
   387  				bad: []string{"dns:.example.com"},
   388  			},
   389  		},
   390  		intermediates: [][]constraintsSpec{
   391  			[]constraintsSpec{
   392  				constraintsSpec{},
   393  			},
   394  		},
   395  		leaf: leafSpec{
   396  			sans: []string{"dns:foo.com", "ip:10.1.1.1"},
   397  		},
   398  	},
   399  
   400  	// #19: IP-based exclusions are permitted and don't affect unrelated IP
   401  	// addresses.
   402  	nameConstraintsTest{
   403  		roots: []constraintsSpec{
   404  			constraintsSpec{
   405  				bad: []string{"ip:10.0.0.0/8"},
   406  			},
   407  		},
   408  		intermediates: [][]constraintsSpec{
   409  			[]constraintsSpec{
   410  				constraintsSpec{},
   411  			},
   412  		},
   413  		leaf: leafSpec{
   414  			sans: []string{"ip:192.168.1.1"},
   415  		},
   416  	},
   417  
   418  	// #20: IP-based exclusions are effective
   419  	nameConstraintsTest{
   420  		roots: []constraintsSpec{
   421  			constraintsSpec{
   422  				bad: []string{"ip:10.0.0.0/8"},
   423  			},
   424  		},
   425  		intermediates: [][]constraintsSpec{
   426  			[]constraintsSpec{
   427  				constraintsSpec{},
   428  			},
   429  		},
   430  		leaf: leafSpec{
   431  			sans: []string{"ip:10.0.0.1"},
   432  		},
   433  		expectedError: "\"10.0.0.1\" is excluded",
   434  	},
   435  
   436  	// #21: intermediates can further constrain IP ranges.
   437  	nameConstraintsTest{
   438  		roots: []constraintsSpec{
   439  			constraintsSpec{
   440  				bad: []string{"ip:0.0.0.0/1"},
   441  			},
   442  		},
   443  		intermediates: [][]constraintsSpec{
   444  			[]constraintsSpec{
   445  				constraintsSpec{
   446  					bad: []string{"ip:11.0.0.0/8"},
   447  				},
   448  			},
   449  		},
   450  		leaf: leafSpec{
   451  			sans: []string{"ip:11.0.0.1"},
   452  		},
   453  		expectedError: "\"11.0.0.1\" is excluded",
   454  	},
   455  
   456  	// #22: when multiple intermediates are present, chain building can
   457  	// avoid intermediates with incompatible constraints.
   458  	nameConstraintsTest{
   459  		roots: []constraintsSpec{
   460  			constraintsSpec{},
   461  		},
   462  		intermediates: [][]constraintsSpec{
   463  			[]constraintsSpec{
   464  				constraintsSpec{
   465  					ok: []string{"dns:.foo.com"},
   466  				},
   467  				constraintsSpec{
   468  					ok: []string{"dns:.example.com"},
   469  				},
   470  			},
   471  		},
   472  		leaf: leafSpec{
   473  			sans: []string{"dns:foo.example.com"},
   474  		},
   475  		noOpenSSL: true, // OpenSSL's chain building is not informed by constraints.
   476  	},
   477  
   478  	// #23: (same as the previous test, but in the other order in ensure
   479  	// that we don't pass it by luck.)
   480  	nameConstraintsTest{
   481  		roots: []constraintsSpec{
   482  			constraintsSpec{},
   483  		},
   484  		intermediates: [][]constraintsSpec{
   485  			[]constraintsSpec{
   486  				constraintsSpec{
   487  					ok: []string{"dns:.example.com"},
   488  				},
   489  				constraintsSpec{
   490  					ok: []string{"dns:.foo.com"},
   491  				},
   492  			},
   493  		},
   494  		leaf: leafSpec{
   495  			sans: []string{"dns:foo.example.com"},
   496  		},
   497  		noOpenSSL: true, // OpenSSL's chain building is not informed by constraints.
   498  	},
   499  
   500  	// #24: when multiple roots are valid, chain building can avoid roots
   501  	// with incompatible constraints.
   502  	nameConstraintsTest{
   503  		roots: []constraintsSpec{
   504  			constraintsSpec{},
   505  			constraintsSpec{
   506  				ok: []string{"dns:foo.com"},
   507  			},
   508  		},
   509  		intermediates: [][]constraintsSpec{
   510  			[]constraintsSpec{
   511  				constraintsSpec{},
   512  			},
   513  		},
   514  		leaf: leafSpec{
   515  			sans: []string{"dns:example.com"},
   516  		},
   517  		noOpenSSL: true, // OpenSSL's chain building is not informed by constraints.
   518  	},
   519  
   520  	// #25: (same as the previous test, but in the other order in ensure
   521  	// that we don't pass it by luck.)
   522  	nameConstraintsTest{
   523  		roots: []constraintsSpec{
   524  			constraintsSpec{
   525  				ok: []string{"dns:foo.com"},
   526  			},
   527  			constraintsSpec{},
   528  		},
   529  		intermediates: [][]constraintsSpec{
   530  			[]constraintsSpec{
   531  				constraintsSpec{},
   532  			},
   533  		},
   534  		leaf: leafSpec{
   535  			sans: []string{"dns:example.com"},
   536  		},
   537  		noOpenSSL: true, // OpenSSL's chain building is not informed by constraints.
   538  	},
   539  
   540  	// #26: chain building can find a valid path even with multiple levels
   541  	// of alternative intermediates and alternative roots.
   542  	nameConstraintsTest{
   543  		roots: []constraintsSpec{
   544  			constraintsSpec{
   545  				ok: []string{"dns:foo.com"},
   546  			},
   547  			constraintsSpec{
   548  				ok: []string{"dns:example.com"},
   549  			},
   550  			constraintsSpec{},
   551  		},
   552  		intermediates: [][]constraintsSpec{
   553  			[]constraintsSpec{
   554  				constraintsSpec{},
   555  				constraintsSpec{
   556  					ok: []string{"dns:foo.com"},
   557  				},
   558  			},
   559  			[]constraintsSpec{
   560  				constraintsSpec{},
   561  				constraintsSpec{
   562  					ok: []string{"dns:foo.com"},
   563  				},
   564  			},
   565  		},
   566  		leaf: leafSpec{
   567  			sans: []string{"dns:bar.com"},
   568  		},
   569  		noOpenSSL: true, // OpenSSL's chain building is not informed by constraints.
   570  	},
   571  
   572  	// #27: chain building doesn't get stuck when there is no valid path.
   573  	nameConstraintsTest{
   574  		roots: []constraintsSpec{
   575  			constraintsSpec{
   576  				ok: []string{"dns:foo.com"},
   577  			},
   578  			constraintsSpec{
   579  				ok: []string{"dns:example.com"},
   580  			},
   581  		},
   582  		intermediates: [][]constraintsSpec{
   583  			[]constraintsSpec{
   584  				constraintsSpec{},
   585  				constraintsSpec{
   586  					ok: []string{"dns:foo.com"},
   587  				},
   588  			},
   589  			[]constraintsSpec{
   590  				constraintsSpec{
   591  					ok: []string{"dns:bar.com"},
   592  				},
   593  				constraintsSpec{
   594  					ok: []string{"dns:foo.com"},
   595  				},
   596  			},
   597  		},
   598  		leaf: leafSpec{
   599  			sans: []string{"dns:bar.com"},
   600  		},
   601  		expectedError: "\"bar.com\" is not permitted",
   602  	},
   603  
   604  	// #28: unknown name types don't cause a problem without constraints.
   605  	nameConstraintsTest{
   606  		roots: []constraintsSpec{
   607  			constraintsSpec{},
   608  		},
   609  		intermediates: [][]constraintsSpec{
   610  			[]constraintsSpec{
   611  				constraintsSpec{},
   612  			},
   613  		},
   614  		leaf: leafSpec{
   615  			sans: []string{"unknown:"},
   616  		},
   617  	},
   618  
   619  	// #29: unknown name types are allowed even in constrained chains.
   620  	nameConstraintsTest{
   621  		roots: []constraintsSpec{
   622  			constraintsSpec{
   623  				ok: []string{"dns:foo.com", "dns:.foo.com"},
   624  			},
   625  		},
   626  		intermediates: [][]constraintsSpec{
   627  			[]constraintsSpec{
   628  				constraintsSpec{},
   629  			},
   630  		},
   631  		leaf: leafSpec{
   632  			sans: []string{"unknown:"},
   633  		},
   634  	},
   635  
   636  	// #30: without SANs, a certificate is rejected in a constrained chain.
   637  	nameConstraintsTest{
   638  		roots: []constraintsSpec{
   639  			constraintsSpec{
   640  				ok: []string{"dns:foo.com", "dns:.foo.com"},
   641  			},
   642  		},
   643  		intermediates: [][]constraintsSpec{
   644  			[]constraintsSpec{
   645  				constraintsSpec{},
   646  			},
   647  		},
   648  		leaf: leafSpec{
   649  			sans: []string{},
   650  		},
   651  		expectedError: "leaf doesn't have a SAN extension",
   652  		noOpenSSL:     true, // OpenSSL doesn't require SANs in this case.
   653  	},
   654  
   655  	// #31: IPv6 addresses work in constraints: roots can permit them as
   656  	// expected.
   657  	nameConstraintsTest{
   658  		roots: []constraintsSpec{
   659  			constraintsSpec{
   660  				ok: []string{"ip:2000:abcd::/32"},
   661  			},
   662  		},
   663  		intermediates: [][]constraintsSpec{
   664  			[]constraintsSpec{
   665  				constraintsSpec{},
   666  			},
   667  		},
   668  		leaf: leafSpec{
   669  			sans: []string{"ip:2000:abcd:1234::"},
   670  		},
   671  	},
   672  
   673  	// #32: IPv6 addresses work in constraints: root restrictions are
   674  	// effective.
   675  	nameConstraintsTest{
   676  		roots: []constraintsSpec{
   677  			constraintsSpec{
   678  				ok: []string{"ip:2000:abcd::/32"},
   679  			},
   680  		},
   681  		intermediates: [][]constraintsSpec{
   682  			[]constraintsSpec{
   683  				constraintsSpec{},
   684  			},
   685  		},
   686  		leaf: leafSpec{
   687  			sans: []string{"ip:2000:1234:abcd::"},
   688  		},
   689  		expectedError: "\"2000:1234:abcd::\" is not permitted",
   690  	},
   691  
   692  	// #33: An IPv6 permitted subtree doesn't affect DNS names.
   693  	nameConstraintsTest{
   694  		roots: []constraintsSpec{
   695  			constraintsSpec{
   696  				ok: []string{"ip:2000:abcd::/32"},
   697  			},
   698  		},
   699  		intermediates: [][]constraintsSpec{
   700  			[]constraintsSpec{
   701  				constraintsSpec{},
   702  			},
   703  		},
   704  		leaf: leafSpec{
   705  			sans: []string{"ip:2000:abcd::", "dns:foo.com"},
   706  		},
   707  	},
   708  
   709  	// #34: IPv6 exclusions don't affect unrelated addresses.
   710  	nameConstraintsTest{
   711  		roots: []constraintsSpec{
   712  			constraintsSpec{
   713  				bad: []string{"ip:2000:abcd::/32"},
   714  			},
   715  		},
   716  		intermediates: [][]constraintsSpec{
   717  			[]constraintsSpec{
   718  				constraintsSpec{},
   719  			},
   720  		},
   721  		leaf: leafSpec{
   722  			sans: []string{"ip:2000:1234::"},
   723  		},
   724  	},
   725  
   726  	// #35: IPv6 exclusions are effective.
   727  	nameConstraintsTest{
   728  		roots: []constraintsSpec{
   729  			constraintsSpec{
   730  				bad: []string{"ip:2000:abcd::/32"},
   731  			},
   732  		},
   733  		intermediates: [][]constraintsSpec{
   734  			[]constraintsSpec{
   735  				constraintsSpec{},
   736  			},
   737  		},
   738  		leaf: leafSpec{
   739  			sans: []string{"ip:2000:abcd::"},
   740  		},
   741  		expectedError: "\"2000:abcd::\" is excluded",
   742  	},
   743  
   744  	// #36: IPv6 constraints do not permit IPv4 addresses.
   745  	nameConstraintsTest{
   746  		roots: []constraintsSpec{
   747  			constraintsSpec{
   748  				ok: []string{"ip:2000:abcd::/32"},
   749  			},
   750  		},
   751  		intermediates: [][]constraintsSpec{
   752  			[]constraintsSpec{
   753  				constraintsSpec{},
   754  			},
   755  		},
   756  		leaf: leafSpec{
   757  			sans: []string{"ip:10.0.0.1"},
   758  		},
   759  		expectedError: "\"10.0.0.1\" is not permitted",
   760  	},
   761  
   762  	// #37: IPv4 constraints do not permit IPv6 addresses.
   763  	nameConstraintsTest{
   764  		roots: []constraintsSpec{
   765  			constraintsSpec{
   766  				ok: []string{"ip:10.0.0.0/8"},
   767  			},
   768  		},
   769  		intermediates: [][]constraintsSpec{
   770  			[]constraintsSpec{
   771  				constraintsSpec{},
   772  			},
   773  		},
   774  		leaf: leafSpec{
   775  			sans: []string{"ip:2000:abcd::"},
   776  		},
   777  		expectedError: "\"2000:abcd::\" is not permitted",
   778  	},
   779  
   780  	// #38: an exclusion of an unknown type doesn't affect other names.
   781  	nameConstraintsTest{
   782  		roots: []constraintsSpec{
   783  			constraintsSpec{
   784  				bad: []string{"unknown:"},
   785  			},
   786  		},
   787  		intermediates: [][]constraintsSpec{
   788  			[]constraintsSpec{
   789  				constraintsSpec{},
   790  			},
   791  		},
   792  		leaf: leafSpec{
   793  			sans: []string{"dns:example.com"},
   794  		},
   795  	},
   796  
   797  	// #39: a permitted subtree of an unknown type doesn't affect other
   798  	// name types.
   799  	nameConstraintsTest{
   800  		roots: []constraintsSpec{
   801  			constraintsSpec{
   802  				ok: []string{"unknown:"},
   803  			},
   804  		},
   805  		intermediates: [][]constraintsSpec{
   806  			[]constraintsSpec{
   807  				constraintsSpec{},
   808  			},
   809  		},
   810  		leaf: leafSpec{
   811  			sans: []string{"dns:example.com"},
   812  		},
   813  	},
   814  
   815  	// #40: exact email constraints work
   816  	nameConstraintsTest{
   817  		roots: []constraintsSpec{
   818  			constraintsSpec{
   819  				ok: []string{"email:foo@example.com"},
   820  			},
   821  		},
   822  		intermediates: [][]constraintsSpec{
   823  			[]constraintsSpec{
   824  				constraintsSpec{},
   825  			},
   826  		},
   827  		leaf: leafSpec{
   828  			sans: []string{"email:foo@example.com"},
   829  		},
   830  	},
   831  
   832  	// #41: exact email constraints are effective
   833  	nameConstraintsTest{
   834  		roots: []constraintsSpec{
   835  			constraintsSpec{
   836  				ok: []string{"email:foo@example.com"},
   837  			},
   838  		},
   839  		intermediates: [][]constraintsSpec{
   840  			[]constraintsSpec{
   841  				constraintsSpec{},
   842  			},
   843  		},
   844  		leaf: leafSpec{
   845  			sans: []string{"email:bar@example.com"},
   846  		},
   847  		expectedError: "\"bar@example.com\" is not permitted",
   848  	},
   849  
   850  	// #42: email canonicalisation works.
   851  	nameConstraintsTest{
   852  		roots: []constraintsSpec{
   853  			constraintsSpec{
   854  				ok: []string{"email:foo@example.com"},
   855  			},
   856  		},
   857  		intermediates: [][]constraintsSpec{
   858  			[]constraintsSpec{
   859  				constraintsSpec{},
   860  			},
   861  		},
   862  		leaf: leafSpec{
   863  			sans: []string{"email:\"\\f\\o\\o\"@example.com"},
   864  		},
   865  		noOpenSSL: true, // OpenSSL doesn't canonicalise email addresses before matching
   866  	},
   867  
   868  	// #43: limiting email addresses to a host works.
   869  	nameConstraintsTest{
   870  		roots: []constraintsSpec{
   871  			constraintsSpec{
   872  				ok: []string{"email:example.com"},
   873  			},
   874  		},
   875  		intermediates: [][]constraintsSpec{
   876  			[]constraintsSpec{
   877  				constraintsSpec{},
   878  			},
   879  		},
   880  		leaf: leafSpec{
   881  			sans: []string{"email:foo@example.com"},
   882  		},
   883  	},
   884  
   885  	// #44: a leading dot matches hosts one level deep
   886  	nameConstraintsTest{
   887  		roots: []constraintsSpec{
   888  			constraintsSpec{
   889  				ok: []string{"email:.example.com"},
   890  			},
   891  		},
   892  		intermediates: [][]constraintsSpec{
   893  			[]constraintsSpec{
   894  				constraintsSpec{},
   895  			},
   896  		},
   897  		leaf: leafSpec{
   898  			sans: []string{"email:foo@sub.example.com"},
   899  		},
   900  	},
   901  
   902  	// #45: a leading dot does not match the host itself
   903  	nameConstraintsTest{
   904  		roots: []constraintsSpec{
   905  			constraintsSpec{
   906  				ok: []string{"email:.example.com"},
   907  			},
   908  		},
   909  		intermediates: [][]constraintsSpec{
   910  			[]constraintsSpec{
   911  				constraintsSpec{},
   912  			},
   913  		},
   914  		leaf: leafSpec{
   915  			sans: []string{"email:foo@example.com"},
   916  		},
   917  		expectedError: "\"foo@example.com\" is not permitted",
   918  	},
   919  
   920  	// #46: a leading dot also matches two (or more) levels deep.
   921  	nameConstraintsTest{
   922  		roots: []constraintsSpec{
   923  			constraintsSpec{
   924  				ok: []string{"email:.example.com"},
   925  			},
   926  		},
   927  		intermediates: [][]constraintsSpec{
   928  			[]constraintsSpec{
   929  				constraintsSpec{},
   930  			},
   931  		},
   932  		leaf: leafSpec{
   933  			sans: []string{"email:foo@sub.sub.example.com"},
   934  		},
   935  	},
   936  
   937  	// #47: the local part of an email is case-sensitive
   938  	nameConstraintsTest{
   939  		roots: []constraintsSpec{
   940  			constraintsSpec{
   941  				ok: []string{"email:foo@example.com"},
   942  			},
   943  		},
   944  		intermediates: [][]constraintsSpec{
   945  			[]constraintsSpec{
   946  				constraintsSpec{},
   947  			},
   948  		},
   949  		leaf: leafSpec{
   950  			sans: []string{"email:Foo@example.com"},
   951  		},
   952  		expectedError: "\"Foo@example.com\" is not permitted",
   953  	},
   954  
   955  	// #48: the domain part of an email is not case-sensitive
   956  	nameConstraintsTest{
   957  		roots: []constraintsSpec{
   958  			constraintsSpec{
   959  				ok: []string{"email:foo@EXAMPLE.com"},
   960  			},
   961  		},
   962  		intermediates: [][]constraintsSpec{
   963  			[]constraintsSpec{
   964  				constraintsSpec{},
   965  			},
   966  		},
   967  		leaf: leafSpec{
   968  			sans: []string{"email:foo@example.com"},
   969  		},
   970  	},
   971  
   972  	// #49: the domain part of a DNS constraint is also not case-sensitive.
   973  	nameConstraintsTest{
   974  		roots: []constraintsSpec{
   975  			constraintsSpec{
   976  				ok: []string{"dns:EXAMPLE.com"},
   977  			},
   978  		},
   979  		intermediates: [][]constraintsSpec{
   980  			[]constraintsSpec{
   981  				constraintsSpec{},
   982  			},
   983  		},
   984  		leaf: leafSpec{
   985  			sans: []string{"dns:example.com"},
   986  		},
   987  	},
   988  
   989  	// #50: URI constraints only cover the host part of the URI
   990  	nameConstraintsTest{
   991  		roots: []constraintsSpec{
   992  			constraintsSpec{
   993  				ok: []string{"uri:example.com"},
   994  			},
   995  		},
   996  		intermediates: [][]constraintsSpec{
   997  			[]constraintsSpec{
   998  				constraintsSpec{},
   999  			},
  1000  		},
  1001  		leaf: leafSpec{
  1002  			sans: []string{
  1003  				"uri:http://example.com/bar",
  1004  				"uri:http://example.com:8080/",
  1005  				"uri:https://example.com/wibble#bar",
  1006  			},
  1007  		},
  1008  	},
  1009  
  1010  	// #51: URIs with IPs are rejected
  1011  	nameConstraintsTest{
  1012  		roots: []constraintsSpec{
  1013  			constraintsSpec{
  1014  				ok: []string{"uri:example.com"},
  1015  			},
  1016  		},
  1017  		intermediates: [][]constraintsSpec{
  1018  			[]constraintsSpec{
  1019  				constraintsSpec{},
  1020  			},
  1021  		},
  1022  		leaf: leafSpec{
  1023  			sans: []string{"uri:http://1.2.3.4/"},
  1024  		},
  1025  		expectedError: "URI with IP",
  1026  	},
  1027  
  1028  	// #52: URIs with IPs and ports are rejected
  1029  	nameConstraintsTest{
  1030  		roots: []constraintsSpec{
  1031  			constraintsSpec{
  1032  				ok: []string{"uri:example.com"},
  1033  			},
  1034  		},
  1035  		intermediates: [][]constraintsSpec{
  1036  			[]constraintsSpec{
  1037  				constraintsSpec{},
  1038  			},
  1039  		},
  1040  		leaf: leafSpec{
  1041  			sans: []string{"uri:http://1.2.3.4:43/"},
  1042  		},
  1043  		expectedError: "URI with IP",
  1044  	},
  1045  
  1046  	// #53: URIs with IPv6 addresses are also rejected
  1047  	nameConstraintsTest{
  1048  		roots: []constraintsSpec{
  1049  			constraintsSpec{
  1050  				ok: []string{"uri:example.com"},
  1051  			},
  1052  		},
  1053  		intermediates: [][]constraintsSpec{
  1054  			[]constraintsSpec{
  1055  				constraintsSpec{},
  1056  			},
  1057  		},
  1058  		leaf: leafSpec{
  1059  			sans: []string{"uri:http://[2006:abcd::1]/"},
  1060  		},
  1061  		expectedError: "URI with IP",
  1062  	},
  1063  
  1064  	// #54: URIs with IPv6 addresses with ports are also rejected
  1065  	nameConstraintsTest{
  1066  		roots: []constraintsSpec{
  1067  			constraintsSpec{
  1068  				ok: []string{"uri:example.com"},
  1069  			},
  1070  		},
  1071  		intermediates: [][]constraintsSpec{
  1072  			[]constraintsSpec{
  1073  				constraintsSpec{},
  1074  			},
  1075  		},
  1076  		leaf: leafSpec{
  1077  			sans: []string{"uri:http://[2006:abcd::1]:16/"},
  1078  		},
  1079  		expectedError: "URI with IP",
  1080  	},
  1081  
  1082  	// #55: URI constraints are effective
  1083  	nameConstraintsTest{
  1084  		roots: []constraintsSpec{
  1085  			constraintsSpec{
  1086  				ok: []string{"uri:example.com"},
  1087  			},
  1088  		},
  1089  		intermediates: [][]constraintsSpec{
  1090  			[]constraintsSpec{
  1091  				constraintsSpec{},
  1092  			},
  1093  		},
  1094  		leaf: leafSpec{
  1095  			sans: []string{"uri:http://bar.com/"},
  1096  		},
  1097  		expectedError: "\"http://bar.com/\" is not permitted",
  1098  	},
  1099  
  1100  	// #56: URI constraints are effective
  1101  	nameConstraintsTest{
  1102  		roots: []constraintsSpec{
  1103  			constraintsSpec{
  1104  				bad: []string{"uri:foo.com"},
  1105  			},
  1106  		},
  1107  		intermediates: [][]constraintsSpec{
  1108  			[]constraintsSpec{
  1109  				constraintsSpec{},
  1110  			},
  1111  		},
  1112  		leaf: leafSpec{
  1113  			sans: []string{"uri:http://foo.com/"},
  1114  		},
  1115  		expectedError: "\"http://foo.com/\" is excluded",
  1116  	},
  1117  
  1118  	// #57: URI constraints can allow subdomains
  1119  	nameConstraintsTest{
  1120  		roots: []constraintsSpec{
  1121  			constraintsSpec{
  1122  				ok: []string{"uri:.foo.com"},
  1123  			},
  1124  		},
  1125  		intermediates: [][]constraintsSpec{
  1126  			[]constraintsSpec{
  1127  				constraintsSpec{},
  1128  			},
  1129  		},
  1130  		leaf: leafSpec{
  1131  			sans: []string{"uri:http://www.foo.com/"},
  1132  		},
  1133  	},
  1134  
  1135  	// #58: excluding an IPv4-mapped-IPv6 address doesn't affect the IPv4
  1136  	// version of that address.
  1137  	nameConstraintsTest{
  1138  		roots: []constraintsSpec{
  1139  			constraintsSpec{
  1140  				bad: []string{"ip:::ffff:1.2.3.4/128"},
  1141  			},
  1142  		},
  1143  		intermediates: [][]constraintsSpec{
  1144  			[]constraintsSpec{
  1145  				constraintsSpec{},
  1146  			},
  1147  		},
  1148  		leaf: leafSpec{
  1149  			sans: []string{"ip:1.2.3.4"},
  1150  		},
  1151  	},
  1152  
  1153  	// #59: a URI constraint isn't matched by a URN.
  1154  	nameConstraintsTest{
  1155  		roots: []constraintsSpec{
  1156  			constraintsSpec{
  1157  				ok: []string{"uri:example.com"},
  1158  			},
  1159  		},
  1160  		intermediates: [][]constraintsSpec{
  1161  			[]constraintsSpec{
  1162  				constraintsSpec{},
  1163  			},
  1164  		},
  1165  		leaf: leafSpec{
  1166  			sans: []string{"uri:urn:example"},
  1167  		},
  1168  		expectedError: "URI with empty host",
  1169  	},
  1170  
  1171  	// #60: excluding all IPv6 addresses doesn't exclude all IPv4 addresses
  1172  	// too, even though IPv4 is mapped into the IPv6 range.
  1173  	nameConstraintsTest{
  1174  		roots: []constraintsSpec{
  1175  			constraintsSpec{
  1176  				ok:  []string{"ip:1.2.3.0/24"},
  1177  				bad: []string{"ip:::0/0"},
  1178  			},
  1179  		},
  1180  		intermediates: [][]constraintsSpec{
  1181  			[]constraintsSpec{
  1182  				constraintsSpec{},
  1183  			},
  1184  		},
  1185  		leaf: leafSpec{
  1186  			sans: []string{"ip:1.2.3.4"},
  1187  		},
  1188  	},
  1189  
  1190  	// #61: omitting extended key usage in a CA certificate implies that
  1191  	// any usage is ok.
  1192  	nameConstraintsTest{
  1193  		roots: []constraintsSpec{
  1194  			constraintsSpec{},
  1195  		},
  1196  		intermediates: [][]constraintsSpec{
  1197  			[]constraintsSpec{
  1198  				constraintsSpec{},
  1199  			},
  1200  		},
  1201  		leaf: leafSpec{
  1202  			sans: []string{"dns:example.com"},
  1203  			ekus: []string{"serverAuth", "other"},
  1204  		},
  1205  	},
  1206  
  1207  	// #62: The “any” EKU also means that any usage is ok.
  1208  	nameConstraintsTest{
  1209  		roots: []constraintsSpec{
  1210  			constraintsSpec{},
  1211  		},
  1212  		intermediates: [][]constraintsSpec{
  1213  			[]constraintsSpec{
  1214  				constraintsSpec{
  1215  					ekus: []string{"any"},
  1216  				},
  1217  			},
  1218  		},
  1219  		leaf: leafSpec{
  1220  			sans: []string{"dns:example.com"},
  1221  			ekus: []string{"serverAuth", "other"},
  1222  		},
  1223  	},
  1224  
  1225  	// #63: An intermediate with enumerated EKUs causes a failure if we
  1226  	// test for an EKU not in that set. (ServerAuth is required by
  1227  	// default.)
  1228  	nameConstraintsTest{
  1229  		roots: []constraintsSpec{
  1230  			constraintsSpec{},
  1231  		},
  1232  		intermediates: [][]constraintsSpec{
  1233  			[]constraintsSpec{
  1234  				constraintsSpec{
  1235  					ekus: []string{"email"},
  1236  				},
  1237  			},
  1238  		},
  1239  		leaf: leafSpec{
  1240  			sans: []string{"dns:example.com"},
  1241  			ekus: []string{"serverAuth"},
  1242  		},
  1243  		expectedError: "incompatible key usage",
  1244  	},
  1245  
  1246  	// #64: an unknown EKU in the leaf doesn't break anything, even if it's not
  1247  	// correctly nested.
  1248  	nameConstraintsTest{
  1249  		roots: []constraintsSpec{
  1250  			constraintsSpec{},
  1251  		},
  1252  		intermediates: [][]constraintsSpec{
  1253  			[]constraintsSpec{
  1254  				constraintsSpec{
  1255  					ekus: []string{"email"},
  1256  				},
  1257  			},
  1258  		},
  1259  		leaf: leafSpec{
  1260  			sans: []string{"dns:example.com"},
  1261  			ekus: []string{"other"},
  1262  		},
  1263  		requestedEKUs: []ExtKeyUsage{ExtKeyUsageAny},
  1264  	},
  1265  
  1266  	// #65: trying to add extra permitted key usages in an intermediate
  1267  	// (after a limitation in the root) is acceptable so long as the leaf
  1268  	// certificate doesn't use them.
  1269  	nameConstraintsTest{
  1270  		roots: []constraintsSpec{
  1271  			constraintsSpec{
  1272  				ekus: []string{"serverAuth"},
  1273  			},
  1274  		},
  1275  		intermediates: [][]constraintsSpec{
  1276  			[]constraintsSpec{
  1277  				constraintsSpec{
  1278  					ekus: []string{"serverAuth", "email"},
  1279  				},
  1280  			},
  1281  		},
  1282  		leaf: leafSpec{
  1283  			sans: []string{"dns:example.com"},
  1284  			ekus: []string{"serverAuth"},
  1285  		},
  1286  	},
  1287  
  1288  	// #66: EKUs in roots are not ignored.
  1289  	nameConstraintsTest{
  1290  		roots: []constraintsSpec{
  1291  			constraintsSpec{
  1292  				ekus: []string{"email"},
  1293  			},
  1294  		},
  1295  		intermediates: [][]constraintsSpec{
  1296  			[]constraintsSpec{
  1297  				constraintsSpec{
  1298  					ekus: []string{"serverAuth"},
  1299  				},
  1300  			},
  1301  		},
  1302  		leaf: leafSpec{
  1303  			sans: []string{"dns:example.com"},
  1304  			ekus: []string{"serverAuth"},
  1305  		},
  1306  		expectedError: "incompatible key usage",
  1307  	},
  1308  
  1309  	// #67: in order to support COMODO chains, SGC key usages permit
  1310  	// serverAuth and clientAuth.
  1311  	nameConstraintsTest{
  1312  		roots: []constraintsSpec{
  1313  			constraintsSpec{},
  1314  		},
  1315  		intermediates: [][]constraintsSpec{
  1316  			[]constraintsSpec{
  1317  				constraintsSpec{
  1318  					ekus: []string{"netscapeSGC"},
  1319  				},
  1320  			},
  1321  		},
  1322  		leaf: leafSpec{
  1323  			sans: []string{"dns:example.com"},
  1324  			ekus: []string{"serverAuth", "clientAuth"},
  1325  		},
  1326  	},
  1327  
  1328  	// #68: in order to support COMODO chains, SGC key usages permit
  1329  	// serverAuth and clientAuth.
  1330  	nameConstraintsTest{
  1331  		roots: []constraintsSpec{
  1332  			constraintsSpec{},
  1333  		},
  1334  		intermediates: [][]constraintsSpec{
  1335  			[]constraintsSpec{
  1336  				constraintsSpec{
  1337  					ekus: []string{"msSGC"},
  1338  				},
  1339  			},
  1340  		},
  1341  		leaf: leafSpec{
  1342  			sans: []string{"dns:example.com"},
  1343  			ekus: []string{"serverAuth", "clientAuth"},
  1344  		},
  1345  	},
  1346  
  1347  	// #69: an empty DNS constraint should allow anything.
  1348  	nameConstraintsTest{
  1349  		roots: []constraintsSpec{
  1350  			constraintsSpec{
  1351  				ok: []string{"dns:"},
  1352  			},
  1353  		},
  1354  		intermediates: [][]constraintsSpec{
  1355  			[]constraintsSpec{
  1356  				constraintsSpec{},
  1357  			},
  1358  		},
  1359  		leaf: leafSpec{
  1360  			sans: []string{"dns:example.com"},
  1361  		},
  1362  	},
  1363  
  1364  	// #70: an empty DNS constraint should also reject everything.
  1365  	nameConstraintsTest{
  1366  		roots: []constraintsSpec{
  1367  			constraintsSpec{
  1368  				bad: []string{"dns:"},
  1369  			},
  1370  		},
  1371  		intermediates: [][]constraintsSpec{
  1372  			[]constraintsSpec{
  1373  				constraintsSpec{},
  1374  			},
  1375  		},
  1376  		leaf: leafSpec{
  1377  			sans: []string{"dns:example.com"},
  1378  		},
  1379  		expectedError: "\"example.com\" is excluded",
  1380  	},
  1381  
  1382  	// #71: an empty email constraint should allow anything
  1383  	nameConstraintsTest{
  1384  		roots: []constraintsSpec{
  1385  			constraintsSpec{
  1386  				ok: []string{"email:"},
  1387  			},
  1388  		},
  1389  		intermediates: [][]constraintsSpec{
  1390  			[]constraintsSpec{
  1391  				constraintsSpec{},
  1392  			},
  1393  		},
  1394  		leaf: leafSpec{
  1395  			sans: []string{"email:foo@example.com"},
  1396  		},
  1397  	},
  1398  
  1399  	// #72: an empty email constraint should also reject everything.
  1400  	nameConstraintsTest{
  1401  		roots: []constraintsSpec{
  1402  			constraintsSpec{
  1403  				bad: []string{"email:"},
  1404  			},
  1405  		},
  1406  		intermediates: [][]constraintsSpec{
  1407  			[]constraintsSpec{
  1408  				constraintsSpec{},
  1409  			},
  1410  		},
  1411  		leaf: leafSpec{
  1412  			sans: []string{"email:foo@example.com"},
  1413  		},
  1414  		expectedError: "\"foo@example.com\" is excluded",
  1415  	},
  1416  
  1417  	// #73: an empty URI constraint should allow anything
  1418  	nameConstraintsTest{
  1419  		roots: []constraintsSpec{
  1420  			constraintsSpec{
  1421  				ok: []string{"uri:"},
  1422  			},
  1423  		},
  1424  		intermediates: [][]constraintsSpec{
  1425  			[]constraintsSpec{
  1426  				constraintsSpec{},
  1427  			},
  1428  		},
  1429  		leaf: leafSpec{
  1430  			sans: []string{"uri:https://example.com/test"},
  1431  		},
  1432  	},
  1433  
  1434  	// #74: an empty URI constraint should also reject everything.
  1435  	nameConstraintsTest{
  1436  		roots: []constraintsSpec{
  1437  			constraintsSpec{
  1438  				bad: []string{"uri:"},
  1439  			},
  1440  		},
  1441  		intermediates: [][]constraintsSpec{
  1442  			[]constraintsSpec{
  1443  				constraintsSpec{},
  1444  			},
  1445  		},
  1446  		leaf: leafSpec{
  1447  			sans: []string{"uri:https://example.com/test"},
  1448  		},
  1449  		expectedError: "\"https://example.com/test\" is excluded",
  1450  	},
  1451  
  1452  	// #75: serverAuth in a leaf shouldn't permit clientAuth when requested in
  1453  	// VerifyOptions.
  1454  	nameConstraintsTest{
  1455  		roots: []constraintsSpec{
  1456  			constraintsSpec{},
  1457  		},
  1458  		intermediates: [][]constraintsSpec{
  1459  			[]constraintsSpec{
  1460  				constraintsSpec{},
  1461  			},
  1462  		},
  1463  		leaf: leafSpec{
  1464  			sans: []string{"dns:example.com"},
  1465  			ekus: []string{"serverAuth"},
  1466  		},
  1467  		requestedEKUs: []ExtKeyUsage{ExtKeyUsageClientAuth},
  1468  		expectedError: "incompatible key usage",
  1469  	},
  1470  
  1471  	// #76: However, MSSGC in a leaf should match a request for serverAuth.
  1472  	nameConstraintsTest{
  1473  		roots: []constraintsSpec{
  1474  			constraintsSpec{},
  1475  		},
  1476  		intermediates: [][]constraintsSpec{
  1477  			[]constraintsSpec{
  1478  				constraintsSpec{},
  1479  			},
  1480  		},
  1481  		leaf: leafSpec{
  1482  			sans: []string{"dns:example.com"},
  1483  			ekus: []string{"msSGC"},
  1484  		},
  1485  		requestedEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth},
  1486  	},
  1487  
  1488  	// An invalid DNS SAN should be detected only at validation time so
  1489  	// that we can process CA certificates in the wild that have invalid SANs.
  1490  	// See https://github.com/golang/go/issues/23995
  1491  
  1492  	// #77: an invalid DNS or mail SAN will not be detected if name constaint
  1493  	// checking is not triggered.
  1494  	nameConstraintsTest{
  1495  		roots: []constraintsSpec{
  1496  			constraintsSpec{},
  1497  		},
  1498  		intermediates: [][]constraintsSpec{
  1499  			[]constraintsSpec{
  1500  				constraintsSpec{},
  1501  			},
  1502  		},
  1503  		leaf: leafSpec{
  1504  			sans: []string{"dns:this is invalid", "email:this @ is invalid"},
  1505  		},
  1506  	},
  1507  
  1508  	// #78: an invalid DNS SAN will be detected if any name constraint checking
  1509  	// is triggered.
  1510  	nameConstraintsTest{
  1511  		roots: []constraintsSpec{
  1512  			constraintsSpec{
  1513  				bad: []string{"uri:"},
  1514  			},
  1515  		},
  1516  		intermediates: [][]constraintsSpec{
  1517  			[]constraintsSpec{
  1518  				constraintsSpec{},
  1519  			},
  1520  		},
  1521  		leaf: leafSpec{
  1522  			sans: []string{"dns:this is invalid"},
  1523  		},
  1524  		expectedError: "cannot parse dnsName",
  1525  	},
  1526  
  1527  	// #79: an invalid email SAN will be detected if any name constraint
  1528  	// checking is triggered.
  1529  	nameConstraintsTest{
  1530  		roots: []constraintsSpec{
  1531  			constraintsSpec{
  1532  				bad: []string{"uri:"},
  1533  			},
  1534  		},
  1535  		intermediates: [][]constraintsSpec{
  1536  			[]constraintsSpec{
  1537  				constraintsSpec{},
  1538  			},
  1539  		},
  1540  		leaf: leafSpec{
  1541  			sans: []string{"email:this @ is invalid"},
  1542  		},
  1543  		expectedError: "cannot parse rfc822Name",
  1544  	},
  1545  
  1546  	// #80: if several EKUs are requested, satisfying any of them is sufficient.
  1547  	nameConstraintsTest{
  1548  		roots: []constraintsSpec{
  1549  			constraintsSpec{},
  1550  		},
  1551  		intermediates: [][]constraintsSpec{
  1552  			[]constraintsSpec{
  1553  				constraintsSpec{},
  1554  			},
  1555  		},
  1556  		leaf: leafSpec{
  1557  			sans: []string{"dns:example.com"},
  1558  			ekus: []string{"email"},
  1559  		},
  1560  		requestedEKUs: []ExtKeyUsage{ExtKeyUsageClientAuth, ExtKeyUsageEmailProtection},
  1561  	},
  1562  
  1563  	// #81: EKUs that are not asserted in VerifyOpts are not required to be
  1564  	// nested.
  1565  	nameConstraintsTest{
  1566  		roots: []constraintsSpec{
  1567  			constraintsSpec{},
  1568  		},
  1569  		intermediates: [][]constraintsSpec{
  1570  			[]constraintsSpec{
  1571  				constraintsSpec{
  1572  					ekus: []string{"serverAuth"},
  1573  				},
  1574  			},
  1575  		},
  1576  		leaf: leafSpec{
  1577  			sans: []string{"dns:example.com"},
  1578  			// There's no email EKU in the intermediate. This would be rejected if
  1579  			// full nesting was required.
  1580  			ekus: []string{"email", "serverAuth"},
  1581  		},
  1582  	},
  1583  }
  1584  
  1585  func makeConstraintsCACert(constraints constraintsSpec, name string, key *ecdsa.PrivateKey, parent *Certificate, parentKey *ecdsa.PrivateKey) (*Certificate, error) {
  1586  	var serialBytes [16]byte
  1587  	rand.Read(serialBytes[:])
  1588  
  1589  	template := &Certificate{
  1590  		SerialNumber: new(big.Int).SetBytes(serialBytes[:]),
  1591  		Subject: pkix.Name{
  1592  			CommonName: name,
  1593  		},
  1594  		NotBefore:             time.Unix(1000, 0),
  1595  		NotAfter:              time.Unix(2000, 0),
  1596  		KeyUsage:              KeyUsageCertSign,
  1597  		BasicConstraintsValid: true,
  1598  		IsCA: true,
  1599  	}
  1600  
  1601  	if err := addConstraintsToTemplate(constraints, template); err != nil {
  1602  		return nil, err
  1603  	}
  1604  
  1605  	if parent == nil {
  1606  		parent = template
  1607  	}
  1608  	derBytes, err := CreateCertificate(rand.Reader, template, parent, &key.PublicKey, parentKey)
  1609  	if err != nil {
  1610  		return nil, err
  1611  	}
  1612  
  1613  	caCert, err := ParseCertificate(derBytes)
  1614  	if err != nil {
  1615  		return nil, err
  1616  	}
  1617  
  1618  	return caCert, nil
  1619  }
  1620  
  1621  func makeConstraintsLeafCert(leaf leafSpec, key *ecdsa.PrivateKey, parent *Certificate, parentKey *ecdsa.PrivateKey) (*Certificate, error) {
  1622  	var serialBytes [16]byte
  1623  	rand.Read(serialBytes[:])
  1624  
  1625  	template := &Certificate{
  1626  		SerialNumber: new(big.Int).SetBytes(serialBytes[:]),
  1627  		Subject: pkix.Name{
  1628  			// Don't set a CommonName because OpenSSL (at least) will try to
  1629  			// match it against name constraints.
  1630  			OrganizationalUnit: []string{"Leaf"},
  1631  		},
  1632  		NotBefore:             time.Unix(1000, 0),
  1633  		NotAfter:              time.Unix(2000, 0),
  1634  		KeyUsage:              KeyUsageDigitalSignature,
  1635  		BasicConstraintsValid: true,
  1636  		IsCA: false,
  1637  	}
  1638  
  1639  	for _, name := range leaf.sans {
  1640  		switch {
  1641  		case strings.HasPrefix(name, "dns:"):
  1642  			template.DNSNames = append(template.DNSNames, name[4:])
  1643  
  1644  		case strings.HasPrefix(name, "ip:"):
  1645  			ip := net.ParseIP(name[3:])
  1646  			if ip == nil {
  1647  				return nil, fmt.Errorf("cannot parse IP %q", name[3:])
  1648  			}
  1649  			template.IPAddresses = append(template.IPAddresses, ip)
  1650  
  1651  		case strings.HasPrefix(name, "invalidip:"):
  1652  			ipBytes, err := hex.DecodeString(name[10:])
  1653  			if err != nil {
  1654  				return nil, fmt.Errorf("cannot parse invalid IP: %s", err)
  1655  			}
  1656  			template.IPAddresses = append(template.IPAddresses, net.IP(ipBytes))
  1657  
  1658  		case strings.HasPrefix(name, "email:"):
  1659  			template.EmailAddresses = append(template.EmailAddresses, name[6:])
  1660  
  1661  		case strings.HasPrefix(name, "uri:"):
  1662  			uri, err := url.Parse(name[4:])
  1663  			if err != nil {
  1664  				return nil, fmt.Errorf("cannot parse URI %q: %s", name[4:], err)
  1665  			}
  1666  			template.URIs = append(template.URIs, uri)
  1667  
  1668  		case strings.HasPrefix(name, "unknown:"):
  1669  			// This is a special case for testing unknown
  1670  			// name types. A custom SAN extension is
  1671  			// injected into the certificate.
  1672  			if len(leaf.sans) != 1 {
  1673  				panic("when using unknown name types, it must be the sole name")
  1674  			}
  1675  
  1676  			template.ExtraExtensions = append(template.ExtraExtensions, pkix.Extension{
  1677  				Id: []int{2, 5, 29, 17},
  1678  				Value: []byte{
  1679  					0x30, // SEQUENCE
  1680  					3,    // three bytes
  1681  					9,    // undefined GeneralName type 9
  1682  					1,
  1683  					1,
  1684  				},
  1685  			})
  1686  
  1687  		default:
  1688  			return nil, fmt.Errorf("unknown name type %q", name)
  1689  		}
  1690  	}
  1691  
  1692  	var err error
  1693  	if template.ExtKeyUsage, template.UnknownExtKeyUsage, err = parseEKUs(leaf.ekus); err != nil {
  1694  		return nil, err
  1695  	}
  1696  
  1697  	if parent == nil {
  1698  		parent = template
  1699  	}
  1700  
  1701  	derBytes, err := CreateCertificate(rand.Reader, template, parent, &key.PublicKey, parentKey)
  1702  	if err != nil {
  1703  		return nil, err
  1704  	}
  1705  
  1706  	return ParseCertificate(derBytes)
  1707  }
  1708  
  1709  func customConstraintsExtension(typeNum int, constraint []byte, isExcluded bool) pkix.Extension {
  1710  	appendConstraint := func(contents []byte, tag uint8) []byte {
  1711  		contents = append(contents, tag|32 /* constructed */ |0x80 /* context-specific */)
  1712  		contents = append(contents, byte(4+len(constraint)) /* length */)
  1713  		contents = append(contents, 0x30 /* SEQUENCE */)
  1714  		contents = append(contents, byte(2+len(constraint)) /* length */)
  1715  		contents = append(contents, byte(typeNum) /* GeneralName type */)
  1716  		contents = append(contents, byte(len(constraint)))
  1717  		return append(contents, constraint...)
  1718  	}
  1719  
  1720  	var contents []byte
  1721  	if !isExcluded {
  1722  		contents = appendConstraint(contents, 0 /* tag 0 for permitted */)
  1723  	} else {
  1724  		contents = appendConstraint(contents, 1 /* tag 1 for excluded */)
  1725  	}
  1726  
  1727  	var value []byte
  1728  	value = append(value, 0x30 /* SEQUENCE */)
  1729  	value = append(value, byte(len(contents)))
  1730  	value = append(value, contents...)
  1731  
  1732  	return pkix.Extension{
  1733  		Id:    []int{2, 5, 29, 30},
  1734  		Value: value,
  1735  	}
  1736  }
  1737  
  1738  func addConstraintsToTemplate(constraints constraintsSpec, template *Certificate) error {
  1739  	parse := func(constraints []string) (dnsNames []string, ips []*net.IPNet, emailAddrs []string, uriDomains []string, err error) {
  1740  		for _, constraint := range constraints {
  1741  			switch {
  1742  			case strings.HasPrefix(constraint, "dns:"):
  1743  				dnsNames = append(dnsNames, constraint[4:])
  1744  
  1745  			case strings.HasPrefix(constraint, "ip:"):
  1746  				_, ipNet, err := net.ParseCIDR(constraint[3:])
  1747  				if err != nil {
  1748  					return nil, nil, nil, nil, err
  1749  				}
  1750  				ips = append(ips, ipNet)
  1751  
  1752  			case strings.HasPrefix(constraint, "email:"):
  1753  				emailAddrs = append(emailAddrs, constraint[6:])
  1754  
  1755  			case strings.HasPrefix(constraint, "uri:"):
  1756  				uriDomains = append(uriDomains, constraint[4:])
  1757  
  1758  			default:
  1759  				return nil, nil, nil, nil, fmt.Errorf("unknown constraint %q", constraint)
  1760  			}
  1761  		}
  1762  
  1763  		return dnsNames, ips, emailAddrs, uriDomains, err
  1764  	}
  1765  
  1766  	handleSpecialConstraint := func(constraint string, isExcluded bool) bool {
  1767  		switch {
  1768  		case constraint == "unknown:":
  1769  			template.ExtraExtensions = append(template.ExtraExtensions, customConstraintsExtension(9 /* undefined GeneralName type */, []byte{1}, isExcluded))
  1770  
  1771  		default:
  1772  			return false
  1773  		}
  1774  
  1775  		return true
  1776  	}
  1777  
  1778  	if len(constraints.ok) == 1 && len(constraints.bad) == 0 {
  1779  		if handleSpecialConstraint(constraints.ok[0], false) {
  1780  			return nil
  1781  		}
  1782  	}
  1783  
  1784  	if len(constraints.bad) == 1 && len(constraints.ok) == 0 {
  1785  		if handleSpecialConstraint(constraints.bad[0], true) {
  1786  			return nil
  1787  		}
  1788  	}
  1789  
  1790  	var err error
  1791  	template.PermittedDNSDomains, template.PermittedIPRanges, template.PermittedEmailAddresses, template.PermittedURIDomains, err = parse(constraints.ok)
  1792  	if err != nil {
  1793  		return err
  1794  	}
  1795  
  1796  	template.ExcludedDNSDomains, template.ExcludedIPRanges, template.ExcludedEmailAddresses, template.ExcludedURIDomains, err = parse(constraints.bad)
  1797  	if err != nil {
  1798  		return err
  1799  	}
  1800  
  1801  	if template.ExtKeyUsage, template.UnknownExtKeyUsage, err = parseEKUs(constraints.ekus); err != nil {
  1802  		return err
  1803  	}
  1804  
  1805  	return nil
  1806  }
  1807  
  1808  func parseEKUs(ekuStrs []string) (ekus []ExtKeyUsage, unknowns []asn1.ObjectIdentifier, err error) {
  1809  	for _, s := range ekuStrs {
  1810  		switch s {
  1811  		case "serverAuth":
  1812  			ekus = append(ekus, ExtKeyUsageServerAuth)
  1813  		case "clientAuth":
  1814  			ekus = append(ekus, ExtKeyUsageClientAuth)
  1815  		case "email":
  1816  			ekus = append(ekus, ExtKeyUsageEmailProtection)
  1817  		case "netscapeSGC":
  1818  			ekus = append(ekus, ExtKeyUsageNetscapeServerGatedCrypto)
  1819  		case "msSGC":
  1820  			ekus = append(ekus, ExtKeyUsageMicrosoftServerGatedCrypto)
  1821  		case "any":
  1822  			ekus = append(ekus, ExtKeyUsageAny)
  1823  		case "other":
  1824  			unknowns = append(unknowns, asn1.ObjectIdentifier{2, 4, 1, 2, 3})
  1825  		default:
  1826  			return nil, nil, fmt.Errorf("unknown EKU %q", s)
  1827  		}
  1828  	}
  1829  
  1830  	return
  1831  }
  1832  
  1833  func TestConstraintCases(t *testing.T) {
  1834  	privateKeys := sync.Pool{
  1835  		New: func() interface{} {
  1836  			priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  1837  			if err != nil {
  1838  				panic(err)
  1839  			}
  1840  			return priv
  1841  		},
  1842  	}
  1843  
  1844  	for i, test := range nameConstraintsTests {
  1845  		rootPool := NewCertPool()
  1846  		rootKey := privateKeys.Get().(*ecdsa.PrivateKey)
  1847  		rootName := "Root " + strconv.Itoa(i)
  1848  
  1849  		// keys keeps track of all the private keys used in a given
  1850  		// test and puts them back in the privateKeys pool at the end.
  1851  		keys := []*ecdsa.PrivateKey{rootKey}
  1852  
  1853  		// At each level (root, intermediate(s), leaf), parent points to
  1854  		// an example parent certificate and parentKey the key for the
  1855  		// parent level. Since all certificates at a given level have
  1856  		// the same name and public key, any parent certificate is
  1857  		// sufficient to get the correct issuer name and authority
  1858  		// key ID.
  1859  		var parent *Certificate
  1860  		parentKey := rootKey
  1861  
  1862  		for _, root := range test.roots {
  1863  			rootCert, err := makeConstraintsCACert(root, rootName, rootKey, nil, rootKey)
  1864  			if err != nil {
  1865  				t.Fatalf("#%d: failed to create root: %s", i, err)
  1866  			}
  1867  
  1868  			parent = rootCert
  1869  			rootPool.AddCert(rootCert)
  1870  		}
  1871  
  1872  		intermediatePool := NewCertPool()
  1873  
  1874  		for level, intermediates := range test.intermediates {
  1875  			levelKey := privateKeys.Get().(*ecdsa.PrivateKey)
  1876  			keys = append(keys, levelKey)
  1877  			levelName := "Intermediate level " + strconv.Itoa(level)
  1878  			var last *Certificate
  1879  
  1880  			for _, intermediate := range intermediates {
  1881  				caCert, err := makeConstraintsCACert(intermediate, levelName, levelKey, parent, parentKey)
  1882  				if err != nil {
  1883  					t.Fatalf("#%d: failed to create %q: %s", i, levelName, err)
  1884  				}
  1885  
  1886  				last = caCert
  1887  				intermediatePool.AddCert(caCert)
  1888  			}
  1889  
  1890  			parent = last
  1891  			parentKey = levelKey
  1892  		}
  1893  
  1894  		leafKey := privateKeys.Get().(*ecdsa.PrivateKey)
  1895  		keys = append(keys, leafKey)
  1896  
  1897  		leafCert, err := makeConstraintsLeafCert(test.leaf, leafKey, parent, parentKey)
  1898  		if err != nil {
  1899  			t.Fatalf("#%d: cannot create leaf: %s", i, err)
  1900  		}
  1901  
  1902  		if !test.noOpenSSL && testNameConstraintsAgainstOpenSSL {
  1903  			output, err := testChainAgainstOpenSSL(leafCert, intermediatePool, rootPool)
  1904  			if err == nil && len(test.expectedError) > 0 {
  1905  				t.Errorf("#%d: unexpectedly succeeded against OpenSSL", i)
  1906  				if debugOpenSSLFailure {
  1907  					return
  1908  				}
  1909  			}
  1910  
  1911  			if err != nil {
  1912  				if _, ok := err.(*exec.ExitError); !ok {
  1913  					t.Errorf("#%d: OpenSSL failed to run: %s", i, err)
  1914  				} else if len(test.expectedError) == 0 {
  1915  					t.Errorf("#%d: OpenSSL unexpectedly failed: %q", i, output)
  1916  					if debugOpenSSLFailure {
  1917  						return
  1918  					}
  1919  				}
  1920  			}
  1921  		}
  1922  
  1923  		verifyOpts := VerifyOptions{
  1924  			Roots:         rootPool,
  1925  			Intermediates: intermediatePool,
  1926  			CurrentTime:   time.Unix(1500, 0),
  1927  			KeyUsages:     test.requestedEKUs,
  1928  		}
  1929  		_, err = leafCert.Verify(verifyOpts)
  1930  
  1931  		logInfo := true
  1932  		if len(test.expectedError) == 0 {
  1933  			if err != nil {
  1934  				t.Errorf("#%d: unexpected failure: %s", i, err)
  1935  			} else {
  1936  				logInfo = false
  1937  			}
  1938  		} else {
  1939  			if err == nil {
  1940  				t.Errorf("#%d: unexpected success", i)
  1941  			} else if !strings.Contains(err.Error(), test.expectedError) {
  1942  				t.Errorf("#%d: expected error containing %q, but got: %s", i, test.expectedError, err)
  1943  			} else {
  1944  				logInfo = false
  1945  			}
  1946  		}
  1947  
  1948  		if logInfo {
  1949  			certAsPEM := func(cert *Certificate) string {
  1950  				var buf bytes.Buffer
  1951  				pem.Encode(&buf, &pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw})
  1952  				return string(buf.Bytes())
  1953  			}
  1954  			t.Errorf("#%d: root:\n%s", i, certAsPEM(rootPool.certs[0]))
  1955  			t.Errorf("#%d: leaf:\n%s", i, certAsPEM(leafCert))
  1956  		}
  1957  
  1958  		for _, key := range keys {
  1959  			privateKeys.Put(key)
  1960  		}
  1961  		keys = keys[:0]
  1962  	}
  1963  }
  1964  
  1965  func writePEMsToTempFile(certs []*Certificate) *os.File {
  1966  	file, err := ioutil.TempFile("", "name_constraints_test")
  1967  	if err != nil {
  1968  		panic("cannot create tempfile")
  1969  	}
  1970  
  1971  	pemBlock := &pem.Block{Type: "CERTIFICATE"}
  1972  	for _, cert := range certs {
  1973  		pemBlock.Bytes = cert.Raw
  1974  		pem.Encode(file, pemBlock)
  1975  	}
  1976  
  1977  	return file
  1978  }
  1979  
  1980  func testChainAgainstOpenSSL(leaf *Certificate, intermediates, roots *CertPool) (string, error) {
  1981  	args := []string{"verify", "-no_check_time"}
  1982  
  1983  	rootsFile := writePEMsToTempFile(roots.certs)
  1984  	if debugOpenSSLFailure {
  1985  		println("roots file:", rootsFile.Name())
  1986  	} else {
  1987  		defer os.Remove(rootsFile.Name())
  1988  	}
  1989  	args = append(args, "-CAfile", rootsFile.Name())
  1990  
  1991  	if len(intermediates.certs) > 0 {
  1992  		intermediatesFile := writePEMsToTempFile(intermediates.certs)
  1993  		if debugOpenSSLFailure {
  1994  			println("intermediates file:", intermediatesFile.Name())
  1995  		} else {
  1996  			defer os.Remove(intermediatesFile.Name())
  1997  		}
  1998  		args = append(args, "-untrusted", intermediatesFile.Name())
  1999  	}
  2000  
  2001  	leafFile := writePEMsToTempFile([]*Certificate{leaf})
  2002  	if debugOpenSSLFailure {
  2003  		println("leaf file:", leafFile.Name())
  2004  	} else {
  2005  		defer os.Remove(leafFile.Name())
  2006  	}
  2007  	args = append(args, leafFile.Name())
  2008  
  2009  	var output bytes.Buffer
  2010  	cmd := exec.Command("openssl", args...)
  2011  	cmd.Stdout = &output
  2012  	cmd.Stderr = &output
  2013  
  2014  	err := cmd.Run()
  2015  	return string(output.Bytes()), err
  2016  }
  2017  
  2018  var rfc2821Tests = []struct {
  2019  	in                string
  2020  	localPart, domain string
  2021  }{
  2022  	{"foo@example.com", "foo", "example.com"},
  2023  	{"@example.com", "", ""},
  2024  	{"\"@example.com", "", ""},
  2025  	{"\"\"@example.com", "", "example.com"},
  2026  	{"\"a\"@example.com", "a", "example.com"},
  2027  	{"\"\\a\"@example.com", "a", "example.com"},
  2028  	{"a\"@example.com", "", ""},
  2029  	{"foo..bar@example.com", "", ""},
  2030  	{".foo.bar@example.com", "", ""},
  2031  	{"foo.bar.@example.com", "", ""},
  2032  	{"|{}?'@example.com", "|{}?'", "example.com"},
  2033  
  2034  	// Examples from RFC 3696
  2035  	{"Abc\\@def@example.com", "Abc@def", "example.com"},
  2036  	{"Fred\\ Bloggs@example.com", "Fred Bloggs", "example.com"},
  2037  	{"Joe.\\\\Blow@example.com", "Joe.\\Blow", "example.com"},
  2038  	{"\"Abc@def\"@example.com", "Abc@def", "example.com"},
  2039  	{"\"Fred Bloggs\"@example.com", "Fred Bloggs", "example.com"},
  2040  	{"customer/department=shipping@example.com", "customer/department=shipping", "example.com"},
  2041  	{"$A12345@example.com", "$A12345", "example.com"},
  2042  	{"!def!xyz%abc@example.com", "!def!xyz%abc", "example.com"},
  2043  	{"_somename@example.com", "_somename", "example.com"},
  2044  }
  2045  
  2046  func TestRFC2821Parsing(t *testing.T) {
  2047  	for i, test := range rfc2821Tests {
  2048  		mailbox, ok := parseRFC2821Mailbox(test.in)
  2049  		expectedFailure := len(test.localPart) == 0 && len(test.domain) == 0
  2050  
  2051  		if ok && expectedFailure {
  2052  			t.Errorf("#%d: %q unexpectedly parsed as (%q, %q)", i, test.in, mailbox.local, mailbox.domain)
  2053  			continue
  2054  		}
  2055  
  2056  		if !ok && !expectedFailure {
  2057  			t.Errorf("#%d: unexpected failure for %q", i, test.in)
  2058  			continue
  2059  		}
  2060  
  2061  		if !ok {
  2062  			continue
  2063  		}
  2064  
  2065  		if mailbox.local != test.localPart || mailbox.domain != test.domain {
  2066  			t.Errorf("#%d: %q parsed as (%q, %q), but wanted (%q, %q)", i, test.in, mailbox.local, mailbox.domain, test.localPart, test.domain)
  2067  		}
  2068  	}
  2069  }
  2070  
  2071  func TestBadNamesInConstraints(t *testing.T) {
  2072  	constraintParseError := func(err error) bool {
  2073  		str := err.Error()
  2074  		return strings.Contains(str, "failed to parse ") && strings.Contains(str, "constraint")
  2075  	}
  2076  
  2077  	encodingError := func(err error) bool {
  2078  		return strings.Contains(err.Error(), "cannot be encoded as an IA5String")
  2079  	}
  2080  
  2081  	// Bad names in constraints should not parse.
  2082  	badNames := []struct {
  2083  		name    string
  2084  		matcher func(error) bool
  2085  	}{
  2086  		{"dns:foo.com.", constraintParseError},
  2087  		{"email:abc@foo.com.", constraintParseError},
  2088  		{"email:foo.com.", constraintParseError},
  2089  		{"uri:example.com.", constraintParseError},
  2090  		{"uri:1.2.3.4", constraintParseError},
  2091  		{"uri:ffff::1", constraintParseError},
  2092  		{"dns:not–hyphen.com", encodingError},
  2093  		{"email:foo@not–hyphen.com", encodingError},
  2094  		{"uri:not–hyphen.com", encodingError},
  2095  	}
  2096  
  2097  	priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  2098  	if err != nil {
  2099  		panic(err)
  2100  	}
  2101  
  2102  	for _, test := range badNames {
  2103  		_, err := makeConstraintsCACert(constraintsSpec{
  2104  			ok: []string{test.name},
  2105  		}, "TestAbsoluteNamesInConstraints", priv, nil, priv)
  2106  
  2107  		if err == nil {
  2108  			t.Errorf("bad name %q unexpectedly accepted in name constraint", test.name)
  2109  			continue
  2110  		} else {
  2111  			if !test.matcher(err) {
  2112  				t.Errorf("bad name %q triggered unrecognised error: %s", test.name, err)
  2113  			}
  2114  		}
  2115  	}
  2116  }
  2117  
  2118  func TestBadNamesInSANs(t *testing.T) {
  2119  	// Bad names in URI and IP SANs should not parse. Bad DNS and email SANs
  2120  	// will parse and are tested in name constraint tests at the top of this
  2121  	// file.
  2122  	badNames := []string{
  2123  		"uri:https://example.com./dsf",
  2124  		"invalidip:0102",
  2125  		"invalidip:0102030405",
  2126  	}
  2127  
  2128  	priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  2129  	if err != nil {
  2130  		panic(err)
  2131  	}
  2132  
  2133  	for _, badName := range badNames {
  2134  		_, err := makeConstraintsLeafCert(leafSpec{sans: []string{badName}}, priv, nil, priv)
  2135  
  2136  		if err == nil {
  2137  			t.Errorf("bad name %q unexpectedly accepted in SAN", badName)
  2138  			continue
  2139  		}
  2140  
  2141  		if err != nil {
  2142  			if str := err.Error(); !strings.Contains(str, "cannot parse ") {
  2143  				t.Errorf("bad name %q triggered unrecognised error: %s", badName, str)
  2144  			}
  2145  		}
  2146  	}
  2147  }