mirror of https://github.com/FreeRDP/FreeRDP
work on Proprietary Certificate
This commit is contained in:
parent
bc1e264eb5
commit
afc9ac89ae
|
@ -227,15 +227,88 @@ void certificate_free_x509_certificate_chain(rdpX509CertChain* x509_cert_chain)
|
|||
xfree(x509_cert_chain);
|
||||
}
|
||||
|
||||
static boolean certificate_process_server_public_key(rdpCertificate* certificate, STREAM* s, uint32 length)
|
||||
{
|
||||
uint8 magic[4];
|
||||
uint32 keylen;
|
||||
uint32 bitlen;
|
||||
uint32 datalen;
|
||||
uint32 modlen;
|
||||
|
||||
memcpy(magic, s->p, 4);
|
||||
if (memcmp(magic, "RSA1", 4) != 0)
|
||||
{
|
||||
printf("gcc_process_server_public_key: magic error\n");
|
||||
return False;
|
||||
}
|
||||
stream_seek(s, 4);
|
||||
stream_read_uint32(s, keylen);
|
||||
stream_read_uint32(s, bitlen);
|
||||
stream_read_uint32(s, datalen);
|
||||
memcpy(certificate->cert_info.exponent, s->p, 4);
|
||||
stream_seek(s, 4);
|
||||
modlen = keylen - 8;
|
||||
freerdp_blob_alloc(&(certificate->cert_info.modulus), modlen);
|
||||
memcpy(certificate->cert_info.modulus.data, s->p, modlen);
|
||||
stream_seek(s, keylen);
|
||||
return True;
|
||||
}
|
||||
|
||||
static boolean certificate_process_server_public_signature(rdpCertificate* certificate, STREAM* s, uint32 length)
|
||||
{
|
||||
stream_seek(s, length);
|
||||
return True;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a Server Proprietary Certificate.\n
|
||||
* @param certificate certificate module
|
||||
* @param s stream
|
||||
*/
|
||||
|
||||
void certificate_read_server_proprietary_certificate(rdpCertificate* certificate, STREAM* s)
|
||||
boolean certificate_read_server_proprietary_certificate(rdpCertificate* certificate, STREAM* s)
|
||||
{
|
||||
uint32 dwSigAlgId;
|
||||
uint32 dwKeyAlgId;
|
||||
uint32 wPublicKeyBlobType;
|
||||
uint32 wPublicKeyBlobLen;
|
||||
uint32 wSignatureBlobType;
|
||||
uint32 wSignatureBlobLen;
|
||||
|
||||
printf("Server Proprietary Certificate\n");
|
||||
|
||||
stream_read_uint32(s, dwSigAlgId);
|
||||
stream_read_uint32(s, dwKeyAlgId);
|
||||
if (!(dwSigAlgId == 1 && dwKeyAlgId == 1))
|
||||
{
|
||||
printf("certificate_read_server_proprietary_certificate: parse error 1\n");
|
||||
return False;
|
||||
}
|
||||
stream_read_uint16(s, wPublicKeyBlobType);
|
||||
if (wPublicKeyBlobType != BB_RSA_KEY_BLOB)
|
||||
{
|
||||
printf("certificate_read_server_proprietary_certificate: parse error 2\n");
|
||||
return False;
|
||||
}
|
||||
stream_read_uint16(s, wPublicKeyBlobLen);
|
||||
if (!certificate_process_server_public_key(certificate, s, wPublicKeyBlobLen))
|
||||
{
|
||||
printf("certificate_read_server_proprietary_certificate: parse error 3\n");
|
||||
return False;
|
||||
}
|
||||
stream_read_uint16(s, wSignatureBlobType);
|
||||
if (wSignatureBlobType != BB_RSA_SIGNATURE_BLOB)
|
||||
{
|
||||
printf("certificate_read_server_proprietary_certificate: parse error 4\n");
|
||||
return False;
|
||||
}
|
||||
stream_read_uint16(s, wSignatureBlobLen);
|
||||
if (!certificate_process_server_public_signature(certificate, s, wSignatureBlobLen))
|
||||
{
|
||||
printf("certificate_read_server_proprietary_certificate: parse error 5\n");
|
||||
return False;
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -244,7 +317,7 @@ void certificate_read_server_proprietary_certificate(rdpCertificate* certificate
|
|||
* @param s stream
|
||||
*/
|
||||
|
||||
void certificate_read_server_x509_certificate_chain(rdpCertificate* certificate, STREAM* s)
|
||||
boolean certificate_read_server_x509_certificate_chain(rdpCertificate* certificate, STREAM* s)
|
||||
{
|
||||
int i;
|
||||
uint32 certLength;
|
||||
|
@ -280,6 +353,7 @@ void certificate_read_server_x509_certificate_chain(rdpCertificate* certificate,
|
|||
DEBUG_CERTIFICATE("modulus length:%d", certificate->cert_info.modulus.length);
|
||||
}
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -289,7 +363,7 @@ void certificate_read_server_x509_certificate_chain(rdpCertificate* certificate,
|
|||
* @param length certificate length
|
||||
*/
|
||||
|
||||
void certificate_read_server_certificate(rdpCertificate* certificate, uint8* server_cert, int length)
|
||||
boolean certificate_read_server_certificate(rdpCertificate* certificate, uint8* server_cert, int length)
|
||||
{
|
||||
STREAM* s;
|
||||
uint32 dwVersion;
|
||||
|
@ -300,7 +374,7 @@ void certificate_read_server_certificate(rdpCertificate* certificate, uint8* ser
|
|||
if (length < 1)
|
||||
{
|
||||
printf("null server certificate\n");
|
||||
return;
|
||||
return False;
|
||||
}
|
||||
|
||||
stream_read_uint32(s, dwVersion); /* dwVersion (4 bytes) */
|
||||
|
@ -319,6 +393,9 @@ void certificate_read_server_certificate(rdpCertificate* certificate, uint8* ser
|
|||
printf("invalid certificate chain version:%d\n", dwVersion & CERT_CHAIN_VERSION_MASK);
|
||||
break;
|
||||
}
|
||||
|
||||
xfree(s);
|
||||
return True;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -327,7 +404,7 @@ void certificate_read_server_certificate(rdpCertificate* certificate, uint8* ser
|
|||
* @return new certificate module
|
||||
*/
|
||||
|
||||
rdpCertificate* certificate_new(rdpRdp* rdp)
|
||||
rdpCertificate* certificate_new(void)
|
||||
{
|
||||
rdpCertificate* certificate;
|
||||
|
||||
|
@ -335,7 +412,6 @@ rdpCertificate* certificate_new(rdpRdp* rdp)
|
|||
|
||||
if (certificate != NULL)
|
||||
{
|
||||
certificate->rdp = rdp;
|
||||
certificate->x509_cert_chain = NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,9 @@ typedef struct rdp_certificate rdpCertificate;
|
|||
#define CERT_PERMANENTLY_ISSUED 0x00000000
|
||||
#define CERT_TEMPORARILY_ISSUED 0x80000000
|
||||
|
||||
#define BB_RSA_KEY_BLOB 6
|
||||
#define BB_RSA_SIGNATURE_BLOB 8
|
||||
|
||||
struct rdp_CertBlob
|
||||
{
|
||||
uint32 length;
|
||||
|
@ -60,7 +63,6 @@ typedef struct rdp_CertInfo rdpCertInfo;
|
|||
|
||||
struct rdp_certificate
|
||||
{
|
||||
struct rdp_rdp* rdp;
|
||||
rdpCertInfo cert_info;
|
||||
rdpX509CertChain* x509_cert_chain;
|
||||
};
|
||||
|
@ -70,11 +72,11 @@ void certificate_read_x509_certificate(rdpCertBlob* cert, rdpCertInfo* info);
|
|||
rdpX509CertChain* certificate_new_x509_certificate_chain(uint32 count);
|
||||
void certificate_free_x509_certificate_chain(rdpX509CertChain* x509_cert_chain);
|
||||
|
||||
void certificate_read_server_proprietary_certificate(rdpCertificate* certificate, STREAM* s);
|
||||
void certificate_read_server_x509_certificate_chain(rdpCertificate* certificate, STREAM* s);
|
||||
void certificate_read_server_certificate(rdpCertificate* certificate, uint8* server_cert, int length);
|
||||
boolean certificate_read_server_proprietary_certificate(rdpCertificate* certificate, STREAM* s);
|
||||
boolean certificate_read_server_x509_certificate_chain(rdpCertificate* certificate, STREAM* s);
|
||||
boolean certificate_read_server_certificate(rdpCertificate* certificate, uint8* server_cert, int length);
|
||||
|
||||
rdpCertificate* certificate_new(rdpRdp* rdp);
|
||||
rdpCertificate* certificate_new(void);
|
||||
void certificate_free(rdpCertificate* certificate);
|
||||
|
||||
#ifdef WITH_DEBUG_CERTIFICATE
|
||||
|
|
|
@ -104,11 +104,38 @@ boolean rdp_client_connect(rdpRdp* rdp)
|
|||
return True;
|
||||
}
|
||||
|
||||
static boolean rdp_establish_keys(rdpRdp* rdp)
|
||||
{
|
||||
uint8 client_random[32];
|
||||
uint8 crypt_client_random[256];
|
||||
uint32 key_len;
|
||||
uint8* mod;
|
||||
uint8* exp;
|
||||
|
||||
printf("rdp_establish_keys:\n");
|
||||
if (rdp->settings->encryption == False)
|
||||
{
|
||||
/* no RDP encryption */
|
||||
return True;
|
||||
}
|
||||
|
||||
memset(client_random, 0x5e, 32); /* TODO: get real random */
|
||||
crypto_nonce(client_random, 32);
|
||||
key_len = rdp->settings->server_cert->cert_info.modulus.length;
|
||||
mod = rdp->settings->server_cert->cert_info.modulus.data;
|
||||
exp = rdp->settings->server_cert->cert_info.exponent;
|
||||
crypto_rsa_encrypt(client_random, 32, key_len, mod, exp, crypt_client_random);
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
boolean rdp_client_connect_mcs_connect_response(rdpRdp* rdp, STREAM* s)
|
||||
{
|
||||
if (!mcs_recv_connect_response(rdp->mcs, s))
|
||||
{
|
||||
printf("rdp_client_connect_mcs_connect_response: mcs_recv_connect_response failed\n");
|
||||
return False;
|
||||
|
||||
}
|
||||
if (!mcs_send_erect_domain_request(rdp->mcs))
|
||||
return False;
|
||||
if (!mcs_send_attach_user_request(rdp->mcs))
|
||||
|
@ -188,6 +215,8 @@ boolean rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, STREAM* s)
|
|||
|
||||
if (rdp->mcs->user_channel_joined && rdp->mcs->global_channel_joined && all_joined)
|
||||
{
|
||||
if (!rdp_establish_keys(rdp))
|
||||
return False;
|
||||
if (!rdp_send_client_info(rdp))
|
||||
return False;
|
||||
rdp->state = CONNECTION_STATE_LICENSE;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
#include "gcc.h"
|
||||
#include "certificate.h"
|
||||
|
||||
/**
|
||||
* T.124 GCC is defined in:
|
||||
|
@ -250,12 +251,16 @@ boolean gcc_read_conference_create_response(STREAM* s, rdpSettings* settings)
|
|||
per_read_choice(s, &choice);
|
||||
|
||||
/* h221NonStandard */
|
||||
per_read_octet_string(s, h221_sc_key, 4, 4); /* h221NonStandard, server-to-client H.221 key, "McDn" */
|
||||
if (!per_read_octet_string(s, h221_sc_key, 4, 4)) /* h221NonStandard, server-to-client H.221 key, "McDn" */
|
||||
return False;
|
||||
|
||||
/* userData (OCTET_STRING) */
|
||||
per_read_length(s, &length);
|
||||
if (!gcc_read_server_data_blocks(s, settings, length))
|
||||
{
|
||||
printf("gcc_read_conference_create_response: gcc_read_server_data_blocks failed\n");
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
@ -357,34 +362,49 @@ boolean gcc_read_server_data_blocks(STREAM* s, rdpSettings *settings, int length
|
|||
uint16 type;
|
||||
uint16 offset = 0;
|
||||
uint16 blockLength;
|
||||
uint8* holdp;
|
||||
|
||||
while (offset < length)
|
||||
{
|
||||
holdp = s->p;
|
||||
|
||||
if (!gcc_read_user_data_header(s, &type, &blockLength))
|
||||
{
|
||||
printf("gcc_read_server_data_blocks: gcc_read_user_data_header failed\n");
|
||||
return False;
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case SC_CORE:
|
||||
if (!gcc_read_server_core_data(s, settings))
|
||||
{
|
||||
printf("gcc_read_server_data_blocks: gcc_read_server_core_data failed\n");
|
||||
return False;
|
||||
}
|
||||
break;
|
||||
|
||||
case SC_SECURITY:
|
||||
if (!gcc_read_server_security_data(s, settings))
|
||||
{
|
||||
printf("gcc_read_server_data_blocks: gcc_read_server_security_data failed\n");
|
||||
return False;
|
||||
}
|
||||
break;
|
||||
|
||||
case SC_NET:
|
||||
if (!gcc_read_server_network_data(s, settings))
|
||||
{
|
||||
printf("gcc_read_server_data_blocks: gcc_read_server_network_data failed\n");
|
||||
return False;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
offset += blockLength;
|
||||
s->p = holdp + blockLength;
|
||||
}
|
||||
|
||||
return True;
|
||||
|
@ -729,7 +749,11 @@ void gcc_write_client_security_data(STREAM* s, rdpSettings *settings)
|
|||
{
|
||||
gcc_write_user_data_header(s, CS_SECURITY, 12);
|
||||
|
||||
if (settings->encryption > 0)
|
||||
printf("settings->encryption %d\n", settings->encryption);
|
||||
printf("settings->encryption_method %d\n", settings->encryption_method);
|
||||
printf("settings->encryption_level %d\n", settings->encryption_level);
|
||||
|
||||
if (settings->encryption)
|
||||
{
|
||||
stream_write_uint32(s, settings->encryption_method); /* encryptionMethods */
|
||||
stream_write_uint32(s, 0); /* extEncryptionMethods */
|
||||
|
@ -744,23 +768,30 @@ void gcc_write_client_security_data(STREAM* s, rdpSettings *settings)
|
|||
|
||||
boolean gcc_read_server_security_data(STREAM* s, rdpSettings *settings)
|
||||
{
|
||||
uint32 encryptionMethod;
|
||||
uint32 encryptionLevel;
|
||||
uint32 serverRandomLen;
|
||||
uint32 serverCertLen;
|
||||
uint8* data;
|
||||
uint32 len;
|
||||
|
||||
stream_read_uint32(s, encryptionMethod); /* encryptionMethod */
|
||||
stream_read_uint32(s, encryptionLevel); /* encryptionLevel */
|
||||
stream_read_uint32(s, settings->encryption_method); /* encryptionMethod */
|
||||
stream_read_uint32(s, settings->encryption_level); /* encryptionLevel */
|
||||
|
||||
if (encryptionMethod == 0 && encryptionLevel == 0)
|
||||
printf("gcc_read_server_security_data: encryption_method %d encryption_level %d\n", settings->encryption_method, settings->encryption_level);
|
||||
|
||||
if (settings->encryption_method == 0 && settings->encryption_level == 0)
|
||||
{
|
||||
/* serverRandom and serverRandom must not be present */
|
||||
settings->encryption = False;
|
||||
settings->encryption_method = ENCRYPTION_METHOD_NONE;
|
||||
settings->encryption_level = ENCRYPTION_LEVEL_NONE;
|
||||
return True;
|
||||
}
|
||||
|
||||
stream_read_uint32(s, serverRandomLen); /* serverRandomLen */
|
||||
stream_read_uint32(s, serverCertLen); /* serverCertLen */
|
||||
|
||||
printf("gcc_read_server_security_data: serverRandomLen %d serverCertLen %d\n", serverRandomLen, serverCertLen);
|
||||
|
||||
if (serverRandomLen > 0)
|
||||
{
|
||||
/* serverRandom */
|
||||
|
@ -768,6 +799,10 @@ boolean gcc_read_server_security_data(STREAM* s, rdpSettings *settings)
|
|||
memcpy(settings->server_random.data, s->p, serverRandomLen);
|
||||
stream_seek(s, serverRandomLen);
|
||||
}
|
||||
else
|
||||
{
|
||||
return False;
|
||||
}
|
||||
|
||||
if (serverCertLen > 0)
|
||||
{
|
||||
|
@ -775,6 +810,18 @@ boolean gcc_read_server_security_data(STREAM* s, rdpSettings *settings)
|
|||
freerdp_blob_alloc(&settings->server_certificate, serverCertLen);
|
||||
memcpy(settings->server_certificate.data, s->p, serverCertLen);
|
||||
stream_seek(s, serverCertLen);
|
||||
certificate_free(settings->server_cert);
|
||||
settings->server_cert = certificate_new();
|
||||
data = settings->server_certificate.data;
|
||||
len = settings->server_certificate.length;
|
||||
if (!certificate_read_server_certificate(settings->server_cert, data, len))
|
||||
{
|
||||
return False;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
|
|
|
@ -864,7 +864,8 @@ rdpLicense* license_new(rdpRdp* rdp)
|
|||
{
|
||||
license->rdp = rdp;
|
||||
license->state = LICENSE_STATE_AWAIT;
|
||||
license->certificate = certificate_new(rdp);
|
||||
//license->certificate = certificate_new(rdp);
|
||||
license->certificate = certificate_new();
|
||||
license->product_info = license_new_product_info();
|
||||
license->error_info = license_new_binary_blob(BB_ERROR_BLOB);
|
||||
license->key_exchange_list = license_new_binary_blob(BB_KEY_EXCHG_ALG_BLOB);
|
||||
|
|
|
@ -517,7 +517,10 @@ boolean mcs_recv_connect_response(rdpMcs* mcs, STREAM* s)
|
|||
ber_read_octet_string(s, &length);
|
||||
|
||||
if (!gcc_read_conference_create_response(s, mcs->transport->settings))
|
||||
{
|
||||
printf("mcs_recv_connect_response: gcc_read_conference_create_response failed\n");
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
|
|
@ -397,6 +397,20 @@ void rdp_recv_data_pdu(rdpRdp* rdp, STREAM* s)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt an RDP packet.\n
|
||||
* @param rdp RDP module
|
||||
* @param s stream
|
||||
* @param length int
|
||||
*/
|
||||
|
||||
static boolean rdp_decrypt(rdpRdp* rdp, STREAM* s, int length)
|
||||
{
|
||||
printf("rdp_decrypt:\n");
|
||||
stream_seek(s, 8); /* signature */
|
||||
return True;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process an RDP packet.\n
|
||||
* @param rdp RDP module
|
||||
|
@ -409,6 +423,7 @@ static boolean rdp_recv_tpkt_pdu(rdpRdp* rdp, STREAM* s)
|
|||
uint16 pduType;
|
||||
uint16 pduLength;
|
||||
uint16 channelId;
|
||||
uint32 securityHeader;
|
||||
|
||||
if (!rdp_read_header(rdp, s, &length, &channelId))
|
||||
{
|
||||
|
@ -416,6 +431,24 @@ static boolean rdp_recv_tpkt_pdu(rdpRdp* rdp, STREAM* s)
|
|||
return False;
|
||||
}
|
||||
|
||||
if (rdp->settings->encryption)
|
||||
{
|
||||
stream_read_uint32(s, securityHeader);
|
||||
if (securityHeader & SEC_SECURE_CHECKSUM)
|
||||
{
|
||||
printf("Error: TODO\n");
|
||||
return False;
|
||||
}
|
||||
if (securityHeader & SEC_ENCRYPT)
|
||||
{
|
||||
if (!rdp_decrypt(rdp, s, length))
|
||||
{
|
||||
printf("rdp_decrypt failed\n");
|
||||
return False;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (channelId != MCS_GLOBAL_CHANNEL_ID)
|
||||
{
|
||||
vchan_process(rdp->vchan, s, channelId);
|
||||
|
@ -492,6 +525,7 @@ static int rdp_recv_callback(rdpTransport* transport, STREAM* s, void* extra)
|
|||
{
|
||||
rdpRdp* rdp = (rdpRdp*) extra;
|
||||
|
||||
printf("state %d\n", rdp->state);
|
||||
switch (rdp->state)
|
||||
{
|
||||
case CONNECTION_STATE_NEGO:
|
||||
|
|
|
@ -167,6 +167,8 @@ void settings_free(rdpSettings* settings)
|
|||
xfree(settings->client_dir);
|
||||
xfree(settings->cert_file);
|
||||
xfree(settings->privatekey_file);
|
||||
freerdp_blob_free(&(settings->server_certificate));
|
||||
certificate_free(settings->server_cert);
|
||||
xfree(settings);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -165,6 +165,11 @@ int tcp_read(rdpTcp* tcp, uint8* data, int length)
|
|||
perror("recv");
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("tcp_read: length %d\n", status);
|
||||
freerdp_hexdump(data, status);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -175,6 +180,9 @@ int tcp_write(rdpTcp* tcp, uint8* data, int length)
|
|||
|
||||
status = send(tcp->sockfd, data, length, MSG_NOSIGNAL);
|
||||
|
||||
printf("tcp_write: length %d\n", status);
|
||||
freerdp_hexdump(data, status);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK)
|
||||
|
|
|
@ -283,6 +283,9 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv,
|
|||
settings->rdp_security = True;
|
||||
settings->tls_security = False;
|
||||
settings->nla_security = False;
|
||||
settings->encryption = True;
|
||||
settings->encryption_method = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_128BIT;
|
||||
settings->encryption_level = ENCRYPTION_LEVEL_HIGH;
|
||||
}
|
||||
else if (strncmp("tls", argv[index], 1) == 0) /* TLS */
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue