...

Source file src/crypto/x509/name_constraints_test.go

Documentation: crypto/x509

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

View as plain text