예제 #1
0
bool DNSResolveQueue::platformProxyIsEnabledInSystemPreferences()
{
    // Don't do DNS prefetch if proxies are involved. For many proxy types, the user agent is never exposed
    // to the IP address during normal operation. Querying an internal DNS server may not help performance,
    // as it doesn't necessarily look up the actual external IP. Also, if DNS returns a fake internal address,
    // local caches may keep it even after re-connecting to another network.

    RetainPtr<CFDictionaryRef> proxySettings = adoptCF(CFNetworkCopySystemProxySettings());
    if (!proxySettings)
        return false;

    RetainPtr<CFURLRef> httpCFURL = URL(ParsedURLString, "http://example.com/").createCFURL();
    RetainPtr<CFURLRef> httpsCFURL = URL(ParsedURLString, "https://example.com/").createCFURL();

    RetainPtr<CFArrayRef> httpProxyArray = adoptCF(CFNetworkCopyProxiesForURL(httpCFURL.get(), proxySettings.get()));
    RetainPtr<CFArrayRef> httpsProxyArray = adoptCF(CFNetworkCopyProxiesForURL(httpsCFURL.get(), proxySettings.get()));

    CFIndex httpProxyCount = CFArrayGetCount(httpProxyArray.get());
    CFIndex httpsProxyCount = CFArrayGetCount(httpsProxyArray.get());
    if (httpProxyCount == 1 && CFEqual(CFDictionaryGetValue(static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(httpProxyArray.get(), 0)), kCFProxyTypeKey), kCFProxyTypeNone))
        httpProxyCount = 0;
    if (httpsProxyCount == 1 && CFEqual(CFDictionaryGetValue(static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(httpsProxyArray.get(), 0)), kCFProxyTypeKey), kCFProxyTypeNone))
        httpsProxyCount = 0;

    return httpProxyCount || httpsProxyCount;
}
예제 #2
0
void SocketStreamHandle::chooseProxy()
{
#ifndef BUILDING_ON_LEOPARD
    RetainPtr<CFDictionaryRef> proxyDictionary(AdoptCF, CFNetworkCopySystemProxySettings());
#else
    // We don't need proxy information often, so there is no need to set up a permanent dynamic store session.
    RetainPtr<CFDictionaryRef> proxyDictionary(AdoptCF, SCDynamicStoreCopyProxies(0));
#endif

    // SOCKS or HTTPS (AKA CONNECT) proxies are supported.
    // WebSocket protocol relies on handshake being transferred unchanged, so we need a proxy that will not modify headers.
    // Since HTTP proxies must add Via headers, they are highly unlikely to work.
    // Many CONNECT proxies limit connectivity to port 443, so we prefer SOCKS, if configured.

    if (!proxyDictionary) {
        m_connectionType = Direct;
        return;
    }

    // CFNetworkCopyProxiesForURL doesn't know about WebSocket schemes, so pretend to use http.
    // Always use "https" to get HTTPS proxies in result - we'll try to use those for ws:// even though many are configured to reject connections to ports other than 443.
    RetainPtr<CFArrayRef> proxyArray(AdoptCF, CFNetworkCopyProxiesForURL(m_httpsURL.get(), proxyDictionary.get()));

    chooseProxyFromArray(proxyArray.get());
}
예제 #3
0
static void addProxyServersForURL(Vector<ProxyServer>& proxyServers, const KURL& url)
{
    RetainPtr<CFDictionaryRef> proxySettings(AdoptCF, CFNetworkCopySystemProxySettings());
    if (!proxySettings)
        return;

    RetainPtr<CFURLRef> cfURL(AdoptCF, url.createCFURL());
    RetainPtr<CFArrayRef> proxiesForURL(AdoptCF, CFNetworkCopyProxiesForURL(cfURL.get(), proxySettings.get()));
    if (!proxiesForURL)
        return;

    processProxyServers(proxyServers, proxiesForURL.get(), cfURL.get());
}
예제 #4
0
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;
}
예제 #5
0
static void addProxyServersForURL(Vector<ProxyServer>& proxyServers, const KURL& url)
{
    RetainPtr<CFDictionaryRef> proxySettings(AdoptCF, CFNetworkCopySystemProxySettings());
    if (!proxySettings)
        return;

    RetainPtr<CFURLRef> cfURL(AdoptCF, url.createCFURL());
    RetainPtr<CFArrayRef> proxiesForURL(AdoptCF, CFNetworkCopyProxiesForURL(cfURL.get(), proxySettings.get()));
    if (!proxiesForURL)
        return;

    CFIndex numProxies = CFArrayGetCount(proxiesForURL.get());
    for (CFIndex i = 0; i < numProxies; ++i) {
        CFDictionaryRef proxyDictionary = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(proxiesForURL.get(), i));

        ProxyServer::Type type = ProxyServer::Direct;
        CFStringRef typeString = static_cast<CFStringRef>(CFDictionaryGetValue(proxyDictionary, kCFProxyTypeKey));
        if (CFEqual(typeString, kCFProxyTypeAutoConfigurationURL)) {
            // FIXME: Handle PAC URLs.
            continue;
        } 
        
        if (CFEqual(typeString, kCFProxyTypeNone)) {
            proxyServers.append(ProxyServer(ProxyServer::Direct, String(), -1));
            continue;
        }
        
        if (CFEqual(typeString, kCFProxyTypeHTTP))
            type = ProxyServer::HTTP;
        else if (CFEqual(typeString, kCFProxyTypeHTTPS))
            type = ProxyServer::HTTPS;
        else if (CFEqual(typeString, kCFProxyTypeSOCKS))
            type = ProxyServer::SOCKS;
        else {
            // We don't know how to handle this type.
            continue;
        }

        CFStringRef host = static_cast<CFStringRef>(CFDictionaryGetValue(proxyDictionary, kCFProxyHostNameKey));
        CFNumberRef port = static_cast<CFNumberRef>(CFDictionaryGetValue(proxyDictionary, kCFProxyPortNumberKey));
        SInt32 portValue;
        CFNumberGetValue(port, kCFNumberSInt32Type, &portValue);

        proxyServers.append(ProxyServer(type, host, portValue));
    }
}
예제 #6
0
JNIEXPORT jobjectArray JNICALL
Java_com_zimbra_znative_ProxyInfo_getProxyInfo(JNIEnv *env, jclass cls, jstring jurl) {
    check_initialized(env);
    CFStringRef urlstr = getCFString(env, jurl);
    CFURLRef url = CFURLCreateWithString(NULL, urlstr, NULL);
    CFDictionaryRef systemProxy = CFNetworkCopySystemProxySettings();
    CFArrayRef proxyArray = CFNetworkCopyProxiesForURL(url, systemProxy);
    CFIndex size = CFArrayGetCount(proxyArray);
    jobjectArray results = (*env)->NewObjectArray(env, (jsize) size, pi_cls, NULL);
    int i;
    for (i = 0; i < size; i++) {
        CFDictionaryRef proxy = CFArrayGetValueAtIndex(proxyArray, i);
        (*env)->SetObjectArrayElement(env, results, i, getProxyInfo(env, proxy));
    }
    CFRelease(proxyArray);
    CFRelease(systemProxy);
    CFRelease(url);
    CFRelease(urlstr);
    return results;
}
    /* Create the stream for the request. */
    require_quiet(http->stream = CFReadStreamCreateForHTTPRequest(
        kCFAllocatorDefault, http->request), errOut);

	/* Set a reasonable timeout */
    require_quiet(http->timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, http->queue), errOut);
    dispatch_source_set_event_handler(http->timer, ^{
        asynchttp_timer_proc(http);
    });
    // Set the timer's fire time to now + STREAM_TIMEOUT seconds with a .5 second fuzz factor.
    dispatch_source_set_timer(http->timer, dispatch_time(DISPATCH_TIME_NOW, STREAM_TIMEOUT),
                              DISPATCH_TIME_FOREVER, (int64_t)(500 * NSEC_PER_MSEC));
    dispatch_resume(http->timer);

	/* Set up possible proxy info */
	CFDictionaryRef proxyDict = CFNetworkCopySystemProxySettings();
	if (proxyDict) {
		CFReadStreamSetProperty(http->stream, kCFStreamPropertyHTTPProxy, proxyDict);
        CFRelease(proxyDict);
    }

    http->data = CFDataCreateMutable(kCFAllocatorDefault, 0);

    CFStreamClientContext stream_context = { .info = http };
    CFReadStreamSetClient(http->stream,
        (kCFStreamEventHasBytesAvailable
         | kCFStreamEventErrorOccurred
         | kCFStreamEventEndEncountered),
        handle_server_response, &stream_context);
    CFReadStreamSetDispatchQueue(http->stream, http->queue);
    CFReadStreamOpen(http->stream);
