]> git.saurik.com Git - apple/security.git/commitdiff
Security-57031.10.10.tar.gz os-x-10102 v57031.10.10
authorApple <opensource@apple.com>
Wed, 10 Jun 2015 05:58:05 +0000 (05:58 +0000)
committerApple <opensource@apple.com>
Wed, 10 Jun 2015 05:58:05 +0000 (05:58 +0000)
41 files changed:
Security/Security.xcodeproj/xcshareddata/xcschemes/secdtests.xcscheme
Security/lib/security.exp-in
Security/libsecurity_apple_x509_tp/lib/certGroupUtils.cpp
Security/libsecurity_apple_x509_tp/lib/ocspRequest.cpp
Security/libsecurity_apple_x509_tp/lib/ocspRequest.h
Security/libsecurity_apple_x509_tp/lib/tpOcspCertVfy.cpp
Security/libsecurity_apple_x509_tp/lib/tpOcspVerify.cpp
Security/libsecurity_codesigning/lib/SecTask.c
Security/libsecurity_codesigning/lib/SecTaskPriv.h
Security/libsecurity_codesigning/lib/StaticCode.cpp
Security/libsecurity_codesigning/lib/StaticCode.h
Security/libsecurity_codesigning/lib/security_codesigning.exp
Security/libsecurity_codesigning/libsecurity_codesigning.xcodeproj/project.pbxproj
Security/libsecurity_keychain/lib/Certificate.cpp
Security/libsecurity_keychain/lib/Certificate.h
Security/libsecurity_ocspd/common/ocspResponse.cpp
Security/libsecurity_ocspd/common/ocspResponse.h
Security/libsecurity_ocspd/common/ocspdUtils.cpp
Security/libsecurity_ocspd/common/ocspdUtils.h
Security/sec/SOSCircle/CloudKeychainProxy/CKDKVSProxy.m
Security/sec/SOSCircle/SecureObjectSync/SOSAccount.c
Security/sec/SOSCircle/SecureObjectSync/SOSAccount.h
Security/sec/SOSCircle/SecureObjectSync/SOSAccountCircles.c
Security/sec/SOSCircle/SecureObjectSync/SOSAccountFullPeerInfo.c
Security/sec/SOSCircle/SecureObjectSync/SOSAccountPeers.c
Security/sec/SOSCircle/SecureObjectSync/SOSAccountPersistence.c
Security/sec/SOSCircle/SecureObjectSync/SOSAccountPriv.h
Security/sec/SOSCircle/SecureObjectSync/SOSAccountUpdate.c
Security/sec/SOSCircle/SecureObjectSync/SOSCircle.c
Security/sec/SOSCircle/SecureObjectSync/SOSCircle.h
Security/sec/SOSCircle/SecureObjectSync/SOSEngine.c
Security/sec/SOSCircle/SecureObjectSync/SOSFullPeerInfo.c
Security/sec/SOSCircle/SecureObjectSync/SOSTransport.c
Security/sec/SOSCircle/SecureObjectSync/SOSTransportMessage.c
Security/sec/ipc/server.c
Security/sec/securityd/Regressions/secd-55-account-circle.c
Security/sec/securityd/Regressions/secd-59-account-cleanup.c
Security/sec/securityd/SOSCloudCircleServer.c
Security/sec/securityd/SecOTRRemote.c
Security/utilities/src/debugging.c
SharedWebCredentialViewService/SWCViewController.m

index 0900729aade849b99d61e111f5553966e3760ccd..7ef30f00f2fb9229ad1c5111dc203707c083e7f6 100644 (file)
             argument = "-s"
             isEnabled = "NO">
          </CommandLineArgument>
+         <CommandLineArgument
+            argument = "su_07_debugging"
+            isEnabled = "NO">
+         </CommandLineArgument>
          <CommandLineArgument
             argument = "si_33_keychain_backup"
             isEnabled = "NO">
index 25d19b324112e4fd3d784a60fd99c6617e5b02b9..4aa9a66508e303e17316ec555f10f0c4f358d8de 100644 (file)
@@ -1536,6 +1536,12 @@ _SecInferLabelFromX509Name
 _SecItemAdd
 _SecItemCopyDisplayNames
 _SecItemCopyMatching
+#if TARGET_OS_MAC
+_SecItemAdd_ios
+_SecItemCopyMatching_ios
+_SecItemDelete_ios
+_SecItemUpdate_ios
+#endif
 _SecItemDelete
 _SecItemUpdate
 __SecItemGetPersistentReference
index 8686e5fd5656dec4c9a512a2a96db9f079769abb..97700ebf0082e8e4b4764d844983e75a476c0906 100644 (file)
@@ -634,7 +634,7 @@ CSSM_BOOL tpCompareDomainSuffix(
 
 /*
  * Following a CSSMOID_ECDSA_WithSpecified algorithm is an encoded
- * ECDSA_SigAlgParams containing the digest agorithm OID. Decode and return
+ * ECDSA_SigAlgParams containing the digest algorithm OID. Decode and return
  * a unified ECDSA/digest alg (e.g. CSSM_ALGID_SHA512WithECDSA).
  * Returns nonzero on error.
  */
index 6add077c7aa5ab71bf822e6d51a5f21f681afeae..c609b78011062163a875c5bf4218ab0017b1e323 100644 (file)
@@ -1,15 +1,15 @@
 /*
  * Copyright (c) 2004,2011-2012,2014 Apple Inc. All Rights Reserved.
- * 
+ *
  * @APPLE_LICENSE_HEADER_START@
- * 
+ *
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
  * compliance with the License. Please obtain a copy of the License at
  * http://www.opensource.apple.com/apsl/ and read it before using this
  * file.
- * 
+ *
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  * Please see the License for the specific language governing rights and
  * limitations under the License.
- * 
+ *
  * @APPLE_LICENSE_HEADER_END@
  */
 
 /*
  * ocspRequest.cpp - OCSP Request class
  */
+
 #include "ocspRequest.h"
 #include "certGroupUtils.h"
 #include "tpdebugging.h"
@@ -47,15 +47,15 @@ static uint8 nullParam[2] = {5, 0};
 #define OCSP_NONCE_SIZE                8
 
 /*
- * The only constructor. Subject and issuer must remain valid for the 
- * lifetime of this object (they are not refcounted). 
+ * The only constructor. Subject and issuer must remain valid for the
+ * lifetime of this object (they are not refcounted).
  */
 OCSPRequest::OCSPRequest(
        TPCertInfo              &subject,
        TPCertInfo              &issuer,
        bool                    genNonce)
                : mCoder(NULL),
-                 mSubject(subject), 
+                 mSubject(subject),
                  mIssuer(issuer),
                  mGenNonce(genNonce),
                  mCertID(NULL)
@@ -81,6 +81,7 @@ const CSSM_DATA *OCSPRequest::encode()
        CSSM_DATA_PTR   issuerName;
        CSSM_DATA_PTR   issuerKey;
        CSSM_KEY_PTR    issuerPubKey;
+       CSSM_DATA               issuerPubKeyBytes;
        /* from subject */
        CSSM_DATA_PTR   subjectSerial=NULL;
 
@@ -98,17 +99,17 @@ const CSSM_DATA *OCSPRequest::encode()
        CSSM_DATA                                       nonceData = {OCSP_NONCE_SIZE, nonceBytes};
        OCSPNonce                                       *nonce = NULL;
        NSS_CertExtension                       *extenArray[2] = {NULL, NULL};
-       
+
        if(mEncoded.Data) {
                /* already done */
                return &mEncoded;
        }
 
-       /* 
+       /*
         * One single request, no extensions
         */
        memset(&singleReq, 0, sizeof(singleReq));
-       
+
        /* algId refers to the hash we'll perform in issuer name and key */
        certId.algId.algorithm = CSSMOID_SHA1;
        certId.algId.parameters.Data = nullParam;
@@ -138,16 +139,17 @@ const CSSM_DATA *OCSPRequest::encode()
                goto errOut;
        }
        issuerPubKey = (CSSM_KEY_PTR)issuerKey->Data;
-       ocspdSha1(issuerPubKey->KeyData.Data, (CC_LONG)issuerPubKey->KeyData.Length, pubKeyHash);
-       
+       ocspdGetPublicKeyBytes(mCoder, issuerPubKey, issuerPubKeyBytes);
+       ocspdSha1(issuerPubKeyBytes.Data, (CC_LONG)issuerPubKeyBytes.Length, pubKeyHash);
+
        /* build the CertID from those components */
        certId.issuerNameHash.Data = issuerNameHash;
        certId.issuerNameHash.Length = CC_SHA1_DIGEST_LENGTH;
        certId.issuerPubKeyHash.Data = pubKeyHash;
-       certId.issuerPubKeyHash.Length = CC_SHA1_DIGEST_LENGTH; 
+       certId.issuerPubKeyHash.Length = CC_SHA1_DIGEST_LENGTH;
        certId.serialNumber = *subjectSerial;
 
-       /* 
+       /*
         * Build top level request with one entry in requestList, no signature,
         * one optional extension (a nonce)
         */
@@ -164,17 +166,17 @@ const CSSM_DATA *OCSPRequest::encode()
                tbs.requestExtensions = extenArray;
                SecAsn1AllocCopyItem(mCoder, &nonceData, &mNonce);
        }
-       
+
        /* Encode */
