]> git.saurik.com Git - apple/security.git/blame - OSX/libsecurity_codesigning/lib/SecAssessment.cpp
Security-58286.240.4.tar.gz
[apple/security.git] / OSX / libsecurity_codesigning / lib / SecAssessment.cpp
CommitLineData
b1ab9ed8 1/*
d8f41ccd 2 * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved.
b1ab9ed8
A
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>
fa7225c8 30#include <CoreFoundation/CFBundlePriv.h>
b1ab9ed8
A
31#include <security_utilities/globalizer.h>
32#include <security_utilities/unix++.h>
33#include <security_utilities/cfmunge.h>
34#include <notify.h>
427c49bc 35#include <esp.h>
b1ab9ed8
A
36
37using namespace CodeSigning;
38
39
427c49bc
A
40static 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
b1ab9ed8
A
47//
48// CF Objects
49//
50struct _SecAssessment : private CFRuntimeBase {
51public:
d8f41ccd 52 _SecAssessment(CFURLRef p, AuthorityType typ, CFDictionaryRef r) : path(p), type(typ), result(r) { }
b1ab9ed8
A
53
54 CFCopyRef<CFURLRef> path;
313fa17b 55 AuthorityType type;
b1ab9ed8
A
56 CFRef<CFDictionaryRef> result;
57
58public:
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
73typedef _SecAssessment SecAssessment;
74
75
76static 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
89static dispatch_once_t assessmentOnce;
90CFTypeID assessmentType = _kCFRuntimeNotATypeID;
91
92CFTypeID SecAssessmentGetTypeID()
93{
b1ab9ed8
A
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//
105CFStringRef kSecAssessmentContextKeyOperation = CFSTR("operation");
106CFStringRef kSecAssessmentOperationTypeExecute = CFSTR("operation:execute");
107CFStringRef kSecAssessmentOperationTypeInstall = CFSTR("operation:install");
108CFStringRef kSecAssessmentOperationTypeOpenDocument = CFSTR("operation:lsopen");
109
110
111//
112// Read-only in-process access to the policy database
113//
114class ReadPolicy : public PolicyDatabase {
115public:
116 ReadPolicy() : PolicyDatabase(defaultDatabase) { }
117};
118ModuleNexus<ReadPolicy> gDatabase;
119
120
121//
122// An on-demand instance of the policy engine
123//
124ModuleNexus<PolicyEngine> gEngine;
125
126
127//
128// Policy evaluation ("assessment") operations
129//
641423b6
A
130CFStringRef kSecAssessmentContextKeyUTI = CFSTR("context:uti");
131
d8f41ccd
A
132CFStringRef kSecAssessmentContextKeyFeedback = CFSTR("context:feedback");
133CFStringRef kSecAssessmentFeedbackProgress = CFSTR("feedback:progress");
134CFStringRef kSecAssessmentFeedbackInfoCurrent = CFSTR("current");
135CFStringRef kSecAssessmentFeedbackInfoTotal = CFSTR("total");
136
fa7225c8
A
137CFStringRef kSecAssessmentContextKeyPrimarySignature = CFSTR("context:primary-signature");
138
b1ab9ed8
A
139CFStringRef kSecAssessmentAssessmentVerdict = CFSTR("assessment:verdict");
140CFStringRef kSecAssessmentAssessmentOriginator = CFSTR("assessment:originator");
141CFStringRef kSecAssessmentAssessmentAuthority = CFSTR("assessment:authority");
142CFStringRef kSecAssessmentAssessmentSource = CFSTR("assessment:authority:source");
143CFStringRef kSecAssessmentAssessmentAuthorityRow = CFSTR("assessment:authority:row");
144CFStringRef kSecAssessmentAssessmentAuthorityOverride = CFSTR("assessment:authority:override");
427c49bc 145CFStringRef kSecAssessmentAssessmentAuthorityOriginalVerdict = CFSTR("assessment:authority:verdict");
fa7225c8 146CFStringRef kSecAssessmentAssessmentAuthorityFlags = CFSTR("assessment:authority:flags");
b1ab9ed8 147CFStringRef kSecAssessmentAssessmentFromCache = CFSTR("assessment:authority:cached");
80e23899
A
148CFStringRef kSecAssessmentAssessmentWeakSignature = CFSTR("assessment:authority:weak");
149CFStringRef kSecAssessmentAssessmentCodeSigningError = CFSTR("assessment:cserror");
79b9da22 150CFStringRef kSecAssessmentAssessmentNotarizationDate = CFSTR("assessment:notarization-date");
b1ab9ed8
A
151
152CFStringRef kDisabledOverride = CFSTR("security disabled");
153
b1ab9ed8
A
154SecAssessmentRef 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 {
427c49bc
A
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
b1ab9ed8
A
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:
427c49bc 189 if (!overrideAssessment(flags))
b1ab9ed8
A
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
427c49bc 197 if (!overrideAssessment(flags))
b1ab9ed8
A
198 throw; // let it go as an error
199 cfadd(result, "{%O=#F}", kSecAssessmentAssessmentVerdict);
200 }
427c49bc
A
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
d8f41ccd 207 return new SecAssessment(path, type, result.yield());
b1ab9ed8
A
208
209 END_CSAPI_ERRORS1(NULL)
210}
211
212
427c49bc 213static void traceResult(CFURLRef target, MessageTrace &trace, std::string &sanitized)
b1ab9ed8 214{
427c49bc
A
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 };
b1ab9ed8
A
243
244 string identifier = "UNBUNDLED";
427c49bc 245 string version = "UNKNOWN";
fa7225c8 246 if (CFRef<CFBundleRef> bundle = _CFBundleCreateUnique(NULL, target)) {
b1ab9ed8
A
247 if (CFStringRef ident = CFBundleGetIdentifier(bundle))
248 identifier = cfString(ident);
427c49bc
A
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}
d8f41ccd 279
427c49bc
A
280static void traceAssessment(SecAssessment &assessment, AuthorityType type, CFDictionaryRef result)
281{
282 if (CFDictionaryGetValue(result, CFSTR("assessment:remote")))
283 return; // just traced in syspolicyd
b1ab9ed8
A
284
285 string authority = "UNSPECIFIED";
286 bool overridden = false;
427c49bc 287 bool old_overridden = false;
b1ab9ed8
A
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))
427c49bc
A
294 if (CFEqual(override, kDisabledOverride)) {
295 old_overridden = true;
296 if (CFDictionaryGetValue(authdict, kSecAssessmentAssessmentAuthorityOriginalVerdict) == kCFBooleanFalse)
297 overridden = true;
298 }
b1ab9ed8 299 }
427c49bc
A
300
301 MessageTrace trace("com.apple.security.assessment.outcome2", NULL);
302 std::string sanitized;
303 traceResult(assessment.path, trace, sanitized);
313fa17b 304 trace.add("signature4", "%d", type);
427c49bc 305
b1ab9ed8
A
306 if (CFDictionaryGetValue(result, kSecAssessmentAssessmentVerdict) == kCFBooleanFalse) {
307 trace.add("signature", "denied:%s", authority.c_str());
b1ab9ed8 308 trace.send("assessment denied for %s", sanitized.c_str());
427c49bc
A
309 } else if (overridden) { // would have failed except for override
310 trace.add("signature", "defeated:%s", authority.c_str());
b1ab9ed8 311 trace.send("assessment denied for %s but overridden", sanitized.c_str());
427c49bc
A
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());
b1ab9ed8
A
315 } else {
316 trace.add("signature", "granted:%s", authority.c_str());
b1ab9ed8
A
317 trace.send("assessment granted for %s by %s", sanitized.c_str(), authority.c_str());
318 }
319}
320
427c49bc
A
321static 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
b1ab9ed8
A
335
336//
337// At present, CopyResult simply retrieves the result already formed by Create.
338// In the future, this will be more lazy.
339//
340CFDictionaryRef 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;
427c49bc 348 if (overrideAssessment(flags)) {
b1ab9ed8 349 // turn rejections into approvals, but note that we did that
427c49bc
A
350 CFTypeRef verdict = CFDictionaryGetValue(result, kSecAssessmentAssessmentVerdict);
351 if (verdict == kCFBooleanFalse) {
b1ab9ed8
A
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);
427c49bc 357 CFDictionarySetValue(authority2, kSecAssessmentAssessmentAuthorityOriginalVerdict, verdict);
b1ab9ed8
A
358 CFDictionarySetValue(adulterated, kSecAssessmentAssessmentAuthority, authority2);
359 } else {
360 cfadd(adulterated, "{%O={%O=%O}}",
361 kSecAssessmentAssessmentAuthority, kSecAssessmentAssessmentAuthorityOverride, kDisabledOverride);
362 }
363 result = adulterated.get();
364 }
365 }
d8f41ccd 366 traceAssessment(assessment, assessment.type, result);
b1ab9ed8
A
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//
377CFStringRef kSecAssessmentContextKeyUpdate = CFSTR("update");
378CFStringRef kSecAssessmentUpdateOperationAdd = CFSTR("update:add");
379CFStringRef kSecAssessmentUpdateOperationRemove = CFSTR("update:remove");
380CFStringRef kSecAssessmentUpdateOperationEnable = CFSTR("update:enable");
381CFStringRef kSecAssessmentUpdateOperationDisable = CFSTR("update:disable");
382CFStringRef kSecAssessmentUpdateOperationFind = CFSTR("update:find");
383
384CFStringRef kSecAssessmentUpdateKeyAuthorization = CFSTR("update:authorization");
385CFStringRef kSecAssessmentUpdateKeyPriority = CFSTR("update:priority");
386CFStringRef kSecAssessmentUpdateKeyLabel = CFSTR("update:label");
387CFStringRef kSecAssessmentUpdateKeyExpires = CFSTR("update:expires");
388CFStringRef kSecAssessmentUpdateKeyAllow = CFSTR("update:allow");
389CFStringRef kSecAssessmentUpdateKeyRemarks = CFSTR("update:remarks");
390
391CFStringRef kSecAssessmentUpdateKeyRow = CFSTR("update:row");
392CFStringRef kSecAssessmentUpdateKeyCount = CFSTR("update:count");
393CFStringRef kSecAssessmentUpdateKeyFound = CFSTR("update:found");
394
395CFStringRef kSecAssessmentRuleKeyID = CFSTR("rule:id");
396CFStringRef kSecAssessmentRuleKeyPriority = CFSTR("rule:priority");
397CFStringRef kSecAssessmentRuleKeyAllow = CFSTR("rule:allow");
398CFStringRef kSecAssessmentRuleKeyLabel = CFSTR("rule:label");
399CFStringRef kSecAssessmentRuleKeyRemarks = CFSTR("rule:remarks");
400CFStringRef kSecAssessmentRuleKeyRequirement = CFSTR("rule:requirement");
401CFStringRef kSecAssessmentRuleKeyType = CFSTR("rule:type");
402CFStringRef kSecAssessmentRuleKeyExpires = CFSTR("rule:expires");
403CFStringRef kSecAssessmentRuleKeyDisabled = CFSTR("rule:disabled");
404CFStringRef kSecAssessmentRuleKeyBookmark = CFSTR("rule:bookmark");
405
406
407Boolean 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
420CFDictionaryRef SecAssessmentCopyUpdate(CFTypeRef target,
421 SecAssessmentFlags flags,
422 CFDictionaryRef context,
423 CFErrorRef *errors)
424{
425 BEGIN_CSAPI
426
427 CFDictionary ctx(context, errSecCSInvalidAttributeValues);
427c49bc 428 CFRef<CFDictionaryRef> result;
b1ab9ed8 429
5c19dc3a 430 // make context exist and writable
866f8763 431 CFRef<CFMutableDictionaryRef> mcontext = context ? makeCFMutableDictionary(context) : makeCFMutableDictionary();
5c19dc3a
A
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
b1ab9ed8 444 if (flags & kSecAssessmentFlagDirect) {
427c49bc
A
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
b1ab9ed8 452 // ask the engine right here to do its thing
427c49bc 453 result = gEngine().update(target, flags, ctx);
b1ab9ed8
A
454 } else {
455 // relay the question to our daemon for consideration
427c49bc 456 result = xpcEngineUpdate(target, flags, ctx);
b1ab9ed8
A
457 }
458
427c49bc
A
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
6b200bc3 467 END_CSAPI_ERRORS1(NULL)
b1ab9ed8
A
468}
469
79b9da22
A
470static void
471updateAuthority(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
b1ab9ed8
A
478
479//
480// The fcntl of System Policies.
481// For those very special requests.
482//
483Boolean SecAssessmentControl(CFStringRef control, void *arguments, CFErrorRef *errors)
484{
485 BEGIN_CSAPI
486
427c49bc
A
487 CFTemp<CFDictionaryRef> dict("{control=%O}", control);
488 esp_do_check("cs-assessment-control", dict);
489
b1ab9ed8
A
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"))) {
79b9da22
A
508 updateAuthority("Developer ID", true, errors);
509 updateAuthority("Notarized Developer ID", true, errors);
313fa17b
A
510 MessageTrace trace("com.apple.security.assessment.state", "enable-devid");
511 trace.send("enable Developer ID approval");
b1ab9ed8
A
512 return true;
513 } else if (CFEqual(control, CFSTR("ui-disable-devid"))) {
79b9da22 514 updateAuthority("Developer ID", false, errors);
313fa17b
A
515 MessageTrace trace("com.apple.security.assessment.state", "disable-devid");
516 trace.send("disable Developer ID approval");
b1ab9ed8 517 return true;
fa7225c8
A
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"))) {
b1ab9ed8
A
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;
79b9da22
A
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;
427c49bc
A
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;
d8f41ccd
A
565 } else if (CFEqual(control, CFSTR("rearm-status"))) {
566 CFTimeInterval &result = *(CFTimeInterval*)(arguments);
567 if (!queryRearmTimer(result))
568 result = 0;
569 return true;
b1ab9ed8
A
570 } else
571 MacOSError::throwMe(errSecCSInvalidAttributeValues);
572
573 END_CSAPI_ERRORS1(false)
574}
79b9da22
A
575
576Boolean SecAssessmentTicketRegister(CFDataRef ticketData, CFErrorRef *errors)
577{
578 BEGIN_CSAPI
579
580 xpcEngineTicketRegister(ticketData);
581 return true;
582
583 END_CSAPI_ERRORS1(false)
584}
585
586Boolean 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