]> git.saurik.com Git - apple/security.git/blobdiff - OSX/libsecurity_keychain/lib/DLDBListCFPref.cpp
Security-58286.260.20.tar.gz
[apple/security.git] / OSX / libsecurity_keychain / lib / DLDBListCFPref.cpp
index 4836f4dcc37f430c33139d6ce26b56dba9cbaab7..aa168bd8b3d257f6b514296606b21580078e1dda 100644 (file)
@@ -41,6 +41,7 @@
 #include <xpc/private.h>
 #include <syslog.h>
 #include <sandbox.h>
+#include <security_keychain/StorageManager.h>
 
 dispatch_once_t AppSandboxChecked;
 xpc_object_t KeychainHomeFromXPC;
@@ -96,7 +97,7 @@ void PasswordDBLookup::lookupInfoOnUID (uid_t uid)
         mCurrent = uid;
         mTime = currentTime;
 
-        secdebug("secpref", "uid=%d caching home=%s", uid, pw->pw_dir);
+        secinfo("secpref", "uid=%d caching home=%s", uid, pw->pw_dir);
 
         endpwent();
     }
@@ -113,7 +114,7 @@ PasswordDBLookup *DLDbListCFPref::mPdbLookup = NULL;
 DLDbListCFPref::DLDbListCFPref(SecPreferencesDomain domain) : mDomain(domain), mPropertyList(NULL), mChanged(false),
     mSearchListSet(false), mDefaultDLDbIdentifierSet(false), mLoginDLDbIdentifierSet(false)
 {
-    secdebug("secpref", "New DLDbListCFPref %p for domain %d", this, domain);
+    secinfo("secpref", "New DLDbListCFPref %p for domain %d", this, domain);
        loadPropertyList(true);
 }
 
@@ -123,7 +124,7 @@ void DLDbListCFPref::set(SecPreferencesDomain domain)
 
        mDomain = domain;
 
-    secdebug("secpref", "DLDbListCFPref %p domain set to %d", this, domain);
+    secinfo("secpref", "DLDbListCFPref %p domain set to %d", this, domain);
 
        if (loadPropertyList(true))
         resetCachedValues();
@@ -164,7 +165,7 @@ DLDbListCFPref::loadPropertyList(bool force)
                MacOSError::throwMe(errSecInvalidPrefsDomain);
        }
 
