]> git.saurik.com Git - apple/security.git/blobdiff - libsecurity_mds/lib/MDSAttrParser.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / libsecurity_mds / lib / MDSAttrParser.cpp
diff --git a/libsecurity_mds/lib/MDSAttrParser.cpp b/libsecurity_mds/lib/MDSAttrParser.cpp
deleted file mode 100644 (file)
index 70892bb..0000000
+++ /dev/null
@@ -1,640 +0,0 @@
-/*
- * Copyright (c) 2000-2001 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.
- */
-
-
-/*
-   File:      MDSAttrParser.cpp
-
-   Contains:  Classes to parse XML plists and fill in MDS DBs with the
-              attributes found there.  
-
-   Copyright: (c) 2001 Apple Computer, Inc., all rights reserved.
-*/
-
-#include "MDSAttrParser.h"
-#include "MDSAttrUtils.h"
-#include "MDSDictionary.h"
-#include <security_utilities/logging.h>
-#include <Security/mds_schema.h>
-
-namespace Security
-{
-
-MDSAttrParser::MDSAttrParser(
-       const char *bundlePath,
-       MDSSession &dl,
-       CSSM_DB_HANDLE objectHand,
-       CSSM_DB_HANDLE cdsaDirHand) :
-               mBundle(NULL),
-               mPath(NULL),
-               mDl(dl),
-               mObjectHand(objectHand),
-               mCdsaDirHand(cdsaDirHand),
-               mGuid(NULL),
-               mDefaults(NULL)
-{
-       /* Only task here is to cook up a CFBundle for the specified path */
-       size_t pathLen = strlen(bundlePath);
-       CFURLRef url = CFURLCreateFromFileSystemRepresentation(NULL,
-               (unsigned char *)bundlePath,
-               pathLen,
-               false);
-       if(url == NULL) {
-               Syslog::alert("CFURLCreateFromFileSystemRepresentation(%s) failure", mPath);
-               CssmError::throwMe(CSSMERR_DL_INVALID_DB_NAME);
-       }
-       
-       /* FIXME - this leaks 28 bytes each time thru, even though we CFRelease the
-        * mBundle in out destructor. I think this is a CF leak. */
-       mBundle = CFBundleCreate(NULL, url);
-       CFRelease(url);
-       if(mBundle == NULL) {
-               Syslog::alert("CFBundleCreate(%s) failure", mPath);
-               CssmError::throwMe(CSSMERR_DL_INVALID_DB_NAME);
-       }
-       mPath = new char[pathLen + 1];
-       strcpy(mPath, bundlePath);
-}
-
-MDSAttrParser::~MDSAttrParser()
-{
-       CF_RELEASE(mBundle);
-       delete [] mPath;
-       delete [] mGuid;
-}
-
-/*********************
- Main public function.
-
-Parsing bundle {
-       get all *.mdsinfo files;
-       for each mdsinfo {
-               get contents of that file as dictionary;
-               switch (ModuleType) {
-               case CSSM:
-                       parse this mdsinfo --> MDS_OBJECT_RECORDTYPE, MDS_CDSADIR_CSSM_RECORDTYPE;
-                       break;
-               case Plugin:
-                       parse this info --> MDS_OBJECT_RECORDTYPE, MDS_CDSADIR_COMMON_RECORDTYPE;
-               case PluginInfo:
-                       recordType = lookup("MdsRecordType");
-                       dispatch to recordtype-specific parsing;
-               }
-       }
-}
-************/ 
-
-void MDSAttrParser::parseAttrs(CFStringRef subdir)
-{
-       /* get all *.mdsinfo files */
-       CFArrayRef bundleInfoFiles = CFBundleCopyResourceURLsOfType(mBundle,
-               CFSTR(MDS_INFO_TYPE),
-               subdir);
-       if(bundleInfoFiles == NULL) {
-               Syslog::alert("MDSAttrParser: no mdsattr files for %s", mPath);
-               return;
-       }
-       assert(CFGetTypeID(bundleInfoFiles) == CFArrayGetTypeID());
-       
-       /* process each .mdsinfo file */
-       CFIndex numFiles = CFArrayGetCount(bundleInfoFiles);
-       for(CFIndex i=0; i<numFiles; i++) {
-               /* get filename as CFURL */
-               CFURLRef infoUrl = NULL;
-               
-               infoUrl = reinterpret_cast<CFURLRef>(
-                       CFArrayGetValueAtIndex(bundleInfoFiles, i));
-               if(infoUrl == NULL) {
-                       MPDebug("MDSAttrParser: CFBundleCopyResourceURLsOfType screwup 1");
-                       continue;
-               }
-               if(CFGetTypeID(infoUrl) != CFURLGetTypeID()) {
-                       MPDebug("MDSAttrParser: CFBundleCopyResourceURLsOfType screwup 2");
-                       continue;
-               }
-               
-               // @@@  Workaround for 4234967: skip any filename beginning with "._"
-               CFStringRef lastComponent = CFURLCopyLastPathComponent(infoUrl);
-               if (lastComponent) {
-                       CFStringRef resFilePfx = CFSTR("._");
-                       // setting the search length and location like this permits, 
-                       // e.g., ".foo.mdsinfo" to be valid
-                       CFIndex resFilePfxLen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(resFilePfx), kCFStringEncodingUTF8);
-                       CFRange range = CFRangeMake(0, resFilePfxLen);
-                       Boolean skip = CFStringFindWithOptions(lastComponent, 
-                                                                                                  resFilePfx, 
-                                                                                                  range,
-                                                                                                  0/*options*/,
-                                                                                                  NULL/*returned substr*/);
-                       CFRelease(lastComponent);
-                       if (skip == true) {
-                               Syslog::warning("MDSAttrParser: ignoring resource file");
-                               continue;
-                       }
-               }
-               
-               parseFile(infoUrl, subdir);
-       } /* for each mdsinfo */
-       CF_RELEASE(bundleInfoFiles);
-}
-
-void MDSAttrParser::parseFile(CFURLRef infoUrl, CFStringRef subdir)
-{
-       CFStringRef infoType = NULL;
-       
-       /* Get contents of mdsinfo file as dictionary */
-       MDSDictionary mdsDict(infoUrl, subdir, mPath);
-       /* Make sure we set all possible MDS values before checking for GUID */
-       mdsDict.setDefaults(mDefaults);
-       if (mGuid == NULL) {
-               CFStringRef guid = (CFStringRef)mdsDict.lookup("ModuleID", true, CFStringGetTypeID());
-               if (guid) {
-                       CFIndex copylen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(guid), kCFStringEncodingUTF8) + 1/*nul terminator*/;
-                       mGuid = new char[copylen];
-                       if (false == CFStringGetCString(guid, mGuid, copylen, kCFStringEncodingUTF8)) {
-                               logFileError("Error copying GUID", infoUrl, NULL, NULL);
-                               delete [] mGuid;
-                               mGuid = NULL;
-                               CssmError::throwMe(CSSM_ERRCODE_MDS_ERROR);
-                       }
-               }
-               else {
-                       logFileError("No GUID associated with plugin?", infoUrl, NULL, NULL);
-                       CssmError::throwMe(CSSM_ERRCODE_MDS_ERROR);
-               }
-       }
-       
-       MPDebug("Parsing mdsinfo file %s", mdsDict.fileDesc());
-       
-       /* Determine what kind of info file this is and dispatch accordingly */
-       infoType = (CFStringRef)mdsDict.lookup(CFSTR(MDS_INFO_FILE_TYPE),
-               true, CFStringGetTypeID());
-       if(infoType == NULL) {
-               logFileError("Malformed MDS Info file", infoUrl, NULL, NULL);
-               CssmError::throwMe(CSSM_ERRCODE_MDS_ERROR);
-       }
-       
-       /* be robust here, errors in these low-level routines do not affect
-        * the rest of our task */
-       try {
-               if(CFStringCompare(infoType, CFSTR(MDS_INFO_FILE_TYPE_CSSM), 0) 
-                               == kCFCompareEqualTo) {
-                       parseCssmInfo(&mdsDict);
-               }
-               else if(CFStringCompare(infoType, CFSTR(MDS_INFO_FILE_TYPE_PLUGIN), 0) 
-                               == kCFCompareEqualTo) {
-                       parsePluginCommon(&mdsDict);
-               }
-               else if(CFStringCompare(infoType, CFSTR(MDS_INFO_FILE_TYPE_RECORD), 0) 
-                               == kCFCompareEqualTo) {
-                       parsePluginSpecific(&mdsDict);
-               }
-               else {
-                       logFileError("Malformed MDS Info file", infoUrl, NULL, NULL);
-               }
-       }
-       catch(...) {
-       
-       }
-}
-
-void MDSAttrParser::logFileError(
-       const char *op,
-       CFURLRef fileUrl,
-       CFStringRef errStr,             // optional if you have it
-       SInt32 *errNo)                  // optional if you have it
-{
-       CFStringRef urlStr = CFURLGetString(fileUrl);
-       const char *cUrlStr = CFStringGetCStringPtr(urlStr, kCFStringEncodingUTF8);
-       char* stringBuffer = NULL;
-    
-    if (cUrlStr == NULL)
-    {
-        CFIndex maxLen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(urlStr), kCFStringEncodingUTF8) + 1;
-        stringBuffer = (char*) malloc(maxLen);
-        CFStringGetCString(urlStr, stringBuffer, maxLen, kCFStringEncodingUTF8);
-        cUrlStr = stringBuffer;
-    }
-    
-       if(errStr) {
-        const char *cerrStr = CFStringGetCStringPtr(errStr, kCFStringEncodingUTF8);
-        char* sbuf2 = NULL;
-        
-        if (cerrStr == NULL)
-        {
-            CFIndex maxLen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(errStr), kCFStringEncodingUTF8) + 1;
-            sbuf2 = (char*) malloc(maxLen);
-            CFStringGetCString(urlStr, sbuf2, maxLen, kCFStringEncodingUTF8);
-            cUrlStr = sbuf2;
-        }
-    
-               Syslog::alert("MDS: %s: bundle %s url %s: error %s",
-                       op, mPath, cUrlStr, cerrStr);
-        
-        if (sbuf2 != NULL)
-        {
-            free(sbuf2);
-        }
-       }
-       else {
-               Syslog::alert("MDS: %s: bundle %s url %s: error %d",
-                       op, mPath, cUrlStr, (int)(errNo ? *errNo : 0));
-       }
-    
-    if (stringBuffer != NULL)
-    {
-        free(stringBuffer);
-    }
-}
-        
-/*
- * Parse a CSSM info file.
- */    
-void MDSAttrParser::parseCssmInfo(
-       MDSDictionary *mdsDict)
-{
-       /* first get object info */
-       parseObjectRecord(mdsDict);
-       
-       /* now CSSM relation */
-       const RelationInfo *relationInfo = 
-               MDSRecordTypeToRelation(MDS_CDSADIR_CSSM_RECORDTYPE);
-       assert(relationInfo != NULL);
-       parseMdsRecord(mdsDict, relationInfo, mCdsaDirHand);
-}
-       
-/*
- * Parse a PluginCommon file.
- */
-void MDSAttrParser::parsePluginCommon(
-       MDSDictionary *mdsDict)
-{
-       
-       /* first get object info */
-       parseObjectRecord(mdsDict);
-       
-       /* now common relation */
-       const RelationInfo *relationInfo = 
-               MDSRecordTypeToRelation(MDS_CDSADIR_COMMON_RECORDTYPE);
-       assert(relationInfo != NULL);
-       parseMdsRecord(mdsDict, relationInfo, mCdsaDirHand);
-}
-
-/*
- * Parse a Plugin Specific file.
- */
-void MDSAttrParser::parsePluginSpecific(
-       MDSDictionary *mdsDict)
-{
-       /* determine record type from the file itself */
-       CFStringRef recordTypeStr = 
-               (CFStringRef)mdsDict->lookup(MDS_INFO_FILE_RECORD_TYPE,
-                       true, CFStringGetTypeID());
-       if(recordTypeStr == NULL) {
-               MPDebug("%s: no %s record found\n", mdsDict->fileDesc(),
-                       MDS_INFO_FILE_RECORD_TYPE);
-               return;
-       }
-
-       /* convert to a known schema */
-       const char *recordTypeCStr = MDSCFStringToCString(recordTypeStr);
-       const RelationInfo *relationInfo = MDSRecordTypeNameToRelation(recordTypeCStr);
-       if(relationInfo == NULL) {
-               Syslog::alert("MDS file %s has unsupported record type %s", 
-                       mdsDict->fileDesc(), recordTypeCStr);
-               MPDebug("MDS file %s has unsupported record type %s", 
-                       mdsDict->fileDesc(), recordTypeCStr);
-               delete [] recordTypeCStr;
-               return;
-       }
-       MPDebug("Parsing MDS file %s, recordType %s", mdsDict->fileDesc(), recordTypeCStr);
-       delete [] recordTypeCStr;
-       
-       /* handle special cases here */
-       switch(relationInfo->DataRecordType) {
-               case MDS_CDSADIR_CSP_CAPABILITY_RECORDTYPE:
-                       parseCspCapabilitiesRecord(mdsDict);
-                       break;
-               case MDS_CDSADIR_TP_OIDS_RECORDTYPE:
-                       parseTpPolicyOidsRecord(mdsDict);
-                       break;
-               default:
-                       /* all (normal) linear schema */
-                       parseMdsRecord(mdsDict, relationInfo, mCdsaDirHand);
-       }
-}
-
-
-/*
- * Given an open MDSDictionary, create an MDS_OBJECT_RECORDTYPE record and 
- * add it to mObjectHand. Used when parsing both CSSM records and MOduleCommon
- * records. 
- */
-void MDSAttrParser::parseObjectRecord(
-       MDSDictionary *mdsDict)
-{
-       assert(mdsDict != NULL);
-       assert(mObjectHand != 0);
-       parseMdsRecord(mdsDict, &kObjectRelation, mObjectHand);
-       
-}
-
-/*
- * Given an open dictionary and a RelationInfo defining a schema, fetch all
- * attributes associated with the specified schema from the dictionary
- * and write them to specified DB.
- */
-void MDSAttrParser::parseMdsRecord(
-       MDSDictionary                           *mdsDict,
-       const RelationInfo                      *relInfo,
-       CSSM_DB_HANDLE                          dbHand)
-{
-       assert(mdsDict != NULL);
-       assert(relInfo != NULL);
-       assert(dbHand != 0);
-       
-       /* 
-        * malloc an CSSM_DB_ATTRIBUTE_DATA array associated with specified schema.
-        */
-       unsigned numSchemaAttrs = relInfo->NumberOfAttributes;
-       CSSM_DB_ATTRIBUTE_DATA *dbAttrs = new CSSM_DB_ATTRIBUTE_DATA[numSchemaAttrs];
-       
-       /* 
-        * Grind thru the attributes in the specified schema. Do not assume the presence
-        * of any given attribute.
-        */
-       uint32 foundAttrs = 0;  
-       mdsDict->lookupAttributes(relInfo, dbAttrs, foundAttrs);
-       
-       /* write to the DB */
-       MDSInsertRecord(dbAttrs, foundAttrs, relInfo->DataRecordType, mDl, dbHand);
-
-       MDSFreeDbRecordAttrs(dbAttrs, foundAttrs);
-       delete [] dbAttrs;
-}
-
-/*
- * Parse CSP capabilities. This is much more complicated than most records. 
- * The propertly list (*.mdsinfo) is set up like this:
- *
- * root(Dictionary) {
- *    ModuleID(String)
- *    SSID(Number)
- *    Capabilities(Array) {
- *       index 0(Dictionary) {
- *           AlgType(String)                                   -- CSSM_ALGID_SHA1
- *           ContextType(String)                               -- CSSM_ALGCLASS_DIGEST
- *           UseeTag(String)                                   -- CSSM_USEE_NONE
- *           Description(String)                               -- "SHA1 Digest"
- *           Attributes(Array)
- *              index 0(Dictionary)
- *                 AttributeType(String)               -- CSSM_ATTRIBUTE_OUTPUT_SIZE
- *                 AttributeValue(Array) {
- *                    index 0(Number)                  -- 20
- *                    ...
- *                 }
- *              index n ...
- *           }
- *       index n...
- *    }
- * }      
- *
- * The plist can specify multiple Capabilities, multiple Attributes for each
- * Capability, and multiple values for each Attribute. (Note that MULTI_UINT32
- * in the DB is represented in the plist as an Array of Numbers.) Each element 
- * of each Attributes array maps to one record in the DB. The GroupID attribute 
- * of a record is the index into the plist's Capabilities array. 
- */
-void MDSAttrParser::parseCspCapabilitiesRecord(
-       MDSDictionary *mdsDict)
-{
-       /* 
-        * Malloc an attribute array big enough for the whole schema. We're going 
-        * to re-use this array every time we write a new record. Portions of 
-        * the array are invariant for some inner loops.
-        */ 
-       const RelationInfo *topRelInfo = 
-               MDSRecordTypeToRelation(MDS_CDSADIR_CSP_CAPABILITY_RECORDTYPE);
-       assert(topRelInfo != NULL);
-       uint32 numInAttrs = topRelInfo->NumberOfAttributes;
-       CSSM_DB_ATTRIBUTE_DATA_PTR outAttrs = new CSSM_DB_ATTRIBUTE_DATA[numInAttrs];
-       
-       /* these attrs are only set once, then they remain invariant */
-       uint32 numTopLevelAttrs;
-       mdsDict->lookupAttributes(&CSPCapabilitiesDict1RelInfo, outAttrs, 
-               numTopLevelAttrs);
-               
-       bool fetchedFromDisk = false;
-       
-       /* obtain Capabilities array */
-       CFArrayRef capArray = (CFArrayRef)mdsDict->lookupWithIndirect("Capabilities",
-               mBundle,
-               CFArrayGetTypeID(),
-               fetchedFromDisk);
-       if(capArray == NULL) {
-               /* well we did not get very far.... */
-               MPDebug("parseCspCapabilitiesRecord: no (or bad) Capabilities");
-               delete [] outAttrs;
-               return;
-       }
-       
-       /*
-        * Descend into Capabilities array. Each element is a dictionary defined 
-        * by CSPCapabilitiesDict2RelInfo.
-        */
-       CFIndex capArraySize = CFArrayGetCount(capArray);
-       CFIndex capDex;
-       for(capDex=0; capDex<capArraySize; capDex++) {
-               MPDebug("...parsing Capability %d", (int)capDex);
-               CFDictionaryRef capDict = 
-                       (CFDictionaryRef)CFArrayGetValueAtIndex(capArray, capDex);
-               if((capDict == NULL) || 
-                  (CFGetTypeID(capDict) != CFDictionaryGetTypeID())) {
-                       MPDebug("parseCspCapabilitiesRecord: bad Capabilities element");
-                       break;
-               }
-               MDSDictionary capDictMds(capDict);
-               
-               /* 
-                * Append this dictionary's attributes to outAttrs, after the fixed
-                * attributes from CSPCapabilitiesDict1RelInfo.
-                */
-               uint32 numCapDictAttrs;
-               capDictMds.lookupAttributes(&CSPCapabilitiesDict2RelInfo,
-                       &outAttrs[numTopLevelAttrs],
-                       numCapDictAttrs);
-               
-               /*
-                * Append the GroupId attribute, which we infer from the current index 
-                * into Capabilitites.  However, thou shalt not use > 4-byte values 
-         * for MDS, so convert from CFIndex first.  
-                */
-        if (capDex > uint32(~0)) {
-            MPDebug("parseCspCapabilitiesRecord: too large an index for MDS");
-            break;
-        }
-        uint32 index32 = uint32(capDex);
-               MDSRawValueToDbAttr(&index32, sizeof(index32), CSSM_DB_ATTRIBUTE_FORMAT_UINT32, 
-                       "GroupId", outAttrs[numTopLevelAttrs + numCapDictAttrs]);
-               numCapDictAttrs++;      
-               
-               /* 
-                * Now descend into the array of this capability's attributes.
-                * Each element is a dictionary defined by
-                * by CSPCapabilitiesDict3RelInfo.
-                */
-               CFArrayRef attrArray = (CFArrayRef)capDictMds.lookup("Attributes",
-                       true, CFArrayGetTypeID());
-               if(attrArray == NULL) {
-                       MPDebug("parseCspCapabilitiesRecord: no (or bad) Attributes");
-                       break;
-               }
-               CFIndex attrArraySize = CFArrayGetCount(attrArray);
-               CFIndex attrDex;
-               for(attrDex=0; attrDex<attrArraySize; attrDex++) {
-                       MPDebug("   ...parsing Attribute %d", (int)attrDex);
-                       CFDictionaryRef attrDict = 
-                               (CFDictionaryRef)CFArrayGetValueAtIndex(attrArray, attrDex);
-                       if((attrDict == NULL) || 
-                          (CFGetTypeID(attrDict) != CFDictionaryGetTypeID())) {
-                               MPDebug("parseCspCapabilitiesRecord: bad Attributes element");
-                               break;
-                       }
-                       MDSDictionary attrDictMds(attrDict);
-                       
-                       /* 
-                        * Append this dictionary's attributes to outAttrs, after the fixed
-                        * attributes from CSPCapabilitiesDict1RelInfo and this capability's
-                        * CSPCapabilitiesDict2RelInfo.
-                        */
-                       uint32 numAttrDictAttrs;
-                       attrDictMds.lookupAttributes(&CSPCapabilitiesDict3RelInfo,
-                               &outAttrs[numTopLevelAttrs + numCapDictAttrs],
-                               numAttrDictAttrs);
-                       
-                       /* write to DB */
-                       MDSInsertRecord(outAttrs,
-                               numTopLevelAttrs + numCapDictAttrs + numAttrDictAttrs,
-                               MDS_CDSADIR_CSP_CAPABILITY_RECORDTYPE, 
-                               mDl, 
-                               mCdsaDirHand);
-                               
-                       /* just free the attrs we allocated in this loop */
-                       MDSFreeDbRecordAttrs(&outAttrs[numTopLevelAttrs + numCapDictAttrs],
-                               numAttrDictAttrs);
-               }       /* for each attribute */
-               /* just free the attrs we allocated in this loop */
-               MDSFreeDbRecordAttrs(&outAttrs[numTopLevelAttrs], numCapDictAttrs);
-       }               /* for each capability */
-       
-       MDSFreeDbRecordAttrs(outAttrs, numTopLevelAttrs);
-       delete [] outAttrs;
-       if(fetchedFromDisk) {
-               CF_RELEASE(capArray);
-       }
-}
-
-/*
- * Parse TP Policy OIDs. 
- * The propertly list (*.mdsinfo) is set up like this:
- *
- * root(Dictionary) {
- *    ModuleID(String)
- *    SSID(Number)
- *    Policies(Array) {
- *       index 0(Dictionary) {
- *           OID(Data)                                                 -- <092a8648 86f76364 0102>
- *           Value(Data)                                               -- optional, OID-specific 
- *       index n...
- *    }
- * }      
- *
- * The plist can specify multiple Policies. Each element of the Policies 
- * array maps to one record in the DB.  
- */
-void MDSAttrParser::parseTpPolicyOidsRecord(
-       MDSDictionary *mdsDict)
-{
-       /* 
-        * Malloc an attribute array big enough for the whole schema. We're going 
-        * to re-use this array every time we write a new record. Portions of 
-        * the array are invariant for some inner loops.
-        */ 
-       const RelationInfo *topRelInfo = 
-               MDSRecordTypeToRelation(MDS_CDSADIR_TP_OIDS_RECORDTYPE);
-       assert(topRelInfo != NULL);
-       uint32 numInAttrs = topRelInfo->NumberOfAttributes;
-       CSSM_DB_ATTRIBUTE_DATA_PTR outAttrs = new CSSM_DB_ATTRIBUTE_DATA[numInAttrs];
-       
-       /* these attrs are only set once, then they remain invariant */
-       uint32 numTopLevelAttrs;
-       mdsDict->lookupAttributes(&TpPolicyOidsDict1RelInfo, outAttrs, 
-               numTopLevelAttrs);
-               
-       /* obtain Policies array */
-       CFArrayRef policyArray = (CFArrayRef)mdsDict->lookup("Policies",
-               true, CFArrayGetTypeID());
-       if(policyArray == NULL) {
-               /* well we did not get very far.... */
-               MPDebug("parseTpPolicyOidsRecord: no (or bad) Policies");
-               delete [] outAttrs;
-               return;
-       }
-       
-       /*
-        * Descend into Policies array. Each element is a dictionary defined 
-        * by TpPolicyOidsDict2RelInfo.
-        */
-       CFIndex policyArraySize = CFArrayGetCount(policyArray);
-       CFIndex policyDex;
-       for(policyDex=0; policyDex<policyArraySize; policyDex++) {
-               MPDebug("...parsing Policy %d", (int)policyDex);
-               CFDictionaryRef policyDict = 
-                       (CFDictionaryRef)CFArrayGetValueAtIndex(policyArray, policyDex);
-               if((policyDict == NULL) || 
-                  (CFGetTypeID(policyDict) != CFDictionaryGetTypeID())) {
-                       MPDebug("parseTpPolicyOidsRecord: bad Policies element");
-                       break;
-               }
-               MDSDictionary policyDictMds(policyDict);
-               
-               /* 
-                * Append this dictionary's attributes to outAttrs, after the fixed
-                * attributes from TpPolicyOidsDict1RelInfo.
-                */
-               uint32 numPolicyDictAttrs;
-               policyDictMds.lookupAttributes(&TpPolicyOidsDict2RelInfo,
-                       &outAttrs[numTopLevelAttrs],
-                       numPolicyDictAttrs);
-               
-                       
-               /* write to DB */
-               MDSInsertRecord(outAttrs,
-                       numTopLevelAttrs + numPolicyDictAttrs,
-                       MDS_CDSADIR_TP_OIDS_RECORDTYPE, 
-                       mDl, 
-                       mCdsaDirHand);
-                       
-               /* free the attrs allocated in this loop */
-               MDSFreeDbRecordAttrs(outAttrs + numTopLevelAttrs, numPolicyDictAttrs);
-       }               /* for each policy */
-       MDSFreeDbRecordAttrs(outAttrs, numTopLevelAttrs);
-       delete [] outAttrs;
-}
-
-
-} // end namespace Security