-       if(SecAsn1EncodeItem(mCoder, &signedReq, kSecAsn1OCSPSignedRequestTemplate, 
+       if(SecAsn1EncodeItem(mCoder, &signedReq, kSecAsn1OCSPSignedRequestTemplate,
                        &mEncoded)) {
                tpErrorLog("OCSPRequest::encode: error encoding OCSP req\n");
                crtn = CSSMERR_TP_INTERNAL_ERROR;
                goto errOut;
        }
        /* save a copy of the CertID */
-       mCertID = new OCSPClientCertID(*issuerName, issuerPubKey->KeyData, *subjectSerial);
-       
+       mCertID = new OCSPClientCertID(*issuerName, issuerPubKeyBytes, *subjectSerial);
+
 errOut:
        if(issuerName) {
                mIssuer.freeField(&CSSMOID_X509V1IssuerNameStd, issuerName);
index 7d68fd0d5f7db69417158883a2b8980f58fefc49..8341dc63399047a9416d69388512a087f0d445f4 100644 (file)
@@ -1,15 +1,15 @@
 /*
  * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved.
- * 
+ *
  * @APPLE_LICENSE_HEADER_START@
- * 
+ *
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
  * compliance with the License. Please obtain a copy of the License at
  * http://www.opensource.apple.com/apsl/ and read it before using this
  * file.
- * 
+ *
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  * Please see the License for the specific language governing rights and
  * limitations under the License.
- * 
+ *
  * @APPLE_LICENSE_HEADER_END@
  */
 
 /*
  * ocspRequest.h - OCSP Request class
  */
+
 #ifndef        _OCSP_REQUEST_H_
 #define _OCSP_REQUEST_H_
 
@@ -39,35 +39,35 @@ class OCSPRequest
        NOCOPY(OCSPRequest)
 public:
        /*
-        * The only constructor. Subject and issuer must remain valid for the 
-        * lifetime of this object (they are not refcounted). 
+        * The only constructor. Subject and issuer must remain valid for the
+        * lifetime of this object (they are not refcounted).
         */
        OCSPRequest(
                TPCertInfo              &subject,
                TPCertInfo              &issuer,
                bool                    genNonce);
-               
+
        ~OCSPRequest();
-       
-       /* 
+
+       /*
         * Obtain encoded OCSP request suitable for posting to responder.
         * This object owns and maintains the memory.
         */
        const CSSM_DATA *encode();
 
-       /* 
+       /*
         * Obtain this request's nonce (which we randomly generate at encode() time),
         * This object owns and maintains the memory. Result is NULL} if we
-        * didn't generate a nonce. 
+        * didn't generate a nonce.
         */
        const CSSM_DATA *nonce();
-                       
-       /* 
+
+       /*
         * Obtain this request's CertID. Used to look up matching SingleResponse
         * in the OCSPResponse.
         */
        OCSPClientCertID        *certID();
-       
+
 private:
        SecAsn1CoderRef         mCoder;
        TPCertInfo                      &mSubject;
@@ -76,7 +76,7 @@ private:
        CSSM_DATA                       mNonce;
        CSSM_DATA                       mEncoded;       /* lazily evaluated */
        OCSPClientCertID        *mCertID;       /* calculated during encode() */
-       
+
 };
 
 #endif /* _OCSP_REQUEST_H_ */
index 6fdb9e69900c00b3f40f16e3ef482abb42623619..5356ca77813d649121d534ee96a8e3b4f9456b4f 100644 (file)
@@ -1,15 +1,15 @@
 /*
  * Copyright (c) 2004,2011-2012,2014 Apple Inc. All Rights Reserved.
- * 
+ *
  * @APPLE_LICENSE_HEADER_START@
- * 
+ *
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
  * compliance with the License. Please obtain a copy of the License at
  * http://www.opensource.apple.com/apsl/ and read it before using this
  * file.
- * 
+ *
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
@@ -17,7 +17,7 @@
  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  * Please see the License for the specific language governing rights and
  * limitations under the License.
- * 
+ *
  * @APPLE_LICENSE_HEADER_END@
  */
 
 #include <CommonCrypto/CommonDigest.h>
 #include <security_ocspd/ocspdUtils.h>
 
+#ifndef        NDEBUG
+#include <Security/SecCertificate.h>
+#endif
+
 /*
  * Is signerCert authorized to sign OCSP responses by issuerCert? IssuerCert is
- * assumed to be (i.e., must, but we don't check that here) the signer of the 
+ * assumed to be (i.e., must, but we don't check that here) the signer of the
  * cert being verified, which is not in the loop for this op. Just a bool returned;
- * it's autoritized or it's not. 
+ * it's authorized or it's not.
  */
 static bool tpIsAuthorizedOcspSigner(
        TPCertInfo &issuerCert,         // issuer of cert being verified
@@ -47,28 +51,67 @@ static bool tpIsAuthorizedOcspSigner(
        bool                            ourRtn = false;
        CE_ExtendedKeyUsage *eku = NULL;
        bool                            foundEku = false;
-       
-       /* 
+
+       /*
         * First see if issuerCert issued signerCert (No signature vfy yet, just
         * subject/issuer check).
         */
        if(!issuerCert.isIssuerOf(signerCert)) {
+#ifndef        NDEBUG
+               SecCertificateRef issuerRef = NULL;
+               SecCertificateRef signerRef = NULL;
+               const CSSM_DATA *issuerData = issuerCert.itemData();
+               const CSSM_DATA *signerData = signerCert.itemData();
+               crtn = SecCertificateCreateFromData(issuerData, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_BER, &issuerRef);
+               crtn = SecCertificateCreateFromData(signerData, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_BER, &signerRef);
+               CFStringRef issuerName = SecCertificateCopySubjectSummary(issuerRef);
+               CFStringRef signerName = SecCertificateCopySubjectSummary(signerRef);
+               if(issuerName) {
+                       CFIndex maxLength = CFStringGetMaximumSizeForEncoding(CFStringGetLength(issuerName), kCFStringEncodingUTF8) + 1;
+                       char* buf = (char*) malloc(maxLength);
+                       if (buf) {
+                               if (CFStringGetCString(issuerName, buf, (CFIndex)maxLength, kCFStringEncodingUTF8)) {
+                                       tpOcspDebug("tpIsAuthorizedOcspSigner: issuerCert \"%s\"", buf);
+                               }
+                               free(buf);
+                       }
+                       CFRelease(issuerName);
+               }
+               if(signerName) {
+                       CFIndex maxLength = CFStringGetMaximumSizeForEncoding(CFStringGetLength(signerName), kCFStringEncodingUTF8) + 1;
+                       char* buf = (char*) malloc(maxLength);
+                       if (buf) {
+                               if (CFStringGetCString(signerName, buf, (CFIndex)maxLength, kCFStringEncodingUTF8)) {
+                                       tpOcspDebug("tpIsAuthorizedOcspSigner: signerCert \"%s\"", buf);
+                               }
+                               free(buf);
+                       }
+                       CFRelease(signerName);
+               }
+               if(issuerRef) {
+                       CFRelease(issuerRef);
+               }
+               if(signerRef) {
+                       CFRelease(signerRef);
+               }
+#endif
+               tpOcspDebug("tpIsAuthorizedOcspSigner: signer is not issued by issuerCert");
                return false;
        }
-       
+
        /* Fetch ExtendedKeyUse field from signerCert */
        crtn = signerCert.fetchField(&CSSMOID_ExtendedKeyUsage, &fieldValue);
        if(crtn) {
                tpOcspDebug("tpIsAuthorizedOcspSigner: signer is issued by issuer, no EKU");
                return false;
-       }       
+       }
        CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)fieldValue->Data;
        if(cssmExt->format != CSSM_X509_DATAFORMAT_PARSED) {
                tpOcspDebug("tpIsAuthorizedOcspSigner: bad extension format");
                goto errOut;
        }
        eku = (CE_ExtendedKeyUsage *)cssmExt->value.parsedValue;
-       
+
        /* Look for OID_KP_OCSPSigning */
        for(unsigned dex=0; dex<eku->numPurposes; dex++) {
                if(tpCompareCssmData(&eku->purposes[dex], &CSSMOID_OCSPSigning)) {
@@ -82,9 +125,9 @@ static bool tpIsAuthorizedOcspSigner(
                goto errOut;
        }
 
-       /* 
-        * OK, signerCert is authorized by *someone* to sign OCSP requests, and 
-        * it claims to be issued by issuer. Sig verify to be sure. 
+       /*
+        * OK, signerCert is authorized by *someone* to sign OCSP requests, and
+        * it claims to be issued by issuer. Sig verify to be sure.
         * FIXME this is not handling partial public keys, which would be a colossal
         * mess to handle in this module...so we don't.
         */
@@ -104,8 +147,8 @@ errOut:
        return ourRtn;
 }
 
-/* 
- * Check ResponderID linkage between an OCSPResponse and a cert we believe to 
+/*
+ * Check ResponderID linkage between an OCSPResponse and a cert we believe to
  * be the issuer of both that response and the cert being verified. Returns
  * true if OK.
  */
@@ -116,14 +159,14 @@ bool tpOcspResponderIDCheck(
 {
        bool shouldBeSigner = false;
        if(ocspResp.responderIDTag() == RIT_Name) {
-               /* 
+               /*
                 * Name inside response must == signer's SubjectName.
                 * Note we can't use signer.subjectName(); that's normalized.
                 */
 
                const CSSM_DATA *respIdName = ocspResp.encResponderName();
                CSSM_DATA *subjectName = NULL;
-               CSSM_RETURN crtn = signer.fetchField(&CSSMOID_X509V1SubjectNameStd, 
+               CSSM_RETURN crtn = signer.fetchField(&CSSMOID_X509V1SubjectNameStd,
                        &subjectName);
                if(crtn) {
                        /* bad cert */
@@ -141,11 +184,13 @@ bool tpOcspResponderIDCheck(
        }
        else {
                /* ResponderID.byKey must == SHA1(signer's public key) */
-               const CSSM_KEY *pubKey = signer.pubKey();
+               const CSSM_KEY_PTR pubKey = signer.pubKey();
                assert(pubKey != NULL);
                uint8 digest[CC_SHA1_DIGEST_LENGTH];
                CSSM_DATA keyHash = {CC_SHA1_DIGEST_LENGTH, digest};
-               ocspdSha1(pubKey->KeyData.Data, (CC_LONG)pubKey->KeyData.Length, digest);
+               CSSM_DATA pubKeyBytes = {0, NULL};
+               ocspdGetPublicKeyBytes(NULL, pubKey, pubKeyBytes);
+               ocspdSha1(pubKeyBytes.Data, (CC_LONG)pubKeyBytes.Length, digest);
                const CSSM_DATA *respKeyHash = &ocspResp.responderID().byKey;
                if(tpCompareCssmData(&keyHash, respKeyHash)) {
                        tpOcspDebug("tpOcspResponderIDCheck: good ResponderID.byKey");
@@ -159,9 +204,9 @@ bool tpOcspResponderIDCheck(
 }
 
 /*
- * Verify the signature of an OCSP response. Caller is responsible for all other 
+ * Verify the signature of an OCSP response. Caller is responsible for all other
  * verification of the response, this is just the crypto.
- * Returns true on success. 
+ * Returns true on success.
  */
 static bool tpOcspResponseSigVerify(
        TPVerifyContext         &vfyCtx,
@@ -172,18 +217,18 @@ static bool tpOcspResponseSigVerify(
        const SecAsn1OCSPBasicResponse &basicResp = ocspResp.basicResponse();
        const CSSM_OID *algOid = &basicResp.algId.algorithm;
        CSSM_ALGORITHMS sigAlg;
-       
+
        if(!cssmOidToAlg(algOid, &sigAlg)) {
                tpOcspDebug("tpOcspResponseSigVerify: unknown signature algorithm");
        }
-       
+
        /* signer's public key from the cert */
        const CSSM_KEY *pubKey = signer.pubKey();
-       
+
        /* signature: on decode, length is in BITS */
        CSSM_DATA sig = basicResp.sig;
        sig.Length /= 8;
-       
+
        CSSM_RETURN crtn;
        CSSM_CC_HANDLE sigHand;
        bool ourRtn = false;
@@ -220,14 +265,14 @@ typedef enum {
 typedef enum {
        OCT_Local,              // LocalResponder - no checking other than signature
        OCT_Issuer,             // it's the issuer of the cert being verified
-       OCT_Provided,   // came with response, provenance unknown 
+       OCT_Provided,   // came with response, provenance unknown
 } OcspCertType;
 
 /*
- * Did specified cert issue the OCSP response? 
+ * Did specified cert issue the OCSP response?
  *
  * This implements the algorithm described in RFC2560, section 4.2.2.2,
- * "Authorized Responders". It sees if the cert could be the issuer of the 
+ * "Authorized Responders". It sees if the cert could be the issuer of the
  * OCSP response per that algorithm; then if it could, it performs signature
  * verification.
  */
@@ -237,12 +282,12 @@ static OcspIssuerStatus tpIsOcspIssuer(
        /* on input specify at least one of the following two */
        const CSSM_DATA         *signerData,
        TPCertInfo                      *signer,
-       OcspCertType            certType,               // where rawCert came from 
+       OcspCertType            certType,               // where rawCert came from
        TPCertInfo                      *issuer,                // OPTIONAL, if known
        TPCertInfo                      **signerRtn)    // optionally RETURNED if at all possible
 {
        assert((signerData != NULL) || (signer != NULL));
-       
+
        /* get signer as TPCertInfo if caller hasn't provided */
        TPCertInfo *tmpSigner = NULL;
        if(signer == NULL) {
@@ -262,14 +307,14 @@ static OcspIssuerStatus tpIsOcspIssuer(
        if(signerRtn != NULL) {
                *signerRtn = signer;
        }
-       
-       /* 
+
+       /*
         * Qualification of "this can be the signer" depends on where the
         * signer came from.
         */
        bool shouldBeSigner = false;
        OcspIssuerStatus ourRtn = OIS_No;
-       
+
        switch(certType) {
                case OCT_Local:                 // caller trusts this and thinks it's the signer
                        shouldBeSigner = true;
@@ -280,12 +325,12 @@ static OcspIssuerStatus tpIsOcspIssuer(
                        break;
                case OCT_Provided:
                {
-                       /* 
+                       /*
                         * This cert came with the response.
                         */
                        if(issuer == NULL) {
-                               /* 
-                                * careful, might not know the issuer...how would this path ever 
+                               /*
+                                * careful, might not know the issuer...how would this path ever
                                 * work then? I don't think it needs to because you can NOT
                                 * do OCSP on a cert without its issuer in hand.
                                 */
@@ -300,12 +345,12 @@ static OcspIssuerStatus tpIsOcspIssuer(
        if(!shouldBeSigner) {
                goto errOut;
        }
-       
+
        /* verify the signature */
        if(tpOcspResponseSigVerify(vfyCtx, ocspResp, *signer)) {
                ourRtn = OIS_Good;
        }
-       
+
 errOut:
        if((signerRtn == NULL) && (tmpSigner != NULL)) {
                delete tmpSigner;
@@ -317,19 +362,19 @@ errOut:
 OcspRespStatus tpVerifyOcspResp(
        TPVerifyContext         &vfyCtx,
        SecNssCoder                     &coder,
-       TPCertInfo                      *issuer,                // issuer of the related cert, may be issuer of 
-                                                                               //   reply, may not be known 
+       TPCertInfo                      *issuer,                // issuer of the related cert, may be issuer of
+                                                                               //   reply, may not be known
        OCSPResponse            &ocspResp,
-       CSSM_RETURN                     &cssmErr)               // possible per-cert error 
+       CSSM_RETURN                     &cssmErr)               // possible per-cert error
 {
        OcspRespStatus  ourRtn = ORS_Unknown;
        CSSM_RETURN             crtn;
-               
+
        tpOcspDebug("tpVerifyOcspResp top");
-       
+
        switch(ocspResp.responseStatus()) {
-               case RS_Success: 
-                       crtn = CSSM_OK; 
+               case RS_Success:
+                       crtn = CSSM_OK;
                        break;
                case RS_MalformedRequest:
                        crtn = CSSMERR_APPLETP_OCSP_RESP_MALFORMED_REQ;
@@ -357,7 +402,7 @@ OcspRespStatus tpVerifyOcspResp(
                return ORS_Unknown;
        }
        cssmErr = CSSM_OK;
-       
+
        /* one of our main jobs is to locate the signer of the response, here */
        TPCertInfo *signerInfo = NULL;
        TPCertInfo *signerInfoTBD = NULL;               // if non NULL at end, we delete
@@ -366,45 +411,45 @@ OcspRespStatus tpVerifyOcspResp(
        CSSM_BOOL verifiedToRoot;
        CSSM_BOOL verifiedToAnchor;
        CSSM_BOOL verifiedViaTrustSetting;
-       
+
        const CSSM_APPLE_TP_OCSP_OPTIONS *ocspOpts = vfyCtx.ocspOpts;
        OcspIssuerStatus issuerStat;
-       
-       /* 
+
+       /*
         * Set true if we ever find an apparent issuer which does not correctly
         * pass signature verify. If true and we never success, that's a XXX error.
         */
        bool foundBadIssuer = false;
        bool foundLocalResponder = false;
        uint32 numSignerCerts = ocspResp.numSignerCerts();
-       
+
        /*
-        * This cert group, allocated by AppleTPSession::CertGroupVerify(), 
+        * This cert group, allocated by AppleTPSession::CertGroupVerify(),
         * serves two functions here:
         *
         * -- it accumulates certs we get from the net (as parts of OCSP responses)
         *    for user in verifying OCSPResponse-related certs.
-        *    TPCertGroup::buildCertGroup() uses this group as one of the many 
+        *    TPCertGroup::buildCertGroup() uses this group as one of the many
         *    sources of certs when building a cert chain.
         *
-        * -- it provides a container into which to stash TPCertInfos which 
+        * -- it provides a container into which to stash TPCertInfos which
         *    persist at least as long as the TPVerifyContext; it's of type TGO_Group,
-        *    so all of the certs added to it get freed when the group does. 
+        *    so all of the certs added to it get freed when the group does.
         */
        assert(vfyCtx.signerCerts != NULL);
-       
+
        TPCertGroup &gatheredCerts = vfyCtx.gatheredCerts;
-       
+
        /* set up for disposal of TPCertInfos created by TPCertGroup::buildCertGroup() */
        TPCertGroup     certsToBeFreed(vfyCtx.alloc, TGO_Group);
-       
-       /* 
+
+       /*
         * First job is to find the cert which signed this response.
         * Give priority to caller's LocalResponderCert.
         */
        if((ocspOpts != NULL) && (ocspOpts->LocalResponderCert != NULL)) {
                TPCertInfo *responderInfo = NULL;
-               issuerStat = tpIsOcspIssuer(vfyCtx, ocspResp, 
+               issuerStat = tpIsOcspIssuer(vfyCtx, ocspResp,
                        ocspOpts->LocalResponderCert, NULL,
                        OCT_Local, issuer, &responderInfo);
                switch(issuerStat) {
@@ -425,9 +470,9 @@ OcspRespStatus tpVerifyOcspResp(
                                break;
                }
        }
-       
+
        if((signerInfo == NULL) && (numSignerCerts != 0)) {
-               /* 
+               /*
                 * App did not specify a local responder (or provided a bad one)
                 * and the response came with some certs. Try those.
                 */
@@ -436,7 +481,7 @@ OcspRespStatus tpVerifyOcspResp(
                        const CSSM_DATA *certData = ocspResp.signerCert(dex);
                        if(signerInfo == NULL) {
                                /* stop trying this after we succeed... */
-                               issuerStat = tpIsOcspIssuer(vfyCtx, ocspResp, 
+                               issuerStat = tpIsOcspIssuer(vfyCtx, ocspResp,
                                        certData, NULL,
                                        OCT_Provided, issuer, &respCert);
                                switch(issuerStat) {
@@ -453,7 +498,7 @@ OcspRespStatus tpVerifyOcspResp(
                                }
                        }
                        else {
-                               /* 
+                               /*
                                 * At least add this cert to certGroup for verification.
                                 * OcspCert will own the TPCertInfo.
                                 */
@@ -471,13 +516,13 @@ OcspRespStatus tpVerifyOcspResp(
                        }
                }
        }
-       
+
        if((signerInfo == NULL) && (issuer != NULL)) {
-               /* 
+               /*
                 * Haven't found it yet, try the actual issuer
                 */
-               issuerStat = tpIsOcspIssuer(vfyCtx, ocspResp, 
-                       NULL, issuer, 
+               issuerStat = tpIsOcspIssuer(vfyCtx, ocspResp,
+                       NULL, issuer,
                        OCT_Issuer, issuer, NULL);
                switch(issuerStat) {
                        case OIS_BadSig:
@@ -492,7 +537,7 @@ OcspRespStatus tpVerifyOcspResp(
                                break;
                }
        }
-               
+
        if(signerInfo == NULL) {
                if((issuer != NULL) && !issuer->isStatusFatal(CSSMERR_APPLETP_OCSP_NO_SIGNER)) {
                        /* user wants to proceed without verifying! */
@@ -521,10 +566,10 @@ OcspRespStatus tpVerifyOcspResp(
                ourRtn = ORS_Good;
                goto errOut;
        }
-       
-       /* 
-        * Last remaining task is to verify the signer, and all the certs back to 
-        * an anchor 
+
+       /*
+        * Last remaining task is to verify the signer, and all the certs back to
+        * an anchor
         */
 
        /* start from scratch with both of these groups */
@@ -547,7 +592,7 @@ OcspRespStatus tpVerifyOcspResp(
                        vfyCtx.policyStr,
                        vfyCtx.policyStrLen,
                        kSecTrustSettingsKeyUseSignRevocation,
-                       verifiedToRoot, 
+                       verifiedToRoot,
                        verifiedToAnchor,
                        verifiedViaTrustSetting);
        if(crtn) {
@@ -582,9 +627,9 @@ OcspRespStatus tpVerifyOcspResp(
                tpOcspDebug("tpVerifyOcspResp SUCCESS; chain verified");
                ourRtn = ORS_Good;
        }
-       
+
        /* FIXME policy verify? */
-       
+
 errOut:
        delete signerInfoTBD;
        /* any other cleanup? */
index e17e7cf05b1090b1b1cc0f35a47ca525bd5d9045..ae11caf6f9661b9449ac4452c696e4153152162b 100644 (file)
@@ -1,15 +1,15 @@
 /*
  * Copyright (c) 2004,2011-2012,2014 Apple Inc. All Rights Reserved.
- * 
+ *
  * @APPLE_LICENSE_HEADER_START@
- * 
+ *
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
  * compliance with the License. Please obtain a copy of the License at
  * http://www.opensource.apple.com/apsl/ and read it before using this
  * file.
- * 
+ *
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  * Please see the License for the specific language governing rights and
  * limitations under the License.
- * 
+ *
  * @APPLE_LICENSE_HEADER_END@
  */
 
 /*
  * tpOcspVerify.cpp - top-level OCSP verification
  */
+
 #include "tpOcspVerify.h"
 #include "tpdebugging.h"
 #include "ocspRequest.h"
@@ -42,7 +42,7 @@
 
 #pragma mark ---- private routines ----
 
-/* 
+/*
  * Get a smart CertID for specified cert and issuer
  */
 static CSSM_RETURN tpOcspGetCertId(
@@ -54,8 +54,9 @@ static CSSM_RETURN tpOcspGetCertId(
        CSSM_DATA_PTR issuerSubject = NULL;
        CSSM_DATA_PTR issuerPubKeyData = NULL;
        CSSM_KEY_PTR issuerPubKey;
+       CSSM_DATA issuerPubKeyBytes;
        CSSM_DATA_PTR subjectSerial = NULL;
-       
+
        crtn = subject.fetchField(&CSSMOID_X509V1SerialNumber, &subjectSerial);
        if(crtn) {
                return crtn;
@@ -70,25 +71,26 @@ static CSSM_RETURN tpOcspGetCertId(
        }
        assert(issuerPubKeyData->Length == sizeof(CSSM_KEY));
        issuerPubKey = (CSSM_KEY_PTR)issuerPubKeyData->Data;
-       certID = new OCSPClientCertID(*issuerSubject, issuerPubKey->KeyData, *subjectSerial);
-       
+       ocspdGetPublicKeyBytes(NULL, issuerPubKey, issuerPubKeyBytes);
+       certID = new OCSPClientCertID(*issuerSubject, issuerPubKeyBytes, *subjectSerial);
+
        subject.freeField(&CSSMOID_X509V1SerialNumber, subjectSerial);
        issuer.freeField(&CSSMOID_X509V1IssuerNameStd, issuerSubject);
        issuer.freeField(&CSSMOID_CSSMKeyStruct, issuerPubKeyData);
        return CSSM_OK;
 }
 
-/* 
+/*
  * Examine cert, looking for AuthorityInfoAccess, with id-ad-ocsp URIs. Create
- * an NULL_terminated array of CSSM_DATAs containing the URIs if found. 
+ * an NULL_terminated array of CSSM_DATAs containing the URIs if found.
  */
 static CSSM_DATA **tpOcspUrlsFromCert(
-       TPCertInfo &subject, 
+       TPCertInfo &subject,
        SecNssCoder &coder)
 {
        CSSM_DATA_PTR extField = NULL;
        CSSM_RETURN crtn;
-       
+
        crtn = subject.fetchField(&CSSMOID_AuthorityInfoAccess, &extField);
        if(crtn) {
                tpOcspDebug("tpOcspUrlsFromCert: no AIA extension");
@@ -103,8 +105,8 @@ static CSSM_DATA **tpOcspUrlsFromCert(
                tpErrorLog("tpOcspUrlsFromCert: malformed CSSM_X509_EXTENSION");
                return NULL;
        }
-       
-       CE_AuthorityInfoAccess *aia = 
+
+       CE_AuthorityInfoAccess *aia =
                (CE_AuthorityInfoAccess *)cssmExt->value.parsedValue;
        CSSM_DATA **urls = NULL;
        unsigned numUrls = 0;
@@ -118,7 +120,7 @@ static CSSM_DATA **tpOcspUrlsFromCert(
                        tpErrorLog("tpOcspUrlsFromCert: CSSMOID_AD_OCSP, but not type URI");
                        continue;
                }
-               
+
                /* got one */
                if(urls == NULL) {
                        urls = coder.mallocn<CSSM_DATA_PTR>(2);
@@ -148,7 +150,7 @@ static CSSM_DATA **tpOcspUrlsFromCert(
        return urls;
 }
 
-/* 
+/*
  * Create an SecAsn1OCSPDRequest for one cert. This consists of:
  *
  * -- cooking up an OCSPRequest if net fetch is enabled or a local responder
@@ -170,7 +172,7 @@ static SecAsn1OCSPDRequest *tpGenOcspdReq(
        OCSPClientCertID                *certID = NULL;
        CSSM_RETURN                             crtn;
        bool                                    deleteCertID = false;
-       
+
        /* gather options or their defaults */
        CSSM_APPLE_TP_OCSP_OPT_FLAGS optFlags = 0;
        const CSSM_APPLE_TP_OCSP_OPTIONS *ocspOpts = vfyCtx.ocspOpts;
@@ -183,16 +185,16 @@ static SecAsn1OCSPDRequest *tpGenOcspdReq(
        }
        bool genNonce = optFlags & CSSM_TP_OCSP_GEN_NONCE ? true : false;
        bool requireRespNonce = optFlags & CSSM_TP_OCSP_REQUIRE_RESP_NONCE ? true : false;
-       
-       /* 
+
+       /*
         * One degenerate case in case we can't really do anything.
         * If no URI and no local responder, only proceed if cache is not disabled
         * and we're requiring full OCSP per cert.
         */
        if( ( (optFlags & CSSM_TP_ACTION_OCSP_CACHE_READ_DISABLE) ||
                  !(optFlags & CSSM_TP_ACTION_OCSP_REQUIRE_PER_CERT)
-               ) && 
-          (localResponder == NULL) &&  
+               ) &&
+          (localResponder == NULL) &&
           (urls == NULL)) {
           tpOcspDebug("tpGenOcspdReq: no route to OCSP; NULL return");
           return NULL;
@@ -213,7 +215,7 @@ static SecAsn1OCSPDRequest *tpGenOcspdReq(
                        }
                }
        }
-       
+
        /* certID needed one way or the other */
        if(certID == NULL) {
                crtn = tpOcspGetCertId(subject, issuer, certID);
@@ -222,7 +224,7 @@ static SecAsn1OCSPDRequest *tpGenOcspdReq(
                }
                deleteCertID = true;
        }
-       
+
        /*
         * Create the SecAsn1OCSPDRequest. All fields optional.
         */
@@ -234,10 +236,10 @@ static SecAsn1OCSPDRequest *tpGenOcspdReq(
                ocspdReq->cacheWriteDisable->Data[0] = 0xff;
                ocspdReq->cacheWriteDisable->Length = 1;
        }
-       /* 
-        * Note we're enforcing a not-so-obvious policy here: if nonce match is 
-        * required, disk cache reads by ocspd are disabled. In-core cache is 
-        * still enabled and hits in that cache do NOT require nonce matches. 
+       /*
+        * Note we're enforcing a not-so-obvious policy here: if nonce match is
+        * required, disk cache reads by ocspd are disabled. In-core cache is
+        * still enabled and hits in that cache do NOT require nonce matches.
         */
        if((optFlags & CSSM_TP_ACTION_OCSP_CACHE_READ_DISABLE) || requireRespNonce) {
                ocspdReq->cacheReadDisable = coder.mallocn<CSSM_DATA>();
@@ -261,7 +263,7 @@ static SecAsn1OCSPDRequest *tpGenOcspdReq(
        if(!(optFlags & CSSM_TP_ACTION_OCSP_DISABLE_NET)) {
                ocspdReq->urls = const_cast<CSSM_DATA **>(urls);
        }
-       
+
 errOut:
        delete ocspReq;
        if(deleteCertID) {
@@ -274,9 +276,9 @@ static bool revocationTimeAfterVerificationTime(CFAbsoluteTime revokedTime, CSSM
 {
     // Return true if the revocation time is after the specified verification time (i.e. "good")
     // If verifyTime not specified, use now for the verifyTime
-    
+
     CFAbsoluteTime verifyTime = 0;
-    
+
     if (verifyTimeStr)
     {
         CFDateRef cfVerifyTime = NULL;  // made with CFDateCreate
@@ -288,7 +290,7 @@ static bool revocationTimeAfterVerificationTime(CFAbsoluteTime revokedTime, CSSM
                 CFRelease(cfVerifyTime);
             }
     }
-    
+
     if (verifyTime == 0)
         verifyTime = CFAbsoluteTimeGetCurrent();
 
@@ -308,13 +310,13 @@ static CSSM_RETURN tpApplySingleResp(
 {
        SecAsn1OCSPCertStatusTag certStatus = singleResp.certStatus();
        CSSM_RETURN crtn = CSSM_OK;
-    if ((certStatus == CS_Revoked) && 
+    if ((certStatus == CS_Revoked) &&
         revocationTimeAfterVerificationTime(singleResp.revokedTime(), verifyTime))
     {
         tpOcspDebug("tpApplySingleResp: CS_Revoked for cert %u, but revoked after verification time", dex);
         certStatus = CS_Good;
     }
-    
+
        switch(certStatus) {
                case CS_Good:
                        tpOcspDebug("tpApplySingleResp: CS_Good for cert %u", dex);
@@ -346,7 +348,7 @@ static CSSM_RETURN tpApplySingleResp(
                        tpOcspDebug("tpApplySingleResp: CS_Unknown for cert %u", dex);
                        break;
                default:
-                       tpOcspDebug("tpApplySingleResp: BAD certStatus (%d) for cert %u", 
+                       tpOcspDebug("tpApplySingleResp: BAD certStatus (%d) for cert %u",
                                        (int)certStatus, dex);
                        if(cert.addStatusCode(CSSMERR_APPLETP_OCSP_STATUS_UNRECOGNIZED)) {
                                crtn = CSSMERR_APPLETP_OCSP_STATUS_UNRECOGNIZED;
@@ -356,20 +358,20 @@ static CSSM_RETURN tpApplySingleResp(
        return crtn;
 }
 
-/* 
+/*
  * An exceptional case: synchronously flush the OCSPD cache and send a new
- * resquest for just this one cert. 
+ * resquest for just this one cert.
  */
 static OCSPResponse *tpOcspFlushAndReFetch(
-       TPVerifyContext         &vfyCtx, 
-       SecNssCoder                     &coder, 
+       TPVerifyContext         &vfyCtx,
+       SecNssCoder                     &coder,
        TPCertInfo                      &subject,
-       TPCertInfo                      &issuer, 
+       TPCertInfo                      &issuer,
        OCSPClientCertID        &certID)
 {
        const CSSM_DATA *derCertID = certID.encode();
        CSSM_RETURN crtn;
-       
+
        crtn = ocspdCacheFlush(*derCertID);
        if(crtn) {
                #ifndef NDEBUG
@@ -377,7 +379,7 @@ static OCSPResponse *tpOcspFlushAndReFetch(
                #endif
                return NULL;
        }
-       
+
        /* Cook up an OCSPDRequests, one request, just for this */
        /* send it to ocsdp */
        /* munge reply into an OCSPRsponse and return it */
@@ -395,14 +397,14 @@ public:
                CSSM_DATA **u,
                unsigned dex);
        ~PendingRequest()       {}
-       
+
        TPCertInfo                      &subject;
        TPCertInfo                      &issuer;
        OCSPClientCertID        &certID;        // owned by caller
        CSSM_DATA                       **urls;         // owner-managed array of URLs obtained from subject's
-                                                                       // AuthorityInfoAccess.id-ad-ocsp. 
-       CSSM_DATA                       nonce;          // owner-managed copy of this requests' nonce, if it 
-                                                                       //   has one 
+                                                                       // AuthorityInfoAccess.id-ad-ocsp.
+       CSSM_DATA                       nonce;          // owner-managed copy of this requests' nonce, if it
+                                                                       //   has one
        unsigned                        dex;            // in inputCerts, for debug
        bool                            processed;
 };
@@ -413,7 +415,7 @@ PendingRequest::PendingRequest(
                OCSPClientCertID &cid,
                CSSM_DATA **u,
                unsigned dx)
-               : subject(subj), issuer(iss), certID(cid), 
+               : subject(subj), issuer(iss), certID(cid),
                  urls(u), dex(dx), processed(false)
 {
        nonce.Data = NULL;
@@ -424,11 +426,11 @@ PendingRequest::PendingRequest(
 
 CSSM_RETURN tpVerifyCertGroupWithOCSP(
        TPVerifyContext &vfyCtx,
-       TPCertGroup     &certGroup)             // to be verified 
+       TPCertGroup     &certGroup)             // to be verified
 {
        assert(vfyCtx.clHand != 0);
        assert(vfyCtx.policy == kRevokeOcsp);
-       
+
        CSSM_RETURN ourRtn = CSSM_OK;
        OcspRespStatus respStat;
        SecNssCoder coder;
@@ -446,7 +448,7 @@ CSSM_RETURN tpVerifyCertGroupWithOCSP(
                return CSSM_OK;
        }
        numCerts--;
-       
+
        /* gather options or their defaults */
        CSSM_APPLE_TP_OCSP_OPT_FLAGS optFlags = 0;
        const CSSM_APPLE_TP_OCSP_OPTIONS *ocspOpts = vfyCtx.ocspOpts;
@@ -457,7 +459,7 @@ CSSM_RETURN tpVerifyCertGroupWithOCSP(
        bool genNonce = false;                  // in outgoing request
        bool requireRespNonce = false;  // in incoming response
        PRErrorCode prtn;
-       
+
        if(ocspOpts != NULL) {
                optFlags = vfyCtx.ocspOpts->Flags;
                localResponder = ocspOpts->LocalResponder;
@@ -480,23 +482,23 @@ CSSM_RETURN tpVerifyCertGroupWithOCSP(
                tpErrorLog("tpVerifyCertGroupWithOCSP: requireRespNonce, !genNonce\n");
                return CSSMERR_TP_INVALID_REQUEST_INPUTS;
        }
-       
-       tpOcspDebug("tpVerifyCertGroupWithOCSP numCerts %u optFlags 0x%lx", 
+
+       tpOcspDebug("tpVerifyCertGroupWithOCSP numCerts %u optFlags 0x%lx",
                numCerts, (unsigned long)optFlags);
-               
+
        /*
         * create list of pendingRequests parallel to certGroup
         */
        PendingRequest **pending = coder.mallocn<PendingRequest *>(numCerts);
        memset(pending, 0, (numCerts * sizeof(PendingRequest *)));
-       
+
        for(unsigned dex=0; dex<numCerts; dex++) {
                OCSPClientCertID *certID = NULL;
                TPCertInfo *subject = certGroup.certAtIndex(dex);
-               
+
                if(subject->trustSettingsFound()) {
                        /* functionally equivalent to root - we're done */
-                       tpOcspDebug("...tpVerifyCertGroupWithOCSP: terminate per user trust at %u", 
+                       tpOcspDebug("...tpVerifyCertGroupWithOCSP: terminate per user trust at %u",
                                (unsigned)dex);
                        goto postOcspd;
                }
@@ -507,35 +509,35 @@ CSSM_RETURN tpVerifyCertGroupWithOCSP(
                                "aborting\n");
                        goto errOut;
                }
-               
-               /* 
+
+               /*
                 * We use the URLs in the subject cert's AuthorityInfoAccess extension
                 * for two things - mainly to get the URL(s) for actual OCSP transactions,
                 * but also for CSSM_TP_ACTION_OCSP_REQUIRE_IF_RESP_PRESENT processing.
                 * So, we do the per-cert processing to get them right now even if we
-                * wind up using a local responder or getting verification from cache. 
+                * wind up using a local responder or getting verification from cache.
                 */
                CSSM_DATA **urls = tpOcspUrlsFromCert(*subject, coder);
                pending[dex] = new PendingRequest(*subject, *issuer, *certID, urls, dex);
        }
        /* subsequent errors to errOut: */
-       
-       /* 
-        * Create empty SecAsn1OCSPDRequests big enough for all certs 
+
+       /*
+        * Create empty SecAsn1OCSPDRequests big enough for all certs
         */
        ocspdReqs.requests = coder.mallocn<SecAsn1OCSPDRequest *>(numCerts + 1);
        memset(ocspdReqs.requests, 0, (numCerts + 1) * sizeof(SecAsn1OCSPDRequest *));
        ocspdReqs.version.Data = &version;
        ocspdReqs.version.Length = 1;
-       
-       /* 
+
+       /*
         * For each cert, either obtain a cached OCSPResponse, or create
-        * a request to get one. 
+        * a request to get one.
         *
         * NOTE: in-core cache reads (via tpOcspCacheLookup() do NOT involve a
         * nonce check, no matter what the app says. If nonce checking is required by the
         * app, responses don't get added to cache if the nonce doesn't match, but once
-        * a response is validated and added to cache it's fair game for that task. 
+        * a response is validated and added to cache it's fair game for that task.
         */
        for(unsigned dex=0; dex<numCerts; dex++) {
                PendingRequest *pendReq = pending[dex];
@@ -544,7 +546,7 @@ CSSM_RETURN tpVerifyCertGroupWithOCSP(
                        singleResp = tpOcspCacheLookup(pendReq->certID, localResponder);
                }
                if(singleResp) {
-                       tpOcspDebug("...tpVerifyCertGroupWithOCSP: localCache hit (1) dex %u", 
+                       tpOcspDebug("...tpVerifyCertGroupWithOCSP: localCache hit (1) dex %u",
                                (unsigned)dex);
                        crtn = tpApplySingleResp(*singleResp, pendReq->subject, dex, optFlags,
                                vfyCtx.verifyTime, pendReq->processed);
@@ -558,19 +560,19 @@ CSSM_RETURN tpVerifyCertGroupWithOCSP(
                                continue;
                        }
                        if(crtn) {
-                               /* 
-                                * This indicates a bad cached response. Well that's kinda weird, let's 
+                               /*
+                                * This indicates a bad cached response. Well that's kinda weird, let's
                                 * just flush this out and try a normal transaction.
                                 */
                                tpOcspCacheFlush(pendReq->certID);
                        }
                }
-               
-               /* 
+
+               /*
                 * Prepare a request for ocspd
                 */
-               SecAsn1OCSPDRequest *ocspdReq = tpGenOcspdReq(vfyCtx, coder, 
-                       pendReq->subject, pendReq->issuer, pendReq->certID, 
+               SecAsn1OCSPDRequest *ocspdReq = tpGenOcspdReq(vfyCtx, coder,
+                       pendReq->subject, pendReq->issuer, pendReq->certID,
                        const_cast<const CSSM_DATA **>(pendReq->urls),
                        pendReq->nonce);
                if(ocspdReq == NULL) {
@@ -584,7 +586,7 @@ CSSM_RETURN tpVerifyCertGroupWithOCSP(
                /* no candidates for OCSP: almost done */
                goto postOcspd;
        }
-       
+
        /* ship requests off to ocspd, get ocspReplies back */
        if(coder.encodeItem(&ocspdReqs, kSecAsn1OCSPDRequestsTemplate, derOcspdRequests)) {
                tpErrorLog("tpVerifyCertGroupWithOCSP: error encoding ocspdReqs\n");
@@ -597,17 +599,17 @@ CSSM_RETURN tpVerifyCertGroupWithOCSP(
                #ifndef NDEBUG
                cssmPerror("ocspdFetch", crtn);
                #endif
-               /* But this is not necessarily fatal...update per-cert status and check 
+               /* But this is not necessarily fatal...update per-cert status and check
                 * caller requirements below */
                goto postOcspd;
        }
        memset(&ocspdReplies, 0, sizeof(ocspdReplies));
-       prtn = coder.decodeItem(derOcspdReplies, kSecAsn1OCSPDRepliesTemplate, 
+       prtn = coder.decodeItem(derOcspdReplies, kSecAsn1OCSPDRepliesTemplate,
                &ocspdReplies);
        /* we're done with this, mallocd in ocspdFetch() */
        vfyCtx.alloc.free(derOcspdReplies.Data);
        if(prtn) {
-               /* 
+               /*
                 * This can happen when an OCSP server provides bad data...we cannot
                 * determine which cert is associated with this bad response;
                 * just flag it with the first one and proceed to the loop that
@@ -625,12 +627,12 @@ CSSM_RETURN tpVerifyCertGroupWithOCSP(
                }
                goto errOut;
        }
-       
+
        /* process each reply */
        numReplies = ocspdArraySize((const void **)ocspdReplies.replies);
        for(unsigned dex=0; dex<numReplies; dex++) {
                SecAsn1OCSPDReply *reply = ocspdReplies.replies[dex];
-               
+
                /* Cook up our version of an OCSPResponse from the encoded data */
                OCSPResponse *ocspResp = NULL;
                try {
@@ -641,15 +643,15 @@ CSSM_RETURN tpVerifyCertGroupWithOCSP(
                        /* what the heck, keep going */
                        continue;
                }
-               
-               /* 
-                * Find matching subject cert if possible (it's technically optional for 
+
+               /*
+                * Find matching subject cert if possible (it's technically optional for
                 * verification of the response in some cases, e.g., local responder).
                 */
                PendingRequest *pendReq = NULL;                         // fully qualified
                PendingRequest *reqWithIdMatch = NULL;          // CertID match only, not nonce
                for(unsigned pdex=0; pdex<numCerts; pdex++) {
-               
+
                        /* first check ID match; that is required no matter what */
                        if((pending[pdex])->certID.compareToExist(reply->certID)) {
                                reqWithIdMatch = pending[pdex];
@@ -660,24 +662,24 @@ CSSM_RETURN tpVerifyCertGroupWithOCSP(
                        if(!genNonce) {
                                /* that's good enough */
                                pendReq = reqWithIdMatch;
-                               tpOcspDebug("OCSP processs reply: CertID match, no nonce");
+                               tpOcspDebug("OCSP process reply: CertID match, no nonce");
                                break;
                        }
                        if(tpCompareCssmData(&reqWithIdMatch->nonce, ocspResp->nonce())) {
-                               tpOcspDebug("OCSP processs reply: nonce MATCH");
+                               tpOcspDebug("OCSP process reply: nonce MATCH");
                                pendReq = reqWithIdMatch;
                                break;
                        }
-                       
+
                        /*
-                        * In this case we keep going; if we never find a match, then we can 
+                        * In this case we keep going; if we never find a match, then we can
                         * use reqWithIdMatch if !requireRespNonce.
                         */
-                       tpOcspDebug("OCSP processs reply: certID match, nonce MISMATCH");
+                       tpOcspDebug("OCSP process reply: certID match, nonce MISMATCH");
                }
                if(pendReq == NULL) {
                        if(requireRespNonce) {
-                               tpOcspDebug("OCSP processs reply: tossing out response due to "
+                               tpOcspDebug("OCSP process reply: tossing out response due to "
                                                "requireRespNonce");
                                delete ocspResp;
                                if(ourRtn == CSSM_OK) {
@@ -690,7 +692,7 @@ CSSM_RETURN tpVerifyCertGroupWithOCSP(
                                 * Nonce mismatch but caller thinks that's OK. Log it and proceed.
                                 */
                                assert(genNonce);
-                               tpOcspDebug("OCSP processs reply: using bad nonce due to !requireRespNonce");
+                               tpOcspDebug("OCSP process reply: using bad nonce due to !requireRespNonce");
                                pendReq = reqWithIdMatch;
                                pendReq->subject.addStatusCode(CSSMERR_APPLETP_OCSP_NONCE_MISMATCH);
                        }
@@ -699,7 +701,7 @@ CSSM_RETURN tpVerifyCertGroupWithOCSP(
                if(pendReq != NULL) {
                        issuer = &pendReq->issuer;
                }
-               
+
                /* verify response and either throw out or add to local cache */
                respStat = tpVerifyOcspResp(vfyCtx, coder, issuer, *ocspResp, crtn);
                switch(respStat) {
@@ -715,9 +717,9 @@ CSSM_RETURN tpVerifyCertGroupWithOCSP(
                                continue;
                        case ORS_Bad:
                                delete ocspResp;
-                               /* 
-                                * An exceptional case: synchronously flush the OCSPD cache and send a 
-                                * new request for just this one cert. 
+                               /*
+                                * An exceptional case: synchronously flush the OCSPD cache and send a
+                                * new request for just this one cert.
                                 * FIXME: does this really buy us anything? A DOS attacker who managed
                                 * to get this bogus response into our cache is likely to be able
                                 * to do it again and again.
@@ -746,21 +748,21 @@ CSSM_RETURN tpVerifyCertGroupWithOCSP(
                                        goto errOut;
                                }
                                /* Voila! Recovery. Proceed. */
-                               tpOcspDebug("tpVerifyCertGroupWithOCSP: refetch for cert %u SUCCEEDED", 
+                               tpOcspDebug("tpVerifyCertGroupWithOCSP: refetch for cert %u SUCCEEDED",
                                                dex);
                                break;
                } /* switch response status */
-               
+
                if(!cacheWriteDisable) {
                        tpOcspCacheAdd(reply->ocspResp, localResponder);
                }
-               
+
                /* attempt to apply to pendReq */
                if(pendReq != NULL) {
-                       OCSPSingleResponse *singleResp = 
+                       OCSPSingleResponse *singleResp =
                                ocspResp->singleResponseFor(pendReq->certID);
                        if(singleResp) {
-                               crtn = tpApplySingleResp(*singleResp, pendReq->subject, pendReq->dex, 
+                               crtn = tpApplySingleResp(*singleResp, pendReq->subject, pendReq->dex,
                                        optFlags, vfyCtx.verifyTime, pendReq->processed);
                                if(crtn && (ourRtn == CSSM_OK)) {
                                        ourRtn = crtn;
@@ -768,8 +770,8 @@ CSSM_RETURN tpVerifyCertGroupWithOCSP(
                                delete singleResp;
                        }
                }       /* a reply which matches a pending request */
-               
-               /* 
+
+               /*
                 * Done with this - note local OCSP response cache doesn't store this
                 * object; it stores an encoded copy.
                 */
@@ -778,9 +780,9 @@ CSSM_RETURN tpVerifyCertGroupWithOCSP(
 
 postOcspd:
 
-       /* 
-        * Now process each cert which hasn't had an OCSP response applied to it. 
-        * This can happen if we get back replies which are not strictly in 1-1 sync with 
+       /*
+        * Now process each cert which hasn't had an OCSP response applied to it.
+        * This can happen if we get back replies which are not strictly in 1-1 sync with
         * our requests but which nevertheless contain valid info for more than one
         * cert each.
         */
@@ -788,7 +790,7 @@ postOcspd:
                PendingRequest *pendReq = pending[dex];
                if(pendReq == NULL) {
                        /* i.e. terminated due to user trust */
-                       tpOcspDebug("...tpVerifyCertGroupWithOCSP: NULL pendReq dex %u", 
+                       tpOcspDebug("...tpVerifyCertGroupWithOCSP: NULL pendReq dex %u",
                                        (unsigned)dex);
                        break;
                }
@@ -801,9 +803,9 @@ postOcspd:
                        singleResp = tpOcspCacheLookup(pendReq->certID, localResponder);
                }
                if(singleResp) {
-                       tpOcspDebug("...tpVerifyCertGroupWithOCSP: localCache (2) hit dex %u", 
+                       tpOcspDebug("...tpVerifyCertGroupWithOCSP: localCache (2) hit dex %u",
                                        (unsigned)dex);
-                       crtn = tpApplySingleResp(*singleResp, pendReq->subject, dex, optFlags, 
+                       crtn = tpApplySingleResp(*singleResp, pendReq->subject, dex, optFlags,
                                        vfyCtx.verifyTime, pendReq->processed);
                        if(crtn) {
                                if(ourRtn == CSSM_OK) {
@@ -856,7 +858,7 @@ postOcspd:
                        }
                }
        }
-errOut:        
+errOut:
        for(unsigned dex=0; dex<numCerts; dex++) {
                PendingRequest *pendReq = pending[dex];
                if(pendReq == NULL) {
index f3a36d2a6b69a3076be064674afb74ea2859c5c8..581fa91ee54e065ea2ec637e934a4a9ebf081e6c 100644 (file)
@@ -290,3 +290,11 @@ CFDictionaryRef SecTaskCopyValuesForEntitlements(SecTaskRef task, CFArrayRef ent
 
        return values;
 }
+
+Boolean SecTaskEntitlementsValidated(SecTaskRef task) {
+    // TODO: Cache the result
+    uint32_t csflags = 0;
+    const uint32_t mask = CS_VALID | CS_KILL | CS_ENTITLEMENTS_VALIDATED;
+    int rc = csops_task(task, CS_OPS_STATUS, &csflags, sizeof(csflags));
+    return rc != -1 && ((csflags & mask) == mask);
+}
index 80bc0479b35a7f4e2b4c0eaf5e607feb7aaf6443..0190ee5b6f31d04b9e57d4dd1fc10816d455ab4c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013 Apple Inc. All Rights Reserved.
+ * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved.
  * 
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -41,6 +41,14 @@ extern "C" {
 */
 OSStatus SecTaskValidateForRequirement(SecTaskRef task, CFStringRef requirement);
 
+/*!
+    @function SecTaskEntitlementsValidated
+    @abstract Check whether entitlements can be trusted or not.  If this returns
+    false the tasks entitlements must not be used for anything security sensetive.
+    @param task A previously created SecTask object
+*/
+Boolean SecTaskEntitlementsValidated(SecTaskRef task);
+
 #if defined(__cplusplus)
 }
 #endif
index 7a5fb1762bb86916b10b2c2d507ef391a6fcf1e1..f7503184cdc9ee735a7d22e50e14668dfa47e929 100644 (file)
@@ -417,11 +417,16 @@ CFDataRef SecStaticCode::signature()
 void SecStaticCode::validateDirectory()
 {
        // echo previous outcome, if any
-       if (!validated())
+       // track revocation separately, as it may not have been checked
+       // during the initial validation
+       if (!validated() || ((mValidationFlags & kSecCSEnforceRevocationChecks) && !revocationChecked()))
                try {
                        // perform validation (or die trying)
                        CODESIGN_EVAL_STATIC_DIRECTORY(this);
                        mValidationExpired = verifySignature();
+                       if (mValidationFlags & kSecCSEnforceRevocationChecks)
+                               mRevocationChecked = true;
+
                        for (CodeDirectory::SpecialSlot slot = codeDirectory()->maxSpecialSlot(); slot >= 1; --slot)
                                if (mCache[slot])       // if we already loaded that resource...
                                        validateComponent(slot, errorForSlot(slot)); // ... then check it now
index 9974a3d5f70cf67877a4ff9cdf4f896a3af4044d..b9eac887de426f3b2e3256c5de7d06d9cb1fe229 100644 (file)
@@ -150,6 +150,7 @@ public:
        void resetValidity();                                           // clear validation caches (if something may have changed)
        
        bool validated() const  { return mValidated; }
+       bool revocationChecked() const { return mRevocationChecked; }
        bool valid() const
                { assert(validated()); return mValidated && (mValidationResult == errSecSuccess); }
        bool validatedExecutable() const        { return mExecutableValidated; }
@@ -211,6 +212,7 @@ private:
        
        // master validation state
        bool mValidated;                                        // core validation was attempted
+       bool mRevocationChecked;                        // the signature was checked for revocation
        OSStatus mValidationResult;                     // outcome of core validation
        bool mValidationExpired;                        // outcome had expired certificates
        
index e865acbd536e3665ebad0f4562fe002eb5eec02f..7a907d31ece1de6c8e1cb0015add5508d71b464a 100644 (file)
@@ -133,6 +133,7 @@ _SecTaskCreateWithAuditToken
 _SecTaskCreateFromSelf
 _SecTaskCopyValueForEntitlement
 _SecTaskCopyValuesForEntitlements
+_SecTaskEntitlementsValidated
 _SecTaskValidateForRequirement
 
 # Assessments
index b42baedaa920290b707ac35839c4fbaca91c5672..bd92c79deaec56c57aca594b3366389467141c74 100644 (file)
@@ -73,6 +73,7 @@
                18B965951472FE30005A4D2E /* cdbuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = C2D383150A237F47005C63A2 /* cdbuilder.h */; settings = {ATTRIBUTES = (Public, ); }; };
                37DDE33C1947A4F3005CE18B /* dirscanner.h in Headers */ = {isa = PBXBuildFile; fileRef = 37DDE33B1947A4F3005CE18B /* dirscanner.h */; };
                37DDE3421947A501005CE18B /* dirscanner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 37DDE3411947A501005CE18B /* dirscanner.cpp */; };
+               48674DE319EC9E610049EB7D /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 48674DE219EC9E610049EB7D /* Security.framework */; };
                7A4FAF1B19C215DF00D297CB /* CrashReporterSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A4FAF1A19C215DF00D297CB /* CrashReporterSupport.framework */; };
                7A9DA65C1948D1BA004635E6 /* opaquewhitelist.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A9DA65A1948D1BA004635E6 /* opaquewhitelist.cpp */; };
                7A9DA65D1948D1BA004635E6 /* opaquewhitelist.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A9DA65B1948D1BA004635E6 /* opaquewhitelist.h */; };
                184461A2146E9AD100B12992 /* release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = release.xcconfig; sourceTree = "<group>"; };
                37DDE33B1947A4F3005CE18B /* dirscanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dirscanner.h; sourceTree = "<group>"; };
                37DDE3411947A501005CE18B /* dirscanner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dirscanner.cpp; sourceTree = "<group>"; };
+               48674DE219EC9E610049EB7D /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = "../../../Volumes/Data/Users/murf/Projects/Security/build/Debug-iphoneos/Security.framework"; sourceTree = "<group>"; };
                4CA1FEBE052A3C8100F22E42 /* libsecurity_codesigning.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libsecurity_codesigning.a; sourceTree = BUILT_PRODUCTS_DIR; };
                7A4FAF1A19C215DF00D297CB /* CrashReporterSupport.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CrashReporterSupport.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.Internal.sdk/System/Library/PrivateFrameworks/CrashReporterSupport.framework; sourceTree = DEVELOPER_DIR; };
                7A9DA65A1948D1BA004635E6 /* opaquewhitelist.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = opaquewhitelist.cpp; sourceTree = "<group>"; };
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
+                               48674DE319EC9E610049EB7D /* Security.framework in Frameworks */,
                                7A4FAF1B19C215DF00D297CB /* CrashReporterSupport.framework in Frameworks */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                C2CC30EF0B8519CF005FA59D /* Frameworks */ = {
                        isa = PBXGroup;
                        children = (
+                               48674DE219EC9E610049EB7D /* Security.framework */,
                                C200424915D425B7004AE0A1 /* libsecurity_codesigning.a */,
                                C200424A15D425B7004AE0A1 /* libsecurity_utilities.a */,
                                C2CC30A00B8519CC005FA59D /* CoreFoundation.framework */,
                                ALWAYS_SEARCH_USER_PATHS = NO;
                                CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
                                CLANG_CXX_LIBRARY = "libc++";
-                               CLANG_ENABLE_MODULES = YES;
+                               CLANG_ENABLE_MODULES = NO;
                                CLANG_ENABLE_OBJC_ARC = YES;
                                CLANG_WARN_BOOL_CONVERSION = YES;
                                CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
                                FRAMEWORK_SEARCH_PATHS = (
                                        "$(inherited)",
                                        "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
+                                       "/Volumes/Data/Users/murf/Projects/Security/build/Debug-iphoneos",
                                );
                                GCC_C_LANGUAGE_STANDARD = gnu99;
                                GCC_DYNAMIC_NO_PIC = NO;
                                ALWAYS_SEARCH_USER_PATHS = NO;
                                CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
                                CLANG_CXX_LIBRARY = "libc++";
-                               CLANG_ENABLE_MODULES = YES;
+                               CLANG_ENABLE_MODULES = NO;
                                CLANG_ENABLE_OBJC_ARC = YES;
                                CLANG_WARN_BOOL_CONVERSION = YES;
                                CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
                                FRAMEWORK_SEARCH_PATHS = (
                                        "$(inherited)",
                                        "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
+                                       "/Volumes/Data/Users/murf/Projects/Security/build/Debug-iphoneos",
                                );
                                GCC_C_LANGUAGE_STANDARD = gnu99;
                                GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
index 76d6c1ce97971a5d31d6ee8e69c62b9a25256492..1b625a497f47e65f9bf40a57c337c69b395c5707 100644 (file)
@@ -2,14 +2,14 @@
  * Copyright (c) 2002-2007,2011-2014 Apple Inc. All Rights Reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
- * 
+ *
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
  * compliance with the License. Please obtain a copy of the License at
  * http://www.opensource.apple.com/apsl/ and read it before using this
  * file.
- * 
+ *
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
@@ -17,7 +17,7 @@
  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  * Please see the License for the specific language governing rights and
  * limitations under the License.
- * 
+ *
  * @APPLE_LICENSE_HEADER_END@
  */
 
@@ -36,6 +36,8 @@
 #include <vector>
 #include <CommonCrypto/CommonDigestSPI.h>
 #include <SecBase.h>
+#include <libDER/libDER.h>
+#include <libDER/DER_Decode.h>
 
 using namespace KeychainCore;
 
@@ -56,7 +58,8 @@ Certificate::Certificate(const CSSM_DATA &data, CSSM_CERT_TYPE type, CSSM_CERT_E
        mV1SubjectPublicKeyCStructValue(NULL),
        mV1SubjectNameCStructValue(NULL),
        mV1IssuerNameCStructValue(NULL),
-       mSha1Hash(NULL)
+       mSha1Hash(NULL),
+       mEncodingVerified(false)
 {
        if (data.Length == 0 || data.Data == NULL)
                MacOSError::throwMe(errSecParam);
@@ -72,7 +75,8 @@ Certificate::Certificate(const Keychain &keychain, const PrimaryKey &primaryKey,
        mV1SubjectPublicKeyCStructValue(NULL),
        mV1SubjectNameCStructValue(NULL),
        mV1IssuerNameCStructValue(NULL),
-       mSha1Hash(NULL)
+       mSha1Hash(NULL),
+       mEncodingVerified(false)
 {
 }
 
@@ -107,7 +111,8 @@ Certificate::Certificate(const Keychain &keychain, const PrimaryKey &primaryKey)
        mV1SubjectPublicKeyCStructValue(NULL),
        mV1SubjectNameCStructValue(NULL),
        mV1IssuerNameCStructValue(NULL),
-       mSha1Hash(NULL)
+       mSha1Hash(NULL),
+       mEncodingVerified(false)
 {
        // @@@ In this case we don't know the type...
 }
@@ -123,7 +128,8 @@ Certificate::Certificate(Certificate &certificate) :
        mV1SubjectPublicKeyCStructValue(NULL),
        mV1SubjectNameCStructValue(NULL),
        mV1IssuerNameCStructValue(NULL),
-       mSha1Hash(NULL)
+       mSha1Hash(NULL),
+       mEncodingVerified(false)
 {
 }
 
@@ -707,22 +713,124 @@ Certificate::populateAttributes()
        mPopulated = true;
 }
 
+bool
+Certificate::verifyEncoding(CSSM_DATA_PTR data)
+{
+       bool verified = false;
+       CSSM_SIZE verifiedLength = 0;
+       {
+               StLock<Mutex>_(mMutex);
+               if (!data || !data->Data || !data->Length) {
+                       mEncodingVerified = false;
+                       return false;
+               }
+               verified = mEncodingVerified;
+               if (verified) {
+                       return true;
+               }
+
+               // Note: the Certificate class supports X509v1 through X509v3 certs,
+               // with CSSM_CERT_ENCODING_BER or CSSM_CERT_ENCODING_DER encoding.
+               // Any other types/encodings would need additional verification code here.
+
+               if (mHaveTypeAndEncoding) {
+                       if (mType < CSSM_CERT_X_509v1 || mType > CSSM_CERT_X_509v3) {
+                               secdebug("Certificate", "verifyEncoding: certificate has custom type (%d)", (int)mType);
+                       }
+                       if (mEncoding < CSSM_CERT_ENCODING_BER || mEncoding > CSSM_CERT_ENCODING_DER) {
+                               secdebug("Certificate", "verifyEncoding: certificate has custom encoding (%d)", (int)mEncoding);
+                       }
+               }
+
+               // attempt to decode the top-level ASN.1 sequence
+               const DERItem der = { (DERByte *)data->Data, (DERSize)data->Length };
+               DERDecodedInfo derInfo;
+               // sanity check the first byte to avoid decoding a non-DER blob
+               if ((DERByte)0x30 != *(der.data)) {
+                       return false;
+               }
+               DERReturn drtn = DERDecodeItem(&der, &derInfo);
+               if (drtn == DR_Success) {
+                       CSSM_SIZE tagLength = (CSSM_SIZE)((uintptr_t)derInfo.content.data - (uintptr_t)der.data);
+                       CSSM_SIZE derLength = (CSSM_SIZE)derInfo.content.length + tagLength;
+                       if (derLength != data->Length) {
+                               secdebug("Certificate", "Certificate DER length is %d, but data length is %d",
+                                               (int)derLength, (int)data->Length);
+                               // will adjust data size if DER length is positive, but smaller than actual length
+                               if ((derLength > 0) && (derLength < data->Length)) {
+                                       verifiedLength = derLength;
+                                       secdebug("Certificate", "Will adjust certificate data length to %d",
+                                                       (int)derLength);
+                               }
+                               else {
+                                       secdebug("Certificate", "Certificate encoding invalid (DER length is %d)",
+                                                       (int)derLength);
+                                       return false;
+                               }
+                       }
+                       verified = mEncodingVerified = true;
+               }
+               else {
+                       // failure to decode provided data as DER sequence
+                       secdebug("Certificate", "Certificate not in DER encoding (error %d)",
+                                       (int)drtn);
+                       return false;
+               }
+       }
+
+       if (verifiedLength > 0) {
+               // setData acquires the mMutex lock, so we call it while not holding the lock
+               setData((UInt32)verifiedLength, data->Data);
+               secdebug("Certificate", "Adjusted certificate data length to %d",
+                               (int)verifiedLength);
+       }
+
+       return verified;
+}
+
 const CssmData &
 Certificate::data()
 {
-       StLock<Mutex>_(mMutex);
-       CssmDataContainer *data = mData.get();
-       if (!data && mKeychain)
+       CssmDataContainer *data = NULL;
+       bool hasKeychain = false;
+       bool verified = false;
+       {
+               StLock<Mutex>_(mMutex);
+               data = mData.get();
+               hasKeychain = (mKeychain != NULL);
+               verified = mEncodingVerified;
+       }
+
+       // If data has been set but not yet verified, verify it now.
+       if (!verified && data) {
+               // verifyEncoding might modify mData, so refresh the data container
+               verified = verifyEncoding(data);
+               {
+                       StLock<Mutex>_(mMutex);
+                       data = mData.get();
+               }
+       }
+
+       // If data isn't set at this point, try to read it from the db record
+       if (!data && hasKeychain)
        {
            // Make sure mUniqueId is set.
                dbUniqueRecord();
                CssmDataContainer _data;
-               mData = NULL;
-               /* new data allocated by CSPDL, implicitly freed by CssmDataContainer */
-               mUniqueId->get(NULL, &_data);
+               {
+                       StLock<Mutex>_(mMutex);
+                       mData = NULL;
+                       /* new data allocated by CSPDL, implicitly freed by CssmDataContainer */
+                       mUniqueId->get(NULL, &_data);
+               }
                /* this saves a copy to be freed at destruction and to be passed to caller */
                setData((UInt32)_data.length(), _data.data());
-               return *mData.get();
+               // verifyEncoding might modify mData, so refresh the data container
+               verified = verifyEncoding(&_data);
+               {
+                       StLock<Mutex>_(mMutex);
+                       data = mData.get();
+               }
        }
 
        // If the data hasn't been set we can't return it.
index 7c478976df87765ba1656328e3aeb5152679e8d1..867cd48037b91a3d054820ce64e3b01601dbe1b3 100644 (file)
@@ -124,6 +124,7 @@ protected:
 
        void addSubjectKeyIdentifier();
        void populateAttributes();
+       bool verifyEncoding(CSSM_DATA_PTR data);
 
 private:
        bool mHaveTypeAndEncoding;
@@ -140,6 +141,7 @@ private:
     CSSM_DATA_PTR mV1SubjectNameCStructValue;
     CSSM_DATA_PTR mV1IssuerNameCStructValue;
        CFDataRef mSha1Hash;
+       bool mEncodingVerified;
 };
 
 } // end namespace KeychainCore
index bce02bc4fb1cc737daa2eebdf6d5e530a4aa31f3..b1f09b05b2043a1bf1cd38be0337a40e9a38adbd 100644 (file)
@@ -1,15 +1,15 @@
 /*
  * Copyright (c) 2004,2011-2012,2014 Apple Inc. All Rights Reserved.
- * 
+ *
  * @APPLE_LICENSE_HEADER_START@
- * 
+ *
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
  * compliance with the License. Please obtain a copy of the License at
  * http://www.opensource.apple.com/apsl/ and read it before using this
  * file.
- * 
+ *
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
@@ -17,7 +17,7 @@
  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  * Please see the License for the specific language governing rights and
  * limitations under the License.
- * 
+ *
  * @APPLE_LICENSE_HEADER_END@
  */
 
@@ -77,7 +77,7 @@ OCSPClientCertID::OCSPClientCertID(
        allocCopyData(issuerPubKey, mIssuerPubKey);
        allocCopyData(subjectSerial, mSubjectSerial);
 }
-               
+
 OCSPClientCertID::~OCSPClientCertID()
 {
        freeData(mIssuerName);
@@ -85,7 +85,7 @@ OCSPClientCertID::~OCSPClientCertID()
        freeData(mSubjectSerial);
        freeData(mEncoded);
 }
-       
+
 /* preencoded DER NULL */
 static uint8 nullParam[2] = {5, 0};
 
@@ -97,11 +97,11 @@ const CSSM_DATA *OCSPClientCertID::encode()
        if(mEncoded.Data != NULL) {
                return &mEncoded;
        }
-       
+
        SecAsn1OCSPCertID       certID;
        uint8                           issuerNameHash[CC_SHA1_DIGEST_LENGTH];
        uint8                           pubKeyHash[CC_SHA1_DIGEST_LENGTH];
-       
+
        /* algId refers to the hash we'll perform in issuer name and key */
        certID.algId.algorithm = CSSMOID_SHA1;
        certID.algId.parameters.Data = nullParam;
@@ -109,32 +109,33 @@ const CSSM_DATA *OCSPClientCertID::encode()
 
        /* SHA1(issuerName) */
        ocspdSha1(mIssuerName.Data, (CC_LONG)mIssuerName.Length, issuerNameHash);
-       /* SHA1(issuer public key) */
+
+       /* SHA1(issuer public key bytes) */
        ocspdSha1(mIssuerPubKey.Data, (CC_LONG)mIssuerPubKey.Length, pubKeyHash);
-       
+
        /* build the CertID from those components */
        certID.issuerNameHash.Data = issuerNameHash;
        certID.issuerNameHash.Length = CC_SHA1_DIGEST_LENGTH;
        certID.issuerPubKeyHash.Data = pubKeyHash;
-       certID.issuerPubKeyHash.Length = CC_SHA1_DIGEST_LENGTH; 
+       certID.issuerPubKeyHash.Length = CC_SHA1_DIGEST_LENGTH;
        certID.serialNumber = mSubjectSerial;
-       
+
        /* encode */
        SecAsn1CoderRef coder;
        SecAsn1CoderCreate(&coder);
-       
+
        CSSM_DATA tmp = {0, NULL};
        SecAsn1EncodeItem(coder, &certID, kSecAsn1OCSPCertIDTemplate, &tmp);
        allocCopyData(tmp, mEncoded);
        SecAsn1CoderRelease(coder);
        return &mEncoded;
 }
-               
+
 /*
  * Does this object refer to the same cert as specified SecAsn1OCSPCertID?
- * This is the main purpose of this class's existence; this function works 
+ * This is the main purpose of this class's existence; this function works
  * even if specified SecAsn1OCSPCertID uses a different hash algorithm
- * than we do, since we keep copies of our basic components. 
+ * than we do, since we keep copies of our basic components.
  *
  * Returns true if compare successful.
  */
@@ -152,7 +153,7 @@ bool OCSPClientCertID::compareToExist(
        const CSSM_OID *alg = &exist.algId.algorithm;
        uint8 digest[OCSPD_MAX_DIGEST_LEN];
        CSSM_DATA digestData = {0, digest};
-       
+
        if(ocspdCompareCssmData(alg, &CSSMOID_SHA1)) {
                hf = ocspdSha1;
                digestData.Length = CC_SHA1_DIGEST_LENGTH;
@@ -169,7 +170,7 @@ bool OCSPClientCertID::compareToExist(
        else {
                return false;
        }
-       
+
        /* generate digests using exist's hash algorithm */
        hf(mIssuerName.Data, (CC_LONG)mIssuerName.Length, digest);
        if(!ocspdCompareCssmData(&digestData, &exist.issuerNameHash)) {
@@ -179,7 +180,7 @@ bool OCSPClientCertID::compareToExist(
        if(!ocspdCompareCssmData(&digestData, &exist.issuerPubKeyHash)) {
                return false;
        }
-       
+
        return true;
 }
 
@@ -189,7 +190,7 @@ bool OCSPClientCertID::compareToExist(
        SecAsn1CoderRef coder;
        SecAsn1OCSPCertID certID;
        bool brtn = false;
-       
+
        SecAsn1CoderCreate(&coder);
        memset(&certID, 0, sizeof(certID));
        if(SecAsn1DecodeData(coder, &exist, kSecAsn1OCSPCertIDTemplate, &certID)) {
@@ -216,7 +217,7 @@ OCSPSingleResponse::OCSPSingleResponse(
                mExtensions(NULL)
 {
        assert(resp != NULL);
-       
+
        SecAsn1CoderCreate(&mCoder);
        if((resp->certStatus.Data == NULL) || (resp->certStatus.Length == 0)) {
                ocspdErrorLog("OCSPSingleResponse: bad certStatus\n");
@@ -227,7 +228,7 @@ OCSPSingleResponse::OCSPSingleResponse(
                /* decode further to get SecAsn1OCSPRevokedInfo */
                SecAsn1OCSPCertStatus certStatus;
                memset(&certStatus, 0, sizeof(certStatus));
-               if(SecAsn1DecodeData(mCoder, &resp->certStatus, 
+               if(SecAsn1DecodeData(mCoder, &resp->certStatus,
                                kSecAsn1OCSPCertStatusRevokedTemplate, &certStatus)) {
                        ocspdErrorLog("OCSPSingleResponse: err decoding certStatus\n");
                        CssmError::throwMe(CSSMERR_APPLETP_OCSP_BAD_RESPONSE);
@@ -249,7 +250,7 @@ OCSPSingleResponse::OCSPSingleResponse(
                mNextUpdate = genTimeToCFAbsTime(resp->nextUpdate);
        }
        mExtensions = new OCSPExtensions(resp->singleExtensions);
-       ocspdDebug("OCSPSingleResponse: status %d reason %d", (int)mCertStatus, 
+       ocspdDebug("OCSPSingleResponse: status %d reason %d", (int)mCertStatus,
                (int)mCrlReason);
 }
 
@@ -293,7 +294,7 @@ CFAbsoluteTime OCSPSingleResponse::archiveCutoff()
 OCSPResponse::OCSPResponse(
        const CSSM_DATA &resp,
        CFTimeInterval defaultTTL)              // default time-to-live in seconds
-               : mLatestNextUpdate(NULL_TIME), 
+               : mLatestNextUpdate(NULL_TIME),
                  mExpireTime(NULL_TIME),
                  mExtensions(NULL)
 {
@@ -305,12 +306,12 @@ OCSPResponse::OCSPResponse(
        mResponderIdTag = (SecAsn1OCSPResponderIDTag)0;         // invalid
        mEncResponderName.Data = NULL;
        mEncResponderName.Length = 0;
-       
+
        if(SecAsn1DecodeData(mCoder, &resp, kSecAsn1OCSPResponseTemplate, &mTopResp)) {
                ocspdErrorLog("OCSPResponse: decode failure at top level\n");
                CssmError::throwMe(CSSMERR_APPLETP_OCSP_BAD_RESPONSE);
        }
-       
+
        /* remainder is valid only on RS_Success */
        if((mTopResp.responseStatus.Data == NULL) ||
           (mTopResp.responseStatus.Length == 0)) {
@@ -318,7 +319,7 @@ OCSPResponse::OCSPResponse(
                CssmError::throwMe(CSSMERR_APPLETP_OCSP_BAD_RESPONSE);
        }
        if(mTopResp.responseStatus.Data[0] != RS_Success) {
-               /* not a failure of our constructor; this object is now useful, but 
+               /* not a failure of our constructor; this object is now useful, but
                 * only for this one byte of status info */
                return;
        }
@@ -332,16 +333,16 @@ OCSPResponse::OCSPResponse(
                ocspdErrorLog("OCSPResponse: unknown responseType\n");
                CssmError::throwMe(CSSMERR_APPLETP_OCSP_BAD_RESPONSE);
        }
-       
+
        /* decode the SecAsn1OCSPBasicResponse */
        if(SecAsn1DecodeData(mCoder, &mTopResp.responseBytes->response,
                        kSecAsn1OCSPBasicResponseTemplate, &mBasicResponse)) {
                ocspdErrorLog("OCSPResponse: decode failure at SecAsn1OCSPBasicResponse\n");
                CssmError::throwMe(CSSMERR_APPLETP_OCSP_BAD_RESPONSE);
        }
-       
+
        /* signature and cert evaluation done externally */
-       
+
        /* decode the SecAsn1OCSPResponseData */
        if(SecAsn1DecodeData(mCoder, &mBasicResponse.tbsResponseData,
                        kSecAsn1OCSPResponseDataTemplate, &mResponseData)) {
@@ -352,17 +353,17 @@ OCSPResponse::OCSPResponse(
                ocspdErrorLog("OCSPResponse: bad responderID\n");
                CssmError::throwMe(CSSMERR_APPLETP_OCSP_BAD_RESPONSE);
        }
-               
+
        /* choice processing for ResponderID */
        mResponderIdTag = (SecAsn1OCSPResponderIDTag)
                (mResponseData.responderID.Data[0] & SEC_ASN1_TAGNUM_MASK);
        const SecAsn1Template *templ;
        switch(mResponderIdTag) {
-               case RIT_Name: 
-                       templ = kSecAsn1OCSPResponderIDAsNameTemplate; 
+               case RIT_Name:
+                       templ = kSecAsn1OCSPResponderIDAsNameTemplate;
                        break;
-               case RIT_Key: 
-                       templ = kSecAsn1OCSPResponderIDAsKeyTemplate; 
+               case RIT_Key:
+                       templ = kSecAsn1OCSPResponderIDAsKeyTemplate;
                        break;
                default:
                        ocspdErrorLog("OCSPResponse: bad responderID tag\n");
@@ -372,14 +373,14 @@ OCSPResponse::OCSPResponse(
                ocspdErrorLog("OCSPResponse: decode failure at responderID\n");
                CssmError::throwMe(CSSMERR_APPLETP_OCSP_BAD_RESPONSE);
        }
-       
+
        /* check temporal validity */
        if(!calculateValidity(defaultTTL)) {
                /* Whoops, abort */
                CssmError::throwMe(CSSMERR_APPLETP_OCSP_BAD_RESPONSE);
        }
-       
-       /* 
+
+       /*
         * Individual responses looked into when we're asked for a specific one
         * via singleResponse()
         */
@@ -428,8 +429,8 @@ const CSSM_DATA *OCSPResponse::signerCert(uint32 dex)
        return mBasicResponse.certs[dex];
 }
 
-/* 
- * Obtain a OCSPSingleResponse for a given "smart" CertID. 
+/*
+ * Obtain a OCSPSingleResponse for a given "smart" CertID.
  */
 OCSPSingleResponse *OCSPResponse::singleResponseFor(OCSPClientCertID &matchCertID)
 {
@@ -453,7 +454,7 @@ OCSPSingleResponse *OCSPResponse::singleResponseFor(OCSPClientCertID &matchCertI
 }
 
 /*
- * If responderID is of form RIT_Name, return the encoded version of the 
+ * If responderID is of form RIT_Name, return the encoded version of the
  * NSS_Name (for comparison with issuer's subjectName). Evaluated lazily,
  * once, in mCoder space.
  */
@@ -474,8 +475,8 @@ const CSSM_DATA *OCSPResponse::encResponderName()
        return &mEncResponderName;
 }
 
-/* 
- * Obtain a OCSPSingleResponse for a given raw encoded CertID. 
+/*
+ * Obtain a OCSPSingleResponse for a given raw encoded CertID.
  */
 OCSPSingleResponse *OCSPResponse::singleResponseFor(const CSSM_DATA &matchCertID)
 {
@@ -506,29 +507,29 @@ OCSPSingleResponse *OCSPResponse::singleResponseFor(const CSSM_DATA &matchCertID
 
 }
 
-/* 
+/*
  * Calculate temporal validity; set mLatestNextUpdate and mExpireTime. Only
- * called from constructor. Returns true if valid, else returns false. 
+ * called from constructor. Returns true if valid, else returns false.
  */
 bool OCSPResponse::calculateValidity(CFTimeInterval defaultTTL)
 {
        mLatestNextUpdate = NULL_TIME;
        CFAbsoluteTime now = CFAbsoluteTimeGetCurrent();
-       
+
        unsigned numResponses = ocspdArraySize((const void **)mResponseData.responses);
        for(unsigned dex=0; dex<numResponses; dex++) {
                SecAsn1OCSPSingleResponse *resp = mResponseData.responses[dex];
-               
-               /* 
-                * First off, a thisUpdate later than 'now' invalidates the whole response. 
+
+               /*
+                * First off, a thisUpdate later than 'now' invalidates the whole response.
                 */
                CFAbsoluteTime thisUpdate = genTimeToCFAbsTime(&resp->thisUpdate);
                if(thisUpdate > now) {
                        ocspdErrorLog("OCSPResponse::calculateValidity: thisUpdate not passed\n");
                        return false;
                }
-               
-               /* 
+
+               /*
                 * Accumulate latest nextUpdate
                 */
                if(resp->nextUpdate != NULL) {
@@ -538,7 +539,7 @@ bool OCSPResponse::calculateValidity(CFTimeInterval defaultTTL)
                        }
                }
        }
-       
+
        CFAbsoluteTime defaultExpire = now + defaultTTL;
        if(mLatestNextUpdate == NULL_TIME) {
                /* absolute expire time = current time plus default TTL */
index 5c0de2f650ba5f5dc289f8c2b30fa554b4aaef1f..bb40695b2c953a9c82f0d290045ef48c233304e7 100644 (file)
@@ -1,15 +1,15 @@
 /*
  * Copyright (c) 2004,2011,2014 Apple Inc. All Rights Reserved.
- * 
+ *
  * @APPLE_LICENSE_HEADER_START@
- * 
+ *
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
  * compliance with the License. Please obtain a copy of the License at
  * http://www.opensource.apple.com/apsl/ and read it before using this
  * file.
- * 
+ *
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  * Please see the License for the specific language governing rights and
  * limitations under the License.
- * 
+ *
  * @APPLE_LICENSE_HEADER_END@
  */
 
 /*
  * ocspResponse.h - OCSP Response class
  */
+
 #ifndef        _OCSP_RESPONSE_H_
 #define _OCSP_RESPONSE_H_
 
 #define CrlReason_NONE         ((CE_CrlReason)-1)
 
 /*
- * CertIDs can be represented differently by two peers even though they refer to 
- * the same cert. Client can use SHA1 hash and server can use MD5, for example. 
+ * CertIDs can be represented differently by two peers even though they refer to
+ * the same cert. Client can use SHA1 hash and server can use MD5, for example.
  * So all of our code which creates a CertID based on known, existing subject and
- * issuer certs uses one of these "smart" certIDs which can encode itself and also 
+ * issuer certs uses one of these "smart" certIDs which can encode itself and also
  * compare against any form of existing SecAsn1OCSPCertID.
  */
 class OCSPClientCertID
@@ -56,31 +56,31 @@ public:
                const CSSM_DATA                 &issuerName,
                const CSSM_DATA                 &issuerPubKey,
                const CSSM_DATA                 &subjectSerial);
-               
+
        ~OCSPClientCertID();
-       
+
        /*
         * DER encode.
         */
        const CSSM_DATA *encode();
-               
+
        /*
         * Does this object refer to the same cert as specified SecAsn1OCSPCertID?
-        * This is the main purpose of this class's existence; this function works 
+        * This is the main purpose of this class's existence; this function works
         * even if specified SecAsn1OCSPCertID uses a different hash algorithm
-        * than we do, since we keep copies of our basic components. 
+        * than we do, since we keep copies of our basic components.
         *
         * Returns true if compare successful.
         */
        bool compareToExist(
                const SecAsn1OCSPCertID &exist);
-               
-       /* 
+
+       /*
         * Convenience function, like compareToExist, with a raw encoded CertID.
         */
-       bool compareToExist( 
+       bool compareToExist(
                const CSSM_DATA &exist);
-               
+
 private:
        CSSM_DATA mIssuerName;
        CSSM_DATA mIssuerPubKey;
@@ -89,11 +89,11 @@ private:
 };
 
 /*
- * Object representing one SecAsn1OCSPSingleResponse, i.e., the portion of 
+ * Object representing one SecAsn1OCSPSingleResponse, i.e., the portion of
  * an OCSP response associated with a single CertID. These are created and
  * vended solely by an OCSPResponse object. The client which gets them from
  * an OCSPResponse (via singleResponse()) must delete the object when finished
- * with it. 
+ * with it.
  */
 class OCSPSingleResponse
 {
@@ -103,7 +103,7 @@ public:
        ~OCSPSingleResponse();
        friend class OCSPResponse;
 protected:
-       
+
        OCSPSingleResponse(
                SecAsn1OCSPSingleResponse       *resp);
 public:
@@ -112,17 +112,17 @@ public:
                CFAbsoluteTime                          nextUpdate()    { return mNextUpdate; }
                CFAbsoluteTime                          revokedTime()   { return mRevokedTime; }
                CE_CrlReason                            crlReason()             { return mCrlReason; }
-               
+
                /* Extension accessors - all are optional */
-               
+
                /* CRL Reference */
                const CSSM_DATA                         *crlUrl();
                const CSSM_DATA                         *crlNum();
                CFAbsoluteTime                          crlTime();                      /* may be NULL_TIME */
-               
+
                /* archive cutoff */
                CFAbsoluteTime                          archiveCutoff();
-               
+
                /* service locator not implemented yet */
 private:
                SecAsn1CoderRef                         mCoder;
@@ -130,42 +130,42 @@ private:
                CFAbsoluteTime                          mThisUpdate;
                CFAbsoluteTime                          mNextUpdate;            /* may be NULL_TIME */
                CFAbsoluteTime                          mRevokedTime;           /* != NULL_TIME for CS_Revoked */
-               CE_CrlReason                            mCrlReason;             
+               CE_CrlReason                            mCrlReason;
                OCSPExtensions                          *mExtensions;
 };
 
 /*
- * OCSPResponse maintains its own temporal validity status based on the values of 
+ * OCSPResponse maintains its own temporal validity status based on the values of
  * all of the enclosed SingleResponses' thisUpdate and (optional) nextUpdate
  * fields, in addition to a default time-to-live (TTL) value passed to
  * OCSPResponse's constructor.
  *
- * First, all of the thisUpdate fields are checked during OCSPResponse's constructor. 
+ * First, all of the thisUpdate fields are checked during OCSPResponse's constructor.
  * if any of these are later than the current time, the entire response is considered
- * invalid and the constructor throws a CssmError(CSSMERR_APPLETP_OCSP_BAD_RESPONSE). 
- * Subsequent to construction, all thisUpdate fields are ignored. 
+ * invalid and the constructor throws a CssmError(CSSMERR_APPLETP_OCSP_BAD_RESPONSE).
+ * Subsequent to construction, all thisUpdate fields are ignored.
  *
- * The NextUpdate times are handled as follows. 
+ * The NextUpdate times are handled as follows.
  *
- * 1. An OCSPResponse's latestNextUpdate is defined as the latest of all of the 
- *    nextUpdate fields in its SingleResponses. This is evaluated during construction. 
+ * 1. An OCSPResponse's latestNextUpdate is defined as the latest of all of the
+ *    nextUpdate fields in its SingleResponses. This is evaluated during construction.
  *
- * 2. An OCSPResponse's latestNextUpdate is NULL_TIME if none of its SingleResponses 
- *    contain any nextUpdate (this field is in fact optional). 
+ * 2. An OCSPResponse's latestNextUpdate is NULL_TIME if none of its SingleResponses
+ *    contain any nextUpdate (this field is in fact optional).
  *
- * 3. The caller of OCSPResponse's constructor passes in a default time-to-live 
- *    (TTL) in seconds; call this defaultTTL. Call the time at which the 
+ * 3. The caller of OCSPResponse's constructor passes in a default time-to-live
+ *    (TTL) in seconds; call this defaultTTL. Call the time at which the
  *    constructor is called, PLUS defaultTTL, "defaultExpire".
- * 
+ *
  * -- If the OCSPResponse's latestNextUpdate is NULL_TIME then expireTime() returns
  *    defaultExpire.
  *
- * -- Otherwise, expireTime() returns the lesser of (latestNextUpdate, 
+ * -- Otherwise, expireTime() returns the lesser of (latestNextUpdate,
  *    defaultExpire).
  *
  * Note that this mechanism is used by both the TP's in-core cache and ocspd's
  * on-disk cache; the two have different default TTLs values but the mechanism
- * for calcuating expireTime() is identical. 
+ * for calcuating expireTime() is identical.
  */
 class OCSPResponse
 {
@@ -175,11 +175,11 @@ public:
        OCSPResponse(
                const CSSM_DATA &resp,
                CFTimeInterval defaultTTL);             // default time-to-live in seconds
-               
+
        ~OCSPResponse();
-       
-       /* 
-        * Info obtained during decode (which is don\ 1e immediately during constructor) 
+
+       /*
+        * Info obtained during decode (which is don\ 1e immediately during constructor)
         */
        SecAsn1OCSPResponseStatus       responseStatus();
        const CSSM_DATA                         *nonce();                       /* NULL means not present */
@@ -187,13 +187,13 @@ public:
        CSSM_RETURN                                     sigStatus();
        uint32                                          numSignerCerts();
        const CSSM_DATA                         *signerCert(uint32 dex);
-       
-       /* 
-        * Obtain a OCSPSingleResponse for a given CertID. 
+
+       /*
+        * Obtain a OCSPSingleResponse for a given CertID.
         */
        OCSPSingleResponse                      *singleResponseFor(OCSPClientCertID &certID);
        OCSPSingleResponse                      *singleResponseFor(const CSSM_DATA &matchCertID);
-       
+
        CFAbsoluteTime                          expireTime()            { return mExpireTime; }
 
        /*
@@ -205,18 +205,18 @@ public:
        SecAsn1OCSPResponderIDTag               responderIDTag()        { return mResponderIdTag; }
 
        const CSSM_DATA                                 *encResponderName();
-       
+
 private:
        bool                                            calculateValidity(CFTimeInterval defaultTTL);
-       
+
        SecAsn1CoderRef                         mCoder;
        CFAbsoluteTime                          mLatestNextUpdate;
        CFAbsoluteTime                          mExpireTime;
-       CSSM_DATA                                       mEncResponderName;      // encoded ResponderId.byName, 
+       CSSM_DATA                                       mEncResponderName;      // encoded ResponderId.byName,
                                                                                                        // if responder is in that format,
                                                                                                        // lazily evaluated
-       /* 
-        * Fields we decode - all in mCoder's memory space 
+       /*
+        * Fields we decode - all in mCoder's memory space
         */
        SecAsn1OCSPResponse                     mTopResp;
        SecAsn1OCSPBasicResponse        mBasicResponse;
@@ -224,6 +224,6 @@ private:
        SecAsn1OCSPResponderID          mResponderId;           // we have to decode
        SecAsn1OCSPResponderIDTag       mResponderIdTag;        // IDs previous field
        OCSPExtensions                          *mExtensions;
-};     
+};
 #endif /* _OCSP_RESPONSE_H_ */
 
index cee4b180d375c9ea9497d8ba5fb272e600307a4e..efbdb8a6b11df3e85bc4e91d6d6053016d4f2d83 100644 (file)
@@ -2,14 +2,14 @@
  * Copyright (c) 2000,2002,2011-2012,2014 Apple Inc. All Rights Reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
- * 
+ *
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
  * compliance with the License. Please obtain a copy of the License at
  * http://www.opensource.apple.com/apsl/ and read it before using this
  * file.
- * 
+ *
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  * Please see the License for the specific language governing rights and
  * limitations under the License.
- * 
+ *
  * @APPLE_LICENSE_HEADER_END@
  */
 
-/* 
+/*
  * ocspUtils.cpp - common utilities for OCSPD
  */
 
 #include "ocspdUtils.h"
+#include "ocspdDebug.h"
+#include <Security/cssmerr.h>
+#include <Security/keyTemplates.h>
 #include <CoreFoundation/CoreFoundation.h>
 
 /*
@@ -34,8 +37,8 @@
 CSSM_BOOL ocspdCompareCssmData(
        const CSSM_DATA *data1,
        const CSSM_DATA *data2)
-{      
-       if((data1 == NULL) || (data1->Data == NULL) || 
+{
+       if((data1 == NULL) || (data1->Data == NULL) ||
           (data2 == NULL) || (data2->Data == NULL) ||
           (data1->Length != data2->Length)) {
                return CSSM_FALSE;
@@ -53,8 +56,8 @@ CSSM_BOOL ocspdCompareCssmData(
 
 /*
  * Convert a generalized time string, with a 4-digit year and no trailing
- * fractional seconds or time zone info, to a CFAbsoluteTime. Returns 
- * NULL_TIME (0.0) on error. 
+ * fractional seconds or time zone info, to a CFAbsoluteTime. Returns
+ * NULL_TIME (0.0) on error.
  */
 static CFAbsoluteTime parseGenTime(
        const uint8 *str,
@@ -63,7 +66,7 @@ static CFAbsoluteTime parseGenTime(
        if((str == NULL) || (len == 0)) {
        return NULL_TIME;
        }
-       
+
        /* tolerate NULL terminated or not */
        if(str[len - 1] == '\0') {
                len--;
@@ -75,7 +78,7 @@ static CFAbsoluteTime parseGenTime(
        CFGregorianDate greg;
        memset(&greg, 0, sizeof(greg));
        const uint8 *cp = str;
-       
+
        /* YEAR */
        szTemp[0] = *cp++;
        szTemp[1] = *cp++;
@@ -84,7 +87,7 @@ static CFAbsoluteTime parseGenTime(
        szTemp[4] = '\0';
        len -= 4;
        greg.year = atoi(szTemp);
-       
+
        /* MONTH - CFGregorianDate ranges 1..12, just like the string */
        if(len < 2) {
                return NULL_TIME;
@@ -104,7 +107,7 @@ static CFAbsoluteTime parseGenTime(
        szTemp[2] = '\0';
        greg.day = atoi( szTemp );
        len -= 2;
-       
+
        if(len >= 2) {
                /* HOUR 0..23 */
                szTemp[0] = *cp++;
@@ -134,7 +137,7 @@ static CFAbsoluteTime parseGenTime(
 
 /*
  * Parse a GeneralizedTime string into a CFAbsoluteTime. Returns NULL on parse error.
- * Fractional parts of a second are discarded. 
+ * Fractional parts of a second are discarded.
  */
 CFAbsoluteTime genTimeToCFAbsTime(
        const CSSM_DATA *strData)
@@ -142,20 +145,20 @@ CFAbsoluteTime genTimeToCFAbsTime(
        if((strData == NULL) || (strData->Data == NULL) || (strData->Length == 0)) {
        return NULL_TIME;
        }
-       
+
        uint8 *timeStr = strData->Data;
        size_t timeStrLen = strData->Length;
-       
+
        /* tolerate NULL terminated or not */
        if(timeStr[timeStrLen - 1] == '\0') {
                timeStrLen--;
        }
-       
+
        /* start with a fresh editable copy */
        uint8 *str = (uint8 *)malloc(timeStrLen);
        uint32 strLen = 0;
-       
-       /* 
+
+       /*
         * If there is a decimal point, strip it and all trailing digits off
         */
        const uint8 *inCp = timeStr;
@@ -166,7 +169,7 @@ CFAbsoluteTime genTimeToCFAbsTime(
        bool minusOffset = false;
        bool isGMT = false;
        size_t toGo = timeStrLen;
-       
+
        do {
                if(*inCp == '.') {
                        if(foundDecimal) {
@@ -176,7 +179,7 @@ CFAbsoluteTime genTimeToCFAbsTime(
                                }
                        }
                        foundDecimal++;
-                       
+
                        /* skip the decimal point... */
                        inCp++;
                        toGo--;
@@ -213,19 +216,19 @@ CFAbsoluteTime genTimeToCFAbsTime(
                        toGo--;
                }
        } while(toGo != 0);
-       
+
        if(str[strLen - 1] == 'Z') {
                isGMT = true;
                strLen--;
        }
-       
+
        CFAbsoluteTime absTime;
        absTime = parseGenTime(str, strLen);
        free(str);
        if(absTime == NULL_TIME) {
                return NULL_TIME;
        }
-       
+
        /* post processing needed? */
        if(isGMT) {
                /* Nope, string was in GMT */
@@ -253,7 +256,7 @@ CFAbsoluteTime genTimeToCFAbsTime(
        return absTime;
 }
 
-/* 
+/*
  * Convert CFAbsoluteTime to generalized time string, GMT format (4 digit year,
  * trailing 'Z'). Caller allocated the output which is GENERAL_TIME_STRLEN+1 bytes.
  */
@@ -266,10 +269,10 @@ void cfAbsTimeToGgenTime(
        CFGregorianDate greg = CFAbsoluteTimeGetGregorianDate(absTime, tz);
        int seconds = (int)greg.second;
        sprintf(genTime, "%04d%02d%02d%02d%02d%02dZ",
-                               (int)greg.year, greg.month, greg.day, greg.hour, 
+                               (int)greg.year, greg.month, greg.day, greg.hour,
                                greg.minute, seconds);
 }
+
 void ocspdSha1(
        const void              *data,
        CC_LONG                 len,
@@ -328,3 +331,87 @@ unsigned ocspdArraySize(
     }
     return count;
 }
+
+/* Fill out a CSSM_DATA with the subset of public key bytes from the given
+ * CSSM_KEY_PTR which should be hashed to produce the issuerKeyHash field
+ * of a CertID in an OCSP request.
+ *
+ * For RSA keys, this simply copies the input key pointer and length.
+ * For EC keys, we need to further deconstruct the SubjectPublicKeyInfo
+ * to obtain the key bytes (i.e. curve point) for hashing.
+ *
+ * Returns CSSM_OK on success, or non-zero error if the bytes could not
+ * be retrieved.
+ */
+CSSM_RETURN ocspdGetPublicKeyBytes(
+       SecAsn1CoderRef coder,          // optional
+       CSSM_KEY_PTR publicKey,         // input public key
+       CSSM_DATA &publicKeyBytes)      // filled in by this function
+{
+       CSSM_RETURN crtn = CSSM_OK;
+       SecAsn1CoderRef _coder = NULL;
+
+       if(publicKey == NULL) {
+               crtn = CSSMERR_CSP_INVALID_KEY_POINTER;
+               goto exit;
+       }
+
+       if(coder == NULL) {
+               crtn = SecAsn1CoderCreate(&_coder);
+               if(crtn) {
+                       goto exit;
+               }
+               coder = _coder;
+       }
+
+       publicKeyBytes.Length = publicKey->KeyData.Length;
+       publicKeyBytes.Data = publicKey->KeyData.Data;
+
+       if(publicKey->KeyHeader.AlgorithmId == CSSM_ALGID_ECDSA) {
+               /*
+                * For an EC key, publicKey->KeyData is a SubjectPublicKeyInfo
+                * ASN.1 sequence that includes the algorithm identifier.
+                * We only want to return the bit string portion of the key here.
+                */
+               SecAsn1PubKeyInfo pkinfo;
+               memset(&pkinfo, 0, sizeof(pkinfo));
+               if(SecAsn1Decode(coder,
+                       publicKey->KeyData.Data,
+                       publicKey->KeyData.Length,
+                       kSecAsn1SubjectPublicKeyInfoTemplate,
+                       &pkinfo) == 0) {
+                       if(pkinfo.subjectPublicKey.Length &&
+                          pkinfo.subjectPublicKey.Data) {
+                               publicKeyBytes.Length = pkinfo.subjectPublicKey.Length >> 3;
+                               publicKeyBytes.Data = pkinfo.subjectPublicKey.Data;
+                               /*
+                                * Important: if we allocated the SecAsn1Coder, the memory
+                                * being pointed to by pkinfo.subjectPublicKey.Data will be
+                                * deallocated when the coder is released below. We want to
+                                * point to the identical data inside the caller's public key,
+                                * now that the decoder has identified it for us.
+                                */
+                               if(publicKeyBytes.Length <= publicKey->KeyData.Length) {
+                                       publicKeyBytes.Data = (uint8*)((uintptr_t)publicKey->KeyData.Data +
+                                               (publicKey->KeyData.Length - publicKeyBytes.Length));
+                                       goto exit;
+                               }
+                               /* intentional fallthrough to error exit */
+                       }
+                       ocspdErrorLog("ocspdGetPublicKeyBytes: invalid SecAsn1PubKeyInfo\n");
+                       crtn = CSSMERR_CSP_INVALID_KEY_POINTER;
+               }
+               else {
+                       /* Unable to decode using kSecAsn1SubjectPublicKeyInfoTemplate.
+                        * This may or may not be an error; just return the unchanged key.
+                        */
+                       ocspdErrorLog("ocspdGetPublicKeyBytes: unable to decode SubjectPublicKeyInfo\n");
+               }
+       }
+
+exit:
+       if(_coder) {
+               SecAsn1CoderRelease(_coder);
+       }
+       return crtn;
+}
index 57691acafd97afc2660d18c36cf4880fde3995fd..63d4f4d55cceb1e858238c911b47038a1f93b781 100644 (file)
@@ -2,14 +2,14 @@
  * Copyright (c) 2000,2002,2011,2014 Apple Inc. All Rights Reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
- * 
+ *
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
  * compliance with the License. Please obtain a copy of the License at
  * http://www.opensource.apple.com/apsl/ and read it before using this
  * file.
- * 
+ *
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  * Please see the License for the specific language governing rights and
  * limitations under the License.
- * 
+ *
  * @APPLE_LICENSE_HEADER_END@
  */
 
-/* 
+/*
  * ocspUtils.h - common utilities for OCSPD
  */
 #ifndef        _OCSPD_UTILS_H_
@@ -33,6 +33,7 @@ extern "C" {
 
 #include <CommonCrypto/CommonDigest.h>
 #include <Security/cssmtype.h>
+#include <Security/SecAsn1Coder.h>
 #include <CoreFoundation/CoreFoundation.h>
 
 /*
@@ -43,15 +44,15 @@ CSSM_BOOL ocspdCompareCssmData(
        const CSSM_DATA *data2);
 
 /*
- * Parse a GeneralizedTime string into a CFAbsoluteTime. Returns NULL_TIME on 
- * parse error. Fractional parts of a second are discarded. 
+ * Parse a GeneralizedTime string into a CFAbsoluteTime. Returns NULL_TIME on
+ * parse error. Fractional parts of a second are discarded.
  */
-#define NULL_TIME      0.0     
+#define NULL_TIME      0.0
 
 CFAbsoluteTime genTimeToCFAbsTime(
        const CSSM_DATA *strData);
 
-/* 
+/*
  * Convert CFAbsoluteTime to generalized time string, GMT format (4 digit year,
  * trailing 'Z'). Caller allocated the output which is GENERAL_TIME_STRLEN bytes plus
  * a NULL.
@@ -87,11 +88,22 @@ void ocspdSHA256(
 unsigned ocspdArraySize(
        const void **array);
 
+/*
+ * Fill out a CSSM_DATA with the subset of public key bytes from the given
+ * CSSM_KEY_PTR which should be hashed to produce the issuerKeyHash field
+ * of a CertID in an OCSP request.
+ */
+CSSM_RETURN ocspdGetPublicKeyBytes(
+       SecAsn1CoderRef coder,
+       CSSM_KEY_PTR publicKey,
+       CSSM_DATA &publicKeyBytes); // filled out by this function
+
+
 #define CFRELEASE(cf)  \
        if(cf != NULL) {        \
                CFRelease(cf);  \
        }
-       
+
 #ifdef __cplusplus
 }
 #endif
index 2f02cd7f987f3bc41ee8d9fc625d1fafaabd1fd1..a9dbaa671d0cf7805816500f9795f27e73f0aea3 100644 (file)
@@ -638,7 +638,7 @@ static const int64_t kSyncTimerLeeway = (NSEC_PER_MSEC * 250);      // 250ms lee
 
             _inCallout = YES;
             if (!_oldInCallout)
-                secnotice("deaf", ">>>>>>>>>>> WTFBBQ _oldInCallout is NO and we're heading in to the callout!");
+                secnotice("deaf", ">>>>>>>>>>> _oldInCallout is NO and we're heading in to the callout!");
 
             _shadowPendingKeys = [NSMutableSet set];
             _shadowSyncWithPeersPending = NO;
index 4a601f4712fbbb83fdcc6b38a2d7a0489a98d044..52d4a632dcf4f7ca233052817b309c5a897284ba 100644 (file)
@@ -77,6 +77,7 @@ bool SOSAccountUpdateGestalt(SOSAccountRef account, CFDictionaryRef new_gestalt)
         if (SOSFullPeerInfoUpdateGestalt(full_peer, new_gestalt, NULL)) {
             SOSAccountModifyCircle(account, SOSCircleGetName(circle),
                                    NULL, ^(SOSCircleRef circle_to_change) {
+                                       secnotice("circleChange", "Calling SOSCircleUpdatePeerInfo for gestalt change");
                                        return SOSCircleUpdatePeerInfo(circle_to_change, SOSFullPeerInfoGetPeerInfo(full_peer));
                                    });
         };
@@ -125,6 +126,7 @@ static void SOSAccountDestroy(CFTypeRef aObj) {
 }
 
 void SOSAccountSetToNew(SOSAccountRef a) {
+    secnotice("accountChange", "Setting Account to New");
     CFAllocatorRef allocator = CFGetAllocator(a);
     CFReleaseNull(a->circle_identities);
     CFReleaseNull(a->circles);
@@ -467,6 +469,7 @@ void SOSAccountAddSyncablePeerBlock(SOSAccountRef a, CFStringRef ds_name, SOSAcc
 bool sosAccountLeaveCircle(SOSAccountRef account, SOSCircleRef circle, CFErrorRef* error) {
     SOSFullPeerInfoRef fpi = SOSAccountGetMyFullPeerInCircle(account, circle, NULL);
     if(!fpi) return false;
+    if(!SOSFullPeerInfoValidate(fpi, NULL)) return false;
        CFErrorRef localError = NULL;
        SOSPeerInfoRef retire_peer = SOSFullPeerInfoPromoteToRetiredAndCopy(fpi, &localError);
     CFStringRef retire_id = SOSPeerInfoGetPeerID(retire_peer);
@@ -619,9 +622,11 @@ SOSCCStatus SOSAccountIsInCircles(SOSAccountRef account, CFErrorRef* error) {
 //
 
 static bool SOSAccountResetThisCircleToOffering(SOSAccountRef account, SOSCircleRef circle, SecKeyRef user_key, CFErrorRef *error) {
-    SOSFullPeerInfoRef myCirclePeer = SOSAccountGetMyFullPeerInCircle(account, circle, error);
+    SOSFullPeerInfoRef myCirclePeer = SOSAccountMakeMyFullPeerInCircleNamed(account, SOSCircleGetName(circle), error);
     if (!myCirclePeer)
         return false;
+    if(!SOSFullPeerInfoValidate(myCirclePeer, NULL)) return false;
+
     
     SOSAccountModifyCircle(account, SOSCircleGetName(circle), error, ^(SOSCircleRef circle) {
         bool result = false;
@@ -712,7 +717,7 @@ static bool SOSAccountJoinThisCircle(SOSAccountRef account, SecKeyRef user_key,
     __block bool result = false;
     __block SOSFullPeerInfoRef cloud_full_peer = NULL;
 
-    SOSFullPeerInfoRef myCirclePeer = SOSAccountGetMyFullPeerInCircle(account, circle, error);
+    SOSFullPeerInfoRef myCirclePeer = SOSAccountMakeMyFullPeerInCircleNamed(account, SOSCircleGetName(circle), error);
     
     require_action_quiet(myCirclePeer, fail,
                          SOSCreateErrorWithFormat(kSOSErrorPeerNotFound, NULL, error, NULL, CFSTR("Can't find/create peer for circle: %@"), circle));
index 2b4a32efd8169fe7e2378dc9dfa63f67f7d1716c..fe361d170a2d204ae1ddf9a2ad7aa54c0dc6ee26 100644 (file)
@@ -100,7 +100,7 @@ SOSPeerInfoRef SOSAccountGetMyPeerInCircle(SOSAccountRef account, SOSCircleRef c
 SOSPeerInfoRef SOSAccountGetMyPeerInCircleNamed(SOSAccountRef account, CFStringRef circle, CFErrorRef* error);
 
 SOSFullPeerInfoRef SOSAccountGetMyFullPeerInCircle(SOSAccountRef account, SOSCircleRef circle, CFErrorRef* error);
-SOSFullPeerInfoRef SOSAccountGetMyFullPeerInCircleNamed(SOSAccountRef account, CFStringRef name, CFErrorRef *error);
+SOSFullPeerInfoRef SOSAccountMakeMyFullPeerInCircleNamed(SOSAccountRef account, CFStringRef name, CFErrorRef *error);
 
 //
 // MARK: Credential management
index 47cba02ac07fd1ef39f97de71a534041aaaaee1c..c40107959ae0453ed98eb9aa492106de16b9f4ef 100644 (file)
@@ -80,25 +80,31 @@ static bool SOSAccountInflateTransportsForCircle(SOSAccountRef account, CFString
     SOSTransportKeyParameterRef tKey = NULL;
     SOSTransportCircleRef tCircle = NULL;
     SOSTransportMessageRef tMessage = NULL;
+    
+#if 0 // IDS_FUTURE
+    // Solve determining transport type without fullpeer
     SOSFullPeerInfoRef fpi = SOSAccountGetMyFullPeerInCircleNamed(account, circleName, error);
     require_quiet(fpi, fail);
     SOSPeerInfoRef myPeer = SOSFullPeerInfoGetPeerInfo(fpi);
     require_quiet(myPeer, fail);
     CFStringRef type = SOSPeerInfoGetTransportType(myPeer);
     if(CFStringCompare(type, CFSTR("KVS"), 0) == kCFCompareEqualTo){
-        tKey = (SOSTransportKeyParameterRef)SOSTransportKeyParameterKVSCreate(account, error);
-        tCircle = (SOSTransportCircleRef)SOSTransportCircleKVSCreate(account, circleName, error);
-        tMessage = (SOSTransportMessageRef)SOSTransportMessageKVSCreate(account, circleName, error);
-        require_quiet(tKey, fail);
-        require_quiet(tCircle, fail);
-        require_quiet(tMessage, fail);
-        
-        CFRetainAssign(account->key_transport, (SOSTransportKeyParameterRef)tKey);
-        CFDictionarySetValue(account->circle_transports, circleName, tCircle);
-        CFDictionarySetValue(account->message_transports, circleName, tMessage);
+#endif
+    tKey = (SOSTransportKeyParameterRef)SOSTransportKeyParameterKVSCreate(account, error);
+    tCircle = (SOSTransportCircleRef)SOSTransportCircleKVSCreate(account, circleName, error);
+    tMessage = (SOSTransportMessageRef)SOSTransportMessageKVSCreate(account, circleName, error);
+    require_quiet(tKey, fail);
+    require_quiet(tCircle, fail);
+    require_quiet(tMessage, fail);
+    
+    CFRetainAssign(account->key_transport, (SOSTransportKeyParameterRef)tKey);
+    CFDictionarySetValue(account->circle_transports, circleName, tCircle);
+    CFDictionarySetValue(account->message_transports, circleName, tMessage);
+#if 0 // IDS_FUTURE
     }
-    
+#endif
     success = true;
+
 fail:
     CFReleaseNull(tKey);
     CFReleaseNull(tCircle);
@@ -125,9 +131,9 @@ SOSCircleRef SOSAccountEnsureCircle(SOSAccountRef a, CFStringRef name, CFErrorRe
 
         SOSUpdateKeyInterest();
     }
-    
+
     require_quiet(SOSAccountInflateTransportsForCircle(a, name, error), fail);
-    
+   
 fail:
     CFReleaseNull(localError);
     return circle;
index 45d2cf4357e15220cb15ee84ef0376a4ce0f441b..aea175553ea9905f337197e6a1f260c77c549410 100644 (file)
@@ -103,7 +103,7 @@ bool SOSAccountIsAccountIdentity(SOSAccountRef account, SOSPeerInfoRef peer_info
 
 
 
-SOSFullPeerInfoRef SOSAccountGetMyFullPeerInCircleNamed(SOSAccountRef account, CFStringRef name, CFErrorRef *error) {
+SOSFullPeerInfoRef SOSAccountMakeMyFullPeerInCircleNamed(SOSAccountRef account, CFStringRef name, CFErrorRef *error) {
     if (CFDictionaryGetValue(account->circles, name) == NULL) {
         SOSCreateErrorWithFormat(kSOSErrorNoCircle, NULL, error, NULL, CFSTR("No circle named '%@'"), name);
         return NULL;
@@ -139,7 +139,7 @@ SOSFullPeerInfoRef SOSAccountGetMyFullPeerInCircleNamed(SOSAccountRef account, C
 
 
 SOSFullPeerInfoRef SOSAccountGetMyFullPeerInCircle(SOSAccountRef account, SOSCircleRef circle, CFErrorRef* error) {
-    return SOSAccountGetMyFullPeerInCircleNamed(account, SOSCircleGetName(circle), error);
+    return SOSAccountGetMyFullPeerInCircleNamedIfPresent(account, SOSCircleGetName(circle), error);
 }
 
 
index d0e0ca0351424c334060b5657b2db703ed8d309c..5f41f26d94c75d5820c83e61fa15ec77586f6098 100644 (file)
@@ -49,14 +49,14 @@ bool SOSAccountDestroyCirclePeerInfo(SOSAccountRef account, SOSCircleRef circle,
 }
 
 SOSPeerInfoRef SOSAccountGetMyPeerInCircle(SOSAccountRef account, SOSCircleRef circle, CFErrorRef* error) {
-    SOSFullPeerInfoRef fpi =  SOSAccountGetMyFullPeerInCircleNamed(account, SOSCircleGetName(circle), error);
+    SOSFullPeerInfoRef fpi =  SOSAccountGetMyFullPeerInCircleNamedIfPresent(account, SOSCircleGetName(circle), error);
     
     return fpi ? SOSFullPeerInfoGetPeerInfo(fpi) : NULL;
 }
 
 SOSPeerInfoRef SOSAccountGetMyPeerInCircleNamed(SOSAccountRef account, CFStringRef name, CFErrorRef *error)
 {
-    SOSFullPeerInfoRef fpi =  SOSAccountGetMyFullPeerInCircleNamed(account, name, error);
+    SOSFullPeerInfoRef fpi =  SOSAccountGetMyFullPeerInCircleNamedIfPresent(account, name, error);
     
     return fpi ? SOSFullPeerInfoGetPeerInfo(fpi) : NULL;
 }
index c9eaa4f371ba6aeedd4dd161db13b1801589eb58..ebaed87f0565d5b19f4b9902208d06286ee70b77 100644 (file)
@@ -339,7 +339,7 @@ SOSAccountRef SOSAccountCreateFromDER(CFAllocatorRef allocator,
                     if (fullPeerInfoData) {
                         SOSFullPeerInfoRef full_peer = SOSFullPeerInfoCreateFromData(kCFAllocatorDefault, fullPeerInfoData, error);
                         require_action_quiet(full_peer, fail, success = false);
-                        
+                    
                         CFDictionaryAddValue(account->circle_identities, circleName, full_peer);
                         CFReleaseNull(full_peer);
                     }
@@ -352,6 +352,7 @@ SOSAccountRef SOSAccountCreateFromDER(CFAllocatorRef allocator,
     CFReleaseNull(array);
     
     require_quiet(success, fail);
+    
     require_action_quiet(SOSAccountEnsureFactoryCircles(account), fail,
                          SOSCreateError(kSOSErrorBadFormat, CFSTR("Cannot EnsureFactoryCircles"), (error != NULL) ? *error : NULL, error));
     
index 91d84a145988ec5179382ea5c620055390a77f56..39be45d2e41c0abf2a956b16b229025acfaf5f66 100644 (file)
@@ -178,7 +178,7 @@ void SOSAccountForEachKnownCircle(SOSAccountRef account,
 
 int SOSAccountCountCircles(SOSAccountRef a);
 
-SOSFullPeerInfoRef SOSAccountGetMyFullPeerInCircleNamed(SOSAccountRef account, CFStringRef name, CFErrorRef *error);
+SOSFullPeerInfoRef SOSAccountMakeMyFullPeerInCircleNamed(SOSAccountRef account, CFStringRef name, CFErrorRef *error);
 
 bool SOSAccountDestroyCirclePeerInfoNamed(SOSAccountRef account, CFStringRef name, CFErrorRef* error);
 
@@ -234,7 +234,7 @@ SOSFullPeerInfoRef SOSAccountGetMyFullPeerInCircleNamedIfPresent(SOSAccountRef a
 
 bool SOSAccountIsAccountIdentity(SOSAccountRef account, SOSPeerInfoRef peer_info, CFErrorRef *error);
 
-SOSFullPeerInfoRef SOSAccountGetMyFullPeerInCircleNamed(SOSAccountRef account, CFStringRef name, CFErrorRef *error);
+SOSFullPeerInfoRef SOSAccountMakeMyFullPeerInCircleNamed(SOSAccountRef account, CFStringRef name, CFErrorRef *error);
 
 SOSFullPeerInfoRef SOSAccountGetMyFullPeerInCircle(SOSAccountRef account, SOSCircleRef circle, CFErrorRef* error);
 
index ad7cae8e5c5e85538ef9f3dcc73caf1eab7b0b7e..5b23afa595cb409a30ecf810571c6cd9c540e032 100644 (file)
@@ -268,8 +268,10 @@ bool SOSAccountHandleUpdateCircle(SOSAccountRef account, SOSCircleRef prospectiv
         // SOSAccountDestroyCirclePeerInfo(account, oldCircle, NULL);
     }
     
-    SOSFullPeerInfoRef me_full = SOSAccountGetMyFullPeerInCircle(account, oldCircle, NULL);
-    SOSPeerInfoRef     me = SOSFullPeerInfoGetPeerInfo(me_full);
+    // Changed to just get the fullpeerinfo if present.  We don't want to make up FPIs here.
+    SOSPeerInfoRef     me = NULL;
+    SOSFullPeerInfoRef me_full = SOSAccountGetMyFullPeerInCircleNamedIfPresent(account, SOSCircleGetName(oldCircle), NULL);
+    if(me_full) me = SOSFullPeerInfoGetPeerInfo(me_full);
     
     SOSTransportCircleRef transport = (SOSTransportCircleRef)CFDictionaryGetValue(account->circle_transports, SOSCircleGetName(prospective_circle));
 
@@ -354,16 +356,18 @@ bool SOSAccountHandleUpdateCircle(SOSAccountRef account, SOSCircleRef prospectiv
         
         if (me && SOSCircleHasPeer(oldCircle, me, NULL)) {
             if (sosAccountLeaveCircle(account, newCircle, error)) {
-                account->departure_code = leave_reason;
                 circleToPush = newCircle;
-                circle_action = accept;
-                me = NULL;
-                me_full = NULL;
+            } else {
+                secnotice("signing", "Can't leave circle %@, but dumping identities", oldCircle);
+                success = false;
             }
-        }
-        else {
+            account->departure_code = leave_reason;
+            circle_action = accept;
+            me = NULL;
+            me_full = NULL;
+        } else {
             // We are not in this circle, but we need to update account with it, since we got it from cloud
-            secnotice("updatecircle", "We are not in this circle, but we need to update account with it");
+            secnotice("signing", "We are not in this circle, but we need to update account with it");
             circle_action = accept;
         }
     }
@@ -408,7 +412,7 @@ bool SOSAccountHandleUpdateCircle(SOSAccountRef account, SOSCircleRef prospectiv
                 me = NULL;
                 me_full = NULL;
             } else {
-                SOSCircleRequestReadmission(newCircle, account->user_public, me_full, NULL);
+                SOSCircleRequestReadmission(newCircle, account->user_public, me, NULL);
                 writeUpdate = true;
             }
         }
@@ -419,7 +423,7 @@ bool SOSAccountHandleUpdateCircle(SOSAccountRef account, SOSCircleRef prospectiv
         
         secnotice("signing", "%@, Accepting circle: %@", concStr, newCircle);
         
-        if (me_full && account->user_public_trusted
+        if (me && account->user_public_trusted
             && SOSCircleHasApplicant(oldCircle, me, NULL)
             && SOSCircleCountPeers(newCircle) > 0
             && !SOSCircleHasPeer(newCircle, me, NULL) && !SOSCircleHasApplicant(newCircle, me, NULL)) {
@@ -427,7 +431,7 @@ bool SOSAccountHandleUpdateCircle(SOSAccountRef account, SOSCircleRef prospectiv
             // We were applying and we weren't accepted.
             // Our application is declared lost, let us reapply.
             
-            if (SOSCircleRequestReadmission(newCircle, account->user_public, me_full, NULL))
+            if (SOSCircleRequestReadmission(newCircle, account->user_public, me, NULL))
                 writeUpdate = true;
         }
         
@@ -461,7 +465,7 @@ bool SOSAccountHandleUpdateCircle(SOSAccountRef account, SOSCircleRef prospectiv
     
     
     if (circleToPush != NULL) {
-        secnotice("circleUpdate", "Pushing:[%s] %@", local_remote, circleToPush);
+        secnotice("signing", "Pushing:[%s] %@", local_remote, circleToPush);
         CFDataRef circle_data = SOSCircleCopyEncodedData(circleToPush, kCFAllocatorDefault, error);
         if (circle_data) {
             success &= SOSTransportCirclePostCircle(transport, SOSCircleGetName(circleToPush), circle_data, error);
index ff085161546221de45a1565a45935d73dcbb2d30..3f167d231de4f5e898722c837b12224b0edd0cba 100644 (file)
@@ -910,6 +910,7 @@ SOSPeerInfoRef SOSCircleCopyPeerWithID(SOSCircleRef circle, CFStringRef peerid,
 }
 
 bool SOSCircleHasPeer(SOSCircleRef circle, SOSPeerInfoRef peerInfo, CFErrorRef *error) {
+    if(!peerInfo) return false;
     return SOSCircleHasPeerWithID(circle, SOSPeerInfoGetPeerID(peerInfo), error);
 }
 
@@ -980,11 +981,10 @@ bool SOSCircleRemoveRetired(SOSCircleRef circle, CFErrorRef *error) {
     return true;
 }
 
-static bool SOSCircleRecordAdmissionRequest(SOSCircleRef circle, SecKeyRef user_pubkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
+static bool SOSCircleRecordAdmissionRequest(SOSCircleRef circle, SecKeyRef user_pubkey, SOSPeerInfoRef requestorPeerInfo, CFErrorRef *error) {
     SOSCircleAssertStable(circle);
     
-    SOSPeerInfoRef requestorPeerInfo = SOSFullPeerInfoGetPeerInfo(requestor);
-    bool isPeer = SOSCircleHasPeer(circle, SOSFullPeerInfoGetPeerInfo(requestor), error);
+    bool isPeer = SOSCircleHasPeer(circle, requestorPeerInfo, error);
     
     require_action_quiet(!isPeer, fail, SOSCreateError(kSOSErrorAlreadyPeer, CFSTR("Cannot request admission when already a peer"), NULL, error));
     
@@ -998,12 +998,11 @@ fail:
     
 }
 
-bool SOSCircleRequestReadmission(SOSCircleRef circle, SecKeyRef user_pubkey, SOSFullPeerInfoRef requestor, CFErrorRef *error) {
+bool SOSCircleRequestReadmission(SOSCircleRef circle, SecKeyRef user_pubkey, SOSPeerInfoRef peer, CFErrorRef *error) {
     bool success = false;
     
-    SOSPeerInfoRef peer = SOSFullPeerInfoGetPeerInfo(requestor);
     require_quiet(SOSPeerInfoApplicationVerify(peer, user_pubkey, error), fail);
-    success = SOSCircleRecordAdmissionRequest(circle, user_pubkey, requestor, error);
+    success = SOSCircleRecordAdmissionRequest(circle, user_pubkey, peer, error);
 fail:
     return success;
 }
@@ -1016,7 +1015,7 @@ bool SOSCircleRequestAdmission(SOSCircleRef circle, SecKeyRef user_privkey, SOSF
 
     require(SOSFullPeerInfoPromoteToApplication(requestor, user_privkey, error), fail);
     
-    success = SOSCircleRecordAdmissionRequest(circle, user_pubkey, requestor, error);
+    success = SOSCircleRecordAdmissionRequest(circle, user_pubkey, SOSFullPeerInfoGetPeerInfo(requestor), error);
 fail:
     CFReleaseNull(user_pubkey);
     return success;
index 84fc7b727dff5275a099bdb9e74af4093fb7dcdf..c20a6242caa2161ca33c071d15ee2f822269cee2 100644 (file)
@@ -104,7 +104,7 @@ bool SOSCircleHasActiveValidPeer(SOSCircleRef circle, SOSPeerInfoRef peerInfo, S
 bool SOSCircleResetToOffering(SOSCircleRef circle, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error);
 bool SOSCircleResetToEmpty(SOSCircleRef circle, CFErrorRef *error);
 bool SOSCircleRequestAdmission(SOSCircleRef circle, SecKeyRef user_privkey, SOSFullPeerInfoRef requestor, CFErrorRef *error);
-bool SOSCircleRequestReadmission(SOSCircleRef circle, SecKeyRef user_pubkey, SOSFullPeerInfoRef requestor, CFErrorRef *error);
+bool SOSCircleRequestReadmission(SOSCircleRef circle, SecKeyRef user_pubkey, SOSPeerInfoRef requestor, CFErrorRef *error);
 
 bool SOSCircleAcceptRequest(SOSCircleRef circle, SecKeyRef user_privkey, SOSFullPeerInfoRef device_approver, SOSPeerInfoRef peerInfo, CFErrorRef *error);
 bool SOSCircleRejectRequest(SOSCircleRef circle, SOSFullPeerInfoRef device_approver, SOSPeerInfoRef peerInfo, CFErrorRef *error);
index 3ae444558057a2a54c69faf6bfdba1d57236ac70..a033cad8594e0e91991f7d3543a2e644eec11ec3 100644 (file)
@@ -352,18 +352,14 @@ static void SOSEngineSetTrustedPeers(SOSEngineRef engine, CFStringRef myPeerID,
                     CFReleaseSafe(mfadd);
                 };
 
-                if (source == kSOSDataSourceSOSTransaction) {
-                    processUpdates();
-                } else {
-                    // WARNING: This will deadlock the engine if you call a
-                    // SecItem API function while holding the engine lock!
-                    // However making this async right now isn't safe yet either
-                    // Due to some code in the enginer using Get v/s copy to
-                    // access some of the values that would be modified
-                    // asynchronously here since the engine is coded as if
-                    // running on a serial queue.
-                    dispatch_sync(engine->queue, processUpdates);
-                }
+                // WARNING: This will deadlock the engine if you call a
+                // SecItem API function while holding the engine lock!
+                // However making this async right now isn't safe yet either
+                // Due to some code in the enginer using Get v/s copy to
+                // access some of the values that would be modified
+                // asynchronously here since the engine is coded as if
+                // running on a serial queue.
+                dispatch_sync(engine->queue, processUpdates);
             });
         } else {
             SOSDataSourceSetNotifyPhaseBlock(engine->dataSource, ^(SOSDataSourceRef ds, SOSTransactionRef txn, SOSDataSourceTransactionPhase phase, SOSDataSourceTransactionSource source, struct SOSDigestVector *removals, struct SOSDigestVector *additions) {
@@ -907,8 +903,10 @@ bool SOSEngineHandleMessage(SOSEngineRef engine, CFStringRef peerID,
     __block bool somethingChanged = false;
     SOSMessageRef message = SOSMessageCreateWithData(kCFAllocatorDefault, raw_message, error);
     result = message && SOSDataSourceWith(engine->dataSource, error, ^(SOSTransactionRef txn, bool *commit) {
-        result = SOSEngineHandleMessage_locked(engine, peerID, message, txn, commit, &somethingChanged, error);
+        dispatch_sync(engine->queue, ^{
+            result = SOSEngineHandleMessage_locked(engine, peerID, message, txn, commit, &somethingChanged, error);
         });
+    });
     CFReleaseSafe(message);
     if (somethingChanged)
         SecKeychainChanged(false);
index a293c10f03e8f24fc0146179e496a534010091a1..a59314c8483f4d98447f9334b5c07b7e0726a3f1 100644 (file)
@@ -139,7 +139,6 @@ exit:
 SOSFullPeerInfoRef SOSFullPeerInfoCreateFromDER(CFAllocatorRef allocator, CFErrorRef* error,
                                         const uint8_t** der_p, const uint8_t *der_end) {
     SOSFullPeerInfoRef fpi = CFTypeAllocate(SOSFullPeerInfo, struct __OpaqueSOSFullPeerInfo, allocator);
-    SecKeyRef device_key = NULL;
     
     const uint8_t *sequence_end;
     
@@ -149,18 +148,12 @@ SOSFullPeerInfoRef SOSFullPeerInfoCreateFromDER(CFAllocatorRef allocator, CFErro
     require_quiet(fpi->peer_info != NULL, fail);
 
     *der_p = der_decode_data(allocator, kCFPropertyListImmutable, &fpi->key_ref, error, *der_p, sequence_end);
-    
-    OSStatus result = SecKeyFindWithPersistentRef(fpi->key_ref, &device_key);
-
-    require_quiet(result == errSecSuccess, fail);
     require_quiet(*der_p != NULL, fail);
     
-    CFReleaseNull(device_key);
     return fpi;
 
 fail:
     CFReleaseNull(fpi);
-    CFReleaseNull(device_key);
     return NULL;
 }
 
@@ -236,7 +229,11 @@ fail:
 
 
 bool SOSFullPeerInfoValidate(SOSFullPeerInfoRef peer, CFErrorRef* error) {
-    return true;
+    SecKeyRef device_key = NULL;
+    OSStatus result = SecKeyFindWithPersistentRef(peer->key_ref, &device_key);
+    CFReleaseNull(device_key);
+    if(result == errSecSuccess) return true;
+    return false;
 }
 
 bool SOSFullPeerInfoPurgePersistentKey(SOSFullPeerInfoRef fullPeer, CFErrorRef* error) {
index 478a22a491b494899949f993a398faf7673f1fde..723d4b758d65723b3a4a394c0aafd03ba35d7ef7 100644 (file)
@@ -228,6 +228,7 @@ CFMutableArrayRef SOSTransportDispatchMessages(SOSAccountRef account, CFDictiona
     CFMutableArrayRef handledKeys = CFArrayCreateMutableForCFTypes(kCFAllocatorDefault);
     
     if(CFDictionaryContainsKey(updates, kSOSKVSAccountChangedKey)){
+        secnotice("accountChange", "SOSTransportDispatchMessages received kSOSKVSAccountChangedKey");
         // While changing accounts we may modify the key params array. To avoid stepping on ourselves we
         // copy the list for iteration.
         CFArrayRef originalKeyParams = CFArrayCreateCopy(kCFAllocatorDefault, SOSGetTransportKeyParameters());
index 2130e61e75e28ad63b8384501ebc9a7cfeef6bd1..0fcb2f0539448a186e88f622ecc81c9ba8794367 100644 (file)
@@ -37,7 +37,7 @@ static void SOSTransportMessageDestroy(CFTypeRef aObj){
     if (transport->destroy)
         transport->destroy(transport);
     
-    CFReleaseSafe(transport->engine);
+    CFReleaseSafe(transport->account);
 }
 
 SOSAccountRef SOSTransportMessageGetAccount(SOSTransportMessageRef transport){
index 4a26d2d74e1135292f78899883927ec8c5f27c79..0ea6e15585aa054ba8254ca38dbbdcaef301ef5d 100644 (file)
 #include <xpc/private.h>
 #include <xpc/xpc.h>
 
+#if TARGET_OS_MAC
+#include <Security/SecTaskPriv.h>
+#endif
+
 static CFStringRef SecTaskCopyStringForEntitlement(SecTaskRef task,
     CFStringRef entitlement)
 {
@@ -122,6 +126,12 @@ static CFArrayRef SecTaskCopyAccessGroups(SecTaskRef task) {
     CFStringRef appID = SecTaskCopyApplicationIdentifier(task);
     CFIndex kagLen = keychainAccessGroups ? CFArrayGetCount(keychainAccessGroups) : 0;
     CFIndex asagLen = appleSecurityApplicationGroups ? CFArrayGetCount(appleSecurityApplicationGroups) : 0;
+#if TARGET_OS_MAC
+    if ((appID || asagLen) && !SecTaskEntitlementsValidated(task)) {
+        CFReleaseNull(appID);
+        asagLen = 0;
+    }
+#endif
     CFIndex len = kagLen + asagLen + (appID ? 1 : 0);
     if (len) {
         groups = CFArrayCreateMutable(kCFAllocatorDefault, len, &kCFTypeArrayCallBacks);
index 39b31e84891dcc5fd78b3d1de13d40be23f8340d..af74e6fdb56d73efaeb2925bdb3b776102bdaa83 100644 (file)
@@ -49,7 +49,7 @@
 
 #include "SOSAccountTesting.h"
 
-static int kTestTestCount = 304;
+static int kTestTestCount = 298;
 
 static void tests(void)
 {
index 43f2d394356cc5d76656e032e0bd36ee015dfb21..bb01b0c82848d213c274dbdf32db10f6eb8779a1 100644 (file)
@@ -102,7 +102,7 @@ static void tests(void)
     ok(peers && CFArrayGetCount(peers) == 2, "See two peers %@ (%@)", peers, error);
     CFReleaseNull(peers);
     
-    SOSFullPeerInfoRef fpiAlice = SOSAccountGetMyFullPeerInCircleNamed(alice_account, circle_name, NULL);
+    SOSFullPeerInfoRef fpiAlice = SOSAccountGetMyFullPeerInCircleNamedIfPresent(alice_account, circle_name, NULL);
     CFStringRef alice_id = CFStringCreateCopy(NULL, SOSPeerInfoGetPeerID(SOSFullPeerInfoGetPeerInfo(fpiAlice)));
     
     ok(SOSAccountLeaveCircles(alice_account, &error), "Alice Leaves (%@)", error);
index 8aa8d45f64dee51479902968f85ad8c495091556..a68bb0ede4a6ea5d15fb67851d790e09d1429cab 100644 (file)
@@ -292,6 +292,11 @@ static void SOSKeychainAccountEnsureSaved(SOSAccountRef account)
     static CFDataRef sLastSavedAccountData = NULL;
 
     CFErrorRef saveError = NULL;
+    
+    if(SOSAccountGetMyFullPeerInCircleNamedIfPresent(account, CFSTR("ak"), NULL) == NULL) {
+        return;
+    }
+    
        SOSCCCircleIsOn_UpdateArtifact(SOSAccountIsInCircles(account, NULL));
 
     CFDataRef accountAsData = SOSAccountCopyEncodedData(account, kCFAllocatorDefault, &saveError);
@@ -353,11 +358,22 @@ static SOSAccountRef SOSKeychainAccountCreateSharedAccount(CFDictionaryRef our_g
 
         account = SOSAccountCreateFromData(kCFAllocatorDefault, savedAccount, factory, &inflationError);
 
+        if(account && SOSAccountGetMyFullPeerInCircleNamedIfPresent(account, CFSTR("ak"), NULL) == NULL) {
+            SOSAccountRef newAccount = SOSAccountCreate(kCFAllocatorDefault, our_gestalt, factory);
+            
+            if (!newAccount) {
+                secnotice("repair_account", "Tried to repair bad account - got null account");
+            } else {
+                account = newAccount;
+            }
+        }
+
         if (account){
             SOSAccountUpdateGestalt(account, our_gestalt);
-        }
-        else
+        } else {
             secerror("Got error inflating account: %@", inflationError);
+        }
+        
         CFReleaseNull(inflationError);
     }
     CFReleaseSafe(savedAccount);
index d1ec5dcb8f9f273c5752ac35487432a2dce5e224..20616cb081a4820edad732391ebedd6dc0cade1d 100644 (file)
@@ -49,6 +49,10 @@ CFDataRef SecOTRSessionCreateRemote_internal(CFDataRef publicAccountData, CFData
     });
     
     SecKeyRef privateKeyRef = SOSFullPeerInfoCopyDeviceKey(full_peer_info, error);
+    if(!privateKeyRef) {
+        secnotice("otr_keysetup", "Could not get private key for FullPeerInfo");
+        return NULL;
+    }
     
     CFStringRef publicKeyString = CFStringCreateFromExternalRepresentation(kCFAllocatorDefault, publicPeerId, kCFStringEncodingUTF8);
     __block SOSPeerInfoRef peer_info = NULL;
index 2d421599602d0bce9032ea009f6ce2abaf1e78be..68ab7122b4e10ff7a0a11d11b5e2d000f84cb305 100644 (file)
@@ -379,6 +379,18 @@ static void setup_environment_scopes() {
     ApplyScopeListForIDC(cur_scope, kScopeIDEnvironment);
 }
 
+#define XPCSCOPESTRWANT "api,account,accountChange,circle,circleChange,circleCreat,flush,fresh,keygen,signing,talkwithkvs"
+#define XPCSCOPESTRDONTWANT "-event,http,item,keytrace,lockassertions,otr_keysetup,securityd,server,serverxpc,session,sync,titc,transport,trust,updates,xpc"
+static void setup_xpcdefault_scopes() {
+    
+    CFDictionaryRef noticeLogging = CFDictionaryCreateForCFTypes(kCFAllocatorDefault,
+                        CFSTR(ASL_STRING_NOTICE), CFSTR(XPCSCOPESTRDONTWANT), NULL);
+    
+    ApplyScopeDictionaryForID(noticeLogging, kScopeIDXPC);
+    
+    CFReleaseNull(noticeLogging);
+}
+
 void __security_debug_init(void) {
     static dispatch_once_t sdOnceToken;
 
@@ -386,10 +398,10 @@ void __security_debug_init(void) {
         setup_environment_scopes();
         setup_config_settings();
         setup_defaults_settings();
+        //setup_xpcdefault_scopes();
     });
 }
 
-
 // MARK: Log handler recording (e.g. grabbing security logging and sending it to test results).
 static void clean_aslclient(void *client)
 {
index 87c85b42625a2e5cacb2e1b4453770f3c829ab70..208270eb4c8aa649ae74214a1ae799452f2eafab 100755 (executable)
@@ -88,7 +88,7 @@ const NSString* SWC_SERVER_KEY   = @"srvr";
         
         self.textLabel.textColor = [UIColor blackColor];
         self.textLabel.textAlignment = NSTextAlignmentLeft;
-        self.textLabel.AdjustsFontSizeToFitWidth = YES;
+        self.textLabel.adjustsFontSizeToFitWidth = YES;
         self.textLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters;
         
         NSString *title = [dict objectForKey:SWC_ACCOUNT_KEY];
@@ -96,7 +96,7 @@ const NSString* SWC_SERVER_KEY   = @"srvr";
         
         self.detailTextLabel.textColor = [UIColor darkGrayColor];
         self.detailTextLabel.textAlignment = NSTextAlignmentLeft;
-        self.detailTextLabel.AdjustsFontSizeToFitWidth = YES;
+        self.detailTextLabel.adjustsFontSizeToFitWidth = YES;
         self.detailTextLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters;
         
         NSString *subtitle = [dict objectForKey:SWC_SERVER_KEY];