]> git.saurik.com Git - apple/security.git/blob - OSX/authd/session.c
Security-59754.80.3.tar.gz
[apple/security.git] / OSX / authd / session.c
1 /* Copyright (c) 2012 Apple Inc. All Rights Reserved. */
2
3 #include "session.h"
4 #include "process.h"
5 #include "debugging.h"
6 #include <dispatch/dispatch.h>
7 #include <CoreFoundation/CoreFoundation.h>
8
9 #include <security_utilities/simulatecrash_assert.h>
10
11 AUTHD_DEFINE_LOG
12
13 struct _session_s {
14 __AUTH_BASE_STRUCT_HEADER__;
15
16 CFMutableSetRef credentials;
17 CFMutableSetRef processes;
18 auditinfo_addr_t auditinfo;
19
20 dispatch_queue_t dispatch_queue;
21
22 };
23
24 static void
25 _session_finalize(CFTypeRef value)
26 {
27 session_t session = (session_t)value;
28
29 os_log_debug(AUTHD_LOG, "session: %i deallocated", session->auditinfo.ai_asid);
30
31 // make sure queue is empty
32 dispatch_barrier_sync(session->dispatch_queue, ^{});
33
34 dispatch_release(session->dispatch_queue);
35 CFReleaseNull(session->credentials);
36 CFReleaseNull(session->processes);
37 }
38
39 AUTH_TYPE_INSTANCE(session,
40 .init = NULL,
41 .copy = NULL,
42 .finalize = _session_finalize,
43 .equal = NULL,
44 .hash = NULL,
45 .copyFormattingDesc = NULL,
46 .copyDebugDesc = NULL
47 );
48
49 static CFTypeID session_get_type_id() {
50 static CFTypeID type_id = _kCFRuntimeNotATypeID;
51 static dispatch_once_t onceToken;
52
53 dispatch_once(&onceToken, ^{
54 type_id = _CFRuntimeRegisterClass(&_auth_type_session);
55 });
56
57 return type_id;
58 }
59
60 session_t
61 session_create(session_id_t sid)
62 {
63 session_t session = NULL;
64
65 session = (session_t)_CFRuntimeCreateInstance(kCFAllocatorDefault, session_get_type_id(), AUTH_CLASS_SIZE(session), NULL);
66 require(session != NULL, done);
67
68 session->auditinfo.ai_asid = sid;
69
70 if (!session_update(session)) {
71 os_log_error(AUTHD_LOG, "session: failed to get session info");
72 }
73
74 session->dispatch_queue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);
75 check(session->dispatch_queue != NULL);
76
77 session->credentials = CFSetCreateMutable(kCFAllocatorDefault, 0, &kCFTypeSetCallBacks);
78 session->processes = CFSetCreateMutable(kCFAllocatorDefault, 0, NULL);
79
80 os_log_debug(AUTHD_LOG, "session: %i created (uid=%i)", session->auditinfo.ai_asid, session->auditinfo.ai_auid);
81
82 done:
83 return session;
84 }
85
86 bool session_update(session_t session)
87 {
88 return auditon(A_GETSINFO_ADDR, &session->auditinfo, sizeof(session->auditinfo)) == 0;
89 }
90
91 uint64_t session_get_attributes(session_t session)
92 {
93 session_update(session);
94
95 return session->auditinfo.ai_flags;
96 }
97
98 static void _set_attributes(session_t session, uint64_t flags)
99 {
100 session->auditinfo.ai_flags = flags;
101 int32_t rc = setaudit_addr(&session->auditinfo, sizeof(session->auditinfo));
102 if (rc != 0) {
103 os_log_debug(AUTHD_LOG, "session: failed to update session info (%d)", rc);
104 }
105 }
106
107 void session_set_attributes(session_t session, uint64_t flags)
108 {
109 session_update(session);
110 _set_attributes(session,session->auditinfo.ai_flags | flags);
111 }
112
113 void session_clear_attributes(session_t session, uint64_t flags)
114 {
115 session_update(session);
116 _set_attributes(session,session->auditinfo.ai_flags & ~flags);
117 }
118
119
120 const void *
121 session_get_key(session_t session)
122 {
123 return &session->auditinfo.ai_asid;
124 }
125
126 session_id_t
127 session_get_id(session_t session)
128 {
129 assert(session); // marked non-null
130 return session->auditinfo.ai_asid;
131 }
132
133 uid_t
134 session_get_uid(session_t session)
135 {
136 assert(session); // marked non-null
137 return session->auditinfo.ai_auid;
138 }
139
140 CFIndex
141 session_add_process(session_t session, process_t proc)
142 {
143 __block CFIndex count = 0;
144 dispatch_sync(session->dispatch_queue, ^{
145 CFSetAddValue(session->processes, proc);
146 count = CFSetGetCount(session->processes);
147 });
148 return count;
149 }
150
151 CFIndex
152 session_remove_process(session_t session, process_t proc)
153 {
154 __block CFIndex count = 0;
155 dispatch_sync(session->dispatch_queue, ^{
156 CFSetRemoveValue(session->processes, proc);
157 count = CFSetGetCount(session->processes);
158 });
159 return count;
160 }
161
162 CFIndex
163 session_get_process_count(session_t session)
164 {
165 __block CFIndex count = 0;
166 dispatch_sync(session->dispatch_queue, ^{
167 count = CFSetGetCount(session->processes);
168 });
169 return count;
170 }
171
172 void
173 session_set_credential(session_t session, credential_t cred)
174 {
175 if (!credential_get_valid(cred))
176 return;
177
178 dispatch_sync(session->dispatch_queue, ^{
179 CFSetSetValue(session->credentials, cred);
180 });
181 }
182
183 void
184 session_credentials_purge(session_t session)
185 {
186 session_credentials_iterate(session, ^bool(credential_t cred) {
187 if (!credential_get_valid(cred)) {
188 CFSetRemoveValue(session->credentials, cred);
189 }
190 return true;
191 });
192 }
193
194 bool
195 session_credentials_iterate(session_t session, credential_iterator_t iter)
196 {
197 __block bool result = false;
198
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
203 count = 128;
204 }
205
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];
210 result = iter(cred);
211 if (!result) {
212 break;
213 }
214 }
215 });
216
217
218 return result;
219 }