]>
Commit | Line | Data |
---|---|---|
29654253 | 1 | /* |
df0e469f A |
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 | |
29654253 A |
22 | */ |
23 | ||
24 | #include <Security/cssmtype.h> | |
25 | #include <string.h> | |
26 | #include <stdlib.h> | |
27 | #include <stdio.h> | |
df0e469f A |
28 | #include "cuOidParser.h" |
29 | #include "cuFileIo.h" | |
29654253 A |
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 char *CONFIG_FILE1 = "../"CONFIG_FILE_NAME; | |
41 | static char *CONFIG_FILE2 = CONFIG_FILE_NAME; | |
42 | /* or from here via getenv */ | |
43 | #define CONFIG_FILE_ENV "LOCAL_BUILD_DIR" | |
44 | ||
45 | static char *OID_ENTRY_START = "OID = "; | |
46 | static char *OID_DESCR_START = "Description = "; | |
47 | /* | |
48 | * Read entire file with extra bytes left over in the mallocd buffer. | |
49 | */ | |
50 | int readFileExtra( | |
51 | char *fileName, | |
52 | unsigned extraBytes, | |
53 | unsigned char **bytes, // mallocd and returned | |
54 | unsigned *numBytes) // returned | |
55 | { | |
56 | int rtn; | |
57 | int fd; | |
58 | unsigned char *buf; | |
59 | struct stat sb; | |
60 | unsigned 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 | (unsigned *)&configData->Length); | |
116 | if(rtn) { | |
117 | rtn = readFileExtra(CONFIG_FILE2, 1, &configData->Data, | |
118 | (unsigned *)&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 | (unsigned *)&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 { | |
29654253 A |
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 |