github.com/c9s/go@v0.0.0-20180120015821-984e81f64e0c/src/crypto/x509/name_constraints_test.go (about)

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