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:
Richard Frith-MacDonald 2006-06-20 09:52:57 +00:00
parent 7eb717ffea
commit cae764e6ec
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.
Written by: Richard Frith-Macdonald <frm@gnu.org>
@ -31,6 +31,7 @@
#include "GNUstepBase/GSMime.h"
static NSMutableDictionary *domainMap = nil;
static NSMutableSet *spaces = nil;
static NSMutableDictionary *store = nil;
static GSLazyLock *storeLock = nil;
@ -70,7 +71,7 @@ static GSMimeParser *mimeParser = nil;
@implementation GSHTTPDigest
@implementation GSHTTPAuthentication
+ (void) initialize
{
@ -78,17 +79,18 @@ static GSMimeParser *mimeParser = nil;
{
mimeParser = [GSMimeParser new];
spaces = [NSMutableSet new];
domainMap = [NSMutableDictionary new];
store = [NSMutableDictionary new];
storeLock = [GSLazyLock new];
}
}
+ (GSHTTPDigest *) digestWithCredential: (NSURLCredential*)credential
inProtectionSpace: (NSURLProtectionSpace*)space
+ (GSHTTPAuthentication *) digestWithCredential: (NSURLCredential*)credential
inProtectionSpace: (NSURLProtectionSpace*)space
{
NSMutableDictionary *cDict;
NSURLProtectionSpace *known;
GSHTTPDigest *digest = nil;
GSHTTPAuthentication *digest = nil;
[storeLock lock];
/*
@ -112,8 +114,8 @@ static GSMimeParser *mimeParser = nil;
digest = [cDict objectForKey: credential];
if (digest == nil)
{
digest = [[GSHTTPDigest alloc] initWithCredential: credential
inProtectionSpace: space];
digest = [[GSHTTPAuthentication alloc] initWithCredential: credential
inProtectionSpace: space];
[cDict setObject: digest forKey: [digest credential]];
}
else
@ -124,18 +126,32 @@ static GSMimeParser *mimeParser = nil;
return AUTORELEASE(digest);
}
+ (NSString*) digestRealmForAuthentication: (NSString*)authentication
+ (NSURLProtectionSpace*) protectionSpaceForAuthentication: (NSString*)auth
requestURL: (NSURL*)URL;
{
if (authentication != nil)
if (auth != nil)
{
NSScanner *sc;
NSString *key;
NSString *val;
NSString *method = nil;
NSURLProtectionSpace *space;
NSScanner *sc;
NSString *domain = nil;
NSString *realm = nil;
NSString *key;
NSString *val;
sc = [NSScanner scannerWithString: authentication];
if ([sc scanString: @"Digest" intoString: 0] == NO)
space = [self protectionSpaceForURL: URL];
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)
{
@ -147,13 +163,161 @@ static GSMimeParser *mimeParser = nil;
{
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
@ -232,7 +396,7 @@ static GSMimeParser *mimeParser = nil;
NSDebugMLog(@"Missing HTTP digest realm in '%@'", authentication);
return nil;
}
if ([realm isEqual: [self->_space realm]] == NO)
if ([realm isEqualToString: [self->_space realm]] == NO)
{
NSDebugMLog(@"Bad HTTP digest realm in '%@'", authentication);
return nil;
@ -243,7 +407,7 @@ static GSMimeParser *mimeParser = nil;
return nil;
}
if ([algorithm isEqual: @"MD5"] == NO)
if ([algorithm isEqualToString: @"MD5"] == NO)
{
NSDebugMLog(@"Unsupported HTTP digest algorithm in '%@'",
authentication);
@ -257,7 +421,8 @@ static GSMimeParser *mimeParser = nil;
}
[self->_lock lock];
if ([stale boolValue] == YES || [nonce isEqual: _nonce] == NO)
if ([stale boolValue] == YES
|| [nonce isEqualToString: _nonce] == NO)
{
_nc = 1;
}

View file

@ -580,16 +580,16 @@ static void debugWrite(GSHTTPURLHandle *handle, NSData *data)
if ([a hasPrefix: @"Basic"] == YES
&& (ah = [document headerNamed: @"WWW-Authenticate"]) != nil)
{
NSString *realm;
NSString *ac;
NSURLProtectionSpace *space;
NSString *ac;
ac = [ah value];
realm = [GSHTTPDigest digestRealmForAuthentication: ac];
if (realm != nil)
space = [GSHTTPAuthentication
protectionSpaceForAuthentication: ac requestURL: url];
if (space != nil)
{
NSURLProtectionSpace *space;
NSURLCredential *cred;
GSHTTPDigest *digest;
GSHTTPAuthentication *digest;
NSString *method;
NSString *a;
@ -602,27 +602,14 @@ static void debugWrite(GSHTTPURLHandle *handle, NSData *data)
password: [url password]
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
* to use for authorisation.
*/
digest = [GSHTTPDigest digestWithCredential: cred
inProtectionSpace: space];
digest = [GSHTTPAuthentication
digestWithCredential: cred
inProtectionSpace: space];
RELEASE(cred);
RELEASE(space);
method = [request objectForKey: GSHTTPPropertyMethodKey];
if (method == nil)

View file

@ -66,10 +66,10 @@
/*
* Internal class for handling HTTP digest authentication
* Internal class for handling HTTP authentication
*/
@class GSLazyLock;
@interface GSHTTPDigest : NSObject
@interface GSHTTPAuthentication : NSObject
{
GSLazyLock *_lock;
NSURLCredential *_credential;
@ -82,12 +82,24 @@
/*
* Return the object for the specified credential/protection space.
*/
+ (GSHTTPDigest *) digestWithCredential: (NSURLCredential*)credential
inProtectionSpace: (NSURLProtectionSpace*)space;
+ (GSHTTPAuthentication *) digestWithCredential: (NSURLCredential*)credential
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
* header, method, and path.