I have a simple Java server that uses a self-signed cert to identify itself that I created with keytool:
System.setProperty("javax.net.ssl.keyStore", "../../pki/z-keystore.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "ZZZZZZ");
System.setProperty("javax.net.debug", "all");
ServerSocketFactory serverSocketFactory = SSLServerSocketFactory
.getDefault();
ServerSocket serverSocket = serverSocketFactory
.createServerSocket(8443);
System.out.println("Waiting for connections on 8443");
final AtomicInteger nextSocketId = new AtomicInteger();
while (true) {
final Socket socket = serverSocket.accept();
new Thread(new Runnable() {
@Override
public void run() {
final int socketId = nextSocketId.getAndIncrement();
try {
System.out.println("Received connection from socketId: " + socketId);
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
PrintWriter printWriter = new PrintWriter(
new OutputStreamWriter(socket.getOutputStream()));
for (String line = bufferedReader.readLine(); line != null; line = bufferedReader
.readLine()) {
System.out.println("Read: " + line);
printWriter.println("Read: " + line);
}
bufferedReader.close();
printWriter.close();
} catch (SSLHandshakeException e) {
// don't care
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Closed connection from socketId: " + socketId);
}
}).start();
}
I connect to it with a simple ios client running in the iphone simulator:
- (void) connectSecurely {
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL,
(CFStringRef)@"mcheath.local",
8443,
&readStream,
&writeStream);
NSDictionary *sslSettings = [NSDictionary dictionaryWithObjectsAndKeys:
(id)kCFBooleanFalse, (id)kCFStreamSSLValidatesCertificateChain,
nil];
CFReadStreamSetProperty(readStream,
kCFStreamPropertySSLSettings,
sslSettings);
/* Turning on this setting makes the SSL handshake fail with OSStatus -9807 */
CFReadStreamSetProperty(readStream,
kCFStreamPropertySocketSecurityLevel,
kCFStreamSocketSecurityLevelNegotiatedSSL);
self.inputStream = (NSInputStream *)readStream;
self.outputStream = (NSOutputStream *)writeStream;
[self.inputStream setDelegate:self];
[self.outputStream setDelegate:self];
[self.inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[self.outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
CFReadStreamOpen(readStream);
CFWriteStreamOpen(writeStream);
}
#pragma mark -
#pragma mark NSStreamDelegate
- (void)stream:(NSStream *)aStream
handleEvent:(NSStreamEvent)eventCode {
switch (eventCode) {
case NSStreamEventNone:
NSLog(@"NSStreamEventNone");
break;
case NSStreamEventOpenCompleted:
NSLog(@"NSStreamEventOpenCompleted");
break;
case NSStreamEventHasBytesAvailable:
NSLog(@"NSStreamEventHasBytesAvailable");
break;
case NSStreamEventHasSpaceAvailable:
NSLog(@"NSStreamEventHasSpaceAvailable");
break;
case NSStreamEventErrorOccurred:
NSLog(@"NSStreamEventErrorOccurred: %@", [aStream streamError]);
NSLog(@"SSL Settings: %@", [aStream propertyForKey:(NSString *) kCFStreamPropertySSLSettings]);
break;
case NSStreamEventEndEncountered:
NSLog(@"NSStreamEventEndEncountered");
break;
default:
break;
}
}
Why does setting kCFStreamPropertySocketSecurityLevel to kCFStreamSocketSecurityLevelNegotiatedSSL cause my SSL handshake to fail?