How to disable sslv3 for NSURLconnection or NSURLSession - ios

With respect to the recent security threat with SSLV3,https://isc.sans.edu/forums/diary/OpenSSL+SSLv3+POODLE+Vulnerability+Official+Release/18827
How can I make NSURLconnection communication secure from this threat?
Can I disable sslv3 programmaticaly in iOS?
Is there any way in iOS by which I can get the supported security protocol list from server url?

I have figure out the way to set it into NSURLSession but still struggling with NSURLConnection.
NSURLSessionConfiguration *config =
[NSURLSessionConfiguration defaultSessionConfiguration];
config.TLSMaximumSupportedProtocol = kTLSProtocol12;
config.TLSMinimumSupportedProtocol = kTLSProtocol12
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig];

Depending on how you connect try to use kCFStreamSocketSecurityLevelTLSv1 instead of kCFStreamSocketSecurityLevelNegotiatedSSL.

Related

NSURLSessionDownloadTask switching from http to https

I have an AFHTTPSessionManager created NSURLSessionDownloadTask being used to download a video within an app that sometimes when initialized with an http:80 url will convert it to https:443. This is happening before any connection attempt is being made (I added a custom HTTP protocol class via NSURLSessionConfiguration to the session in order to log when the connection is being made).
By the time the request makes it to the
-(NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response
delegate method of my CustomHTTPProtocolDelegate class, the request has been changed to https.
App Transport Security is disabled (NSAllowsArbitraryLoads=true) and this behavior seems to be associated with a particular http-only server (other http-only server have no issue, and the connection is made as http on port 80).
Any idea of what could be going on? Anything else I could do to debug?
Here is how the download task is being created (including the debug custom protocol class):
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLSessionConfiguration* config = [NSURLSessionConfiguration ephemeralSessionConfiguration];
config.protocolClasses = #[[CustomHTTPProtocol class]];
AFHTTPSessionManager *session = [[AFHTTPSessionManager manager] initWithSessionConfiguration:config];
self.downloadTask = [session downloadTaskWithRequest:request progress:&progress destination:^NSURL *(NSURL *targetPath, NSURLResponse *response){
...
[UPDATE]
This issue is causing us a number of headaches, so to help facilitate troubleshooting, I created a small test project to help narrow in on the problem. My simple project does two things, loads a url into a UIWebView and downloads a file using NSURLSessionDownloadTask. The urls for these actions follow this pattern:
WebView URL: https://console.company.com/home.html
Download URL: http://data.company.com/file.txt
And those hostnames resolve to different IPs (different servers).
If I download the file before navigating the webview, then everything is fine, but if the webview loads its URL first, then the download URL will be switched to HTTPS automatically and the initial request for data will fail. One thought we had was that once iOS opens a TLS tunnel for the HTTPS connection that the webview is creating, that it tries to use that same tunnel for all subsequent *.company.com connections. Or at the very least, it assumes all *.company.com connections must also be TLS.
Figured it out. Both servers were sending a HSTS header for all subdomains. Because the networking layer under NSURLSession observes this header, the calls to the HTTP server were being upgraded to HTTPS prior to leaving the client.

URLSession background upload task keeps resetting

I am experiencing some weird behaviour when using an uploadTask for a URLSessionConfiguration.background.
My custom delegate is implementing all of the delegate methods that belong to URLSessionDelegate, URLSessionTaskDelegate, and URLSessionDataDelegate. All of them has a print statement indicating that the method has been called.
I am trying to upload five images to a server, each of them has their own session with an id matching the image id.
The problem is that when uploading using a very slow connection "edge", the upload progress will reset before reaching 100% This happens whenever didFinishCollectingMetrics is called as you can see here: Data
This does not happen all the time when using a slow connection but only some of the time.
Anyone got any ideas as to what is happening here?
Edge networking is notoriously unreliable, and frequent upload failures are not atypical. The way you solve this is by replacing whole-file-based uploads with some form of chunked uploads so that you can continue the upload where you left off, but that requires server support.
Increase time-out of NSURLSession for request and resource:
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
[configuration setTimeoutIntervalForRequest:120];
[configuration setTimeoutIntervalForResource:240];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
Use session to upload your image

ios FTP upload using NSURLSession

I am trying to upload files via FTP to server. According to
Apple Documentation NSURLSession class supports FTP operations.
There is a famous Apple Developer blog which also supports that. But still its not clear whether NSURLSession API's supports ftp upload or not? (I tried with the way suggested and getting error).
With the conventional way of CFFTPStreamRef, ftp upload works fine but it's deprecated in 9.0. The header says: CF_DEPRECATED(10_3, 10_11, 2_0, 9_0 , "Use NSURLSessionAPI for ftp requests")
Any idea, example or link to get help with. I am trying something like this for now:
NSURL *url_upload = [NSURL URLWithString:#"ftp://username:password#thelink/myfolder/filename.zip"];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url_upload];
[request setHTTPMethod:#"PUT"];
NSURL *docsDirURL = [NSURL fileURLWithPath:filePath];
NSURLProtectionSpace * protectionSpace = [[NSURLProtectionSpace alloc] initWithHost:url_upload.host port:[url_upload.port integerValue] protocol:url_upload.scheme realm:nil authenticationMethod:nil];
NSURLCredential *cred = [NSURLCredential
credentialWithUser:userId
password:password
persistence:NSURLCredentialPersistenceForSession];
NSURLCredentialStorage * cred_storage ;
[cred_storage setCredential:cred forProtectionSpace:protectionSpace];
NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfig.URLCredentialStorage = cred_storage;
sessionConfig.timeoutIntervalForRequest = 30.0;
sessionConfig.timeoutIntervalForResource = 60.0;
sessionConfig.allowsCellularAccess = YES;
sessionConfig.HTTPMaximumConnectionsPerHost = 1;
NSURLSession *upLoadSession = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:nil];
NSURLSessionUploadTask *uploadTask = [upLoadSession uploadTaskWithRequest:request fromFile:docsDirURL];
[uploadTask resume];
To the best of my recollection, NSURLSession (and NSURLConnection) support retrieving files via FTP, but do not support any other FTP commands, such as STOR (note that PUT is an HTTP method, not an FTP method).
For your purposes, your options are to either use the CFFTPStream API (which only barely works) or stop using FTP.
My strong recommendation would be to stop using FTP. The FTP protocol is hopelessly insecure, sending the username and password in cleartext form over the wire, which makes it really easy for people to sniff the credentials and masquerade as the user. So the only situation where an FTP upload would be even remotely acceptable these days is an anonymous FTP upload to a shared dropbox, and even then, it is somewhat dubious. That's why the functionality was never added to the NSURLConnection API, much less NSURLSession.
There are much better alternatives that are much more secure, such as WebDAV over HTTPS, POST request uploads over HTTPS, WebDAV or POST requests with digest authentication, etc. And those alternatives are actually supportable with NSURLSession and provide other advantages like the ability to resume downloads. Unless you have absolutely no way to change the server side, please use one of those alternatives instead.

NSUrlSession: is it possible to upload files in the background?

Using NSUrlSession with a background configuration let's me download files even if the app gets terminated by iOS. Being curious, I tried to add an upload task and noticed that it won't continue, even not if the app is only suspended.
Apple talks about "Downloading in the background" but they don't explicitly state that uploading would not be possible.
Can somebody confirm that uploads and background session configuration don't work together?
They DO work together.
What you need to do is the following:
Have a NSURLSessionConfiguration with background configuration
NSURLSessionConfiguration *conf = [NSURLSessionConfiguration backgroundSessionConfiguration:#"backgroundSession"];
Setup a NSURLSession (#property NSURLSession *urlSession)
Obtain the path to the file (fullPath)
Create the NSURLRequest (request)
Create a NSURLSessionTask
NSURLSessionTask*task = [self.urlSession uploadTaskWithRequest:request fromFile:fullPath];
[task resume];
And the task will run in background. You can get the status from NSURLSession delegate methods.
Cheers

NSURLSession didReceiveChallenge only called once

I'm using NSURLSession dataTaskWithRequest:completionHandler: to make some requests to my server. I'm using a self-signed certificate, so when the delegate's URLSession:didReceiveChallenge:completionHandler: gets called, I can do my internal checks to verify it everything is fine.
This all works great on the first request I send. After I call the completion handler with NSURLSessionAuthChallengeUseCredential, then the next requests never call URLSession:didReceiveChallenge:completionHandler:.
For reasons I won't go into in this post, I would really like URLSession:didReceiveChallenge:completionHandler: to be called each time, so that I can do my own checking. I'm assuming NSURLSession is somehow caching the certificate and keeping it in some sort of "valid certificates" list so it's not doing this check each time. I want to clear this cache so that I can make my own check each time. If I restart the App, then URLSession:didReceiveChallenge:completionHandler: does get called once more.
I have tried setting the Credential Storage to nil with no success:
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
configuration.URLCredentialStorage = nil;
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
[[session dataTaskWithRequest:request
completionHandler:^(NSData *data,
NSURLResponse *response,
NSError *error) {
...
}] resume];
Any ideas how to accomplish this?
Thank you!
For someone who tried everything here can be problem in the backend. So this problem was fixed by disabling ssl session caching in nginx server.

Resources