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