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