+++ /dev/null
-rotty?Data
 
+++ /dev/null
-AppleCSPDL?Data
 
+++ /dev/null
-PBUserInfo
-AppleX509CL?Data
 
                MacOSError::throwMe(errSecInvalidCallback);
 }
 
-void CCallbackMgr::AlertClients(SecKeychainEvent inEvent,
+void CCallbackMgr::AlertClients(const list<CallbackInfo> &eventCallbacks,
+                                                               SecKeychainEvent inEvent,
                                                                pid_t inPid,
                                 const Keychain &inKeychain,
                                 const Item &inItem)
     secdebug("kcnotify", "dispatch event %ld pid %d keychain %p item %p",
         inEvent, inPid, &inKeychain, !!inItem ? &*inItem : NULL);
 
-    // Deal with events that we care about ourselves first.
-    if (inEvent == kSecDeleteEvent && inKeychain.get() && inItem.get())
-        inKeychain->didDeleteItem(inItem.get());
-
        // Iterate through callbacks, looking for those registered for inEvent
        const SecKeychainEventMask theMask = 1U << inEvent;
 
-       for ( CallbackInfoListIterator ix = CCallbackMgr::Instance().mEventCallbacks.begin();
-               ix != CCallbackMgr::Instance().mEventCallbacks.end(); ++ix )
+       for (ConstCallbackInfoListIterator ix = eventCallbacks.begin(); ix != eventCallbacks.end(); ++ix)
        {
                if (!(ix->mEventMask & theMask))
                        continue;
 *                      If it wasn't 'us', we should remove our cached reference to the item that was deleted.
 *
 ***********************************************************************************/
-void CCallbackMgr::Event (Listener::Domain domain, Listener::Event whichEvent, NameValueDictionary &dictionary)
+void CCallbackMgr::Event(Listener::Domain domain, Listener::Event whichEvent, NameValueDictionary &dictionary)
 {
     // Decode from userInfo the event type, 'keychain' CFDict, and 'item' CFDict
        SecKeychainEvent        thisEvent = whichEvent;
 
     pid_t thisPid;
-       const NameValuePair* pidRef = dictionary.FindByName (PID_KEY);
+       const NameValuePair* pidRef = dictionary.FindByName(PID_KEY);
        if (pidRef == 0)
        {
                thisPid = 0;
        }
        else
        {
-               thisPid = *reinterpret_cast<pid_t*>(pidRef->Value ().data ());
+               thisPid = *reinterpret_cast<pid_t*>(pidRef->Value().data());
        }
 
        Keychain thisKeychain = 0;
-       
-       // make sure we have a database identifier
-       if (dictionary.FindByName (SSUID_KEY) != 0)
-       {
-               DLDbIdentifier dbid = NameValueDictionary::MakeDLDbIdentifierFromNameValueDictionary (dictionary);
-               thisKeychain = globals().storageManager.keychain (dbid);
-       }
-       
-    const NameValuePair* item = dictionary.FindByName (ITEM_KEY);
     Item thisItem;
+       list<CallbackInfo> eventCallbacks;
 
-    if (item && thisKeychain)
-    {
-        PrimaryKey pk(item->Value ());
-               thisItem = thisKeychain->item(pk);
-    }
+       {
+               // Lock the global API lock before doing stuff with StorageManager.
+               StLock<Mutex> _(globals().apiLock);
+
+               // make sure we have a database identifier
+               if (dictionary.FindByName (SSUID_KEY) != 0)
+               {
+                       DLDbIdentifier dbid = NameValueDictionary::MakeDLDbIdentifierFromNameValueDictionary (dictionary);
+                       thisKeychain = globals().storageManager.keychain(dbid);
+               }
+               
+               const NameValuePair* item = dictionary.FindByName(ITEM_KEY);
+               
+               if (item && thisKeychain)
+               {
+                       PrimaryKey pk(item->Value());
+                       thisItem = thisKeychain->item(pk);
+               }
+
+               // Deal with events that we care about ourselves first.
+               if (thisEvent == kSecDeleteEvent && thisKeychain.get() && thisItem.get())
+                       thisKeychain->didDeleteItem(thisItem.get());
+
+               eventCallbacks = CCallbackMgr::Instance().mEventCallbacks;
+               // We can safely release the global API lock now since thisKeychain and thisItem
+               // are CFRetained and will be until they go out of scope.
+       }
 
     // Notify our process of this event.
-       CCallbackMgr::AlertClients(thisEvent, thisPid, thisKeychain, thisItem);
+       CCallbackMgr::AlertClients(eventCallbacks, thisEvent, thisPid, thisKeychain, thisItem);
 }
 
 
        void Event (Listener::Domain domain, Listener::Event whichEvent, NameValueDictionary &dictionary);
        
-       static void AlertClients( SecKeychainEvent inEvent, pid_t inPid,
-               const Keychain& inKeychain, const Item &inItem);
+       static void AlertClients(const list<CallbackInfo> &eventCallbacks, SecKeychainEvent inEvent, pid_t inPid,
+                                                        const Keychain& inKeychain, const Item &inItem);
 
        list<CallbackInfo>              mEventCallbacks;
        static CCallbackMgr*    mCCallbackMgr;
 
        Policy("SecPolicy"),
        PolicyCursor("SecPolicySearch"),
        Trust("SecTrust"),
-       TrustedApplication("SecTrustedApplication")
+       TrustedApplication("SecTrustedApplication"),
+       allocator(CFAllocatorCreate(NULL, &CFClass::allocatorContext))
 {
 }
 
 //
 // CFClass
 //
+CFAllocatorContext CFClass::allocatorContext =
+{
+    0,
+    NULL,
+    NULL, /* retain */
+    NULL, /* release */
+    NULL, /* copyDescription */
+    allocatorAllocate, /* allocate */
+    allocatorReallocate, /* reallocate */
+    allocatorDeallocate, /* deallocate */
+    allocatorPreferredSize /* preferredSize */
+};
+
 CFClass::CFClass(const char *name)
 {
        // initialize the CFRuntimeClass structure
        className = name;
        init = NULL;
        copy = NULL;
-       finalize = finalizeType;
+       finalize = NULL;
        equal = equalType;
        hash = hashType;
        copyFormattingDesc = copyFormattingDescType;
        assert(typeID != _kCFRuntimeNotATypeID);
 }
     
-void
-CFClass::finalizeType(CFTypeRef cf)
-{
-    /*
-     * Called on a CFRelease of any Sec object: single thread through
-     * same lock held by public API calls. This is a recursive lock
-     * so it's safe to do this for CF objects allocated and released
-     * within the Sec layer. 
-     */
-    StLock<Mutex> _(globals().apiLock);
-       SecCFObject *obj = SecCFObject::optional(cf);
-       if (!obj->isNew())
-               obj->~SecCFObject();
-}
-
 Boolean
 CFClass::equalType(CFTypeRef cf1, CFTypeRef cf2)
 {
 {
        return SecCFObject::optional(cf)->copyDebugDesc();
 }
+
+//
+// CFAllocatorContext callbacks.
+//
+void *
+CFClass::allocatorAllocate(CFIndex allocSize, CFOptionFlags hint, void *info)
+{
+       return malloc(allocSize);
+}
+
+void *
+CFClass::allocatorReallocate(void *ptr, CFIndex newsize, CFOptionFlags hint, void *info)
+{
+       return realloc(ptr, newsize);
+}
+
+void
+CFClass::allocatorDeallocate(void *ptr, void *info)
+{
+    /*
+     * Called on a CFRelease of any Sec object: single thread through
+     * same lock held by public API calls. This is a recursive lock
+     * so it's safe to do this for CF objects allocated and released
+     * within the Sec layer. 
+     */
+    StLock<Mutex> _(globals().apiLock);
+       CFTypeRef cf = reinterpret_cast<CFTypeRef>(reinterpret_cast<intptr_t>(ptr) + sizeof(CFAllocatorRef));
+       CFIndex rc = CFGetRetainCount(cf);
+       if (rc == 1)
+       {
+               SecCFObject *obj = SecCFObject::optional(cf);
+               if (!obj->isNew())
+                       obj->~SecCFObject();
+               free(ptr);
+       }
+       else if (rc > 1)
+       {
+               // Since CFRelease did nothing other than call CFAllocatorDeallocate() followed
+               // by a CFRelease() of the allocator we need to counter that here.
+               CFRetain(CFGetAllocator(cf));
+               CFRelease(cf);
+       }
+       else
+       {
+               // Something bad happened we're screwed
+       }
+}
+
+CFIndex
+CFClass::allocatorPreferredSize(CFIndex size, CFOptionFlags hint, void *info)
+{
+       return size;
+}
 
     CFClass(const char *name);
 
 private:
-    static void finalizeType(CFTypeRef cf);
     static Boolean equalType(CFTypeRef cf1, CFTypeRef cf2);
     static CFHashCode hashType(CFTypeRef cf);
        static CFStringRef copyFormattingDescType(CFTypeRef cf, CFDictionaryRef dict);
        static CFStringRef copyDebugDescType(CFTypeRef cf);
 
+       // CFAllocatorContext callbacks.
+       static void *allocatorAllocate(CFIndex allocSize, CFOptionFlags hint, void *info);
+       static void *allocatorReallocate(void *ptr, CFIndex newsize, CFOptionFlags hint, void *info);
+       static void allocatorDeallocate(void *ptr, void *info);
+       static CFIndex allocatorPreferredSize(CFIndex size, CFOptionFlags hint, void *info);
+
 public:
     CFTypeID typeID;
+       static CFAllocatorContext allocatorContext;
 };
 
 /* Singleton that registers all the CFClass instances with the CFRuntime.
        CFClass PolicyCursor;
        CFClass Trust;
        CFClass TrustedApplication;
+
+       CFAllocatorRef allocator;
 };
 
 extern SecCFTypes &gTypes();
 
 void *
 SecCFObject::allocate(size_t size, CFTypeID typeID) throw(std::bad_alloc)
 {
-       void *p = const_cast<void *>(_CFRuntimeCreateInstance(NULL, typeID,
+       void *p = const_cast<void *>(_CFRuntimeCreateInstance(gTypes().allocator, typeID,
                size + kAlignedRuntimeSize - sizeof(CFRuntimeBase), NULL));
        if (p == NULL)
                throw std::bad_alloc();
 
 <plist version="0.9">
 <array>
         <string>/Applications/Mail.app</string>
+        <string>/Applications/System Preferences.app</string>
+        <string>/Applications/iCal.app</string>
         <string>/Applications/iChat.app</string>
+        <string>/Applications/iMovie.app</string>
+        <string>/Applications/iPhoto.app</string>
         <string>/Applications/iSync.app</string>
-        <string>/Applications/System Preferences.app</string>
-        <string>/System/Library/PrivateFrameworks/InstantMessage.framework/iChatAgent.app</string>
+        <string>/Applications/iTunes.app</string>
+        <string>/System/Library/CoreServices/Finder.app</string>
+        <string>/System/Library/CoreServices/MirrorAgent.app</string>
         <string>/System/Library/CoreServices/SyncServer.app</string>
+        <string>/System/Library/PrivateFrameworks/InstantMessage.framework/iChatAgent.app</string>
 </array>
 </plist>
 
        UInt32 moved,
        OSStatus stat)
 {
-       sslLogRecordIo("===%s: req %4lu moved %4lu status %ld\n", 
+       sslLogRecordIo("===%s: req %4lu moved %4lu status %ld", 
                op, req, moved, stat);
 }
 #else
     SSLRecord       rec;
     UInt32          dataLen, processed;
     
+       sslLogRecordIo("SSLWrite top");
     if((ctx == NULL) || (bytesWritten == NULL)) {
        return paramErr;
     }
     UInt32          bufSize, remaining, count;
     SSLRecord       rec;
     
+       sslLogRecordIo("SSLRead top");
     if((ctx == NULL) || (processed == NULL)) {
        return paramErr;
     }
     bufSize = dataLength;
     *processed = 0;        /* Initialize in case we return with errSSLWouldBlock */
 
+readRetry:
        /* first handle cases in which we know we're finished */
        switch(ctx->state) {
                case SSL_HdskStateGracefulClose:
     err = noErr;
     
 exit:
+       /* test for renegotiate: loop until something happens */
+       if((err == noErr) && (*processed == 0)) {
+               sslLogNegotiateDebug("SSLRead recursion");
+               goto readRetry;
+       }
        /* shut down on serious errors */
        switch(err) {
                case noErr:
 {   
        OSStatus      err = noErr;      
     
+       sslHdskStateDebug("SSLClose");
        if(ctx == NULL) {
                return paramErr;
        }
 
+++ /dev/null
-michael.pbxuser
-perry.pbxuser
 
                        );
                        buildSettings = {
                                DYLIB_COMPATIBILITY_VERSION = 1;
-                               DYLIB_CURRENT_VERSION = 164.1;
+                               DYLIB_CURRENT_VERSION = 176;
                                FRAMEWORK_SEARCH_PATHS = "\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"";
                                HEADER_SEARCH_PATHS = "\"$(BUILT_PRODUCTS_DIR)/BSafe.framework/Headers\" \"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks/BSafe.framework/Headers\" \"$(SRCROOT)/AppleCSP\" \"$(SRCROOT)/AppleCSP/open_ssl\"";
                                LIBRARY_STYLE = STATIC;
                        );
                        buildSettings = {
                                DYLIB_COMPATIBILITY_VERSION = 1;
-                               DYLIB_CURRENT_VERSION = 164.1;
+                               DYLIB_CURRENT_VERSION = 176;
                                LIBRARY_STYLE = STATIC;
                                OPTIMIZATION_CFLAGS = "-Os -DNDEBUG";
                                OTHER_CFLAGS = "-DVDADER_RULES";
                        );
                        buildSettings = {
                                DYLIB_COMPATIBILITY_VERSION = 1;
-                               DYLIB_CURRENT_VERSION = 164.1;
+                               DYLIB_CURRENT_VERSION = 176;
                                LIBRARY_STYLE = STATIC;
                                OPTIMIZATION_CFLAGS = "-Os -DNDEBUG";
                                OTHER_CFLAGS = "";
                        );
                        buildSettings = {
                                DYLIB_COMPATIBILITY_VERSION = 1;
-                               DYLIB_CURRENT_VERSION = 164.1;
+                               DYLIB_CURRENT_VERSION = 176;
                                FRAMEWORK_SEARCH_PATHS = "\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"";
                                LIBRARY_STYLE = STATIC;
                                OPTIMIZATION_CFLAGS = "-Os -DNDEBUG";
                        );
                        buildSettings = {
                                DYLIB_COMPATIBILITY_VERSION = 1;
-                               DYLIB_CURRENT_VERSION = 164.1;
+                               DYLIB_CURRENT_VERSION = 176;
                                FRAMEWORK_SEARCH_PATHS = "\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"";
                                LIBRARY_STYLE = STATIC;
                                OPTIMIZATION_CFLAGS = "-Os -DNDEBUG";
                };
                01FA8039FFF2B54C11CD283A = {
                        children = (
+                               B6F3F06205E5C8DD003E48D8,
                                014259A8001645E911CD296C,
                                01FA804DFFF2B54C11CD283A,
                                01FA804EFFF2B54C11CD283A,
                                01FA8900FFF2BC5611CD283A,
                        );
                        buildSettings = {
-                               CURRENT_PROJECT_VERSION = 164.1;
+                               CURRENT_PROJECT_VERSION = 176;
                                HEADER_SEARCH_PATHS = "\"$(BUILT_PRODUCTS_DIR)/derived_src\"";
                                INSTALL_PATH = "$(SYSTEM_CORE_SERVICES_DIR)";
                                LIBRARY_SEARCH_PATHS = "";
                                OPTIMIZATION_CFLAGS = "-Os -DNDEBUG";
                                OTHER_CFLAGS = "-DDatabase=XDatabase";
-                               OTHER_LDFLAGS = "-twolevel_namespace -lSecurityAgentClient";
+                               OTHER_LDFLAGS = "-twolevel_namespace -lSecurityAgentClient -lbsm";
                                OTHER_REZFLAGS = "";
                                PRODUCT_NAME = SecurityServer;
                                REZ_EXECUTABLE = YES;
                                40ACEF4D0462F6EC0035B857,
                                40ACEF510462F6FF0035B857,
                                C2C11915047187E800CA2E77,
+                               B6F3F06605E5C926003E48D8,
                        );
                        isa = PBXHeadersBuildPhase;
                        runOnlyForDeploymentPostprocessing = 0;
                                40ACEF4C0462F6EC0035B857,
                                40ACEF500462F6FF0035B857,
                                C2C11914047187E800CA2E77,
+                               B6F3F06505E5C926003E48D8,
                        );
                        isa = PBXSourcesBuildPhase;
                        runOnlyForDeploymentPostprocessing = 0;
                                01FA890AFFF2BCA811CD283A,
                        );
                        buildSettings = {
-                               CURRENT_PROJECT_VERSION = 164.1;
+                               CURRENT_PROJECT_VERSION = 176;
                                INSTALL_PATH = "$(SYSTEM_CORE_SERVICES_DIR)";
                                LIBRARY_SEARCH_PATHS = "";
                                OPTIMIZATION_CFLAGS = "-Os -DNDEBUG";
                        );
                        buildSettings = {
                                DYLIB_COMPATIBILITY_VERSION = 1;
-                               DYLIB_CURRENT_VERSION = 164.1;
+                               DYLIB_CURRENT_VERSION = 176;
                                INSTALL_PATH = /usr/local/lib;
                                LIBRARY_STYLE = STATIC;
                                OPTIMIZATION_CFLAGS = "-Os -DNDEBUG";
                                F5DDE3AE00B3358F01CD283A,
                        );
                        buildSettings = {
-                               CURRENT_PROJECT_VERSION = 164.1;
+                               CURRENT_PROJECT_VERSION = 176;
                                DYLIB_COMPATIBILITY_VERSION = 1;
-                               DYLIB_CURRENT_VERSION = 164.1;
+                               DYLIB_CURRENT_VERSION = 176;
                                FRAMEWORK_SEARCH_PATHS = "\"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks\"";
                                FRAMEWORK_VERSION = A;
                                HEADER_SEARCH_PATHS = "\"$(SRCROOT)\" \"$(BUILT_PRODUCTS_DIR)/derived_src\"";
        <key>CFBundlePackageType</key>
        <string>FMWK</string>
        <key>CFBundleShortVersionString</key>
-       <string>2.2</string>
+       <string>2.3</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>164.1</string>
+       <string>176</string>
 </dict>
 </plist>
 ";
                        );
                        buildSettings = {
                                DYLIB_COMPATIBILITY_VERSION = 1;
-                               DYLIB_CURRENT_VERSION = 164.1;
+                               DYLIB_CURRENT_VERSION = 176;
                                HEADER_SEARCH_PATHS = "\"$(BUILT_PRODUCTS_DIR)/include\"";
                                INSTALL_PATH = /usr/local/lib;
                                LIBRARY_STYLE = STATIC;
                                325EAA2800D6B08805CD296C,
                        );
                        buildSettings = {
-                               CURRENT_PROJECT_VERSION = 164.1;
+                               CURRENT_PROJECT_VERSION = 176;
                                LIBRARY_SEARCH_PATHS = "";
                                OPTIMIZATION_CFLAGS = "-Os -DNDEBUG";
                                OTHER_CFLAGS = "";
        <key>CFBundlePackageType</key>
        <string>BNDL</string>
        <key>CFBundleShortVersionString</key>
-       <string>2.2</string>
+       <string>2.3</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>164.1</string>
+       <string>176</string>
 </dict>
 </plist>
 ";
                                3290382100D6BA5905CD296C,
                        );
                        buildSettings = {
-                               CURRENT_PROJECT_VERSION = 164.1;
+                               CURRENT_PROJECT_VERSION = 176;
                                LIBRARY_SEARCH_PATHS = "";
                                OPTIMIZATION_CFLAGS = "-Os -DNDEBUG";
                                OTHER_CFLAGS = "";
        <key>CFBundlePackageType</key>
        <string>BNDL</string>
        <key>CFBundleShortVersionString</key>
-       <string>2.2</string>
+       <string>2.3</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>164.1</string>
+       <string>176</string>
 </dict>
 </plist>
 ";
                                3290382700D6BA5905CD296C,
                        );
                        buildSettings = {
-                               CURRENT_PROJECT_VERSION = 164.1;
+                               CURRENT_PROJECT_VERSION = 176;
                                LIBRARY_SEARCH_PATHS = "";
                                OPTIMIZATION_CFLAGS = "-Os -DNDEBUG";
                                OTHER_CFLAGS = "";
        <key>CFBundlePackageType</key>
        <string>BNDL</string>
        <key>CFBundleShortVersionString</key>
-       <string>2.2</string>
+       <string>2.3</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>164.1</string>
+       <string>176</string>
 </dict>
 </plist>
 ";
                                3290382D00D6BA5905CD296C,
                        );
                        buildSettings = {
-                               CURRENT_PROJECT_VERSION = 164.1;
+                               CURRENT_PROJECT_VERSION = 176;
                                LIBRARY_SEARCH_PATHS = "";
                                OPTIMIZATION_CFLAGS = "-Os -DNDEBUG";
                                OTHER_CFLAGS = "";
        <key>CFBundlePackageType</key>
        <string>BNDL</string>
        <key>CFBundleShortVersionString</key>
-       <string>2.2</string>
+       <string>2.3</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>164.1</string>
+       <string>176</string>
 </dict>
 </plist>
 ";
                                3290383300D6BA5905CD296C,
                        );
                        buildSettings = {
-                               CURRENT_PROJECT_VERSION = 164.1;
+                               CURRENT_PROJECT_VERSION = 176;
                                LIBRARY_SEARCH_PATHS = "";
                                OPTIMIZATION_CFLAGS = "-Os -DNDEBUG";
                                OTHER_LDFLAGS = "-bundle -undefined error";
        <key>CFBundlePackageType</key>
        <string>BNDL</string>
        <key>CFBundleShortVersionString</key>
-       <string>2.2</string>
+       <string>2.3</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>164.1</string>
+       <string>176</string>
 </dict>
 </plist>
 ";
                        );
                        buildSettings = {
                                DYLIB_COMPATIBILITY_VERSION = 1;
-                               DYLIB_CURRENT_VERSION = 164.1;
+                               DYLIB_CURRENT_VERSION = 176;
                                INSTALL_PATH = /usr/local/lib;
                                LIBRARY_STYLE = STATIC;
                                OTHER_CFLAGS = "";
 //9D2
 //9D3
 //9D4
+//B60
+//B61
+//B62
+//B63
+//B64
+               B6F3F06205E5C8DD003E48D8 = {
+                       children = (
+                               B6F3F06305E5C926003E48D8,
+                               B6F3F06405E5C926003E48D8,
+                       );
+                       isa = PBXGroup;
+                       name = "Common Criteria";
+                       refType = 4;
+               };
+               B6F3F06305E5C926003E48D8 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       path = ccaudit.cpp;
+                       refType = 4;
+               };
+               B6F3F06405E5C926003E48D8 = {
+                       fileEncoding = 30;
+                       isa = PBXFileReference;
+                       path = ccaudit.h;
+                       refType = 4;
+               };
+               B6F3F06505E5C926003E48D8 = {
+                       fileRef = B6F3F06305E5C926003E48D8;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               B6F3F06605E5C926003E48D8 = {
+                       fileRef = B6F3F06405E5C926003E48D8;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+//B60
+//B61
+//B62
+//B63
+//B64
 //BD0
 //BD1
 //BD2
 
 
 namespace Authorization {
 
-
 //
 // Errors to be thrown
 //
 
 #include <sys/stat.h>
 #include <sys/types.h>
 
-
 class AuthorizationToken;
 
 using Authorization::AuthorizationDBPlist;
 
 #include <grp.h>
 #include <unistd.h>
 
+#include <bsm/libbsm.h>
+#include <bsm/audit_uevents.h>
+#include "ccaudit.h"
 
 //
 // Rule class
 CFStringRef RuleImpl::kRuleDelegateID = CFSTR(kAuthorizationRightRule);
 CFStringRef RuleImpl::kRuleMechanismsID = CFSTR(kAuthorizationRuleClassMechanisms);
 
+
 string
 RuleImpl::Attribute::getString(CFDictionaryRef config, CFStringRef key, bool required = false, char *defaultValue = NULL)
 {
        AuthItemSet context = auth.infoSet();
        AuthItemSet hints = environment;
     
+    CommonCriteria::AuditRecord auditrec(auth.creatorAuditToken());
+
     AuthorizationResult result = kAuthorizationResultAllow;
     vector<string>::const_iterator currentMechanism = mEvalDef.begin();
     
                     Credential newCredential(username, password, true); // create a new shared credential
                                        
                                        if (newCredential->isValid())
+                                       {
                                                Syslog::info("authinternal authenticated user %s (uid %lu) for right %s.", newCredential->username().c_str(), newCredential->uid(), inRight->name());
+                                               auditrec.submit(AUE_ssauthint, CommonCriteria::errNone, inRight->name());
+                                       }
                                        else
+                                       {
                                                // we can't be sure that the user actually exists so inhibit logging of uid
                                                Syslog::error("authinternal failed to authenticate user %s for right %s.", newCredential->username().c_str(), inRight->name());
-                                       
+
+                                               auditrec.submit(AUE_ssauthint, CommonCriteria::errInvalidCredential, inRight->name());
+                                       }
+
                     if (newCredential->isValid())
                     {
                         outCredentials.clear(); // only keep last one
             // fetch context and construct a credential to be tested
                        AuthItemSet inContext = auth.infoSet();
             CredentialSet newCredentials = makeCredentials(inContext);
+                       // clear context after extracting credentials
+                       auth.clearInfoSet(); 
             
             for (CredentialSet::const_iterator it = newCredentials.begin(); it != newCredentials.end(); ++it)
             {
                 const Credential& newCredential = *it;
+                               CommonCriteria::AuditRecord auditrec(auth.creatorAuditToken());
 
                                // @@@ we log the uid a process was running under when it created the authref, which is misleading in the case of loginwindow
                                if (newCredential->isValid())
+                               {
                                        Syslog::info("uid %lu succeeded authenticating as user %s (uid %lu) for right %s.", auth.creatorUid(), newCredential->username().c_str(), newCredential->uid(), inRight->name());
+                                       auditrec.submit(AUE_ssauthorize, CommonCriteria::errNone, inRight->name());
+                               }
                                else
+                               {
                                        // we can't be sure that the user actually exists so inhibit logging of uid
                                        Syslog::error("uid %lu failed to authenticate as user %s for right %s.", auth.creatorUid(), newCredential->username().c_str(), inRight->name());
+                                       auditrec.submit(AUE_ssauthorize, CommonCriteria::errInvalidCredential, inRight->name());
+                               }
                 
                 if (!newCredential->isValid())
                 {
                 {
                                        // whack an equivalent credential, so it gets updated to a later achieved credential which must have been more stringent
                     credentials.erase(newCredential); credentials.insert(newCredential);
+                                       // use valid credential to set context info
+                                       auth.setCredentialInfo(newCredential);
                     secdebug("SSevalMech", "added valid credential for user %s", newCredential->username().c_str());
                     status = errAuthorizationSuccess;
                     break;
                 }
                 else
+                               {
                     reason = SecurityAgent::userNotInGroup; //unacceptableUser; // userNotInGroup
+                                       // don't audit: we denied on the basis of something
+                                       // other than a bad user or password
+                               }
             }
             
             if (status == errAuthorizationSuccess)
         else
             if ((status == errAuthorizationCanceled) ||
                (status == errAuthorizationInternal))
-                break;
+                       {
+                               auth.clearInfoSet();
+                               break;
+                       }
     }
 
     // If we fell out of the loop because of too many tries, notify user
                AuthItemRef triesHint(AGENT_HINT_TRIES, AuthValueOverlay(sizeof(tries), &tries));
                environmentToClient.erase(triesHint); environmentToClient.insert(triesHint); // replace
         evaluateMechanism(inRight, environmentToClient, auth, credentials);
+               auth.clearInfoSet();
     }
 
        Process &cltProc = Server::active().connection().process;
        Credential newCredential;
        // @@@ Keep the default reason the same, so the agent only gets userNotInGroup or invalidPassphrase
        SecurityAgent::Reason reason = SecurityAgent::userNotInGroup;
+
+       CommonCriteria::AuditRecord auditrec(auth.creatorAuditToken());
+
        // @@@ Hardcoded 3 tries to avoid infinite loops.
        for (uint32_t tryCount = 0; tryCount < mTries; ++tryCount)
        {
 
                // Now we have successfully obtained a credential we need to make sure it authorizes the requested right
                if (!newCredential->isValid())
+               {
                        reason = SecurityAgent::invalidPassphrase;
+                       auditrec.submit(AUE_ssauthorize, CommonCriteria::errInvalidCredential, inRight->name());
+               }
                else {
                        status = evaluateCredentialForRight(inRight, inRule, environmentToClient, now, newCredential, true);
                        if (status == errAuthorizationSuccess)
                                // add credential to authinfo
                                auth.setCredentialInfo(newCredential);
                                                                
+                               auditrec.submit(AUE_ssauthorize, CommonCriteria::errNone, inRight->name());
                                return errAuthorizationSuccess;
                        }
                        else if (status != errAuthorizationDenied)
+                       {
+                               if (status == errAuthorizationCanceled)
+                                       auditrec.submit(AUE_ssauthorize, CommonCriteria::errUserCanceled, inRight->name());
+                               // else don't audit--error not due to bad
+                               // username or password
                                return status;
+                       }
                }
                reason = SecurityAgent::userNotInGroup;
        }
        query.cancel(SecurityAgent::tooManyTries);
+
+       auditrec.submit(AUE_ssauthorize, CommonCriteria::errTooManyTries, inRight->name());
        return errAuthorizationDenied;
 }
 
 
        
        map<string,string> localizedPrompts() const { return mLocalizedPrompts; }
        
-    
 // parsed attributes
 private:
        enum Type
 
                        <key>rule</key>
                        <string>appserver-admin</string>
                </dict>
+               <key>com.apple.desktopservices</key>
+               <dict>
+                       <key>class</key>
+                       <string>user</string>
+                       <key>comment</key>
+                       <string>authorize privileged file operations from the finder</string>
+                       <key>group</key>
+                       <string>admin</string>
+                       <key>mechanisms</key>
+                       <array>
+                               <string>builtin:authenticate</string>
+                       </array>
+                       <key>shared</key>
+                       <false/>
+                       <key>timeout</key>
+                       <integer>0</integer>
+               </dict>
                <key>com.apple.appserver.privilege.user</key>
                <dict>
                        <key>class</key>
 
 //
 // Create an authorization token.
 //
-AuthorizationToken::AuthorizationToken(Session &ssn, const CredentialSet &base, const security_token_t &securityToken)
+AuthorizationToken::AuthorizationToken(Session &ssn, const CredentialSet &base, const audit_token_t &auditToken)
        : session(ssn), mBaseCreds(base), mTransferCount(INT_MAX), 
-       mCreatorUid(securityToken.val[0]),
+       mCreatorUid(auditToken.val[1]),
+       mCreatorGid(auditToken.val[2]),
     mCreatorCode(Server::connection().process.clientCode()),
-       mCreatorPid(Server::connection().process.pid())
+       mCreatorPid(Server::connection().process.pid()),
+       mCreatorAuditToken(auditToken)
 {
     // generate our (random) handle
     Server::active().random(mHandle);
        setInfoSet(dstInfoSet);
 }
 
+void
+AuthorizationToken::clearInfoSet()
+{
+    AuthItemSet dstInfoSet;
+    secdebug("SSauth", "Authorization %p clearing context", this);
+    setInfoSet(dstInfoSet);
+}
+
 
 
 class AuthorizationToken {
 public:
-       AuthorizationToken(Session &ssn, const CredentialSet &base, const security_token_t &securityToken);
+       AuthorizationToken(Session &ssn, const CredentialSet &base, const audit_token_t &auditToken);
        ~AuthorizationToken();
 
     Session &session;
        bool mayInternalize(Process &proc, bool countIt = true);
 
        uid_t creatorUid() const        { return mCreatorUid; }
+       uid_t creatorGid() const        { return mCreatorGid; }
     CodeSigning::OSXCode *creatorCode() const { return mCreatorCode; }
        pid_t creatorPid() const        { return mCreatorPid; }
        
+       audit_token_t creatorAuditToken() const {return mCreatorAuditToken; }
+
        AuthItemSet infoSet(AuthorizationString tag = NULL);
     void setInfoSet(AuthItemSet &newInfoSet);
     void setCredentialInfo(const Credential &inCred);
+    void clearInfoSet();
 
 public:
        static AuthorizationToken &find(const AuthorizationBlob &blob);
        ProcessSet mUsingProcesses;             // set of process objects using this token
 
        uid_t mCreatorUid;                              // Uid of proccess that created this authorization
+       gid_t mCreatorGid;                              // Gid of proccess that created this authorization
     RefPointer<OSXCode> mCreatorCode; // code id of creator
        pid_t mCreatorPid;                              // Pid of processs that created this authorization
 
+       audit_token_t mCreatorAuditToken;       // Audit token of the process that created this authorization
+
     AuthItemSet mInfoSet;                      // Side band info gathered from evaluations in this session
 
 private:
 
 #include "notifications.h"
 #include "ucsp.h"
 #include <mach/mach_error.h>
+#include <bsm/audit.h>
+#include <bsm/audit_kevents.h>
+#include <bsm/audit_record.h>
+#include <bsm/audit_uevents.h>
+#include <bsm/libbsm.h>
+#include "ccaudit.h"
 
 using namespace MachPlusPlus;
 
-
 //
 // Construct the server object
 //
     mAuthority(authority),
        mCodeSignatures(signatures)
 {
+
+    initAudit();
+
     // engage the subsidiary port handler for sleep notifications
     add(sleepWatcher);
 }
 {
        MachServer::run(0x10000,
         MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0) |
-        MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_SENDER));
+        MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT));
 }
 
 
 // Everything at and below that level is constructed. This is straight-forward except
 // in the case of session re-initialization (see below).
 //
+// audit_token_t.val[1] is the EUID, audit_token_t.val[2] is the EGID.  
+//
 void Server::setupConnection(ConnectLevel type, Port servicePort, Port replyPort, Port taskPort,
-    const security_token_t &securityToken, const ClientSetupInfo *info, const char *identity)
+    const audit_token_t &auditToken, 
+    const ClientSetupInfo *info, const char *identity)
 {
        // first, make or find the process based on task port
        StLock<Mutex> _(lock);
                        CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
                assert(info && identity);
                proc = new Process(servicePort, taskPort, info, identity,
-                       securityToken.val[0], securityToken.val[1]);
+                       auditToken.val[1], auditToken.val[2]);
                notifyIfDead(taskPort);
        }
 
     Session::lockAllDatabases(true);
 }
 
