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