]> git.saurik.com Git - apple/security.git/blobdiff - Security/libsecurity_keychain/lib/DLDBListCFPref.cpp
Security-57336.1.9.tar.gz
[apple/security.git] / Security / libsecurity_keychain / lib / DLDBListCFPref.cpp
diff --git a/Security/libsecurity_keychain/lib/DLDBListCFPref.cpp b/Security/libsecurity_keychain/lib/DLDBListCFPref.cpp
deleted file mode 100644 (file)
index 4836f4d..0000000
+++ /dev/null
@@ -1,1079 +0,0 @@
-/*
- * Copyright (c) 2000-2004,2011-2014 Apple Inc. All Rights Reserved.
- * 
- * @APPLE_LICENSE_HEADER_START@
- * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
- * The 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.
- * 
- * @APPLE_LICENSE_HEADER_END@
- */
-
-
-/*
-    DLDBListCFPref.cpp
-*/
-
-#include "DLDBListCFPref.h"
-#include <Security/cssmapple.h>
-#include <security_utilities/debugging.h>
-#include <security_utilities/utilities.h>
-#include <memory>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <pwd.h>
-#include <sys/param.h>
-#include <copyfile.h>
-#include <xpc/private.h>
-#include <syslog.h>
-#include <sandbox.h>
-
-dispatch_once_t AppSandboxChecked;
-xpc_object_t KeychainHomeFromXPC;
-
-using namespace CssmClient;
-
-static const double kDLDbListCFPrefRevertInterval = 30.0;
-
-// normal debug calls, which get stubbed out for deployment builds
-
-#define kKeyGUID CFSTR("GUID")
-#define kKeySubserviceId CFSTR("SubserviceId")
-#define kKeySubserviceType CFSTR("SubserviceType")
-#define kKeyDbName CFSTR("DbName")
-#define kKeyDbLocation CFSTR("DbLocation")
-#define kKeyActive CFSTR("Active")
-#define kKeyMajorVersion CFSTR("MajorVersion")
-#define kKeyMinorVersion CFSTR("MinorVersion")
-#define kDefaultDLDbListKey CFSTR("DLDBSearchList")
-#define kDefaultKeychainKey CFSTR("DefaultKeychain")
-#define kLoginKeychainKey CFSTR("LoginKeychain")
-#define kUserDefaultPath "~/Library/Preferences/com.apple.security.plist"
-#define kSystemDefaultPath "/Library/Preferences/com.apple.security.plist"
-#define kCommonDefaultPath "/Library/Preferences/com.apple.security-common.plist"
-#define kLoginKeychainPathPrefix "~/Library/Keychains/"
-#define kUserLoginKeychainPath "~/Library/Keychains/login.keychain"
-#define kSystemLoginKeychainPath "/Library/Keychains/System.keychain"
-
-
-// A utility class for managing password database lookups
-
-const time_t kPasswordCacheExpire = 30; // number of seconds cached password db info is valid
-
-PasswordDBLookup::PasswordDBLookup () : mValid (false), mCurrent (0), mTime (0)
-{
-}
-
-void PasswordDBLookup::lookupInfoOnUID (uid_t uid)
-{
-    time_t currentTime = time (NULL);
-    
-    if (!mValid || uid != mCurrent || currentTime - mTime >= kPasswordCacheExpire)
-    {
-        struct passwd* pw = getpwuid(uid);
-               if (pw == NULL)
-               {
-                       UnixError::throwMe (EPERM);
-               }
-               
-        mDirectory = pw->pw_dir;
-        mName = pw->pw_name;
-        mValid = true;
-        mCurrent = uid;
-        mTime = currentTime;
-
-        secdebug("secpref", "uid=%d caching home=%s", uid, pw->pw_dir);
-
-        endpwent();
-    }
-}
-
-PasswordDBLookup *DLDbListCFPref::mPdbLookup = NULL;
-
-//-------------------------------------------------------------------------------------
-//
-//                     Lists of DL/DBs, with CFPreferences backing store
-//
-//-------------------------------------------------------------------------------------
-
-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);
-       loadPropertyList(true);
-}
-
-void DLDbListCFPref::set(SecPreferencesDomain domain)
-{
-       save();
-
-       mDomain = domain;
-
-    secdebug("secpref", "DLDbListCFPref %p domain set to %d", this, domain);
-
-       if (loadPropertyList(true))
-        resetCachedValues();
-}
-
-DLDbListCFPref::~DLDbListCFPref()
-{
-    save();
-
-       if (mPropertyList)
-               CFRelease(mPropertyList);
-}
-
-void
-DLDbListCFPref::forceUserSearchListReread()
-{
-       // set mPrefsTimeStamp so that it will "expire" the next time loadPropertyList is called
-       mPrefsTimeStamp = CFAbsoluteTimeGetCurrent() - kDLDbListCFPrefRevertInterval;
-}
-
-bool
-DLDbListCFPref::loadPropertyList(bool force)
-{
-    string prefsPath;
-       
-       switch (mDomain)
-    {
-       case kSecPreferencesDomainUser:
-               prefsPath = ExpandTildesInPath(kUserDefaultPath);
-               break;
-       case kSecPreferencesDomainSystem:
-               prefsPath = kSystemDefaultPath;
-               break;
-       case kSecPreferencesDomainCommon:
-               prefsPath = kCommonDefaultPath;
-               break;
-       default:
-               MacOSError::throwMe(errSecInvalidPrefsDomain);
-       }
-
-       secdebug("secpref", "force=%s prefsPath=%s", force ? "true" : "false",
-               prefsPath.c_str());
-
-       CFAbsoluteTime now = CFAbsoluteTimeGetCurrent();
-
-    // If for some reason the prefs file path has changed, blow away the old plist and force an update
-    if (mPrefsPath != prefsPath)
-    {
-        mPrefsPath = prefsPath;
-        if (mPropertyList)
-        {
-            CFRelease(mPropertyList);
-            mPropertyList = NULL;
-        }
-
-               mPrefsTimeStamp = now;
-    }
-       else if (!force)
-       {
-               if (now - mPrefsTimeStamp < kDLDbListCFPrefRevertInterval)
-                       return false;
-
-               mPrefsTimeStamp = now;
-       }
-
-       struct stat st;
-       if (stat(mPrefsPath.c_str(), &st))
-       {
-               if (errno == ENOENT)
-               {
-                       if (mPropertyList)
-                       {
-                               if (CFDictionaryGetCount(mPropertyList) == 0)
-                                       return false;
-                               CFRelease(mPropertyList);
-                       }
-
-                       mPropertyList = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-                       return true;
-               }
-       }
-       else
-       {
-               if (mPropertyList)
-               {
-                       if (mTimespec.tv_sec == st.st_mtimespec.tv_sec
-                               && mTimespec.tv_nsec == st.st_mtimespec.tv_nsec)
-                               return false;
-               }
-
-               mTimespec = st.st_mtimespec;
-       }
-
-       CFMutableDictionaryRef thePropertyList = NULL;
-       CFMutableDataRef xmlData = NULL;
-       CFStringRef errorString = NULL;
-       int fd = -1;
-
-       do
-       {
-               fd = open(mPrefsPath.c_str(), O_RDONLY, 0);
-               if (fd < 0)
-                       break;
-
-               off_t theSize = lseek(fd, 0, SEEK_END);
-               if (theSize <= 0)
-                       break;
-
-               if (lseek(fd, 0, SEEK_SET))
-                       break;
-
-               xmlData = CFDataCreateMutable(NULL, CFIndex(theSize));
-               if (!xmlData)
-                       break;
-               CFDataSetLength(xmlData, CFIndex(theSize));
-               void *buffer = reinterpret_cast<void *>(CFDataGetMutableBytePtr(xmlData));
-               if (!buffer)
-                       break;
-               ssize_t bytesRead = read(fd, buffer, (size_t)theSize);
-               if (bytesRead != theSize)
-                       break;
-
-               thePropertyList = CFMutableDictionaryRef(CFPropertyListCreateFromXMLData(NULL, xmlData, kCFPropertyListMutableContainers, &errorString));
-               if (!thePropertyList)
-                       break;
-
-               if (CFGetTypeID(thePropertyList) != CFDictionaryGetTypeID())
-               {
-                       CFRelease(thePropertyList);
-                       thePropertyList = NULL;
-                       break;
-               }
-       } while (0);
-
-       if (fd >= 0)
-               close(fd);
-       if (xmlData)
-               CFRelease(xmlData);
-       if (errorString)
-               CFRelease(errorString);
-
-       if (!thePropertyList)
-       {
-               thePropertyList = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-       }
-
-       if (mPropertyList)
-       {
-               if (CFEqual(mPropertyList, thePropertyList))
-               {
-            // The new property list is the same as the old one, so nothing has changed.
-                       CFRelease(thePropertyList);
-                       return false;
-               }
-               CFRelease(mPropertyList);
-       }
-
-       mPropertyList = thePropertyList;
-       return true;
-}
-
-void
-DLDbListCFPref::writePropertyList()
-{
-       if (!mPropertyList || CFDictionaryGetCount(mPropertyList) == 0)
-       {
-               // There is nothing in the mPropertyList dictionary,
-               // so we don't need a prefs file.
-               unlink(mPrefsPath.c_str());
-       }
-       else
-       {
-               if(testAndFixPropertyList()) 
-                       return;
-               
-               CFDataRef xmlData = CFPropertyListCreateXMLData(NULL, mPropertyList);
-               if (!xmlData)
-                       return; // Bad out of memory or something evil happened let's act like CF and do nothing.
-                       
-               // 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;
-               changeIdentity(UNPRIV);
-               int fd = open(mPrefsPath.c_str(), O_WRONLY|O_CREAT|O_TRUNC, mode);
-               changeIdentity(PRIV);
-               if (fd >= 0)
-               {
-                       const void *buffer = CFDataGetBytePtr(xmlData);
-                       size_t toWrite = CFDataGetLength(xmlData);
-                       /* ssize_t bytesWritten = */ write(fd, buffer, toWrite);
-                       // Emulate CFPreferences by not checking for any errors.
-       
-                       fsync(fd);
-                       struct stat st;
-                       if (!fstat(fd, &st))
-                               mTimespec = st.st_mtimespec;
-
-                       close(fd);
-               }
-
-               CFRelease(xmlData);
-       }
-
-       mPrefsTimeStamp = CFAbsoluteTimeGetCurrent();
-}
-
-// This function can clean up some problems caused by setuid clients.  We've had instances where the
-// Keychain search list has become owned by root, but is still able to be re-written by the user because
-// of the permissions on the directory above.  We'll take advantage of that fact to recreate the file with
-// the correct ownership by copying it.
-
-int
-DLDbListCFPref::testAndFixPropertyList()
-{
-       char *prefsPath = (char *)mPrefsPath.c_str();
-       
-       int fd1, fd2, retval;
-       struct stat stbuf;
-
-       if((fd1 = open(prefsPath, O_RDONLY)) < 0) {
-               if (errno == ENOENT) return 0; // Doesn't exist - the default case
-               else return -1;
-       }
-       
-       if((retval = fstat(fd1, &stbuf)) == -1) return -1;
-               
-       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;
-               } 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);
-               }
-               changeIdentity(PRIV);
-               close(fd2);
-       }
-       close(fd1);
-       return retval;
-}
-
-// Encapsulated process uid/gid change routine.
-void 
-DLDbListCFPref::changeIdentity(ID_Direction toPriv)
-{
-       if(toPriv == UNPRIV) {
-               savedEUID = geteuid();
-               savedEGID = getegid();
-               if(savedEGID != getgid()) setegid(getgid());
-               if(savedEUID != getuid()) seteuid(getuid());
-       } else {
-               if(savedEUID != getuid()) seteuid(savedEUID);
-               if(savedEGID != getgid()) setegid(savedEGID);
-       }
-}
-
-void
-DLDbListCFPref::resetCachedValues()
-{
-       // Unset the login and default Keychain.
-       mLoginDLDbIdentifier = mDefaultDLDbIdentifier = DLDbIdentifier();
-
-       // Clear the searchList.
-       mSearchList.clear();
-
-       changed(false);
-
-    // Note that none of our cached values are valid
-    mSearchListSet = mDefaultDLDbIdentifierSet = mLoginDLDbIdentifierSet = false;
-
-       mPrefsTimeStamp = CFAbsoluteTimeGetCurrent();
-}
-
-void DLDbListCFPref::save()
-{
-    if (!hasChanged())
-        return;
-
-       // Resync from disc to make sure we don't clobber anyone elses changes.
-       // @@@ This is probably already done by the next layer up so we don't
-       // really need to do it here again.
-       loadPropertyList(true);
-
-    // Do the searchList first since it might end up invoking defaultDLDbIdentifier() which can set
-    // mLoginDLDbIdentifierSet and mDefaultDLDbIdentifierSet to true.
-    if (mSearchListSet)
-    {
-        // Make a temporary CFArray with the contents of the vector
-        if (mSearchList.size() == 1 && mSearchList[0] == defaultDLDbIdentifier() && mSearchList[0] == LoginDLDbIdentifier())
-        {
-            // The only element in the search list is the default keychain, which is a
-            // post Jaguar style login keychain, so omit the entry from the prefs file.
-            CFDictionaryRemoveValue(mPropertyList, kDefaultDLDbListKey);
-        }
-        else
-        {
-            CFMutableArrayRef searchArray = CFArrayCreateMutable(kCFAllocatorDefault, mSearchList.size(), &kCFTypeArrayCallBacks);
-            for (DLDbList::const_iterator ix=mSearchList.begin();ix!=mSearchList.end();ix++)
-            {
-                CFDictionaryRef aDict = dlDbIdentifierToCFDictionaryRef(*ix);
-                CFArrayAppendValue(searchArray, aDict);
-                CFRelease(aDict);
-            }
-    
-            CFDictionarySetValue(mPropertyList, kDefaultDLDbListKey, searchArray);
-            CFRelease(searchArray);
-        }
-    }
-
-    if (mLoginDLDbIdentifierSet)
-    {
-        // Make a temporary CFArray with the login keychain
-        CFArrayRef loginArray = NULL;
-        if (!mLoginDLDbIdentifier)
-        {
-            loginArray = CFArrayCreate(kCFAllocatorDefault, NULL, 0, &kCFTypeArrayCallBacks);
-        }
-        else if (!(mLoginDLDbIdentifier == LoginDLDbIdentifier()))
-        {
-            CFDictionaryRef aDict = dlDbIdentifierToCFDictionaryRef(mLoginDLDbIdentifier);
-            const void *value = reinterpret_cast<const void *>(aDict);
-            loginArray = CFArrayCreate(kCFAllocatorDefault, &value, 1, &kCFTypeArrayCallBacks);
-            CFRelease(aDict);
-        }
-    
-        if (loginArray)
-        {
-            CFDictionarySetValue(mPropertyList, kLoginKeychainKey, loginArray);
-            CFRelease(loginArray);
-        }
-        else
-            CFDictionaryRemoveValue(mPropertyList, kLoginKeychainKey);
-    }
-
-    if (mDefaultDLDbIdentifierSet)
-    {
-        // Make a temporary CFArray with the default keychain
-        CFArrayRef defaultArray = NULL;
-        if (!mDefaultDLDbIdentifier)
-        {
-            defaultArray = CFArrayCreate(kCFAllocatorDefault, NULL, 0, &kCFTypeArrayCallBacks);
-        }
-        else if (!(mDefaultDLDbIdentifier == LoginDLDbIdentifier()))
-        {
-            CFDictionaryRef aDict = dlDbIdentifierToCFDictionaryRef(mDefaultDLDbIdentifier);
-            const void *value = reinterpret_cast<const void *>(aDict);
-            defaultArray = CFArrayCreate(kCFAllocatorDefault, &value, 1, &kCFTypeArrayCallBacks);
-            CFRelease(aDict);
-        }
-    
-        if (defaultArray)
-        {
-            CFDictionarySetValue(mPropertyList, kDefaultKeychainKey, defaultArray);
-            CFRelease(defaultArray);
-        }
-        else
-            CFDictionaryRemoveValue(mPropertyList, kDefaultKeychainKey);
-    }
-
-       writePropertyList();
-    changed(false);
-}
-
-
-//----------------------------------------------------------------------
-//                     Conversions
-//----------------------------------------------------------------------
-
-DLDbIdentifier DLDbListCFPref::LoginDLDbIdentifier()
-{
-       CSSM_VERSION theVersion={};
-    CssmSubserviceUid ssuid(gGuidAppleCSPDL,&theVersion,0,CSSM_SERVICE_DL|CSSM_SERVICE_CSP);
-       CssmNetAddress *dbLocation=NULL;
-
-       switch (mDomain) {
-       case kSecPreferencesDomainUser:
-               return DLDbIdentifier(ssuid, ExpandTildesInPath(kUserLoginKeychainPath).c_str(), dbLocation);
-       default:
-               assert(false);
-       case kSecPreferencesDomainSystem:
-       case kSecPreferencesDomainCommon:
-               return DLDbIdentifier(ssuid, kSystemLoginKeychainPath, dbLocation);
-       }
-}
-
-DLDbIdentifier DLDbListCFPref::JaguarLoginDLDbIdentifier()
-{
-       CSSM_VERSION theVersion={};
-    CssmSubserviceUid ssuid(gGuidAppleCSPDL,&theVersion,0,CSSM_SERVICE_DL|CSSM_SERVICE_CSP);
-       CssmNetAddress *dbLocation=NULL;
-
-       switch (mDomain) {
-       case kSecPreferencesDomainUser:
-    {
-        string basepath = ExpandTildesInPath(kLoginKeychainPathPrefix) + getPwInfo(kUsername);
-        return DLDbIdentifier(ssuid,basepath.c_str(),dbLocation);
-    }
-       case kSecPreferencesDomainSystem:
-       case kSecPreferencesDomainCommon:
-               return DLDbIdentifier(ssuid, kSystemLoginKeychainPath, dbLocation);
-       default:
-               assert(false);
-               return DLDbIdentifier();
-       }
-}
-
-DLDbIdentifier DLDbListCFPref::makeDLDbIdentifier (const CSSM_GUID &guid, const CSSM_VERSION &version,
-                                                                                                  uint32 subserviceId, CSSM_SERVICE_TYPE subserviceType,
-                                                                                                  const char* dbName, CSSM_NET_ADDRESS *dbLocation)
-{
-       CssmSubserviceUid ssuid (guid, &version, subserviceId, subserviceType);
-       return DLDbIdentifier (ssuid, ExpandTildesInPath (dbName).c_str (), dbLocation);
-}
-
-DLDbIdentifier DLDbListCFPref::cfDictionaryRefToDLDbIdentifier(CFDictionaryRef theDict)
-{
-    // We must get individual values from the dictionary and store in basic types
-       if (CFGetTypeID(theDict) != CFDictionaryGetTypeID())
-               throw std::logic_error("wrong type in property list");
-
-    // GUID
-    CCFValue vGuid(::CFDictionaryGetValue(theDict,kKeyGUID));
-    string guidStr=vGuid;
-    const Guid guid(guidStr.c_str());
-
-    //CSSM_VERSION
-       CSSM_VERSION theVersion={0,};
-    CCFValue vMajor(::CFDictionaryGetValue(theDict,kKeyMajorVersion));
-       theVersion.Major = vMajor;
-    CCFValue vMinor(::CFDictionaryGetValue(theDict,kKeyMinorVersion));
-       theVersion.Minor = vMinor;
-
-    //subserviceId
-    CCFValue vSsid(::CFDictionaryGetValue(theDict,kKeySubserviceId));
-    uint32 subserviceId=sint32(vSsid);
-
-    //CSSM_SERVICE_TYPE
-    CSSM_SERVICE_TYPE subserviceType=CSSM_SERVICE_DL;
-    CCFValue vSsType(::CFDictionaryGetValue(theDict,kKeySubserviceType));
-    subserviceType=vSsType;
-    
-    // Get DbName from dictionary
-    CCFValue vDbName(::CFDictionaryGetValue(theDict,kKeyDbName));
-    string dbName=vDbName;
-    
-    // jch Get DbLocation from dictionary
-       CssmNetAddress *dbLocation=NULL;
-    
-       return makeDLDbIdentifier (guid, theVersion, subserviceId, subserviceType, dbName.c_str (), dbLocation);
-}
-
-void DLDbListCFPref::clearPWInfo ()
-{
-    if (mPdbLookup != NULL)
-    {
-        delete mPdbLookup;
-        mPdbLookup = NULL;
-    }
-}
-
-string DLDbListCFPref::getPwInfo(PwInfoType type)
-{
-    const char *value;
-    switch (type)
-    {
-    case kHomeDir:
-               if (KeychainHomeFromXPC) {
-                       value = xpc_string_get_string_ptr(KeychainHomeFromXPC);
-               } else {
-                       value = getenv("HOME");
-               }
-        if (value)
-            return value;
-        break;
-    case kUsername:
-        value = getenv("USER");
-        if (value)
-            return value;
-        break;
-    }
-
-       // Get our effective uid
-       uid_t uid = geteuid();
-       // If we are setuid root use the real uid instead
-       if (!uid) uid = getuid();
-
-    // get the password entries
-    if (mPdbLookup == NULL)
-    {
-        mPdbLookup = new PasswordDBLookup ();
-    }
-    
-    mPdbLookup->lookupInfoOnUID (uid);
-    
-    string result;
-    switch (type)
-    {
-    case kHomeDir:
-        result = mPdbLookup->getDirectory ();
-        break;
-    case kUsername:
-        result = mPdbLookup->getName ();
-        break;
-    }
-
-       return result;
-}
-
-static void check_app_sandbox()
-{
-       if (!_xpc_runtime_is_app_sandboxed()) {
-               // We are not in a sandbox, no work to do here
-               return;
-       }
-       
-       extern xpc_object_t xpc_create_with_format(const char * format, ...);
-       xpc_connection_t con = xpc_connection_create("com.apple.security.XPCKeychainSandboxCheck", NULL);
-    xpc_connection_set_event_handler(con, ^(xpc_object_t event) {
-        xpc_type_t xtype = xpc_get_type(event);
-        if (XPC_TYPE_ERROR == xtype) {
-            syslog(LOG_ERR, "Keychain sandbox connection error: %s\n", xpc_dictionary_get_string(event, XPC_ERROR_KEY_DESCRIPTION));
-        } else {
-            syslog(LOG_ERR, "Keychain sandbox unexpected connection event %p\n", event);
-        }
-    });
-    xpc_connection_resume(con);
-    
-    xpc_object_t message = xpc_create_with_format("{op: GrantKeychainPaths}");
-       xpc_object_t reply = xpc_connection_send_message_with_reply_sync(con, message);
-       xpc_type_t xtype = xpc_get_type(reply);
-       if (XPC_TYPE_DICTIONARY == xtype) {
-#if 0
-               // This is useful for debugging.
-               char *debug = xpc_copy_description(reply);
-               syslog(LOG_ERR, "DEBUG (KCsandbox) %s\n", debug);
-               free(debug);
-#endif
-               
-               xpc_object_t extensions_array = xpc_dictionary_get_value(reply, "extensions");
-               xpc_array_apply(extensions_array, ^(size_t index, xpc_object_t extension) {
-                       char pbuf[MAXPATHLEN];
-                       char *path = pbuf;
-                       int status = sandbox_consume_fs_extension(xpc_string_get_string_ptr(extension), &path);
-                       if (status) {
-                               syslog(LOG_ERR, "Keychain sandbox consume extension error: s=%d p=%s %m\n", status, path);
-                       }
-            status = sandbox_release_fs_extension(xpc_string_get_string_ptr(extension));
-            if (status) {
-                               syslog(LOG_ERR, "Keychain sandbox release extension error: s=%d p=%s %m\n", status, path);
-                       }
-
-                       return (bool)true;
-               });
-               
-               KeychainHomeFromXPC = xpc_dictionary_get_value(reply, "keychain-home");
-               xpc_retain(KeychainHomeFromXPC);
-               xpc_release(con);
-       } else if (XPC_TYPE_ERROR == xtype) {
-               syslog(LOG_ERR, "Keychain sandbox message error: %s\n", xpc_dictionary_get_string(reply, XPC_ERROR_KEY_DESCRIPTION));
-       } else {
-               syslog(LOG_ERR, "Keychain sandbox unexpected message reply type %p\n", xtype);
-       }
-    xpc_release(message);
-       xpc_release(reply);
-}
-
-
-
-string DLDbListCFPref::ExpandTildesInPath(const string &inPath)
-{
-       dispatch_once(&AppSandboxChecked, ^{
-               check_app_sandbox();
-       });
-       
-       if ((short)inPath.find("~/",0,2) == 0)
-        return getPwInfo(kHomeDir) + inPath.substr(1, inPath.length() - 1);
-    else
-        return inPath;
-}
-
-string DLDbListCFPref::StripPathStuff(const string &inPath)
-{
-    if (inPath.find("/private/var/automount/Network/",0,31) == 0)
-        return inPath.substr(22);
-    if (inPath.find("/private/automount/Servers/",0,27) == 0)
-        return "/Network" + inPath.substr(18);
-    if (inPath.find("/automount/Servers/",0,19) == 0)
-        return "/Network" + inPath.substr(10);
-    if (inPath.find("/private/automount/Network/",0,27) == 0)
-        return inPath.substr(18);
-    if (inPath.find("/automount/Network/",0,19) == 0)
-        return inPath.substr(10);
-    if (inPath.find("/private/Network/",0,17) == 0)
-        return inPath.substr(8);
-    return inPath;
-}
-
-string DLDbListCFPref::AbbreviatedPath(const string &inPath)
-{
-    string path = StripPathStuff(inPath);
-    string home = StripPathStuff(getPwInfo(kHomeDir) + "/");
-    size_t homeLen = home.length();
-
-    if (homeLen > 1 && path.find(home.c_str(), 0, homeLen) == 0)
-        return "~" + path.substr(homeLen - 1);
-    else
-        return path;
-}
-
-CFDictionaryRef DLDbListCFPref::dlDbIdentifierToCFDictionaryRef(const DLDbIdentifier& dldbIdentifier)
-{
-       CFRef<CFMutableDictionaryRef> aDict(CFDictionaryCreateMutable(kCFAllocatorDefault,0,
-               &kCFTypeDictionaryKeyCallBacks,&kCFTypeDictionaryValueCallBacks));
-    if (!aDict)
-        throw ::std::bad_alloc();
-
-    // Put SUBSERVICE_UID in dictionary
-    char buffer[Guid::stringRepLength+1];
-    const CssmSubserviceUid& ssuid=dldbIdentifier.ssuid();
-    const Guid &theGuid = Guid::overlay(ssuid.Guid);
-    CFRef<CFStringRef> stringGuid(::CFStringCreateWithCString(kCFAllocatorDefault,
-            theGuid.toString(buffer),kCFStringEncodingMacRoman));
-    if (stringGuid)
-        ::CFDictionarySetValue(aDict,kKeyGUID,stringGuid);
-        
-    if (ssuid.SubserviceId!=0)
-    {
-        CFRef<CFNumberRef> subserviceId(::CFNumberCreate(kCFAllocatorDefault,kCFNumberSInt32Type,&ssuid.SubserviceId));
-        if (subserviceId)
-            ::CFDictionarySetValue(aDict,kKeySubserviceId,subserviceId);
-    }
-    if (ssuid.SubserviceType!=0)
-    {
-        CFRef<CFNumberRef> subserviceType(CFNumberCreate(kCFAllocatorDefault,kCFNumberSInt32Type,&ssuid.SubserviceType));
-        if (subserviceType)
-            ::CFDictionarySetValue(aDict,kKeySubserviceType,subserviceType);
-    }
-    if (ssuid.Version.Major!=0 && ssuid.Version.Minor!=0)
-    {
-        CFRef<CFNumberRef> majorVersion(::CFNumberCreate(kCFAllocatorDefault,kCFNumberSInt32Type,&ssuid.Version.Major));
-        if (majorVersion)
-            ::CFDictionarySetValue(aDict,kKeyMajorVersion,majorVersion);
-        CFRef<CFNumberRef> minorVersion(::CFNumberCreate(kCFAllocatorDefault,kCFNumberSInt32Type,&ssuid.Version.Minor));
-        if (minorVersion)
-            ::CFDictionarySetValue(aDict,kKeyMinorVersion,minorVersion);
-    }
-    
-    // Put DbName in dictionary
-       const char *dbName=dldbIdentifier.dbName();
-    if (dbName)
-    {
-        CFRef<CFStringRef> theDbName(::CFStringCreateWithCString(kCFAllocatorDefault,AbbreviatedPath(dbName).c_str(),kCFStringEncodingUTF8));
-        ::CFDictionarySetValue(aDict,kKeyDbName,theDbName);
-    }
-    // Put DbLocation in dictionary
-       const CSSM_NET_ADDRESS *dbLocation=dldbIdentifier.dbLocation();
-    if (dbLocation!=NULL && dbLocation->AddressType!=CSSM_ADDR_NONE)
-    {
-        CFRef<CFDataRef> theData(::CFDataCreate(kCFAllocatorDefault,dbLocation->Address.Data,dbLocation->Address.Length));
-        if (theData)
-            ::CFDictionarySetValue(aDict,kKeyDbLocation,theData);
-    }
-
-    ::CFRetain(aDict);
-       return aDict;
-}
-
-bool DLDbListCFPref::revert(bool force)
-{ 
-       // If the prefs have not been refreshed in the last kDLDbListCFPrefRevertInterval
-       // seconds or we are asked to force a reload, then reload.
-       if (!loadPropertyList(force))
-               return false;
-
-       resetCachedValues();
-       return true;
-}
-
-void
-DLDbListCFPref::add(const DLDbIdentifier &dldbIdentifier)
-{
-       // convert the location specified in dldbIdentifier to a standard form
-       // make a canonical form of the database name
-       std::string canon = ExpandTildesInPath(AbbreviatedPath(dldbIdentifier.dbName()).c_str());
-
-       DLDbIdentifier localIdentifier  (dldbIdentifier.ssuid(), canon.c_str(), dldbIdentifier.dbLocation ());
-       
-       if (member(localIdentifier))
-               return;
-
-    mSearchList.push_back(localIdentifier);
-    changed(true);
-}
-
-void
-DLDbListCFPref::remove(const DLDbIdentifier &dldbIdentifier)
-{
-    // Make sure mSearchList is set
-    searchList();
-    for (vector<DLDbIdentifier>::iterator ix = mSearchList.begin(); ix != mSearchList.end(); ++ix)
-       {
-               if (*ix==dldbIdentifier)                // found in list
-               {
-                       mSearchList.erase(ix);
-                       changed(true);
-                       break;
-               }
-       }
-}
-
-void
-DLDbListCFPref::rename(const DLDbIdentifier &oldId, const DLDbIdentifier &newId)
-{
-    // Make sure mSearchList is set
-    searchList();
-    for (vector<DLDbIdentifier>::iterator ix = mSearchList.begin();
-               ix != mSearchList.end(); ++ix)
-       {
-               if (*ix==oldId)
-               {
-                       // replace oldId with newId
-                       *ix = newId;
-                       changed(true);
-               }
-               else if (*ix==newId)
-               {
-                       // remove newId except where we just inserted it
-                       mSearchList.erase(ix);
-                       changed(true);
-               }
-       }
-}
-
-bool
-DLDbListCFPref::member(const DLDbIdentifier &dldbIdentifier)
-{
-    if (dldbIdentifier.IsImplEmpty())
-    {
-        return false;
-    }
-    
-    for (vector<DLDbIdentifier>::const_iterator ix = searchList().begin(); ix != mSearchList.end(); ++ix)
-       {
-        if (ix->mImpl == NULL)
-        {
-            continue;
-        }
-        
-               // compare the dldbIdentifiers based on the full, real path to the keychain
-               if (ix->ssuid() == dldbIdentifier.ssuid())
-               {
-                       char localPath[PATH_MAX],
-                                inPath[PATH_MAX];
-                       
-                       // try to resolve these down to a canonical form
-                       const char* localPathPtr = cached_realpath(ix->dbName(), localPath);
-                       const char* inPathPtr = cached_realpath(dldbIdentifier.dbName(), inPath);
-
-                       // if either of the paths didn't resolve for some reason, use the originals
-                       if (localPathPtr == NULL)
-                       {
-                               localPathPtr = ix->dbName();
-                       }
-                       
-                       if (inPathPtr == NULL)
-                       {
-                               inPathPtr = dldbIdentifier.dbName();
-                       }
-                       
-                       if (strcmp(localPathPtr, inPathPtr) == 0)
-                       {
-                               return true;
-                       }
-               }
-       }
-
-       return false;
-}
-
-const vector<DLDbIdentifier> &
-DLDbListCFPref::searchList()
-{
-    if (!mSearchListSet)
-    {
-        CFArrayRef searchList = reinterpret_cast<CFArrayRef>(CFDictionaryGetValue(mPropertyList, kDefaultDLDbListKey));
-        if (searchList && CFGetTypeID(searchList) != CFArrayGetTypeID())
-            searchList = NULL;
-
-        if (searchList)
-        {
-            CFIndex top = CFArrayGetCount(searchList);
-            // Each entry is a CFDictionary; peel it off & add it to the array
-            for (CFIndex idx = 0; idx < top; ++idx)
-            {
-                CFDictionaryRef theDict = reinterpret_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(searchList, idx));
-                try
-                {
-                    mSearchList.push_back(cfDictionaryRefToDLDbIdentifier(theDict));
-                }
-                catch (...)
-                {
-                    // Drop stuff that doesn't parse on the floor.
-                }
-            }
-    
-            // If there were entries specified, but they were invalid revert to using the
-            // default keychain in the searchlist.
-            if (top > 0 && mSearchList.size() == 0)
-                searchList = NULL;
-        }
-
-        // The default when no search list is specified is to only search the
-        // default keychain.
-        if (!searchList && static_cast<bool>(defaultDLDbIdentifier()))
-            mSearchList.push_back(mDefaultDLDbIdentifier);
-
-        mSearchListSet = true;
-    }
-
-       return mSearchList;
-}
-
-void
-DLDbListCFPref::searchList(const vector<DLDbIdentifier> &searchList)
-{
-       vector<DLDbIdentifier> newList(searchList);
-       mSearchList.swap(newList);
-    mSearchListSet = true;
-    changed(true);
-}
-
-void
-DLDbListCFPref::defaultDLDbIdentifier(const DLDbIdentifier &dlDbIdentifier)
-{
-       if (!(defaultDLDbIdentifier() == dlDbIdentifier))
-       {
-               mDefaultDLDbIdentifier = dlDbIdentifier;
-               changed(true);
-       }
-}
-
-const DLDbIdentifier &
-DLDbListCFPref::defaultDLDbIdentifier()
-{
-       
-    if (!mDefaultDLDbIdentifierSet)
-    {
-        CFArrayRef defaultArray = reinterpret_cast<CFArrayRef>(CFDictionaryGetValue(mPropertyList, kDefaultKeychainKey));
-        if (defaultArray && CFGetTypeID(defaultArray) != CFArrayGetTypeID())
-            defaultArray = NULL;
-
-        if (defaultArray && CFArrayGetCount(defaultArray) > 0)
-        {
-            CFDictionaryRef defaultDict = reinterpret_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(defaultArray, 0));
-            try
-            {
-                secdebug("secpref", "getting default DLDbIdentifier from defaultDict");
-                mDefaultDLDbIdentifier = cfDictionaryRefToDLDbIdentifier(defaultDict);
-                secdebug("secpref", "now we think the default keychain is %s", (mDefaultDLDbIdentifier) ? mDefaultDLDbIdentifier.dbName() : "<NULL>");
-            }
-            catch (...)
-            {
-                // If defaultArray doesn't parse fall back on the default way of getting the default keychain
-                defaultArray = NULL;
-            }
-        }
-    
-        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");
-                       
-            struct stat st;
-            int st_result = -1;
-                       
-                       if (mDefaultDLDbIdentifier.mImpl != NULL)
-                       {
-                               st_result = stat(mDefaultDLDbIdentifier.dbName(), &st);
-                       }
-                       
-            if (st_result)
-            {
-                               secdebug("secpref", "stat(%s) -> %d", mDefaultDLDbIdentifier.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>");
-            }
-        }
-               
-        mDefaultDLDbIdentifierSet = true;
-    }
-       
-       
-       return mDefaultDLDbIdentifier;
-}
-
-void
-DLDbListCFPref::loginDLDbIdentifier(const DLDbIdentifier &dlDbIdentifier)
-{
-       if (!(loginDLDbIdentifier() == dlDbIdentifier))
-       {
-               mLoginDLDbIdentifier = dlDbIdentifier;
-               changed(true);
-       }
-}
-
-const DLDbIdentifier &
-DLDbListCFPref::loginDLDbIdentifier()
-{
-    if (!mLoginDLDbIdentifierSet)
-    {
-        CFArrayRef loginArray = reinterpret_cast<CFArrayRef>(CFDictionaryGetValue(mPropertyList, kLoginKeychainKey));
-        if (loginArray && CFGetTypeID(loginArray) != CFArrayGetTypeID())
-            loginArray = NULL;
-
-        if (loginArray && CFArrayGetCount(loginArray) > 0)
-        {
-            CFDictionaryRef loginDict = reinterpret_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(loginArray, 0));
-            try
-            {
-                secdebug("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>");
-            }
-            catch (...)
-            {
-                // If loginArray doesn't parse fall back on the default way of getting the login keychain.
-                loginArray = NULL;
-            }
-        }
-    
-        if (!loginArray)
-        {
-                       mLoginDLDbIdentifier = LoginDLDbIdentifier();
-                       secdebug("secpref", "after LoginDLDbIdentifier(), we think the login keychain is %s", static_cast<bool>(mLoginDLDbIdentifier) ? mLoginDLDbIdentifier.dbName() : "<NULL>");
-        }
-
-        mLoginDLDbIdentifierSet = true;
-    }
-
-       return mLoginDLDbIdentifier;
-}