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