mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-15 00:44:19 +09:00
winpr asn1: fixes and more features
This patches adds support for octet string containers that are used by SPNego (a subfield is contained in an octet string record). It also adds a performance test to test reallocations in asn1 encoder. It fixes reallocation problems for both chunks and containers.
This commit is contained in:
@@ -154,6 +154,9 @@ extern "C"
|
||||
WINPR_API BOOL WinPrAsn1EncSetContainer(WinPrAsn1Encoder* enc);
|
||||
WINPR_API BOOL WinPrAsn1EncContextualSetContainer(WinPrAsn1Encoder* enc, WinPrAsn1_tagId tagId);
|
||||
WINPR_API BOOL WinPrAsn1EncContextualContainer(WinPrAsn1Encoder* enc, WinPrAsn1_tagId tagId);
|
||||
WINPR_API BOOL WinPrAsn1EncOctetStringContainer(WinPrAsn1Encoder* enc);
|
||||
WINPR_API BOOL WinPrAsn1EncContextualOctetStringContainer(WinPrAsn1Encoder* enc,
|
||||
WinPrAsn1_tagId tagId);
|
||||
WINPR_API size_t WinPrAsn1EncEndContainer(WinPrAsn1Encoder* enc);
|
||||
|
||||
WINPR_API size_t WinPrAsn1EncInteger(WinPrAsn1Encoder* enc, WinPrAsn1_INTEGER integer);
|
||||
|
||||
@@ -40,7 +40,8 @@ typedef enum
|
||||
ASN1_CONTAINER_SEQ,
|
||||
ASN1_CONTAINER_SET,
|
||||
ASN1_CONTAINER_APP,
|
||||
ASN1_CONTAINER_CONTEXT_ONLY
|
||||
ASN1_CONTAINER_CONTEXT_ONLY,
|
||||
ASN1_CONTAINER_OCTETSTRING,
|
||||
} ContainerType;
|
||||
|
||||
typedef struct WinPrAsn1EncContainer WinPrAsn1EncContainer;
|
||||
@@ -228,7 +229,7 @@ static Asn1Chunk* asn1enc_get_free_chunk(WinPrAsn1Encoder* enc, size_t chunkSz,
|
||||
return NULL;
|
||||
|
||||
if (enc->chunks == &enc->staticChunks[0])
|
||||
memcpy(tmp, src, enc->chunksCapacity * sizeof(*src));
|
||||
memcpy(tmp, &enc->staticChunks[0], enc->chunksCapacity * sizeof(*src));
|
||||
else
|
||||
memset(tmp + enc->freeChunkId, 0, sizeof(*tmp) * 10);
|
||||
|
||||
@@ -268,7 +269,7 @@ static WinPrAsn1EncContainer* asn1enc_get_free_container(WinPrAsn1Encoder* enc,
|
||||
return NULL;
|
||||
|
||||
if (enc->containers == &enc->staticContainers[0])
|
||||
memcpy(tmp, src, enc->containerCapacity * sizeof(*src));
|
||||
memcpy(tmp, &enc->staticContainers[0], enc->containerCapacity * sizeof(*src));
|
||||
|
||||
enc->containers = tmp;
|
||||
enc->containerCapacity += 10;
|
||||
@@ -375,6 +376,16 @@ BOOL WinPrAsn1EncContextualContainer(WinPrAsn1Encoder* enc, WinPrAsn1_tagId tagI
|
||||
return getAsn1Container(enc, ASN1_CONTAINER_CONTEXT_ONLY, tagId, TRUE, 6) != NULL;
|
||||
}
|
||||
|
||||
BOOL WinPrAsn1EncOctetStringContainer(WinPrAsn1Encoder* enc)
|
||||
{
|
||||
return getAsn1Container(enc, ASN1_CONTAINER_OCTETSTRING, 0, FALSE, 6) != NULL;
|
||||
}
|
||||
|
||||
BOOL WinPrAsn1EncContextualOctetStringContainer(WinPrAsn1Encoder* enc, WinPrAsn1_tagId tagId)
|
||||
{
|
||||
return getAsn1Container(enc, ASN1_CONTAINER_OCTETSTRING, tagId, TRUE, 6 + 6) != NULL;
|
||||
}
|
||||
|
||||
size_t WinPrAsn1EncEndContainer(WinPrAsn1Encoder* enc)
|
||||
{
|
||||
size_t innerLen, i, unused;
|
||||
@@ -405,6 +416,10 @@ size_t WinPrAsn1EncEndContainer(WinPrAsn1Encoder* enc)
|
||||
containerByte = ER_TAG_SET;
|
||||
innerHeaderBytes = 1 + lenBytes(innerLen);
|
||||
break;
|
||||
case ASN1_CONTAINER_OCTETSTRING:
|
||||
containerByte = ER_TAG_OCTET_STRING;
|
||||
innerHeaderBytes = 1 + lenBytes(innerLen);
|
||||
break;
|
||||
case ASN1_CONTAINER_APP:
|
||||
containerByte = ER_TAG_APP | container->tag;
|
||||
innerHeaderBytes = 1 + lenBytes(innerLen);
|
||||
@@ -441,6 +456,7 @@ size_t WinPrAsn1EncEndContainer(WinPrAsn1Encoder* enc)
|
||||
{
|
||||
case ASN1_CONTAINER_SEQ:
|
||||
case ASN1_CONTAINER_SET:
|
||||
case ASN1_CONTAINER_OCTETSTRING:
|
||||
case ASN1_CONTAINER_APP:
|
||||
Stream_Write_UINT8(s, containerByte);
|
||||
asn1WriteLen(s, innerLen);
|
||||
|
||||
@@ -137,6 +137,7 @@ static WinPrAsn1_OID oid4 = { sizeof(oid4_val), oid4_val };
|
||||
|
||||
int TestASN1Write(int argc, char* argv[])
|
||||
{
|
||||
size_t i;
|
||||
wStream* s = NULL;
|
||||
size_t expectedOuputSz;
|
||||
int retCode = 100;
|
||||
@@ -159,6 +160,9 @@ int TestASN1Write(int argc, char* argv[])
|
||||
* [6] SEQ (empty)
|
||||
* [7] UTC time (2016-03-17 16:40:41 UTC)
|
||||
* [8] IA5String(test)
|
||||
* [9] OctetString
|
||||
* SEQ(empty)
|
||||
*
|
||||
*/
|
||||
|
||||
/* APP(3) */
|
||||
@@ -240,8 +244,27 @@ int TestASN1Write(int argc, char* argv[])
|
||||
if (WinPrAsn1EncEndContainer(enc) != 8)
|
||||
goto out;
|
||||
|
||||
/* [9] OctetString
|
||||
* SEQ(empty)
|
||||
*/
|
||||
retCode = 121;
|
||||
if (!WinPrAsn1EncContextualOctetStringContainer(enc, 9))
|
||||
goto out;
|
||||
|
||||
retCode = 122;
|
||||
if (!WinPrAsn1EncSeqContainer(enc))
|
||||
goto out;
|
||||
|
||||
retCode = 123;
|
||||
if (WinPrAsn1EncEndContainer(enc) != 2)
|
||||
goto out;
|
||||
|
||||
retCode = 124;
|
||||
if (WinPrAsn1EncEndContainer(enc) != 6)
|
||||
goto out;
|
||||
|
||||
/* close APP */
|
||||
expectedOuputSz = 24 + 6 + 4 + 17 + 8;
|
||||
expectedOuputSz = 24 + 6 + 4 + 17 + 8 + 6;
|
||||
retCode = 200;
|
||||
if (WinPrAsn1EncEndContainer(enc) != expectedOuputSz)
|
||||
goto out;
|
||||
@@ -255,9 +278,43 @@ int TestASN1Write(int argc, char* argv[])
|
||||
retCode = 202;
|
||||
if (!WinPrAsn1EncToStream(enc, s) || Stream_GetPosition(s) != expectedOuputSz)
|
||||
goto out;
|
||||
/* winpr_HexDump("", WLOG_ERROR, Stream_Buffer(s), Stream_GetPosition(s));*/
|
||||
|
||||
/*
|
||||
* let's perform a mini-performance test, where we encode an ASN1 message with a big depth,
|
||||
* so that we trigger reallocation routines in the encoder. We're gonna encode something like
|
||||
* SEQ1
|
||||
* SEQ2
|
||||
* SEQ3
|
||||
* ...
|
||||
* SEQ1000
|
||||
* INTEGER(2)
|
||||
*
|
||||
* As static chunks and containers are 50, a depth of 1000 should be enough
|
||||
*
|
||||
*/
|
||||
WinPrAsn1Encoder_Reset(enc);
|
||||
|
||||
retCode = 203;
|
||||
for (i = 0; i < 1000; i++)
|
||||
{
|
||||
if (!WinPrAsn1EncSeqContainer(enc))
|
||||
goto out;
|
||||
}
|
||||
|
||||
retCode = 204;
|
||||
if (WinPrAsn1EncInteger(enc, 2) != 3)
|
||||
goto out;
|
||||
|
||||
retCode = 205;
|
||||
for (i = 0; i < 1000; i++)
|
||||
{
|
||||
if (!WinPrAsn1EncEndContainer(enc))
|
||||
goto out;
|
||||
}
|
||||
|
||||
retCode = 0;
|
||||
|
||||
/*winpr_HexDump("", WLOG_ERROR, Stream_Buffer(s), Stream_GetPosition(s));*/
|
||||
out:
|
||||
if (s)
|
||||
Stream_Free(s, TRUE);
|
||||
|
||||
Reference in New Issue
Block a user