예제 #8
0
/* MyCFStreamSetFTPProxy applies the current proxy settings to the specified stream.  This returns a 
reference to the proxy dictionary that we used because of <rdar://problem/3745574>, discussed below. */
static void
MyCFStreamSetFTPProxy(CFTypeRef stream, CFDictionaryRef * proxyDictPtr)
{
    CFDictionaryRef  proxyDict;
    CFNumberRef      passiveMode;
    CFBooleanRef     isPassive;
    Boolean          success;
    
    assert(stream != NULL);
    assert(proxyDictPtr != NULL);
    
    /* SCDynamicStoreCopyProxies gets the current Internet proxy settings.  Then we call
    CFReadStreamSetProperty, with property name kCFStreamPropertyFTPProxy, to apply the
    settings to the FTP read stream. */
    proxyDict = CFNetworkCopySystemProxySettings();
    assert(proxyDict != NULL);    
    
    /* Get the FTP passive mode setting from the proxy dictionary.  Because of a bug <rdar://problem/3625438>
    setting the kCFStreamPropertyFTPProxy property using the SCDynamicStore proxy dictionary does not
    currently set the FTP passive mode setting on the stream, so we need to do it ourselves. 
    Also, <rdar://problem/4526438> indicates that out in the real world some people are setting 
    kSCPropNetProxiesFTPPassive to a Boolean, as opposed to a number.  That's just incorrect, 
    but I've hardened the code against it. */
//    passiveMode = CFDictionaryGetValue(proxyDict, kSCPropNetProxiesFTPPassive);
    passiveMode = true;
    if ( (passiveMode != NULL) && (CFGetTypeID(passiveMode) == CFNumberGetTypeID()) ) {
        int         value;
        
        success = CFNumberGetValue(passiveMode, kCFNumberIntType, &value);
        assert(success);
        
        if (value) isPassive = kCFBooleanTrue;
        else isPassive = kCFBooleanFalse;
    } else {
        assert(false);
        isPassive = kCFBooleanTrue;         // if prefs malformed, we just assume true
    }
        
    if (CFGetTypeID(stream) == CFReadStreamGetTypeID()) {
        success = CFReadStreamSetProperty((CFReadStreamRef)stream, kCFStreamPropertyFTPProxy, proxyDict);
        assert(success);
        success = CFReadStreamSetProperty((CFReadStreamRef)stream, kCFStreamPropertyFTPUsePassiveMode, isPassive);
        assert(success);
    } else if (CFGetTypeID(stream) == CFWriteStreamGetTypeID()) {
        success = CFWriteStreamSetProperty((CFWriteStreamRef)stream, kCFStreamPropertyFTPProxy, proxyDict);
        assert(success);
        success = CFWriteStreamSetProperty((CFWriteStreamRef)stream, kCFStreamPropertyFTPUsePassiveMode, isPassive);
        assert(success);
    } else {
        fprintf(stderr, "This is not a CFStream\n");
    }

    /* Prior to Mac OS X 10.4, CFFTPStream has a bug <rdar://problem/3745574> that causes it to reference the 
    proxy dictionary that you applied /after/ it has released its last reference to that dictionary.  This causes 
    a crash.  We work around this bug by holding on to our own reference to the proxy dictionary until we're 
    done with the stream.  Thus, our reference prevents the dictionary from being disposed, and thus CFFTPStream 
    can access it safely.  So, rather than release our reference to the proxy dictionary, we pass it back to 
    our caller and require it to release it. */
    
    // CFRelease(proxyDict);  After bug #3745574 is fixed, we'll be able to release the proxyDict here.
    
    *proxyDictPtr = proxyDict;
}
예제 #9
0
mailstream_low * mailstream_low_cfstream_open_voip_timeout(const char * hostname, int16_t port,
  int voip_enabled, time_t timeout)
{
#if HAVE_CFNETWORK
  mailstream_low * s;
  struct mailstream_cfstream_data * cfstream_data;
  CFReadStreamRef readStream;
  CFWriteStreamRef writeStream;
  CFStringRef hostString;
  CFOptionFlags readFlags;
  CFOptionFlags writeFlags;
  int r;
  
  hostString = CFStringCreateWithCString(NULL, hostname, kCFStringEncodingUTF8);
  CFStreamCreatePairWithSocketToHost(NULL, hostString, port, &readStream, &writeStream);
  CFRelease(hostString);

#if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR  
  if (voip_enabled) {
    CFReadStreamSetProperty(readStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP);
    CFWriteStreamSetProperty(writeStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP);
  }
#endif

#if !TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR
  CFDictionaryRef proxySettings = CFNetworkCopySystemProxySettings();
  CFNumberRef nbEnabled = CFDictionaryGetValue(proxySettings, kCFNetworkProxiesSOCKSEnable);
  if (numberIntValue(nbEnabled)) {
    CFReadStreamSetProperty(readStream, kCFStreamPropertySOCKSProxy, proxySettings);
    CFWriteStreamSetProperty(writeStream, kCFStreamPropertySOCKSProxy, proxySettings);
  }
  CFRelease(proxySettings);
#endif

  cfstream_data = cfstream_data_new(readStream, writeStream);
  s = mailstream_low_new(cfstream_data, mailstream_cfstream_driver);
	mailstream_low_set_timeout(s, timeout);  

  //fprintf(stderr, "open %s %i -> %p\n", hostname, port, s);
  
  /* setup streams */
  cfstream_data->streamContext.info = s;
  
  readFlags = kCFStreamEventOpenCompleted |
  kCFStreamEventHasBytesAvailable |
  kCFStreamEventErrorOccurred |
  kCFStreamEventEndEncountered;
  
  writeFlags = kCFStreamEventOpenCompleted |
  kCFStreamEventCanAcceptBytes |
  kCFStreamEventErrorOccurred |
  kCFStreamEventEndEncountered;
  
  CFReadStreamSetClient(cfstream_data->readStream, readFlags, readStreamCallback, &cfstream_data->streamContext);
  CFWriteStreamSetClient(cfstream_data->writeStream, writeFlags, writeStreamCallback, &cfstream_data->streamContext);
  
  CFRelease(readStream);
  CFRelease(writeStream);
  readStream = NULL;
  writeStream = NULL;
  
  /* setup cancel */
  cfstream_data->cancelContext.info = s;
  cfstream_data->cancelContext.perform = cancelPerform;
  cfstream_data->cancelSource = CFRunLoopSourceCreate(NULL, 0, &cfstream_data->cancelContext);
  
  r = low_open(s);
  if (r < 0) {
    mailstream_low_cfstream_close(s);
    return NULL;
  }
  
  return s;
#else
  return NULL;
#endif
}