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