-/*
- * 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 <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 -----
-
-/* 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 <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 /* 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;
-}
-