+void Server::initAudit(void)
+{
+    secdebug("SS", "initializing Common Criteria auditing");
+    mAudit.auditId(geteuid());
+    // Set the class mask so only the audit records we submit are written.
+    mAudit.eventMask().set(AUE_NULL, AUE_NULL);
+       mAudit.terminalId().set();
+    // XXX  If we use SS session IDs instead, get the RootSession ID
+    mAudit.sessionId(getpid());
+       mAudit.registerSession();
+}
 
 //
 // Return the primary Cryptographic Service Provider.
 
 #include "xdatabase.h"
 #include "authority.h"
 #include <map>
+#include "ccaudit.h"
 
 #define EQUIVALENCEDBPATH "/var/db/CodeEquivalenceDatabase"
 
                connectNewThread
        };
        void setupConnection(ConnectLevel type, Port servicePort, Port replyPort, Port taskPort,
-        const security_token_t &securityToken,
-               const ClientSetupInfo *info = NULL, const char *executablePath = NULL);
+        const audit_token_t &auditToken, 
+       const ClientSetupInfo *info = NULL, const char *executablePath = NULL);
                
        void endConnection(Port replyPort);
        
         void systemWillSleep();
     };
     SleepWatcher sleepWatcher;
-       
+
+    void initAudit(void);
+
 private:
        Mutex lock;                                     // master lock
        
     
        Authority &mAuthority;
        CodeSignatures &mCodeSignatures;
