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