]> git.saurik.com Git - apple/security.git/blob - OSX/authd/rule.c
Security-57337.40.85.tar.gz
[apple/security.git] / OSX / authd / rule.c
1 /* Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. */
2
3 #include "rule.h"
4 #include "authutilities.h"
5 #include "mechanism.h"
6 #include "crc.h"
7 #include "debugging.h"
8 #include "authitems.h"
9 #include "process.h"
10
11 #include <Security/AuthorizationDB.h>
12 #include <Security/AuthorizationTagsPriv.h>
13 #include "server.h"
14
15 static void _sql_get_id(rule_t,authdb_connection_t);
16 static RuleClass _get_cf_rule_class(CFTypeRef);
17 static bool _copy_cf_rule_mechanisms(rule_t,CFTypeRef,authdb_connection_t);
18 static bool _copy_cf_rule_delegations(rule_t, CFTypeRef,authdb_connection_t);
19
20 #define kMaximumAuthorizationTries 10000
21
22 #define RULE_ID "id"
23 #define RULE_NAME "name"
24 #define RULE_TYPE "type"
25 #define RULE_CLASS "class"
26 #define RULE_GROUP "group"
27 #define RULE_KOFN "kofn"
28 #define RULE_TIMEOUT "timeout"
29 #define RULE_FLAGS "flags"
30 #define RULE_TRIES "tries"
31 #define RULE_COMMENT "comment"
32 #define RULE_VERSION "version"
33 #define RULE_CREATED "created"
34 #define RULE_MODIFIED "modified"
35 #define RULE_IDENTIFIER "identifier"
36 #define RULE_REQUIREMENT "requirement"
37 #define RULE_HASH "hash"
38
39 struct _rule_s {
40 __AUTH_BASE_STRUCT_HEADER__;
41
42 auth_items_t data;
43 CFMutableArrayRef mechanisms;
44 CFMutableArrayRef delegations;
45
46 CFMutableDictionaryRef loc_prompts;
47 CFMutableDictionaryRef loc_buttons;
48
49 CFDataRef requirement_data;
50 SecRequirementRef requirement;
51 };
52
53 static void
54 _rule_finalize(CFTypeRef value)
55 {
56 rule_t rule = (rule_t)value;
57 CFReleaseSafe(rule->data);
58 CFReleaseSafe(rule->mechanisms);
59 CFReleaseSafe(rule->delegations);
60 CFReleaseSafe(rule->loc_prompts);
61 CFReleaseSafe(rule->loc_buttons);
62 CFReleaseSafe(rule->requirement_data);
63 CFReleaseSafe(rule->requirement);
64 }
65
66 static Boolean
67 _rule_equal(CFTypeRef value1, CFTypeRef value2)
68 {
69 rule_t rule1 = (rule_t)value1;
70 rule_t rule2 = (rule_t)value2;
71
72 return strcasecmp(rule_get_name(rule1), rule_get_name(rule2)) == 0;
73 }
74
75 static CFStringRef
76 _rule_copy_description(CFTypeRef value)
77 {
78 rule_t rule = (rule_t)value;
79 CFMutableStringRef str = CFStringCreateMutable(kCFAllocatorDefault, 0);
80 CFStringRef tmp = CFCopyDescription(rule->data);
81 CFStringAppend(str, tmp);
82 CFReleaseNull(tmp);
83 tmp = CFCopyDescription(rule->mechanisms);
84 CFStringAppend(str, tmp);
85 CFReleaseNull(tmp);
86 tmp = CFCopyDescription(rule->delegations);
87 CFStringAppend(str, tmp);
88 CFReleaseNull(tmp);
89 return str;
90 }
91
92 static CFHashCode
93 _rule_hash(CFTypeRef value)
94 {
95 rule_t rule = (rule_t)value;
96 const char * str = rule_get_name(rule);
97 return (CFHashCode)crc64(str, strlen(str));
98 }
99
100 AUTH_TYPE_INSTANCE(rule,
101 .init = NULL,
102 .copy = NULL,
103 .finalize = _rule_finalize,
104 .equal = _rule_equal,
105 .hash = _rule_hash,
106 .copyFormattingDesc = NULL,
107 .copyDebugDesc = _rule_copy_description
108 );
109
110 static CFTypeID rule_get_type_id() {
111 static CFTypeID type_id = _kCFRuntimeNotATypeID;
112 static dispatch_once_t onceToken;
113
114 dispatch_once(&onceToken, ^{
115 type_id = _CFRuntimeRegisterClass(&_auth_type_rule);
116 });
117
118 return type_id;
119 }
120
121 static rule_t
122 _rule_create()
123 {
124 rule_t rule = (rule_t)_CFRuntimeCreateInstance(kCFAllocatorDefault, rule_get_type_id(), AUTH_CLASS_SIZE(rule), NULL);
125 require(rule != NULL, done);
126
127 rule->data = auth_items_create();
128 rule->delegations = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
129 rule->mechanisms = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
130
131 done:
132 return rule;
133 }
134
135 static rule_t
136 _rule_create_with_sql(auth_items_t sql)
137 {
138 rule_t rule = NULL;
139 require(sql != NULL, done);
140
141 rule = _rule_create();
142 require(rule != NULL, done);
143
144 auth_items_copy(rule->data, sql);
145
146 done:
147 return rule;
148 }
149
150 rule_t
151 rule_create_default()
152 {
153 rule_t rule = _rule_create();
154 require(rule != NULL, done);
155
156 auth_items_set_int64(rule->data, RULE_TYPE, RT_RIGHT);
157 auth_items_set_string(rule->data, RULE_NAME, "(default)");
158 auth_items_set_int64(rule->data, RULE_CLASS, RC_USER);
159 auth_items_set_string(rule->data, RULE_GROUP, "admin");
160 auth_items_set_int64(rule->data, RULE_TIMEOUT, 300);
161 auth_items_set_int64(rule->data, RULE_TRIES, kMaximumAuthorizationTries);
162 auth_items_set_int64(rule->data, RULE_FLAGS, RuleFlagShared | RuleFlagAuthenticateUser);
163
164 mechanism_t mech = mechanism_create_with_string("builtin:authenticate", NULL);
165 CFArrayAppendValue(rule->mechanisms, mech);
166 CFReleaseNull(mech);
167
168 mech = mechanism_create_with_string("builtin:reset-password,privileged", NULL);
169 CFArrayAppendValue(rule->mechanisms, mech);
170 CFReleaseNull(mech);
171
172 mech = mechanism_create_with_string("builtin:authenticate,privileged", NULL);
173 CFArrayAppendValue(rule->mechanisms, mech);
174 CFReleaseNull(mech);
175
176 mech = mechanism_create_with_string("PKINITMechanism:auth,privileged", NULL);
177 CFArrayAppendValue(rule->mechanisms, mech);
178 CFReleaseNull(mech);
179
180 done:
181 return rule;
182 }
183
184 rule_t
185 rule_create_with_string(const char * str, authdb_connection_t dbconn)
186 {
187 rule_t rule = NULL;
188 require(str != NULL, done);
189
190 rule = _rule_create();
191 require(rule != NULL, done);
192
193 auth_items_set_string(rule->data, RULE_NAME, str);
194
195 if (dbconn) {
196 rule_sql_fetch(rule, dbconn);
197 }
198
199 done:
200 return rule;
201 }
202
203 static void _set_data_string(rule_t rule, const char * key, CFStringRef str)
204 {
205 char * tmpStr = _copy_cf_string(str, NULL);
206
207 if (tmpStr) {
208 auth_items_set_string(rule->data, key, tmpStr);
209 free_safe(tmpStr);
210 }
211 }
212
213 rule_t
214 rule_create_with_plist(RuleType type, CFStringRef name, CFDictionaryRef plist, authdb_connection_t dbconn)
215 {
216 rule_t rule = NULL;
217 require(name != NULL, done);
218 require(plist != NULL, done);
219
220 rule = _rule_create();
221 require(rule != NULL, done);
222
223 _set_data_string(rule, RULE_NAME, name);
224 require_action(rule_get_name(rule) != NULL, done, CFReleaseSafe(rule));
225
226 _sql_get_id(rule, dbconn);
227
228 auth_items_set_int64(rule->data, RULE_TYPE, type);
229
230 auth_items_set_int64(rule->data, RULE_CLASS, _get_cf_rule_class(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleClass))));
231 _set_data_string(rule, RULE_COMMENT, CFDictionaryGetValue(plist, CFSTR(kAuthorizationComment)));
232
233
234 CFTypeRef loc_tmp = CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterDefaultPrompt));
235 if (loc_tmp) {
236 rule->loc_prompts = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, loc_tmp);
237 }
238 loc_tmp = CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterDefaultButton));
239 if (loc_tmp) {
240 rule->loc_buttons = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, loc_tmp);
241 }
242
243 auth_items_set_int64(rule->data, RULE_VERSION, _get_cf_int(CFDictionaryGetValue(plist, CFSTR("version")), 0));
244
245 RuleFlags flags = 0;
246
247 if (_get_cf_bool(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterEntitled)), false)) {
248 flags |= RuleFlagEntitled;
249 }
250
251 if (_get_cf_bool(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterRequireAppleSigned)), false)) {
252 flags |= RuleFlagRequireAppleSigned;
253 }
254
255 switch (rule_get_class(rule)) {
256 case RC_USER:
257 _set_data_string(rule, RULE_GROUP, CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterGroup)));
258 auth_items_set_int64(rule->data, RULE_TIMEOUT, _get_cf_int(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterCredentialTimeout)), INT32_MAX));
259 auth_items_set_int64(rule->data, RULE_TRIES, _get_cf_int(CFDictionaryGetValue(plist, CFSTR("tries")), kMaximumAuthorizationTries));
260
261 if (_get_cf_bool(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterCredentialShared)), false)) {
262 flags |= RuleFlagShared;
263 }
264 if (_get_cf_bool(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterAllowRoot)), false)) {
265 flags |= RuleFlagAllowRoot;
266 }
267 if (_get_cf_bool(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterCredentialSessionOwner)), false)) {
268 flags |= RuleFlagSessionOwner;
269 }
270 if (_get_cf_bool(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterAuthenticateUser)), true)) {
271 flags |= RuleFlagAuthenticateUser;
272 }
273 if (_get_cf_bool(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterExtractPassword)), false)) {
274 flags |= RuleFlagExtractPassword;
275 }
276 if (_get_cf_bool(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterEntitledAndGroup)), false)) {
277 flags |= RuleFlagEntitledAndGroup;
278 }
279 if (_get_cf_bool(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterVPNEntitledAndGroup)), false)) {
280 flags |= RuleFlagVPNEntitledAndGroup;
281 }
282
283 _copy_cf_rule_mechanisms(rule, CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterMechanisms)), dbconn);
284
285 break;
286 case RC_RULE:
287 auth_items_set_int64(rule->data, RULE_KOFN, _get_cf_int(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterKofN)), 0));
288
289 _copy_cf_rule_delegations(rule, CFDictionaryGetValue(plist, CFSTR(kAuthorizationRightRule)), dbconn);
290 break;
291 case RC_MECHANISM:
292 auth_items_set_int64(rule->data, RULE_TRIES, _get_cf_int(CFDictionaryGetValue(plist, CFSTR("tries")), kMaximumAuthorizationTries));
293 if (_get_cf_bool(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterCredentialShared)), true)) {
294 flags |= RuleFlagShared;
295 }
296 if (_get_cf_bool(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterExtractPassword)), false)) {
297 flags |= RuleFlagExtractPassword;
298 }
299
300 _copy_cf_rule_mechanisms(rule, CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterMechanisms)), dbconn);
301
302 break;
303 case RC_DENY:
304 break;
305 case RC_ALLOW:
306 break;
307 default:
308 LOGD("rule: invalid rule class");
309 break;
310 }
311
312 auth_items_set_int64(rule->data, RULE_FLAGS, flags);
313
314 done:
315 return rule;
316 }
317
318 static void
319 _sql_get_id(rule_t rule, authdb_connection_t dbconn)
320 {
321 authdb_step(dbconn, "SELECT id,created,identifier,requirement FROM rules WHERE name = ? LIMIT 1",
322 ^(sqlite3_stmt *stmt) {
323 sqlite3_bind_text(stmt, 1, rule_get_name(rule), -1, NULL);
324 }, ^bool(auth_items_t data) {
325 auth_items_copy(rule->data, data);
326 return true;
327 });
328 }
329
330 static bool
331 _copy_cf_rule_delegations(rule_t rule, CFTypeRef value, authdb_connection_t dbconn)
332 {
333 bool result = false;
334 char * tmp_str = NULL;
335 require(value != NULL, done);
336
337 if (CFGetTypeID(value) == CFStringGetTypeID()) {
338 tmp_str = _copy_cf_string(value, NULL);
339 rule_t delegate = rule_create_with_string(tmp_str, dbconn);
340 free_safe(tmp_str);
341 if (delegate) {
342 CFArrayAppendValue(rule->delegations, delegate);
343 CFReleaseSafe(delegate);
344 }
345 } else { //array
346 CFIndex count = CFArrayGetCount(value);
347 for (CFIndex i = 0; i < count; i++) {
348 tmp_str = _copy_cf_string(CFArrayGetValueAtIndex(value,i), NULL);
349 rule_t delegate = rule_create_with_string(tmp_str, dbconn);
350 free_safe(tmp_str);
351 if (delegate) {
352 CFArrayAppendValue(rule->delegations, delegate);
353 CFReleaseSafe(delegate);
354 }
355 }
356 }
357
358 result = true;
359
360 done:
361 return result;
362 }
363
364 static bool
365 _copy_cf_rule_mechanisms(rule_t rule, CFTypeRef array, authdb_connection_t dbconn)
366 {
367 bool result = false;
368 require(array != NULL, done);
369 require(CFGetTypeID(array) == CFArrayGetTypeID(), done);
370
371 CFIndex count = CFArrayGetCount(array);
372 for (CFIndex i = 0; i < count; i++) {
373 mechanism_t mech = NULL;
374 char * string = _copy_cf_string(CFArrayGetValueAtIndex(array, i), NULL);
375
376 if (!string)
377 continue;
378
379 mech = mechanism_create_with_string(string, dbconn);
380 if (mech) {
381 CFArrayAppendValue(rule->mechanisms, mech);
382 CFReleaseSafe(mech);
383 }
384 free(string);
385 }
386
387 result = true;
388
389 done:
390 return result;
391 }
392
393 static RuleClass
394 _get_cf_rule_class(CFTypeRef str)
395 {
396 RuleClass rc = RC_RULE;
397 require(str != NULL, done);
398 require(CFGetTypeID(str) == CFStringGetTypeID(), done);
399
400 if (CFEqual(str, CFSTR(kAuthorizationRuleClassUser)))
401 return RC_USER;
402
403 if (CFEqual(str, CFSTR(kAuthorizationRightRule)))
404 return RC_RULE;
405
406 if (CFEqual(str, CFSTR(kAuthorizationRuleClassMechanisms)))
407 return RC_MECHANISM;
408
409 if (CFEqual(str, CFSTR(kAuthorizationRuleClassDeny)))
410 return RC_DENY;
411
412 if (CFEqual(str, CFSTR(kAuthorizationRuleClassAllow)))
413 return RC_ALLOW;
414
415 done:
416 return rc;
417 }
418
419 static bool
420 _sql_bind(rule_t rule, sqlite3_stmt * stmt)
421 {
422 int64_t n;
423 int32_t rc = 0;
424 require(stmt != NULL, err);
425
426 int32_t column = 1;
427 rc = sqlite3_bind_text(stmt, column++, rule_get_name(rule), -1, NULL);
428 require_noerr(rc, err);
429 rc = sqlite3_bind_int(stmt, column++, rule_get_type(rule));
430 require_noerr(rc, err);
431 rc = sqlite3_bind_int(stmt, column++, rule_get_class(rule));
432 require_noerr(rc, err);
433
434 switch (rule_get_class(rule)) {
435 case RC_USER:
436 rc = sqlite3_bind_text(stmt, column++, rule_get_group(rule), -1, NULL);
437 require_noerr(rc, err);
438 rc = sqlite3_bind_null(stmt, column++); // kofn
439 require_noerr(rc, err);
440 rc = sqlite3_bind_int64(stmt, column++, rule_get_timeout(rule));
441 require_noerr(rc, err);
442 rc = sqlite3_bind_int64(stmt, column++, auth_items_get_int64(rule->data, RULE_FLAGS));
443 require_noerr(rc, err);
444 rc = sqlite3_bind_int64(stmt, column++, rule_get_tries(rule));
445 require_noerr(rc, err);
446 break;
447 case RC_RULE:
448 rc = sqlite3_bind_null(stmt, column++); // group
449 require_noerr(rc, err);
450 n = rule_get_kofn(rule);
451 if (n) {
452 rc = sqlite3_bind_int64(stmt, column++, n);
453 } else {
454 rc = sqlite3_bind_null(stmt, column++);
455 }
456 require_noerr(rc, err);
457 rc = sqlite3_bind_null(stmt, column++); // timeout
458 require_noerr(rc, err);
459 rc = sqlite3_bind_int64(stmt, column++, auth_items_get_int64(rule->data, RULE_FLAGS));
460 require_noerr(rc, err);
461 rc = sqlite3_bind_null(stmt, column++); // tries
462 require_noerr(rc, err);
463 break;
464 case RC_MECHANISM:
465 rc = sqlite3_bind_null(stmt, column++); // group
466 require_noerr(rc, err);
467 rc = sqlite3_bind_null(stmt, column++); // kofn
468 require_noerr(rc, err);
469 rc = sqlite3_bind_null(stmt, column++); // timeout
470 require_noerr(rc, err);
471 rc = sqlite3_bind_int64(stmt, column++, auth_items_get_int64(rule->data, RULE_FLAGS));
472 require_noerr(rc, err);
473 rc = sqlite3_bind_int64(stmt, column++, rule_get_tries(rule));
474 require_noerr(rc, err);
475 break;
476 case RC_DENY:
477 case RC_ALLOW:
478 rc = sqlite3_bind_null(stmt, column++); // group
479 require_noerr(rc, err);
480 rc = sqlite3_bind_null(stmt, column++); // kofn
481 require_noerr(rc, err);
482 rc = sqlite3_bind_null(stmt, column++); // timeout
483 require_noerr(rc, err);
484 rc = sqlite3_bind_int64(stmt, column++, auth_items_get_int64(rule->data, RULE_FLAGS));
485 require_noerr(rc, err);
486 rc = sqlite3_bind_null(stmt, column++); // tries
487 require_noerr(rc, err);
488 break;
489 default:
490 LOGD("rule: sql bind, invalid rule class");
491 break;
492 }
493
494 rc = sqlite3_bind_int64(stmt, column++, rule_get_version(rule)); // version
495 require_noerr(rc, err);
496 rc = sqlite3_bind_double(stmt, column++, rule_get_created(rule)); // created
497 require_noerr(rc, err);
498 rc = sqlite3_bind_double(stmt, column++, rule_get_modified(rule)); // modified
499 require_noerr(rc, err);
500 rc = sqlite3_bind_null(stmt, column++); // hash
501 require_noerr(rc, err);
502 rc = sqlite3_bind_text(stmt, column++, rule_get_identifier(rule), -1, NULL);
503 require_noerr(rc, err);
504
505 CFDataRef data = rule_get_requirment_data(rule);
506 if (data) {
507 rc = sqlite3_bind_blob(stmt, column++, CFDataGetBytePtr(data), (int32_t)CFDataGetLength(data), NULL);
508 } else {
509 rc = sqlite3_bind_null(stmt, column++);
510 }
511 require_noerr(rc, err);
512
513 rc = sqlite3_bind_text(stmt, column++, rule_get_comment(rule), -1, NULL);
514 require_noerr(rc, err);
515
516 return true;
517
518 err:
519 LOGD("rule: sql bind, error %i", rc);
520 return false;
521 }
522
523 static void
524 _get_sql_mechanisms(rule_t rule, authdb_connection_t dbconn)
525 {
526 CFArrayRemoveAllValues(rule->mechanisms);
527
528 authdb_step(dbconn, "SELECT mechanisms.* " \
529 "FROM mechanisms " \
530 "JOIN mechanisms_map ON mechanisms.id = mechanisms_map.m_id " \
531 "WHERE mechanisms_map.r_id = ? ORDER BY mechanisms_map.ord ASC",
532 ^(sqlite3_stmt *stmt) {
533 sqlite3_bind_int64(stmt, 1, rule_get_id(rule));
534 }, ^bool(auth_items_t data) {
535 mechanism_t mechanism = mechanism_create_with_sql(data);
536 CFArrayAppendValue(rule->mechanisms, mechanism);
537 CFReleaseSafe(mechanism);
538 return true;
539 });
540 }
541
542 static void
543 _get_sql_delegates(rule_t rule, authdb_connection_t dbconn)
544 {
545 CFArrayRemoveAllValues(rule->delegations);
546
547 authdb_step(dbconn, "SELECT rules.* " \
548 "FROM rules " \
549 "JOIN delegates_map ON rules.id = delegates_map.d_id " \
550 "WHERE delegates_map.r_id = ? ORDER BY delegates_map.ord ASC",
551 ^(sqlite3_stmt *stmt) {
552 sqlite3_bind_int64(stmt, 1, rule_get_id(rule));
553 }, ^bool(auth_items_t data) {
554 rule_t delegate = _rule_create_with_sql(data);
555 if (delegate) {
556 _get_sql_mechanisms(delegate, dbconn);
557
558 if (rule_get_class(rule) == RC_RULE) {
559 _get_sql_delegates(delegate, dbconn);
560 }
561
562 CFArrayAppendValue(rule->delegations, delegate);
563 CFReleaseSafe(delegate);
564 }
565 return true;
566 });
567 }
568
569 bool
570 rule_sql_fetch(rule_t rule, authdb_connection_t dbconn)
571 {
572 __block bool result = false;
573
574 authdb_step(dbconn, "SELECT * FROM rules WHERE name = ? LIMIT 1",
575 ^(sqlite3_stmt *stmt) {
576 sqlite3_bind_text(stmt, 1, rule_get_name(rule), -1, NULL);
577 }, ^bool(auth_items_t data) {
578 result = true;
579 auth_items_copy(rule->data, data);
580 return true;
581 });
582
583 if (rule_get_id(rule) != 0) {
584 _get_sql_mechanisms(rule,dbconn);
585
586 if (rule_get_class(rule) == RC_RULE) {
587 _get_sql_delegates(rule, dbconn);
588 }
589 }
590
591 return result;
592 }
593
594 static bool
595 _sql_update(rule_t rule, authdb_connection_t dbconn)
596 {
597 bool result = false;
598
599 result = authdb_step(dbconn, "UPDATE rules " \
600 "SET name=?,type=?,class=?,'group'=?,kofn=?,timeout=?,flags=?,tries=?,version=?,created=?,modified=?,hash=?,identifier=?,requirement=?,comment=? " \
601 "WHERE id = ?",
602 ^(sqlite3_stmt *stmt) {
603 _sql_bind(rule, stmt);
604 sqlite3_bind_int64(stmt, sqlite3_bind_parameter_count(stmt), rule_get_id(rule));
605 }, NULL);
606 return result;
607 }
608
609 static bool
610 _sql_insert(rule_t rule, authdb_connection_t dbconn)
611 {
612 bool result = false;
613
614 result = authdb_step(dbconn, "INSERT INTO rules VALUES (NULL,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
615 ^(sqlite3_stmt *stmt) {
616 _sql_bind(rule, stmt);
617 }, NULL);
618 return result;
619 }
620
621 static bool
622 _sql_commit_mechanisms_map(rule_t rule, authdb_connection_t dbconn)
623 {
624 bool result = false;
625
626 result = authdb_step(dbconn, "DELETE FROM mechanisms_map WHERE r_id = ?", ^(sqlite3_stmt *stmt) {
627 sqlite3_bind_int64(stmt, 1, rule_get_id(rule));
628 }, NULL);
629 require(result == true, done);
630
631 CFIndex count = CFArrayGetCount(rule->mechanisms);
632 for(CFIndex i = 0; i < count; i++) {
633 mechanism_t mech = (mechanism_t)CFArrayGetValueAtIndex(rule->mechanisms, i);
634 result = authdb_step(dbconn, "INSERT INTO mechanisms_map VALUES (?,?,?)", ^(sqlite3_stmt *stmt) {
635 sqlite3_bind_int64(stmt, 1, rule_get_id(rule));
636 sqlite3_bind_int64(stmt, 2, mechanism_get_id(mech));
637 sqlite3_bind_int64(stmt, 3, i);
638 }, NULL);
639 require(result == true, done);
640 }
641
642 done:
643 return result;
644 }
645
646 static bool
647 _sql_commit_delegates_map(rule_t rule, authdb_connection_t dbconn)
648 {
649 bool result = false;
650
651 result = authdb_step(dbconn, "DELETE FROM delegates_map WHERE r_id = ?", ^(sqlite3_stmt *stmt) {
652 sqlite3_bind_int64(stmt, 1, rule_get_id(rule));
653 }, NULL);
654 require(result == true, done);
655
656 CFIndex count = CFArrayGetCount(rule->delegations);
657 for(CFIndex i = 0; i < count; i++) {
658 rule_t delegate = (rule_t)CFArrayGetValueAtIndex(rule->delegations, i);
659 result = authdb_step(dbconn, "INSERT INTO delegates_map VALUES (?,?,?)", ^(sqlite3_stmt *stmt) {
660 sqlite3_bind_int64(stmt, 1, rule_get_id(rule));
661 sqlite3_bind_int64(stmt, 2, rule_get_id(delegate));
662 sqlite3_bind_int64(stmt, 3, i);
663 }, NULL);
664 require(result == true, done);
665 }
666
667 done:
668 return result;
669 }
670
671 static void
672 _sql_commit_localization(rule_t rule, authdb_connection_t dbconn)
673 {
674
675 authdb_step(dbconn, "DELETE FROM prompts WHERE r_id = ?", ^(sqlite3_stmt *stmt) {
676 sqlite3_bind_int64(stmt, 1, rule_get_id(rule));
677 }, NULL);
678
679 authdb_step(dbconn, "DELETE FROM buttons WHERE r_id = ?", ^(sqlite3_stmt *stmt) {
680 sqlite3_bind_int64(stmt, 1, rule_get_id(rule));
681 }, NULL);
682
683 if (rule->loc_prompts) {
684 _cf_dictionary_iterate(rule->loc_prompts, ^bool(CFTypeRef key, CFTypeRef value) {
685 char * lang = _copy_cf_string(key, NULL);
686 char * str = _copy_cf_string(value, NULL);
687
688 authdb_step(dbconn, "INSERT INTO prompts VALUES (?,?,?)", ^(sqlite3_stmt *stmt) {
689 sqlite3_bind_int64(stmt, 1, rule_get_id(rule));
690 sqlite3_bind_text(stmt, 2, lang, -1, NULL);
691 sqlite3_bind_text(stmt, 3, str, -1, NULL);
692 }, NULL);
693
694 free_safe(lang);
695 free_safe(str);
696
697 return true;
698 });
699 }
700
701 if (rule->loc_buttons) {
702 _cf_dictionary_iterate(rule->loc_buttons, ^bool(CFTypeRef key, CFTypeRef value) {
703 char * lang = _copy_cf_string(key, NULL);
704 char * str = _copy_cf_string(value, NULL);
705
706 authdb_step(dbconn, "INSERT INTO buttons VALUES (?,?,?)", ^(sqlite3_stmt *stmt) {
707 sqlite3_bind_int64(stmt, 1, rule_get_id(rule));
708 sqlite3_bind_text(stmt, 2, lang, -1, NULL);
709 sqlite3_bind_text(stmt, 3, str, -1, NULL);
710 }, NULL);
711
712 free_safe(lang);
713 free_safe(str);
714 return true;
715 });
716 }
717
718 }
719
720 bool
721 rule_sql_commit(rule_t rule, authdb_connection_t dbconn, CFAbsoluteTime modified, process_t proc)
722 {
723 bool result = false;
724 // type and class required else rule is name only?
725 RuleClass rule_class = rule_get_class(rule);
726 require(rule_get_type(rule) != 0, done);
727 require(rule_class != 0, done);
728
729 CFIndex mechCount = 0;
730 if (rule_class == RC_USER || rule_class == RC_MECHANISM) {
731 // Validate mechanisms
732 mechCount = CFArrayGetCount(rule->mechanisms);
733 for (CFIndex i = 0; i < mechCount; i++) {
734 mechanism_t mech = (mechanism_t)CFArrayGetValueAtIndex(rule->mechanisms, i);
735 if (mechanism_get_id(mech) == 0) {
736 if (!mechanism_sql_fetch(mech, dbconn)) {
737 mechanism_sql_commit(mech, dbconn);
738 mechanism_sql_fetch(mech, dbconn);
739 }
740 }
741 if (!mechanism_exists(mech)) {
742 LOGE("Warning mechanism not found on disk %s during import of %s", mechanism_get_string(mech), rule_get_name(rule));
743 }
744 require_action(mechanism_get_id(mech) != 0, done, LOGE("rule: commit, invalid mechanism %s:%s for %s", mechanism_get_plugin(mech), mechanism_get_param(mech), rule_get_name(rule)));
745 }
746 }
747
748 CFIndex delegateCount = 0;
749 if (rule_class == RC_RULE) {
750 // Validate delegates
751 delegateCount = CFArrayGetCount(rule->delegations);
752 for (CFIndex i = 0; i < delegateCount; i++) {
753 rule_t delegate = (rule_t)CFArrayGetValueAtIndex(rule->delegations, i);
754 if (rule_get_id(delegate) == 0) {
755 rule_sql_fetch(delegate, dbconn);
756 }
757 require_action(rule_get_id(delegate) != 0, done, LOGE("rule: commit, missing delegate %s for %s", rule_get_name(delegate), rule_get_name(rule)));
758 }
759 }
760
761 auth_items_set_double(rule->data, RULE_MODIFIED, modified);
762
763 result = authdb_transaction(dbconn, AuthDBTransactionNormal, ^bool{
764 bool update = false;
765
766 if (rule_get_id(rule)) {
767 update = _sql_update(rule, dbconn);
768 } else {
769 if (proc) {
770 const char * ident = process_get_identifier(proc);
771 if (ident) {
772 auth_items_set_string(rule->data, RULE_IDENTIFIER, ident);
773 }
774 CFDataRef req = process_get_requirement_data(proc);
775 if (req) {
776 auth_items_set_data(rule->data, RULE_REQUIREMENT, CFDataGetBytePtr(req), (size_t)CFDataGetLength(req));
777 }
778 }
779 auth_items_set_double(rule->data, RULE_CREATED, modified);
780 update = _sql_insert(rule, dbconn);
781 _sql_get_id(rule, dbconn);
782 }
783
784 _sql_commit_localization(rule, dbconn);
785
786 if (update) {
787 update = _sql_commit_mechanisms_map(rule, dbconn);
788 }
789
790 if (update) {
791 update = _sql_commit_delegates_map(rule,dbconn);
792 }
793
794 return update;
795 });
796
797
798 done:
799 if (!result) {
800 LOGV("rule: commit, failed for %s (%llu)", rule_get_name(rule), rule_get_id(rule));
801 }
802 return result;
803 }
804
805 bool
806 rule_sql_remove(rule_t rule, authdb_connection_t dbconn)
807 {
808 bool result = false;
809 int64_t id = rule_get_id(rule);
810
811 if (id == 0) {
812 rule_sql_fetch(rule, dbconn);
813 id = rule_get_id(rule);
814 require(id != 0, done);
815 }
816
817 result = authdb_step(dbconn, "DELETE FROM rules WHERE id = ?",
818 ^(sqlite3_stmt *stmt) {
819 sqlite3_bind_int64(stmt, 1, id);
820 }, NULL);
821 done:
822 return result;
823 }
824
825 CFMutableDictionaryRef
826 rule_copy_to_cfobject(rule_t rule, authdb_connection_t dbconn) {
827 CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
828
829 CFTypeRef tmp = NULL;
830 CFMutableArrayRef array = NULL;
831 CFIndex count = 0;
832 CFIndex i = 0;
833 int64_t n;
834 double d;
835
836 const char * comment = rule_get_comment(rule);
837 if (comment) {
838 tmp = CFStringCreateWithCString(kCFAllocatorDefault, comment, kCFStringEncodingUTF8);
839 CFDictionarySetValue(dict, CFSTR(kAuthorizationComment), tmp);
840 CFReleaseSafe(tmp);
841 }
842
843 n = rule_get_version(rule);
844 tmp = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &n);
845 CFDictionarySetValue(dict, CFSTR(RULE_VERSION), tmp);
846 CFReleaseSafe(tmp);
847
848 d = rule_get_created(rule);
849 tmp = CFNumberCreate(kCFAllocatorDefault, kCFNumberFloat64Type, &d);
850 CFDictionarySetValue(dict, CFSTR(RULE_CREATED), tmp);
851 CFReleaseSafe(tmp);
852
853 d = rule_get_modified(rule);
854 tmp = CFNumberCreate(kCFAllocatorDefault, kCFNumberFloat64Type, &d);
855 CFDictionarySetValue(dict, CFSTR(RULE_MODIFIED), tmp);
856 CFReleaseSafe(tmp);
857
858 const char * identifier = rule_get_identifier(rule);
859 if (identifier) {
860 tmp = CFStringCreateWithCString(kCFAllocatorDefault, identifier, kCFStringEncodingUTF8);
861 CFDictionarySetValue(dict, CFSTR(RULE_IDENTIFIER), tmp);
862 CFReleaseSafe(tmp);
863 }
864
865 SecRequirementRef req = rule_get_requirment(rule);
866 if (req) {
867 CFStringRef reqStr = NULL;
868 SecRequirementCopyString(req, kSecCSDefaultFlags, &reqStr);
869 if (reqStr) {
870 CFDictionarySetValue(dict, CFSTR(RULE_REQUIREMENT), reqStr);
871 CFReleaseSafe(reqStr);
872 }
873 }
874
875 if (rule_check_flags(rule, RuleFlagEntitled)) {
876 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterEntitled), kCFBooleanTrue);
877 }
878
879 if (rule_check_flags(rule, RuleFlagRequireAppleSigned)) {
880 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterRequireAppleSigned), kCFBooleanTrue);
881 }
882
883 if (rule_get_type(rule) == RT_RIGHT) {
884 CFMutableDictionaryRef prompts = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
885 authdb_step(dbconn, "SELECT * FROM prompts WHERE r_id = ?", ^(sqlite3_stmt *stmt) {
886 sqlite3_bind_int64(stmt, 1, rule_get_id(rule));
887 }, ^bool(auth_items_t data) {
888 CFStringRef key = CFStringCreateWithCString(kCFAllocatorDefault, auth_items_get_string(data, "lang"), kCFStringEncodingUTF8);
889 CFStringRef value = CFStringCreateWithCString(kCFAllocatorDefault, auth_items_get_string(data, "value"), kCFStringEncodingUTF8);
890 CFDictionaryAddValue(prompts, key, value);
891 CFReleaseSafe(key);
892 CFReleaseSafe(value);
893 return true;
894 });
895
896 if (CFDictionaryGetCount(prompts)) {
897 CFDictionaryAddValue(dict, CFSTR(kAuthorizationRuleParameterDefaultPrompt), prompts);
898 }
899 CFReleaseSafe(prompts);
900
901 CFMutableDictionaryRef buttons = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
902 authdb_step(dbconn, "SELECT * FROM buttons WHERE r_id = ?", ^(sqlite3_stmt *stmt) {
903 sqlite3_bind_int64(stmt, 1, rule_get_id(rule));
904 }, ^bool(auth_items_t data) {
905 CFStringRef key = CFStringCreateWithCString(kCFAllocatorDefault, auth_items_get_string(data, "lang"), kCFStringEncodingUTF8);
906 CFStringRef value = CFStringCreateWithCString(kCFAllocatorDefault, auth_items_get_string(data, "value"), kCFStringEncodingUTF8);
907 CFDictionaryAddValue(buttons, key, value);
908 CFReleaseSafe(key);
909 CFReleaseSafe(value);
910 return true;
911 });
912
913 if (CFDictionaryGetCount(buttons)) {
914 CFDictionaryAddValue(dict, CFSTR(kAuthorizationRuleParameterDefaultButton), buttons);
915 }
916 CFReleaseSafe(buttons);
917 }
918
919 switch (rule_get_class(rule)) {
920 case RC_USER:
921 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleClass), CFSTR(kAuthorizationRuleClassUser));
922
923 const char * group = rule_get_group(rule);
924 if (group) {
925 tmp = CFStringCreateWithCString(kCFAllocatorDefault, group, kCFStringEncodingUTF8);
926 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterGroup), tmp);
927 CFReleaseSafe(tmp);
928 }
929
930 n = rule_get_timeout(rule);
931 tmp = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &n);
932 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterCredentialTimeout), tmp);
933 CFReleaseSafe(tmp);
934
935 n = rule_get_tries(rule);
936 tmp = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &n);
937 CFDictionarySetValue(dict, CFSTR("tries"), tmp);
938 CFReleaseSafe(tmp);
939
940 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterCredentialShared), rule_get_shared(rule) ? kCFBooleanTrue : kCFBooleanFalse);
941 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterAllowRoot), rule_get_allow_root(rule) ? kCFBooleanTrue : kCFBooleanFalse);
942 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterCredentialSessionOwner), rule_get_session_owner(rule) ? kCFBooleanTrue : kCFBooleanFalse);
943 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterAuthenticateUser), rule_get_authenticate_user(rule) ? kCFBooleanTrue : kCFBooleanFalse);
944 if (rule_check_flags(rule, RuleFlagEntitledAndGroup)) {
945 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterEntitledAndGroup), kCFBooleanTrue);
946 }
947 if (rule_check_flags(rule, RuleFlagVPNEntitledAndGroup)) {
948 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterVPNEntitledAndGroup), kCFBooleanTrue);
949 }
950 if (rule_get_extract_password(rule)) {
951 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterExtractPassword), kCFBooleanTrue);
952 }
953
954 count = CFArrayGetCount(rule->mechanisms);
955 if (count) {
956 array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
957 for (i = 0; i < count; i++) {
958 mechanism_t mech = (mechanism_t)CFArrayGetValueAtIndex(rule->mechanisms, i);
959 tmp = CFStringCreateWithCString(kCFAllocatorDefault, mechanism_get_string(mech), kCFStringEncodingUTF8);
960 CFArrayAppendValue(array, tmp);
961 CFReleaseSafe(tmp);
962 }
963 CFDictionaryAddValue(dict, CFSTR(kAuthorizationRuleParameterMechanisms), array);
964 CFRelease(array);
965 }
966 break;
967 case RC_RULE:
968 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleClass), CFSTR(kAuthorizationRightRule));
969 int64_t kofn = rule_get_kofn(rule);
970 if (kofn) {
971 tmp = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &kofn);
972 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterKofN), tmp);
973 CFReleaseSafe(tmp);
974 }
975
976 count = CFArrayGetCount(rule->delegations);
977 if (count) {
978 array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
979 for (i = 0; i < count; i++) {
980 rule_t delegate = (rule_t)CFArrayGetValueAtIndex(rule->delegations, i);
981 tmp = CFStringCreateWithCString(kCFAllocatorDefault, rule_get_name(delegate), kCFStringEncodingUTF8);
982 CFArrayAppendValue(array, tmp);
983 CFReleaseSafe(tmp);
984 }
985 CFDictionaryAddValue(dict, CFSTR(kAuthorizationRightRule), array);
986 CFRelease(array);
987 }
988 break;
989 case RC_MECHANISM:
990 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleClass), CFSTR(kAuthorizationRuleClassMechanisms));
991
992 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterCredentialShared), rule_get_shared(rule) ? kCFBooleanTrue : kCFBooleanFalse);
993 if (rule_get_extract_password(rule)) {
994 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterExtractPassword), kCFBooleanTrue);
995 }
996
997 n = rule_get_tries(rule);
998 tmp = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &n);
999 CFDictionarySetValue(dict, CFSTR("tries"), tmp);
1000 CFReleaseSafe(tmp);
1001
1002 count = CFArrayGetCount(rule->mechanisms);
1003 if (count) {
1004 array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
1005 for (i = 0; i < count; i++) {
1006 mechanism_t mech = (mechanism_t)CFArrayGetValueAtIndex(rule->mechanisms, i);
1007 tmp = CFStringCreateWithCString(kCFAllocatorDefault, mechanism_get_string(mech), kCFStringEncodingUTF8);
1008 CFArrayAppendValue(array, tmp);
1009 CFReleaseSafe(tmp);
1010 }
1011 CFDictionaryAddValue(dict, CFSTR(kAuthorizationRuleParameterMechanisms), array);
1012 CFRelease(array);
1013 }
1014 break;
1015 case RC_DENY:
1016 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleClass), CFSTR(kAuthorizationRuleClassDeny));
1017 break;
1018 case RC_ALLOW:
1019 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleClass), CFSTR(kAuthorizationRuleClassAllow));
1020 break;
1021 default:
1022 break;
1023 }
1024
1025 return dict;
1026 }
1027
1028
1029 CFArrayRef
1030 rule_get_mechanisms(rule_t rule)
1031 {
1032 return rule->mechanisms;
1033 }
1034
1035 size_t
1036 rule_get_mechanisms_count(rule_t rule)
1037 {
1038 return (size_t)CFArrayGetCount(rule->mechanisms);
1039 }
1040
1041 bool
1042 rule_mechanisms_iterator(rule_t rule, mechanism_iterator_t iter)
1043 {
1044 bool result = false;
1045
1046 CFIndex count = CFArrayGetCount(rule->mechanisms);
1047 for (CFIndex i = 0; i < count; i++) {
1048 mechanism_t mech = (mechanism_t)CFArrayGetValueAtIndex(rule->mechanisms, i);
1049 result = iter(mech);
1050 if (!result) {
1051 break;
1052 }
1053 }
1054
1055 return result;
1056 }
1057
1058 size_t
1059 rule_get_delegates_count(rule_t rule)
1060 {
1061 return (size_t)CFArrayGetCount(rule->delegations);
1062 }
1063
1064 bool
1065 rule_delegates_iterator(rule_t rule, delegate_iterator_t iter)
1066 {
1067 bool result = false;
1068
1069 CFIndex count = CFArrayGetCount(rule->delegations);
1070 for (CFIndex i = 0; i < count; i++) {
1071 rule_t tmp = (rule_t)CFArrayGetValueAtIndex(rule->delegations, i);
1072 result = iter(tmp);
1073 if (!result) {
1074 break;
1075 }
1076 }
1077
1078 return result;
1079 }
1080
1081 int64_t
1082 rule_get_id(rule_t rule)
1083 {
1084 return auth_items_get_int64(rule->data, RULE_ID);
1085 }
1086
1087 const char *
1088 rule_get_name(rule_t rule)
1089 {
1090 return auth_items_get_string(rule->data, RULE_NAME);
1091 }
1092
1093 RuleType
1094 rule_get_type(rule_t rule)
1095 {
1096 return (RuleType)auth_items_get_int64(rule->data, RULE_TYPE);
1097 }
1098
1099 RuleClass
1100 rule_get_class(rule_t rule)
1101 {
1102 return (RuleClass)auth_items_get_int64(rule->data, RULE_CLASS);
1103 }
1104
1105 const char *
1106 rule_get_group(rule_t rule)
1107 {
1108 return auth_items_get_string(rule->data, RULE_GROUP);
1109 }
1110
1111 int64_t
1112 rule_get_kofn(rule_t rule)
1113 {
1114 return auth_items_get_int64(rule->data, RULE_KOFN);
1115 }
1116
1117 int64_t
1118 rule_get_timeout(rule_t rule)
1119 {
1120 return auth_items_get_int64(rule->data, RULE_TIMEOUT);
1121 }
1122
1123 bool
1124 rule_check_flags(rule_t rule, RuleFlags flags)
1125 {
1126 return (auth_items_get_int64(rule->data, RULE_FLAGS) & flags) != 0;
1127 }
1128
1129 bool
1130 rule_get_shared(rule_t rule)
1131 {
1132 return rule_check_flags(rule, RuleFlagShared);
1133 }
1134
1135 bool
1136 rule_get_allow_root(rule_t rule)
1137 {
1138 return rule_check_flags(rule, RuleFlagAllowRoot);
1139 }
1140
1141 bool
1142 rule_get_session_owner(rule_t rule)
1143 {
1144 return rule_check_flags(rule, RuleFlagSessionOwner);
1145 }
1146
1147 bool
1148 rule_get_authenticate_user(rule_t rule)
1149 {
1150 return rule_check_flags(rule, RuleFlagAuthenticateUser);
1151 }
1152
1153 bool
1154 rule_get_extract_password(rule_t rule)
1155 {
1156 return rule_check_flags(rule, RuleFlagExtractPassword);
1157 }
1158
1159 int64_t
1160 rule_get_tries(rule_t rule)
1161 {
1162 return auth_items_get_int64(rule->data, RULE_TRIES);
1163 }
1164
1165 const char *
1166 rule_get_comment(rule_t rule)
1167 {
1168 return auth_items_get_string(rule->data, RULE_COMMENT);
1169 }
1170
1171 int64_t
1172 rule_get_version(rule_t rule)
1173 {
1174 return auth_items_get_int64(rule->data, RULE_VERSION);
1175 }
1176
1177 double rule_get_created(rule_t rule)
1178 {
1179 return auth_items_get_double(rule->data, RULE_CREATED);
1180 }
1181
1182 double rule_get_modified(rule_t rule)
1183 {
1184 return auth_items_get_double(rule->data, RULE_MODIFIED);
1185 }
1186
1187 const char * rule_get_identifier(rule_t rule)
1188 {
1189 return auth_items_get_string(rule->data, RULE_IDENTIFIER);
1190 }
1191
1192 CFDataRef rule_get_requirment_data(rule_t rule)
1193 {
1194 if (!rule->requirement_data && auth_items_exist(rule->data, RULE_REQUIREMENT)) {
1195 size_t len;
1196 const void * data = auth_items_get_data(rule->data, RULE_REQUIREMENT, &len);
1197 rule->requirement_data = CFDataCreate(kCFAllocatorDefault, data, (CFIndex)len);
1198 }
1199
1200 return rule->requirement_data;
1201 }
1202
1203 SecRequirementRef rule_get_requirment(rule_t rule)
1204 {
1205 if (!rule->requirement) {
1206 CFDataRef data = rule_get_requirment_data(rule);
1207 if (data) {
1208 SecRequirementCreateWithData(data, kSecCSDefaultFlags, &rule->requirement);
1209 }
1210 }
1211
1212 return rule->requirement;
1213 }