Improve authentication handling ... only send authentication information in

response to a challenge from the server.


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@23123 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
rfm 2006-07-04 10:54:12 +00:00
parent 5ee10ff9c7
commit a35bf27851
5 changed files with 322 additions and 266 deletions

View file

@ -1,6 +1,11 @@
2006-07-04 Richard Frith-Macdonald <rfm@gnu.org> 2006-07-04 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSTask.m: On mingw32 create subtask with CREATE_NO_WINDOW * Source/NSTask.m: On mingw32 create subtask with CREATE_NO_WINDOW
* Source/GSURLPrivate.h: Generalise GSHTTPAuthentication
* Source/GSHTTPAuthentication.m: Generalise to support Basic auth
* Source/NSURLProtectionSpace.m: Optimise a little.
* Source/GSHTTPURLHandle.m: Changes for GSHTTPAuthentication update.
Don't send basic authentication info unless challenged by server.
2006-07-02 Richard Frith-Macdonald <rfm@gnu.org> 2006-07-02 Richard Frith-Macdonald <rfm@gnu.org>

View file

@ -86,17 +86,19 @@ static GSMimeParser *mimeParser = nil;
} }
} }
+ (GSHTTPAuthentication *) digestWithCredential: (NSURLCredential*)credential + (GSHTTPAuthentication *) authenticationWithCredential:
inProtectionSpace: (NSURLProtectionSpace*)space (NSURLCredential*)credential
inProtectionSpace: (NSURLProtectionSpace*)space
{ {
NSMutableDictionary *cDict; NSMutableDictionary *cDict = nil;
NSURLProtectionSpace *known; NSURLProtectionSpace *known = nil;
GSHTTPAuthentication *digest = nil; GSHTTPAuthentication *authentication = nil;
[storeLock lock]; [storeLock lock];
/* /*
* Keep track of known protection spaces so we don't make lots of * Keep track of known protection spaces so we don't make lots of
* duplicate copies, but share one copy between digest objects. * duplicate copies, but share one copy between authentication objects.
*/ */
known = [spaces member: space]; known = [spaces member: space];
if (known == nil) if (known == nil)
@ -112,19 +114,21 @@ static GSMimeParser *mimeParser = nil;
[store setObject: cDict forKey: space]; [store setObject: cDict forKey: space];
RELEASE(cDict); RELEASE(cDict);
} }
digest = [cDict objectForKey: credential]; authentication = [cDict objectForKey: credential];
if (digest == nil)
if (authentication == nil)
{ {
digest = [[GSHTTPAuthentication alloc] initWithCredential: credential authentication = [[GSHTTPAuthentication alloc]
inProtectionSpace: space]; initWithCredential: credential
[cDict setObject: digest forKey: [digest credential]]; inProtectionSpace: space];
[cDict setObject: authentication forKey: [authentication credential]];
} }
else else
{ {
RETAIN(digest); RETAIN(authentication);
} }
[storeLock unlock]; [storeLock unlock];
return AUTORELEASE(digest); return AUTORELEASE(authentication);
} }
+ (NSURLProtectionSpace*) protectionSpaceForAuthentication: (NSString*)auth + (NSURLProtectionSpace*) protectionSpaceForAuthentication: (NSString*)auth
@ -187,7 +191,7 @@ static GSMimeParser *mimeParser = nil;
* found for the URL, assume that it is unchanged. * found for the URL, assume that it is unchanged.
*/ */
if ([[space realm] isEqualToString: realm] if ([[space realm] isEqualToString: realm]
&& [[space authenticationMethod] isEqualToString: method]) && [space authenticationMethod] == method)
{ {
return space; return space;
} }
@ -337,155 +341,194 @@ static GSMimeParser *mimeParser = nil;
method: (NSString*)method method: (NSString*)method
path: (NSString*)path path: (NSString*)path
{ {
NSString *realm = nil;
NSString *qop = nil;
NSString *nonce = nil;
NSString *opaque = nil;
NSString *stale = @"FALSE";
NSString *algorithm = @"MD5";
NSString *cnonce;
NSString *HA1;
NSString *HA2;
NSString *response;
NSMutableString *authorisation; NSMutableString *authorisation;
int nc;
if (authentication != nil) if ([self->_space authenticationMethod]
== NSURLAuthenticationMethodHTTPDigest)
{ {
NSScanner *sc; NSString *realm = nil;
NSString *key; NSString *qop = nil;
NSString *val; NSString *nonce = nil;
NSString *opaque = nil;
NSString *stale = @"FALSE";
NSString *algorithm = @"MD5";
NSString *cnonce;
NSString *HA1;
NSString *HA2;
NSString *response;
int nc;
sc = [NSScanner scannerWithString: authentication]; if (authentication != nil)
if ([sc scanString: @"Digest" intoString: 0] == NO)
{ {
NSDebugMLog(@"Bad format HTTP digest in '%@'", authentication); NSScanner *sc;
return nil; // Not a digest authentication NSString *key;
NSString *val;
sc = [NSScanner scannerWithString: authentication];
if ([sc scanString: @"Digest" intoString: 0] == NO)
{
NSDebugMLog(@"Bad format HTTP digest in '%@'", authentication);
return nil; // Not a digest authentication
}
while ((key = [mimeParser scanName: sc]) != nil)
{
if ([sc scanString: @"=" intoString: 0] == NO)
{
NSDebugMLog(@"Missing '=' in HTTP digest '%@'",
authentication);
return nil; // Bad name=value specification
}
if ((val = [mimeParser scanToken: sc]) == nil)
{
NSDebugMLog(@"Missing value in HTTP digest '%@'",
authentication);
return nil; // Bad name=value specification
}
if ([key caseInsensitiveCompare: @"realm"] == NSOrderedSame)
{
realm = val;
}
if ([key caseInsensitiveCompare: @"qop"] == NSOrderedSame)
{
qop = val;
}
if ([key caseInsensitiveCompare: @"nonce"] == NSOrderedSame)
{
nonce = val;
}
if ([key caseInsensitiveCompare: @"opaque"] == NSOrderedSame)
{
opaque = val;
}
if ([key caseInsensitiveCompare: @"stale"] == NSOrderedSame)
{
stale = val;
}
if ([key caseInsensitiveCompare: @"algorithm"] == NSOrderedSame)
{
algorithm = val;
}
if ([sc scanString: @"," intoString: 0] == NO)
{
break; // No more in list.
}
}
if (realm == nil)
{
NSDebugMLog(@"Missing HTTP digest realm in '%@'", authentication);
return nil;
}
if ([realm isEqualToString: [self->_space realm]] == NO)
{
NSDebugMLog(@"Bad HTTP digest realm in '%@'", authentication);
return nil;
}
if (nonce == nil)
{
NSDebugMLog(@"Missing HTTP digest nonce in '%@'", authentication);
return nil;
}
if ([algorithm isEqualToString: @"MD5"] == NO)
{
NSDebugMLog(@"Unsupported HTTP digest algorithm in '%@'",
authentication);
return nil;
}
if (![[qop componentsSeparatedByString: @","]
containsObject: @"auth"])
{
NSDebugMLog(@"Unsupported/missing HTTP digest qop in '%@'",
authentication);
return nil;
}
[self->_lock lock];
if ([stale boolValue] == YES
|| [nonce isEqualToString: _nonce] == NO)
{
_nc = 1;
}
ASSIGN(_nonce, nonce);
ASSIGN(_qop, qop);
ASSIGN(_opaque, opaque);
} }
while ((key = [mimeParser scanName: sc]) != nil) else
{ {
if ([sc scanString: @"=" intoString: 0] == NO) [self->_lock lock];
{ nonce = _nonce;
NSDebugMLog(@"Missing '=' in HTTP digest '%@'", authentication); opaque = _opaque;
return nil; // Bad name=value specification qop = _qop;
} realm = [self->_space realm];
if ((val = [mimeParser scanToken: sc]) == nil)
{
NSDebugMLog(@"Missing value in HTTP digest '%@'", authentication);
return nil; // Bad name=value specification
}
if ([key caseInsensitiveCompare: @"realm"] == NSOrderedSame)
{
realm = val;
}
if ([key caseInsensitiveCompare: @"qop"] == NSOrderedSame)
{
qop = val;
}
if ([key caseInsensitiveCompare: @"nonce"] == NSOrderedSame)
{
nonce = val;
}
if ([key caseInsensitiveCompare: @"opaque"] == NSOrderedSame)
{
opaque = val;
}
if ([key caseInsensitiveCompare: @"stale"] == NSOrderedSame)
{
stale = val;
}
if ([key caseInsensitiveCompare: @"algorithm"] == NSOrderedSame)
{
algorithm = val;
}
if ([sc scanString: @"," intoString: 0] == NO)
{
break; // No more in list.
}
} }
if (realm == nil) nc = _nc++;
qop = @"auth";
cnonce = [[[[[NSProcessInfo processInfo] globallyUniqueString]
dataUsingEncoding: NSUTF8StringEncoding] md5Digest] digestHex];
HA1 = [[[[NSString stringWithFormat: @"%@:%@:%@",
[self->_credential user], realm, [self->_credential password]]
dataUsingEncoding: NSUTF8StringEncoding] md5Digest] digestHex];
HA2 = [[[[NSString stringWithFormat: @"%@:%@", method, path]
dataUsingEncoding: NSUTF8StringEncoding] md5Digest] digestHex];
response = [[[[NSString stringWithFormat: @"%@:%@:%08x:%@:%@:%@",
HA1, nonce, nc, cnonce, qop, HA2]
dataUsingEncoding: NSUTF8StringEncoding] md5Digest] digestHex];
authorisation = [NSMutableString stringWithCapacity: 512];
[authorisation appendFormat: @"Digest realm=\"%@\"", realm];
[authorisation appendFormat: @",username=\"%@\"",
[self->_credential user]];
[authorisation appendFormat: @",nonce=\"%@\"", nonce];
[authorisation appendFormat: @",uri=\"%@\"", path];
[authorisation appendFormat: @",response=\"%@\"", response];
[authorisation appendFormat: @",qop=\"%@\"", qop];
[authorisation appendFormat: @",nc=%08x", nc];
[authorisation appendFormat: @",cnonce=\"%@\"", cnonce];
if (opaque != nil)
{ {
NSDebugMLog(@"Missing HTTP digest realm in '%@'", authentication); [authorisation appendFormat: @",opaque=\"%@\"", opaque];
return nil;
}
if ([realm isEqualToString: [self->_space realm]] == NO)
{
NSDebugMLog(@"Bad HTTP digest realm in '%@'", authentication);
return nil;
}
if (nonce == nil)
{
NSDebugMLog(@"Missing HTTP digest nonce in '%@'", authentication);
return nil;
} }
if ([algorithm isEqualToString: @"MD5"] == NO) [self->_lock unlock];
{
NSDebugMLog(@"Unsupported HTTP digest algorithm in '%@'",
authentication);
return nil;
}
if (![[qop componentsSeparatedByString: @","] containsObject: @"auth"])
{
NSDebugMLog(@"Unsupported/missing HTTP digest qop in '%@'",
authentication);
return nil;
}
[self->_lock lock];
if ([stale boolValue] == YES
|| [nonce isEqualToString: _nonce] == NO)
{
_nc = 1;
}
ASSIGN(_nonce, nonce);
ASSIGN(_qop, qop);
ASSIGN(_opaque, opaque);
} }
else else
{ {
[self->_lock lock]; NSString *toEncode;
nonce = _nonce;
opaque = _opaque; // FIXME ... should support other methods
qop = _qop; if (authentication != nil)
realm = [self->_space realm]; {
NSScanner *sc;
sc = [NSScanner scannerWithString: authentication];
if ([sc scanString: @"Basic" intoString: 0] == NO)
{
NSDebugMLog(@"Bad format HTTP basic in '%@'", authentication);
return nil; // Not a basic authentication
}
}
authorisation = [NSMutableString stringWithCapacity: 64];
if ([[self->_credential password] length] > 0)
{
toEncode = [NSString stringWithFormat: @"%@:%@",
[self->_credential user], [self->_credential password]];
}
else
{
toEncode = [NSString stringWithFormat: @"%@",
[self->_credential user]];
}
[authorisation appendFormat: @"Basic %@",
[GSMimeDocument encodeBase64String: toEncode]];
} }
nc = _nc++;
qop = @"auth";
cnonce = [[[[[NSProcessInfo processInfo] globallyUniqueString]
dataUsingEncoding: NSUTF8StringEncoding] md5Digest] digestHex];
HA1 = [[[[NSString stringWithFormat: @"%@:%@:%@",
[self->_credential user], realm, [self->_credential password]]
dataUsingEncoding: NSUTF8StringEncoding] md5Digest] digestHex];
HA2 = [[[[NSString stringWithFormat: @"%@:%@", method, path]
dataUsingEncoding: NSUTF8StringEncoding] md5Digest] digestHex];
response = [[[[NSString stringWithFormat: @"%@:%@:%08x:%@:%@:%@",
HA1, nonce, nc, cnonce, qop, HA2]
dataUsingEncoding: NSUTF8StringEncoding] md5Digest] digestHex];
authorisation = [NSMutableString stringWithCapacity: 512];
[authorisation appendFormat: @"Digest realm=\"%@\"", realm];
[authorisation appendFormat: @",username=\"%@\"", [self->_credential user]];
[authorisation appendFormat: @",nonce=\"%@\"", nonce];
[authorisation appendFormat: @",uri=\"%@\"", path];
[authorisation appendFormat: @",response=\"%@\"", response];
[authorisation appendFormat: @",qop=\"%@\"", qop];
[authorisation appendFormat: @",nc=%08x", nc];
[authorisation appendFormat: @",cnonce=\"%@\"", cnonce];
if (opaque != nil)
{
[authorisation appendFormat: @",opaque=\"%@\"", opaque];
}
[self->_lock unlock];
return authorisation; return authorisation;
} }

