📄 verify.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
#include "pch.h"
#if ! (defined (UNDER_CE) || defined (WINCE_EMULATION))
#include "bt_100.h"
#pragma code_seg("PAGE", "CODE")
#endif
UCHAR IdxToSize[] = {
sizeof(UCHAR),
sizeof(USHORT),
sizeof(ULONG),
sizeof(ULONGLONG),
sizeof(ULONGLONG) * 2
};
#define INC_STREAM(_inc) \
{ \
pStream += (_inc); \
size -= (_inc); \
}
NTSTATUS
SdpVerifySequenceOf(
UCHAR *pStream,
ULONG size,
UCHAR ofType,
UCHAR *pSpecSizes,
ULONG *pNumFound,
PSDP_STREAM_WALK_FUNC pFunc,
PVOID pContext
)
{
UCHAR type, sizeIndex;
SdpRetrieveHeader(pStream, type, sizeIndex);
if (type != SDP_TYPE_SEQUENCE) {
return STATUS_INVALID_PARAMETER;
}
INC_STREAM(1);
ULONG elementSize, storageSize;
SdpRetrieveVariableSize(pStream, sizeIndex, &elementSize, &storageSize);
INC_STREAM(storageSize);
//
// Make sure the top level seqeunce is the only element in the stream
//
if (size != elementSize) {
return STATUS_INVALID_PARAMETER;
}
while (size) {
SdpRetrieveHeader(pStream, type, sizeIndex);
if (type != ofType) {
return STATUS_INVALID_PARAMETER;
}
INC_STREAM(1);
if (pSpecSizes) {
BOOLEAN matched = FALSE;
for (ULONG idx = 0; pSpecSizes[idx] != 0x00; idx++) {
if (IdxToSize[sizeIndex] == pSpecSizes[idx]) {
matched = TRUE;
break;
}
}
if (matched == FALSE) {
return STATUS_INVALID_PARAMETER;
}
}
if (ARGUMENT_PRESENT(pNumFound)) {
(*pNumFound)++;
}
ULONG dataSize;
switch (sizeIndex) {
case 0:
case 1:
case 2:
case 3:
case 4:
dataSize = IdxToSize[sizeIndex];
break;
default:
SdpRetrieveVariableSize(pStream, sizeIndex, &dataSize, &storageSize);
INC_STREAM(storageSize);
break;
}
if (pFunc != NULL) {
NTSTATUS status = pFunc(pContext,
type,
dataSize,
pStream,
0);
if (!NT_SUCCESS(status) && status != STATUS_REPARSE_POINT_NOT_RESOLVED) {
return status;
}
}
INC_STREAM(dataSize);
}
return STATUS_SUCCESS;
}
typedef NTSTATUS (*PFNVERIFY)(PUCHAR pStream, ULONG size, ULONG flags);
struct ProtocolListInfo {
ProtocolListInfo(ULONG f) : firstSequence(TRUE), havePsm(FALSE), psmFromUuid(FALSE), flags(f) {}
ULONG flags;
BOOLEAN firstSequence;
BOOLEAN psmFromUuid;
BOOLEAN havePsm;
};
NTSTATUS
WalkProtocolSequence(
ProtocolListInfo *pInfo,
UCHAR DataType,
ULONG DataSize,
PUCHAR Data,
ULONG DataStorageSize
)
{
UCHAR type, sizeIndex;
//
// must have content
//
if (DataSize == 0) {
return STATUS_INVALID_PARAMETER;
}
SdpRetrieveHeader(Data, type, sizeIndex);
//
// first element must be a UUID
//
if (type != SDP_TYPE_UUID) {
return STATUS_INVALID_PARAMETER;
}
Data += 1;
DataSize -= 1;
GUID uuid;
SdpRetrieveUuidFromStream(Data, IdxToSize[sizeIndex], &uuid, FALSE);
DataSize -= IdxToSize[sizeIndex];
//
// Perform this check for local services only b/c who knows what is on
// the remote device.
//
if (pInfo->flags & VERIFY_CHECK_MANDATORY_LOCAL) {
if (pInfo->firstSequence) {
//
// ISSUE: right now every profile specifies L2CAP as the lowest layer
// which means that if any profile comes along that doesn't specify
// L2CAP, this needs to be changed....but I don't see that
// happening anytime soon and all we implement is l2cap anyways
if (!IsEqualUuid(&uuid, &L2CAP_PROTOCOL_UUID)) {
//
// first protocol must L2CAP
//
return STATUS_INVALID_PARAMETER;
}
//
// no PSM in the record, see if we can determine it from a well known
// protocol on top of L2CAP
//
if (DataSize == 0) {
pInfo->psmFromUuid = TRUE;
}
pInfo->firstSequence = FALSE;
}
else if (pInfo->psmFromUuid && pInfo->havePsm == FALSE) {
if (IsEqualUuid(&uuid, &SDP_PROTOCOL_UUID) ||
IsEqualUuid(&uuid, &RFCOMM_PROTOCOL_UUID) ||
IsEqualUuid(&uuid, &TCSBIN_PROTOCOL_UUID)) {
pInfo->havePsm = TRUE;
}
else {
return STATUS_INVALID_PARAMETER;
}
}
}
//
// We only know how to look at L2CAP and RFCOMM optinal elements
//
if (DataSize) {
Data += IdxToSize[sizeIndex];
SdpRetrieveHeader(Data, type, sizeIndex);
if (IsEqualUuid(&uuid, &L2CAP_PROTOCOL_UUID)) {
//
// PSM
//
if (type != SDP_TYPE_UINT || IdxToSize[sizeIndex] != sizeof(USHORT)) {
return STATUS_INVALID_PARAMETER;
}
pInfo->havePsm = TRUE;
ASSERT(pInfo->psmFromUuid == FALSE);
}
else if (IsEqualUuid(&uuid, &RFCOMM_PROTOCOL_UUID)) {
//
// Channel number
//
if (type != SDP_TYPE_UINT || IdxToSize[sizeIndex] != sizeof(UCHAR)) {
return STATUS_INVALID_PARAMETER;
}
}
}
return STATUS_SUCCESS;
}
NTSTATUS VerifyProtocolList(PUCHAR pStream, ULONG size, ULONG flags)
{
UCHAR type, sizeIndex;
ULONG numFound;
NTSTATUS status;
SdpRetrieveHeader(pStream, type, sizeIndex);
if (type == SDP_TYPE_SEQUENCE) {
ProtocolListInfo pli(flags);
numFound = 0;
status = SdpVerifySequenceOf(pStream,
size,
SDP_TYPE_SEQUENCE,
NULL,
&numFound,
(PSDP_STREAM_WALK_FUNC) WalkProtocolSequence,
&pli);
if (NT_SUCCESS(status) &&
(numFound == 0 ||
(pli.havePsm == FALSE && (flags & VERIFY_CHECK_MANDATORY_LOCAL)))) {
return STATUS_INVALID_PARAMETER;
}
return status;
}
else if (type == SDP_TYPE_ALTERNATIVE) {
//
// iterate over the list, making sure each one is a well formed sequence
// of sequences
//
ULONG elementSize, storageSize;
INC_STREAM(1);
SdpRetrieveVariableSize(pStream, sizeIndex, &elementSize, &storageSize);
//
// must have content
//
if (elementSize == 0) {
return STATUS_INVALID_PARAMETER;
}
INC_STREAM(storageSize);
//
// must be the only element in the stream
//
if (size != elementSize) {
return STATUS_INVALID_PARAMETER;
}
while (size) {
SdpRetrieveHeader(pStream, type, sizeIndex);
if (type != SDP_TYPE_SEQUENCE) {
return STATUS_INVALID_PARAMETER;
}
PUCHAR tmpStream = pStream;
INC_STREAM(1);
SdpRetrieveVariableSize(pStream, sizeIndex, &elementSize, &storageSize);
ProtocolListInfo pli(flags);
numFound = 0;
status =
SdpVerifySequenceOf(tmpStream,
elementSize + storageSize + 1, // 1 == elem header
SDP_TYPE_SEQUENCE,
NULL,
&numFound,
(PSDP_STREAM_WALK_FUNC) WalkProtocolSequence,
&pli);
if (!NT_SUCCESS(status)) {
return status;
}
else if (numFound == 0 ||
(pli.havePsm == FALSE && (flags & VERIFY_CHECK_MANDATORY_LOCAL))) {
return STATUS_INVALID_PARAMETER;
}
INC_STREAM(storageSize);
INC_STREAM(elementSize);
}
return STATUS_SUCCESS;
}
else {
return STATUS_INVALID_PARAMETER;
}
}
NTSTATUS VerifyLangIdList(PUCHAR pStream, ULONG size, ULONG flags)
{
UCHAR sizes[] = { sizeof(USHORT), 0x00 };
ULONG numFound = 0;
NTSTATUS status;
status = SdpVerifySequenceOf(pStream,
size,
SDP_TYPE_UINT,
sizes,
&numFound,
NULL,
NULL);
if (NT_SUCCESS(status) && ( (numFound == 0) || (numFound % 3 != 0) ) ) {
status = STATUS_INVALID_PARAMETER;
}
return status;
}
NTSTATUS
WalkProfileDescriptor(
PVOID pContext,
UCHAR DataType,
ULONG DataSize,
PUCHAR Data,
ULONG DataStorageSize
)
{
UCHAR type, sizeIndex;
//
// must have content
//
if (DataSize == 0) {
return STATUS_INVALID_PARAMETER;
}
SdpRetrieveHeader(Data, type, sizeIndex);
Data += 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -