1 /* Copyright (c) 2012 Apple Inc. All Rights Reserved. */
6 #include <dispatch/dispatch.h>
7 #include <CoreFoundation/CoreFoundation.h>
9 #include <security_utilities/simulatecrash_assert.h>
14 __AUTH_BASE_STRUCT_HEADER__
;
16 CFMutableSetRef credentials
;
17 CFMutableSetRef processes
;
18 auditinfo_addr_t auditinfo
;
20 dispatch_queue_t dispatch_queue
;
25 _session_finalize(CFTypeRef value
)
27 session_t session
= (session_t
)value
;
29 os_log_debug(AUTHD_LOG
, "session: %i deallocated", session
->auditinfo
.ai_asid
);
31 // make sure queue is empty
32 dispatch_barrier_sync(session
->dispatch_queue
, ^{});
34 dispatch_release(session
->dispatch_queue
);
35 CFReleaseNull(session
->credentials
);
36 CFReleaseNull(session
->processes
);
39 AUTH_TYPE_INSTANCE(session
,
42 .finalize
= _session_finalize
,
45 .copyFormattingDesc
= NULL
,
49 static CFTypeID
session_get_type_id() {
50 static CFTypeID type_id
= _kCFRuntimeNotATypeID
;
51 static dispatch_once_t onceToken
;
53 dispatch_once(&onceToken
, ^{
54 type_id
= _CFRuntimeRegisterClass(&_auth_type_session
);
61 session_create(session_id_t sid
)
63 session_t session
= NULL
;
65 session
= (session_t
)_CFRuntimeCreateInstance(kCFAllocatorDefault
, session_get_type_id(), AUTH_CLASS_SIZE(session
), NULL
);
66 require(session
!= NULL
, done
);
68 session
->auditinfo
.ai_asid
= sid
;
70 if (!session_update(session
)) {
71 os_log_error(AUTHD_LOG
, "session: failed to get session info");
74 session
->dispatch_queue
= dispatch_queue_create(NULL
, DISPATCH_QUEUE_SERIAL
);
75 check(session
->dispatch_queue
!= NULL
);
77 session
->credentials
= CFSetCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeSetCallBacks
);
78 session
->processes
= CFSetCreateMutable(kCFAllocatorDefault
, 0, NULL
);
80 os_log_debug(AUTHD_LOG
, "session: %i created (uid=%i)", session
->auditinfo
.ai_asid
, session
->auditinfo
.ai_auid
);
86 bool session_update(session_t session
)
88 return auditon(A_GETSINFO_ADDR
, &session
->auditinfo
, sizeof(session
->auditinfo
)) == 0;
91 uint64_t session_get_attributes(session_t session
)
93 session_update(session
);
95 return session
->auditinfo
.ai_flags
;
98 static void _set_attributes(session_t session
, uint64_t flags
)
100 session
->auditinfo
.ai_flags
= flags
;
101 int32_t rc
= setaudit_addr(&session
->auditinfo
, sizeof(session
->auditinfo
));
103 os_log_debug(AUTHD_LOG
, "session: failed to update session info (%d)", rc
);
107 void session_set_attributes(session_t session
, uint64_t flags
)
109 session_update(session
);
110 _set_attributes(session
,session
->auditinfo
.ai_flags
| flags
);
113 void session_clear_attributes(session_t session
, uint64_t flags
)
115 session_update(session
);
116 _set_attributes(session
,session
->auditinfo
.ai_flags
& ~flags
);
121 session_get_key(session_t session
)
123 return &session
->auditinfo
.ai_asid
;
127 session_get_id(session_t session
)
129 assert(session
); // marked non-null
130 return session
->auditinfo
.ai_asid
;
134 session_get_uid(session_t session
)
136 assert(session
); // marked non-null
137 return session
->auditinfo
.ai_auid
;
141 session_add_process(session_t session
, process_t proc
)
143 __block CFIndex count
= 0;
144 dispatch_sync(session
->dispatch_queue
, ^{
145 CFSetAddValue(session
->processes
, proc
);
146 count
= CFSetGetCount(session
->processes
);
152 session_remove_process(session_t session
, process_t proc
)
154 __block CFIndex count
= 0;
155 dispatch_sync(session
->dispatch_queue
, ^{
156 CFSetRemoveValue(session
->processes
, proc
);
157 count
= CFSetGetCount(session
->processes
);
163 session_get_process_count(session_t session
)
165 __block CFIndex count
= 0;
166 dispatch_sync(session
->dispatch_queue
, ^{
167 count
= CFSetGetCount(session
->processes
);
173 session_set_credential(session_t session
, credential_t cred
)
175 if (!credential_get_valid(cred
))
178 dispatch_sync(session
->dispatch_queue
, ^{
179 CFSetSetValue(session
->credentials
, cred
);
184 session_credentials_purge(session_t session
)
186 session_credentials_iterate(session
, ^bool(credential_t cred
) {
187 if (!credential_get_valid(cred
)) {
188 CFSetRemoveValue(session
->credentials
, cred
);
195 session_credentials_iterate(session_t session
, credential_iterator_t iter
)
197 __block
bool result
= false;
199 dispatch_sync(session
->dispatch_queue
, ^{
200 CFIndex count
= CFSetGetCount(session
->credentials
);
201 if (count
> 128) { // <rdar://problem/38179345> Variable Length Arrays; AuthD
202 // session usually contains 0 or 1 credential
206 CFTypeRef values
[count
];
207 CFSetGetValues(session
->credentials
, values
);
208 for (CFIndex i
= 0; i
< count
; i
++) {
209 credential_t cred
= (credential_t
)values
[i
];