View file

@ -418,79 +418,53 @@ static void debugWrite(GSHTTPURLHandle *handle, NSData *data)
} }
if ((id)NSMapGet(wProperties, (void*)@"Authorization") == nil) if ((id)NSMapGet(wProperties, (void*)@"Authorization") == nil)
{ {
if ([u user] != nil) NSURLProtectionSpace *space;
/*
* If we have username/password stored in the URL, and there is a
* known protection space for that URL, we generate an authentication
* header.
*/
if ([u user] != nil
&& (space = [GSHTTPAuthentication protectionSpaceForURL: u]) != nil)
{ {
NSString *auth = nil; NSString *auth;
NSURLProtectionSpace *space; GSHTTPAuthentication *authentication;
NSURLCredential *cred;
NSString *method;
/* /*
* If the URL we are loading is in a digest authentication space * Create credential from user and password
* we try to create an authorization header using any existing * stored in the URL.
* cached information so that we can avoid the wasteful
* challenge/response dialogue.
*/ */
space = [GSHTTPAuthentication protectionSpaceForURL: u]; cred = [[NSURLCredential alloc]
if (space != nil && [[space authenticationMethod] isEqual: initWithUser: [u user]
NSURLAuthenticationMethodHTTPDigest] == YES) password: [u password]
persistence: NSURLCredentialPersistenceForSession];
authentication = [GSHTTPAuthentication
authenticationWithCredential: cred
inProtectionSpace: space];
RELEASE(cred);
method = [request objectForKey: GSHTTPPropertyMethodKey];
if (method == nil)
{ {
NSURLCredential *cred; if ([wData length] > 0)
GSHTTPAuthentication *digest;
NSString *method;
/*
* Create credential from user and password
* stored in the URL.
*/
cred = [[NSURLCredential alloc]
initWithUser: [u user]
password: [u password]
persistence: NSURLCredentialPersistenceForSession];
/*
* Get the digest object and ask it for a header
* to use for authorisation.
*/
digest = [GSHTTPAuthentication
digestWithCredential: cred
inProtectionSpace: space];
RELEASE(cred);
method = [request objectForKey: GSHTTPPropertyMethodKey];
if (method == nil)
{ {
if ([wData length] > 0) method = @"POST";
{
method = @"POST";
}
else
{
method = @"GET";
}
}
auth = [digest authorizationForAuthentication: nil
method: method
path: [u path]];
}
if (auth == nil)
{
/*
* Not able to do a digest authentication,
* so do a basic authentication in case the
* server accepts it.
*/
if ([[u password] length] > 0)
{
auth = [NSString stringWithFormat: @"%@:%@",
[u user], [u password]];
} }
else else
{ {
auth = [NSString stringWithFormat: @"%@", [u user]]; method = @"GET";
} }
auth = [NSString stringWithFormat: @"Basic %@",
[GSMimeDocument encodeBase64String: auth]];
} }
auth = [authentication authorizationForAuthentication: nil
method: method
path: [u path]];
NSMapInsert(wProperties, (void*)@"Authorization", (void*)auth); NSMapInsert(wProperties, (void*)@"Authorization", (void*)auth);
} }
} }
@ -632,65 +606,62 @@ static void debugWrite(GSHTTPURLHandle *handle, NSData *data)
val = [info objectForKey: NSHTTPPropertyStatusCodeKey]; val = [info objectForKey: NSHTTPPropertyStatusCodeKey];
if ([val intValue] == 401 && self->challenged < 2) if ([val intValue] == 401 && self->challenged < 2)
{ {
NSString *a;
GSMimeHeader *ah; GSMimeHeader *ah;
self->challenged++; // Prevent repeated challenge/auth self->challenged++; // Prevent repeated challenge/auth
a = (id)NSMapGet(wProperties, (void*)@"Authorization");
if ((ah = [document headerNamed: @"WWW-Authenticate"]) != nil) if ((ah = [document headerNamed: @"WWW-Authenticate"]) != nil)
{ {
NSURLProtectionSpace *space; NSURLProtectionSpace *space;
NSString *ac; NSString *ac;
NSURLCredential *cred;
GSHTTPAuthentication *authentication;
NSString *method;
NSString *a;
ac = [ah value]; ac = [ah value];
space = [GSHTTPAuthentication space = [GSHTTPAuthentication
protectionSpaceForAuthentication: ac requestURL: url]; protectionSpaceForAuthentication: ac requestURL: url];
if (space != nil)
/*
* Create credential from user and password
* stored in the URL.
*/
cred = [[NSURLCredential alloc]
initWithUser: [url user]
password: [url password]
persistence: NSURLCredentialPersistenceForSession];
/*
* Get the digest object and ask it for a header
* to use for authorisation.
*/
authentication = [GSHTTPAuthentication
authenticationWithCredential: cred
inProtectionSpace: space];
RELEASE(cred);
method = [request objectForKey: GSHTTPPropertyMethodKey];
if (method == nil)
{ {
NSURLCredential *cred; if ([wData length] > 0)
GSHTTPAuthentication *digest;
NSString *method;
NSString *a;
/*
* Create credential from user and password
* stored in the URL.
*/
cred = [[NSURLCredential alloc]
initWithUser: [url user]
password: [url password]
persistence: NSURLCredentialPersistenceForSession];
/*
* Get the digest object and ask it for a header
* to use for authorisation.
*/
digest = [GSHTTPAuthentication
digestWithCredential: cred
inProtectionSpace: space];
RELEASE(cred);
method = [request objectForKey: GSHTTPPropertyMethodKey];
if (method == nil)
{ {
if ([wData length] > 0) method = @"POST";
{
method = @"POST";
}
else
{
method = @"GET";
}
} }
a = [digest authorizationForAuthentication: ac else
{
method = @"GET";
}
}
a = [authentication authorizationForAuthentication: ac
method: method method: method
path: [url path]]; path: [url path]];
if (a != nil) if (a != nil)
{ {
[self writeProperty: a forKey: @"Authorization"]; [self writeProperty: a forKey: @"Authorization"];
[self _tryLoadInBackground: u]; [self _tryLoadInBackground: u];
return; // Retrying. return; // Retrying.
}
} }
} }
} }

