2  * Copyright (c) 2000,2002,2011-2014 Apple Inc. All Rights Reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   6  * This file contains Original Code and/or Modifications of Original Code 
   7  * as defined in and that are subject to the Apple Public Source License 
   8  * Version 2.0 (the 'License'). You may not use this file except in 
   9  * compliance with the License. Please obtain a copy of the License at 
  10  * http://www.opensource.apple.com/apsl/ and read it before using this 
  13  * The Original Code and all software distributed under the License are 
  14  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  15  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  16  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  17  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  18  * Please see the License for the specific language governing rights and 
  19  * limitations under the License. 
  21  * @APPLE_LICENSE_HEADER_END@ 
  25  * ocspdClient.cpp - Client interface to OCSP helper daemon 
  28 #include "ocspdClient.h" 
  29 #include "ocspdTypes.h" 
  30 #include "ocspdDebug.h" 
  31 #include <Security/cssmapple.h> 
  32 #include <security_utilities/threading.h> 
  33 #include <security_utilities/mach++.h> 
  34 #include <security_utilities/unix++.h> 
  35 #include <security_ocspd/ocspd.h>                       /* MIG interface */ 
  36 #include <Security/SecBase.h> 
  42         mach_port_t 
serverPort(); 
  44         UnixPlusPlus::ForkMonitor mForkMonitor
; 
  45         MachPlusPlus::Port mServerPort
; 
  49 ocspdGlobals::ocspdGlobals() 
  52         /* nothing here, the real work is done in serverPort() */ 
  55 ocspdGlobals::~ocspdGlobals() 
  57         /* I don't believe this should ever execute */ 
  60 mach_port_t 
ocspdGlobals::serverPort() 
  62         StLock
<Mutex
> _(mLock
); 
  64         // Guard against fork-without-exec. If we are the child of a fork 
  65         // (that has not exec'ed), our apparent connection to SecurityServer 
  66         // is just a mirage, and we better reset it. 
  67         mach_port_t rtnPort 
= mServerPort
.port(); 
  75         const char *serverName 
= NULL
; 
  77         serverName 
