1 /* Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. */
4 #include "authutilities.h"
11 #include <Security/AuthorizationDB.h>
12 #include <Security/AuthorizationTagsPriv.h>
17 static void _sql_get_id(rule_t
,authdb_connection_t
);
18 static RuleClass
_get_cf_rule_class(CFTypeRef
);
19 static bool _copy_cf_rule_mechanisms(rule_t
,CFTypeRef
,authdb_connection_t
);
20 static bool _copy_cf_rule_delegations(rule_t
, CFTypeRef
,authdb_connection_t
);
22 #define kMaximumAuthorizationTries 10000
25 #define RULE_NAME "name"
26 #define RULE_TYPE "type"
27 #define RULE_CLASS "class"
28 #define RULE_GROUP "group"
29 #define RULE_KOFN "kofn"
30 #define RULE_TIMEOUT "timeout"
31 #define RULE_FLAGS "flags"
32 #define RULE_TRIES "tries"
33 #define RULE_COMMENT "comment"
34 #define RULE_VERSION "version"
35 #define RULE_CREATED "created"
36 #define RULE_MODIFIED "modified"
37 #define RULE_IDENTIFIER "identifier"
38 #define RULE_REQUIREMENT "requirement"
39 #define RULE_HASH "hash"
42 __AUTH_BASE_STRUCT_HEADER__
;
45 CFMutableArrayRef mechanisms
;
46 CFMutableArrayRef delegations
;
48 CFMutableDictionaryRef loc_prompts
;
49 CFMutableDictionaryRef loc_buttons
;
51 CFDataRef requirement_data
;
52 SecRequirementRef requirement
;
56 _rule_finalize(CFTypeRef value
)
58 rule_t rule
= (rule_t
)value
;
59 CFReleaseNull(rule
->data
);
60 CFReleaseNull(rule
->mechanisms
);
61 CFReleaseNull(rule
->delegations
);
62 CFReleaseNull(rule
->loc_prompts
);
63 CFReleaseNull(rule
->loc_buttons
);
64 CFReleaseNull(rule
->requirement_data
);
65 CFReleaseNull(rule
->requirement
);
69 _rule_equal(CFTypeRef value1
, CFTypeRef value2
)
71 rule_t rule1
= (rule_t
)value1
;
72 rule_t rule2
= (rule_t
)value2
;
74 return strcasecmp(rule_get_name(rule1
), rule_get_name(rule2
)) == 0;
78 _rule_copy_description(CFTypeRef value
)
80 rule_t rule
= (rule_t
)value
;
81 CFMutableStringRef str
= CFStringCreateMutable(kCFAllocatorDefault
, 0);
82 CFStringRef tmp
= CFCopyDescription(rule
->data
);
83 CFStringAppend(str
, tmp
);
85 tmp
= CFCopyDescription(rule
->mechanisms
);
86 CFStringAppend(str
, tmp
);
88 tmp
= CFCopyDescription(rule
->delegations
);
89 CFStringAppend(str
, tmp
);
95 _rule_hash(CFTypeRef value
)
97 rule_t rule
= (rule_t
)value
;
98 const char * str
= rule_get_name(rule
);
99 return (CFHashCode
)crc64(str
, strlen(str
));
102 AUTH_TYPE_INSTANCE(rule
,
105 .finalize
= _rule_finalize
,
106 .equal
= _rule_equal
,
108 .copyFormattingDesc
= NULL
,
109 .copyDebugDesc
= _rule_copy_description
112 static CFTypeID
rule_get_type_id() {
113 static CFTypeID type_id
= _kCFRuntimeNotATypeID
;
114 static dispatch_once_t onceToken
;
116 dispatch_once(&onceToken
, ^{
117 type_id
= _CFRuntimeRegisterClass(&_auth_type_rule
);
126 rule_t rule
= (rule_t
)_CFRuntimeCreateInstance(kCFAllocatorDefault
, rule_get_type_id(), AUTH_CLASS_SIZE(rule
), NULL
);
127 require(rule
!= NULL
, done
);
129 rule
->data
= auth_items_create();
130 rule
->delegations
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
131 rule
->mechanisms
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
138 _rule_create_with_sql(auth_items_t sql
)
141 require(sql
!= NULL
, done
);
143 rule
= _rule_create();
144 require(rule
!= NULL
, done
);
146 auth_items_copy(rule
->data
, sql
);
153 rule_create_default()
155 rule_t rule
= _rule_create();
156 require(rule
!= NULL
, done
);
158 auth_items_set_int64(rule
->data
, RULE_TYPE
, RT_RIGHT
);
159 auth_items_set_string(rule
->data
, RULE_NAME
, "(default)");
160 auth_items_set_int64(rule
->data
, RULE_CLASS
, RC_USER
);
161 auth_items_set_string(rule
->data
, RULE_GROUP
, "admin");
162 auth_items_set_int64(rule
->data
, RULE_TIMEOUT
, 300);
163 auth_items_set_int64(rule
->data
, RULE_TRIES
, kMaximumAuthorizationTries
);
164 auth_items_set_int64(rule
->data
, RULE_FLAGS
, RuleFlagShared
| RuleFlagAuthenticateUser
);
166 mechanism_t mech
= mechanism_create_with_string("builtin:authenticate", NULL
);
167 CFArrayAppendValue(rule
->mechanisms
, mech
);
170 mech
= mechanism_create_with_string("builtin:reset-password,privileged", NULL
);
171 CFArrayAppendValue(rule
->mechanisms
, mech
);
174 mech
= mechanism_create_with_string("builtin:authenticate,privileged", NULL
);
175 CFArrayAppendValue(rule
->mechanisms
, mech
);
178 mech
= mechanism_create_with_string("PKINITMechanism:auth,privileged", NULL
);
179 CFArrayAppendValue(rule
->mechanisms
, mech
);
187 rule_create_preauthorization()
189 rule_t rule
= _rule_create();
190 require(rule
!= NULL
, done
);
192 auth_items_set_int64(rule
->data
, RULE_TYPE
, RT_RIGHT
);
193 auth_items_set_string(rule
->data
, RULE_NAME
, "(preauthorization)");
194 auth_items_set_int64(rule
->data
, RULE_CLASS
, RC_USER
);
195 auth_items_set_string(rule
->data
, RULE_GROUP
, "admin");
196 auth_items_set_int64(rule
->data
, RULE_TRIES
, 1);
197 auth_items_set_int64(rule
->data
, RULE_FLAGS
, RuleFlagShared
| RuleFlagAuthenticateUser
| RuleFlagRequireAppleSigned
);
199 mechanism_t mech
= mechanism_create_with_string("builtin:authenticate,privileged", NULL
);
200 CFArrayAppendValue(rule
->mechanisms
, mech
);
208 rule_create_with_string(const char * str
, authdb_connection_t dbconn
)
211 require(str
!= NULL
, done
);
213 rule
= _rule_create();
214 require(rule
!= NULL
, done
);
216 auth_items_set_string(rule
->data
, RULE_NAME
, str
);
219 rule_sql_fetch(rule
, dbconn
);
226 static void _set_data_string(rule_t rule
, const char * key
, CFStringRef str
)
228 char * tmpStr
= _copy_cf_string(str
, NULL
);
231 auth_items_set_string(rule
->data
, key
, tmpStr
);
237 rule_create_with_plist(RuleType type
, CFStringRef name
, CFDictionaryRef plist
, authdb_connection_t dbconn
)
240 require(name
!= NULL
, done
);
241 require(plist
!= NULL
, done
);
243 rule
= _rule_create();
244 require(rule
!= NULL
, done
);
246 _set_data_string(rule
, RULE_NAME
, name
);
247 require_action(rule_get_name(rule
) != NULL
, done
, CFReleaseSafe(rule
));
249 _sql_get_id(rule
, dbconn
);
251 auth_items_set_int64(rule
->data
, RULE_TYPE
, type
);
253 auth_items_set_int64(rule
->data
, RULE_CLASS
, _get_cf_rule_class(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleClass
))));
254 _set_data_string(rule
, RULE_COMMENT
, CFDictionaryGetValue(plist
, CFSTR(kAuthorizationComment
)));
257 CFTypeRef loc_tmp
= CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterDefaultPrompt
));
259 rule
->loc_prompts
= CFDictionaryCreateMutableCopy(kCFAllocatorDefault
, 0, loc_tmp
);
261 loc_tmp
= CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterDefaultButton
));
263 rule
->loc_buttons
= CFDictionaryCreateMutableCopy(kCFAllocatorDefault
, 0, loc_tmp
);
266 auth_items_set_int64(rule
->data
, RULE_VERSION
, _get_cf_int(CFDictionaryGetValue(plist
, CFSTR("version")), 0));
270 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterEntitled
)), false)) {
271 flags
|= RuleFlagEntitled
;
274 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterRequireAppleSigned
)), false)) {
275 flags
|= RuleFlagRequireAppleSigned
;
278 switch (rule_get_class(rule
)) {
280 _set_data_string(rule
, RULE_GROUP
, CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterGroup
)));
281 auth_items_set_int64(rule
->data
, RULE_TIMEOUT
, _get_cf_int(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterCredentialTimeout
)), INT32_MAX
));
282 auth_items_set_int64(rule
->data
, RULE_TRIES
, _get_cf_int(CFDictionaryGetValue(plist
, CFSTR("tries")), kMaximumAuthorizationTries
));
284 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterCredentialShared
)), false)) {
285 flags
|= RuleFlagShared
;
287 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterAllowRoot
)), false)) {
288 flags
|= RuleFlagAllowRoot
;
290 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterCredentialSessionOwner
)), false)) {
291 flags
|= RuleFlagSessionOwner
;
293 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterAuthenticateUser
)), true)) {
294 flags
|= RuleFlagAuthenticateUser
;
296 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterExtractPassword
)), false)) {
297 flags
|= RuleFlagExtractPassword
;
299 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterEntitledAndGroup
)), false)) {
300 flags
|= RuleFlagEntitledAndGroup
;
302 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterVPNEntitledAndGroup
)), false)) {
303 flags
|= RuleFlagVPNEntitledAndGroup
;
305 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterPasswordOnly
)), false)) {
306 flags
|= RuleFlagPasswordOnly
;
309 _copy_cf_rule_mechanisms(rule
, CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterMechanisms
)), dbconn
);
313 auth_items_set_int64(rule
->data
, RULE_KOFN
, _get_cf_int(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterKofN
)), 0));
315 _copy_cf_rule_delegations(rule
, CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRightRule
)), dbconn
);
318 auth_items_set_int64(rule
->data
, RULE_TRIES
, _get_cf_int(CFDictionaryGetValue(plist
, CFSTR("tries")), kMaximumAuthorizationTries
));
319 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterCredentialShared
)), true)) {
320 flags
|= RuleFlagShared
;
322 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterExtractPassword
)), false)) {
323 flags
|= RuleFlagExtractPassword
;
326 _copy_cf_rule_mechanisms(rule
, CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterMechanisms
)), dbconn
);
334 os_log_error(AUTHD_LOG
, "rule: invalid rule class");
338 auth_items_set_int64(rule
->data
, RULE_FLAGS
, flags
);
345 _sql_get_id(rule_t rule
, authdb_connection_t dbconn
)
347 authdb_step(dbconn
, "SELECT id,created,identifier,requirement FROM rules WHERE name = ? LIMIT 1",
348 ^(sqlite3_stmt
*stmt
) {
349 sqlite3_bind_text(stmt
, 1, rule_get_name(rule
), -1, NULL
);
350 }, ^bool(auth_items_t data
) {
351 auth_items_copy(rule
->data
, data
);
357 _copy_cf_rule_delegations(rule_t rule
, CFTypeRef value
, authdb_connection_t dbconn
)
360 char * tmp_str
= NULL
;
361 require(value
!= NULL
, done
);
363 if (CFGetTypeID(value
) == CFStringGetTypeID()) {
364 tmp_str
= _copy_cf_string(value
, NULL
);
365 rule_t delegate
= rule_create_with_string(tmp_str
, dbconn
);
368 CFArrayAppendValue(rule
->delegations
, delegate
);
369 CFReleaseSafe(delegate
);
372 CFIndex count
= CFArrayGetCount(value
);
373 for (CFIndex i
= 0; i
< count
; i
++) {
374 tmp_str
= _copy_cf_string(CFArrayGetValueAtIndex(value
,i
), NULL
);
375 rule_t delegate
= rule_create_with_string(tmp_str
, dbconn
);
378 CFArrayAppendValue(rule
->delegations
, delegate
);
379 CFReleaseSafe(delegate
);
391 _copy_cf_rule_mechanisms(rule_t rule
, CFTypeRef array
, authdb_connection_t dbconn
)
394 require(array
!= NULL
, done
);
395 require(CFGetTypeID(array
) == CFArrayGetTypeID(), done
);
397 CFIndex count
= CFArrayGetCount(array
);
398 for (CFIndex i
= 0; i
< count
; i
++) {
399 mechanism_t mech
= NULL
;
400 char * string
= _copy_cf_string(CFArrayGetValueAtIndex(array
, i
), NULL
);
405 mech
= mechanism_create_with_string(string
, dbconn
);
407 CFArrayAppendValue(rule
->mechanisms
, mech
);
420 _get_cf_rule_class(CFTypeRef str
)
422 RuleClass rc
= RC_RULE
;
423 require(str
!= NULL
, done
);
424 require(CFGetTypeID(str
) == CFStringGetTypeID(), done
);
426 if (CFEqual(str
, CFSTR(kAuthorizationRuleClassUser
)))
429 if (CFEqual(str
, CFSTR(kAuthorizationRightRule
)))
432 if (CFEqual(str
, CFSTR(kAuthorizationRuleClassMechanisms
)))
435 if (CFEqual(str
, CFSTR(kAuthorizationRuleClassDeny
)))
438 if (CFEqual(str
, CFSTR(kAuthorizationRuleClassAllow
)))
446 _sql_bind(rule_t rule
, sqlite3_stmt
* stmt
)
450 require(stmt
!= NULL
, err
);
453 rc
= sqlite3_bind_text(stmt
, column
++, rule_get_name(rule
), -1, NULL
);
454 require_noerr(rc
, err
);
455 rc
= sqlite3_bind_int(stmt
, column
++, rule_get_type(rule
));
456 require_noerr(rc
, err
);
457 rc
= sqlite3_bind_int(stmt
, column
++, rule_get_class(rule
));
458 require_noerr(rc
, err
);
460 switch (rule_get_class(rule
)) {
462 rc
= sqlite3_bind_text(stmt
, column
++, rule_get_group(rule
), -1, NULL
);
463 require_noerr(rc
, err
);
464 rc
= sqlite3_bind_null(stmt
, column
++); // kofn
465 require_noerr(rc
, err
);
466 rc
= sqlite3_bind_int64(stmt
, column
++, rule_get_timeout(rule
));
467 require_noerr(rc
, err
);
468 rc
= sqlite3_bind_int64(stmt
, column
++, auth_items_get_int64(rule
->data
, RULE_FLAGS
));
469 require_noerr(rc
, err
);
470 rc
= sqlite3_bind_int64(stmt
, column
++, rule_get_tries(rule
));
471 require_noerr(rc
, err
);
474 rc
= sqlite3_bind_null(stmt
, column
++); // group
475 require_noerr(rc
, err
);
476 n
= rule_get_kofn(rule
);
478 rc
= sqlite3_bind_int64(stmt
, column
++, n
);
480 rc
= sqlite3_bind_null(stmt
, column
++);
482 require_noerr(rc
, err
);
483 rc
= sqlite3_bind_null(stmt
, column
++); // timeout
484 require_noerr(rc
, err
);
485 rc
= sqlite3_bind_int64(stmt
, column
++, auth_items_get_int64(rule
->data
, RULE_FLAGS
));
486 require_noerr(rc
, err
);
487 rc
= sqlite3_bind_null(stmt
, column
++); // tries
488 require_noerr(rc
, err
);
491 rc
= sqlite3_bind_null(stmt
, column
++); // group
492 require_noerr(rc
, err
);
493 rc
= sqlite3_bind_null(stmt
, column
++); // kofn
494 require_noerr(rc
, err
);
495 rc
= sqlite3_bind_null(stmt
, column
++); // timeout
496 require_noerr(rc
, err
);
497 rc
= sqlite3_bind_int64(stmt
, column
++, auth_items_get_int64(rule
->data
, RULE_FLAGS
));
498 require_noerr(rc
, err
);
499 rc
= sqlite3_bind_int64(stmt
, column
++, rule_get_tries(rule
));
500 require_noerr(rc
, err
);
504 rc
= sqlite3_bind_null(stmt
, column
++); // group
505 require_noerr(rc
, err
);
506 rc
= sqlite3_bind_null(stmt
, column
++); // kofn
507 require_noerr(rc
, err
);
508 rc
= sqlite3_bind_null(stmt
, column
++); // timeout
509 require_noerr(rc
, err
);
510 rc
= sqlite3_bind_int64(stmt
, column
++, auth_items_get_int64(rule
->data
, RULE_FLAGS
));
511 require_noerr(rc
, err
);
512 rc
= sqlite3_bind_null(stmt
, column
++); // tries
513 require_noerr(rc
, err
);
516 os_log_error(AUTHD_LOG
, "rule: sql bind, invalid rule class");
520 rc
= sqlite3_bind_int64(stmt
, column
++, rule_get_version(rule
)); // version
521 require_noerr(rc
, err
);
522 rc
= sqlite3_bind_double(stmt
, column
++, rule_get_created(rule
)); // created
523 require_noerr(rc
, err
);
524 rc
= sqlite3_bind_double(stmt
, column
++, rule_get_modified(rule
)); // modified
525 require_noerr(rc
, err
);
526 rc
= sqlite3_bind_null(stmt
, column
++); // hash
527 require_noerr(rc
, err
);
528 rc
= sqlite3_bind_text(stmt
, column
++, rule_get_identifier(rule
), -1, NULL
);
529 require_noerr(rc
, err
);
531 CFDataRef data
= rule_get_requirement_data(rule
);
533 rc
= sqlite3_bind_blob(stmt
, column
++, CFDataGetBytePtr(data
), (int32_t)CFDataGetLength(data
), NULL
);
535 rc
= sqlite3_bind_null(stmt
, column
++);
537 require_noerr(rc
, err
);
539 rc
= sqlite3_bind_text(stmt
, column
++, rule_get_comment(rule
), -1, NULL
);
540 require_noerr(rc
, err
);
545 os_log_error(AUTHD_LOG
, "rule: sql bind, error %i", rc
);
550 _get_sql_mechanisms(rule_t rule
, authdb_connection_t dbconn
)
552 CFArrayRemoveAllValues(rule
->mechanisms
);
554 authdb_step(dbconn
, "SELECT mechanisms.* " \
556 "JOIN mechanisms_map ON mechanisms.id = mechanisms_map.m_id " \
557 "WHERE mechanisms_map.r_id = ? ORDER BY mechanisms_map.ord ASC",
558 ^(sqlite3_stmt
*stmt
) {
559 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
560 }, ^bool(auth_items_t data
) {
561 mechanism_t mechanism
= mechanism_create_with_sql(data
);
562 CFArrayAppendValue(rule
->mechanisms
, mechanism
);
563 CFReleaseSafe(mechanism
);
569 _get_sql_delegates(rule_t rule
, authdb_connection_t dbconn
)
571 CFArrayRemoveAllValues(rule
->delegations
);
573 authdb_step(dbconn
, "SELECT rules.* " \
575 "JOIN delegates_map ON rules.id = delegates_map.d_id " \
576 "WHERE delegates_map.r_id = ? ORDER BY delegates_map.ord ASC",
577 ^(sqlite3_stmt
*stmt
) {
578 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
579 }, ^bool(auth_items_t data
) {
580 rule_t delegate
= _rule_create_with_sql(data
);
582 _get_sql_mechanisms(delegate
, dbconn
);
584 if (rule_get_class(rule
) == RC_RULE
) {
585 _get_sql_delegates(delegate
, dbconn
);
588 CFArrayAppendValue(rule
->delegations
, delegate
);
589 CFReleaseSafe(delegate
);
596 rule_sql_fetch(rule_t rule
, authdb_connection_t dbconn
)
598 __block
bool result
= false;
600 authdb_step(dbconn
, "SELECT * FROM rules WHERE name = ? LIMIT 1",
601 ^(sqlite3_stmt
*stmt
) {
602 sqlite3_bind_text(stmt
, 1, rule_get_name(rule
), -1, NULL
);
603 }, ^bool(auth_items_t data
) {
605 auth_items_copy(rule
->data
, data
);
609 if (rule_get_id(rule
) != 0) {
610 _get_sql_mechanisms(rule
,dbconn
);
612 if (rule_get_class(rule
) == RC_RULE
) {
613 _get_sql_delegates(rule
, dbconn
);
621 _sql_update(rule_t rule
, authdb_connection_t dbconn
)
625 result
= authdb_step(dbconn
, "UPDATE rules " \
626 "SET name=?,type=?,class=?,'group'=?,kofn=?,timeout=?,flags=?,tries=?,version=?,created=?,modified=?,hash=?,identifier=?,requirement=?,comment=? " \
628 ^(sqlite3_stmt
*stmt
) {
629 _sql_bind(rule
, stmt
);
630 sqlite3_bind_int64(stmt
, sqlite3_bind_parameter_count(stmt
), rule_get_id(rule
));
636 _sql_insert(rule_t rule
, authdb_connection_t dbconn
)
640 result
= authdb_step(dbconn
, "INSERT INTO rules VALUES (NULL,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
641 ^(sqlite3_stmt
*stmt
) {
642 _sql_bind(rule
, stmt
);
648 _sql_commit_mechanisms_map(rule_t rule
, authdb_connection_t dbconn
)
652 result
= authdb_step(dbconn
, "DELETE FROM mechanisms_map WHERE r_id = ?", ^(sqlite3_stmt
*stmt
) {
653 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
655 require(result
== true, done
);
657 CFIndex count
= CFArrayGetCount(rule
->mechanisms
);
658 for(CFIndex i
= 0; i
< count
; i
++) {
659 mechanism_t mech
= (mechanism_t
)CFArrayGetValueAtIndex(rule
->mechanisms
, i
);
660 result
= authdb_step(dbconn
, "INSERT INTO mechanisms_map VALUES (?,?,?)", ^(sqlite3_stmt
*stmt
) {
661 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
662 sqlite3_bind_int64(stmt
, 2, mechanism_get_id(mech
));
663 sqlite3_bind_int64(stmt
, 3, i
);
665 require(result
== true, done
);
673 _sql_commit_delegates_map(rule_t rule
, authdb_connection_t dbconn
)
677 result
= authdb_step(dbconn
, "DELETE FROM delegates_map WHERE r_id = ?", ^(sqlite3_stmt
*stmt
) {
678 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
680 require(result
== true, done
);
682 CFIndex count
= CFArrayGetCount(rule
->delegations
);
683 for(CFIndex i
= 0; i
< count
; i
++) {
684 rule_t delegate
= (rule_t
)CFArrayGetValueAtIndex(rule
->delegations
, i
);
685 result
= authdb_step(dbconn
, "INSERT INTO delegates_map VALUES (?,?,?)", ^(sqlite3_stmt
*stmt
) {
686 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
687 sqlite3_bind_int64(stmt
, 2, rule_get_id(delegate
));
688 sqlite3_bind_int64(stmt
, 3, i
);
690 require(result
== true, done
);
698 _sql_commit_localization(rule_t rule
, authdb_connection_t dbconn
)
701 authdb_step(dbconn
, "DELETE FROM prompts WHERE r_id = ?", ^(sqlite3_stmt
*stmt
) {
702 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
705 authdb_step(dbconn
, "DELETE FROM buttons WHERE r_id = ?", ^(sqlite3_stmt
*stmt
) {
706 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
709 if (rule
->loc_prompts
) {
710 _cf_dictionary_iterate(rule
->loc_prompts
, ^bool(CFTypeRef key
, CFTypeRef value
) {
711 char * lang
= _copy_cf_string(key
, NULL
);
712 char * str
= _copy_cf_string(value
, NULL
);
714 authdb_step(dbconn
, "INSERT INTO prompts VALUES (?,?,?)", ^(sqlite3_stmt
*stmt
) {
715 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
716 sqlite3_bind_text(stmt
, 2, lang
, -1, NULL
);
717 sqlite3_bind_text(stmt
, 3, str
, -1, NULL
);
727 if (rule
->loc_buttons
) {
728 _cf_dictionary_iterate(rule
->loc_buttons
, ^bool(CFTypeRef key
, CFTypeRef value
) {
729 char * lang
= _copy_cf_string(key
, NULL
);
730 char * str
= _copy_cf_string(value
, NULL
);
732 authdb_step(dbconn
, "INSERT INTO buttons VALUES (?,?,?)", ^(sqlite3_stmt
*stmt
) {
733 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
734 sqlite3_bind_text(stmt
, 2, lang
, -1, NULL
);
735 sqlite3_bind_text(stmt
, 3, str
, -1, NULL
);
747 rule_sql_commit(rule_t rule
, authdb_connection_t dbconn
, CFAbsoluteTime modified
, process_t proc
)
750 // type and class required else rule is name only?
751 RuleClass rule_class
= rule_get_class(rule
);
752 require(rule_get_type(rule
) != 0, done
);
753 require(rule_class
!= 0, done
);
755 CFIndex mechCount
= 0;
756 if (rule_class
== RC_USER
|| rule_class
== RC_MECHANISM
) {
757 // Validate mechanisms
758 mechCount
= CFArrayGetCount(rule
->mechanisms
);
759 for (CFIndex i
= 0; i
< mechCount
; i
++) {
760 mechanism_t mech
= (mechanism_t
)CFArrayGetValueAtIndex(rule
->mechanisms
, i
);
761 if (mechanism_get_id(mech
) == 0) {
762 if (!mechanism_sql_fetch(mech
, dbconn
)) {
763 mechanism_sql_commit(mech
, dbconn
);
764 mechanism_sql_fetch(mech
, dbconn
);
767 if (!mechanism_exists(mech
)) {
768 os_log_error(AUTHD_LOG
, "Warning mechanism not found on disk %{public}s during import of %{public}s", mechanism_get_string(mech
), rule_get_name(rule
));
770 require_action(mechanism_get_id(mech
) != 0, done
, os_log_error(AUTHD_LOG
, "rule: commit, invalid mechanism %{public}s:%{public}s for %{public}s", mechanism_get_plugin(mech
), mechanism_get_param(mech
), rule_get_name(rule
)));
774 CFIndex delegateCount
= 0;
775 if (rule_class
== RC_RULE
) {
776 // Validate delegates
777 delegateCount
= CFArrayGetCount(rule
->delegations
);
778 for (CFIndex i
= 0; i
< delegateCount
; i
++) {
779 rule_t delegate
= (rule_t
)CFArrayGetValueAtIndex(rule
->delegations
, i
);
780 if (rule_get_id(delegate
) == 0) {
781 rule_sql_fetch(delegate
, dbconn
);
783 require_action(rule_get_id(delegate
) != 0, done
, os_log_error(AUTHD_LOG
, "rule: commit, missing delegate %{public}s for %{public}s", rule_get_name(delegate
), rule_get_name(rule
)));
787 auth_items_set_double(rule
->data
, RULE_MODIFIED
, modified
);
789 result
= authdb_transaction(dbconn
, AuthDBTransactionNormal
, ^bool{
792 if (rule_get_id(rule
)) {
793 update
= _sql_update(rule
, dbconn
);
796 const char * ident
= process_get_identifier(proc
);
798 auth_items_set_string(rule
->data
, RULE_IDENTIFIER
, ident
);
800 CFDataRef req
= process_get_requirement_data(proc
);
802 auth_items_set_data(rule
->data
, RULE_REQUIREMENT
, CFDataGetBytePtr(req
), (size_t)CFDataGetLength(req
));
805 auth_items_set_double(rule
->data
, RULE_CREATED
, modified
);
806 update
= _sql_insert(rule
, dbconn
);
807 _sql_get_id(rule
, dbconn
);
810 _sql_commit_localization(rule
, dbconn
);
813 update
= _sql_commit_mechanisms_map(rule
, dbconn
);
817 update
= _sql_commit_delegates_map(rule
,dbconn
);
826 os_log_debug(AUTHD_LOG
, "rule: commit, failed for %{public}s (%llu)", rule_get_name(rule
), rule_get_id(rule
));
832 rule_sql_remove(rule_t rule
, authdb_connection_t dbconn
)
835 int64_t id
= rule_get_id(rule
);
838 rule_sql_fetch(rule
, dbconn
);
839 id
= rule_get_id(rule
);
840 require(id
!= 0, done
);
843 result
= authdb_step(dbconn
, "DELETE FROM rules WHERE id = ?",
844 ^(sqlite3_stmt
*stmt
) {
845 sqlite3_bind_int64(stmt
, 1, id
);
851 CFMutableDictionaryRef
852 rule_copy_to_cfobject(rule_t rule
, authdb_connection_t dbconn
) {
853 CFMutableDictionaryRef dict
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
855 CFTypeRef tmp
= NULL
;
856 CFMutableArrayRef array
= NULL
;
862 const char * comment
= rule_get_comment(rule
);
864 tmp
= CFStringCreateWithCString(kCFAllocatorDefault
, comment
, kCFStringEncodingUTF8
);
865 CFDictionarySetValue(dict
, CFSTR(kAuthorizationComment
), tmp
);
869 n
= rule_get_version(rule
);
870 tmp
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt64Type
, &n
);
871 CFDictionarySetValue(dict
, CFSTR(RULE_VERSION
), tmp
);
874 d
= rule_get_created(rule
);
875 tmp
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberFloat64Type
, &d
);
876 CFDictionarySetValue(dict
, CFSTR(RULE_CREATED
), tmp
);
879 d
= rule_get_modified(rule
);
880 tmp
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberFloat64Type
, &d
);
881 CFDictionarySetValue(dict
, CFSTR(RULE_MODIFIED
), tmp
);
884 const char * identifier
= rule_get_identifier(rule
);
886 tmp
= CFStringCreateWithCString(kCFAllocatorDefault
, identifier
, kCFStringEncodingUTF8
);
887 CFDictionarySetValue(dict
, CFSTR(RULE_IDENTIFIER
), tmp
);
891 SecRequirementRef req
= rule_get_requirement(rule
);
893 CFStringRef reqStr
= NULL
;
894 SecRequirementCopyString(req
, kSecCSDefaultFlags
, &reqStr
);
896 CFDictionarySetValue(dict
, CFSTR(RULE_REQUIREMENT
), reqStr
);
897 CFReleaseSafe(reqStr
);
901 if (rule_check_flags(rule
, RuleFlagEntitled
)) {
902 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterEntitled
), kCFBooleanTrue
);
905 if (rule_check_flags(rule
, RuleFlagRequireAppleSigned
)) {
906 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterRequireAppleSigned
), kCFBooleanTrue
);
909 if (rule_get_type(rule
) == RT_RIGHT
) {
910 CFMutableDictionaryRef prompts
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
911 authdb_step(dbconn
, "SELECT * FROM prompts WHERE r_id = ?", ^(sqlite3_stmt
*stmt
) {
912 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
913 }, ^bool(auth_items_t data
) {
914 CFStringRef key
= CFStringCreateWithCString(kCFAllocatorDefault
, auth_items_get_string(data
, "lang"), kCFStringEncodingUTF8
);
915 CFStringRef value
= CFStringCreateWithCString(kCFAllocatorDefault
, auth_items_get_string(data
, "value"), kCFStringEncodingUTF8
);
916 CFDictionaryAddValue(prompts
, key
, value
);
918 CFReleaseSafe(value
);
922 if (CFDictionaryGetCount(prompts
)) {
923 CFDictionaryAddValue(dict
, CFSTR(kAuthorizationRuleParameterDefaultPrompt
), prompts
);
925 CFReleaseSafe(prompts
);
927 CFMutableDictionaryRef buttons
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
928 authdb_step(dbconn
, "SELECT * FROM buttons WHERE r_id = ?", ^(sqlite3_stmt
*stmt
) {
929 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
930 }, ^bool(auth_items_t data
) {
931 CFStringRef key
= CFStringCreateWithCString(kCFAllocatorDefault
, auth_items_get_string(data
, "lang"), kCFStringEncodingUTF8
);
932 CFStringRef value
= CFStringCreateWithCString(kCFAllocatorDefault
, auth_items_get_string(data
, "value"), kCFStringEncodingUTF8
);
933 CFDictionaryAddValue(buttons
, key
, value
);
935 CFReleaseSafe(value
);
939 if (CFDictionaryGetCount(buttons
)) {
940 CFDictionaryAddValue(dict
, CFSTR(kAuthorizationRuleParameterDefaultButton
), buttons
);
942 CFReleaseSafe(buttons
);
945 switch (rule_get_class(rule
)) {
947 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleClass
), CFSTR(kAuthorizationRuleClassUser
));
949 const char * group
= rule_get_group(rule
);
951 tmp
= CFStringCreateWithCString(kCFAllocatorDefault
, group
, kCFStringEncodingUTF8
);
952 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterGroup
), tmp
);
956 n
= rule_get_timeout(rule
);
957 tmp
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt64Type
, &n
);
958 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterCredentialTimeout
), tmp
);
961 n
= rule_get_tries(rule
);
962 tmp
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt64Type
, &n
);
963 CFDictionarySetValue(dict
, CFSTR("tries"), tmp
);
966 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterCredentialShared
), rule_get_shared(rule
) ? kCFBooleanTrue
: kCFBooleanFalse
);
967 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterAllowRoot
), rule_get_allow_root(rule
) ? kCFBooleanTrue
: kCFBooleanFalse
);
968 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterCredentialSessionOwner
), rule_get_session_owner(rule
) ? kCFBooleanTrue
: kCFBooleanFalse
);
969 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterAuthenticateUser
), rule_get_authenticate_user(rule
) ? kCFBooleanTrue
: kCFBooleanFalse
);
970 if (rule_check_flags(rule
, RuleFlagEntitledAndGroup
)) {
971 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterEntitledAndGroup
), kCFBooleanTrue
);
973 if (rule_check_flags(rule
, RuleFlagVPNEntitledAndGroup
)) {
974 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterVPNEntitledAndGroup
), kCFBooleanTrue
);
976 if (rule_get_extract_password(rule
)) {
977 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterExtractPassword
), kCFBooleanTrue
);
979 if (rule_get_password_only(rule
)) {
980 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterPasswordOnly
), kCFBooleanTrue
);
983 count
= CFArrayGetCount(rule
->mechanisms
);
985 array
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
986 for (i
= 0; i
< count
; i
++) {
987 mechanism_t mech
= (mechanism_t
)CFArrayGetValueAtIndex(rule
->mechanisms
, i
);
988 tmp
= CFStringCreateWithCString(kCFAllocatorDefault
, mechanism_get_string(mech
), kCFStringEncodingUTF8
);
989 CFArrayAppendValue(array
, tmp
);
992 CFDictionaryAddValue(dict
, CFSTR(kAuthorizationRuleParameterMechanisms
), array
);
997 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleClass
), CFSTR(kAuthorizationRightRule
));
998 int64_t kofn
= rule_get_kofn(rule
);
1000 tmp
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt64Type
, &kofn
);
1001 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterKofN
), tmp
);
1005 count
= CFArrayGetCount(rule
->delegations
);
1007 array
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
1008 for (i
= 0; i
< count
; i
++) {
1009 rule_t delegate
= (rule_t
)CFArrayGetValueAtIndex(rule
->delegations
, i
);
1010 tmp
= CFStringCreateWithCString(kCFAllocatorDefault
, rule_get_name(delegate
), kCFStringEncodingUTF8
);
1011 CFArrayAppendValue(array
, tmp
);
1014 CFDictionaryAddValue(dict
, CFSTR(kAuthorizationRightRule
), array
);
1019 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleClass
), CFSTR(kAuthorizationRuleClassMechanisms
));
1021 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterCredentialShared
), rule_get_shared(rule
) ? kCFBooleanTrue
: kCFBooleanFalse
);
1022 if (rule_get_extract_password(rule
)) {
1023 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterExtractPassword
), kCFBooleanTrue
);
1026 n
= rule_get_tries(rule
);
1027 tmp
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt64Type
, &n
);
1028 CFDictionarySetValue(dict
, CFSTR("tries"), tmp
);
1031 count
= CFArrayGetCount(rule
->mechanisms
);
1033 array
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
1034 for (i
= 0; i
< count
; i
++) {
1035 mechanism_t mech
= (mechanism_t
)CFArrayGetValueAtIndex(rule
->mechanisms
, i
);
1036 tmp
= CFStringCreateWithCString(kCFAllocatorDefault
, mechanism_get_string(mech
), kCFStringEncodingUTF8
);
1037 CFArrayAppendValue(array
, tmp
);
1040 CFDictionaryAddValue(dict
, CFSTR(kAuthorizationRuleParameterMechanisms
), array
);
1045 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleClass
), CFSTR(kAuthorizationRuleClassDeny
));
1048 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleClass
), CFSTR(kAuthorizationRuleClassAllow
));
1059 rule_get_mechanisms(rule_t rule
)
1061 return rule
->mechanisms
;
1065 rule_get_mechanisms_count(rule_t rule
)
1067 return (size_t)CFArrayGetCount(rule
->mechanisms
);
1071 rule_mechanisms_iterator(rule_t rule
, mechanism_iterator_t iter
)
1073 bool result
= false;
1075 CFIndex count
= CFArrayGetCount(rule
->mechanisms
);
1076 for (CFIndex i
= 0; i
< count
; i
++) {
1077 mechanism_t mech
= (mechanism_t
)CFArrayGetValueAtIndex(rule
->mechanisms
, i
);
1078 result
= iter(mech
);
1088 rule_get_delegates_count(rule_t rule
)
1090 return (size_t)CFArrayGetCount(rule
->delegations
);
1094 rule_delegates_iterator(rule_t rule
, delegate_iterator_t iter
)
1096 bool result
= false;
1098 CFIndex count
= CFArrayGetCount(rule
->delegations
);
1099 for (CFIndex i
= 0; i
< count
; i
++) {
1100 rule_t tmp
= (rule_t
)CFArrayGetValueAtIndex(rule
->delegations
, i
);
1111 rule_get_id(rule_t rule
)
1113 return auth_items_get_int64(rule
->data
, RULE_ID
);
1117 rule_get_name(rule_t rule
)
1119 return auth_items_get_string(rule
->data
, RULE_NAME
);
1123 rule_get_type(rule_t rule
)
1125 return (RuleType
)auth_items_get_int64(rule
->data
, RULE_TYPE
);
1129 rule_get_class(rule_t rule
)
1131 return (RuleClass
)auth_items_get_int64(rule
->data
, RULE_CLASS
);
1135 rule_get_group(rule_t rule
)
1137 return auth_items_get_string(rule
->data
, RULE_GROUP
);
1141 rule_get_kofn(rule_t rule
)
1143 return auth_items_get_int64(rule
->data
, RULE_KOFN
);
1147 rule_get_timeout(rule_t rule
)
1149 return auth_items_get_int64(rule
->data
, RULE_TIMEOUT
);
1153 rule_check_flags(rule_t rule
, RuleFlags flags
)
1155 return (auth_items_get_int64(rule
->data
, RULE_FLAGS
) & flags
) != 0;
1159 rule_get_shared(rule_t rule
)
1161 return rule_check_flags(rule
, RuleFlagShared
);
1165 rule_get_allow_root(rule_t rule
)
1167 return rule_check_flags(rule
, RuleFlagAllowRoot
);
1171 rule_get_session_owner(rule_t rule
)
1173 return rule_check_flags(rule
, RuleFlagSessionOwner
);
1177 rule_get_authenticate_user(rule_t rule
)
1179 return rule_check_flags(rule
, RuleFlagAuthenticateUser
);
1183 rule_get_extract_password(rule_t rule
)
1185 return rule_check_flags(rule
, RuleFlagExtractPassword
);
1189 rule_get_password_only(rule_t rule
)
1191 return rule_check_flags(rule
, RuleFlagPasswordOnly
);
1195 rule_get_tries(rule_t rule
)
1197 return auth_items_get_int64(rule
->data
, RULE_TRIES
);
1201 rule_get_comment(rule_t rule
)
1203 return auth_items_get_string(rule
->data
, RULE_COMMENT
);
1207 rule_get_version(rule_t rule
)
1209 return auth_items_get_int64(rule
->data
, RULE_VERSION
);
1212 double rule_get_created(rule_t rule
)
1214 return auth_items_get_double(rule
->data
, RULE_CREATED
);
1217 double rule_get_modified(rule_t rule
)
1219 return auth_items_get_double(rule
->data
, RULE_MODIFIED
);
1222 const char * rule_get_identifier(rule_t rule
)
1224 return auth_items_get_string(rule
->data
, RULE_IDENTIFIER
);
1227 CFDataRef
rule_get_requirement_data(rule_t rule
)
1229 if (!rule
->requirement_data
&& auth_items_exist(rule
->data
, RULE_REQUIREMENT
)) {
1231 const void * data
= auth_items_get_data(rule
->data
, RULE_REQUIREMENT
, &len
);
1232 rule
->requirement_data
= CFDataCreate(kCFAllocatorDefault
, data
, (CFIndex
)len
);
1235 return rule
->requirement_data
;
1238 SecRequirementRef
rule_get_requirement(rule_t rule
)
1240 if (!rule
->requirement
) {
1241 CFDataRef data
= rule_get_requirement_data(rule
);
1243 SecRequirementCreateWithData(data
, kSecCSDefaultFlags
, &rule
->requirement
);
1247 return rule
->requirement
;