Re: How to handle bad certificate error in NSURLDownload?
Re: How to handle bad certificate error in NSURLDownload?
- Subject: Re: How to handle bad certificate error in NSURLDownload?
- From: "parag vibhute" <email@hidden>
- Date: Thu, 22 May 2008 16:27:52 +0530
Following is code which I have implemented:
- (void)download:(WebDownload *)download didFailWithError:(NSError *)error
{
// release the connection
[download release];
// inform the user
// NSLog(@"Download failed! Error - %@ %@",
// [error localizedDescription],
// [[error userInfo]
objectForKey:NSErrorFailingURLStringKey]);
NSURL *url = [[download request] URL];
NSString *path = [url absoluteString];
NSString *description = [error localizedDescription];
NSString *reason = [error localizedFailureReason];
int errorCode = [error code];
if ( (errorCode <= NSURLErrorServerCertificateHasBadDate) && (errorCode
>= NSURLErrorClientCertificateRejected) )
{
NSURL *failingURL = [[error userInfo] objectForKey:@
"NSErrorFailingURLKey"];
NSArray *badCerts = [[error userInfo] objectForKey:@
"NSErrorPeerCertificateChainKey"];
SecPolicySearchRef policySearch = NULL;
if (SecPolicySearchCreate(CSSM_CERT_X_509v3, &CSSMOID_APPLE_TP_SSL,
NULL, &policySearch) == noErr)
{
SecPolicyRef policy = NULL;
OSStatus status;
while ((status = SecPolicySearchCopyNext(policySearch, &policy))
== noErr)
{
SecTrustRef trust = NULL;
if (SecTrustCreateWithCertificates((CFArrayRef)badCerts,
policy, &trust) == noErr)
{
SFCertificateTrustPanel *panel =
[SFCertificateTrustPanel sharedCertificateTrustPanel];
NSString *host = [failingURL host];
[panel setDefaultButtonTitle:@"Continue"];
[panel setAlternateButtonTitle:@"Cancel"];
if ([panel
respondsToSelector:@selector(setInformativeText:)])
// this method is in Tiger but is undocumented
{
NSString *informativeText = [NSString
stringWithFormat:@"Security certificate is invalid for host %@.", host];
[panel performSelector:@selector(setInformativeText:)
withObject:informativeText];
}
[panel setShowsHelp:YES];
NSString *sheetText;
sheetText = [NSString stringWithFormat:@"Security
certificate is not valid. Alter trust settings below or click Cancel"];
[panel beginSheetForWindow:OUpgradeWindow
modalDelegate:self
didEndSelector:@selector
(certificateTrustSheetDidEnd:returnCode:contextInfo:)
contextInfo:[host retain] // didEndSelector
will release
trust:trust
message:sheetText];
CFRelease(trust);
trust = NULL;
}
CFRelease(policy);
policy = NULL;
} // end while
CFRelease(policySearch);
}
}
else // Handle other "normal" download errors
{
NSLog( @"Download of '%@' failed with error:%d, %@.\n", path,
errorCode, description );
}
}
- (void)certificateTrustSheetDidEnd:(NSWindow *)sheet
returnCode:(int)returnCode contextInfo:(void *)contextInfo
{
// we set the contextInfo tp the retained host name of the failing URL,
obtained
// from [[error userInfo] objectForKey:@"NSErrorFailingURLKey"].
// we'll need to release this before returning; done below
NSString *hostName = (NSString *)contextInfo;
// note to self: SecTrustGetResult() useful?
if (returnCode == NSOKButton)
{
// start this download again
[self startDownloadingURL];
}
else // user clicked Cancel
{
NSLog( @"Disallowing invalid certificate for host:%@", hostName );
}
[hostName release];
}
When I run my application first time, it opened up sheet & then I changed
trust settings as "Always trust" & clicked on continue. Then again after 2
min., same sheet opened up showing "bad server certificate". This time I
checked that trust settings were changed one i.e. "Always trust" but then
why did my application give error "bad server certificate"?
Thanks for ur replies,
Parag
On Thu, May 22, 2008 at 12:14 AM, ainxow <email@hidden> wrote:
> On May 19, 2008, at 1:51 PM, Jens Alfke wrote:
>
> I would guess that the Security framework is requiring user confirmation
>> to allow the app to bypass certificate checking.
>>
>
>
> Well, no. NSURLRequest's setAllowsAnyHTTPSCertificate:forHost: does exactly
> that, immediately and without user confirmation.
>
> One may (should) choose to use get user permission first. Could be a
> homegrown dialog, asking "Do you want to use a brute-force, unsupported
> private API to ignore this certificate and make this download work?" Or it
> could be via Security framework and SFCertificateTrustPanel, showing the
> certificate and what's wrong with it to the user before they make their
> choice. But setAllowsAnyHTTPSCertificate:forHost doesn't care whether you
> ask or not.
>
> On 19 May '08, at 8:19 AM, parag vibhute wrote:
>>
>>
>> I implemented same but whenever I launched my application it asks to
>>> change
>>> trust settings. Why is it like that?
>>>
>>>
> It's unclear what you mean here. If you used the Security Framework and it
> asks if you want to change trust settings for the rejected certificate,
> well, yes, that's what it's supposed to do. If you truly don't care about
> the certificate, and don't mind using the private API, just check that
> exists, use it, reissue the download request, and the download will silently
> proceed. I don't do that in my shipping code, but can confirm it works.
>
> (A broader question is why you want to do this. If it's due to certificate
> problems on machines with Safari 3.1.1 installed, a better approach than
> private API may be to wait for the problem to be fixed. Something is clearly
> amiss - example; I've been logging into my iPhone dev account since day one,
> but just yesterday Safari made me accept a developer.apple.com certificate
> "issued by an untrusted authority" to get in. Today, I deleted the
> certificate from Keychain, and still logged in without a hitch. Whatever
> causes this will surely be fixed soon.)
>
--
There are many things in your life that will catch your eye but only a few
will catch your heart....pursue those'.
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden