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