#include <security_ocspd/ocspdDebug.h>
#include "ocspNetwork.h"
#include <security_ocspd/ocspdUtils.h>
#include <CoreFoundation/CoreFoundation.h>
#include <CoreServices/CoreServices.h>
#include <security_cdsa_utils/cuEnc64.h>
#include <stdlib.h>
#include <Security/cssmapple.h>
#include <LDAP/ldap.h>
#pragma mark ----- OCSP support -----
static CFStringRef kContentType = CFSTR("Content-Type");
static CFStringRef kAppOcspRequest = CFSTR("application/ocsp-request");
#ifndef NDEBUG
#define DUMP_BLOBS 0
#else
#define DUMP_BLOBS 0
#endif
#define OCSP_GET_FILE "/tmp/ocspGet"
#define OCSP_RESP_FILE "/tmp/ocspResp"
#if DUMP_BLOBS
#include <security_cdsa_utils/cuFileIo.h>
static void writeBlob(
const char *fileName,
const char *whatIsIt,
const unsigned char *data,
unsigned dataLen)
{
if(writeFile(fileName, data, dataLen)) {
printf("***Error writing %s to %s\n", whatIsIt, fileName);
}
else {
printf("...wrote %u bytes of %s to %s\n", dataLen, whatIsIt, fileName);
}
}
#else
#define writeBlob(f,w,d,l)
#endif
#define POST_BUFSIZE 1024
CSSM_RETURN ocspdHttpPost(
SecAsn1CoderRef coder,
const CSSM_DATA &url,
const CSSM_DATA &ocspReq, CSSM_DATA &fetched) {
CSSM_RETURN ourRtn = CSSM_OK;
CFIndex thisMove;
UInt8 inBuf[POST_BUFSIZE];
CFMutableDataRef inData = NULL;
CFReadStreamRef cfStream = NULL;
CFHTTPMessageRef request = NULL;
CFDataRef postData = NULL;
CFURLRef cfUrl = NULL;
uint32 urlLen = url.Length;
if(url.Data[urlLen - 1] == '\0') {
urlLen--;
}
cfUrl = CFURLCreateWithBytes(NULL,
url.Data, urlLen,
kCFStringEncodingUTF8, NULL); if(cfUrl == NULL) {
ocspdErrorLog("CFURLCreateWithBytes returned NULL\n");
return CSSMERR_APPLETP_CRL_BAD_URI;
}
#ifndef NDEBUG
{
char *ustr = (char *)malloc(urlLen + 1);
memmove(ustr, url.Data, urlLen);
ustr[urlLen] = '\0';
ocspdDebug("ocspdHttpPost: posting to URI %s", ustr);
free(ustr);
}
#endif
writeBlob(OCSP_GET_FILE, "OCSP Request as POST data", ocspReq.Data, ocspReq.Length);
postData = CFDataCreate(NULL, ocspReq.Data, ocspReq.Length);
request = CFHTTPMessageCreateRequest(kCFAllocatorDefault, CFSTR("POST"), cfUrl,
kCFHTTPVersion1_1);
if (request == NULL) {
ocspdErrorLog("ocspdHttpPost: error creating CFHTTPMessage\n");
ourRtn = CSSMERR_TP_INTERNAL_ERROR;
goto errOut;
}
CFHTTPMessageSetBody(request, postData);
CFHTTPMessageSetHeaderFieldValue(request, kContentType, kAppOcspRequest);
cfStream = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, request);
if (cfStream == NULL) {
ocspdErrorLog("ocspdHttpPost: error creating CFReadStream\n");
ourRtn = CSSMERR_TP_INTERNAL_ERROR;
goto errOut;
}
if(!CFReadStreamOpen(cfStream)) {
ocspdErrorLog("ocspdHttpPost: error opening CFReadStream\n");
ourRtn = CSSMERR_TP_INTERNAL_ERROR;
goto errOut;
}
inData = CFDataCreateMutable(NULL, 0);
for(;;) {
thisMove = CFReadStreamRead(cfStream, inBuf, POST_BUFSIZE);
if(thisMove < 0) {
CFStreamError error = CFReadStreamGetError(cfStream);
ocspdErrorLog("ocspdHttpPost: error on CFReadStreamRead: domain "
"%ld error %ld\n", (long)error.domain, (long)error.error);
ourRtn = CSSMERR_APPLETP_NETWORK_FAILURE;
break;
}
else if(thisMove == 0) {
ocspdDebug("ocspdHttpPost: transfer complete, moved %ld bytes",
CFDataGetLength(inData));
ourRtn = CSSM_OK;
break;
}
else {
CFDataAppendBytes(inData, inBuf, thisMove);
}
}
if(ourRtn == CSSM_OK) {
SecAsn1AllocCopy(coder, CFDataGetBytePtr(inData), CFDataGetLength(inData),
&fetched);
writeBlob(OCSP_RESP_FILE, "OCSP Response", fetched.Data, fetched.Length);
}
errOut:
CFRELEASE(inData);
CFRELEASE(cfStream);
CFRELEASE(request);
CFRELEASE(postData);
CFRELEASE(cfUrl);
return ourRtn;
}