A little cleanup work. Still needs a configure script.

This commit is contained in:
Jonathan Schleifer 2011-02-25 23:52:29 +01:00
parent ba13fa3e3a
commit c44fefa67c
5 changed files with 318 additions and 249 deletions

View file

@ -1,6 +1,6 @@
all: all:
objfw-compile -Wall --lib 0.0 -o objxmpp *.m \ objfw-compile -Wall --lib 0.0 -o objxmpp *.m \
`pkg-config --cflags --libs libidn libbsd` `pkg-config --cflags --libs libidn`
clean: clean:
rm -f *.o *.so *.dylib *.dll rm -f *.o *.so *.dylib *.dll

View file

@ -28,7 +28,7 @@
password: (OFString*)password password: (OFString*)password
{ {
return [[[self alloc] initWithAuthcid: authcid return [[[self alloc] initWithAuthcid: authcid
password: password] autorelease]; password: password] autorelease];
} }
+ PLAINAuthWithAuthzid: (OFString*)authzid + PLAINAuthWithAuthzid: (OFString*)authzid
@ -36,23 +36,28 @@
password: (OFString*)password password: (OFString*)password
{ {
return [[[self alloc] initWithAuthzid: authzid return [[[self alloc] initWithAuthzid: authzid
authcid: authcid authcid: authcid
password: password] autorelease]; password: password] autorelease];
} }
- (OFDataArray*)clientFirstMessage - (OFDataArray*)clientFirstMessage
{ {
OFDataArray *message = [OFDataArray dataArrayWithItemSize: 1]; OFDataArray *message = [OFDataArray dataArrayWithItemSize: 1];
/* authzid */ /* authzid */
if (authzid) if (authzid)
[message addItem: authzid]; [message addItem: authzid];
/* separator */ /* separator */
[message addItem: ""]; [message addItem: ""];
/* authcid */ /* authcid */
[message addNItems: [authcid cStringLength] [message addNItems: [authcid cStringLength]
fromCArray: [authcid cString]]; fromCArray: [authcid cString]];
/* separator */ /* separator */
[message addItem: ""]; [message addItem: ""];
/* passwd */ /* passwd */
[message addNItems: [password cStringLength] [message addNItems: [password cStringLength]
fromCArray: [password cString]]; fromCArray: [password cString]];
@ -62,10 +67,10 @@
- (OFDataArray*)calculateResponseWithChallenge: (OFDataArray*)challenge - (OFDataArray*)calculateResponseWithChallenge: (OFDataArray*)challenge
{ {
@throw [XMPPAuthFailedException @throw [XMPPAuthFailedException newWithClass: isa
newWithClass: isa connection: nil
connection: nil reason: @"Received a challenge "
reason: @"Received a challenge during PLAIN auth"]; @"during PLAIN auth"];
} }
- (void)parseServerFinalMessage: (OFDataArray*)message - (void)parseServerFinalMessage: (OFDataArray*)message

View file

@ -44,8 +44,8 @@
* \return A new autoreleased XMPPSCRAMAuth * \return A new autoreleased XMPPSCRAMAuth
*/ */
+ SCRAMAuthWithAuthcid: (OFString*)authcid + SCRAMAuthWithAuthcid: (OFString*)authcid
password: (OFString*)password password: (OFString*)password
hash: (Class)hash; hash: (Class)hash;
/** /**
* Creates a new autoreleased XMPPSCRAMAuth with an authzid, * Creates a new autoreleased XMPPSCRAMAuth with an authzid,
@ -58,9 +58,9 @@
* \return A new autoreleased XMPPSCRAMAuth * \return A new autoreleased XMPPSCRAMAuth
*/ */
+ SCRAMAuthWithAuthzid: (OFString*)authzid + SCRAMAuthWithAuthzid: (OFString*)authzid
authcid: (OFString*)authcid authcid: (OFString*)authcid
password: (OFString*)password password: (OFString*)password
hash: (Class)hash; hash: (Class)hash;
/** /**
* Initializes an already allocated XMPPSCRAMAuth with an authcid and password. * Initializes an already allocated XMPPSCRAMAuth with an authcid and password.
@ -72,7 +72,7 @@
*/ */
- initWithAuthcid: (OFString*)authcid - initWithAuthcid: (OFString*)authcid
password: (OFString*)password password: (OFString*)password
hash: (Class)hash; hash: (Class)hash;
/** /**
* Initializes an already allocated XMPPSCRAMAuth with a authzid, * Initializes an already allocated XMPPSCRAMAuth with a authzid,

View file

@ -1,5 +1,6 @@
/* /*
* Copyright (c) 2011, Florian Zeitz <florob@babelmonkeys.de> * Copyright (c) 2011, Florian Zeitz <florob@babelmonkeys.de>
* Copyright (c) 2011, Jonathan Schleifer <js@webkeks.org>
* *
* https://webkeks.org/hg/objxmpp/ * https://webkeks.org/hg/objxmpp/
* *
@ -21,10 +22,6 @@
*/ */
#include <string.h> #include <string.h>
#include <bsd/stdlib.h>
// FIXME: Remove this once libbsd includes arc4random_uniform() in it's headers
#define fake_arc4random_uniform(upper) \
((uint32_t) (arc4random() / (double) UINT32_MAX * upper))
#import "XMPPSCRAMAuth.h" #import "XMPPSCRAMAuth.h"
#import "XMPPExceptions.h" #import "XMPPExceptions.h"
@ -32,8 +29,11 @@
#define HMAC_IPAD 0x36 #define HMAC_IPAD 0x36
#define HMAC_OPAD 0x5c #define HMAC_OPAD 0x5c
@implementation XMPPSCRAMAuth #ifndef HAVE_ARC4RANDOM_UNIFORM
extern uint32_t arc4random_uniform(uint32_t);
#endif
@implementation XMPPSCRAMAuth
+ SCRAMAuthWithAuthcid: (OFString*)authcid + SCRAMAuthWithAuthcid: (OFString*)authcid
password: (OFString*)password password: (OFString*)password
hash: (Class)hash; hash: (Class)hash;
@ -93,14 +93,12 @@
OFString *old = authzid; OFString *old = authzid;
if (authzid_) { if (authzid_) {
OFMutableString *new = [[OFMutableString alloc] OFMutableString *new = [[authzid_ mutableCopy] autorelease];
initWithString: authzid_];
[new replaceOccurrencesOfString: @"=" [new replaceOccurrencesOfString: @"="
withString: @"=3D"]; withString: @"=3D"];
[new replaceOccurrencesOfString: @"," [new replaceOccurrencesOfString: @","
withString: @"=2C"]; withString: @"=2C"];
authzid = [new copy]; authzid = [new retain];
[new release];
} else } else
authzid = nil; authzid = nil;
@ -112,54 +110,51 @@
OFString *old = authcid; OFString *old = authcid;
if (authcid_) { if (authcid_) {
OFMutableString *new = [[OFMutableString alloc] OFMutableString *new = [[authcid_ mutableCopy] autorelease];
initWithString: authcid_];
[new replaceOccurrencesOfString: @"=" [new replaceOccurrencesOfString: @"="
withString: @"=3D"]; withString: @"=3D"];
[new replaceOccurrencesOfString: @"," [new replaceOccurrencesOfString: @","
withString: @"=2C"]; withString: @"=2C"];
authcid = [new copy]; authcid = [new retain];
[new release];
} else } else
authcid = nil; authcid = nil;
[old release]; [old release];
} }
- (OFString *)_genNonce - (OFString*)_genNonce
{ {
OFMutableString *nonce = [OFMutableString string]; OFMutableString *nonce = [OFMutableString string];
uint32_t res, i; uint32_t res, i;
for (i = 0; i < 64; i++) { for (i = 0; i < 64; i++) {
while((res = fake_arc4random_uniform(0x5e) + 0x21) == 0x2C); while ((res = arc4random_uniform('~' - '!' + 1) + '!') == ',');
[nonce appendFormat: @"%c", res]; [nonce appendFormat: @"%c", res];
} }
return nonce; return nonce;
} }
- (uint8_t *)_hmacWithKey: (OFDataArray*)key - (uint8_t*)_HMACWithKey: (OFDataArray*)key
data: (OFDataArray*)data data: (OFDataArray*)data
{ {
OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];
OFDataArray *k = [OFDataArray dataArrayWithItemSize: 1];
size_t i, kSize, blockSize = [hashType blockSize]; size_t i, kSize, blockSize = [hashType blockSize];
uint8_t *kCArray = NULL, *kI = NULL, *kO = NULL; uint8_t *kCArray, *kI = NULL, *kO = NULL;
OFAutoreleasePool *pool = nil; OFHash *hash;
OFDataArray *k = nil;
OFHash *hash = nil; if (key.itemSize * key.count > blockSize) {
hash = [[[hashType alloc] init] autorelease];
[hash updateWithBuffer: [key cArray]
ofSize: key.itemSize * key.count];
[k addNItems: [hashType digestSize]
fromCArray: [hash digest]];
} else
[k addNItems: key.itemSize * key.count
fromCArray: [key cArray]];
@try { @try {
pool = [[OFAutoreleasePool alloc] init];
k = [OFDataArray dataArrayWithItemSize: 1];
if (key.itemSize * key.count > blockSize) {
hash = [[[hashType alloc] init] autorelease];
[hash updateWithBuffer: [key cArray]
ofSize: key.itemSize * key.count];
[k addNItems: [hashType digestSize]
fromCArray: [hash digest]];
} else
[k addNItems: key.itemSize * key.count
fromCArray: [key cArray]];
kI = [self allocMemoryWithSize: blockSize * sizeof(uint8_t)]; kI = [self allocMemoryWithSize: blockSize * sizeof(uint8_t)];
memset(kI, HMAC_IPAD, blockSize * sizeof(uint8_t)); memset(kI, HMAC_IPAD, blockSize * sizeof(uint8_t));
@ -177,7 +172,7 @@
[k addNItems: blockSize [k addNItems: blockSize
fromCArray: kI]; fromCArray: kI];
[k addNItems: data.itemSize * data.count [k addNItems: data.itemSize * data.count
fromCArray: [data cArray]]; fromCArray: [data cArray]];
hash = [[[hashType alloc] init] autorelease]; hash = [[[hashType alloc] init] autorelease];
[hash updateWithBuffer: [k cArray] [hash updateWithBuffer: [k cArray]
@ -187,89 +182,94 @@
fromCArray: kO]; fromCArray: kO];
[k addNItems: [hashType digestSize] [k addNItems: [hashType digestSize]
fromCArray: [hash digest]]; fromCArray: [hash digest]];
hash = [[[hashType alloc] init] autorelease];
[hash updateWithBuffer: [k cArray]
ofSize: k.count];
[hash retain];
[pool release];
pool = nil;
[hash autorelease];
return [hash digest];
} @finally { } @finally {
[pool release];
[self freeMemory: kI]; [self freeMemory: kI];
[self freeMemory: kO]; [self freeMemory: kO];
} }
hash = [[[hashType alloc] init] autorelease];
[hash updateWithBuffer: [k cArray]
ofSize: k.count];
[hash retain];
[pool release];
return [hash digest];
} }
- (OFDataArray *)_hiWithData: (OFDataArray *)str - (OFDataArray*)_hiWithData: (OFDataArray *)str
salt: (OFDataArray *)salt_ salt: (OFDataArray *)salt_
iterationCount: (unsigned int)i iterationCount: (unsigned int)i
{ {
OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];
size_t digestSize = [hashType digestSize];
uint8_t *result = NULL, *u, *uOld; uint8_t *result = NULL, *u, *uOld;
unsigned int j, k; unsigned int j, k;
size_t digestSize;
OFAutoreleasePool *pool = nil;
OFDataArray *salty, *tmp, *ret; OFDataArray *salty, *tmp, *ret;
result = [self allocMemoryWithSize: digestSize];
@try { @try {
pool = [[OFAutoreleasePool alloc] init]; memset(result, 0, digestSize);
digestSize = [hashType digestSize];
result = [self salty = [[salt_ copy] autorelease];
allocMemoryWithSize: digestSize * sizeof(uint8_t)];
memset(result, 0, digestSize * sizeof(uint8_t));
salty = [salt_ copy];
[salty addNItems: 4 [salty addNItems: 4
fromCArray: "\0\0\0\1"]; fromCArray: "\0\0\0\1"];
uOld = [self _hmacWithKey: str uOld = [self _HMACWithKey: str
data: salty]; data: salty];
[salty release];
for (j = 0; j < digestSize; j++) for (j = 0; j < digestSize; j++)
result[j] ^= uOld[j]; result[j] ^= uOld[j];
for (j = 0; j < i-1; j++) { for (j = 0; j < i - 1; j++) {
tmp = [OFDataArray dataArrayWithItemSize: 1]; tmp = [OFDataArray dataArrayWithItemSize: 1];
[tmp addNItems: digestSize [tmp addNItems: digestSize
fromCArray: uOld]; fromCArray: uOld];
u = [self _hmacWithKey: str
u = [self _HMACWithKey: str
data: tmp]; data: tmp];
for (k = 0; k < digestSize; k++) for (k = 0; k < digestSize; k++)
result[k] ^= u[k]; result[k] ^= u[k];
uOld = u; uOld = u;
[pool releaseObjects];
} }
ret = [OFDataArray dataArrayWithItemSize: 1]; ret = [OFDataArray dataArrayWithItemSize: 1];
[ret addNItems: digestSize [ret addNItems: digestSize
fromCArray: result]; fromCArray: result];
[ret retain];
[pool release];
pool = nil;
return [ret autorelease];
} @finally { } @finally {
[pool release];
[self freeMemory: result]; [self freeMemory: result];
} }
[ret retain];
[pool release];
return [ret autorelease];
} }
- (OFDataArray*)clientFirstMessage - (OFDataArray*)clientFirstMessage
{ {
OFDataArray *ret = [OFDataArray dataArrayWithItemSize: 1]; OFDataArray *ret = [OFDataArray dataArrayWithItemSize: 1];
[GS2Header release]; [GS2Header release];
GS2Header = nil;
if (authzid) if (authzid)
GS2Header = [[OFString alloc] GS2Header = [[OFString alloc]
initWithFormat: @"n,a=%@,", authzid]; initWithFormat: @"n,a=%@,", authzid];
else else
GS2Header = [[OFString alloc] initWithFormat: @"n,,"]; GS2Header = @"n,,";
[cNonce release]; [cNonce release];
cNonce = nil;
cNonce = [[self _genNonce] retain]; cNonce = [[self _genNonce] retain];
[clientFirstMessageBare release]; [clientFirstMessageBare release];
clientFirstMessageBare = nil;
clientFirstMessageBare = [[OFString alloc] clientFirstMessageBare = [[OFString alloc]
initWithFormat: @"n=%@,r=%@", authcid, cNonce]; initWithFormat: @"n=%@,r=%@", authcid, cNonce];
@ -292,183 +292,171 @@
OFString *tmpString, *sNonce; OFString *tmpString, *sNonce;
OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];
@try { hash = [[[hashType alloc] init] autorelease];
hash = [[[hashType alloc] init] autorelease]; ret = [OFDataArray dataArrayWithItemSize: 1];
ret = [OFDataArray dataArrayWithItemSize: 1]; authMessage = [OFDataArray dataArrayWithItemSize: 1];
authMessage = [OFDataArray dataArrayWithItemSize: 1];
OFString *chal = [OFString OFString *chal = [OFString stringWithCString: [challenge cArray]
stringWithCString: [challenge cArray] length: [challenge count] *
length: [challenge itemSize]];
[challenge count] * [challenge itemSize]];
for (OFString *comp for (OFString *comp in [chal componentsSeparatedByString: @","]) {
in [chal componentsSeparatedByString: @","]) { OFString *entry = [comp substringFromIndex: 2
OFString *entry = [comp toIndex: [comp length]];
substringFromIndex: 2
toIndex: [comp length]];
if ([comp hasPrefix: @"r="]) {
if (![entry hasPrefix: cNonce])
@throw [XMPPAuthFailedException
newWithClass: isa
connection: nil
reason:
@"Received wrong nonce"];
sNonce = entry;
} else if ([comp hasPrefix: @"s="])
salt = [OFDataArray
dataArrayWithBase64EncodedString: entry];
else if ([comp hasPrefix: @"i="])
iterCount = [entry decimalValue];
}
// Add c=<base64(GS2Header+channelBindingData)> if ([comp hasPrefix: @"r="]) {
// XXX: No channel binding for now if (![entry hasPrefix: cNonce])
tmpArray = [OFDataArray dataArrayWithItemSize: 1]; @throw [XMPPAuthFailedException
[tmpArray addNItems: [GS2Header cStringLength] newWithClass: isa
fromCArray: [GS2Header cString]]; connection: nil
tmpString = [tmpArray stringByBase64Encoding]; reason: @"Received wrong nonce"];
[ret addNItems: 2
fromCArray: "c="];
[ret addNItems: [tmpString cStringLength]
fromCArray: [tmpString cString]];
// Add r=<nonce> sNonce = entry;
[ret addItem: ","]; } else if ([comp hasPrefix: @"s="])
[ret addNItems: 2 salt = [OFDataArray
fromCArray: "r="]; dataArrayWithBase64EncodedString: entry];
[ret addNItems: [sNonce cStringLength] else if ([comp hasPrefix: @"i="])
fromCArray: [sNonce cString]]; iterCount = [entry decimalValue];
tmpArray = [OFDataArray dataArrayWithItemSize: 1];
[tmpArray addNItems: [password cStringLength]
fromCArray: [password cString]];
/*
* IETF RFC 5802:
* SaltedPassword := Hi(Normalize(password), salt, i)
*/
saltedPassword = [self _hiWithData: tmpArray
salt: salt
iterationCount: iterCount];
/*
* IETF RFC 5802:
* AuthMessage := client-first-message-bare + "," +
* server-first-message + "," +
* client-final-message-without-proof
*/
[authMessage addNItems: [clientFirstMessageBare cStringLength]
fromCArray: [clientFirstMessageBare cString]];
[authMessage addItem: ","];
[authMessage addNItems: [challenge count] * [challenge itemSize]
fromCArray: [challenge cArray]];
[authMessage addItem: ","];
[authMessage addNItems: [ret count]
fromCArray: [ret cArray]];
/*
* IETF RFC 5802:
* ClientKey := HMAC(SaltedPassword, "Client Key")
*/
tmpArray = [OFDataArray dataArrayWithItemSize: 1];
[tmpArray addNItems: 10
fromCArray: "Client Key"];
clientKey = [self _hmacWithKey: saltedPassword
data: tmpArray];
/*
* IETF RFC 5802:
* StoredKey := H(ClientKey)
*/
[hash updateWithBuffer: (void*) clientKey
ofSize: [hashType digestSize]];
tmpArray = [OFDataArray dataArrayWithItemSize: 1];
[tmpArray addNItems: [hashType digestSize]
fromCArray: [hash digest]];
/*
* IETF RFC 5802:
* ClientSignature := HMAC(StoredKey, AuthMessage)
*/
clientSignature = [self _hmacWithKey: tmpArray
data: authMessage];
/*
* IETF RFC 5802:
* ServerKey := HMAC(SaltedPassword, "Server Key")
*/
tmpArray = [OFDataArray dataArrayWithItemSize: 1];
[tmpArray addNItems: 10
fromCArray: "Server Key"];
serverKey = [self _hmacWithKey: saltedPassword
data: tmpArray];
/*
* IETF RFC 5802:
* ServerSignature := HMAC(ServerKey, AuthMessage)
*/
tmpArray = [OFDataArray dataArrayWithItemSize: 1];
[tmpArray addNItems: [hashType digestSize]
fromCArray: serverKey];
serverSignature = [[OFDataArray alloc] initWithItemSize: 1];
[serverSignature addNItems: [hashType digestSize]
fromCArray: [self _hmacWithKey: tmpArray
data: authMessage]];
/*
* IETF RFC 5802:
* ClientProof := ClientKey XOR ClientSignature
*/
tmpArray = [OFDataArray dataArrayWithItemSize: 1];
for (i = 0; i < [hashType digestSize]; i++) {
uint8_t c = clientKey[i] ^ clientSignature[i];
[tmpArray addItem: &c];
}
// Add p=<base64(ClientProof)>
[ret addItem: ","];
[ret addNItems: 2
fromCArray: "p="];
tmpString = [tmpArray stringByBase64Encoding];
[ret addNItems: [tmpString cStringLength]
fromCArray: [tmpString cString]];
[ret retain];
[pool release];
pool = nil;
return [ret autorelease];
} @finally {
[pool release];
} }
// Add c=<base64(GS2Header+channelBindingData)>
// XXX: No channel binding for now
tmpArray = [OFDataArray dataArrayWithItemSize: 1];
[tmpArray addNItems: [GS2Header cStringLength]
fromCArray: [GS2Header cString]];
tmpString = [tmpArray stringByBase64Encoding];
[ret addNItems: 2
fromCArray: "c="];
[ret addNItems: [tmpString cStringLength]
fromCArray: [tmpString cString]];
// Add r=<nonce>
[ret addItem: ","];
[ret addNItems: 2
fromCArray: "r="];
[ret addNItems: [sNonce cStringLength]
fromCArray: [sNonce cString]];
tmpArray = [OFDataArray dataArrayWithItemSize: 1];
[tmpArray addNItems: [password cStringLength]
fromCArray: [password cString]];
/*
* IETF RFC 5802:
* SaltedPassword := Hi(Normalize(password), salt, i)
*/
saltedPassword = [self _hiWithData: tmpArray
salt: salt
iterationCount: iterCount];
/*
* IETF RFC 5802:
* AuthMessage := client-first-message-bare + "," +
* server-first-message + "," +
* client-final-message-without-proof
*/
[authMessage addNItems: [clientFirstMessageBare cStringLength]
fromCArray: [clientFirstMessageBare cString]];
[authMessage addItem: ","];
[authMessage addNItems: [challenge count] * [challenge itemSize]
fromCArray: [challenge cArray]];
[authMessage addItem: ","];
[authMessage addNItems: [ret count]
fromCArray: [ret cArray]];
/*
* IETF RFC 5802:
* ClientKey := HMAC(SaltedPassword, "Client Key")
*/
tmpArray = [OFDataArray dataArrayWithItemSize: 1];
[tmpArray addNItems: 10
fromCArray: "Client Key"];
clientKey = [self _HMACWithKey: saltedPassword
data: tmpArray];
/*
* IETF RFC 5802:
* StoredKey := H(ClientKey)
*/
[hash updateWithBuffer: (void*) clientKey
ofSize: [hashType digestSize]];
tmpArray = [OFDataArray dataArrayWithItemSize: 1];
[tmpArray addNItems: [hashType digestSize]
fromCArray: [hash digest]];
/*
* IETF RFC 5802:
* ClientSignature := HMAC(StoredKey, AuthMessage)
*/
clientSignature = [self _HMACWithKey: tmpArray
data: authMessage];
/*
* IETF RFC 5802:
* ServerKey := HMAC(SaltedPassword, "Server Key")
*/
tmpArray = [OFDataArray dataArrayWithItemSize: 1];
[tmpArray addNItems: 10
fromCArray: "Server Key"];
serverKey = [self _HMACWithKey: saltedPassword
data: tmpArray];
/*
* IETF RFC 5802:
* ServerSignature := HMAC(ServerKey, AuthMessage)
*/
tmpArray = [OFDataArray dataArrayWithItemSize: 1];
[tmpArray addNItems: [hashType digestSize]
fromCArray: serverKey];
serverSignature = [[OFDataArray alloc] initWithItemSize: 1];
[serverSignature addNItems: [hashType digestSize]
fromCArray: [self _HMACWithKey: tmpArray
data: authMessage]];
/*
* IETF RFC 5802:
* ClientProof := ClientKey XOR ClientSignature
*/
tmpArray = [OFDataArray dataArrayWithItemSize: 1];
for (i = 0; i < [hashType digestSize]; i++) {
uint8_t c = clientKey[i] ^ clientSignature[i];
[tmpArray addItem: &c];
}
// Add p=<base64(ClientProof)>
[ret addItem: ","];
[ret addNItems: 2
fromCArray: "p="];
tmpString = [tmpArray stringByBase64Encoding];
[ret addNItems: [tmpString cStringLength]
fromCArray: [tmpString cString]];
[ret retain];
[pool release];
return [ret autorelease];
} }
- (void)parseServerFinalMessage: (OFDataArray*)message - (void)parseServerFinalMessage: (OFDataArray*)message
{ {
OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];
@try { OFString *mess = [OFString stringWithCString: [message cArray]
OFString *mess = [OFString length: [message count] *
stringWithCString: [message cArray] [message itemSize]];
length: [message count] * [message itemSize]]; OFString *value = [mess substringFromIndex: 2
toIndex: [mess length]];
OFString *value = [mess substringFromIndex: 2 if ([mess hasPrefix: @"v="]) {
toIndex: [mess length]]; if (![value isEqual: [serverSignature stringByBase64Encoding]])
@throw [XMPPAuthFailedException
newWithClass: isa
connection: nil
reason: @"Received wrong ServerSignature"];
} else
@throw [XMPPAuthFailedException newWithClass: isa
connection: nil
reason: value];
if ([mess hasPrefix: @"v="]) { [pool release];
if ([value compare:
[serverSignature stringByBase64Encoding]])
@throw [XMPPAuthFailedException
newWithClass: isa
connection: nil
reason:
@"Received wrong ServerSignature"];
} else
@throw [XMPPAuthFailedException newWithClass: isa
connection: nil
reason: value];
} @finally {
[pool release];
}
} }
@end @end

