X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/SecurityTests/clxutils/ocspTool/ocspNetwork.cpp diff --git a/SecurityTests/clxutils/ocspTool/ocspNetwork.cpp b/SecurityTests/clxutils/ocspTool/ocspNetwork.cpp new file mode 100644 index 00000000..75870957 --- /dev/null +++ b/SecurityTests/clxutils/ocspTool/ocspNetwork.cpp @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2000,2002,2005-2006 Apple Computer, Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + * ocspdNetwork.cpp - Network support for ocspd and CRL/cert fetch + */ + +#include +#include "ocspNetwork.h" +#include +#include +#include +#include +#include +#include +#include + +#pragma mark ----- OCSP support ----- + +/* POST method has Content-Type header line equal to "application/ocsp-request" */ +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 + +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 /* DUMP_BLOBS */ + +/* fetch via HTTP POST */ + +#define POST_BUFSIZE 1024 + +CSSM_RETURN ocspdHttpPost( + SecAsn1CoderRef coder, + const CSSM_DATA &url, + const CSSM_DATA &ocspReq, // DER encoded + CSSM_DATA &fetched) // mallocd in coder space and RETURNED +{ + CSSM_RETURN ourRtn = CSSM_OK; + CFIndex thisMove; + UInt8 inBuf[POST_BUFSIZE]; + /* resources to release on exit */ + CFMutableDataRef inData = NULL; + CFReadStreamRef cfStream = NULL; + CFHTTPMessageRef request = NULL; + CFDataRef postData = NULL; + CFURLRef cfUrl = NULL; + + /* trim off possible NULL terminator from incoming URL */ + uint32 urlLen = url.Length; + if(url.Data[urlLen - 1] == '\0') { + urlLen--; + } + + cfUrl = CFURLCreateWithBytes(NULL, + url.Data, urlLen, + kCFStringEncodingUTF8, // right? + NULL); // this is absolute path + if(cfUrl == NULL) { + ocspdErrorLog("CFURLCreateWithBytes returned NULL\n"); + /* FIXME..? */ + return CSSMERR_APPLETP_CRL_BAD_URI; + } + /* subsequent errors to errOut: */ + + #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); + + /* Create a new HTTP request. */ + request = CFHTTPMessageCreateRequest(kCFAllocatorDefault, CFSTR("POST"), cfUrl, + kCFHTTPVersion1_1); + if (request == NULL) { + ocspdErrorLog("ocspdHttpPost: error creating CFHTTPMessage\n"); + ourRtn = CSSMERR_TP_INTERNAL_ERROR; + goto errOut; + } + + // Set the body and required header fields. + CFHTTPMessageSetBody(request, postData); + CFHTTPMessageSetHeaderFieldValue(request, kContentType, kAppOcspRequest); + + // Create the stream for the request. + cfStream = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, request); + if (cfStream == NULL) { + ocspdErrorLog("ocspdHttpPost: error creating CFReadStream\n"); + ourRtn = CSSMERR_TP_INTERNAL_ERROR; + goto errOut; + } + + /* go, synchronously */ + 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; +} +