Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix cert checking in iOS 6 and some general cleanup. #39

Merged
merged 1 commit into from
May 22, 2014
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 30 additions & 23 deletions Stripe/STPAPIConnection.m
Original file line number Diff line number Diff line change
Expand Up @@ -85,19 +85,20 @@ - (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectio
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
[challenge.sender performDefaultHandlingForAuthenticationChallenge:challenge];

NSURLCredential *urlCredential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
[challenge.sender useCredential:urlCredential forAuthenticationChallenge:challenge];

SecTrustRef serverTrust = [[challenge protectionSpace] serverTrust];
SecTrustResultType resultType;
SecTrustEvaluate(serverTrust, &resultType);

// Check for revocation manually since CFNetworking doesn't. (see https://revoked.stripe.com for more)
for (CFIndex i = 0, count = SecTrustGetCertificateCount(serverTrust); i < count; i++) {
NSError *error = nil;
[self.class verifyCertificate:SecTrustGetCertificateAtIndex(serverTrust, i) forChallenge:challenge error:&error];
if (error) {
_overrideError = error;
if ([self.class isCertificateBlacklisted:SecTrustGetCertificateAtIndex(serverTrust, i)]) {
_overrideError = [self.class blacklistedCertificateError];
[challenge.sender cancelAuthenticationChallenge:challenge];
return;
}
}

[challenge.sender performDefaultHandlingForAuthenticationChallenge:challenge];
}
}

Expand All @@ -111,24 +112,18 @@ + (NSArray *)certificateBlacklist
];
}

+ (void)verifyCertificate:(SecCertificateRef)certificate forChallenge:(NSURLAuthenticationChallenge *)challenge error:(NSError **)error
+ (BOOL)isCertificateBlacklisted:(SecCertificateRef)certificate
{
return [[self certificateBlacklist] containsObject:[self SHA1FingerprintOfCertificateData:certificate]];
}

+ (NSString *)SHA1FingerprintOfCertificateData:(SecCertificateRef)certificate
{
CFDataRef data = SecCertificateCopyData(certificate);
NSString *fingerprint = [self.class SHA1FingerprintOfData:(__bridge NSData *) data];
NSString *fingerprint = [self SHA1FingerprintOfData:(__bridge NSData *) data];
CFRelease(data);

if ([[self certificateBlacklist] containsObject:fingerprint]) {
*error = [[NSError alloc] initWithDomain:StripeDomain
code:STPConnectionError
userInfo:@{
NSLocalizedDescriptionKey : STPUnexpectedError,
STPErrorMessageKey : @"Invalid server certificate. You tried to connect to a server "
"that has a revoked SSL certificate, which means we cannot securely send data to that server. "
"Please email support@stripe.com if you need help connecting to the correct API server."
}];

[[challenge sender] cancelAuthenticationChallenge:challenge];
}
return fingerprint;
}

+ (NSString *)SHA1FingerprintOfData:(NSData *)data
Expand All @@ -150,4 +145,16 @@ + (NSString *)SHA1FingerprintOfData:(NSData *)data
return [output lowercaseString];
}

+ (NSError *)blacklistedCertificateError
{
return [[NSError alloc] initWithDomain:StripeDomain
code:STPConnectionError
userInfo:@{
NSLocalizedDescriptionKey : STPUnexpectedError,
STPErrorMessageKey : @"Invalid server certificate. You tried to connect to a server "
"that has a revoked SSL certificate, which means we cannot securely send data to that server. "
"Please email support@stripe.com if you need help connecting to the correct API server."
}];
}

@end