3 #include "attributes.h" 
   4 #include <security_cdsa_client/multidldb.h> 
   6 #include <security_cdsa_client/securestorage.h> // For CSPDL. 
   7 #include <security_cdsa_client/genkey.h> 
   8 #include <security_utilities/trackingallocator.h> 
  10 using namespace CssmClient
; 
  13 #define HEX_DIGITS_PER_LINE  20 
  17 const CSSM_GUID
* gSelectedFileGuid 
= &gGuidAppleFileDL
; 
  21 static void testDLCreate(const Guid 
&dlGuid
); 
  22 static void testDLDelete(const Guid 
&dlGuid
, bool throwOnError
); 
  23 static void testGen(const Guid 
&cspDlGuid
); 
  24 static void testDLCrypt(const Guid 
&cspDlGuid
); 
  25 static void testMultiDLDb(const Guid 
&dlGuid
); 
  26 static void dumpRelation(uint32 indent
, Db 
&db
, uint32 relationID
, const char *relationName
, bool printSchema
); 
  27 static void dumpRecord(uint32 indent
, const DbAttributes 
&record
, const CssmData 
&data
, const DbUniqueRecord 
&uniqueId
); 
  29 #define CSSM_DB_RELATION(RELATIONID) RecordAttrInfo ## RELATIONID 
  31 #define CSSM_DB_DEFINE_RELATION_BEGIN(RELATIONID) \ 
  32 static const CSSM_DB_ATTRIBUTE_INFO AttrInfo ## RELATIONID[] = 
  34 #define CSSM_DB_DEFINE_RELATION_END(RELATIONID) \ 
  36 static const CSSM_DB_RECORD_ATTRIBUTE_INFO CSSM_DB_RELATION(RELATIONID) = \ 
  39     sizeof(AttrInfo ## RELATIONID) / sizeof(CSSM_DB_ATTRIBUTE_INFO), \ 
  40     const_cast<CSSM_DB_ATTRIBUTE_INFO_PTR>(AttrInfo ## RELATIONID) \ 
  44 CSSM_DB_DEFINE_RELATION_BEGIN(CSSM_DL_DB_RECORD_GENERIC_PASSWORD
) 
  46         CSSM_DB_ATTR(Attributes::Class
),  
  47         CSSM_DB_ATTR(Attributes::CreationDate
),  
  48         CSSM_DB_ATTR(Attributes::ModDate
),  
  49         CSSM_DB_ATTR(Attributes::Description
), 
  50         CSSM_DB_ATTR(Attributes::Comment
), 
  51         CSSM_DB_ATTR(Attributes::Creator
), 
  52         CSSM_DB_ATTR(Attributes::Type
), 
  53         CSSM_DB_ATTR(Attributes::ScrCode
), 
  54         CSSM_DB_ATTR(Attributes::Label
), 
  55         CSSM_DB_ATTR(Attributes::Invisible
), 
  56         CSSM_DB_ATTR(Attributes::Negative
), 
  57         CSSM_DB_ATTR(Attributes::Custom
), 
  58         //CSSM_DB_ATTR(Attributes::Protected), 
  59         CSSM_DB_ATTR(Attributes::Account
), 
  60         CSSM_DB_ATTR(Attributes::Service
), 
  61         CSSM_DB_ATTR(Attributes::Generic
) 
  63 CSSM_DB_DEFINE_RELATION_END(CSSM_DL_DB_RECORD_GENERIC_PASSWORD
); 
  66 // APPLESHARE PASSWORDS 
  67 CSSM_DB_DEFINE_RELATION_BEGIN(CSSM_DL_DB_RECORD_APPLESHARE_PASSWORD
) 
  69         CSSM_DB_ATTR(Attributes::Class
),  
  70         CSSM_DB_ATTR(Attributes::CreationDate
),  
  71         CSSM_DB_ATTR(Attributes::ModDate
),  
  72         CSSM_DB_ATTR(Attributes::Description
), 
  73         CSSM_DB_ATTR(Attributes::Comment
), 
  74         CSSM_DB_ATTR(Attributes::Creator
), 
  75         CSSM_DB_ATTR(Attributes::Type
), 
  76         CSSM_DB_ATTR(Attributes::ScrCode
), 
  77         CSSM_DB_ATTR(Attributes::Label
), 
  78         CSSM_DB_ATTR(Attributes::Invisible
), 
  79         CSSM_DB_ATTR(Attributes::Negative
), 
  80         CSSM_DB_ATTR(Attributes::Custom
), 
  81         //CSSM_DB_ATTR(Attributes::Protected), 
  82         CSSM_DB_ATTR(Attributes::Volume
), 
  83         CSSM_DB_ATTR(Attributes::Addr
), 
  84         CSSM_DB_ATTR(Attributes::Signature
), 
  85         CSSM_DB_ATTR(Attributes::ProtocolType
) 
  87 CSSM_DB_DEFINE_RELATION_END(CSSM_DL_DB_RECORD_APPLESHARE_PASSWORD
); 
  90 CSSM_DB_DEFINE_RELATION_BEGIN(CSSM_DL_DB_RECORD_INTERNET_PASSWORD
) 
  92         CSSM_DB_ATTR(Attributes::Class
),  
  93         CSSM_DB_ATTR(Attributes::CreationDate
),  
  94         CSSM_DB_ATTR(Attributes::ModDate
),  
  95         CSSM_DB_ATTR(Attributes::Description
), 
  96         CSSM_DB_ATTR(Attributes::Comment
), 
  97         CSSM_DB_ATTR(Attributes::Creator
), 
  98         CSSM_DB_ATTR(Attributes::Type
), 
  99         CSSM_DB_ATTR(Attributes::ScrCode
), 
 100         CSSM_DB_ATTR(Attributes::Label
), 
 101         CSSM_DB_ATTR(Attributes::Invisible
), 
 102         CSSM_DB_ATTR(Attributes::Negative
), 
 103         CSSM_DB_ATTR(Attributes::Custom
), 
 104         //CSSM_DB_ATTR(Attributes::Protected), 
 105         CSSM_DB_ATTR(Attributes::Account
), 
 106         CSSM_DB_ATTR(Attributes::SecDomain
), 
 107         CSSM_DB_ATTR(Attributes::Server
), 
 108         CSSM_DB_ATTR(Attributes::AuthType
), 
 109         CSSM_DB_ATTR(Attributes::Port
), 
 110         CSSM_DB_ATTR(Attributes::Path
), 
 111         CSSM_DB_ATTR(Attributes::ProtocolType
) 
 113 CSSM_DB_DEFINE_RELATION_END(CSSM_DL_DB_RECORD_INTERNET_PASSWORD
); 
 115 // INTERNET PASSWORDS 
 116 CSSM_DB_DEFINE_RELATION_BEGIN(CSSM_DL_DB_RECORD_SYMMETRIC_KEY
) 
 118         CSSM_DB_ATTR(Attributes::KeyClass
), 
 119         CSSM_DB_ATTR(Attributes::PrintName
), 
 120         CSSM_DB_ATTR(Attributes::Alias
), 
 121         CSSM_DB_ATTR(Attributes::Permanent
), 
 122         CSSM_DB_ATTR(Attributes::Private
), 
 123         CSSM_DB_ATTR(Attributes::Modifiable
), 
 124         CSSM_DB_ATTR(Attributes::Label
), 
 125         CSSM_DB_ATTR(Attributes::ApplicationTag
), 
 126         CSSM_DB_ATTR(Attributes::KeyCreator
), 
 127         CSSM_DB_ATTR(Attributes::KeyType
), 
 128         CSSM_DB_ATTR(Attributes::KeySizeInBits
), 
 129         CSSM_DB_ATTR(Attributes::EffectiveKeySize
), 
 130         CSSM_DB_ATTR(Attributes::StartDate
), 
 131         CSSM_DB_ATTR(Attributes::EndDate
), 
 132         CSSM_DB_ATTR(Attributes::Sensitive
), 
 133         CSSM_DB_ATTR(Attributes::AlwaysSensitive
), 
 134         CSSM_DB_ATTR(Attributes::Extractable
), 
 135         CSSM_DB_ATTR(Attributes::NeverExtractable
), 
 136         CSSM_DB_ATTR(Attributes::Encrypt
), 
 137         CSSM_DB_ATTR(Attributes::Decrypt
), 
 138         CSSM_DB_ATTR(Attributes::Derive
), 
 139         CSSM_DB_ATTR(Attributes::Sign
), 
 140         CSSM_DB_ATTR(Attributes::Verify
), 
 141         CSSM_DB_ATTR(Attributes::SignRecover
), 
 142         CSSM_DB_ATTR(Attributes::VerifyRecover
), 
 143         CSSM_DB_ATTR(Attributes::Wrap
), 
 144         CSSM_DB_ATTR(Attributes::UnWrap
) 
 146 CSSM_DB_DEFINE_RELATION_END(CSSM_DL_DB_RECORD_SYMMETRIC_KEY
); 
 149 static const CSSM_DB_RECORD_ATTRIBUTE_INFO KCAttrs
[] = 
 151         CSSM_DB_RELATION(CSSM_DL_DB_RECORD_GENERIC_PASSWORD
), 
 152         CSSM_DB_RELATION(CSSM_DL_DB_RECORD_APPLESHARE_PASSWORD
), 
 153         CSSM_DB_RELATION(CSSM_DL_DB_RECORD_INTERNET_PASSWORD
) 
 154         //CSSM_DB_RELATION(CSSM_DL_DB_RECORD_SYMMETRIC_KEY) 
 157 static const CSSM_DB_RECORD_INDEX_INFO recordIndex 
=  
 159     CSSM_DB_RECORDTYPE_APP_DEFINED_START
, // CSSM_DB_RECORDTYPE 
 163 static const    CSSM_DB_RECORD_INDEX_INFO recordIndexes
[] = {recordIndex
, recordIndex
, recordIndex
}; 
 165 // parse info (to improve later) 
 166 static const        CSSM_DB_PARSING_MODULE_INFO parseInfo 
= 
 168     CSSM_DB_RECORDTYPE_APP_DEFINED_START
, 
 176 static const    CSSM_DB_PARSING_MODULE_INFO parseInfos
[] = {parseInfo
, parseInfo
, parseInfo
}; 
 178 static const CSSM_DBINFO        KCDBInfo 
= 
 180     sizeof(KCAttrs
) / sizeof(CSSM_DB_RECORD_ATTRIBUTE_INFO
), 
 181     const_cast<CSSM_DB_PARSING_MODULE_INFO_PTR
>(parseInfos
), 
 182     const_cast<CSSM_DB_RECORD_ATTRIBUTE_INFO_PTR
>(KCAttrs
), 
 183     const_cast<CSSM_DB_RECORD_INDEX_INFO_PTR
>(recordIndexes
), 
 191 void dltests(bool autoCommit
) 
 193         testDLDelete(gGuidAppleFileDL
, false); 
 194         testDLCreate(gGuidAppleFileDL
); 
 195         testMultiDLDb(gGuidAppleFileDL
); 
 197         testDLDelete(gGuidAppleCSPDL
, false); 
 198         testDLCreate(gGuidAppleCSPDL
); 
 199         testGen(gGuidAppleCSPDL
); 
 200         testDLCrypt(gGuidAppleCSPDL
); 
 201         testMultiDLDb(gGuidAppleCSPDL
); 
 202         //testDLDelete(gGuidAppleCSPDL, true); 
 205 static void testDLCreate(const Guid 
&dlGuid
) 
 208         Db 
testDb(appledl
, DBNAME1
); 
 209         testDb
->dbInfo(&KCDBInfo
); 
 213 static void testDLDelete(const Guid 
&dlGuid
, bool throwOnError
) 
 216         Db 
testDb(appledl
, DBNAME1
); 
 223                 if (throwOnError 
|| e
.osStatus() != CSSMERR_DL_DATASTORE_DOESNOT_EXIST
) 
 228 static void testGen(const Guid 
&cspDlGuid
) 
 230         printf("\n* performing CSP/DL keygen test...\n"); 
 231         CSPDL 
cspdl(cspDlGuid
); 
 232         Db 
db(cspdl
, DBNAME1
); 
 234     printf("Generating permanent key\n"); 
 235         GenerateKey 
genKey(cspdl
, CSSM_ALGID_DES
, 64); 
 237         CssmPolyData 
label("First Key!"); 
 238         Key key 
= genKey(KeySpec(CSSM_KEYUSE_ANY
, 
 239                                                          CSSM_KEYATTR_PERMANENT 
| CSSM_KEYATTR_SENSITIVE
, 
 244 static void testDLCrypt(const Guid 
&cspDlGuid
) 
 246     printf("\n* performing encrypt/decrypt test...\n"); 
 247         CSPDL 
cspdl(cspDlGuid
); 
 248         Db 
db(cspdl
, DBNAME1
); 
 250     printf("Finding key\n"); 
 252         cursor
->recordType(CSSM_DL_DB_RECORD_SYMMETRIC_KEY
); 
 253         DbUniqueRecord keyId
; 
 254         CssmDataContainer keyData
; 
 255         if (!cursor
->next(NULL
, &keyData
, keyId
)) 
 256                 CssmError::throwMe(CSSMERR_DL_ENDOFDATA
); 
 258         Key 
key(cspdl
, *reinterpret_cast<CSSM_KEY 
*>(keyData
.Data
)); 
 263     printf("Generating iv\n"); 
 264         //CssmData iv = Random(csp, CSSM_ALGID_SHARandom)(8); 
 265         CssmPolyData 
iv("12345678"); 
 267         CssmPolyData 
in("Om mani padme hum"); 
 272     printf("Encrypting\n"); 
 274         Encrypt 
encrypt(cspdl
, CSSM_ALGID_DES
); 
 275         encrypt
.mode(CSSM_ALGMODE_CBCPadIV8
); 
 276         encrypt
.padding(CSSM_PADDING_PKCS1
); 
 277         encrypt
.initVector(iv
); 
 281         encrypt
.encrypt(&in
, 1, &cipher
, 1); 
 282         encrypt
.final(remcipher
); 
 283         printf("ciphertext="); 
 285         printf("remainder="); 
 289     printf("Decrypting\n"); 
 291         Decrypt 
decrypt(cspdl
, CSSM_ALGID_DES
); 
 293         decrypt
.mode(CSSM_ALGMODE_CBCPadIV8
); 
 294         decrypt
.padding(CSSM_PADDING_PKCS1
); 
 295         decrypt
.initVector(iv
); 
 298         CssmData inp
[] = { cipher
, remcipher 
}; 
 299         decrypt
.decrypt(inp
, 2, &plain
, 1); 
 300         decrypt
.final(remplain
); 
 301         printf("plaintext="); 
 303         printf("remainder="); 
 306     printf("end encrypt/decrypt test\n"); 
 309 static void print(sint32 value
) 
 311         printf("%ld", value
); 
 314 static void print(double value
) 
 319 static void print(uint32 value
) 
 321         uint8 
*bytes 
= reinterpret_cast<uint8 
*>(&value
); 
 323         for (uint32 ix 
= 0; ix 
< sizeof(uint32
); ++ix
) 
 324                 if (bytes
[ix
] < 0x20 || bytes
[ix
] > 0x7f) 
 333                 for (uint32 ix 
= 0; ix 
< sizeof(uint32
); ++ix
) 
 336                 printf("' (0x%08lx)", value
); 
 339                 printf("0x%08lx", value
); 
 342 static void printAsString(uint32 indent
, const CSSM_DATA 
&value
) 
 344         printf("%.*s", static_cast<int>(value
.Length
), value
.Data
); 
 347 static void print(uint32 indent
, const char *value
) 
 352 static void printIndent(uint32 indent
) 
 358         for (uint32 ix 
= 0; ix 
< indent
; ++ix
) 
 362 static void printRange(uint32 length
, const uint8 
*data
) 
 364         for (uint32 ix 
= 0; ix 
< HEX_DIGITS_PER_LINE
; ++ix
) 
 366                 if (ix 
&& ix 
% 4 == 0) 
 370                         printf("%02x", static_cast<unsigned int>(data
[ix
])); 
 376         for (uint32 ix 
= 0; ix 
< length
; ++ix
) 
 378                 if (data
[ix
] < 0x20 || data
[ix
] > 0x7f) 
 385 static void print(uint32 indent
, const CSSM_DATA 
&value
) 
 387         if (value
.Length 
== 0) 
 390         if (value
.Length 
> HEX_DIGITS_PER_LINE
) 
 393                 for (ix 
= 0; ix 
< value
.Length 
- HEX_DIGITS_PER_LINE
; ix 
+= HEX_DIGITS_PER_LINE
) 
 396                         printRange(HEX_DIGITS_PER_LINE
, &value
.Data
[ix
]); 
 399                 printRange(value
.Length 
- ix
, &value
.Data
[ix
]); 
 400                 printIndent(indent 
- INDENT_SIZE
); 
 403                 printRange(value
.Length
, value
.Data
); 
 406 static void printOID(uint32 indent
, const CSSM_OID 
&value
) 
 408         print(indent
, value
); 
 411 static const char *format(CSSM_DB_ATTRIBUTE_FORMAT format
) 
 415         case CSSM_DB_ATTRIBUTE_FORMAT_STRING
: return "string"; 
 416         case CSSM_DB_ATTRIBUTE_FORMAT_SINT32
: return "sint32"; 
 417         case CSSM_DB_ATTRIBUTE_FORMAT_UINT32
: return "uint32"; 
 418         case CSSM_DB_ATTRIBUTE_FORMAT_BIG_NUM
: return "big_num"; 
 419         case CSSM_DB_ATTRIBUTE_FORMAT_REAL
: return "real"; 
 420         case CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE
: return "time_date"; 
 421         case CSSM_DB_ATTRIBUTE_FORMAT_BLOB
: return "blob"; 
 422         case CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32
: return "multi_uint32"; 
 423         case CSSM_DB_ATTRIBUTE_FORMAT_COMPLEX
: return "complex"; 
 428 static void print(uint32 indent
, const CssmDbAttributeData 
&attr
) 
 430         bool multiValues 
= false; 
 431         if (attr
.size() == 0) 
 437         if (attr
.size() != 1) 
 441                 indent 
+= INDENT_SIZE
; 
 445         for (uint32 ix 
= 0; ix 
< attr
.size(); ++ix
) 
 450                 printf("<%s>", format(attr
.format())); 
 451                 switch (attr
.format()) 
 453                 case CSSM_DB_ATTRIBUTE_FORMAT_STRING
: 
 454                         printAsString(indent 
+ INDENT_SIZE
, attr
.at(ix
)); 
 456                 case CSSM_DB_ATTRIBUTE_FORMAT_UINT32
: 
 457                         print(attr
.at
<uint32
>(ix
)); 
 459                 case CSSM_DB_ATTRIBUTE_FORMAT_SINT32
: 
 460                         print(attr
.at
<sint32
>(ix
)); 
 462                 case CSSM_DB_ATTRIBUTE_FORMAT_REAL
: 
 463                         print(attr
.at
<double>(ix
)); 
 465                 case CSSM_DB_ATTRIBUTE_FORMAT_TIME_DATE
: 
 466                         printf("%*s", 15, attr
.at
<const char *>(ix
)); 
 468                 case CSSM_DB_ATTRIBUTE_FORMAT_MULTI_UINT32
: 
 469                 case CSSM_DB_ATTRIBUTE_FORMAT_BIG_NUM
: 
 470                 case CSSM_DB_ATTRIBUTE_FORMAT_BLOB
: 
 471                 case CSSM_DB_ATTRIBUTE_FORMAT_COMPLEX
: 
 473                         print(indent 
+ INDENT_SIZE
, attr
.at
<const CssmData 
&>(ix
)); 
 476                 printf("</%s>", format(attr
.format())); 
 481                 indent 
-= INDENT_SIZE
; 
 487 static void print(uint32 indent
, const CssmDbAttributeInfo 
&info
) 
 489                 switch (info
.nameFormat()) 
 491                 case CSSM_DB_ATTRIBUTE_NAME_AS_STRING
: 
 494                         print(indent 
+ INDENT_SIZE
, info
.Label
.AttributeName
); 
 498                 case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER
: 
 501                         print(info
.Label
.AttributeID
); 
 502                         printf("</integer>"); 
 505                 case CSSM_DB_ATTRIBUTE_NAME_AS_OID
: 
 508                         printOID(indent 
+ INDENT_SIZE
, info
.Label
.AttributeOID
); 
 513                         throw Error(CSSMERR_DL_DATABASE_CORRUPT
); 
 517 void dumpDb(char *dbName
, bool printSchema
) 
 519         DL 
appledl(*gSelectedFileGuid
); 
 520         Db 
db(appledl
, dbName
); 
 521         DbCursor 
relations(db
); 
 522         relations
->recordType(CSSM_DL_DB_SCHEMA_INFO
); 
 523         DbAttributes 
schemaRecord(db
, 2); 
 524         schemaRecord
.add(Attributes::RelationID
); 
 525         schemaRecord
.add(Attributes::RelationName
); 
 526         CssmDataContainer data
; 
 527         DbUniqueRecord 
uniqueId(db
); 
 530         printf("<database>"); 
 531         indent 
+= INDENT_SIZE
; 
 533         printf("<name>%s</name>", dbName
); 
 534         while (relations
->next(&schemaRecord
, &data
, uniqueId
)) 
 536                 uint32 relationID 
= schemaRecord
.at(0); 
 537                 if (!printSchema 
&& CSSM_DB_RECORDTYPE_SCHEMA_START 
<= relationID
 
 538                         && relationID 
< CSSM_DB_RECORDTYPE_SCHEMA_END
) 
 542                 printf("<relation>"); 
 543                 string relationName 
= schemaRecord
.at(1); 
 544                 dumpRelation(indent 
+ INDENT_SIZE
, db
, relationID
, relationName
.c_str(), printSchema
); 
 546                 printf("</relation>"); 
 549         indent 
-= INDENT_SIZE
; 
 551         printf("</database>\n"); 
 554 static void dumpRelation(uint32 indent
, Db 
&db
, uint32 relationID
, const char *relationName
, bool printSchema
) 
 556         TrackingAllocator 
anAllocator(Allocator::standard()); 
 560         print(indent 
+ INDENT_SIZE
, relationName
); 
 567         // Create a cursor on the SCHEMA_ATTRIBUTES table for records with RelationID == relationID 
 568         DbCursor 
attributes(db
); 
 569         attributes
->recordType(CSSM_DL_DB_SCHEMA_ATTRIBUTES
); 
 570         attributes
->add(CSSM_DB_EQUAL
, Attributes::RelationID
, relationID
); 
 572         // Set up a record for retriving the SCHEMA_ATTRIBUTES 
 573         DbAttributes 
schemaRecord(db
, 5); 
 574         schemaRecord
.add(Attributes::AttributeNameFormat
); 
 575         schemaRecord
.add(Attributes::AttributeFormat
); 
 576         schemaRecord
.add(Attributes::AttributeName
); 
 577         schemaRecord
.add(Attributes::AttributeID
); 
 578         schemaRecord
.add(Attributes::AttributeNameID
); 
 580         DbAttributes 
record(db
); 
 581         CssmDataContainer data
; 
 582         DbUniqueRecord 
uniqueId(db
); 
 588                 indent 
+= INDENT_SIZE
; 
 591         while (attributes
->next(&schemaRecord
, &data
, uniqueId
)) 
 593                 CssmDbAttributeInfo 
&anInfo 
= record
.add().info(); 
 594                 anInfo
.AttributeNameFormat 
= schemaRecord
.at(0); 
 595                 anInfo
.AttributeFormat 
= schemaRecord
.at(1); 
 596                 switch (anInfo
.AttributeNameFormat
) 
 598                 case CSSM_DB_ATTRIBUTE_NAME_AS_STRING
: 
 600                         CssmDbAttributeData 
&anAttributeName 
= schemaRecord
.at(2); 
 602                         string name 
= static_cast<string
>(anAttributeName
); 
 603                         anInfo
.Label
.AttributeName 
= reinterpret_cast<char *>(anAllocator
.malloc(name
.size() + 1)); 
 604                         strcpy(anInfo
.Label
.AttributeName
, name
.c_str()); 
 606                         // XXX Need to copy the memory.  For now avoid it being freed. 
 607                         anAttributeName
.Value
[0].Data 
= NULL
; 
 608                         anAttributeName
.Value
[0].Length 
= 0; 
 611                 case CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER
: 
 613                         CssmDbAttributeData 
&anAttributeID 
= schemaRecord
.at(3); 
 614                         anInfo
.Label
.AttributeID 
= anAttributeID
; 
 617                 case CSSM_DB_ATTRIBUTE_NAME_AS_OID
: 
 619                         CssmDbAttributeData 
&anAttributeOID 
= schemaRecord
.at(4); 
 620                         anInfo
.Label
.AttributeOID 
= anAttributeOID
; 
 622                         // XXX Need to copy the memory.  For now avoid it being freed. 
 623                         anAttributeOID
.Value
[0].Data 
= NULL
; 
 624                         anAttributeOID
.Value
[0].Length 
= 0; 
 628                         throw Error(CSSMERR_DL_DATABASE_CORRUPT
); 
 634                         print(indent
, anInfo
); 
 635                         printf("<format>%s</format>", format(anInfo
.format())); 
 641                 indent 
-= INDENT_SIZE
; 
 646         DbCursor 
records(db
); 
 647         records
->recordType(relationID
); 
 650         indent 
+= INDENT_SIZE
; 
 651         while (records
->next(&record
, &data
, uniqueId
)) 
 652                 dumpRecord(indent
, record
, data
, uniqueId
); 
 654         indent 
-= INDENT_SIZE
; 
 656         printf("</records>"); 
 660 dumpRecord(uint32 indent
, const DbAttributes 
&record
, const CssmData 
&data
, const DbUniqueRecord 
&uniqueId
) 
 662         const CSSM_DB_UNIQUE_RECORD 
*recId 
= static_cast<const DbUniqueRecord 
&>(uniqueId
); 
 663         uint32 recCount 
= recId
->RecordIdentifier
.Length
; 
 664         const uint32 
*recArray 
= reinterpret_cast<const uint32 
*>(recId
->RecordIdentifier
.Data
); 
 667         for (uint32 ix 
= 0; ix 
< recCount 
/ 4; ++ix
) 
 671                 printf("0x%08lx", recArray
[ix
]); 
 675         // Print the attributes 
 677         if (record
.size() == 0) 
 679                 printf("<attributes/>"); 
 683                 printf("<attributes>"); 
 684                 indent 
+= INDENT_SIZE
; 
 685                 for (uint32 ix 
= 0; ix 
< record
.size(); ix
++) 
 687                         const CssmDbAttributeData 
&anAttr 
= record
.at(ix
); 
 688                         if (anAttr
.size()) // Skip zero valued attributes. 
 691                                 print(indent 
+ INDENT_SIZE
, anAttr
.info()); 
 692                                 print(indent 
+ INDENT_SIZE
, anAttr
); 
 696                 indent 
-= INDENT_SIZE
; 
 698                 printf("</attributes>"); 
 706                 print(indent 
+ INDENT_SIZE
, data
); 
 713 static void testMultiDLDb(const Guid 
&dlGuid
) 
 715         // Setup a list of DLDbIdentifier object to hand off the MultiDLDb. 
 716         vector
<DLDbIdentifier
> list
; 
 717         list
.push_back(DLDbIdentifier(CssmSubserviceUid(dlGuid
), "multidb1.db", NULL
)); 
 718         list
.push_back(DLDbIdentifier(CssmSubserviceUid(dlGuid
), "multidb2.db", NULL
)); 
 720         // Create MultiDLDb instance. 
 721         MultiDLDb 
multiDLDb(list
, false); 
 723         // Get a handle for the first and second Db. 
 724         Db 
db1(multiDLDb
->database(list
[0])); 
 725         Db 
db2(multiDLDb
->database(list
[1])); 
 727         // Until this point no CSSM API's have been called! 
 729         // Delete both databases if they exist.  
 733         { if (e
.osStatus() != CSSMERR_DL_DATASTORE_DOESNOT_EXIST
) throw; } 
 738         { if (e
.osStatus() != CSSMERR_DL_DATASTORE_DOESNOT_EXIST
) throw; } 
 740         // XXX Note to self if you set the schema but do not call create() 
 741         // explicitly maybe the db should only be created if it did not yet exist... 
 743         // Set the schema of both databases so they get created on activate. 
 744         db1
->dbInfo(&KCDBInfo
); 
 745         db2
->dbInfo(&KCDBInfo
); 
 747         // Insert a record into each database. 
 748         DbAttributes 
attrs(db1
); 
 749         attrs
.add(Attributes::Comment
, "This is the first comment").add("This is the second comment", attrs
); 
 750         attrs
.add(Attributes::Label
, "Item1"); 
 751         CssmPolyData 
testdata1("testdata1"); 
 752         db1
->insert(CSSM_DL_DB_RECORD_GENERIC_PASSWORD
, &attrs
, &testdata1
); 
 755         attrs
.add(Attributes::Comment
, "This is the second comment"); 
 756         attrs
.add(Attributes::Label
, "Item (in database2)."); 
 757         CssmPolyData 
testdata2("testdata2"); 
 758         db2
->insert(CSSM_DL_DB_RECORD_GENERIC_PASSWORD
, &attrs
, &testdata2
); 
 760         // Create a cursor on the multiDLDb. 
 761         DbCursor 
cursor(multiDLDb
); 
 762         // Set the type of records we wish to query. 
 763         cursor
->recordType(CSSM_DL_DB_RECORD_GENERIC_PASSWORD
); 
 764         cursor
->add(CSSM_DB_EQUAL
, Attributes::Comment
, "This is the second comment"); 
 766         DbUniqueRecord uniqueId
; // Empty uniqueId calling cursor.next will initialize. 
 767         CssmDataContainer data
; // XXX Think about data's allocator. 
 769         // Iterate over the records in all the db's in the multiDLDb. 
 770         while (cursor
->next(&attrs
, &data
, uniqueId
)) 
 772                 // Print the record data. 
 773                 dumpRecord(0, attrs
, data
, uniqueId
); 
 778         CssmDb::Impl 
*CssmDL::Impl::newDb(args
) { new CssmDbImpl(args
); } 
 780         SecureStorage 
ss(Guid
); 
 781         CssmDb 
db(ss
, DBNAME
); 
 783         db
.insert(attr
, data
, unique
); 
 794         SecureStorage 
ss(Guid
); 
 795         CssmDb db 
= ss
->db(DBNAME
); 
 797         db
->insert(attr
, data
, unique
);