+
+    // Per-process audit initialization.  
+    CommonCriteria::AuditSession mAudit;       
 };
 
 #endif //_H_SERVER
 
        const AuthItemSet &environment,
        AuthorizationFlags flags,
        AuthorizationBlob &newHandle,
-       const security_token_t &securityToken)
+       const audit_token_t &auditToken)
 {
        // invoke the authorization computation engine
        CredentialSet resultCreds;
        
        // this will acquire mLock, so we delay acquiring it
-       auto_ptr<AuthorizationToken> auth(new AuthorizationToken(*this, resultCreds, securityToken));
+       auto_ptr<AuthorizationToken> auth(new AuthorizationToken(*this, resultCreds, auditToken));
 
     // Make a copy of the mSessionCreds
     CredentialSet sessionCreds;
 
        const CredentialSet &authCredentials() const    { return mSessionCreds; }
 
        OSStatus authCreate(const AuthItemSet &rights, const AuthItemSet &environment,
-               AuthorizationFlags flags, AuthorizationBlob &newHandle, const security_token_t &securityToken);
+               AuthorizationFlags flags, AuthorizationBlob &newHandle, const audit_token_t &auditToken);
        void authFree(const AuthorizationBlob &auth, AuthorizationFlags flags);
        OSStatus authGetRights(const AuthorizationBlob &auth,
                const AuthItemSet &requestedRights, const AuthItemSet &environment,
 
 //
 // Bracket Macros
 //
-#define UCSP_ARGS      mach_port_t servicePort, mach_port_t replyPort, security_token_t securityToken, \
+#define UCSP_ARGS      mach_port_t servicePort, mach_port_t replyPort, audit_token_t auditToken, \
                     CSSM_RETURN *rcode
 #define CONTEXT_ARGS Context context, Pointer contextBase, Context::Attr *attributes, mach_msg_type_number_t attrSize
 
 {
        BEGIN_IPCN
        Server::active().setupConnection(Server::connectNewProcess, servicePort, replyPort,
-               taskPort, securityToken, &info, identity);
+               taskPort, auditToken, &info, identity);
        END_IPCN(CSSM)
        return KERN_SUCCESS;
 }
        try {
                Session *session = new DynamicSession(TaskPort(taskPort).bootstrap());
                Server::active().setupConnection(Server::connectNewSession, session->servicePort(), replyPort,
-                       taskPort, securityToken, &info, identity);
+                       taskPort, auditToken, &info, identity);
                *newServicePort = session->servicePort();
        } catch (const MachPlusPlus::Error &err) {
                switch (err.error) {
 {
        BEGIN_IPCN
        Server::active().setupConnection(Server::connectNewThread, servicePort, replyPort,
-               taskPort, securityToken);
+               taskPort, auditToken);
        END_IPCN(CSSM)
        return KERN_SUCCESS;
 }
        Authorization::AuthItemSet rights(inRights), environment(inEnvironment);
 
        *rcode = connection.process.session.authCreate(rights, environment, 
-               flags, *authorization, securityToken);
+               flags, *authorization, auditToken);
        END_IPC(CSSM)
 }
 
 
 //
 #define UCSP_PORTS     requestport sport: mach_port_t; \
                                        replyport rport: mach_port_make_send_t; \
