]> git.saurik.com Git - apple/security.git/blobdiff - Security/authd/session.c
Security-57031.1.35.tar.gz
[apple/security.git] / Security / authd / session.c
diff --git a/Security/authd/session.c b/Security/authd/session.c
new file mode 100644 (file)
index 0000000..3e0d76f
--- /dev/null
@@ -0,0 +1,208 @@
+/* Copyright (c) 2012 Apple Inc. All Rights Reserved. */
+
+#include "session.h"
+#include "process.h"
+#include "debugging.h"
+#include <dispatch/dispatch.h>
+#include <CoreFoundation/CoreFoundation.h>
+
+struct _session_s {
+    __AUTH_BASE_STRUCT_HEADER__;
+    
+    CFMutableSetRef credentials;
+    CFMutableSetRef processes;
+    auditinfo_addr_t auditinfo;
+    
+    dispatch_queue_t dispatch_queue;
+
+};
+
+static void
+_session_finalize(CFTypeRef value)
+{
+    session_t session = (session_t)value;
+    
+    LOGV("session: %i deallocated %p", session->auditinfo.ai_asid, session);
+    
+    // make sure queue is empty
+    dispatch_barrier_sync(session->dispatch_queue, ^{});
+    
+    dispatch_release(session->dispatch_queue);
+    CFReleaseSafe(session->credentials);
+    CFReleaseSafe(session->processes);
+}
+
+AUTH_TYPE_INSTANCE(session,
+                   .init = NULL,
+                   .copy = NULL,
+                   .finalize = _session_finalize,
+                   .equal = NULL,
+                   .hash = NULL,
+                   .copyFormattingDesc = NULL,
+                   .copyDebugDesc = NULL
+                   );
+
+static CFTypeID session_get_type_id() {
+    static CFTypeID type_id = _kCFRuntimeNotATypeID;
+    static dispatch_once_t onceToken;
+    
+    dispatch_once(&onceToken, ^{
+        type_id = _CFRuntimeRegisterClass(&_auth_type_session);
+    });
+    
+    return type_id;
+}
+
+session_t
+session_create(session_id_t sid)
+{
+    session_t session = NULL;
+        
+    session = (session_t)_CFRuntimeCreateInstance(kCFAllocatorDefault, session_get_type_id(), AUTH_CLASS_SIZE(session), NULL);
+    require(session != NULL, done);
+    
+    session->auditinfo.ai_asid = sid;
+    
+    if (!session_update(session)) {
+        LOGE("session: failed to get session info");
+    }
+    
+    session->dispatch_queue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);
+    check(session->dispatch_queue != NULL);
+    
+    session->credentials = CFSetCreateMutable(kCFAllocatorDefault, 0, &kCFTypeSetCallBacks);
+    session->processes = CFSetCreateMutable(kCFAllocatorDefault, 0, NULL);
+    
+    LOGV("session: %i created (uid=%i) %p", session->auditinfo.ai_asid, session->auditinfo.ai_auid, session);
+
+done:
+    return session;
+}
+
+bool session_update(session_t session)
+{
+    return auditon(A_GETSINFO_ADDR, &session->auditinfo, sizeof(session->auditinfo)) == 0;
+}
+
+uint64_t session_get_attributes(session_t session)
+{
+    session_update(session);
+    
+    return session->auditinfo.ai_flags;
+}
+
+static void _set_attributes(session_t session, uint64_t flags)
+{
+    session->auditinfo.ai_flags = flags;
+    int32_t rc = setaudit_addr(&session->auditinfo, sizeof(session->auditinfo));
+    if (rc != 0) {
+        LOGV("session: failed to update session info (%d)", rc);
+    }
+}
+
+void session_set_attributes(session_t session, uint64_t flags)
+{
+    session_update(session);
+    _set_attributes(session,session->auditinfo.ai_flags | flags);
+}
+
+void session_clear_attributes(session_t session, uint64_t flags)
+{
+    session_update(session);
+    _set_attributes(session,session->auditinfo.ai_flags & ~flags);
+}
+
+
+const void *
+session_get_key(session_t session)
+{
+    return &session->auditinfo.ai_asid;
+}
+
+session_id_t
+session_get_id(session_t session)
+{
+    return session ? session->auditinfo.ai_asid : -1;
+}
+
+uid_t
+session_get_uid(session_t session)
+{
+    return session ? session->auditinfo.ai_auid : (uid_t)-2;
+}
+
+CFIndex
+session_add_process(session_t session, process_t proc)
+{
+    __block CFIndex count = 0;
+    dispatch_sync(session->dispatch_queue, ^{
+        CFSetAddValue(session->processes, proc);
+        count = CFSetGetCount(session->processes);
+    });
+    return count;
+}
+
+CFIndex
+session_remove_process(session_t session, process_t proc)
+{
+    __block CFIndex count = 0;
+    dispatch_sync(session->dispatch_queue, ^{
+        CFSetRemoveValue(session->processes, proc);
+        count = CFSetGetCount(session->processes);
+    });
+    return count;
+}
+
+CFIndex
+session_get_process_count(session_t session)
+{
+    __block CFIndex count = 0;
+    dispatch_sync(session->dispatch_queue, ^{
+        count = CFSetGetCount(session->processes);
+    });
+    return count;
+}
+
+void
+session_set_credential(session_t session, credential_t cred)
+{
+    if (!credential_get_valid(cred))
+        return;
+    
+    dispatch_sync(session->dispatch_queue, ^{
+        CFSetSetValue(session->credentials, cred);
+    });
+}
+
+void
+session_credentials_purge(session_t session)
+{
+    session_credentials_iterate(session, ^bool(credential_t cred) {
+        if (!credential_get_valid(cred)) {
+            CFSetRemoveValue(session->credentials, cred);
+        }
+        return true;
+    });
+}
+
+bool
+session_credentials_iterate(session_t session, credential_iterator_t iter)
+{
+    __block bool result = false;
+    
+    dispatch_sync(session->dispatch_queue, ^{
+        CFIndex count = CFSetGetCount(session->credentials);
+        CFTypeRef values[count];
+        CFSetGetValues(session->credentials, values);
+        for (CFIndex i = 0; i < count; i++) {
+            credential_t cred = (credential_t)values[i];
+            result = iter(cred);
+            if (!result) {
+                break;
+            }
+        }
+    });
+
+    
+    return result;
+}