mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-14 00:14:11 +09:00
rdpear: handle basic NTLM commands and fix server-side
This patch adds the handling of basic NTLM commands. Because there's some mysterious 4 zero bytes after pickle header in Kerberos packets, not present in NTLM commands, the patch also had to rework a bit the packet parsing / forging. The patch also addresses a server-side bug when parsing supplemental creds, if the client was sending an empty list, we were considering this as an error. And finally we also implement the parsing of MSV1_0_REMOTE_SUPPLEMENTAL_CREDENTIAL. This breaks the public API, anyway this was basically unused (as not parsed before) and the previous API was wrong as what we receive is MSV1_0_REMOTE_SUPPLEMENTAL_CREDENTIAL not MSV1_0_SUPPLEMENTAL_CREDENTIAL, so I guess the API breakage is ok.
This commit is contained in:
@@ -193,13 +193,13 @@ out:
|
||||
}
|
||||
|
||||
static BOOL rdpear_send_payload(RDPEAR_PLUGIN* rdpear, IWTSVirtualChannelCallback* pChannelCallback,
|
||||
RdpEarPackageType packageType, wStream* payload)
|
||||
BOOL isKerb, wStream* payload)
|
||||
{
|
||||
GENERIC_CHANNEL_CALLBACK* callback = (GENERIC_CHANNEL_CALLBACK*)pChannelCallback;
|
||||
BOOL ret = FALSE;
|
||||
wStream* finalStream = NULL;
|
||||
SecBuffer cryptedBuffer = { 0 };
|
||||
wStream* unencodedContent = rdpear_encodePayload(packageType, payload);
|
||||
wStream* unencodedContent = rdpear_encodePayload(isKerb, payload);
|
||||
if (!unencodedContent)
|
||||
goto out;
|
||||
|
||||
@@ -248,7 +248,7 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL rdpear_prepare_response(NdrContext* rcontext, UINT16 callId, UINT32 status,
|
||||
static BOOL rdpear_prepare_response(NdrContext* rcontext, BOOL isKerb, UINT16 callId, UINT32 status,
|
||||
NdrContext** pwcontext, wStream* retStream)
|
||||
{
|
||||
WINPR_ASSERT(rcontext);
|
||||
@@ -266,8 +266,17 @@ static BOOL rdpear_prepare_response(NdrContext* rcontext, UINT16 callId, UINT32
|
||||
Stream_Write(retStream, payloadHeader, sizeof(payloadHeader));
|
||||
|
||||
if (!ndr_write_header(wcontext, retStream) || !ndr_start_constructed(wcontext, retStream) ||
|
||||
!ndr_write_pickle(wcontext, retStream) || /* pickle header */
|
||||
!ndr_write_uint16(wcontext, retStream, callId) || /* callId */
|
||||
!ndr_write_pickle(wcontext, retStream)) /* pickle header */
|
||||
goto out;
|
||||
if (isKerb)
|
||||
{
|
||||
/* for some reason there's 4 zero undocumented bytes here after the pickle record
|
||||
* in the kerberos package packets */
|
||||
UINT32 v = 0;
|
||||
if (!ndr_write_uint32(wcontext, retStream, v))
|
||||
goto out;
|
||||
}
|
||||
if (!ndr_write_uint16(wcontext, retStream, callId) || /* callId */
|
||||
!ndr_write_uint16(wcontext, retStream, 0x0000) || /* align padding */
|
||||
!ndr_write_uint32(wcontext, retStream, status) || /* status */
|
||||
!ndr_write_uint16(wcontext, retStream, callId) || /* callId */
|
||||
@@ -748,8 +757,22 @@ out:
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL rdpear_ntlm_version(NdrContext* rcontext, wStream* s, UINT32* pstatus, UINT32* pversion)
|
||||
{
|
||||
*pstatus = ERROR_INVALID_DATA;
|
||||
|
||||
if (!ndr_read_uint32(rcontext, s, pversion))
|
||||
return TRUE;
|
||||
|
||||
WLog_DBG(TAG, "-> NtlmNegotiateVersion(v=0x%x)", *pversion);
|
||||
*pstatus = 0;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static UINT rdpear_decode_payload(RDPEAR_PLUGIN* rdpear,
|
||||
IWTSVirtualChannelCallback* pChannelCallback, wStream* s)
|
||||
IWTSVirtualChannelCallback* pChannelCallback,
|
||||
const WinPrAsn1_OctetString* packageName, wStream* s)
|
||||
{
|
||||
UINT ret = ERROR_INVALID_DATA;
|
||||
NdrContext* context = NULL;
|
||||
@@ -761,7 +784,6 @@ static UINT rdpear_decode_payload(RDPEAR_PLUGIN* rdpear,
|
||||
CreateApReqAuthenticatorResp createApReqAuthenticatorResp = { 0 };
|
||||
UnpackKdcReplyBodyResp unpackKdcReplyBodyResp = { 0 };
|
||||
PackApReplyResp packApReplyResp = { 0 };
|
||||
|
||||
void* resp = NULL;
|
||||
NdrMessageType respDescr = NULL;
|
||||
|
||||
@@ -769,16 +791,40 @@ static UINT rdpear_decode_payload(RDPEAR_PLUGIN* rdpear,
|
||||
if (!respStream)
|
||||
goto out;
|
||||
|
||||
Stream_Seek(s, 16); /* skip first 16 bytes */
|
||||
BOOL isKerb = FALSE;
|
||||
switch (rdpear_packageType_from_name(packageName))
|
||||
{
|
||||
case RDPEAR_PACKAGE_KERBEROS:
|
||||
isKerb = TRUE;
|
||||
break;
|
||||
case RDPEAR_PACKAGE_NTLM:
|
||||
isKerb = FALSE;
|
||||
break;
|
||||
default:
|
||||
WLog_ERR(TAG, "unknown package type");
|
||||
goto out;
|
||||
}
|
||||
|
||||
Stream_Seek(s, 16); /* skip first 16 bytes */
|
||||
wStream commandStream = { 0 };
|
||||
UINT16 callId = 0;
|
||||
UINT16 callId2 = 0;
|
||||
|
||||
context = ndr_read_header(s);
|
||||
if (!context || !ndr_read_constructed(context, s, &commandStream) ||
|
||||
!ndr_read_pickle(context, &commandStream) ||
|
||||
!ndr_read_uint16(context, &commandStream, &callId) ||
|
||||
!ndr_read_pickle(context, &commandStream))
|
||||
goto out;
|
||||
|
||||
if (isKerb)
|
||||
{
|
||||
/* for some reason there's 4 zero undocumented bytes here after the pickle record
|
||||
* in the kerberos package packets */
|
||||
UINT32 v = 0;
|
||||
if (!ndr_read_uint32(context, &commandStream, &v))
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!ndr_read_uint16(context, &commandStream, &callId) ||
|
||||
!ndr_read_uint16(context, &commandStream, &callId2) || (callId != callId2))
|
||||
goto out;
|
||||
|
||||
@@ -837,9 +883,12 @@ static UINT rdpear_decode_payload(RDPEAR_PLUGIN* rdpear,
|
||||
if (rdpear_kerb_PackApReply(rdpear, context, &commandStream, &status, &packApReplyResp))
|
||||
ret = CHANNEL_RC_OK;
|
||||
break;
|
||||
|
||||
case RemoteCallNtlmNegotiateVersion:
|
||||
WLog_ERR(TAG, "don't wanna support NTLM");
|
||||
resp = &uint32Resp;
|
||||
respDescr = ndr_uint32_descr();
|
||||
|
||||
if (rdpear_ntlm_version(context, &commandStream, &status, &uint32Resp))
|
||||
ret = CHANNEL_RC_OK;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -849,7 +898,7 @@ static UINT rdpear_decode_payload(RDPEAR_PLUGIN* rdpear,
|
||||
break;
|
||||
}
|
||||
|
||||
if (!rdpear_prepare_response(context, callId, status, &wcontext, respStream))
|
||||
if (!rdpear_prepare_response(context, isKerb, callId, status, &wcontext, respStream))
|
||||
goto out;
|
||||
|
||||
if (resp && respDescr)
|
||||
@@ -870,7 +919,7 @@ static UINT rdpear_decode_payload(RDPEAR_PLUGIN* rdpear,
|
||||
}
|
||||
|
||||
if (!ndr_end_constructed(wcontext, respStream) ||
|
||||
!rdpear_send_payload(rdpear, pChannelCallback, RDPEAR_PACKAGE_KERBEROS, respStream))
|
||||
!rdpear_send_payload(rdpear, pChannelCallback, isKerb, respStream))
|
||||
{
|
||||
WLog_DBG(TAG, "rdpear_send_payload !!!!!!!!");
|
||||
goto out;
|
||||
@@ -946,7 +995,7 @@ static UINT rdpear_on_data_received(IWTSVirtualChannelCallback* pChannelCallback
|
||||
wStream payloadStream = { 0 };
|
||||
Stream_StaticInit(&payloadStream, payload.data, payload.len);
|
||||
|
||||
ret = rdpear_decode_payload(rdpear, pChannelCallback, &payloadStream);
|
||||
ret = rdpear_decode_payload(rdpear, pChannelCallback, &packageName, &payloadStream);
|
||||
out:
|
||||
sspi_SecBufferFree(&decrypted);
|
||||
return ret;
|
||||
|
||||
@@ -216,7 +216,7 @@ BOOL ndr_read_pickle(NdrContext* context, wStream* s)
|
||||
if (!ndr_read_uint32(context, s, &v) || v != 0x20000)
|
||||
return FALSE;
|
||||
|
||||
return ndr_read_uint32(context, s, &v); // padding
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL ndr_write_pickle(NdrContext* context, wStream* s)
|
||||
@@ -227,7 +227,6 @@ BOOL ndr_write_pickle(NdrContext* context, wStream* s)
|
||||
if (!ndr_write_uint32(context, s, 0x20000))
|
||||
return FALSE;
|
||||
|
||||
ndr_write_uint32(context, s, 0); /* padding */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
@@ -79,8 +79,9 @@ typedef enum
|
||||
// End NTLM remote calls
|
||||
} RemoteGuardCallId;
|
||||
|
||||
FREERDP_LOCAL RdpEarPackageType rdpear_packageType_from_name(WinPrAsn1_OctetString* package);
|
||||
FREERDP_LOCAL wStream* rdpear_encodePayload(RdpEarPackageType packageType, wStream* payload);
|
||||
FREERDP_LOCAL RdpEarPackageType rdpear_packageType_from_name(const WinPrAsn1_OctetString* package);
|
||||
WINPR_ATTR_MALLOC(Stream_Free, 1)
|
||||
FREERDP_LOCAL wStream* rdpear_encodePayload(BOOL isKerb, wStream* payload);
|
||||
|
||||
#define RDPEAR_COMMON_MESSAGE_DECL(V) \
|
||||
FREERDP_LOCAL BOOL ndr_read_##V(NdrContext* context, wStream* s, const void* hints, V* obj); \
|
||||
|
||||
@@ -31,7 +31,7 @@ static char kerberosPackageName[] = {
|
||||
};
|
||||
static char ntlmPackageName[] = { 'N', 0, 'T', 0, 'L', 0, 'M', 0 };
|
||||
|
||||
RdpEarPackageType rdpear_packageType_from_name(WinPrAsn1_OctetString* package)
|
||||
RdpEarPackageType rdpear_packageType_from_name(const WinPrAsn1_OctetString* package)
|
||||
{
|
||||
if (package->len == sizeof(kerberosPackageName) &&
|
||||
memcmp(package->data, kerberosPackageName, package->len) == 0)
|
||||
@@ -44,7 +44,7 @@ RdpEarPackageType rdpear_packageType_from_name(WinPrAsn1_OctetString* package)
|
||||
return RDPEAR_PACKAGE_UNKNOWN;
|
||||
}
|
||||
|
||||
wStream* rdpear_encodePayload(RdpEarPackageType packageType, wStream* payload)
|
||||
wStream* rdpear_encodePayload(BOOL isKerb, wStream* payload)
|
||||
{
|
||||
wStream* ret = NULL;
|
||||
WinPrAsn1Encoder* enc = WinPrAsn1Encoder_New(WINPR_ASN1_DER);
|
||||
@@ -57,18 +57,15 @@ wStream* rdpear_encodePayload(RdpEarPackageType packageType, wStream* payload)
|
||||
|
||||
/* packageName [1] OCTET STRING */
|
||||
WinPrAsn1_OctetString packageOctetString;
|
||||
switch (packageType)
|
||||
if (isKerb)
|
||||
{
|
||||
case RDPEAR_PACKAGE_KERBEROS:
|
||||
packageOctetString.data = (BYTE*)kerberosPackageName;
|
||||
packageOctetString.len = sizeof(kerberosPackageName);
|
||||
break;
|
||||
case RDPEAR_PACKAGE_NTLM:
|
||||
packageOctetString.data = (BYTE*)ntlmPackageName;
|
||||
packageOctetString.len = sizeof(ntlmPackageName);
|
||||
break;
|
||||
default:
|
||||
goto out;
|
||||
packageOctetString.data = (BYTE*)kerberosPackageName;
|
||||
packageOctetString.len = sizeof(kerberosPackageName);
|
||||
}
|
||||
else
|
||||
{
|
||||
packageOctetString.data = (BYTE*)ntlmPackageName;
|
||||
packageOctetString.len = sizeof(ntlmPackageName);
|
||||
}
|
||||
|
||||
if (!WinPrAsn1EncContextualOctetString(enc, 1, &packageOctetString))
|
||||
|
||||
@@ -322,7 +322,7 @@ static int TestNdrEarRead(int argc, char* argv[])
|
||||
};
|
||||
size_t sizeofPayload4 = sizeof(payload4);
|
||||
#endif
|
||||
#if 1
|
||||
|
||||
size_t sizeofPayload4 = 0;
|
||||
BYTE* payload4 = parseHexBlock("03 01 03 01 \
|
||||
04 00 02 00 38 9e ef 6b 0c 00 02 00 18 00 02 00 \
|
||||
@@ -346,7 +346,6 @@ static int TestNdrEarRead(int argc, char* argv[])
|
||||
|
||||
if (!payload4)
|
||||
goto out;
|
||||
#endif
|
||||
|
||||
CreateApReqAuthenticatorReq createApReqAuthenticatorReq = { 0 };
|
||||
s = Stream_StaticInit(&staticS, payload4, sizeofPayload4);
|
||||
|
||||
@@ -56,8 +56,18 @@ extern "C"
|
||||
typedef BOOL (*psPeerHasMoreToRead)(freerdp_peer* peer);
|
||||
typedef BOOL (*psPeerClose)(freerdp_peer* peer);
|
||||
typedef void (*psPeerDisconnect)(freerdp_peer* peer);
|
||||
|
||||
/** callback called when we receive remote credential guard credentials during NLA
|
||||
* @param peer the associated freerdp_peer
|
||||
* @param logonCreds the KERB_TICKET_LOGON containing the TGT and the host service ticket
|
||||
* @param suppCreds some MSV1_0_REMOTE_SUPPLEMENTAL_CREDENTIAL containing NTLM hashes
|
||||
* @return if the treatment was successful
|
||||
* @bug before 3.19.0 suppCreds were a pointer to MSV1_0_SUPPLEMENTAL_CREDENTIAL, not
|
||||
* MSV1_0_REMOTE_SUPPLEMENTAL_CREDENTIAL as now
|
||||
*/
|
||||
typedef BOOL (*psPeerRemoteCredentials)(freerdp_peer* peer, KERB_TICKET_LOGON* logonCreds,
|
||||
MSV1_0_SUPPLEMENTAL_CREDENTIAL* suppCreds);
|
||||
MSV1_0_REMOTE_SUPPLEMENTAL_CREDENTIAL* suppCreds);
|
||||
|
||||
typedef BOOL (*psPeerCapabilities)(freerdp_peer* peer);
|
||||
typedef BOOL (*psPeerPostConnect)(freerdp_peer* peer);
|
||||
typedef BOOL (*psPeerActivate)(freerdp_peer* peer);
|
||||
|
||||
@@ -1196,6 +1196,40 @@ static BOOL nla_read_KERB_TICKET_LOGON(WINPR_ATTR_UNUSED rdpNla* nla, wStream* s
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
WINPR_ATTR_MALLOC(free, 1)
|
||||
static MSV1_0_REMOTE_SUPPLEMENTAL_CREDENTIAL* nla_read_NtlmCreds(WINPR_ATTR_UNUSED rdpNla* nla,
|
||||
wStream* s)
|
||||
{
|
||||
WINPR_ASSERT(nla);
|
||||
WINPR_ASSERT(s);
|
||||
|
||||
if (!Stream_CheckAndLogRequiredLength(TAG, s, 32 + 4))
|
||||
return NULL;
|
||||
|
||||
size_t pos = Stream_GetPosition(s);
|
||||
Stream_Seek(s, 32);
|
||||
|
||||
ULONG EncryptedCredsSize = Stream_Get_UINT32(s);
|
||||
if (!Stream_CheckAndLogRequiredLength(TAG, s, EncryptedCredsSize))
|
||||
return NULL;
|
||||
|
||||
Stream_SetPosition(s, pos);
|
||||
|
||||
MSV1_0_REMOTE_SUPPLEMENTAL_CREDENTIAL* ret = (MSV1_0_REMOTE_SUPPLEMENTAL_CREDENTIAL*)calloc(
|
||||
1, sizeof(MSV1_0_REMOTE_SUPPLEMENTAL_CREDENTIAL) - 1 + EncryptedCredsSize);
|
||||
if (!ret)
|
||||
return NULL;
|
||||
|
||||
ret->Version = Stream_Get_UINT32(s);
|
||||
ret->Flags = Stream_Get_UINT32(s);
|
||||
Stream_Read(s, ret->CredentialKey.Data, MSV1_0_CREDENTIAL_KEY_LENGTH);
|
||||
ret->CredentialKeyType = Stream_Get_UINT32(s);
|
||||
ret->EncryptedCredsSize = EncryptedCredsSize;
|
||||
Stream_Read(s, ret->EncryptedCreds, EncryptedCredsSize);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @brief kind of RCG credentials */
|
||||
typedef enum
|
||||
{
|
||||
@@ -1372,10 +1406,11 @@ static BOOL nla_read_ts_credentials(rdpNla* nla, SecBuffer* data)
|
||||
}
|
||||
|
||||
/* supplementalCreds [1] SEQUENCE OF TSRemoteGuardPackageCred OPTIONAL, */
|
||||
MSV1_0_SUPPLEMENTAL_CREDENTIAL* suppCreds = NULL;
|
||||
MSV1_0_REMOTE_SUPPLEMENTAL_CREDENTIAL* suppCreds = NULL;
|
||||
WinPrAsn1Decoder suppCredsSeq = { 0 };
|
||||
|
||||
if (WinPrAsn1DecReadContextualSequence(&dec2, 1, &error, &suppCredsSeq))
|
||||
if (WinPrAsn1DecReadContextualSequence(&dec2, 1, &error, &suppCredsSeq) &&
|
||||
Stream_GetRemainingLength(&suppCredsSeq.source))
|
||||
{
|
||||
WinPrAsn1Decoder ntlmCredsSeq = { 0 };
|
||||
if (!WinPrAsn1DecReadSequence(&suppCredsSeq, &ntlmCredsSeq))
|
||||
@@ -1393,7 +1428,12 @@ static BOOL nla_read_ts_credentials(rdpNla* nla, SecBuffer* data)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* TODO: suppCreds = &ntlmCreds; and parse NTLM creds */
|
||||
suppCreds = nla_read_NtlmCreds(nla, &ntlmPayload);
|
||||
if (!suppCreds)
|
||||
{
|
||||
WLog_ERR(TAG, "invalid supplementalCreds");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else if (error)
|
||||
{
|
||||
@@ -1403,6 +1443,7 @@ static BOOL nla_read_ts_credentials(rdpNla* nla, SecBuffer* data)
|
||||
|
||||
freerdp_peer* peer = nla->rdpcontext->peer;
|
||||
ret = IFCALLRESULT(TRUE, peer->RemoteCredentials, peer, &kerbLogon, suppCreds);
|
||||
free(suppCreds);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -1486,6 +1527,40 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL nla_write_TSRemoteGuardNtlmCred(rdpNla* nla, WinPrAsn1Encoder* enc,
|
||||
const MSV1_0_REMOTE_SUPPLEMENTAL_CREDENTIAL* pntlm)
|
||||
{
|
||||
WINPR_UNUSED(nla);
|
||||
BOOL ret = FALSE;
|
||||
BYTE ntlm[] = { 'N', '\0', 'T', '\0', 'L', '\0', 'M', '\0' };
|
||||
const WinPrAsn1_OctetString packageName = { sizeof(ntlm), ntlm };
|
||||
|
||||
/* packageName [0] OCTET STRING */
|
||||
if (!WinPrAsn1EncContextualOctetString(enc, 0, &packageName))
|
||||
return FALSE;
|
||||
|
||||
/* credBuffer [1] OCTET STRING */
|
||||
wStream* s = Stream_New(NULL, 300);
|
||||
if (!s)
|
||||
goto out;
|
||||
|
||||
Stream_Write_UINT32(s, pntlm->Version); /* Version */
|
||||
Stream_Write_UINT32(s, pntlm->Flags); /* Flags */
|
||||
|
||||
Stream_Write(s, pntlm->CredentialKey.Data, MSV1_0_CREDENTIAL_KEY_LENGTH);
|
||||
Stream_Write_UINT32(s, pntlm->CredentialKeyType);
|
||||
Stream_Write_UINT32(s, pntlm->EncryptedCredsSize);
|
||||
Stream_Write(s, pntlm->EncryptedCreds, pntlm->EncryptedCredsSize);
|
||||
Stream_Zero(s, 6 + 16 * 4 + 14);
|
||||
|
||||
WinPrAsn1_OctetString credBuffer = { Stream_GetPosition(s), Stream_Buffer(s) };
|
||||
ret = WinPrAsn1EncContextualOctetString(enc, 1, &credBuffer) != 0;
|
||||
|
||||
out:
|
||||
Stream_Free(s, TRUE);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode TSCredentials structure.
|
||||
* @param nla A pointer to the NLA to use
|
||||
@@ -1665,13 +1740,26 @@ static BOOL nla_encode_ts_credentials(rdpNla* nla)
|
||||
if (!nla_write_TSRemoteGuardKerbCred(nla, enc) || !WinPrAsn1EncEndContainer(enc))
|
||||
goto out;
|
||||
|
||||
/* supplementalCreds [1] SEQUENCE OF TSRemoteGuardPackageCred OPTIONAL,
|
||||
*
|
||||
* no NTLM supplemental creds for now
|
||||
*
|
||||
*/
|
||||
if (!WinPrAsn1EncContextualSeqContainer(enc, 1) || !WinPrAsn1EncEndContainer(enc))
|
||||
goto out;
|
||||
/* TODO: compute the NTLM supplemental creds */
|
||||
MSV1_0_REMOTE_SUPPLEMENTAL_CREDENTIAL* ntlm = NULL;
|
||||
if (ntlm)
|
||||
{
|
||||
/* supplementalCreds [1] SEQUENCE OF TSRemoteGuardPackageCred OPTIONAL */
|
||||
if (!WinPrAsn1EncContextualSeqContainer(enc, 1))
|
||||
goto out;
|
||||
|
||||
if (!WinPrAsn1EncSeqContainer(enc)) /* start NTLM */
|
||||
goto out;
|
||||
|
||||
if (!nla_write_TSRemoteGuardNtlmCred(nla, enc, ntlm))
|
||||
goto out;
|
||||
|
||||
if (!WinPrAsn1EncEndContainer(enc)) /* end NTLM */
|
||||
goto out;
|
||||
|
||||
if (!WinPrAsn1EncEndContainer(enc)) /* supplementalCreds */
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* End TSRemoteGuardCreds */
|
||||
if (!WinPrAsn1EncEndContainer(enc))
|
||||
|
||||
@@ -70,6 +70,37 @@ typedef struct
|
||||
|
||||
#define MSV1_0_CRED_VERSION_REMOTE 0xffff0002
|
||||
|
||||
typedef enum _MSV1_0_CREDENTIAL_KEY_TYPE
|
||||
{
|
||||
InvalidCredKey,
|
||||
DeprecatedIUMCredKey,
|
||||
DomainUserCredKey,
|
||||
LocalUserCredKey,
|
||||
ExternallySuppliedCredKey
|
||||
} MSV1_0_CREDENTIAL_KEY_TYPE;
|
||||
|
||||
#define MSV1_0_CREDENTIAL_KEY_LENGTH 20
|
||||
#define MSV1_0_CRED_LM_PRESENT 0x1
|
||||
#define MSV1_0_CRED_NT_PRESENT 0x2
|
||||
#define MSV1_0_CRED_REMOVED 0x4
|
||||
#define MSV1_0_CRED_CREDKEY_PRESENT 0x8
|
||||
#define MSV1_0_CRED_SHA_PRESENT 0x10
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UCHAR Data[MSV1_0_CREDENTIAL_KEY_LENGTH];
|
||||
} MSV1_0_CREDENTIAL_KEY, *PMSV1_0_CREDENTIAL_KEY;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ULONG Version;
|
||||
ULONG Flags;
|
||||
MSV1_0_CREDENTIAL_KEY CredentialKey;
|
||||
MSV1_0_CREDENTIAL_KEY_TYPE CredentialKeyType;
|
||||
ULONG EncryptedCredsSize;
|
||||
UCHAR EncryptedCreds[1];
|
||||
} MSV1_0_REMOTE_SUPPLEMENTAL_CREDENTIAL, *PMSV1_0_REMOTE_SUPPLEMENTAL_CREDENTIAL;
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#ifndef KERB_LOGON_FLAG_REDIRECTED
|
||||
|
||||
Reference in New Issue
Block a user