diff --git a/channels/rdpear/client/rdpear_main.c b/channels/rdpear/client/rdpear_main.c index 3b3f86599..4a54cca1e 100644 --- a/channels/rdpear/client/rdpear_main.c +++ b/channels/rdpear/client/rdpear_main.c @@ -52,8 +52,8 @@ typedef struct krb5_context krbContext; } RDPEAR_PLUGIN; -const BYTE payloadHeader[16] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static const BYTE payloadHeader[16] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static krb5_error_code RPC_ENCRYPTION_KEY_to_keyblock(krb5_context ctx, const KERB_RPC_ENCRYPTION_KEY* key, @@ -125,12 +125,12 @@ static krb5_error_code kerb_do_encrypt(krb5_context ctx, const KERB_RPC_ENCRYPTI rv = krb5_c_encrypt_length(ctx, keyblock->enctype, data.length, &elen); if (rv) goto out; - if (!elen) + if (!elen || (elen > UINT32_MAX)) { rv = KRB5_PARSE_MALFORMED; goto out; } - enc.ciphertext.length = elen; + enc.ciphertext.length = (unsigned int)elen; enc.ciphertext.data = malloc(elen); if (!enc.ciphertext.data) { @@ -198,8 +198,11 @@ static BOOL rdpear_send_payload(RDPEAR_PLUGIN* rdpear, IWTSVirtualChannelCallbac if (!unencodedContent) goto out; - size_t unencodedLen = Stream_GetPosition(unencodedContent); - SecBuffer inBuffer = { unencodedLen, SECBUFFER_DATA, Stream_Buffer(unencodedContent) }; + const size_t unencodedLen = Stream_GetPosition(unencodedContent); + if (unencodedLen > ULONG_MAX) + goto out; + + SecBuffer inBuffer = { (ULONG)unencodedLen, SECBUFFER_DATA, Stream_Buffer(unencodedContent) }; if (!freerdp_nla_encrypt(rdpear->rdp_context, &inBuffer, &cryptedBuffer)) goto out; @@ -219,8 +222,12 @@ static BOOL rdpear_send_payload(RDPEAR_PLUGIN* rdpear, IWTSVirtualChannelCallbac Stream_Write(finalStream, cryptedBuffer.pvBuffer, cryptedBuffer.cbBuffer); - UINT status = callback->channel->Write(callback->channel, Stream_GetPosition(finalStream), - Stream_Buffer(finalStream), NULL); + const size_t pos = Stream_GetPosition(finalStream); + if (pos > ULONG_MAX) + goto out; + + UINT status = + callback->channel->Write(callback->channel, (ULONG)pos, Stream_Buffer(finalStream), NULL); ret = (status == CHANNEL_RC_OK); if (!ret) WLog_DBG(TAG, "rdpear_send_payload=0x%x", status); @@ -263,8 +270,7 @@ out: return ret; } -static BOOL rdpear_kerb_version(RDPEAR_PLUGIN* rdpear, IWTSVirtualChannelCallback* pChannelCallback, - NdrContext* rcontext, wStream* s, UINT32* pstatus, UINT32* pversion) +static BOOL rdpear_kerb_version(NdrContext* rcontext, wStream* s, UINT32* pstatus, UINT32* pversion) { *pstatus = ERROR_INVALID_DATA; @@ -277,10 +283,8 @@ static BOOL rdpear_kerb_version(RDPEAR_PLUGIN* rdpear, IWTSVirtualChannelCallbac return TRUE; } -static BOOL rdpear_kerb_ComputeTgsChecksum(RDPEAR_PLUGIN* rdpear, - IWTSVirtualChannelCallback* pChannelCallback, - NdrContext* rcontext, wStream* s, UINT32* pstatus, - KERB_ASN1_DATA* resp) +static BOOL rdpear_kerb_ComputeTgsChecksum(RDPEAR_PLUGIN* rdpear, NdrContext* rcontext, wStream* s, + UINT32* pstatus, KERB_ASN1_DATA* resp) { ComputeTgsChecksumReq req = { 0 }; krb5_checksum checksum = { 0 }; @@ -306,7 +310,10 @@ static BOOL rdpear_kerb_ComputeTgsChecksum(RDPEAR_PLUGIN* rdpear, resp->Pdu = 8; resp->Asn1Buffer = Stream_Buffer(asn1Payload); - resp->Asn1BufferHints.count = Stream_GetPosition(asn1Payload); + const size_t pos = Stream_GetPosition(asn1Payload); + if (pos > UINT32_MAX) + goto out; + resp->Asn1BufferHints.count = (UINT32)pos; *pstatus = 0; out: @@ -316,10 +323,8 @@ out: return TRUE; } -static BOOL rdpear_kerb_BuildEncryptedAuthData(RDPEAR_PLUGIN* rdpear, - IWTSVirtualChannelCallback* pChannelCallback, - NdrContext* rcontext, wStream* s, UINT32* pstatus, - KERB_ASN1_DATA* asn1) +static BOOL rdpear_kerb_BuildEncryptedAuthData(RDPEAR_PLUGIN* rdpear, NdrContext* rcontext, + wStream* s, UINT32* pstatus, KERB_ASN1_DATA* asn1) { BuildEncryptedAuthDataReq req = { 0 }; krb5_data encrypted = { 0 }; @@ -347,7 +352,10 @@ static BOOL rdpear_kerb_BuildEncryptedAuthData(RDPEAR_PLUGIN* rdpear, // winpr_HexDump(TAG, WLOG_DEBUG, Stream_Buffer(asn1Payload), Stream_GetPosition(asn1Payload)); asn1->Pdu = 6; asn1->Asn1Buffer = Stream_Buffer(asn1Payload); - asn1->Asn1BufferHints.count = Stream_GetPosition(asn1Payload); + const size_t pos = Stream_GetPosition(asn1Payload); + if (pos > UINT32_MAX) + goto out; + asn1->Asn1BufferHints.count = (UINT32)pos; *pstatus = 0; out: @@ -388,8 +396,11 @@ static BOOL extractAuthData(const KERB_ASN1_DATA* src, krb5_authdata* authData, !WinPrAsn1DecReadContextualOctetString(&dec3, 1, &error, &os, FALSE)) return FALSE; + if (os.len > UINT32_MAX) + return FALSE; + authData->ad_type = adType; - authData->length = os.len; + authData->length = (unsigned int)os.len; authData->contents = os.data; *haveData = TRUE; return TRUE; @@ -411,8 +422,10 @@ static BOOL extractChecksum(const KERB_ASN1_DATA* src, krb5_checksum* dst) !WinPrAsn1DecReadContextualOctetString(&dec2, 1, &error, &os, FALSE)) return FALSE; + if (os.len > UINT32_MAX) + return FALSE; dst->checksum_type = cksumtype; - dst->length = os.len; + dst->length = (unsigned int)os.len; dst->contents = os.data; return TRUE; } @@ -432,9 +445,8 @@ static void krb5_free_principal_contents(krb5_context ctx, krb5_principal princi krb5_free_data(ctx, principal->data); } -static BOOL rdpear_kerb_CreateApReqAuthenticator(RDPEAR_PLUGIN* rdpear, - IWTSVirtualChannelCallback* pChannelCallback, - NdrContext* rcontext, wStream* s, UINT32* pstatus, +static BOOL rdpear_kerb_CreateApReqAuthenticator(RDPEAR_PLUGIN* rdpear, NdrContext* rcontext, + wStream* s, UINT32* pstatus, CreateApReqAuthenticatorResp* resp) { krb5_error_code rv = 0; @@ -485,8 +497,11 @@ static BOOL rdpear_kerb_CreateApReqAuthenticator(RDPEAR_PLUGIN* rdpear, .authorization_data = haveData ? authDataPtr : NULL }; client.type = req.ClientName->NameType; + if (req.ClientName->nameHints.count > INT32_MAX) + goto out; + client.length = (krb5_int32)req.ClientName->nameHints.count; - client.data = calloc(client.length, sizeof(krb5_data)); + client.data = calloc(req.ClientName->nameHints.count, sizeof(krb5_data)); if (!client.data) goto out; @@ -495,12 +510,12 @@ static BOOL rdpear_kerb_CreateApReqAuthenticator(RDPEAR_PLUGIN* rdpear, client.data[i].data = KERB_RPC_UNICODESTR_to_charptr(&req.ClientName->Names[i]); if (!client.data[i].data) goto out; - client.data[i].length = strlen(client.data[i].data); + client.data[i].length = (unsigned int)strnlen(client.data[i].data, UINT32_MAX); } client.realm.data = KERB_RPC_UNICODESTR_to_charptr(req.ClientRealm); if (!client.realm.data) goto out; - client.realm.length = strlen(client.realm.data); + client.realm.length = (unsigned int)strnlen(client.realm.data, UINT32_MAX); authent.client = &client; krb5_checksum checksum; @@ -549,7 +564,10 @@ static BOOL rdpear_kerb_CreateApReqAuthenticator(RDPEAR_PLUGIN* rdpear, // winpr_HexDump(TAG, WLOG_DEBUG, Stream_Buffer(asn1EncodedAuth), // Stream_GetPosition(asn1EncodedAuth)); - resp->Authenticator.Asn1BufferHints.count = Stream_GetPosition(asn1EncodedAuth); + const size_t size = Stream_GetPosition(asn1EncodedAuth); + if (size > UINT32_MAX) + goto out; + resp->Authenticator.Asn1BufferHints.count = (UINT32)size; resp->Authenticator.Asn1Buffer = Stream_Buffer(asn1EncodedAuth); resp->AuthenticatorTime.QuadPart = krb5_time_to_FILETIME(&authent.ctime, authent.cusec); *pstatus = 0; @@ -581,16 +599,16 @@ static BOOL rdpear_findEncryptedData(const KERB_ASN1_DATA* src, int* penctype, k !WinPrAsn1DecReadContextualOctetString(&dec2, 2, &error, &os, FALSE)) return FALSE; + if (os.len > UINT32_MAX) + return FALSE; data->data = (char*)os.data; - data->length = os.len; + data->length = (unsigned int)os.len; *penctype = encType; return TRUE; } -static BOOL rdpear_kerb_UnpackKdcReplyBody(RDPEAR_PLUGIN* rdpear, - IWTSVirtualChannelCallback* pChannelCallback, - NdrContext* rcontext, wStream* s, UINT32* pstatus, - UnpackKdcReplyBodyResp* resp) +static BOOL rdpear_kerb_UnpackKdcReplyBody(RDPEAR_PLUGIN* rdpear, NdrContext* rcontext, wStream* s, + UINT32* pstatus, UnpackKdcReplyBodyResp* resp) { UnpackKdcReplyBodyReq req = { 0 }; @@ -627,10 +645,8 @@ out: return TRUE; } -static BOOL rdpear_kerb_DecryptApReply(RDPEAR_PLUGIN* rdpear, - IWTSVirtualChannelCallback* pChannelCallback, - NdrContext* rcontext, wStream* s, UINT32* pstatus, - KERB_ASN1_DATA* resp) +static BOOL rdpear_kerb_DecryptApReply(RDPEAR_PLUGIN* rdpear, NdrContext* rcontext, wStream* s, + UINT32* pstatus, KERB_ASN1_DATA* resp) { DecryptApReplyReq req = { 0 }; @@ -665,10 +681,8 @@ out: return TRUE; } -static BOOL rdpear_kerb_PackApReply(RDPEAR_PLUGIN* rdpear, - IWTSVirtualChannelCallback* pChannelCallback, - NdrContext* rcontext, wStream* s, UINT32* pstatus, - PackApReplyResp* resp) +static BOOL rdpear_kerb_PackApReply(RDPEAR_PLUGIN* rdpear, NdrContext* rcontext, wStream* s, + UINT32* pstatus, PackApReplyResp* resp) { PackApReplyReq req = { 0 }; krb5_data asn1Data = { 0 }; @@ -705,8 +719,7 @@ out: } static UINT rdpear_decode_payload(RDPEAR_PLUGIN* rdpear, - IWTSVirtualChannelCallback* pChannelCallback, - RdpEarPackageType packageType, wStream* s) + IWTSVirtualChannelCallback* pChannelCallback, wStream* s) { UINT ret = ERROR_INVALID_DATA; NdrContext* context = NULL; @@ -746,16 +759,14 @@ static UINT rdpear_decode_payload(RDPEAR_PLUGIN* rdpear, resp = &uint32Resp; respDescr = ndr_uint32_descr(); - if (rdpear_kerb_version(rdpear, pChannelCallback, context, &commandStream, &status, - &uint32Resp)) + if (rdpear_kerb_version(context, &commandStream, &status, &uint32Resp)) ret = CHANNEL_RC_OK; break; case RemoteCallKerbCreateApReqAuthenticator: resp = &createApReqAuthenticatorResp; respDescr = ndr_CreateApReqAuthenticatorResp_descr(); - if (rdpear_kerb_CreateApReqAuthenticator(rdpear, pChannelCallback, context, - &commandStream, &status, + if (rdpear_kerb_CreateApReqAuthenticator(rdpear, context, &commandStream, &status, &createApReqAuthenticatorResp)) ret = CHANNEL_RC_OK; break; @@ -763,40 +774,37 @@ static UINT rdpear_decode_payload(RDPEAR_PLUGIN* rdpear, resp = &asn1Data; respDescr = ndr_KERB_ASN1_DATA_descr(); - if (rdpear_kerb_DecryptApReply(rdpear, pChannelCallback, context, &commandStream, - &status, &asn1Data)) + if (rdpear_kerb_DecryptApReply(rdpear, context, &commandStream, &status, &asn1Data)) ret = CHANNEL_RC_OK; break; case RemoteCallKerbComputeTgsChecksum: resp = &asn1Data; respDescr = ndr_KERB_ASN1_DATA_descr(); - if (rdpear_kerb_ComputeTgsChecksum(rdpear, pChannelCallback, context, &commandStream, - &status, &asn1Data)) + if (rdpear_kerb_ComputeTgsChecksum(rdpear, context, &commandStream, &status, &asn1Data)) ret = CHANNEL_RC_OK; break; case RemoteCallKerbBuildEncryptedAuthData: resp = &asn1Data; respDescr = ndr_KERB_ASN1_DATA_descr(); - if (rdpear_kerb_BuildEncryptedAuthData(rdpear, pChannelCallback, context, - &commandStream, &status, &asn1Data)) + if (rdpear_kerb_BuildEncryptedAuthData(rdpear, context, &commandStream, &status, + &asn1Data)) ret = CHANNEL_RC_OK; break; case RemoteCallKerbUnpackKdcReplyBody: resp = &unpackKdcReplyBodyResp; respDescr = ndr_UnpackKdcReplyBodyResp_descr(); - if (rdpear_kerb_UnpackKdcReplyBody(rdpear, pChannelCallback, context, &commandStream, - &status, &unpackKdcReplyBodyResp)) + if (rdpear_kerb_UnpackKdcReplyBody(rdpear, context, &commandStream, &status, + &unpackKdcReplyBodyResp)) ret = CHANNEL_RC_OK; break; case RemoteCallKerbPackApReply: resp = &packApReplyResp; respDescr = ndr_PackApReplyResp_descr(); - if (rdpear_kerb_PackApReply(rdpear, pChannelCallback, context, &commandStream, &status, - &packApReplyResp)) + if (rdpear_kerb_PackApReply(rdpear, context, &commandStream, &status, &packApReplyResp)) ret = CHANNEL_RC_OK; break; @@ -902,15 +910,13 @@ static UINT rdpear_on_data_received(IWTSVirtualChannelCallback* pChannelCallback if (!WinPrAsn1DecReadContextualOctetString(&dec2, 1, &error, &packageName, FALSE)) goto out; - RdpEarPackageType packageType = rdpear_packageType_from_name(&packageName); - if (!WinPrAsn1DecReadContextualOctetString(&dec2, 2, &error, &payload, FALSE)) goto out; wStream payloadStream = { 0 }; Stream_StaticInit(&payloadStream, payload.data, payload.len); - ret = rdpear_decode_payload(rdpear, pChannelCallback, packageType, &payloadStream); + ret = rdpear_decode_payload(rdpear, pChannelCallback, &payloadStream); out: sspi_SecBufferFree(&decrypted); return ret; @@ -923,7 +929,7 @@ out: */ static UINT rdpear_on_open(IWTSVirtualChannelCallback* pChannelCallback) { - + WINPR_UNUSED(pChannelCallback); return CHANNEL_RC_OK; } @@ -934,8 +940,8 @@ static UINT rdpear_on_open(IWTSVirtualChannelCallback* pChannelCallback) */ static UINT rdpear_on_close(IWTSVirtualChannelCallback* pChannelCallback) { - UINT error = CHANNEL_RC_OK; - return error; + WINPR_UNUSED(pChannelCallback); + return CHANNEL_RC_OK; } static void terminate_plugin_cb(GENERIC_DYNVC_PLUGIN* base) @@ -949,6 +955,7 @@ static void terminate_plugin_cb(GENERIC_DYNVC_PLUGIN* base) static UINT init_plugin_cb(GENERIC_DYNVC_PLUGIN* base, rdpContext* rcontext, rdpSettings* settings) { WINPR_ASSERT(base); + WINPR_UNUSED(settings); RDPEAR_PLUGIN* rdpear = (RDPEAR_PLUGIN*)base; rdpear->rdp_context = rcontext; @@ -958,7 +965,8 @@ static UINT init_plugin_cb(GENERIC_DYNVC_PLUGIN* base, rdpContext* rcontext, rdp } static const IWTSVirtualChannelCallback rdpear_callbacks = { rdpear_on_data_received, - rdpear_on_open, rdpear_on_close }; + rdpear_on_open, rdpear_on_close, + NULL }; /** * Function description diff --git a/channels/rdpear/common/ndr.c b/channels/rdpear/common/ndr.c index 73767966a..e4da773b3 100644 --- a/channels/rdpear/common/ndr.c +++ b/channels/rdpear/common/ndr.c @@ -115,6 +115,7 @@ void ndr_context_free(NdrContext* context) void ndr_context_bytes_read(NdrContext* context, size_t len) { + WINPR_ASSERT(context); context->indentLevels[context->currentLevel] += len; } @@ -156,6 +157,7 @@ BOOL ndr_write_header(NdrContext* context, wStream* s) Stream_Write(s, filler, sizeof(filler)); return TRUE; } + BOOL ndr_skip_bytes(NdrContext* context, wStream* s, size_t nbytes) { WINPR_ASSERT(context); @@ -273,11 +275,12 @@ BOOL ndr_start_constructed(NdrContext* context, wStream* s) BOOL ndr_end_constructed(NdrContext* context, wStream* s) { WINPR_ASSERT(context); + WINPR_ASSERT(context->constructs); WINPR_ASSERT(context->constructLevel >= 0); size_t offset = context->constructs[context->constructLevel]; - wStream staticS; + wStream staticS = { 0 }; Stream_StaticInit(&staticS, Stream_Buffer(s) + offset, 4); /* len */ @@ -323,6 +326,7 @@ BOOL ndr_read_uint8(NdrContext* context, wStream* s, BYTE* v) BOOL ndr_read_uint8_(NdrContext* context, wStream* s, const void* hints, void* v) { + WINPR_UNUSED(hints); return ndr_read_uint8(context, s, (BYTE*)v); } @@ -341,6 +345,7 @@ BOOL ndr_write_uint8_(NdrContext* context, wStream* s, const void* hints, const WINPR_ASSERT(context); WINPR_ASSERT(s); WINPR_ASSERT(v); + WINPR_UNUSED(hints); return ndr_write_uint8(context, s, *(const BYTE*)v); } @@ -375,6 +380,7 @@ NdrMessageType ndr_uint8_descr(void) \ BOOL ndr_read_##LOWERTYPE##_(NdrContext* context, wStream* s, const void* hints, void* v) \ { \ + WINPR_UNUSED(hints); \ return ndr_read_##LOWERTYPE(context, s, (UPPERTYPE*)v); \ } \ \ @@ -399,6 +405,7 @@ NdrMessageType ndr_uint8_descr(void) WINPR_ASSERT(context); \ WINPR_ASSERT(s); \ WINPR_ASSERT(v); \ + WINPR_UNUSED(hints); \ \ return ndr_write_##LOWERTYPE(context, s, *(const UPPERTYPE*)v); \ } \ diff --git a/channels/rdpear/common/rdpear-common/rdpear_common.h b/channels/rdpear/common/rdpear-common/rdpear_common.h index 94ae275e1..1734548f5 100644 --- a/channels/rdpear/common/rdpear-common/rdpear_common.h +++ b/channels/rdpear/common/rdpear-common/rdpear_common.h @@ -88,7 +88,7 @@ FREERDP_LOCAL wStream* rdpear_encodePayload(RdpEarPackageType packageType, wStre const V* obj); \ FREERDP_LOCAL void ndr_destroy_##V(NdrContext* context, const void* hints, V* obj); \ FREERDP_LOCAL void ndr_dump_##V(wLog* logger, UINT32 lvl, size_t indentLevel, const V* obj); \ - FREERDP_LOCAL NdrMessageType ndr_##V##_descr() + FREERDP_LOCAL NdrMessageType ndr_##V##_descr(void) /** @brief 2.2.1.2.2 KERB_RPC_OCTET_STRING */ typedef struct @@ -127,15 +127,7 @@ typedef struct RPC_UNICODE_STRING* Names; } KERB_RPC_INTERNAL_NAME; -FREERDP_LOCAL BOOL ndr_read_KERB_RPC_INTERNAL_NAME(NdrContext* context, wStream* s, - const void* hints, KERB_RPC_INTERNAL_NAME* res); -FREERDP_LOCAL BOOL ndr_write_KERB_RPC_INTERNAL_NAME(NdrContext* context, wStream* s, - const void* hints, - const KERB_RPC_INTERNAL_NAME* res); -FREERDP_LOCAL void ndr_dump_KERB_RPC_INTERNAL_NAME(wLog* logger, UINT32 lvl, size_t indentLevel, - const KERB_RPC_INTERNAL_NAME* obj); -FREERDP_LOCAL void ndr_destroy_KERB_RPC_INTERNAL_NAME(NdrContext* context, const void* hints, - KERB_RPC_INTERNAL_NAME* obj); +RDPEAR_COMMON_MESSAGE_DECL(KERB_RPC_INTERNAL_NAME); /** @brief 2.2.1.2.8 KERB_RPC_ENCRYPTION_KEY */ typedef struct @@ -191,7 +183,7 @@ typedef struct LONG KerbProtocolError; } CreateApReqAuthenticatorResp; -FREERDP_LOCAL NdrMessageType ndr_CreateApReqAuthenticatorResp_descr(); +RDPEAR_COMMON_MESSAGE_DECL(CreateApReqAuthenticatorResp); /** @brief 2.2.2.1.6 UnpackKdcReplyBody */ typedef struct @@ -212,7 +204,7 @@ typedef struct KERB_ASN1_DATA ReplyBody; } UnpackKdcReplyBodyResp; -FREERDP_LOCAL NdrMessageType ndr_UnpackKdcReplyBodyResp_descr(); +RDPEAR_COMMON_MESSAGE_DECL(UnpackKdcReplyBodyResp); typedef struct { @@ -237,7 +229,7 @@ typedef struct BYTE* PackedReply; } PackApReplyResp; -FREERDP_LOCAL NdrMessageType ndr_PackApReplyResp_descr(); +RDPEAR_COMMON_MESSAGE_DECL(PackApReplyResp); #undef RDPEAR_COMMON_MESSAGE_DECL diff --git a/channels/rdpear/common/rdpear_common.c b/channels/rdpear/common/rdpear_common.c index 3f7a53063..cf4a195b8 100644 --- a/channels/rdpear/common/rdpear_common.c +++ b/channels/rdpear/common/rdpear_common.c @@ -26,10 +26,10 @@ #define TAG CHANNELS_TAG("rdpear") -const char kerberosPackageName[] = { +static char kerberosPackageName[] = { 'K', 0, 'e', 0, 'r', 0, 'b', 0, 'e', 0, 'r', 0, 'o', 0, 's', 0 }; -const char ntlmPackageName[] = { 'N', 0, 'T', 0, 'L', 0, 'M', 0 }; +static char ntlmPackageName[] = { 'N', 0, 'T', 0, 'L', 0, 'M', 0 }; RdpEarPackageType rdpear_packageType_from_name(WinPrAsn1_OctetString* package) { @@ -99,36 +99,56 @@ out: return ret; } -#define RDPEAR_SIMPLE_MESSAGE_TYPE(V) \ - BOOL ndr_read_##V(NdrContext* context, wStream* s, const void* hints, V* obj) \ - { \ - return ndr_struct_read_fromDescr(context, s, &V##_struct, obj); \ - } \ - BOOL ndr_write_##V(NdrContext* context, wStream* s, const void* hints, const V* obj) \ - { \ - return ndr_struct_write_fromDescr(context, s, &V##_struct, obj); \ - } \ - void ndr_destroy_##V(NdrContext* context, const void* hints, V* obj) \ - { \ - ndr_struct_destroy(context, &V##_struct, obj); \ - } \ - void ndr_dump_##V(wLog* logger, UINT32 lvl, size_t indentLevel, const V* obj) \ - { \ - ndr_struct_dump_fromDescr(logger, lvl, indentLevel, &V##_struct, obj); \ - } \ - \ - NdrMessageDescr ndr_##V##_descr_s = { \ - NDR_ARITY_SIMPLE, \ - sizeof(V), \ - (NDR_READER_FN)ndr_read_##V, \ - (NDR_WRITER_FN)ndr_write_##V, \ - (NDR_DESTROY_FN)ndr_destroy_##V, \ - (NDR_DUMP_FN)ndr_dump_##V, \ - }; \ - \ - NdrMessageType ndr_##V##_descr(void) \ - { \ - return &ndr_##V##_descr_s; \ +#define RDPEAR_SIMPLE_MESSAGE_TYPE(V) \ + BOOL ndr_read_##V(NdrContext* context, wStream* s, const void* hints, V* obj) \ + { \ + WINPR_UNUSED(hints); \ + return ndr_struct_read_fromDescr(context, s, &V##_struct, obj); \ + } \ + BOOL ndr_write_##V(NdrContext* context, wStream* s, const void* hints, const V* obj) \ + { \ + WINPR_UNUSED(hints); \ + return ndr_struct_write_fromDescr(context, s, &V##_struct, obj); \ + } \ + void ndr_destroy_##V(NdrContext* context, const void* hints, V* obj) \ + { \ + WINPR_UNUSED(hints); \ + ndr_struct_destroy(context, &V##_struct, obj); \ + } \ + void ndr_dump_##V(wLog* logger, UINT32 lvl, size_t indentLevel, const V* obj) \ + { \ + ndr_struct_dump_fromDescr(logger, lvl, indentLevel, &V##_struct, obj); \ + } \ + \ + static BOOL ndr_descr_read_##V(NdrContext* context, wStream* s, const void* hints, void* obj) \ + { \ + WINPR_UNUSED(hints); \ + return ndr_struct_read_fromDescr(context, s, &V##_struct, obj); \ + } \ + static BOOL ndr_descr_write_##V(NdrContext* context, wStream* s, const void* hints, \ + const void* obj) \ + { \ + WINPR_UNUSED(hints); \ + return ndr_struct_write_fromDescr(context, s, &V##_struct, obj); \ + } \ + static void ndr_descr_destroy_##V(NdrContext* context, const void* hints, void* obj) \ + { \ + WINPR_UNUSED(hints); \ + ndr_struct_destroy(context, &V##_struct, obj); \ + } \ + static void ndr_descr_dump_##V(wLog* logger, UINT32 lvl, size_t indentLevel, const void* obj) \ + { \ + ndr_struct_dump_fromDescr(logger, lvl, indentLevel, &V##_struct, obj); \ + } \ + \ + static NdrMessageDescr ndr_##V##_descr_s = { \ + NDR_ARITY_SIMPLE, sizeof(V), ndr_descr_read_##V, ndr_descr_write_##V, \ + ndr_descr_destroy_##V, ndr_descr_dump_##V, \ + }; \ + \ + NdrMessageType ndr_##V##_descr(void) \ + { \ + return &ndr_##V##_descr_s; \ } static const NdrFieldStruct KERB_RPC_OCTET_STRING_fields[] = { @@ -166,6 +186,7 @@ BOOL ndr_read_RPC_UNICODE_STRING(NdrContext* context, wStream* s, const void* hi UINT16 Length = 0; UINT16 MaximumLength = 0; + WINPR_UNUSED(hints); if (!ndr_read_uint16(context, s, &Length) || !ndr_read_uint16(context, s, &MaximumLength) || !ndr_read_refpointer(context, s, &bufferDesc.ptrId) || Length > MaximumLength) return FALSE; @@ -177,6 +198,12 @@ BOOL ndr_read_RPC_UNICODE_STRING(NdrContext* context, wStream* s, const void* hi return ndr_push_deferreds(context, &bufferDesc, 1); } +static BOOL ndr_descr_read_RPC_UNICODE_STRING(NdrContext* context, wStream* s, const void* hints, + void* res) +{ + return ndr_read_RPC_UNICODE_STRING(context, s, hints, res); +} + #if 0 BOOL ndr_write_RPC_UNICODE_STRING(NdrContext* context, wStream* s, const void* hints, const RPC_UNICODE_STRING* res) @@ -191,31 +218,43 @@ BOOL ndr_write_RPC_UNICODE_STRING(NdrContext* context, wStream* s, const void* h void ndr_dump_RPC_UNICODE_STRING(wLog* logger, UINT32 lvl, size_t indentLevel, const RPC_UNICODE_STRING* obj) { + WINPR_UNUSED(indentLevel); WLog_Print(logger, lvl, "\tLength=%d MaximumLength=%d", obj->lenHints.length, obj->lenHints.maxLength); winpr_HexLogDump(logger, lvl, obj->Buffer, obj->lenHints.length); } +static void ndr_descr_dump_RPC_UNICODE_STRING(wLog* logger, UINT32 lvl, size_t indentLevel, + const void* obj) +{ + ndr_dump_RPC_UNICODE_STRING(logger, lvl, indentLevel, obj); +} + void ndr_destroy_RPC_UNICODE_STRING(NdrContext* context, const void* hints, RPC_UNICODE_STRING* obj) { + WINPR_UNUSED(context); + WINPR_UNUSED(hints); if (!obj) return; free(obj->Buffer); obj->Buffer = NULL; } -static const NdrMessageDescr RPC_UNICODE_STRING_descr_ = { - NDR_ARITY_SIMPLE, - sizeof(RPC_UNICODE_STRING), - (NDR_READER_FN)ndr_read_RPC_UNICODE_STRING, - /*ndr_write_RPC_UNICODE_STRING*/ NULL, - (NDR_DESTROY_FN)ndr_destroy_RPC_UNICODE_STRING, - (NDR_DUMP_FN)ndr_dump_RPC_UNICODE_STRING -}; - -NdrMessageType RPC_UNICODE_STRING_descr() +static void ndr_descr_destroy_RPC_UNICODE_STRING(NdrContext* context, const void* hints, void* obj) { - return &RPC_UNICODE_STRING_descr_; + ndr_destroy_RPC_UNICODE_STRING(context, hints, obj); +} + +static const NdrMessageDescr RPC_UNICODE_STRING_descr_s = { NDR_ARITY_SIMPLE, + sizeof(RPC_UNICODE_STRING), + ndr_descr_read_RPC_UNICODE_STRING, + /*ndr_write_RPC_UNICODE_STRING*/ NULL, + ndr_descr_destroy_RPC_UNICODE_STRING, + ndr_descr_dump_RPC_UNICODE_STRING }; + +NdrMessageType ndr_RPC_UNICODE_STRING_descr(void) +{ + return &RPC_UNICODE_STRING_descr_s; } /* ========================= RPC_UNICODE_STRING_Array ======================== */ @@ -226,7 +265,7 @@ static BOOL ndr_read_RPC_UNICODE_STRING_Array(NdrContext* context, wStream* s, c WINPR_ASSERT(context); WINPR_ASSERT(s); WINPR_ASSERT(hints); - return ndr_read_uconformant_array(context, s, hints, RPC_UNICODE_STRING_descr(), v); + return ndr_read_uconformant_array(context, s, hints, ndr_RPC_UNICODE_STRING_descr(), v); } static BOOL ndr_write_RPC_UNICODE_STRING_Array(NdrContext* context, wStream* s, const void* ghints, @@ -238,19 +277,21 @@ static BOOL ndr_write_RPC_UNICODE_STRING_Array(NdrContext* context, wStream* s, const NdrArrayHints* hints = (const NdrArrayHints*)ghints; - return ndr_write_uconformant_array(context, s, hints->count, RPC_UNICODE_STRING_descr(), v); + return ndr_write_uconformant_array(context, s, hints->count, ndr_RPC_UNICODE_STRING_descr(), v); } -static const NdrMessageDescr RPC_UNICODE_STRING_Array_descr_ = { NDR_ARITY_ARRAYOF, - sizeof(RPC_UNICODE_STRING), - ndr_read_RPC_UNICODE_STRING_Array, - ndr_write_RPC_UNICODE_STRING_Array, - (NDR_DESTROY_FN)NULL, - (NDR_DUMP_FN)NULL }; +static const NdrMessageDescr RPC_UNICODE_STRING_Array_descr_s = { + NDR_ARITY_ARRAYOF, + sizeof(RPC_UNICODE_STRING), + ndr_read_RPC_UNICODE_STRING_Array, + ndr_write_RPC_UNICODE_STRING_Array, + NULL, + NULL +}; -NdrMessageType RPC_UNICODE_STRING_Array_descr() +static NdrMessageType ndr_RPC_UNICODE_STRING_Array_descr(void) { - return &RPC_UNICODE_STRING_Array_descr_; + return &RPC_UNICODE_STRING_Array_descr_s; } /* ========================== KERB_RPC_INTERNAL_NAME ======================== */ @@ -258,10 +299,20 @@ NdrMessageType RPC_UNICODE_STRING_Array_descr() BOOL ndr_read_KERB_RPC_INTERNAL_NAME(NdrContext* context, wStream* s, const void* hints, KERB_RPC_INTERNAL_NAME* res) { + WINPR_ASSERT(res); + + union + { + RPC_UNICODE_STRING** ppstr; + void* pv; + } cnv; + cnv.ppstr = &res->Names; NdrDeferredEntry names = { NDR_PTR_NULL, "KERB_RPC_INTERNAL_NAME.Names", &res->nameHints, - &res->Names, RPC_UNICODE_STRING_Array_descr() }; + cnv.pv, ndr_RPC_UNICODE_STRING_Array_descr() }; UINT16 nameCount = 0; + WINPR_UNUSED(hints); + if (!ndr_read_uint16(context, s, &res->NameType) || !ndr_read_uint16(context, s, &nameCount)) return FALSE; @@ -270,42 +321,67 @@ BOOL ndr_read_KERB_RPC_INTERNAL_NAME(NdrContext* context, wStream* s, const void return ndr_read_refpointer(context, s, &names.ptrId) && ndr_push_deferreds(context, &names, 1); } +static BOOL ndr_descr_read_KERB_RPC_INTERNAL_NAME(NdrContext* context, wStream* s, + const void* hints, void* res) +{ + return ndr_read_KERB_RPC_INTERNAL_NAME(context, s, hints, res); +} + BOOL ndr_write_KERB_RPC_INTERNAL_NAME(NdrContext* context, wStream* s, const void* hints, const KERB_RPC_INTERNAL_NAME* res) { + WINPR_UNUSED(context); + WINPR_UNUSED(s); + WINPR_UNUSED(hints); + WINPR_UNUSED(res); + WLog_ERR(TAG, "TODO: implement this"); return FALSE; } void ndr_dump_KERB_RPC_INTERNAL_NAME(wLog* logger, UINT32 lvl, size_t indentLevel, const KERB_RPC_INTERNAL_NAME* obj) { + WINPR_UNUSED(indentLevel); + WINPR_UNUSED(obj); + WLog_Print(logger, lvl, "TODO: implement this"); +} + +static void ndr_descr_dump_KERB_RPC_INTERNAL_NAME(wLog* logger, UINT32 lvl, size_t indentLevel, + const void* obj) +{ + ndr_dump_KERB_RPC_INTERNAL_NAME(logger, lvl, indentLevel, obj); } void ndr_destroy_KERB_RPC_INTERNAL_NAME(NdrContext* context, const void* hints, KERB_RPC_INTERNAL_NAME* obj) { + WINPR_UNUSED(hints); if (!obj) return; - for (int i = 0; i < obj->nameHints.count; i++) + for (UINT32 i = 0; i < obj->nameHints.count; i++) ndr_destroy_RPC_UNICODE_STRING(context, NULL, &obj->Names[i]); free(obj->Names); obj->Names = NULL; } -NdrMessageDescr KERB_RPC_INTERNAL_NAME_descr_ = { - NDR_ARITY_SIMPLE, - sizeof(KERB_RPC_INTERNAL_NAME), - (NDR_READER_FN)ndr_read_KERB_RPC_INTERNAL_NAME, - NULL, - (NDR_DESTROY_FN)ndr_destroy_KERB_RPC_INTERNAL_NAME, - (NDR_DUMP_FN)ndr_dump_KERB_RPC_INTERNAL_NAME -}; - -NdrMessageType KERB_RPC_INTERNAL_NAME_descr() +static void ndr_descr_destroy_KERB_RPC_INTERNAL_NAME(NdrContext* context, const void* hints, + void* obj) { - return &KERB_RPC_INTERNAL_NAME_descr_; + ndr_destroy_KERB_RPC_INTERNAL_NAME(context, hints, obj); +} + +static NdrMessageDescr KERB_RPC_INTERNAL_NAME_descr_s = { NDR_ARITY_SIMPLE, + sizeof(KERB_RPC_INTERNAL_NAME), + ndr_descr_read_KERB_RPC_INTERNAL_NAME, + NULL, + ndr_descr_destroy_KERB_RPC_INTERNAL_NAME, + ndr_descr_dump_KERB_RPC_INTERNAL_NAME }; + +NdrMessageType ndr_KERB_RPC_INTERNAL_NAME_descr(void) +{ + return &KERB_RPC_INTERNAL_NAME_descr_s; } /* ========================== KERB_RPC_ENCRYPTION_KEY ======================== */ @@ -366,9 +442,9 @@ static const NdrFieldStruct CreateApReqAuthenticatorReq_fields[] = { { "SequenceNumber", offsetof(CreateApReqAuthenticatorReq, SequenceNumber), NDR_NOT_POINTER, -1, &ndr_uint32_descr_s }, { "ClientName", offsetof(CreateApReqAuthenticatorReq, ClientName), NDR_POINTER_NON_NULL, -1, - &KERB_RPC_INTERNAL_NAME_descr_ }, + &KERB_RPC_INTERNAL_NAME_descr_s }, { "ClientRealm", offsetof(CreateApReqAuthenticatorReq, ClientRealm), NDR_POINTER_NON_NULL, -1, - &RPC_UNICODE_STRING_descr_ }, + &RPC_UNICODE_STRING_descr_s }, { "SkewTime", offsetof(CreateApReqAuthenticatorReq, SkewTime), NDR_POINTER_NON_NULL, -1, &ndr_uint64_descr_s }, { "SubKey", offsetof(CreateApReqAuthenticatorReq, SubKey), NDR_POINTER, -1, diff --git a/channels/rdpear/common/test/CMakeLists.txt b/channels/rdpear/common/test/CMakeLists.txt index f294568ef..1d834ce9f 100644 --- a/channels/rdpear/common/test/CMakeLists.txt +++ b/channels/rdpear/common/test/CMakeLists.txt @@ -4,6 +4,8 @@ set(MODULE_PREFIX "TEST_RDPEAR") set(TEST_RDPEAR_DRIVER TestRdpear.c) +disable_warnings_for_directory(${CMAKE_CURRENT_BINARY_DIR}) + set(TEST_RDPEAR_TESTS TestNdr.c TestNdrEar.c diff --git a/channels/rdpear/common/test/TestNdr.c b/channels/rdpear/common/test/TestNdr.c index 3697340ee..624a72cbe 100644 --- a/channels/rdpear/common/test/TestNdr.c +++ b/channels/rdpear/common/test/TestNdr.c @@ -2,6 +2,9 @@ int TestNdr(int argc, char* argv[]) { + WINPR_UNUSED(argc); + WINPR_UNUSED(argv); + int retCode = -2; NdrContext* context = ndr_context_new(FALSE, 1); if (!context) diff --git a/channels/rdpear/common/test/TestNdrEar.c b/channels/rdpear/common/test/TestNdrEar.c index 934aee631..a9112b1c3 100644 --- a/channels/rdpear/common/test/TestNdrEar.c +++ b/channels/rdpear/common/test/TestNdrEar.c @@ -3,7 +3,22 @@ #include #include -BYTE* parseHexBlock(const char* str, size_t* plen) +#ifndef MAX +#define MAX(a, b) ((a) > (b)) ? (a) : (b) +#endif +#ifndef MIN +#define MIN(a, b) ((a) < (b)) ? (a) : (b) +#endif + +static BYTE nextValue(BYTE old, INT32 offset, char symbol, char startSymbol) +{ + const INT32 uold = 16 * old; + const INT32 diff = symbol - startSymbol; + const INT32 res = uold + diff + offset; + return (BYTE)MIN(MAX(0, res), UINT8_MAX); +} + +static BYTE* parseHexBlock(const char* str, size_t* plen) { WINPR_ASSERT(str); WINPR_ASSERT(plen); @@ -39,7 +54,7 @@ BYTE* parseHexBlock(const char* str, size_t* plen) case '7': case '8': case '9': - tmp = tmp * 16 + (*ptr - '0'); + tmp = nextValue(tmp, 0, *ptr, '0'); nchars++; if (nchars == 2) { @@ -57,7 +72,7 @@ BYTE* parseHexBlock(const char* str, size_t* plen) case 'd': case 'e': case 'f': - tmp = tmp * 16 + (10 + *ptr - 'a'); + tmp = nextValue(tmp, 10, *ptr, 'a'); nchars++; if (nchars == 2) { @@ -75,7 +90,7 @@ BYTE* parseHexBlock(const char* str, size_t* plen) case 'D': case 'E': case 'F': - tmp = tmp * 16 + (10 + *ptr - 'A'); + tmp = nextValue(tmp, 10, *ptr, 'A'); nchars++; if (nchars == 2) { @@ -97,35 +112,38 @@ BYTE* parseHexBlock(const char* str, size_t* plen) return ret; } -int TestNdrEarWrite(int argc, char* argv[]) +static int TestNdrEarWrite(int argc, char* argv[]) { - wStream* s = NULL; + WINPR_UNUSED(argc); + WINPR_UNUSED(argv); + int rc = -1; BYTE buffer[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; - KERB_ASN1_DATA asn1; - asn1.Pdu = 7; - asn1.Asn1BufferHints.count = 16; - asn1.Asn1Buffer = buffer; + KERB_ASN1_DATA asn1 = { 7, { 16 }, buffer }; - s = Stream_New(NULL, 100); + wStream* s = Stream_New(NULL, 100); if (!s) return -1; NdrContext* context = ndr_context_new(FALSE, 1); if (!context) - return -1; + goto fail; if (!ndr_write_KERB_ASN1_DATA(context, s, NULL, &asn1)) - return -2; + goto fail; if (!ndr_treat_deferred_write(context, s)) - return -3; + goto fail; // winpr_HexDump("", WLOG_DEBUG, Stream_Buffer(s), Stream_GetPosition(s)); + + rc = 0; +fail: ndr_context_destroy(&context); - return 0; + Stream_Free(s, TRUE); + return rc; } -int TestNdrEarRead(int argc, char* argv[]) +static int TestNdrEarRead(int argc, char* argv[]) { WINPR_UNUSED(argc); WINPR_UNUSED(argv); @@ -356,5 +374,8 @@ out: int TestNdrEar(int argc, char* argv[]) { + const int rc = TestNdrEarWrite(argc, argv); + if (rc) + return rc; return TestNdrEarRead(argc, argv); }