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