-       secdebug("secpref", "force=%s prefsPath=%s", force ? "true" : "false",
+       secinfo("secpref", "force=%s prefsPath=%s", force ? "true" : "false",
                prefsPath.c_str());
 
        CFAbsoluteTime now = CFAbsoluteTimeGetCurrent();
@@ -306,7 +307,7 @@ DLDbListCFPref::writePropertyList()
                // The prefs file should at least be made readable by user/group/other and writable by the owner.
                // Change from euid to ruid if needed for the duration of the new prefs file creat.
                
-               mode_t mode = 0666;
+               mode_t mode = 0644;
                changeIdentity(UNPRIV);
                int fd = open(mPrefsPath.c_str(), O_WRONLY|O_CREAT|O_TRUNC, mode);
                changeIdentity(PRIV);
@@ -341,7 +342,7 @@ DLDbListCFPref::testAndFixPropertyList()
 {
        char *prefsPath = (char *)mPrefsPath.c_str();
        
-       int fd1, fd2, retval;
+       int fd1, retval;
        struct stat stbuf;
 
        if((fd1 = open(prefsPath, O_RDONLY)) < 0) {
@@ -354,20 +355,27 @@ DLDbListCFPref::testAndFixPropertyList()
        if(stbuf.st_uid != getuid()) {
                char tempfile[MAXPATHLEN+1];
 
-               snprintf(tempfile, MAXPATHLEN, "%s.XXXXX", prefsPath);
-               mktemp(tempfile);
-               changeIdentity(UNPRIV);
-               if((fd2 = open(tempfile, O_RDWR | O_CREAT | O_EXCL, 0666)) < 0) {
-                       retval = -1;
+        changeIdentity(UNPRIV);
+
+               snprintf(tempfile, MAXPATHLEN, "%s.XXXXXX", prefsPath);
+               int fd2 = mkstemp(tempfile);
+        if (fd2 < 0 || ::fchmod(fd2, 0644) != 0) {
+            ::unlink(tempfile);
+            retval = -1;
                } else {
                        copyfile_state_t s = copyfile_state_alloc();
                        retval = fcopyfile(fd1, fd2, s, COPYFILE_DATA);
                        copyfile_state_free(s);
-                       if(!retval) retval = ::unlink(prefsPath);
-                       if(!retval) retval = ::rename(tempfile, prefsPath);
+            if (retval) {
+                ::unlink(tempfile);
+            } else {
+                retval = ::unlink(prefsPath);
+                if(!retval) retval = ::rename(tempfile, prefsPath);
+            }
                }
                changeIdentity(PRIV);
-               close(fd2);
+        if (fd2 >= 0)
+            close(fd2);
        }
        close(fd1);
        return retval;
@@ -957,6 +965,13 @@ DLDbListCFPref::searchList()
 void
 DLDbListCFPref::searchList(const vector<DLDbIdentifier> &searchList)
 {
+    if(searchList.size() == 0) {
+        mSearchList.clear();
+        mSearchListSet = false;
+        changed(true);
+        return;
+    }
+
        vector<DLDbIdentifier> newList(searchList);
        mSearchList.swap(newList);
     mSearchListSet = true;
@@ -973,6 +988,8 @@ DLDbListCFPref::defaultDLDbIdentifier(const DLDbIdentifier &dlDbIdentifier)
        }
 }
 
+// Caution: if the backing file for the defaultDLDbIdentifier doesn't exist (or if the plist file is corrupt),
+//  this will return a DLDbIdentifier with a NULL impl
 const DLDbIdentifier &
 DLDbListCFPref::defaultDLDbIdentifier()
 {
@@ -988,9 +1005,9 @@ DLDbListCFPref::defaultDLDbIdentifier()
             CFDictionaryRef defaultDict = reinterpret_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(defaultArray, 0));
             try
             {
-                secdebug("secpref", "getting default DLDbIdentifier from defaultDict");
+                secinfo("secpref", "getting default DLDbIdentifier from defaultDict");
                 mDefaultDLDbIdentifier = cfDictionaryRefToDLDbIdentifier(defaultDict);
-                secdebug("secpref", "now we think the default keychain is %s", (mDefaultDLDbIdentifier) ? mDefaultDLDbIdentifier.dbName() : "<NULL>");
+                secinfo("secpref", "now we think the default keychain is %s", (mDefaultDLDbIdentifier) ? mDefaultDLDbIdentifier.dbName() : "<NULL>");
             }
             catch (...)
             {
@@ -1001,26 +1018,35 @@ DLDbListCFPref::defaultDLDbIdentifier()
     
         if (!defaultArray)
         {
-                       
             // If the Panther style login keychain actually exists we use that otherwise no
             // default is set.
             mDefaultDLDbIdentifier = loginDLDbIdentifier();
-            secdebug("secpref", "now we think the default keychain is: %s", (mDefaultDLDbIdentifier) ? mDefaultDLDbIdentifier.dbName() : 
-                       "Name doesn't exist");
-                       
+
+            //Since we might be changing the keychain filename, we have to stat the right file. Delegate the knowledge of which files to StorageManager; DLDbListCFPref should contain "login.keychain".
+            DLDbIdentifier actualIdentifier = KeychainCore::StorageManager::mungeDLDbIdentifier(mDefaultDLDbIdentifier, false);
+            secinfo("secpref", "now we think the default keychain is: %s (actual: %s)",
+                    (mDefaultDLDbIdentifier) ? mDefaultDLDbIdentifier.dbName() : "Name doesn't exist",
+                    (actualIdentifier) ? actualIdentifier.dbName() : "Name doesn't exist");
+
             struct stat st;
             int st_result = -1;
-                       
-                       if (mDefaultDLDbIdentifier.mImpl != NULL)
-                       {
-                               st_result = stat(mDefaultDLDbIdentifier.dbName(), &st);
-                       }
-                       
+
+            if (mDefaultDLDbIdentifier.mImpl != NULL && actualIdentifier.mImpl != NULL)
+            {
+                st_result = stat(actualIdentifier.dbName(), &st);
+
+                // Always claim that the system keychain exists for purposes of the search list
+                if (st_result && 0 == strncmp(actualIdentifier.dbName(), kSystemKeychainPath, strlen(kSystemKeychainPath))) {
+                    secnotice("secpref", "System keychain (%s) does not exist. Continuing as if it does...", actualIdentifier.dbName());
+                    st_result = 0;
+                }
+            }
+
             if (st_result)
             {
-                               secdebug("secpref", "stat(%s) -> %d", mDefaultDLDbIdentifier.dbName(), st_result);
+                               secinfo("secpref", "stat(%s) -> %d", actualIdentifier.dbName(), st_result);
                 mDefaultDLDbIdentifier  = DLDbIdentifier(); // initialize a NULL keychain
-                secdebug("secpref", "after DLDbIdentifier(), we think the default keychain is %s", static_cast<bool>(mDefaultDLDbIdentifier) ? mDefaultDLDbIdentifier.dbName() : "<NULL>");
+                secinfo("secpref", "after DLDbIdentifier(), we think the default keychain is %s", static_cast<bool>(mDefaultDLDbIdentifier) ? mDefaultDLDbIdentifier.dbName() : "<NULL>");
             }
         }
                
@@ -1055,9 +1081,9 @@ DLDbListCFPref::loginDLDbIdentifier()
             CFDictionaryRef loginDict = reinterpret_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(loginArray, 0));
             try
             {
-                secdebug("secpref", "Getting login DLDbIdentifier from loginDict");
+                secinfo("secpref", "Getting login DLDbIdentifier from loginDict");
                 mLoginDLDbIdentifier = cfDictionaryRefToDLDbIdentifier(loginDict);
-                secdebug("secpref", "we think the login keychain is %s", static_cast<bool>(mLoginDLDbIdentifier) ? mLoginDLDbIdentifier.dbName() : "<NULL>");
+                secinfo("secpref", "we think the login keychain is %s", static_cast<bool>(mLoginDLDbIdentifier) ? mLoginDLDbIdentifier.dbName() : "<NULL>");
             }
             catch (...)
             {
@@ -1069,7 +1095,7 @@ DLDbListCFPref::loginDLDbIdentifier()
         if (!loginArray)
         {
                        mLoginDLDbIdentifier = LoginDLDbIdentifier();
-                       secdebug("secpref", "after LoginDLDbIdentifier(), we think the login keychain is %s", static_cast<bool>(mLoginDLDbIdentifier) ? mLoginDLDbIdentifier.dbName() : "<NULL>");
+                       secinfo("secpref", "after LoginDLDbIdentifier(), we think the login keychain is %s", static_cast<bool>(mLoginDLDbIdentifier) ? mLoginDLDbIdentifier.dbName() : "<NULL>");
         }
 
         mLoginDLDbIdentifierSet = true;