Changeset 3700


Ignore:
Timestamp:
11/23/12 11:24:58 (17 months ago)
Author:
koke
Message:

Add support for self-signed certificates

Instead of just throwing a generic error, we give the option to continue connecting.
I think the current API for iOS doesn't allow us to store trust permanently, so the alert will show again when the app relaunches.

It's not ideal but at least sites with self-signed or invalid certificates can be used if the user wants to.

fixes #1306

Location:
trunk/WordPressApi
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/WordPressApi/AFAuthenticationAlertView.m

    r3633 r3700  
    1616 
    1717- (id)initWithChallenge:(NSURLAuthenticationChallenge *)challenge { 
    18     self = [super initWithTitle:NSLocalizedString(@"Authentication required", @"Popup title to ask for user credentials.") 
    19                 message:NSLocalizedString(@"Please enter your credentials", @"Popup message to ask for user credentials (fields shown below).") 
    20                delegate:self 
    21       cancelButtonTitle:NSLocalizedString(@"Cancel", @"Cancel button label.") 
    22       otherButtonTitles:NSLocalizedString(@"Log In", @"Log In button label."), nil]; 
     18    self = [super initWithTitle:nil 
     19                        message:nil 
     20                       delegate:self 
     21              cancelButtonTitle:NSLocalizedString(@"Cancel", @"Cancel button label.") 
     22              otherButtonTitles:nil]; 
     23 
    2324    if (self) { 
    2425        _challenge = challenge; 
    25          
    26         self.alertViewStyle = UIAlertViewStyleLoginAndPasswordInput; 
     26 
     27        if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { 
     28            self.alertViewStyle = UIAlertViewStyleDefault; 
     29            self.title = NSLocalizedString(@"Certificate error", @"Popup title for wrong SSL certificate."); 
     30            self.message = [NSString stringWithFormat:NSLocalizedString(@"The certificate for this server is invalid. You might be connecting to a server that is pretending to be “%@” which could put your confidential information at risk.\n\nWould you like to trust the certificate anyway?", @""), challenge.protectionSpace.host]; 
     31            [self addButtonWithTitle:NSLocalizedString(@"Trust", @"Connect when the SSL certificate is invalid")]; 
     32        } else { 
     33            self.alertViewStyle = UIAlertViewStyleLoginAndPasswordInput; 
     34            self.title = NSLocalizedString(@"Authentication required", @"Popup title to ask for user credentials."); 
     35            self.message = NSLocalizedString(@"Please enter your credentials", @"Popup message to ask for user credentials (fields shown below)."); 
     36            [self addButtonWithTitle:NSLocalizedString(@"Log In", @"Log In button label.")]; 
     37        } 
    2738    } 
    2839    return self; 
     
    3243-(void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animated { 
    3344    if (buttonIndex == 1) { 
    34         NSString *username, *password; 
    35         if ([self respondsToSelector:@selector(setAlertViewStyle:)]) { 
    36             username = [[self textFieldAtIndex:0] text]; 
    37             password = [[self textFieldAtIndex:1] text]; 
     45        NSURLCredential *credential; 
     46        if ([_challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { 
     47            credential = [NSURLCredential credentialForTrust:_challenge.protectionSpace.serverTrust]; 
    3848        } else { 
    39             username = usernameField.text; 
    40             password = passwordField.text; 
     49            NSString *username, *password; 
     50            if ([self respondsToSelector:@selector(setAlertViewStyle:)]) { 
     51                username = [[self textFieldAtIndex:0] text]; 
     52                password = [[self textFieldAtIndex:1] text]; 
     53            } else { 
     54                username = usernameField.text; 
     55                password = passwordField.text; 
     56            } 
     57            credential = [NSURLCredential credentialWithUser:username password:password persistence:NSURLCredentialPersistencePermanent]; 
    4158        } 
    42          
    43         NSURLCredential *credential = [NSURLCredential credentialWithUser:username password:password persistence:NSURLCredentialPersistencePermanent]; 
     59 
    4460        [[NSURLCredentialStorage sharedCredentialStorage] setDefaultCredential:credential forProtectionSpace:[_challenge protectionSpace]]; 
    4561        [[_challenge sender] useCredential:credential forAuthenticationChallenge:_challenge]; 
  • trunk/WordPressApi/AFXMLRPCClient.m

    r3633 r3700  
    201201    [operation setCompletionBlockWithSuccess:xmlrpcSuccess failure:xmlrpcFailure]; 
    202202    [operation setAuthenticationChallengeBlock:^(NSURLConnection *connection, NSURLAuthenticationChallenge *challenge) { 
    203         NSURLCredential *credential = [[NSURLCredentialStorage sharedCredentialStorage] defaultCredentialForProtectionSpace:[challenge protectionSpace]]; 
    204          
    205         if ([challenge previousFailureCount] == 0 && credential) { 
    206             [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge]; 
     203        if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { 
     204            // Handle invalid certificates 
     205            SecTrustResultType result; 
     206            OSStatus certificateStatus = SecTrustEvaluate(challenge.protectionSpace.serverTrust, &result); 
     207            if (certificateStatus == 0 && result == kSecTrustResultRecoverableTrustFailure) { 
     208                dispatch_async(dispatch_get_main_queue(), ^(void) { 
     209                    AFAuthenticationAlertView *alert = [[AFAuthenticationAlertView alloc] initWithChallenge:challenge]; 
     210                    [alert show]; 
     211                }); 
     212            } else { 
     213                [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge]; 
     214            } 
    207215        } else { 
    208             dispatch_async(dispatch_get_main_queue(), ^(void) { 
    209                 AFAuthenticationAlertView *alert = [[AFAuthenticationAlertView alloc] initWithChallenge:challenge]; 
    210                 [alert show]; 
    211             }); 
    212         }         
     216            NSURLCredential *credential = [[NSURLCredentialStorage sharedCredentialStorage] defaultCredentialForProtectionSpace:[challenge protectionSpace]]; 
     217 
     218            if ([challenge previousFailureCount] == 0 && credential) { 
     219                [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge]; 
     220            } else { 
     221                dispatch_async(dispatch_get_main_queue(), ^(void) { 
     222                    AFAuthenticationAlertView *alert = [[AFAuthenticationAlertView alloc] initWithChallenge:challenge]; 
     223                    [alert show]; 
     224                }); 
     225            } 
     226        } 
     227    }]; 
     228    [operation setAuthenticationAgainstProtectionSpaceBlock:^BOOL(NSURLConnection *connection, NSURLProtectionSpace *protectionSpace) { 
     229        // We can handle any authentication available except Client Certificates 
     230        return ![protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodClientCertificate]; 
    213231    }]; 
    214232 
Note: See TracChangeset for help on using the changeset viewer.