]> git.saurik.com Git - apple/security.git/blob - OSX/authd/rule.c
Security-59754.80.3.tar.gz
[apple/security.git] / OSX / authd / rule.c
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 #include <libproc.h>
15
16 AUTHD_DEFINE_LOG
17
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);
22
23 #define kMaximumAuthorizationTries 10000
24
25 #define RULE_ID "id"
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"
41
42 struct _rule_s {
43 __AUTH_BASE_STRUCT_HEADER__;
44
45 auth_items_t data;
46 CFMutableArrayRef mechanisms;
47 CFMutableArrayRef delegations;
48
49 CFMutableDictionaryRef loc_prompts;
50 CFMutableDictionaryRef loc_buttons;
51
52 CFDataRef requirement_data;
53 SecRequirementRef requirement;
54 };
55
56 static void
57 _rule_finalize(CFTypeRef value)
58 {
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);
67 }
68
69 static Boolean
70 _rule_equal(CFTypeRef value1, CFTypeRef value2)
71 {
72 rule_t rule1 = (rule_t)value1;
73 rule_t rule2 = (rule_t)value2;
74
75 return strcasecmp(rule_get_name(rule1), rule_get_name(rule2)) == 0;
76 }
77
78 static CFStringRef
79 _rule_copy_description(CFTypeRef value)
80 {
81 rule_t rule = (rule_t)value;
82 CFMutableStringRef str = CFStringCreateMutable(kCFAllocatorDefault, 0);
83 CFStringRef tmp = CFCopyDescription(rule->data);
84 CFStringAppend(str, tmp);
85 CFReleaseNull(tmp);
86 tmp = CFCopyDescription(rule->mechanisms);
87 CFStringAppend(str, tmp);
88 CFReleaseNull(tmp);
89 tmp = CFCopyDescription(rule->delegations);
90 CFStringAppend(str, tmp);
91 CFReleaseNull(tmp);
92 return str;
93 }
94
95 static CFHashCode
96 _rule_hash(CFTypeRef value)
97 {
98 rule_t rule = (rule_t)value;
99 const char * str = rule_get_name(rule);
100 return (CFHashCode)crc64(str, strlen(str));
101 }
102
103 AUTH_TYPE_INSTANCE(rule,
104 .init = NULL,
105 .copy = NULL,
106 .finalize = _rule_finalize,
107 .equal = _rule_equal,
108 .hash = _rule_hash,
109 .copyFormattingDesc = NULL,
110 .copyDebugDesc = _rule_copy_description
111 );
112
113 static CFTypeID rule_get_type_id() {
114 static CFTypeID type_id = _kCFRuntimeNotATypeID;
115 static dispatch_once_t onceToken;
116
117 dispatch_once(&onceToken, ^{
118 type_id = _CFRuntimeRegisterClass(&_auth_type_rule);
119 });
120
121 return type_id;
122 }
123
124 static rule_t
125 _rule_create()
126 {
127 rule_t rule = (rule_t)_CFRuntimeCreateInstance(kCFAllocatorDefault, rule_get_type_id(), AUTH_CLASS_SIZE(rule), NULL);
128 require(rule != NULL, done);
129
130 rule->data = auth_items_create();
131 rule->delegations = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
132 rule->mechanisms = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
133
134 done:
135 return rule;
136 }
137
138 static rule_t
139 _rule_create_with_sql(auth_items_t sql)
140 {
141 rule_t rule = NULL;
142 require(sql != NULL, done);
143
144 rule = _rule_create();
145 require(rule != NULL, done);
146
147 auth_items_copy(rule->data, sql);
148
149 done:
150 return rule;
151 }
152
153 rule_t
154 rule_create_default()
155 {
156 rule_t rule = _rule_create();
157 require(rule != NULL, done);
158
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);
166
167 mechanism_t mech = mechanism_create_with_string("builtin:authenticate", NULL);
168 CFArrayAppendValue(rule->mechanisms, mech);
169 CFReleaseNull(mech);
170
171 mech = mechanism_create_with_string("builtin:reset-password,privileged", NULL);
172 CFArrayAppendValue(rule->mechanisms, mech);
173 CFReleaseNull(mech);
174
175 mech = mechanism_create_with_string("builtin:authenticate,privileged", NULL);
176 CFArrayAppendValue(rule->mechanisms, mech);
177 CFReleaseNull(mech);
178
179 done:
180 return rule;
181 }
182
183 rule_t
184 rule_create_with_string(const char * str, authdb_connection_t dbconn)
185 {
186 rule_t rule = NULL;
187 require(str != NULL, done);
188
189 rule = _rule_create();
190 require(rule != NULL, done);
191
192 auth_items_set_string(rule->data, RULE_NAME, str);
193
194 if (dbconn) {
195 rule_sql_fetch(rule, dbconn);
196 }
197
198 done:
199 return rule;
200 }
201
202 static void _set_data_string(rule_t rule, const char * key, CFStringRef str)
203 {
204 char * tmpStr = _copy_cf_string(str, NULL);
205
206 if (tmpStr) {
207 auth_items_set_string(rule->data, key, tmpStr);
208 free_safe(tmpStr);
209 }
210 }
211
212 rule_t
213 rule_create_with_plist(RuleType type, CFStringRef name, CFDictionaryRef plist, authdb_connection_t dbconn)
214 {
215 rule_t rule = NULL;
216 require(name != NULL, done);
217 require(plist != NULL, done);
218
219 rule = _rule_create();
220 require(rule != NULL, done);
221
222 _set_data_string(rule, RULE_NAME, name);
223 require_action(rule_get_name(rule) != NULL, done, CFReleaseSafe(rule));
224
225 _sql_get_id(rule, dbconn);
226
227 auth_items_set_int64(rule->data, RULE_TYPE, type);
228
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)));
231
232
233 CFTypeRef loc_tmp = CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterDefaultPrompt));
234 if (loc_tmp) {
235 rule->loc_prompts = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, loc_tmp);
236 }
237 loc_tmp = CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterDefaultButton));
238 if (loc_tmp) {
239 rule->loc_buttons = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, loc_tmp);
240 }
241
242 auth_items_set_int64(rule->data, RULE_VERSION, _get_cf_int(CFDictionaryGetValue(plist, CFSTR("version")), 0));
243
244 RuleFlags flags = 0;
245
246 if (_get_cf_bool(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterEntitled)), false)) {
247 flags |= RuleFlagEntitled;
248 }
249
250 if (_get_cf_bool(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterRequireAppleSigned)), false)) {
251 flags |= RuleFlagRequireAppleSigned;
252 }
253
254 switch (rule_get_class(rule)) {
255 case RC_USER:
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));
259
260 if (_get_cf_bool(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterCredentialShared)), false)) {
261 flags |= RuleFlagShared;
262 }
263 if (_get_cf_bool(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterAllowRoot)), false)) {
264 flags |= RuleFlagAllowRoot;
265 }
266 if (_get_cf_bool(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterCredentialSessionOwner)), false)) {
267 flags |= RuleFlagSessionOwner;
268 }
269 if (_get_cf_bool(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterAuthenticateUser)), true)) {
270 flags |= RuleFlagAuthenticateUser;
271 }
272 if (_get_cf_bool(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterExtractPassword)), false)) {
273 flags |= RuleFlagExtractPassword;
274 }
275 if (_get_cf_bool(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterEntitledAndGroup)), false)) {
276 flags |= RuleFlagEntitledAndGroup;
277 }
278 if (_get_cf_bool(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterVPNEntitledAndGroup)), false)) {
279 flags |= RuleFlagVPNEntitledAndGroup;
280 }
281 if (_get_cf_bool(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterPasswordOnly)), false)) {
282 flags |= RuleFlagPasswordOnly;
283 }
284
285 _copy_cf_rule_mechanisms(rule, CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterMechanisms)), dbconn);
286
287 break;
288 case RC_RULE:
289 auth_items_set_int64(rule->data, RULE_KOFN, _get_cf_int(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterKofN)), 0));
290
291 _copy_cf_rule_delegations(rule, CFDictionaryGetValue(plist, CFSTR(kAuthorizationRightRule)), dbconn);
292 break;
293 case RC_MECHANISM:
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;
297 }
298 if (_get_cf_bool(CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterExtractPassword)), false)) {
299 flags |= RuleFlagExtractPassword;
300 }
301
302 _copy_cf_rule_mechanisms(rule, CFDictionaryGetValue(plist, CFSTR(kAuthorizationRuleParameterMechanisms)), dbconn);
303
304 break;
305 case RC_DENY:
306 break;
307 case RC_ALLOW:
308 break;
309 default:
310 os_log_error(AUTHD_LOG, "rule: invalid rule class");
311 break;
312 }
313
314 auth_items_set_int64(rule->data, RULE_FLAGS, flags);
315
316 done:
317 return rule;
318 }
319
320 static void
321 _sql_get_id(rule_t rule, authdb_connection_t dbconn)
322 {
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);
328 return true;
329 });
330 }
331
332 static bool
333 _copy_cf_rule_delegations(rule_t rule, CFTypeRef value, authdb_connection_t dbconn)
334 {
335 bool result = false;
336 char * tmp_str = NULL;
337 require(value != NULL, done);
338
339 if (CFGetTypeID(value) == CFStringGetTypeID()) {
340 tmp_str = _copy_cf_string(value, NULL);
341 rule_t delegate = rule_create_with_string(tmp_str, dbconn);
342 free_safe(tmp_str);
343 if (delegate) {
344 CFArrayAppendValue(rule->delegations, delegate);
345 CFReleaseSafe(delegate);
346 }
347 } else { //array
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);
352 free_safe(tmp_str);
353 if (delegate) {
354 CFArrayAppendValue(rule->delegations, delegate);
355 CFReleaseSafe(delegate);
356 }
357 }
358 }
359
360 result = true;
361
362 done:
363 return result;
364 }
365
366 static bool
367 _copy_cf_rule_mechanisms(rule_t rule, CFTypeRef array, authdb_connection_t dbconn)
368 {
369 bool result = false;
370 require(array != NULL, done);
371 require(CFGetTypeID(array) == CFArrayGetTypeID(), done);
372
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);
377
378 if (!string)
379 continue;
380
381 mech = mechanism_create_with_string(string, dbconn);
382 if (mech) {
383 CFArrayAppendValue(rule->mechanisms, mech);
384 CFReleaseSafe(mech);
385 }
386 free(string);
387 }
388
389 result = true;
390
391 done:
392 return result;
393 }
394
395 static RuleClass
396 _get_cf_rule_class(CFTypeRef str)
397 {
398 RuleClass rc = RC_RULE;
399 require(str != NULL, done);
400 require(CFGetTypeID(str) == CFStringGetTypeID(), done);
401
402 if (CFEqual(str, CFSTR(kAuthorizationRuleClassUser)))
403 return RC_USER;
404
405 if (CFEqual(str, CFSTR(kAuthorizationRightRule)))
406 return RC_RULE;
407
408 if (CFEqual(str, CFSTR(kAuthorizationRuleClassMechanisms)))
409 return RC_MECHANISM;
410
411 if (CFEqual(str, CFSTR(kAuthorizationRuleClassDeny)))
412 return RC_DENY;
413
414 if (CFEqual(str, CFSTR(kAuthorizationRuleClassAllow)))
415 return RC_ALLOW;
416
417 done:
418 return rc;
419 }
420
421 static bool
422 _sql_bind(rule_t rule, sqlite3_stmt * stmt)
423 {
424 int64_t n;
425 int32_t rc = 0;
426 require(stmt != NULL, err);
427
428 int32_t column = 1;
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);
435
436 switch (rule_get_class(rule)) {
437 case RC_USER:
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);
448 break;
449 case RC_RULE:
450 rc = sqlite3_bind_null(stmt, column++); // group
451 require_noerr(rc, err);
452 n = rule_get_kofn(rule);
453 if (n) {
454 rc = sqlite3_bind_int64(stmt, column++, n);
455 } else {
456 rc = sqlite3_bind_null(stmt, column++);
457 }
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);
465 break;
466 case RC_MECHANISM:
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);
477 break;
478 case RC_DENY:
479 case RC_ALLOW:
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);
490 break;
491 default:
492 os_log_error(AUTHD_LOG, "rule: sql bind, invalid rule class");
493 break;
494 }
495
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);
506
507 CFDataRef data = rule_get_requirement_data(rule);
508 if (data) {
509 rc = sqlite3_bind_blob(stmt, column++, CFDataGetBytePtr(data), (int32_t)CFDataGetLength(data), NULL);
510 } else {
511 rc = sqlite3_bind_null(stmt, column++);
512 }
513 require_noerr(rc, err);
514
515 rc = sqlite3_bind_text(stmt, column++, rule_get_comment(rule), -1, NULL);
516 require_noerr(rc, err);
517
518 return true;
519
520 err:
521 os_log_error(AUTHD_LOG, "rule: sql bind, error %i", rc);
522 return false;
523 }
524
525 static void
526 _get_sql_mechanisms(rule_t rule, authdb_connection_t dbconn)
527 {
528 CFArrayRemoveAllValues(rule->mechanisms);
529
530 authdb_step(dbconn, "SELECT mechanisms.* " \
531 "FROM 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);
540 return true;
541 });
542 }
543
544 static void
545 _get_sql_delegates(rule_t rule, authdb_connection_t dbconn)
546 {
547 CFArrayRemoveAllValues(rule->delegations);
548
549 authdb_step(dbconn, "SELECT rules.* " \
550 "FROM 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);
557 if (delegate) {
558 _get_sql_mechanisms(delegate, dbconn);
559
560 if (rule_get_class(rule) == RC_RULE) {
561 _get_sql_delegates(delegate, dbconn);
562 }
563
564 CFArrayAppendValue(rule->delegations, delegate);
565 CFReleaseSafe(delegate);
566 }
567 return true;
568 });
569 }
570
571 bool
572 rule_sql_fetch(rule_t rule, authdb_connection_t dbconn)
573 {
574 __block bool result = false;
575
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) {
580 result = true;
581 auth_items_copy(rule->data, data);
582 return true;
583 });
584
585 if (rule_get_id(rule) != 0) {
586 _get_sql_mechanisms(rule,dbconn);
587
588 if (rule_get_class(rule) == RC_RULE) {
589 _get_sql_delegates(rule, dbconn);
590 }
591 }
592
593 return result;
594 }
595
596 static bool
597 _sql_update(rule_t rule, authdb_connection_t dbconn)
598 {
599 bool result = false;
600
601 result = authdb_step(dbconn, "UPDATE rules " \
602 "SET name=?,type=?,class=?,'group'=?,kofn=?,timeout=?,flags=?,tries=?,version=?,created=?,modified=?,hash=?,identifier=?,requirement=?,comment=? " \
603 "WHERE id = ?",
604 ^(sqlite3_stmt *stmt) {
605 _sql_bind(rule, stmt);
606 sqlite3_bind_int64(stmt, sqlite3_bind_parameter_count(stmt), rule_get_id(rule));
607 }, NULL);
608 return result;
609 }
610
611 static bool
612 _sql_insert(rule_t rule, authdb_connection_t dbconn)
613 {
614 bool result = false;
615
616 result = authdb_step(dbconn, "INSERT INTO rules VALUES (NULL,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
617 ^(sqlite3_stmt *stmt) {
618 _sql_bind(rule, stmt);
619 }, NULL);
620 return result;
621 }
622
623 static bool
624 _sql_commit_mechanisms_map(rule_t rule, authdb_connection_t dbconn)
625 {
626 bool result = false;
627
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));
630 }, NULL);
631 require(result == true, done);
632
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);
640 }, NULL);
641 require(result == true, done);
642 }
643
644 done:
645 return result;
646 }
647
648 static bool
649 _sql_commit_delegates_map(rule_t rule, authdb_connection_t dbconn)
650 {
651 bool result = false;
652
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));
655 }, NULL);
656 require(result == true, done);
657
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);
665 }, NULL);
666 require(result == true, done);
667 }
668
669 done:
670 return result;
671 }
672
673 static void
674 _sql_commit_localization(rule_t rule, authdb_connection_t dbconn)
675 {
676
677 authdb_step(dbconn, "DELETE FROM prompts WHERE r_id = ?", ^(sqlite3_stmt *stmt) {
678 sqlite3_bind_int64(stmt, 1, rule_get_id(rule));
679 }, NULL);
680
681 authdb_step(dbconn, "DELETE FROM buttons WHERE r_id = ?", ^(sqlite3_stmt *stmt) {
682 sqlite3_bind_int64(stmt, 1, rule_get_id(rule));
683 }, NULL);
684
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);
689
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);
694 }, NULL);
695
696 free_safe(lang);
697 free_safe(str);
698
699 return true;
700 });
701 }
702
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);
707
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);
712 }, NULL);
713
714 free_safe(lang);
715 free_safe(str);
716 return true;
717 });
718 }
719
720 }
721
722 bool
723 rule_sql_commit(rule_t rule, authdb_connection_t dbconn, CFAbsoluteTime modified, process_t proc)
724 {
725 bool result = false;
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);
731
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);
742 }
743 }
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));
746 }
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)));
748 }
749 }
750
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);
759 }
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)));
761 }
762 }
763
764 auth_items_set_double(rule->data, RULE_MODIFIED, modified);
765
766 result = authdb_transaction(dbconn, AuthDBTransactionNormal, ^bool{
767 bool update = false;
768
769 if (rule_get_id(rule)) {
770 update = _sql_update(rule, dbconn);
771 } else {
772 insert = true;
773 if (proc) {
774 const char * ident = process_get_identifier(proc);
775 if (ident) {
776 auth_items_set_string(rule->data, RULE_IDENTIFIER, ident);
777 }
778 CFDataRef req = process_get_requirement_data(proc);
779 if (req) {
780 auth_items_set_data(rule->data, RULE_REQUIREMENT, CFDataGetBytePtr(req), (size_t)CFDataGetLength(req));
781 }
782 }
783 auth_items_set_double(rule->data, RULE_CREATED, modified);
784 update = _sql_insert(rule, dbconn);
785 _sql_get_id(rule, dbconn);
786 }
787
788 _sql_commit_localization(rule, dbconn);
789
790 if (update) {
791 update = _sql_commit_mechanisms_map(rule, dbconn);
792 }
793
794 if (update) {
795 update = _sql_commit_delegates_map(rule,dbconn);
796 }
797
798 return update;
799 });
800
801
802 done:
803 if (!result) {
804 os_log_debug(AUTHD_LOG, "rule: commit, failed for %{public}s (%llu)", rule_get_name(rule), rule_get_id(rule));
805 } else {
806 rule_log_manipulation(dbconn, rule, insert ? rule_insert : rule_update, proc);
807 }
808 return result;
809 }
810
811 bool
812 rule_sql_remove(rule_t rule, authdb_connection_t dbconn, process_t proc)
813 {
814 bool result = false;
815 int64_t id = rule_get_id(rule);
816
817 if (id == 0) {
818 rule_sql_fetch(rule, dbconn);
819 id = rule_get_id(rule);
820 require(id != 0, done);
821 }
822
823 result = authdb_step(dbconn, "DELETE FROM rules WHERE id = ?",
824 ^(sqlite3_stmt *stmt) {
825 sqlite3_bind_int64(stmt, 1, id);
826 }, NULL);
827
828 if (result) {
829 rule_log_manipulation(dbconn, rule, rule_delete, proc);
830 }
831
832 done:
833 return result;
834 }
835
836 CFMutableDictionaryRef
837 rule_copy_to_cfobject(rule_t rule, authdb_connection_t dbconn) {
838 CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
839
840 CFTypeRef tmp = NULL;
841 CFMutableArrayRef array = NULL;
842 CFIndex count = 0;
843 CFIndex i = 0;
844 int64_t n;
845 double d;
846
847 const char * comment = rule_get_comment(rule);
848 if (comment) {
849 tmp = CFStringCreateWithCString(kCFAllocatorDefault, comment, kCFStringEncodingUTF8);
850 CFDictionarySetValue(dict, CFSTR(kAuthorizationComment), tmp);
851 CFReleaseSafe(tmp);
852 }
853
854 n = rule_get_version(rule);
855 tmp = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &n);
856 CFDictionarySetValue(dict, CFSTR(RULE_VERSION), tmp);
857 CFReleaseSafe(tmp);
858
859 d = rule_get_created(rule);
860 tmp = CFNumberCreate(kCFAllocatorDefault, kCFNumberFloat64Type, &d);
861 CFDictionarySetValue(dict, CFSTR(RULE_CREATED), tmp);
862 CFReleaseSafe(tmp);
863
864 d = rule_get_modified(rule);
865 tmp = CFNumberCreate(kCFAllocatorDefault, kCFNumberFloat64Type, &d);
866 CFDictionarySetValue(dict, CFSTR(RULE_MODIFIED), tmp);
867 CFReleaseSafe(tmp);
868
869 const char * identifier = rule_get_identifier(rule);
870 if (identifier) {
871 tmp = CFStringCreateWithCString(kCFAllocatorDefault, identifier, kCFStringEncodingUTF8);
872 CFDictionarySetValue(dict, CFSTR(RULE_IDENTIFIER), tmp);
873 CFReleaseSafe(tmp);
874 }
875
876 SecRequirementRef req = rule_get_requirement(rule);
877 if (req) {
878 CFStringRef reqStr = NULL;
879 SecRequirementCopyString(req, kSecCSDefaultFlags, &reqStr);
880 if (reqStr) {
881 CFDictionarySetValue(dict, CFSTR(RULE_REQUIREMENT), reqStr);
882 CFReleaseSafe(reqStr);
883 }
884 }
885
886 if (rule_check_flags(rule, RuleFlagEntitled)) {
887 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterEntitled), kCFBooleanTrue);
888 }
889
890 if (rule_check_flags(rule, RuleFlagRequireAppleSigned)) {
891 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterRequireAppleSigned), kCFBooleanTrue);
892 }
893
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);
902 CFReleaseSafe(key);
903 CFReleaseSafe(value);
904 return true;
905 });
906
907 if (CFDictionaryGetCount(prompts)) {
908 CFDictionaryAddValue(dict, CFSTR(kAuthorizationRuleParameterDefaultPrompt), prompts);
909 }
910 CFReleaseSafe(prompts);
911
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);
919 CFReleaseSafe(key);
920 CFReleaseSafe(value);
921 return true;
922 });
923
924 if (CFDictionaryGetCount(buttons)) {
925 CFDictionaryAddValue(dict, CFSTR(kAuthorizationRuleParameterDefaultButton), buttons);
926 }
927 CFReleaseSafe(buttons);
928 }
929
930 switch (rule_get_class(rule)) {
931 case RC_USER:
932 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleClass), CFSTR(kAuthorizationRuleClassUser));
933
934 const char * group = rule_get_group(rule);
935 if (group) {
936 tmp = CFStringCreateWithCString(kCFAllocatorDefault, group, kCFStringEncodingUTF8);
937 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterGroup), tmp);
938 CFReleaseSafe(tmp);
939 }
940
941 n = rule_get_timeout(rule);
942 tmp = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &n);
943 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterCredentialTimeout), tmp);
944 CFReleaseSafe(tmp);
945
946 n = rule_get_tries(rule);
947 tmp = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &n);
948 CFDictionarySetValue(dict, CFSTR("tries"), tmp);
949 CFReleaseSafe(tmp);
950
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);
957 }
958 if (rule_check_flags(rule, RuleFlagVPNEntitledAndGroup)) {
959 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterVPNEntitledAndGroup), kCFBooleanTrue);
960 }
961 if (rule_get_extract_password(rule)) {
962 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterExtractPassword), kCFBooleanTrue);
963 }
964 if (rule_get_password_only(rule)) {
965 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterPasswordOnly), kCFBooleanTrue);
966 }
967
968 count = CFArrayGetCount(rule->mechanisms);
969 if (count) {
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);
975 CFReleaseSafe(tmp);
976 }
977 CFDictionaryAddValue(dict, CFSTR(kAuthorizationRuleParameterMechanisms), array);
978 CFRelease(array);
979 }
980 break;
981 case RC_RULE:
982 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleClass), CFSTR(kAuthorizationRightRule));
983 int64_t kofn = rule_get_kofn(rule);
984 if (kofn) {
985 tmp = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &kofn);
986 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterKofN), tmp);
987 CFReleaseSafe(tmp);
988 }
989
990 count = CFArrayGetCount(rule->delegations);
991 if (count) {
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);
997 CFReleaseSafe(tmp);
998 }
999 CFDictionaryAddValue(dict, CFSTR(kAuthorizationRightRule), array);
1000 CFRelease(array);
1001 }
1002 break;
1003 case RC_MECHANISM:
1004 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleClass), CFSTR(kAuthorizationRuleClassMechanisms));
1005
1006 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterCredentialShared), rule_get_shared(rule) ? kCFBooleanTrue : kCFBooleanFalse);
1007 if (rule_get_extract_password(rule)) {
1008 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleParameterExtractPassword), kCFBooleanTrue);
1009 }
1010
1011 n = rule_get_tries(rule);
1012 tmp = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &n);
1013 CFDictionarySetValue(dict, CFSTR("tries"), tmp);
1014 CFReleaseSafe(tmp);
1015
1016 count = CFArrayGetCount(rule->mechanisms);
1017 if (count) {
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);
1023 CFReleaseSafe(tmp);
1024 }
1025 CFDictionaryAddValue(dict, CFSTR(kAuthorizationRuleParameterMechanisms), array);
1026 CFRelease(array);
1027 }
1028 break;
1029 case RC_DENY:
1030 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleClass), CFSTR(kAuthorizationRuleClassDeny));
1031 break;
1032 case RC_ALLOW:
1033 CFDictionarySetValue(dict, CFSTR(kAuthorizationRuleClass), CFSTR(kAuthorizationRuleClassAllow));
1034 break;
1035 default:
1036 break;
1037 }
1038
1039 return dict;
1040 }
1041
1042
1043 CFArrayRef
1044 rule_get_mechanisms(rule_t rule)
1045 {
1046 return rule->mechanisms;
1047 }
1048
1049 size_t
1050 rule_get_mechanisms_count(rule_t rule)
1051 {
1052 return (size_t)CFArrayGetCount(rule->mechanisms);
1053 }
1054
1055 bool
1056 rule_mechanisms_iterator(rule_t rule, mechanism_iterator_t iter)
1057 {
1058 bool result = false;
1059
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);
1064 if (!result) {
1065 break;
1066 }
1067 }
1068
1069 return result;
1070 }
1071
1072 size_t
1073 rule_get_delegates_count(rule_t rule)
1074 {
1075 return (size_t)CFArrayGetCount(rule->delegations);
1076 }
1077
1078 bool
1079 rule_delegates_iterator(rule_t rule, delegate_iterator_t iter)
1080 {
1081 bool result = false;
1082
1083 CFIndex count = CFArrayGetCount(rule->delegations);
1084 for (CFIndex i = 0; i < count; i++) {
1085 rule_t tmp = (rule_t)CFArrayGetValueAtIndex(rule->delegations, i);
1086 result = iter(tmp);
1087 if (!result) {
1088 break;
1089 }
1090 }
1091
1092 return result;
1093 }
1094
1095 int64_t
1096 rule_get_id(rule_t rule)
1097 {
1098 return auth_items_get_int64(rule->data, RULE_ID);
1099 }
1100
1101 const char *
1102 rule_get_name(rule_t rule)
1103 {
1104 return auth_items_get_string(rule->data, RULE_NAME);
1105 }
1106
1107 RuleType
1108 rule_get_type(rule_t rule)
1109 {
1110 return (RuleType)auth_items_get_int64(rule->data, RULE_TYPE);
1111 }
1112
1113 RuleClass
1114 rule_get_class(rule_t rule)
1115 {
1116 return (RuleClass)auth_items_get_int64(rule->data, RULE_CLASS);
1117 }
1118
1119 const char *
1120 rule_get_group(rule_t rule)
1121 {
1122 return auth_items_get_string(rule->data, RULE_GROUP);
1123 }
1124
1125 int64_t
1126 rule_get_kofn(rule_t rule)
1127 {
1128 return auth_items_get_int64(rule->data, RULE_KOFN);
1129 }
1130
1131 int64_t
1132 rule_get_timeout(rule_t rule)
1133 {
1134 return auth_items_get_int64(rule->data, RULE_TIMEOUT);
1135 }
1136
1137 bool
1138 rule_check_flags(rule_t rule, RuleFlags flags)
1139 {
1140 return (auth_items_get_int64(rule->data, RULE_FLAGS) & flags) != 0;
1141 }
1142
1143 bool
1144 rule_get_shared(rule_t rule)
1145 {
1146 if (isInLWOS()) {
1147 return false;
1148 }
1149 return rule_check_flags(rule, RuleFlagShared);
1150 }
1151
1152 bool
1153 rule_get_allow_root(rule_t rule)
1154 {
1155 return rule_check_flags(rule, RuleFlagAllowRoot);
1156 }
1157
1158 bool
1159 rule_get_session_owner(rule_t rule)
1160 {
1161 return rule_check_flags(rule, RuleFlagSessionOwner);
1162 }
1163
1164 bool
1165 rule_get_authenticate_user(rule_t rule)
1166 {
1167 return rule_check_flags(rule, RuleFlagAuthenticateUser);
1168 }
1169
1170 bool
1171 rule_get_extract_password(rule_t rule)
1172 {
1173 return rule_check_flags(rule, RuleFlagExtractPassword);
1174 }
1175
1176 bool
1177 rule_get_password_only(rule_t rule)
1178 {
1179 return rule_check_flags(rule, RuleFlagPasswordOnly);
1180 }
1181
1182 int64_t
1183 rule_get_tries(rule_t rule)
1184 {
1185 return auth_items_get_int64(rule->data, RULE_TRIES);
1186 }
1187
1188 const char *
1189 rule_get_comment(rule_t rule)
1190 {
1191 return auth_items_get_string(rule->data, RULE_COMMENT);
1192 }
1193
1194 int64_t
1195 rule_get_version(rule_t rule)
1196 {
1197 return auth_items_get_int64(rule->data, RULE_VERSION);
1198 }
1199
1200 double rule_get_created(rule_t rule)
1201 {
1202 return auth_items_get_double(rule->data, RULE_CREATED);
1203 }
1204
1205 double rule_get_modified(rule_t rule)
1206 {
1207 return auth_items_get_double(rule->data, RULE_MODIFIED);
1208 }
1209
1210 const char * rule_get_identifier(rule_t rule)
1211 {
1212 return auth_items_get_string(rule->data, RULE_IDENTIFIER);
1213 }
1214
1215 CFDataRef rule_get_requirement_data(rule_t rule)
1216 {
1217 if (!rule->requirement_data && auth_items_exist(rule->data, RULE_REQUIREMENT)) {
1218 size_t len;
1219 const void * data = auth_items_get_data(rule->data, RULE_REQUIREMENT, &len);
1220 rule->requirement_data = CFDataCreate(kCFAllocatorDefault, data, (CFIndex)len);
1221 }
1222
1223 return rule->requirement_data;
1224 }
1225
1226 SecRequirementRef rule_get_requirement(rule_t rule)
1227 {
1228 if (!rule->requirement) {
1229 CFDataRef data = rule_get_requirement_data(rule);
1230 if (data) {
1231 SecRequirementCreateWithData(data, kSecCSDefaultFlags, &rule->requirement);
1232 }
1233 }
1234
1235 return rule->requirement;
1236 }
1237
1238 void
1239 rule_log_manipulation(authdb_connection_t dbconn, rule_t rule, RuleOperation operation, process_t source)
1240 {
1241 authdb_step(dbconn, "INSERT INTO rules_history (rule, source, operation, version) VALUES (?,?,?,?)", ^(sqlite3_stmt *stmt) {
1242 char pathbuf[PROC_PIDPATHINFO_MAXSIZE];
1243 if (source) {
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);
1248 }
1249 } else {
1250 strncpy(pathbuf, "authd", sizeof(pathbuf));
1251 }
1252
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));
1257 }, NULL);
1258 }