La determinazione di Fiducia Con NSURLConnection e NSURLProtectionSpace

Vorrei chiedere un follow-up domanda per una prima posta la domanda. Ho il codice per creare un NSURLRequest/Connessione, eseguire e i metodi di callback per l’autenticazione chiamato. Ecco il codice specifico:

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
    return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust] || [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodDefault];
}

-(void)connection:(NSURLConnection *)connection
didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{   

    if ([challenge previousFailureCount] > 0) {
        [[challenge sender] cancelAuthenticationChallenge:challenge];
        NSLog(@"Bad Username Or Password");
        badUsernameAndPassword = YES;
        finished = YES;
        return;
    }

    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
    {
        if (appDelegate._allowInvalidCert)
        {
            //Go ahead...trust me!
            [challenge.sender useCredential:
             [NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust] 
                 forAuthenticationChallenge: challenge];
        }
        else
        {
            TrustGenerator *tg = [[TrustGenerator alloc] init];

            if ([tg getTrust:challenge.protectionSpace])
            {
                //Go ahead...trust me!
                [challenge.sender useCredential:
                 [NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust] 
                     forAuthenticationChallenge: challenge];
            }
            else {
                [[challenge sender] cancelAuthenticationChallenge:challenge];
            }
        }
    }
    else if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodDefault) {
        NSURLCredential *newCredential = [NSURLCredential credentialWithUser:_username password:_password persistence:NSURLCredentialPersistenceNone];
        [[challenge sender] useCredential:newCredential forAuthenticationChallenge:challenge];
    }
}

Quello che sto correndo è che “didReceiveAuthenticationChallenge” con “[sfida.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]” è SEMPRE di essere chiamato, anche quando il certificato del server a cui sto tentando di connettersi a è affidabile, facendo il test con un Verisign cert). Quindi quello che sto vedendo è la mia domanda è sempre chiedere conferma all’utente finale di avere fiducia anche quando il sito è attendibile. Bad karma considerando che ciò che immaginiamo per accadere con un man in the middle attack, ecc. Quello che sto cercando è un codice come questo:

        if (appDelegate._allowInvalidCert)
        {
            //Go ahead...trust me!
            [challenge.sender useCredential:
             [NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust] 
                 forAuthenticationChallenge: challenge];
        }
        else if(The OS trusts the cert on the server)
        {
             [challenge.sender useCredential:
                 [NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust] 
                     forAuthenticationChallenge: challenge];
        }
        else{...
  • Grande post! Dove posso trovare il TrustGenerator codice?
InformationsquelleAutor Staros | 2011-02-18

 

3 Replies
  1. 23

    Così ho trascorso un paio di giorni alla ricerca di questo. Sembra che mentre il NSURLConnection API non è possibile determinare se un certificato è attendibile, non c’è un metodo nella struttura di Sicurezza che handels che. Così ecco il codice che mi è venuta:

    -(void)connection:(NSURLConnection *)connection
    didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
    {   
    
        if ([challenge previousFailureCount] > 0) {
            [[challenge sender] cancelAuthenticationChallenge:challenge];
            NSLog(@"Bad Username Or Password");
            badUsernameAndPassword = YES;
            finished = YES;
            return;
        }
    
        if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
        {
    
            SecTrustResultType result;
            //This takes the serverTrust object and checkes it against your keychain
            SecTrustEvaluate(challenge.protectionSpace.serverTrust, &result);
    
            if (appDelegate._allowInvalidCert)
            {
                [challenge.sender useCredential:
                 [NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust] 
                     forAuthenticationChallenge: challenge];
            }
            //When testing this against a trusted server I got kSecTrustResultUnspecified every time. But the other two match the description of a trusted server
            else if(result == kSecTrustResultProceed || result == kSecTrustResultConfirm ||  result == kSecTrustResultUnspecified){
                [challenge.sender useCredential:
                 [NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust] 
                     forAuthenticationChallenge: challenge];
            }
            else
            {
                //Asks the user for trust
                TrustGenerator *tg = [[TrustGenerator alloc] init];
    
                if ([tg getTrust:challenge.protectionSpace])
                {
    
                    //May need to add a method to add serverTrust to the keychain like Firefox's "Add Excpetion"
                    [challenge.sender useCredential:
                     [NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust] 
                         forAuthenticationChallenge: challenge];
                }
                else {
                    [[challenge sender] cancelAuthenticationChallenge:challenge];
                }
            }
        }
        else if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodDefault) {
            NSURLCredential *newCredential = [NSURLCredential credentialWithUser:_username password:_password persistence:NSURLCredentialPersistenceNone];
            [[challenge sender] useCredential:newCredential forAuthenticationChallenge:challenge];
        }
    }
    • Questo mi aiuta, vi ringrazio molto.
    • +[NSURLCredential credentialForTrust:] crea una credenziale che è solo persiste, per la sessione, in modo che non si comportano come un ulteriore eccezione in Firefox. Una volta che l’app viene ucciso, dovrete re-fiducia esso.
    • So che questo è un vecchio post, ma ho appena notato kSecTrustResultConfirm è deprecato.
  2. 1

    Se il risultato è kSecTrustResultConfirm, che in realtà si dovrebbe chiedere all’utente se è un server di fiducia.

  3. 0

    La risposta di cui sopra funziona solo se si dispone di un CA di certificazione attendibile, perché in questo caso si utilizza la apple ammessi certificati CA per la convalida.

    Se hai i certificati autofirmati si dovrebbe usare il proprio CA certificato del server per controllare se è valido…

    Ho trovato un buon (po ‘ di confusione) qui. Esso copre anche una doppia stretta di mano….

    La speranza è di aiuto un po’!

Lascia un commento