1/* 2 * Copyright (c) 2002-2003 Apple Computer, Inc. All Rights Reserved. 3 * 4 * The contents of this file constitute Original Code as defined in and are 5 * subject to the Apple Public Source License Version 1.2 (the 'License'). 6 * You may not use this file except in compliance with the License. 7 * Please obtain a copy of the License at http://www.apple.com/publicsource 8 * and read it before using this file. 9 * 10 * This Original Code and all software distributed under the License are 11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 12 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 13 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 14 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 15 * Please see the License for the specific language governing rights 16 * and limitations under the License. 17 */ 18 19/* 20 * cuOidParser.cpp - parse an Intel-style OID, with the assistance 21 * of dumpasn1.cfg 22 */ 23 24#include <Security/cssmtype.h> 25#include <string.h> 26#include <stdlib.h> 27#include <stdio.h> 28#include "cuOidParser.h" 29#include "cuFileIo.h" 30#include <fcntl.h> 31#include <errno.h> 32#include <stdio.h> 33#include <stdlib.h> 34#include <sys/types.h> 35#include <sys/stat.h> 36#include <unistd.h> 37 38/* get config file from .. or from . */ 39#define CONFIG_FILE_NAME "dumpasn1.cfg" 40static const char *CONFIG_FILE1 = "../"CONFIG_FILE_NAME; 41static const char *CONFIG_FILE2 = CONFIG_FILE_NAME; 42/* or from here via getenv */ 43#define CONFIG_FILE_ENV "LOCAL_BUILD_DIR" 44 45static const char *OID_ENTRY_START = "OID = "; 46static const char *OID_DESCR_START = "Description = "; 47/* 48 * Read entire file with extra bytes left over in the mallocd buffer. 49 */ 50static 51int readFileExtra( 52 const char *fileName, 53 unsigned extraBytes, 54 unsigned char **bytes, // mallocd and returned 55 CSSM_SIZE *numBytes) // returned 56{ 57 int rtn; 58 int fd; 59 unsigned char *buf; 60 struct stat sb; 61 size_t size; 62 63 *numBytes = 0; 64 *bytes = NULL; 65 fd = open(fileName, O_RDONLY, 0); 66 if(fd < 0) { 67 return 1; 68 } 69 rtn = fstat(fd, &sb); 70 if(rtn) { 71 goto errOut; 72 } 73 size = (size_t)sb.st_size; 74 buf = (unsigned char *)malloc(size + extraBytes); 75 if(buf == NULL) { 76 rtn = ENOMEM; 77 goto errOut; 78 } 79 rtn = (int)lseek(fd, 0, SEEK_SET); 80 if(rtn < 0) { 81 goto errOut; 82 } 83 rtn = (int)read(fd, buf, (size_t)size); 84 if(rtn != (int)size) { 85 if(rtn >= 0) { 86 printf("readFile: short read\n"); 87 } 88 rtn = EIO; 89 } 90 else { 91 rtn = 0; 92 *bytes = buf; 93 *numBytes = size; 94 } 95errOut: 96 close(fd); 97 return rtn; 98} 99 100/* 101 * Attempt to read dumpasn1.cfg from various places. If we can't find it, 102 * printOid() function will just print raw bytes as it 103 * would if the .cfg file did not contain the desired OID. 104 */ 105static CSSM_DATA_PTR readConfig() 106{ 107 CSSM_DATA_PTR configData = NULL; 108 int rtn; 109 110 configData = (CSSM_DATA_PTR)malloc(sizeof(CSSM_DATA)); 111 if(configData == NULL) { 112 return NULL; 113 } 114 /* malloc one extra byte, we'll null it later */ 115 rtn = readFileExtra(CONFIG_FILE1, 1, &configData->Data, 116 &configData->Length); 117 if(rtn) { 118 rtn = readFileExtra(CONFIG_FILE2, 1, &configData->Data, 119 &configData->Length); 120 } 121 if(rtn) { 122 char fileName[100]; 123 char *localBuildDir = getenv(CONFIG_FILE_ENV); 124 if(localBuildDir == NULL) { 125 rtn = 1; 126 } 127 else { 128 sprintf(fileName, "%s/%s", localBuildDir, CONFIG_FILE_NAME); 129 rtn = readFileExtra(fileName, 1, &configData->Data, 130 &configData->Length); 131 } 132 } 133 if(rtn == 0) { 134 /* make the whole shebang one long C string */ 135 configData->Data[configData->Length++] = '\0'; 136 return configData; 137 } 138 else { 139 free(configData); 140 return NULL; 141 } 142} 143 144/* 145 * The heart of this module. 146 * 147 * -- Convert Intel-style OID to a string which might be found 148 * in the config file 149 * -- search config file for that string 150 * -- if found, use that entry in config file to output meaningful 151 * string and return CSSM_TRUE. Else return CSSM_FALSE. 152 */ 153static CSSM_BOOL parseOidWithConfig( 154 const CSSM_DATA_PTR configData, 155 const CSSM_OID_PTR oid, 156 char *strBuf) 157{ 158 char *fullOidStr = NULL; 159 char *ourEntry = NULL; 160 char *nextEntry = NULL; 161 char *descStart = NULL; 162 char *cp; 163 unsigned i; 164 CSSM_BOOL brtn; 165 char *nextCr; // next CR if any 166 char *nextNl; // next NL if any 167 char *eol; // end of line 168 int len; 169 170 if(configData == NULL) { 171 return CSSM_FALSE; 172 } 173 174 /* cook up a full OID string, with tag and length */ 175 fullOidStr = (char *)malloc((3 * oid->Length) + 176 // 2 chars plus space per byte 177 strlen(OID_ENTRY_START) + // "OID = " 178 6 + // 06 xx - tag and length 179 1); // NULL 180 if(fullOidStr == NULL) { 181 return CSSM_FALSE; 182 } 183 /* subsequent errors to errOut: */ 184 185 sprintf(fullOidStr, "OID = 06 %02X", (unsigned)oid->Length); 186 cp = fullOidStr + strlen(fullOidStr); 187 for(i=0; i<oid->Length; i++) { 188 /* move cp to current end of string */ 189 cp += strlen(cp); 190 /* add one byte */ 191 sprintf(cp, " %02X", oid->Data[i]); 192 } 193 194 /* 195 * Let's play it loose and assume that there are no embedded NULLs 196 * in the config file. Thus we can use the spiffy string functions 197 * in stdlib. 198 */ 199 ourEntry = strstr((char *)configData->Data, fullOidStr); 200 if(ourEntry == NULL) { 201 brtn = CSSM_FALSE; 202 goto errOut; 203 } 204 205 /* get position of NEXT full entry - may be NULL (end of file) */ 206 nextEntry = strstr(ourEntry+1, OID_ENTRY_START); 207 208 /* get position of our entry's description line */ 209 descStart = strstr(ourEntry+1, OID_DESCR_START); 210 211 /* handle not found/overflow */ 212 if( (descStart == NULL) || // no more description lines 213 ( (descStart > nextEntry) && // no description in THIS entry 214 (nextEntry != NULL) ) ) { // make sure this is valid 215 brtn = CSSM_FALSE; 216 goto errOut; 217 } 218 219 /* set descStart to after the leader */ 220 descStart += strlen(OID_DESCR_START); 221 222 /* 223 * descStart points to the text we're interested in. 224 * First find end of line, any style. 225 */ 226 nextNl = strchr(descStart, '\n'); 227 nextCr = strchr(descStart, '\r'); 228 if((nextNl == NULL) && (nextCr == NULL)) { 229 /* no line terminator, go to eof */ 230 eol = (char *)configData->Data + configData->Length; 231 } 232 else if(nextCr == NULL) { 233 eol = nextNl; 234 } 235 else if(nextNl == NULL) { 236 eol = nextCr; 237 } 238 else if(nextNl < nextCr) { 239 /* both present, take first one */ 240 eol = nextNl; 241 } 242 else { 243 eol = nextCr; 244 } 245 246 /* caller's string buf = remainder of description line */ 247 len = (int)(eol - descStart); 248 if(len > (OID_PARSER_STRING_SIZE - 1)) { 249 /* fixed-length output buf, avoid overflow */ 250 len = OID_PARSER_STRING_SIZE - 1; 251 } 252 memcpy(strBuf, descStart, len); 253 strBuf[len] = '\0'; 254 brtn = CSSM_TRUE; 255errOut: 256 if(fullOidStr != NULL) { 257 free(fullOidStr); 258 } 259 return brtn; 260} 261 262/*** OidParser class ***/ 263OidParser::OidParser(bool noConfig) 264{ 265 if(noConfig) { 266 configData = NULL; 267 } 268 else { 269 configData = readConfig(); 270 } 271} 272 273OidParser::~OidParser() 274{ 275 if(configData == NULL) { 276 return; 277 } 278 if(configData->Data != NULL) { 279 free(configData->Data); 280 } 281 free(configData); 282} 283 284/* 285 * Parse an Intel-style OID, generating a C string in caller-supplied buffer. 286 */ 287void OidParser::oidParse( 288 const unsigned char *oidp, 289 unsigned oidLen, 290 char *strBuf) 291{ 292 unsigned i; 293 CSSM_OID oid; 294 295 oid.Data = (uint8 *)oidp; 296 oid.Length = oidLen; 297 298 if((oidLen == 0) || (oidp == NULL)) { 299 strcpy(strBuf, "EMPTY"); 300 return; 301 } 302 if(parseOidWithConfig(configData, &oid, strBuf) == CSSM_FALSE) { 303 /* no config file, just dump the bytes */ 304 char cbuf[8]; 305 306 sprintf(strBuf, "OID : < 06 %02X ", (unsigned)oid.Length); 307 for(i=0; i<oid.Length; i++) { 308 sprintf(cbuf, "%02X ", oid.Data[i]); 309 strcat(strBuf, cbuf); 310 } 311 strcat(strBuf, ">"); 312 } 313} 314 315 316