]> git.saurik.com Git - apple/security.git/blob - OSX/authd/authutilities.c
Security-59754.80.3.tar.gz
[apple/security.git] / OSX / authd / authutilities.c
1 /* Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. */
2
3 #include "authutilities.h"
4 #include "authd_private.h"
5 #include "debugging.h"
6
7 #include <AssertMacros.h>
8
9 AUTHD_DEFINE_LOG
10
11 xpc_object_t
12 SerializeItemSet(const AuthorizationItemSet * itemSet)
13 {
14 xpc_object_t set = NULL;
15 require_quiet(itemSet != NULL, done);
16 require_quiet(itemSet->count != 0, done);
17
18 set = xpc_array_create(NULL, 0);
19 require(set != NULL, done);
20
21 for (uint32_t i = 0; i < itemSet->count; i++) {
22 xpc_object_t item = xpc_dictionary_create(NULL, NULL, 0);
23 require(item != NULL, done);
24
25 if (itemSet->items[i].name == NULL) {
26 os_log_error(AUTHD_LOG, "ItemSet - item #%d name is NULL", i);
27 xpc_release(item);
28 continue;
29 }
30 xpc_dictionary_set_string(item, AUTH_XPC_ITEM_NAME, itemSet->items[i].name);
31 xpc_dictionary_set_uint64(item, AUTH_XPC_ITEM_FLAGS, itemSet->items[i].flags);
32 xpc_dictionary_set_data(item, AUTH_XPC_ITEM_VALUE, itemSet->items[i].value, itemSet->items[i].valueLength);
33 xpc_array_set_value(set, XPC_ARRAY_APPEND, item);
34 xpc_release(item);
35 }
36
37 done:
38 return set;
39 }
40
41 AuthorizationItemSet *
42 DeserializeItemSet(const xpc_object_t data)
43 {
44 AuthorizationItemSet * set = NULL;
45 require_quiet(data != NULL, done);
46 xpc_retain(data);
47 require(xpc_get_type(data) == XPC_TYPE_ARRAY, done);
48
49 set = (AuthorizationItemSet*)calloc(1u, sizeof(AuthorizationItemSet));
50 require(set != NULL, done);
51
52 set->count = (uint32_t)xpc_array_get_count(data);
53 if (set->count) {
54 set->items = (AuthorizationItem*)calloc(set->count, sizeof(AuthorizationItem));
55 require_action(set->items != NULL, done, set->count = 0);
56
57 xpc_array_apply(data, ^bool(size_t index, xpc_object_t value) {
58 void *dataCopy = 0;
59 require(xpc_get_type(value) == XPC_TYPE_DICTIONARY, done);
60 size_t nameLen = 0;
61 const char * name = xpc_dictionary_get_string(value, AUTH_XPC_ITEM_NAME);
62 if (name) {
63 nameLen = strlen(name) + 1;
64 set->items[index].name = calloc(1u, nameLen);
65 require(set->items[index].name != NULL, done);
66
67 strlcpy((char*)set->items[index].name, name, nameLen);
68 }
69 set->items[index].flags = (uint32_t)xpc_dictionary_get_uint64(value, AUTH_XPC_ITEM_FLAGS);
70 size_t len;
71 const void * valueData = xpc_dictionary_get_data(value, AUTH_XPC_ITEM_VALUE, &len);
72
73 // <rdar://problem/13033889> authd is holding on to multiple copies of my password in the clear
74 if (xpc_dictionary_get_value(value, AUTH_XPC_ITEM_SENSITIVE_VALUE_LENGTH) != NULL) {
75 size_t sensitiveLength = (size_t)xpc_dictionary_get_uint64(value, AUTH_XPC_ITEM_SENSITIVE_VALUE_LENGTH);
76 if (sensitiveLength > len) {
77 os_log_error(AUTHD_LOG, "Sensitive data len %zu is not valid", sensitiveLength);
78 goto done;
79 }
80 dataCopy = malloc(sensitiveLength);
81 require(dataCopy != NULL, done);
82 memcpy(dataCopy, valueData, sensitiveLength);
83 memset_s((void *)valueData, len, 0, sensitiveLength); // clear the sensitive data, memset_s is never optimized away
84 len = sensitiveLength;
85 } else {
86 dataCopy = malloc(len);
87 require(dataCopy != NULL, done);
88 memcpy(dataCopy, valueData, len);
89 }
90
91 set->items[index].valueLength = len;
92 if (len) {
93 set->items[index].value = calloc(1u, len);
94 require(set->items[index].value != NULL, done);
95
96 memcpy(set->items[index].value, dataCopy, len);
97 }
98
99 done:
100 if (dataCopy)
101 free(dataCopy);
102 return true;
103 });
104 }
105
106 done:
107 if (data != NULL) {
108 xpc_release(data);
109 }
110 return set;
111 }
112
113 void FreeItemSet(AuthorizationItemSet * itemSet)
114 {
115 if (!itemSet) { return; }
116
117 for(uint32_t i = 0; i < itemSet->count; i++ ) {
118 if (itemSet->items[i].name) {
119 free((void*)itemSet->items[i].name);
120 }
121 if (itemSet->items[i].value) {
122 free(itemSet->items[i].value);
123 }
124 }
125 if (itemSet->items) {
126 free(itemSet->items);
127 }
128
129 free(itemSet);
130 }
131
132 char *
133 _copy_cf_string(CFTypeRef str, const char * defaultValue)
134 {
135 char * result = NULL;
136 require(str != NULL, done);
137 require(CFGetTypeID(str) == CFStringGetTypeID(), done);
138
139 CFIndex length = CFStringGetLength(str);
140 CFIndex size = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1;
141
142 result = (char*)calloc(1u, (size_t)size);
143 check(result != NULL);
144
145 if (!CFStringGetCString(str, result, size, kCFStringEncodingUTF8)) {
146 free_safe(result);
147 }
148
149 done:
150 if (result == NULL && defaultValue) {
151 size_t len = strlen(defaultValue);
152 result = (char*)calloc(1u, len);
153 check(result != NULL);
154
155 strlcpy(result, defaultValue, len);
156 }
157
158 return result;
159 }
160
161 int64_t
162 _get_cf_int(CFTypeRef num, int64_t defaultValue)
163 {
164 int64_t result = defaultValue;
165 require(num != NULL, done);
166 require(CFGetTypeID(num) == CFNumberGetTypeID(), done);
167
168 if (!CFNumberGetValue(num, kCFNumberSInt64Type, &result)) {
169 result = defaultValue;
170 }
171
172 done:
173 return result;
174 }
175
176 bool
177 _get_cf_bool(CFTypeRef value, bool defaultValue)
178 {
179 bool result = defaultValue;
180 require(value != NULL, done);
181 require(CFGetTypeID(value) == CFBooleanGetTypeID(), done);
182
183 result = CFBooleanGetValue(value);
184
185 done:
186 return result;
187 }
188
189 bool
190 _compare_string(const char * str1, const char * str2)
191 {
192 if (!(str1 == str2)) { // compare null or same pointer
193 if (str1 && str2) { // check both are non null
194 if (strcasecmp(str1, str2) != 0) { // compare strings
195 return false; // return false if not equal
196 }
197 } else {
198 return false; // return false if one null
199 }
200 }
201
202 return true;
203 }
204
205 char *
206 _copy_string(const char * str)
207 {
208 char * result = NULL;
209 require(str != NULL, done);
210
211 size_t len = strlen(str) + 1;
212 result = calloc(1u, len);
213 require(result != NULL, done);
214
215 strlcpy(result, str, len);
216
217 done:
218 return result;
219 }
220
221 void *
222 _copy_data(const void * data, size_t dataLen)
223 {
224 void * result = NULL;
225 require(data != NULL, done);
226
227 result = calloc(1u, dataLen);
228 require(result != NULL, done);
229
230 memcpy(result, data, dataLen);
231
232 done:
233 return result;
234 }
235
236 bool _cf_set_iterate(CFSetRef set, bool(^iterator)(CFTypeRef value))
237 {
238 bool result = false;
239 CFTypeRef* values = NULL;
240
241 require(set != NULL, done);
242
243 CFIndex count = CFSetGetCount(set);
244 values = calloc((size_t)count, sizeof(CFTypeRef));
245 require(values != NULL, done);
246
247 CFSetGetValues(set, values);
248 for (CFIndex i = 0; i < count; i++) {
249 result = iterator(values[i]);
250 if (!result) {
251 break;
252 }
253 }
254
255 done:
256 free_safe(values);
257 return result;
258 }
259
260 bool _cf_bag_iterate(CFBagRef bag, bool(^iterator)(CFTypeRef value))
261 {
262 bool result = false;
263 CFTypeRef* values = NULL;
264
265 require(bag != NULL, done);
266
267 CFIndex count = CFBagGetCount(bag);
268 values = calloc((size_t)count, sizeof(CFTypeRef));
269 require(values != NULL, done);
270
271 CFBagGetValues(bag, values);
272 for (CFIndex i = 0; i < count; i++) {
273 result = iterator(values[i]);
274 if (!result) {
275 break;
276 }
277 }
278
279 done:
280 free_safe(values);
281 return result;
282 }
283
284 bool _cf_dictionary_iterate(CFDictionaryRef dict, bool(^iterator)(CFTypeRef key, CFTypeRef value))
285 {
286 bool result = false;
287 CFTypeRef* keys = NULL;
288 CFTypeRef* values = NULL;
289
290 require(dict != NULL, done);
291
292 CFIndex count = CFDictionaryGetCount(dict);
293 keys = calloc((size_t)count, sizeof(CFTypeRef));
294 require(keys != NULL, done);
295
296 values = calloc((size_t)count, sizeof(CFTypeRef));
297 require(values != NULL, done);
298
299 CFDictionaryGetKeysAndValues(dict, keys, values);
300 for (CFIndex i = 0; i < count; i++) {
301 result = iterator(keys[i], values[i]);
302 if (!result) {
303 break;
304 }
305 }
306
307 done:
308 free_safe(keys);
309 free_safe(values);
310 return result;
311 }
312
313 bool isInLWOS()
314 {
315 // temporary solution until we find a better way
316 return getenv("__OSINSTALL_ENVIRONMENT") != NULL;
317 }