/*----------------------------------------------------------------------- * File: ACC_CRED.C * * Copyright (c) 1995-2000 Intel Corporation. All rights reserved. *----------------------------------------------------------------------- */ /* This file contains utility functions which can be used to copy and delete * CSSM_ACCESS_CREDENTIAL structures. */ #if defined(POSIX) || VMS /* Include this file here to resolve header include order problems if * pthread.h is not the first file included. */ #include #else #if defined WIN32 #pragma warning (disable:4201 4514 4214 4115) #include "windows.h" #pragma warning (default:4201 4214 4115) #endif /* WIN32 */ #endif /* POSIX */ /* standard includes */ #include #include #include #include #ifdef VMS #include #endif /* CDSA includes */ #include "cssmtype.h" #include "cssmerr.h" #include "cssmport.h" #include "cssmutil.h" /* memory tracking inclusion - will be removed when possible */ #include "cssmMemTrack.h" /* trace routines/definitions */ #include "trc_util.h" #include "codefile.h" /* This function frees all of the certs contained within a CSSM_CERTGROUP but does not free the top level structure. */ CSSM_RETURN CSSMAPI cssmutil_CleanCertGroup(CSSM_CERTGROUP_PTR CertGroup, CSSM_FREE free_func, void *mem_ref) { CSSM_RETURN err = CSSM_OK; if(NULL == CertGroup) { ERR(err = CSSMERR_CSSM_INVALID_POINTER); } else { switch(CertGroup->CertGroupType) { case CSSM_CERTGROUP_DATA: { ERR(err = cssmutil_FreeDataCertList(CertGroup->NumCerts, &CertGroup->GroupList.CertList, free_func, mem_ref)); } break; case CSSM_CERTGROUP_ENCODED_CERT: { ERR(err = cssmutil_FreeEncodedCertList(CertGroup->NumCerts, &CertGroup->GroupList.EncodedCertList, free_func, mem_ref)); } break; case CSSM_CERTGROUP_PARSED_CERT: { ERR(err = cssmutil_FreeParsedCertList(CertGroup->NumCerts, &CertGroup->GroupList.ParsedCertList, free_func, mem_ref)); } break; case CSSM_CERTGROUP_CERT_PAIR: { ERR(err = cssmutil_FreePairCertList(CertGroup->NumCerts, &CertGroup->GroupList.PairCertList, free_func, mem_ref)); } break; default: { ERR(err = CSSMERR_CSSM_INVALID_ATTRIBUTE); } break; } if(CSSM_OK == err) { CertGroup->NumCerts = 0; CertGroup->GroupList.CertList = NULL; } } return err; } CSSM_RETURN CSSMAPI cssmutil_FreeDataCertList(uint32 NumCerts, CSSM_DATA_PTR *CertList, CSSM_FREE free_func, void *mem_ref) { CSSM_RETURN err = CSSM_OK; CSSM_DATA_PTR CurrentCert; uint32 i; if( NumCerts != 0) { if((NULL == CertList) || (NULL == *CertList)) { ERR(err = CSSMERR_CSSM_INVALID_POINTER); } else { CurrentCert = *CertList; for(i = 0; i < NumCerts; i++) { if( (NULL != CurrentCert[i].Data ) && (0 != CurrentCert[i].Length) ) { CSSM_FREE_WRAPPER(free_func,CurrentCert[i].Data, mem_ref); } } CSSM_FREE_WRAPPER(free_func,CurrentCert, mem_ref); *CertList = NULL; } } return err; } CSSM_RETURN CSSMAPI cssmutil_FreeEncodedCertList(uint32 NumCerts, CSSM_ENCODED_CERT_PTR *EncodedCertList, CSSM_FREE free_func, void *mem_ref) { CSSM_RETURN err = CSSM_OK; CSSM_ENCODED_CERT_PTR CurrentCert; uint32 i; if( NumCerts != 0) { if((NULL == EncodedCertList) || (NULL == *EncodedCertList)) { ERR(err = CSSMERR_CSSM_INVALID_POINTER); } else { CurrentCert = *EncodedCertList; for(i = 0; i < NumCerts; i++) { if( (NULL != CurrentCert[i].CertBlob.Data) && (0 != CurrentCert[i].CertBlob.Length) ) { CSSM_FREE_WRAPPER(free_func,CurrentCert[i].CertBlob.Data, mem_ref); } } CSSM_FREE_WRAPPER(free_func,CurrentCert, mem_ref); *EncodedCertList = NULL; } } return err; } CSSM_RETURN CSSMAPI cssmutil_FreeParsedCertList(uint32 NumCerts, CSSM_PARSED_CERT_PTR *ParsedCertList, CSSM_FREE free_func, void *mem_ref) { CSSM_RETURN err; ERR(err = CSSMERR_CSSM_FUNCTION_NOT_IMPLEMENTED); return err; } CSSM_RETURN CSSMAPI cssmutil_FreePairCertList(uint32 NumCerts, CSSM_CERT_PAIR_PTR *PairCertList, CSSM_FREE free_func, void *mem_ref) { CSSM_RETURN err; ERR(err = CSSMERR_CSSM_FUNCTION_NOT_IMPLEMENTED); return err; } CSSM_RETURN CSSMAPI cssmutil_FreeCSSMSamples(uint32 NumberOfSamples, CSSM_SAMPLE_PTR *SamplesToFree, CSSM_FREE free_func, void *mem_ref) { CSSM_RETURN err = CSSM_OK; uint32 i; if( NumberOfSamples != 0 ) { if((NULL == SamplesToFree) || ((NULL == *SamplesToFree) && (0 != NumberOfSamples))) { ERR(err = CSSMERR_CSSM_INVALID_POINTER); } else { i = 0; while((i < NumberOfSamples) && (CSSM_OK == err)) { /* if there's a list in this sample, free it */ if(NULL != (*SamplesToFree)[i].TypedSample.Head) { ERR(err = cssmutil_FreeCSSMListElements(&((*SamplesToFree)[i].TypedSample.Head), free_func, mem_ref)); } /* if there's a verifier, free it */ if(NULL != (*SamplesToFree)[i].Verifier) { CSSM_FREE_WRAPPER(free_func,(CSSM_GUID*)(*SamplesToFree)[i].Verifier, mem_ref); } i++; } /* now we free the entire sample list */ CSSM_FREE_WRAPPER(free_func,(*SamplesToFree), mem_ref); } } return err; } CSSM_RETURN CSSMAPI cssmutil_FreeCSSMListElements(CSSM_LIST_ELEMENT_PTR *HeadPtr, CSSM_FREE free_func, void *mem_ref) { CSSM_RETURN err = CSSM_OK; CSSM_LIST_ELEMENT_PTR NextElemPtr = NULL; CSSM_LIST_ELEMENT_PTR CurrentElemPtr = NULL; if((NULL == HeadPtr) || (NULL == *HeadPtr)) { ERR(err = CSSMERR_CSSM_INVALID_POINTER); } else { NextElemPtr = *HeadPtr; while((CSSM_OK == err) && (NULL != NextElemPtr)) { CurrentElemPtr = NextElemPtr; NextElemPtr = CurrentElemPtr->NextElement; switch(CurrentElemPtr->ElementType) { case CSSM_LIST_ELEMENT_DATUM: { /* We just free the data contained in the CSSM_DATA */ if( (NULL != CurrentElemPtr->Element.Word.Data) && (0 != CurrentElemPtr->Element.Word.Length ) ) { CSSM_FREE_WRAPPER(free_func,CurrentElemPtr->Element.Word.Data, mem_ref); } } break; case CSSM_LIST_ELEMENT_SUBLIST: { /* We have to recurse through the sublist to free up the memory contained there. After that there's nothing left for this case - we just have to free our current element. */ ERR(err = cssmutil_FreeCSSMListElements(&CurrentElemPtr->Element.Sublist.Head, free_func, mem_ref)); } break; case CSSM_LIST_ELEMENT_WORDID: { /* We just clear this field out. There's no memory associated that we need to free. */ CurrentElemPtr->WordID = 0; } break; default: { /* no clue what this input really is, but it's an error */ ERR(err = CSSMERR_CSSM_INVALID_ATTRIBUTE); } break; } /* now we free the current element */ CSSM_FREE_WRAPPER(free_func,CurrentElemPtr, mem_ref); } } return err; } CSSM_RETURN CSSMAPI cssmutil_DuplicateAccessCredentials(const CSSM_ACCESS_CREDENTIALS *SrcCred, CSSM_MALLOC malloc_func, CSSM_FREE free_func, void *mem_ref, CSSM_ACCESS_CREDENTIALS_PTR *DestCred) { CSSM_RETURN err = CSSM_OK; if((NULL == SrcCred) || (NULL == DestCred)) { ERR(err = CSSMERR_CSSM_INVALID_POINTER); } else { *DestCred = CSSM_MALLOC_WRAPPER(malloc_func,sizeof(CSSM_ACCESS_CREDENTIALS), mem_ref); if(NULL == *DestCred) { ERR(err = CSSMERR_CSSM_MEMORY_ERROR); } else { memcpy((*DestCred)->EntryTag, SrcCred->EntryTag, sizeof(CSSM_STRING)); (*DestCred)->Callback = SrcCred->Callback; (*DestCred)->CallerCtx = SrcCred->CallerCtx; ERR(err = cssmutil_DuplicateBaseCerts(&(SrcCred->BaseCerts), malloc_func, free_func, mem_ref, &((*DestCred)->BaseCerts))); if(CSSM_OK == err) { ERR(err = cssmutil_DuplicateSampleGroup(&(SrcCred->Samples), malloc_func, free_func, mem_ref, &((*DestCred)->Samples))); } if(CSSM_OK != err) { CSSM_FREE_WRAPPER(free_func,(*DestCred), mem_ref); (*DestCred) = NULL; } } } return err; } CSSM_RETURN CSSMAPI cssmutil_DuplicateBaseCerts(const CSSM_BASE_CERTS *SrcCerts, CSSM_MALLOC malloc_func, CSSM_FREE free_func, void *mem_ref, CSSM_BASE_CERTS_PTR DestCerts) { CSSM_RETURN err = CSSM_OK; if((NULL == SrcCerts) || (NULL == DestCerts)) { ERR(err = CSSMERR_CSSM_INVALID_POINTER); } else { DestCerts->TPHandle = SrcCerts->TPHandle; DestCerts->CLHandle = SrcCerts->CLHandle; DestCerts->Certs.CertGroupType = SrcCerts->Certs.CertGroupType; DestCerts->Certs.CertEncoding = SrcCerts->Certs.CertEncoding; DestCerts->Certs.NumCerts = SrcCerts->Certs.NumCerts; DestCerts->Certs.CertType = SrcCerts->Certs.CertType; DestCerts->Certs.Reserved = SrcCerts->Certs.Reserved; switch(SrcCerts->Certs.CertGroupType) { case CSSM_CERTGROUP_DATA: { ERR(err = cssmutil_DuplicateDataCertList(SrcCerts->Certs.NumCerts, SrcCerts->Certs.GroupList.CertList, malloc_func, free_func, mem_ref, &(DestCerts->Certs.NumCerts), &(DestCerts->Certs.GroupList.CertList))); } break; case CSSM_CERTGROUP_ENCODED_CERT: { ERR(err = cssmutil_DuplicateEncodedCertList(SrcCerts->Certs.NumCerts, SrcCerts->Certs.GroupList.EncodedCertList, malloc_func, free_func, mem_ref, &(DestCerts->Certs.NumCerts), &(DestCerts->Certs.GroupList.EncodedCertList))); } break; case CSSM_CERTGROUP_PARSED_CERT: { ERR(err = cssmutil_DuplicateParsedCertList(SrcCerts->Certs.NumCerts, SrcCerts->Certs.GroupList.ParsedCertList, malloc_func, free_func, mem_ref, &(DestCerts->Certs.NumCerts), &(DestCerts->Certs.GroupList.ParsedCertList))); } break; case CSSM_CERTGROUP_CERT_PAIR: { ERR(err = cssmutil_DuplicatePairCertList(SrcCerts->Certs.NumCerts, SrcCerts->Certs.GroupList.PairCertList, malloc_func, free_func, mem_ref, &(DestCerts->Certs.NumCerts), &(DestCerts->Certs.GroupList.PairCertList))); } break; default: { ERR(err = CSSMERR_CSSM_INVALID_ATTRIBUTE); } break; } } return err; } CSSM_RETURN CSSMAPI cssmutil_DuplicateDataCertList(uint32 NumSrcCerts, const CSSM_DATA *SrcCertList, CSSM_MALLOC malloc_func, CSSM_FREE free_func, void *mem_ref, uint32 *NumDestCerts, CSSM_DATA_PTR *DestCertList) { CSSM_RETURN err = CSSM_OK; uint32 i; uint32 j; if(((NULL == SrcCertList) && (0 != NumSrcCerts)) || (NULL == NumDestCerts) || (NULL == DestCertList)) { ERR(err = CSSMERR_CSSM_INVALID_POINTER); } else { *NumDestCerts = 0; *DestCertList = NULL; if(0 != NumSrcCerts) { (*DestCertList) = CSSM_MALLOC_WRAPPER(malloc_func,(sizeof(CSSM_DATA) * NumSrcCerts), mem_ref); if(NULL == (*DestCertList)) { ERR(err = CSSMERR_CSSM_MEMORY_ERROR); } else { i = 0; while((CSSM_OK == err) && (i < NumSrcCerts)) { (*DestCertList)[i].Length = SrcCertList[i].Length; if( (NULL != SrcCertList[i].Data) && (0 != SrcCertList[i].Length) ) { (*DestCertList)[i].Data = CSSM_MALLOC_WRAPPER(malloc_func,SrcCertList[i].Length, mem_ref); if(NULL == (*DestCertList)[i].Data) { ERR(err = CSSMERR_CSSM_MEMORY_ERROR); } else { memcpy((*DestCertList)[i].Data, SrcCertList[i].Data, SrcCertList[i].Length); } } else { (*DestCertList)[i].Data = NULL; } i++; } if(CSSM_OK != err) { /* free all the memory we've allocated */ j = 0; while(j < (i-1)) { if( (NULL != (*DestCertList)[j].Data) && (0 != (*DestCertList)[j].Length) ) { CSSM_FREE_WRAPPER(free_func,(*DestCertList)[j].Data, mem_ref); } j++; } CSSM_FREE_WRAPPER(free_func,(*DestCertList), mem_ref); *DestCertList = NULL; } } } else { /* the NULL value is the correct "copy" */ *DestCertList = NULL; } if(CSSM_OK == err) { *NumDestCerts = NumSrcCerts; } } return err; } CSSM_RETURN CSSMAPI cssmutil_DuplicateEncodedCertList(uint32 NumSrcCerts, const CSSM_ENCODED_CERT *SrcCertList, CSSM_MALLOC malloc_func, CSSM_FREE free_func, void *mem_ref, uint32 *NumDestCerts, CSSM_ENCODED_CERT_PTR *DestCertList) { CSSM_RETURN err = CSSM_OK; uint32 i; uint32 j; if(((NULL == SrcCertList) && (0 != NumSrcCerts)) || (NULL == NumDestCerts) || (NULL == DestCertList)) { ERR(err = CSSMERR_CSSM_INVALID_POINTER); } else { *NumDestCerts = 0; *DestCertList = NULL; if(0 != NumSrcCerts) { (*DestCertList) = CSSM_MALLOC_WRAPPER(malloc_func,(sizeof(CSSM_ENCODED_CERT) * NumSrcCerts), mem_ref); if(NULL == (*DestCertList)) { ERR(err = CSSMERR_CSSM_MEMORY_ERROR); } else { i = 0; while((CSSM_OK == err) && (i < NumSrcCerts)) { (*DestCertList)[i].CertType = SrcCertList[i].CertType; (*DestCertList)[i].CertEncoding = SrcCertList[i].CertEncoding; (*DestCertList)[i].CertBlob.Length = SrcCertList[i].CertBlob.Length; if( (NULL != SrcCertList[i].CertBlob.Data) && (0 != (*DestCertList)[i].CertBlob.Length) ) { (*DestCertList)[i].CertBlob.Data = CSSM_MALLOC_WRAPPER(malloc_func,SrcCertList[i].CertBlob.Length, mem_ref); if(NULL == (*DestCertList)[i].CertBlob.Data) { ERR(err = CSSMERR_CSSM_MEMORY_ERROR); } else { memcpy((*DestCertList)[i].CertBlob.Data, SrcCertList[i].CertBlob.Data, SrcCertList[i].CertBlob.Length); } } else { (*DestCertList)[i].CertBlob.Data = NULL; } i++; } if(CSSM_OK != err) { /* free all the memory we've allocated */ j = 0; while(j < (i-1)) { if( (NULL != (*DestCertList)[j].CertBlob.Data) && (0 != (*DestCertList)[j].CertBlob.Length) ) { CSSM_FREE_WRAPPER(free_func,(*DestCertList)[j].CertBlob.Data, mem_ref); } j++; } CSSM_FREE_WRAPPER(free_func,(*DestCertList), mem_ref); *DestCertList = NULL; } } } else { /* the NULL value is the correct "copy" */ *DestCertList = NULL; } if(CSSM_OK == err) { *NumDestCerts = NumSrcCerts; } } return err; } CSSM_RETURN CSSMAPI cssmutil_DuplicateParsedCertList(uint32 NumSrcCerts, const CSSM_PARSED_CERT *SrcCertList, CSSM_MALLOC malloc_func, CSSM_FREE free_func, void *mem_ref, uint32 *NumDestCerts, CSSM_PARSED_CERT_PTR *DestCertList) { CSSM_RETURN err; ERR(err = CSSMERR_CSSM_FUNCTION_NOT_IMPLEMENTED); return err; } CSSM_RETURN CSSMAPI cssmutil_DuplicatePairCertList(uint32 NumSrcCerts, const CSSM_CERT_PAIR *SrcCertList, CSSM_MALLOC malloc_func, CSSM_FREE free_func, void *mem_ref, uint32 *NumDestCerts, CSSM_CERT_PAIR_PTR *DestCertList) { CSSM_RETURN err; ERR(err = CSSMERR_CSSM_FUNCTION_NOT_IMPLEMENTED); return err; } CSSM_RETURN CSSMAPI cssmutil_DuplicateSampleGroup(const CSSM_SAMPLEGROUP *SrcSamples, CSSM_MALLOC malloc_func, CSSM_FREE free_func, void *mem_ref, CSSM_SAMPLEGROUP_PTR DestSamples) { CSSM_RETURN err = CSSM_OK; uint32 i; if((NULL == SrcSamples) || (NULL == DestSamples)) { ERR(err = CSSMERR_CSSM_INVALID_POINTER); } else { DestSamples->NumberOfSamples = SrcSamples->NumberOfSamples; if(0 < DestSamples->NumberOfSamples) { DestSamples->Samples = CSSM_MALLOC_WRAPPER(malloc_func,(sizeof(CSSM_SAMPLE) * DestSamples->NumberOfSamples), mem_ref); if(NULL == DestSamples->Samples) { ERR(err = CSSMERR_CSSM_MEMORY_ERROR); } else { i = 0; while((i < DestSamples->NumberOfSamples) && (CSSM_OK == err)) { ERR(err = cssmutil_DuplicateSample(&(SrcSamples->Samples[i]), malloc_func, free_func, mem_ref, (CSSM_SAMPLE_PTR)&(DestSamples->Samples[i]))); i++; } if(CSSM_OK != err) { CSSM_FREE_WRAPPER(free_func,(void*)DestSamples->Samples, mem_ref); DestSamples->Samples = NULL; DestSamples->NumberOfSamples = 0; } } } else { DestSamples->Samples = NULL; } } return err; } CSSM_RETURN CSSMAPI cssmutil_DuplicateSample(const CSSM_SAMPLE *SrcSample, CSSM_MALLOC malloc_func, CSSM_FREE free_func, void *mem_ref, CSSM_SAMPLE_PTR DestSample) { CSSM_RETURN err = CSSM_OK; if((NULL == SrcSample) || (NULL == DestSample)) { ERR(err = CSSMERR_CSSM_INVALID_POINTER); } else { /* if there's a verifier, copy it */ if(NULL != SrcSample->Verifier) { DestSample->Verifier = CSSM_MALLOC_WRAPPER(malloc_func,sizeof(CSSM_SUBSERVICE_UID), mem_ref); if(NULL == DestSample->Verifier) { ERR(err = CSSMERR_CSSM_MEMORY_ERROR); } else { memcpy((void*)DestSample->Verifier, (void*)SrcSample->Verifier, sizeof(CSSM_SUBSERVICE_UID)); } } else { DestSample->Verifier = NULL; } /* now we copy the typed sample - this is a CSSM_LIST */ if(CSSM_OK == err) { ERR(err = cssmutil_DuplicateCSSMList(&SrcSample->TypedSample, malloc_func, free_func, mem_ref, &DestSample->TypedSample)); } } return err; } CSSM_RETURN CSSMAPI cssmutil_DuplicateCSSMList(const CSSM_LIST *SrcList, CSSM_MALLOC malloc_func, CSSM_FREE free_func, void *mem_ref, CSSM_LIST_PTR DestList) { CSSM_RETURN err = CSSM_OK; if((NULL == SrcList) || (NULL == DestList)) { ERR(err = CSSMERR_CSSM_INVALID_POINTER); } else { DestList->ListType = SrcList->ListType; /* make sure there's actually a list */ if(NULL != SrcList->Head) { ERR(err = cssmutil_DuplicateCSSMListElements(SrcList->Head, malloc_func, free_func, mem_ref, &DestList->Head)); if(CSSM_OK == err) { DestList->Tail = DestList->Head; while(NULL != DestList->Tail->NextElement) { DestList->Tail = DestList->Tail->NextElement; } } } else { DestList->Head = NULL; DestList->Tail = NULL; } } return err; } CSSM_RETURN CSSMAPI cssmutil_DuplicateCSSMListElements(const CSSM_LIST_ELEMENT *SrcElement, CSSM_MALLOC malloc_func, CSSM_FREE free_func, void *mem_ref, CSSM_LIST_ELEMENT_PTR *DestElement) { CSSM_RETURN err = CSSM_OK; CSSM_LIST_ELEMENT_PTR CurrentSrcElemPtr; CSSM_LIST_ELEMENT_PTR newElemHead, CurrentDestElemPtr, LastDestElemPtr; if((NULL == SrcElement) || (NULL == DestElement)) { ERR(err = CSSMERR_CSSM_INVALID_POINTER); } else { *DestElement = NULL; /* we'll change this later if no errors occur */ CurrentSrcElemPtr = (CSSM_LIST_ELEMENT_PTR)SrcElement; newElemHead = CSSM_MALLOC_WRAPPER(malloc_func,sizeof(CSSM_LIST_ELEMENT), mem_ref); if(NULL == newElemHead) { ERR(err = CSSMERR_CSSM_MEMORY_ERROR); } else { CurrentDestElemPtr = newElemHead; while((CSSM_OK == err) && (NULL != CurrentDestElemPtr)) { CurrentDestElemPtr->WordID = CurrentSrcElemPtr->WordID; CurrentDestElemPtr->ElementType = CurrentSrcElemPtr->ElementType; switch(CurrentSrcElemPtr->ElementType) { case CSSM_LIST_ELEMENT_DATUM: { /* We just copy the data contained in the CSSM_DATA */ CurrentDestElemPtr->Element.Word.Length = CurrentSrcElemPtr->Element.Word.Length; CurrentDestElemPtr->Element.Word.Data = CSSM_MALLOC_WRAPPER(malloc_func, CurrentDestElemPtr->Element.Word.Length, mem_ref); if(NULL != CurrentDestElemPtr->Element.Word.Data) { memcpy(CurrentDestElemPtr->Element.Word.Data, CurrentSrcElemPtr->Element.Word.Data, CurrentDestElemPtr->Element.Word.Length); } else { ERR(err = CSSMERR_CSSM_MEMORY_ERROR); CurrentDestElemPtr->Element.Word.Length = 0; } } break; case CSSM_LIST_ELEMENT_SUBLIST: { /* We have to recurse through the sublist to copy the memory contained there. After that we need to find the tail pointer so we can set it. */ ERR(err = cssmutil_DuplicateCSSMList((const CSSM_LIST *)&CurrentSrcElemPtr->Element.Sublist, malloc_func, free_func, mem_ref, (CSSM_LIST_PTR)&CurrentDestElemPtr->Element.Sublist)); } break; case CSSM_LIST_ELEMENT_WORDID: { /* we do nothing because we already copied the WordID */ } break; default: { /* no clue what this input really is, but it's an error */ ERR(err = CSSMERR_CSSM_INVALID_ATTRIBUTE); } break; } CurrentSrcElemPtr = CurrentSrcElemPtr->NextElement; if(NULL != CurrentSrcElemPtr) { LastDestElemPtr = CurrentDestElemPtr; CurrentDestElemPtr = CSSM_MALLOC_WRAPPER(malloc_func,sizeof(CSSM_LIST_ELEMENT), mem_ref); if(NULL == CurrentDestElemPtr) { ERR(err = CSSMERR_CSSM_MEMORY_ERROR); LastDestElemPtr->NextElement = NULL; } else { LastDestElemPtr->NextElement = CurrentDestElemPtr; } } else { CurrentDestElemPtr->NextElement = NULL; CurrentDestElemPtr = NULL; } } if(CSSM_OK != err) { /* something went wrong, so we'll free up the list elements we've allocated */ ERR(cssmutil_FreeCSSMListElements(&newElemHead, free_func, mem_ref)); } } if(CSSM_OK == err) { *DestElement = newElemHead; } } return err; }