summaryrefslogtreecommitdiff
path: root/security/nss/lib/pki1/atav.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/pki1/atav.c')
-rw-r--r--security/nss/lib/pki1/atav.c1821
1 files changed, 0 insertions, 1821 deletions
diff --git a/security/nss/lib/pki1/atav.c b/security/nss/lib/pki1/atav.c
deleted file mode 100644
index cdf311a37..000000000
--- a/security/nss/lib/pki1/atav.c
+++ /dev/null
@@ -1,1821 +0,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * The Original Code is the Netscape security libraries.
- *
- * The Initial Developer of the Original Code is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1994-2000 Netscape Communications Corporation. All
- * Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL"), in which case the provisions of the GPL are applicable
- * instead of those above. If you wish to allow use of your
- * version of this file only under the terms of the GPL and not to
- * allow others to use your version of this file under the MPL,
- * indicate your decision by deleting the provisions above and
- * replace them with the notice and other provisions required by
- * the GPL. If you do not delete the provisions above, a recipient
- * may use your version of this file under either the MPL or the
- * GPL.
- */
-
-#ifdef DEBUG
-static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$";
-#endif /* DEBUG */
-
-/*
- * atav.c
- *
- * This file contains the implementation of the PKIX part-1 object
- * AttributeTypeAndValue.
- */
-
-#ifndef NSSBASE_H
-#include "nssbase.h"
-#endif /* NSSBASE_H */
-
-#ifndef ASN1_H
-#include "asn1.h"
-#endif /* ASN1_H */
-
-#ifndef PKI1_H
-#include "pki1.h"
-#endif /* PKI1_H */
-
-/*
- * AttributeTypeAndValue
- *
- * From draft-ietf-pkix-ipki-part1-10:
- *
- * AttributeTypeAndValue ::= SEQUENCE {
- * type ATTRIBUTE.&id ({SupportedAttributes}),
- * value ATTRIBUTE.&Type ({SupportedAttributes}{@type})}
- *
- * -- ATTRIBUTE information object class specification
- * -- Note: This has been greatly simplified for PKIX !!
- *
- * ATTRIBUTE ::= CLASS {
- * &Type,
- * &id OBJECT IDENTIFIER UNIQUE }
- * WITH SYNTAX {
- * WITH SYNTAX &Type ID &id }
- *
- * What this means is that the "type" of the value is determined by
- * the value of the oid. If we hide the structure, our accessors
- * can (at least in debug builds) assert value semantics beyond what
- * the compiler can provide. Since these things are only used in
- * RelativeDistinguishedNames, and since RDNs always contain a SET
- * of these things, we don't lose anything by hiding the structure
- * (and its size).
- */
-
-struct NSSATAVStr {
- NSSBER ber;
- const NSSOID *oid;
- NSSUTF8 *value;
- nssStringType stringForm;
-};
-
-/*
- * NSSATAV
- *
- * The public "methods" regarding this "object" are:
- *
- * NSSATAV_CreateFromBER -- constructor
- * NSSATAV_CreateFromUTF8 -- constructor
- * NSSATAV_Create -- constructor
- *
- * NSSATAV_Destroy
- * NSSATAV_GetDEREncoding
- * NSSATAV_GetUTF8Encoding
- * NSSATAV_GetType
- * NSSATAV_GetValue
- * NSSATAV_Compare
- * NSSATAV_Duplicate
- *
- * The non-public "methods" regarding this "object" are:
- *
- * nssATAV_CreateFromBER -- constructor
- * nssATAV_CreateFromUTF8 -- constructor
- * nssATAV_Create -- constructor
- *
- * nssATAV_Destroy
- * nssATAV_GetDEREncoding
- * nssATAV_GetUTF8Encoding
- * nssATAV_GetType
- * nssATAV_GetValue
- * nssATAV_Compare
- * nssATAV_Duplicate
- *
- * In debug builds, the following non-public call is also available:
- *
- * nssATAV_verifyPointer
- */
-
-/*
- * NSSATAV_CreateFromBER
- *
- * This routine creates an NSSATAV by decoding a BER- or DER-encoded
- * ATAV. If the optional arena argument is non-null, the memory used
- * will be obtained from that arena; otherwise, the memory will be
- * obtained from the heap. This routine may return NULL upon error,
- * in which case it will have created an error stack.
- *
- * The error may be one of the following values:
- * NSS_ERROR_INVALID_BER
- * NSS_ERROR_NO_MEMORY
- *
- * Return value:
- * NULL upon error
- * A pointer to an NSSATAV upon success
- */
-
-NSS_IMPLEMENT NSSATAV *
-NSSATAV_CreateFromBER
-(
- NSSArena *arenaOpt,
- NSSBER *berATAV
-)
-{
- nss_ClearErrorStack();
-
-#ifdef DEBUG
- if( (NSSArena *)NULL != arenaOpt ) {
- if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
- return (NSSATAV *)NULL;
- }
- }
-
- /*
- * NSSBERs can be created by the user,
- * so no pointer-tracking can be checked.
- */
-
- if( (NSSBER *)NULL == berATAV ) {
- nss_SetError(NSS_ERROR_INVALID_BER);
- return (NSSATAV *)NULL;
- }
-
- if( (void *)NULL == berATAV->data ) {
- nss_SetError(NSS_ERROR_INVALID_BER);
- return (NSSATAV *)NULL;
- }
-#endif /* DEBUG */
-
- return nssATAV_CreateFromBER(arenaOpt, berATAV);
-}
-
-/*
- * NSSATAV_CreateFromUTF8
- *
- * This routine creates an NSSATAV by decoding a UTF8 string in the
- * "equals" format, e.g., "c=US." If the optional arena argument is
- * non-null, the memory used will be obtained from that arena;
- * otherwise, the memory will be obtained from the heap. This routine
- * may return NULL upon error, in which case it will have created an
- * error stack.
- *
- * The error may be one of the following values:
- * NSS_ERROR_UNKNOWN_ATTRIBUTE
- * NSS_ERROR_INVALID_STRING
- * NSS_ERROR_NO_MEMORY
- *
- * Return value:
- * NULL upon error
- * A pointer to an NSSATAV upon success
- */
-
-NSS_IMPLEMENT NSSATAV *
-NSSATAV_CreateFromUTF8
-(
- NSSArena *arenaOpt,
- NSSUTF8 *stringATAV
-)
-{
- nss_ClearErrorStack();
-
-#ifdef DEBUG
- if( (NSSArena *)NULL != arenaOpt ) {
- if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
- return (NSSATAV *)NULL;
- }
- }
-
- /*
- * NSSUTF8s can be created by the user,
- * so no pointer-tracking can be checked.
- */
-
- if( (NSSUTF8 *)NULL == stringATAV ) {
- nss_SetError(NSS_ERROR_INVALID_UTF8);
- return (NSSATAV *)NULL;
- }
-#endif /* DEBUG */
-
- return nssATAV_CreateFromUTF8(arenaOpt, stringATAV);
-}
-
-/*
- * NSSATAV_Create
- *
- * This routine creates an NSSATAV from the specified NSSOID and the
- * specified data. If the optional arena argument is non-null, the
- * memory used will be obtained from that arena; otherwise, the memory
- * will be obtained from the heap.If the specified data length is zero,
- * the data is assumed to be terminated by first zero byte; this allows
- * UTF8 strings to be easily specified. This routine may return NULL
- * upon error, in which case it will have created an error stack.
- *
- * The error may be one of the following values:
- * NSS_ERROR_INVALID_ARENA
- * NSS_ERROR_INVALID_NSSOID
- * NSS_ERROR_INVALID_POINTER
- * NSS_ERROR_NO_MEMORY
- *
- * Return value:
- * NULL upon error
- * A pointer to an NSSATAV upon success
- */
-
-NSS_IMPLEMENT NSSATAV *
-NSSATAV_Create
-(
- NSSArena *arenaOpt,
- const NSSOID *oid,
- const void *data,
- PRUint32 length
-)
-{
- nss_ClearErrorStack();
-
-#ifdef DEBUG
- if( (NSSArena *)NULL != arenaOpt ) {
- if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
- return (NSSATAV *)NULL;
- }
- }
-
- if( PR_SUCCESS != nssOID_verifyPointer(oid) ) {
- return (NSSATAV *)NULL;
- }
-
- if( (const void *)NULL == data ) {
- nss_SetError(NSS_ERROR_INVALID_POINTER);
- return (NSSATAV *)NULL;
- }
-#endif /* DEBUG */
-
- return nssATAV_Create(arenaOpt, oid, data, length);
-}
-
-/*
- * NSSATAV_Destroy
- *
- * This routine will destroy an ATAV object. It should eventually be
- * called on all ATAVs created without an arena. While it is not
- * necessary to call it on ATAVs created within an arena, it is not an
- * error to do so. This routine returns a PRStatus value; if
- * successful, it will return PR_SUCCESS. If unsuccessful, it will
- * create an error stack and return PR_FAILURE.
- *
- * The error may be one of the following values:
- * NSS_ERROR_INVALID_ATAV
- *
- * Return value:
- * PR_FAILURE upon error
- * PR_SUCCESS upon success
- */
-
-NSS_IMPLEMENT PRStatus
-NSSATAV_Destroy
-(
- NSSATAV *atav
-)
-{
- nss_ClearErrorStack();
-
-#ifdef DEBUG
- if( PR_SUCCESS != nssATAV_verifyPointer(atav) ) {
- return PR_FAILURE;
- }
-#endif /* DEBUG */
-
- return nssATAV_Destroy(atav);
-}
-
-/*
- * NSSATAV_GetDEREncoding
- *
- * This routine will DER-encode an ATAV object. If the optional arena
- * argument is non-null, the memory used will be obtained from that
- * arena; otherwise, the memory will be obtained from the heap. This
- * routine may return null upon error, in which case it will have
- * created an error stack.
- *
- * The error may be one of the following values:
- * NSS_ERROR_INVALID_ATAV
- * NSS_ERROR_NO_MEMORY
- *
- * Return value:
- * NULL upon error
- * The DER encoding of this NSSATAV
- */
-
-NSS_IMPLEMENT NSSDER *
-NSSATAV_GetDEREncoding
-(
- NSSATAV *atav,
- NSSArena *arenaOpt
-)
-{
- nss_ClearErrorStack();
-
-#ifdef DEBUG
- if( PR_SUCCESS != nssATAV_verifyPointer(atav) ) {
- return (NSSDER *)NULL;
- }
-
- if( (NSSArena *)NULL != arenaOpt ) {
- if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
- return (NSSDER *)NULL;
- }
- }
-#endif /* DEBUG */
-
- return nssATAV_GetDEREncoding(atav, arenaOpt);
-}
-
-/*
- * NSSATAV_GetUTF8Encoding
- *
- * This routine returns a UTF8 string containing a string
- * representation of the ATAV in "equals" notation (e.g., "o=Acme").
- * If the optional arena argument is non-null, the memory used will be
- * obtained from that arena; otherwise, the memory will be obtained
- * from the heap. This routine may return null upon error, in which
- * case it will have created an error stack.
- *
- * The error may be one of the following values:
- * NSS_ERROR_INVALID_ATAV
- * NSS_ERROR_NO_MEMORY
- *
- * Return value:
- * NULL upon error
- * A pointer to a UTF8 string containing the "equals" encoding of the
- * ATAV
- */
-
-NSS_IMPLEMENT NSSUTF8 *
-NSSATAV_GetUTF8Encoding
-(
- NSSATAV *atav,
- NSSArena *arenaOpt
-)
-{
- nss_ClearErrorStack();
-
-#ifdef DEBUG
- if( PR_SUCCESS != nssATAV_verifyPointer(atav) ) {
- return (NSSUTF8 *)NULL;
- }
-
- if( (NSSArena *)NULL != arenaOpt ) {
- if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
- return (NSSUTF8 *)NULL;
- }
- }
-#endif /* DEBUG */
-
- return nssATAV_GetUTF8Encoding(atav, arenaOpt);
-}
-
-/*
- * NSSATAV_GetType
- *
- * This routine returns the NSSOID corresponding to the attribute type
- * in the specified ATAV. This routine may return NSS_OID_UNKNOWN
- * upon error, in which case it will have created an error stack.
- *
- * The error may be one of the following values:
- * NSS_ERROR_INVALID_ATAV
- *
- * Return value:
- * NSS_OID_UNKNOWN upon error
- * An element of enum NSSOIDenum upon success
- */
-
-NSS_IMPLEMENT const NSSOID *
-NSSATAV_GetType
-(
- NSSATAV *atav
-)
-{
- nss_ClearErrorStack();
-
-#ifdef DEBUG
- if( PR_SUCCESS != nssATAV_verifyPointer(atav) ) {
- return (NSSOID *)NULL;
- }
-#endif /* DEBUG */
-
- return nssATAV_GetType(atav);
-}
-
-/*
- * NSSATAV_GetValue
- *
- * This routine returns a string containing the attribute value
- * in the specified ATAV. If the optional arena argument is non-null,
- * the memory used will be obtained from that arena; otherwise, the
- * memory will be obtained from the heap. This routine may return
- * NULL upon error, in which case it will have created an error stack.
- *
- * The error may be one of the following values:
- * NSS_ERROR_INVALID_ATAV
- * NSS_ERROR_NO_MEMORY
- *
- * Return value:
- * NULL upon error
- * A pointer to an NSSItem containing the attribute value.
- */
-
-NSS_IMPLEMENT NSSUTF8 *
-NSSATAV_GetValue
-(
- NSSATAV *atav,
- NSSArena *arenaOpt
-)
-{
- nss_ClearErrorStack();
-
-#ifdef DEBUG
- if( PR_SUCCESS != nssATAV_verifyPointer(atav) ) {
- return (NSSUTF8 *)NULL;
- }
-
- if( (NSSArena *)NULL != arenaOpt ) {
- if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
- return (NSSUTF8 *)NULL;
- }
- }
-#endif /* DEBUG */
-
- return nssATAV_GetValue(atav, arenaOpt);
-}
-
-/*
- * NSSATAV_Compare
- *
- * This routine compares two ATAVs for equality. For two ATAVs to be
- * equal, the attribute types must be the same, and the attribute
- * values must have equal length and contents. The result of the
- * comparison will be stored at the location pointed to by the "equalp"
- * variable, which must point to a valid PRBool. This routine may
- * return PR_FAILURE upon error, in which case it will have created an
- * error stack.
- *
- * The error may be one of the following values:
- * NSS_ERROR_INVALID_ATAV
- * NSS_ERROR_INVALID_ARGUMENT
- *
- * Return value:
- * PR_FAILURE on error
- * PR_SUCCESS upon a successful comparison (equal or not)
- */
-
-NSS_IMPLEMENT PRStatus
-NSSATAV_Compare
-(
- NSSATAV *atav1,
- NSSATAV *atav2,
- PRBool *equalp
-)
-{
- nss_ClearErrorStack();
-
-#ifdef DEBUG
- if( PR_SUCCESS != nssATAV_verifyPointer(atav1) ) {
- return PR_FAILURE;
- }
-
- if( PR_SUCCESS != nssATAV_verifyPointer(atav2) ) {
- return PR_FAILURE;
- }
-
- if( (PRBool *)NULL == equalp ) {
- nss_SetError(NSS_ERROR_INVALID_ARGUMENT);
- return PR_FAILURE;
- }
-#endif /* DEBUG */
-
- return nssATAV_Compare(atav1, atav2, equalp);
-}
-
-/*
- * NSSATAV_Duplicate
- *
- * This routine duplicates the specified ATAV. If the optional arena
- * argument is non-null, the memory required will be obtained from
- * that arena; otherwise, the memory will be obtained from the heap.
- * This routine may return NULL upon error, in which case it will have
- * created an error stack.
- *
- * The error may be one of the following values:
- * NSS_ERROR_INVALID_ATAV
- * NSS_ERROR_NO_MEMORY
- *
- * Return value:
- * NULL on error
- * A pointer to a new ATAV
- */
-
-NSS_IMPLEMENT NSSATAV *
-NSSATAV_Duplicate
-(
- NSSATAV *atav,
- NSSArena *arenaOpt
-)
-{
- nss_ClearErrorStack();
-
-#ifdef DEBUG
- if( PR_SUCCESS != nssATAV_verifyPointer(atav) ) {
- return (NSSATAV *)NULL;
- }
-
- if( (NSSArena *)NULL != arenaOpt ) {
- if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
- return (NSSATAV *)NULL;
- }
- }
-#endif /* DEBUG */
-
- return nssATAV_Duplicate(atav, arenaOpt);
-}
-
-/*
- * The pointer-tracking code
- */
-
-#ifdef DEBUG
-extern const NSSError NSS_ERROR_INTERNAL_ERROR;
-
-static nssPointerTracker atav_pointer_tracker;
-
-static PRStatus
-atav_add_pointer
-(
- const NSSATAV *atav
-)
-{
- PRStatus rv;
-
- rv = nssPointerTracker_initialize(&atav_pointer_tracker);
- if( PR_SUCCESS != rv ) {
- return rv;
- }
-
- rv = nssPointerTracker_add(&atav_pointer_tracker, atav);
- if( PR_SUCCESS != rv ) {
- NSSError e = NSS_GetError();
- if( NSS_ERROR_NO_MEMORY != e ) {
- nss_SetError(NSS_ERROR_INTERNAL_ERROR);
- }
-
- return rv;
- }
-
- return PR_SUCCESS;
-}
-
-static PRStatus
-atav_remove_pointer
-(
- const NSSATAV *atav
-)
-{
- PRStatus rv;
-
- rv = nssPointerTracker_remove(&atav_pointer_tracker, atav);
- if( PR_SUCCESS != rv ) {
- nss_SetError(NSS_ERROR_INTERNAL_ERROR);
- }
-
- return rv;
-}
-
-/*
- * nssATAV_verifyPointer
- *
- * This method is only present in debug builds.
- *
- * If the specified pointer is a valid pointer to an NSSATAV object,
- * this routine will return PR_SUCCESS. Otherwise, it will put an
- * error on the error stack and return PR_FAILRUE.
- *
- * The error may be one of the following values:
- * NSS_ERROR_INVALID_NSSATAV
- * NSS_ERROR_NO_MEMORY
- *
- * Return value:
- * PR_SUCCESS if the pointer is valid
- * PR_FAILURE if it isn't
- */
-
-NSS_IMPLEMENT PRStatus
-nssATAV_verifyPointer
-(
- NSSATAV *atav
-)
-{
- PRStatus rv;
-
- rv = nssPointerTracker_initialize(&atav_pointer_tracker);
- if( PR_SUCCESS != rv ) {
- return PR_FAILURE;
- }
-
- rv = nssPointerTracker_verify(&atav_pointer_tracker, atav);
- if( PR_SUCCESS != rv ) {
- nss_SetError(NSS_ERROR_INVALID_ATAV);
- return PR_FAILURE;
- }
-
- return PR_SUCCESS;
-}
-#endif /* DEBUG */
-
-typedef struct {
- NSSBER oid;
- NSSBER value;
-} atav_holder;
-
-static const nssASN1Template nss_atav_template[] = {
- { nssASN1_SEQUENCE, 0, NULL, sizeof(atav_holder) },
- { nssASN1_OBJECT_ID, nsslibc_offsetof(atav_holder, oid), NULL, 0 },
- { nssASN1_ANY, nsslibc_offsetof(atav_holder, value), NULL, 0 },
- { 0, 0, NULL, 0 }
-};
-
-/*
- * There are several common attributes, with well-known type aliases
- * and value semantics. This table lists the ones we recognize.
- */
-
-struct nss_attribute_data_str {
- const NSSOID **oid;
- nssStringType stringType;
- PRUint32 minStringLength;
- PRUint32 maxStringLength; /* zero for no limit */
-};
-
-static const struct nss_attribute_data_str nss_attribute_data[] = {
- { &NSS_OID_X520_NAME,
- nssStringType_DirectoryString, 1, 32768 },
- { &NSS_OID_X520_COMMON_NAME,
- nssStringType_DirectoryString, 1, 64 },
- { &NSS_OID_X520_SURNAME,
- nssStringType_DirectoryString, 1, 40 },
- { &NSS_OID_X520_GIVEN_NAME,
- nssStringType_DirectoryString, 1, 16 },
- { &NSS_OID_X520_INITIALS,
- nssStringType_DirectoryString, 1, 5 },
- { &NSS_OID_X520_GENERATION_QUALIFIER,
- nssStringType_DirectoryString, 1, 3 },
- { &NSS_OID_X520_DN_QUALIFIER,
- nssStringType_PrintableString, 1, 0 },
- { &NSS_OID_X520_COUNTRY_NAME,
- nssStringType_PrintableString, 2, 2 },
- { &NSS_OID_X520_LOCALITY_NAME,
- nssStringType_DirectoryString, 1, 128 },
- { &NSS_OID_X520_STATE_OR_PROVINCE_NAME,
- nssStringType_DirectoryString, 1, 128 },
- { &NSS_OID_X520_ORGANIZATION_NAME,
- nssStringType_DirectoryString, 1, 64 },
- { &NSS_OID_X520_ORGANIZATIONAL_UNIT_NAME,
- nssStringType_DirectoryString, 1,
- /*
- * Note, draft #11 defines both "32" and "64" for this maximum,
- * in two separate places. Until it's settled, "conservative
- * in what you send." We're always liberal in what we accept.
- */
- 32 },
- { &NSS_OID_X520_TITLE,
- nssStringType_DirectoryString, 1, 64 },
- { &NSS_OID_RFC1274_EMAIL,
- nssStringType_PHGString, 1, 128 }
-};
-
-PRUint32 nss_attribute_data_quantity =
- (sizeof(nss_attribute_data)/sizeof(nss_attribute_data[0]));
-
-static nssStringType
-nss_attr_underlying_string_form
-(
- nssStringType type,
- void *data
-)
-{
- if( nssStringType_DirectoryString == type ) {
- PRUint8 tag = *(PRUint8 *)data;
- switch( tag & nssASN1_TAGNUM_MASK ) {
- case 20:
- /*
- * XXX fgmr-- we have to accept Latin-1 for Teletex; (see
- * below) but is T61 a suitable value for "Latin-1"?
- */
- return nssStringType_TeletexString;
- case 19:
- return nssStringType_PrintableString;
- case 28:
- return nssStringType_UniversalString;
- case 30:
- return nssStringType_BMPString;
- case 12:
- return nssStringType_UTF8String;
- default:
- return nssStringType_Unknown;
- }
- }
-
- return type;
-}
-
-
-/*
- * This routine decodes the attribute value, in a type-specific way.
- *
- */
-
-static NSSUTF8 *
-nss_attr_to_utf8
-(
- NSSArena *arenaOpt,
- const NSSOID *oid,
- NSSItem *item,
- nssStringType *stringForm
-)
-{
- NSSUTF8 *rv = (NSSUTF8 *)NULL;
- PRUint32 i;
- const struct nss_attribute_data_str *which =
- (struct nss_attribute_data_str *)NULL;
- PRUint32 len = 0;
-
- for( i = 0; i < nss_attribute_data_quantity; i++ ) {
- if( *(nss_attribute_data[ i ].oid) == oid ) {
- which = &nss_attribute_data[i];
- break;
- }
- }
-
- if( (struct nss_attribute_data_str *)NULL == which ) {
- /* Unknown OID. Encode it as hex. */
- PRUint8 *c;
- PRUint8 *d = (PRUint8 *)item->data;
- PRUint32 amt = item->size;
-
- if( item->size >= 0x7FFFFFFF ) {
- nss_SetError(NSS_ERROR_INVALID_STRING);
- return (NSSUTF8 *)NULL;
- }
-
- len = 1 + (item->size * 2) + 1; /* '#' + hex + '\0' */
- rv = (NSSUTF8 *)nss_ZAlloc(arenaOpt, len);
- if( (NSSUTF8 *)NULL == rv ) {
- return (NSSUTF8 *)NULL;
- }
-
- c = (PRUint8 *)rv;
- *c++ = '#'; /* XXX fgmr check this */
- while( amt > 0 ) {
- static char hex[16] = "0123456789ABCDEF";
- *c++ = hex[ ((*d) & 0xf0) >> 4 ];
- *c++ = hex[ ((*d) & 0x0f) ];
- }
-
- /* *c = '\0'; nss_ZAlloc, remember */
-
- *stringForm = nssStringType_Unknown; /* force exact comparison */
- } else {
- PRStatus status;
- rv = nssUTF8_CreateFromBER(arenaOpt, which->stringType,
- (NSSBER *)item);
-
- if( (NSSUTF8 *)NULL == rv ) {
- return (NSSUTF8 *)NULL;
- }
-
- len = nssUTF8_Length(rv, &status);
- if( PR_SUCCESS != status || len == 0 ) {
- nss_ZFreeIf(rv);
- return (NSSUTF8 *)NULL;
- }
-
- *stringForm = nss_attr_underlying_string_form(which->stringType,
- item->data);
- }
-
- return rv;
-}
-
-/*
- * nssATAV_CreateFromBER
- *
- * This routine creates an NSSATAV by decoding a BER- or DER-encoded
- * ATAV. If the optional arena argument is non-null, the memory used
- * will be obtained from that arena; otherwise, the memory will be
- * obtained from the heap. This routine may return NULL upon error,
- * in which case it will have set an error on the error stack.
- *
- * The error may be one of the following values:
- * NSS_ERROR_INVALID_BER
- * NSS_ERROR_NO_MEMORY
- *
- * Return value:
- * NULL upon error
- * A pointer to an NSSATAV upon success
- */
-
-NSS_IMPLEMENT NSSATAV *
-nssATAV_CreateFromBER
-(
- NSSArena *arenaOpt,
- const NSSBER *berATAV
-)
-{
- atav_holder holder;
- PRStatus status;
- NSSATAV *rv;
-
-#ifdef NSSDEBUG
- if( (NSSArena *)NULL != arenaOpt ) {
- if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
- return (NSSATAV *)NULL;
- }
- }
-
- /*
- * NSSBERs can be created by the user,
- * so no pointer-tracking can be checked.
- */
-
- if( (NSSBER *)NULL == berATAV ) {
- nss_SetError(NSS_ERROR_INVALID_BER);
- return (NSSATAV *)NULL;
- }
-
- if( (void *)NULL == berATAV->data ) {
- nss_SetError(NSS_ERROR_INVALID_BER);
- return (NSSATAV *)NULL;
- }
-#endif /* NSSDEBUG */
-
- status = nssASN1_DecodeBER(arenaOpt, &holder,
- nss_atav_template, berATAV);
- if( PR_SUCCESS != status ) {
- return (NSSATAV *)NULL;
- }
-
- rv = nss_ZNEW(arenaOpt, NSSATAV);
- if( (NSSATAV *)NULL == rv ) {
- nss_ZFreeIf(holder.oid.data);
- nss_ZFreeIf(holder.value.data);
- return (NSSATAV *)NULL;
- }
-
- rv->oid = nssOID_CreateFromBER(&holder.oid);
- if( (NSSOID *)NULL == rv->oid ) {
- nss_ZFreeIf(rv);
- nss_ZFreeIf(holder.oid.data);
- nss_ZFreeIf(holder.value.data);
- return (NSSATAV *)NULL;
- }
-
- nss_ZFreeIf(holder.oid.data);
-
- rv->ber.data = nss_ZAlloc(arenaOpt, berATAV->size);
- if( (void *)NULL == rv->ber.data ) {
- nss_ZFreeIf(rv);
- nss_ZFreeIf(holder.value.data);
- return (NSSATAV *)NULL;
- }
-
- rv->ber.size = berATAV->size;
- (void)nsslibc_memcpy(rv->ber.data, berATAV->data, berATAV->size);
-
- rv->value = nss_attr_to_utf8(arenaOpt, rv->oid, &holder.value,
- &rv->stringForm);
- if( (NSSUTF8 *)NULL == rv->value ) {
- nss_ZFreeIf(rv->ber.data);
- nss_ZFreeIf(rv);
- nss_ZFreeIf(holder.value.data);
- return (NSSATAV *)NULL;
- }
-
- nss_ZFreeIf(holder.value.data);
-
-#ifdef DEBUG
- if( PR_SUCCESS != atav_add_pointer(rv) ) {
- nss_ZFreeIf(rv->ber.data);
- nss_ZFreeIf(rv->value);
- nss_ZFreeIf(rv);
- return (NSSATAV *)NULL;
- }
-#endif /* DEBUG */
-
- return rv;
-}
-
-static PRBool
-nss_atav_utf8_string_is_hex
-(
- const NSSUTF8 *s
-)
-{
- /* All hex digits are ASCII, so this works */
- PRUint8 *p = (PRUint8 *)s;
-
- for( ; (PRUint8)0 != *p; p++ ) {
- if( (('0' <= *p) && (*p <= '9')) ||
- (('A' <= *p) && (*p <= 'F')) ||
- (('a' <= *p) && (*p <= 'f')) ) {
- continue;
- } else {
- return PR_FALSE;
- }
- }
-
- return PR_TRUE;
-}
-
-static NSSUTF8
-nss_atav_fromhex
-(
- NSSUTF8 *d
-)
-{
- NSSUTF8 rv;
-
- if( d[0] <= '9' ) {
- rv = (d[0] - '0') * 16;
- } else if( d[0] >= 'a' ) {
- rv = (d[0] - 'a' + 10) * 16;
- } else {
- rv = (d[0] - 'A' + 10);
- }
-
- if( d[1] <= '9' ) {
- rv += (d[1] - '0');
- } else if( d[1] >= 'a' ) {
- rv += (d[1] - 'a' + 10);
- } else {
- rv += (d[1] - 'A' + 10);
- }
-
- return rv;
-}
-
-/*
- * nssATAV_CreateFromUTF8
- *
- * This routine creates an NSSATAV by decoding a UTF8 string in the
- * "equals" format, e.g., "c=US." If the optional arena argument is
- * non-null, the memory used will be obtained from that arena;
- * otherwise, the memory will be obtained from the heap. This routine
- * may return NULL upon error, in which case it will have set an error
- * on the error stack.
- *
- * The error may be one of the following values:
- * NSS_ERROR_UNKNOWN_ATTRIBUTE
- * NSS_ERROR_INVALID_STRING
- * NSS_ERROR_NO_MEMORY
- *
- * Return value:
- * NULL upon error
- * A pointer to an NSSATAV upon success
- */
-
-extern const NSSError NSS_ERROR_INTERNAL_ERROR;
-
-NSS_IMPLEMENT NSSATAV *
-nssATAV_CreateFromUTF8
-(
- NSSArena *arenaOpt,
- const NSSUTF8 *stringATAV
-)
-{
- char *c;
- NSSUTF8 *type;
- NSSUTF8 *value;
- PRUint32 i;
- const NSSOID *oid = (NSSOID *)NULL;
- NSSATAV *rv;
- NSSItem xitem;
-
- xitem.data = (void *)NULL;
-
- for( c = (char *)stringATAV; '\0' != *c; c++ ) {
- if( '=' == *c ) {
-#ifdef PEDANTIC
- /*
- * Theoretically, one could have an '=' in an
- * attribute string alias. We don't, yet, though.
- */
- if( (char *)stringATAV == c ) {
- nss_SetError(NSS_ERROR_INVALID_STRING);
- return (NSSATAV *)NULL;
- } else {
- if( '\\' == c[-1] ) {
- continue;
- }
- }
-#endif /* PEDANTIC */
- break;
- }
- }
-
- if( '\0' == *c ) {
- nss_SetError(NSS_ERROR_INVALID_UTF8);
- return (NSSATAV *)NULL;
- } else {
- c++;
- value = (NSSUTF8 *)c;
- }
-
- i = ((NSSUTF8 *)c - stringATAV);
- type = (NSSUTF8 *)nss_ZAlloc((NSSArena *)NULL, i);
- if( (NSSUTF8 *)NULL == type ) {
- return (NSSATAV *)NULL;
- }
-
- (void)nsslibc_memcpy(type, stringATAV, i-1);
-
- c = (char *)stringATAV;
- if( (('0' <= *c) && (*c <= '9')) || ('#' == *c) ) {
- oid = nssOID_CreateFromUTF8(type);
- if( (NSSOID *)NULL == oid ) {
- nss_ZFreeIf(type);
- return (NSSATAV *)NULL;
- }
- } else {
- for( i = 0; i < nss_attribute_type_alias_count; i++ ) {
- PRStatus status;
- const nssAttributeTypeAliasTable *e = &nss_attribute_type_aliases[i];
- PRBool match = nssUTF8_CaseIgnoreMatch(type, e->alias, &status);
- if( PR_SUCCESS != status ) {
- nss_ZFreeIf(type);
- return (NSSATAV *)NULL;
- }
- if( PR_TRUE == match ) {
- oid = *(e->oid);
- break;
- }
- }
-
- if( (NSSOID *)NULL == oid ) {
- nss_ZFreeIf(type);
- nss_SetError(NSS_ERROR_UNKNOWN_ATTRIBUTE);
- return (NSSATAV *)NULL;
- }
- }
-
- nss_ZFreeIf(type);
- type = (NSSUTF8 *)NULL;
-
- rv = nss_ZNEW(arenaOpt, NSSATAV);
- if( (NSSATAV *)NULL == rv ) {
- return (NSSATAV *)NULL;
- }
-
- rv->oid = oid;
-
- if( '#' == *value ) { /* XXX fgmr.. was it '#'? or backslash? */
- PRUint32 size;
- PRUint32 len;
- NSSUTF8 *c;
- NSSUTF8 *d;
- PRStatus status;
- /* It's in hex */
-
- value++;
- if( PR_TRUE != nss_atav_utf8_string_is_hex(value) ) {
- (void)nss_ZFreeIf(rv);
- nss_SetError(NSS_ERROR_INVALID_STRING);
- return (NSSATAV *)NULL;
- }
-
- size = nssUTF8_Size(value, &status);
- if( PR_SUCCESS != status ) {
- /*
- * Only returns an error on bad pointer (nope) or string
- * too long. The defined limits for known attributes are
- * small enough to fit in PRUint32, and when undefined we
- * get to apply our own practical limits. Ergo, I say the
- * string is invalid.
- */
- (void)nss_ZFreeIf(rv);
- nss_SetError(NSS_ERROR_INVALID_STRING);
- return (NSSATAV *)NULL;
- }
-
- if( ((size-1) & 1) ) {
- /* odd length */
- (void)nss_ZFreeIf(rv);
- nss_SetError(NSS_ERROR_INVALID_STRING);
- return (NSSATAV *)NULL;
- }
-
- len = (size-1)/2;
-
- rv->value = (NSSUTF8 *)nss_ZAlloc(arenaOpt, len+1);
- if( (NSSUTF8 *)NULL == rv->value ) {
- (void)nss_ZFreeIf(rv);
- return (NSSATAV *)NULL;
- }
-
- xitem.size = len;
- xitem.data = (void *)rv->value;
-
- for( c = rv->value, d = value; len--; c++, d += 2 ) {
- *c = nss_atav_fromhex(d);
- }
-
- *c = 0;
- } else {
- PRStatus status;
- PRUint32 i, len;
- PRUint8 *s;
-
- /*
- * XXX fgmr-- okay, this is a little wasteful, and should
- * probably be abstracted out a bit. Later.
- */
-
- rv->value = nssUTF8_Duplicate(value, arenaOpt);
- if( (NSSUTF8 *)NULL == rv->value ) {
- (void)nss_ZFreeIf(rv);
- return (NSSATAV *)NULL;
- }
-
- len = nssUTF8_Size(rv->value, &status);
- if( PR_SUCCESS != status ) {
- (void)nss_ZFreeIf(rv->value);
- (void)nss_ZFreeIf(rv);
- return (NSSATAV *)NULL;
- }
-
- s = (PRUint8 *)rv->value;
- for( i = 0; i < len; i++ ) {
- if( '\\' == s[i] ) {
- (void)nsslibc_memcpy(&s[i], &s[i+1], len-i-1);
- }
- }
- }
-
- /* Now just BER-encode the baby and we're through.. */
- {
- const struct nss_attribute_data_str *which =
- (struct nss_attribute_data_str *)NULL;
- PRUint32 i;
- NSSArena *a;
- NSSDER *oidder;
- NSSItem *vitem;
- atav_holder ah;
- NSSDER *status;
-
- for( i = 0; i < nss_attribute_data_quantity; i++ ) {
- if( *(nss_attribute_data[ i ].oid) == rv->oid ) {
- which = &nss_attribute_data[i];
- break;
- }
- }
-
- a = NSSArena_Create();
- if( (NSSArena *)NULL == a ) {
- (void)nss_ZFreeIf(rv->value);
- (void)nss_ZFreeIf(rv);
- return (NSSATAV *)NULL;
- }
-
- oidder = nssOID_GetDEREncoding(rv->oid, (NSSDER *)NULL, a);
- if( (NSSDER *)NULL == oidder ) {
- (void)NSSArena_Destroy(a);
- (void)nss_ZFreeIf(rv->value);
- (void)nss_ZFreeIf(rv);
- return (NSSATAV *)NULL;
- }
-
- if( (struct nss_attribute_data_str *)NULL == which ) {
- /*
- * We'll just have to take the user data as an octet stream.
- */
- if( (void *)NULL == xitem.data ) {
- /*
- * This means that an ATTR entry has been added to oids.txt,
- * but no corresponding entry has been added to the array
- * ns_attribute_data[] above.
- */
- nss_SetError(NSS_ERROR_INTERNAL_ERROR);
- (void)NSSArena_Destroy(a);
- (void)nss_ZFreeIf(rv->value);
- (void)nss_ZFreeIf(rv);
- return (NSSATAV *)NULL;
- }
-
- vitem = nssASN1_EncodeItem(a, (NSSDER *)NULL, &xitem,
- nssASN1Template_OctetString, NSSASN1DER);
- if( (NSSItem *)NULL == vitem ) {
- (void)NSSArena_Destroy(a);
- (void)nss_ZFreeIf(rv->value);
- (void)nss_ZFreeIf(rv);
- return (NSSATAV *)NULL;
- }
-
- rv->stringForm = nssStringType_Unknown;
- } else {
- PRUint32 length = 0;
- PRStatus stat;
-
- length = nssUTF8_Length(rv->value, &stat);
- if( PR_SUCCESS != stat ) {
- (void)NSSArena_Destroy(a);
- (void)nss_ZFreeIf(rv->value);
- (void)nss_ZFreeIf(rv);
- return (NSSATAV *)NULL;
- }
-
- if( ((0 != which->minStringLength) &&
- (length < which->minStringLength)) ||
- ((0 != which->maxStringLength) &&
- (length > which->maxStringLength)) ) {
- nss_SetError(NSS_ERROR_INVALID_STRING);
- (void)NSSArena_Destroy(a);
- (void)nss_ZFreeIf(rv->value);
- (void)nss_ZFreeIf(rv);
- return (NSSATAV *)NULL;
- }
-
- vitem = nssUTF8_GetDEREncoding(a, which->stringType, rv->value);
- if( (NSSItem *)NULL == vitem ) {
- (void)NSSArena_Destroy(a);
- (void)nss_ZFreeIf(rv->value);
- (void)nss_ZFreeIf(rv);
- return (NSSATAV *)NULL;
- }
-
- if( nssStringType_DirectoryString == which->stringType ) {
- rv->stringForm = nssStringType_UTF8String;
- } else {
- rv->stringForm = which->stringType;
- }
- }
-
- ah.oid = *oidder;
- ah.value = *vitem;
-
- status = nssASN1_EncodeItem(arenaOpt, &rv->ber, &ah,
- nss_atav_template, NSSASN1DER);
-
- if( (NSSDER *)NULL == status ) {
- (void)NSSArena_Destroy(a);
- (void)nss_ZFreeIf(rv->value);
- (void)nss_ZFreeIf(rv);
- return (NSSATAV *)NULL;
- }
-
- (void)NSSArena_Destroy(a);
- }
-
- return rv;
-}
-
-/*
- * nssATAV_Create
- *
- * This routine creates an NSSATAV from the specified NSSOID and the
- * specified data. If the optional arena argument is non-null, the
- * memory used will be obtained from that arena; otherwise, the memory
- * will be obtained from the heap.If the specified data length is zero,
- * the data is assumed to be terminated by first zero byte; this allows
- * UTF8 strings to be easily specified. This routine may return NULL
- * upon error, in which case it will have set an error on the error
- * stack.
- *
- * The error may be one of the following values:
- * NSS_ERROR_INVALID_ARENA
- * NSS_ERROR_INVALID_NSSOID
- * NSS_ERROR_INVALID_POINTER
- * NSS_ERROR_NO_MEMORY
- *
- * Return value:
- * NULL upon error
- * A pointer to an NSSATAV upon success
- */
-
-NSS_IMPLEMENT NSSATAV *
-nssATAV_Create
-(
- NSSArena *arenaOpt,
- const NSSOID *oid,
- const void *data,
- PRUint32 length
-)
-{
-#ifdef NSSDEBUG
- if( (NSSArena *)NULL != arenaOpt ) {
- if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
- return (NSSATAV *)NULL;
- }
- }
-
- if( PR_SUCCESS != nssOID_verifyPointer(oid) ) {
- return (NSSATAV *)NULL;
- }
-
- if( (const void *)NULL == data ) {
- nss_SetError(NSS_ERROR_INVALID_POINTER);
- return (NSSATAV *)NULL;
- }
-#endif /* NSSDEBUG */
-
- /* XXX fgmr-- oops, forgot this one */
- return (NSSATAV *)NULL;
-}
-
-/*
- * nssATAV_Destroy
- *
- * This routine will destroy an ATAV object. It should eventually be
- * called on all ATAVs created without an arena. While it is not
- * necessary to call it on ATAVs created within an arena, it is not an
- * error to do so. This routine returns a PRStatus value; if
- * successful, it will return PR_SUCCESS. If unsuccessful, it will
- * set an error on the error stack and return PR_FAILURE.
- *
- * The error may be one of the following values:
- * NSS_ERROR_INVALID_ATAV
- *
- * Return value:
- * PR_FAILURE upon error
- * PR_SUCCESS upon success
- */
-
-NSS_IMPLEMENT PRStatus
-nssATAV_Destroy
-(
- NSSATAV *atav
-)
-{
-#ifdef NSSDEBUG
- if( PR_SUCCESS != nssATAV_verifyPointer(atav) ) {
- return PR_FAILURE;
- }
-#endif /* NSSDEBUG */
-
- (void)nss_ZFreeIf(atav->ber.data);
- (void)nss_ZFreeIf(atav->value);
-
-#ifdef DEBUG
- if( PR_SUCCESS != atav_remove_pointer(atav) ) {
- return PR_FAILURE;
- }
-#endif /* DEBUG */
-
- return PR_SUCCESS;
-}
-
-/*
- * nssATAV_GetDEREncoding
- *
- * This routine will DER-encode an ATAV object. If the optional arena
- * argument is non-null, the memory used will be obtained from that
- * arena; otherwise, the memory will be obtained from the heap. This
- * routine may return null upon error, in which case it will have set
- * an error on the error stack.
- *
- * The error may be one of the following values:
- * NSS_ERROR_INVALID_ATAV
- * NSS_ERROR_NO_MEMORY
- *
- * Return value:
- * NULL upon error
- * The DER encoding of this NSSATAV
- */
-
-NSS_IMPLEMENT NSSDER *
-nssATAV_GetDEREncoding
-(
- NSSATAV *atav,
- NSSArena *arenaOpt
-)
-{
- NSSDER *rv;
-
-#ifdef NSSDEBUG
- if( PR_SUCCESS != nssATAV_verifyPointer(atav) ) {
- return (NSSDER *)NULL;
- }
-#endif /* NSSDEBUG */
-
- rv = nss_ZNEW(arenaOpt, NSSDER);
- if( (NSSDER *)NULL == rv ) {
- return (NSSDER *)NULL;
- }
-
- rv->data = nss_ZAlloc(arenaOpt, atav->ber.size);
- if( (void *)NULL == rv->data ) {
- (void)nss_ZFreeIf(rv);
- return (NSSDER *)NULL;
- }
-
- rv->size = atav->ber.size;
- if( NULL == nsslibc_memcpy(rv->data, atav->ber.data, rv->size) ) {
- (void)nss_ZFreeIf(rv->data);
- (void)nss_ZFreeIf(rv);
- return (NSSDER *)NULL;
- }
-
- return rv;
-}
-
-/*
- * nssATAV_GetUTF8Encoding
- *
- * This routine returns a UTF8 string containing a string
- * representation of the ATAV in "equals" notation (e.g., "o=Acme").
- * If the optional arena argument is non-null, the memory used will be
- * obtained from that arena; otherwise, the memory will be obtained
- * from the heap. This routine may return null upon error, in which
- * case it will have set an error on the error stack.
- *
- * The error may be one of the following values:
- * NSS_ERROR_INVALID_ATAV
- * NSS_ERROR_NO_MEMORY
- *
- * Return value:
- * NULL upon error
- * A pointer to a UTF8 string containing the "equals" encoding of the
- * ATAV
- */
-
-NSS_IMPLEMENT NSSUTF8 *
-nssATAV_GetUTF8Encoding
-(
- NSSATAV *atav,
- NSSArena *arenaOpt
-)
-{
- NSSUTF8 *rv;
- PRUint32 i;
- const NSSUTF8 *alias = (NSSUTF8 *)NULL;
- NSSUTF8 *oid;
- NSSUTF8 *value;
- PRUint32 oidlen;
- PRUint32 valuelen;
- PRUint32 totallen;
- PRStatus status;
-
-#ifdef NSSDEBUG
- if( PR_SUCCESS != nssATAV_verifyPointer(atav) ) {
- return (NSSUTF8 *)NULL;
- }
-#endif /* NSSDEBUG */
-
- for( i = 0; i < nss_attribute_type_alias_count; i++ ) {
- if( *(nss_attribute_type_aliases[i].oid) == atav->oid ) {
- alias = nss_attribute_type_aliases[i].alias;
- break;
- }
- }
-
- if( (NSSUTF8 *)NULL == alias ) {
- oid = nssOID_GetUTF8Encoding(atav->oid, (NSSArena *)NULL);
- if( (NSSUTF8 *)NULL == oid ) {
- return (NSSUTF8 *)NULL;
- }
-
- oidlen = nssUTF8_Size(oid, &status);
- if( PR_SUCCESS != status ) {
- (void)nss_ZFreeIf(oid);
- return (NSSUTF8 *)NULL;
- }
- } else {
- oidlen = nssUTF8_Size(alias, &status);
- if( PR_SUCCESS != status ) {
- return (NSSUTF8 *)NULL;
- }
- oid = (NSSUTF8 *)NULL;
- }
-
- value = nssATAV_GetValue(atav, (NSSArena *)NULL);
- if( (NSSUTF8 *)NULL == value ) {
- (void)nss_ZFreeIf(oid);
- return (NSSUTF8 *)NULL;
- }
-
- valuelen = nssUTF8_Size(value, &status);
- if( PR_SUCCESS != status ) {
- (void)nss_ZFreeIf(value);
- (void)nss_ZFreeIf(oid);
- return (NSSUTF8 *)NULL;
- }
-
- totallen = oidlen + valuelen - 1 + 1;
- rv = (NSSUTF8 *)nss_ZAlloc(arenaOpt, totallen);
- if( (NSSUTF8 *)NULL == rv ) {
- (void)nss_ZFreeIf(value);
- (void)nss_ZFreeIf(oid);
- return (NSSUTF8 *)NULL;
- }
-
- if( (NSSUTF8 *)NULL == alias ) {
- if( (void *)NULL == nsslibc_memcpy(rv, oid, oidlen-1) ) {
- (void)nss_ZFreeIf(rv);
- (void)nss_ZFreeIf(value);
- (void)nss_ZFreeIf(oid);
- return (NSSUTF8 *)NULL;
- }
- } else {
- if( (void *)NULL == nsslibc_memcpy(rv, alias, oidlen-1) ) {
- (void)nss_ZFreeIf(rv);
- (void)nss_ZFreeIf(value);
- return (NSSUTF8 *)NULL;
- }
- }
-
- rv[ oidlen-1 ] = '=';
-
- if( (void *)NULL == nsslibc_memcpy(&rv[oidlen], value, valuelen) ) {
- (void)nss_ZFreeIf(rv);
- (void)nss_ZFreeIf(value);
- (void)nss_ZFreeIf(oid);
- return (NSSUTF8 *)NULL;
- }
-
- return rv;
-}
-
-/*
- * nssATAV_GetType
- *
- * This routine returns the NSSOID corresponding to the attribute type
- * in the specified ATAV. This routine may return NSS_OID_UNKNOWN
- * upon error, in which case it will have set an error on the error
- * stack.
- *
- * The error may be one of the following values:
- * NSS_ERROR_INVALID_ATAV
- *
- * Return value:
- * NSS_OID_UNKNOWN upon error
- * A valid NSSOID pointer upon success
- */
-
-NSS_IMPLEMENT const NSSOID *
-nssATAV_GetType
-(
- NSSATAV *atav
-)
-{
-#ifdef NSSDEBUG
- if( PR_SUCCESS != nssATAV_verifyPointer(atav) ) {
- return (NSSOID *)NULL;
- }
-#endif /* NSSDEBUG */
-
- return atav->oid;
-}
-
-/*
- * nssATAV_GetValue
- *
- * This routine returns a NSSUTF8 string containing the attribute value
- * in the specified ATAV. If the optional arena argument is non-null,
- * the memory used will be obtained from that arena; otherwise, the
- * memory will be obtained from the heap. This routine may return
- * NULL upon error, in which case it will have set an error upon the
- * error stack.
- *
- * The error may be one of the following values:
- * NSS_ERROR_INVALID_ATAV
- * NSS_ERROR_NO_MEMORY
- *
- * Return value:
- * NULL upon error
- * A pointer to an NSSItem containing the attribute value.
- */
-
-NSS_IMPLEMENT NSSUTF8 *
-nssATAV_GetValue
-(
- NSSATAV *atav,
- NSSArena *arenaOpt
-)
-{
-#ifdef NSSDEBUG
- if( PR_SUCCESS != nssATAV_verifyPointer(atav) ) {
- return (NSSUTF8 *)NULL;
- }
-#endif /* NSSDEBUG */
-
- return nssUTF8_Duplicate(atav->value, arenaOpt);
-}
-
-/*
- * nssATAV_Compare
- *
- * This routine compares two ATAVs for equality. For two ATAVs to be
- * equal, the attribute types must be the same, and the attribute
- * values must have equal length and contents. The result of the
- * comparison will be stored at the location pointed to by the "equalp"
- * variable, which must point to a valid PRBool. This routine may
- * return PR_FAILURE upon error, in which case it will have set an
- * error on the error stack.
- *
- * The error may be one of the following values:
- * NSS_ERROR_INVALID_ATAV
- * NSS_ERROR_INVALID_ARGUMENT
- *
- * Return value:
- * PR_FAILURE on error
- * PR_SUCCESS upon a successful comparison (equal or not)
- */
-
-NSS_IMPLEMENT PRStatus
-nssATAV_Compare
-(
- NSSATAV *atav1,
- NSSATAV *atav2,
- PRBool *equalp
-)
-{
- nssStringType comparison;
- PRUint32 len1;
- PRUint32 len2;
- PRStatus status;
-
-#ifdef DEBUG
- if( PR_SUCCESS != nssATAV_verifyPointer(atav1) ) {
- return PR_FAILURE;
- }
-
- if( PR_SUCCESS != nssATAV_verifyPointer(atav2) ) {
- return PR_FAILURE;
- }
-
- if( (PRBool *)NULL == equalp ) {
- nss_SetError(NSS_ERROR_INVALID_ARGUMENT);
- return PR_FAILURE;
- }
-#endif /* DEBUG */
-
- if( atav1->oid != atav2->oid ) {
- *equalp = PR_FALSE;
- return PR_SUCCESS;
- }
-
- if( atav1->stringForm != atav2->stringForm ) {
- if( (nssStringType_PrintableString == atav1->stringForm) ||
- (nssStringType_PrintableString == atav2->stringForm) ) {
- comparison = nssStringType_PrintableString;
- } else if( (nssStringType_PHGString == atav1->stringForm) ||
- (nssStringType_PHGString == atav2->stringForm) ) {
- comparison = nssStringType_PHGString;
- } else {
- comparison = atav1->stringForm;
- }
- } else {
- comparison = atav1->stringForm;
- }
-
- switch( comparison ) {
- case nssStringType_DirectoryString:
- nss_SetError(NSS_ERROR_INTERNAL_ERROR);
- return PR_FAILURE;
- case nssStringType_TeletexString:
- break;
- case nssStringType_PrintableString:
- *equalp = nssUTF8_PrintableMatch(atav1->value, atav2->value, &status);
- return status;
- /* Case-insensitive, with whitespace reduction */
- break;
- case nssStringType_UniversalString:
- break;
- case nssStringType_BMPString:
- break;
- case nssStringType_GeneralString:
- /* what to do here? */
- break;
- case nssStringType_UTF8String:
- break;
- case nssStringType_PHGString:
- /* Case-insensitive (XXX fgmr, actually see draft-11 pg. 21) */
- *equalp = nssUTF8_CaseIgnoreMatch(atav1->value, atav2->value, &status);
- return status;
- case nssStringType_Unknown:
- break;
- }
-
- len1 = nssUTF8_Size(atav1->value, &status);
- if( PR_SUCCESS != status ) {
- return PR_FAILURE;
- }
-
- len2 = nssUTF8_Size(atav2->value, &status);
- if( PR_SUCCESS != status ) {
- return PR_FAILURE;
- }
-
- if( len1 != len2 ) {
- *equalp = PR_FALSE;
- return PR_SUCCESS;
- }
-
- *equalp = nsslibc_memequal(atav1->value, atav2->value, len1, &status);
- return status;
-}
-
-
-/*
- * nssATAV_Duplicate
- *
- * This routine duplicates the specified ATAV. If the optional arena
- * argument is non-null, the memory required will be obtained from
- * that arena; otherwise, the memory will be obtained from the heap.
- * This routine may return NULL upon error, in which case it will have
- * placed an error on the error stack.
- *
- * The error may be one of the following values:
- * NSS_ERROR_INVALID_ATAV
- * NSS_ERROR_NO_MEMORY
- *
- * Return value:
- * NULL on error
- * A pointer to a new ATAV
- */
-
-NSS_IMPLEMENT NSSATAV *
-nssATAV_Duplicate
-(
- NSSATAV *atav,
- NSSArena *arenaOpt
-)
-{
- NSSATAV *rv;
-
-#ifdef NSSDEBUG
- if( PR_SUCCESS != nssATAV_verifyPointer(atav) ) {
- return (NSSATAV *)NULL;
- }
-
- if( (NSSArena *)NULL != arenaOpt ) {
- if( PR_SUCCESS != nssArena_verifyPointer(arenaOpt) ) {
- return (NSSATAV *)NULL;
- }
- }
-#endif /* NSSDEBUG */
-
- rv = nss_ZNEW(arenaOpt, NSSATAV);
- if( (NSSATAV *)NULL == rv ) {
- return (NSSATAV *)NULL;
- }
-
- rv->oid = atav->oid;
- rv->stringForm = atav->stringForm;
- rv->value = nssUTF8_Duplicate(atav->value, arenaOpt);
- if( (NSSUTF8 *)NULL == rv->value ) {
- (void)nss_ZFreeIf(rv);
- return (NSSATAV *)NULL;
- }
-
- rv->ber.data = nss_ZAlloc(arenaOpt, atav->ber.size);
- if( (void *)NULL == rv->ber.data ) {
- (void)nss_ZFreeIf(rv->value);
- (void)nss_ZFreeIf(rv);
- return (NSSATAV *)NULL;
- }
-
- rv->ber.size = atav->ber.size;
- if( NULL == nsslibc_memcpy(rv->ber.data, atav->ber.data,
- atav->ber.size) ) {
- (void)nss_ZFreeIf(rv->ber.data);
- (void)nss_ZFreeIf(rv->value);
- (void)nss_ZFreeIf(rv);
- return (NSSATAV *)NULL;
- }
-
- return rv;
-}