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