buffer_unpackers.cpp [plain text]
#include "buffer_unpackers.h"
#include "DSUtils.h"
sInt32 Get2FromBuffer( tDataBufferPtr inAuthData, tDataList **inOutDataList, char **inOutItemOne, char **inOutItemTwo, unsigned int *outItemCount )
{
sInt32 siResult = eDSNoErr;
tDataList *dataList = NULL;
unsigned int itemCount = 0;
try
{
dataList = dsAuthBufferGetDataListAllocPriv(inAuthData);
if ( dataList == nil ) throw( (sInt32)eDSInvalidBuffFormat );
itemCount = dsDataListGetNodeCountPriv(dataList);
if ( outItemCount != NULL )
*outItemCount = itemCount;
if ( itemCount < 2 ) throw( (sInt32)eDSInvalidBuffFormat );
*inOutItemOne = dsDataListGetNodeStringPriv(dataList, 1);
if ( *inOutItemOne == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( strlen(*inOutItemOne) < 1 )
siResult = eDSInvalidBuffFormat;
*inOutItemTwo = dsDataListGetNodeStringPriv(dataList, 2);
if ( *inOutItemTwo == nil ) throw( (sInt32)eDSInvalidBuffFormat );
}
catch( sInt32 catchErr )
{
siResult = catchErr;
}
if ( inOutDataList != NULL )
{
*inOutDataList = dataList;
}
else
{
if ( dataList != NULL )
{
dsDataListDeallocatePriv(dataList);
free(dataList);
dataList = NULL;
}
}
return siResult;
}
sInt32 UnpackSambaBufferFirstThreeItems( tDataBufferPtr inAuthData, tDataListPtr *outDataList, char **outUserName, unsigned char *outChallenge, unsigned long *outChallengeLen, unsigned char **outResponse, unsigned long *outResponseLen )
{
sInt32 siResult = eDSNoErr;
tDataListPtr dataList = NULL;
tDataNodePtr pC8Node = NULL;
tDataNodePtr pP24InputNode = NULL;
try
{
dataList = dsAuthBufferGetDataListAllocPriv(inAuthData);
if ( dataList == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( dsDataListGetNodeCountPriv(dataList) < 3 ) throw( (sInt32)eDSInvalidBuffFormat );
*outUserName = dsDataListGetNodeStringPriv(dataList, 1);
if ( *outUserName == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( strlen(*outUserName) < 1 ) throw( (sInt32)eDSInvalidBuffFormat );
siResult = dsDataListGetNodePriv(dataList, 2, &pC8Node);
if ( pC8Node == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( pC8Node->fBufferLength > 16 ) throw( (sInt32)eDSInvalidBuffFormat);
if ( siResult != eDSNoErr ) throw( (sInt32)eDSInvalidBuffFormat );
memmove(outChallenge, ((tDataBufferPriv*)pC8Node)->fBufferData, pC8Node->fBufferLength);
*outChallengeLen = pC8Node->fBufferLength;
siResult = dsDataListGetNodePriv(dataList, 3, &pP24InputNode);
if ( siResult != eDSNoErr || pP24InputNode == nil )
throw( (sInt32)eDSInvalidBuffFormat );
*outResponse = (unsigned char *) malloc( pP24InputNode->fBufferLength );
if ( *outResponse == NULL )
throw( (sInt32)eMemoryError );
*outResponseLen = pP24InputNode->fBufferLength;
memmove(*outResponse, ((tDataBufferPriv*)pP24InputNode)->fBufferData, pP24InputNode->fBufferLength);
}
catch ( sInt32 error )
{
siResult = error;
}
*outDataList = dataList;
return siResult;
}
sInt32 UnpackSambaBuffer( tDataBufferPtr inAuthData, char **outUserName, unsigned char *outC8, unsigned char *outP24 )
{
sInt32 siResult = eDSNoErr;
tDataListPtr dataList = NULL;
unsigned char *response = NULL;
unsigned long challengeLen = 0;
unsigned long responseLen = 0;
unsigned char challengeBytes[17];
siResult = UnpackSambaBufferFirstThreeItems( inAuthData, &dataList, outUserName, challengeBytes, &challengeLen, &response, &responseLen );
if ( siResult == eDSNoErr ) {
if ( dsDataListGetNodeCountPriv(dataList) != 3 )
siResult = eDSInvalidBuffFormat;
if ( challengeLen != kHashShadowChallengeLength || responseLen != kHashShadowResponseLength )
siResult = eDSInvalidBuffFormat;
if ( siResult == eDSNoErr ) {
memmove( outC8, challengeBytes, challengeLen );
memmove( outP24, response, responseLen );
}
}
if ( dataList != NULL ) {
dsDataListDeallocatePriv( dataList );
free( dataList );
}
if ( response != NULL )
free( response );
return siResult;
}
sInt32 UnpackNTLMv2Buffer(
tDataBufferPtr inAuthData,
char **outNIName,
unsigned char *outChal,
unsigned char **outDigest,
unsigned long *outDigestLen,
char **outSambaName,
char **outDomain)
{
sInt32 siResult = eDSNoErr;
tDataListPtr dataList = NULL;
unsigned long challengeLen = 0;
siResult = UnpackSambaBufferFirstThreeItems( inAuthData, &dataList, outNIName, outChal, &challengeLen, outDigest, outDigestLen );
if ( siResult == eDSNoErr ) {
if ( dsDataListGetNodeCountPriv(dataList) != 5 || challengeLen != kHashShadowChallengeLength )
siResult = eDSInvalidBuffFormat;
}
try
{
if ( siResult == eDSNoErr )
{
*outSambaName = dsDataListGetNodeStringPriv(dataList, 4);
if ( *outSambaName == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( strlen(*outSambaName) < 1 ) throw( (sInt32)eDSInvalidBuffFormat );
*outDomain = dsDataListGetNodeStringPriv(dataList, 5);
if ( *outDomain == nil ) {
*outDomain = (char *)calloc(1,1);
if ( *outDomain == nil ) throw( (sInt32)eMemoryError );
}
}
}
catch ( sInt32 error )
{
siResult = error;
}
if (dataList != NULL) {
dsDataListDeallocatePriv(dataList);
free(dataList);
dataList = NULL;
}
return siResult;
}
sInt32 UnpackMSCHAPv2Buffer(
tDataBufferPtr inAuthData,
char **outNIName,
unsigned char *outChal,
unsigned char **outPeerChal,
unsigned char **outDigest,
unsigned long *outDigestLen,
char **outSambaName)
{
sInt32 siResult = eDSNoErr;
tDataListPtr dataList = NULL;
tDataNodePtr pP24InputNode = NULL;
unsigned long challengeLen = 0;
unsigned long peerChallengeLen = 0;
siResult = UnpackSambaBufferFirstThreeItems( inAuthData, &dataList, outNIName, outChal, &challengeLen, outPeerChal, &peerChallengeLen );
if ( siResult == eDSNoErr ) {
if ( dsDataListGetNodeCountPriv(dataList) != 5 || challengeLen != 16 || peerChallengeLen != 16 )
siResult = eDSInvalidBuffFormat;
}
try
{
if ( siResult == eDSNoErr )
{
siResult = dsDataListGetNodePriv( dataList, 4, &pP24InputNode );
if ( siResult != eDSNoErr || pP24InputNode == NULL )
throw( (sInt32)eDSInvalidBuffFormat );
*outDigest = (unsigned char *) malloc( pP24InputNode->fBufferLength );
if ( *outDigest == NULL )
throw( (sInt32)eMemoryError );
*outDigestLen = pP24InputNode->fBufferLength;
memmove(*outDigest, ((tDataBufferPriv*)pP24InputNode)->fBufferData, pP24InputNode->fBufferLength);
*outSambaName = dsDataListGetNodeStringPriv( dataList, 5 );
if ( *outSambaName == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( strlen(*outSambaName) < 1 ) throw( (sInt32)eDSInvalidBuffFormat );
}
}
catch ( sInt32 error )
{
siResult = error;
}
if (dataList != NULL) {
dsDataListDeallocatePriv(dataList);
free(dataList);
dataList = NULL;
}
return siResult;
}
sInt32 UnpackMPPEKeyBuffer( tDataBufferPtr inAuthData, char **outUserName, unsigned char *outP24, int *outKeySize )
{
sInt32 siResult = eDSNoErr;
tDataListPtr dataList = NULL;
tDataNodePtr pP24Node = NULL;
tDataNodePtr pKeySizeNode = NULL;
try
{
dataList = dsAuthBufferGetDataListAllocPriv(inAuthData);
if ( dataList == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( dsDataListGetNodeCountPriv(dataList) != 3 ) throw( (sInt32)eDSInvalidBuffFormat );
*outUserName = dsDataListGetNodeStringPriv(dataList, 1);
if ( *outUserName == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( strlen(*outUserName) < 1 ) throw( (sInt32)eDSInvalidBuffFormat );
siResult = dsDataListGetNodePriv(dataList, 2, &pP24Node);
if ( siResult != eDSNoErr )
throw( siResult );
if ( pP24Node == NULL || pP24Node->fBufferLength != 24)
throw( (sInt32)eDSInvalidBuffFormat );
memmove(outP24, ((tDataBufferPriv*)pP24Node)->fBufferData, pP24Node->fBufferLength);
siResult = dsDataListGetNodePriv(dataList, 3, &pKeySizeNode);
if ( siResult != eDSNoErr || pKeySizeNode == NULL || pKeySizeNode->fBufferLength != 1 )
throw( (sInt32)eDSInvalidBuffFormat );
*outKeySize = ((tDataBufferPriv*)pKeySizeNode)->fBufferData[0];
if ( *outKeySize != 8 && *outKeySize != 16 )
throw( (sInt32)eDSInvalidBuffFormat );
}
catch ( sInt32 error )
{
siResult = error;
}
if (dataList != NULL) {
dsDataListDeallocatePriv(dataList);
free(dataList);
dataList = NULL;
}
return siResult;
}
sInt32 UnpackDigestBuffer( tDataBufferPtr inAuthData, char **outUserName, digest_context_t *digestContext )
{
sInt32 siResult = eDSNoErr;
tDataListPtr dataList = NULL;
tDataNodePtr pResponseNode = NULL;
unsigned int itemCount = 0;
char *challenge = NULL;
char *challengePlus = NULL;
char *response = NULL;
char *method = NULL;
int saslResult = 0;
try
{
siResult = Get2FromBuffer( inAuthData, &dataList, outUserName, &challenge, &itemCount );
if ( siResult != noErr )
throw( siResult );
method = dsDataListGetNodeStringPriv( dataList, 4 );
if ( method == nil ) throw( (sInt32)eDSInvalidBuffFormat );
if ( strlen(method) < 1 ) throw( (sInt32)eDSInvalidBuffFormat );
challengePlus = (char *) malloc( strlen(challenge) + 10 + strlen(method) );
strcpy( challengePlus, challenge );
strcat( challengePlus, ",method=\"" );
strcat( challengePlus, method );
strcat( challengePlus, "\"" );
siResult = dsDataListGetNodePriv( dataList, 3, &pResponseNode );
if ( siResult != eDSNoErr ) throw( (sInt32)eDSInvalidBuffFormat );
if ( pResponseNode == NULL ) throw( (sInt32)eDSInvalidBuffFormat );
response = (char *) calloc( 1, pResponseNode->fBufferLength + 1 );
memmove( response, ((tDataBufferPriv*)pResponseNode)->fBufferData, ((tDataBufferPriv*)pResponseNode)->fBufferLength );
saslResult = digest_server_parse( challengePlus, strlen(challengePlus), response, digestContext );
if ( saslResult != 0 )
throw( (sInt32)eDSAuthFailed );
}
catch ( sInt32 error )
{
siResult = error;
}
if ( challenge != NULL ) {
free( challenge );
challenge = NULL;
}
if ( challengePlus != NULL ) {
free( challengePlus );
challengePlus = NULL;
}
if ( method != NULL ) {
free( method );
method = NULL;
}
if ( response != NULL ) {
free( response );
response = NULL;
}
if (dataList != NULL) {
dsDataListDeallocatePriv(dataList);
free(dataList);
dataList = NULL;
}
return siResult;
}
sInt32 UnpackCramBuffer( tDataBufferPtr inAuthData, char **outUserName, char **outChal, unsigned char **outResponse, unsigned long *outResponseLen )
{
sInt32 siResult = eDSNoErr;
tDataListPtr dataList = NULL;
tDataNodePtr pResponseNode = NULL;
unsigned int itemCount = 0;
try
{
siResult = Get2FromBuffer( inAuthData, &dataList, outUserName, outChal, &itemCount );
if ( siResult != noErr )
throw( siResult );
if ( itemCount != 3 )
throw( (sInt32)eDSInvalidBuffFormat );
siResult = dsDataListGetNodePriv( dataList, 3, &pResponseNode );
if ( siResult != eDSNoErr || pResponseNode == NULL || pResponseNode->fBufferLength < 32 )
throw( (sInt32)eDSInvalidBuffFormat );
*outResponse = (unsigned char *) malloc( pResponseNode->fBufferLength );
if ( *outResponse == NULL )
throw( (sInt32)eMemoryError );
*outResponseLen = pResponseNode->fBufferLength;
memmove( *outResponse, ((tDataBufferPriv*)pResponseNode)->fBufferData, pResponseNode->fBufferLength );
}
catch ( sInt32 error )
{
siResult = error;
if ( *outUserName != NULL ) {
free( *outUserName );
*outUserName = NULL;
}
if ( *outChal != NULL ) {
free( *outChal );
*outChal = NULL;
}
}
if ( dataList != NULL ) {
dsDataListDeallocatePriv( dataList );
free( dataList );
dataList = NULL;
}
return siResult;
}
sInt32 UnpackAPOPBuffer( tDataBufferPtr inAuthData, char **outUserName, char **outChal, char **outResponse )
{
sInt32 siResult = eDSNoErr;
tDataListPtr dataList = NULL;
unsigned int itemCount = 0;
try
{
siResult = Get2FromBuffer( inAuthData, &dataList, outUserName, outChal, &itemCount );
if ( siResult != noErr )
throw( siResult );
if ( itemCount != 3 )
throw( (sInt32)eDSInvalidBuffFormat );
*outResponse = dsDataListGetNodeStringPriv( dataList, 3 );
if ( *outResponse == NULL )
throw( (sInt32)eDSInvalidBuffFormat );
}
catch ( sInt32 error )
{
siResult = error;
if ( *outUserName != NULL ) {
free( *outUserName );
*outUserName = NULL;
}
if ( *outChal != NULL ) {
free( *outChal );
*outChal = NULL;
}
}
if ( dataList != NULL ) {
dsDataListDeallocatePriv( dataList );
free( dataList );
dataList = NULL;
}
return siResult;
}
sInt32 RepackBufferForPWServer ( tDataBufferPtr inBuff, const char *inUserID, unsigned long inUserIDNodeNum, tDataBufferPtr *outBuff )
{
sInt32 result = eDSNoErr;
tDataListPtr dataList = NULL;
tDataNodePtr dataNode = NULL;
unsigned long index, nodeCount;
unsigned long uidLen;
if ( !inBuff || !inUserID || !outBuff )
return eDSAuthParameterError;
try
{
uidLen = strlen(inUserID);
*outBuff = ::dsDataBufferAllocatePriv( inBuff->fBufferLength + uidLen + 1 );
if ( *outBuff == nil ) throw( (sInt32)eMemoryError );
(*outBuff)->fBufferLength = 0;
dataList = dsAuthBufferGetDataListAllocPriv(inBuff);
if ( dataList == nil ) throw( (sInt32)eDSInvalidBuffFormat );
nodeCount = dsDataListGetNodeCountPriv(dataList);
if ( nodeCount < 1 ) throw( (sInt32)eDSInvalidBuffFormat );
for ( index = 1; index <= nodeCount; index++ )
{
if ( index == inUserIDNodeNum )
{
memcpy( (*outBuff)->fBufferData + (*outBuff)->fBufferLength, &uidLen, sizeof(unsigned long) );
(*outBuff)->fBufferLength += sizeof(unsigned long);
memcpy( (*outBuff)->fBufferData + (*outBuff)->fBufferLength, inUserID, uidLen );
(*outBuff)->fBufferLength += uidLen;
}
else
{
result = dsDataListGetNodeAllocPriv(dataList, index, &dataNode);
if ( result != eDSNoErr ) throw( (sInt32)eDSInvalidBuffFormat );
memcpy((*outBuff)->fBufferData + (*outBuff)->fBufferLength, &dataNode->fBufferLength, sizeof(unsigned long));
(*outBuff)->fBufferLength += sizeof(unsigned long);
memcpy( (*outBuff)->fBufferData + (*outBuff)->fBufferLength, dataNode->fBufferData, dataNode->fBufferLength );
(*outBuff)->fBufferLength += dataNode->fBufferLength;
dsDataBufferDeallocatePriv(dataNode);
}
}
(void)dsDataListDeallocatePriv(dataList);
free(dataList);
}
catch( sInt32 error )
{
result = error;
}
return result;
}
sInt32 GetUserNameFromAuthBuffer ( tDataBufferPtr inAuthData, unsigned long inUserNameIndex,
char **outUserName )
{
tDataListPtr dataList = dsAuthBufferGetDataListAllocPriv(inAuthData);
if (dataList != NULL)
{
*outUserName = dsDataListGetNodeStringPriv(dataList, inUserNameIndex);
dsDataListDeallocatePriv(dataList);
free(dataList);
dataList = NULL;
return eDSNoErr;
}
return eDSInvalidBuffFormat;
}