static ssize_t mailstream_low_cfstream_write(mailstream_low * s, const void * buf, size_t count) { #if HAVE_CFNETWORK struct mailstream_cfstream_data * cfstream_data; int r; cfstream_data = (struct mailstream_cfstream_data *) s->data; cfstream_data->writeBuffer = buf; cfstream_data->writeBufferSize = count; if (cfstream_data->cancelled) return -1; if (CFWriteStreamCanAcceptBytes(cfstream_data->writeStream)) { writeDataToStream(s); return cfstream_data->writeResult; } r = wait_runloop(s, STATE_WAIT_WRITE); if (r != WAIT_RUNLOOP_EXIT_NO_ERROR) { return -1; } return cfstream_data->writeResult; #else return -1; #endif }
static ssize_t mailstream_low_cfstream_read(mailstream_low * s, void * buf, size_t count) { #if HAVE_CFNETWORK struct mailstream_cfstream_data * cfstream_data; int r; cfstream_data = (struct mailstream_cfstream_data *) s->data; cfstream_data->readBuffer = buf; cfstream_data->readBufferSize = count; if (cfstream_data->cancelled) { return -1; } if (CFReadStreamHasBytesAvailable(cfstream_data->readStream)) { readDataFromStream(s); return cfstream_data->readResult; } r = wait_runloop(s, STATE_WAIT_READ); if (r != WAIT_RUNLOOP_EXIT_NO_ERROR) { return -1; } return cfstream_data->readResult; #else return -1; #endif }
static int low_open(mailstream_low * s) { struct mailstream_cfstream_data * cfstream_data; int r; cfstream_data = (struct mailstream_cfstream_data *) s->data; CFReadStreamOpen(cfstream_data->readStream); CFWriteStreamOpen(cfstream_data->writeStream); r = wait_runloop(s, STATE_WAIT_OPEN); if (r != WAIT_RUNLOOP_EXIT_NO_ERROR) { return -1; } if (cfstream_data->writeOpenResult < 0) return -1; if (cfstream_data->readOpenResult < 0) return -1; return 0; }
int mailstream_low_cfstream_wait_idle(mailstream_low * low, int max_idle_delay) { #if HAVE_CFNETWORK struct mailstream_cfstream_data * cfstream_data; int r; cfstream_data = (struct mailstream_cfstream_data *) low->data; cfstream_data->idleMaxDelay = max_idle_delay; r = wait_runloop(low, STATE_WAIT_IDLE); switch (r) { case WAIT_RUNLOOP_EXIT_TIMEOUT: return MAILSTREAM_IDLE_TIMEOUT; case WAIT_RUNLOOP_EXIT_INTERRUPTED: return MAILSTREAM_IDLE_INTERRUPTED; case WAIT_RUNLOOP_EXIT_CANCELLED: return MAILSTREAM_IDLE_CANCELLED; } return MAILSTREAM_IDLE_HASDATA; #else return MAILSTREAM_IDLE_ERROR; #endif }
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 }
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 }