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