nla: use winpr asn1 library

This commit is contained in:
fifthdegree 2022-07-14 16:19:38 -04:00 committed by David Fort
parent decc55c30d
commit 5f3bc5842a
8 changed files with 323 additions and 2173 deletions

View File

@ -62,8 +62,6 @@ set(${MODULE_PREFIX}_SRCS
nla.c
nla.h
smartcardlogon.c
tscredentials.c
tscredentials.h
nego.c
nego.h
info.c

View File

@ -1,48 +0,0 @@
TSCredentials ::= SEQUENCE {
credType [0] INTEGER,
credentials [1] OCTET STRING
}
TSPasswordCreds ::= SEQUENCE {
domainName [0] OCTET STRING,
userName [1] OCTET STRING,
password [2] OCTET STRING
}
TSCspDataDetail ::= SEQUENCE {
keySpec [0] INTEGER,
cardName [1] OCTET STRING OPTIONAL,
readerName [2] OCTET STRING OPTIONAL,
containerName [3] OCTET STRING OPTIONAL,
cspName [4] OCTET STRING OPTIONAL
}
TSSmartCardCreds ::= SEQUENCE {
pin [0] OCTET STRING,
cspData [1] TSCspDataDetail,
userHint [2] OCTET STRING OPTIONAL,
domainHint [3] OCTET STRING OPTIONAL
}
TSRemoteGuardPackageCred ::= SEQUENCE {
packageName [0] OCTET STRING,
credBuffer [1] OCTET STRING,
}
TSRemoteGuardCreds ::= SEQUENCE {
logonCred [0] TSRemoteGuardPackageCred,
supplementalCreds [1] SEQUENCE OF TSRemoteGuardPackageCred OPTIONAL,
}
%options {
fieldOption TSCspDataDetail.cardName charInMemorySerializeToUnicode
fieldOption TSCspDataDetail.readerName charInMemorySerializeToUnicode
fieldOption TSCspDataDetail.containerName charInMemorySerializeToUnicode
fieldOption TSCspDataDetail.cspName charInMemorySerializeToUnicode
fieldOption TSSmartCardCreds.pin charInMemorySerializeToUnicode
fieldOption TSSmartCardCreds.userHint charInMemorySerializeToUnicode
fieldOption TSSmartCardCreds.domainHint charInMemorySerializeToUnicode
prefix nla_
}

View File

@ -44,10 +44,10 @@
#include <winpr/ncrypt.h>
#include <winpr/cred.h>
#include <winpr/debug.h>
#include <winpr/asn1.h>
#include "nla.h"
#include "utils.h"
#include "tscredentials.h"
#include <freerdp/utils/smartcardlogon.h>
#define TAG FREERDP_TAG("core.nla")
@ -153,7 +153,6 @@ static SECURITY_STATUS nla_decrypt_public_key_echo(rdpNla* nla);
static SECURITY_STATUS nla_decrypt_public_key_hash(rdpNla* nla);
static SECURITY_STATUS nla_encrypt_ts_credentials(rdpNla* nla);
static SECURITY_STATUS nla_decrypt_ts_credentials(rdpNla* nla);
static BOOL nla_read_ts_password_creds(rdpNla* nla, wStream* s);
static BOOL nla_Digest_Update_From_SecBuffer(WINPR_DIGEST_CTX* ctx, const SecBuffer* buffer)
{
@ -192,21 +191,6 @@ static BOOL nla_sec_buffer_alloc_from_buffer(SecBuffer* buffer, const SecBuffer*
return nla_sec_buffer_alloc_from_data(buffer, data->pvBuffer, offset, data->cbBuffer);
}
static BOOL nla_decode_to_buffer(wStream* s, SecBuffer* buffer)
{
BOOL rc = FALSE;
size_t length;
if (!s || !buffer)
return FALSE;
if (!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */
!Stream_CheckAndLogRequiredLength(TAG, s, length))
return FALSE;
rc = nla_sec_buffer_alloc_from_data(buffer, Stream_Pointer(s), 0, length);
Stream_Seek(s, length);
return rc;
}
static BOOL nla_set_package_name(rdpNla* nla, const TCHAR* name)
{
if (!nla)
@ -467,27 +451,6 @@ static SECURITY_STATUS nla_encrypt(rdpNla* nla, SecBuffer* buffer, size_t header
return status;
}
static size_t ber_sizeof_sequence_octet_string(size_t length)
{
size_t rc = ber_sizeof_contextual_tag(ber_sizeof_octet_string(length));
rc += ber_sizeof_octet_string(length);
return rc;
}
static size_t ber_write_sequence_octet_string(wStream* stream, BYTE context, const BYTE* value,
size_t length)
{
size_t rc = ber_write_contextual_tag(stream, context, ber_sizeof_octet_string(length), TRUE);
rc += ber_write_octet_string(stream, value, length);
return rc;
}
static size_t ber_write_sequence_octet_string_from_secbuffer(wStream* stream, BYTE context,
const SecBuffer* buffer)
{
return ber_write_sequence_octet_string(stream, context, buffer->pvBuffer, buffer->cbBuffer);
}
/* CredSSP Client-To-Server Binding Hash\0 */
static const BYTE ClientServerHashMagic[] = { 0x43, 0x72, 0x65, 0x64, 0x53, 0x53, 0x50, 0x20,
0x43, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x2D, 0x54,
@ -1936,110 +1899,66 @@ fail:
return status;
}
BOOL nla_read_ts_password_creds(rdpNla* nla, wStream* s)
{
size_t length;
size_t userLen = 0;
size_t domainLen = 0;
size_t passwordLen = 0;
const WCHAR* user = NULL;
const WCHAR* domain = NULL;
const WCHAR* password = NULL;
WINPR_ASSERT(nla);
WINPR_ASSERT(s);
if (!nla->identity)
{
WLog_ERR(TAG, "nla->identity is NULL!");
return FALSE;
}
/* TSPasswordCreds (SEQUENCE)
* Initialise to default values. */
sspi_FreeAuthIdentity(nla->identity);
if (!ber_read_sequence_tag(s, &length))
return FALSE;
/* The sequence is empty, return early,
* TSPasswordCreds (SEQUENCE) is optional. */
if (length == 0)
return TRUE;
/* [0] domainName (OCTET STRING) */
if (!ber_read_contextual_tag(s, 0, &length, TRUE) || !ber_read_octet_string_tag(s, &length))
{
return FALSE;
}
domainLen = length / sizeof(WCHAR);
if (length > 0)
domain = Stream_PointerAs(s, const WCHAR);
if (!Stream_SafeSeek(s, length))
return FALSE;
/* [1] userName (OCTET STRING) */
if (!ber_read_contextual_tag(s, 1, &length, TRUE) || !ber_read_octet_string_tag(s, &length))
return FALSE;
userLen = length / sizeof(WCHAR);
if (length > 0)
user = Stream_PointerAs(s, const WCHAR);
if (!Stream_SafeSeek(s, length))
return FALSE;
/* [2] password (OCTET STRING) */
if (!ber_read_contextual_tag(s, 2, &length, TRUE) || !ber_read_octet_string_tag(s, &length))
return FALSE;
passwordLen = length / sizeof(WCHAR);
if (length > 0)
password = Stream_PointerAs(s, const WCHAR);
if (!Stream_SafeSeek(s, length))
return FALSE;
return sspi_SetAuthIdentityWithLengthW(nla->identity, user, userLen, domain, domainLen,
password, passwordLen) > 0;
}
static BOOL nla_read_ts_credentials(rdpNla* nla, SecBuffer* data, size_t offset)
{
wStream* s;
size_t length;
size_t ts_password_creds_length = 0;
BOOL ret = FALSE;
WinPrAsn1Decoder dec, dec2;
WinPrAsn1_OctetString credentials;
BOOL error;
WinPrAsn1_INTEGER credType;
WINPR_ASSERT(nla);
if (!data)
WINPR_ASSERT(data);
WINPR_ASSERT(data->cbBuffer >= offset);
WinPrAsn1Decoder_InitMem(&dec, WINPR_ASN1_DER, (BYTE*)data->pvBuffer + offset,
data->cbBuffer - offset);
/* TSCredentials */
if (!WinPrAsn1DecReadSequence(&dec, &dec2))
return FALSE;
dec = dec2;
/* credType [0] INTEGER */
if (!WinPrAsn1DecReadContextualInteger(&dec, 0, &error, &credType))
return FALSE;
s = Stream_New(data->pvBuffer, data->cbBuffer);
/* credentials [1] OCTET STRING */
if (!WinPrAsn1DecReadContextualOctetString(&dec, 1, &error, &credentials, FALSE))
return FALSE;
if (!s)
WinPrAsn1Decoder_InitMem(&dec, WINPR_ASN1_DER, credentials.data, credentials.len);
if (credType == 1)
{
WLog_ERR(TAG, "Stream_New failed!");
return FALSE;
WinPrAsn1_OctetString domain;
WinPrAsn1_OctetString username;
WinPrAsn1_OctetString password;
/* TSPasswordCreds */
if (!WinPrAsn1DecReadSequence(&dec, &dec2))
return FALSE;
dec = dec2;
/* domainName [0] OCTET STRING */
if (!WinPrAsn1DecReadContextualOctetString(&dec, 0, &error, &domain, FALSE) && error)
return FALSE;
/* userName [1] OCTET STRING */
if (!WinPrAsn1DecReadContextualOctetString(&dec, 1, &error, &username, FALSE) && error)
return FALSE;
/* password [2] OCTET STRING */
if (!WinPrAsn1DecReadContextualOctetString(&dec, 2, &error, &password, FALSE))
return FALSE;
if (sspi_SetAuthIdentityWithLengthW(nla->identity, (WCHAR*)username.data,
username.len / sizeof(WCHAR), (WCHAR*)domain.data,
domain.len / sizeof(WCHAR), (WCHAR*)password.data,
password.len / sizeof(WCHAR)) < 0)
return FALSE;
}
if (!Stream_SafeSeek(s, offset))
goto fail;
/* TSCredentials (SEQUENCE) */
ret = ber_read_sequence_tag(s, &length) &&
/* [0] credType (INTEGER) */
ber_read_contextual_tag(s, 0, &length, TRUE) && ber_read_integer(s, NULL) &&
/* [1] credentials (OCTET STRING) */
ber_read_contextual_tag(s, 1, &length, TRUE) &&
ber_read_octet_string_tag(s, &ts_password_creds_length) &&
nla_read_ts_password_creds(nla, s);
fail:
Stream_Free(s, FALSE);
return ret;
return TRUE;
}
/**
@ -2049,13 +1968,12 @@ fail:
static BOOL nla_encode_ts_credentials(rdpNla* nla)
{
wStream* credsContentStream;
wStream staticRetStream;
wStream* s;
size_t length;
rdpSettings* settings;
BOOL ret = FALSE;
TSCredentials_t cr = { 0 };
WinPrAsn1Encoder* enc;
size_t length;
wStream s;
int credType;
WINPR_ASSERT(nla);
WINPR_ASSERT(nla->rdpcontext);
@ -2063,77 +1981,135 @@ static BOOL nla_encode_ts_credentials(rdpNla* nla)
settings = nla->rdpcontext->settings;
WINPR_ASSERT(settings);
enc = WinPrAsn1Encoder_New(WINPR_ASN1_DER);
if (!enc)
return FALSE;
/* TSCredentials */
if (!WinPrAsn1EncSeqContainer(enc))
goto out;
/* credType [0] INTEGER */
credType = settings->SmartcardLogon ? 2 : 1;
if (!WinPrAsn1EncContextualInteger(enc, 0, credType))
goto out;
/* credentials [1] OCTET STRING */
if (!WinPrAsn1EncContextualOctetStringContainer(enc, 1))
goto out;
if (settings->SmartcardLogon)
{
TSSmartCardCreds_t smartcardCreds = { 0 };
TSCspDataDetail_t cspData = { 0 };
char* Password = freerdp_settings_get_string_writable(settings, FreeRDP_Password);
struct
{
WinPrAsn1_tagId tag;
size_t setting_id;
} cspData_fields[] = { { 1, FreeRDP_CardName },
{ 2, FreeRDP_ReaderName },
{ 3, FreeRDP_ContainerName },
{ 4, FreeRDP_CspName } };
WinPrAsn1_OctetString octet_string = { 0 };
char* str;
BOOL ret;
smartcardCreds.pin = Password ? Password : "";
/* TSSmartCardCreds */
if (!WinPrAsn1EncSeqContainer(enc))
goto out;
/*smartcardCreds.userHint = settings->UserHint;
smartcardCreds.domainHint = settings->DomainHint;*/
smartcardCreds.cspData = &cspData;
/* pin [0] OCTET STRING */
str = freerdp_settings_get_string_writable(settings, FreeRDP_Password);
octet_string.len =
ConvertToUnicode(CP_UTF8, 0, str, -1, (LPWSTR*)&octet_string.data, 0) * sizeof(WCHAR);
ret = WinPrAsn1EncContextualOctetString(enc, 0, &octet_string);
free(octet_string.data);
if (!ret)
goto out;
cspData.keySpec = freerdp_settings_get_uint32(settings, FreeRDP_KeySpec);
cspData.cspName = freerdp_settings_get_string_writable(settings, FreeRDP_CspName);
cspData.readerName = freerdp_settings_get_string_writable(settings, FreeRDP_ReaderName);
cspData.cardName = freerdp_settings_get_string_writable(settings, FreeRDP_CardName);
cspData.containerName =
freerdp_settings_get_string_writable(settings, FreeRDP_ContainerName);
/* cspData [1] SEQUENCE */
if (!WinPrAsn1EncContextualSeqContainer(enc, 1))
goto out;
length = ber_sizeof_nla_TSSmartCardCreds(&smartcardCreds);
credsContentStream = Stream_New(NULL, length);
if (!credsContentStream)
return FALSE;
/* keySpec [0] INTEGER */
if (!WinPrAsn1EncContextualInteger(enc, 0,
freerdp_settings_get_uint32(settings, FreeRDP_KeySpec)))
goto out;
if (ber_write_nla_TSSmartCardCreds(credsContentStream, &smartcardCreds) == 0)
return FALSE;
for (int i = 0; i < ARRAYSIZE(cspData_fields); i++)
{
str = freerdp_settings_get_string_writable(settings, cspData_fields[i].setting_id);
octet_string.len =
ConvertToUnicode(CP_UTF8, 0, str, -1, (LPWSTR*)&octet_string.data, 0) *
sizeof(WCHAR);
if (octet_string.len)
{
ret = WinPrAsn1EncContextualOctetString(enc, cspData_fields[i].tag, &octet_string);
free(octet_string.data);
if (!ret)
goto out;
}
}
cr.credType = 2;
/* End cspData */
if (!WinPrAsn1EncEndContainer(enc))
goto out;
/* End TSSmartCardCreds */
if (!WinPrAsn1EncEndContainer(enc))
goto out;
}
else
{
TSPasswordCreds_t passCreds = { 0 };
WinPrAsn1_OctetString username = { 0 };
WinPrAsn1_OctetString domain = { 0 };
WinPrAsn1_OctetString password = { 0 };
/* TSPasswordCreds */
if (!WinPrAsn1EncSeqContainer(enc))
goto out;
if (!settings->DisableCredentialsDelegation && nla->identity)
{
passCreds.userNameLen = nla->identity->UserLength * 2;
passCreds.userName = (BYTE*)nla->identity->User;
username.len = nla->identity->UserLength * 2;
username.data = (BYTE*)nla->identity->User;
passCreds.domainNameLen = nla->identity->DomainLength * 2;
passCreds.domainName = (BYTE*)nla->identity->Domain;
domain.len = nla->identity->DomainLength * 2;
domain.data = (BYTE*)nla->identity->Domain;
passCreds.passwordLen = nla->identity->PasswordLength * 2;
passCreds.password = (BYTE*)nla->identity->Password;
password.len = nla->identity->PasswordLength * 2;
password.data = (BYTE*)nla->identity->Password;
}
length = ber_sizeof_nla_TSPasswordCreds(&passCreds);
credsContentStream = Stream_New(NULL, length);
if (!credsContentStream)
return FALSE;
if (!WinPrAsn1EncContextualOctetString(enc, 0, &domain))
goto out;
if (!WinPrAsn1EncContextualOctetString(enc, 1, &username))
goto out;
if (!WinPrAsn1EncContextualOctetString(enc, 2, &password))
goto out;
ber_write_nla_TSPasswordCreds(credsContentStream, &passCreds);
cr.credType = 1;
/* End TSPasswordCreds */
if (!WinPrAsn1EncEndContainer(enc))
goto out;
}
cr.credentialsLen = length;
cr.credentials = Stream_Buffer(credsContentStream);
/* End credentials | End TSCredentials */
if (!WinPrAsn1EncEndContainer(enc) || !WinPrAsn1EncEndContainer(enc))
goto out;
if (!WinPrAsn1EncStreamSize(enc, &length))
goto out;
length = ber_sizeof_nla_TSCredentials(&cr);
if (!nla_sec_buffer_alloc(&nla->tsCredentials, length))
{
WLog_ERR(TAG, "sspi_SecBufferAlloc failed!");
goto out;
}
s = Stream_StaticInit(&staticRetStream, (BYTE*)nla->tsCredentials.pvBuffer, length);
ber_write_nla_TSCredentials(s, &cr);
ret = TRUE;
Stream_StaticInit(&s, (BYTE*)nla->tsCredentials.pvBuffer, length);
if (WinPrAsn1EncToStream(enc, &s))
ret = TRUE;
out:
Stream_Free(credsContentStream, TRUE);
WinPrAsn1Encoder_Free(&enc);
return ret;
}
@ -2179,103 +2155,6 @@ static SECURITY_STATUS nla_decrypt_ts_credentials(rdpNla* nla)
return SEC_E_OK;
}
static size_t nla_sizeof_nego_token(size_t length)
{
length = ber_sizeof_octet_string(length);
length += ber_sizeof_contextual_tag(length);
return length;
}
static size_t nla_sizeof_nego_tokens(const SecBuffer* buffer)
{
WINPR_ASSERT(buffer);
size_t length = buffer->cbBuffer;
if (length == 0)
return 0;
length = nla_sizeof_nego_token(length);
length += ber_sizeof_sequence_tag(length);
length += ber_sizeof_sequence_tag(length);
length += ber_sizeof_contextual_tag(length);
return length;
}
static size_t nla_sizeof_pub_key_auth(const SecBuffer* buffer)
{
WINPR_ASSERT(buffer);
size_t length = buffer->cbBuffer;
if (length == 0)
return 0;
length = ber_sizeof_octet_string(length);
length += ber_sizeof_contextual_tag(length);
return length;
}
static size_t nla_sizeof_auth_info(const SecBuffer* buffer)
{
WINPR_ASSERT(buffer);
size_t length = buffer->cbBuffer;
if (length == 0)
return 0;
length = ber_sizeof_octet_string(length);
length += ber_sizeof_contextual_tag(length);
return length;
}
static size_t nla_sizeof_client_nonce(const SecBuffer* buffer)
{
WINPR_ASSERT(buffer);
size_t length = buffer->cbBuffer;
if (length == 0)
return 0;
length = ber_sizeof_octet_string(length);
length += ber_sizeof_contextual_tag(length);
return length;
}
static size_t nla_sizeof_ts_request(size_t length)
{
length += ber_sizeof_integer(2);
length += ber_sizeof_contextual_tag(3);
return length;
}
static BOOL nla_client_write_nego_token(wStream* s, const SecBuffer* negoToken)
{
const size_t nego_tokens_length = nla_sizeof_nego_tokens(negoToken);
WINPR_ASSERT(s);
if (Stream_GetRemainingCapacity(s) < nego_tokens_length)
return FALSE;
if (nego_tokens_length > 0)
{
size_t length;
WLog_DBG(TAG, " ----->> nego token");
length =
ber_write_contextual_tag(s, 1,
ber_sizeof_sequence(ber_sizeof_sequence(
ber_sizeof_sequence_octet_string(negoToken->cbBuffer))),
TRUE); /* NegoData */
length +=
ber_write_sequence_tag(s, ber_sizeof_sequence(ber_sizeof_sequence_octet_string(
negoToken->cbBuffer))); /* SEQUENCE OF NegoDataItem */
length += ber_write_sequence_tag(
s, ber_sizeof_sequence_octet_string(negoToken->cbBuffer)); /* NegoDataItem */
length +=
ber_write_sequence_octet_string_from_secbuffer(s, 0, negoToken); /* OCTET STRING */
if (length != nego_tokens_length)
return FALSE;
}
return TRUE;
}
/**
* Send CredSSP message.
* @param credssp
@ -2286,113 +2165,135 @@ BOOL nla_send(rdpNla* nla)
BOOL rc = FALSE;
wStream* s;
size_t length;
size_t ts_request_length;
size_t error_code_context_length = 0;
size_t error_code_length = 0;
WinPrAsn1Encoder* enc;
WinPrAsn1_OctetString octet_string;
WINPR_ASSERT(nla);
const size_t nego_tokens_length = nla_sizeof_nego_tokens(&nla->negoToken);
const size_t pub_key_auth_length = nla_sizeof_pub_key_auth(&nla->pubKeyAuth);
const size_t auth_info_length = nla_sizeof_auth_info(&nla->authInfo);
const size_t client_nonce_length = nla_sizeof_client_nonce(&nla->ClientNonce);
if (nla->peerVersion >= 3 && nla->peerVersion != 5 && nla->errorCode != 0)
{
error_code_length = ber_sizeof_integer(nla->errorCode);
error_code_context_length = ber_sizeof_contextual_tag(error_code_length);
}
length = nego_tokens_length + pub_key_auth_length + auth_info_length +
error_code_context_length + error_code_length + client_nonce_length;
ts_request_length = nla_sizeof_ts_request(length);
s = Stream_New(NULL, ber_sizeof_sequence(ts_request_length));
if (!s)
{
WLog_ERR(TAG, "Stream_New failed!");
enc = WinPrAsn1Encoder_New(WINPR_ASN1_DER);
if (!enc)
return FALSE;
}
WLog_DBG(TAG, "----->> sending...");
/* TSRequest */
ber_write_sequence_tag(s, ts_request_length); /* SEQUENCE */
/* [0] version */
ber_write_contextual_tag(s, 0, 3, TRUE);
WLog_DBG(TAG, " ----->> protocol version %" PRIu32, nla->version);
ber_write_integer(s, nla->version); /* INTEGER */
/* [1] negoTokens (NegoData) */
if (!nla_client_write_nego_token(s, &nla->negoToken))
WLog_DBG(TAG, "----->> sending...");
if (!WinPrAsn1EncSeqContainer(enc))
goto fail;
/* [2] authInfo (OCTET STRING) */
if (auth_info_length > 0)
/* version [0] INTEGER */
WLog_DBG(TAG, " ----->> protocol version %" PRIu32, nla->version);
if (!WinPrAsn1EncContextualInteger(enc, 0, nla->version))
goto fail;
/* negoTokens [1] SEQUENCE OF SEQUENCE */
if (nla->negoToken.cbBuffer > 0)
{
WLog_DBG(TAG, " ----->> auth info");
if (ber_write_sequence_octet_string_from_secbuffer(s, 2, &nla->authInfo) !=
auth_info_length)
if (!WinPrAsn1EncContextualSeqContainer(enc, 1) || !WinPrAsn1EncSeqContainer(enc))
goto fail;
/* negoToken [0] OCTET STRING */
octet_string.data = nla->negoToken.pvBuffer;
octet_string.len = nla->negoToken.cbBuffer;
if (!WinPrAsn1EncContextualOctetString(enc, 0, &octet_string))
goto fail;
/* End negoTokens (SEQUENCE OF SEQUENCE) */
if (!WinPrAsn1EncEndContainer(enc) || !WinPrAsn1EncEndContainer(enc))
goto fail;
}
/* [3] pubKeyAuth (OCTET STRING) */
if (pub_key_auth_length > 0)
/* authInfo [2] OCTET STRING */
if (nla->authInfo.cbBuffer > 0)
{
WLog_DBG(TAG, " ----->> public key auth");
if (ber_write_sequence_octet_string_from_secbuffer(s, 3, &nla->pubKeyAuth) !=
pub_key_auth_length)
octet_string.data = nla->authInfo.pvBuffer;
octet_string.len = nla->authInfo.cbBuffer;
if (!WinPrAsn1EncContextualOctetString(enc, 2, &octet_string))
goto fail;
}
/* [4] errorCode (INTEGER) */
if (error_code_length > 0)
/* pubKeyAuth [3] OCTET STRING */
if (nla->pubKeyAuth.cbBuffer > 0)
{
WLog_DBG(TAG, " ----->> public key auth");
octet_string.data = nla->pubKeyAuth.pvBuffer;
octet_string.len = nla->pubKeyAuth.cbBuffer;
if (!WinPrAsn1EncContextualOctetString(enc, 3, &octet_string))
goto fail;
}
/* errorCode [4] INTEGER */
if (nla->errorCode && nla->peerVersion >= 3 && nla->peerVersion != 5)
{
char buffer[1024];
WLog_DBG(TAG, " ----->> error code %s 0x%08" PRIx32,
winpr_strerror(nla->errorCode, buffer, sizeof(buffer)), nla->errorCode);
ber_write_contextual_tag(s, 4, error_code_length, TRUE);
ber_write_integer(s, nla->errorCode);
}
/* [5] clientNonce (OCTET STRING) */
if (client_nonce_length > 0)
{
WLog_DBG(TAG, " ----->> client nonce");
if (ber_write_sequence_octet_string_from_secbuffer(s, 5, &nla->ClientNonce) !=
client_nonce_length)
if (!WinPrAsn1EncContextualInteger(enc, 4, nla->errorCode))
goto fail;
}
WLog_DBG(TAG, "[%" PRIuz " bytes]", Stream_GetPosition(s));
/* clientNonce [5] OCTET STRING */
if (nla->ClientNonce.cbBuffer > 0)
{
WLog_DBG(TAG, " ----->> client nonce");
octet_string.data = nla->ClientNonce.pvBuffer;
octet_string.len = nla->ClientNonce.cbBuffer;
if (!WinPrAsn1EncContextualOctetString(enc, 5, &octet_string))
goto fail;
}
/* End TSRequest */
if (!WinPrAsn1EncEndContainer(enc))
goto fail;
if (!WinPrAsn1EncStreamSize(enc, &length))
goto fail;
s = Stream_New(NULL, length);
if (!s)
goto fail;
if (!WinPrAsn1EncToStream(enc, s))
goto fail;
WLog_DBG(TAG, "[%" PRIuz " bytes]", length);
if (transport_write(nla->transport, s) < 0)
goto fail;
rc = TRUE;
fail:
Stream_Free(s, TRUE);
WinPrAsn1Encoder_Free(&enc);
return rc;
}
static int nla_decode_ts_request(rdpNla* nla, wStream* s)
{
int rc = -1;
size_t length;
WinPrAsn1Decoder dec, dec2, dec3;
BOOL error;
WinPrAsn1_tagId tag;
WinPrAsn1_OctetString octet_string;
WinPrAsn1_INTEGER val;
UINT32 version = 0;
char buffer[1024];
WINPR_ASSERT(nla);
WINPR_ASSERT(s);
WinPrAsn1Decoder_Init(&dec, WINPR_ASN1_DER, s);
WLog_DBG(TAG, "<<----- receiving...");
/* TSRequest */
if (!ber_read_sequence_tag(s, &length) || !ber_read_contextual_tag(s, 0, &length, TRUE) ||
!ber_read_integer(s, &version))
{
goto fail;
}
if (!WinPrAsn1DecReadSequence(&dec, &dec2))
return -1;
dec = dec2;
/* version [0] INTEGER */
if (!WinPrAsn1DecReadContextualInteger(&dec, 0, &error, &val))
return -1;
version = (UINT)val;
WLog_DBG(TAG, " <<----- protocol version %" PRIu32, version);
if (nla->peerVersion == 0)
nla->peerVersion = version;
@ -2401,66 +2302,69 @@ static int nla_decode_ts_request(rdpNla* nla, wStream* s)
{
WLog_ERR(TAG, "CredSSP peer changed protocol version from %" PRIu32 " to %" PRIu32,
nla->peerVersion, version);
goto fail;
return -1;
}
/* [1] negoTokens (NegoData) */
if (ber_read_contextual_tag(s, 1, &length, TRUE) != FALSE)
while (WinPrAsn1DecReadContextualTag(&dec, &tag, &dec2))
{
WLog_DBG(TAG, " <<----- nego token");
if (!ber_read_sequence_tag(s, &length) || /* SEQUENCE OF NegoDataItem */
!ber_read_sequence_tag(s, &length) || /* NegoDataItem */
!ber_read_contextual_tag(s, 0, &length, TRUE))
switch (tag)
{
goto fail;
}
if (!nla_decode_to_buffer(s, &nla->negoToken))
goto fail;
}
/* [2] authInfo (OCTET STRING) */
if (ber_read_contextual_tag(s, 2, &length, TRUE) != FALSE)
{
WLog_DBG(TAG, " <<----- auth info");
if (!nla_decode_to_buffer(s, &nla->authInfo))
goto fail;
}
/* [3] pubKeyAuth (OCTET STRING) */
if (ber_read_contextual_tag(s, 3, &length, TRUE) != FALSE)
{
WLog_DBG(TAG, " <<----- public key info");
if (!nla_decode_to_buffer(s, &nla->pubKeyAuth))
goto fail;
}
/* [4] errorCode (INTEGER) */
if (nla->peerVersion >= 3)
{
if (ber_read_contextual_tag(s, 4, &length, TRUE) != FALSE)
{
char buffer[1024];
if (!ber_read_integer(s, &nla->errorCode))
goto fail;
WLog_DBG(TAG, " <<----- error code %s 0x%08" PRIx32,
winpr_strerror(nla->errorCode, buffer, sizeof(buffer)), nla->errorCode);
}
if (nla->peerVersion >= 5)
{
if (ber_read_contextual_tag(s, 5, &length, TRUE) != FALSE)
{
case 1:
WLog_DBG(TAG, " <<----- nego token");
/* negoTokens [1] SEQUENCE OF SEQUENCE */
if (!WinPrAsn1DecReadSequence(&dec2, &dec3) ||
!WinPrAsn1DecReadSequence(&dec3, &dec2))
return -1;
/* negoToken [0] OCTET STRING */
if (!WinPrAsn1DecReadContextualOctetString(&dec2, 0, &error, &octet_string,
FALSE) &&
error)
return -1;
if (!nla_sec_buffer_alloc_from_data(&nla->negoToken, octet_string.data, 0,
octet_string.len))
return -1;
break;
case 2:
WLog_DBG(TAG, " <<----- auth info");
/* authInfo [2] OCTET STRING */
if (!WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE))
return -1;
if (!nla_sec_buffer_alloc_from_data(&nla->authInfo, octet_string.data, 0,
octet_string.len))
return -1;
break;
case 3:
WLog_DBG(TAG, " <<----- public key info");
/* pubKeyAuth [3] OCTET STRING */
if (!WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE))
return -1;
if (!nla_sec_buffer_alloc_from_data(&nla->pubKeyAuth, octet_string.data, 0,
octet_string.len))
return -1;
break;
case 4:
/* errorCode [4] INTEGER */
if (!WinPrAsn1DecReadInteger(&dec2, &val))
return -1;
nla->errorCode = (UINT)val;
WLog_DBG(TAG, " <<----- error code %s 0x%08" PRIx32,
winpr_strerror(nla->errorCode, buffer, sizeof(buffer)), nla->errorCode);
break;
case 5:
WLog_DBG(TAG, " <<----- client nonce");
if (!nla_decode_to_buffer(s, &nla->ClientNonce))
goto fail;
}
/* clientNonce [5] OCTET STRING */
if (!WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE))
return -1;
if (!nla_sec_buffer_alloc_from_data(&nla->ClientNonce, octet_string.data, 0,
octet_string.len))
return -1;
break;
default:
return -1;
}
}
rc = 1;
fail:
return rc;
return 1;
}
int nla_recv_pdu(rdpNla* nla, wStream* s)

View File

@ -1,982 +0,0 @@
/* ============================================================================================================
* this file has been generated using
* ./tools/asn_parser_generator.py --input=libfreerdp/core/credssp.asn1 --output-kind=impls
* --output=libfreerdp/core/tscredentials.c
*
* /!\ If you want to modify this file you'd probably better change asn_parser_generator.py or the
* corresponding ASN1 definition file
*
* ============================================================================================================
*/
#include <winpr/string.h>
#include <freerdp/crypto/ber.h>
#include "tscredentials.h"
#include <freerdp/log.h>
#define TAG FREERDP_TAG("core.tscredentials")
size_t ber_sizeof_nla_TSCredentials_content(const TSCredentials_t* item)
{
size_t ret = 0;
/* [0] credType (INTEGER)*/
ret += ber_sizeof_contextual_integer(item->credType);
/* [1] credentials (OCTET STRING)*/
ret += ber_sizeof_contextual_octet_string(item->credentialsLen);
return ret;
}
size_t ber_sizeof_nla_TSCredentials(const TSCredentials_t* item)
{
size_t ret = ber_sizeof_nla_TSCredentials_content(item);
return ber_sizeof_sequence(ret);
}
size_t ber_sizeof_contextual_nla_TSCredentials(const TSCredentials_t* item)
{
size_t innerSz = ber_sizeof_nla_TSCredentials(item);
return ber_sizeof_contextual_tag(innerSz) + innerSz;
}
void nla_TSCredentials_free(TSCredentials_t** pitem)
{
TSCredentials_t* item;
WINPR_ASSERT(pitem);
item = *pitem;
if (!item)
return;
free(item->credentials);
free(item);
*pitem = NULL;
}
size_t ber_write_nla_TSCredentials(wStream* s, const TSCredentials_t* item)
{
size_t content_size = ber_sizeof_nla_TSCredentials_content(item);
size_t ret = 0;
ret = ber_write_sequence_tag(s, content_size);
/* [0] credType (INTEGER) */
if (!ber_write_contextual_integer(s, 0, item->credType))
return 0;
/* [1] credentials (OCTET STRING) */
if (!ber_write_contextual_octet_string(s, 1, item->credentials, item->credentialsLen))
return 0;
return ret + content_size;
}
size_t ber_write_contextual_nla_TSCredentials(wStream* s, BYTE tag, const TSCredentials_t* item)
{
size_t ret;
size_t inner = ber_sizeof_nla_TSCredentials(item);
ret = ber_write_contextual_tag(s, tag, inner, TRUE);
ber_write_nla_TSCredentials(s, item);
return ret + inner;
}
BOOL ber_read_nla_TSCredentials(wStream* s, TSCredentials_t** pret)
{
wStream seqstream;
size_t seqLength;
size_t inner_size;
wStream fieldStream;
TSCredentials_t* item;
BOOL ret;
if (!ber_read_sequence_tag(s, &seqLength) ||
!Stream_CheckAndLogRequiredLength(TAG, s, seqLength))
return FALSE;
Stream_StaticInit(&seqstream, Stream_Pointer(s), seqLength);
item = calloc(1, sizeof(*item));
if (!item)
return FALSE;
/* [0] credType (INTEGER) */
ret = ber_read_contextual_tag(&seqstream, 0, &inner_size, TRUE);
if (!ret)
goto out_fail_credType;
Stream_StaticInit(&fieldStream, Stream_Pointer(&seqstream), inner_size);
Stream_Seek(&seqstream, inner_size);
ret = ber_read_integer(&fieldStream, &item->credType);
if (!ret)
goto out_fail_credType;
/* [1] credentials (OCTET STRING) */
ret = ber_read_contextual_tag(&seqstream, 1, &inner_size, TRUE);
if (!ret)
goto out_fail_credentials;
Stream_StaticInit(&fieldStream, Stream_Pointer(&seqstream), inner_size);
Stream_Seek(&seqstream, inner_size);
ret = ber_read_octet_string(&fieldStream, &item->credentials, &item->credentialsLen);
if (!ret)
goto out_fail_credentials;
*pret = item;
return TRUE;
out_fail_credentials:
out_fail_credType:
free(item);
return FALSE;
}
size_t ber_sizeof_nla_TSPasswordCreds_content(const TSPasswordCreds_t* item)
{
size_t ret = 0;
/* [0] domainName (OCTET STRING)*/
ret += ber_sizeof_contextual_octet_string(item->domainNameLen);
/* [1] userName (OCTET STRING)*/
ret += ber_sizeof_contextual_octet_string(item->userNameLen);
/* [2] password (OCTET STRING)*/
ret += ber_sizeof_contextual_octet_string(item->passwordLen);
return ret;
}
size_t ber_sizeof_nla_TSPasswordCreds(const TSPasswordCreds_t* item)
{
size_t ret = ber_sizeof_nla_TSPasswordCreds_content(item);
return ber_sizeof_sequence(ret);
}
size_t ber_sizeof_contextual_nla_TSPasswordCreds(const TSPasswordCreds_t* item)
{
size_t innerSz = ber_sizeof_nla_TSPasswordCreds(item);
return ber_sizeof_contextual_tag(innerSz) + innerSz;
}
void nla_TSPasswordCreds_free(TSPasswordCreds_t** pitem)
{
TSPasswordCreds_t* item;
WINPR_ASSERT(pitem);
item = *pitem;
if (!item)
return;
free(item->domainName);
free(item->userName);
free(item->password);
free(item);
*pitem = NULL;
}
size_t ber_write_nla_TSPasswordCreds(wStream* s, const TSPasswordCreds_t* item)
{
size_t content_size = ber_sizeof_nla_TSPasswordCreds_content(item);
size_t ret = 0;
ret = ber_write_sequence_tag(s, content_size);
/* [0] domainName (OCTET STRING) */
if (!ber_write_contextual_octet_string(s, 0, item->domainName, item->domainNameLen))
return 0;
/* [1] userName (OCTET STRING) */
if (!ber_write_contextual_octet_string(s, 1, item->userName, item->userNameLen))
return 0;
/* [2] password (OCTET STRING) */
if (!ber_write_contextual_octet_string(s, 2, item->password, item->passwordLen))
return 0;
return ret + content_size;
}
size_t ber_write_contextual_nla_TSPasswordCreds(wStream* s, BYTE tag, const TSPasswordCreds_t* item)
{
size_t ret;
size_t inner = ber_sizeof_nla_TSPasswordCreds(item);
ret = ber_write_contextual_tag(s, tag, inner, TRUE);
ber_write_nla_TSPasswordCreds(s, item);
return ret + inner;
}
BOOL ber_read_nla_TSPasswordCreds(wStream* s, TSPasswordCreds_t** pret)
{
wStream seqstream;
size_t seqLength;
size_t inner_size;
wStream fieldStream;
TSPasswordCreds_t* item;
BOOL ret;
if (!ber_read_sequence_tag(s, &seqLength) ||
!Stream_CheckAndLogRequiredLength(TAG, s, seqLength))
return FALSE;
Stream_StaticInit(&seqstream, Stream_Pointer(s), seqLength);
item = calloc(1, sizeof(*item));
if (!item)
return FALSE;
/* [0] domainName (OCTET STRING) */
ret = ber_read_contextual_tag(&seqstream, 0, &inner_size, TRUE);
if (!ret)
goto out_fail_domainName;
Stream_StaticInit(&fieldStream, Stream_Pointer(&seqstream), inner_size);
Stream_Seek(&seqstream, inner_size);
ret = ber_read_octet_string(&fieldStream, &item->domainName, &item->domainNameLen);
if (!ret)
goto out_fail_domainName;
/* [1] userName (OCTET STRING) */
ret = ber_read_contextual_tag(&seqstream, 1, &inner_size, TRUE);
if (!ret)
goto out_fail_userName;
Stream_StaticInit(&fieldStream, Stream_Pointer(&seqstream), inner_size);
Stream_Seek(&seqstream, inner_size);
ret = ber_read_octet_string(&fieldStream, &item->userName, &item->userNameLen);
if (!ret)
goto out_fail_userName;
/* [2] password (OCTET STRING) */
ret = ber_read_contextual_tag(&seqstream, 2, &inner_size, TRUE);
if (!ret)
goto out_fail_password;
Stream_StaticInit(&fieldStream, Stream_Pointer(&seqstream), inner_size);
Stream_Seek(&seqstream, inner_size);
ret = ber_read_octet_string(&fieldStream, &item->password, &item->passwordLen);
if (!ret)
goto out_fail_password;
*pret = item;
return TRUE;
out_fail_password:
free(item->userName);
out_fail_userName:
free(item->domainName);
out_fail_domainName:
free(item);
return FALSE;
}
size_t ber_sizeof_nla_TSCspDataDetail_content(const TSCspDataDetail_t* item)
{
size_t ret = 0;
/* [0] keySpec (INTEGER)*/
ret += ber_sizeof_contextual_integer(item->keySpec);
/* [1] cardName (OCTET STRING) OPTIONAL*/
if (item->cardName)
{
ret += ber_sizeof_contextual_octet_string(strlen(item->cardName) * 2);
}
/* [2] readerName (OCTET STRING) OPTIONAL*/
if (item->readerName)
{
ret += ber_sizeof_contextual_octet_string(strlen(item->readerName) * 2);
}
/* [3] containerName (OCTET STRING) OPTIONAL*/
if (item->containerName)
{
ret += ber_sizeof_contextual_octet_string(strlen(item->containerName) * 2);
}
/* [4] cspName (OCTET STRING) OPTIONAL*/
if (item->cspName)
{
ret += ber_sizeof_contextual_octet_string(strlen(item->cspName) * 2);
}
return ret;
}
size_t ber_sizeof_nla_TSCspDataDetail(const TSCspDataDetail_t* item)
{
size_t ret = ber_sizeof_nla_TSCspDataDetail_content(item);
return ber_sizeof_sequence(ret);
}
size_t ber_sizeof_contextual_nla_TSCspDataDetail(const TSCspDataDetail_t* item)
{
size_t innerSz = ber_sizeof_nla_TSCspDataDetail(item);
return ber_sizeof_contextual_tag(innerSz) + innerSz;
}
void nla_TSCspDataDetail_free(TSCspDataDetail_t** pitem)
{
TSCspDataDetail_t* item;
WINPR_ASSERT(pitem);
item = *pitem;
if (!item)
return;
free(item->cardName);
free(item->readerName);
free(item->containerName);
free(item->cspName);
free(item);
*pitem = NULL;
}
size_t ber_write_nla_TSCspDataDetail(wStream* s, const TSCspDataDetail_t* item)
{
size_t content_size = ber_sizeof_nla_TSCspDataDetail_content(item);
size_t ret = 0;
ret = ber_write_sequence_tag(s, content_size);
/* [0] keySpec (INTEGER) */
if (!ber_write_contextual_integer(s, 0, item->keySpec))
return 0;
/* [1] cardName (OCTET STRING) OPTIONAL */
if (item->cardName)
{
if (!ber_write_contextual_char_to_unicode_octet_string(s, 1, item->cardName))
return 0;
}
/* [2] readerName (OCTET STRING) OPTIONAL */
if (item->readerName)
{
if (!ber_write_contextual_char_to_unicode_octet_string(s, 2, item->readerName))
return 0;
}
/* [3] containerName (OCTET STRING) OPTIONAL */
if (item->containerName)
{
if (!ber_write_contextual_char_to_unicode_octet_string(s, 3, item->containerName))
return 0;
}
/* [4] cspName (OCTET STRING) OPTIONAL */
if (item->cspName)
{
if (!ber_write_contextual_char_to_unicode_octet_string(s, 4, item->cspName))
return 0;
}
return ret + content_size;
}
size_t ber_write_contextual_nla_TSCspDataDetail(wStream* s, BYTE tag, const TSCspDataDetail_t* item)
{
size_t ret;
size_t inner = ber_sizeof_nla_TSCspDataDetail(item);
ret = ber_write_contextual_tag(s, tag, inner, TRUE);
ber_write_nla_TSCspDataDetail(s, item);
return ret + inner;
}
BOOL ber_read_nla_TSCspDataDetail(wStream* s, TSCspDataDetail_t** pret)
{
wStream seqstream;
size_t seqLength;
size_t inner_size;
wStream fieldStream;
TSCspDataDetail_t* item;
BOOL ret;
if (!ber_read_sequence_tag(s, &seqLength) ||
!Stream_CheckAndLogRequiredLength(TAG, s, seqLength))
return FALSE;
Stream_StaticInit(&seqstream, Stream_Pointer(s), seqLength);
item = calloc(1, sizeof(*item));
if (!item)
return FALSE;
/* [0] keySpec (INTEGER) */
ret = ber_read_contextual_tag(&seqstream, 0, &inner_size, TRUE);
if (!ret)
goto out_fail_keySpec;
Stream_StaticInit(&fieldStream, Stream_Pointer(&seqstream), inner_size);
Stream_Seek(&seqstream, inner_size);
ret = ber_read_integer(&fieldStream, &item->keySpec);
if (!ret)
goto out_fail_keySpec;
/* [1] cardName (OCTET STRING) OPTIONAL */
ret = ber_read_contextual_tag(&seqstream, 1, &inner_size, TRUE);
if (ret)
{
Stream_StaticInit(&fieldStream, Stream_Pointer(&seqstream), inner_size);
Stream_Seek(&seqstream, inner_size);
ret = ber_read_char_from_unicode_octet_string(&fieldStream, &item->cardName);
if (!ret)
goto out_fail_cardName;
}
/* [2] readerName (OCTET STRING) OPTIONAL */
ret = ber_read_contextual_tag(&seqstream, 2, &inner_size, TRUE);
if (ret)
{
Stream_StaticInit(&fieldStream, Stream_Pointer(&seqstream), inner_size);
Stream_Seek(&seqstream, inner_size);
ret = ber_read_char_from_unicode_octet_string(&fieldStream, &item->readerName);
if (!ret)
goto out_fail_readerName;
}
/* [3] containerName (OCTET STRING) OPTIONAL */
ret = ber_read_contextual_tag(&seqstream, 3, &inner_size, TRUE);
if (ret)
{
Stream_StaticInit(&fieldStream, Stream_Pointer(&seqstream), inner_size);
Stream_Seek(&seqstream, inner_size);
ret = ber_read_char_from_unicode_octet_string(&fieldStream, &item->containerName);
if (!ret)
goto out_fail_containerName;
}
/* [4] cspName (OCTET STRING) OPTIONAL */
ret = ber_read_contextual_tag(&seqstream, 4, &inner_size, TRUE);
if (ret)
{
Stream_StaticInit(&fieldStream, Stream_Pointer(&seqstream), inner_size);
Stream_Seek(&seqstream, inner_size);
ret = ber_read_char_from_unicode_octet_string(&fieldStream, &item->cspName);
if (!ret)
goto out_fail_cspName;
}
*pret = item;
return TRUE;
out_fail_cspName:
free(item->containerName);
out_fail_containerName:
free(item->readerName);
out_fail_readerName:
free(item->cardName);
out_fail_cardName:
out_fail_keySpec:
free(item);
return FALSE;
}
size_t ber_sizeof_nla_TSSmartCardCreds_content(const TSSmartCardCreds_t* item)
{
size_t ret = 0;
/* [0] pin (OCTET STRING)*/
ret += ber_sizeof_contextual_octet_string(strlen(item->pin) * 2);
/* [1] cspData (TSCspDataDetail)*/
ret += ber_sizeof_contextual_nla_TSCspDataDetail(item->cspData);
/* [2] userHint (OCTET STRING) OPTIONAL*/
if (item->userHint)
{
ret += ber_sizeof_contextual_octet_string(strlen(item->userHint) * 2);
}
/* [3] domainHint (OCTET STRING) OPTIONAL*/
if (item->domainHint)
{
ret += ber_sizeof_contextual_octet_string(strlen(item->domainHint) * 2);
}
return ret;
}
size_t ber_sizeof_nla_TSSmartCardCreds(const TSSmartCardCreds_t* item)
{
size_t ret = ber_sizeof_nla_TSSmartCardCreds_content(item);
return ber_sizeof_sequence(ret);
}
size_t ber_sizeof_contextual_nla_TSSmartCardCreds(const TSSmartCardCreds_t* item)
{
size_t innerSz = ber_sizeof_nla_TSSmartCardCreds(item);
return ber_sizeof_contextual_tag(innerSz) + innerSz;
}
void nla_TSSmartCardCreds_free(TSSmartCardCreds_t** pitem)
{
TSSmartCardCreds_t* item;
WINPR_ASSERT(pitem);
item = *pitem;
if (!item)
return;
free(item->pin);
nla_TSCspDataDetail_free(&item->cspData);
free(item->userHint);
free(item->domainHint);
free(item);
*pitem = NULL;
}
size_t ber_write_nla_TSSmartCardCreds(wStream* s, const TSSmartCardCreds_t* item)
{
size_t content_size = ber_sizeof_nla_TSSmartCardCreds_content(item);
size_t ret = 0;
ret = ber_write_sequence_tag(s, content_size);
/* [0] pin (OCTET STRING) */
if (!ber_write_contextual_char_to_unicode_octet_string(s, 0, item->pin))
return 0;
/* [1] cspData (TSCspDataDetail) */
if (!ber_write_contextual_nla_TSCspDataDetail(s, 1, item->cspData))
return 0;
/* [2] userHint (OCTET STRING) OPTIONAL */
if (item->userHint)
{
if (!ber_write_contextual_char_to_unicode_octet_string(s, 2, item->userHint))
return 0;
}
/* [3] domainHint (OCTET STRING) OPTIONAL */
if (item->domainHint)
{
if (!ber_write_contextual_char_to_unicode_octet_string(s, 3, item->domainHint))
return 0;
}
return ret + content_size;
}
size_t ber_write_contextual_nla_TSSmartCardCreds(wStream* s, BYTE tag,
const TSSmartCardCreds_t* item)
{
size_t ret;
size_t inner = ber_sizeof_nla_TSSmartCardCreds(item);
ret = ber_write_contextual_tag(s, tag, inner, TRUE);
ber_write_nla_TSSmartCardCreds(s, item);
return ret + inner;
}
BOOL ber_read_nla_TSSmartCardCreds(wStream* s, TSSmartCardCreds_t** pret)
{
wStream seqstream;
size_t seqLength;
size_t inner_size;
wStream fieldStream;
TSSmartCardCreds_t* item;
BOOL ret;
if (!ber_read_sequence_tag(s, &seqLength) ||
!Stream_CheckAndLogRequiredLength(TAG, s, seqLength))
return FALSE;
Stream_StaticInit(&seqstream, Stream_Pointer(s), seqLength);
item = calloc(1, sizeof(*item));
if (!item)
return FALSE;
/* [0] pin (OCTET STRING) */
ret = ber_read_contextual_tag(&seqstream, 0, &inner_size, TRUE);
if (!ret)
goto out_fail_pin;
Stream_StaticInit(&fieldStream, Stream_Pointer(&seqstream), inner_size);
Stream_Seek(&seqstream, inner_size);
ret = ber_read_char_from_unicode_octet_string(&fieldStream, &item->pin);
if (!ret)
goto out_fail_pin;
/* [1] cspData (TSCspDataDetail) */
ret = ber_read_contextual_tag(&seqstream, 1, &inner_size, TRUE);
if (!ret)
goto out_fail_cspData;
Stream_StaticInit(&fieldStream, Stream_Pointer(&seqstream), inner_size);
Stream_Seek(&seqstream, inner_size);
ret = ber_read_nla_TSCspDataDetail(&fieldStream, &item->cspData);
if (!ret)
goto out_fail_cspData;
/* [2] userHint (OCTET STRING) OPTIONAL */
ret = ber_read_contextual_tag(&seqstream, 2, &inner_size, TRUE);
if (ret)
{
Stream_StaticInit(&fieldStream, Stream_Pointer(&seqstream), inner_size);
Stream_Seek(&seqstream, inner_size);
ret = ber_read_char_from_unicode_octet_string(&fieldStream, &item->userHint);
if (!ret)
goto out_fail_userHint;
}
/* [3] domainHint (OCTET STRING) OPTIONAL */
ret = ber_read_contextual_tag(&seqstream, 3, &inner_size, TRUE);
if (ret)
{
Stream_StaticInit(&fieldStream, Stream_Pointer(&seqstream), inner_size);
Stream_Seek(&seqstream, inner_size);
ret = ber_read_char_from_unicode_octet_string(&fieldStream, &item->domainHint);
if (!ret)
goto out_fail_domainHint;
}
*pret = item;
return TRUE;
out_fail_domainHint:
free(item->userHint);
out_fail_userHint:
nla_TSCspDataDetail_free(&item->cspData);
out_fail_cspData:
free(item->pin);
out_fail_pin:
free(item);
return FALSE;
}
size_t ber_sizeof_nla_TSRemoteGuardPackageCred_content(const TSRemoteGuardPackageCred_t* item)
{
size_t ret = 0;
/* [0] packageName (OCTET STRING)*/
ret += ber_sizeof_contextual_octet_string(item->packageNameLen);
/* [1] credBuffer (OCTET STRING)*/
ret += ber_sizeof_contextual_octet_string(item->credBufferLen);
return ret;
}
size_t ber_sizeof_nla_TSRemoteGuardPackageCred(const TSRemoteGuardPackageCred_t* item)
{
size_t ret = ber_sizeof_nla_TSRemoteGuardPackageCred_content(item);
return ber_sizeof_sequence(ret);
}
size_t ber_sizeof_contextual_nla_TSRemoteGuardPackageCred(const TSRemoteGuardPackageCred_t* item)
{
size_t innerSz = ber_sizeof_nla_TSRemoteGuardPackageCred(item);
return ber_sizeof_contextual_tag(innerSz) + innerSz;
}
void nla_TSRemoteGuardPackageCred_free(TSRemoteGuardPackageCred_t** pitem)
{
TSRemoteGuardPackageCred_t* item;
WINPR_ASSERT(pitem);
item = *pitem;
if (!item)
return;
free(item->packageName);
free(item->credBuffer);
free(item);
*pitem = NULL;
}
size_t ber_write_nla_TSRemoteGuardPackageCred(wStream* s, const TSRemoteGuardPackageCred_t* item)
{
size_t content_size = ber_sizeof_nla_TSRemoteGuardPackageCred_content(item);
size_t ret = 0;
ret = ber_write_sequence_tag(s, content_size);
/* [0] packageName (OCTET STRING) */
if (!ber_write_contextual_octet_string(s, 0, item->packageName, item->packageNameLen))
return 0;
/* [1] credBuffer (OCTET STRING) */
if (!ber_write_contextual_octet_string(s, 1, item->credBuffer, item->credBufferLen))
return 0;
return ret + content_size;
}
size_t ber_write_contextual_nla_TSRemoteGuardPackageCred(wStream* s, BYTE tag,
const TSRemoteGuardPackageCred_t* item)
{
size_t ret;
size_t inner = ber_sizeof_nla_TSRemoteGuardPackageCred(item);
ret = ber_write_contextual_tag(s, tag, inner, TRUE);
ber_write_nla_TSRemoteGuardPackageCred(s, item);
return ret + inner;
}
BOOL ber_read_nla_TSRemoteGuardPackageCred(wStream* s, TSRemoteGuardPackageCred_t** pret)
{
wStream seqstream;
size_t seqLength;
size_t inner_size;
wStream fieldStream;
TSRemoteGuardPackageCred_t* item;
BOOL ret;
if (!ber_read_sequence_tag(s, &seqLength) ||
!Stream_CheckAndLogRequiredLength(TAG, s, seqLength))
return FALSE;
Stream_StaticInit(&seqstream, Stream_Pointer(s), seqLength);
item = calloc(1, sizeof(*item));
if (!item)
return FALSE;
/* [0] packageName (OCTET STRING) */
ret = ber_read_contextual_tag(&seqstream, 0, &inner_size, TRUE);
if (!ret)
goto out_fail_packageName;
Stream_StaticInit(&fieldStream, Stream_Pointer(&seqstream), inner_size);
Stream_Seek(&seqstream, inner_size);
ret = ber_read_octet_string(&fieldStream, &item->packageName, &item->packageNameLen);
if (!ret)
goto out_fail_packageName;
/* [1] credBuffer (OCTET STRING) */
ret = ber_read_contextual_tag(&seqstream, 1, &inner_size, TRUE);
if (!ret)
goto out_fail_credBuffer;
Stream_StaticInit(&fieldStream, Stream_Pointer(&seqstream), inner_size);
Stream_Seek(&seqstream, inner_size);
ret = ber_read_octet_string(&fieldStream, &item->credBuffer, &item->credBufferLen);
if (!ret)
goto out_fail_credBuffer;
*pret = item;
return TRUE;
out_fail_credBuffer:
free(item->packageName);
out_fail_packageName:
free(item);
return FALSE;
}
size_t ber_sizeof_nla_TSRemoteGuardPackageCred_array_content(const TSRemoteGuardPackageCred_t* item,
size_t nitems)
{
size_t i, ret = 0;
for (i = 0; i < nitems; i++, item++)
ret += ber_sizeof_nla_TSRemoteGuardPackageCred(item);
return ber_sizeof_sequence(ret);
}
size_t ber_sizeof_nla_TSRemoteGuardPackageCred_array(const TSRemoteGuardPackageCred_t* item,
size_t nitems)
{
return ber_sizeof_sequence(ber_sizeof_nla_TSRemoteGuardPackageCred_array_content(item, nitems));
}
size_t
ber_sizeof_contextual_nla_TSRemoteGuardPackageCred_array(const TSRemoteGuardPackageCred_t* item,
size_t nitems)
{
size_t inner = ber_sizeof_nla_TSRemoteGuardPackageCred_array(item, nitems);
return ber_sizeof_contextual_tag(inner) + inner;
}
size_t ber_write_nla_TSRemoteGuardPackageCred_array(wStream* s,
const TSRemoteGuardPackageCred_t* item,
size_t nitems)
{
size_t i, r, ret;
size_t inner_len = ber_sizeof_nla_TSRemoteGuardPackageCred_array_content(item, nitems);
ret = ber_write_sequence_tag(s, inner_len);
for (i = 0; i < nitems; i++, item++)
{
r = ber_write_nla_TSRemoteGuardPackageCred(s, item);
if (!r)
return 0;
ret += r;
}
return ret;
}
size_t ber_write_contextual_nla_TSRemoteGuardPackageCred_array(
wStream* s, BYTE tag, const TSRemoteGuardPackageCred_t* item, size_t nitems)
{
size_t ret;
size_t inner = ber_sizeof_nla_TSRemoteGuardPackageCred_array(item, nitems);
ret = ber_write_contextual_tag(s, tag, inner, TRUE);
ber_write_nla_TSRemoteGuardPackageCred_array(s, item, nitems);
return ret + inner;
}
BOOL ber_read_nla_TSRemoteGuardPackageCred_array(wStream* s, TSRemoteGuardPackageCred_t** pitems,
size_t* nitems)
{
size_t subLen;
wStream subStream;
TSRemoteGuardPackageCred_t* retItems = NULL;
size_t ret = 0;
if (!ber_read_sequence_tag(s, &subLen) || !Stream_CheckAndLogRequiredLength(TAG, s, subLen))
return FALSE;
Stream_StaticInit(&subStream, Stream_Pointer(s), subLen);
while (Stream_GetRemainingLength(&subStream))
{
TSRemoteGuardPackageCred_t* item;
TSRemoteGuardPackageCred_t* tmpRet;
if (!ber_read_nla_TSRemoteGuardPackageCred(&subStream, &item))
{
free(retItems);
return FALSE;
}
tmpRet = realloc(retItems, (ret + 1) * sizeof(TSRemoteGuardPackageCred_t));
if (!tmpRet)
{
free(retItems);
return FALSE;
}
retItems = tmpRet;
memcpy(&retItems[ret], item, sizeof(*item));
free(item);
ret++;
}
*pitems = retItems;
*nitems = ret;
return TRUE;
}
size_t ber_sizeof_nla_TSRemoteGuardCreds_content(const TSRemoteGuardCreds_t* item)
{
size_t ret = 0;
/* [0] logonCred (TSRemoteGuardPackageCred)*/
ret += ber_sizeof_contextual_nla_TSRemoteGuardPackageCred(item->logonCred);
/* [1] supplementalCreds (SEQUENCE OF) OPTIONAL*/
if (item->supplementalCreds)
{
ret += ber_sizeof_contextual_nla_TSRemoteGuardPackageCred_array(
item->supplementalCreds, item->supplementalCredsItems);
}
return ret;
}
size_t ber_sizeof_nla_TSRemoteGuardCreds(const TSRemoteGuardCreds_t* item)
{
size_t ret = ber_sizeof_nla_TSRemoteGuardCreds_content(item);
return ber_sizeof_sequence(ret);
}
size_t ber_sizeof_contextual_nla_TSRemoteGuardCreds(const TSRemoteGuardCreds_t* item)
{
size_t innerSz = ber_sizeof_nla_TSRemoteGuardCreds(item);
return ber_sizeof_contextual_tag(innerSz) + innerSz;
}
void nla_TSRemoteGuardCreds_free(TSRemoteGuardCreds_t** pitem)
{
TSRemoteGuardCreds_t* item;
WINPR_ASSERT(pitem);
item = *pitem;
if (!item)
return;
nla_TSRemoteGuardPackageCred_free(&item->logonCred);
free(item);
*pitem = NULL;
}
size_t ber_write_nla_TSRemoteGuardCreds(wStream* s, const TSRemoteGuardCreds_t* item)
{
size_t content_size = ber_sizeof_nla_TSRemoteGuardCreds_content(item);
size_t ret = 0;
ret = ber_write_sequence_tag(s, content_size);
/* [0] logonCred (TSRemoteGuardPackageCred) */
if (!ber_write_contextual_nla_TSRemoteGuardPackageCred(s, 0, item->logonCred))
return 0;
/* [1] supplementalCreds (SEQUENCE OF) OPTIONAL */
if (item->supplementalCreds)
{
if (!ber_write_contextual_nla_TSRemoteGuardPackageCred_array(s, 1, item->supplementalCreds,
item->supplementalCredsItems))
return 0;
}
return ret + content_size;
}
size_t ber_write_contextual_nla_TSRemoteGuardCreds(wStream* s, BYTE tag,
const TSRemoteGuardCreds_t* item)
{
size_t ret;
size_t inner = ber_sizeof_nla_TSRemoteGuardCreds(item);
ret = ber_write_contextual_tag(s, tag, inner, TRUE);
ber_write_nla_TSRemoteGuardCreds(s, item);
return ret + inner;
}
BOOL ber_read_nla_TSRemoteGuardCreds(wStream* s, TSRemoteGuardCreds_t** pret)
{
wStream seqstream;
size_t seqLength;
size_t inner_size;
wStream fieldStream;
TSRemoteGuardCreds_t* item;
BOOL ret;
if (!ber_read_sequence_tag(s, &seqLength) ||
!Stream_CheckAndLogRequiredLength(TAG, s, seqLength))
return FALSE;
Stream_StaticInit(&seqstream, Stream_Pointer(s), seqLength);
item = calloc(1, sizeof(*item));
if (!item)
return FALSE;
/* [0] logonCred (TSRemoteGuardPackageCred) */
ret = ber_read_contextual_tag(&seqstream, 0, &inner_size, TRUE);
if (!ret)
goto out_fail_logonCred;
Stream_StaticInit(&fieldStream, Stream_Pointer(&seqstream), inner_size);
Stream_Seek(&seqstream, inner_size);
ret = ber_read_nla_TSRemoteGuardPackageCred(&fieldStream, &item->logonCred);
if (!ret)
goto out_fail_logonCred;
/* [1] supplementalCreds (SEQUENCE OF) OPTIONAL */
ret = ber_read_contextual_tag(&seqstream, 1, &inner_size, TRUE);
if (ret)
{
Stream_StaticInit(&fieldStream, Stream_Pointer(&seqstream), inner_size);
Stream_Seek(&seqstream, inner_size);
ret = ber_read_nla_TSRemoteGuardPackageCred_array(&fieldStream, &item->supplementalCreds,
&item->supplementalCredsItems);
if (!ret)
goto out_fail_supplementalCreds;
}
*pret = item;
return TRUE;
out_fail_supplementalCreds:
nla_TSRemoteGuardPackageCred_free(&item->logonCred);
out_fail_logonCred:
free(item);
return FALSE;
}

