📄 zdm2read.c
字号:
/* Copyright 2003-2006, Voltage Security, all rights reserved.
*/
#include "vibe.h"
#include "environment.h"
#include "base.h"
#include "libctx.h"
#include "securearchive.h"
#include "errorctx.h"
#include "vtassert.h"
#include "datanode.h"
#include "compress.h"
#include "archive.h"
#include "sacommon.h"
#include "zdm2common.h"
#include "stringutil.h"
#include "securemail.h"
#include "zdm.h"
typedef struct VoltZDM2ReadLocalCtx {
VtSecureArchiveObject mSecureArchive;
VtBufferTypeInfo mBufferTypeInfo;
unsigned int mMessageFormat;
VtZDMEmailRecipientList mPrimaryRecipientList;
VtZDMEmailRecipientList mCCRecipientList;
int mCurrentEntryType;
VtDataNodeObject mInsecureAttributes;
VtStreamObject mInputStream;
unsigned char mOwnsInputStream;
unsigned char mReadInitCalled;
unsigned char mMessageUnwrapped;
unsigned char mEmailRecipientsInited;
unsigned char mSecureArchiveInited;
} VoltZDM2ReadLocalCtx;
static void VoltZDM2ReadLocalCtxDestroy(Pointer obj, Pointer ctx)
{
VtZDMObject zdmObj = (VtZDMObject)obj;
VoltZDM2ReadLocalCtx* readCtx;
VtLibCtx libCtx = (VtLibCtx)0;
if ((obj == (Pointer)0) || (ctx == (Pointer)0))
return;
readCtx = (VoltZDM2ReadLocalCtx*)ctx;
VT_ASSERT(readCtx != (VoltZDM2ReadLocalCtx*)0);
libCtx = zdmObj->voltObject.libraryCtx;
VT_ASSERT(libCtx != (VtLibCtx)0);
VtDestroySecureArchiveObject(&readCtx->mSecureArchive);
VtDestroyDataNodeObject(&readCtx->mInsecureAttributes);
if (readCtx->mOwnsInputStream)
VtDestroyStreamObject(&readCtx->mInputStream);
Z2Free(readCtx->mPrimaryRecipientList.emailList);
Z2Free(readCtx->mCCRecipientList.emailList);
Z2Free(readCtx);
}
static int VoltZDM2InitEmailRecipients(
VtZDMObject zdmObj
)
{
int status = 0;
VtLibCtx libCtx = (VtLibCtx)0;
VoltZDM2ReadLocalCtx* readCtx;
VtDataNodeObject attributesNode;
VtDataNodeObject recipientsNode;
VtDataNodeObject recipientNode;
VtDataNodeObject node;
const unsigned char* recipientAddress;
long recipientFlags;
int recipientCount;
int i;
VOLT_DECLARE_FNCT_LINE(fnctLine)
VOLT_DECLARE_ERROR_TYPE(errorType)
VT_ASSERT(zdmObj != (VtZDMObject)0);
libCtx = zdmObj->voltObject.libraryCtx;
VT_ASSERT(libCtx != (VtLibCtx)0);
readCtx = (VoltZDM2ReadLocalCtx*) zdmObj->localCtx;
VT_ASSERT(readCtx != (VoltZDM2ReadLocalCtx*)0);
VT_ASSERT(readCtx->mSecureArchive != (VtSecureArchiveObject)0);
VOLT_SET_ERROR_TYPE(errorType, 0)
do
{
if (readCtx->mEmailRecipientsInited)
break;
/* Access the attributes node maintained by the secure archive.
* This is sort of a hack and we could get around it by getting
* all the information through the public attribute API, but it
* would be inconvenient.
*/
VOLT_SET_FNCT_LINE(fnctLine)
status = VtGetSecureArchiveParam(readCtx->mSecureArchive,
VtSecureArchiveParamAttributesNode, (Pointer*)&attributesNode);
if (status != 0)
break;
VOLT_SET_FNCT_LINE(fnctLine)
status = VtDataNodeResolveChild(attributesNode,
VoltZDM2RecipientsAttributeName, 0, &recipientsNode);
if (status != 0)
break;
/* Figure out how many total recipients there are. This count will
* include both primary and CC recipients. We use this total to
* allocate the email address array for both the primary and CC
* recipients even though we probably won't fill them up, but it's
* not that wasteful and it avoid having to make a preliminary pass
* over the recipients to determine the counts.
*/
VOLT_SET_FNCT_LINE(fnctLine)
status = VtDataNodeGetChildCount(recipientsNode, &recipientCount);
if (status != 0)
break;
readCtx->mPrimaryRecipientList.emailList = (const unsigned char**)
Z3Malloc(recipientCount * sizeof(unsigned char*));
readCtx->mCCRecipientList.emailList = (const unsigned char**)
Z3Malloc(recipientCount * sizeof(unsigned char*));
if ((readCtx->mPrimaryRecipientList.emailList == (const unsigned char**)0) ||
(readCtx->mCCRecipientList.emailList == (const unsigned char**)0))
{
VOLT_SET_ERROR_TYPE(errorType, VT_ERROR_TYPE_PRIMARY)
VOLT_SET_FNCT_LINE(fnctLine)
status = VT_ERROR_MEMORY;
break;
}
/* Loop over the recipients, extracting the recipient email
* address and flags.
*/
for (i = 0; i < recipientCount; i++)
{
VOLT_SET_FNCT_LINE(fnctLine)
status = VtDataNodeGetChild(recipientsNode, i, &recipientNode);
if (status != 0)
break;
VOLT_SET_FNCT_LINE(fnctLine)
status = VtDataNodeLookupChild(recipientNode,
VoltZDM2AddressAttributeName, &node);
if (status != 0)
break;
VOLT_SET_FNCT_LINE(fnctLine)
status = VtDataNodeGetStringValue(node, &recipientAddress);
if (status != 0)
break;
VOLT_SET_FNCT_LINE(fnctLine)
status = VtDataNodeLookupChild(recipientNode,
VoltZDM2FlagsAttributeName, &node);
if (status != 0)
break;
VOLT_SET_FNCT_LINE(fnctLine)
status = VtDataNodeGetIntegerValue(node, &recipientFlags);
if (status != 0)
break;
/* If the primary recipient flag is set then add it to the
* primary recipient list.
*/
if ((recipientFlags & VOLT_ZDM_RECIPIENT_FLAGS_PRIMARY) != 0)
{
readCtx->mPrimaryRecipientList.emailList[
readCtx->mPrimaryRecipientList.count++] = recipientAddress;
}
/* If the CC recipient flag is set then add it to the
* CC recipient list.
*/
if ((recipientFlags & VOLT_ZDM_RECIPIENT_FLAGS_CC) != 0)
{
readCtx->mCCRecipientList.emailList[
readCtx->mCCRecipientList.count++] = recipientAddress;
}
}
readCtx->mEmailRecipientsInited = 1;
}
while (0);
VOLT_LOG_ERROR_COMPARE(status, libCtx, status, errorType,
fnctLine,"VoltZDM2InitEmailRecipients", (unsigned char*)0)
return status;
}
static int VoltZDM2InitInsecureAttributes(
VtZDMObject zdmObj
)
{
int status = 0;
VtLibCtx libCtx = (VtLibCtx)0;
VoltZDM2ReadLocalCtx* readCtx;
VtSecureArchiveCurrentEntryInfo currentEntryInfo;
unsigned char buffer[1000];
unsigned int size;
VtStreamSize streamSize;
unsigned char* attributesXML = (unsigned char*)0;
VtStreamObject attributesStream = (VtStreamObject)0;
VtStreamImplMemoryInfo memoryInfo;
VOLT_DECLARE_FNCT_LINE(fnctLine)
VOLT_DECLARE_ERROR_TYPE(errorType)
VT_ASSERT(zdmObj != (VtZDMObject)0);
libCtx = zdmObj->voltObject.libraryCtx;
VT_ASSERT(libCtx != (VtLibCtx)0);
readCtx = (VoltZDM2ReadLocalCtx*) zdmObj->localCtx;
VT_ASSERT(readCtx != (VoltZDM2ReadLocalCtx*)0);
VT_ASSERT(readCtx->mSecureArchive != (VtSecureArchiveObject)0);
VOLT_SET_ERROR_TYPE(errorType, 0)
do
{
if (readCtx->mInsecureAttributes != (VtDataNodeObject)0)
break;
/* Create a stream to hold the contents of the insecure
* attributes entry. Since we're going to access the buffer
* directly below to pass to the data node call, the stream
* needs to be a memory-based stream, so we always create the
* stream using the VtStreamImplMemory instead of using the
* buffer type specified by the user. The insecure attributes
* entry will typically be pretty small, so there shouldn't be
* much of a memory overhead from using the memory-based stream.
*/
VOLT_SET_FNCT_LINE(fnctLine)
Z2Memset(&memoryInfo, 0, sizeof(memoryInfo));
memoryInfo.flags = VT_STREAM_OPEN_ON_ACCESS;
memoryInfo.openMode = VT_STREAM_OPEN_READ_WRITE;
status = VtCreateStreamObject(libCtx, VtStreamImplMemory,
(Pointer)&memoryInfo, &attributesStream);
if (status != 0)
break;
/* Set the current entry in the secure archive */
currentEntryInfo.type = VT_SECURE_ARCHIVE_CURRENT_ENTRY_INSECURE;
currentEntryInfo.name = VoltZDM2InsecureAttributesFilePathName;
VOLT_SET_FNCT_LINE(fnctLine)
status = VtSetSecureArchiveParam(readCtx->mSecureArchive,
VtSecureArchiveParamCurrentEntry, (Pointer)¤tEntryInfo);
if (status != 0)
break;
/* Copy over the contents to the stream */
for (;;)
{
VOLT_SET_FNCT_LINE(fnctLine)
status = VtSecureArchiveReadUpdate(readCtx->mSecureArchive,
(unsigned char*)0, 0, (unsigned int*)0, buffer,
sizeof(buffer), &size);
if ((status != 0) || (size == 0))
{
if (status == VT_ERROR_END_OF_STREAM)
status = 0;
break;
}
VOLT_SET_FNCT_LINE(fnctLine)
status = VtStreamWrite(attributesStream, buffer, size);
if (status != 0)
break;
}
if (status != 0)
break;
/* Add a null-terminator, so we can use the memory buffer
* as a C string to pass to the data node call.
*/
VOLT_SET_FNCT_LINE(fnctLine)
status = VtStreamWrite(attributesStream, "", 1);
if (status != 0)
break;
/* Get a pointer to the stream's underlying buffer. This buffer
* is still owned by the stream, so we don't need to delete it
*/
VOLT_SET_FNCT_LINE(fnctLine)
status = VtStreamGetBuffer(attributesStream, &attributesXML, &streamSize);
if (status != 0)
break;
VOLT_SET_FNCT_LINE(fnctLine)
status = VtCreateDataNodeObjectFromXML(libCtx, attributesXML,
&readCtx->mInsecureAttributes);
if (status != 0)
break;
}
while (0);
VtDestroyStreamObject(&attributesStream);
VOLT_LOG_ERROR_COMPARE(status, libCtx, status, errorType,
fnctLine,"VoltZDM2InitInsecureAttributes", (unsigned char*)0)
return status;
}
static int VoltZDM2UnwrapMessage(
VtZDMObject zdmObj
)
{
int status = 0;
VtLibCtx libCtx = (VtLibCtx)0;
VoltZDM2ReadLocalCtx* readCtx;
const unsigned int messageBufferSize = 4096;
unsigned char* messageBuffer = (unsigned char*)0;
unsigned char* dataBuffer = (unsigned char*)0;
unsigned int dataBufferSize = 0;
unsigned int dataSize;
VtAlgorithmObject base64Decoder = (VtAlgorithmObject)0;
VtStreamSize dataLength;
int copyDataLength = 0;
unsigned char* copySrc;
int foundStartTag = 0;
int foundEndTag = 0;
int maxStartTagLength;
unsigned char* startData = 0;
unsigned char* endData;
unsigned int bytesConsumed;
unsigned int startTagVersion;
unsigned int tagStartOffset;
unsigned int tagEndOffset;
const char* startInputFieldValue = "value=\"";
int startInputFieldLength;
int inInputFieldTag = 0;
unsigned char* p;
VOLT_DECLARE_FNCT_LINE(fnctLine)
VOLT_DECLARE_ERROR_TYPE(errorType)
VT_ASSERT(zdmObj != (VtZDMObject)0);
libCtx = zdmObj->voltObject.libraryCtx;
VT_ASSERT(libCtx != (VtLibCtx)0);
readCtx = (VoltZDM2ReadLocalCtx*) zdmObj->localCtx;
VT_ASSERT(readCtx != (VoltZDM2ReadLocalCtx*)0);
VOLT_SET_ERROR_TYPE(errorType, 0)
do
{
if (readCtx->mMessageUnwrapped)
break;
startInputFieldLength = Z2Strlen(startInputFieldValue);
maxStartTagLength = Z2Strlen(VoltZDM2SecureBlockStartTagPrefix) +
Z2Strlen(VoltZDM2SecureBlockStartTagPrefix) +
VOLT_ZDM2_MAX_VERSION_NUMBER_LENGTH;
messageBuffer = (unsigned char*) Z3Malloc(messageBufferSize);
if (messageBuffer == (unsigned char*)0)
{
VOLT_SET_FNCT_LINE(fnctLine)
VOLT_SET_ERROR_TYPE(errorType, VT_ERROR_TYPE_PRIMARY)
status = VT_ERROR_MEMORY;
break;
}
do
{
VOLT_SET_FNCT_LINE(fnctLine)
status = VtStreamRead(readCtx->mInputStream,
messageBuffer + copyDataLength,
messageBufferSize - copyDataLength, &dataLength);
if (status != 0)
{
status = VT_ERROR_INVALID_ZDM_MSG;
break;
}
startData = (unsigned char*)0;
endData = (unsigned char*)0;
dataLength += copyDataLength;
//messageBuffer[dataLength] = 0;
if (foundStartTag)
{
startData = messageBuffer;
}
else
{
foundStartTag = VoltZDM2FindMessageTag(libCtx,
VoltZDM2SecureBlockStartTagPrefix,
VoltZDM2SecureBlockStartTagSuffix, messageBuffer,
dataLength, 2, VOLT_ZDM2_CURRENT_VERSION, &startTagVersion,
&tagStartOffset, &tagEndOffset);
if (foundStartTag)
{
startData = messageBuffer + tagEndOffset;
}
}
if (foundStartTag)
{
copyDataLength = startInputFieldLength;
endData = 0;
p = startData;
while ((p < messageBuffer + dataLength) && !foundEndTag)
{
if (inInputFieldTag)
{
if ((p + startInputFieldLength < messageBuffer + dataLength) &&
(VoltCaseInsensitiveCompareBuffers(p, startInputFieldLength,
startInputFieldValue, startInputFieldLength, libCtx) == 0))
{
p += startInputFieldLength;
startData = p;
inInputFieldTag = 0;
}
else
{
p++;
}
}
else if (*p == '"')
{
endData = p++;
inInputFieldTag = 1;
}
else if (*p == VoltZDM2SecureBlockEndTagPrefix[0])
{
endData = p;
foundEndTag = 1;
}
else
{
p++;
if (p == messageBuffer + dataLength)
endData = p - copyDataLength;
}
if (endData > startData)
{
if (base64Decoder == (VtAlgorithmObject)0)
{
VOLT_SET_FNCT_LINE(fnctLine)
status = VtCreateAlgorithmObject(libCtx, VtAlgorithmImplBase64,
(Pointer)0, &base64Decoder);
if (status != 0)
break;
VOLT_SET_FNCT_LINE(fnctLine)
status = VtDecodeInit(base64Decoder);
if (status != 0)
break;
}
if (foundEndTag)
{
status = VtDecodeFinal(base64Decoder, (VtRandomObject)0,
startData, endData - startData, dataBuffer,
dataBufferSize, &dataSize);
}
else
{
status = VtDecodeUpdate(base64Decoder, (VtRandomObject)0,
startData, endData - startData, dataBuffer,
dataBufferSize, &dataSize);
}
if (status == VT_ERROR_BUFFER_TOO_SMALL)
{
Z2Free(dataBuffer);
dataBuffer = (unsigned char*) Z3Malloc(dataSize);
if (dataBuffer == (unsigned char*)0)
{
VOLT_SET_FNCT_LINE(fnctLine)
VOLT_SET_ERROR_TYPE(errorType, VT_ERROR_TYPE_PRIMARY)
status = VT_ERROR_MEMORY;
break;
}
dataBufferSize = dataSize;
if (foundEndTag)
{
VOLT_SET_FNCT_LINE(fnctLine)
status = VtDecodeFinal(base64Decoder, (VtRandomObject)0,
startData, endData - startData, dataBuffer,
dataBufferSize, &dataSize);
}
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -