]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_codesigning/lib/SecAssessment.cpp
Security-58286.200.222.tar.gz
[apple/security.git] / OSX / libsecurity_codesigning / lib / SecAssessment.cpp
1 /*
2 * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23 #include "cs.h"
24 #include "SecAssessment.h"
25 #include "policydb.h"
26 #include "policyengine.h"
27 #include "xpcengine.h"
28 #include "csutilities.h"
29 #include <CoreFoundation/CFRuntime.h>
30 #include <CoreFoundation/CFBundlePriv.h>
31 #include <security_utilities/globalizer.h>
32 #include <security_utilities/unix++.h>
33 #include <security_utilities/cfmunge.h>
34 #include <notify.h>
35 #include <esp.h>
36
37 using namespace CodeSigning;
38
39
40 static void esp_do_check(const char *op, CFDictionaryRef dict)
41 {
42 OSStatus result = __esp_check_ns(op, (void *)(CFDictionaryRef)dict);
43 if (result != noErr)
44 MacOSError::throwMe(result);
45 }
46
47 //
48 // CF Objects
49 //
50 struct _SecAssessment : private CFRuntimeBase {
51 public:
52 _SecAssessment(CFURLRef p, AuthorityType typ, CFDictionaryRef r) : path(p), type(typ), result(r) { }
53
54 CFCopyRef<CFURLRef> path;
55 AuthorityType type;
56 CFRef<CFDictionaryRef> result;
57
58 public:
59 static _SecAssessment &ref(SecAssessmentRef r)
60 { return *(_SecAssessment *)r; }
61
62 // CF Boiler-plate
63 void *operator new (size_t size)
64 {
65 return (void *)_CFRuntimeCreateInstance(NULL, SecAssessmentGetTypeID(),
66 sizeof(_SecAssessment) - sizeof(CFRuntimeBase), NULL);
67 }
68
69 static void finalize(CFTypeRef obj)
70 { ((_SecAssessment *)obj)->~_SecAssessment(); }
71 };
72
73 typedef _SecAssessment SecAssessment;
74
75
76 static const CFRuntimeClass assessmentClass = {
77 0, // version
78 "SecAssessment", // name
79 NULL, // init
80 NULL, // copy
81 SecAssessment::finalize, // finalize
82 NULL, // equal
83 NULL, // hash
84 NULL, // formatting
85 NULL // debug string
86 };
87
88
89 static dispatch_once_t assessmentOnce;
90 CFTypeID assessmentType = _kCFRuntimeNotATypeID;
91
92 CFTypeID SecAssessmentGetTypeID()
93 {
94 dispatch_once(&assessmentOnce, ^void() {
95 if ((assessmentType = _CFRuntimeRegisterClass(&assessmentClass)) == _kCFRuntimeNotATypeID)
96 abort();
97 });
98 return assessmentType;
99 }
100
101
102 //
103 // Common dictionary constants
104 //
105 CFStringRef kSecAssessmentContextKeyOperation = CFSTR("operation");
106 CFStringRef kSecAssessmentOperationTypeExecute = CFSTR("operation:execute");
107 CFStringRef kSecAssessmentOperationTypeInstall = CFSTR("operation:install");
108 CFStringRef kSecAssessmentOperationTypeOpenDocument = CFSTR("operation:lsopen");
109
110
111 //
112 // Read-only in-process access to the policy database
113 //
114 class ReadPolicy : public PolicyDatabase {
115 public:
116 ReadPolicy() : PolicyDatabase(defaultDatabase) { }
117 };
118 ModuleNexus<ReadPolicy> gDatabase;
119
120
121 //
122 // An on-demand instance of the policy engine
123 //
124 ModuleNexus<PolicyEngine> gEngine;
125
126
127 //
128 // Policy evaluation ("assessment") operations
129 //
130 CFStringRef kSecAssessmentContextKeyUTI = CFSTR("context:uti");
131
132 CFStringRef kSecAssessmentContextKeyFeedback = CFSTR("context:feedback");
133 CFStringRef kSecAssessmentFeedbackProgress = CFSTR("feedback:progress");
134 CFStringRef kSecAssessmentFeedbackInfoCurrent = CFSTR("current");
135 CFStringRef kSecAssessmentFeedbackInfoTotal = CFSTR("total");
136
137 CFStringRef kSecAssessmentContextKeyPrimarySignature = CFSTR("context:primary-signature");
138
139 CFStringRef kSecAssessmentAssessmentVerdict = CFSTR("assessment:verdict");
140 CFStringRef kSecAssessmentAssessmentOriginator = CFSTR("assessment:originator");
141 CFStringRef kSecAssessmentAssessmentAuthority = CFSTR("assessment:authority");
142 CFStringRef kSecAssessmentAssessmentSource = CFSTR("assessment:authority:source");
143 CFStringRef kSecAssessmentAssessmentAuthorityRow = CFSTR("assessment:authority:row");
144 CFStringRef kSecAssessmentAssessmentAuthorityOverride = CFSTR("assessment:authority:override");
145 CFStringRef kSecAssessmentAssessmentAuthorityOriginalVerdict = CFSTR("assessment:authority:verdict");
146 CFStringRef kSecAssessmentAssessmentAuthorityFlags = CFSTR("assessment:authority:flags");
147 CFStringRef kSecAssessmentAssessmentFromCache = CFSTR("assessment:authority:cached");
148 CFStringRef kSecAssessmentAssessmentWeakSignature = CFSTR("assessment:authority:weak");
149 CFStringRef kSecAssessmentAssessmentCodeSigningError = CFSTR("assessment:cserror");
150 CFStringRef kSecAssessmentAssessmentNotarizationDate = CFSTR("assessment:notarization-date");
151
152 CFStringRef kDisabledOverride = CFSTR("security disabled");
153
154 SecAssessmentRef SecAssessmentCreate(CFURLRef path,
155 SecAssessmentFlags flags,
156 CFDictionaryRef context,
157 CFErrorRef *errors)
158 {
159 BEGIN_CSAPI
160
161 if (flags & kSecAssessmentFlagAsynchronous)
162 MacOSError::throwMe(errSecCSUnimplemented);
163
164 AuthorityType type = typeFor(context, kAuthorityExecute);
165 CFRef<CFMutableDictionaryRef> result = makeCFMutableDictionary();
166
167 SYSPOLICY_ASSESS_API(cfString(path).c_str(), int(type), flags);
168
169 try {
170 if (__esp_enabled() && (flags & kSecAssessmentFlagDirect)) {
171 CFTemp<CFDictionaryRef> dict("{path=%O, flags=%d, context=%O, override=%d}", path, flags, context, overrideAssessment());
172 esp_do_check("cs-assessment-evaluate", dict);
173 }
174
175 if (flags & kSecAssessmentFlagDirect) {
176 // ask the engine right here to do its thing
177 SYSPOLICY_ASSESS_LOCAL();
178 gEngine().evaluate(path, type, flags, context, result);
179 } else {
180 // relay the question to our daemon for consideration
181 SYSPOLICY_ASSESS_REMOTE();
182 xpcEngineAssess(path, flags, context, result);
183 }
184 } catch (CommonError &error) {
185 switch (error.osStatus()) {
186 case CSSMERR_TP_CERT_REVOKED:
187 throw;
188 default:
189 if (!overrideAssessment(flags))
190 throw; // let it go as an error
191 break;
192 }
193 // record the error we would have returned
194 cfadd(result, "{%O=#F,'assessment:error'=%d}}", kSecAssessmentAssessmentVerdict, error.osStatus());
195 } catch (...) {
196 // catch stray errors not conforming to the CommonError scheme
197 if (!overrideAssessment(flags))
198 throw; // let it go as an error
199 cfadd(result, "{%O=#F}", kSecAssessmentAssessmentVerdict);
200 }
201
202 if (__esp_enabled() && (flags & kSecAssessmentFlagDirect)) {
203 CFTemp<CFDictionaryRef> dict("{path=%O, flags=%d, context=%O, override=%d, result=%O}", path, flags, context, overrideAssessment(), (CFDictionaryRef)result);
204 __esp_notify_ns("cs-assessment-evaluate", (void *)(CFDictionaryRef)dict);
205 }
206
207 return new SecAssessment(path, type, result.yield());
208
209 END_CSAPI_ERRORS1(NULL)
210 }
211
212
213 static void traceResult(CFURLRef target, MessageTrace &trace, std::string &sanitized)
214 {
215 static const char *interestingBundles[] = {
216 "UNBUNDLED",
217 "com.apple.",
218 "com.install4j.",
219 "com.MindVision.",
220 "com.yourcompany.",
221
222 "com.adobe.flashplayer.installmanager",
223 "com.adobe.Installers.Setup",
224 "com.adobe.PDApp.setup",
225 "com.bittorrent.uTorrent",
226 "com.divx.divx6formacinstaller",
227 "com.getdropbox.dropbox",
228 "com.google.Chrome",
229 "com.Google.GoogleEarthPlugin.plugin",
230 "com.Google.GoogleEarthPlus",
231 "com.hp.Installer",
232 "com.macpaw.CleanMyMac",
233 "com.microsoft.SilverlightInstaller",
234 "com.paragon-software.filesystems.NTFS.pkg",
235 "com.RealNetworks.RealPlayer",
236 "com.skype.skype",
237 "it.alfanet.squared5.MPEGStreamclip",
238 "org.mozilla.firefox",
239 "org.videolan.vlc",
240
241 NULL // sentinel
242 };
243
244 string identifier = "UNBUNDLED";
245 string version = "UNKNOWN";
246 if (CFRef<CFBundleRef> bundle = _CFBundleCreateUnique(NULL, target)) {
247 if (CFStringRef ident = CFBundleGetIdentifier(bundle))
248 identifier = cfString(ident);
249 if (CFStringRef vers = CFStringRef(CFBundleGetValueForInfoDictionaryKey(bundle, CFSTR("CFBundleShortVersionString"))))
250 version = cfString(vers);
251 }
252
253 CFRef<CFURLRef> url = CFURLCopyAbsoluteURL(target);
254 sanitized = cfString(url);
255 string::size_type rslash = sanitized.rfind('/');
256 if (rslash != string::npos)
257 sanitized = sanitized.substr(rslash+1);
258 bool keepFilename = false;
259 for (const char **pfx = interestingBundles; *pfx; pfx++) {
260 size_t pfxlen = strlen(*pfx);
261 if (identifier.compare(0, pfxlen, *pfx, pfxlen) == 0)
262 if (pfxlen == identifier.size() || (*pfx)[pfxlen-1] == '.') {
263 keepFilename = true;
264 break;
265 }
266 }
267 if (!keepFilename) {
268 string::size_type dot = sanitized.rfind('.');
269 if (dot != string::npos)
270 sanitized = sanitized.substr(dot);
271 else
272 sanitized = "(none)";
273 }
274
275 trace.add("signature2", "bundle:%s", identifier.c_str());
276 trace.add("signature3", "%s", sanitized.c_str());
277 trace.add("signature5", "%s", version.c_str());
278 }
279
280 static void traceAssessment(SecAssessment &assessment, AuthorityType type, CFDictionaryRef result)
281 {
282 if (CFDictionaryGetValue(result, CFSTR("assessment:remote")))
283 return; // just traced in syspolicyd
284
285 string authority = "UNSPECIFIED";
286 bool overridden = false;
287 bool old_overridden = false;
288 if (CFDictionaryRef authdict = CFDictionaryRef(CFDictionaryGetValue(result, kSecAssessmentAssessmentAuthority))) {
289 if (CFStringRef auth = CFStringRef(CFDictionaryGetValue(authdict, kSecAssessmentAssessmentSource)))
290 authority = cfString(auth);
291 else
292 authority = "no authority";
293 if (CFTypeRef override = CFDictionaryGetValue(authdict, kSecAssessmentAssessmentAuthorityOverride))
294 if (CFEqual(override, kDisabledOverride)) {
295 old_overridden = true;
296 if (CFDictionaryGetValue(authdict, kSecAssessmentAssessmentAuthorityOriginalVerdict) == kCFBooleanFalse)
297 overridden = true;
298 }
299 }
300
301 MessageTrace trace("com.apple.security.assessment.outcome2", NULL);
302 std::string sanitized;
303 traceResult(assessment.path, trace, sanitized);
304 trace.add("signature4", "%d", type);
305
306 if (CFDictionaryGetValue(result, kSecAssessmentAssessmentVerdict) == kCFBooleanFalse) {
307 trace.add("signature", "denied:%s", authority.c_str());
308 trace.send("assessment denied for %s", sanitized.c_str());
309 } else if (overridden) { // would have failed except for override
310 trace.add("signature", "defeated:%s", authority.c_str());
311 trace.send("assessment denied for %s but overridden", sanitized.c_str());
312 } else if (old_overridden) { // would have succeeded even without override
313 trace.add("signature", "override:%s", authority.c_str());
314 trace.send("assessment granted for %s and overridden", sanitized.c_str());
315 } else {
316 trace.add("signature", "granted:%s", authority.c_str());
317 trace.send("assessment granted for %s by %s", sanitized.c_str(), authority.c_str());
318 }
319 }
320
321 static void traceUpdate(CFTypeRef target, CFDictionaryRef context, CFDictionaryRef result)
322 {
323 // only trace add operations on URL targets
324 if (target == NULL || CFGetTypeID(target) != CFURLGetTypeID())
325 return;
326 CFStringRef edit = CFStringRef(CFDictionaryGetValue(context, kSecAssessmentContextKeyUpdate));
327 if (!CFEqual(edit, kSecAssessmentUpdateOperationAdd))
328 return;
329 MessageTrace trace("com.apple.security.assessment.update", NULL);
330 std::string sanitized;
331 traceResult(CFURLRef(target), trace, sanitized);
332 trace.send("added rule for %s", sanitized.c_str());
333 }
334
335
336 //
337 // At present, CopyResult simply retrieves the result already formed by Create.
338 // In the future, this will be more lazy.
339 //
340 CFDictionaryRef SecAssessmentCopyResult(SecAssessmentRef assessmentRef,
341 SecAssessmentFlags flags,
342 CFErrorRef *errors)
343 {
344 BEGIN_CSAPI
345
346 SecAssessment &assessment = SecAssessment::ref(assessmentRef);
347 CFCopyRef<CFDictionaryRef> result = assessment.result;
348 if (overrideAssessment(flags)) {
349 // turn rejections into approvals, but note that we did that
350 CFTypeRef verdict = CFDictionaryGetValue(result, kSecAssessmentAssessmentVerdict);
351 if (verdict == kCFBooleanFalse) {
352 CFRef<CFMutableDictionaryRef> adulterated = makeCFMutableDictionary(result.get());
353 CFDictionarySetValue(adulterated, kSecAssessmentAssessmentVerdict, kCFBooleanTrue);
354 if (CFDictionaryRef authority = CFDictionaryRef(CFDictionaryGetValue(adulterated, kSecAssessmentAssessmentAuthority))) {
355 CFRef<CFMutableDictionaryRef> authority2 = makeCFMutableDictionary(authority);
356 CFDictionarySetValue(authority2, kSecAssessmentAssessmentAuthorityOverride, kDisabledOverride);
357 CFDictionarySetValue(authority2, kSecAssessmentAssessmentAuthorityOriginalVerdict, verdict);
358 CFDictionarySetValue(adulterated, kSecAssessmentAssessmentAuthority, authority2);
359 } else {
360 cfadd(adulterated, "{%O={%O=%O}}",
361 kSecAssessmentAssessmentAuthority, kSecAssessmentAssessmentAuthorityOverride, kDisabledOverride);
362 }
363 result = adulterated.get();
364 }
365 }
366 traceAssessment(assessment, assessment.type, result);
367 return result.yield();
368
369 END_CSAPI_ERRORS1(NULL)
370 }
371
372
373 //
374 // Policy editing operations.
375 // These all make permanent changes to the system-wide authority records.
376 //
377 CFStringRef kSecAssessmentContextKeyUpdate = CFSTR("update");
378 CFStringRef kSecAssessmentUpdateOperationAdd = CFSTR("update:add");
379 CFStringRef kSecAssessmentUpdateOperationRemove = CFSTR("update:remove");
380 CFStringRef kSecAssessmentUpdateOperationEnable = CFSTR("update:enable");
381 CFStringRef kSecAssessmentUpdateOperationDisable = CFSTR("update:disable");
382 CFStringRef kSecAssessmentUpdateOperationFind = CFSTR("update:find");
383
384 CFStringRef kSecAssessmentUpdateKeyAuthorization = CFSTR("update:authorization");
385 CFStringRef kSecAssessmentUpdateKeyPriority = CFSTR("update:priority");
386 CFStringRef kSecAssessmentUpdateKeyLabel = CFSTR("update:label");
387 CFStringRef kSecAssessmentUpdateKeyExpires = CFSTR("update:expires");
388 CFStringRef kSecAssessmentUpdateKeyAllow = CFSTR("update:allow");
389 CFStringRef kSecAssessmentUpdateKeyRemarks = CFSTR("update:remarks");
390
391 CFStringRef kSecAssessmentUpdateKeyRow = CFSTR("update:row");
392 CFStringRef kSecAssessmentUpdateKeyCount = CFSTR("update:count");
393 CFStringRef kSecAssessmentUpdateKeyFound = CFSTR("update:found");
394
395 CFStringRef kSecAssessmentRuleKeyID = CFSTR("rule:id");
396 CFStringRef kSecAssessmentRuleKeyPriority = CFSTR("rule:priority");
397 CFStringRef kSecAssessmentRuleKeyAllow = CFSTR("rule:allow");
398 CFStringRef kSecAssessmentRuleKeyLabel = CFSTR("rule:label");
399 CFStringRef kSecAssessmentRuleKeyRemarks = CFSTR("rule:remarks");
400 CFStringRef kSecAssessmentRuleKeyRequirement = CFSTR("rule:requirement");
401 CFStringRef kSecAssessmentRuleKeyType = CFSTR("rule:type");
402 CFStringRef kSecAssessmentRuleKeyExpires = CFSTR("rule:expires");
403 CFStringRef kSecAssessmentRuleKeyDisabled = CFSTR("rule:disabled");
404 CFStringRef kSecAssessmentRuleKeyBookmark = CFSTR("rule:bookmark");
405
406
407 Boolean SecAssessmentUpdate(CFTypeRef target,
408 SecAssessmentFlags flags,
409 CFDictionaryRef context,
410 CFErrorRef *errors)
411 {
412 if (CFDictionaryRef outcome = SecAssessmentCopyUpdate(target, flags, context, errors)) {
413 CFRelease(outcome);
414 return true;
415 } else {
416 return false;
417 }
418 }
419
420 CFDictionaryRef SecAssessmentCopyUpdate(CFTypeRef target,
421 SecAssessmentFlags flags,
422 CFDictionaryRef context,
423 CFErrorRef *errors)
424 {
425 BEGIN_CSAPI
426
427 CFDictionary ctx(context, errSecCSInvalidAttributeValues);
428 CFRef<CFDictionaryRef> result;
429
430 // make context exist and writable
431 CFRef<CFMutableDictionaryRef> mcontext = context ? makeCFMutableDictionary(context) : makeCFMutableDictionary();
432
433 if (CFDictionaryGetValue(mcontext, kSecAssessmentUpdateKeyAuthorization) == NULL) {
434 // no authorization passed in. Make an empty one in this context
435 AuthorizationRef authorization;
436 MacOSError::check(AuthorizationCreate(NULL, NULL, kAuthorizationFlagDefaults, &authorization));
437 AuthorizationExternalForm extform;
438 MacOSError::check(AuthorizationMakeExternalForm(authorization, &extform));
439 CFDictionaryAddValue(mcontext, kSecAssessmentUpdateKeyAuthorization, CFTempData(&extform, sizeof(extform)));
440 if (!(flags & kSecAssessmentFlagDirect))
441 AuthorizationFree(authorization, kAuthorizationFlagDefaults);
442 }
443
444 if (flags & kSecAssessmentFlagDirect) {
445 if (__esp_enabled()) {
446 CFTemp<CFDictionaryRef> dict("{target=%O, flags=%d, context=%O}", target, flags, context);
447 OSStatus esp_result = __esp_check_ns("cs-assessment-update", (void *)(CFDictionaryRef)dict);
448 if (esp_result != noErr)
449 return NULL;
450 }
451
452 // ask the engine right here to do its thing
453 result = gEngine().update(target, flags, ctx);
454 } else {
455 // relay the question to our daemon for consideration
456 result = xpcEngineUpdate(target, flags, ctx);
457 }
458
459 if (__esp_enabled() && (flags & kSecAssessmentFlagDirect)) {
460 CFTemp<CFDictionaryRef> dict("{target=%O, flags=%d, context=%O, outcome=%O}", target, flags, context, (CFDictionaryRef)result);
461 __esp_notify_ns("cs-assessment-update", (void *)(CFDictionaryRef)dict);
462 }
463
464 traceUpdate(target, context, result);
465 return result.yield();
466
467 END_CSAPI_ERRORS1(NULL)
468 }
469
470 static void
471 updateAuthority(const char *authority, bool enable, CFErrorRef *errors)
472 {
473 CFStringRef updateValue = enable ? kSecAssessmentUpdateOperationEnable : kSecAssessmentUpdateOperationDisable;
474 CFTemp<CFDictionaryRef> ctx("{%O=%s, %O=%O}", kSecAssessmentUpdateKeyLabel, authority, kSecAssessmentContextKeyUpdate, updateValue);
475 SecAssessmentUpdate(NULL, kSecCSDefaultFlags, ctx, errors);
476 }
477
478
479 //
480 // The fcntl of System Policies.
481 // For those very special requests.
482 //
483 Boolean SecAssessmentControl(CFStringRef control, void *arguments, CFErrorRef *errors)
484 {
485 BEGIN_CSAPI
486
487 CFTemp<CFDictionaryRef> dict("{control=%O}", control);
488 esp_do_check("cs-assessment-control", dict);
489
490 if (CFEqual(control, CFSTR("ui-enable"))) {
491 setAssessment(true);
492 MessageTrace trace("com.apple.security.assessment.state", "enable");
493 trace.send("enable assessment outcomes");
494 return true;
495 } else if (CFEqual(control, CFSTR("ui-disable"))) {
496 setAssessment(false);
497 MessageTrace trace("com.apple.security.assessment.state", "disable");
498 trace.send("disable assessment outcomes");
499 return true;
500 } else if (CFEqual(control, CFSTR("ui-status"))) {
501 CFBooleanRef &result = *(CFBooleanRef*)(arguments);
502 if (overrideAssessment())
503 result = kCFBooleanFalse;
504 else
505 result = kCFBooleanTrue;
506 return true;
507 } else if (CFEqual(control, CFSTR("ui-enable-devid"))) {
508 updateAuthority("Developer ID", true, errors);
509 updateAuthority("Notarized Developer ID", true, errors);
510 MessageTrace trace("com.apple.security.assessment.state", "enable-devid");
511 trace.send("enable Developer ID approval");
512 return true;
513 } else if (CFEqual(control, CFSTR("ui-disable-devid"))) {
514 updateAuthority("Developer ID", false, errors);
515 MessageTrace trace("com.apple.security.assessment.state", "disable-devid");
516 trace.send("disable Developer ID approval");
517 return true;
518 } else if (CFEqual(control, CFSTR("ui-get-devid"))) {
519 xpcEngineCheckDevID((CFBooleanRef*)(arguments));
520 return true;
521 } else if (CFEqual(control, CFSTR("ui-get-devid-local"))) {
522 CFBooleanRef &result = *(CFBooleanRef*)(arguments);
523 if (gEngine().value<int>("SELECT disabled FROM authority WHERE label = 'Developer ID';", true))
524 result = kCFBooleanFalse;
525 else
526 result = kCFBooleanTrue;
527 return true;
528 } else if (CFEqual(control, CFSTR("ui-enable-notarized"))) {
529 updateAuthority("Notarized Developer ID", true, errors);
530 MessageTrace trace("com.apple.security.assessment.state", "enable-notarized");
531 trace.send("enable Notarized Developer ID approval");
532 return true;
533 } else if (CFEqual(control, CFSTR("ui-disable-notarized"))) {
534 updateAuthority("Notarized Developer ID", false, errors);
535 MessageTrace trace("com.apple.security.assessment.state", "disable-notarized");
536 trace.send("disable Notarized Developer ID approval");
537 return true;
538 } else if (CFEqual(control, CFSTR("ui-get-notarized"))) {
539 xpcEngineCheckNotarized((CFBooleanRef*)(arguments));
540 return true;
541 } else if (CFEqual(control, CFSTR("ui-get-notarized-local"))) {
542 CFBooleanRef &result = *(CFBooleanRef*)(arguments);
543 if (gEngine().value<int>("SELECT disabled FROM authority WHERE label = 'Notarized Developer ID';", true))
544 result = kCFBooleanFalse;
545 else
546 result = kCFBooleanTrue;
547 return true;
548 } else if (CFEqual(control, CFSTR("ui-record-reject"))) {
549 // send this through syspolicyd for update validation
550 xpcEngineRecord(CFDictionaryRef(arguments));
551 return true;
552 } else if (CFEqual(control, CFSTR("ui-record-reject-local"))) {
553 // perform the local operation (requires root)
554 gEngine().recordFailure(CFDictionaryRef(arguments));
555 return true;
556 } else if (CFEqual(control, CFSTR("ui-recall-reject"))) {
557 // no special privileges required for this, so read directly
558 CFDictionaryRef &result = *(CFDictionaryRef*)(arguments);
559 CFRef<CFDataRef> infoData = cfLoadFile(lastRejectFile);
560 if (infoData)
561 result = makeCFDictionaryFrom(infoData);
562 else
563 result = NULL;
564 return true;
565 } else if (CFEqual(control, CFSTR("rearm-status"))) {
566 CFTimeInterval &result = *(CFTimeInterval*)(arguments);
567 if (!queryRearmTimer(result))
568 result = 0;
569 return true;
570 } else
571 MacOSError::throwMe(errSecCSInvalidAttributeValues);
572
573 END_CSAPI_ERRORS1(false)
574 }
575
576 Boolean SecAssessmentTicketRegister(CFDataRef ticketData, CFErrorRef *errors)
577 {
578 BEGIN_CSAPI
579
580 xpcEngineTicketRegister(ticketData);
581 return true;
582
583 END_CSAPI_ERRORS1(false)
584 }
585
586 Boolean SecAssessmentTicketLookup(CFDataRef hash, SecCSDigestAlgorithm hashType, SecAssessmentTicketFlags flags, double *date, CFErrorRef *errors)
587 {
588 BEGIN_CSAPI
589
590 xpcEngineTicketLookup(hash, hashType, flags, date);
591 return true;
592
593 END_CSAPI_ERRORS1(false)
594 }
595