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