Change GSHTTPDigest to GSHTTPAuthentication ... more appropriate name.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@23090 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
rfm 2006-06-20 09:52:57 +00:00
parent 8b55e40030
commit 2a2814fbe6
3 changed files with 213 additions and 49 deletions

View file

@ -1,4 +1,4 @@
/* Implementation for GSHTTPDigest for GNUstep /* Implementation for GSHTTPAuthentication for GNUstep
Copyright (C) 2006 Software Foundation, Inc. Copyright (C) 2006 Software Foundation, Inc.
Written by: Richard Frith-Macdonald <frm@gnu.org> Written by: Richard Frith-Macdonald <frm@gnu.org>
@ -31,6 +31,7 @@
#include "GNUstepBase/GSMime.h" #include "GNUstepBase/GSMime.h"
static NSMutableDictionary *domainMap = nil;
static NSMutableSet *spaces = nil; static NSMutableSet *spaces = nil;
static NSMutableDictionary *store = nil; static NSMutableDictionary *store = nil;
static GSLazyLock *storeLock = nil; static GSLazyLock *storeLock = nil;
@ -70,7 +71,7 @@ static GSMimeParser *mimeParser = nil;
@implementation GSHTTPDigest @implementation GSHTTPAuthentication
+ (void) initialize + (void) initialize
{ {
@ -78,17 +79,18 @@ static GSMimeParser *mimeParser = nil;
{ {
mimeParser = [GSMimeParser new]; mimeParser = [GSMimeParser new];
spaces = [NSMutableSet new]; spaces = [NSMutableSet new];
domainMap = [NSMutableDictionary new];
store = [NSMutableDictionary new]; store = [NSMutableDictionary new];
storeLock = [GSLazyLock new]; storeLock = [GSLazyLock new];
} }
} }
+ (GSHTTPDigest *) digestWithCredential: (NSURLCredential*)credential + (GSHTTPAuthentication *) digestWithCredential: (NSURLCredential*)credential
inProtectionSpace: (NSURLProtectionSpace*)space inProtectionSpace: (NSURLProtectionSpace*)space
{ {
NSMutableDictionary *cDict; NSMutableDictionary *cDict;
NSURLProtectionSpace *known; NSURLProtectionSpace *known;
GSHTTPDigest *digest = nil; GSHTTPAuthentication *digest = nil;
[storeLock lock]; [storeLock lock];
/* /*
@ -112,8 +114,8 @@ static GSMimeParser *mimeParser = nil;
digest = [cDict objectForKey: credential]; digest = [cDict objectForKey: credential];
if (digest == nil) if (digest == nil)
{ {
digest = [[GSHTTPDigest alloc] initWithCredential: credential digest = [[GSHTTPAuthentication alloc] initWithCredential: credential
inProtectionSpace: space]; inProtectionSpace: space];
[cDict setObject: digest forKey: [digest credential]]; [cDict setObject: digest forKey: [digest credential]];
} }
else else
@ -124,18 +126,32 @@ static GSMimeParser *mimeParser = nil;
return AUTORELEASE(digest); return AUTORELEASE(digest);
} }
+ (NSString*) digestRealmForAuthentication: (NSString*)authentication + (NSURLProtectionSpace*) protectionSpaceForAuthentication: (NSString*)auth
requestURL: (NSURL*)URL;
{ {
if (authentication != nil) if (auth != nil)
{ {
NSScanner *sc; NSString *method = nil;
NSString *key; NSURLProtectionSpace *space;
NSString *val; NSScanner *sc;
NSString *domain = nil;
NSString *realm = nil;
NSString *key;
NSString *val;
sc = [NSScanner scannerWithString: authentication]; space = [self protectionSpaceForURL: URL];
if ([sc scanString: @"Digest" intoString: 0] == NO) sc = [NSScanner scannerWithString: auth];
if ([sc scanString: @"Basic" intoString: 0] == YES)
{
method = NSURLAuthenticationMethodHTTPBasic;
}
else if ([sc scanString: @"Digest" intoString: 0] == NO)
{
method = NSURLAuthenticationMethodHTTPDigest;
}
else
{ {
return nil; // Not a digest authentication return nil; // Not a known authentication
} }
while ((key = [mimeParser scanName: sc]) != nil) while ((key = [mimeParser scanName: sc]) != nil)
{ {
@ -147,13 +163,161 @@ static GSMimeParser *mimeParser = nil;
{ {
return nil; // Bad name=value specification return nil; // Bad name=value specification
} }
if ([key caseInsensitiveCompare: @"realm"] == NSOrderedSame) if ([key caseInsensitiveCompare: @"domain"] == NSOrderedSame)
{ {
return val; domain = val;
}
else if ([key caseInsensitiveCompare: @"realm"] == NSOrderedSame)
{
realm = val;
}
}
if (realm == nil)
{
return nil; // No real to authenticate in
}
/*
* If the realm and authentication method match the space we
* found for the URL, assume that it is unchanged.
*/
if ([[space realm] isEqualToString: realm]
&& [[space authenticationMethod] isEqualToString: method])
{
return space;
}
space = [[NSURLProtectionSpace alloc] initWithHost: [URL host]
port: [[URL port] intValue]
protocol: [URL scheme]
realm: realm
authenticationMethod: method];
[self setProtectionSpace: space
forDomains: [domain componentsSeparatedByString: @" "]
baseURL: URL];
return AUTORELEASE(space);
}
return nil;
}
+ (NSURLProtectionSpace *) protectionSpaceForURL: (NSURL*)URL
{
NSURLProtectionSpace *space = nil;
NSString *found = nil;
NSString *scheme;
NSNumber *port;
NSString *server;
NSDictionary *sDict;
NSArray *keys;
unsigned count;
NSString *path;
scheme = [URL scheme];
port = [URL port];
if ([port intValue] == 80 && [scheme isEqualToString: @"http"])
{
port = nil;
}
else if ([port intValue] == 443 && [scheme isEqualToString: @"https"])
{
port = nil;
}
if ([port intValue] == 0)
{
server = [NSString stringWithFormat: @"%@://%@",
scheme, [URL host]];
}
else
{
server = [NSString stringWithFormat: @"%@://%@:%@",
scheme, [URL host], port];
}
[storeLock lock];
sDict = [domainMap objectForKey: server];
keys = [sDict allKeys];
count = [keys count];
path = [URL path];
while (count-- > 0)
{
NSString *key = [keys objectAtIndex: count];
if (found == nil || [key length] > [found length])
{
if ([path hasPrefix: key] == YES)
{
found = key;
} }
} }
} }
return nil; if (found != nil)
{
space = RETAIN([sDict objectForKey: found]);
}
[storeLock unlock];
return AUTORELEASE(space);
}
+ (void) setProtectionSpace: (NSURLProtectionSpace *)space
forDomains: (NSArray*)domains
baseURL: (NSURL*)base
{
NSEnumerator *e;
NSString *domain;
/*
* If there are no URIs specified, everything on the
* host of the base URL is in the protection space
*/
if ([domains count] == 0)
{
domains = [NSArray arrayWithObject: @"/"];
}
[storeLock lock];
e = [domains objectEnumerator];
while ((domain = [e nextObject]) != nil)
{
NSURL *u;
NSNumber *port;
NSString *scheme;
NSString *server;
NSMutableDictionary *sDict;
u = [NSURL URLWithString: domain];
if (u == nil)
{
u = [NSURL URLWithString: domain relativeToURL: base];
}
port = [u port];
scheme = [u scheme];
if ([port intValue] == 80 && [scheme isEqualToString: @"http"])
{
port = nil;
}
else if ([port intValue] == 443 && [scheme isEqualToString: @"https"])
{
port = nil;
}
if ([port intValue] == 0)
{
server = [NSString stringWithFormat: @"%@://%@",
scheme, [u host]];
}
else
{
server = [NSString stringWithFormat: @"%@://%@:%@",
scheme, [u host], port];
}
sDict = [domainMap objectForKey: server];
if (sDict == nil)
{
sDict = [NSMutableDictionary new];
[domainMap setObject: sDict forKey: server];
RELEASE(sDict);
}
[sDict setObject: space forKey: [u path]];
}
[storeLock unlock];
} }
- (NSString*) authorizationForAuthentication: (NSString*)authentication - (NSString*) authorizationForAuthentication: (NSString*)authentication
@ -232,7 +396,7 @@ static GSMimeParser *mimeParser = nil;
NSDebugMLog(@"Missing HTTP digest realm in '%@'", authentication); NSDebugMLog(@"Missing HTTP digest realm in '%@'", authentication);
return nil; return nil;
} }
if ([realm isEqual: [self->_space realm]] == NO) if ([realm isEqualToString: [self->_space realm]] == NO)
{ {
NSDebugMLog(@"Bad HTTP digest realm in '%@'", authentication); NSDebugMLog(@"Bad HTTP digest realm in '%@'", authentication);
return nil; return nil;
@ -243,7 +407,7 @@ static GSMimeParser *mimeParser = nil;
return nil; return nil;
} }
if ([algorithm isEqual: @"MD5"] == NO) if ([algorithm isEqualToString: @"MD5"] == NO)
{ {
NSDebugMLog(@"Unsupported HTTP digest algorithm in '%@'", NSDebugMLog(@"Unsupported HTTP digest algorithm in '%@'",
authentication); authentication);
@ -257,7 +421,8 @@ static GSMimeParser *mimeParser = nil;
} }
[self->_lock lock]; [self->_lock lock];
if ([stale boolValue] == YES || [nonce isEqual: _nonce] == NO) if ([stale boolValue] == YES
|| [nonce isEqualToString: _nonce] == NO)
{ {
_nc = 1; _nc = 1;
} }

