]> git.saurik.com Git - apple/security.git/blobdiff - SecurityTests/clxutils/NISCC/TLS_SSL/certDecode/certDecode.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / SecurityTests / clxutils / NISCC / TLS_SSL / certDecode / certDecode.cpp
diff --git a/SecurityTests/clxutils/NISCC/TLS_SSL/certDecode/certDecode.cpp b/SecurityTests/clxutils/NISCC/TLS_SSL/certDecode/certDecode.cpp
new file mode 100644 (file)
index 0000000..22c80bf
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * Attempt to decode either one file, or every file in cwd,
+ * as a cert. Used to study vulnerability to NISCC cert DOS attacks. 
+ */
+#include <Security/SecAsn1Coder.h>
+#include <Security/X509Templates.h>
+#include <security_cdsa_utils/cuFileIo.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+
+static void usage(char **argv)
+{
+       printf("usage: %s [-l(oop))] [certFile]\n", argv[0]);
+       exit(1);
+}
+
+/*
+ * Known file names to NOT parse
+ */
+static const char *skipTheseFiles[] = 
+{
+       /* standard entries */
+       ".",
+       "..",
+       "CVS",
+       ".cvsignore",
+       /* the certs we know crash */
+       #if 0
+       "00000668",
+       "00000681",
+       "00001980",
+       "00002040",
+       "00002892",
+       "00007472",
+       "00008064",
+       "00008656",
+       "00009840",
+       "00010432",
+       "00011614",     // trouble somewhere in this neighborhood
+       "00011615",
+       "00011616",
+       #endif
+       NULL
+};
+
+/* returns false if specified fileName is in skipTheseFiles[] */
+static bool shouldWeParse(
+       const char *fileName)           // C string
+{
+       for(const char **stf=skipTheseFiles; *stf!=NULL; stf++) { 
+               const char *tf = *stf;
+               if(!strcmp(fileName, *stf)) {
+                       return false;
+               }
+       }
+       return true;
+}
+
+/* 
+ * Just try to decode - if SecAsn1Decode returns, good 'nuff.
+ * Returns true if it does (i.e. ignore decode error; we're trying
+ * to detect a crash when the decoder should return an error).
+ */
+bool decodeCert(
+       const void *certData, 
+       size_t certDataLen)
+{
+       SecAsn1CoderRef coder = NULL;
+       NSS_Certificate nssCert;
+       NSS_SignedCertOrCRL certOrCrl;
+       
+       SecAsn1CoderCreate(&coder);
+       
+       /* first the full decode */
+       memset(&nssCert, 0, sizeof(nssCert));
+       SecAsn1Decode(coder, certData, certDataLen,     kSecAsn1SignedCertTemplate, &nssCert);
+
+       /* now the "just TBS and sig" decode - this is actually harder
+        * due to nested SEC_ASN1_SAVE ops */
+       memset(&certOrCrl, 0, sizeof(NSS_SignedCertOrCRL));
+       SecAsn1Decode(coder, certData, certDataLen,     kSecAsn1SignedCertOrCRLTemplate, &certOrCrl);
+
+       SecAsn1CoderRelease(coder);
+       return true;
+}
+
+int main(int argc, char **argv)
+{
+       bool quiet = false;
+       unsigned char *certData;
+       unsigned certDataLen;
+       bool loop = false;
+       int filearg = 1;
+       
+       if(argc > 3 ) {
+               usage(argv);
+       }
+       if((argc > 1) && (argv[1][0] == '-')) {
+               switch(argv[1][1]) {
+                       case 'l':
+                               loop = true;
+                               break;
+                       default:
+                               usage(argv);
+               }
+               filearg++;
+               argc--;
+       }
+       if(argc == 2) {
+               /* read & parse one file */
+               char *oneFile = argv[filearg];
+               if(readFile(oneFile, &certData, &certDataLen)) {
+                       printf("\n***Error reading file %s. Aborting.\n", oneFile);
+                       exit(1);
+               }
+               do {
+                       if(!quiet) {
+                               printf("...%s", oneFile);
+                               fflush(stdout);
+                       }
+                       if(!decodeCert(certData, certDataLen)) {
+                               printf("\n***GOT AN EXCEPTION ON %s\n", oneFile);
+                               exit(1);
+                       }
+               } while(loop);
+               free(certData);
+               exit(0);
+       }
+       DIR *dir = opendir(".");
+       if(dir == NULL) {
+               printf("Huh? Can't open . as a directory.\n");
+               exit(1);
+       }
+       struct dirent *de = readdir(dir);
+       while(de != NULL) {
+               char filename[MAXNAMLEN + 1];
+               memmove(filename, de->d_name, de->d_namlen);
+               filename[de->d_namlen] = '\0';
+               if(shouldWeParse(filename)) {
+                       if(!quiet) {
+                               printf("...%s", filename);
+                               fflush(stdout);
+                       }
+                       if(readFile(filename, &certData, &certDataLen)) {
+                               printf("\n***Error reading file %s. Aborting.\n", filename);
+                               exit(1);
+                       }
+                       if(!decodeCert(certData, certDataLen)) {
+                               printf("\n***GOT AN EXCEPTION ON %s\n", filename);
+                               exit(1);
+                       }
+                       free(certData);
+               }
+               de = readdir(dir);
+       }       
+       closedir(dir);
+       printf("\ncertDecode did not crash.\n");
+       return 0;
+}
+