windows-nt/Source/XPSP1/NT/termsrv/remdsk/rds/t120/mst120/ogcccode.cpp

355 lines
10 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
#include "precomp.h"
DEBUG_FILEZONE(ZONE_T120_GCCNC);
/*
* ogcccode.cpp
*
* Copyright (c) 1994 by DataBeam Corporation, Lexington, KY
*
* Abstract:
* This is the implementation file for the CGCCCoder class. This class
* is responsible for encoding and decoding GCC (T.124) PDU's using ASN.1
* encoding rules via the ASN.1 toolkit. This class is also capable
* of determining the size of both the encoded and decoded PDU's.
*
* Static Variables:
*
* Caveats:
* Only one instance of this class should be in existance at any one time
* due to the static variable.
*
* Author:
* John B. O'Nan
*/
/*
* External Interfaces
*/
#include <string.h>
#include "ogcccode.h"
/*
* This is a global variable that has a pointer to the one GCC coder that
* is instantiated by the GCC Controller. Most objects know in advance
* whether they need to use the MCS or the GCC coder, so, they do not need
* this pointer in their constructors.
*/
CGCCCoder *g_GCCCoder;
/*
* CGCCCoder ()
*
* Public
*
* Functional Description:
* This is the constructor for the CGCCCoder class. It initializes
* the ASN.1 encoder/decoder and sets the encoding rules to the
* Packed-Aligned variant.
*/
CGCCCoder::CGCCCoder ()
:m_pEncInfo(NULL),
m_pDecInfo(NULL)
{
// lonchanc: We should move Init out of constructor. However,
// to minimize the changes in the GCC/MCS code, we put it here for now.
// Otherwise, we need to change MCS and Packet interfaces.
// We will move it out and call Init() separately.
Init();
}
BOOL CGCCCoder::Init ( void )
{
BOOL fRet = FALSE;
GCCPDU_Module_Startup();
if (GCCPDU_Module != NULL)
{
if (ASN1_CreateEncoder(
GCCPDU_Module, // ptr to mdule
&m_pEncInfo, // ptr to encoder info
NULL, // buffer ptr
0, // buffer size
NULL) // parent ptr
== ASN1_SUCCESS)
{
ASSERT(m_pEncInfo != NULL);
fRet = (ASN1_CreateDecoder(
GCCPDU_Module, // ptr to mdule
&m_pDecInfo, // ptr to decoder info
NULL, // buffer ptr
0, // buffer size
NULL) // parent ptr
== ASN1_SUCCESS);
ASSERT(fRet && m_pDecInfo != NULL);
}
}
ASSERT(fRet);
return fRet;
}
/*
* ~CGCCCoder ()
*
* Public Functional Description:
* This is a virtual destructor. It is used to clean up after ASN.1.
*/
CGCCCoder::~CGCCCoder ()
{
if (GCCPDU_Module != NULL)
{
ASN1_CloseEncoder(m_pEncInfo);
ASN1_CloseDecoder(m_pDecInfo);
GCCPDU_Module_Cleanup();
}
}
/*
* Encode ()
*
* Public Functional Description:
* This function encodes GCC Protocol Data Units (PDU's) into ASN.1
* compliant byte streams using the ASN.1 toolkit.
* The coder allocates the buffer space for the encoded data.
*/
BOOL CGCCCoder::Encode(LPVOID pdu_structure,
int pdu_type,
UINT nEncodingRule_not_used,
LPBYTE *encoding_buffer,
UINT *encoding_buffer_length)
{
BOOL fRet = FALSE;
int return_value;
ConnectData connect_data_structure;
// clean up local buffer pointer
connect_data_structure.connect_pdu.value = NULL;
/*
* If the PDU to be encoded is a "ConnectGCC" PDU we must first encode the
* "ConnectGCC" PDU. A "ConnectData" PDU structure is then built which
* contains the encoded "ConnectGCC" PDU along with object identifier key.
* The "ConnectData" PDU is then encoded into the provided buffer.
*/
if (pdu_type == CONNECT_GCC_PDU)
{
return_value = ASN1_Encode(m_pEncInfo, // ptr to encoder info
pdu_structure, // pdu data structure
pdu_type, // pdu id
ASN1ENCODE_ALLOCATEBUFFER, // flags
NULL, // do not provide buffer
0); // buffer size if provided
if (ASN1_FAILED(return_value))
{
ERROR_OUT(("CGCCCoder::Encode: ASN1_Encode failed, err=%d in CONNECT_GCC_PDU.",
return_value));
ASSERT(FALSE);
goto MyExit;
}
ASSERT(return_value == ASN1_SUCCESS);
/*
* Fill in the "ConnectData" PDU structure and encode it.
*/
connect_data_structure.t124_identifier = t124identifier;
connect_data_structure.connect_pdu.length = m_pEncInfo->len; // len of encoded data in buffer
connect_data_structure.connect_pdu.value = m_pEncInfo->buf; // buffer to encode into
// Prepare for the encode call
pdu_structure = (LPVOID) &connect_data_structure;
pdu_type = CONNECT_DATA_PDU;
}
/*
* Encode the Non-Connect PDU into the buffer provided.
*/
return_value = ASN1_Encode(m_pEncInfo, // ptr to encoder info
pdu_structure, // pdu data structure
pdu_type, // pdu id
ASN1ENCODE_ALLOCATEBUFFER, // flags
NULL, // do not provide buffer
0); // buffer size if provided
if (ASN1_FAILED(return_value))
{
ERROR_OUT(("CGCCCoder::Encode: ASN1_Encode failed, err=%d", return_value));
ASSERT(FALSE);
goto MyExit;
}
ASSERT(return_value == ASN1_SUCCESS);
*encoding_buffer_length = m_pEncInfo->len; // len of encoded data in buffer
*encoding_buffer = m_pEncInfo->buf; // buffer to encode into
fRet = TRUE;
MyExit:
/*
* If this was a CONNECT_DATA_PDU we need to free the buffer that
* was allocated by ASN.1.
*/
if (CONNECT_DATA_PDU == pdu_type && connect_data_structure.connect_pdu.value != NULL)
{
ASN1_FreeEncoded(m_pEncInfo, connect_data_structure.connect_pdu.value);
}
return fRet;
}
/*
* Decode ()
*
* Public Functional Description:
* This function decodes ASN.1 compliant byte streams into the
* appropriate GCC PDU structures using the ASN.1 toolkit.
*/
BOOL CGCCCoder::Decode(LPBYTE encoded_buffer,
UINT encoded_buffer_length,
int pdu_type,
UINT nEncodingRule_not_used,
LPVOID *pdecoding_buffer,
UINT *pdecoding_buffer_length)
{
BOOL fRet = FALSE;
int return_value;
LPVOID connect_data_decoding_buffer = NULL;
ASN1optionparam_s OptParam;
/*
* If the PDU is a "ConnectGCC" PDU then after it is decoded we must decode
* the "ConnectGCC" PDU which is actually contained within a "ConnectData"
* PDU.
*/
if (pdu_type == CONNECT_GCC_PDU)
{
return_value = ASN1_Decode(m_pDecInfo, // ptr to decoder info
&connect_data_decoding_buffer, // destination buffer
CONNECT_DATA_PDU, // pdu type
ASN1DECODE_SETBUFFER, // flags
encoded_buffer, // source buffer
encoded_buffer_length); // source buffer size
if (ASN1_FAILED(return_value))
{
ERROR_OUT(("CGCCCoder::Decode: ASN1_Decode failed, err=%d", return_value));
ASSERT(FALSE);
goto MyExit;
}
ASSERT(return_value == ASN1_SUCCESS);
/*
* If the decoded PDU is a "ConnectData" PDU, then we first must check
* to make sure this PDU originated from a T.124-compliant source.
* If so we then decode the "ConnectGCC" PDU which is held in the
* "connect_pdu" field. If the PDU is not T.124-compliant, we will
* report an error which will cause the PDU to be rejected.
*/
if (IsObjectIDCompliant(&(((PConnectData) connect_data_decoding_buffer)->t124_identifier))
== FALSE)
{
ERROR_OUT(("CGCCCoder::Decode: Non-T.124 objectID"));
ASSERT (FALSE);
goto MyExit;
}
ASSERT(connect_data_decoding_buffer != NULL);
encoded_buffer = (PUChar)((PConnectData) connect_data_decoding_buffer)->
connect_pdu.value;
encoded_buffer_length = (UINT)((PConnectData) connect_data_decoding_buffer)->
connect_pdu.length;
}
/*
* Decode the Non-Connect PDU into the buffer provided.
*/
return_value = ASN1_Decode(m_pDecInfo, // ptr to decoder info
pdecoding_buffer, // destination buffer
pdu_type, // pdu type
ASN1DECODE_SETBUFFER, // flags
encoded_buffer, // source buffer
encoded_buffer_length); // source buffer size
if (ASN1_FAILED(return_value))
{
ERROR_OUT(("CCCCoder::Decode: ASN1_Decode failed, err=%d", return_value));
ASSERT(FALSE);
goto MyExit;
}
ASSERT(return_value == ASN1_SUCCESS);
OptParam.eOption = ASN1OPT_GET_DECODED_BUFFER_SIZE;
return_value = ASN1_GetDecoderOption(m_pDecInfo, &OptParam);
if (ASN1_FAILED(return_value))
{
ERROR_OUT(("CGCCCoder::Decode: ASN1_GetDecoderOption failed, err=%d", return_value));
ASSERT(FALSE);
goto MyExit;
}
*pdecoding_buffer_length = OptParam.cbRequiredDecodedBufSize;
ASSERT(return_value == ASN1_SUCCESS);
ASSERT(*pdecoding_buffer_length > 0);
fRet = TRUE;
MyExit:
/*
* Free the PDU structure allocated by decoder for the Connect-Data PDU.
*/
if (connect_data_decoding_buffer != NULL)
{
ASSERT (pdu_type == CONNECT_GCC_PDU);
ASN1_FreeDecoded(m_pDecInfo, connect_data_decoding_buffer, CONNECT_DATA_PDU);
}
return fRet;
}
/*
* IsObjectIDCompliant ()
*
* Private Functional Description:
* This function is used to verify that the object identifier contained
* in a "Connect" PDU is compliant with this version of GCC.
*/
BOOL CGCCCoder::IsObjectIDCompliant (PKey t124_identifier)
{
BOOL return_value = TRUE;
PSetOfObjectID test_object_id_set;
PSetOfObjectID valid_object_id_set;
/*
* First check to make sure that the identifier is a standard Object
* Identifier type.
*/
if (t124_identifier->choice == OBJECT_CHOSEN)
{
/*
* Retrieve the object identifier to test and the valid T.124
* identifier ("t124identifier) to use as a comparison.
*/
test_object_id_set = t124_identifier->u.object;
valid_object_id_set = t124identifier.u.object;
while ((valid_object_id_set != NULL) && (test_object_id_set != NULL))
{
if (test_object_id_set->value != valid_object_id_set->value)
{
return_value = FALSE;
break;
}
test_object_id_set = test_object_id_set->next;
valid_object_id_set = valid_object_id_set->next;
}
}
else
return_value = FALSE;
return (return_value);
}
void CGCCCoder::FreeEncoded (PUChar encoded_buffer)
{
ASN1_FreeEncoded(m_pEncInfo, encoded_buffer);
}
void CGCCCoder::FreeDecoded (int pdu_type, LPVOID decoded_buffer)
{
ASN1_FreeDecoded(m_pDecInfo, decoded_buffer, pdu_type);
}