]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 A |
1 | /* |
2 | * Copyright (c) 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. Please obtain | |
7 | * a copy of the License at http://www.apple.com/publicsource and read it before | |
8 | * 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 EXPRESS | |
12 | * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT | |
13 | * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR | |
14 | * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the | |
15 | * specific language governing rights and limitations under the License. | |
16 | */ | |
17 | ||
18 | /* | |
19 | * clNameUtils.cpp - support for Name, GeneralizedName, all sorts of names | |
20 | */ | |
21 | ||
22 | #include "clNameUtils.h" | |
23 | #include "clNssUtils.h" | |
24 | #include "cldebugging.h" | |
25 | #include <security_utilities/utilities.h> | |
26 | ||
27 | #pragma mark ----- NSS_Name <--> CSSM_X509_NAME ----- | |
28 | ||
29 | /* | |
30 | * NSS_ATV --> CSSM_X509_TYPE_VALUE_PAIR | |
31 | */ | |
427c49bc | 32 | static |
b1ab9ed8 A |
33 | void CL_nssAtvToCssm( |
34 | const NSS_ATV &nssObj, | |
35 | CSSM_X509_TYPE_VALUE_PAIR &cssmObj, | |
36 | Allocator &alloc) | |
37 | { | |
38 | /* tag and decoded data */ | |
39 | cssmObj.valueType = nssObj.value.tag; | |
40 | clAllocCopyData(alloc, nssObj.value.item, cssmObj.value); | |
41 | /* the OID */ | |
42 | clAllocCopyData(alloc, nssObj.type, cssmObj.type); | |
43 | } | |
44 | ||
45 | /* NSS_RDN --> CSSM_X509_RDN */ | |
46 | void CL_nssRdnToCssm( | |
47 | const NSS_RDN &nssObj, | |
48 | CSSM_X509_RDN &cssmObj, | |
49 | Allocator &alloc, | |
50 | SecNssCoder &coder) // conversion requires further decoding | |
51 | { | |
52 | memset(&cssmObj, 0, sizeof(cssmObj)); | |
53 | unsigned numAtvs = clNssArraySize((const void **)nssObj.atvs); | |
54 | if(numAtvs == 0) { | |
55 | return; | |
56 | } | |
57 | ||
58 | size_t len = numAtvs * sizeof(CSSM_X509_TYPE_VALUE_PAIR); | |
59 | cssmObj.AttributeTypeAndValue = | |
60 | (CSSM_X509_TYPE_VALUE_PAIR_PTR)alloc.malloc(len); | |
61 | cssmObj.numberOfPairs = numAtvs; | |
62 | CSSM_X509_TYPE_VALUE_PAIR_PTR cssmAtvs = cssmObj.AttributeTypeAndValue; | |
63 | memset(cssmAtvs, 0, len); | |
64 | ||
65 | for(unsigned dex=0; dex<numAtvs; dex++) { | |
66 | CL_nssAtvToCssm(*(nssObj.atvs[dex]), cssmAtvs[dex], alloc); | |
67 | } | |
68 | return; | |
69 | } | |
70 | ||
71 | /* NSS_Name --> CSSM_X509_NAME */ | |
72 | void CL_nssNameToCssm( | |
73 | const NSS_Name &nssObj, | |
74 | CSSM_X509_NAME &cssmObj, | |
75 | Allocator &alloc) | |
76 | { | |
77 | memset(&cssmObj, 0, sizeof(cssmObj)); | |
78 | unsigned numRdns = clNssArraySize((const void **)nssObj.rdns); | |
79 | if(numRdns == 0) { | |
80 | /* not technically an error */ | |
81 | return; | |
82 | } | |
83 | ||
84 | size_t len = numRdns * sizeof(CSSM_X509_RDN); | |
85 | cssmObj.RelativeDistinguishedName = (CSSM_X509_RDN_PTR)alloc.malloc(len); | |
86 | cssmObj.numberOfRDNs = numRdns; | |
87 | CSSM_X509_RDN_PTR cssmRdns = cssmObj.RelativeDistinguishedName; | |
88 | memset(cssmRdns, 0, len); | |
89 | ||
90 | SecNssCoder coder; // conversion requires further decoding | |
91 | ||
92 | for(unsigned dex=0; dex<numRdns; dex++) { | |
93 | CL_nssRdnToCssm(*(nssObj.rdns[dex]), cssmRdns[dex], alloc, coder); | |
94 | } | |
95 | return; | |
96 | } | |
97 | ||
98 | /* | |
99 | * CSSM_X509_TYPE_VALUE_PAIR --> NSS_ATV | |
100 | */ | |
101 | void CL_cssmAtvToNss( | |
102 | const CSSM_X509_TYPE_VALUE_PAIR &cssmObj, | |
103 | NSS_ATV &nssObj, | |
104 | SecNssCoder &coder) | |
105 | { | |
106 | memset(&nssObj, 0, sizeof(nssObj)); | |
107 | ||
108 | /* copy the OID */ | |
109 | coder.allocCopyItem(cssmObj.type, nssObj.type); | |
110 | ||
111 | /* tag and value */ | |
112 | nssObj.value.tag = cssmObj.valueType; | |
113 | coder.allocCopyItem(cssmObj.value, nssObj.value.item); | |
114 | } | |
115 | ||
116 | /* CSSM_X509_RDN --> NSS_RDN */ | |
117 | void CL_cssmRdnToNss( | |
118 | const CSSM_X509_RDN &cssmObj, | |
119 | NSS_RDN &nssObj, | |
120 | SecNssCoder &coder) | |
121 | { | |
122 | memset(&nssObj, 0, sizeof(nssObj)); | |
123 | ||
124 | /* alloc NULL-terminated array of ATV pointers */ | |
125 | unsigned numAtvs = cssmObj.numberOfPairs; | |
126 | unsigned size = (numAtvs + 1) * sizeof(void *); | |
127 | nssObj.atvs = (NSS_ATV **)coder.malloc(size); | |
128 | memset(nssObj.atvs, 0, size); | |
129 | ||
130 | /* grind thru the elements */ | |
131 | for(unsigned atvDex=0; atvDex<numAtvs; atvDex++) { | |
132 | nssObj.atvs[atvDex] = (NSS_ATV *)coder.malloc(sizeof(NSS_ATV)); | |
133 | CL_cssmAtvToNss(cssmObj.AttributeTypeAndValue[atvDex], | |
134 | *nssObj.atvs[atvDex], coder); | |
135 | } | |
136 | } | |
137 | ||
138 | /* CSSM_X509_NAME --> NSS_Name */ | |
139 | void CL_cssmNameToNss( | |
140 | const CSSM_X509_NAME &cssmObj, | |
141 | NSS_Name &nssObj, | |
142 | SecNssCoder &coder) | |
143 | { | |
144 | memset(&nssObj, 0, sizeof(nssObj)); | |
145 | ||
146 | /* alloc NULL-terminated array of RDN pointers */ | |
147 | unsigned numRdns = cssmObj.numberOfRDNs; | |
148 | nssObj.rdns = (NSS_RDN **)clNssNullArray(numRdns, coder); | |
149 | ||
150 | /* grind thru the elements */ | |
151 | for(unsigned rdnDex=0; rdnDex<numRdns; rdnDex++) { | |
152 | nssObj.rdns[rdnDex] = (NSS_RDN *)coder.malloc(sizeof(NSS_RDN)); | |
153 | CL_cssmRdnToNss(cssmObj.RelativeDistinguishedName[rdnDex], | |
154 | *nssObj.rdns[rdnDex], coder); | |
155 | } | |
156 | } | |
157 | ||
158 | #pragma mark ----- Name Normalization ----- | |
159 | ||
160 | void CL_normalizeString( | |
161 | char *strPtr, | |
162 | int &strLen) // IN/OUT | |
163 | { | |
164 | char *pCh = strPtr; // working ptr | |
165 | char *pD = pCh; // start of good string chars | |
166 | char *pEos = pCh + strLen - 1; | |
167 | ||
168 | if(strLen == 0) { | |
169 | return; | |
170 | } | |
171 | ||
172 | /* adjust if Length included NULL terminator */ | |
173 | while(*pEos == 0) { | |
174 | pEos--; | |
175 | } | |
176 | ||
177 | /* Remove trailing spaces */ | |
178 | while(isspace(*pEos)) { | |
179 | pEos--; | |
180 | } | |
181 | ||
182 | /* Point to one past last non-space character */ | |
183 | pEos++; | |
184 | ||
185 | /* upper case */ | |
186 | while(pCh < pEos) { | |
187 | *pCh = toupper(*pCh); | |
188 | pCh++; | |
189 | } | |
190 | ||
191 | /* clean out whitespace */ | |
192 | /* | |
193 | * 1. skip all leading whitespace | |
194 | */ | |
195 | pCh = pD; | |
196 | while(isspace(*pCh) && (pCh < pEos)) { | |
197 | pCh++; | |
198 | } | |
199 | ||
200 | /* | |
201 | * 2. eliminate multiple whitespace. | |
202 | * pCh points to first non-white char. | |
203 | * pD still points to start of string | |
204 | */ | |
205 | char ch; | |
206 | while(pCh < pEos) { | |
207 | ch = *pCh++; | |
208 | *pD++ = ch; // normal case | |
209 | if( isspace(ch) ){ | |
210 | /* skip 'til next nonwhite */ | |
211 | while(isspace(*pCh) && (pCh < pEos)) { | |
212 | pCh++; | |
213 | } | |
214 | } | |
215 | }; | |
216 | ||
427c49bc | 217 | strLen = (int)(pD - strPtr); |
b1ab9ed8 A |
218 | } |
219 | ||
220 | /* | |
221 | * Normalize an RDN. Per RFC2459 (4.1.2.4), printable strings are case | |
222 | * insensitive and we're supposed to ignore leading and trailing | |
223 | * whitespace, and collapse multiple whitespace characters into one. | |
224 | * | |
225 | * Incoming NSS_Name is assumed to be entirely within specifed coder's | |
226 | * address space; we'll be munging some of that and possibly replacing | |
227 | * some pointers with others allocated from the same space. | |
228 | */ | |
229 | void CL_normalizeX509NameNSS( | |
230 | NSS_Name &nssName, | |
231 | SecNssCoder &coder) | |
232 | { | |
233 | unsigned numRdns = clNssArraySize((const void **)nssName.rdns); | |
234 | if(numRdns == 0) { | |
235 | /* not technically an error */ | |
236 | return; | |
237 | } | |
238 | ||
239 | for(unsigned rdnDex=0; rdnDex<numRdns; rdnDex++) { | |
240 | NSS_RDN *rdn = nssName.rdns[rdnDex]; | |
241 | assert(rdn != NULL); | |
242 | unsigned numAttrs = clNssArraySize((const void **)rdn->atvs); | |
243 | if(numAttrs == 0) { | |
244 | clFieldLog("clNormalizeX509Name: zero numAttrs at index %d", rdnDex); | |
245 | continue; | |
246 | } | |
247 | ||
248 | /* descend into array of attribute/values */ | |
249 | for(unsigned attrDex=0; attrDex<numAttrs; attrDex++) { | |
250 | NSS_ATV *attr = rdn->atvs[attrDex]; | |
251 | assert(attr != NULL); | |
252 | ||
253 | /* | |
254 | * attr->value is an ASN_ANY containing an encoded | |
255 | * string. We only normalize Prinatable String types. | |
256 | * If we find one, decode it, normalize it, encode the | |
257 | * result, and put the encoding back in attr->value. | |
258 | * We temporarily "leak" the original string, which only | |
259 | * has a lifetime of the incoming SecNssCoder. | |
260 | */ | |
261 | NSS_TaggedItem &attrVal = attr->value; | |
262 | if(attrVal.tag != SEC_ASN1_PRINTABLE_STRING) { | |
263 | /* skip it */ | |
264 | continue; | |
265 | } | |
266 | ||
267 | /* normalize */ | |
268 | char *strPtr = (char *)attrVal.item.Data; | |
427c49bc | 269 | int newLen = (int)attrVal.item.Length; |
b1ab9ed8 A |
270 | CL_normalizeString(strPtr, newLen); |
271 | ||
272 | /* possible length adjustment */ | |
273 | attrVal.item.Length = newLen; | |
274 | } /* for each attribute/value */ | |
275 | } /* for each RDN */ | |
276 | } | |
277 | ||
278 | #pragma mark ----- CE_GeneralNames <--> NSS_GeneralNames ----- | |
279 | ||
280 | void CL_nssGeneralNameToCssm( | |
281 | NSS_GeneralName &nssObj, | |
282 | CE_GeneralName &cdsaObj, | |
283 | SecNssCoder &coder, // for temp decoding | |
284 | Allocator &alloc) // destination | |
285 | { | |
286 | memset(&cdsaObj, 0, sizeof(cdsaObj)); | |
287 | PRErrorCode prtn; | |
288 | ||
289 | /* for caller's CE_GeneralName */ | |
290 | CSSM_BOOL berEncoded = CSSM_FALSE; | |
291 | CE_GeneralNameType cdsaTag; | |
292 | ||
293 | /* | |
294 | * At this point, depending on the decoded object's tag, we either | |
295 | * have the final bytes to copy out, or we need to decode further. | |
296 | * After this switch, if doCopy is true, give the caller a copy | |
297 | * of nssObj.item. | |
298 | */ | |
299 | bool doCopy = true; | |
300 | switch(nssObj.tag) { | |
301 | case NGT_OtherName: // ASN_ANY -> CE_OtherName | |
302 | { | |
303 | cdsaTag = GNT_OtherName; | |
304 | ||
305 | /* decode to coder memory */ | |
306 | CE_OtherName *nssOther = | |
307 | (CE_OtherName *)coder.malloc(sizeof(CE_OtherName)); | |
308 | memset(nssOther, 0, sizeof(CE_OtherName)); | |
309 | prtn = coder.decodeItem(nssObj.item, | |
310 | kSecAsn1GenNameOtherNameTemplate, | |
311 | nssOther); | |
312 | if(prtn) { | |
313 | clErrorLog("CL_nssGeneralNameToCssm: error decoding " | |
314 | "OtherName\n"); | |
315 | CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); | |
316 | } | |
317 | ||
318 | /* copy out to caller */ | |
319 | clAllocData(alloc, cdsaObj.name, sizeof(CE_OtherName)); | |
320 | clCopyOtherName(*nssOther, *((CE_OtherName *)cdsaObj.name.Data), | |
321 | alloc); | |
322 | doCopy = false; | |
323 | break; | |
324 | } | |
325 | case NGT_RFC822Name: // IA5String, done | |
326 | cdsaTag = GNT_RFC822Name; | |
327 | break; | |
328 | case NGT_DNSName: // IA5String | |
329 | cdsaTag = GNT_DNSName; | |
330 | break; | |
331 | case NGT_X400Address: // ASY_ANY, leave alone | |
332 | cdsaTag = GNT_X400Address; | |
333 | berEncoded = CSSM_TRUE; | |
334 | break; | |
335 | case NGT_DirectoryName: // ASN_ANY --> NSS_Name | |
336 | { | |
337 | cdsaTag = GNT_DirectoryName; | |
338 | ||
339 | /* Decode to coder memory */ | |
340 | NSS_Name *nssName = (NSS_Name *)coder.malloc(sizeof(NSS_Name)); | |
341 | memset(nssName, 0, sizeof(NSS_Name)); | |
342 | prtn = coder.decodeItem(nssObj.item, kSecAsn1NameTemplate, nssName); | |
343 | if(prtn) { | |
344 | clErrorLog("CL_nssGeneralNameToCssm: error decoding " | |
345 | "NSS_Name\n"); | |
346 | CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); | |
347 | } | |
348 | ||
349 | /* convert & copy out to caller */ | |
350 | clAllocData(alloc, cdsaObj.name, sizeof(CSSM_X509_NAME)); | |
351 | CL_nssNameToCssm(*nssName, | |
352 | *((CSSM_X509_NAME *)cdsaObj.name.Data), alloc); | |
353 | doCopy = false; | |
354 | break; | |
355 | } | |
356 | case NGT_EdiPartyName: // ASN_ANY, leave alone | |
357 | cdsaTag = GNT_EdiPartyName; | |
358 | berEncoded = CSSM_TRUE; | |
359 | break; | |
360 | case NGT_URI: // IA5String | |
361 | cdsaTag = GNT_URI; | |
362 | break; | |
363 | case NGT_IPAddress: // OCTET_STRING | |
364 | cdsaTag = GNT_IPAddress; | |
365 | break; | |
366 | case NGT_RegisteredID: // OID | |
367 | cdsaTag = GNT_RegisteredID; | |
368 | break; | |
369 | default: | |
370 | clErrorLog("CL_nssGeneralNameToCssm: bad name tag\n"); | |
371 | CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); | |
372 | } | |
373 | ||
374 | cdsaObj.nameType = cdsaTag; | |
375 | cdsaObj.berEncoded = berEncoded; | |
376 | if(doCopy) { | |
377 | clAllocCopyData(alloc, nssObj.item, cdsaObj.name); | |
378 | } | |
379 | } | |
380 | ||
381 | void CL_nssGeneralNamesToCssm( | |
382 | const NSS_GeneralNames &nssObj, | |
383 | CE_GeneralNames &cdsaObj, | |
384 | SecNssCoder &coder, // for temp decoding | |
385 | Allocator &alloc) // destination | |
386 | { | |
387 | memset(&cdsaObj, 0, sizeof(cdsaObj)); | |
388 | unsigned numNames = clNssArraySize((const void **)nssObj.names); | |
389 | if(numNames == 0) { | |
390 | return; | |
391 | } | |
392 | ||
393 | /* | |
394 | * Decode each name element, currently a raw ASN_ANY blob. | |
395 | * Then convert each result into CDSA form. | |
396 | * This array of (NSS_GeneralName)s is temporary, it doesn't | |
397 | * persist outside of this routine other than the fact that it's | |
398 | * mallocd by the coder arena pool. | |
399 | */ | |
400 | NSS_GeneralName *names = | |
401 | (NSS_GeneralName *)coder.malloc(sizeof(NSS_GeneralName) * numNames); | |
402 | memset(names, 0, sizeof(NSS_GeneralName) * numNames); | |
403 | cdsaObj.generalName = (CE_GeneralName *)alloc.malloc( | |
404 | sizeof(CE_GeneralName) * numNames); | |
405 | cdsaObj.numNames = numNames; | |
406 | ||
407 | for(unsigned dex=0; dex<numNames; dex++) { | |
408 | if(coder.decodeItem(*nssObj.names[dex], kSecAsn1GeneralNameTemplate, | |
409 | &names[dex])) { | |
410 | clErrorLog("***CL_nssGeneralNamesToCssm: Error decoding " | |
411 | "General.name\n"); | |
412 | CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); | |
413 | } | |
414 | ||
415 | CL_nssGeneralNameToCssm(names[dex], | |
416 | cdsaObj.generalName[dex], | |
417 | coder, alloc); | |
418 | } | |
419 | } | |
420 | ||
421 | void CL_cssmGeneralNameToNss( | |
422 | CE_GeneralName &cdsaObj, | |
423 | NSS_GeneralName &nssObj, // actually an NSSTaggedItem | |
424 | SecNssCoder &coder) // for temp decoding | |
425 | { | |
426 | memset(&nssObj, 0, sizeof(nssObj)); | |
427 | ||
428 | /* | |
429 | * The default here is just to use the app-supplied data as is... | |
430 | */ | |
431 | nssObj.item = cdsaObj.name; | |
432 | unsigned char itemTag; // for nssObj.tag | |
433 | bool doCopy = false; // unless we have to modify tag byte | |
434 | unsigned char overrideTag; // to force context-specific tag for | |
435 | // an ASN_ANY | |
436 | PRErrorCode prtn; | |
437 | ||
438 | switch(cdsaObj.nameType) { | |
439 | case GNT_OtherName: | |
440 | /* | |
441 | * Caller supplies an CE_OtherName. Encode it. | |
442 | */ | |
443 | if((cdsaObj.name.Length != sizeof(CE_OtherName)) || | |
444 | (cdsaObj.name.Data == NULL)) { | |
445 | clErrorLog("CL_cssmGeneralNameToNss: OtherName.Length" | |
446 | " error\n"); | |
447 | CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); | |
448 | } | |
449 | prtn = coder.encodeItem(cdsaObj.name.Data, | |
450 | kSecAsn1OtherNameTemplate, nssObj.item); | |
451 | if(prtn) { | |
452 | clErrorLog("CL_cssmGeneralNameToNss: OtherName encode" | |
453 | " error\n"); | |
454 | CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR); | |
455 | } | |
456 | itemTag = NGT_OtherName; | |
457 | break; | |
458 | case GNT_RFC822Name: // IA5String | |
459 | itemTag = NGT_RFC822Name; | |
460 | break; | |
461 | case GNT_DNSName: // IA5String | |
462 | itemTag = NGT_DNSName; | |
463 | break; | |
464 | case GNT_X400Address: // caller's resposibility | |
465 | /* | |
466 | * Encoded as ASN_ANY, the only thing we do is to | |
467 | * force the correct context-specific tag | |
468 | */ | |
469 | itemTag = GNT_X400Address; | |
470 | if(!cdsaObj.berEncoded) { | |
471 | clErrorLog("CL_cssmGeneralNameToNss: X400Address must" | |
472 | " be BER-encoded\n"); | |
473 | CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); | |
474 | } | |
475 | overrideTag = SEC_ASN1_CONTEXT_SPECIFIC | | |
476 | SEC_ASN1_CONSTRUCTED | NGT_X400Address; | |
477 | doCopy = true; | |
478 | break; | |
479 | case GNT_DirectoryName: | |
480 | { | |
481 | /* | |
482 | * Caller supplies an CSSM_X509_NAME. Convert to NSS | |
483 | * format and encode it. | |
484 | */ | |
485 | if((cdsaObj.name.Length != sizeof(CSSM_X509_NAME)) || | |
486 | (cdsaObj.name.Data == NULL)) { | |
487 | clErrorLog("CL_cssmGeneralNameToNss: DirectoryName.Length" | |
488 | " error\n"); | |
489 | CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); | |
490 | } | |
491 | NSS_Name nssName; | |
492 | CSSM_X509_NAME_PTR cdsaName = | |
493 | (CSSM_X509_NAME_PTR)cdsaObj.name.Data; | |
494 | CL_cssmNameToNss(*cdsaName, nssName, coder); | |
495 | prtn = coder.encodeItem(&nssName, | |
496 | kSecAsn1NameTemplate, nssObj.item); | |
497 | if(prtn) { | |
498 | clErrorLog("CL_cssmGeneralNameToNss: X509Name encode" | |
499 | " error\n"); | |
500 | CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR); | |
501 | } | |
502 | itemTag = GNT_DirectoryName; | |
503 | ||
504 | /* | |
505 | * AND, munge the tag to make it a context-specific | |
506 | * sequence | |
507 | * no, not needed, this is wrapped in an explicit... | |
508 | */ | |
509 | //nssObj.item.Data[0] = SEC_ASN1_CONTEXT_SPECIFIC | | |
510 | // SEC_ASN1_CONSTRUCTED | GNT_DirectoryName; | |
511 | ||
512 | break; | |
513 | } | |
514 | case GNT_EdiPartyName: // caller's resposibility | |
515 | /* | |
516 | * Encoded as ASN_ANY, the only thing we do is to | |
517 | * force the correct context-specific tag | |
518 | */ | |
519 | itemTag = GNT_EdiPartyName; | |
520 | if(!cdsaObj.berEncoded) { | |
521 | clErrorLog("CL_cssmGeneralNameToNss: EdiPartyName must" | |
522 | " be BER-encoded\n"); | |
523 | CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); | |
524 | } | |
525 | overrideTag = SEC_ASN1_CONTEXT_SPECIFIC | NGT_X400Address; | |
526 | doCopy = true; | |
527 | break; | |
528 | case GNT_URI: // IA5String | |
529 | itemTag = GNT_URI; | |
530 | break; | |
531 | case GNT_IPAddress: // OCTET_STRING | |
532 | itemTag = NGT_IPAddress; | |
533 | break; | |
534 | case GNT_RegisteredID: // OID | |
535 | itemTag = NGT_RegisteredID; | |
536 | break; | |
537 | default: | |
538 | clErrorLog("CL_cssmGeneralNameToNss: bad name tag\n"); | |
539 | CssmError::throwMe(CSSMERR_CL_UNKNOWN_TAG); | |
540 | } | |
541 | if(doCopy) { | |
542 | coder.allocCopyItem(cdsaObj.name, nssObj.item); | |
543 | nssObj.item.Data[0] = overrideTag; | |
544 | } | |
545 | nssObj.tag = itemTag; | |
546 | } | |
547 | ||
548 | void CL_cssmGeneralNamesToNss( | |
549 | const CE_GeneralNames &cdsaObj, | |
550 | NSS_GeneralNames &nssObj, | |
551 | SecNssCoder &coder) | |
552 | { | |
553 | uint32 numNames = cdsaObj.numNames; | |
554 | nssObj.names = (CSSM_DATA **)clNssNullArray(numNames, coder); | |
555 | ||
556 | /* | |
557 | * Convert each element in cdsaObj to NSS form, encode, drop into | |
558 | * the ASN_ANY array. | |
559 | * | |
560 | * This array of (NSS_GeneralName)s is temporary, it doesn't | |
561 | * persist outside of this routine other than the fact that it's | |
562 | * mallocd by the coder arena pool. | |
563 | */ | |
564 | NSS_GeneralName *names = | |
565 | (NSS_GeneralName *)coder.malloc(sizeof(NSS_GeneralName) * numNames); | |
566 | memset(names, 0, sizeof(NSS_GeneralName) * numNames); | |
567 | for(unsigned dex=0; dex<cdsaObj.numNames; dex++) { | |
568 | nssObj.names[dex] = (CSSM_DATA_PTR)coder.malloc(sizeof(CSSM_DATA)); | |
569 | memset(nssObj.names[dex], 0, sizeof(CSSM_DATA)); | |
570 | CL_cssmGeneralNameToNss(cdsaObj.generalName[dex], | |
571 | names[dex], coder); | |
572 | if(coder.encodeItem(&names[dex], kSecAsn1GeneralNameTemplate, | |
573 | *nssObj.names[dex])) { | |
574 | clErrorLog("***Error encoding General.name\n"); | |
575 | CssmError::throwMe(CSSMERR_CL_MEMORY_ERROR); | |
576 | } | |
577 | } | |
578 | } | |
579 | ||
580 | /* Copy a CE_OtherName */ | |
581 | void clCopyOtherName( | |
582 | const CE_OtherName &src, | |
583 | CE_OtherName &dst, | |
584 | Allocator &alloc) | |
585 | { | |
586 | clAllocCopyData(alloc, src.typeId, dst.typeId); | |
587 | clAllocCopyData(alloc, src.value, dst.value); | |
588 | } | |
589 | ||
590 | #pragma mark ----- Name-related Free ----- | |
591 | ||
592 | void CL_freeAuthorityKeyId( | |
593 | CE_AuthorityKeyID &cdsaObj, | |
594 | Allocator &alloc) | |
595 | { | |
596 | alloc.free(cdsaObj.keyIdentifier.Data); | |
597 | CL_freeCssmGeneralNames(cdsaObj.generalNames, alloc); | |
598 | alloc.free(cdsaObj.generalNames); | |
599 | alloc.free(cdsaObj.serialNumber.Data); | |
600 | memset(&cdsaObj, 0, sizeof(CE_AuthorityKeyID)); | |
601 | } | |
602 | ||
603 | void CL_freeCssmGeneralName( | |
604 | CE_GeneralName &genName, | |
605 | Allocator &alloc) | |
606 | { | |
607 | switch(genName.nameType) { | |
608 | /* | |
609 | * Two special cases here. | |
610 | */ | |
611 | case GNT_DirectoryName: | |
612 | if((!genName.berEncoded) && // we're flexible | |
613 | (genName.name.Length == | |
614 | sizeof(CSSM_X509_NAME))) { // paranoia | |
615 | CL_freeX509Name((CSSM_X509_NAME_PTR)genName.name.Data, alloc); | |
616 | } | |
617 | break; | |
618 | ||
619 | case GNT_OtherName: | |
620 | if((!genName.berEncoded) && // we're flexible | |
621 | (genName.name.Length == | |
622 | sizeof(CE_OtherName))) { // paranoia | |
623 | CE_OtherName *con = (CE_OtherName *)genName.name.Data; | |
624 | CL_freeOtherName(con, alloc); | |
625 | } | |
626 | break; | |
627 | default: | |
628 | break; | |
629 | } | |
630 | /* and always free this */ | |
631 | alloc.free(genName.name.Data); | |
632 | } | |
633 | ||
634 | void CL_freeCssmGeneralNames( | |
635 | CE_GeneralNames *cdsaObj, | |
636 | Allocator &alloc) | |
637 | { | |
638 | if(cdsaObj == NULL) { | |
639 | return; | |
640 | } | |
641 | for(unsigned i=0; i<cdsaObj->numNames; i++) { | |
642 | CL_freeCssmGeneralName(cdsaObj->generalName[i], alloc); | |
643 | } | |
644 | if(cdsaObj->numNames) { | |
645 | memset(cdsaObj->generalName, 0, cdsaObj->numNames * sizeof(CE_GeneralName)); | |
646 | alloc.free(cdsaObj->generalName); | |
647 | } | |
648 | memset(cdsaObj, 0, sizeof(CE_GeneralNames)); | |
649 | } | |
650 | ||
651 | void CL_freeCssmDistPointName( | |
652 | CE_DistributionPointName *cssmDpn, | |
653 | Allocator &alloc) | |
654 | { | |
655 | if(cssmDpn == NULL) { | |
656 | return; | |
657 | } | |
658 | switch(cssmDpn->nameType) { | |
659 | case CE_CDNT_FullName: | |
660 | CL_freeCssmGeneralNames(cssmDpn->dpn.fullName, alloc); | |
661 | alloc.free(cssmDpn->dpn.fullName); | |
662 | break; | |
663 | case CE_CDNT_NameRelativeToCrlIssuer: | |
664 | CL_freeX509Rdn(cssmDpn->dpn.rdn, alloc); | |
665 | alloc.free(cssmDpn->dpn.rdn); | |
666 | break; | |
667 | } | |
668 | memset(cssmDpn, 0, sizeof(*cssmDpn)); | |
669 | } | |
670 | ||
671 | void CL_freeCssmDistPoints( | |
672 | CE_CRLDistPointsSyntax *cssmDps, | |
673 | Allocator &alloc) | |
674 | { | |
675 | if(cssmDps == NULL) { | |
676 | return; | |
677 | } | |
678 | for(unsigned dex=0; dex<cssmDps->numDistPoints; dex++) { | |
679 | CE_CRLDistributionPoint *cssmDp = &cssmDps->distPoints[dex]; | |
680 | if(cssmDp->distPointName) { | |
681 | CL_freeCssmDistPointName(cssmDp->distPointName, alloc); | |
682 | alloc.free(cssmDp->distPointName); | |
683 | } | |
684 | if(cssmDp->crlIssuer) { | |
685 | CL_freeCssmGeneralNames(cssmDp->crlIssuer, alloc); | |
686 | alloc.free(cssmDp->crlIssuer); | |
687 | } | |
688 | } | |
689 | memset(cssmDps->distPoints, 0, | |
690 | cssmDps->numDistPoints * sizeof(CE_CRLDistributionPoint)); | |
691 | alloc.free(cssmDps->distPoints); | |
692 | memset(cssmDps, 0, sizeof(*cssmDps)); | |
693 | } | |
694 | ||
695 | /* free contents of an CSSM_X509_NAME */ | |
696 | void CL_freeX509Name( | |
697 | CSSM_X509_NAME_PTR x509Name, | |
698 | Allocator &alloc) | |
699 | { | |
700 | if(x509Name == NULL) { | |
701 | return; | |
702 | } | |
703 | for(unsigned rdnDex=0; rdnDex<x509Name->numberOfRDNs; rdnDex++) { | |
704 | CSSM_X509_RDN_PTR rdn = &x509Name->RelativeDistinguishedName[rdnDex]; | |
705 | CL_freeX509Rdn(rdn, alloc); | |
706 | } | |
707 | alloc.free(x509Name->RelativeDistinguishedName); | |
708 | memset(x509Name, 0, sizeof(CSSM_X509_NAME)); | |
709 | } | |
710 | ||
711 | void CL_freeX509Rdn( | |
712 | CSSM_X509_RDN_PTR rdn, | |
713 | Allocator &alloc) | |
714 | { | |
715 | if(rdn == NULL) { | |
716 | return; | |
717 | } | |
718 | for(unsigned atvDex=0; atvDex<rdn->numberOfPairs; atvDex++) { | |
719 | CSSM_X509_TYPE_VALUE_PAIR_PTR atv = | |
720 | &rdn->AttributeTypeAndValue[atvDex]; | |
721 | alloc.free(atv->type.Data); | |
722 | alloc.free(atv->value.Data); | |
723 | memset(atv, 0, sizeof(CSSM_X509_TYPE_VALUE_PAIR)); | |
724 | } | |
725 | alloc.free(rdn->AttributeTypeAndValue); | |
726 | memset(rdn, 0, sizeof(CSSM_X509_RDN)); | |
727 | } | |
728 | ||
729 | void CL_freeOtherName( | |
730 | CE_OtherName *cssmOther, | |
731 | Allocator &alloc) | |
732 | { | |
733 | if(cssmOther == NULL) { | |
734 | return; | |
735 | } | |
736 | alloc.free(cssmOther->typeId.Data); | |
737 | alloc.free(cssmOther->value.Data); | |
738 | memset(cssmOther, 0, sizeof(*cssmOther)); | |
739 | } | |
740 | ||
741 | void CL_freeCssmIssuingDistPoint( | |
742 | CE_IssuingDistributionPoint *cssmIdp, | |
743 | Allocator &alloc) | |
744 | { | |
745 | CL_freeCssmDistPointName(cssmIdp->distPointName, alloc); | |
746 | } | |
747 |