196 lines
6.0 KiB
Objective-C
196 lines
6.0 KiB
Objective-C
#import "HTTPAuthenticationRequest.h"
|
|
#import "HTTPMessage.h"
|
|
|
|
#if ! __has_feature(objc_arc)
|
|
#warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
|
|
#endif
|
|
|
|
@interface HTTPAuthenticationRequest (PrivateAPI)
|
|
- (NSString *)quotedSubHeaderFieldValue:(NSString *)param fromHeaderFieldValue:(NSString *)header;
|
|
- (NSString *)nonquotedSubHeaderFieldValue:(NSString *)param fromHeaderFieldValue:(NSString *)header;
|
|
@end
|
|
|
|
|
|
@implementation HTTPAuthenticationRequest
|
|
|
|
- (id)initWithRequest:(HTTPMessage *)request
|
|
{
|
|
if ((self = [super init]))
|
|
{
|
|
NSString *authInfo = [request headerField:@"Authorization"];
|
|
|
|
isBasic = NO;
|
|
if ([authInfo length] >= 6)
|
|
{
|
|
isBasic = [[authInfo substringToIndex:6] caseInsensitiveCompare:@"Basic "] == NSOrderedSame;
|
|
}
|
|
|
|
isDigest = NO;
|
|
if ([authInfo length] >= 7)
|
|
{
|
|
isDigest = [[authInfo substringToIndex:7] caseInsensitiveCompare:@"Digest "] == NSOrderedSame;
|
|
}
|
|
|
|
if (isBasic)
|
|
{
|
|
NSMutableString *temp = [[authInfo substringFromIndex:6] mutableCopy];
|
|
CFStringTrimWhitespace((__bridge CFMutableStringRef)temp);
|
|
|
|
base64Credentials = [temp copy];
|
|
}
|
|
|
|
if (isDigest)
|
|
{
|
|
username = [self quotedSubHeaderFieldValue:@"username" fromHeaderFieldValue:authInfo];
|
|
realm = [self quotedSubHeaderFieldValue:@"realm" fromHeaderFieldValue:authInfo];
|
|
nonce = [self quotedSubHeaderFieldValue:@"nonce" fromHeaderFieldValue:authInfo];
|
|
uri = [self quotedSubHeaderFieldValue:@"uri" fromHeaderFieldValue:authInfo];
|
|
|
|
// It appears from RFC 2617 that the qop is to be given unquoted
|
|
// Tests show that Firefox performs this way, but Safari does not
|
|
// Thus we'll attempt to retrieve the value as nonquoted, but we'll verify it doesn't start with a quote
|
|
qop = [self nonquotedSubHeaderFieldValue:@"qop" fromHeaderFieldValue:authInfo];
|
|
if(qop && ([qop characterAtIndex:0] == '"'))
|
|
{
|
|
qop = [self quotedSubHeaderFieldValue:@"qop" fromHeaderFieldValue:authInfo];
|
|
}
|
|
|
|
nc = [self nonquotedSubHeaderFieldValue:@"nc" fromHeaderFieldValue:authInfo];
|
|
cnonce = [self quotedSubHeaderFieldValue:@"cnonce" fromHeaderFieldValue:authInfo];
|
|
response = [self quotedSubHeaderFieldValue:@"response" fromHeaderFieldValue:authInfo];
|
|
}
|
|
}
|
|
return self;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
#pragma mark Accessors:
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
- (BOOL)isBasic {
|
|
return isBasic;
|
|
}
|
|
|
|
- (BOOL)isDigest {
|
|
return isDigest;
|
|
}
|
|
|
|
- (NSString *)base64Credentials {
|
|
return base64Credentials;
|
|
}
|
|
|
|
- (NSString *)username {
|
|
return username;
|
|
}
|
|
|
|
- (NSString *)realm {
|
|
return realm;
|
|
}
|
|
|
|
- (NSString *)nonce {
|
|
return nonce;
|
|
}
|
|
|
|
- (NSString *)uri {
|
|
return uri;
|
|
}
|
|
|
|
- (NSString *)qop {
|
|
return qop;
|
|
}
|
|
|
|
- (NSString *)nc {
|
|
return nc;
|
|
}
|
|
|
|
- (NSString *)cnonce {
|
|
return cnonce;
|
|
}
|
|
|
|
- (NSString *)response {
|
|
return response;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
#pragma mark Private API:
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/**
|
|
* Retrieves a "Sub Header Field Value" from a given header field value.
|
|
* The sub header field is expected to be quoted.
|
|
*
|
|
* In the following header field:
|
|
* Authorization: Digest username="Mufasa", qop=auth, response="6629fae4939"
|
|
* The sub header field titled 'username' is quoted, and this method would return the value @"Mufasa".
|
|
**/
|
|
- (NSString *)quotedSubHeaderFieldValue:(NSString *)param fromHeaderFieldValue:(NSString *)header
|
|
{
|
|
NSRange startRange = [header rangeOfString:[NSString stringWithFormat:@"%@=\"", param]];
|
|
if(startRange.location == NSNotFound)
|
|
{
|
|
// The param was not found anywhere in the header
|
|
return nil;
|
|
}
|
|
|
|
NSUInteger postStartRangeLocation = startRange.location + startRange.length;
|
|
NSUInteger postStartRangeLength = [header length] - postStartRangeLocation;
|
|
NSRange postStartRange = NSMakeRange(postStartRangeLocation, postStartRangeLength);
|
|
|
|
NSRange endRange = [header rangeOfString:@"\"" options:0 range:postStartRange];
|
|
if(endRange.location == NSNotFound)
|
|
{
|
|
// The ending double-quote was not found anywhere in the header
|
|
return nil;
|
|
}
|
|
|
|
NSRange subHeaderRange = NSMakeRange(postStartRangeLocation, endRange.location - postStartRangeLocation);
|
|
return [header substringWithRange:subHeaderRange];
|
|
}
|
|
|
|
/**
|
|
* Retrieves a "Sub Header Field Value" from a given header field value.
|
|
* The sub header field is expected to not be quoted.
|
|
*
|
|
* In the following header field:
|
|
* Authorization: Digest username="Mufasa", qop=auth, response="6629fae4939"
|
|
* The sub header field titled 'qop' is nonquoted, and this method would return the value @"auth".
|
|
**/
|
|
- (NSString *)nonquotedSubHeaderFieldValue:(NSString *)param fromHeaderFieldValue:(NSString *)header
|
|
{
|
|
NSRange startRange = [header rangeOfString:[NSString stringWithFormat:@"%@=", param]];
|
|
if(startRange.location == NSNotFound)
|
|
{
|
|
// The param was not found anywhere in the header
|
|
return nil;
|
|
}
|
|
|
|
NSUInteger postStartRangeLocation = startRange.location + startRange.length;
|
|
NSUInteger postStartRangeLength = [header length] - postStartRangeLocation;
|
|
NSRange postStartRange = NSMakeRange(postStartRangeLocation, postStartRangeLength);
|
|
|
|
NSRange endRange = [header rangeOfString:@"," options:0 range:postStartRange];
|
|
if(endRange.location == NSNotFound)
|
|
{
|
|
// The ending comma was not found anywhere in the header
|
|
// However, if the nonquoted param is at the end of the string, there would be no comma
|
|
// This is only possible if there are no spaces anywhere
|
|
NSRange endRange2 = [header rangeOfString:@" " options:0 range:postStartRange];
|
|
if(endRange2.location != NSNotFound)
|
|
{
|
|
return nil;
|
|
}
|
|
else
|
|
{
|
|
return [header substringWithRange:postStartRange];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NSRange subHeaderRange = NSMakeRange(postStartRangeLocation, endRange.location - postStartRangeLocation);
|
|
return [header substringWithRange:subHeaderRange];
|
|
}
|
|
}
|
|
|
|
@end
|