]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_mds/lib/MDSAttrParser.cpp
Security-57740.1.18.tar.gz
[apple/security.git] / OSX / libsecurity_mds / lib / MDSAttrParser.cpp
1 /*
2 * Copyright (c) 2000-2001,2011-2014 Apple Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19 /*
20 File: MDSAttrParser.cpp
21
22 Contains: Classes to parse XML plists and fill in MDS DBs with the
23 attributes found there.
24
25 Copyright (c) 2001,2011-2014 Apple Inc. All Rights Reserved.
26 */
27
28 #include "MDSAttrParser.h"
29 #include "MDSAttrUtils.h"
30 #include "MDSDictionary.h"
31 #include <security_utilities/logging.h>
32 #include <security_utilities/cfutilities.h>
33 #include <Security/mds_schema.h>
34
35 namespace Security
36 {
37
38 MDSAttrParser::MDSAttrParser(
39 const char *bundlePath,
40 MDSSession &dl,
41 CSSM_DB_HANDLE objectHand,
42 CSSM_DB_HANDLE cdsaDirHand) :
43 mBundle(NULL),
44 mPath(NULL),
45 mDl(dl),
46 mObjectHand(objectHand),
47 mCdsaDirHand(cdsaDirHand),
48 mGuid(NULL),
49 mDefaults(NULL)
50 {
51 /* Only task here is to cook up a CFBundle for the specified path */
52 size_t pathLen = strlen(bundlePath);
53 CFURLRef url = CFURLCreateFromFileSystemRepresentation(NULL,
54 (unsigned char *)bundlePath,
55 pathLen,
56 false);
57 if(url == NULL) {
58 Syslog::alert("CFURLCreateFromFileSystemRepresentation(%s) failure", mPath);
59 CssmError::throwMe(CSSMERR_DL_INVALID_DB_NAME);
60 }
61
62 /* FIXME - this leaks 28 bytes each time thru, even though we CFRelease the
63 * mBundle in out destructor. I think this is a CF leak. */
64 mBundle = CFBundleCreate(NULL, url);
65 CFRelease(url);
66 if(mBundle == NULL) {
67 Syslog::alert("CFBundleCreate(%s) failure", mPath);
68 CssmError::throwMe(CSSMERR_DL_INVALID_DB_NAME);
69 }
70 mPath = new char[pathLen + 1];
71 strcpy(mPath, bundlePath);
72 }
73
74 MDSAttrParser::~MDSAttrParser()
75 {
76 CF_RELEASE(mBundle);
77 delete [] mPath;
78 delete [] mGuid;
79 }
80
81 /*********************
82 Main public function.
83
84 Parsing bundle {
85 get all *.mdsinfo files;
86 for each mdsinfo {
87 get contents of that file as dictionary;
88 switch (ModuleType) {
89 case CSSM:
90 parse this mdsinfo --> MDS_OBJECT_RECORDTYPE, MDS_CDSADIR_CSSM_RECORDTYPE;
91 break;
92 case Plugin:
93 parse this info --> MDS_OBJECT_RECORDTYPE, MDS_CDSADIR_COMMON_RECORDTYPE;
94 case PluginInfo:
95 recordType = lookup("MdsRecordType");
96 dispatch to recordtype-specific parsing;
97 }
98 }
99 }
100 ************/
101
102 void MDSAttrParser::parseAttrs(CFStringRef subdir)
103 {
104 /* get all *.mdsinfo files */
105 CFRef<CFArrayRef> bundleInfoFiles = CFBundleCopyResourceURLsOfType(mBundle,
106 CFSTR(MDS_INFO_TYPE),
107 subdir);
108 if(!bundleInfoFiles) {
109 Syslog::alert("MDSAttrParser: no mdsattr files for %s", mPath);
110 return;
111 }
112 assert(CFGetTypeID(bundleInfoFiles) == CFArrayGetTypeID());
113
114 /* process each .mdsinfo file */
115 CFIndex numFiles = CFArrayGetCount(bundleInfoFiles);
116 for(CFIndex i=0; i<numFiles; i++) {
117 /* get filename as CFURL */
118 CFURLRef infoUrl = NULL;
119
120 infoUrl = reinterpret_cast<CFURLRef>(
121 CFArrayGetValueAtIndex(bundleInfoFiles, i));
122 if(infoUrl == NULL) {
123 MPDebug("MDSAttrParser: CFBundleCopyResourceURLsOfType screwup 1");
124 continue;
125 }
126 if(CFGetTypeID(infoUrl) != CFURLGetTypeID()) {
127 MPDebug("MDSAttrParser: CFBundleCopyResourceURLsOfType screwup 2");
128 continue;
129 }
130
131 // @@@ Workaround for 4234967: skip any filename beginning with "._"
132 CFRef<CFStringRef> lastComponent = CFURLCopyLastPathComponent(infoUrl);
133 if (lastComponent) {
134 CFStringRef resFilePfx = CFSTR("._");
135 // setting the search length and location like this permits,
136 // e.g., ".foo.mdsinfo" to be valid
137 CFIndex resFilePfxLen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(resFilePfx), kCFStringEncodingUTF8);
138 CFRange range = CFRangeMake(0, resFilePfxLen);
139 Boolean skip = CFStringFindWithOptions(lastComponent,
140 resFilePfx,
141 range,
142 0/*options*/,
143 NULL/*returned substr*/);
144 if (skip == true) {
145 Syslog::warning("MDSAttrParser: ignoring resource file");
146 continue;
147 }
148 }
149
150 parseFile(infoUrl, subdir);
151 } /* for each mdsinfo */
152 }
153
154 void MDSAttrParser::parseFile(CFURLRef infoUrl, CFStringRef subdir)
155 {
156 CFStringRef infoType = NULL;
157
158 /* Get contents of mdsinfo file as dictionary */
159 MDSDictionary mdsDict(infoUrl, subdir, mPath);
160 /* Make sure we set all possible MDS values before checking for GUID */
161 mdsDict.setDefaults(mDefaults);
162 if (mGuid == NULL) {
163 CFStringRef guid = (CFStringRef)mdsDict.lookup("ModuleID", true, CFStringGetTypeID());
164 if (guid) {
165 CFIndex copylen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(guid), kCFStringEncodingUTF8) + 1/*nul terminator*/;
166 mGuid = new char[copylen];
167 if (false == CFStringGetCString(guid, mGuid, copylen, kCFStringEncodingUTF8)) {
168 logFileError("Error copying GUID", infoUrl, NULL, NULL);
169 delete [] mGuid;
170 mGuid = NULL;
171 CssmError::throwMe(CSSM_ERRCODE_MDS_ERROR);
172 }
173 }
174 else {
175 logFileError("No GUID associated with plugin?", infoUrl, NULL, NULL);
176 CssmError::throwMe(CSSM_ERRCODE_MDS_ERROR);
177 }
178 }
179
180 MPDebug("Parsing mdsinfo file %s", mdsDict.fileDesc());
181
182 /* Determine what kind of info file this is and dispatch accordingly */
183 infoType = (CFStringRef)mdsDict.lookup(CFSTR(MDS_INFO_FILE_TYPE),
184 true, CFStringGetTypeID());
185 if(infoType == NULL) {
186 logFileError("Malformed MDS Info file", infoUrl, NULL, NULL);
187 CssmError::throwMe(CSSM_ERRCODE_MDS_ERROR);
188 }
189
190 /* be robust here, errors in these low-level routines do not affect
191 * the rest of our task */
192 try {
193 if(CFStringCompare(infoType, CFSTR(MDS_INFO_FILE_TYPE_CSSM), 0)
194 == kCFCompareEqualTo) {
195 parseCssmInfo(&mdsDict);
196 }
197 else if(CFStringCompare(infoType, CFSTR(MDS_INFO_FILE_TYPE_PLUGIN), 0)
198 == kCFCompareEqualTo) {
199 parsePluginCommon(&mdsDict);
200 }
201 else if(CFStringCompare(infoType, CFSTR(MDS_INFO_FILE_TYPE_RECORD), 0)
202 == kCFCompareEqualTo) {
203 parsePluginSpecific(&mdsDict);
204 }
205 else {
206 logFileError("Malformed MDS Info file", infoUrl, NULL, NULL);
207 }
208 }
209 catch(...) {
210
211 }
212 }
213
214 void MDSAttrParser::logFileError(
215 const char *op,
216 CFURLRef fileUrl,
217 CFStringRef errStr, // optional if you have it
218 SInt32 *errNo) // optional if you have it
219 {
220 CFStringRef urlStr = CFURLGetString(fileUrl);
221 const char *cUrlStr = CFStringGetCStringPtr(urlStr, kCFStringEncodingUTF8);
222 char* stringBuffer = NULL;
223
224 if (cUrlStr == NULL)
225 {
226 CFIndex maxLen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(urlStr), kCFStringEncodingUTF8) + 1;
227 stringBuffer = (char*) malloc(maxLen);
228 CFStringGetCString(urlStr, stringBuffer, maxLen, kCFStringEncodingUTF8);
229 cUrlStr = stringBuffer;
230 }
231
232 if(errStr) {
233 const char *cerrStr = CFStringGetCStringPtr(errStr, kCFStringEncodingUTF8);
234 char* sbuf2 = NULL;
235
236 if (cerrStr == NULL)
237 {
238 CFIndex maxLen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(errStr), kCFStringEncodingUTF8) + 1;
239 sbuf2 = (char*) malloc(maxLen);
240 CFStringGetCString(urlStr, sbuf2, maxLen, kCFStringEncodingUTF8);
241 cUrlStr = sbuf2;
242 }
243
244 Syslog::alert("MDS: %s: bundle %s url %s: error %s",
245 op, mPath, cUrlStr, cerrStr);
246
247 if (sbuf2 != NULL)
248 {
249 free(sbuf2);
250 }
251 }
252 else {
253 Syslog::alert("MDS: %s: bundle %s url %s: error %d",
254 op, mPath, cUrlStr, (int)(errNo ? *errNo : 0));
255 }
256
257 if (stringBuffer != NULL)
258 {
259 free(stringBuffer);
260 }
261 }
262
263 /*
264 * Parse a CSSM info file.
265 */
266 void MDSAttrParser::parseCssmInfo(
267 MDSDictionary *mdsDict)
268 {
269 /* first get object info */
270 parseObjectRecord(mdsDict);
271
272 /* now CSSM relation */
273 const RelationInfo *relationInfo =
274 MDSRecordTypeToRelation(MDS_CDSADIR_CSSM_RECORDTYPE);
275 assert(relationInfo != NULL);
276 parseMdsRecord(mdsDict, relationInfo, mCdsaDirHand);
277 }
278
279 /*
280 * Parse a PluginCommon file.
281 */
282 void MDSAttrParser::parsePluginCommon(
283 MDSDictionary *mdsDict)
284 {
285
286 /* first get object info */
287 parseObjectRecord(mdsDict);
288
289 /* now common relation */
290 const RelationInfo *relationInfo =
291 MDSRecordTypeToRelation(MDS_CDSADIR_COMMON_RECORDTYPE);
292 assert(relationInfo != NULL);
293 parseMdsRecord(mdsDict, relationInfo, mCdsaDirHand);
294 }
295
296 /*
297 * Parse a Plugin Specific file.
298 */
299 void MDSAttrParser::parsePluginSpecific(
300 MDSDictionary *mdsDict)
301 {
302 /* determine record type from the file itself */
303 CFStringRef recordTypeStr =
304 (CFStringRef)mdsDict->lookup(MDS_INFO_FILE_RECORD_TYPE,
305 true, CFStringGetTypeID());
306 if(recordTypeStr == NULL) {
307 MPDebug("%s: no %s record found\n", mdsDict->fileDesc(),
308 MDS_INFO_FILE_RECORD_TYPE);
309 return;
310 }
311
312 /* convert to a known schema */
313 const char *recordTypeCStr = MDSCFStringToCString(recordTypeStr);
314 const RelationInfo *relationInfo = MDSRecordTypeNameToRelation(recordTypeCStr);
315 if(relationInfo == NULL) {
316 Syslog::alert("MDS file %s has unsupported record type %s",
317 mdsDict->fileDesc(), recordTypeCStr);
318 MPDebug("MDS file %s has unsupported record type %s",
319 mdsDict->fileDesc(), recordTypeCStr);
320 delete [] recordTypeCStr;
321 return;
322 }
323 MPDebug("Parsing MDS file %s, recordType %s", mdsDict->fileDesc(), recordTypeCStr);
324 delete [] recordTypeCStr;
325
326 /* handle special cases here */
327 switch(relationInfo->DataRecordType) {
328 case MDS_CDSADIR_CSP_CAPABILITY_RECORDTYPE:
329 parseCspCapabilitiesRecord(mdsDict);
330 break;
331 case MDS_CDSADIR_TP_OIDS_RECORDTYPE:
332 parseTpPolicyOidsRecord(mdsDict);
333 break;
334 default:
335 /* all (normal) linear schema */
336 parseMdsRecord(mdsDict, relationInfo, mCdsaDirHand);
337 }
338 }
339
340
341 /*
342 * Given an open MDSDictionary, create an MDS_OBJECT_RECORDTYPE record and
343 * add it to mObjectHand. Used when parsing both CSSM records and MOduleCommon
344 * records.
345 */
346 void MDSAttrParser::parseObjectRecord(
347 MDSDictionary *mdsDict)
348 {
349 assert(mdsDict != NULL);
350 assert(mObjectHand != 0);
351 parseMdsRecord(mdsDict, &kObjectRelation, mObjectHand);
352
353 }
354
355 /*
356 * Given an open dictionary and a RelationInfo defining a schema, fetch all
357 * attributes associated with the specified schema from the dictionary
358 * and write them to specified DB.
359 */
360 void MDSAttrParser::parseMdsRecord(
361 MDSDictionary *mdsDict,
362 const RelationInfo *relInfo,
363 CSSM_DB_HANDLE dbHand)
364 {
365 assert(mdsDict != NULL);
366 assert(relInfo != NULL);
367 assert(dbHand != 0);
368
369 /*
370 * malloc an CSSM_DB_ATTRIBUTE_DATA array associated with specified schema.
371 */
372 unsigned numSchemaAttrs = relInfo->NumberOfAttributes;
373 CSSM_DB_ATTRIBUTE_DATA *dbAttrs = new CSSM_DB_ATTRIBUTE_DATA[numSchemaAttrs];
374
375 /*
376 * Grind thru the attributes in the specified schema. Do not assume the presence
377 * of any given attribute.
378 */
379 uint32 foundAttrs = 0;
380 mdsDict->lookupAttributes(relInfo, dbAttrs, foundAttrs);
381
382 /* write to the DB */
383 MDSInsertRecord(dbAttrs, foundAttrs, relInfo->DataRecordType, mDl, dbHand);
384
385 MDSFreeDbRecordAttrs(dbAttrs, foundAttrs);
386 delete [] dbAttrs;
387 }
388
389 /*
390 * Parse CSP capabilities. This is much more complicated than most records.
391 * The propertly list (*.mdsinfo) is set up like this:
392 *
393 * root(Dictionary) {
394 * ModuleID(String)
395 * SSID(Number)
396 * Capabilities(Array) {
397 * index 0(Dictionary) {
398 * AlgType(String) -- CSSM_ALGID_SHA1
399 * ContextType(String) -- CSSM_ALGCLASS_DIGEST
400 * UseeTag(String) -- CSSM_USEE_NONE
401 * Description(String) -- "SHA1 Digest"
402 * Attributes(Array)
403 * index 0(Dictionary)
404 * AttributeType(String) -- CSSM_ATTRIBUTE_OUTPUT_SIZE
405 * AttributeValue(Array) {
406 * index 0(Number) -- 20
407 * ...
408 * }
409 * index n ...
410 * }
411 * index n...
412 * }
413 * }
414 *
415 * The plist can specify multiple Capabilities, multiple Attributes for each
416 * Capability, and multiple values for each Attribute. (Note that MULTI_UINT32
417 * in the DB is represented in the plist as an Array of Numbers.) Each element
418 * of each Attributes array maps to one record in the DB. The GroupID attribute
419 * of a record is the index into the plist's Capabilities array.
420 */
421 void MDSAttrParser::parseCspCapabilitiesRecord(
422 MDSDictionary *mdsDict)
423 {
424 /*
425 * Malloc an attribute array big enough for the whole schema. We're going
426 * to re-use this array every time we write a new record. Portions of
427 * the array are invariant for some inner loops.
428 */
429 const RelationInfo *topRelInfo =
430 MDSRecordTypeToRelation(MDS_CDSADIR_CSP_CAPABILITY_RECORDTYPE);
431 assert(topRelInfo != NULL);
432 uint32 numInAttrs = topRelInfo->NumberOfAttributes;
433 CSSM_DB_ATTRIBUTE_DATA_PTR outAttrs = new CSSM_DB_ATTRIBUTE_DATA[numInAttrs];
434
435 /* these attrs are only set once, then they remain invariant */
436 uint32 numTopLevelAttrs;
437 mdsDict->lookupAttributes(&CSPCapabilitiesDict1RelInfo, outAttrs,
438 numTopLevelAttrs);
439
440 /* obtain Capabilities array */
441 CFRef<CFArrayRef> capArray = (CFArrayRef)mdsDict->lookupWithIndirect("Capabilities",
442 mBundle,
443 CFArrayGetTypeID());
444 if(!capArray) {
445 /* well we did not get very far.... */
446 MPDebug("parseCspCapabilitiesRecord: no (or bad) Capabilities");
447 delete [] outAttrs;
448 return;
449 }
450
451 /*
452 * Descend into Capabilities array. Each element is a dictionary defined
453 * by CSPCapabilitiesDict2RelInfo.
454 */
455 CFIndex capArraySize = CFArrayGetCount(capArray);
456 CFIndex capDex;
457 for(capDex=0; capDex<capArraySize; capDex++) {
458 MPDebug("...parsing Capability %d", (int)capDex);
459 CFDictionaryRef capDict =
460 (CFDictionaryRef)CFArrayGetValueAtIndex(capArray, capDex);
461 if((capDict == NULL) ||
462 (CFGetTypeID(capDict) != CFDictionaryGetTypeID())) {
463 MPDebug("parseCspCapabilitiesRecord: bad Capabilities element");
464 break;
465 }
466 MDSDictionary capDictMds(capDict);
467
468 /*
469 * Append this dictionary's attributes to outAttrs, after the fixed
470 * attributes from CSPCapabilitiesDict1RelInfo.
471 */
472 uint32 numCapDictAttrs;
473 capDictMds.lookupAttributes(&CSPCapabilitiesDict2RelInfo,
474 &outAttrs[numTopLevelAttrs],
475 numCapDictAttrs);
476
477 /*
478 * Append the GroupId attribute, which we infer from the current index
479 * into Capabilitites. However, thou shalt not use > 4-byte values
480 * for MDS, so convert from CFIndex first.
481 */
482 if (capDex > uint32(~0)) {
483 MPDebug("parseCspCapabilitiesRecord: too large an index for MDS");
484 break;
485 }
486 uint32 index32 = uint32(capDex);
487 MDSRawValueToDbAttr(&index32, sizeof(index32), CSSM_DB_ATTRIBUTE_FORMAT_UINT32,
488 "GroupId", outAttrs[numTopLevelAttrs + numCapDictAttrs]);
489 numCapDictAttrs++;
490
491 /*
492 * Now descend into the array of this capability's attributes.
493 * Each element is a dictionary defined by
494 * by CSPCapabilitiesDict3RelInfo.
495 */
496 CFArrayRef attrArray = (CFArrayRef)capDictMds.lookup("Attributes",
497 true, CFArrayGetTypeID());
498 if(attrArray == NULL) {
499 MPDebug("parseCspCapabilitiesRecord: no (or bad) Attributes");
500 break;
501 }
502 CFIndex attrArraySize = CFArrayGetCount(attrArray);
503 CFIndex attrDex;
504 for(attrDex=0; attrDex<attrArraySize; attrDex++) {
505 MPDebug(" ...parsing Attribute %d", (int)attrDex);
506 CFDictionaryRef attrDict =
507 (CFDictionaryRef)CFArrayGetValueAtIndex(attrArray, attrDex);
508 if((attrDict == NULL) ||
509 (CFGetTypeID(attrDict) != CFDictionaryGetTypeID())) {
510 MPDebug("parseCspCapabilitiesRecord: bad Attributes element");
511 break;
512 }
513 MDSDictionary attrDictMds(attrDict);
514
515 /*
516 * Append this dictionary's attributes to outAttrs, after the fixed
517 * attributes from CSPCapabilitiesDict1RelInfo and this capability's
518 * CSPCapabilitiesDict2RelInfo.
519 */
520 uint32 numAttrDictAttrs;
521 attrDictMds.lookupAttributes(&CSPCapabilitiesDict3RelInfo,
522 &outAttrs[numTopLevelAttrs + numCapDictAttrs],
523 numAttrDictAttrs);
524
525 /* write to DB */
526 MDSInsertRecord(outAttrs,
527 numTopLevelAttrs + numCapDictAttrs + numAttrDictAttrs,
528 MDS_CDSADIR_CSP_CAPABILITY_RECORDTYPE,
529 mDl,
530 mCdsaDirHand);
531
532 /* just free the attrs we allocated in this loop */
533 MDSFreeDbRecordAttrs(&outAttrs[numTopLevelAttrs + numCapDictAttrs],
534 numAttrDictAttrs);
535 } /* for each attribute */
536 /* just free the attrs we allocated in this loop */
537 MDSFreeDbRecordAttrs(&outAttrs[numTopLevelAttrs], numCapDictAttrs);
538 } /* for each capability */
539
540 MDSFreeDbRecordAttrs(outAttrs, numTopLevelAttrs);
541 delete [] outAttrs;
542 }
543
544 /*
545 * Parse TP Policy OIDs.
546 * The propertly list (*.mdsinfo) is set up like this:
547 *
548 * root(Dictionary) {
549 * ModuleID(String)
550 * SSID(Number)
551 * Policies(Array) {
552 * index 0(Dictionary) {
553 * OID(Data) -- <092a8648 86f76364 0102>
554 * Value(Data) -- optional, OID-specific
555 * index n...
556 * }
557 * }
558 *
559 * The plist can specify multiple Policies. Each element of the Policies
560 * array maps to one record in the DB.
561 */
562 void MDSAttrParser::parseTpPolicyOidsRecord(
563 MDSDictionary *mdsDict)
564 {
565 /*
566 * Malloc an attribute array big enough for the whole schema. We're going
567 * to re-use this array every time we write a new record. Portions of
568 * the array are invariant for some inner loops.
569 */
570 const RelationInfo *topRelInfo =
571 MDSRecordTypeToRelation(MDS_CDSADIR_TP_OIDS_RECORDTYPE);
572 assert(topRelInfo != NULL);
573 uint32 numInAttrs = topRelInfo->NumberOfAttributes;
574 CSSM_DB_ATTRIBUTE_DATA_PTR outAttrs = new CSSM_DB_ATTRIBUTE_DATA[numInAttrs];
575
576 /* these attrs are only set once, then they remain invariant */
577 uint32 numTopLevelAttrs;
578 mdsDict->lookupAttributes(&TpPolicyOidsDict1RelInfo, outAttrs,
579 numTopLevelAttrs);
580
581 /* obtain Policies array */
582 CFArrayRef policyArray = (CFArrayRef)mdsDict->lookup("Policies",
583 true, CFArrayGetTypeID());
584 if(policyArray == NULL) {
585 /* well we did not get very far.... */
586 MPDebug("parseTpPolicyOidsRecord: no (or bad) Policies");
587 delete [] outAttrs;
588 return;
589 }
590
591 /*
592 * Descend into Policies array. Each element is a dictionary defined
593 * by TpPolicyOidsDict2RelInfo.
594 */
595 CFIndex policyArraySize = CFArrayGetCount(policyArray);
596 CFIndex policyDex;
597 for(policyDex=0; policyDex<policyArraySize; policyDex++) {
598 MPDebug("...parsing Policy %d", (int)policyDex);
599 CFDictionaryRef policyDict =
600 (CFDictionaryRef)CFArrayGetValueAtIndex(policyArray, policyDex);
601 if((policyDict == NULL) ||
602 (CFGetTypeID(policyDict) != CFDictionaryGetTypeID())) {
603 MPDebug("parseTpPolicyOidsRecord: bad Policies element");
604 break;
605 }
606 MDSDictionary policyDictMds(policyDict);
607
608 /*
609 * Append this dictionary's attributes to outAttrs, after the fixed
610 * attributes from TpPolicyOidsDict1RelInfo.
611 */
612 uint32 numPolicyDictAttrs;
613 policyDictMds.lookupAttributes(&TpPolicyOidsDict2RelInfo,
614 &outAttrs[numTopLevelAttrs],
615 numPolicyDictAttrs);
616
617
618 /* write to DB */
619 MDSInsertRecord(outAttrs,
620 numTopLevelAttrs + numPolicyDictAttrs,
621 MDS_CDSADIR_TP_OIDS_RECORDTYPE,
622 mDl,
623 mCdsaDirHand);
624
625 /* free the attrs allocated in this loop */
626 MDSFreeDbRecordAttrs(outAttrs + numTopLevelAttrs, numPolicyDictAttrs);
627 } /* for each policy */
628 MDSFreeDbRecordAttrs(outAttrs, numTopLevelAttrs);
629 delete [] outAttrs;
630 }
631
632
633 } // end namespace Security