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