From d352e7c45d68076d719d4cb4dcc97aba5ea5cfae Mon Sep 17 00:00:00 2001 From: Kelvin Sherlock Date: Sat, 20 Nov 2021 09:43:22 -0500 Subject: [PATCH] Download manager - support for password protected web sites (basic authorization). Since there's no UI for the username/password, these need to be managed within keychain. Add a new keychain item with the porotocol + server (ie, https://romz.example.com) as the keychain item name, account name, and password. --- Ample/DownloadWindowController.m | 70 ++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/Ample/DownloadWindowController.m b/Ample/DownloadWindowController.m index 1901491..4126184 100644 --- a/Ample/DownloadWindowController.m +++ b/Ample/DownloadWindowController.m @@ -593,6 +593,76 @@ static NSInteger TaskStatusCode(NSURLSessionTask *task) { NSLog(@"%@", src); } + + +-(NSURLCredential *)credentialForChallenge: (NSURLAuthenticationChallenge *)challenge { + + + //if ([challenge previousFailureCount]) return nil; + + NSURLCredential *credential = nil; + NSURLProtectionSpace *space = [challenge protectionSpace]; + + + OSStatus status; + NSDictionary *query; + CFTypeRef item = nil; + + + query = @{ + (id)kSecClass: (id)kSecClassInternetPassword, + (id)kSecReturnData: (id)kCFBooleanTrue, + (id)kSecReturnAttributes: (id)kCFBooleanTrue, + (id)kSecAttrServer: [space host], + //(id)kSecAttrProtocol: [space protocol], + (id)kSecMatchLimit: (id)kSecMatchLimitOne, + }; + + status = SecItemCopyMatching((CFDictionaryRef)query, &item); + NSLog(@"%@", query); + if (status != 0) return nil; + + NSDictionary *d = (__bridge NSDictionary *)item; + NSLog(@"%@", d); + + NSString *account = [d objectForKey: (id)kSecAttrAccount]; + NSData *passwordData = [d objectForKey: (id)kSecValueData]; + NSString *password = [[NSString alloc] initWithData: passwordData encoding: NSUTF8StringEncoding]; + + + credential = [NSURLCredential credentialWithUser: account password: password persistence: NSURLCredentialPersistenceForSession]; + + return credential; + +} + +- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler { + + NSLog(@"challenge: %@", challenge); + + if ([challenge previousFailureCount]) { + completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil); + return; + } + + NSURLProtectionSpace *space = [challenge protectionSpace]; + NSString *method = [space authenticationMethod]; + + if ([NSURLAuthenticationMethodHTTPBasic isEqualToString: method] || + [NSURLAuthenticationMethodNTLM isEqualToString: method] || + [NSURLAuthenticationMethodHTTPDigest isEqualToString: method]) { + + NSURLCredential *credential = [self credentialForChallenge: challenge]; + + if (credential) { + completionHandler(NSURLSessionAuthChallengeUseCredential, credential); + return; + } + } + + completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); +} + @end