@@ -87,8 +87,8 @@ -(NSString*) clientFirstMessageWithNoMatchingChannelBindingFound:(BOOL) noMatchi
8787 MLAssert (!_finishedSuccessfully, @" SCRAM handler finished already!" );
8888 MLAssert (!_serverFirstMessageParsed, @" SCRAM handler already parsed server-first-message!" );
8989 // no matching channel binding could be found, but server advertised channel-binding capability
90- // --> tell the server we DON'T support channel-binding and abort the authentication later on,
91- // if the server doesn't support SSDP to sign this fact
90+ // --> tell the server we DON'T support channel-binding and, if the server doesn't support SSDP
91+ // to sign this fact, abort the authentication later on,
9292 // NOTE: XEP-0440 makes tls-server-end-point mandatory and we support this
9393 // NOTE: ==> not having a match almost always means a MITM attacker tampered with the XEP-0440 list
9494 if (noMatchingChannelBindingFound)
@@ -109,7 +109,7 @@ -(MLScramStatus) parseServerFirstMessage:(NSString*) str
109109{
110110 MLAssert (!_finishedSuccessfully, @" SCRAM handler finished already!" );
111111 MLAssert (!_serverFirstMessageParsed, @" SCRAM handler already parsed server-first-message!" );
112- NSDictionary * msg = [self parseScramString: str];
112+ NSDictionary * msg = [self parseScramString: str withKeysRegex: @" ^m?rsi.*$ " ];
113113 _serverFirstMessageParsed = YES ;
114114 // server nonce MUST start with our client nonce
115115 if (![msg[@" r" ] hasPrefix: _nonce])
@@ -140,7 +140,7 @@ -(MLScramStatus) parseServerFirstMessage:(NSString*) str
140140-(NSString *) clientFinalMessageWithChannelBindingData : (NSData * _Nullable) channelBindingData
141141{
142142 MLAssert (!_finishedSuccessfully, @" SCRAM handler finished already!" );
143- MLAssert (_serverFirstMessageParsed, @" SCRAM handler did not parsed server-first-message yet!" );
143+ MLAssert (_serverFirstMessageParsed, @" SCRAM handler did not parse server-first-message yet!" );
144144 // calculate gss header with optional channel binding data
145145 NSMutableData * gssHeaderWithChannelBindingData = [NSMutableData new ];
146146 [gssHeaderWithChannelBindingData appendData: [_gssHeader dataUsingEncoding: NSUTF8StringEncoding]];
@@ -180,7 +180,7 @@ -(MLScramStatus) parseServerFinalMessage:(NSString*) str
180180{
181181 MLAssert (!_finishedSuccessfully, @" SCRAM handler finished already!" );
182182 MLAssert (_serverFirstMessageParsed, @" SCRAM handler did not parsed server-first-message yet!" );
183- NSDictionary * msg = [self parseScramString: str];
183+ NSDictionary * msg = [self parseScramString: str withKeysRegex: @" ^(e|v).*$ " ];
184184 // wrong v-value
185185 if (![HelperTools constantTimeCompareAttackerString: msg[@" v" ] withKnownString: _expectedServerSignature])
186186 return MLScramStatusWrongServerProof;
@@ -245,15 +245,21 @@ -(NSData*) hash:(NSData*) data
245245 return nil ;
246246}
247247
248- -(NSDictionary * _Nullable) parseScramString : (NSString *) str
248+ -(NSDictionary * _Nullable) parseScramString : (NSString *) str withKeysRegex : ( NSString *) keyRegex
249249{
250+ NSRegularExpression * regex = [NSRegularExpression regularExpressionWithPattern: keyRegex options: 0 error: nil ];
251+ NSMutableString * keys = [NSMutableString new ];
250252 NSMutableDictionary * retval = [NSMutableDictionary new ];
251253 for (NSString * component in [str componentsSeparatedByString: @" ," ])
252254 {
253255 NSString * attribute = [component substringToIndex: 1 ];
254256 NSString * value = [component substringFromIndex: 2 ];
255257 retval[attribute] = [self unquote: value];
258+ [keys appendString: attribute];
256259 }
260+ // check order of attributes in accordance to RFC 5802
261+ if ([regex numberOfMatchesInString: keys options: 0 range: NSMakeRange (0 , [keys length ])] == 0 )
262+ return @{}; // return empty dictionary to make sure the wrong order doesn't lead to successful authentications
257263 return retval;
258264}
259265
0 commit comments