-                    serversectoken sourceSecurity: security_token_t; \
+                   serveraudittoken sourceAudit: audit_token_t; \
                                        out rcode: CSSM_RETURN
 #define IN_CONTEXT     in context: Context; in contextBase: BasePointer; in attrs: ContextAttributes
 #define IN_BLOB(name,type)     in name: type##Blob; in name##Base: type##Ptr
 
+++ /dev/null
-cdsa_pluginlib?Data
 
+++ /dev/null
-cdsa_utilities?Data
 
--- /dev/null
+/*
+ * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved.
+ * 
+ * The contents of this file constitute Original Code as defined in and are
+ * subject to the Apple Public Source License Version 1.2 (the 'License').
+ * You may not use this file except in compliance with the License. Please obtain
+ * a copy of the License at http://www.apple.com/publicsource and read it before
+ * using this file.
+ * 
+ * This 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.
+ */
+
+
+#include <strings.h>   // bcopy()
+#include <unistd.h>    // gethostname()
+#include <netdb.h>     // gethostbyname()
+#include <sys/types.h> // inet_addr()
+#include <sys/socket.h>        // inet_addr()
+#include <netinet/in.h>        // inet_addr()
+#include <arpa/inet.h> // inet_addr()
+#include <errno.h>
+#include "utilities.h"
+#include <Security/logging.h>
+#include <bsm/libbsm.h>
+#include "ccaudit.h"
+
+namespace Security
+{
+namespace CommonCriteria
+{
+
+void TerminalId::set(void)
+{
+       if (audit_set_terminal_id(&mTid) != kAUNoErr)
+       {
+               // If we start seeing the syslog too often, change to secdebug()
+               Syslog::warning("setting terminal ID info failed; using defaults");
+               mTid.port = 0;
+               mTid.machine = 0;
+       }
+}
+
+void AuditSession::registerSession(void)
+{
+    auditinfo_t auinfo;
+
+    auinfo.ai_auid = mAuditId;
+    auinfo.ai_asid = mSessionId;
+    bcopy(&mTerminalId.get(), &(auinfo.ai_termid), sizeof(auinfo.ai_termid));
+    bcopy(&mEventMask.get(), &(auinfo.ai_mask), sizeof(auinfo.ai_mask));
+
+    if (setaudit(&auinfo) != 0)
+       {
+               if (errno == ENOTSUP)
+               {
+                       Syslog::notice("Attempted to initialize auditing, but this kernel that does not support auditing");
+                       return;
+               }
+               Syslog::notice("Could not initialize auditing; continuing");
+       }
+}
+
+void AuditRecord::submit(const short event_code, const int returnCode, 
+                        const char *msg)
+{
+    // If we're not auditing, do nothing
+    if (au_get_state() == AUC_NOAUDIT)
+               return;
+
+    // XXX  make this a secdebug, then enable it
+    // Syslog::notice("Submitting authorization audit record");
+
+    int ret = kAUNoErr;
+
+    // XXX/gh  3574731: Fix BSM SPI so the const_cast<>s aren't necessary
+    if (returnCode == 0)
+    {
+               token_t *tok = NULL;
+
+               if (msg)
+                       tok = au_to_text(const_cast<char *>(msg));
+               ret = audit_write_success(event_code, const_cast<token_t *>(tok), 
+                                                                 mAuditId, mEUid, mEGid, mRUid, mRGid, 
+                                                                 mPid, mSessionId,
+                                                                 const_cast<au_tid_t *>(&(mTerminalId.get())));
+    }
+    else
+    {
+               ret = audit_write_failure(event_code, const_cast<char *>(msg), 
+                                                                 returnCode, mAuditId, mEUid, mEGid, 
+                                                                 mRUid, mRGid, mPid, mSessionId,
+                                                                 const_cast<au_tid_t *>(&(mTerminalId.get())));
+    }
+    if (ret != kAUNoErr)
+               MacOSError::throwMe(ret);
+}
+
+
+}      // end namespace CommonCriteria
+}      // end namespace Security
 
