]> git.saurik.com Git - apple/security.git/blobdiff - CertTool/cdsaUtils/oidParser.cpp
Security-54.tar.gz
[apple/security.git] / CertTool / cdsaUtils / oidParser.cpp
diff --git a/CertTool/cdsaUtils/oidParser.cpp b/CertTool/cdsaUtils/oidParser.cpp
new file mode 100644 (file)
index 0000000..a25a9be
--- /dev/null
@@ -0,0 +1,296 @@
+/*
+ * oidParser.cpp - parse an Intel-style OID, with the assistance of dumpasn1.cfg
+ */
+#include <Security/cssmtype.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "oidParser.h"
+#include "fileIo.h"
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+/* get config file from .. or from . */
+#define                CONFIG_FILE_NAME        "dumpasn1.cfg"
+static char    *CONFIG_FILE1 =         "../"CONFIG_FILE_NAME;
+static char    *CONFIG_FILE2 =         CONFIG_FILE_NAME;
+/* or from here via getenv */
+#define                CONFIG_FILE_ENV         "LOCAL_BUILD_DIR"
+
+static char    *OID_ENTRY_START = "OID = ";
+static char    *OID_DESCR_START = "Description = ";
+/*
+ * Read entire file with extra bytes left over in the mallocd buffer. 
+ */
+int readFileExtra(
+       char                    *fileName,
+       unsigned                extraBytes,
+       unsigned char   **bytes,                // mallocd and returned
+       unsigned                *numBytes)              // returned
+{
+       int rtn;
+       int fd;
+       unsigned char *buf;
+       struct stat     sb;
+       unsigned size;
+       
+       *numBytes = 0;
+       *bytes = NULL;
+       fd = open(fileName, O_RDONLY, 0);
+       if(fd <= 0) {
+               return 1;
+       }
+       rtn = fstat(fd, &sb);
+       if(rtn) {
+               goto errOut;
+       }
+       size = sb.st_size;
+       buf = (unsigned char *)malloc(size + extraBytes);
+       if(buf == NULL) {
+               rtn = ENOMEM;
+               goto errOut;
+       }
+       rtn = lseek(fd, 0, SEEK_SET);
+       if(rtn < 0) {
+               goto errOut;
+       }
+       rtn = read(fd, buf, (size_t)size);
+       if(rtn != (int)size) {
+               if(rtn >= 0) {
+                       printf("readFile: short read\n");
+               }
+               rtn = EIO;
+       }
+       else {
+               rtn = 0;
+               *bytes = buf;
+               *numBytes = size;
+       }
+errOut:
+       close(fd);
+       return rtn;
+}
+
+/*
+ * Attempt to read dumpasn1.cfg from various places. If we can't find it, 
+ * printOid() function will just print raw bytes as it
+ * would if the .cfg file did not contain the desired OID.
+ */
+static CSSM_DATA_PTR readConfig()
+{
+       CSSM_DATA_PTR   configData = NULL;
+       int                             rtn;
+       
+       configData = (CSSM_DATA_PTR)malloc(sizeof(CSSM_DATA));
+       if(configData == NULL) {
+               return NULL;
+       }
+       /* malloc one extra byte, we'll null it later */
+       rtn = readFileExtra(CONFIG_FILE1, 1, &configData->Data, 
+               (unsigned *)&configData->Length);
+       if(rtn) {
+               rtn = readFileExtra(CONFIG_FILE2, 1, &configData->Data, 
+                               (unsigned *)&configData->Length);
+       }
+       if(rtn) {
+               char fileName[100];
+               char *localBuildDir  = getenv(CONFIG_FILE_ENV);
+               if(localBuildDir == NULL) {
+                       rtn = 1;
+               }
+               else {
+                       sprintf(fileName,  "%s/%s", localBuildDir, CONFIG_FILE_NAME);
+                       rtn = readFileExtra(fileName, 1, &configData->Data, 
+                                       (unsigned *)&configData->Length);
+               }
+       }
+       if(rtn == 0) {
+               /* make the whole shebang one long C string */
+               configData->Data[configData->Length++] = '\0';
+               return configData;
+       }
+       else {
+               printf("""warning: no OID parser config file\n");
+               free(configData);
+               return NULL;
+       }
+}
+
+/*
+ * The heart of this module. 
+ *
+ * -- Convert Intel-style OID to a string which might be found 
+ *    in the config file
+ * -- search config file for that string
+ * -- if found, use that entry in config file to output meaningful
+ *    string and return CSSM_TRUE. Else return CSSM_FALSE.
+ */
+static CSSM_BOOL parseOidWithConfig(
+       const CSSM_DATA_PTR configData, 
+       const CSSM_OID_PTR      oid, 
+       char                            *strBuf)
+{
+       char                            *fullOidStr = NULL;
+       char                            *ourEntry = NULL;
+       char                            *nextEntry = NULL;
+       char                            *descStart = NULL;
+       char                            *cp;
+       unsigned                        i;
+       CSSM_BOOL                       brtn;
+       char                            *nextCr;                // next CR if any
+       char                            *nextNl;                // next NL if any
+       char                            *eol;                   // end of line
+       int                                     len;
+       
+       if(configData == NULL) {
+               return CSSM_FALSE;
+       }
+       
+       /* cook up a full OID string, with tag and length */
+       fullOidStr = (char *)malloc((3 * oid->Length) +         
+                                                                                               // 2 chars plus space per byte
+               strlen(OID_ENTRY_START) +                               // "OID = "
+               6 +                                                                             // 06 xx - tag and length
+               1);                                                                             // NULL
+       if(fullOidStr == NULL) {
+               return CSSM_FALSE;
+       }
+       /* subsequent errors to errOut: */
+       
+       sprintf(fullOidStr, "OID = 06 %02X", (unsigned)oid->Length);
+       cp = fullOidStr + strlen(fullOidStr);
+       for(i=0; i<oid->Length; i++) {
+               /* move cp to current end of string */
+               cp += strlen(cp);
+               /* add one byte */
+               sprintf(cp, " %02X", oid->Data[i]);
+       }
+       
+       /* 
+        * Let's play it loose and assume that there are no embedded NULLs
+        * in the config file. Thus we can use the spiffy string functions
+        * in stdlib. 
+        */
+       ourEntry = strstr((char *)configData->Data, fullOidStr);
+       if(ourEntry == NULL) {
+               brtn = CSSM_FALSE;
+               goto errOut;
+       }
+       
+       /* get position of NEXT full entry - may be NULL (end of file) */
+       nextEntry = strstr(ourEntry+1, OID_ENTRY_START);
+       
+       /* get position of our entry's description line */
+       descStart = strstr(ourEntry+1, OID_DESCR_START);
+       
+       /* handle not found/overflow */
+       if( (descStart == NULL) ||                      // no more description lines
+           ( (descStart > nextEntry) &&        // no description in THIS entry
+             (nextEntry != NULL) ) ) {         // make sure this is valid
+               brtn = CSSM_FALSE;
+               goto errOut;
+       }
+       
+       /* set descStart to after the leader */
+       descStart += strlen(OID_DESCR_START);
+       
+       /* 
+        * descStart points to the text we're interested in.
+        * First find end of line, any style. 
+        */
+       nextNl = strchr(descStart, '\n');
+       nextCr = strchr(descStart, '\r');
+       if((nextNl == NULL) && (nextCr == NULL)) {
+               /* no line terminator, go to eof */
+               eol = (char *)configData->Data + configData->Length;
+       }
+       else if(nextCr == NULL) {
+               eol = nextNl;
+       }
+       else if(nextNl == NULL) {
+               eol = nextCr;
+       }
+       else if(nextNl < nextCr) {
+               /* both present, take first one */
+               eol = nextNl;
+       }
+       else {
+               eol = nextCr;
+       }
+       
+       /* caller's string buf = remainder of description line */
+       len = eol - descStart;
+       if(len > (OID_PARSER_STRING_SIZE - 1)) {
+               /* fixed-length output buf, avoid overflow */
+               len = OID_PARSER_STRING_SIZE - 1;
+       }
+       memcpy(strBuf, descStart, len);
+       strBuf[len] = '\0';
+       brtn = CSSM_TRUE; 
+errOut:
+       if(fullOidStr != NULL) {
+               free(fullOidStr);
+       }
+       return brtn;
+}
+
+/*** OidParser class ***/
+OidParser::OidParser(bool noConfig)
+{
+       if(noConfig) {
+               configData = NULL;
+       }
+       else {
+               configData = readConfig();
+       }
+}
+
+OidParser::~OidParser()
+{
+       if(configData == NULL) {
+               return;
+       }
+       if(configData->Data != NULL) {
+               free(configData->Data);
+       }
+       free(configData);
+}
+
+/*
+ * Parse an Intel-style OID, generating a C string in caller-supplied buffer.
+ */
+void OidParser::oidParse(
+       const unsigned char     *oidp,
+       unsigned                        oidLen,
+       char                            *strBuf)
+{
+       unsigned i;
+       CSSM_OID oid;
+       
+       oid.Data = (uint8  *)oidp;
+       oid.Length = oidLen;
+       
+       if((oidLen == 0) || (oidp == NULL)) {
+               strcpy(strBuf, "EMPTY");
+               return;
+       }
+       if(parseOidWithConfig(configData, &oid, strBuf) == CSSM_FALSE) {
+               /* no config file, just dump the bytes */
+               char cbuf[8];
+               
+               sprintf(strBuf, "OID : < 06 %02X ", (unsigned)oid.Length);
+               for(i=0; i<oid.Length; i++) {
+                       sprintf(cbuf, "%02X ", oid.Data[i]);
+                       strcat(strBuf, cbuf);
+               }
+               strcat(strBuf, ">");
+       }
+}
+
+