github.com/goproxy0/go@v0.0.0-20171111080102-49cc0c489d2c/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  	// TODO(agl): handle empty name constraints. Currently this doesn't
  1189  	// work because empty values are treated as missing.
  1190  
  1191  	// #61: omitting extended key usage in a CA certificate implies that
  1192  	// any usage is ok.
  1193  	nameConstraintsTest{
  1194  		roots: []constraintsSpec{
  1195  			constraintsSpec{},
  1196  		},
  1197  		intermediates: [][]constraintsSpec{
  1198  			[]constraintsSpec{
  1199  				constraintsSpec{},
  1200  			},
  1201  		},
  1202  		leaf: leafSpec{
  1203  			sans: []string{"dns:example.com"},
  1204  			ekus: []string{"serverAuth", "other"},
  1205  		},
  1206  	},
  1207  
  1208  	// #62: The “any” EKU also means that any usage is ok.
  1209  	nameConstraintsTest{
  1210  		roots: []constraintsSpec{
  1211  			constraintsSpec{},
  1212  		},
  1213  		intermediates: [][]constraintsSpec{
  1214  			[]constraintsSpec{
  1215  				constraintsSpec{
  1216  					ekus: []string{"any"},
  1217  				},
  1218  			},
  1219  		},
  1220  		leaf: leafSpec{
  1221  			sans: []string{"dns:example.com"},
  1222  			ekus: []string{"serverAuth", "other"},
  1223  		},
  1224  	},
  1225  
  1226  	// #63: A specified key usage in an intermediate forbids other usages
  1227  	// in the leaf.
  1228  	nameConstraintsTest{
  1229  		roots: []constraintsSpec{
  1230  			constraintsSpec{},
  1231  		},
  1232  		intermediates: [][]constraintsSpec{
  1233  			[]constraintsSpec{
  1234  				constraintsSpec{
  1235  					ekus: []string{"email"},
  1236  				},
  1237  			},
  1238  		},
  1239  		leaf: leafSpec{
  1240  			sans: []string{"dns:example.com"},
  1241  			ekus: []string{"serverAuth"},
  1242  		},
  1243  		expectedError: "EKU not permitted",
  1244  	},
  1245  
  1246  	// #64: A specified key usage in an intermediate forbids other usages
  1247  	// in the leaf, even if we don't recognise them.
  1248  	nameConstraintsTest{
  1249  		roots: []constraintsSpec{
  1250  			constraintsSpec{},
  1251  		},
  1252  		intermediates: [][]constraintsSpec{
  1253  			[]constraintsSpec{
  1254  				constraintsSpec{
  1255  					ekus: []string{"email"},
  1256  				},
  1257  			},
  1258  		},
  1259  		leaf: leafSpec{
  1260  			sans: []string{"dns:example.com"},
  1261  			ekus: []string{"other"},
  1262  		},
  1263  		expectedError: "EKU not permitted",
  1264  	},
  1265  
  1266  	// #65: trying to add extra permitted key usages in an intermediate
  1267  	// (after a limitation in the root) is acceptable so long as the leaf
  1268  	// certificate doesn't use them.
  1269  	nameConstraintsTest{
  1270  		roots: []constraintsSpec{
  1271  			constraintsSpec{
  1272  				ekus: []string{"serverAuth"},
  1273  			},
  1274  		},
  1275  		intermediates: [][]constraintsSpec{
  1276  			[]constraintsSpec{
  1277  				constraintsSpec{
  1278  					ekus: []string{"serverAuth", "email"},
  1279  				},
  1280  			},
  1281  		},
  1282  		leaf: leafSpec{
  1283  			sans: []string{"dns:example.com"},
  1284  			ekus: []string{"serverAuth"},
  1285  		},
  1286  	},
  1287  
  1288  	// #66: trying to add extra permitted key usages in an intermediate
  1289  	// (after a limitation in the root) doesn't allow those usages in a
  1290  	// leaf.
  1291  	nameConstraintsTest{
  1292  		roots: []constraintsSpec{
  1293  			constraintsSpec{
  1294  				ekus: []string{"serverAuth"},
  1295  			},
  1296  		},
  1297  		intermediates: [][]constraintsSpec{
  1298  			[]constraintsSpec{
  1299  				constraintsSpec{
  1300  					ekus: []string{"serverAuth", "email"},
  1301  				},
  1302  			},
  1303  		},
  1304  		leaf: leafSpec{
  1305  			sans: []string{"dns:example.com"},
  1306  			ekus: []string{"serverAuth", "email"},
  1307  		},
  1308  		expectedError: "EKU not permitted",
  1309  	},
  1310  
  1311  	// #67: in order to support COMODO chains, SGC key usages permit
  1312  	// serverAuth and clientAuth.
  1313  	nameConstraintsTest{
  1314  		roots: []constraintsSpec{
  1315  			constraintsSpec{},
  1316  		},
  1317  		intermediates: [][]constraintsSpec{
  1318  			[]constraintsSpec{
  1319  				constraintsSpec{
  1320  					ekus: []string{"netscapeSGC"},
  1321  				},
  1322  			},
  1323  		},
  1324  		leaf: leafSpec{
  1325  			sans: []string{"dns:example.com"},
  1326  			ekus: []string{"serverAuth", "clientAuth"},
  1327  		},
  1328  	},
  1329  
  1330  	// #68: in order to support COMODO chains, SGC key usages permit
  1331  	// serverAuth and clientAuth.
  1332  	nameConstraintsTest{
  1333  		roots: []constraintsSpec{
  1334  			constraintsSpec{},
  1335  		},
  1336  		intermediates: [][]constraintsSpec{
  1337  			[]constraintsSpec{
  1338  				constraintsSpec{
  1339  					ekus: []string{"msSGC"},
  1340  				},
  1341  			},
  1342  		},
  1343  		leaf: leafSpec{
  1344  			sans: []string{"dns:example.com"},
  1345  			ekus: []string{"serverAuth", "clientAuth"},
  1346  		},
  1347  	},
  1348  }
  1349  
  1350  func makeConstraintsCACert(constraints constraintsSpec, name string, key *ecdsa.PrivateKey, parent *Certificate, parentKey *ecdsa.PrivateKey) (*Certificate, error) {
  1351  	var serialBytes [16]byte
  1352  	rand.Read(serialBytes[:])
  1353  
  1354  	template := &Certificate{
  1355  		SerialNumber: new(big.Int).SetBytes(serialBytes[:]),
  1356  		Subject: pkix.Name{
  1357  			CommonName: name,
  1358  		},
  1359  		NotBefore:             time.Unix(1000, 0),
  1360  		NotAfter:              time.Unix(2000, 0),
  1361  		KeyUsage:              KeyUsageCertSign,
  1362  		BasicConstraintsValid: true,
  1363  		IsCA: true,
  1364  	}
  1365  
  1366  	if err := addConstraintsToTemplate(constraints, template); err != nil {
  1367  		return nil, err
  1368  	}
  1369  
  1370  	if parent == nil {
  1371  		parent = template
  1372  	}
  1373  	derBytes, err := CreateCertificate(rand.Reader, template, parent, &key.PublicKey, parentKey)
  1374  	if err != nil {
  1375  		return nil, err
  1376  	}
  1377  
  1378  	caCert, err := ParseCertificate(derBytes)
  1379  	if err != nil {
  1380  		return nil, err
  1381  	}
  1382  
  1383  	return caCert, nil
  1384  }
  1385  
  1386  func makeConstraintsLeafCert(leaf leafSpec, key *ecdsa.PrivateKey, parent *Certificate, parentKey *ecdsa.PrivateKey) (*Certificate, error) {
  1387  	var serialBytes [16]byte
  1388  	rand.Read(serialBytes[:])
  1389  
  1390  	template := &Certificate{
  1391  		SerialNumber: new(big.Int).SetBytes(serialBytes[:]),
  1392  		Subject: pkix.Name{
  1393  			// Don't set a CommonName because OpenSSL (at least) will try to
  1394  			// match it against name constraints.
  1395  			OrganizationalUnit: []string{"Leaf"},
  1396  		},
  1397  		NotBefore:             time.Unix(1000, 0),
  1398  		NotAfter:              time.Unix(2000, 0),
  1399  		KeyUsage:              KeyUsageDigitalSignature,
  1400  		BasicConstraintsValid: true,
  1401  		IsCA: false,
  1402  	}
  1403  
  1404  	for _, name := range leaf.sans {
  1405  		switch {
  1406  		case strings.HasPrefix(name, "dns:"):
  1407  			template.DNSNames = append(template.DNSNames, name[4:])
  1408  
  1409  		case strings.HasPrefix(name, "ip:"):
  1410  			ip := net.ParseIP(name[3:])
  1411  			if ip == nil {
  1412  				return nil, fmt.Errorf("cannot parse IP %q", name[3:])
  1413  			}
  1414  			template.IPAddresses = append(template.IPAddresses, ip)
  1415  
  1416  		case strings.HasPrefix(name, "email:"):
  1417  			template.EmailAddresses = append(template.EmailAddresses, name[6:])
  1418  
  1419  		case strings.HasPrefix(name, "uri:"):
  1420  			uri, err := url.Parse(name[4:])
  1421  			if err != nil {
  1422  				return nil, fmt.Errorf("cannot parse URI %q: %s", name[4:], err)
  1423  			}
  1424  			template.URIs = append(template.URIs, uri)
  1425  
  1426  		case strings.HasPrefix(name, "unknown:"):
  1427  			// This is a special case for testing unknown
  1428  			// name types. A custom SAN extension is
  1429  			// injected into the certificate.
  1430  			if len(leaf.sans) != 1 {
  1431  				panic("when using unknown name types, it must be the sole name")
  1432  			}
  1433  
  1434  			template.ExtraExtensions = append(template.ExtraExtensions, pkix.Extension{
  1435  				Id: []int{2, 5, 29, 17},
  1436  				Value: []byte{
  1437  					0x30, // SEQUENCE
  1438  					3,    // three bytes
  1439  					9,    // undefined GeneralName type 9
  1440  					1,
  1441  					1,
  1442  				},
  1443  			})
  1444  
  1445  		default:
  1446  			return nil, fmt.Errorf("unknown name type %q", name)
  1447  		}
  1448  	}
  1449  
  1450  	var err error
  1451  	if template.ExtKeyUsage, template.UnknownExtKeyUsage, err = parseEKUs(leaf.ekus); err != nil {
  1452  		return nil, err
  1453  	}
  1454  
  1455  	if parent == nil {
  1456  		parent = template
  1457  	}
  1458  
  1459  	derBytes, err := CreateCertificate(rand.Reader, template, parent, &key.PublicKey, parentKey)
  1460  	if err != nil {
  1461  		return nil, err
  1462  	}
  1463  
  1464  	return ParseCertificate(derBytes)
  1465  }
  1466  
  1467  func customConstraintsExtension(typeNum int, constraint []byte, isExcluded bool) pkix.Extension {
  1468  	appendConstraint := func(contents []byte, tag uint8) []byte {
  1469  		contents = append(contents, tag|32 /* constructed */ |0x80 /* context-specific */)
  1470  		contents = append(contents, byte(4+len(constraint)) /* length */)
  1471  		contents = append(contents, 0x30 /* SEQUENCE */)
  1472  		contents = append(contents, byte(2+len(constraint)) /* length */)
  1473  		contents = append(contents, byte(typeNum) /* GeneralName type */)
  1474  		contents = append(contents, byte(len(constraint)))
  1475  		return append(contents, constraint...)
  1476  	}
  1477  
  1478  	var contents []byte
  1479  	if !isExcluded {
  1480  		contents = appendConstraint(contents, 0 /* tag 0 for permitted */)
  1481  	} else {
  1482  		contents = appendConstraint(contents, 1 /* tag 1 for excluded */)
  1483  	}
  1484  
  1485  	var value []byte
  1486  	value = append(value, 0x30 /* SEQUENCE */)
  1487  	value = append(value, byte(len(contents)))
  1488  	value = append(value, contents...)
  1489  
  1490  	return pkix.Extension{
  1491  		Id:    []int{2, 5, 29, 30},
  1492  		Value: value,
  1493  	}
  1494  }
  1495  
  1496  func addConstraintsToTemplate(constraints constraintsSpec, template *Certificate) error {
  1497  	parse := func(constraints []string) (dnsNames []string, ips []*net.IPNet, emailAddrs []string, uriDomains []string, err error) {
  1498  		for _, constraint := range constraints {
  1499  			switch {
  1500  			case strings.HasPrefix(constraint, "dns:"):
  1501  				dnsNames = append(dnsNames, constraint[4:])
  1502  
  1503  			case strings.HasPrefix(constraint, "ip:"):
  1504  				_, ipNet, err := net.ParseCIDR(constraint[3:])
  1505  				if err != nil {
  1506  					return nil, nil, nil, nil, err
  1507  				}
  1508  				ips = append(ips, ipNet)
  1509  
  1510  			case strings.HasPrefix(constraint, "email:"):
  1511  				emailAddrs = append(emailAddrs, constraint[6:])
  1512  
  1513  			case strings.HasPrefix(constraint, "uri:"):
  1514  				uriDomains = append(uriDomains, constraint[4:])
  1515  
  1516  			default:
  1517  				return nil, nil, nil, nil, fmt.Errorf("unknown constraint %q", constraint)
  1518  			}
  1519  		}
  1520  
  1521  		return dnsNames, ips, emailAddrs, uriDomains, err
  1522  	}
  1523  
  1524  	handleSpecialConstraint := func(constraint string, isExcluded bool) bool {
  1525  		switch {
  1526  		case constraint == "unknown:":
  1527  			template.ExtraExtensions = append(template.ExtraExtensions, customConstraintsExtension(9 /* undefined GeneralName type */, []byte{1}, isExcluded))
  1528  
  1529  		default:
  1530  			return false
  1531  		}
  1532  
  1533  		return true
  1534  	}
  1535  
  1536  	if len(constraints.ok) == 1 && len(constraints.bad) == 0 {
  1537  		if handleSpecialConstraint(constraints.ok[0], false) {
  1538  			return nil
  1539  		}
  1540  	}
  1541  
  1542  	if len(constraints.bad) == 1 && len(constraints.ok) == 0 {
  1543  		if handleSpecialConstraint(constraints.bad[0], true) {
  1544  			return nil
  1545  		}
  1546  	}
  1547  
  1548  	var err error
  1549  	template.PermittedDNSDomains, template.PermittedIPRanges, template.PermittedEmailAddresses, template.PermittedURIDomains, err = parse(constraints.ok)
  1550  	if err != nil {
  1551  		return err
  1552  	}
  1553  
  1554  	template.ExcludedDNSDomains, template.ExcludedIPRanges, template.ExcludedEmailAddresses, template.ExcludedURIDomains, err = parse(constraints.bad)
  1555  	if err != nil {
  1556  		return err
  1557  	}
  1558  
  1559  	if template.ExtKeyUsage, template.UnknownExtKeyUsage, err = parseEKUs(constraints.ekus); err != nil {
  1560  		return err
  1561  	}
  1562  
  1563  	return nil
  1564  }
  1565  
  1566  func parseEKUs(ekuStrs []string) (ekus []ExtKeyUsage, unknowns []asn1.ObjectIdentifier, err error) {
  1567  	for _, s := range ekuStrs {
  1568  		switch s {
  1569  		case "serverAuth":
  1570  			ekus = append(ekus, ExtKeyUsageServerAuth)
  1571  		case "clientAuth":
  1572  			ekus = append(ekus, ExtKeyUsageClientAuth)
  1573  		case "email":
  1574  			ekus = append(ekus, ExtKeyUsageEmailProtection)
  1575  		case "netscapeSGC":
  1576  			ekus = append(ekus, ExtKeyUsageNetscapeServerGatedCrypto)
  1577  		case "msSGC":
  1578  			ekus = append(ekus, ExtKeyUsageMicrosoftServerGatedCrypto)
  1579  		case "any":
  1580  			ekus = append(ekus, ExtKeyUsageAny)
  1581  		case "other":
  1582  			unknowns = append(unknowns, asn1.ObjectIdentifier{2, 4, 1, 2, 3})
  1583  		default:
  1584  			return nil, nil, fmt.Errorf("unknown EKU %q", s)
  1585  		}
  1586  	}
  1587  
  1588  	return
  1589  }
  1590  
  1591  func TestConstraintCases(t *testing.T) {
  1592  	privateKeys := sync.Pool{
  1593  		New: func() interface{} {
  1594  			priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  1595  			if err != nil {
  1596  				panic(err)
  1597  			}
  1598  			return priv
  1599  		},
  1600  	}
  1601  
  1602  	for i, test := range nameConstraintsTests {
  1603  		rootPool := NewCertPool()
  1604  		rootKey := privateKeys.Get().(*ecdsa.PrivateKey)
  1605  		rootName := "Root " + strconv.Itoa(i)
  1606  
  1607  		// keys keeps track of all the private keys used in a given
  1608  		// test and puts them back in the privateKeys pool at the end.
  1609  		keys := []*ecdsa.PrivateKey{rootKey}
  1610  
  1611  		// At each level (root, intermediate(s), leaf), parent points to
  1612  		// an example parent certificate and parentKey the key for the
  1613  		// parent level. Since all certificates at a given level have
  1614  		// the same name and public key, any parent certificate is
  1615  		// sufficient to get the correct issuer name and authority
  1616  		// key ID.
  1617  		var parent *Certificate
  1618  		parentKey := rootKey
  1619  
  1620  		for _, root := range test.roots {
  1621  			rootCert, err := makeConstraintsCACert(root, rootName, rootKey, nil, rootKey)
  1622  			if err != nil {
  1623  				t.Fatalf("#%d: failed to create root: %s", i, err)
  1624  			}
  1625  
  1626  			parent = rootCert
  1627  			rootPool.AddCert(rootCert)
  1628  		}
  1629  
  1630  		intermediatePool := NewCertPool()
  1631  
  1632  		for level, intermediates := range test.intermediates {
  1633  			levelKey := privateKeys.Get().(*ecdsa.PrivateKey)
  1634  			keys = append(keys, levelKey)
  1635  			levelName := "Intermediate level " + strconv.Itoa(level)
  1636  			var last *Certificate
  1637  
  1638  			for _, intermediate := range intermediates {
  1639  				caCert, err := makeConstraintsCACert(intermediate, levelName, levelKey, parent, parentKey)
  1640  				if err != nil {
  1641  					t.Fatalf("#%d: failed to create %q: %s", i, levelName, err)
  1642  				}
  1643  
  1644  				last = caCert
  1645  				intermediatePool.AddCert(caCert)
  1646  			}
  1647  
  1648  			parent = last
  1649  			parentKey = levelKey
  1650  		}
  1651  
  1652  		leafKey := privateKeys.Get().(*ecdsa.PrivateKey)
  1653  		keys = append(keys, leafKey)
  1654  
  1655  		leafCert, err := makeConstraintsLeafCert(test.leaf, leafKey, parent, parentKey)
  1656  		if err != nil {
  1657  			t.Fatalf("#%d: cannot create leaf: %s", i, err)
  1658  		}
  1659  
  1660  		if !test.noOpenSSL && testNameConstraintsAgainstOpenSSL {
  1661  			output, err := testChainAgainstOpenSSL(leafCert, intermediatePool, rootPool)
  1662  			if err == nil && len(test.expectedError) > 0 {
  1663  				t.Errorf("#%d: unexpectedly succeeded against OpenSSL", i)
  1664  				if debugOpenSSLFailure {
  1665  					return
  1666  				}
  1667  			}
  1668  
  1669  			if err != nil {
  1670  				if _, ok := err.(*exec.ExitError); !ok {
  1671  					t.Errorf("#%d: OpenSSL failed to run: %s", i, err)
  1672  				} else if len(test.expectedError) == 0 {
  1673  					t.Errorf("#%d: OpenSSL unexpectedly failed: %q", i, output)
  1674  					if debugOpenSSLFailure {
  1675  						return
  1676  					}
  1677  				}
  1678  			}
  1679  		}
  1680  
  1681  		verifyOpts := VerifyOptions{
  1682  			Roots:         rootPool,
  1683  			Intermediates: intermediatePool,
  1684  			CurrentTime:   time.Unix(1500, 0),
  1685  		}
  1686  		_, err = leafCert.Verify(verifyOpts)
  1687  
  1688  		logInfo := true
  1689  		if len(test.expectedError) == 0 {
  1690  			if err != nil {
  1691  				t.Errorf("#%d: unexpected failure: %s", i, err)
  1692  			} else {
  1693  				logInfo = false
  1694  			}
  1695  		} else {
  1696  			if err == nil {
  1697  				t.Errorf("#%d: unexpected success", i)
  1698  			} else if !strings.Contains(err.Error(), test.expectedError) {
  1699  				t.Errorf("#%d: expected error containing %q, but got: %s", i, test.expectedError, err)
  1700  			} else {
  1701  				logInfo = false
  1702  			}
  1703  		}
  1704  
  1705  		if logInfo {
  1706  			certAsPEM := func(cert *Certificate) string {
  1707  				var buf bytes.Buffer
  1708  				pem.Encode(&buf, &pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw})
  1709  				return string(buf.Bytes())
  1710  			}
  1711  			t.Errorf("#%d: root:\n%s", i, certAsPEM(rootPool.certs[0]))
  1712  			t.Errorf("#%d: leaf:\n%s", i, certAsPEM(leafCert))
  1713  		}
  1714  
  1715  		for _, key := range keys {
  1716  			privateKeys.Put(key)
  1717  		}
  1718  		keys = keys[:0]
  1719  	}
  1720  }
  1721  
  1722  func writePEMsToTempFile(certs []*Certificate) *os.File {
  1723  	file, err := ioutil.TempFile("", "name_constraints_test")
  1724  	if err != nil {
  1725  		panic("cannot create tempfile")
  1726  	}
  1727  
  1728  	pemBlock := &pem.Block{Type: "CERTIFICATE"}
  1729  	for _, cert := range certs {
  1730  		pemBlock.Bytes = cert.Raw
  1731  		pem.Encode(file, pemBlock)
  1732  	}
  1733  
  1734  	return file
  1735  }
  1736  
  1737  func testChainAgainstOpenSSL(leaf *Certificate, intermediates, roots *CertPool) (string, error) {
  1738  	args := []string{"verify", "-no_check_time"}
  1739  
  1740  	rootsFile := writePEMsToTempFile(roots.certs)
  1741  	if debugOpenSSLFailure {
  1742  		println("roots file:", rootsFile.Name())
  1743  	} else {
  1744  		defer os.Remove(rootsFile.Name())
  1745  	}
  1746  	args = append(args, "-CAfile", rootsFile.Name())
  1747  
  1748  	if len(intermediates.certs) > 0 {
  1749  		intermediatesFile := writePEMsToTempFile(intermediates.certs)
  1750  		if debugOpenSSLFailure {
  1751  			println("intermediates file:", intermediatesFile.Name())
  1752  		} else {
  1753  			defer os.Remove(intermediatesFile.Name())
  1754  		}
  1755  		args = append(args, "-untrusted", intermediatesFile.Name())
  1756  	}
  1757  
  1758  	leafFile := writePEMsToTempFile([]*Certificate{leaf})
  1759  	if debugOpenSSLFailure {
  1760  		println("leaf file:", leafFile.Name())
  1761  	} else {
  1762  		defer os.Remove(leafFile.Name())
  1763  	}
  1764  	args = append(args, leafFile.Name())
  1765  
  1766  	var output bytes.Buffer
  1767  	cmd := exec.Command("openssl", args...)
  1768  	cmd.Stdout = &output
  1769  	cmd.Stderr = &output
  1770  
  1771  	err := cmd.Run()
  1772  	return string(output.Bytes()), err
  1773  }
  1774  
  1775  var rfc2821Tests = []struct {
  1776  	in                string
  1777  	localPart, domain string
  1778  }{
  1779  	{"foo@example.com", "foo", "example.com"},
  1780  	{"@example.com", "", ""},
  1781  	{"\"@example.com", "", ""},
  1782  	{"\"\"@example.com", "", "example.com"},
  1783  	{"\"a\"@example.com", "a", "example.com"},
  1784  	{"\"\\a\"@example.com", "a", "example.com"},
  1785  	{"a\"@example.com", "", ""},
  1786  	{"foo..bar@example.com", "", ""},
  1787  	{".foo.bar@example.com", "", ""},
  1788  	{"foo.bar.@example.com", "", ""},
  1789  	{"|{}?'@example.com", "|{}?'", "example.com"},
  1790  
  1791  	// Examples from RFC 3696
  1792  	{"Abc\\@def@example.com", "Abc@def", "example.com"},
  1793  	{"Fred\\ Bloggs@example.com", "Fred Bloggs", "example.com"},
  1794  	{"Joe.\\\\Blow@example.com", "Joe.\\Blow", "example.com"},
  1795  	{"\"Abc@def\"@example.com", "Abc@def", "example.com"},
  1796  	{"\"Fred Bloggs\"@example.com", "Fred Bloggs", "example.com"},
  1797  	{"customer/department=shipping@example.com", "customer/department=shipping", "example.com"},
  1798  	{"$A12345@example.com", "$A12345", "example.com"},
  1799  	{"!def!xyz%abc@example.com", "!def!xyz%abc", "example.com"},
  1800  	{"_somename@example.com", "_somename", "example.com"},
  1801  }
  1802  
  1803  func TestRFC2821Parsing(t *testing.T) {
  1804  	for i, test := range rfc2821Tests {
  1805  		mailbox, ok := parseRFC2821Mailbox(test.in)
  1806  		expectedFailure := len(test.localPart) == 0 && len(test.domain) == 0
  1807  
  1808  		if ok && expectedFailure {
  1809  			t.Errorf("#%d: %q unexpectedly parsed as (%q, %q)", i, test.in, mailbox.local, mailbox.domain)
  1810  			continue
  1811  		}
  1812  
  1813  		if !ok && !expectedFailure {
  1814  			t.Errorf("#%d: unexpected failure for %q", i, test.in)
  1815  			continue
  1816  		}
  1817  
  1818  		if !ok {
  1819  			continue
  1820  		}
  1821  
  1822  		if mailbox.local != test.localPart || mailbox.domain != test.domain {
  1823  			t.Errorf("#%d: %q parsed as (%q, %q), but wanted (%q, %q)", i, test.in, mailbox.local, mailbox.domain, test.localPart, test.domain)
  1824  		}
  1825  	}
  1826  }
  1827  
  1828  func TestBadNamesInConstraints(t *testing.T) {
  1829  	// Bad names in constraints should not parse.
  1830  	badNames := []string{
  1831  		"dns:foo.com.",
  1832  		"email:abc@foo.com.",
  1833  		"email:foo.com.",
  1834  		"uri:example.com.",
  1835  		"uri:1.2.3.4",
  1836  		"uri:ffff::1",
  1837  	}
  1838  
  1839  	priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  1840  	if err != nil {
  1841  		panic(err)
  1842  	}
  1843  
  1844  	for _, badName := range badNames {
  1845  		_, err := makeConstraintsCACert(constraintsSpec{
  1846  			ok: []string{badName},
  1847  		}, "TestAbsoluteNamesInConstraints", priv, nil, priv)
  1848  
  1849  		if err == nil {
  1850  			t.Errorf("bad name %q unexpectedly accepted in name constraint", badName)
  1851  			continue
  1852  		}
  1853  
  1854  		if err != nil {
  1855  			if str := err.Error(); !strings.Contains(str, "failed to parse ") && !strings.Contains(str, "constraint") {
  1856  				t.Errorf("bad name %q triggered unrecognised error: %s", badName, str)
  1857  			}
  1858  		}
  1859  	}
  1860  }
  1861  
  1862  func TestBadNamesInSANs(t *testing.T) {
  1863  	// Bad names in SANs should not parse.
  1864  	badNames := []string{
  1865  		"dns:foo.com.",
  1866  		"email:abc@foo.com.",
  1867  		"email:foo.com.",
  1868  		"uri:https://example.com./dsf",
  1869  	}
  1870  
  1871  	priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  1872  	if err != nil {
  1873  		panic(err)
  1874  	}
  1875  
  1876  	for _, badName := range badNames {
  1877  		_, err := makeConstraintsLeafCert(leafSpec{sans: []string{badName}}, priv, nil, priv)
  1878  
  1879  		if err == nil {
  1880  			t.Errorf("bad name %q unexpectedly accepted in SAN", badName)
  1881  			continue
  1882  		}
  1883  
  1884  		if err != nil {
  1885  			if str := err.Error(); !strings.Contains(str, "cannot parse ") {
  1886  				t.Errorf("bad name %q triggered unrecognised error: %s", badName, str)
  1887  			}
  1888  		}
  1889  	}
  1890  }