--- /dev/null
+/*
+ * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved.
+ * 
+ * The contents of this file constitute Original Code as defined in and are
+ * subject to the Apple Public Source License Version 1.2 (the 'License').
+ * You may not use this file except in compliance with the License. Please obtain
+ * a copy of the License at http://www.apple.com/publicsource and read it before
+ * using this file.
+ * 
+ * This 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.
+ */
+
+
+#ifndef _H_CCAUDIT
+#define _H_CCAUDIT
+
+#include <Security/utility_config.h>
+#include <bsm/audit.h>
+
+namespace Security
+{
+
+namespace CommonCriteria
+{
+
+// for Tiger, this should be incorporated into Security's OSStatus range
+enum ExternalErrors
+{
+       errNone = 0,
+       errInvalidCredential = 1111,    // try to make easier to find in log
+       errUserCanceled,
+       errTooManyTries,
+       errEndOfExternalErrors                  // sentry/placeholder
+};
+
+class AuditMask
+{
+  public:
+    AuditMask()                                { }
+    AuditMask(const AuditMask &am)     { set(am.get()); }
+    AuditMask(const au_mask_t &am)     { set(am); }
+    ~AuditMask()                       { }
+
+    void set(const au_mask_t &am)      { set(am.am_success, am.am_failure); }
+    void set(unsigned int s, unsigned int f)   { mMask.am_success = s; mMask.am_failure = f; }
+    const au_mask_t &get(void) const   { return mMask; }
+
+  private:
+    au_mask_t mMask;
+};
+
+// For the most part, we won't have a machine ID to initialize the 
+// au_tid_t's machine field.  There's no machine ID in the audit token,
+// for example, since MIG is localhost-only.  
+class TerminalId
+{
+  public:
+    TerminalId()                       { }
+    TerminalId(const TerminalId &t)    { set(t.get()); }
+    TerminalId(const au_tid_t &tid)    { set(tid); }
+    TerminalId(dev_t p, u_int32_t m)   { port(p); machine(m); }
+    ~TerminalId()                      { }
+
+    void set(void);                    // set using localhost
+    void set(const au_tid_t &tid)      { port(tid.port); machine(tid.machine); }
+    void port(dev_t p)                 { mTid.port = p; }
+    void machine(u_int32_t m)          { mTid.machine = m; }
+    const au_tid_t &get(void) const    { return mTid; }
+
+  private:
+    au_tid_t mTid;
+};
+
+// audit session state for the current process; only used by Server
+class AuditSession
+{
+  public:
+    AuditSession()                     { }
+    AuditSession(au_id_t auid, AuditMask &mask, au_asid_t sid, 
+                TerminalId &tid) 
+       : mAuditId(auid), mEventMask(mask), mTerminalId(tid),
+         mSessionId(sid)               { }
+    ~AuditSession()                    { }
+
+    // set audit info for this process in kernel
+    void registerSession(void);
+
+    void auditId(au_id_t auid)         { mAuditId = auid; }
+    void eventMask(AuditMask &mask)    { mEventMask = mask; }
+    void terminalId(TerminalId &tid)   { mTerminalId = tid; }
+    void sessionId(au_asid_t sid)      { mSessionId = sid; }
+
+    au_id_t auditId(void)              { return mAuditId; }
+    AuditMask &eventMask(void)         { return mEventMask; }
+    TerminalId &terminalId(void)       { return mTerminalId; }
+    au_asid_t sessionId(void)          { return mSessionId; }
+
+  private:
+    au_id_t mAuditId;
+    AuditMask mEventMask;
+    TerminalId mTerminalId;
+    au_asid_t mSessionId;
+};
+
+//
+// For submitting audit records.  Not general-purpose: no ability to 
+// submit arbitrary BSM tokens, for example.  However, the SecurityServer 
+// has only limited auditing requirements under Common Criteria.  
+//
+class AuditRecord
+{
+  public:
+    AuditRecord(const audit_token_t &auditToken)
+       : mAuditId(auditToken.val[0]),
+         mRUid(auditToken.val[3]),
+         mRGid(auditToken.val[4]),
+         mEUid(auditToken.val[1]),
+         mEGid(auditToken.val[2]),
+         mPid(auditToken.val[5]),
+         mSessionId(auditToken.val[6]),
+         mTerminalId(auditToken.val[7], 0)     { }
+    ~AuditRecord()                             { }
+
+    // returnCode == 0 --> success; nonzero returnCode --> failure
+    void submit(const short event_code, const int returnCode, 
+               const char *msg = NULL);
+
+  private:
+    au_id_t mAuditId;
+    uid_t mRUid;
+    gid_t mRGid;
+    uid_t mEUid;
+    gid_t mEGid;
+    pid_t mPid;
+    au_asid_t mSessionId;
+    TerminalId mTerminalId;
+};
+
+} // end namespace CommonCriteria
+
+} // end namespace Security
+
+#endif // _H_CCAUDIT
 
     const _Tp *_M_finish;
 };
 