View file

@ -580,16 +580,16 @@ static void debugWrite(GSHTTPURLHandle *handle, NSData *data)
if ([a hasPrefix: @"Basic"] == YES if ([a hasPrefix: @"Basic"] == YES
&& (ah = [document headerNamed: @"WWW-Authenticate"]) != nil) && (ah = [document headerNamed: @"WWW-Authenticate"]) != nil)
{ {
NSString *realm; NSURLProtectionSpace *space;
NSString *ac; NSString *ac;
ac = [ah value]; ac = [ah value];
realm = [GSHTTPDigest digestRealmForAuthentication: ac]; space = [GSHTTPAuthentication
if (realm != nil) protectionSpaceForAuthentication: ac requestURL: url];
if (space != nil)
{ {
NSURLProtectionSpace *space;
NSURLCredential *cred; NSURLCredential *cred;
GSHTTPDigest *digest; GSHTTPAuthentication *digest;
NSString *method; NSString *method;
NSString *a; NSString *a;
@ -602,27 +602,14 @@ static void debugWrite(GSHTTPURLHandle *handle, NSData *data)
password: [url password] password: [url password]
persistence: NSURLCredentialPersistenceForSession]; persistence: NSURLCredentialPersistenceForSession];
/*
* Create protection space from the information in
* the URL and the realm of the authentication
* challenge.
*/
space = [[NSURLProtectionSpace alloc]
initWithHost: [url host]
port: [[url port] intValue]
protocol: [url scheme]
realm: realm
authenticationMethod:
NSURLAuthenticationMethodHTTPDigest];
/* /*
* Get the digest object and ask it for a header * Get the digest object and ask it for a header
* to use for authorisation. * to use for authorisation.
*/ */
digest = [GSHTTPDigest digestWithCredential: cred digest = [GSHTTPAuthentication
inProtectionSpace: space]; digestWithCredential: cred
inProtectionSpace: space];
RELEASE(cred); RELEASE(cred);
RELEASE(space);
method = [request objectForKey: GSHTTPPropertyMethodKey]; method = [request objectForKey: GSHTTPPropertyMethodKey];
if (method == nil) if (method == nil)

View file

@ -66,10 +66,10 @@
/* /*
* Internal class for handling HTTP digest authentication * Internal class for handling HTTP authentication
*/ */
@class GSLazyLock; @class GSLazyLock;
@interface GSHTTPDigest : NSObject @interface GSHTTPAuthentication : NSObject
{ {
GSLazyLock *_lock; GSLazyLock *_lock;
NSURLCredential *_credential; NSURLCredential *_credential;
@ -82,12 +82,24 @@
/* /*
* Return the object for the specified credential/protection space. * Return the object for the specified credential/protection space.
*/ */
+ (GSHTTPDigest *) digestWithCredential: (NSURLCredential*)credential + (GSHTTPAuthentication *) digestWithCredential: (NSURLCredential*)credential
inProtectionSpace: (NSURLProtectionSpace*)space; inProtectionSpace: (NSURLProtectionSpace*)space;
/* /*
* Look for a digest realm in a header * Create/return the protection space involved in the specified authentication
* header returned in a response to a request sent to the URL.
*/ */
+ (NSString*) digestRealmForAuthentication: (NSString*)authentication; + (NSURLProtectionSpace*) protectionSpaceForAuthentication: (NSString*)auth
requestURL: (NSURL*)URL;
/*
* Return the protection space for the specified URL (if known).
*/
+ (NSURLProtectionSpace *) protectionSpaceForURL: (NSURL*)URL;
+ (void) setProtectionSpace: (NSURLProtectionSpace *)space
forDomains: (NSArray*)domains
baseURL: (NSURL*)base;
/* /*
* Generate next authorisation header for the specified authentication * Generate next authorisation header for the specified authentication
* header, method, and path. * header, method, and path.