2012-11-23 14 views
6

Sto utilizzando CFStream/NSStream per effettuare connessioni http. Voglio essere in grado di rilevare che un handshake SSL non riesce per tre casi:Come configurare CFStream (o NSStream) per l'handshake SSL?

  • caso A: server non è affidabile
  • caso B: il server è attendibile, ma chiede un certificato client
  • caso C: server non è attendibile e chiede un certificato client

Oggi senza fare anithing sulle Proprietà SSL della mia CFStream, ottengo:

  • caso A: Errore -9807
  • caso B: nessun errore ma il server rifiuta la connessione (errore 500)
  • caso C: errore 9807

C'è un modo per configurare CFStream di distinguere correttamente questi 3 casi? O per avere alcuni callback durante l'handshake SSL?

Grazie per il vostro aiuto.

risposta

4

Qualche tempo fa mi sono imbattuto in una stessa cosa con CFSocket usando SSL. CFStream gestisce tutte le cose della stretta di mano. Ho scritto una piccola aggiunta di classe per NSStream (il codice base viene da Apple, non ho più il link, se lo trovo lo aggiungerò). Questo è quello che ha funzionato per me.

interfaccia

@interface NSStream (FSNetworkAdditions) 

+ (void)qNetworkAdditions_getStreamsToHostNamed:(NSString *)hostName 
              port:(NSInteger)port 
            inputStream:(out NSInputStream **)inputStreamPtr 
            outputStream:(out NSOutputStream **)outputStreamPtr; 

@end 

e l'attuazione

#import "FSNetworkAdditions.h" 

@implementation NSStream (FSNetworkAdditions) 

+ (void)qNetworkAdditions_getStreamsToHostNamed:(NSString *)hostName 
              port:(NSInteger)port 
            inputStream:(out NSInputStream **)inputStreamPtr 
            outputStream:(out NSOutputStream **)outputStreamPtr 
{ 
    CFReadStreamRef  readStream; 
    CFWriteStreamRef writeStream; 

    assert(hostName != nil); 
    assert((port > 0) && (port < 65536)); 
    assert((inputStreamPtr != NULL) || (outputStreamPtr != NULL)); 

    readStream = NULL; 
    writeStream = NULL; 

    CFStreamCreatePairWithSocketToHost(
             NULL, 
             (CFStringRef) hostName, 
             port, 
             ((inputStreamPtr != NULL) ? &readStream : NULL), 
             ((outputStreamPtr != NULL) ? &writeStream : NULL) 
             ); 

    NSDictionary *settings = [[NSDictionary alloc] initWithObjectsAndKeys: 
           [NSNumber numberWithBool:YES], kCFStreamSSLAllowsExpiredCertificates, 
           [NSNumber numberWithBool:YES], kCFStreamSSLAllowsAnyRoot, 
           [NSNumber numberWithBool:YES], kCFStreamSSLAllowsExpiredRoots, 
           [NSNumber numberWithBool:NO], kCFStreamSSLValidatesCertificateChain, 
           //kCFNull,kCFStreamSSLPeerName, 
           kCFStreamSocketSecurityLevelSSLv3, kCFStreamSSLLevel, 
           [NSNumber numberWithBool:YES], kCFStreamPropertyShouldCloseNativeSocket, 
           nil]; 

    if (readStream) { 
     CFReadStreamSetProperty(readStream, kCFStreamPropertySSLSettings, (CFTypeRef)settings); 
    } 

    if (writeStream) { 
     CFWriteStreamSetProperty(writeStream, kCFStreamPropertySSLSettings, (CFTypeRef)settings); 
    } 

    if (inputStreamPtr != NULL) { 
     *inputStreamPtr = CFBridgingRelease(readStream); 
    } 
    if (outputStreamPtr != NULL) { 
     *outputStreamPtr = CFBridgingRelease(writeStream); 
    } 


} 

@end 

Questo è tutto non è possibile connettersi a un server come questo:

NSInputStream *inputStream; 
NSOutputStream *outputStream; 
[NSStream qNetworkAdditions_getStreamsToHostNamed:host 
              port:port 
             inputStream:&inputStream 
            outputStream:&outputStream]; 

     inputStream.delegate = self; 
     outputStream.delegate = self; 

Dove "sé" è conforme al protocollo NSStreamDelegate.

Spero che questi frammenti siano d'aiuto.

+1

Ecco il link ai documenti Apple a cui fa riferimento Arndt: https://developer.apple.com/library/ios/qa/qa1652/_index.html – Fletch