= getenv(OCSPD_BOOTSTRAP_ENV
); 
  79         if(serverName 
== NULL
) { 
  80                 serverName 
= (char*) OCSPD_BOOTSTRAP_NAME
; 
  83                 mServerPort 
= MachPlusPlus::Bootstrap().lookup2(serverName
); 
  86                 ocspdErrorLog("ocspdGlobals: error contacting server\n"); 
  92 static ModuleNexus
<ocspdGlobals
> OcspdGlobals
; 
  95  * Perform network fetch of an OCSP response. Result is not verified in any  
  98 CSSM_RETURN 
ocspdFetch( 
 100         const CSSM_DATA         
&ocspdReq
,              // DER-encoded SecAsn1OCSPDRequests 
 101         CSSM_DATA                       
&ocspdResp
)             // DER-encoded kSecAsn1OCSPDReplies 
 103         mach_port_t serverPort 
= 0; 
 105         unsigned char *rtnData 
= NULL
; 
 109                 serverPort 
= OcspdGlobals().serverPort(); 
 112                 ocspdErrorLog("ocspdFetch: OCSPD server error\n"); 
 113                 return CSSMERR_TP_INTERNAL_ERROR
; 
 116         krtn 
= ocsp_client_ocspdFetch(serverPort
, ocspdReq
.Data
, (mach_msg_type_number_t
)ocspdReq
.Length
, 
 117                 (void **)&rtnData
, &rtnLen
); 
 119                 ocspdErrorLog("ocspdFetch: RPC returned %d\n", krtn
); 
 120                 return CSSMERR_APPLETP_OCSP_UNAVAILABLE
; 
 122         if((rtnData 
== NULL
) || (rtnLen 
== 0)) { 
 123                 ocspdErrorLog("ocspdFetch: RPC returned NULL data\n"); 
 124                 return CSSMERR_APPLETP_OCSP_UNAVAILABLE
; 
 126         ocspdResp
.Data 
= (uint8 
*)alloc
.malloc(rtnLen
); 
 127         ocspdResp
.Length 
= rtnLen
; 
 128         memmove(ocspdResp
.Data
, rtnData
, rtnLen
); 
 129         mig_deallocate((vm_address_t
)rtnData
, rtnLen
); 
 134  * Flush all responses associated with specifed CertID from cache.  
 136 CSSM_RETURN 
ocspdCacheFlush( 
 137         const CSSM_DATA         
&certID
) 
 139         mach_port_t serverPort 
= 0; 
 143                 serverPort 
= OcspdGlobals().serverPort(); 
 146                 ocspdErrorLog("ocspdCacheFlush: OCSPD server error\n"); 
 147                 return CSSMERR_TP_INTERNAL_ERROR
; 
 149         krtn 
= ocsp_client_ocspdCacheFlush(serverPort
, certID
.Data
, (mach_msg_type_number_t
)certID
.Length
); 
 151                 ocspdErrorLog("ocspdCacheFlush: RPC returned %d\n", krtn
); 
 152                 return CSSMERR_APPLETP_OCSP_UNAVAILABLE
; 
 158  * Flush stale entries from cache.  
 160 CSSM_RETURN 
ocspdCacheFlushStale() 
 162         mach_port_t serverPort 
= 0; 
 166                 serverPort 
= OcspdGlobals().serverPort(); 
 169                 ocspdErrorLog("ocspdCacheFlush: OCSPD server error\n"); 
 170                 return CSSMERR_TP_INTERNAL_ERROR
; 
 172         krtn 
= ocsp_client_ocspdCacheFlushStale(serverPort
); 
 174                 ocspdErrorLog("ocsp_client_ocspdCacheFlushStale: RPC returned %d\n", krtn
); 
 175                 return (CSSM_RETURN
)krtn
; 
 181  * fetch a certificate from the net.  
 183 CSSM_RETURN 
ocspdCertFetch( 
 185         const CSSM_DATA         
&certURL
, 
 186         CSSM_DATA                       
&certData
)              // mallocd via alloc and RETURNED 
 188         mach_port_t serverPort 
= 0; 
 190         unsigned char *rtnData 
= NULL
; 
 194                 serverPort 
= OcspdGlobals().serverPort(); 
 197                 ocspdErrorLog("ocspdCertFetch: OCSPD server error\n"); 
 198                 return CSSMERR_TP_INTERNAL_ERROR
; 
 201         krtn 
= ocsp_client_certFetch(serverPort
, certURL
.Data
, (mach_msg_type_number_t
)certURL
.Length
, 
 202                 (void **)&rtnData
, &rtnLen
); 
 204                 ocspdErrorLog("ocspdCertFetch: RPC returned %d\n", krtn
); 
 205                 return CSSMERR_APPLETP_NETWORK_FAILURE
; 
 208         if((rtnData 
== NULL
) || (rtnLen 
== 0)) { 
 209                 ocspdErrorLog("ocspdCertFetch: RPC returned NULL data\n"); 
 210                 return CSSMERR_APPLETP_CERT_NOT_FOUND_FROM_ISSUER
; 
 212         certData
.Data 
= (uint8 
*)alloc
.malloc(rtnLen
); 
 213         certData
.Length 
= rtnLen
; 
 214         memmove(certData
.Data
, rtnData
, rtnLen
); 
 215         mig_deallocate((vm_address_t
)rtnData
, rtnLen
); 
 220  * Fetch a CRL from net with optional cache lookup and store. 
 221  * verifyTime only used for cache lookup.  
 223 CSSM_RETURN 
ocspdCRLFetch( 
 225         const CSSM_DATA         
&crlURL
, 
 226         const CSSM_DATA         
*crlIssuer
,             // optional 
 227         bool                            cacheReadEnable
, 
 228         bool                            cacheWriteEnable
, 
 229         CSSM_TIMESTRING         verifyTime
, 
 230         CSSM_DATA                       
&crlData
)               // mallocd via alloc and RETURNED 
 232         mach_port_t serverPort 
= 0; 
 234         unsigned char *rtnData 
= NULL
; 
 237         if(verifyTime 
== NULL
) { 
 238                 ocspdErrorLog("ocspdCRLFetch: verifyTime NOT OPTIONAL\n"); 
 239                 return CSSMERR_TP_INTERNAL_ERROR
; 
 242                 serverPort 
= OcspdGlobals().serverPort(); 
 245                 ocspdErrorLog("ocspdCRLFetch: OCSPD server error\n"); 
 246                 return CSSMERR_TP_INTERNAL_ERROR
; 
 249         krtn 
= ocsp_client_crlFetch(serverPort
, crlURL
.Data
, (mach_msg_type_number_t
)crlURL
.Length
, 
 250                 crlIssuer 
? crlIssuer
->Data 
: NULL
, crlIssuer 
? (mach_msg_type_number_t
)crlIssuer
->Length 
: 0, 
 251                 cacheReadEnable
, cacheWriteEnable
, 
 252                 verifyTime
, (mach_msg_type_number_t
)strlen(verifyTime
), 
 253                 (void **)&rtnData
, &rtnLen
); 
 255                 ocspdErrorLog("ocspdCRLFetch: RPC returned %d\n", krtn
); 
 256                 return CSSMERR_APPLETP_NETWORK_FAILURE
; 
 259         if((rtnData 
== NULL
) || (rtnLen 
== 0)) { 
 260                 ocspdErrorLog("ocspdCRLFetch: RPC returned NULL data\n"); 
 261                 return CSSMERR_APPLETP_CRL_NOT_FOUND
; 
 263         crlData
.Data 
= (uint8 
*)alloc
.malloc(rtnLen
); 
 264         crlData
.Length 
= rtnLen
; 
 265         memmove(crlData
.Data
, rtnData
, rtnLen
); 
 266         mig_deallocate((vm_address_t
)rtnData
, rtnLen
); 
 272  * Get CRL status for given serial number and issuing entity 
 274 CSSM_RETURN 
ocspdCRLStatus( 
 275         const CSSM_DATA         
&serialNumber
, 
 276         const CSSM_DATA         
&issuers
, 
 277         const CSSM_DATA         
*crlIssuer
,             // optional if URL is supplied 
 278         const CSSM_DATA         
*crlURL
)                // optional if issuer is supplied 
 280         mach_port_t serverPort 
= 0; 
 283         if(!crlIssuer 
&& !crlURL
) { 
 284                 ocspdErrorLog("ocspdCRLStatus: either an issuer or URL is required\n"); 
 285                 return CSSMERR_TP_INTERNAL_ERROR
; 
 288                 serverPort 
= OcspdGlobals().serverPort(); 
 291                 ocspdErrorLog("ocspdCRLStatus: OCSPD server error\n"); 
 292                 return CSSMERR_TP_INTERNAL_ERROR
; 
 295         krtn 
= ocsp_client_crlStatus(serverPort
, 
 296                 serialNumber
.Data
, (mach_msg_type_number_t
)serialNumber
.Length
, 
 297                 issuers
.Data
, (mach_msg_type_number_t
)issuers
.Length
, 
 298                 crlIssuer 
? crlIssuer
->Data 
: NULL
, crlIssuer 
? (mach_msg_type_number_t
)crlIssuer
->Length 
: 0, 
 299                 crlURL 
? crlURL
->Data 
: NULL
, crlURL 
? (mach_msg_type_number_t
)crlURL
->Length 
: 0); 
 305  * Refresh the CRL cache. 
 307 CSSM_RETURN 
ocspdCRLRefresh( 
 309         unsigned        expireOverlapSeconds
, 
 311         bool            fullCryptoVerify
) 
 313         mach_port_t serverPort 
= 0; 
 316                 serverPort 
= OcspdGlobals().serverPort(); 
 319                 ocspdErrorLog("ocspdCRLRefresh: OCSPD server error\n"); 
 320                 return CSSMERR_TP_INTERNAL_ERROR
; 
 323         krtn 
= ocsp_client_crlRefresh(serverPort
, staleDays
, expireOverlapSeconds
, 
 324                 purgeAll
, fullCryptoVerify
); 
 326                 ocspdErrorLog("ocspdCRLRefresh: RPC returned %d\n", krtn
); 
 327                 return CSSMERR_APPLETP_NETWORK_FAILURE
; 
 334  * Flush all CRLs obtained from specified URL from cache. Called by client when 
 335  * *it* detects a bad CRL. 
 337 CSSM_RETURN 
ocspdCRLFlush( 
 338         const CSSM_DATA         
&crlURL
) 
 340         mach_port_t serverPort 
= 0; 
 344                 serverPort 
= OcspdGlobals().serverPort(); 
 347                 ocspdErrorLog("ocspdCRLFlush: OCSPD server error\n"); 
 348                 return CSSMERR_TP_INTERNAL_ERROR
; 
 351         krtn 
= ocsp_client_crlFlush(serverPort
, crlURL
.Data
, (mach_msg_type_number_t
)crlURL
.Length
); 
 353                 ocspdErrorLog("ocspdCRLFlush: RPC returned %d\n", krtn
); 
 354                 return CSSMERR_APPLETP_NETWORK_FAILURE
; 
 360  * Obtain TrustSettings.  
 362 OSStatus 
ocspdTrustSettingsRead( 
 364         SecTrustSettingsDomain  domain
, 
 365         CSSM_DATA                               
&trustSettings
)         // mallocd via alloc and RETURNED 
 367         mach_port_t serverPort 
= 0; 
 369         unsigned char *rtnData 
= NULL
; 
 374                 serverPort 
= OcspdGlobals().serverPort(); 
 377                 ocspdErrorLog("ocspdTrustSettingsRead: OCSPD server error\n"); 
 378                 return errSecInternalComponent
; 
 381         krtn 
= ocsp_client_trustSettingsRead(serverPort
, domain
, 
 382                 (void **)&rtnData
, &rtnLen
, &ortn
); 
 384                 ocspdErrorLog("ocspdTrustSettingsRead: RPC returned %d\n", krtn
); 
 385                 return errSecNotAvailable
; 
 388                 /* e.g., errSecNoUserTrustRecord */ 
 391         if((rtnData 
== NULL
) || (rtnLen 
== 0)) { 
 392                 ocspdErrorLog("ocspdTrustSettingsRead: RPC returned NULL data\n"); 
 393                 return errSecItemNotFound
; 
 395         trustSettings
.Data 
= (uint8 
*)alloc
.malloc(rtnLen
); 
 396         trustSettings
.Length 
= rtnLen
; 
 397         memmove(trustSettings
.Data
, rtnData
, rtnLen
); 
 398         mig_deallocate((vm_address_t
)rtnData
, rtnLen
); 
 399         return errSecSuccess
; 
 403  * Write TrustSettings to disk. Results in authentication dialog. 
 405 OSStatus 
ocspdTrustSettingsWrite( 
 406         SecTrustSettingsDomain  domain
, 
 407         const CSSM_DATA                 
&authBlob
, 
 408         const CSSM_DATA                 
&trustSettings
) 
 410         mach_port_t serverPort 
= 0; 
 411         mach_port_t clientPort 
= 0; 
 416                 serverPort 
= OcspdGlobals().serverPort(); 
 417                 clientPort 
= MachPlusPlus::Bootstrap(); 
 420                 ocspdErrorLog("ocspdTrustSettingsWrite: OCSPD server error\n"); 
 421                 return errSecInternalComponent
; 
 424         krtn 
= ocsp_client_trustSettingsWrite(serverPort
, clientPort
, domain
, 
 425                 authBlob
.Data
, (mach_msg_type_number_t
)authBlob
.Length
, 
 426                 trustSettings
.Data
, (mach_msg_type_number_t
)trustSettings
.Length
, 
 429                 ocspdErrorLog("ocspdTrustSettingsWrite: RPC returned %d\n", krtn
); 
 430                 return errSecInternalComponent
;