X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/c38e3ce98599a410a47dc10253faa4d5830f13b2..427c49bcad63d042b29ada2ac27e3dfc4845c779:/authd/session.c?ds=inline diff --git a/authd/session.c b/authd/session.c new file mode 100644 index 00000000..2484ddf3 --- /dev/null +++ b/authd/session.c @@ -0,0 +1,208 @@ +/* Copyright (c) 2012 Apple Inc. All rights reserved. */ + +#include "session.h" +#include "process.h" +#include "debugging.h" +#include +#include + +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; +}