Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
357 views
in Technique[技术] by (71.8m points)

ios - Problems with SSL Pinning and AFNetworking 2.5.0 (NSURLErrorDomain error -1012.)

We’ve been having a hard time securing our app’s network connections with SSL using AFNetworking 2.5.0.

We use a self-signed certificate authority and implemented a custom security policy using pinned certificates.

We’ve tested quite a few configurations provided by AFNetworking but have not been lucky so far. The error message we receive is:

2015-01-05 19:03:07.191 AppName[9301:319051] Error updating user journey. Error: Error Domain=NSURLErrorDomain Code=-1012 "The operation couldn’t be completed. (NSURLErrorDomain error -1012.)" UserInfo=0x7ae056b0 {NSErrorFailingURLKey=https://api.XXX.com/XXX/XXX/, NSErrorFailingURLStringKey=https://api.XXX.com/XXX/XXX/}

Our certificate works fine on other clients such as cURL and Android. When using HTTP, our implementation works perfectly fine too.

Is anyone aware of any issues related to pinned certificates and AFNetworking? If yes, we’d appreciate any pointers you may have.

Here's part of the implementation:

+ (AFSecurityPolicy*)customSecurityPolicy {
   AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
   NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"filename" ofType:@"der"];
   NSData *certData = [NSData dataWithContentsOfFile:cerPath];
   [securityPolicy setAllowInvalidCertificates:NO];
   [securityPolicy setValidatesCertificateChain:NO];
   [securityPolicy setPinnedCertificates:@[certData]];
   return securityPolicy;
}

+ (AFHTTPRequestOperationManager*)customHttpRequestOperationManager {
   AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
   manager.securityPolicy = [self customSecurityPolicy]; // SSL
   return manager;
}

+(void)getRequestWithUrl:(NSString*)url success:(void(^)(AFHTTPRequestOperation *operation, id responseObject))success failure:(void(^) (AFHTTPRequestOperation *operation, NSError *error))failure {
   [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
   AFHTTPRequestOperationManager *manager = [HttpClient customHttpRequestOperationManager];
   manager.responseSerializer = [AFHTTPResponseSerializer serializer];
   [manager GET:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
       [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
       success(operation, responseObject);
   } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
       [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
       failure(operation, error);
   }];
}

Thank you!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

After reading through the AFNetworking code & and checking the change logs, here's what I had to do to get this working.

Create your AFSecurityPolicy object with AFSSLPinningModeCertificate:

AFSecurityPolicy* policy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];

By default, AFNetworking will validate the domain name of the certificate. Our certificates are generated on a per-server basis, and not all of them will have a domain name, so we need to disable that:

[policy setValidatesDomainName:NO];

Since the certificates are self-signed, they are technically 'invalid', so we need to allow that as well:

[policy setAllowInvalidCertificates:YES];

Lastly, AFNetworking will attempt to validate the certificate all the way up the certificate chain, which to me seems like it would only go up the chain to OUR CA, but for whatever reason it doesn't, so we have to disable that too:

[policy setValidatesCertificateChain:NO];

And that's it! Set the security policy in your request manager like you're already doing and it should work fine.

So, recap, all you really need to change in the code you posted is this:

A) As David Caunt mentioned, change your pinning mode from AFSSLPinningModeNone to AFSSLPinningModeCertificate

and

B) Add the line to disable validating the domain name: [policy setValidatesDomainName:NO]

Another note, AFNetworking now automatically checks your bundle for .cer files, so if you were to rename your certificate to have a .cer extension, you can eliminate the code to get the certificate data out of the bundle and set the pinned certificates.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...