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