View File

@ -1,132 +0,0 @@
/* ============================================================================================================
* this file has been generated using
* ./tools/asn_parser_generator.py --input=libfreerdp/core/credssp.asn1 --output-kind=headers
* --output=libfreerdp/core/tscredentials.h
*
* /!\ If you want to modify this file you'd probably better change asn_parser_generator.py or the
* corresponding ASN1 definition file
*
* ============================================================================================================
*/
#ifndef LIBFREERDP_CORE_CREDSSP_ASN1_H
#define LIBFREERDP_CORE_CREDSSP_ASN1_H
#include <winpr/stream.h>
typedef struct
{
UINT32 credType;
size_t credentialsLen;
BYTE* credentials;
} TSCredentials_t;
typedef struct
{
size_t domainNameLen;
BYTE* domainName;
size_t userNameLen;
BYTE* userName;
size_t passwordLen;
BYTE* password;
} TSPasswordCreds_t;
typedef struct
{
UINT32 keySpec;
char* cardName;
char* readerName;
char* containerName;
char* cspName;
} TSCspDataDetail_t;
typedef struct
{
char* pin;
TSCspDataDetail_t* cspData;
char* userHint;
char* domainHint;
} TSSmartCardCreds_t;
typedef struct
{
size_t packageNameLen;
BYTE* packageName;
size_t credBufferLen;
BYTE* credBuffer;
} TSRemoteGuardPackageCred_t;
typedef struct
{
TSRemoteGuardPackageCred_t* logonCred;
size_t supplementalCredsItems;
TSRemoteGuardPackageCred_t* supplementalCreds;
} TSRemoteGuardCreds_t;
size_t ber_sizeof_nla_TSCredentials_content(const TSCredentials_t* item);
size_t ber_sizeof_nla_TSCredentials(const TSCredentials_t* item);
size_t ber_sizeof_contextual_nla_TSCredentials(const TSCredentials_t* item);
void nla_TSCredentials_free(TSCredentials_t** pitem);
size_t ber_write_nla_TSCredentials(wStream* s, const TSCredentials_t* item);
size_t ber_write_contextual_nla_TSCredentials(wStream* s, BYTE tag, const TSCredentials_t* item);
BOOL ber_read_nla_TSCredentials(wStream* s, TSCredentials_t** pret);
size_t ber_sizeof_nla_TSPasswordCreds_content(const TSPasswordCreds_t* item);
size_t ber_sizeof_nla_TSPasswordCreds(const TSPasswordCreds_t* item);
size_t ber_sizeof_contextual_nla_TSPasswordCreds(const TSPasswordCreds_t* item);
void nla_TSPasswordCreds_free(TSPasswordCreds_t** pitem);
size_t ber_write_nla_TSPasswordCreds(wStream* s, const TSPasswordCreds_t* item);
size_t ber_write_contextual_nla_TSPasswordCreds(wStream* s, BYTE tag,
const TSPasswordCreds_t* item);
BOOL ber_read_nla_TSPasswordCreds(wStream* s, TSPasswordCreds_t** pret);
size_t ber_sizeof_nla_TSCspDataDetail_content(const TSCspDataDetail_t* item);
size_t ber_sizeof_nla_TSCspDataDetail(const TSCspDataDetail_t* item);
size_t ber_sizeof_contextual_nla_TSCspDataDetail(const TSCspDataDetail_t* item);
void nla_TSCspDataDetail_free(TSCspDataDetail_t** pitem);
size_t ber_write_nla_TSCspDataDetail(wStream* s, const TSCspDataDetail_t* item);
size_t ber_write_contextual_nla_TSCspDataDetail(wStream* s, BYTE tag,
const TSCspDataDetail_t* item);
BOOL ber_read_nla_TSCspDataDetail(wStream* s, TSCspDataDetail_t** pret);
size_t ber_sizeof_nla_TSSmartCardCreds_content(const TSSmartCardCreds_t* item);
size_t ber_sizeof_nla_TSSmartCardCreds(const TSSmartCardCreds_t* item);
size_t ber_sizeof_contextual_nla_TSSmartCardCreds(const TSSmartCardCreds_t* item);
void nla_TSSmartCardCreds_free(TSSmartCardCreds_t** pitem);
size_t ber_write_nla_TSSmartCardCreds(wStream* s, const TSSmartCardCreds_t* item);
size_t ber_write_contextual_nla_TSSmartCardCreds(wStream* s, BYTE tag,
const TSSmartCardCreds_t* item);
BOOL ber_read_nla_TSSmartCardCreds(wStream* s, TSSmartCardCreds_t** pret);
size_t ber_sizeof_nla_TSRemoteGuardPackageCred_content(const TSRemoteGuardPackageCred_t* item);
size_t ber_sizeof_nla_TSRemoteGuardPackageCred(const TSRemoteGuardPackageCred_t* item);
size_t ber_sizeof_contextual_nla_TSRemoteGuardPackageCred(const TSRemoteGuardPackageCred_t* item);
void nla_TSRemoteGuardPackageCred_free(TSRemoteGuardPackageCred_t** pitem);
size_t ber_write_nla_TSRemoteGuardPackageCred(wStream* s, const TSRemoteGuardPackageCred_t* item);
size_t ber_write_contextual_nla_TSRemoteGuardPackageCred(wStream* s, BYTE tag,
const TSRemoteGuardPackageCred_t* item);
BOOL ber_read_nla_TSRemoteGuardPackageCred(wStream* s, TSRemoteGuardPackageCred_t** pret);
size_t ber_sizeof_nla_TSRemoteGuardPackageCred_array_content(const TSRemoteGuardPackageCred_t* item,
size_t nitems);
size_t ber_sizeof_nla_TSRemoteGuardPackageCred_array(const TSRemoteGuardPackageCred_t* item,
size_t nitems);
size_t
ber_sizeof_contextual_nla_TSRemoteGuardPackageCred_array(const TSRemoteGuardPackageCred_t* item,
size_t nitems);
size_t ber_write_nla_TSRemoteGuardPackageCred_array(wStream* s,
const TSRemoteGuardPackageCred_t* item,
size_t nitems);
size_t ber_write_contextual_nla_TSRemoteGuardPackageCred_array(
wStream* s, BYTE tag, const TSRemoteGuardPackageCred_t* item, size_t nitems);
BOOL ber_read_nla_TSRemoteGuardPackageCred_array(wStream* s, TSRemoteGuardPackageCred_t** item,
size_t* nitems);
size_t ber_sizeof_nla_TSRemoteGuardCreds_content(const TSRemoteGuardCreds_t* item);
size_t ber_sizeof_nla_TSRemoteGuardCreds(const TSRemoteGuardCreds_t* item);
size_t ber_sizeof_contextual_nla_TSRemoteGuardCreds(const TSRemoteGuardCreds_t* item);
void nla_TSRemoteGuardCreds_free(TSRemoteGuardCreds_t** pitem);
size_t ber_write_nla_TSRemoteGuardCreds(wStream* s, const TSRemoteGuardCreds_t* item);
size_t ber_write_contextual_nla_TSRemoteGuardCreds(wStream* s, BYTE tag,
const TSRemoteGuardCreds_t* item);
BOOL ber_read_nla_TSRemoteGuardCreds(wStream* s, TSRemoteGuardCreds_t** pret);
#endif /* LIBFREERDP_CORE_CREDSSP_ASN1_H */