76
src/arc4random_uniform.m Normal file
View file

@ -0,0 +1,76 @@
/*
* Copyright (c) 1996, David Mazieres <dm@uun.org>
* Copyright (c) 2008, Damien Miller <djm@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* Arc4 random number generator for OpenBSD.
*
* This code is derived from section 17.1 of Applied Cryptography,
* second edition, which describes a stream cipher allegedly
* compatible with RSA Labs "RC4" cipher (the actual description of
* which is a trade secret). The same algorithm is used as a stream
* cipher called "arcfour" in Tatu Ylonen's ssh package.
*
* RC4 is a registered trademark of RSA Laboratories.
*/
#include <stdlib.h>
#include <stdint.h>
/*
* Calculate a uniformly distributed random number less than upper_bound
* avoiding "modulo bias".
*
* Uniformity is achieved by generating new random numbers until the one
* returned is outside the range [0, 2**32 % upper_bound). This
* guarantees the selected random number will be inside
* [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound)
* after reduction modulo upper_bound.
*/
uint32_t
arc4random_uniform(uint32_t upper_bound)
{
uint32_t r, min;
if (upper_bound < 2)
return 0;
#if (ULONG_MAX > 0xffffffffUL)
min = 0x100000000UL % upper_bound;
#else
/* Calculate (2**32 % upper_bound) avoiding 64-bit math */
if (upper_bound > 0x80000000)
min = 1 + ~upper_bound; /* 2**32 - upper_bound */
else {
/* (2**32 - (x * 2)) % x == 2**32 % x when x <= 2**31 */
min = ((0xffffffff - (upper_bound * 2)) + 1) % upper_bound;
}
#endif
/*
* This could theoretically loop forever but each retry has
* p > 0.5 (worst case, usually far better) of selecting a
* number inside the range we need, so it should rarely need
* to re-roll.
*/
for (;;) {
r = arc4random();
if (r >= min)
break;
}
return r % upper_bound;
}