static bool SecCAIssuerRequestIssue(SecCAIssuerRequestRef request) { while (request->issuerIX < CFArrayGetCount(request->issuers)) { CFURLRef issuer = CFArrayGetValueAtIndex(request->issuers, request->issuerIX++); CFStringRef scheme = CFURLCopyScheme(issuer); if (scheme) { if (CFEqual(CFSTR("http"), scheme)) { CFHTTPMessageRef msg = CFHTTPMessageCreateRequest(kCFAllocatorDefault, CFSTR("GET"), issuer, kCFHTTPVersion1_1); if (msg) { secdebug("caissuer", "%@", msg); bool done = asynchttp_request(msg, &request->http); CFRelease(msg); if (done == false) { CFRelease(scheme); return done; } } secdebug("caissuer", "failed to get %@", issuer); } else { secdebug("caissuer", "skipping unsupported uri %@", issuer); } CFRelease(scheme); } } /* No more issuers left to try, we're done. */ secdebug("caissuer", "no request issued"); request->callback(request->context, NULL); SecCAIssuerRequestRelease(request); return true; }
bool HTTPInputSource::Open(CFErrorRef *error) { if(IsOpen()) { LOGGER_WARNING("org.sbooth.AudioEngine.InputSource.HTTP", "Open() called on an InputSource that is already open"); return true; } // Set up the HTTP request mRequest = CFHTTPMessageCreateRequest(kCFAllocatorDefault, CFSTR("GET"), mURL, kCFHTTPVersion1_1); if(NULL == mRequest) { if(error) *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, ENOMEM, NULL); return false; } CFHTTPMessageSetHeaderFieldValue(mRequest, CFSTR("User-Agent"), CFSTR("SFBAudioEngine")); // Seek support if(0 < mDesiredOffset) { CFStringRef byteRange = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("bytes=%ld-"), mDesiredOffset); CFHTTPMessageSetHeaderFieldValue(mRequest, CFSTR("Range"), byteRange); CFRelease(byteRange), byteRange = NULL; } mReadStream = CFReadStreamCreateForStreamedHTTPRequest(kCFAllocatorDefault, mRequest, NULL); if(NULL == mReadStream) { CFRelease(mRequest), mRequest = NULL; if(error) *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, ENOMEM, NULL); return false; } // Start the HTTP connection CFStreamClientContext myContext = { 0, this, NULL, NULL, NULL }; CFOptionFlags clientFlags = kCFStreamEventOpenCompleted | kCFStreamEventHasBytesAvailable | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered; if(!CFReadStreamSetClient(mReadStream, clientFlags, myCFReadStreamClientCallBack, &myContext)) { CFRelease(mRequest), mRequest = NULL; CFRelease(mReadStream), mReadStream = NULL; if(error) *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, ENOMEM, NULL); return false; } CFReadStreamScheduleWithRunLoop(mReadStream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); if(!CFReadStreamOpen(mReadStream)) { CFRelease(mRequest), mRequest = NULL; CFRelease(mReadStream), mReadStream = NULL; if(error) *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, ENOMEM, NULL); return false; } while(NULL == mResponseHeaders) CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true); mIsOpen = true; return true; }
static void FetchIPAddress() { if(publicIPState == IPStateFetching) return; publicIPState = IPStateFetching; const UInt8 bodyBytes[] = {0}; CFDataRef body = CFDataCreate(kCFAllocatorDefault, bodyBytes, 0); CFURLRef url = CFURLCreateWithString(kCFAllocatorDefault, CFSTR("http://icanhazip.com"), NULL); CFHTTPMessageRef request = CFHTTPMessageCreateRequest(kCFAllocatorDefault, CFSTR("GET"), url, kCFHTTPVersion1_1); CFHTTPMessageSetBody(request, body); #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" // Apple suggests the NSURLSession API instead of CFReadStreamCreateForHTTPRequest, // But obviously that doesn't really work here CFReadStreamRef stream = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, request); #pragma clang diagnostic pop CFRelease(body); CFRelease(url); CFRelease(request); CFMutableDataRef responseData = CFDataCreateMutable(kCFAllocatorDefault, 17); CFStreamClientContext context = { 0, responseData, NULL, NULL, NULL }; if(!CFReadStreamSetClient(stream, kCFStreamEventOpenCompleted | kCFStreamEventHasBytesAvailable | kCFStreamEventEndEncountered | kCFStreamEventErrorOccurred, &IPStreamCallback, &context)) { CFRelease(stream); publicIPState = IPStateInvalid; return; } // Add to the run loop and open the stream CFReadStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); if(!CFReadStreamOpen(stream)) { CFReadStreamSetClient(stream, 0, NULL, NULL); CFReadStreamUnscheduleFromRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); CFRelease(stream); publicIPState = IPStateInvalid; return; } // Run the run loop do { CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1.0, TRUE); } while(publicIPState == IPStateFetching); }
CFReadStreamRef HTTP_Stream::createReadStream(CFURLRef url) { CFReadStreamRef readStream = 0; CFHTTPMessageRef request = 0; CFDictionaryRef proxySettings = 0; Stream_Configuration *config = Stream_Configuration::configuration(); if (!(request = CFHTTPMessageCreateRequest(kCFAllocatorDefault, httpRequestMethod, url, kCFHTTPVersion1_1))) { goto out; } if (config->userAgent) { CFHTTPMessageSetHeaderFieldValue(request, httpUserAgentHeader, config->userAgent); } CFHTTPMessageSetHeaderFieldValue(request, icyMetaDataHeader, icyMetaDataValue); if (m_position.start > 0 && m_position.end > m_position.start) { CFStringRef rangeHeaderValue = CFStringCreateWithFormat(NULL, NULL, CFSTR("bytes=%llu-%llu"), m_position.start, m_position.end); CFHTTPMessageSetHeaderFieldValue(request, httpRangeHeader, rangeHeaderValue); CFRelease(rangeHeaderValue); } if (!(readStream = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, request))) { goto out; } CFReadStreamSetProperty(readStream, kCFStreamPropertyHTTPShouldAutoredirect, kCFBooleanTrue); proxySettings = CFNetworkCopySystemProxySettings(); if (proxySettings) { CFReadStreamSetProperty(readStream, kCFStreamPropertyHTTPProxy, proxySettings); CFRelease(proxySettings); } out: if (request) { CFRelease(request); } return readStream; }
void SocketStreamHandle::addCONNECTCredentials(CFHTTPMessageRef proxyResponse) { RetainPtr<CFHTTPAuthenticationRef> authentication(AdoptCF, CFHTTPAuthenticationCreateFromResponse(0, proxyResponse)); if (!CFHTTPAuthenticationRequiresUserNameAndPassword(authentication.get())) { // That's all we can offer... m_client->didFail(this, SocketStreamError()); // FIXME: Provide a sensible error. return; } int port = 0; CFNumberGetValue(m_proxyPort.get(), kCFNumberIntType, &port); RetainPtr<CFStringRef> methodCF(AdoptCF, CFHTTPAuthenticationCopyMethod(authentication.get())); RetainPtr<CFStringRef> realmCF(AdoptCF, CFHTTPAuthenticationCopyRealm(authentication.get())); ProtectionSpace protectionSpace(String(m_proxyHost.get()), port, ProtectionSpaceProxyHTTPS, String(realmCF.get()), authenticationSchemeFromAuthenticationMethod(methodCF.get())); String login; String password; if (!m_sentStoredCredentials && getStoredCONNECTProxyCredentials(protectionSpace, login, password)) { // Try to apply stored credentials, if we haven't tried those already. RetainPtr<CFStringRef> loginCF(AdoptCF, login.createCFString()); RetainPtr<CFStringRef> passwordCF(AdoptCF, password.createCFString()); // Creating a temporary request to make CFNetwork apply credentials to it. Unfortunately, this cannot work with NTLM authentication. RetainPtr<CFHTTPMessageRef> dummyRequest(AdoptCF, CFHTTPMessageCreateRequest(0, CFSTR("GET"), m_httpsURL.get(), kCFHTTPVersion1_1)); Boolean appliedCredentials = CFHTTPMessageApplyCredentials(dummyRequest.get(), authentication.get(), loginCF.get(), passwordCF.get(), 0); ASSERT_UNUSED(appliedCredentials, appliedCredentials); RetainPtr<CFStringRef> proxyAuthorizationString(AdoptCF, CFHTTPMessageCopyHeaderFieldValue(dummyRequest.get(), CFSTR("Proxy-Authorization"))); if (!proxyAuthorizationString) { // Fails e.g. for NTLM auth. m_client->didFail(this, SocketStreamError()); // FIXME: Provide a sensible error. return; } // Setting the authorization results in a new connection attempt. wkSetCONNECTProxyAuthorizationForStream(m_readStream.get(), proxyAuthorizationString.get()); m_sentStoredCredentials = true; return; } // FIXME: Ask the client if credentials could not be found. m_client->didFail(this, SocketStreamError()); // FIXME: Provide a sensible error. }
void HTTPLoader::load(CFURLRef url) { CFHTTPMessageRef request = CFHTTPMessageCreateRequest(NULL, CFSTR("GET"), url, kCFHTTPVersion1_1); mStream = CFReadStreamCreateForHTTPRequest(NULL, request); CFRelease(request); if (!CFReadStreamOpen(mStream)) { CFRelease(mStream); mStream = 0; } else { CFStreamClientContext context = {0, this, NULL, NULL, NULL}; CFReadStreamSetClient(mStream, kCFStreamEventHasBytesAvailable | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered, readStreamCallback, &context); CFReadStreamScheduleWithRunLoop(mStream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); } }
static Boolean addAuthenticationToWSInvokation( WSMethodInvocationRef wsRef, CFStringRef username, CFStringRef password, CFDictionaryRef response) { CFHTTPMessageRef message = (CFHTTPMessageRef)CFDictionaryGetValue(response, kWSHTTPResponseMessage); CFHTTPMessageRef outgoingMessage = NULL; if (message != NULL) { CFURLRef theURL = CFHTTPMessageCopyRequestURL(message); if (theURL != NULL) { //Move the stuff that counts into our new message outgoingMessage = CFHTTPMessageCreateRequest(NULL, CFSTR("POST"), theURL, kCFHTTPVersion1_1); CFRelease(theURL); } } Boolean successful = FALSE; if ((message != NULL) && (outgoingMessage != NULL)) { successful = CFHTTPMessageAddAuthentication(outgoingMessage, message, username, password, kCFHTTPAuthenticationSchemeDigest, FALSE); } if (successful) { /* FIXME kWSHTTPMessage isn't exported by WebServicesCore * I can't find the source but there is a string in the binary that * looks like this, with the leading '/' */ WSMethodInvocationSetProperty(wsRef, CFSTR("/kWSHTTPMessage"), outgoingMessage); } if (outgoingMessage) { CFRelease(outgoingMessage); } return successful; }
bool asyncHttpPost(CFURLRef responder, CFDataRef requestData /* , bool force_nocache */ , asynchttp_t *http) { bool result = true; /* True, we didn't schedule any work. */ /* resources to release on exit */ CFURLRef getURL = NULL; /* Interesting tidbit from rfc5019 When sending requests that are less than or equal to 255 bytes in total (after encoding) including the scheme and delimiters (http://), server name and base64-encoded OCSPRequest structure, clients MUST use the GET method (to enable OCSP response caching). OCSP requests larger than 255 bytes SHOULD be submitted using the POST method. Interesting tidbit from rfc2616: Note: Servers ought to be cautious about depending on URI lengths above 255 bytes, because some older client or proxy implementations might not properly support these lengths. Given the second note I'm assuming that the note in rfc5019 is about the length of the URI, not the length of the entire HTTP request. If we need to consider the entire request we need to have 17 bytes less, or 17 + 25 = 42 if we are appending a "Cache-Control: no-cache CRLF" header field. The 17 and 42 above are based on the request encoding from rfc2616 Method SP Request-URI SP HTTP-Version CRLF (header CRLF)* CRLF so in our case it's: GET SP URI SP HTTP/1.1 CRLF CRLF 17 + len(URI) bytes or GET SP URI SP HTTP/1.1 CRLF Cache-Control: SP no-cache CRLF CRLF 42 + len(URI) bytes */ /* First let's try creating a GET request. */ getURL = createGetURL(responder, requestData); if (getURL && CFURLGetBytes(getURL, NULL, 0) < 256) { /* Get URI is less than 256 bytes encoded, making it safe even for older proxy or caching servers, so let's use HTTP GET. */ secdebug("http", "GET[%ld] %@", CFURLGetBytes(getURL, NULL, 0), getURL); require_quiet(http->request = CFHTTPMessageCreateRequest(kCFAllocatorDefault, CFSTR("GET"), getURL, kCFHTTPVersion1_1), errOut); } else { /* GET Request too big to ensure error free transmission, let's create a HTTP POST http->request instead. */ secdebug("http", "POST %@ CRLF body", responder); require_quiet(http->request = CFHTTPMessageCreateRequest(kCFAllocatorDefault, CFSTR("POST"), responder, kCFHTTPVersion1_1), errOut); /* Set the body and required header fields. */ CFHTTPMessageSetBody(http->request, requestData); CFHTTPMessageSetHeaderFieldValue(http->request, kContentType, kAppOcspRequest); } #if 0 if (force_nocache) { CFHTTPMessageSetHeaderFieldValue(http->request, CFSTR("Cache-Control"), CFSTR("no-cache")); } #endif result = asynchttp_request(NULL, http); errOut: CFReleaseSafe(getURL); return result; }
nuiHTTPResponse* nuiHTTPRequest::SendRequest() { char* pUrl = mUrl.Export(); CFStringRef originalURLString = CFStringCreateWithCString(kCFAllocatorDefault, pUrl, kCFStringEncodingUTF8); CFStringRef preprocessedString = CFURLCreateStringByReplacingPercentEscapesUsingEncoding(kCFAllocatorDefault, originalURLString, CFSTR(""), kCFStringEncodingUTF8); CFStringRef urlString = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, preprocessedString, NULL, NULL, kCFStringEncodingUTF8); free(pUrl); CFURLRef url = CFURLCreateWithString(kCFAllocatorDefault, urlString, NULL); CFRelease(urlString); char* pMeth = mMethod.Export(); CFStringRef method = CFStringCreateWithCString(kCFAllocatorDefault, pMeth, kCFStringEncodingUTF8); free(pMeth); CFHTTPMessageRef req = CFHTTPMessageCreateRequest(kCFAllocatorDefault, method, url, kCFHTTPVersion1_1); CFStringRef userAgentField = CFSTR("User-Agent"); CFStringRef userAgentName = CFSTR("nuiHTTP/2.0"); CFHTTPMessageSetHeaderFieldValue(req, userAgentField, userAgentName); CFRelease(userAgentField); CFRelease(userAgentName); nuiHTTPHeaderMap::const_iterator end = mHeaders.end(); for (nuiHTTPHeaderMap::const_iterator it = mHeaders.begin(); it != end; ++it) { char* pName = it->first.Export(); char* pVal = it->second.Export(); CFStringRef fieldName = CFStringCreateWithCString(kCFAllocatorDefault, pName, kCFStringEncodingUTF8); CFStringRef fieldValue = CFStringCreateWithCString(kCFAllocatorDefault, pVal, kCFStringEncodingUTF8); CFHTTPMessageSetHeaderFieldValue(req, fieldName, fieldValue); CFRelease(fieldName); CFRelease(fieldValue); delete pName; delete pVal; } CFDataRef body = NULL; if (mBody.size()) { body = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (UInt8*)&mBody[0], mBody.size(), kCFAllocatorNull); CFHTTPMessageSetBody(req, body); } CFReadStreamRef readStream = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, req); CFReadStreamOpen(readStream); std::vector<char> buf; CFIndex pos = 0; CFIndex size = 0; bool cont = true; do { buf.resize(pos + 1024); size = CFReadStreamRead(readStream, (UInt8*)&buf[pos], 1024); if (size == -1) { return NULL; } else if (size == 0) { if (CFReadStreamGetStatus(readStream) == kCFStreamStatusAtEnd) cont = false; else nglThread::MsSleep(10); } pos += size; } while (cont); CFHTTPMessageRef responseHeader = (CFHTTPMessageRef)CFReadStreamCopyProperty(readStream, kCFStreamPropertyHTTPResponseHeader); CFStringRef statusLine = CFHTTPMessageCopyResponseStatusLine(responseHeader); CFIndex strSize = CFStringGetLength(statusLine)+1; char* pStatus = new char[strSize]; CFStringGetCString(statusLine, pStatus, strSize, kCFStringEncodingUTF8); nglString status(pStatus); UInt32 statusCode = CFHTTPMessageGetResponseStatusCode(responseHeader); nuiHTTPResponse* pResponse = new nuiHTTPResponse(statusCode, status); pResponse->SetBody(&buf[0], pos); delete[] pStatus; CFDictionaryRef dict = CFHTTPMessageCopyAllHeaderFields(responseHeader); CFIndex valueCount = CFDictionaryGetCount(dict); const CFStringRef* pNames = new CFStringRef[valueCount]; const CFStringRef* pValues = new CFStringRef[valueCount]; CFDictionaryGetKeysAndValues(dict, (const void**)pNames, (const void**)pValues); for (CFIndex i = 0; i< valueCount; i++) { strSize = CFStringGetLength(pNames[i])+1; char* pName = new char[strSize]; CFStringGetCString(pNames[i], pName, strSize, kCFStringEncodingUTF8); strSize = CFStringGetLength(pValues[i])+1; char* pVal = new char[strSize]; CFStringGetCString(pValues[i], pVal, strSize, kCFStringEncodingUTF8); nglString name(pName); nglString val(pVal); pResponse->AddHeader(name, val); delete[] pName; delete[] pVal; } delete[] pNames; delete[] pValues; CFRelease(responseHeader); CFRelease(url); CFRelease(method); CFRelease(req); CFRelease(readStream); CFRelease(dict); CFRelease(statusLine); if (body) CFRelease(body); return pResponse; }
static void make_request( SG_context* pCtx, const char* pszUrl, const char* psz_method, const char* psz_data, CFHTTPMessageRef* pp ) { CFStringRef url = NULL; CFURLRef myURL = NULL; CFStringRef requestMethod = NULL; CFHTTPMessageRef myRequest = NULL; url = CFStringCreateWithCString(kCFAllocatorDefault, pszUrl,kCFStringEncodingUTF8); SG_NULLARGCHECK(url); myURL = CFURLCreateWithString(kCFAllocatorDefault, url, NULL); SG_NULLARGCHECK(myURL); requestMethod = CFStringCreateWithCString(kCFAllocatorDefault, psz_method,kCFStringEncodingUTF8); SG_NULLARGCHECK(requestMethod); myRequest = CFHTTPMessageCreateRequest( kCFAllocatorDefault, requestMethod, myURL, kCFHTTPVersion1_1 ); SG_NULLARGCHECK(myRequest); if (psz_data) { CFStringRef s = CFStringCreateWithCString(kCFAllocatorDefault, psz_data, kCFStringEncodingUTF8); CFDataRef bodyData = CFStringCreateExternalRepresentation(kCFAllocatorDefault, s, kCFStringEncodingUTF8, 0); CFRelease(s); CFHTTPMessageSetBody(myRequest, bodyData); CFRelease(bodyData); } *pp = myRequest; myRequest = NULL; fail: if (myRequest) { CFRelease(myRequest); myRequest = NULL; } if (myURL) { CFRelease(myURL); myURL = NULL; } if (requestMethod) { CFRelease(requestMethod); requestMethod = NULL; } if (url) { CFRelease(url); url = NULL; } }
char* DotMacQuery::ReadStream (CFURLRef url, size_t &responseLength) { SInt32 ito; CFNumberRef cfnTo = NULL; CFDictionaryRef proxyDict = NULL; // make a connection to the provided URL CFHTTPMessageRef httpRequestRef = CFHTTPMessageCreateRequest (kCFAllocatorDefault, CFSTR("GET"), url, kCFHTTPVersion1_1); if (httpRequestRef == NULL) { CSSMError::ThrowCSSMError (CSSMERR_DL_RECORD_NOT_FOUND); } // open the stream CFReadStreamRef httpStreamRef = CFReadStreamCreateForHTTPRequest (kCFAllocatorDefault, httpRequestRef); if (httpStreamRef == NULL) { CSSMError::ThrowCSSMError (CSSMERR_DL_RECORD_NOT_FOUND); } // set a reasonable timeout ito = READ_STREAM_TIMEOUT; cfnTo = CFNumberCreate(NULL, kCFNumberSInt32Type, &ito); if(!CFReadStreamSetProperty(httpStreamRef, _kCFStreamPropertyReadTimeout, cfnTo)) { // oh well - keep going } /* set up possible proxy info */ proxyDict = SCDynamicStoreCopyProxies(NULL); if(proxyDict) { CFReadStreamSetProperty(httpStreamRef, kCFStreamPropertyHTTPProxy, proxyDict); } if (CFReadStreamOpen (httpStreamRef) == false) { CFRelease(httpRequestRef); CFRelease(httpStreamRef); CFRelease(cfnTo); if(proxyDict) { CFRelease(proxyDict); } CSSMError::ThrowCSSMError (CSSMERR_DL_RECORD_NOT_FOUND); } char* response = (char*) malloc (kResponseIncrement); size_t responseBufferLength = kResponseIncrement; responseLength = 0; // read data from the stream CFIndex bytesRead = CFReadStreamRead (httpStreamRef, (UInt8*) response + responseLength, kResponseIncrement); while (bytesRead > 0) { responseLength += bytesRead; responseBufferLength = responseLength + kResponseIncrement; response = (char*) realloc (response, responseBufferLength); bytesRead = CFReadStreamRead (httpStreamRef, (UInt8*) response + responseLength, kResponseIncrement); } CFRelease (httpRequestRef); CFRelease (httpStreamRef); CFRelease(cfnTo); if(proxyDict) { CFRelease(proxyDict); } // check for error if (bytesRead < 0) { CSSMError::ThrowCSSMError (CSSMERR_DL_RECORD_NOT_FOUND); } return response; }