]> git.saurik.com Git - apple/security.git/blobdiff - OSX/libsecurity_cdsa_client/lib/dlclient.cpp
Security-58286.270.3.0.1.tar.gz
[apple/security.git] / OSX / libsecurity_cdsa_client / lib / dlclient.cpp
index 882fde1e21e082de2761d9043d0972c9965e4d4e..3fb96df8d5d27a0cf86b7a8b20fc52d03154ec65 100644 (file)
@@ -24,6 +24,7 @@
 #include <Security/cssmapple.h>
 #include <Security/cssmapplePriv.h>
 #include <Security/SecBase.h>
+#include <security_cdsa_utilities/Schema.h>
 
 using namespace CssmClient;
 
@@ -194,6 +195,7 @@ DbImpl::close()
 void
 DbImpl::activate()
 {
+    StLock<Mutex> _(mActivateMutex);
        if (!mActive)
        {
                if (mDbInfo)
@@ -472,6 +474,88 @@ void DbImpl::setBatchMode(Boolean mode, Boolean rollback)
        }
 }
 
+uint32 DbImpl::dbBlobVersion() {
+    uint32 dbBlobVersion = 0;
+    uint32* dbBlobVersionPtr = &dbBlobVersion;
+
+    // We only have a blob version if we're an apple CSPDL
+    if(dl()->guid() == gGuidAppleCSPDL) {
+        check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_GET_BLOB_VERSION, NULL, (void**) &dbBlobVersionPtr));
+    } else {
+        secnotice("integrity", "Non-Apple CSPDL keychains don't have keychain versions");
+    }
+    return dbBlobVersion;
+}
+
+uint32 DbImpl::recodeDbToVersion(uint32 version) {
+    uint32 newDbVersion;
+    uint32* newDbVersionPtr = &newDbVersion;
+    check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_RECODE_TO_BLOB_VERSION, &version, (void**) &newDbVersionPtr));
+    return newDbVersion;
+}
+
+void DbImpl::recodeFinished() {
+    check(CSSM_DL_PassThrough(handle(), CSSM_APPLECSPDL_DB_RECODE_FINISHED, NULL, NULL));
+}
+
+void DbImpl::takeFileLock() {
+    passThrough(CSSM_APPLECSPDL_DB_TAKE_FILE_LOCK, NULL, NULL);
+}
+
+void DbImpl::releaseFileLock(bool success) {
+    passThrough(CSSM_APPLECSPDL_DB_RELEASE_FILE_LOCK, &success, NULL);
+}
+
+void DbImpl::makeBackup() {
+    passThrough(CSSM_APPLECSPDL_DB_MAKE_BACKUP, NULL, NULL);
+}
+
+void DbImpl::makeCopy(const char* path) {
+    passThrough(CSSM_APPLECSPDL_DB_MAKE_COPY, path, NULL);
+}
+
+void DbImpl::deleteFile() {
+    passThrough(CSSM_APPLECSPDL_DB_DELETE_FILE, NULL, NULL);
+}
+
+void DbImpl::transferTo(const DLDbIdentifier& dldbidentifier) {
+    if (dldbidentifier.ssuid().subserviceType() & CSSM_SERVICE_CSP) {
+        // if we're an Apple CSPDL, do the fancy transfer:
+        //  clone the file, clone the db, remove the original file
+        string oldPath = name();
+
+        CSSM_DB_HANDLE dbhandle;
+        passThrough(CSSM_APPLECSPDL_DB_CLONE, &dldbidentifier, &dbhandle);
+
+        mDbName = dldbidentifier.dbName();
+        mHandle.DBHandle = dbhandle;
+
+        unlink(oldPath.c_str());
+
+        // Don't cache this name
+        if (mNameFromHandle) {
+            allocator().free(mNameFromHandle);
+            mNameFromHandle = NULL;
+        }
+    } else {
+        // if we're not an Apple CSPDL, just call rename
+        this->rename(dldbidentifier.dbName());
+    }
+}
+
+
+// cloneTo only makes sense if you're on an Apple CSPDL
+Db DbImpl::cloneTo(const DLDbIdentifier& dldbidentifier) {
+    CSSM_DB_HANDLE dbhandle;
+    passThrough(CSSM_APPLECSPDL_DB_CLONE, &dldbidentifier, &dbhandle);
+
+    // This is the only reasonable way to make a SSDbImpl at this layer.
+    CssmClient::Db db(dl(), dldbidentifier.dbName(), dldbidentifier.dbLocation());
+    db->mHandle.DBHandle = dbhandle;
+
+    return db;
+}
+
 //
 // DbCursorMaker
 //
@@ -544,7 +628,6 @@ CSSM_HANDLE Db::dlGetFirst(const CSSM_QUERY &query, CSSM_DB_RECORD_ATTRIBUTE_DAT
                return CSSM_INVALID_HANDLE;
        default:
                CssmError::throwMe(rc);
-               return CSSM_INVALID_HANDLE; // placebo
        }
 }
 
@@ -559,7 +642,6 @@ bool Db::dlGetNext(CSSM_HANDLE query, CSSM_DB_RECORD_ATTRIBUTE_DATA &attributes,
                return false;
        default:
                CssmError::throwMe(rc);
-               return false;   // placebo
        }
 }
 
@@ -903,3 +985,34 @@ DbAttributes::DbAttributes(const Db &db, uint32 capacity, Allocator &allocator)
 :  CssmAutoDbRecordAttributeData(capacity, db->allocator(), allocator)
 {
 }
+
+void DbAttributes::updateWithDbAttributes(DbAttributes* newValues) {
+    if(!newValues) {
+        return;
+    }
+
+    canonicalize();
+    newValues->canonicalize();
+
+    updateWith(newValues);
+}
+
+void
+DbAttributes::canonicalize() {
+    for(int i = 0; i < size(); i++) {
+        CssmDbAttributeData& data = attributes()[i];
+        CssmDbAttributeInfo& datainfo = data.info();
+
+        // Calling Schema::attributeInfo is the best way to canonicalize.
+        // There's no way around the try-catch structure, since it throws if it
+        // can't find something.
+
+        try {
+            if(datainfo.nameFormat() == CSSM_DB_ATTRIBUTE_NAME_AS_INTEGER) {
+                data.info() = Security::KeychainCore::Schema::attributeInfo(datainfo.intName());
+            }
+        } catch(...) {
+            // Don't worry about it
+        }
+    }
+}