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
;