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