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?