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