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