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