mirror of
https://github.com/gnustep/libs-base.git
synced 2025-06-02 01:21:08 +00:00
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:
parent
8b55e40030
commit
2a2814fbe6
3 changed files with 213 additions and 49 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue