github.com/ltltlt/go-source-code@v0.0.0-20190830023027-95be009773aa/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: An intermediate with enumerated EKUs causes a failure if we 1226 // test for an EKU not in that set. (ServerAuth is required by 1227 // default.) 1228 nameConstraintsTest{ 1229 roots: []constraintsSpec{ 1230 constraintsSpec{}, 1231 }, 1232 intermediates: [][]constraintsSpec{ 1233 []constraintsSpec{ 1234 constraintsSpec{ 1235 ekus: []string{"email"}, 1236 }, 1237 }, 1238 }, 1239 leaf: leafSpec{ 1240 sans: []string{"dns:example.com"}, 1241 ekus: []string{"serverAuth"}, 1242 }, 1243 expectedError: "incompatible key usage", 1244 }, 1245 1246 // #64: an unknown EKU in the leaf doesn't break anything, even if it's not 1247 // correctly nested. 1248 nameConstraintsTest{ 1249 roots: []constraintsSpec{ 1250 constraintsSpec{}, 1251 }, 1252 intermediates: [][]constraintsSpec{ 1253 []constraintsSpec{ 1254 constraintsSpec{ 1255 ekus: []string{"email"}, 1256 }, 1257 }, 1258 }, 1259 leaf: leafSpec{ 1260 sans: []string{"dns:example.com"}, 1261 ekus: []string{"other"}, 1262 }, 1263 requestedEKUs: []ExtKeyUsage{ExtKeyUsageAny}, 1264 }, 1265 1266 // #65: trying to add extra permitted key usages in an intermediate 1267 // (after a limitation in the root) is acceptable so long as the leaf 1268 // certificate doesn't use them. 1269 nameConstraintsTest{ 1270 roots: []constraintsSpec{ 1271 constraintsSpec{ 1272 ekus: []string{"serverAuth"}, 1273 }, 1274 }, 1275 intermediates: [][]constraintsSpec{ 1276 []constraintsSpec{ 1277 constraintsSpec{ 1278 ekus: []string{"serverAuth", "email"}, 1279 }, 1280 }, 1281 }, 1282 leaf: leafSpec{ 1283 sans: []string{"dns:example.com"}, 1284 ekus: []string{"serverAuth"}, 1285 }, 1286 }, 1287 1288 // #66: EKUs in roots are not ignored. 1289 nameConstraintsTest{ 1290 roots: []constraintsSpec{ 1291 constraintsSpec{ 1292 ekus: []string{"email"}, 1293 }, 1294 }, 1295 intermediates: [][]constraintsSpec{ 1296 []constraintsSpec{ 1297 constraintsSpec{ 1298 ekus: []string{"serverAuth"}, 1299 }, 1300 }, 1301 }, 1302 leaf: leafSpec{ 1303 sans: []string{"dns:example.com"}, 1304 ekus: []string{"serverAuth"}, 1305 }, 1306 expectedError: "incompatible key usage", 1307 }, 1308 1309 // #67: in order to support COMODO chains, SGC key usages permit 1310 // serverAuth and clientAuth. 1311 nameConstraintsTest{ 1312 roots: []constraintsSpec{ 1313 constraintsSpec{}, 1314 }, 1315 intermediates: [][]constraintsSpec{ 1316 []constraintsSpec{ 1317 constraintsSpec{ 1318 ekus: []string{"netscapeSGC"}, 1319 }, 1320 }, 1321 }, 1322 leaf: leafSpec{ 1323 sans: []string{"dns:example.com"}, 1324 ekus: []string{"serverAuth", "clientAuth"}, 1325 }, 1326 }, 1327 1328 // #68: in order to support COMODO chains, SGC key usages permit 1329 // serverAuth and clientAuth. 1330 nameConstraintsTest{ 1331 roots: []constraintsSpec{ 1332 constraintsSpec{}, 1333 }, 1334 intermediates: [][]constraintsSpec{ 1335 []constraintsSpec{ 1336 constraintsSpec{ 1337 ekus: []string{"msSGC"}, 1338 }, 1339 }, 1340 }, 1341 leaf: leafSpec{ 1342 sans: []string{"dns:example.com"}, 1343 ekus: []string{"serverAuth", "clientAuth"}, 1344 }, 1345 }, 1346 1347 // #69: an empty DNS constraint should allow anything. 1348 nameConstraintsTest{ 1349 roots: []constraintsSpec{ 1350 constraintsSpec{ 1351 ok: []string{"dns:"}, 1352 }, 1353 }, 1354 intermediates: [][]constraintsSpec{ 1355 []constraintsSpec{ 1356 constraintsSpec{}, 1357 }, 1358 }, 1359 leaf: leafSpec{ 1360 sans: []string{"dns:example.com"}, 1361 }, 1362 }, 1363 1364 // #70: an empty DNS constraint should also reject everything. 1365 nameConstraintsTest{ 1366 roots: []constraintsSpec{ 1367 constraintsSpec{ 1368 bad: []string{"dns:"}, 1369 }, 1370 }, 1371 intermediates: [][]constraintsSpec{ 1372 []constraintsSpec{ 1373 constraintsSpec{}, 1374 }, 1375 }, 1376 leaf: leafSpec{ 1377 sans: []string{"dns:example.com"}, 1378 }, 1379 expectedError: "\"example.com\" is excluded", 1380 }, 1381 1382 // #71: an empty email constraint should allow anything 1383 nameConstraintsTest{ 1384 roots: []constraintsSpec{ 1385 constraintsSpec{ 1386 ok: []string{"email:"}, 1387 }, 1388 }, 1389 intermediates: [][]constraintsSpec{ 1390 []constraintsSpec{ 1391 constraintsSpec{}, 1392 }, 1393 }, 1394 leaf: leafSpec{ 1395 sans: []string{"email:foo@example.com"}, 1396 }, 1397 }, 1398 1399 // #72: an empty email constraint should also reject everything. 1400 nameConstraintsTest{ 1401 roots: []constraintsSpec{ 1402 constraintsSpec{ 1403 bad: []string{"email:"}, 1404 }, 1405 }, 1406 intermediates: [][]constraintsSpec{ 1407 []constraintsSpec{ 1408 constraintsSpec{}, 1409 }, 1410 }, 1411 leaf: leafSpec{ 1412 sans: []string{"email:foo@example.com"}, 1413 }, 1414 expectedError: "\"foo@example.com\" is excluded", 1415 }, 1416 1417 // #73: an empty URI constraint should allow anything 1418 nameConstraintsTest{ 1419 roots: []constraintsSpec{ 1420 constraintsSpec{ 1421 ok: []string{"uri:"}, 1422 }, 1423 }, 1424 intermediates: [][]constraintsSpec{ 1425 []constraintsSpec{ 1426 constraintsSpec{}, 1427 }, 1428 }, 1429 leaf: leafSpec{ 1430 sans: []string{"uri:https://example.com/test"}, 1431 }, 1432 }, 1433 1434 // #74: an empty URI constraint should also reject everything. 1435 nameConstraintsTest{ 1436 roots: []constraintsSpec{ 1437 constraintsSpec{ 1438 bad: []string{"uri:"}, 1439 }, 1440 }, 1441 intermediates: [][]constraintsSpec{ 1442 []constraintsSpec{ 1443 constraintsSpec{}, 1444 }, 1445 }, 1446 leaf: leafSpec{ 1447 sans: []string{"uri:https://example.com/test"}, 1448 }, 1449 expectedError: "\"https://example.com/test\" is excluded", 1450 }, 1451 1452 // #75: serverAuth in a leaf shouldn't permit clientAuth when requested in 1453 // VerifyOptions. 1454 nameConstraintsTest{ 1455 roots: []constraintsSpec{ 1456 constraintsSpec{}, 1457 }, 1458 intermediates: [][]constraintsSpec{ 1459 []constraintsSpec{ 1460 constraintsSpec{}, 1461 }, 1462 }, 1463 leaf: leafSpec{ 1464 sans: []string{"dns:example.com"}, 1465 ekus: []string{"serverAuth"}, 1466 }, 1467 requestedEKUs: []ExtKeyUsage{ExtKeyUsageClientAuth}, 1468 expectedError: "incompatible key usage", 1469 }, 1470 1471 // #76: However, MSSGC in a leaf should match a request for serverAuth. 1472 nameConstraintsTest{ 1473 roots: []constraintsSpec{ 1474 constraintsSpec{}, 1475 }, 1476 intermediates: [][]constraintsSpec{ 1477 []constraintsSpec{ 1478 constraintsSpec{}, 1479 }, 1480 }, 1481 leaf: leafSpec{ 1482 sans: []string{"dns:example.com"}, 1483 ekus: []string{"msSGC"}, 1484 }, 1485 requestedEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}, 1486 }, 1487 1488 // An invalid DNS SAN should be detected only at validation time so 1489 // that we can process CA certificates in the wild that have invalid SANs. 1490 // See https://github.com/golang/go/issues/23995 1491 1492 // #77: an invalid DNS or mail SAN will not be detected if name constaint 1493 // checking is not triggered. 1494 nameConstraintsTest{ 1495 roots: []constraintsSpec{ 1496 constraintsSpec{}, 1497 }, 1498 intermediates: [][]constraintsSpec{ 1499 []constraintsSpec{ 1500 constraintsSpec{}, 1501 }, 1502 }, 1503 leaf: leafSpec{ 1504 sans: []string{"dns:this is invalid", "email:this @ is invalid"}, 1505 }, 1506 }, 1507 1508 // #78: an invalid DNS SAN will be detected if any name constraint checking 1509 // is triggered. 1510 nameConstraintsTest{ 1511 roots: []constraintsSpec{ 1512 constraintsSpec{ 1513 bad: []string{"uri:"}, 1514 }, 1515 }, 1516 intermediates: [][]constraintsSpec{ 1517 []constraintsSpec{ 1518 constraintsSpec{}, 1519 }, 1520 }, 1521 leaf: leafSpec{ 1522 sans: []string{"dns:this is invalid"}, 1523 }, 1524 expectedError: "cannot parse dnsName", 1525 }, 1526 1527 // #79: an invalid email SAN will be detected if any name constraint 1528 // checking is triggered. 1529 nameConstraintsTest{ 1530 roots: []constraintsSpec{ 1531 constraintsSpec{ 1532 bad: []string{"uri:"}, 1533 }, 1534 }, 1535 intermediates: [][]constraintsSpec{ 1536 []constraintsSpec{ 1537 constraintsSpec{}, 1538 }, 1539 }, 1540 leaf: leafSpec{ 1541 sans: []string{"email:this @ is invalid"}, 1542 }, 1543 expectedError: "cannot parse rfc822Name", 1544 }, 1545 1546 // #80: if several EKUs are requested, satisfying any of them is sufficient. 1547 nameConstraintsTest{ 1548 roots: []constraintsSpec{ 1549 constraintsSpec{}, 1550 }, 1551 intermediates: [][]constraintsSpec{ 1552 []constraintsSpec{ 1553 constraintsSpec{}, 1554 }, 1555 }, 1556 leaf: leafSpec{ 1557 sans: []string{"dns:example.com"}, 1558 ekus: []string{"email"}, 1559 }, 1560 requestedEKUs: []ExtKeyUsage{ExtKeyUsageClientAuth, ExtKeyUsageEmailProtection}, 1561 }, 1562 1563 // #81: EKUs that are not asserted in VerifyOpts are not required to be 1564 // nested. 1565 nameConstraintsTest{ 1566 roots: []constraintsSpec{ 1567 constraintsSpec{}, 1568 }, 1569 intermediates: [][]constraintsSpec{ 1570 []constraintsSpec{ 1571 constraintsSpec{ 1572 ekus: []string{"serverAuth"}, 1573 }, 1574 }, 1575 }, 1576 leaf: leafSpec{ 1577 sans: []string{"dns:example.com"}, 1578 // There's no email EKU in the intermediate. This would be rejected if 1579 // full nesting was required. 1580 ekus: []string{"email", "serverAuth"}, 1581 }, 1582 }, 1583 } 1584 1585 func makeConstraintsCACert(constraints constraintsSpec, name string, key *ecdsa.PrivateKey, parent *Certificate, parentKey *ecdsa.PrivateKey) (*Certificate, error) { 1586 var serialBytes [16]byte 1587 rand.Read(serialBytes[:]) 1588 1589 template := &Certificate{ 1590 SerialNumber: new(big.Int).SetBytes(serialBytes[:]), 1591 Subject: pkix.Name{ 1592 CommonName: name, 1593 }, 1594 NotBefore: time.Unix(1000, 0), 1595 NotAfter: time.Unix(2000, 0), 1596 KeyUsage: KeyUsageCertSign, 1597 BasicConstraintsValid: true, 1598 IsCA: true, 1599 } 1600 1601 if err := addConstraintsToTemplate(constraints, template); err != nil { 1602 return nil, err 1603 } 1604 1605 if parent == nil { 1606 parent = template 1607 } 1608 derBytes, err := CreateCertificate(rand.Reader, template, parent, &key.PublicKey, parentKey) 1609 if err != nil { 1610 return nil, err 1611 } 1612 1613 caCert, err := ParseCertificate(derBytes) 1614 if err != nil { 1615 return nil, err 1616 } 1617 1618 return caCert, nil 1619 } 1620 1621 func makeConstraintsLeafCert(leaf leafSpec, key *ecdsa.PrivateKey, parent *Certificate, parentKey *ecdsa.PrivateKey) (*Certificate, error) { 1622 var serialBytes [16]byte 1623 rand.Read(serialBytes[:]) 1624 1625 template := &Certificate{ 1626 SerialNumber: new(big.Int).SetBytes(serialBytes[:]), 1627 Subject: pkix.Name{ 1628 // Don't set a CommonName because OpenSSL (at least) will try to 1629 // match it against name constraints. 1630 OrganizationalUnit: []string{"Leaf"}, 1631 }, 1632 NotBefore: time.Unix(1000, 0), 1633 NotAfter: time.Unix(2000, 0), 1634 KeyUsage: KeyUsageDigitalSignature, 1635 BasicConstraintsValid: true, 1636 IsCA: false, 1637 } 1638 1639 for _, name := range leaf.sans { 1640 switch { 1641 case strings.HasPrefix(name, "dns:"): 1642 template.DNSNames = append(template.DNSNames, name[4:]) 1643 1644 case strings.HasPrefix(name, "ip:"): 1645 ip := net.ParseIP(name[3:]) 1646 if ip == nil { 1647 return nil, fmt.Errorf("cannot parse IP %q", name[3:]) 1648 } 1649 template.IPAddresses = append(template.IPAddresses, ip) 1650 1651 case strings.HasPrefix(name, "invalidip:"): 1652 ipBytes, err := hex.DecodeString(name[10:]) 1653 if err != nil { 1654 return nil, fmt.Errorf("cannot parse invalid IP: %s", err) 1655 } 1656 template.IPAddresses = append(template.IPAddresses, net.IP(ipBytes)) 1657 1658 case strings.HasPrefix(name, "email:"): 1659 template.EmailAddresses = append(template.EmailAddresses, name[6:]) 1660 1661 case strings.HasPrefix(name, "uri:"): 1662 uri, err := url.Parse(name[4:]) 1663 if err != nil { 1664 return nil, fmt.Errorf("cannot parse URI %q: %s", name[4:], err) 1665 } 1666 template.URIs = append(template.URIs, uri) 1667 1668 case strings.HasPrefix(name, "unknown:"): 1669 // This is a special case for testing unknown 1670 // name types. A custom SAN extension is 1671 // injected into the certificate. 1672 if len(leaf.sans) != 1 { 1673 panic("when using unknown name types, it must be the sole name") 1674 } 1675 1676 template.ExtraExtensions = append(template.ExtraExtensions, pkix.Extension{ 1677 Id: []int{2, 5, 29, 17}, 1678 Value: []byte{ 1679 0x30, // SEQUENCE 1680 3, // three bytes 1681 9, // undefined GeneralName type 9 1682 1, 1683 1, 1684 }, 1685 }) 1686 1687 default: 1688 return nil, fmt.Errorf("unknown name type %q", name) 1689 } 1690 } 1691 1692 var err error 1693 if template.ExtKeyUsage, template.UnknownExtKeyUsage, err = parseEKUs(leaf.ekus); err != nil { 1694 return nil, err 1695 } 1696 1697 if parent == nil { 1698 parent = template 1699 } 1700 1701 derBytes, err := CreateCertificate(rand.Reader, template, parent, &key.PublicKey, parentKey) 1702 if err != nil { 1703 return nil, err 1704 } 1705 1706 return ParseCertificate(derBytes) 1707 } 1708 1709 func customConstraintsExtension(typeNum int, constraint []byte, isExcluded bool) pkix.Extension { 1710 appendConstraint := func(contents []byte, tag uint8) []byte { 1711 contents = append(contents, tag|32 /* constructed */ |0x80 /* context-specific */) 1712 contents = append(contents, byte(4+len(constraint)) /* length */) 1713 contents = append(contents, 0x30 /* SEQUENCE */) 1714 contents = append(contents, byte(2+len(constraint)) /* length */) 1715 contents = append(contents, byte(typeNum) /* GeneralName type */) 1716 contents = append(contents, byte(len(constraint))) 1717 return append(contents, constraint...) 1718 } 1719 1720 var contents []byte 1721 if !isExcluded { 1722 contents = appendConstraint(contents, 0 /* tag 0 for permitted */) 1723 } else { 1724 contents = appendConstraint(contents, 1 /* tag 1 for excluded */) 1725 } 1726 1727 var value []byte 1728 value = append(value, 0x30 /* SEQUENCE */) 1729 value = append(value, byte(len(contents))) 1730 value = append(value, contents...) 1731 1732 return pkix.Extension{ 1733 Id: []int{2, 5, 29, 30}, 1734 Value: value, 1735 } 1736 } 1737 1738 func addConstraintsToTemplate(constraints constraintsSpec, template *Certificate) error { 1739 parse := func(constraints []string) (dnsNames []string, ips []*net.IPNet, emailAddrs []string, uriDomains []string, err error) { 1740 for _, constraint := range constraints { 1741 switch { 1742 case strings.HasPrefix(constraint, "dns:"): 1743 dnsNames = append(dnsNames, constraint[4:]) 1744 1745 case strings.HasPrefix(constraint, "ip:"): 1746 _, ipNet, err := net.ParseCIDR(constraint[3:]) 1747 if err != nil { 1748 return nil, nil, nil, nil, err 1749 } 1750 ips = append(ips, ipNet) 1751 1752 case strings.HasPrefix(constraint, "email:"): 1753 emailAddrs = append(emailAddrs, constraint[6:]) 1754 1755 case strings.HasPrefix(constraint, "uri:"): 1756 uriDomains = append(uriDomains, constraint[4:]) 1757 1758 default: 1759 return nil, nil, nil, nil, fmt.Errorf("unknown constraint %q", constraint) 1760 } 1761 } 1762 1763 return dnsNames, ips, emailAddrs, uriDomains, err 1764 } 1765 1766 handleSpecialConstraint := func(constraint string, isExcluded bool) bool { 1767 switch { 1768 case constraint == "unknown:": 1769 template.ExtraExtensions = append(template.ExtraExtensions, customConstraintsExtension(9 /* undefined GeneralName type */, []byte{1}, isExcluded)) 1770 1771 default: 1772 return false 1773 } 1774 1775 return true 1776 } 1777 1778 if len(constraints.ok) == 1 && len(constraints.bad) == 0 { 1779 if handleSpecialConstraint(constraints.ok[0], false) { 1780 return nil 1781 } 1782 } 1783 1784 if len(constraints.bad) == 1 && len(constraints.ok) == 0 { 1785 if handleSpecialConstraint(constraints.bad[0], true) { 1786 return nil 1787 } 1788 } 1789 1790 var err error 1791 template.PermittedDNSDomains, template.PermittedIPRanges, template.PermittedEmailAddresses, template.PermittedURIDomains, err = parse(constraints.ok) 1792 if err != nil { 1793 return err 1794 } 1795 1796 template.ExcludedDNSDomains, template.ExcludedIPRanges, template.ExcludedEmailAddresses, template.ExcludedURIDomains, err = parse(constraints.bad) 1797 if err != nil { 1798 return err 1799 } 1800 1801 if template.ExtKeyUsage, template.UnknownExtKeyUsage, err = parseEKUs(constraints.ekus); err != nil { 1802 return err 1803 } 1804 1805 return nil 1806 } 1807 1808 func parseEKUs(ekuStrs []string) (ekus []ExtKeyUsage, unknowns []asn1.ObjectIdentifier, err error) { 1809 for _, s := range ekuStrs { 1810 switch s { 1811 case "serverAuth": 1812 ekus = append(ekus, ExtKeyUsageServerAuth) 1813 case "clientAuth": 1814 ekus = append(ekus, ExtKeyUsageClientAuth) 1815 case "email": 1816 ekus = append(ekus, ExtKeyUsageEmailProtection) 1817 case "netscapeSGC": 1818 ekus = append(ekus, ExtKeyUsageNetscapeServerGatedCrypto) 1819 case "msSGC": 1820 ekus = append(ekus, ExtKeyUsageMicrosoftServerGatedCrypto) 1821 case "any": 1822 ekus = append(ekus, ExtKeyUsageAny) 1823 case "other": 1824 unknowns = append(unknowns, asn1.ObjectIdentifier{2, 4, 1, 2, 3}) 1825 default: 1826 return nil, nil, fmt.Errorf("unknown EKU %q", s) 1827 } 1828 } 1829 1830 return 1831 } 1832 1833 func TestConstraintCases(t *testing.T) { 1834 privateKeys := sync.Pool{ 1835 New: func() interface{} { 1836 priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 1837 if err != nil { 1838 panic(err) 1839 } 1840 return priv 1841 }, 1842 } 1843 1844 for i, test := range nameConstraintsTests { 1845 rootPool := NewCertPool() 1846 rootKey := privateKeys.Get().(*ecdsa.PrivateKey) 1847 rootName := "Root " + strconv.Itoa(i) 1848 1849 // keys keeps track of all the private keys used in a given 1850 // test and puts them back in the privateKeys pool at the end. 1851 keys := []*ecdsa.PrivateKey{rootKey} 1852 1853 // At each level (root, intermediate(s), leaf), parent points to 1854 // an example parent certificate and parentKey the key for the 1855 // parent level. Since all certificates at a given level have 1856 // the same name and public key, any parent certificate is 1857 // sufficient to get the correct issuer name and authority 1858 // key ID. 1859 var parent *Certificate 1860 parentKey := rootKey 1861 1862 for _, root := range test.roots { 1863 rootCert, err := makeConstraintsCACert(root, rootName, rootKey, nil, rootKey) 1864 if err != nil { 1865 t.Fatalf("#%d: failed to create root: %s", i, err) 1866 } 1867 1868 parent = rootCert 1869 rootPool.AddCert(rootCert) 1870 } 1871 1872 intermediatePool := NewCertPool() 1873 1874 for level, intermediates := range test.intermediates { 1875 levelKey := privateKeys.Get().(*ecdsa.PrivateKey) 1876 keys = append(keys, levelKey) 1877 levelName := "Intermediate level " + strconv.Itoa(level) 1878 var last *Certificate 1879 1880 for _, intermediate := range intermediates { 1881 caCert, err := makeConstraintsCACert(intermediate, levelName, levelKey, parent, parentKey) 1882 if err != nil { 1883 t.Fatalf("#%d: failed to create %q: %s", i, levelName, err) 1884 } 1885 1886 last = caCert 1887 intermediatePool.AddCert(caCert) 1888 } 1889 1890 parent = last 1891 parentKey = levelKey 1892 } 1893 1894 leafKey := privateKeys.Get().(*ecdsa.PrivateKey) 1895 keys = append(keys, leafKey) 1896 1897 leafCert, err := makeConstraintsLeafCert(test.leaf, leafKey, parent, parentKey) 1898 if err != nil { 1899 t.Fatalf("#%d: cannot create leaf: %s", i, err) 1900 } 1901 1902 if !test.noOpenSSL && testNameConstraintsAgainstOpenSSL { 1903 output, err := testChainAgainstOpenSSL(leafCert, intermediatePool, rootPool) 1904 if err == nil && len(test.expectedError) > 0 { 1905 t.Errorf("#%d: unexpectedly succeeded against OpenSSL", i) 1906 if debugOpenSSLFailure { 1907 return 1908 } 1909 } 1910 1911 if err != nil { 1912 if _, ok := err.(*exec.ExitError); !ok { 1913 t.Errorf("#%d: OpenSSL failed to run: %s", i, err) 1914 } else if len(test.expectedError) == 0 { 1915 t.Errorf("#%d: OpenSSL unexpectedly failed: %q", i, output) 1916 if debugOpenSSLFailure { 1917 return 1918 } 1919 } 1920 } 1921 } 1922 1923 verifyOpts := VerifyOptions{ 1924 Roots: rootPool, 1925 Intermediates: intermediatePool, 1926 CurrentTime: time.Unix(1500, 0), 1927 KeyUsages: test.requestedEKUs, 1928 } 1929 _, err = leafCert.Verify(verifyOpts) 1930 1931 logInfo := true 1932 if len(test.expectedError) == 0 { 1933 if err != nil { 1934 t.Errorf("#%d: unexpected failure: %s", i, err) 1935 } else { 1936 logInfo = false 1937 } 1938 } else { 1939 if err == nil { 1940 t.Errorf("#%d: unexpected success", i) 1941 } else if !strings.Contains(err.Error(), test.expectedError) { 1942 t.Errorf("#%d: expected error containing %q, but got: %s", i, test.expectedError, err) 1943 } else { 1944 logInfo = false 1945 } 1946 } 1947 1948 if logInfo { 1949 certAsPEM := func(cert *Certificate) string { 1950 var buf bytes.Buffer 1951 pem.Encode(&buf, &pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw}) 1952 return string(buf.Bytes()) 1953 } 1954 t.Errorf("#%d: root:\n%s", i, certAsPEM(rootPool.certs[0])) 1955 t.Errorf("#%d: leaf:\n%s", i, certAsPEM(leafCert)) 1956 } 1957 1958 for _, key := range keys { 1959 privateKeys.Put(key) 1960 } 1961 keys = keys[:0] 1962 } 1963 } 1964 1965 func writePEMsToTempFile(certs []*Certificate) *os.File { 1966 file, err := ioutil.TempFile("", "name_constraints_test") 1967 if err != nil { 1968 panic("cannot create tempfile") 1969 } 1970 1971 pemBlock := &pem.Block{Type: "CERTIFICATE"} 1972 for _, cert := range certs { 1973 pemBlock.Bytes = cert.Raw 1974 pem.Encode(file, pemBlock) 1975 } 1976 1977 return file 1978 } 1979 1980 func testChainAgainstOpenSSL(leaf *Certificate, intermediates, roots *CertPool) (string, error) { 1981 args := []string{"verify", "-no_check_time"} 1982 1983 rootsFile := writePEMsToTempFile(roots.certs) 1984 if debugOpenSSLFailure { 1985 println("roots file:", rootsFile.Name()) 1986 } else { 1987 defer os.Remove(rootsFile.Name()) 1988 } 1989 args = append(args, "-CAfile", rootsFile.Name()) 1990 1991 if len(intermediates.certs) > 0 { 1992 intermediatesFile := writePEMsToTempFile(intermediates.certs) 1993 if debugOpenSSLFailure { 1994 println("intermediates file:", intermediatesFile.Name()) 1995 } else { 1996 defer os.Remove(intermediatesFile.Name()) 1997 } 1998 args = append(args, "-untrusted", intermediatesFile.Name()) 1999 } 2000 2001 leafFile := writePEMsToTempFile([]*Certificate{leaf}) 2002 if debugOpenSSLFailure { 2003 println("leaf file:", leafFile.Name()) 2004 } else { 2005 defer os.Remove(leafFile.Name()) 2006 } 2007 args = append(args, leafFile.Name()) 2008 2009 var output bytes.Buffer 2010 cmd := exec.Command("openssl", args...) 2011 cmd.Stdout = &output 2012 cmd.Stderr = &output 2013 2014 err := cmd.Run() 2015 return string(output.Bytes()), err 2016 } 2017 2018 var rfc2821Tests = []struct { 2019 in string 2020 localPart, domain string 2021 }{ 2022 {"foo@example.com", "foo", "example.com"}, 2023 {"@example.com", "", ""}, 2024 {"\"@example.com", "", ""}, 2025 {"\"\"@example.com", "", "example.com"}, 2026 {"\"a\"@example.com", "a", "example.com"}, 2027 {"\"\\a\"@example.com", "a", "example.com"}, 2028 {"a\"@example.com", "", ""}, 2029 {"foo..bar@example.com", "", ""}, 2030 {".foo.bar@example.com", "", ""}, 2031 {"foo.bar.@example.com", "", ""}, 2032 {"|{}?'@example.com", "|{}?'", "example.com"}, 2033 2034 // Examples from RFC 3696 2035 {"Abc\\@def@example.com", "Abc@def", "example.com"}, 2036 {"Fred\\ Bloggs@example.com", "Fred Bloggs", "example.com"}, 2037 {"Joe.\\\\Blow@example.com", "Joe.\\Blow", "example.com"}, 2038 {"\"Abc@def\"@example.com", "Abc@def", "example.com"}, 2039 {"\"Fred Bloggs\"@example.com", "Fred Bloggs", "example.com"}, 2040 {"customer/department=shipping@example.com", "customer/department=shipping", "example.com"}, 2041 {"$A12345@example.com", "$A12345", "example.com"}, 2042 {"!def!xyz%abc@example.com", "!def!xyz%abc", "example.com"}, 2043 {"_somename@example.com", "_somename", "example.com"}, 2044 } 2045 2046 func TestRFC2821Parsing(t *testing.T) { 2047 for i, test := range rfc2821Tests { 2048 mailbox, ok := parseRFC2821Mailbox(test.in) 2049 expectedFailure := len(test.localPart) == 0 && len(test.domain) == 0 2050 2051 if ok && expectedFailure { 2052 t.Errorf("#%d: %q unexpectedly parsed as (%q, %q)", i, test.in, mailbox.local, mailbox.domain) 2053 continue 2054 } 2055 2056 if !ok && !expectedFailure { 2057 t.Errorf("#%d: unexpected failure for %q", i, test.in) 2058 continue 2059 } 2060 2061 if !ok { 2062 continue 2063 } 2064 2065 if mailbox.local != test.localPart || mailbox.domain != test.domain { 2066 t.Errorf("#%d: %q parsed as (%q, %q), but wanted (%q, %q)", i, test.in, mailbox.local, mailbox.domain, test.localPart, test.domain) 2067 } 2068 } 2069 } 2070 2071 func TestBadNamesInConstraints(t *testing.T) { 2072 constraintParseError := func(err error) bool { 2073 str := err.Error() 2074 return strings.Contains(str, "failed to parse ") && strings.Contains(str, "constraint") 2075 } 2076 2077 encodingError := func(err error) bool { 2078 return strings.Contains(err.Error(), "cannot be encoded as an IA5String") 2079 } 2080 2081 // Bad names in constraints should not parse. 2082 badNames := []struct { 2083 name string 2084 matcher func(error) bool 2085 }{ 2086 {"dns:foo.com.", constraintParseError}, 2087 {"email:abc@foo.com.", constraintParseError}, 2088 {"email:foo.com.", constraintParseError}, 2089 {"uri:example.com.", constraintParseError}, 2090 {"uri:1.2.3.4", constraintParseError}, 2091 {"uri:ffff::1", constraintParseError}, 2092 {"dns:not–hyphen.com", encodingError}, 2093 {"email:foo@not–hyphen.com", encodingError}, 2094 {"uri:not–hyphen.com", encodingError}, 2095 } 2096 2097 priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 2098 if err != nil { 2099 panic(err) 2100 } 2101 2102 for _, test := range badNames { 2103 _, err := makeConstraintsCACert(constraintsSpec{ 2104 ok: []string{test.name}, 2105 }, "TestAbsoluteNamesInConstraints", priv, nil, priv) 2106 2107 if err == nil { 2108 t.Errorf("bad name %q unexpectedly accepted in name constraint", test.name) 2109 continue 2110 } else { 2111 if !test.matcher(err) { 2112 t.Errorf("bad name %q triggered unrecognised error: %s", test.name, err) 2113 } 2114 } 2115 } 2116 } 2117 2118 func TestBadNamesInSANs(t *testing.T) { 2119 // Bad names in URI and IP SANs should not parse. Bad DNS and email SANs 2120 // will parse and are tested in name constraint tests at the top of this 2121 // file. 2122 badNames := []string{ 2123 "uri:https://example.com./dsf", 2124 "invalidip:0102", 2125 "invalidip:0102030405", 2126 } 2127 2128 priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 2129 if err != nil { 2130 panic(err) 2131 } 2132 2133 for _, badName := range badNames { 2134 _, err := makeConstraintsLeafCert(leafSpec{sans: []string{badName}}, priv, nil, priv) 2135 2136 if err == nil { 2137 t.Errorf("bad name %q unexpectedly accepted in SAN", badName) 2138 continue 2139 } 2140 2141 if err != nil { 2142 if str := err.Error(); !strings.Contains(str, "cannot parse ") { 2143 t.Errorf("bad name %q triggered unrecognised error: %s", badName, str) 2144 } 2145 } 2146 } 2147 }