1 /* Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. */
4 #include "authutilities.h"
11 #include <Security/AuthorizationDB.h>
12 #include <Security/AuthorizationTagsPriv.h>
18 static void _sql_get_id(rule_t
,authdb_connection_t
);
19 static RuleClass
_get_cf_rule_class(CFTypeRef
);
20 static bool _copy_cf_rule_mechanisms(rule_t
,CFTypeRef
,authdb_connection_t
);
21 static bool _copy_cf_rule_delegations(rule_t
, CFTypeRef
,authdb_connection_t
);
23 #define kMaximumAuthorizationTries 10000
26 #define RULE_NAME "name"
27 #define RULE_TYPE "type"
28 #define RULE_CLASS "class"
29 #define RULE_GROUP "group"
30 #define RULE_KOFN "kofn"
31 #define RULE_TIMEOUT "timeout"
32 #define RULE_FLAGS "flags"
33 #define RULE_TRIES "tries"
34 #define RULE_COMMENT "comment"
35 #define RULE_VERSION "version"
36 #define RULE_CREATED "created"
37 #define RULE_MODIFIED "modified"
38 #define RULE_IDENTIFIER "identifier"
39 #define RULE_REQUIREMENT "requirement"
40 #define RULE_HASH "hash"
43 __AUTH_BASE_STRUCT_HEADER__
;
46 CFMutableArrayRef mechanisms
;
47 CFMutableArrayRef delegations
;
49 CFMutableDictionaryRef loc_prompts
;
50 CFMutableDictionaryRef loc_buttons
;
52 CFDataRef requirement_data
;
53 SecRequirementRef requirement
;
57 _rule_finalize(CFTypeRef value
)
59 rule_t rule
= (rule_t
)value
;
60 CFReleaseNull(rule
->data
);
61 CFReleaseNull(rule
->mechanisms
);
62 CFReleaseNull(rule
->delegations
);
63 CFReleaseNull(rule
->loc_prompts
);
64 CFReleaseNull(rule
->loc_buttons
);
65 CFReleaseNull(rule
->requirement_data
);
66 CFReleaseNull(rule
->requirement
);
70 _rule_equal(CFTypeRef value1
, CFTypeRef value2
)
72 rule_t rule1
= (rule_t
)value1
;
73 rule_t rule2
= (rule_t
)value2
;
75 return strcasecmp(rule_get_name(rule1
), rule_get_name(rule2
)) == 0;
79 _rule_copy_description(CFTypeRef value
)
81 rule_t rule
= (rule_t
)value
;
82 CFMutableStringRef str
= CFStringCreateMutable(kCFAllocatorDefault
, 0);
83 CFStringRef tmp
= CFCopyDescription(rule
->data
);
84 CFStringAppend(str
, tmp
);
86 tmp
= CFCopyDescription(rule
->mechanisms
);
87 CFStringAppend(str
, tmp
);
89 tmp
= CFCopyDescription(rule
->delegations
);
90 CFStringAppend(str
, tmp
);
96 _rule_hash(CFTypeRef value
)
98 rule_t rule
= (rule_t
)value
;
99 const char * str
= rule_get_name(rule
);
100 return (CFHashCode
)crc64(str
, strlen(str
));
103 AUTH_TYPE_INSTANCE(rule
,
106 .finalize
= _rule_finalize
,
107 .equal
= _rule_equal
,
109 .copyFormattingDesc
= NULL
,
110 .copyDebugDesc
= _rule_copy_description
113 static CFTypeID
rule_get_type_id() {
114 static CFTypeID type_id
= _kCFRuntimeNotATypeID
;
115 static dispatch_once_t onceToken
;
117 dispatch_once(&onceToken
, ^{
118 type_id
= _CFRuntimeRegisterClass(&_auth_type_rule
);
127 rule_t rule
= (rule_t
)_CFRuntimeCreateInstance(kCFAllocatorDefault
, rule_get_type_id(), AUTH_CLASS_SIZE(rule
), NULL
);
128 require(rule
!= NULL
, done
);
130 rule
->data
= auth_items_create();
131 rule
->delegations
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
132 rule
->mechanisms
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
139 _rule_create_with_sql(auth_items_t sql
)
142 require(sql
!= NULL
, done
);
144 rule
= _rule_create();
145 require(rule
!= NULL
, done
);
147 auth_items_copy(rule
->data
, sql
);
154 rule_create_default()
156 rule_t rule
= _rule_create();
157 require(rule
!= NULL
, done
);
159 auth_items_set_int64(rule
->data
, RULE_TYPE
, RT_RIGHT
);
160 auth_items_set_string(rule
->data
, RULE_NAME
, "(default)");
161 auth_items_set_int64(rule
->data
, RULE_CLASS
, RC_USER
);
162 auth_items_set_string(rule
->data
, RULE_GROUP
, "admin");
163 auth_items_set_int64(rule
->data
, RULE_TIMEOUT
, 300);
164 auth_items_set_int64(rule
->data
, RULE_TRIES
, kMaximumAuthorizationTries
);
165 auth_items_set_int64(rule
->data
, RULE_FLAGS
, RuleFlagShared
| RuleFlagAuthenticateUser
);
167 mechanism_t mech
= mechanism_create_with_string("builtin:authenticate", NULL
);
168 CFArrayAppendValue(rule
->mechanisms
, mech
);
171 mech
= mechanism_create_with_string("builtin:reset-password,privileged", NULL
);
172 CFArrayAppendValue(rule
->mechanisms
, mech
);
175 mech
= mechanism_create_with_string("builtin:authenticate,privileged", NULL
);
176 CFArrayAppendValue(rule
->mechanisms
, mech
);
179 mech
= mechanism_create_with_string("PKINITMechanism:auth,privileged", NULL
);
180 CFArrayAppendValue(rule
->mechanisms
, mech
);
188 rule_create_preauthorization()
190 rule_t rule
= _rule_create();
191 require(rule
!= NULL
, done
);
193 auth_items_set_int64(rule
->data
, RULE_TYPE
, RT_RIGHT
);
194 auth_items_set_string(rule
->data
, RULE_NAME
, "(preauthorization)");
195 auth_items_set_int64(rule
->data
, RULE_CLASS
, RC_USER
);
196 auth_items_set_string(rule
->data
, RULE_GROUP
, "admin");
197 auth_items_set_int64(rule
->data
, RULE_TRIES
, 1);
198 auth_items_set_int64(rule
->data
, RULE_FLAGS
, RuleFlagShared
| RuleFlagAuthenticateUser
| RuleFlagRequireAppleSigned
);
200 mechanism_t mech
= mechanism_create_with_string("builtin:authenticate,privileged", NULL
);
201 CFArrayAppendValue(rule
->mechanisms
, mech
);
209 rule_create_with_string(const char * str
, authdb_connection_t dbconn
)
212 require(str
!= NULL
, done
);
214 rule
= _rule_create();
215 require(rule
!= NULL
, done
);
217 auth_items_set_string(rule
->data
, RULE_NAME
, str
);
220 rule_sql_fetch(rule
, dbconn
);
227 static void _set_data_string(rule_t rule
, const char * key
, CFStringRef str
)
229 char * tmpStr
= _copy_cf_string(str
, NULL
);
232 auth_items_set_string(rule
->data
, key
, tmpStr
);
238 rule_create_with_plist(RuleType type
, CFStringRef name
, CFDictionaryRef plist
, authdb_connection_t dbconn
)
241 require(name
!= NULL
, done
);
242 require(plist
!= NULL
, done
);
244 rule
= _rule_create();
245 require(rule
!= NULL
, done
);
247 _set_data_string(rule
, RULE_NAME
, name
);
248 require_action(rule_get_name(rule
) != NULL
, done
, CFReleaseSafe(rule
));
250 _sql_get_id(rule
, dbconn
);
252 auth_items_set_int64(rule
->data
, RULE_TYPE
, type
);
254 auth_items_set_int64(rule
->data
, RULE_CLASS
, _get_cf_rule_class(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleClass
))));
255 _set_data_string(rule
, RULE_COMMENT
, CFDictionaryGetValue(plist
, CFSTR(kAuthorizationComment
)));
258 CFTypeRef loc_tmp
= CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterDefaultPrompt
));
260 rule
->loc_prompts
= CFDictionaryCreateMutableCopy(kCFAllocatorDefault
, 0, loc_tmp
);
262 loc_tmp
= CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterDefaultButton
));
264 rule
->loc_buttons
= CFDictionaryCreateMutableCopy(kCFAllocatorDefault
, 0, loc_tmp
);
267 auth_items_set_int64(rule
->data
, RULE_VERSION
, _get_cf_int(CFDictionaryGetValue(plist
, CFSTR("version")), 0));
271 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterEntitled
)), false)) {
272 flags
|= RuleFlagEntitled
;
275 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterRequireAppleSigned
)), false)) {
276 flags
|= RuleFlagRequireAppleSigned
;
279 switch (rule_get_class(rule
)) {
281 _set_data_string(rule
, RULE_GROUP
, CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterGroup
)));
282 auth_items_set_int64(rule
->data
, RULE_TIMEOUT
, _get_cf_int(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterCredentialTimeout
)), INT32_MAX
));
283 auth_items_set_int64(rule
->data
, RULE_TRIES
, _get_cf_int(CFDictionaryGetValue(plist
, CFSTR("tries")), kMaximumAuthorizationTries
));
285 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterCredentialShared
)), false)) {
286 flags
|= RuleFlagShared
;
288 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterAllowRoot
)), false)) {
289 flags
|= RuleFlagAllowRoot
;
291 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterCredentialSessionOwner
)), false)) {
292 flags
|= RuleFlagSessionOwner
;
294 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterAuthenticateUser
)), true)) {
295 flags
|= RuleFlagAuthenticateUser
;
297 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterExtractPassword
)), false)) {
298 flags
|= RuleFlagExtractPassword
;
300 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterEntitledAndGroup
)), false)) {
301 flags
|= RuleFlagEntitledAndGroup
;
303 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterVPNEntitledAndGroup
)), false)) {
304 flags
|= RuleFlagVPNEntitledAndGroup
;
306 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterPasswordOnly
)), false)) {
307 flags
|= RuleFlagPasswordOnly
;
310 _copy_cf_rule_mechanisms(rule
, CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterMechanisms
)), dbconn
);
314 auth_items_set_int64(rule
->data
, RULE_KOFN
, _get_cf_int(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterKofN
)), 0));
316 _copy_cf_rule_delegations(rule
, CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRightRule
)), dbconn
);
319 auth_items_set_int64(rule
->data
, RULE_TRIES
, _get_cf_int(CFDictionaryGetValue(plist
, CFSTR("tries")), kMaximumAuthorizationTries
));
320 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterCredentialShared
)), true)) {
321 flags
|= RuleFlagShared
;
323 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterExtractPassword
)), false)) {
324 flags
|= RuleFlagExtractPassword
;
327 _copy_cf_rule_mechanisms(rule
, CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterMechanisms
)), dbconn
);
335 os_log_error(AUTHD_LOG
, "rule: invalid rule class");
339 auth_items_set_int64(rule
->data
, RULE_FLAGS
, flags
);
346 _sql_get_id(rule_t rule
, authdb_connection_t dbconn
)
348 authdb_step(dbconn
, "SELECT id,created,identifier,requirement FROM rules WHERE name = ? LIMIT 1",
349 ^(sqlite3_stmt
*stmt
) {
350 sqlite3_bind_text(stmt
, 1, rule_get_name(rule
), -1, NULL
);
351 }, ^bool(auth_items_t data
) {
352 auth_items_copy(rule
->data
, data
);
358 _copy_cf_rule_delegations(rule_t rule
, CFTypeRef value
, authdb_connection_t dbconn
)
361 char * tmp_str
= NULL
;
362 require(value
!= NULL
, done
);
364 if (CFGetTypeID(value
) == CFStringGetTypeID()) {
365 tmp_str
= _copy_cf_string(value
, NULL
);
366 rule_t delegate
= rule_create_with_string(tmp_str
, dbconn
);
369 CFArrayAppendValue(rule
->delegations
, delegate
);
370 CFReleaseSafe(delegate
);
373 CFIndex count
= CFArrayGetCount(value
);
374 for (CFIndex i
= 0; i
< count
; i
++) {
375 tmp_str
= _copy_cf_string(CFArrayGetValueAtIndex(value
,i
), NULL
);
376 rule_t delegate
= rule_create_with_string(tmp_str
, dbconn
);
379 CFArrayAppendValue(rule
->delegations
, delegate
);
380 CFReleaseSafe(delegate
);
392 _copy_cf_rule_mechanisms(rule_t rule
, CFTypeRef array
, authdb_connection_t dbconn
)
395 require(array
!= NULL
, done
);
396 require(CFGetTypeID(array
) == CFArrayGetTypeID(), done
);
398 CFIndex count
= CFArrayGetCount(array
);
399 for (CFIndex i
= 0; i
< count
; i
++) {
400 mechanism_t mech
= NULL
;
401 char * string
= _copy_cf_string(CFArrayGetValueAtIndex(array
, i
), NULL
);
406 mech
= mechanism_create_with_string(string
, dbconn
);
408 CFArrayAppendValue(rule
->mechanisms
, mech
);
421 _get_cf_rule_class(CFTypeRef str
)
423 RuleClass rc
= RC_RULE
;
424 require(str
!= NULL
, done
);
425 require(CFGetTypeID(str
) == CFStringGetTypeID(), done
);
427 if (CFEqual(str
, CFSTR(kAuthorizationRuleClassUser
)))
430 if (CFEqual(str
, CFSTR(kAuthorizationRightRule
)))
433 if (CFEqual(str
, CFSTR(kAuthorizationRuleClassMechanisms
)))
436 if (CFEqual(str
, CFSTR(kAuthorizationRuleClassDeny
)))
439 if (CFEqual(str
, CFSTR(kAuthorizationRuleClassAllow
)))
447 _sql_bind(rule_t rule
, sqlite3_stmt
* stmt
)
451 require(stmt
!= NULL
, err
);
454 rc
= sqlite3_bind_text(stmt
, column
++, rule_get_name(rule
), -1, NULL
);
455 require_noerr(rc
, err
);
456 rc
= sqlite3_bind_int(stmt
, column
++, rule_get_type(rule
));
457 require_noerr(rc
, err
);
458 rc
= sqlite3_bind_int(stmt
, column
++, rule_get_class(rule
));
459 require_noerr(rc
, err
);
461 switch (rule_get_class(rule
)) {
463 rc
= sqlite3_bind_text(stmt
, column
++, rule_get_group(rule
), -1, NULL
);
464 require_noerr(rc
, err
);
465 rc
= sqlite3_bind_null(stmt
, column
++); // kofn
466 require_noerr(rc
, err
);
467 rc
= sqlite3_bind_int64(stmt
, column
++, rule_get_timeout(rule
));
468 require_noerr(rc
, err
);
469 rc
= sqlite3_bind_int64(stmt
, column
++, auth_items_get_int64(rule
->data
, RULE_FLAGS
));
470 require_noerr(rc
, err
);
471 rc
= sqlite3_bind_int64(stmt
, column
++, rule_get_tries(rule
));
472 require_noerr(rc
, err
);
475 rc
= sqlite3_bind_null(stmt
, column
++); // group
476 require_noerr(rc
, err
);
477 n
= rule_get_kofn(rule
);
479 rc
= sqlite3_bind_int64(stmt
, column
++, n
);
481 rc
= sqlite3_bind_null(stmt
, column
++);
483 require_noerr(rc
, err
);
484 rc
= sqlite3_bind_null(stmt
, column
++); // timeout
485 require_noerr(rc
, err
);
486 rc
= sqlite3_bind_int64(stmt
, column
++, auth_items_get_int64(rule
->data
, RULE_FLAGS
));
487 require_noerr(rc
, err
);
488 rc
= sqlite3_bind_null(stmt
, column
++); // tries
489 require_noerr(rc
, err
);
492 rc
= sqlite3_bind_null(stmt
, column
++); // group
493 require_noerr(rc
, err
);
494 rc
= sqlite3_bind_null(stmt
, column
++); // kofn
495 require_noerr(rc
, err
);
496 rc
= sqlite3_bind_null(stmt
, column
++); // timeout
497 require_noerr(rc
, err
);
498 rc
= sqlite3_bind_int64(stmt
, column
++, auth_items_get_int64(rule
->data
, RULE_FLAGS
));
499 require_noerr(rc
, err
);
500 rc
= sqlite3_bind_int64(stmt
, column
++, rule_get_tries(rule
));
501 require_noerr(rc
, err
);
505 rc
= sqlite3_bind_null(stmt
, column
++); // group
506 require_noerr(rc
, err
);
507 rc
= sqlite3_bind_null(stmt
, column
++); // kofn
508 require_noerr(rc
, err
);
509 rc
= sqlite3_bind_null(stmt
, column
++); // timeout
510 require_noerr(rc
, err
);
511 rc
= sqlite3_bind_int64(stmt
, column
++, auth_items_get_int64(rule
->data
, RULE_FLAGS
));
512 require_noerr(rc
, err
);
513 rc
= sqlite3_bind_null(stmt
, column
++); // tries
514 require_noerr(rc
, err
);
517 os_log_error(AUTHD_LOG
, "rule: sql bind, invalid rule class");
521 rc
= sqlite3_bind_int64(stmt
, column
++, rule_get_version(rule
)); // version
522 require_noerr(rc
, err
);
523 rc
= sqlite3_bind_double(stmt
, column
++, rule_get_created(rule
)); // created
524 require_noerr(rc
, err
);
525 rc
= sqlite3_bind_double(stmt
, column
++, rule_get_modified(rule
)); // modified
526 require_noerr(rc
, err
);
527 rc
= sqlite3_bind_null(stmt
, column
++); // hash
528 require_noerr(rc
, err
);
529 rc
= sqlite3_bind_text(stmt
, column
++, rule_get_identifier(rule
), -1, NULL
);
530 require_noerr(rc
, err
);
532 CFDataRef data
= rule_get_requirement_data(rule
);
534 rc
= sqlite3_bind_blob(stmt
, column
++, CFDataGetBytePtr(data
), (int32_t)CFDataGetLength(data
), NULL
);
536 rc
= sqlite3_bind_null(stmt
, column
++);
538 require_noerr(rc
, err
);
540 rc
= sqlite3_bind_text(stmt
, column
++, rule_get_comment(rule
), -1, NULL
);
541 require_noerr(rc
, err
);
546 os_log_error(AUTHD_LOG
, "rule: sql bind, error %i", rc
);
551 _get_sql_mechanisms(rule_t rule
, authdb_connection_t dbconn
)
553 CFArrayRemoveAllValues(rule
->mechanisms
);
555 authdb_step(dbconn
, "SELECT mechanisms.* " \
557 "JOIN mechanisms_map ON mechanisms.id = mechanisms_map.m_id " \
558 "WHERE mechanisms_map.r_id = ? ORDER BY mechanisms_map.ord ASC",
559 ^(sqlite3_stmt
*stmt
) {
560 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
561 }, ^bool(auth_items_t data
) {
562 mechanism_t mechanism
= mechanism_create_with_sql(data
);
563 CFArrayAppendValue(rule
->mechanisms
, mechanism
);
564 CFReleaseSafe(mechanism
);
570 _get_sql_delegates(rule_t rule
, authdb_connection_t dbconn
)
572 CFArrayRemoveAllValues(rule
->delegations
);
574 authdb_step(dbconn
, "SELECT rules.* " \
576 "JOIN delegates_map ON rules.id = delegates_map.d_id " \
577 "WHERE delegates_map.r_id = ? ORDER BY delegates_map.ord ASC",
578 ^(sqlite3_stmt
*stmt
) {
579 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
580 }, ^bool(auth_items_t data
) {
581 rule_t delegate
= _rule_create_with_sql(data
);
583 _get_sql_mechanisms(delegate
, dbconn
);
585 if (rule_get_class(rule
) == RC_RULE
) {
586 _get_sql_delegates(delegate
, dbconn
);
589 CFArrayAppendValue(rule
->delegations
, delegate
);
590 CFReleaseSafe(delegate
);
597 rule_sql_fetch(rule_t rule
, authdb_connection_t dbconn
)
599 __block
bool result
= false;
601 authdb_step(dbconn
, "SELECT * FROM rules WHERE name = ? LIMIT 1",
602 ^(sqlite3_stmt
*stmt
) {
603 sqlite3_bind_text(stmt
, 1, rule_get_name(rule
), -1, NULL
);
604 }, ^bool(auth_items_t data
) {
606 auth_items_copy(rule
->data
, data
);
610 if (rule_get_id(rule
) != 0) {
611 _get_sql_mechanisms(rule
,dbconn
);
613 if (rule_get_class(rule
) == RC_RULE
) {
614 _get_sql_delegates(rule
, dbconn
);
622 _sql_update(rule_t rule
, authdb_connection_t dbconn
)
626 result
= authdb_step(dbconn
, "UPDATE rules " \
627 "SET name=?,type=?,class=?,'group'=?,kofn=?,timeout=?,flags=?,tries=?,version=?,created=?,modified=?,hash=?,identifier=?,requirement=?,comment=? " \
629 ^(sqlite3_stmt
*stmt
) {
630 _sql_bind(rule
, stmt
);
631 sqlite3_bind_int64(stmt
, sqlite3_bind_parameter_count(stmt
), rule_get_id(rule
));
637 _sql_insert(rule_t rule
, authdb_connection_t dbconn
)
641 result
= authdb_step(dbconn
, "INSERT INTO rules VALUES (NULL,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
642 ^(sqlite3_stmt
*stmt
) {
643 _sql_bind(rule
, stmt
);
649 _sql_commit_mechanisms_map(rule_t rule
, authdb_connection_t dbconn
)
653 result
= authdb_step(dbconn
, "DELETE FROM mechanisms_map WHERE r_id = ?", ^(sqlite3_stmt
*stmt
) {
654 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
656 require(result
== true, done
);
658 CFIndex count
= CFArrayGetCount(rule
->mechanisms
);
659 for(CFIndex i
= 0; i
< count
; i
++) {
660 mechanism_t mech
= (mechanism_t
)CFArrayGetValueAtIndex(rule
->mechanisms
, i
);
661 result
= authdb_step(dbconn
, "INSERT INTO mechanisms_map VALUES (?,?,?)", ^(sqlite3_stmt
*stmt
) {
662 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
663 sqlite3_bind_int64(stmt
, 2, mechanism_get_id(mech
));
664 sqlite3_bind_int64(stmt
, 3, i
);
666 require(result
== true, done
);
674 _sql_commit_delegates_map(rule_t rule
, authdb_connection_t dbconn
)
678 result
= authdb_step(dbconn
, "DELETE FROM delegates_map WHERE r_id = ?", ^(sqlite3_stmt
*stmt
) {
679 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
681 require(result
== true, done
);
683 CFIndex count
= CFArrayGetCount(rule
->delegations
);
684 for(CFIndex i
= 0; i
< count
; i
++) {
685 rule_t delegate
= (rule_t
)CFArrayGetValueAtIndex(rule
->delegations
, i
);
686 result
= authdb_step(dbconn
, "INSERT INTO delegates_map VALUES (?,?,?)", ^(sqlite3_stmt
*stmt
) {
687 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
688 sqlite3_bind_int64(stmt
, 2, rule_get_id(delegate
));
689 sqlite3_bind_int64(stmt
, 3, i
);
691 require(result
== true, done
);
699 _sql_commit_localization(rule_t rule
, authdb_connection_t dbconn
)
702 authdb_step(dbconn
, "DELETE FROM prompts WHERE r_id = ?", ^(sqlite3_stmt
*stmt
) {
703 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
706 authdb_step(dbconn
, "DELETE FROM buttons WHERE r_id = ?", ^(sqlite3_stmt
*stmt
) {
707 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
710 if (rule
->loc_prompts
) {
711 _cf_dictionary_iterate(rule
->loc_prompts
, ^bool(CFTypeRef key
, CFTypeRef value
) {
712 char * lang
= _copy_cf_string(key
, NULL
);
713 char * str
= _copy_cf_string(value
, NULL
);
715 authdb_step(dbconn
, "INSERT INTO prompts VALUES (?,?,?)", ^(sqlite3_stmt
*stmt
) {
716 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
717 sqlite3_bind_text(stmt
, 2, lang
, -1, NULL
);
718 sqlite3_bind_text(stmt
, 3, str
, -1, NULL
);
728 if (rule
->loc_buttons
) {
729 _cf_dictionary_iterate(rule
->loc_buttons
, ^bool(CFTypeRef key
, CFTypeRef value
) {
730 char * lang
= _copy_cf_string(key
, NULL
);
731 char * str
= _copy_cf_string(value
, NULL
);
733 authdb_step(dbconn
, "INSERT INTO buttons VALUES (?,?,?)", ^(sqlite3_stmt
*stmt
) {
734 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
735 sqlite3_bind_text(stmt
, 2, lang
, -1, NULL
);
736 sqlite3_bind_text(stmt
, 3, str
, -1, NULL
);
748 rule_sql_commit(rule_t rule
, authdb_connection_t dbconn
, CFAbsoluteTime modified
, process_t proc
)
751 __block
bool insert
= false;
752 // type and class required else rule is name only?
753 RuleClass rule_class
= rule_get_class(rule
);
754 require(rule_get_type(rule
) != 0, done
);
755 require(rule_class
!= 0, done
);
757 CFIndex mechCount
= 0;
758 if (rule_class
== RC_USER
|| rule_class
== RC_MECHANISM
) {
759 // Validate mechanisms
760 mechCount
= CFArrayGetCount(rule
->mechanisms
);
761 for (CFIndex i
= 0; i
< mechCount
; i
++) {
762 mechanism_t mech
= (mechanism_t
)CFArrayGetValueAtIndex(rule
->mechanisms
, i
);
763 if (mechanism_get_id(mech
) == 0) {
764 if (!mechanism_sql_fetch(mech
, dbconn
)) {
765 mechanism_sql_commit(mech
, dbconn
);
766 mechanism_sql_fetch(mech
, dbconn
);
769 if (!mechanism_exists(mech
)) {
770 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
));
772 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
)));
776 CFIndex delegateCount
= 0;
777 if (rule_class
== RC_RULE
) {
778 // Validate delegates
779 delegateCount
= CFArrayGetCount(rule
->delegations
);
780 for (CFIndex i
= 0; i
< delegateCount
; i
++) {
781 rule_t delegate
= (rule_t
)CFArrayGetValueAtIndex(rule
->delegations
, i
);
782 if (rule_get_id(delegate
) == 0) {
783 rule_sql_fetch(delegate
, dbconn
);
785 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
)));
789 auth_items_set_double(rule
->data
, RULE_MODIFIED
, modified
);
791 result
= authdb_transaction(dbconn
, AuthDBTransactionNormal
, ^bool{
794 if (rule_get_id(rule
)) {
795 update
= _sql_update(rule
, dbconn
);
799 const char * ident
= process_get_identifier(proc
);
801 auth_items_set_string(rule
->data
, RULE_IDENTIFIER
, ident
);
803 CFDataRef req
= process_get_requirement_data(proc
);
805 auth_items_set_data(rule
->data
, RULE_REQUIREMENT
, CFDataGetBytePtr(req
), (size_t)CFDataGetLength(req
));
808 auth_items_set_double(rule
->data
, RULE_CREATED
, modified
);
809 update
= _sql_insert(rule
, dbconn
);
810 _sql_get_id(rule
, dbconn
);
813 _sql_commit_localization(rule
, dbconn
);
816 update
= _sql_commit_mechanisms_map(rule
, dbconn
);
820 update
= _sql_commit_delegates_map(rule
,dbconn
);
829 os_log_debug(AUTHD_LOG
, "rule: commit, failed for %{public}s (%llu)", rule_get_name(rule
), rule_get_id(rule
));
831 rule_log_manipulation(dbconn
, rule
, insert
? rule_insert
: rule_update
, proc
);
837 rule_sql_remove(rule_t rule
, authdb_connection_t dbconn
, process_t proc
)
840 int64_t id
= rule_get_id(rule
);
843 rule_sql_fetch(rule
, dbconn
);
844 id
= rule_get_id(rule
);
845 require(id
!= 0, done
);
848 result
= authdb_step(dbconn
, "DELETE FROM rules WHERE id = ?",
849 ^(sqlite3_stmt
*stmt
) {
850 sqlite3_bind_int64(stmt
, 1, id
);
854 rule_log_manipulation(dbconn
, rule
, rule_delete
, proc
);
861 CFMutableDictionaryRef
862 rule_copy_to_cfobject(rule_t rule
, authdb_connection_t dbconn
) {
863 CFMutableDictionaryRef dict
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
865 CFTypeRef tmp
= NULL
;
866 CFMutableArrayRef array
= NULL
;
872 const char * comment
= rule_get_comment(rule
);
874 tmp
= CFStringCreateWithCString(kCFAllocatorDefault
, comment
, kCFStringEncodingUTF8
);
875 CFDictionarySetValue(dict
, CFSTR(kAuthorizationComment
), tmp
);
879 n
= rule_get_version(rule
);
880 tmp
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt64Type
, &n
);
881 CFDictionarySetValue(dict
, CFSTR(RULE_VERSION
), tmp
);
884 d
= rule_get_created(rule
);
885 tmp
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberFloat64Type
, &d
);
886 CFDictionarySetValue(dict
, CFSTR(RULE_CREATED
), tmp
);
889 d
= rule_get_modified(rule
);
890 tmp
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberFloat64Type
, &d
);
891 CFDictionarySetValue(dict
, CFSTR(RULE_MODIFIED
), tmp
);
894 const char * identifier
= rule_get_identifier(rule
);
896 tmp
= CFStringCreateWithCString(kCFAllocatorDefault
, identifier
, kCFStringEncodingUTF8
);
897 CFDictionarySetValue(dict
, CFSTR(RULE_IDENTIFIER
), tmp
);
901 SecRequirementRef req
= rule_get_requirement(rule
);
903 CFStringRef reqStr
= NULL
;
904 SecRequirementCopyString(req
, kSecCSDefaultFlags
, &reqStr
);
906 CFDictionarySetValue(dict
, CFSTR(RULE_REQUIREMENT
), reqStr
);
907 CFReleaseSafe(reqStr
);
911 if (rule_check_flags(rule
, RuleFlagEntitled
)) {
912 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterEntitled
), kCFBooleanTrue
);
915 if (rule_check_flags(rule
, RuleFlagRequireAppleSigned
)) {
916 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterRequireAppleSigned
), kCFBooleanTrue
);
919 if (rule_get_type(rule
) == RT_RIGHT
) {
920 CFMutableDictionaryRef prompts
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
921 authdb_step(dbconn
, "SELECT * FROM prompts WHERE r_id = ?", ^(sqlite3_stmt
*stmt
) {
922 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
923 }, ^bool(auth_items_t data
) {
924 CFStringRef key
= CFStringCreateWithCString(kCFAllocatorDefault
, auth_items_get_string(data
, "lang"), kCFStringEncodingUTF8
);
925 CFStringRef value
= CFStringCreateWithCString(kCFAllocatorDefault
, auth_items_get_string(data
, "value"), kCFStringEncodingUTF8
);
926 CFDictionaryAddValue(prompts
, key
, value
);
928 CFReleaseSafe(value
);
932 if (CFDictionaryGetCount(prompts
)) {
933 CFDictionaryAddValue(dict
, CFSTR(kAuthorizationRuleParameterDefaultPrompt
), prompts
);
935 CFReleaseSafe(prompts
);
937 CFMutableDictionaryRef buttons
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
938 authdb_step(dbconn
, "SELECT * FROM buttons WHERE r_id = ?", ^(sqlite3_stmt
*stmt
) {
939 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
940 }, ^bool(auth_items_t data
) {
941 CFStringRef key
= CFStringCreateWithCString(kCFAllocatorDefault
, auth_items_get_string(data
, "lang"), kCFStringEncodingUTF8
);
942 CFStringRef value
= CFStringCreateWithCString(kCFAllocatorDefault
, auth_items_get_string(data
, "value"), kCFStringEncodingUTF8
);
943 CFDictionaryAddValue(buttons
, key
, value
);
945 CFReleaseSafe(value
);
949 if (CFDictionaryGetCount(buttons
)) {
950 CFDictionaryAddValue(dict
, CFSTR(kAuthorizationRuleParameterDefaultButton
), buttons
);
952 CFReleaseSafe(buttons
);
955 switch (rule_get_class(rule
)) {
957 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleClass
), CFSTR(kAuthorizationRuleClassUser
));
959 const char * group
= rule_get_group(rule
);
961 tmp
= CFStringCreateWithCString(kCFAllocatorDefault
, group
, kCFStringEncodingUTF8
);
962 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterGroup
), tmp
);
966 n
= rule_get_timeout(rule
);
967 tmp
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt64Type
, &n
);
968 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterCredentialTimeout
), tmp
);
971 n
= rule_get_tries(rule
);
972 tmp
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt64Type
, &n
);
973 CFDictionarySetValue(dict
, CFSTR("tries"), tmp
);
976 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterCredentialShared
), rule_get_shared(rule
) ? kCFBooleanTrue
: kCFBooleanFalse
);
977 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterAllowRoot
), rule_get_allow_root(rule
) ? kCFBooleanTrue
: kCFBooleanFalse
);
978 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterCredentialSessionOwner
), rule_get_session_owner(rule
) ? kCFBooleanTrue
: kCFBooleanFalse
);
979 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterAuthenticateUser
), rule_get_authenticate_user(rule
) ? kCFBooleanTrue
: kCFBooleanFalse
);
980 if (rule_check_flags(rule
, RuleFlagEntitledAndGroup
)) {
981 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterEntitledAndGroup
), kCFBooleanTrue
);
983 if (rule_check_flags(rule
, RuleFlagVPNEntitledAndGroup
)) {
984 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterVPNEntitledAndGroup
), kCFBooleanTrue
);
986 if (rule_get_extract_password(rule
)) {
987 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterExtractPassword
), kCFBooleanTrue
);
989 if (rule_get_password_only(rule
)) {
990 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterPasswordOnly
), kCFBooleanTrue
);
993 count
= CFArrayGetCount(rule
->mechanisms
);
995 array
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
996 for (i
= 0; i
< count
; i
++) {
997 mechanism_t mech
= (mechanism_t
)CFArrayGetValueAtIndex(rule
->mechanisms
, i
);
998 tmp
= CFStringCreateWithCString(kCFAllocatorDefault
, mechanism_get_string(mech
), kCFStringEncodingUTF8
);
999 CFArrayAppendValue(array
, tmp
);
1002 CFDictionaryAddValue(dict
, CFSTR(kAuthorizationRuleParameterMechanisms
), array
);
1007 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleClass
), CFSTR(kAuthorizationRightRule
));
1008 int64_t kofn
= rule_get_kofn(rule
);
1010 tmp
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt64Type
, &kofn
);
1011 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterKofN
), tmp
);
1015 count
= CFArrayGetCount(rule
->delegations
);
1017 array
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
1018 for (i
= 0; i
< count
; i
++) {
1019 rule_t delegate
= (rule_t
)CFArrayGetValueAtIndex(rule
->delegations
, i
);
1020 tmp
= CFStringCreateWithCString(kCFAllocatorDefault
, rule_get_name(delegate
), kCFStringEncodingUTF8
);
1021 CFArrayAppendValue(array
, tmp
);
1024 CFDictionaryAddValue(dict
, CFSTR(kAuthorizationRightRule
), array
);
1029 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleClass
), CFSTR(kAuthorizationRuleClassMechanisms
));
1031 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterCredentialShared
), rule_get_shared(rule
) ? kCFBooleanTrue
: kCFBooleanFalse
);
1032 if (rule_get_extract_password(rule
)) {
1033 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterExtractPassword
), kCFBooleanTrue
);
1036 n
= rule_get_tries(rule
);
1037 tmp
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt64Type
, &n
);
1038 CFDictionarySetValue(dict
, CFSTR("tries"), tmp
);
1041 count
= CFArrayGetCount(rule
->mechanisms
);
1043 array
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
1044 for (i
= 0; i
< count
; i
++) {
1045 mechanism_t mech
= (mechanism_t
)CFArrayGetValueAtIndex(rule
->mechanisms
, i
);
1046 tmp
= CFStringCreateWithCString(kCFAllocatorDefault
, mechanism_get_string(mech
), kCFStringEncodingUTF8
);
1047 CFArrayAppendValue(array
, tmp
);
1050 CFDictionaryAddValue(dict
, CFSTR(kAuthorizationRuleParameterMechanisms
), array
);
1055 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleClass
), CFSTR(kAuthorizationRuleClassDeny
));
1058 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleClass
), CFSTR(kAuthorizationRuleClassAllow
));
1069 rule_get_mechanisms(rule_t rule
)
1071 return rule
->mechanisms
;
1075 rule_get_mechanisms_count(rule_t rule
)
1077 return (size_t)CFArrayGetCount(rule
->mechanisms
);
1081 rule_mechanisms_iterator(rule_t rule
, mechanism_iterator_t iter
)
1083 bool result
= false;
1085 CFIndex count
= CFArrayGetCount(rule
->mechanisms
);
1086 for (CFIndex i
= 0; i
< count
; i
++) {
1087 mechanism_t mech
= (mechanism_t
)CFArrayGetValueAtIndex(rule
->mechanisms
, i
);
1088 result
= iter(mech
);
1098 rule_get_delegates_count(rule_t rule
)
1100 return (size_t)CFArrayGetCount(rule
->delegations
);
1104 rule_delegates_iterator(rule_t rule
, delegate_iterator_t iter
)
1106 bool result
= false;
1108 CFIndex count
= CFArrayGetCount(rule
->delegations
);
1109 for (CFIndex i
= 0; i
< count
; i
++) {
1110 rule_t tmp
= (rule_t
)CFArrayGetValueAtIndex(rule
->delegations
, i
);
1121 rule_get_id(rule_t rule
)
1123 return auth_items_get_int64(rule
->data
, RULE_ID
);
1127 rule_get_name(rule_t rule
)
1129 return auth_items_get_string(rule
->data
, RULE_NAME
);
1133 rule_get_type(rule_t rule
)
1135 return (RuleType
)auth_items_get_int64(rule
->data
, RULE_TYPE
);
1139 rule_get_class(rule_t rule
)
1141 return (RuleClass
)auth_items_get_int64(rule
->data
, RULE_CLASS
);
1145 rule_get_group(rule_t rule
)
1147 return auth_items_get_string(rule
->data
, RULE_GROUP
);
1151 rule_get_kofn(rule_t rule
)
1153 return auth_items_get_int64(rule
->data
, RULE_KOFN
);
1157 rule_get_timeout(rule_t rule
)
1159 return auth_items_get_int64(rule
->data
, RULE_TIMEOUT
);
1163 rule_check_flags(rule_t rule
, RuleFlags flags
)
1165 return (auth_items_get_int64(rule
->data
, RULE_FLAGS
) & flags
) != 0;
1169 rule_get_shared(rule_t rule
)
1171 return rule_check_flags(rule
, RuleFlagShared
);
1175 rule_get_allow_root(rule_t rule
)
1177 return rule_check_flags(rule
, RuleFlagAllowRoot
);
1181 rule_get_session_owner(rule_t rule
)
1183 return rule_check_flags(rule
, RuleFlagSessionOwner
);
1187 rule_get_authenticate_user(rule_t rule
)
1189 return rule_check_flags(rule
, RuleFlagAuthenticateUser
);
1193 rule_get_extract_password(rule_t rule
)
1195 return rule_check_flags(rule
, RuleFlagExtractPassword
);
1199 rule_get_password_only(rule_t rule
)
1201 return rule_check_flags(rule
, RuleFlagPasswordOnly
);
1205 rule_get_tries(rule_t rule
)
1207 return auth_items_get_int64(rule
->data
, RULE_TRIES
);
1211 rule_get_comment(rule_t rule
)
1213 return auth_items_get_string(rule
->data
, RULE_COMMENT
);
1217 rule_get_version(rule_t rule
)
1219 return auth_items_get_int64(rule
->data
, RULE_VERSION
);
1222 double rule_get_created(rule_t rule
)
1224 return auth_items_get_double(rule
->data
, RULE_CREATED
);
1227 double rule_get_modified(rule_t rule
)
1229 return auth_items_get_double(rule
->data
, RULE_MODIFIED
);
1232 const char * rule_get_identifier(rule_t rule
)
1234 return auth_items_get_string(rule
->data
, RULE_IDENTIFIER
);
1237 CFDataRef
rule_get_requirement_data(rule_t rule
)
1239 if (!rule
->requirement_data
&& auth_items_exist(rule
->data
, RULE_REQUIREMENT
)) {
1241 const void * data
= auth_items_get_data(rule
->data
, RULE_REQUIREMENT
, &len
);
1242 rule
->requirement_data
= CFDataCreate(kCFAllocatorDefault
, data
, (CFIndex
)len
);
1245 return rule
->requirement_data
;
1248 SecRequirementRef
rule_get_requirement(rule_t rule
)
1250 if (!rule
->requirement
) {
1251 CFDataRef data
= rule_get_requirement_data(rule
);
1253 SecRequirementCreateWithData(data
, kSecCSDefaultFlags
, &rule
->requirement
);
1257 return rule
->requirement
;
1261 rule_log_manipulation(authdb_connection_t dbconn
, rule_t rule
, RuleOperation operation
, process_t source
)
1263 authdb_step(dbconn
, "INSERT INTO rules_history (rule, source, operation, version) VALUES (?,?,?,?)", ^(sqlite3_stmt
*stmt
) {
1264 char pathbuf
[PROC_PIDPATHINFO_MAXSIZE
];
1266 pid_t pid
= process_get_pid(source
);
1267 if (!proc_pidpath(pid
, pathbuf
, sizeof(pathbuf
))) {
1268 os_log_error(AUTHD_LOG
, "Failed to get path for pid %d", pid
);
1269 snprintf(pathbuf
, sizeof(pathbuf
), "Unknown process with PID %d", pid
);
1272 strncpy(pathbuf
, "authd", sizeof(pathbuf
));
1275 sqlite3_bind_text(stmt
, 1, rule_get_name(rule
), -1, NULL
);
1276 sqlite3_bind_text(stmt
, 2, pathbuf
, -1, NULL
);
1277 sqlite3_bind_int(stmt
, 3, operation
);
1278 sqlite3_bind_int64(stmt
, 4, rule_get_version(rule
));