#ifndef __BIG_ENDIAN__
#include "DSMachEndian.h"
#include <string.h>
#include <errno.h> // system call error numbers
#include <unistd.h> // for select call
#include <stdlib.h> // for calloc()
#include <stdio.h>
#include <ctype.h>
#include <syslog.h>
#include <Security/Authorization.h>
#include "CServerPlugin.h"
#include "CLog.h"
#include "CReftable.h"
#include "CSharedData.h"
#define DUMP_BUFFER 0
#if DUMP_BUFFER
char* objectTypes[] =
{
"kResult",
"ktDirRef",
"ktNodeRef",
"ktRecRef",
"ktAttrListRef",
"ktAttrValueListRef",
"ktDataBuff",
"ktDataList",
"ktDirPattMatch",
"kAttrPattMatch",
"kAttrMatch",
"kMatchRecCount",
"kNodeNamePatt",
"ktAccessControlEntry",
"ktAttrEntry",
"ktAttrValueEntry",
"kOpenRecBool",
"kAttrInfoOnly",
"kRecFlags",
"kAttrFlags",
"kRecEntryIndex",
"kAttrInfoIndex",
"kAttrValueIndex",
"kAttrValueID",
"kOutBuffLen",
"kAuthStepDataLen",
"kAuthOnlyBool",
"kDirNodeName",
"kAuthMethod",
"kNodeInfoTypeList",
"kRecNameList",
"kRecTypeList",
"kAttrTypeList",
"kRecTypeBuff",
"kRecNameBuff",
"kAttrType",
"kAttrTypeBuff",
"kAttrValueBuff",
"kNewAttrBuff",
"kFirstAttrBuff",
"unknown",
"kAttrBuff",
"kAuthStepBuff",
"kAuthResponseBuff",
"kAttrTypeRequestList",
"kCustomRequestCode",
"kPluginName",
"kNodeCount",
"kNodeIndex",
"kAttrInfoCount",
"kAttrRecEntryCount",
"ktRecordEntry",
"kAuthStepDataResponse",
"kContextData",
"ktPidRef",
"ktGenericRef",
"kNodeChangeToken",
"ktEffectiveUID",
"ktUID",
"kAttrMatches",
"kAttrValueList"
};
FILE* gDumpFile = NULL;
void DumpBuf(char* buf, uInt32 len)
{
char acsiiBuf[17];
for (uInt32 i = 0; i < len; i++)
{
if ((i % 16) == 0) ::memset(acsiiBuf, 0, 17);
fprintf(gDumpFile, "%02X ", buf[i]);
if (::isprint(buf[i]))
acsiiBuf[i % 16] = buf[i];
else
acsiiBuf[i % 16] = '.';
if ((i % 16) == 15) fprintf(gDumpFile, " %s\n", acsiiBuf);
}
}
#endif
DSMachEndian::DSMachEndian(sComData* fMessage, int direction) : fMessage(fMessage)
{
toBig = (direction == kDSSwapToBig);
}
void DSMachEndian::SwapMessage()
{
short i;
sObject* object;
bool isTwoWay = false;
if (fMessage == nil) return;
#if DUMP_BUFFER
uInt32 bufSize = 0;
if (gDumpFile == NULL)
gDumpFile = fopen("/Library/Logs/DirectoryService/PacketDump", "w");
if (toBig)
fprintf(gDumpFile, "\n\n\nBuffer in host order (preSwap)\n");
else
fprintf(gDumpFile, "\n\n\nBuffer in network order (preSwap)\n");
for (i=0; i< 10; i++)
{
object = &fMessage->obj[i];
uInt32 objType = DSGetLong(&object->type, toBig);
uInt32 offset = DSGetLong(&object->offset, toBig);
uInt32 length = DSGetLong(&object->length, toBig);
char* type = "unknown";
if (objType >= kResult && objType <= kAttrValueList)
type = objectTypes[objType - kResult];
if (objType != 0)
{
if (length > 0)
fprintf(gDumpFile, "Object %d, type %s, offset %ld, size %ld\n", i, type, DSGetLong(&object->offset, toBig), DSGetLong(&object->length, toBig));
else
fprintf(gDumpFile, "Object %d, type %s, value %ld\n", i, type, DSGetLong(&object->count, toBig));
}
if (length > 0)
{
uInt32 size = offset + length - sizeof(sComData) + 4;
if (size > bufSize) bufSize = size;
}
}
DumpBuf(fMessage->data, bufSize);
#endif
DSSwapLong(&fMessage->fDataSize, toBig);
DSSwapLong(&fMessage->fDataLength, toBig);
DSSwapLong(&fMessage->fMsgID, toBig);
DSSwapLong(&fMessage->fPID, toBig);
uInt32 aNodeRef = 0;
bool bCustomCall = false;
uInt32 aCustomRequestNum = 0;
bool bIsAPICallResponse = false;
const char* aPluginName = nil;
for (i=0; i< 10; i++)
{
object = &fMessage->obj[i];
uInt32 objType = DSGetLong(&object->type, toBig);
if (objType == kAuthMethod)
{
char* method = (char *)fMessage + DSGetLong(&object->offset, toBig);
if ( ::strcmp( method, kDSStdAuth2WayRandom ) == 0 )
isTwoWay = true;
}
if (objType == kCustomRequestCode)
{
bCustomCall = true;
aCustomRequestNum = (uInt32)DSGetLong(&object->count, toBig);
DBGLOG1(kLogTCPEndpoint, "DSMachEndian::SwapMessage(): kCustomRequestCode with code %u", aCustomRequestNum );
}
if (objType == ktNodeRef)
{
aNodeRef = (uInt32)DSGetLong(&object->count, toBig);
}
if (objType == kResult)
{
bIsAPICallResponse = true;
}
}
if ( bCustomCall && (aCustomRequestNum != 0) )
{
if (aNodeRef != 0)
{
CServerPlugin *aPluginPtr = nil;
sInt32 myResult = CRefTable::VerifyNodeRef( aNodeRef, &aPluginPtr, fMessage->fPID, 0 );
if (myResult == eDSNoErr)
{
aPluginName = aPluginPtr->GetPluginName();
if (aPluginName != nil)
{
}
}
}
}
for (i=0; i< 10; i++)
{
object = &fMessage->obj[i];
if (object->type == 0)
continue;
uInt32 objType = DSGetAndSwapLong(&object->type, toBig);
DSSwapLong(&object->count, toBig);
uInt32 objOffset = DSGetAndSwapLong(&object->offset, toBig);
DSSwapLong(&object->used, toBig);
uInt32 objLength = DSGetAndSwapLong(&object->length, toBig);
DSSwapObjectData(objType, (char *)fMessage + objOffset, objLength, (!isTwoWay), bCustomCall, aCustomRequestNum, (const char*)aPluginName, bIsAPICallResponse, toBig);
}
#if DUMP_BUFFER
if (toBig)
fprintf(gDumpFile, "\n\nBuffer in network order (post Swap)\n");
else
fprintf(gDumpFile, "\n\nBuffer in host order (post Swap)\n");
DumpBuf(fMessage->data, bufSize);
fflush(stdout);
#endif
}
#endif