Fix XMPPAuthenticator to support non-optimized message flow

While RFC6120 allows and encourages sending data with the success
message it is also legal to send the same data as a challenge and
await an empty response. This rework honors that fact.
This commit is contained in:
Florian Zeitz 2011-09-18 21:33:19 +02:00
parent 64f131641f
commit 74727c159c
6 changed files with 83 additions and 69 deletions

View file

@ -143,12 +143,18 @@
[old release];
}
- (OFDataArray*)clientFirstMessage
- (OFDataArray*)initialMessage
{
OFDataArray *ret = [OFDataArray dataArrayWithItemSize: 1];
/* New authentication attempt, reset status */
[cNonce release];
cNonce = nil;
[GS2Header release];
GS2Header = nil;
[serverSignature release];
serverSignature = nil;
authenticated = NO;
if (authzid)
GS2Header = [[OFString alloc]
@ -158,8 +164,6 @@
else
GS2Header = (plusAvailable ? @"p=tls-unique,," : @"y,,");
[cNonce release];
cNonce = nil;
cNonce = [[self XMPP_genNonce] retain];
[clientFirstMessageBare release];
@ -174,10 +178,27 @@
[ret addNItems: [clientFirstMessageBare UTF8StringLength]
fromCArray: [clientFirstMessageBare UTF8String]];
return ret;
}
- (OFDataArray*)calculateResponseWithChallenge: (OFDataArray*)challenge
- (OFDataArray*)continueWithData: (OFDataArray*)data
{
OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];
OFDataArray *ret;
if (!serverSignature)
ret = [self XMPP_parseServerFirstMessage: data];
else
ret = [self XMPP_parseServerFinalMessage: data];
[ret retain];
[pool release];
return [ret autorelease];
}
- (OFDataArray*)XMPP_parseServerFirstMessage: (OFDataArray*)data
{
size_t i;
uint8_t *clientKey, *serverKey, *clientSignature;
@ -185,7 +206,6 @@
OFHash *hash;
OFDataArray *ret, *authMessage, *tmpArray, *salt = nil, *saltedPassword;
OFString *tmpString, *sNonce = nil;
OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];
OFEnumerator *enumerator;
OFString *comp;
enum {
@ -198,9 +218,9 @@
ret = [OFDataArray dataArrayWithItemSize: 1];
authMessage = [OFDataArray dataArrayWithItemSize: 1];
OFString *chal = [OFString stringWithUTF8String: [challenge cArray]
length: [challenge count] *
[challenge itemSize]];
OFString *chal = [OFString stringWithUTF8String: [data cArray]
length: [data count] *
[data itemSize]];
enumerator =
[[chal componentsSeparatedByString: @","] objectEnumerator];
@ -253,14 +273,14 @@
[ret addNItems: [sNonce UTF8StringLength]
fromCArray: [sNonce UTF8String]];
tmpArray = [OFDataArray dataArrayWithItemSize: 1];
[tmpArray addNItems: [password UTF8StringLength]
fromCArray: [password UTF8String]];
/*
* IETF RFC 5802:
* SaltedPassword := Hi(Normalize(password), salt, i)
*/
tmpArray = [OFDataArray dataArrayWithItemSize: 1];
[tmpArray addNItems: [password UTF8StringLength]
fromCArray: [password UTF8String]];
saltedPassword = [self XMPP_hiWithData: tmpArray
salt: salt
iterationCount: iterCount];
@ -274,8 +294,8 @@
[authMessage addNItems: [clientFirstMessageBare UTF8StringLength]
fromCArray: [clientFirstMessageBare UTF8String]];
[authMessage addItem: ","];
[authMessage addNItems: [challenge count] * [challenge itemSize]
fromCArray: [challenge cArray]];
[authMessage addNItems: [data count] * [data itemSize]
fromCArray: [data cArray]];
[authMessage addItem: ","];
[authMessage addNItems: [ret count]
fromCArray: [ret cArray]];
@ -347,20 +367,24 @@
[ret addNItems: [tmpString UTF8StringLength]
fromCArray: [tmpString UTF8String]];
[ret retain];
[pool release];
return [ret autorelease];
return ret;
}
- (void)parseServerFinalMessage: (OFDataArray*)message
- (OFDataArray*)XMPP_parseServerFinalMessage: (OFDataArray*)data
{
OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];
OFString *mess = [OFString stringWithUTF8String: [message cArray]
length: [message count] *
[message itemSize]];
OFString *value = [mess substringWithRange:
of_range(2, [mess length] - 2)];
OFString *mess, *value;
/*
* server-final-message already received,
* we were just waiting for the last word from the server
*/
if (authenticated)
return nil;
mess = [OFString stringWithUTF8String: [data cArray]
length: [data count] *
[data itemSize]];
value = [mess substringWithRange: of_range(2, [mess length] - 2)];
if ([mess hasPrefix: @"v="]) {
if (![value isEqual: [serverSignature stringByBase64Encoding]])
@ -368,12 +392,13 @@
newWithClass: isa
connection: nil
reason: @"Received wrong ServerSignature"];
authenticated = YES;
} else
@throw [XMPPAuthFailedException newWithClass: isa
connection: nil
reason: value];
[pool release];
return nil;
}
- (OFString*)XMPP_genNonce