2 * Copyright (c) 2000,2002,2005-2006 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 * ocspdNetwork.cpp - Network support for ocspd and CRL/cert fetch
27 #include <security_ocspd/ocspdDebug.h>
28 #include "ocspNetwork.h"
29 #include <security_ocspd/ocspdUtils.h>
30 #include <CoreFoundation/CoreFoundation.h>
31 #include <CoreServices/CoreServices.h>
32 #include <security_cdsa_utils/cuEnc64.h>
34 #include <Security/cssmapple.h>
35 #include <LDAP/ldap.h>
37 #pragma mark ----- OCSP support -----
39 /* POST method has Content-Type header line equal to "application/ocsp-request" */
40 static CFStringRef kContentType
= CFSTR("Content-Type");
41 static CFStringRef kAppOcspRequest
= CFSTR("application/ocsp-request");
49 #define OCSP_GET_FILE "/tmp/ocspGet"
50 #define OCSP_RESP_FILE "/tmp/ocspResp"
54 #include <security_cdsa_utils/cuFileIo.h>
56 static void writeBlob(
59 const unsigned char *data
,
62 if(writeFile(fileName
, data
, dataLen
)) {
63 printf("***Error writing %s to %s\n", whatIsIt
, fileName
);
66 printf("...wrote %u bytes of %s to %s\n", dataLen
, whatIsIt
, fileName
);
72 #define writeBlob(f,w,d,l)
74 #endif /* DUMP_BLOBS */
76 /* fetch via HTTP POST */
78 #define POST_BUFSIZE 1024
80 CSSM_RETURN
ocspdHttpPost(
81 SecAsn1CoderRef coder
,
83 const CSSM_DATA
&ocspReq
, // DER encoded
84 CSSM_DATA
&fetched
) // mallocd in coder space and RETURNED
86 CSSM_RETURN ourRtn
= CSSM_OK
;
88 UInt8 inBuf
[POST_BUFSIZE
];
89 /* resources to release on exit */
90 CFMutableDataRef inData
= NULL
;
91 CFReadStreamRef cfStream
= NULL
;
92 CFHTTPMessageRef request
= NULL
;
93 CFDataRef postData
= NULL
;
94 CFURLRef cfUrl
= NULL
;
96 /* trim off possible NULL terminator from incoming URL */
97 uint32 urlLen
= url
.Length
;
98 if(url
.Data
[urlLen
- 1] == '\0') {
102 cfUrl
= CFURLCreateWithBytes(NULL
,
104 kCFStringEncodingUTF8
, // right?
105 NULL
); // this is absolute path
107 ocspdErrorLog("CFURLCreateWithBytes returned NULL\n");
109 return CSSMERR_APPLETP_CRL_BAD_URI
;
111 /* subsequent errors to errOut: */
115 char *ustr
= (char *)malloc(urlLen
+ 1);
116 memmove(ustr
, url
.Data
, urlLen
);
118 ocspdDebug("ocspdHttpPost: posting to URI %s", ustr
);
123 writeBlob(OCSP_GET_FILE
, "OCSP Request as POST data", ocspReq
.Data
, ocspReq
.Length
);
124 postData
= CFDataCreate(NULL
, ocspReq
.Data
, ocspReq
.Length
);
126 /* Create a new HTTP request. */
127 request
= CFHTTPMessageCreateRequest(kCFAllocatorDefault
, CFSTR("POST"), cfUrl
,
129 if (request
== NULL
) {
130 ocspdErrorLog("ocspdHttpPost: error creating CFHTTPMessage\n");
131 ourRtn
= CSSMERR_TP_INTERNAL_ERROR
;
135 // Set the body and required header fields.
136 CFHTTPMessageSetBody(request
, postData
);
137 CFHTTPMessageSetHeaderFieldValue(request
, kContentType
, kAppOcspRequest
);
139 // Create the stream for the request.
140 cfStream
= CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault
, request
);
141 if (cfStream
== NULL
) {
142 ocspdErrorLog("ocspdHttpPost: error creating CFReadStream\n");
143 ourRtn
= CSSMERR_TP_INTERNAL_ERROR
;
147 /* go, synchronously */
148 if(!CFReadStreamOpen(cfStream
)) {
149 ocspdErrorLog("ocspdHttpPost: error opening CFReadStream\n");
150 ourRtn
= CSSMERR_TP_INTERNAL_ERROR
;
153 inData
= CFDataCreateMutable(NULL
, 0);
155 thisMove
= CFReadStreamRead(cfStream
, inBuf
, POST_BUFSIZE
);
157 CFStreamError error
= CFReadStreamGetError(cfStream
);
158 ocspdErrorLog("ocspdHttpPost: error on CFReadStreamRead: domain "
159 "%ld error %ld\n", (long)error
.domain
, (long)error
.error
);
160 ourRtn
= CSSMERR_APPLETP_NETWORK_FAILURE
;
163 else if(thisMove
== 0) {
164 ocspdDebug("ocspdHttpPost: transfer complete, moved %ld bytes",
165 CFDataGetLength(inData
));
170 CFDataAppendBytes(inData
, inBuf
, thisMove
);
173 if(ourRtn
== CSSM_OK
) {
174 SecAsn1AllocCopy(coder
, CFDataGetBytePtr(inData
), CFDataGetLength(inData
),
176 writeBlob(OCSP_RESP_FILE
, "OCSP Response", fetched
.Data
, fetched
.Length
);