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