kCFStreamPropertySocketSecurityLevel to kCFStreamS

2019-06-08 00:08发布

问题:

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?

回答1:

The answer is from cocoa-unbound. I need to set kCFStreamPropertySocketSecurityLevel first because setting it reverts my kCFStreamPropertySSLSettings to defaults. Of course, the documentation mentions nothing of this.



回答2:

OSStatus -9807 is:

errSSLXCertChainInvalid     = -9807,    /* Invalid certificate chain */

Your client is unable to verify the validity of the self-signed certificate.