1 /* Copyright (c) 2012 Apple Inc. All rights reserved. */
4 #include "authutilities.h"
11 #include <Security/AuthorizationDB.h>
12 #include <Security/AuthorizationTagsPriv.h>
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
);
20 #define kMaximumAuthorizationTries 10000
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"
40 __AUTH_BASE_STRUCT_HEADER__
;
43 CFMutableArrayRef mechanisms
;
44 CFMutableArrayRef delegations
;
46 CFMutableDictionaryRef loc_prompts
;
47 CFMutableDictionaryRef loc_buttons
;
49 CFDataRef requirement_data
;
50 SecRequirementRef requirement
;
54 _rule_finalize(CFTypeRef value
)
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
);
67 _rule_equal(CFTypeRef value1
, CFTypeRef value2
)
69 rule_t rule1
= (rule_t
)value1
;
70 rule_t rule2
= (rule_t
)value2
;
72 return strcasecmp(rule_get_name(rule1
), rule_get_name(rule2
)) == 0;
76 _rule_copy_description(CFTypeRef value
)
78 rule_t rule
= (rule_t
)value
;
79 CFMutableStringRef str
= CFStringCreateMutable(kCFAllocatorDefault
, 0);
80 CFStringRef tmp
= CFCopyDescription(rule
->data
);
81 CFStringAppend(str
, tmp
);
83 tmp
= CFCopyDescription(rule
->mechanisms
);
84 CFStringAppend(str
, tmp
);
86 tmp
= CFCopyDescription(rule
->delegations
);
87 CFStringAppend(str
, tmp
);
93 _rule_hash(CFTypeRef value
)
95 rule_t rule
= (rule_t
)value
;
96 const char * str
= rule_get_name(rule
);
97 return crc64(str
, strlen(str
));
100 AUTH_TYPE_INSTANCE(rule
,
103 .finalize
= _rule_finalize
,
104 .equal
= _rule_equal
,
106 .copyFormattingDesc
= NULL
,
107 .copyDebugDesc
= _rule_copy_description
110 static CFTypeID
rule_get_type_id() {
111 static CFTypeID type_id
= _kCFRuntimeNotATypeID
;
112 static dispatch_once_t onceToken
;
114 dispatch_once(&onceToken
, ^{
115 type_id
= _CFRuntimeRegisterClass(&_auth_type_rule
);
124 rule_t rule
= (rule_t
)_CFRuntimeCreateInstance(kCFAllocatorDefault
, rule_get_type_id(), AUTH_CLASS_SIZE(rule
), NULL
);
125 require(rule
!= NULL
, done
);
127 rule
->data
= auth_items_create();
128 rule
->delegations
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
129 rule
->mechanisms
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
136 _rule_create_with_sql(auth_items_t sql
)
139 require(sql
!= NULL
, done
);
141 rule
= _rule_create();
142 require(rule
!= NULL
, done
);
144 auth_items_copy(rule
->data
, sql
);
151 rule_create_default()
153 rule_t rule
= _rule_create();
154 require(rule
!= NULL
, done
);
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
);
164 mechanism_t mech
= mechanism_create_with_string("builtin:authenticate", NULL
);
165 CFArrayAppendValue(rule
->mechanisms
, mech
);
168 mech
= mechanism_create_with_string("builtin:reset-password,privileged", NULL
);
169 CFArrayAppendValue(rule
->mechanisms
, mech
);
172 mech
= mechanism_create_with_string("builtin:authenticate,privileged", NULL
);
173 CFArrayAppendValue(rule
->mechanisms
, mech
);
176 mech
= mechanism_create_with_string("PKINITMechanism:auth,privileged", NULL
);
177 CFArrayAppendValue(rule
->mechanisms
, mech
);
185 rule_create_with_string(const char * str
, authdb_connection_t dbconn
)
188 require(str
!= NULL
, done
);
190 rule
= _rule_create();
191 require(rule
!= NULL
, done
);
193 auth_items_set_string(rule
->data
, RULE_NAME
, str
);
196 rule_sql_fetch(rule
, dbconn
);
203 static void _set_data_string(rule_t rule
, const char * key
, CFStringRef str
)
205 char * tmpStr
= _copy_cf_string(str
, NULL
);
208 auth_items_set_string(rule
->data
, key
, tmpStr
);
214 rule_create_with_plist(RuleType type
, CFStringRef name
, CFDictionaryRef plist
, authdb_connection_t dbconn
)
217 require(name
!= NULL
, done
);
218 require(plist
!= NULL
, done
);
220 rule
= _rule_create();
221 require(rule
!= NULL
, done
);
223 _set_data_string(rule
, RULE_NAME
, name
);
224 require_action(rule_get_name(rule
) != NULL
, done
, CFReleaseSafe(rule
));
226 _sql_get_id(rule
, dbconn
);
228 auth_items_set_int64(rule
->data
, RULE_TYPE
, type
);
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
)));
234 CFTypeRef loc_tmp
= CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterDefaultPrompt
));
236 rule
->loc_prompts
= CFDictionaryCreateMutableCopy(kCFAllocatorDefault
, 0, loc_tmp
);
238 loc_tmp
= CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterDefaultButton
));
240 rule
->loc_buttons
= CFDictionaryCreateMutableCopy(kCFAllocatorDefault
, 0, loc_tmp
);
243 auth_items_set_int64(rule
->data
, RULE_VERSION
, _get_cf_int(CFDictionaryGetValue(plist
, CFSTR("version")), 0));
247 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterEntitled
)), false)) {
248 flags
|= RuleFlagEntitled
;
251 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterRequireAppleSigned
)), false)) {
252 flags
|= RuleFlagRequireAppleSigned
;
255 switch (rule_get_class(rule
)) {
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
));
261 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterCredentialShared
)), false)) {
262 flags
|= RuleFlagShared
;
264 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterAllowRoot
)), false)) {
265 flags
|= RuleFlagAllowRoot
;
267 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterCredentialSessionOwner
)), false)) {
268 flags
|= RuleFlagSessionOwner
;
270 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterAuthenticateUser
)), true)) {
271 flags
|= RuleFlagAuthenticateUser
;
273 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterExtractPassword
)), false)) {
274 flags
|= RuleFlagExtractPassword
;
276 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterEntitledAndGroup
)), false)) {
277 flags
|= RuleFlagEntitledAndGroup
;
279 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterVPNEntitledAndGroup
)), false)) {
280 flags
|= RuleFlagVPNEntitledAndGroup
;
283 _copy_cf_rule_mechanisms(rule
, CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterMechanisms
)), dbconn
);
287 auth_items_set_int64(rule
->data
, RULE_KOFN
, _get_cf_int(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterKofN
)), 0));
289 _copy_cf_rule_delegations(rule
, CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRightRule
)), dbconn
);
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
;
296 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterExtractPassword
)), false)) {
297 flags
|= RuleFlagExtractPassword
;
300 _copy_cf_rule_mechanisms(rule
, CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterMechanisms
)), dbconn
);
308 LOGD("rule: invalid rule class");
312 auth_items_set_int64(rule
->data
, RULE_FLAGS
, flags
);
319 _sql_get_id(rule_t rule
, authdb_connection_t dbconn
)
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
);
331 _copy_cf_rule_delegations(rule_t rule
, CFTypeRef value
, authdb_connection_t dbconn
)
334 char * tmp_str
= NULL
;
335 require(value
!= NULL
, done
);
337 if (CFGetTypeID(value
) == CFStringGetTypeID()) {
338 tmp_str
= _copy_cf_string(value
, NULL
);
339 rule_t delegate
= rule_create_with_string(tmp_str
, dbconn
);
342 CFArrayAppendValue(rule
->delegations
, delegate
);
343 CFReleaseSafe(delegate
);
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
);
352 CFArrayAppendValue(rule
->delegations
, delegate
);
353 CFReleaseSafe(delegate
);
365 _copy_cf_rule_mechanisms(rule_t rule
, CFTypeRef array
, authdb_connection_t dbconn
)
368 require(array
!= NULL
, done
);
369 require(CFGetTypeID(array
) == CFArrayGetTypeID(), done
);
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
);
379 mech
= mechanism_create_with_string(string
, dbconn
);
381 CFArrayAppendValue(rule
->mechanisms
, mech
);
394 _get_cf_rule_class(CFTypeRef str
)
396 RuleClass rc
= RC_RULE
;
397 require(str
!= NULL
, done
);
398 require(CFGetTypeID(str
) == CFStringGetTypeID(), done
);
400 if (CFEqual(str
, CFSTR(kAuthorizationRuleClassUser
)))
403 if (CFEqual(str
, CFSTR(kAuthorizationRightRule
)))
406 if (CFEqual(str
, CFSTR(kAuthorizationRuleClassMechanisms
)))
409 if (CFEqual(str
, CFSTR(kAuthorizationRuleClassDeny
)))
412 if (CFEqual(str
, CFSTR(kAuthorizationRuleClassAllow
)))
420 _sql_bind(rule_t rule
, sqlite3_stmt
* stmt
)
424 require(stmt
!= NULL
, err
);
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
);
434 switch (rule_get_class(rule
)) {
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
);
448 rc
= sqlite3_bind_null(stmt
, column
++); // group
449 require_noerr(rc
, err
);
450 n
= rule_get_kofn(rule
);
452 rc
= sqlite3_bind_int64(stmt
, column
++, n
);
454 rc
= sqlite3_bind_null(stmt
, column
++);
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
);
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
);
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
);
490 LOGD("rule: sql bind, invalid rule class");
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
);
505 CFDataRef data
= rule_get_requirment_data(rule
);
507 rc
= sqlite3_bind_blob(stmt
, column
++, CFDataGetBytePtr(data
), (int32_t)CFDataGetLength(data
), NULL
);
509 rc
= sqlite3_bind_null(stmt
, column
++);
511 require_noerr(rc
, err
);
513 rc
= sqlite3_bind_text(stmt
, column
++, rule_get_comment(rule
), -1, NULL
);
514 require_noerr(rc
, err
);
519 LOGD("rule: sql bind, error %i", rc
);
524 _get_sql_mechanisms(rule_t rule
, authdb_connection_t dbconn
)
526 CFArrayRemoveAllValues(rule
->mechanisms
);
528 authdb_step(dbconn
, "SELECT 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
);
543 _get_sql_delegates(rule_t rule
, authdb_connection_t dbconn
)
545 CFArrayRemoveAllValues(rule
->delegations
);
547 authdb_step(dbconn
, "SELECT 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
);
556 _get_sql_mechanisms(delegate
, dbconn
);
558 if (rule_get_class(rule
) == RC_RULE
) {
559 _get_sql_delegates(delegate
, dbconn
);
562 CFArrayAppendValue(rule
->delegations
, delegate
);
563 CFReleaseSafe(delegate
);
570 rule_sql_fetch(rule_t rule
, authdb_connection_t dbconn
)
572 __block
bool result
= false;
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
) {
579 auth_items_copy(rule
->data
, data
);
583 if (rule_get_id(rule
) != 0) {
584 _get_sql_mechanisms(rule
,dbconn
);
586 if (rule_get_class(rule
) == RC_RULE
) {
587 _get_sql_delegates(rule
, dbconn
);
595 _sql_update(rule_t rule
, authdb_connection_t dbconn
)
599 result
= authdb_step(dbconn
, "UPDATE rules " \
600 "SET name=?,type=?,class=?,'group'=?,kofn=?,timeout=?,flags=?,tries=?,version=?,created=?,modified=?,hash=?,identifier=?,requirement=?,comment=? " \
602 ^(sqlite3_stmt
*stmt
) {
603 _sql_bind(rule
, stmt
);
604 sqlite3_bind_int64(stmt
, sqlite3_bind_parameter_count(stmt
), rule_get_id(rule
));
610 _sql_insert(rule_t rule
, authdb_connection_t dbconn
)
614 result
= authdb_step(dbconn
, "INSERT INTO rules VALUES (NULL,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
615 ^(sqlite3_stmt
*stmt
) {
616 _sql_bind(rule
, stmt
);
622 _sql_commit_mechanisms_map(rule_t rule
, authdb_connection_t dbconn
)
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
));
629 require(result
== true, done
);
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
);
639 require(result
== true, done
);
647 _sql_commit_delegates_map(rule_t rule
, authdb_connection_t dbconn
)
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
));
654 require(result
== true, done
);
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
);
664 require(result
== true, done
);
672 _sql_commit_localization(rule_t rule
, authdb_connection_t dbconn
)
675 authdb_step(dbconn
, "DELETE FROM prompts WHERE r_id = ?", ^(sqlite3_stmt
*stmt
) {
676 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
679 authdb_step(dbconn
, "DELETE FROM buttons WHERE r_id = ?", ^(sqlite3_stmt
*stmt
) {
680 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
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
);
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
);
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
);
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
);
721 rule_sql_commit(rule_t rule
, authdb_connection_t dbconn
, CFAbsoluteTime modified
, process_t proc
)
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
);
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
);
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
));
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
)));
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
);
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
)));
761 auth_items_set_double(rule
->data
, RULE_MODIFIED
, modified
);
763 result
= authdb_transaction(dbconn
, AuthDBTransactionNormal
, ^bool{
766 if (rule_get_id(rule
)) {
767 update
= _sql_update(rule
, dbconn
);
770 const char * ident
= process_get_identifier(proc
);
772 auth_items_set_string(rule
->data
, RULE_IDENTIFIER
, ident
);
774 CFDataRef req
= process_get_requirement_data(proc
);
776 auth_items_set_data(rule
->data
, RULE_REQUIREMENT
, CFDataGetBytePtr(req
), (size_t)CFDataGetLength(req
));
779 auth_items_set_double(rule
->data
, RULE_CREATED
, modified
);
780 update
= _sql_insert(rule
, dbconn
);
781 _sql_get_id(rule
, dbconn
);
784 _sql_commit_localization(rule
, dbconn
);
787 update
= _sql_commit_mechanisms_map(rule
, dbconn
);
791 update
= _sql_commit_delegates_map(rule
,dbconn
);
800 LOGV("rule: commit, failed for %s (%llu)", rule_get_name(rule
), rule_get_id(rule
));
806 rule_sql_remove(rule_t rule
, authdb_connection_t dbconn
)
809 int64_t id
= rule_get_id(rule
);
812 rule_sql_fetch(rule
, dbconn
);
813 id
= rule_get_id(rule
);
814 require(id
!= 0, done
);
817 result
= authdb_step(dbconn
, "DELETE FROM rules WHERE id = ?",
818 ^(sqlite3_stmt
*stmt
) {
819 sqlite3_bind_int64(stmt
, 1, id
);
825 CFMutableDictionaryRef
826 rule_copy_to_cfobject(rule_t rule
, authdb_connection_t dbconn
) {
827 CFMutableDictionaryRef dict
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
829 CFTypeRef tmp
= NULL
;
830 CFMutableArrayRef array
= NULL
;
836 const char * comment
= rule_get_comment(rule
);
838 tmp
= CFStringCreateWithCString(kCFAllocatorDefault
, comment
, kCFStringEncodingUTF8
);
839 CFDictionarySetValue(dict
, CFSTR(kAuthorizationComment
), tmp
);
843 n
= rule_get_version(rule
);
844 tmp
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt64Type
, &n
);
845 CFDictionarySetValue(dict
, CFSTR(RULE_VERSION
), tmp
);
848 d
= rule_get_created(rule
);
849 tmp
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberFloat64Type
, &d
);
850 CFDictionarySetValue(dict
, CFSTR(RULE_CREATED
), tmp
);
853 d
= rule_get_modified(rule
);
854 tmp
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberFloat64Type
, &d
);
855 CFDictionarySetValue(dict
, CFSTR(RULE_MODIFIED
), tmp
);
858 const char * identifier
= rule_get_identifier(rule
);
860 tmp
= CFStringCreateWithCString(kCFAllocatorDefault
, identifier
, kCFStringEncodingUTF8
);
861 CFDictionarySetValue(dict
, CFSTR(RULE_IDENTIFIER
), tmp
);
865 SecRequirementRef req
= rule_get_requirment(rule
);
867 CFStringRef reqStr
= NULL
;
868 SecRequirementCopyString(req
, kSecCSDefaultFlags
, &reqStr
);
870 CFDictionarySetValue(dict
, CFSTR(RULE_REQUIREMENT
), reqStr
);
871 CFReleaseSafe(reqStr
);
875 if (rule_check_flags(rule
, RuleFlagEntitled
)) {
876 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterEntitled
), kCFBooleanTrue
);
879 if (rule_check_flags(rule
, RuleFlagRequireAppleSigned
)) {
880 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterRequireAppleSigned
), kCFBooleanTrue
);
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
);
892 CFReleaseSafe(value
);
896 if (CFDictionaryGetCount(prompts
)) {
897 CFDictionaryAddValue(dict
, CFSTR(kAuthorizationRuleParameterDefaultPrompt
), prompts
);
899 CFReleaseSafe(prompts
);
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
);
909 CFReleaseSafe(value
);
913 if (CFDictionaryGetCount(buttons
)) {
914 CFDictionaryAddValue(dict
, CFSTR(kAuthorizationRuleParameterDefaultButton
), buttons
);
916 CFReleaseSafe(buttons
);
919 switch (rule_get_class(rule
)) {
921 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleClass
), CFSTR(kAuthorizationRuleClassUser
));
923 const char * group
= rule_get_group(rule
);
925 tmp
= CFStringCreateWithCString(kCFAllocatorDefault
, group
, kCFStringEncodingUTF8
);
926 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterGroup
), tmp
);
930 n
= rule_get_timeout(rule
);
931 tmp
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt64Type
, &n
);
932 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterCredentialTimeout
), tmp
);
935 n
= rule_get_tries(rule
);
936 tmp
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt64Type
, &n
);
937 CFDictionarySetValue(dict
, CFSTR("tries"), tmp
);
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
);
947 if (rule_check_flags(rule
, RuleFlagVPNEntitledAndGroup
)) {
948 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterVPNEntitledAndGroup
), kCFBooleanTrue
);
950 if (rule_get_extract_password(rule
)) {
951 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterExtractPassword
), kCFBooleanTrue
);
954 count
= CFArrayGetCount(rule
->mechanisms
);
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
);
963 CFDictionaryAddValue(dict
, CFSTR(kAuthorizationRuleParameterMechanisms
), array
);
968 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleClass
), CFSTR(kAuthorizationRightRule
));
969 int64_t kofn
= rule_get_kofn(rule
);
971 tmp
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt64Type
, &kofn
);
972 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterKofN
), tmp
);
976 count
= CFArrayGetCount(rule
->delegations
);
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
);
985 CFDictionaryAddValue(dict
, CFSTR(kAuthorizationRightRule
), array
);
990 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleClass
), CFSTR(kAuthorizationRuleClassMechanisms
));
992 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterCredentialShared
), rule_get_shared(rule
) ? kCFBooleanTrue
: kCFBooleanFalse
);
993 if (rule_get_extract_password(rule
)) {
994 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterExtractPassword
), kCFBooleanTrue
);
997 n
= rule_get_tries(rule
);
998 tmp
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt64Type
, &n
);
999 CFDictionarySetValue(dict
, CFSTR("tries"), tmp
);
1002 count
= CFArrayGetCount(rule
->mechanisms
);
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
);
1011 CFDictionaryAddValue(dict
, CFSTR(kAuthorizationRuleParameterMechanisms
), array
);
1016 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleClass
), CFSTR(kAuthorizationRuleClassDeny
));
1019 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleClass
), CFSTR(kAuthorizationRuleClassAllow
));
1030 rule_get_mechanisms(rule_t rule
)
1032 return rule
->mechanisms
;
1036 rule_get_mechanisms_count(rule_t rule
)
1038 return (size_t)CFArrayGetCount(rule
->mechanisms
);
1042 rule_mechanisms_iterator(rule_t rule
, mechanism_iterator_t iter
)
1044 bool result
= false;
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
);
1059 rule_get_delegates_count(rule_t rule
)
1061 return (size_t)CFArrayGetCount(rule
->delegations
);
1065 rule_delegates_iterator(rule_t rule
, delegate_iterator_t iter
)
1067 bool result
= false;
1069 CFIndex count
= CFArrayGetCount(rule
->delegations
);
1070 for (CFIndex i
= 0; i
< count
; i
++) {
1071 rule_t tmp
= (rule_t
)CFArrayGetValueAtIndex(rule
->delegations
, i
);
1082 rule_get_id(rule_t rule
)
1084 return auth_items_get_int64(rule
->data
, RULE_ID
);
1088 rule_get_name(rule_t rule
)
1090 return auth_items_get_string(rule
->data
, RULE_NAME
);
1094 rule_get_type(rule_t rule
)
1096 return (RuleType
)auth_items_get_int64(rule
->data
, RULE_TYPE
);
1100 rule_get_class(rule_t rule
)
1102 return (RuleClass
)auth_items_get_int64(rule
->data
, RULE_CLASS
);
1106 rule_get_group(rule_t rule
)
1108 return auth_items_get_string(rule
->data
, RULE_GROUP
);
1112 rule_get_kofn(rule_t rule
)
1114 return auth_items_get_int64(rule
->data
, RULE_KOFN
);
1118 rule_get_timeout(rule_t rule
)
1120 return auth_items_get_int64(rule
->data
, RULE_TIMEOUT
);
1124 rule_check_flags(rule_t rule
, RuleFlags flags
)
1126 return (auth_items_get_int64(rule
->data
, RULE_FLAGS
) & flags
) != 0;
1130 rule_get_shared(rule_t rule
)
1132 return rule_check_flags(rule
, RuleFlagShared
);
1136 rule_get_allow_root(rule_t rule
)
1138 return rule_check_flags(rule
, RuleFlagAllowRoot
);
1142 rule_get_session_owner(rule_t rule
)
1144 return rule_check_flags(rule
, RuleFlagSessionOwner
);
1148 rule_get_authenticate_user(rule_t rule
)
1150 return rule_check_flags(rule
, RuleFlagAuthenticateUser
);
1154 rule_get_extract_password(rule_t rule
)
1156 return rule_check_flags(rule
, RuleFlagExtractPassword
);
1160 rule_get_tries(rule_t rule
)
1162 return auth_items_get_int64(rule
->data
, RULE_TRIES
);
1166 rule_get_comment(rule_t rule
)
1168 return auth_items_get_string(rule
->data
, RULE_COMMENT
);
1172 rule_get_version(rule_t rule
)
1174 return auth_items_get_int64(rule
->data
, RULE_VERSION
);
1177 double rule_get_created(rule_t rule
)
1179 return auth_items_get_double(rule
->data
, RULE_CREATED
);
1182 double rule_get_modified(rule_t rule
)
1184 return auth_items_get_double(rule
->data
, RULE_MODIFIED
);
1187 const char * rule_get_identifier(rule_t rule
)
1189 return auth_items_get_string(rule
->data
, RULE_IDENTIFIER
);
1192 CFDataRef
rule_get_requirment_data(rule_t rule
)
1194 if (!rule
->requirement_data
&& auth_items_exist(rule
->data
, RULE_REQUIREMENT
)) {
1196 const void * data
= auth_items_get_data(rule
->data
, RULE_REQUIREMENT
, &len
);
1197 rule
->requirement_data
= CFDataCreate(kCFAllocatorDefault
, data
, (CFIndex
)len
);
1200 return rule
->requirement_data
;
1203 SecRequirementRef
rule_get_requirment(rule_t rule
)
1205 if (!rule
->requirement
) {
1206 CFDataRef data
= rule_get_requirment_data(rule
);
1208 SecRequirementCreateWithData(data
, kSecCSDefaultFlags
, &rule
->requirement
);
1212 return rule
->requirement
;