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