mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-31 00:30:53 +00:00
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:
parent
5ee10ff9c7
commit
a35bf27851
5 changed files with 322 additions and 266 deletions
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue