/* * Copyright (c) 2003 Apple Computer, Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). * You may not use this file except in compliance with the License. Please obtain * a copy of the License at http://www.apple.com/publicsource and read it before * using this file. * * This Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the * specific language governing rights and limitations under the License. */ /* * clNameUtils.cpp - support for Name, GeneralizedName, all sorts of names */ #include "clNameUtils.h" #include "clNssUtils.h" #include "cldebugging.h" #include #pragma mark ----- NSS_Name <--> CSSM_X509_NAME ----- /* * NSS_ATV --> CSSM_X509_TYPE_VALUE_PAIR */ void CL_nssAtvToCssm( const NSS_ATV &nssObj, CSSM_X509_TYPE_VALUE_PAIR &cssmObj, CssmAllocator &alloc) { /* tag and decoded data */ cssmObj.valueType = nssObj.value.tag; clAllocCopyData(alloc, nssObj.value.item, cssmObj.value); /* the OID */ clAllocCopyData(alloc, nssObj.type, cssmObj.type); } /* NSS_RDN --> CSSM_X509_RDN */ void CL_nssRdnToCssm( const NSS_RDN &nssObj, CSSM_X509_RDN &cssmObj, CssmAllocator &alloc, SecNssCoder &coder) // conversion requires further decoding { memset(&cssmObj, 0, sizeof(cssmObj)); unsigned numAtvs = clNssArraySize((const void **)nssObj.atvs); if(numAtvs == 0) { return; } size_t len = numAtvs * sizeof(CSSM_X509_TYPE_VALUE_PAIR); cssmObj.AttributeTypeAndValue = (CSSM_X509_TYPE_VALUE_PAIR_PTR)alloc.malloc(len); cssmObj.numberOfPairs = numAtvs; CSSM_X509_TYPE_VALUE_PAIR_PTR cssmAtvs = cssmObj.AttributeTypeAndValue; memset(cssmAtvs, 0, len); for(unsigned dex=0; dex CSSM_X509_NAME */ void CL_nssNameToCssm( const NSS_Name &nssObj, CSSM_X509_NAME &cssmObj, CssmAllocator &alloc) { memset(&cssmObj, 0, sizeof(cssmObj)); unsigned numRdns = clNssArraySize((const void **)nssObj.rdns); if(numRdns == 0) { /* not technically an error */ return; } size_t len = numRdns * sizeof(CSSM_X509_RDN); cssmObj.RelativeDistinguishedName = (CSSM_X509_RDN_PTR)alloc.malloc(len); cssmObj.numberOfRDNs = numRdns; CSSM_X509_RDN_PTR cssmRdns = cssmObj.RelativeDistinguishedName; memset(cssmRdns, 0, len); SecNssCoder coder; // conversion requires further decoding for(unsigned dex=0; dex NSS_ATV */ void CL_cssmAtvToNss( const CSSM_X509_TYPE_VALUE_PAIR &cssmObj, NSS_ATV &nssObj, SecNssCoder &coder) { memset(&nssObj, 0, sizeof(nssObj)); /* copy the OID */ coder.allocCopyItem(cssmObj.type, nssObj.type); /* tag and value */ nssObj.value.tag = cssmObj.valueType; coder.allocCopyItem(cssmObj.value, nssObj.value.item); } /* CSSM_X509_RDN --> NSS_RDN */ void CL_cssmRdnToNss( const CSSM_X509_RDN &cssmObj, NSS_RDN &nssObj, SecNssCoder &coder) { memset(&nssObj, 0, sizeof(nssObj)); /* alloc NULL-terminated array of ATV pointers */ unsigned numAtvs = cssmObj.numberOfPairs; unsigned size = (numAtvs + 1) * sizeof(void *); nssObj.atvs = (NSS_ATV **)coder.malloc(size); memset(nssObj.atvs, 0, size); /* grind thru the elements */ for(unsigned atvDex=0; atvDex NSS_Name */ void CL_cssmNameToNss( const CSSM_X509_NAME &cssmObj, NSS_Name &nssObj, SecNssCoder &coder) { memset(&nssObj, 0, sizeof(nssObj)); /* alloc NULL-terminated array of RDN pointers */ unsigned numRdns = cssmObj.numberOfRDNs; nssObj.rdns = (NSS_RDN **)clNssNullArray(numRdns, coder); /* grind thru the elements */ for(unsigned rdnDex=0; rdnDexatvs); if(numAttrs == 0) { clFieldLog("clNormalizeX509Name: zero numAttrs at index %d", rdnDex); continue; } /* descend into array of attribute/values */ for(unsigned attrDex=0; attrDexatvs[attrDex]; assert(attr != NULL); /* * attr->value is an ASN_ANY containing an encoded * string. We only normalize Prinatable String types. * If we find one, decode it, normalize it, encode the * result, and put the encoding back in attr->value. * We temporarily "leak" the original string, which only * has a lifetime of the incoming SecNssCoder. */ NSS_TaggedItem &attrVal = attr->value; if(attrVal.tag != SEC_ASN1_PRINTABLE_STRING) { /* skip it */ continue; } /* normalize */ char *strPtr = (char *)attrVal.item.Data; int newLen = attrVal.item.Length; CL_normalizeString(strPtr, newLen); /* possible length adjustment */ attrVal.item.Length = newLen; } /* for each attribute/value */ } /* for each RDN */ } #pragma mark ----- CE_GeneralNames <--> NSS_GeneralNames ----- void CL_nssGeneralNameToCssm( NSS_GeneralName &nssObj, CE_GeneralName &cdsaObj, SecNssCoder &coder, // for temp decoding CssmAllocator &alloc) // destination { memset(&cdsaObj, 0, sizeof(cdsaObj)); PRErrorCode prtn; /* for caller's CE_GeneralName */ CSSM_BOOL berEncoded = CSSM_FALSE; CE_GeneralNameType cdsaTag; /* * At this point, depending on the decoded object's tag, we either * have the final bytes to copy out, or we need to decode further. * After this switch, if doCopy is true, give the caller a copy * of nssObj.item. */ bool doCopy = true; switch(nssObj.tag) { case NGT_OtherName: // ASN_ANY -> CE_OtherName { cdsaTag = GNT_OtherName; /* decode to coder memory */ CE_OtherName *nssOther = (CE_OtherName *)coder.malloc(sizeof(CE_OtherName)); memset(nssOther, 0, sizeof(CE_OtherName)); prtn = coder.decodeItem(nssObj.item, NSS_GenNameOtherNameTemplate, nssOther); if(prtn) { clErrorLog("CL_nssGeneralNameToCssm: error decoding " "OtherName\n"); CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); } /* copy out to caller */ clAllocData(alloc, cdsaObj.name, sizeof(CE_OtherName)); clCopyOtherName(*nssOther, *((CE_OtherName *)cdsaObj.name.Data), alloc); doCopy = false; break; } case NGT_RFC822Name: // IA5String, done cdsaTag = GNT_RFC822Name; break; case NGT_DNSName: // IA5String cdsaTag = GNT_DNSName; break; case NGT_X400Address: // ASY_ANY, leave alone cdsaTag = GNT_X400Address; berEncoded = CSSM_TRUE; break; case NGT_DirectoryName: // ASN_ANY --> NSS_Name { cdsaTag = GNT_DirectoryName; /* Decode to coder memory */ NSS_Name *nssName = (NSS_Name *)coder.malloc(sizeof(NSS_Name)); memset(nssName, 0, sizeof(NSS_Name)); prtn = coder.decodeItem(nssObj.item, NSS_NameTemplate, nssName); if(prtn) { clErrorLog("CL_nssGeneralNameToCssm: error decoding " "NSS_Name\n"); CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); } /* convert & copy out to caller */ clAllocData(alloc, cdsaObj.name, sizeof(CSSM_X509_NAME)); CL_nssNameToCssm(*nssName, *((CSSM_X509_NAME *)cdsaObj.name.Data), alloc); doCopy = false; break; } case NGT_EdiPartyName: // ASN_ANY, leave alone cdsaTag = GNT_EdiPartyName; berEncoded = CSSM_TRUE; break; case NGT_URI: // IA5String cdsaTag = GNT_URI; break; case NGT_IPAddress: // OCTET_STRING cdsaTag = GNT_IPAddress; break; case NGT_RegisteredID: // OID cdsaTag = GNT_RegisteredID; break; default: clErrorLog("CL_nssGeneralNameToCssm: bad name tag\n"); CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT); } cdsaObj.nameType = cdsaTag; cdsaObj.berEncoded = berEncoded; if(doCopy) { clAllocCopyData(alloc, nssObj.item, cdsaObj.name); } } void CL_nssGeneralNamesToCssm( const NSS_GeneralNames &nssObj, CE_GeneralNames &cdsaObj, SecNssCoder &coder, // for temp decoding CssmAllocator &alloc) // destination { memset(&cdsaObj, 0, sizeof(cdsaObj)); unsigned numNames = clNssArraySize((const void **)nssObj.names); if(numNames == 0) { return; } /* * Decode each name element, currently a raw ASN_ANY blob. * Then convert each result into CDSA form. * This array of (NSS_GeneralName)s is temporary, it doesn't * persist outside of this routine other than the fact that it's * mallocd by the coder arena pool. */ NSS_GeneralName *names = (NSS_GeneralName *)coder.malloc(sizeof(NSS_GeneralName) * numNames); memset(names, 0, sizeof(NSS_GeneralName) * numNames); cdsaObj.generalName = (CE_GeneralName *)alloc.malloc( sizeof(CE_GeneralName) * numNames); cdsaObj.numNames = numNames; for(unsigned dex=0; dexnumNames; i++) { /* * Two special cases here. */ CE_GeneralName *genName = &cdsaObj->generalName[i]; switch(genName->nameType) { case GNT_DirectoryName: if((!genName->berEncoded) && // we're flexible (genName->name.Length == sizeof(CSSM_X509_NAME))) { // paranoia CL_freeX509Name((CSSM_X509_NAME_PTR)genName->name.Data, alloc); } break; case GNT_OtherName: if((!genName->berEncoded) && // we're flexible (genName->name.Length == sizeof(CE_OtherName))) { // paranoia CE_OtherName *con = (CE_OtherName *)genName->name.Data; CL_freeOtherName(con, alloc); } break; default: break; } /* and always free this */ alloc.free(cdsaObj->generalName[i].name.Data); } if(cdsaObj->numNames) { memset(cdsaObj->generalName, 0, cdsaObj->numNames * sizeof(CE_GeneralName)); alloc.free(cdsaObj->generalName); } memset(cdsaObj, 0, sizeof(CE_GeneralNames)); } void CL_freeCssmDistPoints( CE_CRLDistPointsSyntax *cssmDps, CssmAllocator &alloc) { if(cssmDps == NULL) { return; } for(unsigned dex=0; dexnumDistPoints; dex++) { CE_CRLDistributionPoint *cssmDp = &cssmDps->distPoints[dex]; if(cssmDp->distPointName) { CL_freeCssmDistPointName(cssmDp->distPointName, alloc); alloc.free(cssmDp->distPointName); } if(cssmDp->crlIssuer) { CL_freeCssmGeneralNames(cssmDp->crlIssuer, alloc); alloc.free(cssmDp->crlIssuer); } } memset(cssmDps->distPoints, 0, cssmDps->numDistPoints * sizeof(CE_CRLDistributionPoint)); alloc.free(cssmDps->distPoints); memset(cssmDps, 0, sizeof(*cssmDps)); } void CL_freeCssmDistPointName( CE_DistributionPointName *cssmDpn, CssmAllocator &alloc) { if(cssmDpn == NULL) { return; } switch(cssmDpn->nameType) { case CE_CDNT_FullName: CL_freeCssmGeneralNames(cssmDpn->fullName, alloc); alloc.free(cssmDpn->fullName); break; case CE_CDNT_NameRelativeToCrlIssuer: CL_freeX509Rdn(cssmDpn->rdn, alloc); alloc.free(cssmDpn->rdn); break; } memset(cssmDpn, 0, sizeof(*cssmDpn)); } /* free contents of an CSSM_X509_NAME */ void CL_freeX509Name( CSSM_X509_NAME_PTR x509Name, CssmAllocator &alloc) { if(x509Name == NULL) { return; } for(unsigned rdnDex=0; rdnDexnumberOfRDNs; rdnDex++) { CSSM_X509_RDN_PTR rdn = &x509Name->RelativeDistinguishedName[rdnDex]; CL_freeX509Rdn(rdn, alloc); } alloc.free(x509Name->RelativeDistinguishedName); memset(x509Name, 0, sizeof(CSSM_X509_NAME)); } void CL_freeX509Rdn( CSSM_X509_RDN_PTR rdn, CssmAllocator &alloc) { if(rdn == NULL) { return; } for(unsigned atvDex=0; atvDexnumberOfPairs; atvDex++) { CSSM_X509_TYPE_VALUE_PAIR_PTR atv = &rdn->AttributeTypeAndValue[atvDex]; alloc.free(atv->type.Data); alloc.free(atv->value.Data); memset(atv, 0, sizeof(CSSM_X509_TYPE_VALUE_PAIR)); } alloc.free(rdn->AttributeTypeAndValue); memset(rdn, 0, sizeof(CSSM_X509_RDN)); } void CL_freeOtherName( CE_OtherName *cssmOther, CssmAllocator &alloc) { if(cssmOther == NULL) { return; } alloc.free(cssmOther->typeId.Data); alloc.free(cssmOther->value.Data); memset(cssmOther, 0, sizeof(*cssmOther)); } void CL_freeCssmIssuingDistPoint( CE_IssuingDistributionPoint *cssmIdp, CssmAllocator &alloc) { CL_freeCssmDistPointName(cssmIdp->distPointName, alloc); }