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