1 /* Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. */
4 #include "authutilities.h"
11 #include <Security/AuthorizationDB.h>
12 #include <Security/AuthorizationTagsPriv.h>
15 static void _sql_get_id(rule_t
,authdb_connection_t
);
16 static RuleClass
_get_cf_rule_class(CFTypeRef
);
17 static bool _copy_cf_rule_mechanisms(rule_t
,CFTypeRef
,authdb_connection_t
);
18 static bool _copy_cf_rule_delegations(rule_t
, CFTypeRef
,authdb_connection_t
);
20 #define kMaximumAuthorizationTries 10000
23 #define RULE_NAME "name"
24 #define RULE_TYPE "type"
25 #define RULE_CLASS "class"
26 #define RULE_GROUP "group"
27 #define RULE_KOFN "kofn"
28 #define RULE_TIMEOUT "timeout"
29 #define RULE_FLAGS "flags"
30 #define RULE_TRIES "tries"
31 #define RULE_COMMENT "comment"
32 #define RULE_VERSION "version"
33 #define RULE_CREATED "created"
34 #define RULE_MODIFIED "modified"
35 #define RULE_IDENTIFIER "identifier"
36 #define RULE_REQUIREMENT "requirement"
37 #define RULE_HASH "hash"
40 __AUTH_BASE_STRUCT_HEADER__
;
43 CFMutableArrayRef mechanisms
;
44 CFMutableArrayRef delegations
;
46 CFMutableDictionaryRef loc_prompts
;
47 CFMutableDictionaryRef loc_buttons
;
49 CFDataRef requirement_data
;
50 SecRequirementRef requirement
;
54 _rule_finalize(CFTypeRef value
)
56 rule_t rule
= (rule_t
)value
;
57 CFReleaseSafe(rule
->data
);
58 CFReleaseSafe(rule
->mechanisms
);
59 CFReleaseSafe(rule
->delegations
);
60 CFReleaseSafe(rule
->loc_prompts
);
61 CFReleaseSafe(rule
->loc_buttons
);
62 CFReleaseSafe(rule
->requirement_data
);
63 CFReleaseSafe(rule
->requirement
);
67 _rule_equal(CFTypeRef value1
, CFTypeRef value2
)
69 rule_t rule1
= (rule_t
)value1
;
70 rule_t rule2
= (rule_t
)value2
;
72 return strcasecmp(rule_get_name(rule1
), rule_get_name(rule2
)) == 0;
76 _rule_copy_description(CFTypeRef value
)
78 rule_t rule
= (rule_t
)value
;
79 CFMutableStringRef str
= CFStringCreateMutable(kCFAllocatorDefault
, 0);
80 CFStringRef tmp
= CFCopyDescription(rule
->data
);
81 CFStringAppend(str
, tmp
);
83 tmp
= CFCopyDescription(rule
->mechanisms
);
84 CFStringAppend(str
, tmp
);
86 tmp
= CFCopyDescription(rule
->delegations
);
87 CFStringAppend(str
, tmp
);
93 _rule_hash(CFTypeRef value
)
95 rule_t rule
= (rule_t
)value
;
96 const char * str
= rule_get_name(rule
);
97 return (CFHashCode
)crc64(str
, strlen(str
));
100 AUTH_TYPE_INSTANCE(rule
,
103 .finalize
= _rule_finalize
,
104 .equal
= _rule_equal
,
106 .copyFormattingDesc
= NULL
,
107 .copyDebugDesc
= _rule_copy_description
110 static CFTypeID
rule_get_type_id() {
111 static CFTypeID type_id
= _kCFRuntimeNotATypeID
;
112 static dispatch_once_t onceToken
;
114 dispatch_once(&onceToken
, ^{
115 type_id
= _CFRuntimeRegisterClass(&_auth_type_rule
);
124 rule_t rule
= (rule_t
)_CFRuntimeCreateInstance(kCFAllocatorDefault
, rule_get_type_id(), AUTH_CLASS_SIZE(rule
), NULL
);
125 require(rule
!= NULL
, done
);
127 rule
->data
= auth_items_create();
128 rule
->delegations
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
129 rule
->mechanisms
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
136 _rule_create_with_sql(auth_items_t sql
)
139 require(sql
!= NULL
, done
);
141 rule
= _rule_create();
142 require(rule
!= NULL
, done
);
144 auth_items_copy(rule
->data
, sql
);
151 rule_create_default()
153 rule_t rule
= _rule_create();
154 require(rule
!= NULL
, done
);
156 auth_items_set_int64(rule
->data
, RULE_TYPE
, RT_RIGHT
);
157 auth_items_set_string(rule
->data
, RULE_NAME
, "(default)");
158 auth_items_set_int64(rule
->data
, RULE_CLASS
, RC_USER
);
159 auth_items_set_string(rule
->data
, RULE_GROUP
, "admin");
160 auth_items_set_int64(rule
->data
, RULE_TIMEOUT
, 300);
161 auth_items_set_int64(rule
->data
, RULE_TRIES
, kMaximumAuthorizationTries
);
162 auth_items_set_int64(rule
->data
, RULE_FLAGS
, RuleFlagShared
| RuleFlagAuthenticateUser
);
164 mechanism_t mech
= mechanism_create_with_string("builtin:authenticate", NULL
);
165 CFArrayAppendValue(rule
->mechanisms
, mech
);
168 mech
= mechanism_create_with_string("builtin:reset-password,privileged", NULL
);
169 CFArrayAppendValue(rule
->mechanisms
, mech
);
172 mech
= mechanism_create_with_string("builtin:authenticate,privileged", NULL
);
173 CFArrayAppendValue(rule
->mechanisms
, mech
);
176 mech
= mechanism_create_with_string("PKINITMechanism:auth,privileged", NULL
);
177 CFArrayAppendValue(rule
->mechanisms
, mech
);
185 rule_create_with_string(const char * str
, authdb_connection_t dbconn
)
188 require(str
!= NULL
, done
);
190 rule
= _rule_create();
191 require(rule
!= NULL
, done
);
193 auth_items_set_string(rule
->data
, RULE_NAME
, str
);
196 rule_sql_fetch(rule
, dbconn
);
203 static void _set_data_string(rule_t rule
, const char * key
, CFStringRef str
)
205 char * tmpStr
= _copy_cf_string(str
, NULL
);
208 auth_items_set_string(rule
->data
, key
, tmpStr
);
214 rule_create_with_plist(RuleType type
, CFStringRef name
, CFDictionaryRef plist
, authdb_connection_t dbconn
)
217 require(name
!= NULL
, done
);
218 require(plist
!= NULL
, done
);
220 rule
= _rule_create();
221 require(rule
!= NULL
, done
);
223 _set_data_string(rule
, RULE_NAME
, name
);
224 require_action(rule_get_name(rule
) != NULL
, done
, CFReleaseSafe(rule
));
226 _sql_get_id(rule
, dbconn
);
228 auth_items_set_int64(rule
->data
, RULE_TYPE
, type
);
230 auth_items_set_int64(rule
->data
, RULE_CLASS
, _get_cf_rule_class(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleClass
))));
231 _set_data_string(rule
, RULE_COMMENT
, CFDictionaryGetValue(plist
, CFSTR(kAuthorizationComment
)));
234 CFTypeRef loc_tmp
= CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterDefaultPrompt
));
236 rule
->loc_prompts
= CFDictionaryCreateMutableCopy(kCFAllocatorDefault
, 0, loc_tmp
);
238 loc_tmp
= CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterDefaultButton
));
240 rule
->loc_buttons
= CFDictionaryCreateMutableCopy(kCFAllocatorDefault
, 0, loc_tmp
);
243 auth_items_set_int64(rule
->data
, RULE_VERSION
, _get_cf_int(CFDictionaryGetValue(plist
, CFSTR("version")), 0));
247 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterEntitled
)), false)) {
248 flags
|= RuleFlagEntitled
;
251 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterRequireAppleSigned
)), false)) {
252 flags
|= RuleFlagRequireAppleSigned
;
255 switch (rule_get_class(rule
)) {
257 _set_data_string(rule
, RULE_GROUP
, CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterGroup
)));
258 auth_items_set_int64(rule
->data
, RULE_TIMEOUT
, _get_cf_int(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterCredentialTimeout
)), INT32_MAX
));
259 auth_items_set_int64(rule
->data
, RULE_TRIES
, _get_cf_int(CFDictionaryGetValue(plist
, CFSTR("tries")), kMaximumAuthorizationTries
));
261 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterCredentialShared
)), false)) {
262 flags
|= RuleFlagShared
;
264 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterAllowRoot
)), false)) {
265 flags
|= RuleFlagAllowRoot
;
267 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterCredentialSessionOwner
)), false)) {
268 flags
|= RuleFlagSessionOwner
;
270 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterAuthenticateUser
)), true)) {
271 flags
|= RuleFlagAuthenticateUser
;
273 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterExtractPassword
)), false)) {
274 flags
|= RuleFlagExtractPassword
;
276 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterEntitledAndGroup
)), false)) {
277 flags
|= RuleFlagEntitledAndGroup
;
279 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterVPNEntitledAndGroup
)), false)) {
280 flags
|= RuleFlagVPNEntitledAndGroup
;
282 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterPasswordOnly
)), false)) {
283 flags
|= RuleFlagPasswordOnly
;
286 _copy_cf_rule_mechanisms(rule
, CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterMechanisms
)), dbconn
);
290 auth_items_set_int64(rule
->data
, RULE_KOFN
, _get_cf_int(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterKofN
)), 0));
292 _copy_cf_rule_delegations(rule
, CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRightRule
)), dbconn
);
295 auth_items_set_int64(rule
->data
, RULE_TRIES
, _get_cf_int(CFDictionaryGetValue(plist
, CFSTR("tries")), kMaximumAuthorizationTries
));
296 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterCredentialShared
)), true)) {
297 flags
|= RuleFlagShared
;
299 if (_get_cf_bool(CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterExtractPassword
)), false)) {
300 flags
|= RuleFlagExtractPassword
;
303 _copy_cf_rule_mechanisms(rule
, CFDictionaryGetValue(plist
, CFSTR(kAuthorizationRuleParameterMechanisms
)), dbconn
);
311 LOGD("rule: invalid rule class");
315 auth_items_set_int64(rule
->data
, RULE_FLAGS
, flags
);
322 _sql_get_id(rule_t rule
, authdb_connection_t dbconn
)
324 authdb_step(dbconn
, "SELECT id,created,identifier,requirement FROM rules WHERE name = ? LIMIT 1",
325 ^(sqlite3_stmt
*stmt
) {
326 sqlite3_bind_text(stmt
, 1, rule_get_name(rule
), -1, NULL
);
327 }, ^bool(auth_items_t data
) {
328 auth_items_copy(rule
->data
, data
);
334 _copy_cf_rule_delegations(rule_t rule
, CFTypeRef value
, authdb_connection_t dbconn
)
337 char * tmp_str
= NULL
;
338 require(value
!= NULL
, done
);
340 if (CFGetTypeID(value
) == CFStringGetTypeID()) {
341 tmp_str
= _copy_cf_string(value
, NULL
);
342 rule_t delegate
= rule_create_with_string(tmp_str
, dbconn
);
345 CFArrayAppendValue(rule
->delegations
, delegate
);
346 CFReleaseSafe(delegate
);
349 CFIndex count
= CFArrayGetCount(value
);
350 for (CFIndex i
= 0; i
< count
; i
++) {
351 tmp_str
= _copy_cf_string(CFArrayGetValueAtIndex(value
,i
), NULL
);
352 rule_t delegate
= rule_create_with_string(tmp_str
, dbconn
);
355 CFArrayAppendValue(rule
->delegations
, delegate
);
356 CFReleaseSafe(delegate
);
368 _copy_cf_rule_mechanisms(rule_t rule
, CFTypeRef array
, authdb_connection_t dbconn
)
371 require(array
!= NULL
, done
);
372 require(CFGetTypeID(array
) == CFArrayGetTypeID(), done
);
374 CFIndex count
= CFArrayGetCount(array
);
375 for (CFIndex i
= 0; i
< count
; i
++) {
376 mechanism_t mech
= NULL
;
377 char * string
= _copy_cf_string(CFArrayGetValueAtIndex(array
, i
), NULL
);
382 mech
= mechanism_create_with_string(string
, dbconn
);
384 CFArrayAppendValue(rule
->mechanisms
, mech
);
397 _get_cf_rule_class(CFTypeRef str
)
399 RuleClass rc
= RC_RULE
;
400 require(str
!= NULL
, done
);
401 require(CFGetTypeID(str
) == CFStringGetTypeID(), done
);
403 if (CFEqual(str
, CFSTR(kAuthorizationRuleClassUser
)))
406 if (CFEqual(str
, CFSTR(kAuthorizationRightRule
)))
409 if (CFEqual(str
, CFSTR(kAuthorizationRuleClassMechanisms
)))
412 if (CFEqual(str
, CFSTR(kAuthorizationRuleClassDeny
)))
415 if (CFEqual(str
, CFSTR(kAuthorizationRuleClassAllow
)))
423 _sql_bind(rule_t rule
, sqlite3_stmt
* stmt
)
427 require(stmt
!= NULL
, err
);
430 rc
= sqlite3_bind_text(stmt
, column
++, rule_get_name(rule
), -1, NULL
);
431 require_noerr(rc
, err
);
432 rc
= sqlite3_bind_int(stmt
, column
++, rule_get_type(rule
));
433 require_noerr(rc
, err
);
434 rc
= sqlite3_bind_int(stmt
, column
++, rule_get_class(rule
));
435 require_noerr(rc
, err
);
437 switch (rule_get_class(rule
)) {
439 rc
= sqlite3_bind_text(stmt
, column
++, rule_get_group(rule
), -1, NULL
);
440 require_noerr(rc
, err
);
441 rc
= sqlite3_bind_null(stmt
, column
++); // kofn
442 require_noerr(rc
, err
);
443 rc
= sqlite3_bind_int64(stmt
, column
++, rule_get_timeout(rule
));
444 require_noerr(rc
, err
);
445 rc
= sqlite3_bind_int64(stmt
, column
++, auth_items_get_int64(rule
->data
, RULE_FLAGS
));
446 require_noerr(rc
, err
);
447 rc
= sqlite3_bind_int64(stmt
, column
++, rule_get_tries(rule
));
448 require_noerr(rc
, err
);
451 rc
= sqlite3_bind_null(stmt
, column
++); // group
452 require_noerr(rc
, err
);
453 n
= rule_get_kofn(rule
);
455 rc
= sqlite3_bind_int64(stmt
, column
++, n
);
457 rc
= sqlite3_bind_null(stmt
, column
++);
459 require_noerr(rc
, err
);
460 rc
= sqlite3_bind_null(stmt
, column
++); // timeout
461 require_noerr(rc
, err
);
462 rc
= sqlite3_bind_int64(stmt
, column
++, auth_items_get_int64(rule
->data
, RULE_FLAGS
));
463 require_noerr(rc
, err
);
464 rc
= sqlite3_bind_null(stmt
, column
++); // tries
465 require_noerr(rc
, err
);
468 rc
= sqlite3_bind_null(stmt
, column
++); // group
469 require_noerr(rc
, err
);
470 rc
= sqlite3_bind_null(stmt
, column
++); // kofn
471 require_noerr(rc
, err
);
472 rc
= sqlite3_bind_null(stmt
, column
++); // timeout
473 require_noerr(rc
, err
);
474 rc
= sqlite3_bind_int64(stmt
, column
++, auth_items_get_int64(rule
->data
, RULE_FLAGS
));
475 require_noerr(rc
, err
);
476 rc
= sqlite3_bind_int64(stmt
, column
++, rule_get_tries(rule
));
477 require_noerr(rc
, err
);
481 rc
= sqlite3_bind_null(stmt
, column
++); // group
482 require_noerr(rc
, err
);
483 rc
= sqlite3_bind_null(stmt
, column
++); // kofn
484 require_noerr(rc
, err
);
485 rc
= sqlite3_bind_null(stmt
, column
++); // timeout
486 require_noerr(rc
, err
);
487 rc
= sqlite3_bind_int64(stmt
, column
++, auth_items_get_int64(rule
->data
, RULE_FLAGS
));
488 require_noerr(rc
, err
);
489 rc
= sqlite3_bind_null(stmt
, column
++); // tries
490 require_noerr(rc
, err
);
493 LOGD("rule: sql bind, invalid rule class");
497 rc
= sqlite3_bind_int64(stmt
, column
++, rule_get_version(rule
)); // version
498 require_noerr(rc
, err
);
499 rc
= sqlite3_bind_double(stmt
, column
++, rule_get_created(rule
)); // created
500 require_noerr(rc
, err
);
501 rc
= sqlite3_bind_double(stmt
, column
++, rule_get_modified(rule
)); // modified
502 require_noerr(rc
, err
);
503 rc
= sqlite3_bind_null(stmt
, column
++); // hash
504 require_noerr(rc
, err
);
505 rc
= sqlite3_bind_text(stmt
, column
++, rule_get_identifier(rule
), -1, NULL
);
506 require_noerr(rc
, err
);
508 CFDataRef data
= rule_get_requirement_data(rule
);
510 rc
= sqlite3_bind_blob(stmt
, column
++, CFDataGetBytePtr(data
), (int32_t)CFDataGetLength(data
), NULL
);
512 rc
= sqlite3_bind_null(stmt
, column
++);
514 require_noerr(rc
, err
);
516 rc
= sqlite3_bind_text(stmt
, column
++, rule_get_comment(rule
), -1, NULL
);
517 require_noerr(rc
, err
);
522 LOGD("rule: sql bind, error %i", rc
);
527 _get_sql_mechanisms(rule_t rule
, authdb_connection_t dbconn
)
529 CFArrayRemoveAllValues(rule
->mechanisms
);
531 authdb_step(dbconn
, "SELECT mechanisms.* " \
533 "JOIN mechanisms_map ON mechanisms.id = mechanisms_map.m_id " \
534 "WHERE mechanisms_map.r_id = ? ORDER BY mechanisms_map.ord ASC",
535 ^(sqlite3_stmt
*stmt
) {
536 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
537 }, ^bool(auth_items_t data
) {
538 mechanism_t mechanism
= mechanism_create_with_sql(data
);
539 CFArrayAppendValue(rule
->mechanisms
, mechanism
);
540 CFReleaseSafe(mechanism
);
546 _get_sql_delegates(rule_t rule
, authdb_connection_t dbconn
)
548 CFArrayRemoveAllValues(rule
->delegations
);
550 authdb_step(dbconn
, "SELECT rules.* " \
552 "JOIN delegates_map ON rules.id = delegates_map.d_id " \
553 "WHERE delegates_map.r_id = ? ORDER BY delegates_map.ord ASC",
554 ^(sqlite3_stmt
*stmt
) {
555 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
556 }, ^bool(auth_items_t data
) {
557 rule_t delegate
= _rule_create_with_sql(data
);
559 _get_sql_mechanisms(delegate
, dbconn
);
561 if (rule_get_class(rule
) == RC_RULE
) {
562 _get_sql_delegates(delegate
, dbconn
);
565 CFArrayAppendValue(rule
->delegations
, delegate
);
566 CFReleaseSafe(delegate
);
573 rule_sql_fetch(rule_t rule
, authdb_connection_t dbconn
)
575 __block
bool result
= false;
577 authdb_step(dbconn
, "SELECT * FROM rules WHERE name = ? LIMIT 1",
578 ^(sqlite3_stmt
*stmt
) {
579 sqlite3_bind_text(stmt
, 1, rule_get_name(rule
), -1, NULL
);
580 }, ^bool(auth_items_t data
) {
582 auth_items_copy(rule
->data
, data
);
586 if (rule_get_id(rule
) != 0) {
587 _get_sql_mechanisms(rule
,dbconn
);
589 if (rule_get_class(rule
) == RC_RULE
) {
590 _get_sql_delegates(rule
, dbconn
);
598 _sql_update(rule_t rule
, authdb_connection_t dbconn
)
602 result
= authdb_step(dbconn
, "UPDATE rules " \
603 "SET name=?,type=?,class=?,'group'=?,kofn=?,timeout=?,flags=?,tries=?,version=?,created=?,modified=?,hash=?,identifier=?,requirement=?,comment=? " \
605 ^(sqlite3_stmt
*stmt
) {
606 _sql_bind(rule
, stmt
);
607 sqlite3_bind_int64(stmt
, sqlite3_bind_parameter_count(stmt
), rule_get_id(rule
));
613 _sql_insert(rule_t rule
, authdb_connection_t dbconn
)
617 result
= authdb_step(dbconn
, "INSERT INTO rules VALUES (NULL,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
618 ^(sqlite3_stmt
*stmt
) {
619 _sql_bind(rule
, stmt
);
625 _sql_commit_mechanisms_map(rule_t rule
, authdb_connection_t dbconn
)
629 result
= authdb_step(dbconn
, "DELETE FROM mechanisms_map WHERE r_id = ?", ^(sqlite3_stmt
*stmt
) {
630 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
632 require(result
== true, done
);
634 CFIndex count
= CFArrayGetCount(rule
->mechanisms
);
635 for(CFIndex i
= 0; i
< count
; i
++) {
636 mechanism_t mech
= (mechanism_t
)CFArrayGetValueAtIndex(rule
->mechanisms
, i
);
637 result
= authdb_step(dbconn
, "INSERT INTO mechanisms_map VALUES (?,?,?)", ^(sqlite3_stmt
*stmt
) {
638 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
639 sqlite3_bind_int64(stmt
, 2, mechanism_get_id(mech
));
640 sqlite3_bind_int64(stmt
, 3, i
);
642 require(result
== true, done
);
650 _sql_commit_delegates_map(rule_t rule
, authdb_connection_t dbconn
)
654 result
= authdb_step(dbconn
, "DELETE FROM delegates_map WHERE r_id = ?", ^(sqlite3_stmt
*stmt
) {
655 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
657 require(result
== true, done
);
659 CFIndex count
= CFArrayGetCount(rule
->delegations
);
660 for(CFIndex i
= 0; i
< count
; i
++) {
661 rule_t delegate
= (rule_t
)CFArrayGetValueAtIndex(rule
->delegations
, i
);
662 result
= authdb_step(dbconn
, "INSERT INTO delegates_map VALUES (?,?,?)", ^(sqlite3_stmt
*stmt
) {
663 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
664 sqlite3_bind_int64(stmt
, 2, rule_get_id(delegate
));
665 sqlite3_bind_int64(stmt
, 3, i
);
667 require(result
== true, done
);
675 _sql_commit_localization(rule_t rule
, authdb_connection_t dbconn
)
678 authdb_step(dbconn
, "DELETE FROM prompts WHERE r_id = ?", ^(sqlite3_stmt
*stmt
) {
679 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
682 authdb_step(dbconn
, "DELETE FROM buttons WHERE r_id = ?", ^(sqlite3_stmt
*stmt
) {
683 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
686 if (rule
->loc_prompts
) {
687 _cf_dictionary_iterate(rule
->loc_prompts
, ^bool(CFTypeRef key
, CFTypeRef value
) {
688 char * lang
= _copy_cf_string(key
, NULL
);
689 char * str
= _copy_cf_string(value
, NULL
);
691 authdb_step(dbconn
, "INSERT INTO prompts VALUES (?,?,?)", ^(sqlite3_stmt
*stmt
) {
692 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
693 sqlite3_bind_text(stmt
, 2, lang
, -1, NULL
);
694 sqlite3_bind_text(stmt
, 3, str
, -1, NULL
);
704 if (rule
->loc_buttons
) {
705 _cf_dictionary_iterate(rule
->loc_buttons
, ^bool(CFTypeRef key
, CFTypeRef value
) {
706 char * lang
= _copy_cf_string(key
, NULL
);
707 char * str
= _copy_cf_string(value
, NULL
);
709 authdb_step(dbconn
, "INSERT INTO buttons VALUES (?,?,?)", ^(sqlite3_stmt
*stmt
) {
710 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
711 sqlite3_bind_text(stmt
, 2, lang
, -1, NULL
);
712 sqlite3_bind_text(stmt
, 3, str
, -1, NULL
);
724 rule_sql_commit(rule_t rule
, authdb_connection_t dbconn
, CFAbsoluteTime modified
, process_t proc
)
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 LOGE("Warning mechanism not found on disk %s during import of %s", mechanism_get_string(mech
), rule_get_name(rule
));
747 require_action(mechanism_get_id(mech
) != 0, done
, LOGE("rule: commit, invalid mechanism %s:%s for %s", mechanism_get_plugin(mech
), mechanism_get_param(mech
), rule_get_name(rule
)));
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
, LOGE("rule: commit, missing delegate %s for %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
);
773 const char * ident
= process_get_identifier(proc
);
775 auth_items_set_string(rule
->data
, RULE_IDENTIFIER
, ident
);
777 CFDataRef req
= process_get_requirement_data(proc
);
779 auth_items_set_data(rule
->data
, RULE_REQUIREMENT
, CFDataGetBytePtr(req
), (size_t)CFDataGetLength(req
));
782 auth_items_set_double(rule
->data
, RULE_CREATED
, modified
);
783 update
= _sql_insert(rule
, dbconn
);
784 _sql_get_id(rule
, dbconn
);
787 _sql_commit_localization(rule
, dbconn
);
790 update
= _sql_commit_mechanisms_map(rule
, dbconn
);
794 update
= _sql_commit_delegates_map(rule
,dbconn
);
803 LOGV("rule: commit, failed for %s (%llu)", rule_get_name(rule
), rule_get_id(rule
));
809 rule_sql_remove(rule_t rule
, authdb_connection_t dbconn
)
812 int64_t id
= rule_get_id(rule
);
815 rule_sql_fetch(rule
, dbconn
);
816 id
= rule_get_id(rule
);
817 require(id
!= 0, done
);
820 result
= authdb_step(dbconn
, "DELETE FROM rules WHERE id = ?",
821 ^(sqlite3_stmt
*stmt
) {
822 sqlite3_bind_int64(stmt
, 1, id
);
828 CFMutableDictionaryRef
829 rule_copy_to_cfobject(rule_t rule
, authdb_connection_t dbconn
) {
830 CFMutableDictionaryRef dict
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
832 CFTypeRef tmp
= NULL
;
833 CFMutableArrayRef array
= NULL
;
839 const char * comment
= rule_get_comment(rule
);
841 tmp
= CFStringCreateWithCString(kCFAllocatorDefault
, comment
, kCFStringEncodingUTF8
);
842 CFDictionarySetValue(dict
, CFSTR(kAuthorizationComment
), tmp
);
846 n
= rule_get_version(rule
);
847 tmp
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt64Type
, &n
);
848 CFDictionarySetValue(dict
, CFSTR(RULE_VERSION
), tmp
);
851 d
= rule_get_created(rule
);
852 tmp
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberFloat64Type
, &d
);
853 CFDictionarySetValue(dict
, CFSTR(RULE_CREATED
), tmp
);
856 d
= rule_get_modified(rule
);
857 tmp
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberFloat64Type
, &d
);
858 CFDictionarySetValue(dict
, CFSTR(RULE_MODIFIED
), tmp
);
861 const char * identifier
= rule_get_identifier(rule
);
863 tmp
= CFStringCreateWithCString(kCFAllocatorDefault
, identifier
, kCFStringEncodingUTF8
);
864 CFDictionarySetValue(dict
, CFSTR(RULE_IDENTIFIER
), tmp
);
868 SecRequirementRef req
= rule_get_requirement(rule
);
870 CFStringRef reqStr
= NULL
;
871 SecRequirementCopyString(req
, kSecCSDefaultFlags
, &reqStr
);
873 CFDictionarySetValue(dict
, CFSTR(RULE_REQUIREMENT
), reqStr
);
874 CFReleaseSafe(reqStr
);
878 if (rule_check_flags(rule
, RuleFlagEntitled
)) {
879 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterEntitled
), kCFBooleanTrue
);
882 if (rule_check_flags(rule
, RuleFlagRequireAppleSigned
)) {
883 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterRequireAppleSigned
), kCFBooleanTrue
);
886 if (rule_get_type(rule
) == RT_RIGHT
) {
887 CFMutableDictionaryRef prompts
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
888 authdb_step(dbconn
, "SELECT * FROM prompts WHERE r_id = ?", ^(sqlite3_stmt
*stmt
) {
889 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
890 }, ^bool(auth_items_t data
) {
891 CFStringRef key
= CFStringCreateWithCString(kCFAllocatorDefault
, auth_items_get_string(data
, "lang"), kCFStringEncodingUTF8
);
892 CFStringRef value
= CFStringCreateWithCString(kCFAllocatorDefault
, auth_items_get_string(data
, "value"), kCFStringEncodingUTF8
);
893 CFDictionaryAddValue(prompts
, key
, value
);
895 CFReleaseSafe(value
);
899 if (CFDictionaryGetCount(prompts
)) {
900 CFDictionaryAddValue(dict
, CFSTR(kAuthorizationRuleParameterDefaultPrompt
), prompts
);
902 CFReleaseSafe(prompts
);
904 CFMutableDictionaryRef buttons
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
905 authdb_step(dbconn
, "SELECT * FROM buttons WHERE r_id = ?", ^(sqlite3_stmt
*stmt
) {
906 sqlite3_bind_int64(stmt
, 1, rule_get_id(rule
));
907 }, ^bool(auth_items_t data
) {
908 CFStringRef key
= CFStringCreateWithCString(kCFAllocatorDefault
, auth_items_get_string(data
, "lang"), kCFStringEncodingUTF8
);
909 CFStringRef value
= CFStringCreateWithCString(kCFAllocatorDefault
, auth_items_get_string(data
, "value"), kCFStringEncodingUTF8
);
910 CFDictionaryAddValue(buttons
, key
, value
);
912 CFReleaseSafe(value
);
916 if (CFDictionaryGetCount(buttons
)) {
917 CFDictionaryAddValue(dict
, CFSTR(kAuthorizationRuleParameterDefaultButton
), buttons
);
919 CFReleaseSafe(buttons
);
922 switch (rule_get_class(rule
)) {
924 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleClass
), CFSTR(kAuthorizationRuleClassUser
));
926 const char * group
= rule_get_group(rule
);
928 tmp
= CFStringCreateWithCString(kCFAllocatorDefault
, group
, kCFStringEncodingUTF8
);
929 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterGroup
), tmp
);
933 n
= rule_get_timeout(rule
);
934 tmp
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt64Type
, &n
);
935 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterCredentialTimeout
), tmp
);
938 n
= rule_get_tries(rule
);
939 tmp
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt64Type
, &n
);
940 CFDictionarySetValue(dict
, CFSTR("tries"), tmp
);
943 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterCredentialShared
), rule_get_shared(rule
) ? kCFBooleanTrue
: kCFBooleanFalse
);
944 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterAllowRoot
), rule_get_allow_root(rule
) ? kCFBooleanTrue
: kCFBooleanFalse
);
945 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterCredentialSessionOwner
), rule_get_session_owner(rule
) ? kCFBooleanTrue
: kCFBooleanFalse
);
946 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterAuthenticateUser
), rule_get_authenticate_user(rule
) ? kCFBooleanTrue
: kCFBooleanFalse
);
947 if (rule_check_flags(rule
, RuleFlagEntitledAndGroup
)) {
948 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterEntitledAndGroup
), kCFBooleanTrue
);
950 if (rule_check_flags(rule
, RuleFlagVPNEntitledAndGroup
)) {
951 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterVPNEntitledAndGroup
), kCFBooleanTrue
);
953 if (rule_get_extract_password(rule
)) {
954 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterExtractPassword
), kCFBooleanTrue
);
956 if (rule_get_password_only(rule
)) {
957 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterPasswordOnly
), kCFBooleanTrue
);
960 count
= CFArrayGetCount(rule
->mechanisms
);
962 array
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
963 for (i
= 0; i
< count
; i
++) {
964 mechanism_t mech
= (mechanism_t
)CFArrayGetValueAtIndex(rule
->mechanisms
, i
);
965 tmp
= CFStringCreateWithCString(kCFAllocatorDefault
, mechanism_get_string(mech
), kCFStringEncodingUTF8
);
966 CFArrayAppendValue(array
, tmp
);
969 CFDictionaryAddValue(dict
, CFSTR(kAuthorizationRuleParameterMechanisms
), array
);
974 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleClass
), CFSTR(kAuthorizationRightRule
));
975 int64_t kofn
= rule_get_kofn(rule
);
977 tmp
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt64Type
, &kofn
);
978 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterKofN
), tmp
);
982 count
= CFArrayGetCount(rule
->delegations
);
984 array
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
985 for (i
= 0; i
< count
; i
++) {
986 rule_t delegate
= (rule_t
)CFArrayGetValueAtIndex(rule
->delegations
, i
);
987 tmp
= CFStringCreateWithCString(kCFAllocatorDefault
, rule_get_name(delegate
), kCFStringEncodingUTF8
);
988 CFArrayAppendValue(array
, tmp
);
991 CFDictionaryAddValue(dict
, CFSTR(kAuthorizationRightRule
), array
);
996 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleClass
), CFSTR(kAuthorizationRuleClassMechanisms
));
998 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterCredentialShared
), rule_get_shared(rule
) ? kCFBooleanTrue
: kCFBooleanFalse
);
999 if (rule_get_extract_password(rule
)) {
1000 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleParameterExtractPassword
), kCFBooleanTrue
);
1003 n
= rule_get_tries(rule
);
1004 tmp
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt64Type
, &n
);
1005 CFDictionarySetValue(dict
, CFSTR("tries"), tmp
);
1008 count
= CFArrayGetCount(rule
->mechanisms
);
1010 array
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
1011 for (i
= 0; i
< count
; i
++) {
1012 mechanism_t mech
= (mechanism_t
)CFArrayGetValueAtIndex(rule
->mechanisms
, i
);
1013 tmp
= CFStringCreateWithCString(kCFAllocatorDefault
, mechanism_get_string(mech
), kCFStringEncodingUTF8
);
1014 CFArrayAppendValue(array
, tmp
);
1017 CFDictionaryAddValue(dict
, CFSTR(kAuthorizationRuleParameterMechanisms
), array
);
1022 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleClass
), CFSTR(kAuthorizationRuleClassDeny
));
1025 CFDictionarySetValue(dict
, CFSTR(kAuthorizationRuleClass
), CFSTR(kAuthorizationRuleClassAllow
));
1036 rule_get_mechanisms(rule_t rule
)
1038 return rule
->mechanisms
;
1042 rule_get_mechanisms_count(rule_t rule
)
1044 return (size_t)CFArrayGetCount(rule
->mechanisms
);
1048 rule_mechanisms_iterator(rule_t rule
, mechanism_iterator_t iter
)
1050 bool result
= false;
1052 CFIndex count
= CFArrayGetCount(rule
->mechanisms
);
1053 for (CFIndex i
= 0; i
< count
; i
++) {
1054 mechanism_t mech
= (mechanism_t
)CFArrayGetValueAtIndex(rule
->mechanisms
, i
);
1055 result
= iter(mech
);
1065 rule_get_delegates_count(rule_t rule
)
1067 return (size_t)CFArrayGetCount(rule
->delegations
);
1071 rule_delegates_iterator(rule_t rule
, delegate_iterator_t iter
)
1073 bool result
= false;
1075 CFIndex count
= CFArrayGetCount(rule
->delegations
);
1076 for (CFIndex i
= 0; i
< count
; i
++) {
1077 rule_t tmp
= (rule_t
)CFArrayGetValueAtIndex(rule
->delegations
, i
);
1088 rule_get_id(rule_t rule
)
1090 return auth_items_get_int64(rule
->data
, RULE_ID
);
1094 rule_get_name(rule_t rule
)
1096 return auth_items_get_string(rule
->data
, RULE_NAME
);
1100 rule_get_type(rule_t rule
)
1102 return (RuleType
)auth_items_get_int64(rule
->data
, RULE_TYPE
);
1106 rule_get_class(rule_t rule
)
1108 return (RuleClass
)auth_items_get_int64(rule
->data
, RULE_CLASS
);
1112 rule_get_group(rule_t rule
)
1114 return auth_items_get_string(rule
->data
, RULE_GROUP
);
1118 rule_get_kofn(rule_t rule
)
1120 return auth_items_get_int64(rule
->data
, RULE_KOFN
);
1124 rule_get_timeout(rule_t rule
)
1126 return auth_items_get_int64(rule
->data
, RULE_TIMEOUT
);
1130 rule_check_flags(rule_t rule
, RuleFlags flags
)
1132 return (auth_items_get_int64(rule
->data
, RULE_FLAGS
) & flags
) != 0;
1136 rule_get_shared(rule_t rule
)
1138 return rule_check_flags(rule
, RuleFlagShared
);
1142 rule_get_allow_root(rule_t rule
)
1144 return rule_check_flags(rule
, RuleFlagAllowRoot
);
1148 rule_get_session_owner(rule_t rule
)
1150 return rule_check_flags(rule
, RuleFlagSessionOwner
);
1154 rule_get_authenticate_user(rule_t rule
)
1156 return rule_check_flags(rule
, RuleFlagAuthenticateUser
);
1160 rule_get_extract_password(rule_t rule
)
1162 return rule_check_flags(rule
, RuleFlagExtractPassword
);
1166 rule_get_password_only(rule_t rule
)
1168 return rule_check_flags(rule
, RuleFlagPasswordOnly
);
1172 rule_get_tries(rule_t rule
)
1174 return auth_items_get_int64(rule
->data
, RULE_TRIES
);
1178 rule_get_comment(rule_t rule
)
1180 return auth_items_get_string(rule
->data
, RULE_COMMENT
);
1184 rule_get_version(rule_t rule
)
1186 return auth_items_get_int64(rule
->data
, RULE_VERSION
);
1189 double rule_get_created(rule_t rule
)
1191 return auth_items_get_double(rule
->data
, RULE_CREATED
);
1194 double rule_get_modified(rule_t rule
)
1196 return auth_items_get_double(rule
->data
, RULE_MODIFIED
);
1199 const char * rule_get_identifier(rule_t rule
)
1201 return auth_items_get_string(rule
->data
, RULE_IDENTIFIER
);
1204 CFDataRef
rule_get_requirement_data(rule_t rule
)
1206 if (!rule
->requirement_data
&& auth_items_exist(rule
->data
, RULE_REQUIREMENT
)) {
1208 const void * data
= auth_items_get_data(rule
->data
, RULE_REQUIREMENT
, &len
);
1209 rule
->requirement_data
= CFDataCreate(kCFAllocatorDefault
, data
, (CFIndex
)len
);
1212 return rule
->requirement_data
;
1215 SecRequirementRef
rule_get_requirement(rule_t rule
)
1217 if (!rule
->requirement
) {
1218 CFDataRef data
= rule_get_requirement_data(rule
);
1220 SecRequirementCreateWithData(data
, kSecCSDefaultFlags
, &rule
->requirement
);
1224 return rule
->requirement
;