]> git.saurik.com Git - apple/security.git/blobdiff - Security/libsecurity_apple_x509_tp/lib/TPNetwork.cpp
Security-57336.1.9.tar.gz
[apple/security.git] / Security / libsecurity_apple_x509_tp / lib / TPNetwork.cpp
diff --git a/Security/libsecurity_apple_x509_tp/lib/TPNetwork.cpp b/Security/libsecurity_apple_x509_tp/lib/TPNetwork.cpp
deleted file mode 100644 (file)
index bc9cf3f..0000000
+++ /dev/null
@@ -1,511 +0,0 @@
-/*
- * Copyright (c) 2002-2012 Apple Inc. All Rights Reserved.
- * 
- * The contents of this file constitute Original Code as defined in and are
- * subject to the Apple Public Source License Version 1.2 (the 'License').
- * You may not use this file except in compliance with the License. Please obtain
- * a copy of the License at http://www.apple.com/publicsource and read it before
- * using this file.
- * 
- * This 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, INCLUDING WITHOUT
- * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 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.
- */
-
-
-/*
- * TPNetwork.h - LDAP, HTTP and (eventually) other network tools 
- */
-#include "TPNetwork.h"
-#include "tpdebugging.h"
-#include "tpTime.h"
-#include "cuEnc64.h"
-#include <Security/cssmtype.h>
-#include <Security/cssmapple.h>
-#include <Security/oidscert.h>
-#include <security_utilities/logging.h>
-#include <security_ocspd/ocspdClient.h>
-
-#define CA_ISSUERS_OID              OID_PKIX, 0x30, 0x02
-#define CA_ISSUERS_OID_LEN          OID_PKIX_LENGTH + 2
-
-static const uint8     OID_CA_ISSUERS[]      = {CA_ISSUERS_OID};
-const CSSM_OID CSSMOID_CA_ISSUERS        = {CA_ISSUERS_OID_LEN, (uint8 *)OID_CA_ISSUERS};
-
-typedef enum {
-       LT_Crl = 1,
-       LT_Cert
-} LF_Type;
-
-static CSSM_RETURN tpDecodeCert(
-       Allocator               &alloc,
-       CSSM_DATA               &rtnBlob)               // will be reallocated if needed
-{
-       const unsigned char *inbuf = (const unsigned char *)rtnBlob.Data;
-       unsigned inlen = (unsigned)rtnBlob.Length;
-       unsigned char *outbuf = NULL;
-       unsigned outlen = 0;
-       CSSM_RETURN ortn = cuConvertPem(inbuf, inlen, &outbuf, &outlen);
-
-       if(ortn == 0 && outbuf != NULL) {
-               /* Decoded result needs to be malloc'd via input allocator */
-               unsigned char *rtnP = (unsigned char *) alloc.malloc(outlen);
-               if(rtnP != NULL) {
-                       memcpy(rtnP, outbuf, outlen);
-                       rtnBlob.Data = rtnP;
-                       rtnBlob.Length = outlen;
-               }
-               free(outbuf);
-               alloc.free((void *)inbuf);
-       }
-       return ortn;
-}
-
-static CSSM_RETURN tpFetchViaNet(
-       const CSSM_DATA &url,
-       const CSSM_DATA *issuer,                // optional
-       LF_Type                 lfType,
-       CSSM_TIMESTRING verifyTime,             // CRL only
-       Allocator               &alloc,
-       CSSM_DATA               &rtnBlob)               // mallocd and RETURNED
-{
-       if(lfType == LT_Crl) {
-               return ocspdCRLFetch(alloc, url, issuer,
-                       true, true,                             // cache r/w both enable
-                       verifyTime, rtnBlob);
-       }
-       else {
-               CSSM_RETURN result = ocspdCertFetch(alloc, url, rtnBlob);
-               if(result == CSSM_OK) {
-                       /* The data might be in PEM format; if so, convert it here */
-                       (void)tpDecodeCert(alloc, rtnBlob);
-               }
-               return result;
-       }
-}
-
-static CSSM_RETURN tpCrlViaNet(
-       const CSSM_DATA &url,
-       const CSSM_DATA *issuer,        // optional, only if cert and CRL have same issuer
-       TPVerifyContext &vfyCtx,
-       TPCertInfo &forCert,            // for verifyWithContext
-       TPCrlInfo *&rtnCrl)
-{
-       TPCrlInfo *crl = NULL;
-       CSSM_DATA crlData;
-       CSSM_RETURN crtn;
-       Allocator &alloc = Allocator::standard();
-       char cssmTime[CSSM_TIME_STRLEN+1];
-       
-       rtnCrl = NULL;
-       
-       /* verifyTime: we want a CRL that's valid right now. */
-       {
-               StLock<Mutex> _(tpTimeLock());
-               timeAtNowPlus(0, TIME_CSSM, cssmTime);
-       }
-
-       crtn = tpFetchViaNet(url, issuer, LT_Crl, cssmTime, alloc, crlData);
-       if(crtn) {
-               return crtn;
-       }
-       try {
-               crl = new TPCrlInfo(vfyCtx.clHand,
-                       vfyCtx.cspHand,
-                       &crlData,
-                       TIC_CopyData,
-                       NULL);                  // verifyTime = Now
-       }
-       catch(...) {
-               alloc.free(crlData.Data);
-               
-               /* 
-                * There is a slight possibility of recovering from this error. In case
-                * the CRL came from disk cache, flush the cache and try to get the CRL
-                * from the net.
-                */
-               tpDebug("   bad CRL; flushing from cache and retrying"); 
-               ocspdCRLFlush(url);
-               crtn = tpFetchViaNet(url, issuer, LT_Crl, cssmTime, alloc, crlData);
-               if(crtn == CSSM_OK) {
-                       try {
-                               crl = new TPCrlInfo(vfyCtx.clHand,
-                                       vfyCtx.cspHand,
-                                       &crlData,
-                                       TIC_CopyData,
-                                       NULL);  
-                               tpDebug("   RECOVERY: good CRL obtained from net"); 
-                       }
-                       catch(...) {
-                               alloc.free(crlData.Data);
-                               tpDebug("   bad CRL; recovery FAILED (1)"); 
-                               return CSSMERR_APPLETP_CRL_NOT_FOUND;
-                       }
-               }
-               else {
-                       /* it was in cache but we can't find it on the net */
-                       tpDebug("   bad CRL; recovery FAILED (2)"); 
-                       return CSSMERR_APPLETP_CRL_NOT_FOUND;
-               }
-       }
-       alloc.free(crlData.Data);
-       
-       /* 
-        * Full CRL verify.
-        * The verify time in the TPVerifyContext is the time at which various
-        * entities (CRL and its own cert chain) are to be verified; that's
-        * NULL for "right now". The current vfyCtx.verifyTime is the time at
-        * which the cert's revocation status to be determined; this call to 
-        * verifyWithContextNow() doesn't do that. 
-        */
-       crtn = crl->verifyWithContextNow(vfyCtx, &forCert);
-       if(crtn == CSSM_OK) {
-               crl->uri(url);
-       }
-       else {
-               delete crl;
-               crl = NULL;
-       }
-       rtnCrl = crl;
-       return crtn;
-}
-
-static CSSM_RETURN tpIssuerCertViaNet(
-       const CSSM_DATA &url,
-       CSSM_CL_HANDLE  clHand,
-       CSSM_CSP_HANDLE cspHand,
-       const char              *verifyTime,
-       TPCertInfo              &subject,       
-       TPCertInfo              *&rtnCert)
-{
-       TPCertInfo *issuer = NULL;
-       CSSM_DATA certData;
-       CSSM_RETURN crtn;
-       Allocator &alloc = Allocator::standard();
-       
-       crtn = tpFetchViaNet(url, NULL, LT_Cert, NULL, alloc, certData);
-       if(crtn) {
-               tpErrorLog("tpIssuerCertViaNet: net fetch failed\n");
-               return CSSMERR_APPLETP_CERT_NOT_FOUND_FROM_ISSUER;
-       }       
-       try {
-               issuer = new TPCertInfo(clHand,
-                       cspHand,
-                       &certData,
-                       TIC_CopyData,
-                       verifyTime);
-       }
-       catch(...) {
-               tpErrorLog("tpIssuerCertViaNet: bad cert via net fetch\n");
-               alloc.free(certData.Data);
-               rtnCert = NULL;
-               return CSSMERR_APPLETP_BAD_CERT_FROM_ISSUER;
-       }
-       alloc.free(certData.Data);
-       
-       /* subject/issuer match? */
-       if(!issuer->isIssuerOf(subject)) {
-               tpErrorLog("tpIssuerCertViaNet: wrong issuer cert via net fetch\n");
-               crtn = CSSMERR_APPLETP_BAD_CERT_FROM_ISSUER;
-       }
-       else {
-               /* yep, do a sig verify */
-               crtn = subject.verifyWithIssuer(issuer);
-               if(crtn) {
-                       tpErrorLog("tpIssuerCertViaNet: sig verify fail for cert via net "
-                               "fetch\n");
-                       crtn = CSSMERR_APPLETP_BAD_CERT_FROM_ISSUER;
-               }
-       }
-       if(crtn) {
-               assert(issuer != NULL);
-               delete issuer;
-               issuer = NULL;
-       }
-       rtnCert = issuer;
-       return crtn;
-}
-
-/*
- * Fetch a CRL or a cert via a GeneralNames.
- * Shared by cert and CRL code to avoid duplicating GeneralNames traversal
- * code, despite the awkward interface for this function. 
- */
-static CSSM_RETURN tpFetchViaGeneralNames(
-       const CE_GeneralNames   *names,
-       TPCertInfo                              &forCert,
-       const CSSM_DATA                 *issuer,                        // optional, and only for CRLs
-       TPVerifyContext                 *verifyContext,         // only for CRLs
-       CSSM_CL_HANDLE                  clHand,                         // only for certs
-       CSSM_CSP_HANDLE                 cspHand,                        // only for certs
-       const char                              *verifyTime,            // optional
-       /* exactly one must be non-NULL, that one is returned */
-       TPCertInfo                              **certInfo,
-       TPCrlInfo                               **crlInfo)
-{      
-       assert(certInfo || crlInfo);
-       assert(!certInfo || !crlInfo);
-       CSSM_RETURN crtn;
-       
-       for(unsigned nameDex=0; nameDex<names->numNames; nameDex++) {
-               CE_GeneralName *name = &names->generalName[nameDex];
-               switch(name->nameType) {
-                       case GNT_URI:
-                               if(name->name.Length < 5) {
-                                       continue;
-                               }
-                               if(strncmp((char *)name->name.Data, "ldap:", 5) &&
-                                  strncmp((char *)name->name.Data, "http:", 5) && 
-                                  strncmp((char *)name->name.Data, "https:", 6)) {
-                                       /* eventually handle other schemes here */
-                                       continue;
-                               }
-                               if(certInfo) {
-                                       tpDebug("   fetching cert via net"); 
-                                       crtn = tpIssuerCertViaNet(name->name, 
-                                               clHand,
-                                               cspHand,
-                                               verifyTime,
-                                               forCert,
-                                               *certInfo);
-                               }
-                               else {
-                                       tpDebug("   fetching CRL via net"); 
-                                       assert(verifyContext != NULL);
-                                       crtn = tpCrlViaNet(name->name, 
-                                               issuer,
-                                               *verifyContext,
-                                               forCert,
-                                               *crlInfo);
-                               }
-                               switch(crtn) {
-                                       case CSSM_OK:
-                                       case CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE:   // caller handles
-                                               return crtn;
-                                       default:
-                                               break;
-                               }
-                               /* not found/no good; try again */
-                               break;
-                       default:
-                               tpCrlDebug("  tpFetchCrlFromNet: unknown"
-                                       "nameType (%u)", (unsigned)name->nameType); 
-                               break;
-               }       /* switch nameType */
-       }       /* for each name */
-       if(certInfo) {
-               return CSSMERR_TP_CERTGROUP_INCOMPLETE;
-       }
-       else {
-               return CSSMERR_APPLETP_CRL_NOT_FOUND;
-       }
-}
-
-/*
- * Fetch CRL(s) from specified cert if the cert has a cRlDistributionPoint
- * extension.
- *
- * Return values:
- *   CSSM_OK - found and returned fully verified CRL 
- *   CSSMERR_APPLETP_CRL_NOT_FOUND - no CRL in cRlDistributionPoint
- *   Anything else - gross error, typically from last LDAP/HTTP attempt
- *
- * FIXME - this whole mechanism sort of falls apart if verifyContext.verifyTime
- * is non-NULL. How are we supposed to get the CRL which was valid at 
- * a specified time in the past?
- */
-CSSM_RETURN tpFetchCrlFromNet(
-       TPCertInfo                      &cert,
-       TPVerifyContext         &vfyCtx,
-       TPCrlInfo                       *&crl)                  // RETURNED
-{
-       /* does the cert have a cRlDistributionPoint? */
-       CSSM_DATA_PTR fieldValue;                       // mallocd by CL
-       
-       CSSM_RETURN crtn = cert.fetchField(&CSSMOID_CrlDistributionPoints,
-               &fieldValue);
-       switch(crtn) {
-               case CSSM_OK:
-                       break;
-               case CSSMERR_CL_NO_FIELD_VALUES:
-                       /* field not present */
-                       return CSSMERR_APPLETP_CRL_NOT_FOUND;
-               default:
-                       /* gross error */
-                       return crtn;
-       }
-       if(fieldValue->Length != sizeof(CSSM_X509_EXTENSION)) {
-               tpErrorLog("tpFetchCrlFromNet: malformed CSSM_FIELD");
-               return CSSMERR_TP_UNKNOWN_FORMAT;
-       }
-       CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)fieldValue->Data;
-       CE_CRLDistPointsSyntax *dps = 
-               (CE_CRLDistPointsSyntax *)cssmExt->value.parsedValue;
-       TPCrlInfo *rtnCrl = NULL;
-
-       /* default return if we don't find anything */
-       crtn = CSSMERR_APPLETP_CRL_NOT_FOUND;
-       for(unsigned dex=0; dex<dps->numDistPoints; dex++) {
-               CE_CRLDistributionPoint *dp = &dps->distPoints[dex];
-               if(dp->distPointName == NULL) {
-                       continue;
-               }
-               /*
-                * FIXME if this uses an indirect CRL, we need to follow the 
-                * crlIssuer field... TBD.
-                */
-               switch(dp->distPointName->nameType) {
-                       case CE_CDNT_NameRelativeToCrlIssuer:
-                               /* not yet */
-                               tpErrorLog("tpFetchCrlFromNet: "
-                                       "CE_CDNT_NameRelativeToCrlIssuer not implemented\n");
-                               break;
-                               
-                       case CE_CDNT_FullName:
-                       {
-                               /*
-                                * Since we don't support indirect CRLs (yet), we always pass
-                                * the cert-to-be-verified's issuer as the CRL issuer for 
-                                * cache lookup.
-                                */
-                               CE_GeneralNames *names = dp->distPointName->dpn.fullName;
-                               crtn = tpFetchViaGeneralNames(names,
-                                       cert,
-                                       cert.issuerName(),
-                                       &vfyCtx,
-                                       0,                      // clHand, use the one in vfyCtx
-                                       0,                      // cspHand, ditto
-                                       vfyCtx.verifyTime,      
-                                       NULL,           
-                                       &rtnCrl);
-                               break;
-                       }       /* CE_CDNT_FullName */
-                       
-                       default:
-                               /* not yet */
-                               tpErrorLog("tpFetchCrlFromNet: "
-                                       "unknown distPointName->nameType (%u)\n",
-                                               (unsigned)dp->distPointName->nameType);
-                               break;
-               }       /* switch distPointName->nameType */
-               if(crtn == CSSM_OK) {
-                       /* i.e., tpFetchViaGeneralNames SUCCEEDED */
-                       break;
-               }
-       }       /* for each distPoints */
-
-       cert.freeField(&CSSMOID_CrlDistributionPoints,  fieldValue);
-       if(crtn == CSSM_OK) {
-               assert(rtnCrl != NULL);
-               crl = rtnCrl;
-       }
-       return crtn;
-}
-
-/*
- * Fetch issuer cert of specified cert if the cert has an issuerAltName
- * with a URI. If non-NULL cert is returned, it has passed subject/issuer
- * name comparison and signature verification with target cert.
- *
- * Return values:
- *   CSSM_OK - found and returned issuer cert 
- *   CSSMERR_TP_CERTGROUP_INCOMPLETE - no URL in issuerAltName
- *   CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE - found and returned issuer
- *      cert, but signature verification needs subsequent retry.
- *   Anything else - gross error, typically from last LDAP/HTTP attempt
- */
-CSSM_RETURN tpFetchIssuerFromNet(
-       TPCertInfo                      &subject,
-       CSSM_CL_HANDLE          clHand,
-       CSSM_CSP_HANDLE         cspHand,
-       const char                      *verifyTime,
-       TPCertInfo                      *&issuer)               // RETURNED
-{
-       CSSM_OID_PTR fieldOid = NULL;
-       CSSM_DATA_PTR fieldValue = NULL;        // mallocd by CL
-       CSSM_RETURN crtn;
-       bool hasAIA = false;
-
-       /* look for the Authority Info Access extension first */
-       fieldOid = (CSSM_OID_PTR)&CSSMOID_AuthorityInfoAccess;
-       crtn = subject.fetchField(fieldOid,
-               &fieldValue);
-       hasAIA = (crtn == CSSM_OK);
-       if (!hasAIA) {
-               /* fall back to Issuer Alternative Name extension */
-               fieldOid = (CSSM_OID_PTR)&CSSMOID_IssuerAltName;
-               crtn = subject.fetchField(fieldOid,
-                                                                 &fieldValue);
-       }
-       switch(crtn) {
-               case CSSM_OK:
-                       break;
-               case CSSMERR_CL_NO_FIELD_VALUES:
-                       /* field not present */
-                       return CSSMERR_TP_CERTGROUP_INCOMPLETE;
-               default:
-                       /* gross error */
-                       return crtn;
-       }
-       if(fieldValue->Length != sizeof(CSSM_X509_EXTENSION)) {
-               tpPolicyError("tpFetchIssuerFromNet: malformed CSSM_FIELD");
-               return CSSMERR_TP_UNKNOWN_FORMAT;
-       }
-       CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)fieldValue->Data;
-       CE_GeneralNames *names = (CE_GeneralNames *)cssmExt->value.parsedValue;
-       TPCertInfo *rtnCert = NULL;
-       if (hasAIA) {   /* authority info access */
-               CE_AuthorityInfoAccess *access = (CE_AuthorityInfoAccess *)cssmExt->value.parsedValue;
-               for (uint32 index = 0; access && index < access->numAccessDescriptions; index++) {
-                       CE_AccessDescription *accessDesc = &access->accessDescriptions[index];
-                       CSSM_OID_PTR methodOid = (CSSM_OID_PTR)&accessDesc->accessMethod;
-                       /* look for the CA Issuers method */
-                       if(methodOid->Data != NULL && methodOid->Length == CSSMOID_CA_ISSUERS.Length &&
-                          !memcmp(methodOid->Data, CSSMOID_CA_ISSUERS.Data, methodOid->Length)) {
-                               CE_GeneralNames aiaNames = { 1, &accessDesc->accessLocation };
-                               /* attempt to fetch cert from named location */
-                               crtn = tpFetchViaGeneralNames(&aiaNames,
-                                                                                         subject,
-                                                                                         NULL,         // issuer - not used
-                                                                                         NULL,         // verifyContext
-                                                                                         clHand,
-                                                                                         cspHand,
-                                                                                         verifyTime,
-                                                                                         &rtnCert,
-                                                                                         NULL);
-                               if (crtn == CSSM_OK ||
-                                       crtn == CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE) {
-                                       break; // got one
-                               }
-                       }
-               }
-               subject.freeField(fieldOid,     fieldValue);
-       }
-       else {  /* issuer alt name */
-               crtn = tpFetchViaGeneralNames(names,
-                                               subject,
-                                               NULL,           // issuer - not used
-                                               NULL,           // verifyContext
-                                               clHand,
-                                               cspHand,
-                                               verifyTime,
-                                               &rtnCert,
-                                               NULL);
-               subject.freeField(fieldOid,     fieldValue);
-       }
-       switch(crtn) {
-               case CSSM_OK:
-               case CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE:
-                       issuer = rtnCert;
-                       break;
-               default:
-                       break;
-       }
-       return crtn;
-}
-
-