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 void resetServerPort();
43 mach_port_t
serverPort();
45 UnixPlusPlus::ForkMonitor mForkMonitor
;
46 MachPlusPlus::Port mServerPort
;
50 ocspdGlobals::ocspdGlobals()
53 /* nothing here, the real work is done in serverPort() */
56 ocspdGlobals::~ocspdGlobals()
58 /* I don't believe this should ever execute */
61 mach_port_t
ocspdGlobals::serverPort()
63 StLock
<Mutex
> _(mLock
);
65 // Guard against fork-without-exec. If we are the child of a fork
66 // (that has not exec'ed), our apparent connection to SecurityServer
67 // is just a mirage, and we better reset it.
68 mach_port_t rtnPort
= mServerPort
.port();
76 const char *serverName
= NULL
;
78 serverName
= getenv(OCSPD_BOOTSTRAP_ENV
);
80 if(serverName
== NULL
) {
81 serverName
= (char*) OCSPD_BOOTSTRAP_NAME
;
84 mServerPort
= MachPlusPlus::Bootstrap().lookup2(serverName
);
87 ocspdErrorLog("ocspdGlobals: error contacting server\n");
93 void ocspdGlobals::resetServerPort()
96 mServerPort
.deallocate();
102 static ModuleNexus
<ocspdGlobals
> OcspdGlobals
;
105 * Perform network fetch of an OCSP response. Result is not verified in any
108 CSSM_RETURN
ocspdFetch(
110 const CSSM_DATA
&ocspdReq
, // DER-encoded SecAsn1OCSPDRequests
111 CSSM_DATA
&ocspdResp
) // DER-encoded kSecAsn1OCSPDReplies
113 mach_port_t serverPort
= 0;
115 unsigned char *rtnData
= NULL
;
119 serverPort
= OcspdGlobals().serverPort();
122 ocspdErrorLog("ocspdFetch: OCSPD server error\n");
123 return CSSMERR_TP_INTERNAL_ERROR
;
126 krtn
= ocsp_client_ocspdFetch(serverPort
, ocspdReq
.Data
, (mach_msg_type_number_t
)ocspdReq
.Length
,
127 (void **)&rtnData
, &rtnLen
);
129 ocspdErrorLog("ocspdFetch: RPC returned %d\n", krtn
);
130 return CSSMERR_APPLETP_OCSP_UNAVAILABLE
;
132 if((rtnData
== NULL
) || (rtnLen
== 0)) {
133 ocspdErrorLog("ocspdFetch: RPC returned NULL data\n");
134 return CSSMERR_APPLETP_OCSP_UNAVAILABLE
;
136 ocspdResp
.Data
= (uint8
*)alloc
.malloc(rtnLen
);
137 ocspdResp
.Length
= rtnLen
;
138 memmove(ocspdResp
.Data
, rtnData
, rtnLen
);
139 mig_deallocate((vm_address_t
)rtnData
, rtnLen
);
144 * Flush all responses associated with specifed CertID from cache.
146 CSSM_RETURN
ocspdCacheFlush(
147 const CSSM_DATA
&certID
)
149 mach_port_t serverPort
= 0;
153 serverPort
= OcspdGlobals().serverPort();
156 ocspdErrorLog("ocspdCacheFlush: OCSPD server error\n");
157 return CSSMERR_TP_INTERNAL_ERROR
;
159 krtn
= ocsp_client_ocspdCacheFlush(serverPort
, certID
.Data
, (mach_msg_type_number_t
)certID
.Length
);
161 ocspdErrorLog("ocspdCacheFlush: RPC returned %d\n", krtn
);
162 return CSSMERR_APPLETP_OCSP_UNAVAILABLE
;
168 * Flush stale entries from cache.
170 CSSM_RETURN
ocspdCacheFlushStale()
172 mach_port_t serverPort
= 0;
176 serverPort
= OcspdGlobals().serverPort();
179 ocspdErrorLog("ocspdCacheFlush: OCSPD server error\n");
180 return CSSMERR_TP_INTERNAL_ERROR
;
182 krtn
= ocsp_client_ocspdCacheFlushStale(serverPort
);
184 if (krtn
== MACH_SEND_INVALID_DEST
)
185 OcspdGlobals().resetServerPort();
186 ocspdErrorLog("ocsp_client_ocspdCacheFlushStale: RPC returned %d\n", krtn
);
187 return (CSSM_RETURN
)krtn
;
193 * fetch a certificate from the net.
195 CSSM_RETURN
ocspdCertFetch(
197 const CSSM_DATA
&certURL
,
198 CSSM_DATA
&certData
) // mallocd via alloc and RETURNED
200 mach_port_t serverPort
= 0;
202 unsigned char *rtnData
= NULL
;
206 serverPort
= OcspdGlobals().serverPort();
209 ocspdErrorLog("ocspdCertFetch: OCSPD server error\n");
210 return CSSMERR_TP_INTERNAL_ERROR
;
213 krtn
= ocsp_client_certFetch(serverPort
, certURL
.Data
, (mach_msg_type_number_t
)certURL
.Length
,
214 (void **)&rtnData
, &rtnLen
);
216 if (krtn
== MACH_SEND_INVALID_DEST
)
217 OcspdGlobals().resetServerPort();
218 ocspdErrorLog("ocspdCertFetch: RPC returned %d\n", krtn
);
219 return CSSMERR_APPLETP_NETWORK_FAILURE
;
222 if((rtnData
== NULL
) || (rtnLen
== 0)) {
223 ocspdErrorLog("ocspdCertFetch: RPC returned NULL data\n");
224 return CSSMERR_APPLETP_CERT_NOT_FOUND_FROM_ISSUER
;
226 certData
.Data
= (uint8
*)alloc
.malloc(rtnLen
);
227 certData
.Length
= rtnLen
;
228 memmove(certData
.Data
, rtnData
, rtnLen
);
229 mig_deallocate((vm_address_t
)rtnData
, rtnLen
);
234 * Fetch a CRL from net with optional cache lookup and store.
235 * verifyTime only used for cache lookup.
237 CSSM_RETURN
ocspdCRLFetch(
239 const CSSM_DATA
&crlURL
,
240 const CSSM_DATA
*crlIssuer
, // optional
241 bool cacheReadEnable
,
242 bool cacheWriteEnable
,
243 CSSM_TIMESTRING verifyTime
,
244 CSSM_DATA
&crlData
) // mallocd via alloc and RETURNED
246 mach_port_t serverPort
= 0;
248 unsigned char *rtnData
= NULL
;
251 if(verifyTime
== NULL
) {
252 ocspdErrorLog("ocspdCRLFetch: verifyTime NOT OPTIONAL\n");
253 return CSSMERR_TP_INTERNAL_ERROR
;
256 serverPort
= OcspdGlobals().serverPort();
259 ocspdErrorLog("ocspdCRLFetch: OCSPD server error\n");
260 return CSSMERR_TP_INTERNAL_ERROR
;
263 krtn
= ocsp_client_crlFetch(serverPort
, crlURL
.Data
, (mach_msg_type_number_t
)crlURL
.Length
,
264 crlIssuer
? crlIssuer
->Data
: NULL
, crlIssuer
? (mach_msg_type_number_t
)crlIssuer
->Length
: 0,
265 cacheReadEnable
, cacheWriteEnable
,
266 verifyTime
, (mach_msg_type_number_t
)strlen(verifyTime
),
267 (void **)&rtnData
, &rtnLen
);
269 if (krtn
== MACH_SEND_INVALID_DEST
)
270 OcspdGlobals().resetServerPort();
271 ocspdErrorLog("ocspdCRLFetch: RPC returned %d\n", krtn
);
272 return CSSMERR_APPLETP_NETWORK_FAILURE
;
275 if((rtnData
== NULL
) || (rtnLen
== 0)) {
276 ocspdErrorLog("ocspdCRLFetch: RPC returned NULL data\n");
277 return CSSMERR_APPLETP_CRL_NOT_FOUND
;
279 crlData
.Data
= (uint8
*)alloc
.malloc(rtnLen
);
280 crlData
.Length
= rtnLen
;
281 memmove(crlData
.Data
, rtnData
, rtnLen
);
282 mig_deallocate((vm_address_t
)rtnData
, rtnLen
);
288 * Get CRL status for given serial number and issuing entity
290 CSSM_RETURN
ocspdCRLStatus(
291 const CSSM_DATA
&serialNumber
,
292 const CSSM_DATA
&issuers
,
293 const CSSM_DATA
*crlIssuer
, // optional if URL is supplied
294 const CSSM_DATA
*crlURL
) // optional if issuer is supplied
296 mach_port_t serverPort
= 0;
299 if(!crlIssuer
&& !crlURL
) {
300 ocspdErrorLog("ocspdCRLStatus: either an issuer or URL is required\n");
301 return CSSMERR_TP_INTERNAL_ERROR
;
304 serverPort
= OcspdGlobals().serverPort();
307 ocspdErrorLog("ocspdCRLStatus: OCSPD server error\n");
308 return CSSMERR_TP_INTERNAL_ERROR
;
311 krtn
= ocsp_client_crlStatus(serverPort
,
312 serialNumber
.Data
, (mach_msg_type_number_t
)serialNumber
.Length
,
313 issuers
.Data
, (mach_msg_type_number_t
)issuers
.Length
,
314 crlIssuer
? crlIssuer
->Data
: NULL
, crlIssuer
? (mach_msg_type_number_t
)crlIssuer
->Length
: 0,
315 crlURL
? crlURL
->Data
: NULL
, crlURL
? (mach_msg_type_number_t
)crlURL
->Length
: 0);
316 if (krtn
== MACH_SEND_INVALID_DEST
)
317 OcspdGlobals().resetServerPort();
323 * Refresh the CRL cache.
325 CSSM_RETURN
ocspdCRLRefresh(
327 unsigned expireOverlapSeconds
,
329 bool fullCryptoVerify
)
331 mach_port_t serverPort
= 0;
334 serverPort
= OcspdGlobals().serverPort();
337 ocspdErrorLog("ocspdCRLRefresh: OCSPD server error\n");
338 return CSSMERR_TP_INTERNAL_ERROR
;
341 krtn
= ocsp_client_crlRefresh(serverPort
, staleDays
, expireOverlapSeconds
,
342 purgeAll
, fullCryptoVerify
);
344 if (krtn
== MACH_SEND_INVALID_DEST
)
345 OcspdGlobals().resetServerPort();
346 ocspdErrorLog("ocspdCRLRefresh: RPC returned %d\n", krtn
);
347 return CSSMERR_APPLETP_NETWORK_FAILURE
;
354 * Flush all CRLs obtained from specified URL from cache. Called by client when
355 * *it* detects a bad CRL.
357 CSSM_RETURN
ocspdCRLFlush(
358 const CSSM_DATA
&crlURL
)
360 mach_port_t serverPort
= 0;
364 serverPort
= OcspdGlobals().serverPort();
367 ocspdErrorLog("ocspdCRLFlush: OCSPD server error\n");
368 return CSSMERR_TP_INTERNAL_ERROR
;
371 krtn
= ocsp_client_crlFlush(serverPort
, crlURL
.Data
, (mach_msg_type_number_t
)crlURL
.Length
);
373 if (krtn
== MACH_SEND_INVALID_DEST
)
374 OcspdGlobals().resetServerPort();
375 ocspdErrorLog("ocspdCRLFlush: RPC returned %d\n", krtn
);
376 return CSSMERR_APPLETP_NETWORK_FAILURE
;
382 * Obtain TrustSettings.
384 OSStatus
ocspdTrustSettingsRead(
386 SecTrustSettingsDomain domain
,
387 CSSM_DATA
&trustSettings
) // mallocd via alloc and RETURNED
389 mach_port_t serverPort
= 0;
391 unsigned char *rtnData
= NULL
;
396 serverPort
= OcspdGlobals().serverPort();
399 ocspdErrorLog("ocspdTrustSettingsRead: OCSPD server error\n");
400 return errSecInternalComponent
;
403 krtn
= ocsp_client_trustSettingsRead(serverPort
, domain
,
404 (void **)&rtnData
, &rtnLen
, &ortn
);
406 if (krtn
== MACH_SEND_INVALID_DEST
)
407 OcspdGlobals().resetServerPort();
408 ocspdErrorLog("ocspdTrustSettingsRead: RPC returned %d\n", krtn
);
409 return errSecNotAvailable
;
412 /* e.g., errSecNoUserTrustRecord */
415 if((rtnData
== NULL
) || (rtnLen
== 0)) {
416 ocspdErrorLog("ocspdTrustSettingsRead: RPC returned NULL data\n");
417 return errSecItemNotFound
;
419 trustSettings
.Data
= (uint8
*)alloc
.malloc(rtnLen
);
420 trustSettings
.Length
= rtnLen
;
421 memmove(trustSettings
.Data
, rtnData
, rtnLen
);
422 mig_deallocate((vm_address_t
)rtnData
, rtnLen
);
423 return errSecSuccess
;
427 * Write TrustSettings to disk. Results in authentication dialog.
429 OSStatus
ocspdTrustSettingsWrite(
430 SecTrustSettingsDomain domain
,
431 const CSSM_DATA
&authBlob
,
432 const CSSM_DATA
&trustSettings
)
434 mach_port_t serverPort
= 0;
435 mach_port_t clientPort
= 0;
440 serverPort
= OcspdGlobals().serverPort();
441 clientPort
= MachPlusPlus::Bootstrap();
444 ocspdErrorLog("ocspdTrustSettingsWrite: OCSPD server error\n");
445 return errSecInternalComponent
;
448 krtn
= ocsp_client_trustSettingsWrite(serverPort
, clientPort
, domain
,
449 authBlob
.Data
, (mach_msg_type_number_t
)authBlob
.Length
,
450 trustSettings
.Data
, (mach_msg_type_number_t
)trustSettings
.Length
,
453 if (krtn
== MACH_SEND_INVALID_DEST
)
454 OcspdGlobals().resetServerPort();
455 ocspdErrorLog("ocspdTrustSettingsWrite: RPC returned %d\n", krtn
);
456 return errSecInternalComponent
;