1/* Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. */ 2 3#include "rule.h" 4#include "authutilities.h" 5#include "mechanism.h" 6#include "crc.h" 7#include "debugging.h" 8#include "authitems.h" 9#include "process.h" 10 11#include <Security/AuthorizationDB.h> 12#include <Security/AuthorizationTagsPriv.h> 13#include "server.h" 14 15static void _sql_get_id(rule_t,authdb_connection_t); 16static RuleClass _get_cf_rule_class(CFTypeRef); 17static bool _copy_cf_rule_mechanisms(rule_t,CFTypeRef,authdb_connection_t); 18static bool _copy_cf_rule_delegations(rule_t, CFTypeRef,authdb_connection_t); 19 20#define kMaximumAuthorizationTries 10000 21 22#define RULE_ID "id" 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" 38 39struct _rule_s { 40 __AUTH_BASE_STRUCT_HEADER__; 41 42 auth_items_t data; 43 CFMutableArrayRef mechanisms; 44 CFMutableArrayRef delegations; 45 46 CFMutableDictionaryRef loc_prompts; 47 CFMutableDictionaryRef loc_buttons; 48 49 CFDataRef requirement_data; 50 SecRequirementRef requirement; 51}; 52 53static void 54_rule_finalize(CFTypeRef value) 55{ 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); 64} 65 66static Boolean 67_rule_equal(CFTypeRef value1, CFTypeRef value2) 68{ 69 rule_t rule1 = (rule_t)value1; 70 rule_t rule2 = (rule_t)value2; 71 72 return strcasecmp(rule_get_name(rule1), rule_get_name(rule2)) == 0; 73} 74 75static CFStringRef 76_rule_copy_description(CFTypeRef value) 77{ 78 rule_t rule = (rule_t)value; 79 CFMutableStringRef str = CFStringCreateMutable(kCFAllocatorDefault, 0); 80 CFStringRef tmp = CFCopyDescription(rule->data); 81 CFStringAppend(str, tmp); 82 CFReleaseNull(tmp); 83 tmp = CFCopyDescription(rule->mechanisms); 84 CFStringAppend(str, tmp); 85 CFReleaseNull(tmp); 86 tmp = CFCopyDescription(rule->delegations); 87 CFStringAppend(str, tmp); 88 CFReleaseNull(tmp); 89 return str; 90} 91 92static CFHashCode 93_rule_hash(CFTypeRef value) 94{ 95 rule_t rule = (rule_t)value; 96 const char * str = rule_get_name(rule); 97 return crc64(str, strlen(str)); 98} 99 100AUTH_TYPE_INSTANCE(rule, 101 .init = NULL, 102 .copy = NULL, 103 .finalize = _rule_finalize, 104 .equal = _rule_equal, 105 .hash = _rule_hash, 106 .copyFormattingDesc = NULL, 107 .copyDebugDesc = _rule_copy_description 108 ); 109 110static CFTypeID rule_get_type_id() { 111 static CFTypeID type_id = _kCFRuntimeNotATypeID; 112 static dispatch_once_t onceToken; 113 114 dispatch_once(&onceToken, ^{ 115 type_id = _CFRuntimeRegisterClass(&_auth_type_rule); 116 }); 117 118 return type_id; 119} 120 121static rule_t 122_rule_create() 123{ 124 rule_t rule = (rule_t)_CFRuntimeCreateInstance(kCFAllocatorDefault, rule_get_type_id(), AUTH_CLASS_SIZE(rule), NULL); 125 require(rule != NULL, done); 126 127 rule->data = auth_items_create(); 128 rule->delegations = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); 129 rule->mechanisms = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); 130 131done: 132 return rule; 133} 134 135static rule_t 136_rule_create_with_sql(auth_items_t sql) 137{ 138 rule_t rule = NULL; 139 require(sql != NULL, done); 140 141 rule = _rule_create(); 142 require(rule != NULL, done); 143 144 auth_items_copy(rule->data, sql); 145 146done: 147 return rule; 148} 149 150rule_t 151rule_create_default() 152{ 153 rule_t rule = _rule_create(); 154 require(rule != NULL, done); 155 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); 163 164 mechanism_t mech = mechanism_create_with_string("builtin:authenticate", NULL); 165 CFArrayAppendValue(rule->mechanisms, mech); 166 CFReleaseNull(mech); 167 168 mech = mechanism_create_with_string("builtin:reset-password,privileged", NULL); 169 CFArrayAppendValue(rule->mechanisms, mech); 170 CFReleaseNull(mech); 171 172 mech = mechanism_create_with_string("builtin:authenticate,privileged", NULL); 173 CFArrayAppendValue(rule->mechanisms, mech); 174 CFReleaseNull(mech); 175 176 mech = mechanism_create_with_string("PKINITMechanism:auth,privileged", NULL); 177 CFArrayAppendValue(rule->mechanisms, mech); 178 CFReleaseNull(mech); 179 180done: 181 return rule; 182} 183 184rule_t 185rule_create_with_string(const char * str, authdb_connection_t dbconn) 186{ 187 rule_t rule = NULL; 188 require(str != NULL, done); 189 190 rule = _rule_create(); 191 require(rule != NULL, done); 192 193 auth_items_set_string(rule->data, RULE_NAME, str); 194 195 if (dbconn) { 196 rule_sql_fetch(rule, dbconn); 197 } 198 199done: 200 return rule; 201} 202 203static void _set_data_string(rule_t rule, const char * key, CFStringRef str) 204{ 205 char * tmpStr = _copy_cf_string(str, NULL); 206 207 if (tmpStr) { 208 auth_items_set_string(rule->data, key, tmpStr); 209 free_safe(tmpStr); 210 } 211} 212 213rule_t 214rule_create_with_plist(RuleType type, CFStringRef name, CFDictionaryRef plist, authdb_connection_t dbconn) 215{ 216 rule_t rule = NULL; 217 require(name != NULL, done); 218 require(plist != NULL, done); 219 220 rule = _rule_create(); 221 require(rule != NULL, done); 222 223 _set_data_string(rule, RULE_NAME, name); 224 require_action(rule_get_name(rule) != NULL, done, CFReleaseSafe(rule)); 225 226 _sql_get_id(rule, dbconn); 227 228 auth_items_set_int64(rule->data, RULE_TYPE, type); 229 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))); 232 233 234 CFTypeRef loc_tmp = CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterDefaultPrompt)); 235 if (loc_tmp) { 236 rule->loc_prompts = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, loc_tmp); 237 } 238 loc_tmp = CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterDefaultButton)); 239 if (loc_tmp) { 240 rule->loc_buttons = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, loc_tmp); 241 } 242 243 auth_items_set_int64(rule->data, RULE_VERSION, _get_cf_int(CFDictionaryGetValue(plist, CFSTR("version")), 0)); 244 245 RuleFlags flags = 0; 246 247 if (_get_cf_bool(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterEntitled)), false)) { 248 flags |= RuleFlagEntitled; 249 } 250 251 if (_get_cf_bool(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterRequireAppleSigned)), false)) { 252 flags |= RuleFlagRequireAppleSigned; 253 } 254 255 switch (rule_get_class(rule)) { 256 case RC_USER: 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)); 260 261 if (_get_cf_bool(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterCredentialShared)), false)) { 262 flags |= RuleFlagShared; 263 } 264 if (_get_cf_bool(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterAllowRoot)), false)) { 265 flags |= RuleFlagAllowRoot; 266 } 267 if (_get_cf_bool(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterCredentialSessionOwner)), false)) { 268 flags |= RuleFlagSessionOwner; 269 } 270 if (_get_cf_bool(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterAuthenticateUser)), true)) { 271 flags |= RuleFlagAuthenticateUser; 272 } 273 if (_get_cf_bool(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterExtractPassword)), false)) { 274 flags |= RuleFlagExtractPassword; 275 } 276 if (_get_cf_bool(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterEntitledAndGroup)), false)) { 277 flags |= RuleFlagEntitledAndGroup; 278 } 279 if (_get_cf_bool(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterVPNEntitledAndGroup)), false)) { 280 flags |= RuleFlagVPNEntitledAndGroup; 281 } 282 283 _copy_cf_rule_mechanisms(rule, CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterMechanisms)), dbconn); 284 285 break; 286 case RC_RULE: 287 auth_items_set_int64(rule->data, RULE_KOFN, _get_cf_int(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterKofN)), 0)); 288 289 _copy_cf_rule_delegations(rule, CFDictionaryGetValue(plist, CFSTR(kAuthorizationRightRule)), dbconn); 290 break; 291 case RC_MECHANISM: 292 auth_items_set_int64(rule->data, RULE_TRIES, _get_cf_int(CFDictionaryGetValue(plist, CFSTR("tries")), kMaximumAuthorizationTries)); 293 if (_get_cf_bool(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterCredentialShared)), true)) { 294 flags |= RuleFlagShared; 295 } 296 if (_get_cf_bool(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterExtractPassword)), false)) { 297 flags |= RuleFlagExtractPassword; 298 } 299 300 _copy_cf_rule_mechanisms(rule, CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterMechanisms)), dbconn); 301 302 break; 303 case RC_DENY: 304 break; 305 case RC_ALLOW: 306 break; 307 default: 308 LOGD("rule: invalid rule class"); 309 break; 310 } 311 312 auth_items_set_int64(rule->data, RULE_FLAGS, flags); 313 314done: 315 return rule; 316} 317 318static void 319_sql_get_id(rule_t rule, authdb_connection_t dbconn) 320{ 321 authdb_step(dbconn, "SELECT id,created,identifier,requirement FROM rules WHERE name = ? LIMIT 1", 322 ^(sqlite3_stmt *stmt) { 323 sqlite3_bind_text(stmt, 1, rule_get_name(rule), -1, NULL); 324 }, ^bool(auth_items_t data) { 325 auth_items_copy(rule->data, data); 326 return true; 327 }); 328} 329 330static bool 331_copy_cf_rule_delegations(rule_t rule, CFTypeRef value, authdb_connection_t dbconn) 332{ 333 bool result = false; 334 char * tmp_str = NULL; 335 require(value != NULL, done); 336 337 if (CFGetTypeID(value) == CFStringGetTypeID()) { 338 tmp_str = _copy_cf_string(value, NULL); 339 rule_t delegate = rule_create_with_string(tmp_str, dbconn); 340 free_safe(tmp_str); 341 if (delegate) { 342 CFArrayAppendValue(rule->delegations, delegate); 343 CFReleaseSafe(delegate); 344 } 345 } else { //array 346 CFIndex count = CFArrayGetCount(value); 347 for (CFIndex i = 0; i < count; i++) { 348 tmp_str = _copy_cf_string(CFArrayGetValueAtIndex(value,i), NULL); 349 rule_t delegate = rule_create_with_string(tmp_str, dbconn); 350 free_safe(tmp_str); 351 if (delegate) { 352 CFArrayAppendValue(rule->delegations, delegate); 353 CFReleaseSafe(delegate); 354 } 355 } 356 } 357 358 result = true; 359 360done: 361 return result; 362} 363 364static bool 365_copy_cf_rule_mechanisms(rule_t rule, CFTypeRef array, authdb_connection_t dbconn) 366{ 367 bool result = false; 368 require(array != NULL, done); 369 require(CFGetTypeID(array) == CFArrayGetTypeID(), done); 370 371 CFIndex count = CFArrayGetCount(array); 372 for (CFIndex i = 0; i < count; i++) { 373 mechanism_t mech = NULL; 374 char * string = _copy_cf_string(CFArrayGetValueAtIndex(array, i), NULL); 375 376 if (!string) 377 continue; 378 379 mech = mechanism_create_with_string(string, dbconn); 380 if (mech) { 381 CFArrayAppendValue(rule->mechanisms, mech); 382 CFReleaseSafe(mech); 383 } 384 free(string); 385 } 386 387 result = true; 388 389done: 390 return result; 391} 392 393static RuleClass 394_get_cf_rule_class(CFTypeRef str) 395{ 396 RuleClass rc = RC_RULE; 397 require(str != NULL, done); 398 require(CFGetTypeID(str) == CFStringGetTypeID(), done); 399 400 if (CFEqual(str, CFSTR(kAuthorizationRuleClassUser))) 401 return RC_USER; 402 403 if (CFEqual(str, CFSTR(kAuthorizationRightRule))) 404 return RC_RULE; 405 406 if (CFEqual(str, CFSTR(kAuthorizationRuleClassMechanisms))) 407 return RC_MECHANISM; 408 409 if (CFEqual(str, CFSTR(kAuthorizationRuleClassDeny))) 410 return RC_DENY; 411 412 if (CFEqual(str, CFSTR(kAuthorizationRuleClassAllow))) 413 return RC_ALLOW; 414 415done: 416 return rc; 417} 418 419static bool 420_sql_bind(rule_t rule, sqlite3_stmt * stmt) 421{ 422 int64_t n; 423 int32_t rc = 0; 424 require(stmt != NULL, err); 425 426 int32_t column = 1; 427 rc = sqlite3_bind_text(stmt, column++, rule_get_name(rule), -1, NULL); 428 require_noerr(rc, err); 429 rc = sqlite3_bind_int(stmt, column++, rule_get_type(rule)); 430 require_noerr(rc, err); 431 rc = sqlite3_bind_int(stmt, column++, rule_get_class(rule)); 432 require_noerr(rc, err); 433 434 switch (rule_get_class(rule)) { 435 case RC_USER: 436 rc = sqlite3_bind_text(stmt, column++, rule_get_group(rule), -1, NULL); 437 require_noerr(rc, err); 438 rc = sqlite3_bind_null(stmt, column++); // kofn 439 require_noerr(rc, err); 440 rc = sqlite3_bind_int64(stmt, column++, rule_get_timeout(rule)); 441 require_noerr(rc, err); 442 rc = sqlite3_bind_int64(stmt, column++, auth_items_get_int64(rule->data, RULE_FLAGS)); 443 require_noerr(rc, err); 444 rc = sqlite3_bind_int64(stmt, column++, rule_get_tries(rule)); 445 require_noerr(rc, err); 446 break; 447 case RC_RULE: 448 rc = sqlite3_bind_null(stmt, column++); // group 449 require_noerr(rc, err); 450 n = rule_get_kofn(rule); 451 if (n) { 452 rc = sqlite3_bind_int64(stmt, column++, n); 453 } else { 454 rc = sqlite3_bind_null(stmt, column++); 455 } 456 require_noerr(rc, err); 457 rc = sqlite3_bind_null(stmt, column++); // timeout 458 require_noerr(rc, err); 459 rc = sqlite3_bind_int64(stmt, column++, auth_items_get_int64(rule->data, RULE_FLAGS)); 460 require_noerr(rc, err); 461 rc = sqlite3_bind_null(stmt, column++); // tries 462 require_noerr(rc, err); 463 break; 464 case RC_MECHANISM: 465 rc = sqlite3_bind_null(stmt, column++); // group 466 require_noerr(rc, err); 467 rc = sqlite3_bind_null(stmt, column++); // kofn 468 require_noerr(rc, err); 469 rc = sqlite3_bind_null(stmt, column++); // timeout 470 require_noerr(rc, err); 471 rc = sqlite3_bind_int64(stmt, column++, auth_items_get_int64(rule->data, RULE_FLAGS)); 472 require_noerr(rc, err); 473 rc = sqlite3_bind_int64(stmt, column++, rule_get_tries(rule)); 474 require_noerr(rc, err); 475 break; 476 case RC_DENY: 477 case RC_ALLOW: 478 rc = sqlite3_bind_null(stmt, column++); // group 479 require_noerr(rc, err); 480 rc = sqlite3_bind_null(stmt, column++); // kofn 481 require_noerr(rc, err); 482 rc = sqlite3_bind_null(stmt, column++); // timeout 483 require_noerr(rc, err); 484 rc = sqlite3_bind_int64(stmt, column++, auth_items_get_int64(rule->data, RULE_FLAGS)); 485 require_noerr(rc, err); 486 rc = sqlite3_bind_null(stmt, column++); // tries 487 require_noerr(rc, err); 488 break; 489 default: 490 LOGD("rule: sql bind, invalid rule class"); 491 break; 492 } 493 494 rc = sqlite3_bind_int64(stmt, column++, rule_get_version(rule)); // version 495 require_noerr(rc, err); 496 rc = sqlite3_bind_double(stmt, column++, rule_get_created(rule)); // created 497 require_noerr(rc, err); 498 rc = sqlite3_bind_double(stmt, column++, rule_get_modified(rule)); // modified 499 require_noerr(rc, err); 500 rc = sqlite3_bind_null(stmt, column++); // hash 501 require_noerr(rc, err); 502 rc = sqlite3_bind_text(stmt, column++, rule_get_identifier(rule), -1, NULL); 503 require_noerr(rc, err); 504 505 CFDataRef data = rule_get_requirment_data(rule); 506 if (data) { 507 rc = sqlite3_bind_blob(stmt, column++, CFDataGetBytePtr(data), (int32_t)CFDataGetLength(data), NULL); 508 } else { 509 rc = sqlite3_bind_null(stmt, column++); 510 } 511 require_noerr(rc, err); 512 513 rc = sqlite3_bind_text(stmt, column++, rule_get_comment(rule), -1, NULL); 514 require_noerr(rc, err); 515 516 return true; 517 518err: 519 LOGD("rule: sql bind, error %i", rc); 520 return false; 521} 522 523static void 524_get_sql_mechanisms(rule_t rule, authdb_connection_t dbconn) 525{ 526 CFArrayRemoveAllValues(rule->mechanisms); 527 528 authdb_step(dbconn, "SELECT mechanisms.* " \ 529 "FROM mechanisms " \ 530 "JOIN mechanisms_map ON mechanisms.id = mechanisms_map.m_id " \ 531 "WHERE mechanisms_map.r_id = ? ORDER BY mechanisms_map.ord ASC", 532 ^(sqlite3_stmt *stmt) { 533 sqlite3_bind_int64(stmt, 1, rule_get_id(rule)); 534 }, ^bool(auth_items_t data) { 535 mechanism_t mechanism = mechanism_create_with_sql(data); 536 CFArrayAppendValue(rule->mechanisms, mechanism); 537 CFReleaseSafe(mechanism); 538 return true; 539 }); 540} 541 542static void 543_get_sql_delegates(rule_t rule, authdb_connection_t dbconn) 544{ 545 CFArrayRemoveAllValues(rule->delegations); 546 547 authdb_step(dbconn, "SELECT rules.* " \ 548 "FROM rules " \ 549 "JOIN delegates_map ON rules.id = delegates_map.d_id " \ 550 "WHERE delegates_map.r_id = ? ORDER BY delegates_map.ord ASC", 551 ^(sqlite3_stmt *stmt) { 552 sqlite3_bind_int64(stmt, 1, rule_get_id(rule)); 553 }, ^bool(auth_items_t data) { 554 rule_t delegate = _rule_create_with_sql(data); 555 if (delegate) { 556 _get_sql_mechanisms(delegate, dbconn); 557 558 if (rule_get_class(rule) == RC_RULE) { 559 _get_sql_delegates(delegate, dbconn); 560 } 561 562 CFArrayAppendValue(rule->delegations, delegate); 563 CFReleaseSafe(delegate); 564 } 565 return true; 566 }); 567} 568 569bool 570rule_sql_fetch(rule_t rule, authdb_connection_t dbconn) 571{ 572 __block bool result = false; 573 574 authdb_step(dbconn, "SELECT * FROM rules WHERE name = ? LIMIT 1", 575 ^(sqlite3_stmt *stmt) { 576 sqlite3_bind_text(stmt, 1, rule_get_name(rule), -1, NULL); 577 }, ^bool(auth_items_t data) { 578 result = true; 579 auth_items_copy(rule->data, data); 580 return true; 581 }); 582 583 if (rule_get_id(rule) != 0) { 584 _get_sql_mechanisms(rule,dbconn); 585 586 if (rule_get_class(rule) == RC_RULE) { 587 _get_sql_delegates(rule, dbconn); 588 } 589 } 590 591 return result; 592} 593 594static bool 595_sql_update(rule_t rule, authdb_connection_t dbconn) 596{ 597 bool result = false; 598 599 result = authdb_step(dbconn, "UPDATE rules " \ 600 "SET name=?,type=?,class=?,'group'=?,kofn=?,timeout=?,flags=?,tries=?,version=?,created=?,modified=?,hash=?,identifier=?,requirement=?,comment=? " \ 601 "WHERE id = ?", 602 ^(sqlite3_stmt *stmt) { 603 _sql_bind(rule, stmt); 604 sqlite3_bind_int64(stmt, sqlite3_bind_parameter_count(stmt), rule_get_id(rule)); 605 }, NULL); 606 return result; 607} 608 609static bool 610_sql_insert(rule_t rule, authdb_connection_t dbconn) 611{ 612 bool result = false; 613 614 result = authdb_step(dbconn, "INSERT INTO rules VALUES (NULL,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", 615 ^(sqlite3_stmt *stmt) { 616 _sql_bind(rule, stmt); 617 }, NULL); 618 return result; 619} 620 621static bool 622_sql_commit_mechanisms_map(rule_t rule, authdb_connection_t dbconn) 623{ 624 bool result = false; 625 626 result = authdb_step(dbconn, "DELETE FROM mechanisms_map WHERE r_id = ?", ^(sqlite3_stmt *stmt) { 627 sqlite3_bind_int64(stmt, 1, rule_get_id(rule)); 628 }, NULL); 629 require(result == true, done); 630 631 CFIndex count = CFArrayGetCount(rule->mechanisms); 632 for(CFIndex i = 0; i < count; i++) { 633 mechanism_t mech = (mechanism_t)CFArrayGetValueAtIndex(rule->mechanisms, i); 634 result = authdb_step(dbconn, "INSERT INTO mechanisms_map VALUES (?,?,?)", ^(sqlite3_stmt *stmt) { 635 sqlite3_bind_int64(stmt, 1, rule_get_id(rule)); 636 sqlite3_bind_int64(stmt, 2, mechanism_get_id(mech)); 637 sqlite3_bind_int64(stmt, 3, i); 638 }, NULL); 639 require(result == true, done); 640 } 641 642done: 643 return result; 644} 645 646static bool 647_sql_commit_delegates_map(rule_t rule, authdb_connection_t dbconn) 648{ 649 bool result = false; 650 651 result = authdb_step(dbconn, "DELETE FROM delegates_map WHERE r_id = ?", ^(sqlite3_stmt *stmt) { 652 sqlite3_bind_int64(stmt, 1, rule_get_id(rule)); 653 }, NULL); 654 require(result == true, done); 655 656 CFIndex count = CFArrayGetCount(rule->delegations); 657 for(CFIndex i = 0; i < count; i++) { 658 rule_t delegate = (rule_t)CFArrayGetValueAtIndex(rule->delegations, i); 659 result = authdb_step(dbconn, "INSERT INTO delegates_map VALUES (?,?,?)", ^(sqlite3_stmt *stmt) { 660 sqlite3_bind_int64(stmt, 1, rule_get_id(rule)); 661 sqlite3_bind_int64(stmt, 2, rule_get_id(delegate)); 662 sqlite3_bind_int64(stmt, 3, i); 663 }, NULL); 664 require(result == true, done); 665 } 666 667done: 668 return result; 669} 670 671static void 672_sql_commit_localization(rule_t rule, authdb_connection_t dbconn) 673{ 674 675 authdb_step(dbconn, "DELETE FROM prompts WHERE r_id = ?", ^(sqlite3_stmt *stmt) { 676 sqlite3_bind_int64(stmt, 1, rule_get_id(rule)); 677 }, NULL); 678 679 authdb_step(dbconn, "DELETE FROM buttons WHERE r_id = ?", ^(sqlite3_stmt *stmt) { 680 sqlite3_bind_int64(stmt, 1, rule_get_id(rule)); 681 }, NULL); 682 683 if (rule->loc_prompts) { 684 _cf_dictionary_iterate(rule->loc_prompts, ^bool(CFTypeRef key, CFTypeRef value) { 685 char * lang = _copy_cf_string(key, NULL); 686 char * str = _copy_cf_string(value, NULL); 687 688 authdb_step(dbconn, "INSERT INTO prompts VALUES (?,?,?)", ^(sqlite3_stmt *stmt) { 689 sqlite3_bind_int64(stmt, 1, rule_get_id(rule)); 690 sqlite3_bind_text(stmt, 2, lang, -1, NULL); 691 sqlite3_bind_text(stmt, 3, str, -1, NULL); 692 }, NULL); 693 694 free_safe(lang); 695 free_safe(str); 696 697 return true; 698 }); 699 } 700 701 if (rule->loc_buttons) { 702 _cf_dictionary_iterate(rule->loc_buttons, ^bool(CFTypeRef key, CFTypeRef value) { 703 char * lang = _copy_cf_string(key, NULL); 704 char * str = _copy_cf_string(value, NULL); 705 706 authdb_step(dbconn, "INSERT INTO buttons VALUES (?,?,?)", ^(sqlite3_stmt *stmt) { 707 sqlite3_bind_int64(stmt, 1, rule_get_id(rule)); 708 sqlite3_bind_text(stmt, 2, lang, -1, NULL); 709 sqlite3_bind_text(stmt, 3, str, -1, NULL); 710 }, NULL); 711 712 free_safe(lang); 713 free_safe(str); 714 return true; 715 }); 716 } 717 718} 719 720bool 721rule_sql_commit(rule_t rule, authdb_connection_t dbconn, CFAbsoluteTime modified, process_t proc) 722{ 723 bool result = false; 724 // type and class required else rule is name only? 725 RuleClass rule_class = rule_get_class(rule); 726 require(rule_get_type(rule) != 0, done); 727 require(rule_class != 0, done); 728 729 CFIndex mechCount = 0; 730 if (rule_class == RC_USER || rule_class == RC_MECHANISM) { 731 // Validate mechanisms 732 mechCount = CFArrayGetCount(rule->mechanisms); 733 for (CFIndex i = 0; i < mechCount; i++) { 734 mechanism_t mech = (mechanism_t)CFArrayGetValueAtIndex(rule->mechanisms, i); 735 if (mechanism_get_id(mech) == 0) { 736 if (!mechanism_sql_fetch(mech, dbconn)) { 737 mechanism_sql_commit(mech, dbconn); 738 mechanism_sql_fetch(mech, dbconn); 739 } 740 } 741 if (!mechanism_exists(mech)) { 742 LOGE("Warning mechanism not found on disk %s during import of %s", mechanism_get_string(mech), rule_get_name(rule)); 743 } 744 require_action(mechanism_get_id(mech) != 0, done, LOGE("rule: commit, invalid mechanism %s:%s for %s", mechanism_get_plugin(mech), mechanism_get_param(mech), rule_get_name(rule))); 745 } 746 } 747 748 CFIndex delegateCount = 0; 749 if (rule_class == RC_RULE) { 750 // Validate delegates 751 delegateCount = CFArrayGetCount(rule->delegations); 752 for (CFIndex i = 0; i < delegateCount; i++) { 753 rule_t delegate = (rule_t)CFArrayGetValueAtIndex(rule->delegations, i); 754 if (rule_get_id(delegate) == 0) { 755 rule_sql_fetch(delegate, dbconn); 756 } 757 require_action(rule_get_id(delegate) != 0, done, LOGE("rule: commit, missing delegate %s for %s", rule_get_name(delegate), rule_get_name(rule))); 758 } 759 } 760 761 auth_items_set_double(rule->data, RULE_MODIFIED, modified); 762 763 result = authdb_transaction(dbconn, AuthDBTransactionNormal, ^bool{ 764 bool update = false; 765 766 if (rule_get_id(rule)) { 767 update = _sql_update(rule, dbconn); 768 } else { 769 if (proc) { 770 const char * ident = process_get_identifier(proc); 771 if (ident) { 772 auth_items_set_string(rule->data, RULE_IDENTIFIER, ident); 773 } 774 CFDataRef req = process_get_requirement_data(proc); 775 if (req) { 776 auth_items_set_data(rule->data, RULE_REQUIREMENT, CFDataGetBytePtr(req), (size_t)CFDataGetLength(req)); 777 } 778 } 779 auth_items_set_double(rule->data, RULE_CREATED, modified); 780 update = _sql_insert(rule, dbconn); 781 _sql_get_id(rule, dbconn); 782 } 783 784 _sql_commit_localization(rule, dbconn); 785 786 if (update) { 787 update = _sql_commit_mechanisms_map(rule, dbconn); 788 } 789 790 if (update) { 791 update = _sql_commit_delegates_map(rule,dbconn); 792 } 793 794 return update; 795 }); 796 797 798done: 799 if (!result) { 800 LOGV("rule: commit, failed for %s (%llu)", rule_get_name(rule), rule_get_id(rule)); 801 } 802 return result; 803} 804 805bool 806rule_sql_remove(rule_t rule, authdb_connection_t dbconn) 807{ 808 bool result = false; 809 int64_t id = rule_get_id(rule); 810 811 if (id == 0) { 812 rule_sql_fetch(rule, dbconn); 813 id = rule_get_id(rule); 814 require(id != 0, done); 815 } 816 817 result = authdb_step(dbconn, "DELETE FROM rules WHERE id = ?", 818 ^(sqlite3_stmt *stmt) { 819 sqlite3_bind_int64(stmt, 1, id); 820 }, NULL); 821done: 822 return result; 823} 824 825CFMutableDictionaryRef 826rule_copy_to_cfobject(rule_t rule, authdb_connection_t dbconn) { 827 CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 828 829 CFTypeRef tmp = NULL; 830 CFMutableArrayRef array = NULL; 831 CFIndex count = 0; 832 CFIndex i = 0; 833 int64_t n; 834 double d; 835 836 const char * comment = rule_get_comment(rule); 837 if (comment) { 838 tmp = CFStringCreateWithCString(kCFAllocatorDefault, comment, kCFStringEncodingUTF8); 839 CFDictionarySetValue(dict, CFSTR(kAuthorizationComment), tmp); 840 CFReleaseSafe(tmp); 841 } 842 843 n = rule_get_version(rule); 844 tmp = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &n); 845 CFDictionarySetValue(dict, CFSTR(RULE_VERSION), tmp); 846 CFReleaseSafe(tmp); 847 848 d = rule_get_created(rule); 849 tmp = CFNumberCreate(kCFAllocatorDefault, kCFNumberFloat64Type, &d); 850 CFDictionarySetValue(dict, CFSTR(RULE_CREATED), tmp); 851 CFReleaseSafe(tmp); 852 853 d = rule_get_modified(rule); 854 tmp = CFNumberCreate(kCFAllocatorDefault, kCFNumberFloat64Type, &d); 855 CFDictionarySetValue(dict, CFSTR(RULE_MODIFIED), tmp); 856 CFReleaseSafe(tmp); 857 858 const char * identifier = rule_get_identifier(rule); 859 if (identifier) { 860 tmp = CFStringCreateWithCString(kCFAllocatorDefault, identifier, kCFStringEncodingUTF8); 861 CFDictionarySetValue(dict, CFSTR(RULE_IDENTIFIER), tmp); 862 CFReleaseSafe(tmp); 863 } 864 865 SecRequirementRef req = rule_get_requirment(rule); 866 if (req) { 867 CFStringRef reqStr = NULL; 868 SecRequirementCopyString(req, kSecCSDefaultFlags, &reqStr); 869 if (reqStr) { 870 CFDictionarySetValue(dict, CFSTR(RULE_REQUIREMENT), reqStr); 871 CFReleaseSafe(reqStr); 872 } 873 } 874 875 if (rule_check_flags(rule, RuleFlagEntitled)) { 876 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterEntitled), kCFBooleanTrue); 877 } 878 879 if (rule_check_flags(rule, RuleFlagRequireAppleSigned)) { 880 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterRequireAppleSigned), kCFBooleanTrue); 881 } 882 883 if (rule_get_type(rule) == RT_RIGHT) { 884 CFMutableDictionaryRef prompts = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 885 authdb_step(dbconn, "SELECT * FROM prompts WHERE r_id = ?", ^(sqlite3_stmt *stmt) { 886 sqlite3_bind_int64(stmt, 1, rule_get_id(rule)); 887 }, ^bool(auth_items_t data) { 888 CFStringRef key = CFStringCreateWithCString(kCFAllocatorDefault, auth_items_get_string(data, "lang"), kCFStringEncodingUTF8); 889 CFStringRef value = CFStringCreateWithCString(kCFAllocatorDefault, auth_items_get_string(data, "value"), kCFStringEncodingUTF8); 890 CFDictionaryAddValue(prompts, key, value); 891 CFReleaseSafe(key); 892 CFReleaseSafe(value); 893 return true; 894 }); 895 896 if (CFDictionaryGetCount(prompts)) { 897 CFDictionaryAddValue(dict, CFSTR(kAuthorizationRuleParameterDefaultPrompt), prompts); 898 } 899 CFReleaseSafe(prompts); 900 901 CFMutableDictionaryRef buttons = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 902 authdb_step(dbconn, "SELECT * FROM buttons WHERE r_id = ?", ^(sqlite3_stmt *stmt) { 903 sqlite3_bind_int64(stmt, 1, rule_get_id(rule)); 904 }, ^bool(auth_items_t data) { 905 CFStringRef key = CFStringCreateWithCString(kCFAllocatorDefault, auth_items_get_string(data, "lang"), kCFStringEncodingUTF8); 906 CFStringRef value = CFStringCreateWithCString(kCFAllocatorDefault, auth_items_get_string(data, "value"), kCFStringEncodingUTF8); 907 CFDictionaryAddValue(buttons, key, value); 908 CFReleaseSafe(key); 909 CFReleaseSafe(value); 910 return true; 911 }); 912 913 if (CFDictionaryGetCount(buttons)) { 914 CFDictionaryAddValue(dict, CFSTR(kAuthorizationRuleParameterDefaultButton), buttons); 915 } 916 CFReleaseSafe(buttons); 917 } 918 919 switch (rule_get_class(rule)) { 920 case RC_USER: 921 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleClass), CFSTR(kAuthorizationRuleClassUser)); 922 923 const char * group = rule_get_group(rule); 924 if (group) { 925 tmp = CFStringCreateWithCString(kCFAllocatorDefault, group, kCFStringEncodingUTF8); 926 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterGroup), tmp); 927 CFReleaseSafe(tmp); 928 } 929 930 n = rule_get_timeout(rule); 931 tmp = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &n); 932 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterCredentialTimeout), tmp); 933 CFReleaseSafe(tmp); 934 935 n = rule_get_tries(rule); 936 tmp = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &n); 937 CFDictionarySetValue(dict, CFSTR("tries"), tmp); 938 CFReleaseSafe(tmp); 939 940 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterCredentialShared), rule_get_shared(rule) ? kCFBooleanTrue : kCFBooleanFalse); 941 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterAllowRoot), rule_get_allow_root(rule) ? kCFBooleanTrue : kCFBooleanFalse); 942 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterCredentialSessionOwner), rule_get_session_owner(rule) ? kCFBooleanTrue : kCFBooleanFalse); 943 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterAuthenticateUser), rule_get_authenticate_user(rule) ? kCFBooleanTrue : kCFBooleanFalse); 944 if (rule_check_flags(rule, RuleFlagEntitledAndGroup)) { 945 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterEntitledAndGroup), kCFBooleanTrue); 946 } 947 if (rule_check_flags(rule, RuleFlagVPNEntitledAndGroup)) { 948 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterVPNEntitledAndGroup), kCFBooleanTrue); 949 } 950 if (rule_get_extract_password(rule)) { 951 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterExtractPassword), kCFBooleanTrue); 952 } 953 954 count = CFArrayGetCount(rule->mechanisms); 955 if (count) { 956 array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); 957 for (i = 0; i < count; i++) { 958 mechanism_t mech = (mechanism_t)CFArrayGetValueAtIndex(rule->mechanisms, i); 959 tmp = CFStringCreateWithCString(kCFAllocatorDefault, mechanism_get_string(mech), kCFStringEncodingUTF8); 960 CFArrayAppendValue(array, tmp); 961 CFReleaseSafe(tmp); 962 } 963 CFDictionaryAddValue(dict, CFSTR(kAuthorizationRuleParameterMechanisms), array); 964 CFRelease(array); 965 } 966 break; 967 case RC_RULE: 968 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleClass), CFSTR(kAuthorizationRightRule)); 969 int64_t kofn = rule_get_kofn(rule); 970 if (kofn) { 971 tmp = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &kofn); 972 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterKofN), tmp); 973 CFReleaseSafe(tmp); 974 } 975 976 count = CFArrayGetCount(rule->delegations); 977 if (count) { 978 array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); 979 for (i = 0; i < count; i++) { 980 rule_t delegate = (rule_t)CFArrayGetValueAtIndex(rule->delegations, i); 981 tmp = CFStringCreateWithCString(kCFAllocatorDefault, rule_get_name(delegate), kCFStringEncodingUTF8); 982 CFArrayAppendValue(array, tmp); 983 CFReleaseSafe(tmp); 984 } 985 CFDictionaryAddValue(dict, CFSTR(kAuthorizationRightRule), array); 986 CFRelease(array); 987 } 988 break; 989 case RC_MECHANISM: 990 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleClass), CFSTR(kAuthorizationRuleClassMechanisms)); 991 992 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterCredentialShared), rule_get_shared(rule) ? kCFBooleanTrue : kCFBooleanFalse); 993 if (rule_get_extract_password(rule)) { 994 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterExtractPassword), kCFBooleanTrue); 995 } 996 997 n = rule_get_tries(rule); 998 tmp = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &n); 999 CFDictionarySetValue(dict, CFSTR("tries"), tmp); 1000 CFReleaseSafe(tmp); 1001 1002 count = CFArrayGetCount(rule->mechanisms); 1003 if (count) { 1004 array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); 1005 for (i = 0; i < count; i++) { 1006 mechanism_t mech = (mechanism_t)CFArrayGetValueAtIndex(rule->mechanisms, i); 1007 tmp = CFStringCreateWithCString(kCFAllocatorDefault, mechanism_get_string(mech), kCFStringEncodingUTF8); 1008 CFArrayAppendValue(array, tmp); 1009 CFReleaseSafe(tmp); 1010 } 1011 CFDictionaryAddValue(dict, CFSTR(kAuthorizationRuleParameterMechanisms), array); 1012 CFRelease(array); 1013 } 1014 break; 1015 case RC_DENY: 1016 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleClass), CFSTR(kAuthorizationRuleClassDeny)); 1017 break; 1018 case RC_ALLOW: 1019 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleClass), CFSTR(kAuthorizationRuleClassAllow)); 1020 break; 1021 default: 1022 break; 1023 } 1024 1025 return dict; 1026} 1027 1028 1029CFArrayRef 1030rule_get_mechanisms(rule_t rule) 1031{ 1032 return rule->mechanisms; 1033} 1034 1035size_t 1036rule_get_mechanisms_count(rule_t rule) 1037{ 1038 return (size_t)CFArrayGetCount(rule->mechanisms); 1039} 1040 1041bool 1042rule_mechanisms_iterator(rule_t rule, mechanism_iterator_t iter) 1043{ 1044 bool result = false; 1045 1046 CFIndex count = CFArrayGetCount(rule->mechanisms); 1047 for (CFIndex i = 0; i < count; i++) { 1048 mechanism_t mech = (mechanism_t)CFArrayGetValueAtIndex(rule->mechanisms, i); 1049 result = iter(mech); 1050 if (!result) { 1051 break; 1052 } 1053 } 1054 1055 return result; 1056} 1057 1058size_t 1059rule_get_delegates_count(rule_t rule) 1060{ 1061 return (size_t)CFArrayGetCount(rule->delegations); 1062} 1063 1064bool 1065rule_delegates_iterator(rule_t rule, delegate_iterator_t iter) 1066{ 1067 bool result = false; 1068 1069 CFIndex count = CFArrayGetCount(rule->delegations); 1070 for (CFIndex i = 0; i < count; i++) { 1071 rule_t tmp = (rule_t)CFArrayGetValueAtIndex(rule->delegations, i); 1072 result = iter(tmp); 1073 if (!result) { 1074 break; 1075 } 1076 } 1077 1078 return result; 1079} 1080 1081int64_t 1082rule_get_id(rule_t rule) 1083{ 1084 return auth_items_get_int64(rule->data, RULE_ID); 1085} 1086 1087const char * 1088rule_get_name(rule_t rule) 1089{ 1090 return auth_items_get_string(rule->data, RULE_NAME); 1091} 1092 1093RuleType 1094rule_get_type(rule_t rule) 1095{ 1096 return (RuleType)auth_items_get_int64(rule->data, RULE_TYPE); 1097} 1098 1099RuleClass 1100rule_get_class(rule_t rule) 1101{ 1102 return (RuleClass)auth_items_get_int64(rule->data, RULE_CLASS); 1103} 1104 1105const char * 1106rule_get_group(rule_t rule) 1107{ 1108 return auth_items_get_string(rule->data, RULE_GROUP); 1109} 1110 1111int64_t 1112rule_get_kofn(rule_t rule) 1113{ 1114 return auth_items_get_int64(rule->data, RULE_KOFN); 1115} 1116 1117int64_t 1118rule_get_timeout(rule_t rule) 1119{ 1120 return auth_items_get_int64(rule->data, RULE_TIMEOUT); 1121} 1122 1123bool 1124rule_check_flags(rule_t rule, RuleFlags flags) 1125{ 1126 return (auth_items_get_int64(rule->data, RULE_FLAGS) & flags) != 0; 1127} 1128 1129bool 1130rule_get_shared(rule_t rule) 1131{ 1132 return rule_check_flags(rule, RuleFlagShared); 1133} 1134 1135bool 1136rule_get_allow_root(rule_t rule) 1137{ 1138 return rule_check_flags(rule, RuleFlagAllowRoot); 1139} 1140 1141bool 1142rule_get_session_owner(rule_t rule) 1143{ 1144 return rule_check_flags(rule, RuleFlagSessionOwner); 1145} 1146 1147bool 1148rule_get_authenticate_user(rule_t rule) 1149{ 1150 return rule_check_flags(rule, RuleFlagAuthenticateUser); 1151} 1152 1153bool 1154rule_get_extract_password(rule_t rule) 1155{ 1156 return rule_check_flags(rule, RuleFlagExtractPassword); 1157} 1158 1159int64_t 1160rule_get_tries(rule_t rule) 1161{ 1162 return auth_items_get_int64(rule->data, RULE_TRIES); 1163} 1164 1165const char * 1166rule_get_comment(rule_t rule) 1167{ 1168 return auth_items_get_string(rule->data, RULE_COMMENT); 1169} 1170 1171int64_t 1172rule_get_version(rule_t rule) 1173{ 1174 return auth_items_get_int64(rule->data, RULE_VERSION); 1175} 1176 1177double rule_get_created(rule_t rule) 1178{ 1179 return auth_items_get_double(rule->data, RULE_CREATED); 1180} 1181 1182double rule_get_modified(rule_t rule) 1183{ 1184 return auth_items_get_double(rule->data, RULE_MODIFIED); 1185} 1186 1187const char * rule_get_identifier(rule_t rule) 1188{ 1189 return auth_items_get_string(rule->data, RULE_IDENTIFIER); 1190} 1191 1192CFDataRef rule_get_requirment_data(rule_t rule) 1193{ 1194 if (!rule->requirement_data && auth_items_exist(rule->data, RULE_REQUIREMENT)) { 1195 size_t len; 1196 const void * data = auth_items_get_data(rule->data, RULE_REQUIREMENT, &len); 1197 rule->requirement_data = CFDataCreate(kCFAllocatorDefault, data, (CFIndex)len); 1198 } 1199 1200 return rule->requirement_data; 1201} 1202 1203SecRequirementRef rule_get_requirment(rule_t rule) 1204{ 1205 if (!rule->requirement) { 1206 CFDataRef data = rule_get_requirment_data(rule); 1207 if (data) { 1208 SecRequirementCreateWithData(data, kSecCSDefaultFlags, &rule->requirement); 1209 } 1210 } 1211 1212 return rule->requirement; 1213} 1214