View file

@ -82,8 +82,10 @@
/* /*
* Return the object for the specified credential/protection space. * Return the object for the specified credential/protection space.
*/ */
+ (GSHTTPAuthentication *) digestWithCredential: (NSURLCredential*)credential + (GSHTTPAuthentication *) authenticationWithCredential:
inProtectionSpace: (NSURLProtectionSpace*)space; (NSURLCredential*)credential
inProtectionSpace: (NSURLProtectionSpace*)space;
/* /*
* Create/return the protection space involved in the specified authentication * Create/return the protection space involved in the specified authentication
* header returned in a response to a request sent to the URL. * header returned in a response to a request sent to the URL.
@ -109,7 +111,7 @@
path: (NSString*)path; path: (NSString*)path;
- (NSURLCredential *) credential; - (NSURLCredential *) credential;
- (id) initWithCredential: (NSURLCredential*)credential - (id) initWithCredential: (NSURLCredential*)credential
inProtectionSpace: (NSURLProtectionSpace*)space; inProtectionSpace: (NSURLProtectionSpace*)space;
- (NSURLProtectionSpace *) space; - (NSURLProtectionSpace *) space;
@end @end

View file

@ -43,8 +43,8 @@ typedef struct {
int port; int port;
NSString *protocol; NSString *protocol;
NSString *realm; NSString *realm;
NSString *proxyType; NSString *proxyType; // Not retained
NSString *authenticationMethod; NSString *authenticationMethod; // Not retained
BOOL isProxy; BOOL isProxy;
} Internal; } Internal;
@ -90,7 +90,7 @@ typedef struct {
if (o != nil) if (o != nil)
{ {
inst->isProxy = this->isProxy; inst->isProxy = this->isProxy;
ASSIGN(inst->proxyType, this->proxyType); inst->proxyType = this->proxyType;
} }
return o; return o;
} }
@ -102,9 +102,7 @@ typedef struct {
{ {
RELEASE(this->host); RELEASE(this->host);
RELEASE(this->protocol); RELEASE(this->protocol);
RELEASE(this->proxyType);
RELEASE(this->realm); RELEASE(this->realm);
RELEASE(this->authenticationMethod);
NSZoneFree([self zone], this); NSZoneFree([self zone], this);
} }
[super dealloc]; [super dealloc];
@ -114,7 +112,7 @@ typedef struct {
{ {
return [[self host] hash] + [self port] return [[self host] hash] + [self port]
+ [[self realm] hash] + [[self protocol] hash] + [[self realm] hash] + [[self protocol] hash]
+ [[self proxyType] hash] + [[self authenticationMethod] hash]; + (uintptr_t)this->proxyType + (uintptr_t)this->authenticationMethod;
} }
- (NSString *) host - (NSString *) host
@ -133,7 +131,25 @@ authenticationMethod: (NSString *)authenticationMethod
this->host = [host copy]; this->host = [host copy];
this->protocol = [protocol copy]; this->protocol = [protocol copy];
this->realm = [realm copy]; this->realm = [realm copy];
this->authenticationMethod = [authenticationMethod copy]; if ([authenticationMethod isEqualToString:
NSURLAuthenticationMethodHTMLForm] == YES)
{
this->authenticationMethod = NSURLAuthenticationMethodHTMLForm;
}
else if ([authenticationMethod isEqualToString:
NSURLAuthenticationMethodHTTPBasic] == YES)
{
this->authenticationMethod = NSURLAuthenticationMethodHTTPBasic;
}
else if ([authenticationMethod isEqualToString:
NSURLAuthenticationMethodHTTPDigest] == YES)
{
this->authenticationMethod = NSURLAuthenticationMethodHTTPDigest;
}
else
{
this->authenticationMethod = NSURLAuthenticationMethodDefault;
}
this->port = port; this->port = port;
this->proxyType = nil; this->proxyType = nil;
this->isProxy = NO; this->isProxy = NO;
@ -155,9 +171,28 @@ authenticationMethod: (NSString *)authenticationMethod
if (self != nil) if (self != nil)
{ {
this->isProxy = YES; this->isProxy = YES;
ASSIGNCOPY(this->proxyType, type); if ([type isEqualToString: NSURLProtectionSpaceFTPProxy] == YES)
{
this->proxyType = NSURLProtectionSpaceFTPProxy;
}
else if ([type isEqualToString: NSURLProtectionSpaceHTTPProxy] == YES)
{
this->proxyType = NSURLProtectionSpaceHTTPProxy;
}
else if ([type isEqualToString: NSURLProtectionSpaceHTTPSProxy] == YES)
{
this->proxyType = NSURLProtectionSpaceHTTPSProxy;
}
else if ([type isEqualToString: NSURLProtectionSpaceSOCKSProxy] == YES)
{
this->proxyType = NSURLProtectionSpaceSOCKSProxy;
}
else
{
DESTROY(self); // Bad proxy type.
}
} }
return NO; return self;
} }
- (BOOL) isEqual: (id)other - (BOOL) isEqual: (id)other
@ -237,13 +272,13 @@ authenticationMethod: (NSString *)authenticationMethod
- (BOOL) receivesCredentialSecurely - (BOOL) receivesCredentialSecurely
{ {
if ([this->authenticationMethod isEqual: NSURLAuthenticationMethodHTTPDigest]) if (this->authenticationMethod == NSURLAuthenticationMethodHTTPDigest)
{ {
return YES; return YES;
} }
if (this->isProxy) if (this->isProxy)
{ {
if ([this->proxyType isEqual: NSURLProtectionSpaceHTTPSProxy] == YES) if (this->proxyType == NSURLProtectionSpaceHTTPSProxy)
{ {
return YES; return YES;
} }