// // Get the host for an Code // OSStatus SecCodeCopyHost(SecCodeRef guestRef, SecCSFlags flags, SecCodeRef *hostRef) { BEGIN_CSAPI checkFlags(flags); SecPointer<SecCode> host = SecCode::required(guestRef)->host(); CodeSigning::Required(hostRef) = host ? host->handle() : NULL; END_CSAPI }
/*! */ OSStatus SecAccessCreateFromOwnerAndACL(const CSSM_ACL_OWNER_PROTOTYPE *owner, uint32 aclCount, const CSSM_ACL_ENTRY_INFO *acls, SecAccessRef *accessRef) { BEGIN_SECAPI Required(accessRef); // preflight SecPointer<Access> access = new Access(Required(owner), aclCount, &Required(acls)); *accessRef = access->handle(); END_SECAPI }
OSStatus SecKeychainItemCopyAccess(SecKeychainItemRef itemRef, SecAccessRef* accessRef) { BEGIN_SECKCITEMAPI Required(accessRef); // preflight SecPointer<Access> access = new Access(*aclBearer(reinterpret_cast<CFTypeRef>(__itemImplRef))); *accessRef = access->handle(); END_SECKCITEMAPI }
static OSStatus SecAccessCreateFromObject(CFTypeRef sourceRef, SecAccessRef *accessRef) { BEGIN_SECAPI Required(accessRef); // preflight SecPointer<Access> access = new Access(*aclBearer(sourceRef)); *accessRef = access->handle(); END_SECAPI }
OSStatus SecPolicyCopyAll(CSSM_CERT_TYPE certificateType, CFArrayRef* policies) { BEGIN_SECAPI Required(policies); CFMutableArrayRef currPolicies = NULL; currPolicies = CFArrayCreateMutable(NULL, 0, NULL); if ( currPolicies ) { SecPointer<PolicyCursor> cursor(new PolicyCursor(NULL, NULL)); SecPointer<Policy> policy; while ( cursor->next(policy) ) /* copies the next policy */ { CFArrayAppendValue(currPolicies, policy->handle()); /* 'SecPolicyRef' appended */ CFRelease(policy->handle()); /* refcount bumped up when appended to array */ } *policies = CFArrayCreateCopy(NULL, currPolicies); CFRelease(currPolicies); CFRelease(cursor->handle()); } END_SECAPI }
SecPolicyRef SecPolicyCreateWithSecAsn1Oid(SecAsn1Oid *oidPtr) { SecPolicyRef policy = NULL; try { SecPointer<Policy> policyObj; PolicyCursor::policy(oidPtr, policyObj); policy = policyObj->handle(); } catch (...) {} return policy; }
// // Add a code object to the whitelist // void OpaqueWhitelist::add(SecStaticCodeRef codeRef) { // make our own copy of the code object SecPointer<SecStaticCode> code = new SecStaticCode(SecStaticCode::requiredStatic(codeRef)->diskRep()); CFCopyRef<CFDataRef> current = code->cdHash(); attachOpaque(code->handle(false), NULL); // compute and attach an opaque signature CFDataRef opaque = code->cdHash(); SQLite::Statement insert(*this, "INSERT OR REPLACE INTO whitelist (current,opaque) VALUES (:current, :opaque)"); insert.bind(":current") = current.get(); insert.bind(":opaque") = opaque; insert.execute(); }
OSStatus SecIdentitySearchCopyNext( SecIdentitySearchRef searchRef, SecIdentityRef *identityRef) { BEGIN_SECAPI RequiredParam(identityRef); SecPointer<Identity> identityPtr; if (!IdentityCursor::required(searchRef)->next(identityPtr)) return errSecItemNotFound; *identityRef = identityPtr->handle(); END_SECAPI }
// // Get the StaticCode for an Code // OSStatus SecCodeCopyStaticCode(SecCodeRef codeRef, SecCSFlags flags, SecStaticCodeRef *staticCodeRef) { BEGIN_CSAPI checkFlags(flags, kSecCSUseAllArchitectures); SecPointer<SecStaticCode> staticCode = SecCode::required(codeRef)->staticCode(); if (flags & kSecCSUseAllArchitectures) if (Universal* macho = staticCode->diskRep()->mainExecutableImage()) // Mach-O main executable if (macho->narrowed()) { // create a new StaticCode comprising the whole fat file RefPointer<DiskRep> rep = DiskRep::bestGuess(staticCode->diskRep()->mainExecutablePath()); staticCode = new SecStaticCode(rep); } CodeSigning::Required(staticCodeRef) = staticCode ? staticCode->handle() : NULL; END_CSAPI }
/*! * Create a new SecAccessRef that is set to the default configuration * of a (newly created) security object. */ OSStatus SecAccessCreate(CFStringRef descriptor, CFArrayRef trustedList, SecAccessRef *accessRef) { BEGIN_SECAPI Required(descriptor); SecPointer<Access> access; if (trustedList) { CFIndex length = CFArrayGetCount(trustedList); ACL::ApplicationList trusted; for (CFIndex n = 0; n < length; n++) trusted.push_back(TrustedApplication::required( SecTrustedApplicationRef(CFArrayGetValueAtIndex(trustedList, n)))); access = new Access(cfString(descriptor), trusted); } else { access = new Access(cfString(descriptor)); } Required(accessRef) = access->handle(); END_SECAPI }
/*! */ OSStatus SecACLCreateFromSimpleContents(SecAccessRef accessRef, CFArrayRef applicationList, CFStringRef description, const CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR *promptSelector, SecACLRef *newAcl) { BEGIN_SECAPI SecPointer<Access> access = Access::required(accessRef); SecPointer<ACL> acl = new ACL(cfString(description), *promptSelector); if (applicationList) { // application-list + prompt acl->form(ACL::appListForm); setApplications(acl, applicationList); } else { // allow-any acl->form(ACL::allowAllForm); } access->add(acl.get()); Required(newAcl) = acl->handle(); END_SECAPI }
OSStatus SecKeyGenerateWithAttributes( SecKeychainAttributeList* attrList, SecKeychainRef keychainRef, CSSM_ALGORITHMS algorithm, uint32 keySizeInBits, CSSM_CC_HANDLE contextHandle, CSSM_KEYUSE keyUsage, uint32 keyAttr, SecAccessRef initialAccess, SecKeyRef* keyRef) { BEGIN_SECAPI Keychain keychain; SecPointer<Access> theAccess; if (keychainRef) keychain = KeychainImpl::required(keychainRef); if (initialAccess) theAccess = Access::required(initialAccess); SecPointer<KeyItem> item = KeyItem::generateWithAttributes(attrList, keychain, algorithm, keySizeInBits, contextHandle, keyUsage, keyAttr, theAccess); // Return the generated key. if (keyRef) *keyRef = item->handle(); END_SECAPI }
bool IdentityCursorPolicyAndID::next(SecPointer<Identity> &identity) { SecPointer<Identity> currIdentity; Boolean identityOK = true; if (!mPreferredIdentityChecked) { try { findPreferredIdentity(); } catch(...) {} mPreferredIdentityChecked = true; if (mPreferredIdentity) { identity = mPreferredIdentity; return true; } } for (;;) { bool result = IdentityCursor::next(currIdentity); // base class finds the next identity by keyUsage if ( result ) { if (mPreferredIdentity && (currIdentity == mPreferredIdentity)) { identityOK = false; // we already returned this one, move on to the next continue; } // If there was no policy specified, we're done. if ( !mPolicy ) { identityOK = true; // return this identity break; } // To reduce the number of (potentially expensive) trust evaluations performed, we need // to do some pre-processing to filter out certs that don't match the search criteria. // Rather than try to duplicate the TP's policy logic here, we'll just call the TP with // a single-element certificate array, no anchors, and no keychains to search. SecPointer<Certificate> certificate = currIdentity->certificate(); CFRef<SecCertificateRef> certRef(certificate->handle()); CFRef<CFMutableArrayRef> anchorsArray(CFArrayCreateMutable(NULL, 1, NULL)); CFRef<CFMutableArrayRef> certArray(CFArrayCreateMutable(NULL, 1, NULL)); if ( !certArray || !anchorsArray ) { identityOK = false; // skip this and move on to the next one continue; } CFArrayAppendValue(certArray, certRef); SecPointer<Trust> trustLite = new Trust(certArray, mPolicy); StorageManager::KeychainList emptyList; // Set the anchors and keychain search list to be empty trustLite->anchors(anchorsArray); trustLite->searchLibs(emptyList); trustLite->evaluate(); SecTrustResultType trustResult = trustLite->result(); if (trustResult == kSecTrustResultRecoverableTrustFailure || trustResult == kSecTrustResultFatalTrustFailure) { CFArrayRef certChain = NULL; CSSM_TP_APPLE_EVIDENCE_INFO *statusChain = NULL, *evInfo = NULL; trustLite->buildEvidence(certChain, TPEvidenceInfo::overlayVar(statusChain)); if (statusChain) evInfo = &statusChain[0]; if (!evInfo || evInfo->NumStatusCodes > 0) // per-cert codes means we can't use this cert for this policy trustResult = kSecTrustResultInvalid; // handled below if (certChain) CFRelease(certChain); } if (trustResult == kSecTrustResultInvalid) { identityOK = false; // move on to the next one continue; } // If trust evaluation isn't requested, we're done. if ( !mReturnOnlyValidIdentities ) { identityOK = true; // return this identity break; } // Perform a full trust evaluation on the certificate with the specified policy. SecPointer<Trust> trust = new Trust(certArray, mPolicy); trust->evaluate(); trustResult = trust->result(); if (trustResult == kSecTrustResultInvalid || trustResult == kSecTrustResultRecoverableTrustFailure || trustResult == kSecTrustResultFatalTrustFailure) { identityOK = false; // move on to the next one continue; } identityOK = true; // this one was OK; return it. break; } else { identityOK = false; // no more left. break; } } // for(;;) if ( identityOK ) { identity = currIdentity; // caller will release the identity return true; } else { return false; } }
/* * This method returns a copy of the mPolicies array which ensures that * revocation checking (preferably OCSP, otherwise CRL) will be attempted. * * If OCSP is already in the mPolicies array, this makes sure the * CSSM_TP_ACTION_OCSP_REQUIRE_IF_RESP_PRESENT and CSSM_TP_ACTION_OCSP_SUFFICIENT * flags are set. If it's not already in the array, a new policy object is added. * * If CRL is already in the mPolicies array, this makes sure the * CSSM_TP_ACTION_FETCH_CRL_FROM_NET and CSSM_TP_ACTION_CRL_SUFFICIENT flags are * set. If it's not already in the array, a new policy object is added. * * Caller is responsible for releasing the returned policies array. */ CFMutableArrayRef Trust::forceRevocationPolicies( uint32 &numAdded, Allocator &alloc, bool requirePerCert) { SecPointer<Policy> ocspPolicy; SecPointer<Policy> crlPolicy; CSSM_APPLE_TP_OCSP_OPT_FLAGS ocspFlags; CSSM_APPLE_TP_CRL_OPT_FLAGS crlFlags; bool hasOcspPolicy = false; bool hasCrlPolicy = false; numAdded = 0; ocspFlags = CSSM_TP_ACTION_OCSP_SUFFICIENT; crlFlags = CSSM_TP_ACTION_FETCH_CRL_FROM_NET | CSSM_TP_ACTION_CRL_SUFFICIENT; if (requirePerCert) { ocspFlags |= CSSM_TP_ACTION_OCSP_REQUIRE_IF_RESP_PRESENT; crlFlags |= CSSM_TP_ACTION_REQUIRE_CRL_IF_PRESENT; } CFIndex numPolicies = (mPolicies) ? CFArrayGetCount(mPolicies) : 0; for(CFIndex dex=0; dex<numPolicies; dex++) { SecPolicyRef secPol = (SecPolicyRef)CFArrayGetValueAtIndex(mPolicies, dex); SecPointer<Policy> pol = Policy::required(SecPolicyRef(secPol)); const CssmOid &oid = pol->oid(); const CssmData &optData = pol->value(); if(oid == CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP)) { // make sure OCSP options are set correctly CSSM_APPLE_TP_OCSP_OPTIONS *opts = (CSSM_APPLE_TP_OCSP_OPTIONS *)optData.Data; if (opts) { opts->Flags |= ocspFlags; } else { CSSM_APPLE_TP_OCSP_OPTIONS newOpts; memset(&newOpts, 0, sizeof(newOpts)); newOpts.Version = CSSM_APPLE_TP_OCSP_OPTS_VERSION; newOpts.Flags = ocspFlags; CSSM_DATA optData = {sizeof(newOpts), (uint8 *)&newOpts}; pol->value() = optData; } hasOcspPolicy = true; } else if(oid == CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL)) { // make sure CRL options are set correctly CSSM_APPLE_TP_CRL_OPTIONS *opts = (CSSM_APPLE_TP_CRL_OPTIONS *)optData.Data; if (opts) { opts->CrlFlags |= crlFlags; } else { CSSM_APPLE_TP_CRL_OPTIONS newOpts; memset(&newOpts, 0, sizeof(newOpts)); newOpts.Version = CSSM_APPLE_TP_CRL_OPTS_VERSION; newOpts.CrlFlags = crlFlags; CSSM_DATA optData = {sizeof(newOpts), (uint8 *)&newOpts}; pol->value() = optData; } hasCrlPolicy = true; } } /* We're potentially adding something to mPolicies, so make a copy we can work with */ CFMutableArrayRef policies = CFArrayCreateMutableCopy(NULL, 0, mPolicies); if(policies == NULL) { throw std::bad_alloc(); } if(!hasOcspPolicy) { /* Cook up a new Policy object */ ocspPolicy = new Policy(mTP, CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP)); CSSM_APPLE_TP_OCSP_OPTIONS opts; memset(&opts, 0, sizeof(opts)); opts.Version = CSSM_APPLE_TP_OCSP_OPTS_VERSION; opts.Flags = ocspFlags; /* Check prefs dict for local responder info */ Dictionary *prefsDict = NULL; try { /* per-user prefs */ prefsDict = Dictionary::CreateDictionary(kSecRevocationDomain, Dictionary::US_User, true); if (!prefsDict->dict()) { delete prefsDict; prefsDict = NULL; } } catch(...) {} if(prefsDict == NULL) { try { /* system prefs */ prefsDict = Dictionary::CreateDictionary(kSecRevocationDomain, Dictionary::US_System, true); if (!prefsDict->dict()) { delete prefsDict; prefsDict = NULL; } } catch(...) {} } if(prefsDict != NULL) { CFStringRef val = prefsDict->getStringValue(kSecOCSPLocalResponder); if(val != NULL) { CFDataRef cfData = CFStringCreateExternalRepresentation(NULL, val, kCFStringEncodingUTF8, 0); CFIndex len = CFDataGetLength(cfData); opts.LocalResponder = (CSSM_DATA_PTR)alloc.malloc(sizeof(CSSM_DATA)); opts.LocalResponder->Data = (uint8 *)alloc.malloc(len); opts.LocalResponder->Length = len; memmove(opts.LocalResponder->Data, CFDataGetBytePtr(cfData), len); CFRelease(cfData); } } /* Policy manages its own copy of the options data */ CSSM_DATA optData = {sizeof(opts), (uint8 *)&opts}; ocspPolicy->value() = optData; /* Policies array retains the Policy object */ CFArrayAppendValue(policies, ocspPolicy->handle(false)); numAdded++; if(prefsDict != NULL) delete prefsDict; } if(!hasCrlPolicy) { /* Cook up a new Policy object */ crlPolicy = new Policy(mTP, CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL)); CSSM_APPLE_TP_CRL_OPTIONS opts; memset(&opts, 0, sizeof(opts)); opts.Version = CSSM_APPLE_TP_CRL_OPTS_VERSION; opts.CrlFlags = crlFlags; /* Policy manages its own copy of this data */ CSSM_DATA optData = {sizeof(opts), (uint8 *)&opts}; crlPolicy->value() = optData; /* Policies array retains the Policy object */ CFArrayAppendValue(policies, crlPolicy->handle(false)); numAdded++; } return policies; }
CFMutableArrayRef Trust::addPreferenceRevocationPolicies( uint32 &numAdded, Allocator &alloc) { numAdded = 0; /* any per-user prefs? */ Dictionary* pd = Dictionary::CreateDictionary(kSecRevocationDomain, Dictionary::US_User, true); if (pd) { if (!pd->dict()) { delete pd; pd = NULL; } } if(pd == NULL) { pd = Dictionary::CreateDictionary(kSecRevocationDomain, Dictionary::US_System, true); if (!pd->dict()) { delete pd; pd = NULL; } } if(pd == NULL) { CFDictionaryRef tempDict = defaultRevocationSettings(); if (tempDict == NULL) return NULL; pd = new Dictionary(tempDict); CFRelease(tempDict); } auto_ptr<Dictionary> prefsDict(pd); bool doOcsp = false; bool doCrl = false; CFStringRef val; SecRevocationPolicyStyle ocspStyle = kSecBestAttempt; SecRevocationPolicyStyle crlStyle = kSecBestAttempt; SecPointer<Policy> ocspPolicy; SecPointer<Policy> crlPolicy; /* Are any revocation policies enabled? */ val = prefsDict->getStringValue(kSecRevocationOcspStyle); if(val != NULL) { ocspStyle = parseRevStyle(val); if(ocspStyle != kSecDisabled) { doOcsp = true; } } val = prefsDict->getStringValue(kSecRevocationCrlStyle); if(val != NULL) { crlStyle = parseRevStyle(val); if(crlStyle != kSecDisabled) { doCrl = true; } } if(!doCrl && !doOcsp) { return NULL; } /* which policy first? */ bool ocspFirst = true; // default if both present if(doCrl && doOcsp) { val = prefsDict->getStringValue(kSecRevocationWhichFirst); if((val != NULL) && CFEqual(val, kSecRevocationCrlFirst)) { ocspFirst = false; } } /* We're adding something to mPolicies, so make a copy we can work with */ CFMutableArrayRef policies = CFArrayCreateMutableCopy(NULL, 0, mPolicies); if(policies == NULL) { throw std::bad_alloc(); } if(doOcsp) { /* Cook up a new Policy object */ ocspPolicy = new Policy(mTP, CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP)); CSSM_APPLE_TP_OCSP_OPTIONS opts; memset(&opts, 0, sizeof(opts)); opts.Version = CSSM_APPLE_TP_OCSP_OPTS_VERSION; /* Now fill in the OCSP-related blanks */ switch(ocspStyle) { case kSecDisabled: assert(0); break; case kSecBestAttempt: /* default, nothing to set */ break; case kSecRequireIfPresentInCertificate: opts.Flags |= CSSM_TP_ACTION_OCSP_REQUIRE_IF_RESP_PRESENT; break; case kSecRequireForAllCertificates: opts.Flags |= CSSM_TP_ACTION_OCSP_REQUIRE_PER_CERT; break; } if(prefsDict->getBoolValue(kSecRevocationOCSPSufficientPerCert)) { opts.Flags |= CSSM_TP_ACTION_OCSP_SUFFICIENT; } val = prefsDict->getStringValue(kSecOCSPLocalResponder); if(val != NULL) { CFDataRef cfData = CFStringCreateExternalRepresentation(NULL, val, kCFStringEncodingUTF8, 0); CFIndex len = CFDataGetLength(cfData); opts.LocalResponder = (CSSM_DATA_PTR)alloc.malloc(sizeof(CSSM_DATA)); opts.LocalResponder->Data = (uint8 *)alloc.malloc(len); opts.LocalResponder->Length = len; memmove(opts.LocalResponder->Data, CFDataGetBytePtr(cfData), len); CFRelease(cfData); } /* Policy manages its own copy of this data */ CSSM_DATA optData = {sizeof(opts), (uint8 *)&opts}; ocspPolicy->value() = optData; numAdded++; } if(doCrl) { /* Cook up a new Policy object */ crlPolicy = new Policy(mTP, CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL)); CSSM_APPLE_TP_CRL_OPTIONS opts; memset(&opts, 0, sizeof(opts)); opts.Version = CSSM_APPLE_TP_CRL_OPTS_VERSION; /* Now fill in the CRL-related blanks */ opts.CrlFlags = CSSM_TP_ACTION_FETCH_CRL_FROM_NET; // default true switch(crlStyle) { case kSecDisabled: assert(0); break; case kSecBestAttempt: /* default, nothing to set */ break; case kSecRequireIfPresentInCertificate: opts.CrlFlags |= CSSM_TP_ACTION_REQUIRE_CRL_IF_PRESENT; break; case kSecRequireForAllCertificates: opts.CrlFlags |= CSSM_TP_ACTION_REQUIRE_CRL_PER_CERT; break; } if(prefsDict->getBoolValue(kSecRevocationCRLSufficientPerCert)) { opts.CrlFlags |= CSSM_TP_ACTION_CRL_SUFFICIENT; } /* Policy manages its own copy of this data */ CSSM_DATA optData = {sizeof(opts), (uint8 *)&opts}; crlPolicy->value() = optData; numAdded++; } /* append in order */ if(doOcsp) { if(doCrl) { if(ocspFirst) { /* these SecCFObject go away when the policies array does */ CFArrayAppendValue(policies, ocspPolicy->handle(false)); CFArrayAppendValue(policies, crlPolicy->handle(false)); } else { CFArrayAppendValue(policies, crlPolicy->handle(false)); CFArrayAppendValue(policies, ocspPolicy->handle(false)); } } else { CFArrayAppendValue(policies, ocspPolicy->handle(false)); } } else { assert(doCrl); CFArrayAppendValue(policies, crlPolicy->handle(false)); } return policies; }