Imported Upstream version 3.13.6
[platform/upstream/nss.git] / mozilla / security / nss / lib / libpkix / pkix_pl_nss / pki / pkix_pl_generalname.c
1 /* ***** BEGIN LICENSE BLOCK *****
2  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3  *
4  * The contents of this file are subject to the Mozilla Public License Version
5  * 1.1 (the "License"); you may not use this file except in compliance with
6  * the License. You may obtain a copy of the License at
7  * http://www.mozilla.org/MPL/
8  *
9  * Software distributed under the License is distributed on an "AS IS" basis,
10  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11  * for the specific language governing rights and limitations under the
12  * License.
13  *
14  * The Original Code is the PKIX-C library.
15  *
16  * The Initial Developer of the Original Code is
17  * Sun Microsystems, Inc.
18  * Portions created by the Initial Developer are
19  * Copyright 2004-2007 Sun Microsystems, Inc.  All Rights Reserved.
20  *
21  * Contributor(s):
22  *   Sun Microsystems, Inc.
23  *
24  * Alternatively, the contents of this file may be used under the terms of
25  * either the GNU General Public License Version 2 or later (the "GPL"), or
26  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27  * in which case the provisions of the GPL or the LGPL are applicable instead
28  * of those above. If you wish to allow use of your version of this file only
29  * under the terms of either the GPL or the LGPL, and not to allow others to
30  * use your version of this file under the terms of the MPL, indicate your
31  * decision by deleting the provisions above and replace them with the notice
32  * and other provisions required by the GPL or the LGPL. If you do not delete
33  * the provisions above, a recipient may use your version of this file under
34  * the terms of any one of the MPL, the GPL or the LGPL.
35  *
36  * ***** END LICENSE BLOCK ***** */
37 /*
38  * pkix_pl_generalname.c
39  *
40  * GeneralName Object Definitions
41  *
42  */
43
44 #include "pkix_pl_generalname.h"
45
46 /* --Private-GeneralName-Functions------------------------------------- */
47
48 /*
49  * FUNCTION: pkix_pl_GeneralName_GetNssGeneralName
50  * DESCRIPTION:
51  *
52  *  Retrieves the NSS representation of the PKIX_PL_GeneralName pointed by
53  *  "genName" and stores it at "pNssGenName". The NSS data type CERTGeneralName
54  *  is stored in this object when the object was created.
55  *
56  * PARAMETERS:
57  *  "genName"
58  *      Address of PKIX_PL_GeneralName. Must be non-NULL.
59  *  "pNssGenName"
60  *      Address where CERTGeneralName will be stored. Must be non-NULL.
61  *  "plContext" - Platform-specific context pointer.
62  * THREAD SAFETY:
63  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
64  * RETURNS:
65  *  Returns NULL if the function succeeds.
66  *  Returns a GeneralName Error if the function fails in a non-fatal way.
67  *  Returns a Fatal Error if the function fails in an unrecoverable way.
68  */
69 PKIX_Error *
70 pkix_pl_GeneralName_GetNssGeneralName(
71         PKIX_PL_GeneralName *genName,
72         CERTGeneralName **pNssGenName,
73         void *plContext)
74 {
75         CERTGeneralName *nssGenName = NULL;
76
77         PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_GetNssGeneralName");
78         PKIX_NULLCHECK_THREE(genName, pNssGenName, genName->nssGeneralNameList);
79
80         nssGenName = genName->nssGeneralNameList->name;
81
82         *pNssGenName = nssGenName;
83
84         PKIX_RETURN(GENERALNAME);
85 }
86
87 /*
88  * FUNCTION: pkix_pl_OtherName_Create
89  * DESCRIPTION:
90  *
91  *  Creates new OtherName which represents the CERTGeneralName pointed to by
92  *  "nssAltName" and stores it at "pOtherName".
93  *
94  * PARAMETERS:
95  *  "nssAltName"
96  *      Address of CERTGeneralName. Must be non-NULL.
97  *  "pOtherName"
98  *      Address where object pointer will be stored. Must be non-NULL.
99  *  "plContext" - Platform-specific context pointer.
100  * THREAD SAFETY:
101  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
102  * RETURNS:
103  *  Returns NULL if the function succeeds.
104  *  Returns a GeneralName Error if the function fails in a non-fatal way.
105  *  Returns a Fatal Error if the function fails in an unrecoverable way.
106  */
107 static PKIX_Error *
108 pkix_pl_OtherName_Create(
109         CERTGeneralName *nssAltName,
110         OtherName **pOtherName,
111         void *plContext)
112 {
113         OtherName *otherName = NULL;
114         SECItem secItemName;
115         SECItem secItemOID;
116         SECStatus rv;
117
118         PKIX_ENTER(GENERALNAME, "pkix_pl_OtherName_Create");
119         PKIX_NULLCHECK_TWO(nssAltName, pOtherName);
120
121         PKIX_CHECK(PKIX_PL_Malloc
122                     (sizeof (OtherName), (void **)&otherName, plContext),
123                     PKIX_MALLOCFAILED);
124
125         /* make a copy of the name field */
126         PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_CopyItem).\n");
127         rv = SECITEM_CopyItem
128                 (NULL, &otherName->name, &nssAltName->name.OthName.name);
129         if (rv != SECSuccess) {
130                 PKIX_ERROR(PKIX_OUTOFMEMORY);
131         }
132
133         /* make a copy of the oid field */
134         PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_CopyItem).\n");
135         rv = SECITEM_CopyItem
136                 (NULL, &otherName->oid, &nssAltName->name.OthName.oid);
137         if (rv != SECSuccess) {
138                 PKIX_ERROR(PKIX_OUTOFMEMORY);
139         }
140
141         *pOtherName = otherName;
142
143 cleanup:
144
145         if (otherName && PKIX_ERROR_RECEIVED){
146                 secItemName = otherName->name;
147                 secItemOID = otherName->oid;
148
149                 PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_FreeItem).\n");
150                 SECITEM_FreeItem(&secItemName, PR_FALSE);
151
152                 PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_FreeItem).\n");
153                 SECITEM_FreeItem(&secItemOID, PR_FALSE);
154
155                 PKIX_FREE(otherName);
156                 otherName = NULL;
157         }
158
159         PKIX_RETURN(GENERALNAME);
160 }
161
162 /*
163  * FUNCTION: pkix_pl_DirectoryName_Create
164  * DESCRIPTION:
165  *
166  *  Creates a new X500Name which represents the directoryName component of the
167  *  CERTGeneralName pointed to by "nssAltName" and stores it at "pX500Name".
168  *
169  * PARAMETERS:
170  *  "nssAltName"
171  *      Address of CERTGeneralName. Must be non-NULL.
172  *  "pX500Name"
173  *      Address where object pointer will be stored. Must be non-NULL.
174  *  "plContext" - Platform-specific context pointer.
175  * THREAD SAFETY:
176  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
177  * RETURNS:
178  *  Returns NULL if the function succeeds.
179  *  Returns a GeneralName Error if the function fails in a non-fatal way.
180  *  Returns a Fatal Error if the function fails in an unrecoverable way.
181  */
182 static PKIX_Error *
183 pkix_pl_DirectoryName_Create(
184         CERTGeneralName *nssAltName,
185         PKIX_PL_X500Name **pX500Name,
186         void *plContext)
187 {
188         PKIX_PL_X500Name *pkixDN = NULL;
189         CERTName *dirName = NULL;
190         PKIX_PL_String *pkixDNString = NULL;
191         char *utf8String = NULL;
192
193         PKIX_ENTER(GENERALNAME, "pkix_pl_DirectoryName_Create");
194         PKIX_NULLCHECK_TWO(nssAltName, pX500Name);
195
196         dirName = &nssAltName->name.directoryName;
197
198         PKIX_CHECK(PKIX_PL_X500Name_CreateFromCERTName(NULL, dirName, 
199                                                        &pkixDN, plContext),
200                    PKIX_X500NAMECREATEFROMCERTNAMEFAILED);
201
202         *pX500Name = pkixDN;
203
204 cleanup:
205
206         PR_Free(utf8String);
207         PKIX_DECREF(pkixDNString);
208
209         PKIX_RETURN(GENERALNAME);
210 }
211
212 /*
213  * FUNCTION: pkix_pl_GeneralName_Create
214  * DESCRIPTION:
215  *
216  *  Creates new GeneralName which represents the CERTGeneralName pointed to by
217  *  "nssAltName" and stores it at "pGenName".
218  *
219  * PARAMETERS:
220  *  "nssAltName"
221  *      Address of CERTGeneralName. Must be non-NULL.
222  *  "pGenName"
223  *      Address where object pointer will be stored. Must be non-NULL.
224  *  "plContext" - Platform-specific context pointer.
225  * THREAD SAFETY:
226  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
227  * RETURNS:
228  *  Returns NULL if the function succeeds.
229  *  Returns a GeneralName Error if the function fails in a non-fatal way.
230  *  Returns a Fatal Error if the function fails in an unrecoverable way.
231  */
232 PKIX_Error *
233 pkix_pl_GeneralName_Create(
234         CERTGeneralName *nssAltName,
235         PKIX_PL_GeneralName **pGenName,
236         void *plContext)
237 {
238         PKIX_PL_GeneralName *genName = NULL;
239         PKIX_PL_X500Name *pkixDN = NULL;
240         PKIX_PL_OID *pkixOID = NULL;
241         OtherName *otherName = NULL;
242         CERTGeneralNameList *nssGenNameList = NULL;
243         CERTGeneralNameType nameType;
244
245         PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_Create");
246         PKIX_NULLCHECK_TWO(nssAltName, pGenName);
247
248         /* create a PKIX_PL_GeneralName object */
249         PKIX_CHECK(PKIX_PL_Object_Alloc
250                     (PKIX_GENERALNAME_TYPE,
251                     sizeof (PKIX_PL_GeneralName),
252                     (PKIX_PL_Object **)&genName,
253                     plContext),
254                     PKIX_COULDNOTCREATEOBJECT);
255
256         nameType = nssAltName->type;
257
258         /*
259          * We use CERT_CreateGeneralNameList to create just one CERTGeneralName
260          * item for memory allocation reason. If we want to just create one
261          * item, we have to use the calling path CERT_NewGeneralName, then
262          * CERT_CopyOneGeneralName. With this calling path, if we pass
263          * the arena argument as NULL, in CERT_CopyOneGeneralName's subsequent
264          * call to CERT_CopyName, it assumes arena should be valid, hence
265          * segmentation error (not sure this is a NSS bug, certainly it is
266          * not consistent). But on the other hand, we don't want to keep an
267          * arena record here explicitely for every PKIX_PL_GeneralName.
268          * So I concluded it is better to use CERT_CreateGeneralNameList,
269          * which keeps an arena pointer in its data structure and also masks
270          * out details calls from this libpkix level.
271          */
272
273         PKIX_GENERALNAME_DEBUG("\t\tCalling CERT_CreateGeneralNameList).\n");
274         nssGenNameList = CERT_CreateGeneralNameList(nssAltName);
275
276         if (nssGenNameList == NULL) {
277                 PKIX_ERROR(PKIX_CERTCREATEGENERALNAMELISTFAILED);
278         }
279
280         genName->nssGeneralNameList = nssGenNameList;
281
282         /* initialize fields */
283         genName->type = nameType;
284         genName->directoryName = NULL;
285         genName->OthName = NULL;
286         genName->other = NULL;
287         genName->oid = NULL;
288
289         switch (nameType){
290         case certOtherName:
291
292                 PKIX_CHECK(pkix_pl_OtherName_Create
293                             (nssAltName, &otherName, plContext),
294                             PKIX_OTHERNAMECREATEFAILED);
295
296                 genName->OthName = otherName;
297                 break;
298
299         case certDirectoryName:
300
301                 PKIX_CHECK(pkix_pl_DirectoryName_Create
302                             (nssAltName, &pkixDN, plContext),
303                             PKIX_DIRECTORYNAMECREATEFAILED);
304
305                 genName->directoryName = pkixDN;
306                 break;
307         case certRegisterID:
308                 PKIX_CHECK(PKIX_PL_OID_CreateBySECItem(&nssAltName->name.other,
309                                                        &pkixOID, plContext),
310                             PKIX_OIDCREATEFAILED);
311
312                 genName->oid = pkixOID;
313                 break;
314         case certDNSName:
315         case certEDIPartyName:
316         case certIPAddress:
317         case certRFC822Name:
318         case certX400Address:
319         case certURI:
320                 genName->other = SECITEM_DupItem(&nssAltName->name.other);
321                 if (!genName->other) {
322                     PKIX_ERROR(PKIX_OUTOFMEMORY);
323                 }     
324                 break;
325         default:
326                 PKIX_ERROR(PKIX_NAMETYPENOTSUPPORTED);
327         }
328
329         *pGenName = genName;
330         genName = NULL;
331
332 cleanup:
333         PKIX_DECREF(genName);
334
335         PKIX_RETURN(GENERALNAME);
336 }
337
338 /*
339  * FUNCTION: pkix_pl_GeneralName_ToString_Helper
340  * DESCRIPTION:
341  *
342  *  Helper function that creates a string representation of the GeneralName
343  *  pointed to by "name" and stores it at "pString" Different mechanisms are
344  *  used to create the string, depending on the type of the GeneralName.
345  *
346  * PARAMETERS
347  *  "name"
348  *      Address of GeneralName whose string representation is desired.
349  *      Must be non-NULL.
350  *  "pString"
351  *      Address where object pointer will be stored. Must be non-NULL.
352  *  "plContext" - Platform-specific context pointer.
353  * THREAD SAFETY:
354  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
355  * RETURNS:
356  *  Returns NULL if the function succeeds.
357  *  Returns a GeneralName Error if the function fails in a non-fatal way.
358  *  Returns a Fatal Error if the function fails in an unrecoverable way.
359  */
360 static PKIX_Error *
361 pkix_pl_GeneralName_ToString_Helper(
362         PKIX_PL_GeneralName *name,
363         PKIX_PL_String **pString,
364         void *plContext)
365 {
366         PKIX_PL_X500Name *pkixDN = NULL;
367         PKIX_PL_OID *pkixOID = NULL;
368         char *x400AsciiName = NULL;
369         char *ediPartyName = NULL;
370         char *asciiName = NULL;
371
372         PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_ToString_Helper");
373         PKIX_NULLCHECK_TWO(name, pString);
374
375         switch (name->type) {
376         case certRFC822Name:
377         case certDNSName:
378         case certURI:
379                 /*
380                  * Note that we can't use PKIX_ESCASCII here because
381                  * name->other->data is not guaranteed to be null-terminated.
382                  */
383
384                 PKIX_NULLCHECK_ONE(name->other);
385
386                 PKIX_CHECK(PKIX_PL_String_Create(PKIX_UTF8,
387                                                 (name->other)->data,
388                                                 (name->other)->len,
389                                                 pString,
390                                                 plContext),
391                             PKIX_STRINGCREATEFAILED);
392                 break;
393         case certEDIPartyName:
394                 /* XXX print out the actual bytes */
395                 ediPartyName = "EDIPartyName: <DER-encoded value>";
396                 PKIX_CHECK(PKIX_PL_String_Create(PKIX_ESCASCII,
397                                                 ediPartyName,
398                                                 0,
399                                                 pString,
400                                                 plContext),
401                             PKIX_STRINGCREATEFAILED);
402                 break;
403         case certX400Address:
404                 /* XXX print out the actual bytes */
405                 x400AsciiName = "X400Address: <DER-encoded value>";
406                 PKIX_CHECK(PKIX_PL_String_Create(PKIX_ESCASCII,
407                                                 x400AsciiName,
408                                                 0,
409                                                 pString,
410                                                 plContext),
411                             PKIX_STRINGCREATEFAILED);
412                 break;
413         case certIPAddress:
414                 PKIX_CHECK(pkix_pl_ipAddrBytes2Ascii
415                             (name->other, &asciiName, plContext),
416                             PKIX_IPADDRBYTES2ASCIIFAILED);
417
418                 PKIX_CHECK(PKIX_PL_String_Create(PKIX_ESCASCII,
419                                                 asciiName,
420                                                 0,
421                                                 pString,
422                                                 plContext),
423                             PKIX_STRINGCREATEFAILED);
424                 break;
425         case certOtherName:
426                 PKIX_NULLCHECK_ONE(name->OthName);
427
428                 /* we only print type-id - don't know how to print value */
429                 /* XXX print out the bytes of the value */
430                 PKIX_CHECK(pkix_pl_oidBytes2Ascii
431                             (&name->OthName->oid, &asciiName, plContext),
432                             PKIX_OIDBYTES2ASCIIFAILED);
433
434                 PKIX_CHECK(PKIX_PL_String_Create
435                             (PKIX_ESCASCII,
436                             asciiName,
437                             0,
438                             pString,
439                             plContext),
440                             PKIX_STRINGCREATEFAILED);
441                 break;
442         case certRegisterID:
443                 pkixOID = name->oid;
444                 PKIX_CHECK(PKIX_PL_Object_ToString
445                             ((PKIX_PL_Object *)pkixOID, pString, plContext),
446                             PKIX_OIDTOSTRINGFAILED);
447                 break;
448         case certDirectoryName:
449                 pkixDN = name->directoryName;
450                 PKIX_CHECK(PKIX_PL_Object_ToString
451                             ((PKIX_PL_Object *)pkixDN, pString, plContext),
452                             PKIX_X500NAMETOSTRINGFAILED);
453                 break;
454         default:
455                 PKIX_ERROR
456                         (PKIX_TOSTRINGFORTHISGENERALNAMETYPENOTSUPPORTED);
457         }
458
459 cleanup:
460
461         PKIX_FREE(asciiName);
462
463         PKIX_RETURN(GENERALNAME);
464 }
465
466 /*
467  * FUNCTION: pkix_pl_GeneralName_Destroy
468  * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
469  */
470 static PKIX_Error *
471 pkix_pl_GeneralName_Destroy(
472         PKIX_PL_Object *object,
473         void *plContext)
474 {
475         PKIX_PL_GeneralName *name = NULL;
476         SECItem secItemName;
477         SECItem secItemOID;
478
479         PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_Destroy");
480         PKIX_NULLCHECK_ONE(object);
481
482         PKIX_CHECK(pkix_CheckType(object, PKIX_GENERALNAME_TYPE, plContext),
483                     PKIX_OBJECTNOTGENERALNAME);
484
485         name = (PKIX_PL_GeneralName *)object;
486
487         PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_FreeItem).\n");
488         SECITEM_FreeItem(name->other, PR_TRUE);
489         name->other = NULL;
490
491         if (name->OthName){
492                 secItemName = name->OthName->name;
493                 secItemOID = name->OthName->oid;
494
495                 PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_FreeItem).\n");
496                 SECITEM_FreeItem(&secItemName, PR_FALSE);
497
498                 PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_FreeItem).\n");
499                 SECITEM_FreeItem(&secItemOID, PR_FALSE);
500
501                 PKIX_FREE(name->OthName);
502                 name->OthName = NULL;
503         }
504
505         if (name->nssGeneralNameList != NULL) {
506                 PKIX_GENERALNAME_DEBUG
507                         ("\t\tCalling CERT_DestroyGeneralNameList).\n");
508                 CERT_DestroyGeneralNameList(name->nssGeneralNameList);
509         }
510
511         PKIX_DECREF(name->directoryName);
512         PKIX_DECREF(name->oid);
513
514 cleanup:
515
516         PKIX_RETURN(GENERALNAME);
517 }
518
519 /*
520  * FUNCTION: pkix_pl_GeneralName_ToString
521  * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
522  */
523 static PKIX_Error *
524 pkix_pl_GeneralName_ToString(
525         PKIX_PL_Object *object,
526         PKIX_PL_String **pString,
527         void *plContext)
528 {
529         PKIX_PL_String *nameString = NULL;
530         PKIX_PL_GeneralName *name = NULL;
531
532         PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_toString");
533         PKIX_NULLCHECK_TWO(object, pString);
534
535         PKIX_CHECK(pkix_CheckType(object, PKIX_GENERALNAME_TYPE, plContext),
536                     PKIX_OBJECTNOTGENERALNAME);
537
538         name = (PKIX_PL_GeneralName *)object;
539
540         PKIX_CHECK(pkix_pl_GeneralName_ToString_Helper
541                     (name, &nameString, plContext),
542                     PKIX_GENERALNAMETOSTRINGHELPERFAILED);
543
544         *pString = nameString;
545
546 cleanup:
547
548
549
550         PKIX_RETURN(GENERALNAME);
551 }
552
553 /*
554  * FUNCTION: pkix_pl_GeneralName_Hashcode
555  * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
556  */
557 static PKIX_Error *
558 pkix_pl_GeneralName_Hashcode(
559         PKIX_PL_Object *object,
560         PKIX_UInt32 *pHashcode,
561         void *plContext)
562 {
563         PKIX_PL_GeneralName *name = NULL;
564         PKIX_UInt32 firstHash, secondHash, nameHash;
565
566         PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_Hashcode");
567         PKIX_NULLCHECK_TWO(object, pHashcode);
568
569         PKIX_CHECK(pkix_CheckType(object, PKIX_GENERALNAME_TYPE, plContext),
570                     PKIX_OBJECTNOTGENERALNAME);
571
572         name = (PKIX_PL_GeneralName *)object;
573
574         switch (name->type) {
575         case certRFC822Name:
576         case certDNSName:
577         case certX400Address:
578         case certEDIPartyName:
579         case certURI:
580         case certIPAddress:
581                 PKIX_NULLCHECK_ONE(name->other);
582                 PKIX_CHECK(pkix_hash
583                             ((const unsigned char *)
584                             name->other->data,
585                             name->other->len,
586                             &nameHash,
587                             plContext),
588                             PKIX_HASHFAILED);
589                 break;
590         case certRegisterID:
591                 PKIX_CHECK(PKIX_PL_Object_Hashcode
592                             ((PKIX_PL_Object *)name->oid,
593                             &nameHash,
594                             plContext),
595                             PKIX_OIDHASHCODEFAILED);
596                 break;
597         case certOtherName:
598                 PKIX_NULLCHECK_ONE(name->OthName);
599                 PKIX_CHECK(pkix_hash
600                             ((const unsigned char *)
601                             name->OthName->oid.data,
602                             name->OthName->oid.len,
603                             &firstHash,
604                             plContext),
605                             PKIX_HASHFAILED);
606
607                 PKIX_CHECK(pkix_hash
608                             ((const unsigned char *)
609                             name->OthName->name.data,
610                             name->OthName->name.len,
611                             &secondHash,
612                             plContext),
613                             PKIX_HASHFAILED);
614
615                 nameHash = firstHash + secondHash;
616                 break;
617         case certDirectoryName:
618                 PKIX_CHECK(PKIX_PL_Object_Hashcode
619                             ((PKIX_PL_Object *)
620                             name->directoryName,
621                             &nameHash,
622                             plContext),
623                             PKIX_X500NAMEHASHCODEFAILED);
624                 break;
625         }
626
627         *pHashcode = nameHash;
628
629 cleanup:
630
631         PKIX_RETURN(GENERALNAME);
632
633 }
634
635 /*
636  * FUNCTION: pkix_pl_GeneralName_Equals
637  * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
638  */
639 static PKIX_Error *
640 pkix_pl_GeneralName_Equals(
641         PKIX_PL_Object *firstObject,
642         PKIX_PL_Object *secondObject,
643         PKIX_Boolean *pResult,
644         void *plContext)
645 {
646         PKIX_PL_GeneralName *firstName = NULL;
647         PKIX_PL_GeneralName *secondName = NULL;
648         PKIX_UInt32 secondType;
649
650         PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_Equals");
651         PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
652
653         /* test that firstObject is a GeneralName */
654         PKIX_CHECK(pkix_CheckType
655                     (firstObject, PKIX_GENERALNAME_TYPE, plContext),
656                     PKIX_FIRSTOBJECTNOTGENERALNAME);
657
658         /*
659          * Since we know firstObject is a GeneralName, if both references are
660          * identical, they must be equal
661          */
662         if (firstObject == secondObject){
663                 *pResult = PKIX_TRUE;
664                 goto cleanup;
665         }
666
667         /*
668          * If secondObject isn't a GeneralName, we don't throw an error.
669          * We simply return a Boolean result of FALSE
670          */
671         *pResult = PKIX_FALSE;
672         PKIX_CHECK(PKIX_PL_Object_GetType
673                     (secondObject, &secondType, plContext),
674                     PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
675         if (secondType != PKIX_GENERALNAME_TYPE){
676                 goto cleanup;
677         }
678
679         firstName = (PKIX_PL_GeneralName *)firstObject;
680         secondName = (PKIX_PL_GeneralName *)secondObject;
681
682         if (firstName->type != secondName->type){
683                 goto cleanup;
684         }
685
686         switch (firstName->type) {
687         case certRFC822Name:
688         case certDNSName:
689         case certX400Address:
690         case certEDIPartyName:
691         case certURI:
692         case certIPAddress:
693                 PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_CompareItem).\n");
694                 if (SECITEM_CompareItem(firstName->other,
695                                         secondName->other) != SECEqual) {
696                         goto cleanup;
697                 }
698                 break;
699         case certRegisterID:
700                 PKIX_CHECK(PKIX_PL_Object_Equals
701                             ((PKIX_PL_Object *)firstName->oid,
702                             (PKIX_PL_Object *)secondName->oid,
703                             pResult,
704                             plContext),
705                             PKIX_OIDEQUALSFAILED);
706                 goto cleanup;
707         case certOtherName:
708                 PKIX_NULLCHECK_TWO(firstName->OthName, secondName->OthName);
709                 PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_CompareItem).\n");
710                 if (SECITEM_CompareItem(&firstName->OthName->oid,
711                                         &secondName->OthName->oid)
712                     != SECEqual ||
713                     SECITEM_CompareItem(&firstName->OthName->name,
714                                         &secondName->OthName->name)
715                     != SECEqual) {
716                         goto cleanup;
717                 }
718                 break;
719         case certDirectoryName:
720                 PKIX_CHECK(PKIX_PL_Object_Equals
721                             ((PKIX_PL_Object *)firstName->directoryName,
722                             (PKIX_PL_Object *)secondName->directoryName,
723                             pResult,
724                             plContext),
725                             PKIX_X500NAMEEQUALSFAILED);
726                 goto cleanup;
727         }
728
729         *pResult = PKIX_TRUE;
730
731 cleanup:
732
733         PKIX_RETURN(GENERALNAME);
734 }
735
736 /*
737  * FUNCTION: pkix_pl_GeneralName_RegisterSelf
738  * DESCRIPTION:
739  *  Registers PKIX_GENERALNAME_TYPE and related functions with systemClasses[]
740  * THREAD SAFETY:
741  *  Not Thread Safe - for performance and complexity reasons
742  *
743  *  Since this function is only called by PKIX_PL_Initialize, which should
744  *  only be called once, it is acceptable that this function is not
745  *  thread-safe.
746  */
747 PKIX_Error *
748 pkix_pl_GeneralName_RegisterSelf(void *plContext)
749 {
750
751         extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
752         pkix_ClassTable_Entry entry;
753
754         PKIX_ENTER(GENERALNAME, "pkix_pl_GeneralName_RegisterSelf");
755
756         entry.description = "GeneralName";
757         entry.objCounter = 0;
758         entry.typeObjectSize = sizeof(PKIX_PL_GeneralName);
759         entry.destructor = pkix_pl_GeneralName_Destroy;
760         entry.equalsFunction = pkix_pl_GeneralName_Equals;
761         entry.hashcodeFunction = pkix_pl_GeneralName_Hashcode;
762         entry.toStringFunction = pkix_pl_GeneralName_ToString;
763         entry.comparator = NULL;
764         entry.duplicateFunction = pkix_duplicateImmutable;
765
766         systemClasses[PKIX_GENERALNAME_TYPE] = entry;
767
768         PKIX_RETURN(GENERALNAME);
769 }
770
771 /* --Public-Functions------------------------------------------------------- */
772
773 #ifdef BUILD_LIBPKIX_TESTS
774 /*
775  * FUNCTION: PKIX_PL_GeneralName_Create (see comments in pkix_pl_pki.h)
776  */
777 PKIX_Error *
778 PKIX_PL_GeneralName_Create(
779         PKIX_UInt32 nameType,
780         PKIX_PL_String *stringRep,
781         PKIX_PL_GeneralName **pGName,
782         void *plContext)
783 {
784         PKIX_PL_X500Name *pkixDN = NULL;
785         PKIX_PL_OID *pkixOID = NULL;
786         SECItem *secItem = NULL;
787         char *asciiString = NULL;
788         PKIX_UInt32 length = 0;
789         PKIX_PL_GeneralName *genName = NULL;
790         CERTGeneralName *nssGenName = NULL;
791         CERTGeneralNameList *nssGenNameList = NULL;
792         CERTName *nssCertName = NULL;
793         PLArenaPool *arena = NULL;
794
795         PKIX_ENTER(GENERALNAME, "PKIX_PL_GeneralName_Create");
796         PKIX_NULLCHECK_TWO(pGName, stringRep);
797
798         PKIX_CHECK(PKIX_PL_String_GetEncoded
799                     (stringRep,
800                     PKIX_ESCASCII,
801                     (void **)&asciiString,
802                     &length,
803                     plContext),
804                     PKIX_STRINGGETENCODEDFAILED);
805
806         /* Create a temporary CERTGeneralName */
807         PKIX_GENERALNAME_DEBUG("\t\tCalling PL_strlen).\n");
808         length = PL_strlen(asciiString);
809         PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_AllocItem).\n");
810         secItem = SECITEM_AllocItem(NULL, NULL, length);
811         PKIX_GENERALNAME_DEBUG("\t\tCalling PORT_Memcpy).\n");
812         (void) PORT_Memcpy(secItem->data, asciiString, length);
813         PKIX_CERT_DEBUG("\t\tCalling PORT_NewArena).\n");
814         arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
815         if (arena == NULL) {
816                 PKIX_ERROR(PKIX_OUTOFMEMORY);
817         }
818         PKIX_GENERALNAME_DEBUG("\t\tCalling CERT_NewGeneralName).\n");
819         nssGenName = CERT_NewGeneralName(arena, nameType);
820         if (nssGenName == NULL) {
821                 PKIX_ERROR(PKIX_ALLOCATENEWCERTGENERALNAMEFAILED);
822         }
823
824         switch (nameType) {
825         case certRFC822Name:
826         case certDNSName:
827         case certURI:
828                 nssGenName->name.other = *secItem;
829                 break;
830
831         case certDirectoryName:
832
833                 PKIX_CHECK(PKIX_PL_X500Name_Create
834                             (stringRep, &pkixDN, plContext),
835                             PKIX_X500NAMECREATEFAILED);
836
837                 PKIX_GENERALNAME_DEBUG("\t\tCalling CERT_AsciiToName).\n");
838                 nssCertName = CERT_AsciiToName(asciiString);
839                 nssGenName->name.directoryName = *nssCertName;
840                 break;
841
842         case certRegisterID:
843                 PKIX_CHECK(PKIX_PL_OID_Create
844                             (asciiString, &pkixOID, plContext),
845                             PKIX_OIDCREATEFAILED);
846                 nssGenName->name.other = *secItem;
847                 break;
848         default:
849                 /* including IPAddress, EDIPartyName, OtherName, X400Address */
850                 PKIX_ERROR(PKIX_UNABLETOCREATEGENERALNAMEOFTHISTYPE);
851         }
852
853         /* create a PKIX_PL_GeneralName object */
854         PKIX_CHECK(PKIX_PL_Object_Alloc
855                     (PKIX_GENERALNAME_TYPE,
856                     sizeof (PKIX_PL_GeneralName),
857                     (PKIX_PL_Object **)&genName,
858                     plContext),
859                     PKIX_COULDNOTCREATEOBJECT);
860
861         /* create a CERTGeneralNameList */
862         nssGenName->type = nameType;
863         PKIX_GENERALNAME_DEBUG("\t\tCalling CERT_CreateGeneralNameList).\n");
864         nssGenNameList = CERT_CreateGeneralNameList(nssGenName);
865         if (nssGenNameList == NULL) {
866                 PKIX_ERROR(PKIX_CERTCREATEGENERALNAMELISTFAILED);
867         }
868         genName->nssGeneralNameList = nssGenNameList;
869
870         /* initialize fields */
871         genName->type = nameType;
872         genName->directoryName = pkixDN;
873         genName->OthName = NULL;
874         genName->other = secItem;
875         genName->oid = pkixOID;
876
877         *pGName = genName;
878 cleanup:
879
880         PKIX_FREE(asciiString);
881
882         if (nssCertName != NULL) {
883                 PKIX_CERT_DEBUG("\t\tCalling CERT_DestroyName).\n");
884                 CERT_DestroyName(nssCertName);
885         }
886
887         if (arena){ /* will free nssGenName */
888                 PKIX_CERT_DEBUG("\t\tCalling PORT_FreeArena).\n");
889                 PORT_FreeArena(arena, PR_FALSE);
890         }
891
892         if (PKIX_ERROR_RECEIVED){
893                 PKIX_DECREF(pkixDN);
894                 PKIX_DECREF(pkixOID);
895
896                 PKIX_GENERALNAME_DEBUG("\t\tCalling SECITEM_FreeItem).\n");
897                 if (secItem){
898                         SECITEM_FreeItem(secItem, PR_TRUE);
899                         secItem = NULL;
900                 }
901         }
902
903         PKIX_RETURN(GENERALNAME);
904 }
905
906 #endif /* BUILD_LIBPKIX_TESTS */