/* MyCFStreamSetUsernamePassword applies the specified user name and password to the stream. */ static void MyCFStreamSetUsernamePassword(CFTypeRef stream, CFStringRef username, CFStringRef password) { Boolean success; assert(stream != NULL); assert( (username != NULL) || (password == NULL) ); if (username && CFStringGetLength(username) > 0) { if (CFGetTypeID(stream) == CFReadStreamGetTypeID()) { success = CFReadStreamSetProperty((CFReadStreamRef)stream, kCFStreamPropertyFTPUserName, username); assert(success); if (password) { success = CFReadStreamSetProperty((CFReadStreamRef)stream, kCFStreamPropertyFTPPassword, password); assert(success); } } else if (CFGetTypeID(stream) == CFWriteStreamGetTypeID()) { success = CFWriteStreamSetProperty((CFWriteStreamRef)stream, kCFStreamPropertyFTPUserName, username); assert(success); if (password) { success = CFWriteStreamSetProperty((CFWriteStreamRef)stream, kCFStreamPropertyFTPPassword, password); assert(success); } } else { assert(false); } } }
CURLcode SSLImpl::connect(int sockfd, int nonblocking, int *done, int ssl_verify_peer, void *storage, char* host_name) { ssl_data_t *data = (ssl_data_t*)storage; CFStreamCreatePairWithSocket(kCFAllocatorDefault, sockfd, &data->readStream, &data->writeStream); // Indicate that the connection needs to be done in secure manner CFReadStreamSetProperty(data->readStream, kCFStreamPropertySocketSecurityLevel, kCFStreamSocketSecurityLevelSSLv3); CFWriteStreamSetProperty(data->writeStream, kCFStreamPropertySocketSecurityLevel, kCFStreamSocketSecurityLevelSSLv3); CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (!dict) { RAWLOG_ERROR("Can not allocate CFMutableDictionaryRef"); return CURLE_SSL_CONNECT_ERROR; } CFDictionarySetValue(dict, kCFStreamSSLValidatesCertificateChain, ssl_verify_peer ? kCFBooleanTrue : kCFBooleanFalse); CFReadStreamSetProperty(data->readStream, kCFStreamPropertySSLSettings, dict); CFWriteStreamSetProperty(data->writeStream, kCFStreamPropertySSLSettings, dict); CFRelease(dict); if (!CFReadStreamOpen(data->readStream) || !CFWriteStreamOpen(data->writeStream)) { RAWLOG_ERROR("SSL connection error"); return CURLE_SSL_CONNECT_ERROR; } CFReadStreamScheduleWithRunLoop( data->readStream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); CFWriteStreamScheduleWithRunLoop( data->writeStream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); *done = 1; return CURLE_OK; }
void SocketStreamHandle::createStreams() { if (m_connectionType == Unknown) chooseProxy(); // If it's still unknown, then we're resolving a PAC file asynchronously. if (m_connectionType == Unknown) return; RetainPtr<CFStringRef> host = m_url.host().createCFString(); // Creating streams to final destination, not to proxy. CFReadStreamRef readStream = 0; CFWriteStreamRef writeStream = 0; CFStreamCreatePairWithSocketToHost(0, host.get(), port(), &readStream, &writeStream); #if PLATFORM(IOS) || (PLATFORM(MAC) && MAC_OS_X_VERSION_MIN_REQUIRED >= 1080) // <rdar://problem/12855587> _kCFStreamSocketSetNoDelay is not exported on Windows CFWriteStreamSetProperty(writeStream, _kCFStreamSocketSetNoDelay, kCFBooleanTrue); #endif m_readStream.adoptCF(readStream); m_writeStream.adoptCF(writeStream); switch (m_connectionType) { case Unknown: ASSERT_NOT_REACHED(); break; case Direct: break; case SOCKSProxy: { // FIXME: SOCKS5 doesn't do challenge-response, should we try to apply credentials from Keychain right away? // But SOCKS5 credentials don't work at the time of this writing anyway, see <rdar://6776698>. const void* proxyKeys[] = { kCFStreamPropertySOCKSProxyHost, kCFStreamPropertySOCKSProxyPort }; const void* proxyValues[] = { m_proxyHost.get(), m_proxyPort.get() }; RetainPtr<CFDictionaryRef> connectDictionary(AdoptCF, CFDictionaryCreate(0, proxyKeys, proxyValues, WTF_ARRAY_LENGTH(proxyKeys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); CFReadStreamSetProperty(m_readStream.get(), kCFStreamPropertySOCKSProxy, connectDictionary.get()); break; } case CONNECTProxy: wkSetCONNECTProxyForStream(m_readStream.get(), m_proxyHost.get(), m_proxyPort.get()); break; } if (shouldUseSSL()) { const void* keys[] = { kCFStreamSSLPeerName, kCFStreamSSLLevel }; const void* values[] = { host.get(), kCFStreamSocketSecurityLevelNegotiatedSSL }; RetainPtr<CFDictionaryRef> settings(AdoptCF, CFDictionaryCreate(0, keys, values, WTF_ARRAY_LENGTH(keys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); CFReadStreamSetProperty(m_readStream.get(), kCFStreamPropertySSLSettings, settings.get()); CFWriteStreamSetProperty(m_writeStream.get(), kCFStreamPropertySSLSettings, settings.get()); } }
static void nc_trigger(int argc, char **argv) { Boolean background = FALSE; int i; CFStringRef hostName = NULL; int port = 80; for (i = 0; i < 3 && i < argc; i++) { /* Parse host name. Must be first arg. */ if (i == 0) { hostName = CFStringCreateWithCString(NULL, argv[i], kCFStringEncodingUTF8); continue; } /* Check for optional background flag */ if (strcmp(argv[i], "background") == 0) { background = TRUE; continue; } /* Parse optional port number */ CFStringRef str = CFStringCreateWithCString(NULL, argv[i], kCFStringEncodingUTF8); if (str) { int num = CFStringGetIntValue(str); if (num) { port = num; } my_CFRelease(&str); } } if (hostName) { CFReadStreamRef readStream = NULL; CFWriteStreamRef writeStream = NULL; CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, hostName, port, &readStream, &writeStream); if (background) { CFReadStreamSetProperty(readStream, CFSTR("kCFStreamNetworkServiceType"), CFSTR("kCFStreamNetworkServiceTypeBackground")); CFWriteStreamSetProperty(writeStream, CFSTR("kCFStreamNetworkServiceType"), CFSTR("kCFStreamNetworkServiceTypeBackground")); } if (readStream && writeStream) { CFReadStreamOpen(readStream); CFWriteStreamOpen(writeStream); SCPrint(TRUE, stdout, CFSTR("Opened stream to %@, port %d%s\n"), hostName, port, background ? ", background traffic class" : ""); sleep(1); } my_CFRelease(&readStream); my_CFRelease(&writeStream); } else { SCPrint(TRUE, stderr, CFSTR("Invalid or missing host name\n")); } my_CFRelease(&hostName); exit(0); }
/* CF_EXPORT */ void _CFSocketStreamPairSetAuthenticatesServerCertificate(CFReadStreamRef rStream, CFWriteStreamRef wStream, Boolean authenticates) { CFBooleanRef value = (!authenticates ? kCFBooleanFalse : kCFBooleanTrue); if (rStream) CFReadStreamSetProperty(rStream, _kCFStreamPropertySocketSecurityAuthenticatesServerCertificate, value); else CFWriteStreamSetProperty(wStream, _kCFStreamPropertySocketSecurityAuthenticatesServerCertificate, value); }
void write_buffer(CFStringRef inData) { #ifdef DEBUG syslog(LOG_ERR,"Writing buffer to file."); #endif if (CFWriteStreamGetStatus(logStream)!=kCFStreamStatusOpen) { CFWriteStreamSetProperty(logStream,kCFStreamPropertyAppendToFile,kCFBooleanTrue); CFWriteStreamOpen(logStream); } if (!CFBooleanGetValue(doEncrypt)) { CFWriteStreamWrite(logStream,(const UInt8*)CFStringGetCStringPtr(inData,CFStringGetFastestEncoding(inData)),CFStringGetLength(inData)); return; } int buff_pos = 0; while (1) { int avail_space = 8-CFDataGetLength(encrypt_buffer); //space rem in buffer int rem_to_copy = CFStringGetLength(inData)-buff_pos; //stuff in data that needs to be copied int to_copy = rem_to_copy<avail_space?rem_to_copy:avail_space; //amount left to encryp, or avail space if (avail_space) { UInt8 tmp_buff[8]; CFStringGetBytes(inData,CFRangeMake(buff_pos,to_copy),kCFStringEncodingNonLossyASCII,0,false,tmp_buff,8,NULL); CFDataAppendBytes(encrypt_buffer,tmp_buff,to_copy); avail_space -= to_copy; if (avail_space>0) // small buffer? still space left? break; buff_pos += to_copy; //move along the buffer } UInt8 enc_buff[8]; BF_ecb_encrypt(CFDataGetBytePtr(encrypt_buffer),enc_buff,&encrypt_bf_key,BF_ENCRYPT); CFWriteStreamWrite(logStream,enc_buff,8); CFDataDeleteBytes(encrypt_buffer,CFRangeMake(0,8)); if (buff_pos==CFStringGetLength(inData)) //just in case buffer happens to fit perfectly break; } return; }
extern MyInfoRef StartWWAN(ConnectClientCallBack clientCB, void *refCon) { char host[] = kTestHost; int portNum = kTestPort; CFDataRef addressData; MyStreamInfoPtr myInfoPtr; CFStreamClientContext ctxt = {0, NULL, NULL, NULL, NULL}; Boolean errorOccurred = FALSE; myInfoPtr = malloc(sizeof(MyStreamInfo)); if (!myInfoPtr) { return NULL; } // init the allocated memory memset(myInfoPtr, 0, sizeof(MyStreamInfo)); myInfoPtr->clientCB = clientCB; myInfoPtr->refCon = refCon; ctxt.info = myInfoPtr; // Check for a dotted-quad address, if so skip any host lookups in_addr_t addr = inet_addr(host); if (addr != INADDR_NONE) { // Create the streams from numberical host struct sockaddr_in sin; memset(&sin, 0, sizeof(sin)); sin.sin_len= sizeof(sin); sin.sin_family = AF_INET; sin.sin_addr.s_addr = addr; sin.sin_port = htons(portNum); addressData = CFDataCreate(NULL, (UInt8 *)&sin, sizeof(sin)); CFSocketSignature sig = { AF_INET, SOCK_STREAM, IPPROTO_TCP, addressData }; // Create the streams. CFStreamCreatePairWithPeerSocketSignature(kCFAllocatorDefault, &sig, &(myInfoPtr->rStreamRef), &(myInfoPtr->wStreamRef)); CFRelease(addressData); } else { // Create the streams from ascii host name CFStringRef hostStr = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, host, kCFStringEncodingUTF8, kCFAllocatorNull); CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, hostStr, portNum, &(myInfoPtr->rStreamRef), &(myInfoPtr->wStreamRef)); //hostStr = NULL; if(hostStr) { CFRelease(hostStr); } } myInfoPtr->isConnected = FALSE; myInfoPtr->isStreamInitd = TRUE; myInfoPtr->isClientSet = FALSE; // Inform the streams to kill the socket when it is done with it. // This effects the write stream too since the pair shares the // one socket. CFWriteStreamSetProperty(myInfoPtr->wStreamRef, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue); // set up the client if (!CFWriteStreamSetClient(myInfoPtr->wStreamRef, kCFStreamEventOpenCompleted | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered, MyCFWriteStreamClientCallBack, &ctxt)) { printf("CFWriteStreamSetClient failed\n"); errorOccurred = TRUE; } else myInfoPtr->isClientSet = TRUE; if (!errorOccurred) { // schedule the stream CFWriteStreamScheduleWithRunLoop(myInfoPtr->wStreamRef, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); // Try to open the stream. if (!CFWriteStreamOpen(myInfoPtr->wStreamRef)) { printf("CFWriteStreamOpen failed\n"); errorOccurred = TRUE; } } if (!errorOccurred) { // everything worked so far, so run the runloop - when the callback gets called, it will stop the run loop printf("CFWriteStreamOpen returned with no error - calling CFRunLoopRun\n"); CFRunLoopRun(); if (myInfoPtr->errorOccurred) errorOccurred = TRUE; printf("after CFRunLoopRun - returning\n"); } if (errorOccurred) { myInfoPtr->isConnected = FALSE; CleanupAfterWAAN(myInfoPtr); CloseStreams(myInfoPtr); if (myInfoPtr->isStreamInitd) { if(myInfoPtr->rStreamRef) CFRelease(myInfoPtr->rStreamRef); if(myInfoPtr->wStreamRef) CFRelease(myInfoPtr->wStreamRef); myInfoPtr->isStreamInitd = FALSE; } free(myInfoPtr); return NULL; } return (MyInfoRef)myInfoPtr; }
int mailstream_cfstream_set_ssl_enabled(mailstream * s, int ssl_enabled) { #if HAVE_CFNETWORK struct mailstream_cfstream_data * cfstream_data; int r; cfstream_data = (struct mailstream_cfstream_data *) s->low->data; cfstream_data->ssl_enabled = ssl_enabled; if (ssl_enabled) { CFMutableDictionaryRef settings; settings = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); switch (cfstream_data->ssl_level) { case MAILSTREAM_CFSTREAM_SSL_LEVEL_NONE: CFDictionarySetValue(settings, kCFStreamSSLLevel, kCFStreamSocketSecurityLevelNone); break; case MAILSTREAM_CFSTREAM_SSL_LEVEL_SSLv2: CFDictionarySetValue(settings, kCFStreamSSLLevel, kCFStreamSocketSecurityLevelSSLv2); break; case MAILSTREAM_CFSTREAM_SSL_LEVEL_SSLv3: CFDictionarySetValue(settings, kCFStreamSSLLevel, kCFStreamSocketSecurityLevelSSLv3); break; case MAILSTREAM_CFSTREAM_SSL_LEVEL_TLSv1: CFDictionarySetValue(settings, kCFStreamSSLLevel, kCFStreamSocketSecurityLevelTLSv1); break; case MAILSTREAM_CFSTREAM_SSL_LEVEL_NEGOCIATED_SSL: CFDictionarySetValue(settings, kCFStreamSSLLevel, kCFStreamSocketSecurityLevelNegotiatedSSL); break; } if ((cfstream_data->ssl_certificate_verification_mask & MAILSTREAM_CFSTREAM_SSL_ALLOWS_EXPIRED_CERTIFICATES) != 0) { CFDictionarySetValue(settings, kCFStreamSSLAllowsExpiredCertificates, kCFBooleanTrue); } if ((cfstream_data->ssl_certificate_verification_mask & MAILSTREAM_CFSTREAM_SSL_ALLOWS_EXPIRED_ROOTS) != 0) { CFDictionarySetValue(settings, kCFStreamSSLAllowsExpiredRoots, kCFBooleanTrue); } if ((cfstream_data->ssl_certificate_verification_mask & MAILSTREAM_CFSTREAM_SSL_ALLOWS_ANY_ROOT) != 0) { CFDictionarySetValue(settings, kCFStreamSSLAllowsAnyRoot, kCFBooleanTrue); } if ((cfstream_data->ssl_certificate_verification_mask & MAILSTREAM_CFSTREAM_SSL_DISABLE_VALIDATES_CERTIFICATE_CHAIN) != 0) { CFDictionarySetValue(settings, kCFStreamSSLValidatesCertificateChain, kCFBooleanFalse); } CFReadStreamSetProperty(cfstream_data->readStream, kCFStreamPropertySSLSettings, settings); CFWriteStreamSetProperty(cfstream_data->writeStream, kCFStreamPropertySSLSettings, settings); CFRelease(settings); } else { CFMutableDictionaryRef settings; settings = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionarySetValue(settings, kCFStreamSSLLevel, kCFStreamSocketSecurityLevelNone); CFReadStreamSetProperty(cfstream_data->readStream, kCFStreamPropertySSLSettings, settings); CFWriteStreamSetProperty(cfstream_data->writeStream, kCFStreamPropertySSLSettings, settings); CFRelease(settings); //fprintf(stderr, "is not ssl\n"); } // We need to investigate more about how to establish a STARTTLS connection. // For now, wait until we get the certificate chain. while (1) { r = wait_runloop(s->low, STATE_WAIT_SSL); if (r != WAIT_RUNLOOP_EXIT_NO_ERROR) { return -1; } if (cfstream_data->writeSSLResult < 0) return -1; if (cfstream_data->readSSLResult < 0) return -1; SecTrustRef secTrust = (SecTrustRef)CFReadStreamCopyProperty(cfstream_data->readStream, kCFStreamPropertySSLPeerTrust); if (secTrust == NULL) { // No trust, wait more. continue; } CFIndex count = SecTrustGetCertificateCount(secTrust); CFRelease(secTrust); if (count == 0) { // No certificates, wait more. continue; } break; } return 0; #else return -1; #endif }
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 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 }
int tnet_transport_wrap(tnet_transport_t *transport, int index) { transport_context_t *context = transport->context; transport_socket_t *sock = context->sockets[index]; // If the socket is already wrapped in a CFSocket then return. if (sock->cf_socket || sock->cf_read_stream) { return 1; } // Put a reference to the transport context const CFSocketContext socket_context = { 0, transport, NULL, NULL, NULL }; if (TNET_SOCKET_TYPE_IS_DGRAM(sock->type)) { // Create a CFSocket from the native socket and register for Read events sock->cf_socket = CFSocketCreateWithNative(kCFAllocatorDefault, sock->fd, kCFSocketReadCallBack, &__CFSocketCallBack, &socket_context); // Don't close the socket if the CFSocket is invalidated CFOptionFlags flags = CFSocketGetSocketFlags(sock->cf_socket); flags = flags & ~kCFSocketCloseOnInvalidate; CFSocketSetSocketFlags(sock->cf_socket, flags); // Create a new RunLoopSource and register it with the main thread RunLoop sock->cf_run_loop_source = CFSocketCreateRunLoopSource(kCFAllocatorDefault, sock->cf_socket, 0); CFRunLoopAddSource(context->cf_run_loop, sock->cf_run_loop_source, kCFRunLoopDefaultMode); CFRelease(sock->cf_run_loop_source); } else if (TNET_SOCKET_TYPE_IS_STREAM(sock->type)) { // Create a pair of streams (read/write) from the socket CFStreamCreatePairWithSocket(kCFAllocatorDefault, sock->fd, &sock->cf_read_stream, &sock->cf_write_stream); // Don't close underlying socket CFReadStreamSetProperty(sock->cf_read_stream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanFalse); CFWriteStreamSetProperty(sock->cf_write_stream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanFalse); if (TNET_SOCKET_TYPE_IS_SECURE(sock->type)) { CFMutableDictionaryRef settings = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionaryAddValue(settings, kCFStreamSSLAllowsExpiredCertificates, kCFBooleanTrue); CFDictionaryAddValue(settings, kCFStreamSSLAllowsAnyRoot, kCFBooleanTrue); CFDictionaryAddValue(settings, kCFStreamSSLValidatesCertificateChain, kCFBooleanFalse); CFDictionaryAddValue(settings, kCFStreamSSLPeerName, kCFNull); // Set the SSL settings CFReadStreamSetProperty(sock->cf_read_stream, kCFStreamPropertySocketSecurityLevel, kCFStreamSocketSecurityLevelNegotiatedSSL); CFReadStreamSetProperty(sock->cf_read_stream, kCFStreamPropertySSLSettings, settings); CFWriteStreamSetProperty(sock->cf_write_stream, kCFStreamPropertySocketSecurityLevel, kCFStreamSocketSecurityLevelNegotiatedSSL); CFWriteStreamSetProperty(sock->cf_write_stream, kCFStreamPropertySSLSettings, settings); CFRelease(settings); } #if __IPHONE_4_0 // Mark the stream for VoIP usage CFReadStreamSetProperty(sock->cf_read_stream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP); CFWriteStreamSetProperty(sock->cf_write_stream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP); #endif // Setup a context for the streams CFStreamClientContext streamContext = { 0, transport, NULL, NULL, NULL }; // Set the client callback for the stream CFReadStreamSetClient(sock->cf_read_stream, kCFStreamEventOpenCompleted | kCFStreamEventHasBytesAvailable | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered, &__CFReadStreamClientCallBack, &streamContext); CFWriteStreamSetClient(sock->cf_write_stream, kCFStreamEventOpenCompleted | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered, &__CFWriteStreamClientCallBack, &streamContext); // Enroll streams in the run-loop CFReadStreamScheduleWithRunLoop(sock->cf_read_stream, context->cf_run_loop, kCFRunLoopDefaultMode); CFWriteStreamScheduleWithRunLoop(sock->cf_write_stream, context->cf_run_loop, kCFRunLoopDefaultMode); // Release references CFRelease(sock->cf_read_stream); CFRelease(sock->cf_write_stream); CFReadStreamOpen(sock->cf_read_stream); CFWriteStreamOpen(sock->cf_write_stream); } return 0; }
int mailstream_cfstream_set_ssl_enabled(mailstream * s, int ssl_enabled) { #if HAVE_CFNETWORK struct mailstream_cfstream_data * cfstream_data; int r; cfstream_data = (struct mailstream_cfstream_data *) s->low->data; cfstream_data->ssl_enabled = ssl_enabled; if (ssl_enabled) { CFMutableDictionaryRef settings; settings = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); switch (cfstream_data->ssl_level) { case MAILSTREAM_CFSTREAM_SSL_LEVEL_NONE: CFDictionarySetValue(settings, kCFStreamSSLLevel, kCFStreamSocketSecurityLevelNone); break; case MAILSTREAM_CFSTREAM_SSL_LEVEL_SSLv2: CFDictionarySetValue(settings, kCFStreamSSLLevel, kCFStreamSocketSecurityLevelSSLv2); break; case MAILSTREAM_CFSTREAM_SSL_LEVEL_SSLv3: CFDictionarySetValue(settings, kCFStreamSSLLevel, kCFStreamSocketSecurityLevelSSLv3); break; case MAILSTREAM_CFSTREAM_SSL_LEVEL_TLSv1: CFDictionarySetValue(settings, kCFStreamSSLLevel, kCFStreamSocketSecurityLevelTLSv1); break; case MAILSTREAM_CFSTREAM_SSL_LEVEL_NEGOCIATED_SSL: CFDictionarySetValue(settings, kCFStreamSSLLevel, kCFStreamSocketSecurityLevelNegotiatedSSL); break; } if ((cfstream_data->ssl_certificate_verification_mask & MAILSTREAM_CFSTREAM_SSL_ALLOWS_EXPIRED_CERTIFICATES) != 0) { CFDictionarySetValue(settings, kCFStreamSSLAllowsExpiredCertificates, kCFBooleanTrue); } if ((cfstream_data->ssl_certificate_verification_mask & MAILSTREAM_CFSTREAM_SSL_ALLOWS_EXPIRED_ROOTS) != 0) { CFDictionarySetValue(settings, kCFStreamSSLAllowsExpiredRoots, kCFBooleanTrue); } if ((cfstream_data->ssl_certificate_verification_mask & MAILSTREAM_CFSTREAM_SSL_ALLOWS_ANY_ROOT) != 0) { CFDictionarySetValue(settings, kCFStreamSSLAllowsAnyRoot, kCFBooleanTrue); } if ((cfstream_data->ssl_certificate_verification_mask & MAILSTREAM_CFSTREAM_SSL_DISABLE_VALIDATES_CERTIFICATE_CHAIN) != 0) { CFDictionarySetValue(settings, kCFStreamSSLValidatesCertificateChain, kCFBooleanFalse); } CFReadStreamSetProperty(cfstream_data->readStream, kCFStreamPropertySSLSettings, settings); CFWriteStreamSetProperty(cfstream_data->writeStream, kCFStreamPropertySSLSettings, settings); CFRelease(settings); } else { CFMutableDictionaryRef settings; settings = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionarySetValue(settings, kCFStreamSSLLevel, kCFStreamSocketSecurityLevelNone); CFReadStreamSetProperty(cfstream_data->readStream, kCFStreamPropertySSLSettings, settings); CFWriteStreamSetProperty(cfstream_data->writeStream, kCFStreamPropertySSLSettings, settings); CFRelease(settings); //fprintf(stderr, "is not ssl\n"); } r = wait_runloop(s->low, STATE_WAIT_SSL); if (r != WAIT_RUNLOOP_EXIT_NO_ERROR) { return -1; } if (cfstream_data->writeSSLResult < 0) return -1; if (cfstream_data->readSSLResult < 0) return -1; return 0; #else return -1; #endif }
/* 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; }