-
 } // end namespace Security
 
 
 
+++ /dev/null
-PBUserInfo
-mds?Data
 
        unsigned long           fPID;
        unsigned long           fPort;
        unsigned long           fIPAddress;
+       mach_msg_audit_trailer_t fTail;
        sObject                         obj[ 10 ];
        char                            data[ 1 ];
 } sComData;
        unsigned long           fPort;
        sObject                         obj[ 10 ];
        char                            fData[ kIPCMsgLen ];
-       mach_msg_security_trailer_t     fTail;
+       mach_msg_audit_trailer_t        fTail;  // this is the largest trailer struct 
+                                               // we have the bucket large enough to receive it
 } sIPCMsg;
 
 typedef enum {
                msg->obj[0].length = curr;
                
                msg->fHeader.msgh_bits                  = MACH_MSGH_BITS( MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND );
-               msg->fHeader.msgh_size                  = sizeof( sIPCMsg ) - sizeof( mach_msg_security_trailer_t );
+               msg->fHeader.msgh_size                  = sizeof( sIPCMsg ) - sizeof( mach_msg_audit_trailer_t );
                msg->fHeader.msgh_id                    = kCheckUserNameAndPassword;
                msg->fHeader.msgh_remote_port   = serverPort;
                msg->fHeader.msgh_local_port    = replyPort;
                // get reply
                memset( msg, 0, kIPCMsgLen );
        
-               result = mach_msg( (mach_msg_header_t *)msg, MACH_RCV_MSG | MACH_RCV_TIMEOUT,
+               result = mach_msg( (mach_msg_header_t *)msg, 
+                                   MACH_RCV_MSG | MACH_RCV_TIMEOUT | 
+                                   MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT) | MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0),
                                                        0, kIPCMsgSize, replyPort, 300 * 1000, MACH_PORT_NULL );
 
                if ( result != MACH_MSG_SUCCESS ) {
 
 
 SYSTEM_LIBRARY_DIR=$(DSTROOT)/System/Library
 KEYCHAINS_DIR=$(SYSTEM_LIBRARY_DIR)/Keychains
-X509KEYCHAINS=X509Anchors X509Certificates
+ANCHORS_DIR=$(KEYCHAINS_DIR)/Anchors
+CERTIFICATES_DIR=$(KEYCHAINS_DIR)/Certificates
 
 #
 # world-writable directory we need to create for CRL cache
 # Install
 #
 install:
-       if [ ! -d $(KEYCHAINS_DIR) ]; then \
-               mkdir -p $(KEYCHAINS_DIR); \
-               chown root.admin $(KEYCHAINS_DIR); \
-               chmod 755 $(KEYCHAINS_DIR); \
-       fi
-       cd $(KEYCHAINS_SRC); cp $(X509KEYCHAINS) $(KEYCHAINS_DIR)
-       cd $(KEYCHAINS_DIR); \
-       chown root.admin $(X509KEYCHAINS); \
-       chmod 664 $(X509KEYCHAINS); \
-       ls -l $(X509KEYCHAINS)
+       for d in "$(KEYCHAINS_DIR)" "$(ANCHORS_DIR)" "$(CERTIFICATES_DIR)"; do \
+           if [ ! -d "$${d}" ]; then \
+                   mkdir -p "$${d}"; \
+                   chown root:admin "$${d}"; \
+                   chmod 755 "$${d}"; \
+           fi; \
+       done; \
+       find "$(KEYCHAINS_SRC)/roots" -maxdepth 1 -a -type f -exec cp {} "$(ANCHORS_DIR)" \; ; \
+       find "$(KEYCHAINS_SRC)/certs" -maxdepth 1 -a -type f -exec cp {} "$(CERTIFICATES_DIR)" \; ; \
+       chown root:admin "$(ANCHORS_DIR)/"*; \
+       chmod 664 "$(ANCHORS_DIR)/"*; \
+       chown root:admin "$(CERTIFICATES_DIR)/"*; \
+       chmod 664 "$(CERTIFICATES_DIR)/"*; \
        if [ ! -d $(CRL_CACHE_DIR) ]; then \
                mkdir -p $(CRL_CACHE_DIR); \
-               chown root.wheel $(CRL_CACHE_DIR); \
+               chown root:wheel $(CRL_CACHE_DIR); \
                chmod 777 $(CRL_CACHE_DIR); \
        fi
 
+++ /dev/null
-#! /bin/csh -f
-#
-# Build a keychain out of roots or certs.
-#
-set prog=$0
-if ( $#argv != 2 ) then
-        echo usage: ${prog:t} dbfile certsdir
-               echo dbfile must NOT exist.
-        exit(1)
-endif
-#
-# Our job is to cook up a list of files in certsdir, not including
-# the CVS directory.
-#
-set cwd=`pwd`
-set dbfile=$cwd/$argv[1]
-set certsdir=$argv[2]
-if ( -e $dbfile ) then
-   echo I insist that you delete $argv[1] manually.
-   exit(1)
-endif
-#
-set cmd="./makecerts $dbfile $certsdir/[a-zABD-Z0-9]* $certsdir/C[a-zA-UW-Z0-9]*"
-$cmd || exit(1)
 
+++ /dev/null
-#!/usr/bin/perl
-#
-# Use to gather certificates into specified keychain. 
-#
-$numFiles = $#ARGV;
-if($numFiles < 1) {
-       print "usage: makecerts keychainfile cert...\n";
-       die;
-}
-$dbname = $ARGV[0];
-
-my $count = 0;
-my $created;
-foreach $argnum (1 .. $numFiles) {
-        $thisCert = $ARGV[$argnum];
-        my @cmd = ("certtool", "i", $thisCert, "k=$dbname", "d");
-        do { push @cmd, "c"; $created = 1; } unless $created;
-        print "$thisCert ";
-        die if system @cmd;
-        $count++;
-}
-
-print "$count certificates placed into $dbname\n";
-exit 0;
 
+++ /dev/null
-#!/usr/bin/perl
-#
-#
-#
-use strict;
-
-my $dbname = "X509Anchors";
-
-my $count = 0;
-my $created;
-for my $file (@ARGV) {
-       my @cmd = ("certtool", "i", $file, "k=$dbname", "d");
-       do { push @cmd, "c"; $created = 1; } unless $created;
-       print "$file ";
-       die if system @cmd;
-       $count++;
-}
-
-print "$count certificates placed into $dbname\n";
-exit 0;
 
--- /dev/null
+#!/bin/sh
+
+# Create keychains if not there already
+if [ ! -f "$targetdisk/System/Library/Keychains/X509Anchors" ]; then
+       "$targetdisk/usr/bin/security" create-keychain -p X509Anchors "$targetdisk/System/Library/Keychains/X509Anchors"
+fi
+if [ ! -f "$targetdisk/System/Library/Keychains/X509Certificates" ]; then
+       "$targetdisk/usr/bin/security" create-keychain -p X509Certificates "$targetdisk/System/Library/Keychains/X509Certificates"
+fi
+
+# Add all anchors
+cd "$targetdisk/System/Library/Keychains/Anchors/"
+"$targetdisk/usr/bin/security" add-certificate -k "$targetdisk/System/Library/Keychains/X509Anchors" *
+
+# Add all intermediates
+cd "$targetdisk/System/Library/Keychains/Certificates/"
+"$targetdisk/usr/bin/security" add-certificate -k "$targetdisk/System/Library/Keychains/X509Certificates" *
+
+# we might want to delete the raw certificate files, in the interest of cruft cleanup
+#rm -rf "$targetdisk/System/Library/Keychains/Anchors"
+#rm -rf "$targetdisk/System/Library/Keychains/Certificates"