View File

@ -1,620 +0,0 @@
#!/usr/bin/env python3
import sys
import getopt
import os.path
def compressTokens(tokens):
ret = []
for t in tokens:
if t:
ret.append(t)
return ret
class AsnField(object):
'''
'''
def __init__(self, name, seqIndex, optional, asnType, subType):
self.name = name
self.seqIndex = seqIndex
self.optional = optional
self.asnType = asnType
self.asnTypePointer = None
self.subType = subType
self.outputType = None
self.lenFunc = None
self.writeFunc = None
self.readFunc = None
self.cleanupFunc = None
self.freeFunc = None
self.options = []
if asnType.upper() in ['OCTET STRING', 'INTEGER']:
self.asnTypePointer = self.asnType
def __str__(self):
return "{0} [{1}] {2}{3}".format(self.name, self.seqIndex, self.asnType, self.optional and " OPTIONAL" or "")
class AsnSequence(object):
'''
'''
def __init__(self, name):
self.name = name
self.fields = []
FIELD_OPTION = 'fieldOption'
CHAR_TO_UNICODE = 'charInMemorySerializeToUnicode'
UNICODE = "unicode"
KNOWN_FIELD_OPTIONS = (CHAR_TO_UNICODE, UNICODE,)
class AsnParser(object):
KNOWN_OPTIONS = (FIELD_OPTION, 'prefix', )
STATE_ROOT, STATE_IN_ITEM, STATE_IN_OPTIONS = range(0, 3)
def __init__(self):
self.state = AsnParser.STATE_ROOT
self.defs = {}
self.currentItem = None
self.currentName = None
self.emitArraycode = []
# options
self.options = {
'prefix': '',
'octetStringLen': {
'char': 'strlen(item->{fieldName})',
'WCHAR': '_wcslen(item->{fieldName}) * 2',
CHAR_TO_UNICODE: 'strlen(item->{fieldName}) * 2',
}
}
def parse(self, content):
for l in content.split("\n"):
if l.startswith('#'):
continue
tokens = compressTokens(l.lstrip().rstrip().split(' '))
if self.state == AsnParser.STATE_ROOT:
if not len(tokens):
continue
if tokens[0] == "%options" and tokens[1] == "{":
self.state = AsnParser.STATE_IN_OPTIONS
continue
if tokens[1] != "::=":
continue
if tokens[2] != "SEQUENCE":
raise Exception("ERROR: not handling non sequence items for now")
self.currentName = tokens[0]
self.currentItem = AsnSequence(tokens[0])
self.state = AsnParser.STATE_IN_ITEM
elif self.state == AsnParser.STATE_IN_ITEM:
if tokens[0] == '}':
self.defs[self.currentName] = self.currentItem
self.state = AsnParser.STATE_ROOT
continue
optional = tokens[-1] in ["OPTIONAL", "OPTIONAL,"]
fieldIndex = int(tokens[1][1:-1])
if optional:
typeTokens = tokens[2:-1]
else:
typeTokens = tokens[2:]
asnType = " ".join(typeTokens)
if asnType[-1] == ',':
asnType = asnType[0:-1]
subType = None
if asnType.startswith("SEQUENCE OF"):
subType = typeTokens[-1]
asnType = "SEQUENCE OF"
self.currentItem.fields.append(AsnField(tokens[0], fieldIndex, optional, asnType, subType))
elif self.state == AsnParser.STATE_IN_OPTIONS:
if not len(tokens) or l.startswith("#"):
continue
if tokens[0] == "}":
self.state == AsnParser.STATE_ROOT
continue
option = tokens[0]
if option not in AsnParser.KNOWN_OPTIONS:
raise Exception("unknown option '{0}'".format(option))
if option == FIELD_OPTION:
target = tokens[1]
objName, fieldName = target.split(".", 2)
obj = self.defs.get(objName, None)
if not obj:
raise Exception("object type {0} unknown".format(objName))
found = False
for field in obj.fields:
if field.name == fieldName:
found = True
break
if not found:
raise Exception("object {0} has no field {1}".format(objName, fieldName))
if tokens[2] not in KNOWN_FIELD_OPTIONS:
raise Exception("unknown field option {0}".format(objName, tokens[2]))
field.options.append(tokens[2])
elif option == "prefix":
self.options['prefix'] = tokens[1]
# try to resolve custom types in fields
for typeDef in self.defs.values():
for field in typeDef.fields:
if field.asnTypePointer is None:
field.asnTypePointer = self.defs.get(field.asnType, None)
if field.asnType == "SEQUENCE OF":
self.emitArraycode.append(field.subType)
# adjust AsnField fields
for typeDef in self.defs.values():
for field in typeDef.fields:
if field.asnType == "OCTET STRING":
fieldType = field.outputType
if not fieldType:
fieldType = "WCHAR"
if CHAR_TO_UNICODE in field.options:
fieldType = "char"
field.outputType = "char"
field.writeFunc = "ber_write_contextual_char_to_unicode_octet_string(s, {fieldIndex}, item->{fieldName})"
field.lenFunc = "ber_sizeof_contextual_octet_string(strlen(item->{fieldName}) * 2)"
field.readFunc = "ber_read_char_from_unicode_octet_string({stream}, &item->{fieldName})"
elif UNICODE in field.options:
fieldType = "WCHAR"
field.outputType = "WCHAR"
field.writeFunc = "ber_write_contextual_unicode_octet_string(s, {fieldIndex}, item->{fieldName})"
field.lenFunc = "ber_sizeof_contextual_octet_string(" + self.options['octetStringLen'][fieldType] + ")"
field.readFunc = "ber_read_unicode_octet_string({stream}, &item->{fieldName})"
else:
field.writeFunc = "ber_write_contextual_octet_string(s, {fieldIndex}, item->{fieldName}, item->{fieldName}Len)"
field.lenFunc = "ber_sizeof_contextual_octet_string(item->{fieldName}Len)"
field.readFunc = "ber_read_octet_string({stream}, &item->{fieldName}, &item->{fieldName}Len)"
field.cleanupFunc = "free(item->{fieldName});"
elif field.asnType == "INTEGER":
field.lenFunc = "ber_sizeof_contextual_integer(item->{fieldName})"
field.writeFunc = "ber_write_contextual_integer(s, {fieldIndex}, item->{fieldName})"
field.readFunc = "ber_read_integer({stream}, &item->{fieldName})"
field.cleanupFunc = ""
elif field.asnType == "SEQUENCE OF":
field.lenFunc = "ber_sizeof_contextual_{prefix}{fieldSubType}_array(item->{fieldName}, item->{fieldName}Items)"
field.writeFunc = "ber_write_contextual_{prefix}{fieldSubType}_array(s, {fieldIndex}, item->{fieldName}, item->{fieldName}Items)"
field.readFunc = "ber_read_{prefix}{fieldSubType}_array({stream}, &item->{fieldName}, &item->{fieldName}Items)"
field.cleanupFunc = ""
else:
field.lenFunc = "ber_sizeof_contextual_{prefix}{fieldType}(item->{fieldName})"
field.writeFunc = "ber_write_contextual_{prefix}{fieldType}(s, {fieldIndex}, item->{fieldName})"
field.readFunc = "ber_read_{prefix}{fieldType}({stream}, &item->{fieldName})"
field.cleanupFunc = "{prefix}{fieldType}_free(&item->{fieldName});"
return True
def emitStructDefs(self):
ret = ''
for defName, seq in self.defs.items():
h = { 'prefix': self.options['prefix'], 'defName': defName }
ret += 'typedef struct {\n'
for field in seq.fields:
if field.asnType == "INTEGER":
ret += "\tUINT32 {fieldName};\n".format(fieldName=field.name)
elif field.asnType == "OCTET STRING":
fieldType = field.outputType
if CHAR_TO_UNICODE in field.options:
fieldType = 'char'
elif fieldType == 'WCHAR':
pass
else:
fieldType = 'BYTE'
ret += "\tsize_t {fieldName}Len;\n".format(fieldName=field.name, fieldType=fieldType)
ret += "\t{fieldType}* {fieldName};\n".format(fieldName=field.name, fieldType=fieldType)
elif field.asnType == "SEQUENCE OF":
ret += "\tsize_t {fieldName}Items;\n".format(fieldName=field.name, fieldType=field.subType)
ret += "\t{fieldType}_t* {fieldName};\n".format(fieldName=field.name, fieldType=field.subType)
else:
ret += "\t{typeName}_t* {fieldName};\n".format(fieldName=field.name, typeName=field.asnType)
ret += '}} {defName}_t;\n\n'.format(**h)
return ret
def emitPrototypes(self):
ret = ''
for defName, seq in self.defs.items():
h = { 'prefix': self.options['prefix'], 'defName': defName }
ret += "size_t ber_sizeof_{prefix}{defName}_content(const {defName}_t* item);\n".format(**h)
ret += "size_t ber_sizeof_{prefix}{defName}(const {defName}_t* item);\n".format(**h)
ret += "size_t ber_sizeof_contextual_{prefix}{defName}(const {defName}_t* item);\n".format(**h)
ret += "void {prefix}{defName}_free({defName}_t** pitem);\n".format(**h)
ret += "size_t ber_write_{prefix}{defName}(wStream *s, const {defName}_t* item);\n".format(**h)
ret += "size_t ber_write_contextual_{prefix}{defName}(wStream *s, BYTE tag, const {defName}_t* item);\n".format(**h)
ret += 'BOOL ber_read_{prefix}{defName}(wStream *s, {defName}_t** pret);\n'.format(**h)
if defName in self.emitArraycode:
ret += "size_t ber_sizeof_{prefix}{defName}_array_content(const {defName}_t* item, size_t nitems);\n".format(**h)
ret += "size_t ber_sizeof_{prefix}{defName}_array(const {defName}_t* item, size_t nitems);\n".format(**h)
ret += "size_t ber_sizeof_contextual_{prefix}{defName}_array(const {defName}_t* item, size_t nitems);\n".format(**h)
ret += "size_t ber_write_{prefix}{defName}_array(wStream* s, const {defName}_t* item, size_t nitems);\n".format(**h)
ret += "size_t ber_write_contextual_{prefix}{defName}_array(wStream* s, BYTE tag, const {defName}_t* item, size_t nitems);\n".format(**h)
ret += "BOOL ber_read_{prefix}{defName}_array(wStream* s, {defName}_t** item, size_t* nitems);\n".format(**h)
ret += '\n'
return ret
def emitImpl(self):
ret = ''
for defName, seq in self.defs.items():
h = { 'prefix': self.options['prefix'], 'defName': defName }
# ================= ber_sizeof_ =========================================
ret += "size_t ber_sizeof_{prefix}{defName}_content(const {defName}_t* item) {{\n".format(**h)
ret += "\tsize_t ret = 0;\n\n"
for field in seq.fields:
h2 = {'fieldName': field.name, 'fieldIndex': field.seqIndex, 'fieldType':field.asnType,
'fieldSubType': field.subType }
shift = '\t'
ret += shift + "/* [{fieldIndex}] {fieldName} ({fieldType}){optional}*/\n".format(**h2, optional=field.optional and " OPTIONAL" or "")
if field.optional:
ret += shift + "if (item->{fieldName}) {{\n".format(fieldName=field.name)
shift = '\t\t'
ret += shift + "ret += " + field.lenFunc.format(**h2, **h) + ";\n"
if field.optional:
ret += "\t}\n"
ret += '\n'
ret += '\treturn ret;\n'
ret += '}\n\n'
ret += '''size_t ber_sizeof_{prefix}{defName}(const {defName}_t* item)
{{
size_t ret = ber_sizeof_{prefix}{defName}_content(item);
return ber_sizeof_sequence(ret);
}}
'''.format(**h)
ret += "size_t ber_sizeof_contextual_{prefix}{defName}(const {defName}_t* item) {{\n".format(**h)
ret += "\tsize_t innerSz = ber_sizeof_{prefix}{defName}(item);\n".format(**h)
ret += "\treturn ber_sizeof_contextual_tag(innerSz) + innerSz;\n"
ret += "}\n\n"
# ================= free_ =========================================
ret += "void {prefix}{defName}_free({defName}_t** pitem) {{\n".format(**h)
ret += "\t{defName}_t* item;\n\n".format(**h)
ret += "\tWINPR_ASSERT(pitem);\n"
ret += "\titem = *pitem;\n"
ret += "\tif (!item)\n"
ret += "\t\treturn;\n\n"
for field in seq.fields:
if field.cleanupFunc:
h2 = { 'fieldName': field.name, 'fieldIndex': field.seqIndex, 'fieldType':field.asnType }
ret += "\t" + field.cleanupFunc.format(**h2, **h) + "\n"
ret += "\tfree(item);\n"
ret += "\t*pitem = NULL;\n"
ret += "}\n\n"
# ================= ber_write_ =========================================
ret += '''size_t ber_write_{prefix}{defName}(wStream *s, const {defName}_t* item)
{{
size_t content_size = ber_sizeof_{prefix}{defName}_content(item);
size_t ret = 0;
ret = ber_write_sequence_tag(s, content_size);
'''.format(**h)
for field in seq.fields:
h2 = { 'fieldName': field.name, 'fieldIndex': field.seqIndex, 'fieldType':field.asnType,
'fieldSubType': field.subType }
shift = " "
ret += shift + "/* [{fieldIndex}] {fieldName} ({fieldType}){optional} */\n".format(**h2, optional=field.optional and " OPTIONAL" or "")
if field.optional:
ret += shift + "if (item->{fieldName}) {{\n" .format(**h2)
shift += ' '
ret += shift + "if (!" + field.writeFunc.format(**h2, **h) + ")\n"
ret += shift + ' return 0;\n'
if field.optional:
ret += " }\n"
ret += "\n"
ret += ' return ret + content_size;\n'
ret += '}\n\n'
ret += '''size_t ber_write_contextual_{prefix}{defName}(wStream *s, BYTE tag, const {defName}_t* item)
{{
size_t ret;
size_t inner = ber_sizeof_{prefix}{defName}(item);
ret = ber_write_contextual_tag(s, tag, inner, TRUE);
ber_write_{prefix}{defName}(s, item);
return ret + inner;
}}
'''.format(**h)
# ================= ber_read_ =========================================
ret += '''BOOL ber_read_{prefix}{defName}(wStream *s, {defName}_t** pret) {{
wStream seqstream;
size_t seqLength;
size_t inner_size;
wStream fieldStream;
{defName}_t* item;
BOOL ret;
if (!ber_read_sequence_tag(s, &seqLength) || !Stream_CheckAndLogRequiredLength(TAG,s, seqLength))
return FALSE;
Stream_StaticInit(&seqstream, Stream_Pointer(s), seqLength);
item = calloc(1, sizeof(*item));
if (!item)
return FALSE;
'''.format(**h)
shiftLevel = 1
shift = ' ' * 4 * shiftLevel
cleanupLabels = []
for field in seq.fields:
h2 = { 'fieldName': field.name, 'fieldIndex': field.seqIndex, 'fieldType':field.asnType,
'stream': '&fieldStream', 'fieldSubType': field.subType }
cleanupLabels.insert(0, "\t" + field.cleanupFunc.format(**h2, **h))
cleanupLabels.insert(1, "out_fail_{fieldName}:".format(**h2, **h))
ret += shift + "/* [{fieldIndex}] {fieldName} ({fieldType}){optional} */\n".format(**h2, optional=field.optional and " OPTIONAL" or "")
ret += shift + 'ret = ber_read_contextual_tag(&seqstream, {fieldIndex}, &inner_size, TRUE);\n'.format(**h2)
if not field.optional:
ret += shift + "if (!ret) \n"
ret += shift + '\tgoto out_fail_{fieldName};\n'.format(**h2)
else:
ret += shift + "if (ret) { \n"
shiftLevel += 1
shift = ' ' * 4 * shiftLevel
ret += shift + "Stream_StaticInit(&fieldStream, Stream_Pointer(&seqstream), inner_size);\n"
ret += shift + "Stream_Seek(&seqstream, inner_size);\n"
ret += '\n'
ret += shift + "ret = " + field.readFunc.format(**h2, **h) + ";\n"
ret += shift + "if (!ret)\n"
ret += shift + '\tgoto out_fail_{fieldName};\n'.format(**h2)
if field.optional:
shiftLevel -= 1
shift = ' ' * 4 * shiftLevel
ret += shift + '}'
ret += '\n'
ret += shift + "*pret = item;\n"
ret += shift + "return TRUE;\n"
ret += '\n'
cleanupLabels = cleanupLabels[1:]
ret += "\n".join(cleanupLabels)
ret += '\n'
ret += shift + 'free(item);\n'
ret += shift + 'return FALSE;\n'
ret += '}\n\n'
# ====================== code for handling arrays ====================================
if defName in self.emitArraycode:
ret += '''size_t ber_sizeof_{prefix}{defName}_array_content(const {defName}_t* item, size_t nitems)
{{
size_t i, ret = 0;
for (i = 0; i < nitems; i++, item++)
ret += ber_sizeof_{prefix}{defName}(item);
return ber_sizeof_sequence(ret);
}}
size_t ber_sizeof_{prefix}{defName}_array(const {defName}_t* item, size_t nitems)
{{
return ber_sizeof_sequence( ber_sizeof_{prefix}{defName}_array_content(item, nitems) );
}}
size_t ber_sizeof_contextual_{prefix}{defName}_array(const {defName}_t* item, size_t nitems)
{{
size_t inner = ber_sizeof_{prefix}{defName}_array(item, nitems);
return ber_sizeof_contextual_tag(inner) + inner;
}}
size_t ber_write_{prefix}{defName}_array(wStream* s, const {defName}_t* item, size_t nitems)
{{
size_t i, r, ret;
size_t inner_len = ber_sizeof_{prefix}{defName}_array_content(item, nitems);
ret = ber_write_sequence_tag(s, inner_len);
for (i = 0; i < nitems; i++, item++)
{{
r = ber_write_{prefix}{defName}(s, item);
if (!r)
return 0;
ret += r;
}}
return ret;
}}
size_t ber_write_contextual_{prefix}{defName}_array(wStream* s, BYTE tag, const {defName}_t* item, size_t nitems)
{{
size_t ret;
size_t inner = ber_sizeof_{prefix}{defName}_array(item, nitems);
ret = ber_write_contextual_tag(s, tag, inner, TRUE);
ber_write_{prefix}{defName}_array(s, item, nitems);
return ret + inner;
}}
BOOL ber_read_{prefix}{defName}_array(wStream* s, {defName}_t** pitems, size_t* nitems)
{{
size_t subLen;
wStream subStream;
{defName}_t* retItems = NULL;
size_t ret = 0;
if (!ber_read_sequence_tag(s, &subLen) || !Stream_CheckAndLogRequiredLength(TAG,s, subLen))
return FALSE;
Stream_StaticInit(&subStream, Stream_Pointer(s), subLen);
while (Stream_GetRemainingLength(&subStream))
{{
{defName}_t *item;
{defName}_t* tmpRet;
if (!ber_read_{prefix}{defName}(&subStream, &item))
{{
free(retItems);
return FALSE;
}}
tmpRet = realloc(retItems, (ret+1) * sizeof({defName}_t));
if (!tmpRet)
{{
free(retItems);
return FALSE;
}}
retItems = tmpRet;
memcpy(&retItems[ret], item, sizeof(*item));
free(item);
ret++;
}}
*pitems = retItems;
*nitems = ret;
return TRUE;
}}
'''.format(**h)
return ret
if __name__ == '__main__':
opts, extraArgs = getopt.getopt(sys.argv[1:], "hi:o:t:", ['input=', 'output=', 'output-kind=', 'help'])
ALLOWED_OUTPUTS = ('headers', 'impls',)
inputStream = sys.stdin
outputStream = sys.stdout
outputs = ALLOWED_OUTPUTS
inputHeaderName = "ASN1_HEADER_H"
headerName = "tscredentials"
for option, value in opts:
if option in ('-h', '--help',):
print("usage: {0} [-i|--input]=<file> [-o|--output]=<file>")
print("\t[-i|--input] <file>: input file")
print("\t[-o|--output] <file>: output file")
print("\t[-t|--output-kind] [header|impl]: the kind of output")
elif option in ('-o', '--output',):
outputStream = open(value, "w")
# libfreerdp/core/credssp.c => credssp.h
headerName = os.path.splitext(os.path.basename(value))[0]
elif option in ('-i', '--input',):
inputStream = open(value, "r")
# libfreerdp/core/credssp.asn1 => LIBFREERDP_CORE_CREDSSP_ASN1_H
inputHeaderName = os.path.normpath(value).replace(os.path.sep, '_').replace('.', '_').upper() + '_H'
elif option in ('-t', '--output-kind',):
if value not in ALLOWED_OUTPUTS:
raise Exception("unknown output kind '{0}'".format(value))
outputs = value
else:
raise Exception("unknown option {0}".format(option))
input = inputStream.read()
parser = AsnParser()
parser.parse(input)
h = {'programName': os.path.basename(sys.argv[0]), 'cmdLine': ' '.join(sys.argv), 'programPath': sys.argv[0],
'inputHeaderName': inputHeaderName, 'headerName': headerName }
outputStream.write('''/* ============================================================================================================
* this file has been generated using
* {cmdLine}
*
* /!\\ If you want to modify this file you'd probably better change {programName} or the corresponding ASN1
* definition file
*
* ============================================================================================================
*/
'''.format(**h))
if outputs == 'headers':
outputStream.write('''#ifndef {inputHeaderName}
#define {inputHeaderName}
#include <winpr/stream.h>
'''.format(**h))
outputStream.write(parser.emitStructDefs())
outputStream.write(parser.emitPrototypes())
outputStream.write('#endif /* {inputHeaderName} */\n'.format(**h))
elif outputs == "impls":
outputStream.write('''
#include <winpr/string.h>
#include <freerdp/crypto/ber.h>
#include "{headerName}.h"
#include <freerdp/log.h>
#define TAG FREERDP_TAG("core.{headerName}")
'''.format(**h))
outputStream.write(parser.emitImpl())

