Mercurial > trustbridge > nss-cmake-static
comparison nss/lib/certdb/genname.c @ 0:1e5118fa0cb1
This is NSS with a Cmake Buildsyste
To compile a static NSS library for Windows we've used the
Chromium-NSS fork and added a Cmake buildsystem to compile
it statically for Windows. See README.chromium for chromium
changes and README.trustbridge for our modifications.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Mon, 28 Jul 2014 10:47:06 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1e5118fa0cb1 |
---|---|
1 /* This Source Code Form is subject to the terms of the Mozilla Public | |
2 * License, v. 2.0. If a copy of the MPL was not distributed with this | |
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
4 | |
5 #include "plarena.h" | |
6 #include "seccomon.h" | |
7 #include "secitem.h" | |
8 #include "secoidt.h" | |
9 #include "secasn1.h" | |
10 #include "secder.h" | |
11 #include "certt.h" | |
12 #include "cert.h" | |
13 #include "certi.h" | |
14 #include "xconst.h" | |
15 #include "secerr.h" | |
16 #include "secoid.h" | |
17 #include "prprf.h" | |
18 #include "genname.h" | |
19 | |
20 SEC_ASN1_MKSUB(SEC_AnyTemplate) | |
21 SEC_ASN1_MKSUB(SEC_IntegerTemplate) | |
22 SEC_ASN1_MKSUB(SEC_IA5StringTemplate) | |
23 SEC_ASN1_MKSUB(SEC_ObjectIDTemplate) | |
24 SEC_ASN1_MKSUB(SEC_OctetStringTemplate) | |
25 | |
26 static const SEC_ASN1Template CERTNameConstraintTemplate[] = { | |
27 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTNameConstraint) }, | |
28 { SEC_ASN1_ANY, offsetof(CERTNameConstraint, DERName) }, | |
29 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, | |
30 offsetof(CERTNameConstraint, min), | |
31 SEC_ASN1_SUB(SEC_IntegerTemplate) }, | |
32 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1, | |
33 offsetof(CERTNameConstraint, max), | |
34 SEC_ASN1_SUB(SEC_IntegerTemplate) }, | |
35 { 0, } | |
36 }; | |
37 | |
38 const SEC_ASN1Template CERT_NameConstraintSubtreeSubTemplate[] = { | |
39 { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_XTRN, 0, SEC_ASN1_SUB(SEC_AnyTemplate) } | |
40 }; | |
41 | |
42 static const SEC_ASN1Template CERTNameConstraintsTemplate[] = { | |
43 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTNameConstraints) }, | |
44 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, | |
45 offsetof(CERTNameConstraints, DERPermited), | |
46 CERT_NameConstraintSubtreeSubTemplate}, | |
47 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, | |
48 offsetof(CERTNameConstraints, DERExcluded), | |
49 CERT_NameConstraintSubtreeSubTemplate}, | |
50 { 0, } | |
51 }; | |
52 | |
53 | |
54 static const SEC_ASN1Template CERTOthNameTemplate[] = { | |
55 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(OtherName) }, | |
56 { SEC_ASN1_OBJECT_ID, | |
57 offsetof(OtherName, oid) }, | |
58 { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | | |
59 SEC_ASN1_XTRN | 0, offsetof(OtherName, name), | |
60 SEC_ASN1_SUB(SEC_AnyTemplate) }, | |
61 { 0, } | |
62 }; | |
63 | |
64 static const SEC_ASN1Template CERTOtherNameTemplate[] = { | |
65 { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | 0 , | |
66 offsetof(CERTGeneralName, name.OthName), CERTOthNameTemplate, | |
67 sizeof(CERTGeneralName) } | |
68 }; | |
69 | |
70 static const SEC_ASN1Template CERTOtherName2Template[] = { | |
71 { SEC_ASN1_SEQUENCE | SEC_ASN1_CONTEXT_SPECIFIC | 0 , | |
72 0, NULL, sizeof(CERTGeneralName) }, | |
73 { SEC_ASN1_OBJECT_ID, | |
74 offsetof(CERTGeneralName, name.OthName) + offsetof(OtherName, oid) }, | |
75 { SEC_ASN1_ANY, | |
76 offsetof(CERTGeneralName, name.OthName) + offsetof(OtherName, name) }, | |
77 { 0, } | |
78 }; | |
79 | |
80 static const SEC_ASN1Template CERT_RFC822NameTemplate[] = { | |
81 { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1 , | |
82 offsetof(CERTGeneralName, name.other), | |
83 SEC_ASN1_SUB(SEC_IA5StringTemplate), | |
84 sizeof (CERTGeneralName)} | |
85 }; | |
86 | |
87 static const SEC_ASN1Template CERT_DNSNameTemplate[] = { | |
88 { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 2 , | |
89 offsetof(CERTGeneralName, name.other), | |
90 SEC_ASN1_SUB(SEC_IA5StringTemplate), | |
91 sizeof (CERTGeneralName)} | |
92 }; | |
93 | |
94 static const SEC_ASN1Template CERT_X400AddressTemplate[] = { | |
95 { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_XTRN | 3, | |
96 offsetof(CERTGeneralName, name.other), SEC_ASN1_SUB(SEC_AnyTemplate), | |
97 sizeof (CERTGeneralName)} | |
98 }; | |
99 | |
100 static const SEC_ASN1Template CERT_DirectoryNameTemplate[] = { | |
101 { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | | |
102 SEC_ASN1_XTRN | 4, offsetof(CERTGeneralName, derDirectoryName), | |
103 SEC_ASN1_SUB(SEC_AnyTemplate), sizeof (CERTGeneralName)} | |
104 }; | |
105 | |
106 | |
107 static const SEC_ASN1Template CERT_EDIPartyNameTemplate[] = { | |
108 { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_XTRN | 5, | |
109 offsetof(CERTGeneralName, name.other), SEC_ASN1_SUB(SEC_AnyTemplate), | |
110 sizeof (CERTGeneralName)} | |
111 }; | |
112 | |
113 static const SEC_ASN1Template CERT_URITemplate[] = { | |
114 { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 6 , | |
115 offsetof(CERTGeneralName, name.other), | |
116 SEC_ASN1_SUB(SEC_IA5StringTemplate), | |
117 sizeof (CERTGeneralName)} | |
118 }; | |
119 | |
120 static const SEC_ASN1Template CERT_IPAddressTemplate[] = { | |
121 { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 7 , | |
122 offsetof(CERTGeneralName, name.other), | |
123 SEC_ASN1_SUB(SEC_OctetStringTemplate), | |
124 sizeof (CERTGeneralName)} | |
125 }; | |
126 | |
127 static const SEC_ASN1Template CERT_RegisteredIDTemplate[] = { | |
128 { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 8 , | |
129 offsetof(CERTGeneralName, name.other), | |
130 SEC_ASN1_SUB(SEC_ObjectIDTemplate), | |
131 sizeof (CERTGeneralName)} | |
132 }; | |
133 | |
134 | |
135 const SEC_ASN1Template CERT_GeneralNamesTemplate[] = { | |
136 { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_XTRN , 0, SEC_ASN1_SUB(SEC_AnyTemplate) } | |
137 }; | |
138 | |
139 | |
140 static struct { | |
141 CERTGeneralNameType type; | |
142 char *name; | |
143 } typesArray[] = { | |
144 { certOtherName, "other" }, | |
145 { certRFC822Name, "email" }, | |
146 { certRFC822Name, "rfc822" }, | |
147 { certDNSName, "dns" }, | |
148 { certX400Address, "x400" }, | |
149 { certX400Address, "x400addr" }, | |
150 { certDirectoryName, "directory" }, | |
151 { certDirectoryName, "dn" }, | |
152 { certEDIPartyName, "edi" }, | |
153 { certEDIPartyName, "ediparty" }, | |
154 { certURI, "uri" }, | |
155 { certIPAddress, "ip" }, | |
156 { certIPAddress, "ipaddr" }, | |
157 { certRegisterID, "registerid" } | |
158 }; | |
159 | |
160 CERTGeneralNameType | |
161 CERT_GetGeneralNameTypeFromString(const char *string) | |
162 { | |
163 int types_count = sizeof(typesArray)/sizeof(typesArray[0]); | |
164 int i; | |
165 | |
166 for (i=0; i < types_count; i++) { | |
167 if (PORT_Strcasecmp(string, typesArray[i].name) == 0) { | |
168 return typesArray[i].type; | |
169 } | |
170 } | |
171 return 0; | |
172 } | |
173 | |
174 CERTGeneralName * | |
175 CERT_NewGeneralName(PLArenaPool *arena, CERTGeneralNameType type) | |
176 { | |
177 CERTGeneralName *name = arena | |
178 ? PORT_ArenaZNew(arena, CERTGeneralName) | |
179 : PORT_ZNew(CERTGeneralName); | |
180 if (name) { | |
181 name->type = type; | |
182 name->l.prev = name->l.next = &name->l; | |
183 } | |
184 return name; | |
185 } | |
186 | |
187 /* Copy content of one General Name to another. | |
188 ** Caller has allocated destination general name. | |
189 ** This function does not change the destinate's GeneralName's list linkage. | |
190 */ | |
191 SECStatus | |
192 cert_CopyOneGeneralName(PLArenaPool *arena, | |
193 CERTGeneralName *dest, | |
194 CERTGeneralName *src) | |
195 { | |
196 SECStatus rv; | |
197 void *mark = NULL; | |
198 | |
199 PORT_Assert(dest != NULL); | |
200 dest->type = src->type; | |
201 | |
202 mark = PORT_ArenaMark(arena); | |
203 | |
204 switch (src->type) { | |
205 case certDirectoryName: | |
206 rv = SECITEM_CopyItem(arena, &dest->derDirectoryName, | |
207 &src->derDirectoryName); | |
208 if (rv == SECSuccess) | |
209 rv = CERT_CopyName(arena, &dest->name.directoryName, | |
210 &src->name.directoryName); | |
211 break; | |
212 | |
213 case certOtherName: | |
214 rv = SECITEM_CopyItem(arena, &dest->name.OthName.name, | |
215 &src->name.OthName.name); | |
216 if (rv == SECSuccess) | |
217 rv = SECITEM_CopyItem(arena, &dest->name.OthName.oid, | |
218 &src->name.OthName.oid); | |
219 break; | |
220 | |
221 default: | |
222 rv = SECITEM_CopyItem(arena, &dest->name.other, | |
223 &src->name.other); | |
224 break; | |
225 | |
226 } | |
227 if (rv != SECSuccess) { | |
228 PORT_ArenaRelease(arena, mark); | |
229 } else { | |
230 PORT_ArenaUnmark(arena, mark); | |
231 } | |
232 return rv; | |
233 } | |
234 | |
235 | |
236 void | |
237 CERT_DestroyGeneralNameList(CERTGeneralNameList *list) | |
238 { | |
239 PZLock *lock; | |
240 | |
241 if (list != NULL) { | |
242 lock = list->lock; | |
243 PZ_Lock(lock); | |
244 if (--list->refCount <= 0 && list->arena != NULL) { | |
245 PORT_FreeArena(list->arena, PR_FALSE); | |
246 PZ_Unlock(lock); | |
247 PZ_DestroyLock(lock); | |
248 } else { | |
249 PZ_Unlock(lock); | |
250 } | |
251 } | |
252 return; | |
253 } | |
254 | |
255 CERTGeneralNameList * | |
256 CERT_CreateGeneralNameList(CERTGeneralName *name) { | |
257 PLArenaPool *arena; | |
258 CERTGeneralNameList *list = NULL; | |
259 | |
260 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | |
261 if (arena == NULL) { | |
262 goto done; | |
263 } | |
264 list = PORT_ArenaZNew(arena, CERTGeneralNameList); | |
265 if (!list) | |
266 goto loser; | |
267 if (name != NULL) { | |
268 SECStatus rv; | |
269 list->name = CERT_NewGeneralName(arena, (CERTGeneralNameType)0); | |
270 if (!list->name) | |
271 goto loser; | |
272 rv = CERT_CopyGeneralName(arena, list->name, name); | |
273 if (rv != SECSuccess) | |
274 goto loser; | |
275 } | |
276 list->lock = PZ_NewLock(nssILockList); | |
277 if (!list->lock) | |
278 goto loser; | |
279 list->arena = arena; | |
280 list->refCount = 1; | |
281 done: | |
282 return list; | |
283 | |
284 loser: | |
285 PORT_FreeArena(arena, PR_FALSE); | |
286 return NULL; | |
287 } | |
288 | |
289 CERTGeneralName * | |
290 CERT_GetNextGeneralName(CERTGeneralName *current) | |
291 { | |
292 PRCList *next; | |
293 | |
294 next = current->l.next; | |
295 return (CERTGeneralName *) (((char *) next) - offsetof(CERTGeneralName, l)); | |
296 } | |
297 | |
298 CERTGeneralName * | |
299 CERT_GetPrevGeneralName(CERTGeneralName *current) | |
300 { | |
301 PRCList *prev; | |
302 prev = current->l.prev; | |
303 return (CERTGeneralName *) (((char *) prev) - offsetof(CERTGeneralName, l)); | |
304 } | |
305 | |
306 CERTNameConstraint * | |
307 CERT_GetNextNameConstraint(CERTNameConstraint *current) | |
308 { | |
309 PRCList *next; | |
310 | |
311 next = current->l.next; | |
312 return (CERTNameConstraint *) (((char *) next) - offsetof(CERTNameConstraint, l)); | |
313 } | |
314 | |
315 CERTNameConstraint * | |
316 CERT_GetPrevNameConstraint(CERTNameConstraint *current) | |
317 { | |
318 PRCList *prev; | |
319 prev = current->l.prev; | |
320 return (CERTNameConstraint *) (((char *) prev) - offsetof(CERTNameConstraint, l)); | |
321 } | |
322 | |
323 SECItem * | |
324 CERT_EncodeGeneralName(CERTGeneralName *genName, SECItem *dest, PLArenaPool *arena) | |
325 { | |
326 | |
327 const SEC_ASN1Template * template; | |
328 | |
329 PORT_Assert(arena); | |
330 if (arena == NULL) { | |
331 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
332 return NULL; | |
333 } | |
334 /* TODO: mark arena */ | |
335 if (dest == NULL) { | |
336 dest = PORT_ArenaZNew(arena, SECItem); | |
337 if (!dest) | |
338 goto loser; | |
339 } | |
340 if (genName->type == certDirectoryName) { | |
341 if (genName->derDirectoryName.data == NULL) { | |
342 /* The field hasn't been encoded yet. */ | |
343 SECItem * pre_dest = | |
344 SEC_ASN1EncodeItem (arena, &(genName->derDirectoryName), | |
345 &(genName->name.directoryName), | |
346 CERT_NameTemplate); | |
347 if (!pre_dest) | |
348 goto loser; | |
349 } | |
350 if (genName->derDirectoryName.data == NULL) { | |
351 goto loser; | |
352 } | |
353 } | |
354 switch (genName->type) { | |
355 case certURI: template = CERT_URITemplate; break; | |
356 case certRFC822Name: template = CERT_RFC822NameTemplate; break; | |
357 case certDNSName: template = CERT_DNSNameTemplate; break; | |
358 case certIPAddress: template = CERT_IPAddressTemplate; break; | |
359 case certOtherName: template = CERTOtherNameTemplate; break; | |
360 case certRegisterID: template = CERT_RegisteredIDTemplate; break; | |
361 /* for this type, we expect the value is already encoded */ | |
362 case certEDIPartyName: template = CERT_EDIPartyNameTemplate; break; | |
363 /* for this type, we expect the value is already encoded */ | |
364 case certX400Address: template = CERT_X400AddressTemplate; break; | |
365 case certDirectoryName: template = CERT_DirectoryNameTemplate; break; | |
366 default: | |
367 PORT_Assert(0); goto loser; | |
368 } | |
369 dest = SEC_ASN1EncodeItem(arena, dest, genName, template); | |
370 if (!dest) { | |
371 goto loser; | |
372 } | |
373 /* TODO: unmark arena */ | |
374 return dest; | |
375 loser: | |
376 /* TODO: release arena back to mark */ | |
377 return NULL; | |
378 } | |
379 | |
380 SECItem ** | |
381 cert_EncodeGeneralNames(PLArenaPool *arena, CERTGeneralName *names) | |
382 { | |
383 CERTGeneralName *current_name; | |
384 SECItem **items = NULL; | |
385 int count = 0; | |
386 int i; | |
387 PRCList *head; | |
388 | |
389 PORT_Assert(arena); | |
390 /* TODO: mark arena */ | |
391 current_name = names; | |
392 if (names != NULL) { | |
393 count = 1; | |
394 } | |
395 head = &(names->l); | |
396 while (current_name->l.next != head) { | |
397 current_name = CERT_GetNextGeneralName(current_name); | |
398 ++count; | |
399 } | |
400 current_name = CERT_GetNextGeneralName(current_name); | |
401 items = PORT_ArenaNewArray(arena, SECItem *, count + 1); | |
402 if (items == NULL) { | |
403 goto loser; | |
404 } | |
405 for (i = 0; i < count; i++) { | |
406 items[i] = CERT_EncodeGeneralName(current_name, (SECItem *)NULL, arena); | |
407 if (items[i] == NULL) { | |
408 goto loser; | |
409 } | |
410 current_name = CERT_GetNextGeneralName(current_name); | |
411 } | |
412 items[i] = NULL; | |
413 /* TODO: unmark arena */ | |
414 return items; | |
415 loser: | |
416 /* TODO: release arena to mark */ | |
417 return NULL; | |
418 } | |
419 | |
420 CERTGeneralName * | |
421 CERT_DecodeGeneralName(PLArenaPool *reqArena, | |
422 SECItem *encodedName, | |
423 CERTGeneralName *genName) | |
424 { | |
425 const SEC_ASN1Template * template; | |
426 CERTGeneralNameType genNameType; | |
427 SECStatus rv = SECSuccess; | |
428 SECItem* newEncodedName; | |
429 | |
430 if (!reqArena) { | |
431 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
432 return NULL; | |
433 } | |
434 /* make a copy for decoding so the data decoded with QuickDER doesn't | |
435 point to temporary memory */ | |
436 newEncodedName = SECITEM_ArenaDupItem(reqArena, encodedName); | |
437 if (!newEncodedName) { | |
438 return NULL; | |
439 } | |
440 /* TODO: mark arena */ | |
441 genNameType = (CERTGeneralNameType)((*(newEncodedName->data) & 0x0f) + 1); | |
442 if (genName == NULL) { | |
443 genName = CERT_NewGeneralName(reqArena, genNameType); | |
444 if (!genName) | |
445 goto loser; | |
446 } else { | |
447 genName->type = genNameType; | |
448 genName->l.prev = genName->l.next = &genName->l; | |
449 } | |
450 | |
451 switch (genNameType) { | |
452 case certURI: template = CERT_URITemplate; break; | |
453 case certRFC822Name: template = CERT_RFC822NameTemplate; break; | |
454 case certDNSName: template = CERT_DNSNameTemplate; break; | |
455 case certIPAddress: template = CERT_IPAddressTemplate; break; | |
456 case certOtherName: template = CERTOtherNameTemplate; break; | |
457 case certRegisterID: template = CERT_RegisteredIDTemplate; break; | |
458 case certEDIPartyName: template = CERT_EDIPartyNameTemplate; break; | |
459 case certX400Address: template = CERT_X400AddressTemplate; break; | |
460 case certDirectoryName: template = CERT_DirectoryNameTemplate; break; | |
461 default: | |
462 goto loser; | |
463 } | |
464 rv = SEC_QuickDERDecodeItem(reqArena, genName, template, newEncodedName); | |
465 if (rv != SECSuccess) | |
466 goto loser; | |
467 if (genNameType == certDirectoryName) { | |
468 rv = SEC_QuickDERDecodeItem(reqArena, &(genName->name.directoryName), | |
469 CERT_NameTemplate, | |
470 &(genName->derDirectoryName)); | |
471 if (rv != SECSuccess) | |
472 goto loser; | |
473 } | |
474 | |
475 /* TODO: unmark arena */ | |
476 return genName; | |
477 loser: | |
478 /* TODO: release arena to mark */ | |
479 return NULL; | |
480 } | |
481 | |
482 CERTGeneralName * | |
483 cert_DecodeGeneralNames (PLArenaPool *arena, | |
484 SECItem **encodedGenName) | |
485 { | |
486 PRCList *head = NULL; | |
487 PRCList *tail = NULL; | |
488 CERTGeneralName *currentName = NULL; | |
489 | |
490 PORT_Assert(arena); | |
491 if (!encodedGenName || !arena) { | |
492 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
493 return NULL; | |
494 } | |
495 /* TODO: mark arena */ | |
496 while (*encodedGenName != NULL) { | |
497 currentName = CERT_DecodeGeneralName(arena, *encodedGenName, NULL); | |
498 if (currentName == NULL) | |
499 break; | |
500 if (head == NULL) { | |
501 head = &(currentName->l); | |
502 tail = head; | |
503 } | |
504 currentName->l.next = head; | |
505 currentName->l.prev = tail; | |
506 tail = head->prev = tail->next = &(currentName->l); | |
507 encodedGenName++; | |
508 } | |
509 if (currentName) { | |
510 /* TODO: unmark arena */ | |
511 return CERT_GetNextGeneralName(currentName); | |
512 } | |
513 /* TODO: release arena to mark */ | |
514 return NULL; | |
515 } | |
516 | |
517 void | |
518 CERT_DestroyGeneralName(CERTGeneralName *name) | |
519 { | |
520 cert_DestroyGeneralNames(name); | |
521 } | |
522 | |
523 SECStatus | |
524 cert_DestroyGeneralNames(CERTGeneralName *name) | |
525 { | |
526 CERTGeneralName *first; | |
527 CERTGeneralName *next = NULL; | |
528 | |
529 | |
530 first = name; | |
531 do { | |
532 next = CERT_GetNextGeneralName(name); | |
533 PORT_Free(name); | |
534 name = next; | |
535 } while (name != first); | |
536 return SECSuccess; | |
537 } | |
538 | |
539 static SECItem * | |
540 cert_EncodeNameConstraint(CERTNameConstraint *constraint, | |
541 SECItem *dest, | |
542 PLArenaPool *arena) | |
543 { | |
544 PORT_Assert(arena); | |
545 if (dest == NULL) { | |
546 dest = PORT_ArenaZNew(arena, SECItem); | |
547 if (dest == NULL) { | |
548 return NULL; | |
549 } | |
550 } | |
551 CERT_EncodeGeneralName(&(constraint->name), &(constraint->DERName), arena); | |
552 | |
553 dest = SEC_ASN1EncodeItem (arena, dest, constraint, | |
554 CERTNameConstraintTemplate); | |
555 return dest; | |
556 } | |
557 | |
558 SECStatus | |
559 cert_EncodeNameConstraintSubTree(CERTNameConstraint *constraints, | |
560 PLArenaPool *arena, | |
561 SECItem ***dest, | |
562 PRBool permited) | |
563 { | |
564 CERTNameConstraint *current_constraint = constraints; | |
565 SECItem **items = NULL; | |
566 int count = 0; | |
567 int i; | |
568 PRCList *head; | |
569 | |
570 PORT_Assert(arena); | |
571 /* TODO: mark arena */ | |
572 if (constraints != NULL) { | |
573 count = 1; | |
574 } | |
575 head = &constraints->l; | |
576 while (current_constraint->l.next != head) { | |
577 current_constraint = CERT_GetNextNameConstraint(current_constraint); | |
578 ++count; | |
579 } | |
580 current_constraint = CERT_GetNextNameConstraint(current_constraint); | |
581 items = PORT_ArenaZNewArray(arena, SECItem *, count + 1); | |
582 if (items == NULL) { | |
583 goto loser; | |
584 } | |
585 for (i = 0; i < count; i++) { | |
586 items[i] = cert_EncodeNameConstraint(current_constraint, | |
587 (SECItem *) NULL, arena); | |
588 if (items[i] == NULL) { | |
589 goto loser; | |
590 } | |
591 current_constraint = CERT_GetNextNameConstraint(current_constraint); | |
592 } | |
593 *dest = items; | |
594 if (*dest == NULL) { | |
595 goto loser; | |
596 } | |
597 /* TODO: unmark arena */ | |
598 return SECSuccess; | |
599 loser: | |
600 /* TODO: release arena to mark */ | |
601 return SECFailure; | |
602 } | |
603 | |
604 SECStatus | |
605 cert_EncodeNameConstraints(CERTNameConstraints *constraints, | |
606 PLArenaPool *arena, | |
607 SECItem *dest) | |
608 { | |
609 SECStatus rv = SECSuccess; | |
610 | |
611 PORT_Assert(arena); | |
612 /* TODO: mark arena */ | |
613 if (constraints->permited != NULL) { | |
614 rv = cert_EncodeNameConstraintSubTree(constraints->permited, arena, | |
615 &constraints->DERPermited, | |
616 PR_TRUE); | |
617 if (rv == SECFailure) { | |
618 goto loser; | |
619 } | |
620 } | |
621 if (constraints->excluded != NULL) { | |
622 rv = cert_EncodeNameConstraintSubTree(constraints->excluded, arena, | |
623 &constraints->DERExcluded, | |
624 PR_FALSE); | |
625 if (rv == SECFailure) { | |
626 goto loser; | |
627 } | |
628 } | |
629 dest = SEC_ASN1EncodeItem(arena, dest, constraints, | |
630 CERTNameConstraintsTemplate); | |
631 if (dest == NULL) { | |
632 goto loser; | |
633 } | |
634 /* TODO: unmark arena */ | |
635 return SECSuccess; | |
636 loser: | |
637 /* TODO: release arena to mark */ | |
638 return SECFailure; | |
639 } | |
640 | |
641 | |
642 CERTNameConstraint * | |
643 cert_DecodeNameConstraint(PLArenaPool *reqArena, | |
644 SECItem *encodedConstraint) | |
645 { | |
646 CERTNameConstraint *constraint; | |
647 SECStatus rv = SECSuccess; | |
648 CERTGeneralName *temp; | |
649 SECItem* newEncodedConstraint; | |
650 | |
651 if (!reqArena) { | |
652 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
653 return NULL; | |
654 } | |
655 newEncodedConstraint = SECITEM_ArenaDupItem(reqArena, encodedConstraint); | |
656 if (!newEncodedConstraint) { | |
657 return NULL; | |
658 } | |
659 /* TODO: mark arena */ | |
660 constraint = PORT_ArenaZNew(reqArena, CERTNameConstraint); | |
661 if (!constraint) | |
662 goto loser; | |
663 rv = SEC_QuickDERDecodeItem(reqArena, constraint, | |
664 CERTNameConstraintTemplate, | |
665 newEncodedConstraint); | |
666 if (rv != SECSuccess) { | |
667 goto loser; | |
668 } | |
669 temp = CERT_DecodeGeneralName(reqArena, &(constraint->DERName), | |
670 &(constraint->name)); | |
671 if (temp != &(constraint->name)) { | |
672 goto loser; | |
673 } | |
674 | |
675 /* ### sjlee: since the name constraint contains only one | |
676 * CERTGeneralName, the list within CERTGeneralName shouldn't | |
677 * point anywhere else. Otherwise, bad things will happen. | |
678 */ | |
679 constraint->name.l.prev = constraint->name.l.next = &(constraint->name.l); | |
680 /* TODO: unmark arena */ | |
681 return constraint; | |
682 loser: | |
683 /* TODO: release arena back to mark */ | |
684 return NULL; | |
685 } | |
686 | |
687 CERTNameConstraint * | |
688 cert_DecodeNameConstraintSubTree(PLArenaPool *arena, | |
689 SECItem **subTree, | |
690 PRBool permited) | |
691 { | |
692 CERTNameConstraint *current = NULL; | |
693 CERTNameConstraint *first = NULL; | |
694 CERTNameConstraint *last = NULL; | |
695 int i = 0; | |
696 | |
697 PORT_Assert(arena); | |
698 /* TODO: mark arena */ | |
699 while (subTree[i] != NULL) { | |
700 current = cert_DecodeNameConstraint(arena, subTree[i]); | |
701 if (current == NULL) { | |
702 goto loser; | |
703 } | |
704 if (last == NULL) { | |
705 first = last = current; | |
706 } | |
707 current->l.prev = &(last->l); | |
708 current->l.next = last->l.next; | |
709 last->l.next = &(current->l); | |
710 i++; | |
711 } | |
712 first->l.prev = &(current->l); | |
713 /* TODO: unmark arena */ | |
714 return first; | |
715 loser: | |
716 /* TODO: release arena back to mark */ | |
717 return NULL; | |
718 } | |
719 | |
720 CERTNameConstraints * | |
721 cert_DecodeNameConstraints(PLArenaPool *reqArena, | |
722 const SECItem *encodedConstraints) | |
723 { | |
724 CERTNameConstraints *constraints; | |
725 SECStatus rv; | |
726 SECItem* newEncodedConstraints; | |
727 | |
728 if (!reqArena) { | |
729 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
730 return NULL; | |
731 } | |
732 PORT_Assert(encodedConstraints); | |
733 newEncodedConstraints = SECITEM_ArenaDupItem(reqArena, encodedConstraints); | |
734 | |
735 /* TODO: mark arena */ | |
736 constraints = PORT_ArenaZNew(reqArena, CERTNameConstraints); | |
737 if (constraints == NULL) { | |
738 goto loser; | |
739 } | |
740 rv = SEC_QuickDERDecodeItem(reqArena, constraints, | |
741 CERTNameConstraintsTemplate, | |
742 newEncodedConstraints); | |
743 if (rv != SECSuccess) { | |
744 goto loser; | |
745 } | |
746 if (constraints->DERPermited != NULL && | |
747 constraints->DERPermited[0] != NULL) { | |
748 constraints->permited = | |
749 cert_DecodeNameConstraintSubTree(reqArena, | |
750 constraints->DERPermited, | |
751 PR_TRUE); | |
752 if (constraints->permited == NULL) { | |
753 goto loser; | |
754 } | |
755 } | |
756 if (constraints->DERExcluded != NULL && | |
757 constraints->DERExcluded[0] != NULL) { | |
758 constraints->excluded = | |
759 cert_DecodeNameConstraintSubTree(reqArena, | |
760 constraints->DERExcluded, | |
761 PR_FALSE); | |
762 if (constraints->excluded == NULL) { | |
763 goto loser; | |
764 } | |
765 } | |
766 /* TODO: unmark arena */ | |
767 return constraints; | |
768 loser: | |
769 /* TODO: release arena back to mark */ | |
770 return NULL; | |
771 } | |
772 | |
773 /* Copy a chain of one or more general names to a destination chain. | |
774 ** Caller has allocated at least the first destination GeneralName struct. | |
775 ** Both source and destination chains are circular doubly-linked lists. | |
776 ** The first source struct is copied to the first destination struct. | |
777 ** If the source chain has more than one member, and the destination chain | |
778 ** has only one member, then this function allocates new structs for all but | |
779 ** the first copy from the arena and links them into the destination list. | |
780 ** If the destination struct is part of a list with more than one member, | |
781 ** then this function traverses both the source and destination lists, | |
782 ** copying each source struct to the corresponding dest struct. | |
783 ** In that case, the destination list MUST contain at least as many | |
784 ** structs as the source list or some dest entries will be overwritten. | |
785 */ | |
786 SECStatus | |
787 CERT_CopyGeneralName(PLArenaPool *arena, | |
788 CERTGeneralName *dest, | |
789 CERTGeneralName *src) | |
790 { | |
791 SECStatus rv; | |
792 CERTGeneralName *destHead = dest; | |
793 CERTGeneralName *srcHead = src; | |
794 | |
795 PORT_Assert(dest != NULL); | |
796 if (!dest) { | |
797 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
798 return SECFailure; | |
799 } | |
800 /* TODO: mark arena */ | |
801 do { | |
802 rv = cert_CopyOneGeneralName(arena, dest, src); | |
803 if (rv != SECSuccess) | |
804 goto loser; | |
805 src = CERT_GetNextGeneralName(src); | |
806 /* if there is only one general name, we shouldn't do this */ | |
807 if (src != srcHead) { | |
808 if (dest->l.next == &destHead->l) { | |
809 CERTGeneralName *temp; | |
810 temp = CERT_NewGeneralName(arena, (CERTGeneralNameType)0); | |
811 if (!temp) | |
812 goto loser; | |
813 temp->l.next = &destHead->l; | |
814 temp->l.prev = &dest->l; | |
815 destHead->l.prev = &temp->l; | |
816 dest->l.next = &temp->l; | |
817 dest = temp; | |
818 } else { | |
819 dest = CERT_GetNextGeneralName(dest); | |
820 } | |
821 } | |
822 } while (src != srcHead && rv == SECSuccess); | |
823 /* TODO: unmark arena */ | |
824 return rv; | |
825 loser: | |
826 /* TODO: release back to mark */ | |
827 return SECFailure; | |
828 } | |
829 | |
830 | |
831 CERTGeneralNameList * | |
832 CERT_DupGeneralNameList(CERTGeneralNameList *list) | |
833 { | |
834 if (list != NULL) { | |
835 PZ_Lock(list->lock); | |
836 list->refCount++; | |
837 PZ_Unlock(list->lock); | |
838 } | |
839 return list; | |
840 } | |
841 | |
842 /* Allocate space and copy CERTNameConstraint from src to dest */ | |
843 CERTNameConstraint * | |
844 CERT_CopyNameConstraint(PLArenaPool *arena, | |
845 CERTNameConstraint *dest, | |
846 CERTNameConstraint *src) | |
847 { | |
848 SECStatus rv; | |
849 | |
850 /* TODO: mark arena */ | |
851 if (dest == NULL) { | |
852 dest = PORT_ArenaZNew(arena, CERTNameConstraint); | |
853 if (!dest) | |
854 goto loser; | |
855 /* mark that it is not linked */ | |
856 dest->name.l.prev = dest->name.l.next = &(dest->name.l); | |
857 } | |
858 rv = CERT_CopyGeneralName(arena, &dest->name, &src->name); | |
859 if (rv != SECSuccess) { | |
860 goto loser; | |
861 } | |
862 rv = SECITEM_CopyItem(arena, &dest->DERName, &src->DERName); | |
863 if (rv != SECSuccess) { | |
864 goto loser; | |
865 } | |
866 rv = SECITEM_CopyItem(arena, &dest->min, &src->min); | |
867 if (rv != SECSuccess) { | |
868 goto loser; | |
869 } | |
870 rv = SECITEM_CopyItem(arena, &dest->max, &src->max); | |
871 if (rv != SECSuccess) { | |
872 goto loser; | |
873 } | |
874 dest->l.prev = dest->l.next = &dest->l; | |
875 /* TODO: unmark arena */ | |
876 return dest; | |
877 loser: | |
878 /* TODO: release arena to mark */ | |
879 return NULL; | |
880 } | |
881 | |
882 | |
883 CERTGeneralName * | |
884 cert_CombineNamesLists(CERTGeneralName *list1, CERTGeneralName *list2) | |
885 { | |
886 PRCList *begin1; | |
887 PRCList *begin2; | |
888 PRCList *end1; | |
889 PRCList *end2; | |
890 | |
891 if (list1 == NULL){ | |
892 return list2; | |
893 } else if (list2 == NULL) { | |
894 return list1; | |
895 } else { | |
896 begin1 = &list1->l; | |
897 begin2 = &list2->l; | |
898 end1 = list1->l.prev; | |
899 end2 = list2->l.prev; | |
900 end1->next = begin2; | |
901 end2->next = begin1; | |
902 begin1->prev = end2; | |
903 begin2->prev = end1; | |
904 return list1; | |
905 } | |
906 } | |
907 | |
908 | |
909 CERTNameConstraint * | |
910 cert_CombineConstraintsLists(CERTNameConstraint *list1, CERTNameConstraint *list2) | |
911 { | |
912 PRCList *begin1; | |
913 PRCList *begin2; | |
914 PRCList *end1; | |
915 PRCList *end2; | |
916 | |
917 if (list1 == NULL){ | |
918 return list2; | |
919 } else if (list2 == NULL) { | |
920 return list1; | |
921 } else { | |
922 begin1 = &list1->l; | |
923 begin2 = &list2->l; | |
924 end1 = list1->l.prev; | |
925 end2 = list2->l.prev; | |
926 end1->next = begin2; | |
927 end2->next = begin1; | |
928 begin1->prev = end2; | |
929 begin2->prev = end1; | |
930 return list1; | |
931 } | |
932 } | |
933 | |
934 | |
935 /* Add a CERTNameConstraint to the CERTNameConstraint list */ | |
936 CERTNameConstraint * | |
937 CERT_AddNameConstraint(CERTNameConstraint *list, | |
938 CERTNameConstraint *constraint) | |
939 { | |
940 PORT_Assert(constraint != NULL); | |
941 constraint->l.next = constraint->l.prev = &constraint->l; | |
942 list = cert_CombineConstraintsLists(list, constraint); | |
943 return list; | |
944 } | |
945 | |
946 | |
947 SECStatus | |
948 CERT_GetNameConstraintByType (CERTNameConstraint *constraints, | |
949 CERTGeneralNameType type, | |
950 CERTNameConstraint **returnList, | |
951 PLArenaPool *arena) | |
952 { | |
953 CERTNameConstraint *current = NULL; | |
954 void *mark = NULL; | |
955 | |
956 *returnList = NULL; | |
957 if (!constraints) | |
958 return SECSuccess; | |
959 | |
960 mark = PORT_ArenaMark(arena); | |
961 | |
962 current = constraints; | |
963 do { | |
964 PORT_Assert(current->name.type); | |
965 if (current->name.type == type) { | |
966 CERTNameConstraint *temp; | |
967 temp = CERT_CopyNameConstraint(arena, NULL, current); | |
968 if (temp == NULL) | |
969 goto loser; | |
970 *returnList = CERT_AddNameConstraint(*returnList, temp); | |
971 } | |
972 current = CERT_GetNextNameConstraint(current); | |
973 } while (current != constraints); | |
974 PORT_ArenaUnmark(arena, mark); | |
975 return SECSuccess; | |
976 | |
977 loser: | |
978 PORT_ArenaRelease(arena, mark); | |
979 return SECFailure; | |
980 } | |
981 | |
982 void * | |
983 CERT_GetGeneralNameByType (CERTGeneralName *genNames, | |
984 CERTGeneralNameType type, PRBool derFormat) | |
985 { | |
986 CERTGeneralName *current; | |
987 | |
988 if (!genNames) | |
989 return NULL; | |
990 current = genNames; | |
991 | |
992 do { | |
993 if (current->type == type) { | |
994 switch (type) { | |
995 case certDNSName: | |
996 case certEDIPartyName: | |
997 case certIPAddress: | |
998 case certRegisterID: | |
999 case certRFC822Name: | |
1000 case certX400Address: | |
1001 case certURI: | |
1002 return (void *)¤t->name.other; /* SECItem * */ | |
1003 | |
1004 case certOtherName: | |
1005 return (void *)¤t->name.OthName; /* OthName * */ | |
1006 | |
1007 case certDirectoryName: | |
1008 return derFormat | |
1009 ? (void *)¤t->derDirectoryName /* SECItem * */ | |
1010 : (void *)¤t->name.directoryName; /* CERTName * */ | |
1011 } | |
1012 PORT_Assert(0); | |
1013 return NULL; | |
1014 } | |
1015 current = CERT_GetNextGeneralName(current); | |
1016 } while (current != genNames); | |
1017 return NULL; | |
1018 } | |
1019 | |
1020 int | |
1021 CERT_GetNamesLength(CERTGeneralName *names) | |
1022 { | |
1023 int length = 0; | |
1024 CERTGeneralName *first; | |
1025 | |
1026 first = names; | |
1027 if (names != NULL) { | |
1028 do { | |
1029 length++; | |
1030 names = CERT_GetNextGeneralName(names); | |
1031 } while (names != first); | |
1032 } | |
1033 return length; | |
1034 } | |
1035 | |
1036 /* Creates new GeneralNames for any email addresses found in the | |
1037 ** input DN, and links them onto the list for the DN. | |
1038 */ | |
1039 SECStatus | |
1040 cert_ExtractDNEmailAddrs(CERTGeneralName *name, PLArenaPool *arena) | |
1041 { | |
1042 CERTGeneralName *nameList = NULL; | |
1043 const CERTRDN **nRDNs = (const CERTRDN **)(name->name.directoryName.rdns); | |
1044 SECStatus rv = SECSuccess; | |
1045 | |
1046 PORT_Assert(name->type == certDirectoryName); | |
1047 if (name->type != certDirectoryName) { | |
1048 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
1049 return SECFailure; | |
1050 } | |
1051 /* TODO: mark arena */ | |
1052 while (nRDNs && *nRDNs) { /* loop over RDNs */ | |
1053 const CERTRDN *nRDN = *nRDNs++; | |
1054 CERTAVA **nAVAs = nRDN->avas; | |
1055 while (nAVAs && *nAVAs) { /* loop over AVAs */ | |
1056 int tag; | |
1057 CERTAVA *nAVA = *nAVAs++; | |
1058 tag = CERT_GetAVATag(nAVA); | |
1059 if ( tag == SEC_OID_PKCS9_EMAIL_ADDRESS || | |
1060 tag == SEC_OID_RFC1274_MAIL) { /* email AVA */ | |
1061 CERTGeneralName *newName = NULL; | |
1062 SECItem *avaValue = CERT_DecodeAVAValue(&nAVA->value); | |
1063 if (!avaValue) | |
1064 goto loser; | |
1065 rv = SECFailure; | |
1066 newName = CERT_NewGeneralName(arena, certRFC822Name); | |
1067 if (newName) { | |
1068 rv = SECITEM_CopyItem(arena, &newName->name.other, avaValue); | |
1069 } | |
1070 SECITEM_FreeItem(avaValue, PR_TRUE); | |
1071 if (rv != SECSuccess) | |
1072 goto loser; | |
1073 nameList = cert_CombineNamesLists(nameList, newName); | |
1074 } /* handle one email AVA */ | |
1075 } /* loop over AVAs */ | |
1076 } /* loop over RDNs */ | |
1077 /* combine new names with old one. */ | |
1078 name = cert_CombineNamesLists(name, nameList); | |
1079 /* TODO: unmark arena */ | |
1080 return SECSuccess; | |
1081 | |
1082 loser: | |
1083 /* TODO: release arena back to mark */ | |
1084 return SECFailure; | |
1085 } | |
1086 | |
1087 /* Extract all names except Subject Common Name from a cert | |
1088 ** in preparation for a name constraints test. | |
1089 */ | |
1090 CERTGeneralName * | |
1091 CERT_GetCertificateNames(CERTCertificate *cert, PLArenaPool *arena) | |
1092 { | |
1093 return CERT_GetConstrainedCertificateNames(cert, arena, PR_FALSE); | |
1094 } | |
1095 | |
1096 /* This function is called by CERT_VerifyCertChain to extract all | |
1097 ** names from a cert in preparation for a name constraints test. | |
1098 */ | |
1099 CERTGeneralName * | |
1100 CERT_GetConstrainedCertificateNames(const CERTCertificate *cert, | |
1101 PLArenaPool *arena, | |
1102 PRBool includeSubjectCommonName) | |
1103 { | |
1104 CERTGeneralName *DN; | |
1105 CERTGeneralName *SAN; | |
1106 PRUint32 numDNSNames = 0; | |
1107 SECStatus rv; | |
1108 | |
1109 if (!arena) { | |
1110 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
1111 return NULL; | |
1112 } | |
1113 /* TODO: mark arena */ | |
1114 DN = CERT_NewGeneralName(arena, certDirectoryName); | |
1115 if (DN == NULL) { | |
1116 goto loser; | |
1117 } | |
1118 rv = CERT_CopyName(arena, &DN->name.directoryName, &cert->subject); | |
1119 if (rv != SECSuccess) { | |
1120 goto loser; | |
1121 } | |
1122 rv = SECITEM_CopyItem(arena, &DN->derDirectoryName, &cert->derSubject); | |
1123 if (rv != SECSuccess) { | |
1124 goto loser; | |
1125 } | |
1126 /* Extract email addresses from DN, construct CERTGeneralName structs | |
1127 ** for them, add them to the name list | |
1128 */ | |
1129 rv = cert_ExtractDNEmailAddrs(DN, arena); | |
1130 if (rv != SECSuccess) | |
1131 goto loser; | |
1132 | |
1133 /* Now extract any GeneralNames from the subject name names extension. */ | |
1134 SAN = cert_GetSubjectAltNameList(cert, arena); | |
1135 if (SAN) { | |
1136 numDNSNames = cert_CountDNSPatterns(SAN); | |
1137 DN = cert_CombineNamesLists(DN, SAN); | |
1138 } | |
1139 if (!numDNSNames && includeSubjectCommonName) { | |
1140 char *cn = CERT_GetCommonName(&cert->subject); | |
1141 if (cn) { | |
1142 CERTGeneralName *CN = CERT_NewGeneralName(arena, certDNSName); | |
1143 if (CN) { | |
1144 SECItem cnItem = {siBuffer, NULL, 0}; | |
1145 cnItem.data = (unsigned char *)cn; | |
1146 cnItem.len = strlen(cn); | |
1147 rv = SECITEM_CopyItem(arena, &CN->name.other, &cnItem); | |
1148 if (rv == SECSuccess) { | |
1149 DN = cert_CombineNamesLists(DN, CN); | |
1150 } | |
1151 } | |
1152 PORT_Free(cn); | |
1153 } | |
1154 } | |
1155 if (rv == SECSuccess) { | |
1156 /* TODO: unmark arena */ | |
1157 return DN; | |
1158 } | |
1159 loser: | |
1160 /* TODO: release arena to mark */ | |
1161 return NULL; | |
1162 } | |
1163 | |
1164 /* Returns SECSuccess if name matches constraint per RFC 3280 rules for | |
1165 ** URI name constraints. SECFailure otherwise. | |
1166 ** If the constraint begins with a dot, it is a domain name, otherwise | |
1167 ** It is a host name. Examples: | |
1168 ** Constraint Name Result | |
1169 ** ------------ --------------- -------- | |
1170 ** foo.bar.com foo.bar.com matches | |
1171 ** foo.bar.com FoO.bAr.CoM matches | |
1172 ** foo.bar.com www.foo.bar.com no match | |
1173 ** foo.bar.com nofoo.bar.com no match | |
1174 ** .foo.bar.com www.foo.bar.com matches | |
1175 ** .foo.bar.com nofoo.bar.com no match | |
1176 ** .foo.bar.com foo.bar.com no match | |
1177 ** .foo.bar.com www..foo.bar.com no match | |
1178 */ | |
1179 static SECStatus | |
1180 compareURIN2C(const SECItem *name, const SECItem *constraint) | |
1181 { | |
1182 int offset; | |
1183 /* The spec is silent on intepreting zero-length constraints. | |
1184 ** We interpret them as matching no URI names. | |
1185 */ | |
1186 if (!constraint->len) | |
1187 return SECFailure; | |
1188 if (constraint->data[0] != '.') { | |
1189 /* constraint is a host name. */ | |
1190 if (name->len != constraint->len || | |
1191 PL_strncasecmp((char *)name->data, | |
1192 (char *)constraint->data, constraint->len)) | |
1193 return SECFailure; | |
1194 return SECSuccess; | |
1195 } | |
1196 /* constraint is a domain name. */ | |
1197 if (name->len < constraint->len) | |
1198 return SECFailure; | |
1199 offset = name->len - constraint->len; | |
1200 if (PL_strncasecmp((char *)(name->data + offset), | |
1201 (char *)constraint->data, constraint->len)) | |
1202 return SECFailure; | |
1203 if (!offset || | |
1204 (name->data[offset - 1] == '.') + (constraint->data[0] == '.') == 1) | |
1205 return SECSuccess; | |
1206 return SECFailure; | |
1207 } | |
1208 | |
1209 /* for DNSname constraints, RFC 3280 says, (section 4.2.1.11, page 38) | |
1210 ** | |
1211 ** DNS name restrictions are expressed as foo.bar.com. Any DNS name | |
1212 ** that can be constructed by simply adding to the left hand side of the | |
1213 ** name satisfies the name constraint. For example, www.foo.bar.com | |
1214 ** would satisfy the constraint but foo1.bar.com would not. | |
1215 ** | |
1216 ** But NIST's PKITS test suite requires that the constraint be treated | |
1217 ** as a domain name, and requires that any name added to the left hand | |
1218 ** side end in a dot ".". Sensible, but not strictly following the RFC. | |
1219 ** | |
1220 ** Constraint Name RFC 3280 NIST PKITS | |
1221 ** ------------ --------------- -------- ---------- | |
1222 ** foo.bar.com foo.bar.com matches matches | |
1223 ** foo.bar.com FoO.bAr.CoM matches matches | |
1224 ** foo.bar.com www.foo.bar.com matches matches | |
1225 ** foo.bar.com nofoo.bar.com MATCHES NO MATCH | |
1226 ** .foo.bar.com www.foo.bar.com matches matches? disallowed? | |
1227 ** .foo.bar.com foo.bar.com no match no match | |
1228 ** .foo.bar.com www..foo.bar.com matches probably not | |
1229 ** | |
1230 ** We will try to conform to NIST's PKITS tests, and the unstated | |
1231 ** rules they imply. | |
1232 */ | |
1233 static SECStatus | |
1234 compareDNSN2C(const SECItem *name, const SECItem *constraint) | |
1235 { | |
1236 int offset; | |
1237 /* The spec is silent on intepreting zero-length constraints. | |
1238 ** We interpret them as matching all DNSnames. | |
1239 */ | |
1240 if (!constraint->len) | |
1241 return SECSuccess; | |
1242 if (name->len < constraint->len) | |
1243 return SECFailure; | |
1244 offset = name->len - constraint->len; | |
1245 if (PL_strncasecmp((char *)(name->data + offset), | |
1246 (char *)constraint->data, constraint->len)) | |
1247 return SECFailure; | |
1248 if (!offset || | |
1249 (name->data[offset - 1] == '.') + (constraint->data[0] == '.') == 1) | |
1250 return SECSuccess; | |
1251 return SECFailure; | |
1252 } | |
1253 | |
1254 /* Returns SECSuccess if name matches constraint per RFC 3280 rules for | |
1255 ** internet email addresses. SECFailure otherwise. | |
1256 ** If constraint contains a '@' then the two strings much match exactly. | |
1257 ** Else if constraint starts with a '.'. then it must match the right-most | |
1258 ** substring of the name, | |
1259 ** else constraint string must match entire name after the name's '@'. | |
1260 ** Empty constraint string matches all names. All comparisons case insensitive. | |
1261 */ | |
1262 static SECStatus | |
1263 compareRFC822N2C(const SECItem *name, const SECItem *constraint) | |
1264 { | |
1265 int offset; | |
1266 if (!constraint->len) | |
1267 return SECSuccess; | |
1268 if (name->len < constraint->len) | |
1269 return SECFailure; | |
1270 if (constraint->len == 1 && constraint->data[0] == '.') | |
1271 return SECSuccess; | |
1272 for (offset = constraint->len - 1; offset >= 0; --offset) { | |
1273 if (constraint->data[offset] == '@') { | |
1274 return (name->len == constraint->len && | |
1275 !PL_strncasecmp((char *)name->data, | |
1276 (char *)constraint->data, constraint->len)) | |
1277 ? SECSuccess : SECFailure; | |
1278 } | |
1279 } | |
1280 offset = name->len - constraint->len; | |
1281 if (PL_strncasecmp((char *)(name->data + offset), | |
1282 (char *)constraint->data, constraint->len)) | |
1283 return SECFailure; | |
1284 if (constraint->data[0] == '.') | |
1285 return SECSuccess; | |
1286 if (offset > 0 && name->data[offset - 1] == '@') | |
1287 return SECSuccess; | |
1288 return SECFailure; | |
1289 } | |
1290 | |
1291 /* name contains either a 4 byte IPv4 address or a 16 byte IPv6 address. | |
1292 ** constraint contains an address of the same length, and a subnet mask | |
1293 ** of the same length. Compare name's address to the constraint's | |
1294 ** address, subject to the mask. | |
1295 ** Return SECSuccess if they match, SECFailure if they don't. | |
1296 */ | |
1297 static SECStatus | |
1298 compareIPaddrN2C(const SECItem *name, const SECItem *constraint) | |
1299 { | |
1300 int i; | |
1301 if (name->len == 4 && constraint->len == 8) { /* ipv4 addr */ | |
1302 for (i = 0; i < 4; i++) { | |
1303 if ((name->data[i] ^ constraint->data[i]) & constraint->data[i+4]) | |
1304 goto loser; | |
1305 } | |
1306 return SECSuccess; | |
1307 } | |
1308 if (name->len == 16 && constraint->len == 32) { /* ipv6 addr */ | |
1309 for (i = 0; i < 16; i++) { | |
1310 if ((name->data[i] ^ constraint->data[i]) & constraint->data[i+16]) | |
1311 goto loser; | |
1312 } | |
1313 return SECSuccess; | |
1314 } | |
1315 loser: | |
1316 return SECFailure; | |
1317 } | |
1318 | |
1319 /* start with a SECItem that points to a URI. Parse it lookingg for | |
1320 ** a hostname. Modify item->data and item->len to define the hostname, | |
1321 ** but do not modify and data at item->data. | |
1322 ** If anything goes wrong, the contents of *item are undefined. | |
1323 */ | |
1324 static SECStatus | |
1325 parseUriHostname(SECItem * item) | |
1326 { | |
1327 int i; | |
1328 PRBool found = PR_FALSE; | |
1329 for (i = 0; (unsigned)(i+2) < item->len; ++i) { | |
1330 if (item->data[i ] == ':' && | |
1331 item->data[i+1] == '/' && | |
1332 item->data[i+2] == '/') { | |
1333 i += 3; | |
1334 item->data += i; | |
1335 item->len -= i; | |
1336 found = PR_TRUE; | |
1337 break; | |
1338 } | |
1339 } | |
1340 if (!found) | |
1341 return SECFailure; | |
1342 /* now look for a '/', which is an upper bound in the end of the name */ | |
1343 for (i = 0; (unsigned)i < item->len; ++i) { | |
1344 if (item->data[i] == '/') { | |
1345 item->len = i; | |
1346 break; | |
1347 } | |
1348 } | |
1349 /* now look for a ':', which marks the end of the name */ | |
1350 for (i = item->len; --i >= 0; ) { | |
1351 if (item->data[i] == ':') { | |
1352 item->len = i; | |
1353 break; | |
1354 } | |
1355 } | |
1356 /* now look for an '@', which marks the beginning of the hostname */ | |
1357 for (i = 0; (unsigned)i < item->len; ++i) { | |
1358 if (item->data[i] == '@') { | |
1359 ++i; | |
1360 item->data += i; | |
1361 item->len -= i; | |
1362 break; | |
1363 } | |
1364 } | |
1365 return item->len ? SECSuccess : SECFailure; | |
1366 } | |
1367 | |
1368 /* This function takes one name, and a list of constraints. | |
1369 ** It searches the constraints looking for a match. | |
1370 ** It returns SECSuccess if the name satisfies the constraints, i.e., | |
1371 ** if excluded, then the name does not match any constraint, | |
1372 ** if permitted, then the name matches at least one constraint. | |
1373 ** It returns SECFailure if the name fails to satisfy the constraints, | |
1374 ** or if some code fails (e.g. out of memory, or invalid constraint) | |
1375 */ | |
1376 SECStatus | |
1377 cert_CompareNameWithConstraints(const CERTGeneralName *name, | |
1378 const CERTNameConstraint *constraints, | |
1379 PRBool excluded) | |
1380 { | |
1381 SECStatus rv = SECSuccess; | |
1382 SECStatus matched = SECFailure; | |
1383 const CERTNameConstraint *current; | |
1384 | |
1385 PORT_Assert(constraints); /* caller should not call with NULL */ | |
1386 if (!constraints) { | |
1387 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
1388 return SECFailure; | |
1389 } | |
1390 | |
1391 current = constraints; | |
1392 do { | |
1393 rv = SECSuccess; | |
1394 matched = SECFailure; | |
1395 PORT_Assert(name->type == current->name.type); | |
1396 switch (name->type) { | |
1397 | |
1398 case certDNSName: | |
1399 matched = compareDNSN2C(&name->name.other, | |
1400 ¤t->name.name.other); | |
1401 break; | |
1402 | |
1403 case certRFC822Name: | |
1404 matched = compareRFC822N2C(&name->name.other, | |
1405 ¤t->name.name.other); | |
1406 break; | |
1407 | |
1408 case certURI: | |
1409 { | |
1410 /* make a modifiable copy of the URI SECItem. */ | |
1411 SECItem uri = name->name.other; | |
1412 /* find the hostname in the URI */ | |
1413 rv = parseUriHostname(&uri); | |
1414 if (rv == SECSuccess) { | |
1415 /* does our hostname meet the constraint? */ | |
1416 matched = compareURIN2C(&uri, ¤t->name.name.other); | |
1417 } | |
1418 } | |
1419 break; | |
1420 | |
1421 case certDirectoryName: | |
1422 /* Determine if the constraint directory name is a "prefix" | |
1423 ** for the directory name being tested. | |
1424 */ | |
1425 { | |
1426 /* status defaults to SECEqual, so that a constraint with | |
1427 ** no AVAs will be a wildcard, matching all directory names. | |
1428 */ | |
1429 SECComparison status = SECEqual; | |
1430 const CERTRDN **cRDNs = | |
1431 (const CERTRDN **)current->name.name.directoryName.rdns; | |
1432 const CERTRDN **nRDNs = | |
1433 (const CERTRDN **)name->name.directoryName.rdns; | |
1434 while (cRDNs && *cRDNs && nRDNs && *nRDNs) { | |
1435 /* loop over name RDNs and constraint RDNs in lock step */ | |
1436 const CERTRDN *cRDN = *cRDNs++; | |
1437 const CERTRDN *nRDN = *nRDNs++; | |
1438 CERTAVA **cAVAs = cRDN->avas; | |
1439 while (cAVAs && *cAVAs) { /* loop over constraint AVAs */ | |
1440 CERTAVA *cAVA = *cAVAs++; | |
1441 CERTAVA **nAVAs = nRDN->avas; | |
1442 while (nAVAs && *nAVAs) { /* loop over name AVAs */ | |
1443 CERTAVA *nAVA = *nAVAs++; | |
1444 status = CERT_CompareAVA(cAVA, nAVA); | |
1445 if (status == SECEqual) | |
1446 break; | |
1447 } /* loop over name AVAs */ | |
1448 if (status != SECEqual) | |
1449 break; | |
1450 } /* loop over constraint AVAs */ | |
1451 if (status != SECEqual) | |
1452 break; | |
1453 } /* loop over name RDNs and constraint RDNs */ | |
1454 matched = (status == SECEqual) ? SECSuccess : SECFailure; | |
1455 break; | |
1456 } | |
1457 | |
1458 case certIPAddress: /* type 8 */ | |
1459 matched = compareIPaddrN2C(&name->name.other, | |
1460 ¤t->name.name.other); | |
1461 break; | |
1462 | |
1463 /* NSS does not know how to compare these "Other" type names with | |
1464 ** their respective constraints. But it does know how to tell | |
1465 ** if the constraint applies to the type of name (by comparing | |
1466 ** the constraint OID to the name OID). NSS makes no use of "Other" | |
1467 ** type names at all, so NSS errs on the side of leniency for these | |
1468 ** types, provided that their OIDs match. So, when an "Other" | |
1469 ** name constraint appears in an excluded subtree, it never causes | |
1470 ** a name to fail. When an "Other" name constraint appears in a | |
1471 ** permitted subtree, AND the constraint's OID matches the name's | |
1472 ** OID, then name is treated as if it matches the constraint. | |
1473 */ | |
1474 case certOtherName: /* type 1 */ | |
1475 matched = (!excluded && | |
1476 name->type == current->name.type && | |
1477 SECITEM_ItemsAreEqual(&name->name.OthName.oid, | |
1478 ¤t->name.name.OthName.oid)) | |
1479 ? SECSuccess : SECFailure; | |
1480 break; | |
1481 | |
1482 /* NSS does not know how to compare these types of names with their | |
1483 ** respective constraints. But NSS makes no use of these types of | |
1484 ** names at all, so it errs on the side of leniency for these types. | |
1485 ** Constraints for these types of names never cause the name to | |
1486 ** fail the constraints test. NSS behaves as if the name matched | |
1487 ** for permitted constraints, and did not match for excluded ones. | |
1488 */ | |
1489 case certX400Address: /* type 4 */ | |
1490 case certEDIPartyName: /* type 6 */ | |
1491 case certRegisterID: /* type 9 */ | |
1492 matched = excluded ? SECFailure : SECSuccess; | |
1493 break; | |
1494 | |
1495 default: /* non-standard types are not supported */ | |
1496 rv = SECFailure; | |
1497 break; | |
1498 } | |
1499 if (matched == SECSuccess || rv != SECSuccess) | |
1500 break; | |
1501 current = CERT_GetNextNameConstraint((CERTNameConstraint*)current); | |
1502 } while (current != constraints); | |
1503 if (rv == SECSuccess) { | |
1504 if (matched == SECSuccess) | |
1505 rv = excluded ? SECFailure : SECSuccess; | |
1506 else | |
1507 rv = excluded ? SECSuccess : SECFailure; | |
1508 return rv; | |
1509 } | |
1510 | |
1511 return SECFailure; | |
1512 } | |
1513 | |
1514 /* Add and link a CERTGeneralName to a CERTNameConstraint list. Most | |
1515 ** likely the CERTNameConstraint passed in is either the permitted | |
1516 ** list or the excluded list of a CERTNameConstraints. | |
1517 */ | |
1518 SECStatus | |
1519 CERT_AddNameConstraintByGeneralName(PLArenaPool *arena, | |
1520 CERTNameConstraint **constraints, | |
1521 CERTGeneralName *name) | |
1522 { | |
1523 SECStatus rv; | |
1524 CERTNameConstraint *current = NULL; | |
1525 CERTNameConstraint *first = *constraints; | |
1526 void *mark = NULL; | |
1527 | |
1528 mark = PORT_ArenaMark(arena); | |
1529 | |
1530 current = PORT_ArenaZNew(arena, CERTNameConstraint); | |
1531 if (current == NULL) { | |
1532 rv = SECFailure; | |
1533 goto done; | |
1534 } | |
1535 | |
1536 rv = cert_CopyOneGeneralName(arena, ¤t->name, name); | |
1537 if (rv != SECSuccess) { | |
1538 goto done; | |
1539 } | |
1540 | |
1541 current->name.l.prev = current->name.l.next = &(current->name.l); | |
1542 | |
1543 if (first == NULL) { | |
1544 *constraints = current; | |
1545 PR_INIT_CLIST(¤t->l); | |
1546 } else { | |
1547 PR_INSERT_BEFORE(¤t->l, &first->l); | |
1548 } | |
1549 | |
1550 done: | |
1551 if (rv == SECFailure) { | |
1552 PORT_ArenaRelease(arena, mark); | |
1553 } else { | |
1554 PORT_ArenaUnmark(arena, mark); | |
1555 } | |
1556 return rv; | |
1557 } | |
1558 | |
1559 /* Add name constraints to certain certs that do not include name constraints | |
1560 * This is the core of the implementation for bug 952572. | |
1561 */ | |
1562 | |
1563 static SECStatus | |
1564 getNameExtensionsBuiltIn(CERTCertificate *cert, | |
1565 SECItem *extensions) | |
1566 { | |
1567 const char constraintFranceGov[] = "\x30\x5D" /* sequence len = 93*/ | |
1568 "\xA0\x5B" /* element len =91 */ | |
1569 "\x30\x05" /* sequence len 5 */ | |
1570 "\x82\x03" /* entry len 3 */ | |
1571 ".fr" | |
1572 "\x30\x05\x82\x03" /* sequence len5, entry len 3 */ | |
1573 ".gp" | |
1574 "\x30\x05\x82\x03" | |
1575 ".gf" | |
1576 "\x30\x05\x82\x03" | |
1577 ".mq" | |
1578 "\x30\x05\x82\x03" | |
1579 ".re" | |
1580 "\x30\x05\x82\x03" | |
1581 ".yt" | |
1582 "\x30\x05\x82\x03" | |
1583 ".pm" | |
1584 "\x30\x05\x82\x03" | |
1585 ".bl" | |
1586 "\x30\x05\x82\x03" | |
1587 ".mf" | |
1588 "\x30\x05\x82\x03" | |
1589 ".wf" | |
1590 "\x30\x05\x82\x03" | |
1591 ".pf" | |
1592 "\x30\x05\x82\x03" | |
1593 ".nc" | |
1594 "\x30\x05\x82\x03" | |
1595 ".tf"; | |
1596 | |
1597 /* The stringified value for the subject is: | |
1598 E=igca@sgdn.pm.gouv.fr,CN=IGC/A,OU=DCSSI,O=PM/SGDN,L=Paris,ST=France,C=FR | |
1599 */ | |
1600 const char rawANSSISubject[] = "\x30\x81\x85\x31\x0B\x30\x09\x06\x03\x55\x04" | |
1601 "\x06\x13\x02\x46\x52\x31\x0F\x30\x0D\x06\x03" | |
1602 "\x55\x04\x08\x13\x06\x46\x72\x61\x6E\x63\x65" | |
1603 "\x31\x0E\x30\x0C\x06\x03\x55\x04\x07\x13\x05" | |
1604 "\x50\x61\x72\x69\x73\x31\x10\x30\x0E\x06\x03" | |
1605 "\x55\x04\x0A\x13\x07\x50\x4D\x2F\x53\x47\x44" | |
1606 "\x4E\x31\x0E\x30\x0C\x06\x03\x55\x04\x0B\x13" | |
1607 "\x05\x44\x43\x53\x53\x49\x31\x0E\x30\x0C\x06" | |
1608 "\x03\x55\x04\x03\x13\x05\x49\x47\x43\x2F\x41" | |
1609 "\x31\x23\x30\x21\x06\x09\x2A\x86\x48\x86\xF7" | |
1610 "\x0D\x01\x09\x01\x16\x14\x69\x67\x63\x61\x40" | |
1611 "\x73\x67\x64\x6E\x2E\x70\x6D\x2E\x67\x6F\x75" | |
1612 "\x76\x2E\x66\x72"; | |
1613 | |
1614 const SECItem anssi_subject = {0, (unsigned char *) rawANSSISubject, | |
1615 sizeof(rawANSSISubject)-1}; | |
1616 const SECItem permitFranceGovNC = {0, (unsigned char *) constraintFranceGov, | |
1617 sizeof(constraintFranceGov)-1}; | |
1618 | |
1619 if (SECITEM_ItemsAreEqual(&cert->derSubject, &anssi_subject)) { | |
1620 SECStatus rv; | |
1621 rv = SECITEM_CopyItem(NULL, extensions, &permitFranceGovNC); | |
1622 return rv; | |
1623 } | |
1624 PORT_SetError(SEC_ERROR_EXTENSION_NOT_FOUND); | |
1625 return SECFailure; | |
1626 } | |
1627 | |
1628 /* Extract the name constraints extension from the CA cert. */ | |
1629 SECStatus | |
1630 CERT_FindNameConstraintsExten(PLArenaPool *arena, | |
1631 CERTCertificate *cert, | |
1632 CERTNameConstraints **constraints) | |
1633 { | |
1634 SECStatus rv = SECSuccess; | |
1635 SECItem constraintsExtension; | |
1636 void *mark = NULL; | |
1637 | |
1638 *constraints = NULL; | |
1639 | |
1640 rv = CERT_FindCertExtension(cert, SEC_OID_X509_NAME_CONSTRAINTS, | |
1641 &constraintsExtension); | |
1642 if (rv != SECSuccess) { | |
1643 if (PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND) { | |
1644 return rv; | |
1645 } | |
1646 rv = getNameExtensionsBuiltIn(cert, &constraintsExtension); | |
1647 if (rv != SECSuccess) { | |
1648 if (PORT_GetError() == SEC_ERROR_EXTENSION_NOT_FOUND) { | |
1649 return SECSuccess; | |
1650 } | |
1651 return rv; | |
1652 } | |
1653 } | |
1654 | |
1655 mark = PORT_ArenaMark(arena); | |
1656 | |
1657 *constraints = cert_DecodeNameConstraints(arena, &constraintsExtension); | |
1658 if (*constraints == NULL) { /* decode failed */ | |
1659 rv = SECFailure; | |
1660 } | |
1661 PORT_Free (constraintsExtension.data); | |
1662 | |
1663 if (rv == SECFailure) { | |
1664 PORT_ArenaRelease(arena, mark); | |
1665 } else { | |
1666 PORT_ArenaUnmark(arena, mark); | |
1667 } | |
1668 | |
1669 return rv; | |
1670 } | |
1671 | |
1672 /* Verify name against all the constraints relevant to that type of | |
1673 ** the name. | |
1674 */ | |
1675 SECStatus | |
1676 CERT_CheckNameSpace(PLArenaPool *arena, | |
1677 const CERTNameConstraints *constraints, | |
1678 const CERTGeneralName *currentName) | |
1679 { | |
1680 CERTNameConstraint *matchingConstraints; | |
1681 SECStatus rv = SECSuccess; | |
1682 | |
1683 if (constraints->excluded != NULL) { | |
1684 rv = CERT_GetNameConstraintByType(constraints->excluded, | |
1685 currentName->type, | |
1686 &matchingConstraints, arena); | |
1687 if (rv == SECSuccess && matchingConstraints != NULL) { | |
1688 rv = cert_CompareNameWithConstraints(currentName, | |
1689 matchingConstraints, | |
1690 PR_TRUE); | |
1691 } | |
1692 if (rv != SECSuccess) { | |
1693 return(rv); | |
1694 } | |
1695 } | |
1696 | |
1697 if (constraints->permited != NULL) { | |
1698 rv = CERT_GetNameConstraintByType(constraints->permited, | |
1699 currentName->type, | |
1700 &matchingConstraints, arena); | |
1701 if (rv == SECSuccess && matchingConstraints != NULL) { | |
1702 rv = cert_CompareNameWithConstraints(currentName, | |
1703 matchingConstraints, | |
1704 PR_FALSE); | |
1705 } | |
1706 if (rv != SECSuccess) { | |
1707 return(rv); | |
1708 } | |
1709 } | |
1710 | |
1711 return(SECSuccess); | |
1712 } | |
1713 | |
1714 /* Extract the name constraints extension from the CA cert. | |
1715 ** Test each and every name in namesList against all the constraints | |
1716 ** relevant to that type of name. | |
1717 ** Returns NULL in pBadCert for success, if all names are acceptable. | |
1718 ** If some name is not acceptable, returns a pointer to the cert that | |
1719 ** contained that name. | |
1720 */ | |
1721 SECStatus | |
1722 CERT_CompareNameSpace(CERTCertificate *cert, | |
1723 CERTGeneralName *namesList, | |
1724 CERTCertificate **certsList, | |
1725 PLArenaPool *reqArena, | |
1726 CERTCertificate **pBadCert) | |
1727 { | |
1728 SECStatus rv = SECSuccess; | |
1729 CERTNameConstraints *constraints; | |
1730 CERTGeneralName *currentName; | |
1731 int count = 0; | |
1732 CERTCertificate *badCert = NULL; | |
1733 | |
1734 /* If no names to check, then no names can be bad. */ | |
1735 if (!namesList) | |
1736 goto done; | |
1737 rv = CERT_FindNameConstraintsExten(reqArena, cert, &constraints); | |
1738 if (rv != SECSuccess) { | |
1739 count = -1; | |
1740 goto done; | |
1741 } | |
1742 | |
1743 currentName = namesList; | |
1744 do { | |
1745 if (constraints){ | |
1746 rv = CERT_CheckNameSpace(reqArena, constraints, currentName); | |
1747 if (rv != SECSuccess) { | |
1748 break; | |
1749 } | |
1750 } | |
1751 currentName = CERT_GetNextGeneralName(currentName); | |
1752 count ++; | |
1753 } while (currentName != namesList); | |
1754 | |
1755 done: | |
1756 if (rv != SECSuccess) { | |
1757 badCert = (count >= 0) ? certsList[count] : cert; | |
1758 } | |
1759 if (pBadCert) | |
1760 *pBadCert = badCert; | |
1761 | |
1762 return rv; | |
1763 } | |
1764 | |
1765 #if 0 | |
1766 /* not exported from shared libs, not used. Turn on if we ever need it. */ | |
1767 SECStatus | |
1768 CERT_CompareGeneralName(CERTGeneralName *a, CERTGeneralName *b) | |
1769 { | |
1770 CERTGeneralName *currentA; | |
1771 CERTGeneralName *currentB; | |
1772 PRBool found; | |
1773 | |
1774 currentA = a; | |
1775 currentB = b; | |
1776 if (a != NULL) { | |
1777 do { | |
1778 if (currentB == NULL) { | |
1779 return SECFailure; | |
1780 } | |
1781 currentB = CERT_GetNextGeneralName(currentB); | |
1782 currentA = CERT_GetNextGeneralName(currentA); | |
1783 } while (currentA != a); | |
1784 } | |
1785 if (currentB != b) { | |
1786 return SECFailure; | |
1787 } | |
1788 currentA = a; | |
1789 do { | |
1790 currentB = b; | |
1791 found = PR_FALSE; | |
1792 do { | |
1793 if (currentB->type == currentA->type) { | |
1794 switch (currentB->type) { | |
1795 case certDNSName: | |
1796 case certEDIPartyName: | |
1797 case certIPAddress: | |
1798 case certRegisterID: | |
1799 case certRFC822Name: | |
1800 case certX400Address: | |
1801 case certURI: | |
1802 if (SECITEM_CompareItem(¤tA->name.other, | |
1803 ¤tB->name.other) | |
1804 == SECEqual) { | |
1805 found = PR_TRUE; | |
1806 } | |
1807 break; | |
1808 case certOtherName: | |
1809 if (SECITEM_CompareItem(¤tA->name.OthName.oid, | |
1810 ¤tB->name.OthName.oid) | |
1811 == SECEqual && | |
1812 SECITEM_CompareItem(¤tA->name.OthName.name, | |
1813 ¤tB->name.OthName.name) | |
1814 == SECEqual) { | |
1815 found = PR_TRUE; | |
1816 } | |
1817 break; | |
1818 case certDirectoryName: | |
1819 if (CERT_CompareName(¤tA->name.directoryName, | |
1820 ¤tB->name.directoryName) | |
1821 == SECEqual) { | |
1822 found = PR_TRUE; | |
1823 } | |
1824 } | |
1825 | |
1826 } | |
1827 currentB = CERT_GetNextGeneralName(currentB); | |
1828 } while (currentB != b && found != PR_TRUE); | |
1829 if (found != PR_TRUE) { | |
1830 return SECFailure; | |
1831 } | |
1832 currentA = CERT_GetNextGeneralName(currentA); | |
1833 } while (currentA != a); | |
1834 return SECSuccess; | |
1835 } | |
1836 | |
1837 SECStatus | |
1838 CERT_CompareGeneralNameLists(CERTGeneralNameList *a, CERTGeneralNameList *b) | |
1839 { | |
1840 SECStatus rv; | |
1841 | |
1842 if (a == b) { | |
1843 return SECSuccess; | |
1844 } | |
1845 if (a != NULL && b != NULL) { | |
1846 PZ_Lock(a->lock); | |
1847 PZ_Lock(b->lock); | |
1848 rv = CERT_CompareGeneralName(a->name, b->name); | |
1849 PZ_Unlock(a->lock); | |
1850 PZ_Unlock(b->lock); | |
1851 } else { | |
1852 rv = SECFailure; | |
1853 } | |
1854 return rv; | |
1855 } | |
1856 #endif | |
1857 | |
1858 #if 0 | |
1859 /* This function is not exported from NSS shared libraries, and is not | |
1860 ** used inside of NSS. | |
1861 ** XXX it doesn't check for failed allocations. :-( | |
1862 */ | |
1863 void * | |
1864 CERT_GetGeneralNameFromListByType(CERTGeneralNameList *list, | |
1865 CERTGeneralNameType type, | |
1866 PLArenaPool *arena) | |
1867 { | |
1868 CERTName *name = NULL; | |
1869 SECItem *item = NULL; | |
1870 OtherName *other = NULL; | |
1871 OtherName *tmpOther = NULL; | |
1872 void *data; | |
1873 | |
1874 PZ_Lock(list->lock); | |
1875 data = CERT_GetGeneralNameByType(list->name, type, PR_FALSE); | |
1876 if (data != NULL) { | |
1877 switch (type) { | |
1878 case certDNSName: | |
1879 case certEDIPartyName: | |
1880 case certIPAddress: | |
1881 case certRegisterID: | |
1882 case certRFC822Name: | |
1883 case certX400Address: | |
1884 case certURI: | |
1885 if (arena != NULL) { | |
1886 item = PORT_ArenaNew(arena, SECItem); | |
1887 if (item != NULL) { | |
1888 XXX SECITEM_CopyItem(arena, item, (SECItem *) data); | |
1889 } | |
1890 } else { | |
1891 item = SECITEM_DupItem((SECItem *) data); | |
1892 } | |
1893 PZ_Unlock(list->lock); | |
1894 return item; | |
1895 case certOtherName: | |
1896 other = (OtherName *) data; | |
1897 if (arena != NULL) { | |
1898 tmpOther = PORT_ArenaNew(arena, OtherName); | |
1899 } else { | |
1900 tmpOther = PORT_New(OtherName); | |
1901 } | |
1902 if (tmpOther != NULL) { | |
1903 XXX SECITEM_CopyItem(arena, &tmpOther->oid, &other->oid); | |
1904 XXX SECITEM_CopyItem(arena, &tmpOther->name, &other->name); | |
1905 } | |
1906 PZ_Unlock(list->lock); | |
1907 return tmpOther; | |
1908 case certDirectoryName: | |
1909 if (arena) { | |
1910 name = PORT_ArenaZNew(list->arena, CERTName); | |
1911 if (name) { | |
1912 XXX CERT_CopyName(arena, name, (CERTName *) data); | |
1913 } | |
1914 } | |
1915 PZ_Unlock(list->lock); | |
1916 return name; | |
1917 } | |
1918 } | |
1919 PZ_Unlock(list->lock); | |
1920 return NULL; | |
1921 } | |
1922 #endif | |
1923 | |
1924 #if 0 | |
1925 /* This function is not exported from NSS shared libraries, and is not | |
1926 ** used inside of NSS. | |
1927 ** XXX it should NOT be a void function, since it does allocations | |
1928 ** that can fail. | |
1929 */ | |
1930 void | |
1931 CERT_AddGeneralNameToList(CERTGeneralNameList *list, | |
1932 CERTGeneralNameType type, | |
1933 void *data, SECItem *oid) | |
1934 { | |
1935 CERTGeneralName *name; | |
1936 | |
1937 if (list != NULL && data != NULL) { | |
1938 PZ_Lock(list->lock); | |
1939 name = CERT_NewGeneralName(list->arena, type); | |
1940 if (!name) | |
1941 goto done; | |
1942 switch (type) { | |
1943 case certDNSName: | |
1944 case certEDIPartyName: | |
1945 case certIPAddress: | |
1946 case certRegisterID: | |
1947 case certRFC822Name: | |
1948 case certX400Address: | |
1949 case certURI: | |
1950 XXX SECITEM_CopyItem(list->arena, &name->name.other, (SECItem *)data); | |
1951 break; | |
1952 case certOtherName: | |
1953 XXX SECITEM_CopyItem(list->arena, &name->name.OthName.name, | |
1954 (SECItem *) data); | |
1955 XXX SECITEM_CopyItem(list->arena, &name->name.OthName.oid, | |
1956 oid); | |
1957 break; | |
1958 case certDirectoryName: | |
1959 XXX CERT_CopyName(list->arena, &name->name.directoryName, | |
1960 (CERTName *) data); | |
1961 break; | |
1962 } | |
1963 list->name = cert_CombineNamesLists(list->name, name); | |
1964 list->len++; | |
1965 done: | |
1966 PZ_Unlock(list->lock); | |
1967 } | |
1968 return; | |
1969 } | |
1970 #endif |