]> git.saurik.com Git - apple/security.git/blob - SecurityTests/clxutils/NISCC/TLS_SSL/certDecode/certDecode.cpp
Security-57336.1.9.tar.gz
[apple/security.git] / SecurityTests / clxutils / NISCC / TLS_SSL / certDecode / certDecode.cpp
1 /*
2 * Attempt to decode either one file, or every file in cwd,
3 * as a cert. Used to study vulnerability to NISCC cert DOS attacks.
4 */
5 #include <Security/SecAsn1Coder.h>
6 #include <Security/X509Templates.h>
7 #include <security_cdsa_utils/cuFileIo.h>
8 #include <sys/types.h>
9 #include <dirent.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <strings.h>
13
14 static void usage(char **argv)
15 {
16 printf("usage: %s [-l(oop))] [certFile]\n", argv[0]);
17 exit(1);
18 }
19
20 /*
21 * Known file names to NOT parse
22 */
23 static const char *skipTheseFiles[] =
24 {
25 /* standard entries */
26 ".",
27 "..",
28 "CVS",
29 ".cvsignore",
30 /* the certs we know crash */
31 #if 0
32 "00000668",
33 "00000681",
34 "00001980",
35 "00002040",
36 "00002892",
37 "00007472",
38 "00008064",
39 "00008656",
40 "00009840",
41 "00010432",
42 "00011614", // trouble somewhere in this neighborhood
43 "00011615",
44 "00011616",
45 #endif
46 NULL
47 };
48
49 /* returns false if specified fileName is in skipTheseFiles[] */
50 static bool shouldWeParse(
51 const char *fileName) // C string
52 {
53 for(const char **stf=skipTheseFiles; *stf!=NULL; stf++) {
54 const char *tf = *stf;
55 if(!strcmp(fileName, *stf)) {
56 return false;
57 }
58 }
59 return true;
60 }
61
62 /*
63 * Just try to decode - if SecAsn1Decode returns, good 'nuff.
64 * Returns true if it does (i.e. ignore decode error; we're trying
65 * to detect a crash when the decoder should return an error).
66 */
67 bool decodeCert(
68 const void *certData,
69 size_t certDataLen)
70 {
71 SecAsn1CoderRef coder = NULL;
72 NSS_Certificate nssCert;
73 NSS_SignedCertOrCRL certOrCrl;
74
75 SecAsn1CoderCreate(&coder);
76
77 /* first the full decode */
78 memset(&nssCert, 0, sizeof(nssCert));
79 SecAsn1Decode(coder, certData, certDataLen, kSecAsn1SignedCertTemplate, &nssCert);
80
81 /* now the "just TBS and sig" decode - this is actually harder
82 * due to nested SEC_ASN1_SAVE ops */
83 memset(&certOrCrl, 0, sizeof(NSS_SignedCertOrCRL));
84 SecAsn1Decode(coder, certData, certDataLen, kSecAsn1SignedCertOrCRLTemplate, &certOrCrl);
85
86 SecAsn1CoderRelease(coder);
87 return true;
88 }
89
90 int main(int argc, char **argv)
91 {
92 bool quiet = false;
93 unsigned char *certData;
94 unsigned certDataLen;
95 bool loop = false;
96 int filearg = 1;
97
98 if(argc > 3 ) {
99 usage(argv);
100 }
101 if((argc > 1) && (argv[1][0] == '-')) {
102 switch(argv[1][1]) {
103 case 'l':
104 loop = true;
105 break;
106 default:
107 usage(argv);
108 }
109 filearg++;
110 argc--;
111 }
112 if(argc == 2) {
113 /* read & parse one file */
114 char *oneFile = argv[filearg];
115 if(readFile(oneFile, &certData, &certDataLen)) {
116 printf("\n***Error reading file %s. Aborting.\n", oneFile);
117 exit(1);
118 }
119 do {
120 if(!quiet) {
121 printf("...%s", oneFile);
122 fflush(stdout);
123 }
124 if(!decodeCert(certData, certDataLen)) {
125 printf("\n***GOT AN EXCEPTION ON %s\n", oneFile);
126 exit(1);
127 }
128 } while(loop);
129 free(certData);
130 exit(0);
131 }
132 DIR *dir = opendir(".");
133 if(dir == NULL) {
134 printf("Huh? Can't open . as a directory.\n");
135 exit(1);
136 }
137 struct dirent *de = readdir(dir);
138 while(de != NULL) {
139 char filename[MAXNAMLEN + 1];
140 memmove(filename, de->d_name, de->d_namlen);
141 filename[de->d_namlen] = '\0';
142 if(shouldWeParse(filename)) {
143 if(!quiet) {
144 printf("...%s", filename);
145 fflush(stdout);
146 }
147 if(readFile(filename, &certData, &certDataLen)) {
148 printf("\n***Error reading file %s. Aborting.\n", filename);
149 exit(1);
150 }
151 if(!decodeCert(certData, certDataLen)) {
152 printf("\n***GOT AN EXCEPTION ON %s\n", filename);
153 exit(1);
154 }
155 free(certData);
156 }
157 de = readdir(dir);
158 }
159 closedir(dir);
160 printf("\ncertDecode did not crash.\n");
161 return 0;
162 }
163