From 872c31493c7d197d9fb0fe0314a102cd461f2e05 Mon Sep 17 00:00:00 2001 From: Robert Sesek Date: Sun, 1 Jan 2017 01:37:40 -0500 Subject: [PATCH] Add small program to help debug TLS issues using a non-Go stack. --- deployment/tlstest.mm | 151 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 deployment/tlstest.mm diff --git a/deployment/tlstest.mm b/deployment/tlstest.mm new file mode 100644 index 0000000..59805ba --- /dev/null +++ b/deployment/tlstest.mm @@ -0,0 +1,151 @@ +// clang++ tlstest.mm -o tlstest -framework Foundation -framework Security -std=c++11 + +#include +#import +#include + +struct StreamPair { + NSInputStream* in; + NSOutputStream* out; +}; + +const size_t kBufferSize = 1024; + +NSString* ReadBuffer(NSInputStream* stream) { + uint8_t buf[kBufferSize]; + NSInteger bytes_read = [stream read:buf maxLength:sizeof(buf)]; + NSString* line = [[[NSString alloc] initWithBytes:buf + length:bytes_read + encoding:NSASCIIStringEncoding] autorelease]; + NSLog(@">>> %@", line); + return line; +} + +void WriteLine(NSOutputStream* stream, NSString* line) { + NSLog(@"<<< %@", line); + [stream write:(const uint8_t*)[line UTF8String] maxLength:[line length]]; + const uint8_t nl = '\n'; + [stream write:&nl maxLength:1]; +} + +OSStatus MySSLRead(SSLConnectionRef conn, void* data, size_t* data_len) { + NSInputStream* stream = ((StreamPair*)conn)->in; + *data_len = [stream read:(uint8_t*)data maxLength:*data_len]; + return noErr; +} + +OSStatus MySSLWrite(SSLConnectionRef conn, const void* data, size_t* data_len) { + NSOutputStream* stream = ((StreamPair*)conn)->out; + *data_len = [stream write:(uint8_t*)data maxLength:*data_len]; + return noErr; +} + +NSString* ReadBuffer(SSLContextRef tlsctx) { + uint8_t buf[kBufferSize]; + size_t data_len; + OSStatus status = SSLRead(tlsctx, buf, sizeof(buf), &data_len); + if (status != noErr) { + NSLog(@"SSLRead error: %d", status); + return nil; + } + + NSString* line = [[[NSString alloc] initWithBytes:buf + length:data_len + encoding:NSASCIIStringEncoding] autorelease]; + NSLog(@">+> %@", line); + return line; +} + +void WriteLine(SSLContextRef tlsctx, NSString* line) { + NSLog(@"<+< %@", line); + size_t processed; + OSStatus status = SSLWrite(tlsctx, [line UTF8String], [line length], &processed); + if (status != noErr) { + NSLog(@"SSLWrite error: %d", status); + return; + } + + const char nl = '\n'; + status = SSLWrite(tlsctx, &nl, 1, &processed); + if (status != noErr) { + NSLog(@"SSLWrite error: %d", status); + return; + } +} + +int main() { + CFReadStreamRef read_cf; + CFWriteStreamRef write_cf; + CFStreamCreatePairWithSocketToHost(NULL, CFSTR("localhost"), 9925, &read_cf, &write_cf); + + NSInputStream* is = (NSInputStream*)read_cf; + NSOutputStream* os = (NSOutputStream*)write_cf; + + [is open]; + [os open]; + + ReadBuffer(is); + WriteLine(os, @"EHLO tlstest"); + ReadBuffer(is); + + StreamPair pair = { is, os }; + + SSLContextRef tlsctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType); + SSLSetIOFuncs(tlsctx, MySSLRead, MySSLWrite); + SSLSetConnection(tlsctx, &pair); + SSLSetSessionOption(tlsctx, kSSLSessionOptionBreakOnServerAuth, true); + + WriteLine(os, @"STARTTLS"); + ReadBuffer(is); + + // Skip trust verification. + OSStatus handshake = SSLHandshake(tlsctx); + NSLog(@"SSL Handshake = %d", handshake); + if (handshake == errSSLServerAuthCompleted) { + handshake = SSLHandshake(tlsctx); + NSLog(@"SSL Handshake = %d", handshake); + } + + ReadBuffer(tlsctx); + WriteLine(tlsctx, @"EHLO tlstest-tls"); + + ReadBuffer(tlsctx); + ReadBuffer(tlsctx); + + WriteLine(tlsctx, @"MAIL FROM:"); + ReadBuffer(tlsctx); + + WriteLine(tlsctx, @"RCPT TO:"); + ReadBuffer(tlsctx); + + WriteLine(tlsctx, @"DATA"); + sleep(10); + ReadBuffer(tlsctx); + + WriteLine(tlsctx, @"More data"); + WriteLine(tlsctx, @"and some more"); + WriteLine(tlsctx, @"more more more"); + WriteLine(tlsctx, @"adfasdf;lan io;aweofani ef;awe"); + WriteLine(tlsctx, @"adfasdf;lan io;aweofani ef;awe"); + WriteLine(tlsctx, @"adfasdf;lan io;aweofani ef;awe"); + WriteLine(tlsctx, @"adfasdf;lan io;aweofani ef;awe"); + WriteLine(tlsctx, @"adfasdf;lan io;aweofani ef;awe"); + WriteLine(tlsctx, @"adfasdf;lan io;aweofani ef;awe"); + WriteLine(tlsctx, @"adfasdf;lan io;aweofani ef;awe"); + WriteLine(tlsctx, @"adfasdf;lan io;aweofani ef;awe"); + WriteLine(tlsctx, @"adfasdf;lan io;aweofani ef;awe"); + WriteLine(tlsctx, @"adfasdf;lan io;aweofani ef;awe"); + WriteLine(tlsctx, @"adfasdf;lan io;aweofani ef;awe"); + WriteLine(tlsctx, @"adfasdf;lan io;aweofani ef;awe"); + WriteLine(tlsctx, @"."); + + ReadBuffer(tlsctx); + + WriteLine(tlsctx, @"QUIT"); + ReadBuffer(tlsctx); + + SSLClose(tlsctx); + + [is close]; + [os close]; +} -- 2.22.5