]> git.saurik.com Git - apple/security.git/blob - libsecurity_ocspd/client/ocspdClient.cpp
Security-55471.14.18.tar.gz
[apple/security.git] / libsecurity_ocspd / client / ocspdClient.cpp
1 /*
2 * Copyright (c) 2002,2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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.
11 *
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
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22
23 /*
24 * ocspdClient.cpp - Client interface to OCSP helper daemon
25 */
26
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>
36 class ocspdGlobals
37 {
38 public:
39 ocspdGlobals();
40 ~ocspdGlobals();
41 mach_port_t serverPort();
42 private:
43 UnixPlusPlus::ForkMonitor mForkMonitor;
44 MachPlusPlus::Port mServerPort;
45 Mutex mLock;
46 };
47
48 ocspdGlobals::ocspdGlobals()
49 : mServerPort(0)
50 {
51 /* nothing here, the real work is done in serverPort() */
52 }
53
54 ocspdGlobals::~ocspdGlobals()
55 {
56 /* I don't believe this should ever execute */
57 }
58
59 mach_port_t ocspdGlobals::serverPort()
60 {
61 StLock<Mutex> _(mLock);
62
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();
67 if (mForkMonitor()) {
68 rtnPort = 0;
69 }
70 if(rtnPort != 0) {
71 return rtnPort;
72 }
73
74 const char *serverName = NULL;
75 #ifndef NDEBUG
76 serverName = getenv(OCSPD_BOOTSTRAP_ENV);
77 #endif
78 if(serverName == NULL) {
79 serverName = (char*) OCSPD_BOOTSTRAP_NAME;
80 }
81 try {
82 mServerPort = MachPlusPlus::Bootstrap().lookup2(serverName);
83 }
84 catch(...) {
85 ocspdErrorLog("ocspdGlobals: error contacting server\n");
86 throw;
87 }
88 return mServerPort;
89 }
90
91 static ModuleNexus<ocspdGlobals> OcspdGlobals;
92
93 /*
94 * Perform network fetch of an OCSP response. Result is not verified in any
95 * way.
96 */
97 CSSM_RETURN ocspdFetch(
98 Allocator &alloc,
99 const CSSM_DATA &ocspdReq, // DER-encoded SecAsn1OCSPDRequests
100 CSSM_DATA &ocspdResp) // DER-encoded kSecAsn1OCSPDReplies
101 {
102 mach_port_t serverPort = 0;
103 kern_return_t krtn;
104 unsigned char *rtnData = NULL;
105 unsigned rtnLen = 0;
106
107 try {
108 serverPort = OcspdGlobals().serverPort();
109 }
110 catch(...) {
111 ocspdErrorLog("ocspdFetch: OCSPD server error\n");
112 return CSSMERR_TP_INTERNAL_ERROR;
113 }
114
115 krtn = ocsp_client_ocspdFetch(serverPort, ocspdReq.Data, (mach_msg_type_number_t)ocspdReq.Length,
116 (void **)&rtnData, &rtnLen);
117 if(krtn) {
118 ocspdErrorLog("ocspdFetch: RPC returned %d\n", krtn);
119 return CSSMERR_APPLETP_OCSP_UNAVAILABLE;
120 }
121 if((rtnData == NULL) || (rtnLen == 0)) {
122 ocspdErrorLog("ocspdFetch: RPC returned NULL data\n");
123 return CSSMERR_APPLETP_OCSP_UNAVAILABLE;
124 }
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);
129 return CSSM_OK;
130 }
131
132 /*
133 * Flush all responses associated with specifed CertID from cache.
134 */
135 CSSM_RETURN ocspdCacheFlush(
136 const CSSM_DATA &certID)
137 {
138 mach_port_t serverPort = 0;
139 kern_return_t krtn;
140
141 try {
142 serverPort = OcspdGlobals().serverPort();
143 }
144 catch(...) {
145 ocspdErrorLog("ocspdCacheFlush: OCSPD server error\n");
146 return CSSMERR_TP_INTERNAL_ERROR;
147 }
148 krtn = ocsp_client_ocspdCacheFlush(serverPort, certID.Data, (mach_msg_type_number_t)certID.Length);
149 if(krtn) {
150 ocspdErrorLog("ocspdCacheFlush: RPC returned %d\n", krtn);
151 return CSSMERR_APPLETP_OCSP_UNAVAILABLE;
152 }
153 return CSSM_OK;
154 }
155
156 /*
157 * Flush stale entries from cache.
158 */
159 CSSM_RETURN ocspdCacheFlushStale()
160 {
161 mach_port_t serverPort = 0;
162 kern_return_t krtn;
163
164 try {
165 serverPort = OcspdGlobals().serverPort();
166 }
167 catch(...) {
168 ocspdErrorLog("ocspdCacheFlush: OCSPD server error\n");
169 return CSSMERR_TP_INTERNAL_ERROR;
170 }
171 krtn = ocsp_client_ocspdCacheFlushStale(serverPort);
172 if(krtn) {
173 ocspdErrorLog("ocsp_client_ocspdCacheFlushStale: RPC returned %d\n", krtn);
174 return (CSSM_RETURN)krtn;
175 }
176 return CSSM_OK;
177 }
178
179 /*
180 * fetch a certificate from the net.
181 */
182 CSSM_RETURN ocspdCertFetch(
183 Allocator &alloc,
184 const CSSM_DATA &certURL,
185 CSSM_DATA &certData) // mallocd via alloc and RETURNED
186 {
187 mach_port_t serverPort = 0;
188 kern_return_t krtn;
189 unsigned char *rtnData = NULL;
190 unsigned rtnLen = 0;
191
192 try {
193 serverPort = OcspdGlobals().serverPort();
194 }
195 catch(...) {
196 ocspdErrorLog("ocspdCertFetch: OCSPD server error\n");
197 return CSSMERR_TP_INTERNAL_ERROR;
198 }
199
200 krtn = ocsp_client_certFetch(serverPort, certURL.Data, (mach_msg_type_number_t)certURL.Length,
201 (void **)&rtnData, &rtnLen);
202 if(krtn) {
203 ocspdErrorLog("ocspdCertFetch: RPC returned %d\n", krtn);
204 return CSSMERR_APPLETP_NETWORK_FAILURE;
205 }
206
207 if((rtnData == NULL) || (rtnLen == 0)) {
208 ocspdErrorLog("ocspdCertFetch: RPC returned NULL data\n");
209 return CSSMERR_APPLETP_CERT_NOT_FOUND_FROM_ISSUER;
210 }
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);
215 return CSSM_OK;
216 }
217
218 /*
219 * Fetch a CRL from net with optional cache lookup and store.
220 * verifyTime only used for cache lookup.
221 */
222 CSSM_RETURN ocspdCRLFetch(
223 Allocator &alloc,
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
230 {
231 mach_port_t serverPort = 0;
232 kern_return_t krtn;
233 unsigned char *rtnData = NULL;
234 unsigned rtnLen = 0;
235
236 if(verifyTime == NULL) {
237 ocspdErrorLog("ocspdCRLFetch: verifyTime NOT OPTIONAL\n");
238 return CSSMERR_TP_INTERNAL_ERROR;
239 }
240 try {
241 serverPort = OcspdGlobals().serverPort();
242 }
243 catch(...) {
244 ocspdErrorLog("ocspdCRLFetch: OCSPD server error\n");
245 return CSSMERR_TP_INTERNAL_ERROR;
246 }
247
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);
253 if(krtn) {
254 ocspdErrorLog("ocspdCRLFetch: RPC returned %d\n", krtn);
255 return CSSMERR_APPLETP_NETWORK_FAILURE;
256 }
257
258 if((rtnData == NULL) || (rtnLen == 0)) {
259 ocspdErrorLog("ocspdCRLFetch: RPC returned NULL data\n");
260 return CSSMERR_APPLETP_CRL_NOT_FOUND;
261 }
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);
266 return CSSM_OK;
267 }
268
269
270 /*
271 * Get CRL status for given serial number and issuing entity
272 */
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
278 {
279 mach_port_t serverPort = 0;
280 kern_return_t krtn;
281
282 if(!crlIssuer && !crlURL) {
283 ocspdErrorLog("ocspdCRLStatus: either an issuer or URL is required\n");
284 return CSSMERR_TP_INTERNAL_ERROR;
285 }
286 try {
287 serverPort = OcspdGlobals().serverPort();
288 }
289 catch(...) {
290 ocspdErrorLog("ocspdCRLStatus: OCSPD server error\n");
291 return CSSMERR_TP_INTERNAL_ERROR;
292 }
293
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);
299
300 return krtn;
301 }
302
303 /*
304 * Refresh the CRL cache.
305 */
306 CSSM_RETURN ocspdCRLRefresh(
307 unsigned staleDays,
308 unsigned expireOverlapSeconds,
309 bool purgeAll,
310 bool fullCryptoVerify)
311 {
312 mach_port_t serverPort = 0;
313 kern_return_t krtn;
314 try {
315 serverPort = OcspdGlobals().serverPort();
316 }
317 catch(...) {
318 ocspdErrorLog("ocspdCRLRefresh: OCSPD server error\n");
319 return CSSMERR_TP_INTERNAL_ERROR;
320 }
321
322 krtn = ocsp_client_crlRefresh(serverPort, staleDays, expireOverlapSeconds,
323 purgeAll, fullCryptoVerify);
324 if(krtn) {
325 ocspdErrorLog("ocspdCRLRefresh: RPC returned %d\n", krtn);
326 return CSSMERR_APPLETP_NETWORK_FAILURE;
327 }
328
329 return CSSM_OK;
330 }
331
332 /*
333 * Flush all CRLs obtained from specified URL from cache. Called by client when
334 * *it* detects a bad CRL.
335 */
336 CSSM_RETURN ocspdCRLFlush(
337 const CSSM_DATA &crlURL)
338 {
339 mach_port_t serverPort = 0;
340 kern_return_t krtn;
341
342 try {
343 serverPort = OcspdGlobals().serverPort();
344 }
345 catch(...) {
346 ocspdErrorLog("ocspdCRLFlush: OCSPD server error\n");
347 return CSSMERR_TP_INTERNAL_ERROR;
348 }
349
350 krtn = ocsp_client_crlFlush(serverPort, crlURL.Data, (mach_msg_type_number_t)crlURL.Length);
351 if(krtn) {
352 ocspdErrorLog("ocspdCRLFlush: RPC returned %d\n", krtn);
353 return CSSMERR_APPLETP_NETWORK_FAILURE;
354 }
355 return CSSM_OK;
356 }
357
358 /*
359 * Obtain TrustSettings.
360 */
361 OSStatus ocspdTrustSettingsRead(
362 Allocator &alloc,
363 SecTrustSettingsDomain domain,
364 CSSM_DATA &trustSettings) // mallocd via alloc and RETURNED
365 {
366 mach_port_t serverPort = 0;
367 kern_return_t krtn;
368 unsigned char *rtnData = NULL;
369 unsigned rtnLen = 0;
370 OSStatus ortn;
371
372 try {
373 serverPort = OcspdGlobals().serverPort();
374 }
375 catch(...) {
376 ocspdErrorLog("ocspdTrustSettingsRead: OCSPD server error\n");
377 return errSecInternalComponent;
378 }
379
380 krtn = ocsp_client_trustSettingsRead(serverPort, domain,
381 (void **)&rtnData, &rtnLen, &ortn);
382 if(krtn) {
383 ocspdErrorLog("ocspdTrustSettingsRead: RPC returned %d\n", krtn);
384 return errSecNotAvailable;
385 }
386 if(ortn) {
387 /* e.g., errSecNoUserTrustRecord */
388 return ortn;
389 }
390 if((rtnData == NULL) || (rtnLen == 0)) {
391 ocspdErrorLog("ocspdTrustSettingsRead: RPC returned NULL data\n");
392 return errSecItemNotFound;
393 }
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;
399 }
400
401 /*
402 * Write TrustSettings to disk. Results in authentication dialog.
403 */
404 OSStatus ocspdTrustSettingsWrite(
405 SecTrustSettingsDomain domain,
406 const CSSM_DATA &authBlob,
407 const CSSM_DATA &trustSettings)
408 {
409 mach_port_t serverPort = 0;
410 mach_port_t clientPort = 0;
411 kern_return_t krtn;
412 OSStatus ortn;
413
414 try {
415 serverPort = OcspdGlobals().serverPort();
416 clientPort = MachPlusPlus::Bootstrap();
417 }
418 catch(...) {
419 ocspdErrorLog("ocspdTrustSettingsWrite: OCSPD server error\n");
420 return errSecInternalComponent;
421 }
422
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,
426 &ortn);
427 if(krtn) {
428 ocspdErrorLog("ocspdTrustSettingsWrite: RPC returned %d\n", krtn);
429 return errSecInternalComponent;
430 }
431 return ortn;
432 }