View File

@ -146,6 +146,10 @@ extern "C"
WINPR_API size_t WinPrAsn1DecReadContextualOID(WinPrAsn1Decoder* dec, WinPrAsn1_tagId tagId,
BOOL* error, WinPrAsn1_OID* target,
BOOL allocate);
WINPR_API size_t WinPrAsn1DecReadContextualOctetString(WinPrAsn1Decoder* dec,
WinPrAsn1_tagId tagId, BOOL* error,
WinPrAsn1_OctetString* target,
BOOL allocate);
WINPR_API size_t WinPrAsn1DecReadContextualSequence(WinPrAsn1Decoder* dec,
WinPrAsn1_tagId tagId, BOOL* error,
WinPrAsn1Decoder* target);

View File

@ -1390,6 +1390,32 @@ size_t WinPrAsn1DecReadContextualOID(WinPrAsn1Decoder* dec, WinPrAsn1_tagId tagI
return ret;
}
size_t WinPrAsn1DecReadContextualOctetString(WinPrAsn1Decoder* dec, WinPrAsn1_tagId tagId,
BOOL* error, WinPrAsn1_OctetString* target,
BOOL allocate)
{
size_t ret, ret2;
WinPrAsn1_tag ftag;
WinPrAsn1Decoder content;
WINPR_ASSERT(error);
ret = WinPrAsn1DecPeekContextualTag(dec, &ftag, &content);
if (!ret || ftag != tagId)
return 0;
ret2 = WinPrAsn1DecReadOctetString(&content, target, allocate);
if (!ret2)
{
*error = TRUE;
return 0;
}
*error = FALSE;
Stream_Seek(&dec->source, ret);
return ret;
}
size_t WinPrAsn1DecReadContextualSequence(WinPrAsn1Decoder* dec, WinPrAsn1_tagId tagId, BOOL* error,
WinPrAsn1Decoder* target)
{