2 * Copyright (c) 2002,2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
24 * ocspdClient.cpp - Client interface to OCSP helper daemon
27 #include "ocspdClient.h"
28 #include "ocspdTypes.h"
29 #include "ocspdDebug.h"
30 #include <Security/cssmapple.h>
31 #include <security_utilities/threading.h>
32 #include <security_utilities/mach++.h>
33 #include <security_utilities/unix++.h>
34 #include <security_ocspd/ocspd.h> /* MIG interface */
35 #include <Security/SecBase.h>
41 mach_port_t
serverPort();
43 UnixPlusPlus::ForkMonitor mForkMonitor
;
44 MachPlusPlus::Port mServerPort
;
48 ocspdGlobals::ocspdGlobals()
51 /* nothing here, the real work is done in serverPort() */
54 ocspdGlobals::~ocspdGlobals()
56 /* I don't believe this should ever execute */
59 mach_port_t
ocspdGlobals::serverPort()
61 StLock
<Mutex
> _(mLock
);
63 // Guard against fork-without-exec. If we are the child of a fork
64 // (that has not exec'ed), our apparent connection to SecurityServer
65 // is just a mirage, and we better reset it.
66 mach_port_t rtnPort
= mServerPort
.port();
74 const char *serverName
= NULL
;
76 serverName
= getenv(OCSPD_BOOTSTRAP_ENV
);
78 if(serverName
== NULL
) {
79 serverName
= (char*) OCSPD_BOOTSTRAP_NAME
;
82 mServerPort
= MachPlusPlus::Bootstrap().lookup2(serverName
);
85 ocspdErrorLog("ocspdGlobals: error contacting server\n");
91 static ModuleNexus
<ocspdGlobals
> OcspdGlobals
;
94 * Perform network fetch of an OCSP response. Result is not verified in any
97 CSSM_RETURN
ocspdFetch(
99 const CSSM_DATA
&ocspdReq
, // DER-encoded SecAsn1OCSPDRequests
100 CSSM_DATA
&ocspdResp
) // DER-encoded kSecAsn1OCSPDReplies
102 mach_port_t serverPort
= 0;
104 unsigned char *rtnData
= NULL
;
108 serverPort
= OcspdGlobals().serverPort();
111 ocspdErrorLog("ocspdFetch: OCSPD server error\n");
112 return CSSMERR_TP_INTERNAL_ERROR
;
115 krtn
= ocsp_client_ocspdFetch(serverPort
, ocspdReq
.Data
, (mach_msg_type_number_t
)ocspdReq
.Length
,
116 (void **)&rtnData
, &rtnLen
);
118 ocspdErrorLog("ocspdFetch: RPC returned %d\n", krtn
);
119 return CSSMERR_APPLETP_OCSP_UNAVAILABLE
;
121 if((rtnData
== NULL
) || (rtnLen
== 0)) {
122 ocspdErrorLog("ocspdFetch: RPC returned NULL data\n");
123 return CSSMERR_APPLETP_OCSP_UNAVAILABLE
;
125 ocspdResp
.Data
= (uint8
*)alloc
.malloc(rtnLen
);
126 ocspdResp
.Length
= rtnLen
;
127 memmove(ocspdResp
.Data
, rtnData
, rtnLen
);
128 mig_deallocate((vm_address_t
)rtnData
, rtnLen
);
133 * Flush all responses associated with specifed CertID from cache.
135 CSSM_RETURN
ocspdCacheFlush(
136 const CSSM_DATA
&certID
)
138 mach_port_t serverPort
= 0;
142 serverPort
= OcspdGlobals().serverPort();
145 ocspdErrorLog("ocspdCacheFlush: OCSPD server error\n");
146 return CSSMERR_TP_INTERNAL_ERROR
;
148 krtn
= ocsp_client_ocspdCacheFlush(serverPort
, certID
.Data
, (mach_msg_type_number_t
)certID
.Length
);
150 ocspdErrorLog("ocspdCacheFlush: RPC returned %d\n", krtn
);
151 return CSSMERR_APPLETP_OCSP_UNAVAILABLE
;
157 * Flush stale entries from cache.
159 CSSM_RETURN
ocspdCacheFlushStale()
161 mach_port_t serverPort
= 0;
165 serverPort
= OcspdGlobals().serverPort();
168 ocspdErrorLog("ocspdCacheFlush: OCSPD server error\n");
169 return CSSMERR_TP_INTERNAL_ERROR
;
171 krtn
= ocsp_client_ocspdCacheFlushStale(serverPort
);
173 ocspdErrorLog("ocsp_client_ocspdCacheFlushStale: RPC returned %d\n", krtn
);
174 return (CSSM_RETURN
)krtn
;
180 * fetch a certificate from the net.
182 CSSM_RETURN
ocspdCertFetch(
184 const CSSM_DATA
&certURL
,
185 CSSM_DATA
&certData
) // mallocd via alloc and RETURNED
187 mach_port_t serverPort
= 0;
189 unsigned char *rtnData
= NULL
;
193 serverPort
= OcspdGlobals().serverPort();
196 ocspdErrorLog("ocspdCertFetch: OCSPD server error\n");
197 return CSSMERR_TP_INTERNAL_ERROR
;
200 krtn
= ocsp_client_certFetch(serverPort
, certURL
.Data
, (mach_msg_type_number_t
)certURL
.Length
,
201 (void **)&rtnData
, &rtnLen
);
203 ocspdErrorLog("ocspdCertFetch: RPC returned %d\n", krtn
);
204 return CSSMERR_APPLETP_NETWORK_FAILURE
;
207 if((rtnData
== NULL
) || (rtnLen
== 0)) {
208 ocspdErrorLog("ocspdCertFetch: RPC returned NULL data\n");
209 return CSSMERR_APPLETP_CERT_NOT_FOUND_FROM_ISSUER
;
211 certData
.Data
= (uint8
*)alloc
.malloc(rtnLen
);
212 certData
.Length
= rtnLen
;
213 memmove(certData
.Data
, rtnData
, rtnLen
);
214 mig_deallocate((vm_address_t
)rtnData
, rtnLen
);
219 * Fetch a CRL from net with optional cache lookup and store.
220 * verifyTime only used for cache lookup.
222 CSSM_RETURN
ocspdCRLFetch(
224 const CSSM_DATA
&crlURL
,
225 const CSSM_DATA
*crlIssuer
, // optional
226 bool cacheReadEnable
,
227 bool cacheWriteEnable
,
228 CSSM_TIMESTRING verifyTime
,
229 CSSM_DATA
&crlData
) // mallocd via alloc and RETURNED
231 mach_port_t serverPort
= 0;
233 unsigned char *rtnData
= NULL
;
236 if(verifyTime
== NULL
) {
237 ocspdErrorLog("ocspdCRLFetch: verifyTime NOT OPTIONAL\n");
238 return CSSMERR_TP_INTERNAL_ERROR
;
241 serverPort
= OcspdGlobals().serverPort();
244 ocspdErrorLog("ocspdCRLFetch: OCSPD server error\n");
245 return CSSMERR_TP_INTERNAL_ERROR
;
248 krtn
= ocsp_client_crlFetch(serverPort
, crlURL
.Data
, (mach_msg_type_number_t
)crlURL
.Length
,
249 crlIssuer
? crlIssuer
->Data
: NULL
, crlIssuer
? (mach_msg_type_number_t
)crlIssuer
->Length
: 0,
250 cacheReadEnable
, cacheWriteEnable
,
251 verifyTime
, (mach_msg_type_number_t
)strlen(verifyTime
),
252 (void **)&rtnData
, &rtnLen
);
254 ocspdErrorLog("ocspdCRLFetch: RPC returned %d\n", krtn
);
255 return CSSMERR_APPLETP_NETWORK_FAILURE
;
258 if((rtnData
== NULL
) || (rtnLen
== 0)) {
259 ocspdErrorLog("ocspdCRLFetch: RPC returned NULL data\n");
260 return CSSMERR_APPLETP_CRL_NOT_FOUND
;
262 crlData
.Data
= (uint8
*)alloc
.malloc(rtnLen
);
263 crlData
.Length
= rtnLen
;
264 memmove(crlData
.Data
, rtnData
, rtnLen
);
265 mig_deallocate((vm_address_t
)rtnData
, rtnLen
);
271 * Get CRL status for given serial number and issuing entity
273 CSSM_RETURN
ocspdCRLStatus(
274 const CSSM_DATA
&serialNumber
,
275 const CSSM_DATA
&issuers
,
276 const CSSM_DATA
*crlIssuer
, // optional if URL is supplied
277 const CSSM_DATA
*crlURL
) // optional if issuer is supplied
279 mach_port_t serverPort
= 0;
282 if(!crlIssuer
&& !crlURL
) {
283 ocspdErrorLog("ocspdCRLStatus: either an issuer or URL is required\n");
284 return CSSMERR_TP_INTERNAL_ERROR
;
287 serverPort
= OcspdGlobals().serverPort();
290 ocspdErrorLog("ocspdCRLStatus: OCSPD server error\n");
291 return CSSMERR_TP_INTERNAL_ERROR
;
294 krtn
= ocsp_client_crlStatus(serverPort
,
295 serialNumber
.Data
, (mach_msg_type_number_t
)serialNumber
.Length
,
296 issuers
.Data
, (mach_msg_type_number_t
)issuers
.Length
,
297 crlIssuer
? crlIssuer
->Data
: NULL
, crlIssuer
? (mach_msg_type_number_t
)crlIssuer
->Length
: 0,
298 crlURL
? crlURL
->Data
: NULL
, crlURL
? (mach_msg_type_number_t
)crlURL
->Length
: 0);
304 * Refresh the CRL cache.
306 CSSM_RETURN
ocspdCRLRefresh(
308 unsigned expireOverlapSeconds
,
310 bool fullCryptoVerify
)
312 mach_port_t serverPort
= 0;
315 serverPort
= OcspdGlobals().serverPort();
318 ocspdErrorLog("ocspdCRLRefresh: OCSPD server error\n");
319 return CSSMERR_TP_INTERNAL_ERROR
;
322 krtn
= ocsp_client_crlRefresh(serverPort
, staleDays
, expireOverlapSeconds
,
323 purgeAll
, fullCryptoVerify
);
325 ocspdErrorLog("ocspdCRLRefresh: RPC returned %d\n", krtn
);
326 return CSSMERR_APPLETP_NETWORK_FAILURE
;
333 * Flush all CRLs obtained from specified URL from cache. Called by client when
334 * *it* detects a bad CRL.
336 CSSM_RETURN
ocspdCRLFlush(
337 const CSSM_DATA
&crlURL
)
339 mach_port_t serverPort
= 0;
343 serverPort
= OcspdGlobals().serverPort();
346 ocspdErrorLog("ocspdCRLFlush: OCSPD server error\n");
347 return CSSMERR_TP_INTERNAL_ERROR
;
350 krtn
= ocsp_client_crlFlush(serverPort
, crlURL
.Data
, (mach_msg_type_number_t
)crlURL
.Length
);
352 ocspdErrorLog("ocspdCRLFlush: RPC returned %d\n", krtn
);
353 return CSSMERR_APPLETP_NETWORK_FAILURE
;
359 * Obtain TrustSettings.
361 OSStatus
ocspdTrustSettingsRead(
363 SecTrustSettingsDomain domain
,
364 CSSM_DATA
&trustSettings
) // mallocd via alloc and RETURNED
366 mach_port_t serverPort
= 0;
368 unsigned char *rtnData
= NULL
;
373 serverPort
= OcspdGlobals().serverPort();
376 ocspdErrorLog("ocspdTrustSettingsRead: OCSPD server error\n");
377 return errSecInternalComponent
;
380 krtn
= ocsp_client_trustSettingsRead(serverPort
, domain
,
381 (void **)&rtnData
, &rtnLen
, &ortn
);
383 ocspdErrorLog("ocspdTrustSettingsRead: RPC returned %d\n", krtn
);
384 return errSecNotAvailable
;
387 /* e.g., errSecNoUserTrustRecord */
390 if((rtnData
== NULL
) || (rtnLen
== 0)) {
391 ocspdErrorLog("ocspdTrustSettingsRead: RPC returned NULL data\n");
392 return errSecItemNotFound
;
394 trustSettings
.Data
= (uint8
*)alloc
.malloc(rtnLen
);
395 trustSettings
.Length
= rtnLen
;
396 memmove(trustSettings
.Data
, rtnData
, rtnLen
);
397 mig_deallocate((vm_address_t
)rtnData
, rtnLen
);
398 return errSecSuccess
;
402 * Write TrustSettings to disk. Results in authentication dialog.
404 OSStatus
ocspdTrustSettingsWrite(
405 SecTrustSettingsDomain domain
,
406 const CSSM_DATA
&authBlob
,
407 const CSSM_DATA
&trustSettings
)
409 mach_port_t serverPort
= 0;
410 mach_port_t clientPort
= 0;
415 serverPort
= OcspdGlobals().serverPort();
416 clientPort
= MachPlusPlus::Bootstrap();
419 ocspdErrorLog("ocspdTrustSettingsWrite: OCSPD server error\n");
420 return errSecInternalComponent
;
423 krtn
= ocsp_client_trustSettingsWrite(serverPort
, clientPort
, domain
,
424 authBlob
.Data
, (mach_msg_type_number_t
)authBlob
.Length
,
425 trustSettings
.Data
, (mach_msg_type_number_t
)trustSettings
.Length
,
428 ocspdErrorLog("ocspdTrustSettingsWrite: RPC returned %d\n", krtn
);
429 return errSecInternalComponent
;