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
);
184 rule_create_with_string(const char * str
, authdb_connection_t dbconn
)
187 require(str
!= NULL
, done
);
189 rule
= _rule_create();
190 require(rule
!= NULL
, done
);
192 auth_items_set_string(rule
->data
, RULE_NAME
, str
);
195 rule_sql_fetch(rule
, dbconn
);
202 static void _set_data_string(rule_t rule
, const char * key
, CFStringRef str
)
204 char * tmpStr
= _copy_cf_string(str
, NULL
);
207 auth_items_set_string(rule
->data
, key
, tmpStr
);
213 rule_create_with_plist(RuleType type
, CFStringRef name
, CFDictionaryRef plist
, authdb_connection_t dbconn
)
216 require(name
!= NULL
, done
);
217 require(plist
!= NULL
, done
);
219 rule
= _rule_create();
220 require(rule
!= NULL
, done
);
222 _set_data_string(rule
, RULE_NAME
, name
);
223 require_action(rule_get_name(rule
) != NULL
, done
, CFReleaseSafe(rule
));
225 _sql_get_id(rule
, dbconn
);
227 auth_items_set_int64(rule
->data
, RULE_TYPE
, type
);
229 auth_items_set_int64(rule
->data
, RULE_CLASS
, _get_cf_rule_class(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleClass
))));
230 _set_data_string(rule
, RULE_COMMENT
, CFDictionaryGetValue(plist
, CFSTR(kAuthorizationComment
)));
233 CFTypeRef loc_tmp
= CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterDefaultPrompt
));
235 rule
->loc_prompts
= CFDictionaryCreateMutableCopy(kCFAllocatorDefault
, 0, loc_tmp
);
237 loc_tmp
= CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterDefaultButton
));
239 rule
->loc_buttons
= CFDictionaryCreateMutableCopy(kCFAllocatorDefault
, 0, loc_tmp
);
242 auth_items_set_int64(rule
->data
, RULE_VERSION
, _get_cf_int(CFDictionaryGetValue(plist
, CFSTR("version")), 0));
246 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterEntitled
)), false)) {
247 flags
|= RuleFlagEntitled
;
250 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterRequireAppleSigned
)), false)) {
251 flags
|= RuleFlagRequireAppleSigned
;
254 switch (rule_get_class(rule
)) {
256 _set_data_string(rule
, RULE_GROUP
, CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterGroup
)));
257 auth_items_set_int64(rule
->data
, RULE_TIMEOUT
, _get_cf_int(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterCredentialTimeout
)), INT32_MAX
));
258 auth_items_set_int64(rule
->data
, RULE_TRIES
, _get_cf_int(CFDictionaryGetValue(plist
, CFSTR("tries")), kMaximumAuthorizationTries
));
260 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterCredentialShared
)), false)) {
261 flags
|= RuleFlagShared
;
263 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterAllowRoot
)), false)) {
264 flags
|= RuleFlagAllowRoot
;
266 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterCredentialSessionOwner
)), false)) {
267 flags
|= RuleFlagSessionOwner
;
269 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterAuthenticateUser
)), true)) {
270 flags
|= RuleFlagAuthenticateUser
;
272 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterExtractPassword
)), false)) {
273 flags
|= RuleFlagExtractPassword
;
275 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterEntitledAndGroup
)), false)) {
276 flags
|= RuleFlagEntitledAndGroup
;
278 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterVPNEntitledAndGroup
)), false)) {
279 flags
|= RuleFlagVPNEntitledAndGroup
;
281 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterPasswordOnly
)), false)) {
282 flags
|= RuleFlagPasswordOnly
;
285 _copy_cf_rule_mechanisms(rule
, CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterMechanisms
)), dbconn
);
289 auth_items_set_int64(rule
->data
, RULE_KOFN
, _get_cf_int(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterKofN
)), 0));
291 _copy_cf_rule_delegations(rule
, CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRightRule
)), dbconn
);
294 auth_items_set_int64(rule
->data
, RULE_TRIES
, _get_cf_int(CFDictionaryGetValue(plist
, CFSTR("tries")), kMaximumAuthorizationTries
));
295 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterCredentialShared
)), true)) {
296 flags
|= RuleFlagShared
;
298 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterExtractPassword
)), false)) {
299 flags
|= RuleFlagExtractPassword
;
302 _copy_cf_rule_mechanisms(rule
, CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterMechanisms
)), dbconn
);
310 os_log_error(AUTHD_LOG
, "rule: invalid rule class");
314 auth_items_set_int64(rule
->data
, RULE_FLAGS
, flags
);
321 _sql_get_id(rule_t rule
, authdb_connection_t dbconn
)
323 authdb_step(dbconn
, "SELECT id,created,identifier,requirement FROM rules WHERE name = ? LIMIT 1",
324 ^(sqlite3_stmt
*stmt
) {
325 sqlite3_bind_text(stmt
, 1, rule_get_name(rule
), -1, NULL
);
326 }, ^bool(auth_items_t data
) {
327 auth_items_copy(rule
->data
, data
);
333 _copy_cf_rule_delegations(rule_t rule
, CFTypeRef value
, authdb_connection_t dbconn
)
336 char * tmp_str
= NULL
;
337 require(value
!= NULL
, done
);
339 if (CFGetTypeID(value
) == CFStringGetTypeID()) {
340 tmp_str
= _copy_cf_string(value
, NULL
);
341 rule_t delegate
= rule_create_with_string(tmp_str
, dbconn
);
344 CFArrayAppendValue(rule
->delegations
, delegate
);
345 CFReleaseSafe(delegate
);
348 CFIndex count
= CFArrayGetCount(value
);
349 for (CFIndex i
= 0; i
< count
; i
++) {
350 tmp_str
= _copy_cf_string(CFArrayGetValueAtIndex(value
,i
), NULL
);
351 rule_t delegate
= rule_create_with_string(tmp_str
, dbconn
);
354 CFArrayAppendValue(rule
->delegations
, delegate
);
355 CFReleaseSafe(delegate
);
367 _copy_cf_rule_mechanisms(rule_t rule
, CFTypeRef array
, authdb_connection_t dbconn
)
370 require(array
!= NULL
, done
);
371 require(CFGetTypeID(array
) == CFArrayGetTypeID(), done
);
373 CFIndex count
= CFArrayGetCount(array
);
374 for (CFIndex i
= 0; i
< count
; i
++) {
375 mechanism_t mech
= NULL
;
376 char * string
= _copy_cf_string(CFArrayGetValueAtIndex(array
, i
), NULL
);
381 mech
= mechanism_create_with_string(string
, dbconn
);
383 CFArrayAppendValue(rule
->mechanisms
, mech
);
396 _get_cf_rule_class(CFTypeRef str
)
398 RuleClass rc
= RC_RULE
;
399 require(str
!= NULL
, done
);
400 require(CFGetTypeID(str
) == CFStringGetTypeID(), done
);
402 if (CFEqual(str
, CFSTR(kAuthorizationRuleClassUser
)))
405 if (CFEqual(str
, CFSTR(kAuthorizationRightRule
)))
408 if (CFEqual(str
, CFSTR(kAuthorizationRuleClassMechanisms
)))
411 if (CFEqual(str
, CFSTR(kAuthorizationRuleClassDeny
)))
414 if (CFEqual(str
, CFSTR(kAuthorizationRuleClassAllow
)))
422 _sql_bind(rule_t rule
, sqlite3_stmt
* stmt
)
426 require(stmt
!= NULL
, err
);
429 rc
= sqlite3_bind_text(stmt
, column
++, rule_get_name(rule
), -1, NULL
);
430 require_noerr(rc
, err
);
431 rc
= sqlite3_bind_int(stmt
, column
++, rule_get_type(rule
));
432 require_noerr(rc
, err
);
433 rc
= sqlite3_bind_int(stmt
, column
++, rule_get_class(rule
));
434 require_noerr(rc
, err
);
436 switch (rule_get_class(rule
)) {
438 rc
= sqlite3_bind_text(stmt
, column
++, rule_get_group(rule
), -1, NULL
);
439 require_noerr(rc
, err
);
440 rc
= sqlite3_bind_null(stmt
, column
++); // kofn
441 require_noerr(rc
, err
);
442 rc
= sqlite3_bind_int64(stmt
, column
++, rule_get_timeout(rule
));
443 require_noerr(rc
, err
);
444 rc
= sqlite3_bind_int64(stmt
, column
++, auth_items_get_int64(rule
->data
, RULE_FLAGS
));
445 require_noerr(rc
, err
);
446 rc
= sqlite3_bind_int64(stmt
, column
++, rule_get_tries(rule
));
447 require_noerr(rc
, err
);
450 rc
= sqlite3_bind_null(stmt
, column
++); // group
451 require_noerr(rc
, err
);
452 n
= rule_get_kofn(rule
);
454 rc
= sqlite3_bind_int64(stmt
, column
++, n
);
456 rc
= sqlite3_bind_null(stmt
, column
++);
458 require_noerr(rc
, err
);
459 rc
= sqlite3_bind_null(stmt
, column
++); // timeout
460 require_noerr(rc
, err
);
461 rc
= sqlite3_bind_int64(stmt
, column
++, auth_items_get_int64(rule
->data
, RULE_FLAGS
));
462 require_noerr(rc
, err
);
463 rc
= sqlite3_bind_null(stmt
, column
++); // tries
464 require_noerr(rc
, err
);
467 rc
= sqlite3_bind_null(stmt
, column
++); // group
468 require_noerr(rc
, err
);
469 rc
= sqlite3_bind_null(stmt
, column
++); // kofn
470 require_noerr(rc
, err
);
471 rc
= sqlite3_bind_null(stmt
, column
++); // timeout
472 require_noerr(rc
, err
);
473 rc
= sqlite3_bind_int64(stmt
, column
++, auth_items_get_int64(rule
->data
, RULE_FLAGS
));
474 require_noerr(rc
, err
);
475 rc
= sqlite3_bind_int64(stmt
, column
++, rule_get_tries(rule
));
476 require_noerr(rc
, err
);
480 rc
= sqlite3_bind_null(stmt
, column
++); // group
481 require_noerr(rc
, err
);
482 rc
= sqlite3_bind_null(stmt
, column
++); // kofn
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 os_log_error(AUTHD_LOG
, "rule: sql bind, invalid rule class");
496 rc
= sqlite3_bind_int64(stmt
, column
++, rule_get_version(rule
)); // version
497 require_noerr(rc
, err
);
498 rc
= sqlite3_bind_double(stmt
, column
++, rule_get_created(rule
)); // created
499 require_noerr(rc
, err
);
500 rc
= sqlite3_bind_double(stmt
, column
++, rule_get_modified(rule
)); // modified
501 require_noerr(rc
, err
);
502 rc
= sqlite3_bind_null(stmt
, column
++); // hash
503 require_noerr(rc
, err
);
504 rc
= sqlite3_bind_text(stmt
, column
++, rule_get_identifier(rule
), -1, NULL
);
505 require_noerr(rc
, err
);
507 CFDataRef data
= rule_get_requirement_data(rule
);
509 rc
= sqlite3_bind_blob(stmt
, column
++, CFDataGetBytePtr(data
), (int32_t)CFDataGetLength(data
), NULL
);
511 rc
= sqlite3_bind_null(stmt
, column
++);
513 require_noerr(rc
, err
);
515 rc
= sqlite3_bind_text(stmt
, column
++, rule_get_comment(rule
), -1, NULL
);
516 require_noerr(rc
, err
);
521 os_log_error(AUTHD_LOG
, "rule: sql bind, error %i", rc
);
526 _get_sql_mechanisms(rule_t rule
, authdb_connection_t dbconn
)
528 CFArrayRemoveAllValues(rule
->mechanisms
);
530 authdb_step(dbconn
, "SELECT mechanisms.* " \
532 "JOIN mechanisms_map ON mechanisms.id = mechanisms_map.m_id " \
533 "WHERE mechanisms_map.r_id = ? ORDER BY mechanisms_map.ord ASC",
534 ^(sqlite3_stmt
*stmt
) {
535 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
536 }, ^bool(auth_items_t data
) {
537 mechanism_t mechanism
= mechanism_create_with_sql(data
);
538 CFArrayAppendValue(rule
->mechanisms
, mechanism
);
539 CFReleaseSafe(mechanism
);
545 _get_sql_delegates(rule_t rule
, authdb_connection_t dbconn
)
547 CFArrayRemoveAllValues(rule
->delegations
);
549 authdb_step(dbconn
, "SELECT rules.* " \
551 "JOIN delegates_map ON rules.id = delegates_map.d_id " \
552 "WHERE delegates_map.r_id = ? ORDER BY delegates_map.ord ASC",
553 ^(sqlite3_stmt
*stmt
) {
554 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
555 }, ^bool(auth_items_t data
) {
556 rule_t delegate
= _rule_create_with_sql(data
);
558 _get_sql_mechanisms(delegate
, dbconn
);
560 if (rule_get_class(rule
) == RC_RULE
) {
561 _get_sql_delegates(delegate
, dbconn
);
564 CFArrayAppendValue(rule
->delegations
, delegate
);
565 CFReleaseSafe(delegate
);
572 rule_sql_fetch(rule_t rule
, authdb_connection_t dbconn
)
574 __block
bool result
= false;
576 authdb_step(dbconn
, "SELECT * FROM rules WHERE name = ? LIMIT 1",
577 ^(sqlite3_stmt
*stmt
) {
578 sqlite3_bind_text(stmt
, 1, rule_get_name(rule
), -1, NULL
);
579 }, ^bool(auth_items_t data
) {
581 auth_items_copy(rule
->data
, data
);
585 if (rule_get_id(rule
) != 0) {
586 _get_sql_mechanisms(rule
,dbconn
);
588 if (rule_get_class(rule
) == RC_RULE
) {
589 _get_sql_delegates(rule
, dbconn
);
597 _sql_update(rule_t rule
, authdb_connection_t dbconn
)
601 result
= authdb_step(dbconn
, "UPDATE rules " \
602 "SET name=?,type=?,class=?,'group'=?,kofn=?,timeout=?,flags=?,tries=?,version=?,created=?,modified=?,hash=?,identifier=?,requirement=?,comment=? " \
604 ^(sqlite3_stmt
*stmt
) {
605 _sql_bind(rule
, stmt
);
606 sqlite3_bind_int64(stmt
, sqlite3_bind_parameter_count(stmt
), rule_get_id(rule
));
612 _sql_insert(rule_t rule
, authdb_connection_t dbconn
)
616 result
= authdb_step(dbconn
, "INSERT INTO rules VALUES (NULL,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
617 ^(sqlite3_stmt
*stmt
) {
618 _sql_bind(rule
, stmt
);
624 _sql_commit_mechanisms_map(rule_t rule
, authdb_connection_t dbconn
)
628 result
= authdb_step(dbconn
, "DELETE FROM mechanisms_map WHERE r_id = ?", ^(sqlite3_stmt
*stmt
) {
629 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
631 require(result
== true, done
);
633 CFIndex count
= CFArrayGetCount(rule
->mechanisms
);
634 for(CFIndex i
= 0; i
< count
; i
++) {
635 mechanism_t mech
= (mechanism_t
)CFArrayGetValueAtIndex(rule
->mechanisms
, i
);
636 result
= authdb_step(dbconn
, "INSERT INTO mechanisms_map VALUES (?,?,?)", ^(sqlite3_stmt
*stmt
) {
637 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
638 sqlite3_bind_int64(stmt
, 2, mechanism_get_id(mech
));
639 sqlite3_bind_int64(stmt
, 3, i
);
641 require(result
== true, done
);
649 _sql_commit_delegates_map(rule_t rule
, authdb_connection_t dbconn
)
653 result
= authdb_step(dbconn
, "DELETE FROM delegates_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
->delegations
);
659 for(CFIndex i
= 0; i
< count
; i
++) {
660 rule_t delegate
= (rule_t
)CFArrayGetValueAtIndex(rule
->delegations
, i
);
661 result
= authdb_step(dbconn
, "INSERT INTO delegates_map VALUES (?,?,?)", ^(sqlite3_stmt
*stmt
) {
662 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
663 sqlite3_bind_int64(stmt
, 2, rule_get_id(delegate
));
664 sqlite3_bind_int64(stmt
, 3, i
);
666 require(result
== true, done
);
674 _sql_commit_localization(rule_t rule
, authdb_connection_t dbconn
)
677 authdb_step(dbconn
, "DELETE FROM prompts WHERE r_id = ?", ^(sqlite3_stmt
*stmt
) {
678 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
681 authdb_step(dbconn
, "DELETE FROM buttons WHERE r_id = ?", ^(sqlite3_stmt
*stmt
) {
682 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
685 if (rule
->loc_prompts
) {
686 _cf_dictionary_iterate(rule
->loc_prompts
, ^bool(CFTypeRef key
, CFTypeRef value
) {
687 char * lang
= _copy_cf_string(key
, NULL
);
688 char * str
= _copy_cf_string(value
, NULL
);
690 authdb_step(dbconn
, "INSERT INTO prompts VALUES (?,?,?)", ^(sqlite3_stmt
*stmt
) {
691 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
692 sqlite3_bind_text(stmt
, 2, lang
, -1, NULL
);
693 sqlite3_bind_text(stmt
, 3, str
, -1, NULL
);
703 if (rule
->loc_buttons
) {
704 _cf_dictionary_iterate(rule
->loc_buttons
, ^bool(CFTypeRef key
, CFTypeRef value
) {
705 char * lang
= _copy_cf_string(key
, NULL
);
706 char * str
= _copy_cf_string(value
, NULL
);
708 authdb_step(dbconn
, "INSERT INTO buttons VALUES (?,?,?)", ^(sqlite3_stmt
*stmt
) {
709 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
710 sqlite3_bind_text(stmt
, 2, lang
, -1, NULL
);
711 sqlite3_bind_text(stmt
, 3, str
, -1, NULL
);
723 rule_sql_commit(rule_t rule
, authdb_connection_t dbconn
, CFAbsoluteTime modified
, process_t proc
)
726 __block
bool insert
= false;
727 // type and class required else rule is name only?
728 RuleClass rule_class
= rule_get_class(rule
);
729 require(rule_get_type(rule
) != 0, done
);
730 require(rule_class
!= 0, done
);
732 CFIndex mechCount
= 0;
733 if (rule_class
== RC_USER
|| rule_class
== RC_MECHANISM
) {
734 // Validate mechanisms
735 mechCount
= CFArrayGetCount(rule
->mechanisms
);
736 for (CFIndex i
= 0; i
< mechCount
; i
++) {
737 mechanism_t mech
= (mechanism_t
)CFArrayGetValueAtIndex(rule
->mechanisms
, i
);
738 if (mechanism_get_id(mech
) == 0) {
739 if (!mechanism_sql_fetch(mech
, dbconn
)) {
740 mechanism_sql_commit(mech
, dbconn
);
741 mechanism_sql_fetch(mech
, dbconn
);
744 if (!mechanism_exists(mech
)) {
745 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
));
747 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
)));
751 CFIndex delegateCount
= 0;
752 if (rule_class
== RC_RULE
) {
753 // Validate delegates
754 delegateCount
= CFArrayGetCount(rule
->delegations
);
755 for (CFIndex i
= 0; i
< delegateCount
; i
++) {
756 rule_t delegate
= (rule_t
)CFArrayGetValueAtIndex(rule
->delegations
, i
);
757 if (rule_get_id(delegate
) == 0) {
758 rule_sql_fetch(delegate
, dbconn
);
760 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
)));
764 auth_items_set_double(rule
->data
, RULE_MODIFIED
, modified
);
766 result
= authdb_transaction(dbconn
, AuthDBTransactionNormal
, ^bool{
769 if (rule_get_id(rule
)) {
770 update
= _sql_update(rule
, dbconn
);
774 const char * ident
= process_get_identifier(proc
);
776 auth_items_set_string(rule
->data
, RULE_IDENTIFIER
, ident
);
778 CFDataRef req
= process_get_requirement_data(proc
);
780 auth_items_set_data(rule
->data
, RULE_REQUIREMENT
, CFDataGetBytePtr(req
), (size_t)CFDataGetLength(req
));
783 auth_items_set_double(rule
->data
, RULE_CREATED
, modified
);
784 update
= _sql_insert(rule
, dbconn
);
785 _sql_get_id(rule
, dbconn
);
788 _sql_commit_localization(rule
, dbconn
);
791 update
= _sql_commit_mechanisms_map(rule
, dbconn
);
795 update
= _sql_commit_delegates_map(rule
,dbconn
);
804 os_log_debug(AUTHD_LOG
, "rule: commit, failed for %{public}s (%llu)", rule_get_name(rule
), rule_get_id(rule
));
806 rule_log_manipulation(dbconn
, rule
, insert
? rule_insert
: rule_update
, proc
);
812 rule_sql_remove(rule_t rule
, authdb_connection_t dbconn
, process_t proc
)
815 int64_t id
= rule_get_id(rule
);
818 rule_sql_fetch(rule
, dbconn
);
819 id
= rule_get_id(rule
);
820 require(id
!= 0, done
);
823 result
= authdb_step(dbconn
, "DELETE FROM rules WHERE id = ?",
824 ^(sqlite3_stmt
*stmt
) {
825 sqlite3_bind_int64(stmt
, 1, id
);
829 rule_log_manipulation(dbconn
, rule
, rule_delete
, proc
);
836 CFMutableDictionaryRef
837 rule_copy_to_cfobject(rule_t rule
, authdb_connection_t dbconn
) {
838 CFMutableDictionaryRef dict
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
840 CFTypeRef tmp
= NULL
;
841 CFMutableArrayRef array
= NULL
;
847 const char * comment
= rule_get_comment(rule
);
849 tmp
= CFStringCreateWithCString(kCFAllocatorDefault
, comment
, kCFStringEncodingUTF8
);
850 CFDictionarySetValue(dict
, CFSTR(kAuthorizationComment
), tmp
);
854 n
= rule_get_version(rule
);
855 tmp
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt64Type
, &n
);
856 CFDictionarySetValue(dict
, CFSTR(RULE_VERSION
), tmp
);
859 d
= rule_get_created(rule
);
860 tmp
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberFloat64Type
, &d
);
861 CFDictionarySetValue(dict
, CFSTR(RULE_CREATED
), tmp
);
864 d
= rule_get_modified(rule
);
865 tmp
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberFloat64Type
, &d
);
866 CFDictionarySetValue(dict
, CFSTR(RULE_MODIFIED
), tmp
);
869 const char * identifier
= rule_get_identifier(rule
);
871 tmp
= CFStringCreateWithCString(kCFAllocatorDefault
, identifier
, kCFStringEncodingUTF8
);
872 CFDictionarySetValue(dict
, CFSTR(RULE_IDENTIFIER
), tmp
);
876 SecRequirementRef req
= rule_get_requirement(rule
);
878 CFStringRef reqStr
= NULL
;
879 SecRequirementCopyString(req
, kSecCSDefaultFlags
, &reqStr
);
881 CFDictionarySetValue(dict
, CFSTR(RULE_REQUIREMENT
), reqStr
);
882 CFReleaseSafe(reqStr
);
886 if (rule_check_flags(rule
, RuleFlagEntitled
)) {
887 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterEntitled
), kCFBooleanTrue
);
890 if (rule_check_flags(rule
, RuleFlagRequireAppleSigned
)) {
891 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterRequireAppleSigned
), kCFBooleanTrue
);
894 if (rule_get_type(rule
) == RT_RIGHT
) {
895 CFMutableDictionaryRef prompts
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
896 authdb_step(dbconn
, "SELECT * FROM prompts WHERE r_id = ?", ^(sqlite3_stmt
*stmt
) {
897 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
898 }, ^bool(auth_items_t data
) {
899 CFStringRef key
= CFStringCreateWithCString(kCFAllocatorDefault
, auth_items_get_string(data
, "lang"), kCFStringEncodingUTF8
);
900 CFStringRef value
= CFStringCreateWithCString(kCFAllocatorDefault
, auth_items_get_string(data
, "value"), kCFStringEncodingUTF8
);
901 CFDictionaryAddValue(prompts
, key
, value
);
903 CFReleaseSafe(value
);
907 if (CFDictionaryGetCount(prompts
)) {
908 CFDictionaryAddValue(dict
, CFSTR(kAuthorizationRuleParameterDefaultPrompt
), prompts
);
910 CFReleaseSafe(prompts
);
912 CFMutableDictionaryRef buttons
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
913 authdb_step(dbconn
, "SELECT * FROM buttons WHERE r_id = ?", ^(sqlite3_stmt
*stmt
) {
914 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
915 }, ^bool(auth_items_t data
) {
916 CFStringRef key
= CFStringCreateWithCString(kCFAllocatorDefault
, auth_items_get_string(data
, "lang"), kCFStringEncodingUTF8
);
917 CFStringRef value
= CFStringCreateWithCString(kCFAllocatorDefault
, auth_items_get_string(data
, "value"), kCFStringEncodingUTF8
);
918 CFDictionaryAddValue(buttons
, key
, value
);
920 CFReleaseSafe(value
);
924 if (CFDictionaryGetCount(buttons
)) {
925 CFDictionaryAddValue(dict
, CFSTR(kAuthorizationRuleParameterDefaultButton
), buttons
);
927 CFReleaseSafe(buttons
);
930 switch (rule_get_class(rule
)) {
932 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleClass
), CFSTR(kAuthorizationRuleClassUser
));
934 const char * group
= rule_get_group(rule
);
936 tmp
= CFStringCreateWithCString(kCFAllocatorDefault
, group
, kCFStringEncodingUTF8
);
937 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterGroup
), tmp
);
941 n
= rule_get_timeout(rule
);
942 tmp
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt64Type
, &n
);
943 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterCredentialTimeout
), tmp
);
946 n
= rule_get_tries(rule
);
947 tmp
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt64Type
, &n
);
948 CFDictionarySetValue(dict
, CFSTR("tries"), tmp
);
951 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterCredentialShared
), rule_get_shared(rule
) ? kCFBooleanTrue
: kCFBooleanFalse
);
952 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterAllowRoot
), rule_get_allow_root(rule
) ? kCFBooleanTrue
: kCFBooleanFalse
);
953 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterCredentialSessionOwner
), rule_get_session_owner(rule
) ? kCFBooleanTrue
: kCFBooleanFalse
);
954 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterAuthenticateUser
), rule_get_authenticate_user(rule
) ? kCFBooleanTrue
: kCFBooleanFalse
);
955 if (rule_check_flags(rule
, RuleFlagEntitledAndGroup
)) {
956 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterEntitledAndGroup
), kCFBooleanTrue
);
958 if (rule_check_flags(rule
, RuleFlagVPNEntitledAndGroup
)) {
959 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterVPNEntitledAndGroup
), kCFBooleanTrue
);
961 if (rule_get_extract_password(rule
)) {
962 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterExtractPassword
), kCFBooleanTrue
);
964 if (rule_get_password_only(rule
)) {
965 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterPasswordOnly
), kCFBooleanTrue
);
968 count
= CFArrayGetCount(rule
->mechanisms
);
970 array
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
971 for (i
= 0; i
< count
; i
++) {
972 mechanism_t mech
= (mechanism_t
)CFArrayGetValueAtIndex(rule
->mechanisms
, i
);
973 tmp
= CFStringCreateWithCString(kCFAllocatorDefault
, mechanism_get_string(mech
), kCFStringEncodingUTF8
);
974 CFArrayAppendValue(array
, tmp
);
977 CFDictionaryAddValue(dict
, CFSTR(kAuthorizationRuleParameterMechanisms
), array
);
982 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleClass
), CFSTR(kAuthorizationRightRule
));
983 int64_t kofn
= rule_get_kofn(rule
);
985 tmp
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt64Type
, &kofn
);
986 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterKofN
), tmp
);
990 count
= CFArrayGetCount(rule
->delegations
);
992 array
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
993 for (i
= 0; i
< count
; i
++) {
994 rule_t delegate
= (rule_t
)CFArrayGetValueAtIndex(rule
->delegations
, i
);
995 tmp
= CFStringCreateWithCString(kCFAllocatorDefault
, rule_get_name(delegate
), kCFStringEncodingUTF8
);
996 CFArrayAppendValue(array
, tmp
);
999 CFDictionaryAddValue(dict
, CFSTR(kAuthorizationRightRule
), array
);
1004 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleClass
), CFSTR(kAuthorizationRuleClassMechanisms
));
1006 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterCredentialShared
), rule_get_shared(rule
) ? kCFBooleanTrue
: kCFBooleanFalse
);
1007 if (rule_get_extract_password(rule
)) {
1008 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterExtractPassword
), kCFBooleanTrue
);
1011 n
= rule_get_tries(rule
);
1012 tmp
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt64Type
, &n
);
1013 CFDictionarySetValue(dict
, CFSTR("tries"), tmp
);
1016 count
= CFArrayGetCount(rule
->mechanisms
);
1018 array
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
1019 for (i
= 0; i
< count
; i
++) {
1020 mechanism_t mech
= (mechanism_t
)CFArrayGetValueAtIndex(rule
->mechanisms
, i
);
1021 tmp
= CFStringCreateWithCString(kCFAllocatorDefault
, mechanism_get_string(mech
), kCFStringEncodingUTF8
);
1022 CFArrayAppendValue(array
, tmp
);
1025 CFDictionaryAddValue(dict
, CFSTR(kAuthorizationRuleParameterMechanisms
), array
);
1030 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleClass
), CFSTR(kAuthorizationRuleClassDeny
));
1033 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleClass
), CFSTR(kAuthorizationRuleClassAllow
));
1044 rule_get_mechanisms(rule_t rule
)
1046 return rule
->mechanisms
;
1050 rule_get_mechanisms_count(rule_t rule
)
1052 return (size_t)CFArrayGetCount(rule
->mechanisms
);
1056 rule_mechanisms_iterator(rule_t rule
, mechanism_iterator_t iter
)
1058 bool result
= false;
1060 CFIndex count
= CFArrayGetCount(rule
->mechanisms
);
1061 for (CFIndex i
= 0; i
< count
; i
++) {
1062 mechanism_t mech
= (mechanism_t
)CFArrayGetValueAtIndex(rule
->mechanisms
, i
);
1063 result
= iter(mech
);
1073 rule_get_delegates_count(rule_t rule
)
1075 return (size_t)CFArrayGetCount(rule
->delegations
);
1079 rule_delegates_iterator(rule_t rule
, delegate_iterator_t iter
)
1081 bool result
= false;
1083 CFIndex count
= CFArrayGetCount(rule
->delegations
);
1084 for (CFIndex i
= 0; i
< count
; i
++) {
1085 rule_t tmp
= (rule_t
)CFArrayGetValueAtIndex(rule
->delegations
, i
);
1096 rule_get_id(rule_t rule
)
1098 return auth_items_get_int64(rule
->data
, RULE_ID
);
1102 rule_get_name(rule_t rule
)
1104 return auth_items_get_string(rule
->data
, RULE_NAME
);
1108 rule_get_type(rule_t rule
)
1110 return (RuleType
)auth_items_get_int64(rule
->data
, RULE_TYPE
);
1114 rule_get_class(rule_t rule
)
1116 return (RuleClass
)auth_items_get_int64(rule
->data
, RULE_CLASS
);
1120 rule_get_group(rule_t rule
)
1122 return auth_items_get_string(rule
->data
, RULE_GROUP
);
1126 rule_get_kofn(rule_t rule
)
1128 return auth_items_get_int64(rule
->data
, RULE_KOFN
);
1132 rule_get_timeout(rule_t rule
)
1134 return auth_items_get_int64(rule
->data
, RULE_TIMEOUT
);
1138 rule_check_flags(rule_t rule
, RuleFlags flags
)
1140 return (auth_items_get_int64(rule
->data
, RULE_FLAGS
) & flags
) != 0;
1144 rule_get_shared(rule_t rule
)
1149 return rule_check_flags(rule
, RuleFlagShared
);
1153 rule_get_allow_root(rule_t rule
)
1155 return rule_check_flags(rule
, RuleFlagAllowRoot
);
1159 rule_get_session_owner(rule_t rule
)
1161 return rule_check_flags(rule
, RuleFlagSessionOwner
);
1165 rule_get_authenticate_user(rule_t rule
)
1167 return rule_check_flags(rule
, RuleFlagAuthenticateUser
);
1171 rule_get_extract_password(rule_t rule
)
1173 return rule_check_flags(rule
, RuleFlagExtractPassword
);
1177 rule_get_password_only(rule_t rule
)
1179 return rule_check_flags(rule
, RuleFlagPasswordOnly
);
1183 rule_get_tries(rule_t rule
)
1185 return auth_items_get_int64(rule
->data
, RULE_TRIES
);
1189 rule_get_comment(rule_t rule
)
1191 return auth_items_get_string(rule
->data
, RULE_COMMENT
);
1195 rule_get_version(rule_t rule
)
1197 return auth_items_get_int64(rule
->data
, RULE_VERSION
);
1200 double rule_get_created(rule_t rule
)
1202 return auth_items_get_double(rule
->data
, RULE_CREATED
);
1205 double rule_get_modified(rule_t rule
)
1207 return auth_items_get_double(rule
->data
, RULE_MODIFIED
);
1210 const char * rule_get_identifier(rule_t rule
)
1212 return auth_items_get_string(rule
->data
, RULE_IDENTIFIER
);
1215 CFDataRef
rule_get_requirement_data(rule_t rule
)
1217 if (!rule
->requirement_data
&& auth_items_exist(rule
->data
, RULE_REQUIREMENT
)) {
1219 const void * data
= auth_items_get_data(rule
->data
, RULE_REQUIREMENT
, &len
);
1220 rule
->requirement_data
= CFDataCreate(kCFAllocatorDefault
, data
, (CFIndex
)len
);
1223 return rule
->requirement_data
;
1226 SecRequirementRef
rule_get_requirement(rule_t rule
)
1228 if (!rule
->requirement
) {
1229 CFDataRef data
= rule_get_requirement_data(rule
);
1231 SecRequirementCreateWithData(data
, kSecCSDefaultFlags
, &rule
->requirement
);
1235 return rule
->requirement
;
1239 rule_log_manipulation(authdb_connection_t dbconn
, rule_t rule
, RuleOperation operation
, process_t source
)
1241 authdb_step(dbconn
, "INSERT INTO rules_history (rule, source, operation, version) VALUES (?,?,?,?)", ^(sqlite3_stmt
*stmt
) {
1242 char pathbuf
[PROC_PIDPATHINFO_MAXSIZE
];
1244 pid_t pid
= process_get_pid(source
);
1245 if (!proc_pidpath(pid
, pathbuf
, sizeof(pathbuf
))) {
1246 os_log_error(AUTHD_LOG
, "Failed to get path for pid %d", pid
);
1247 snprintf(pathbuf
, sizeof(pathbuf
), "Unknown process with PID %d", pid
);
1250 strncpy(pathbuf
, "authd", sizeof(pathbuf
));
1253 sqlite3_bind_text(stmt
, 1, rule_get_name(rule
), -1, NULL
);
1254 sqlite3_bind_text(stmt
, 2, pathbuf
, -1, NULL
);
1255 sqlite3_bind_int(stmt
, 3, operation
);
1256 sqlite3_bind_int64(stmt
, 4, rule_get_version(rule
));