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:
parent
64f131641f
commit
74727c159c
6 changed files with 83 additions and 69 deletions
|
@ -68,20 +68,13 @@
|
|||
/**
|
||||
* \return A OFDataAray containing the initial authentication message
|
||||
*/
|
||||
- (OFDataArray*)clientFirstMessage;
|
||||
- (OFDataArray*)initialMessage;
|
||||
|
||||
/**
|
||||
* \param challenge The challenge to generate a response for
|
||||
* \return The response to the given challenge
|
||||
* \param data The continuation data send by the server
|
||||
* \return The appropriate response if the data was a challenge, nil otherwise
|
||||
*/
|
||||
- (OFDataArray*)calculateResponseWithChallenge: (OFDataArray*)challenge;
|
||||
|
||||
/**
|
||||
* Checks whether the servers final message was valid
|
||||
*
|
||||
* \param message The servers final message
|
||||
*/
|
||||
- (void)parseServerFinalMessage: (OFDataArray*)message;
|
||||
- (OFDataArray*)continueWithData: (OFDataArray*)data;
|
||||
|
||||
- (void)setAuthzid: (OFString*)authzid;
|
||||
- (OFString*)authzid;
|
||||
|
|
|
@ -93,21 +93,13 @@
|
|||
return [[password copy] autorelease];
|
||||
}
|
||||
|
||||
- (OFDataArray*)clientFirstMessage
|
||||
- (OFDataArray*)initialMessage
|
||||
{
|
||||
@throw [OFNotImplementedException newWithClass: isa
|
||||
selector: _cmd];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (OFDataArray*)calculateResponseWithChallenge: (OFDataArray*)challenge
|
||||
- (OFDataArray*)continueWithData: (OFDataArray*)challenge
|
||||
{
|
||||
@throw [OFNotImplementedException newWithClass: isa
|
||||
selector: _cmd];
|
||||
}
|
||||
|
||||
- (void)parseServerFinalMessage: (OFDataArray*)message
|
||||
{
|
||||
@throw [OFNotImplementedException newWithClass: isa
|
||||
selector: _cmd];
|
||||
return nil;
|
||||
}
|
||||
@end
|
||||
|
|
|
@ -619,19 +619,26 @@
|
|||
OFDataArray *challenge = [OFDataArray
|
||||
dataArrayWithBase64EncodedString: [element stringValue]];
|
||||
OFDataArray *response = [authModule
|
||||
calculateResponseWithChallenge: challenge];
|
||||
continueWithData: challenge];
|
||||
|
||||
responseTag = [OFXMLElement elementWithName: @"response"
|
||||
namespace: XMPP_NS_SASL];
|
||||
[responseTag addChild: [OFXMLElement elementWithCharacters:
|
||||
[response stringByBase64Encoding]]];
|
||||
if (response) {
|
||||
if ([response count] == 0)
|
||||
[responseTag addChild: [OFXMLElement
|
||||
elementWithCharacters: @"="]];
|
||||
else
|
||||
[responseTag addChild: [OFXMLElement
|
||||
elementWithCharacters: [response
|
||||
stringByBase64Encoding]]];
|
||||
}
|
||||
|
||||
[self sendStanza: responseTag];
|
||||
return;
|
||||
}
|
||||
|
||||
if ([[element name] isEqual: @"success"]) {
|
||||
[authModule parseServerFinalMessage: [OFDataArray
|
||||
[authModule continueWithData: [OFDataArray
|
||||
dataArrayWithBase64EncodedString: [element stringValue]]];
|
||||
|
||||
if ([delegate respondsToSelector:
|
||||
|
@ -780,13 +787,20 @@
|
|||
- (void)XMPP_sendAuth: (OFString*)authName
|
||||
{
|
||||
OFXMLElement *authTag;
|
||||
OFDataArray *initialMessage = [authModule initialMessage];
|
||||
|
||||
authTag = [OFXMLElement elementWithName: @"auth"
|
||||
namespace: XMPP_NS_SASL];
|
||||
[authTag addAttributeWithName: @"mechanism"
|
||||
stringValue: authName];
|
||||
if (initialMessage) {
|
||||
if ([initialMessage count] == 0)
|
||||
[authTag addChild: [OFXMLElement
|
||||
elementWithCharacters: @"="]];
|
||||
else
|
||||
[authTag addChild: [OFXMLElement elementWithCharacters:
|
||||
[[authModule clientFirstMessage] stringByBase64Encoding]]];
|
||||
[initialMessage stringByBase64Encoding]]];
|
||||
}
|
||||
|
||||
[self sendStanza: authTag];
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
password: password] autorelease];
|
||||
}
|
||||
|
||||
- (OFDataArray*)clientFirstMessage
|
||||
- (OFDataArray*)initialMessage
|
||||
{
|
||||
OFDataArray *message = [OFDataArray dataArrayWithItemSize: 1];
|
||||
|
||||
|
@ -68,17 +68,4 @@
|
|||
|
||||
return message;
|
||||
}
|
||||
|
||||
- (OFDataArray*)calculateResponseWithChallenge: (OFDataArray*)challenge
|
||||
{
|
||||
@throw [XMPPAuthFailedException newWithClass: isa
|
||||
connection: nil
|
||||
reason: @"Received a challenge "
|
||||
@"during PLAIN auth"];
|
||||
}
|
||||
|
||||
- (void)parseServerFinalMessage: (OFDataArray*)message
|
||||
{
|
||||
return;
|
||||
}
|
||||
@end
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
OFDataArray *serverSignature;
|
||||
XMPPConnection *connection;
|
||||
BOOL plusAvailable;
|
||||
BOOL authenticated;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -114,4 +115,6 @@
|
|||
- (OFDataArray*)XMPP_hiWithData: (OFDataArray *)str
|
||||
salt: (OFDataArray *)salt_
|
||||
iterationCount: (intmax_t)i;
|
||||
- (OFDataArray*)XMPP_parseServerFirstMessage: (OFDataArray*)data;
|
||||
- (OFDataArray*)XMPP_parseServerFinalMessage: (OFDataArray*)data;
|
||||
@end
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue