mirror of
https://github.com/FreeRDP/FreeRDP.git
synced 2024-11-27 20:04:11 +08:00
libwinpr-sspi: parse CredSSP plaintext credentials
This commit is contained in:
parent
2ff8a103d6
commit
f897159058
@ -70,8 +70,8 @@ FREERDP_API int ber_write_sequence_tag(STREAM* s, int length);
|
||||
FREERDP_API int ber_skip_sequence(int length);
|
||||
FREERDP_API int ber_skip_sequence_tag(int length);
|
||||
FREERDP_API boolean ber_read_bit_string(STREAM* s, int* length, uint8* padding);
|
||||
FREERDP_API boolean ber_read_octet_string(STREAM* s, int* length);
|
||||
FREERDP_API void ber_write_octet_string(STREAM* s, const uint8* oct_str, int length);
|
||||
FREERDP_API boolean ber_read_octet_string_tag(STREAM* s, int* length);
|
||||
FREERDP_API int ber_write_octet_string_tag(STREAM* s, int length);
|
||||
FREERDP_API int ber_skip_octet_string(int length);
|
||||
FREERDP_API boolean ber_read_boolean(STREAM* s, boolean* value);
|
||||
|
@ -331,12 +331,12 @@ boolean mcs_recv_connect_initial(rdpMcs* mcs, STREAM* s)
|
||||
return false;
|
||||
|
||||
/* callingDomainSelector (OCTET_STRING) */
|
||||
if (!ber_read_octet_string(s, &length))
|
||||
if (!ber_read_octet_string_tag(s, &length))
|
||||
return false;
|
||||
stream_seek(s, length);
|
||||
|
||||
/* calledDomainSelector (OCTET_STRING) */
|
||||
if (!ber_read_octet_string(s, &length))
|
||||
if (!ber_read_octet_string_tag(s, &length))
|
||||
return false;
|
||||
stream_seek(s, length);
|
||||
|
||||
@ -353,7 +353,7 @@ boolean mcs_recv_connect_initial(rdpMcs* mcs, STREAM* s)
|
||||
/* maximumParameters (DomainParameters) */
|
||||
mcs_read_domain_parameters(s, &mcs->maximumParameters);
|
||||
|
||||
if (!ber_read_octet_string(s, &length))
|
||||
if (!ber_read_octet_string_tag(s, &length))
|
||||
return false;
|
||||
|
||||
if (!gcc_read_conference_create_request(s, mcs->transport->settings))
|
||||
@ -499,7 +499,7 @@ boolean mcs_recv_connect_response(rdpMcs* mcs, STREAM* s)
|
||||
if (!mcs_read_domain_parameters(s, &(mcs->domainParameters)))
|
||||
return false;
|
||||
|
||||
ber_read_octet_string(s, &length);
|
||||
ber_read_octet_string_tag(s, &length);
|
||||
|
||||
if (!gcc_read_conference_create_response(s, mcs->transport->settings))
|
||||
{
|
||||
|
@ -267,14 +267,6 @@ boolean ber_read_bit_string(STREAM* s, int* length, uint8* padding)
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean ber_read_octet_string(STREAM* s, int* length)
|
||||
{
|
||||
ber_read_universal_tag(s, BER_TAG_OCTET_STRING, false);
|
||||
ber_read_length(s, length);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a BER OCTET_STRING
|
||||
* @param s stream
|
||||
@ -289,6 +281,13 @@ void ber_write_octet_string(STREAM* s, const uint8* oct_str, int length)
|
||||
stream_write(s, oct_str, length);
|
||||
}
|
||||
|
||||
boolean ber_read_octet_string_tag(STREAM* s, int* length)
|
||||
{
|
||||
ber_read_universal_tag(s, BER_TAG_OCTET_STRING, false);
|
||||
ber_read_length(s, length);
|
||||
return true;
|
||||
}
|
||||
|
||||
int ber_write_octet_string_tag(STREAM* s, int length)
|
||||
{
|
||||
ber_write_universal_tag(s, BER_TAG_OCTET_STRING, false);
|
||||
|
@ -712,6 +712,173 @@ SECURITY_STATUS credssp_verify_public_key_echo(rdpCredssp* credssp)
|
||||
return SEC_E_OK;
|
||||
}
|
||||
|
||||
int credssp_skip_ts_password_creds(rdpCredssp* credssp)
|
||||
{
|
||||
int length;
|
||||
int ts_password_creds_length = 0;
|
||||
|
||||
length = ber_skip_octet_string(credssp->identity.DomainLength);
|
||||
length += ber_skip_contextual_tag(length);
|
||||
ts_password_creds_length += length;
|
||||
|
||||
length = ber_skip_octet_string(credssp->identity.UserLength);
|
||||
length += ber_skip_contextual_tag(length);
|
||||
ts_password_creds_length += length;
|
||||
|
||||
length = ber_skip_octet_string(credssp->identity.PasswordLength);
|
||||
length += ber_skip_contextual_tag(length);
|
||||
ts_password_creds_length += length;
|
||||
|
||||
length = ber_skip_sequence(ts_password_creds_length);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
void credssp_read_ts_password_creds(rdpCredssp* credssp, STREAM* s)
|
||||
{
|
||||
int length;
|
||||
|
||||
/* TSPasswordCreds (SEQUENCE) */
|
||||
ber_read_sequence_tag(s, &length);
|
||||
|
||||
/* [0] domainName (OCTET STRING) */
|
||||
ber_read_contextual_tag(s, 0, &length, true);
|
||||
ber_read_octet_string_tag(s, &length);
|
||||
credssp->identity.DomainLength = (uint32) length;
|
||||
credssp->identity.Domain = (uint16*) malloc(length);
|
||||
CopyMemory(credssp->identity.Domain, s->p, credssp->identity.DomainLength);
|
||||
stream_seek(s, credssp->identity.DomainLength);
|
||||
|
||||
/* [1] userName (OCTET STRING) */
|
||||
ber_read_contextual_tag(s, 1, &length, true);
|
||||
ber_read_octet_string_tag(s, &length);
|
||||
credssp->identity.UserLength = (uint32) length;
|
||||
credssp->identity.User = (uint16*) malloc(length);
|
||||
CopyMemory(credssp->identity.User, s->p, credssp->identity.UserLength);
|
||||
stream_seek(s, credssp->identity.UserLength);
|
||||
|
||||
/* [2] password (OCTET STRING) */
|
||||
ber_read_contextual_tag(s, 2, &length, true);
|
||||
ber_read_octet_string_tag(s, &length);
|
||||
credssp->identity.PasswordLength = (uint32) length;
|
||||
credssp->identity.Password = (uint16*) malloc(length);
|
||||
CopyMemory(credssp->identity.Password, s->p, credssp->identity.PasswordLength);
|
||||
stream_seek(s, credssp->identity.PasswordLength);
|
||||
}
|
||||
|
||||
void credssp_write_ts_password_creds(rdpCredssp* credssp, STREAM* s)
|
||||
{
|
||||
int length;
|
||||
|
||||
length = credssp_skip_ts_password_creds(credssp);
|
||||
|
||||
/* TSPasswordCreds (SEQUENCE) */
|
||||
length = ber_get_content_length(length);
|
||||
ber_write_sequence_tag(s, length);
|
||||
|
||||
/* [0] domainName (OCTET STRING) */
|
||||
ber_write_contextual_tag(s, 0, credssp->identity.DomainLength + 2, true);
|
||||
ber_write_octet_string(s, (BYTE*) credssp->identity.Domain, credssp->identity.DomainLength);
|
||||
|
||||
/* [1] userName (OCTET STRING) */
|
||||
ber_write_contextual_tag(s, 1, credssp->identity.UserLength + 2, true);
|
||||
ber_write_octet_string(s, (BYTE*) credssp->identity.User, credssp->identity.UserLength);
|
||||
|
||||
/* [2] password (OCTET STRING) */
|
||||
ber_write_contextual_tag(s, 2, credssp->identity.PasswordLength + 2, true);
|
||||
ber_write_octet_string(s, (BYTE*) credssp->identity.Password, credssp->identity.PasswordLength);
|
||||
}
|
||||
|
||||
int credssp_skip_ts_credentials(rdpCredssp* credssp)
|
||||
{
|
||||
int length;
|
||||
int ts_password_creds_length;
|
||||
int ts_credentials_length = 0;
|
||||
|
||||
length = ber_skip_integer(0);
|
||||
length += ber_skip_contextual_tag(length);
|
||||
ts_credentials_length += length;
|
||||
|
||||
ts_password_creds_length = credssp_skip_ts_password_creds(credssp);
|
||||
length = ber_skip_octet_string(ts_password_creds_length);
|
||||
length += ber_skip_contextual_tag(length);
|
||||
ts_credentials_length += length;
|
||||
|
||||
length = ber_skip_sequence(ts_credentials_length);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
void credssp_read_ts_credentials(rdpCredssp* credssp, PSecBuffer ts_credentials)
|
||||
{
|
||||
STREAM* s;
|
||||
int length;
|
||||
int ts_password_creds_length;
|
||||
|
||||
s = stream_new(0);
|
||||
stream_attach(s, ts_credentials->pvBuffer, ts_credentials->cbBuffer);
|
||||
|
||||
/* TSCredentials (SEQUENCE) */
|
||||
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);
|
||||
|
||||
credssp_read_ts_password_creds(credssp, s);
|
||||
|
||||
stream_detach(s);
|
||||
stream_free(s);
|
||||
}
|
||||
|
||||
void credssp_write_ts_credentials(rdpCredssp* credssp, STREAM* s)
|
||||
{
|
||||
int length;
|
||||
int ts_password_creds_length;
|
||||
|
||||
length = credssp_skip_ts_credentials(credssp);
|
||||
ts_password_creds_length = credssp_skip_ts_password_creds(credssp);
|
||||
|
||||
/* TSCredentials (SEQUENCE) */
|
||||
length = ber_get_content_length(length);
|
||||
length -= ber_write_sequence_tag(s, length);
|
||||
|
||||
/* [0] credType (INTEGER) */
|
||||
length -= ber_write_contextual_tag(s, 0, 3, true);
|
||||
length -= ber_write_integer(s, 1);
|
||||
|
||||
/* [1] credentials (OCTET STRING) */
|
||||
length -= 1;
|
||||
length -= ber_write_contextual_tag(s, 1, length, true);
|
||||
length -= ber_write_octet_string_tag(s, ts_password_creds_length);
|
||||
|
||||
credssp_write_ts_password_creds(credssp, s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode TSCredentials structure.
|
||||
* @param credssp
|
||||
*/
|
||||
|
||||
void credssp_encode_ts_credentials(rdpCredssp* credssp)
|
||||
{
|
||||
STREAM* s;
|
||||
int length;
|
||||
|
||||
s = stream_new(0);
|
||||
length = credssp_skip_ts_credentials(credssp);
|
||||
sspi_SecBufferAlloc(&credssp->ts_credentials, length);
|
||||
stream_attach(s, credssp->ts_credentials.pvBuffer, length);
|
||||
|
||||
credssp_write_ts_credentials(credssp, s);
|
||||
stream_detach(s);
|
||||
stream_free(s);
|
||||
}
|
||||
|
||||
SECURITY_STATUS credssp_encrypt_ts_credentials(rdpCredssp* credssp)
|
||||
{
|
||||
BYTE* p;
|
||||
@ -779,127 +946,17 @@ SECURITY_STATUS credssp_decrypt_ts_credentials(rdpCredssp* credssp)
|
||||
|
||||
status = credssp->table->DecryptMessage(&credssp->context, &Message, 1, 0);
|
||||
|
||||
freerdp_hexdump(Buffers[0].pvBuffer, Buffers[0].cbBuffer);
|
||||
freerdp_hexdump(Buffers[1].pvBuffer, Buffers[1].cbBuffer);
|
||||
|
||||
if (status != SEC_E_OK)
|
||||
return status;
|
||||
|
||||
credssp_read_ts_credentials(credssp, &Buffers[1]);
|
||||
|
||||
free(Buffers[0].pvBuffer);
|
||||
free(Buffers[1].pvBuffer);
|
||||
|
||||
return SEC_E_OK;
|
||||
}
|
||||
|
||||
int credssp_skip_ts_password_creds(rdpCredssp* credssp)
|
||||
{
|
||||
int length;
|
||||
int ts_password_creds_length = 0;
|
||||
|
||||
length = ber_skip_octet_string(credssp->identity.DomainLength);
|
||||
length += ber_skip_contextual_tag(length);
|
||||
ts_password_creds_length += length;
|
||||
|
||||
length = ber_skip_octet_string(credssp->identity.UserLength);
|
||||
length += ber_skip_contextual_tag(length);
|
||||
ts_password_creds_length += length;
|
||||
|
||||
length = ber_skip_octet_string(credssp->identity.PasswordLength);
|
||||
length += ber_skip_contextual_tag(length);
|
||||
ts_password_creds_length += length;
|
||||
|
||||
length = ber_skip_sequence(ts_password_creds_length);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
void credssp_write_ts_password_creds(rdpCredssp* credssp, STREAM* s)
|
||||
{
|
||||
int length;
|
||||
|
||||
length = credssp_skip_ts_password_creds(credssp);
|
||||
|
||||
/* TSPasswordCreds (SEQUENCE) */
|
||||
length = ber_get_content_length(length);
|
||||
ber_write_sequence_tag(s, length);
|
||||
|
||||
/* [0] domainName (OCTET STRING) */
|
||||
ber_write_contextual_tag(s, 0, credssp->identity.DomainLength + 2, true);
|
||||
ber_write_octet_string(s, (uint8*) credssp->identity.Domain, credssp->identity.DomainLength);
|
||||
|
||||
/* [1] userName (OCTET STRING) */
|
||||
ber_write_contextual_tag(s, 1, credssp->identity.UserLength + 2, true);
|
||||
ber_write_octet_string(s, (uint8*) credssp->identity.User, credssp->identity.UserLength);
|
||||
|
||||
/* [2] password (OCTET STRING) */
|
||||
ber_write_contextual_tag(s, 2, credssp->identity.PasswordLength + 2, true);
|
||||
ber_write_octet_string(s, (uint8*) credssp->identity.Password, credssp->identity.PasswordLength);
|
||||
}
|
||||
|
||||
int credssp_skip_ts_credentials(rdpCredssp* credssp)
|
||||
{
|
||||
int length;
|
||||
int ts_password_creds_length;
|
||||
int ts_credentials_length = 0;
|
||||
|
||||
length = ber_skip_integer(0);
|
||||
length += ber_skip_contextual_tag(length);
|
||||
ts_credentials_length += length;
|
||||
|
||||
ts_password_creds_length = credssp_skip_ts_password_creds(credssp);
|
||||
length = ber_skip_octet_string(ts_password_creds_length);
|
||||
length += ber_skip_contextual_tag(length);
|
||||
ts_credentials_length += length;
|
||||
|
||||
length = ber_skip_sequence(ts_credentials_length);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
void credssp_write_ts_credentials(rdpCredssp* credssp, STREAM* s)
|
||||
{
|
||||
int length;
|
||||
int ts_password_creds_length;
|
||||
|
||||
length = credssp_skip_ts_credentials(credssp);
|
||||
ts_password_creds_length = credssp_skip_ts_password_creds(credssp);
|
||||
|
||||
/* TSCredentials (SEQUENCE) */
|
||||
length = ber_get_content_length(length);
|
||||
length -= ber_write_sequence_tag(s, length);
|
||||
|
||||
/* [0] credType (INTEGER) */
|
||||
length -= ber_write_contextual_tag(s, 0, 3, true);
|
||||
length -= ber_write_integer(s, 1);
|
||||
|
||||
/* [1] credentials (OCTET STRING) */
|
||||
length -= 1;
|
||||
length -= ber_write_contextual_tag(s, 1, length, true);
|
||||
length -= ber_write_octet_string_tag(s, ts_password_creds_length);
|
||||
|
||||
credssp_write_ts_password_creds(credssp, s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode TSCredentials structure.
|
||||
* @param credssp
|
||||
*/
|
||||
|
||||
void credssp_encode_ts_credentials(rdpCredssp* credssp)
|
||||
{
|
||||
STREAM* s;
|
||||
int length;
|
||||
|
||||
s = stream_new(0);
|
||||
length = credssp_skip_ts_credentials(credssp);
|
||||
sspi_SecBufferAlloc(&credssp->ts_credentials, length);
|
||||
stream_attach(s, credssp->ts_credentials.pvBuffer, length);
|
||||
|
||||
credssp_write_ts_credentials(credssp, s);
|
||||
stream_detach(s);
|
||||
stream_free(s);
|
||||
}
|
||||
|
||||
int credssp_skip_nego_token(int length)
|
||||
{
|
||||
length = ber_skip_octet_string(length);
|
||||
@ -1031,7 +1088,7 @@ int credssp_recv(rdpCredssp* credssp)
|
||||
ber_read_sequence_tag(s, &length); /* SEQUENCE OF NegoDataItem */
|
||||
ber_read_sequence_tag(s, &length); /* NegoDataItem */
|
||||
ber_read_contextual_tag(s, 0, &length, true); /* [0] negoToken */
|
||||
ber_read_octet_string(s, &length); /* OCTET STRING */
|
||||
ber_read_octet_string_tag(s, &length); /* OCTET STRING */
|
||||
sspi_SecBufferAlloc(&credssp->negoToken, length);
|
||||
stream_read(s, credssp->negoToken.pvBuffer, length);
|
||||
credssp->negoToken.cbBuffer = length;
|
||||
@ -1040,7 +1097,7 @@ int credssp_recv(rdpCredssp* credssp)
|
||||
/* [2] authInfo (OCTET STRING) */
|
||||
if (ber_read_contextual_tag(s, 2, &length, true) != false)
|
||||
{
|
||||
ber_read_octet_string(s, &length); /* OCTET STRING */
|
||||
ber_read_octet_string_tag(s, &length); /* OCTET STRING */
|
||||
sspi_SecBufferAlloc(&credssp->authInfo, length);
|
||||
stream_read(s, credssp->authInfo.pvBuffer, length);
|
||||
credssp->authInfo.cbBuffer = length;
|
||||
@ -1049,7 +1106,7 @@ int credssp_recv(rdpCredssp* credssp)
|
||||
/* [3] pubKeyAuth (OCTET STRING) */
|
||||
if (ber_read_contextual_tag(s, 3, &length, true) != false)
|
||||
{
|
||||
ber_read_octet_string(s, &length); /* OCTET STRING */
|
||||
ber_read_octet_string_tag(s, &length); /* OCTET STRING */
|
||||
sspi_SecBufferAlloc(&credssp->pubKeyAuth, length);
|
||||
stream_read(s, credssp->pubKeyAuth.pvBuffer, length);
|
||||
credssp->pubKeyAuth.cbBuffer = length;
|
||||
|
Loading…
Reference in New Issue
Block a user