Merge pull request #1756 from hardening/malloc_checks
Adds some check to treat OOM problems + RDP security fix
This commit is contained in:
commit
8040c58ff7
@ -166,70 +166,133 @@ RDPDR_DEVICE* freerdp_device_collection_find(rdpSettings* settings, const char*
|
||||
|
||||
RDPDR_DEVICE* freerdp_device_clone(RDPDR_DEVICE* device)
|
||||
{
|
||||
RDPDR_DEVICE* _device = NULL;
|
||||
|
||||
if (device->Type == RDPDR_DTYP_FILESYSTEM)
|
||||
{
|
||||
RDPDR_DRIVE* drive = (RDPDR_DRIVE*) device;
|
||||
RDPDR_DRIVE* _drive = (RDPDR_DRIVE*) malloc(sizeof(RDPDR_DRIVE));
|
||||
if (!_drive)
|
||||
return NULL;
|
||||
|
||||
_drive->Id = drive->Id;
|
||||
_drive->Type = drive->Type;
|
||||
_drive->Name = _strdup(drive->Name);
|
||||
if (!_drive->Name)
|
||||
goto out_fs_name_error;
|
||||
_drive->Path = _strdup(drive->Path);
|
||||
if (!_drive->Path)
|
||||
goto out_fs_path_error;
|
||||
|
||||
_device = (RDPDR_DEVICE*) _drive;
|
||||
return (RDPDR_DEVICE*) _drive;
|
||||
|
||||
out_fs_path_error:
|
||||
free(_drive->Name);
|
||||
out_fs_name_error:
|
||||
free(_drive);
|
||||
return NULL;
|
||||
}
|
||||
else if (device->Type == RDPDR_DTYP_PRINT)
|
||||
|
||||
if (device->Type == RDPDR_DTYP_PRINT)
|
||||
{
|
||||
RDPDR_PRINTER* printer = (RDPDR_PRINTER*) device;
|
||||
RDPDR_PRINTER* _printer = (RDPDR_PRINTER*) malloc(sizeof(RDPDR_PRINTER));
|
||||
if (!_printer)
|
||||
return NULL;
|
||||
|
||||
_printer->Id = printer->Id;
|
||||
_printer->Type = printer->Type;
|
||||
_printer->Name = _strdup(printer->Name);
|
||||
if (!_printer->Name)
|
||||
goto out_print_name_error;
|
||||
_printer->DriverName = _strdup(printer->DriverName);
|
||||
if(!_printer->DriverName)
|
||||
goto out_print_path_error;
|
||||
|
||||
_device = (RDPDR_DEVICE*) _printer;
|
||||
return (RDPDR_DEVICE*) _printer;
|
||||
|
||||
out_print_path_error:
|
||||
free(_printer->Name);
|
||||
out_print_name_error:
|
||||
free(_printer);
|
||||
return NULL;
|
||||
}
|
||||
else if (device->Type == RDPDR_DTYP_SMARTCARD)
|
||||
|
||||
if (device->Type == RDPDR_DTYP_SMARTCARD)
|
||||
{
|
||||
RDPDR_SMARTCARD* smartcard = (RDPDR_SMARTCARD*) device;
|
||||
RDPDR_SMARTCARD* _smartcard = (RDPDR_SMARTCARD*) malloc(sizeof(RDPDR_SMARTCARD));
|
||||
if (!_smartcard)
|
||||
return NULL;
|
||||
|
||||
_smartcard->Id = smartcard->Id;
|
||||
_smartcard->Type = smartcard->Type;
|
||||
_smartcard->Name = _strdup(smartcard->Name);
|
||||
if (!_smartcard->Name)
|
||||
goto out_smartc_name_error;
|
||||
_smartcard->Path = _strdup(smartcard->Path);
|
||||
if (!_smartcard->Path)
|
||||
goto out_smartc_path_error;
|
||||
|
||||
_device = (RDPDR_DEVICE*) _smartcard;
|
||||
return (RDPDR_DEVICE*) _smartcard;
|
||||
|
||||
out_smartc_path_error:
|
||||
free(_smartcard->Name);
|
||||
out_smartc_name_error:
|
||||
free(_smartcard);
|
||||
return NULL;
|
||||
}
|
||||
else if (device->Type == RDPDR_DTYP_SERIAL)
|
||||
|
||||
if (device->Type == RDPDR_DTYP_SERIAL)
|
||||
{
|
||||
RDPDR_SERIAL* serial = (RDPDR_SERIAL*) device;
|
||||
RDPDR_SERIAL* _serial = (RDPDR_SERIAL*) malloc(sizeof(RDPDR_SERIAL));
|
||||
if (!_serial)
|
||||
return NULL;
|
||||
|
||||
_serial->Id = serial->Id;
|
||||
_serial->Type = serial->Type;
|
||||
_serial->Name = _strdup(serial->Name);
|
||||
if (!_serial->Name)
|
||||
goto out_serial_name_error;
|
||||
_serial->Path = _strdup(serial->Path);
|
||||
if (!_serial->Path)
|
||||
goto out_serial_path_error;
|
||||
|
||||
_device = (RDPDR_DEVICE*) _serial;
|
||||
return (RDPDR_DEVICE*) _serial;
|
||||
|
||||
out_serial_path_error:
|
||||
free(_serial->Name);
|
||||
out_serial_name_error:
|
||||
free(_serial);
|
||||
return NULL;
|
||||
}
|
||||
else if (device->Type == RDPDR_DTYP_PARALLEL)
|
||||
|
||||
if (device->Type == RDPDR_DTYP_PARALLEL)
|
||||
{
|
||||
RDPDR_PARALLEL* parallel = (RDPDR_PARALLEL*) device;
|
||||
RDPDR_PARALLEL* _parallel = (RDPDR_PARALLEL*) malloc(sizeof(RDPDR_PARALLEL));
|
||||
if (!_parallel)
|
||||
return NULL;
|
||||
|
||||
_parallel->Id = parallel->Id;
|
||||
_parallel->Type = parallel->Type;
|
||||
_parallel->Name = _strdup(parallel->Name);
|
||||
if (!_parallel->Name)
|
||||
goto out_parallel_name_error;
|
||||
_parallel->Path = _strdup(parallel->Path);
|
||||
if (!_parallel->Path)
|
||||
goto out_parallel_path_error;
|
||||
|
||||
return (RDPDR_DEVICE*) _parallel;
|
||||
out_parallel_path_error:
|
||||
free(_parallel->Name);
|
||||
out_parallel_name_error:
|
||||
free(_parallel);
|
||||
return NULL;
|
||||
|
||||
_device = (RDPDR_DEVICE*) _parallel;
|
||||
}
|
||||
|
||||
return _device;
|
||||
fprintf(stderr, "%s: unknown device type %d\n", __FUNCTION__, device->Type);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void freerdp_device_collection_free(rdpSettings* settings)
|
||||
@ -308,16 +371,29 @@ ADDIN_ARGV* freerdp_static_channel_clone(ADDIN_ARGV* channel)
|
||||
ADDIN_ARGV* _channel = NULL;
|
||||
|
||||
_channel = (ADDIN_ARGV*) malloc(sizeof(ADDIN_ARGV));
|
||||
if (!_channel)
|
||||
return NULL;
|
||||
|
||||
_channel->argc = channel->argc;
|
||||
_channel->argv = (char**) malloc(sizeof(char*) * channel->argc);
|
||||
_channel->argv = (char**) calloc(channel->argc, sizeof(char*));
|
||||
if (!_channel->argv)
|
||||
goto out_free;
|
||||
|
||||
for (index = 0; index < _channel->argc; index++)
|
||||
{
|
||||
_channel->argv[index] = _strdup(channel->argv[index]);
|
||||
if (!_channel->argv[index])
|
||||
goto out_release_args;
|
||||
}
|
||||
|
||||
return _channel;
|
||||
|
||||
out_release_args:
|
||||
for (index = 0; _channel->argv[index]; index++)
|
||||
free(_channel->argv[index]);
|
||||
out_free:
|
||||
free(_channel);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void freerdp_static_channel_collection_free(rdpSettings* settings)
|
||||
@ -375,16 +451,29 @@ ADDIN_ARGV* freerdp_dynamic_channel_clone(ADDIN_ARGV* channel)
|
||||
ADDIN_ARGV* _channel = NULL;
|
||||
|
||||
_channel = (ADDIN_ARGV*) malloc(sizeof(ADDIN_ARGV));
|
||||
if (!_channel)
|
||||
return NULL;
|
||||
|
||||
_channel->argc = channel->argc;
|
||||
_channel->argv = (char**) malloc(sizeof(char*) * channel->argc);
|
||||
if (!_channel->argv)
|
||||
goto out_free;
|
||||
|
||||
for (index = 0; index < _channel->argc; index++)
|
||||
{
|
||||
_channel->argv[index] = _strdup(channel->argv[index]);
|
||||
if (!_channel->argv[index])
|
||||
goto out_release_args;
|
||||
}
|
||||
|
||||
return _channel;
|
||||
|
||||
out_release_args:
|
||||
for (index = 0; _channel->argv[index]; index++)
|
||||
free(_channel->argv[index]);
|
||||
out_free:
|
||||
free(_channel);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void freerdp_dynamic_channel_collection_free(rdpSettings* settings)
|
||||
|
@ -183,13 +183,13 @@ rdpBulk* bulk_new(rdpContext* context)
|
||||
|
||||
void bulk_free(rdpBulk* bulk)
|
||||
{
|
||||
if (bulk)
|
||||
{
|
||||
mppc_context_free(bulk->mppcSend);
|
||||
mppc_context_free(bulk->mppcRecv);
|
||||
if (!bulk)
|
||||
return;
|
||||
|
||||
ncrush_context_free(bulk->ncrushRecv);
|
||||
mppc_context_free(bulk->mppcSend);
|
||||
mppc_context_free(bulk->mppcRecv);
|
||||
|
||||
free(bulk);
|
||||
}
|
||||
ncrush_context_free(bulk->ncrushRecv);
|
||||
|
||||
free(bulk);
|
||||
}
|
||||
|
@ -161,6 +161,8 @@ BOOL certificate_read_x509_certificate(rdpCertBlob* cert, rdpCertInfo* info)
|
||||
int error = 0;
|
||||
|
||||
s = Stream_New(cert->data, cert->length);
|
||||
if (!s)
|
||||
return FALSE;
|
||||
info->Modulus = 0;
|
||||
|
||||
if (!ber_read_sequence_tag(s, &length)) /* Certificate (SEQUENCE) */
|
||||
@ -253,6 +255,8 @@ BOOL certificate_read_x509_certificate(rdpCertBlob* cert, rdpCertInfo* info)
|
||||
|
||||
info->ModulusLength = modulus_length;
|
||||
info->Modulus = (BYTE*) malloc(info->ModulusLength);
|
||||
if (!info->Modulus)
|
||||
goto error1;
|
||||
Stream_Read(s, info->Modulus, info->ModulusLength);
|
||||
error++;
|
||||
|
||||
@ -290,12 +294,17 @@ rdpX509CertChain* certificate_new_x509_certificate_chain(UINT32 count)
|
||||
{
|
||||
rdpX509CertChain* x509_cert_chain;
|
||||
|
||||
x509_cert_chain = (rdpX509CertChain*) malloc(sizeof(rdpX509CertChain));
|
||||
x509_cert_chain = (rdpX509CertChain *)malloc(sizeof(rdpX509CertChain));
|
||||
if (!x509_cert_chain)
|
||||
return NULL;
|
||||
|
||||
x509_cert_chain->count = count;
|
||||
x509_cert_chain->array = (rdpCertBlob*) malloc(sizeof(rdpCertBlob) * count);
|
||||
ZeroMemory(x509_cert_chain->array, sizeof(rdpCertBlob) * count);
|
||||
|
||||
x509_cert_chain->array = (rdpCertBlob *)calloc(count, sizeof(rdpCertBlob));
|
||||
if (!x509_cert_chain->array)
|
||||
{
|
||||
free(x509_cert_chain);
|
||||
return NULL;
|
||||
}
|
||||
return x509_cert_chain;
|
||||
}
|
||||
|
||||
@ -308,17 +317,17 @@ void certificate_free_x509_certificate_chain(rdpX509CertChain* x509_cert_chain)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (x509_cert_chain != NULL)
|
||||
{
|
||||
for (i = 0; i < (int) x509_cert_chain->count; i++)
|
||||
{
|
||||
if (x509_cert_chain->array[i].data != NULL)
|
||||
free(x509_cert_chain->array[i].data);
|
||||
}
|
||||
if (!x509_cert_chain)
|
||||
return;
|
||||
|
||||
free(x509_cert_chain->array);
|
||||
free(x509_cert_chain);
|
||||
for (i = 0; i < (int)x509_cert_chain->count; i++)
|
||||
{
|
||||
if (x509_cert_chain->array[i].data)
|
||||
free(x509_cert_chain->array[i].data);
|
||||
}
|
||||
|
||||
free(x509_cert_chain->array);
|
||||
free(x509_cert_chain);
|
||||
}
|
||||
|
||||
static BOOL certificate_process_server_public_key(rdpCertificate* certificate, wStream* s, UINT32 length)
|
||||
@ -335,7 +344,7 @@ static BOOL certificate_process_server_public_key(rdpCertificate* certificate, w
|
||||
|
||||
if (memcmp(magic, "RSA1", 4) != 0)
|
||||
{
|
||||
fprintf(stderr, "gcc_process_server_public_key: magic error\n");
|
||||
fprintf(stderr, "%s: magic error\n", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -349,6 +358,8 @@ static BOOL certificate_process_server_public_key(rdpCertificate* certificate, w
|
||||
return FALSE;
|
||||
certificate->cert_info.ModulusLength = modlen;
|
||||
certificate->cert_info.Modulus = malloc(certificate->cert_info.ModulusLength);
|
||||
if (!certificate->cert_info.Modulus)
|
||||
return FALSE;
|
||||
Stream_Read(s, certificate->cert_info.Modulus, certificate->cert_info.ModulusLength);
|
||||
/* 8 bytes of zero padding */
|
||||
Stream_Seek(s, 8);
|
||||
@ -366,6 +377,8 @@ static BOOL certificate_process_server_public_signature(rdpCertificate* certific
|
||||
BYTE md5hash[CRYPTO_MD5_DIGEST_LENGTH];
|
||||
|
||||
md5ctx = crypto_md5_init();
|
||||
if (!md5ctx)
|
||||
return FALSE;
|
||||
crypto_md5_update(md5ctx, sigdata, sigdatalen);
|
||||
crypto_md5_final(md5ctx, md5hash);
|
||||
|
||||
@ -378,18 +391,19 @@ static BOOL certificate_process_server_public_signature(rdpCertificate* certific
|
||||
|
||||
if (sum != 0)
|
||||
{
|
||||
fprintf(stderr, "certificate_process_server_public_signature: invalid signature\n");
|
||||
fprintf(stderr, "%s: invalid signature\n", __FUNCTION__);
|
||||
//return FALSE;
|
||||
}
|
||||
|
||||
siglen -= 8;
|
||||
|
||||
// TODO: check the result of decrypt
|
||||
crypto_rsa_public_decrypt(encsig, siglen, TSSK_KEY_LENGTH, tssk_modulus, tssk_exponent, sig);
|
||||
|
||||
/* Verify signature. */
|
||||
if (memcmp(md5hash, sig, sizeof(md5hash)) != 0)
|
||||
{
|
||||
fprintf(stderr, "certificate_process_server_public_signature: invalid signature\n");
|
||||
fprintf(stderr, "%s: invalid signature\n", __FUNCTION__);
|
||||
//return FALSE;
|
||||
}
|
||||
|
||||
@ -405,7 +419,7 @@ static BOOL certificate_process_server_public_signature(rdpCertificate* certific
|
||||
|
||||
if (sig[16] != 0x00 || sum != 0xFF * (62 - 17) || sig[62] != 0x01)
|
||||
{
|
||||
fprintf(stderr, "certificate_process_server_public_signature: invalid signature\n");
|
||||
fprintf(stderr, "%s: invalid signature\n", __FUNCTION__);
|
||||
//return FALSE;
|
||||
}
|
||||
|
||||
@ -439,7 +453,8 @@ BOOL certificate_read_server_proprietary_certificate(rdpCertificate* certificate
|
||||
|
||||
if (!(dwSigAlgId == SIGNATURE_ALG_RSA && dwKeyAlgId == KEY_EXCHANGE_ALG_RSA))
|
||||
{
|
||||
fprintf(stderr, "certificate_read_server_proprietary_certificate: parse error 1\n");
|
||||
fprintf(stderr, "%s: unsupported signature or key algorithm, dwSigAlgId=%d dwKeyAlgId=%d\n",
|
||||
__FUNCTION__, dwSigAlgId, dwKeyAlgId);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -447,7 +462,7 @@ BOOL certificate_read_server_proprietary_certificate(rdpCertificate* certificate
|
||||
|
||||
if (wPublicKeyBlobType != BB_RSA_KEY_BLOB)
|
||||
{
|
||||
fprintf(stderr, "certificate_read_server_proprietary_certificate: parse error 2\n");
|
||||
fprintf(stderr, "%s: unsupported public key blob type %d\n", __FUNCTION__, wPublicKeyBlobType);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -457,7 +472,7 @@ BOOL certificate_read_server_proprietary_certificate(rdpCertificate* certificate
|
||||
|
||||
if (!certificate_process_server_public_key(certificate, s, wPublicKeyBlobLen))
|
||||
{
|
||||
fprintf(stderr, "certificate_read_server_proprietary_certificate: parse error 3\n");
|
||||
fprintf(stderr, "%s: error in server public key\n", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -469,23 +484,26 @@ BOOL certificate_read_server_proprietary_certificate(rdpCertificate* certificate
|
||||
|
||||
if (wSignatureBlobType != BB_RSA_SIGNATURE_BLOB)
|
||||
{
|
||||
fprintf(stderr, "certificate_read_server_proprietary_certificate: parse error 4\n");
|
||||
fprintf(stderr, "%s: unsupported blob signature %d\n", __FUNCTION__, wSignatureBlobType);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Stream_Read_UINT16(s, wSignatureBlobLen);
|
||||
if (Stream_GetRemainingLength(s) < wSignatureBlobLen)
|
||||
{
|
||||
fprintf(stderr, "%s: not enought bytes for signature(len=%d)\n", __FUNCTION__, wSignatureBlobLen);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (wSignatureBlobLen != 72)
|
||||
{
|
||||
fprintf(stderr, "certificate_process_server_public_signature: invalid signature length (got %d, expected %d)\n", wSignatureBlobLen, 64);
|
||||
fprintf(stderr, "%s: invalid signature length (got %d, expected %d)\n", __FUNCTION__, wSignatureBlobLen, 64);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!certificate_process_server_public_signature(certificate, sigdata, sigdatalen, s, wSignatureBlobLen))
|
||||
{
|
||||
fprintf(stderr, "certificate_read_server_proprietary_certificate: parse error 5\n");
|
||||
fprintf(stderr, "%s: unable to parse server public signature\n", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -512,6 +530,8 @@ BOOL certificate_read_server_x509_certificate_chain(rdpCertificate* certificate,
|
||||
Stream_Read_UINT32(s, numCertBlobs); /* numCertBlobs */
|
||||
|
||||
certificate->x509_cert_chain = certificate_new_x509_certificate_chain(numCertBlobs);
|
||||
if (!certificate->x509_cert_chain)
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < (int) numCertBlobs; i++)
|
||||
{
|
||||
@ -526,6 +546,8 @@ BOOL certificate_read_server_x509_certificate_chain(rdpCertificate* certificate,
|
||||
DEBUG_CERTIFICATE("\nX.509 Certificate #%d, length:%d", i + 1, certLength);
|
||||
|
||||
certificate->x509_cert_chain->array[i].data = (BYTE*) malloc(certLength);
|
||||
if (!certificate->x509_cert_chain->array[i].data)
|
||||
return FALSE;
|
||||
Stream_Read(s, certificate->x509_cert_chain->array[i].data, certLength);
|
||||
certificate->x509_cert_chain->array[i].length = certLength;
|
||||
|
||||
@ -608,29 +630,24 @@ rdpRsaKey* key_new(const char* keyfile)
|
||||
RSA* rsa;
|
||||
rdpRsaKey* key;
|
||||
|
||||
key = (rdpRsaKey*) malloc(sizeof(rdpRsaKey));
|
||||
ZeroMemory(key, sizeof(rdpRsaKey));
|
||||
|
||||
if (key == NULL)
|
||||
key = (rdpRsaKey *)calloc(1, sizeof(rdpRsaKey));
|
||||
if (!key)
|
||||
return NULL;
|
||||
|
||||
fp = fopen(keyfile, "r");
|
||||
|
||||
if (fp == NULL)
|
||||
{
|
||||
fprintf(stderr, "unable to load RSA key from %s: %s.", keyfile, strerror(errno));
|
||||
free(key) ;
|
||||
return NULL;
|
||||
fprintf(stderr, "%s: unable to open RSA key file %s: %s.", __FUNCTION__, keyfile, strerror(errno));
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
|
||||
|
||||
if (rsa == NULL)
|
||||
{
|
||||
ERR_print_errors_fp(stdout);
|
||||
fprintf(stderr, "%s: unable to load RSA key from %s: %s.", __FUNCTION__, keyfile, strerror(errno));
|
||||
ERR_print_errors_fp(stderr);
|
||||
fclose(fp);
|
||||
free(key) ;
|
||||
return NULL;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
@ -638,37 +655,36 @@ rdpRsaKey* key_new(const char* keyfile)
|
||||
switch (RSA_check_key(rsa))
|
||||
{
|
||||
case 0:
|
||||
RSA_free(rsa);
|
||||
fprintf(stderr, "invalid RSA key in %s", keyfile);
|
||||
free(key) ;
|
||||
return NULL;
|
||||
fprintf(stderr, "%s: invalid RSA key in %s\n", __FUNCTION__, keyfile);
|
||||
goto out_free_rsa;
|
||||
|
||||
case 1:
|
||||
/* Valid key. */
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "%s: unexpected error when checking RSA key from %s: %s.", __FUNCTION__, keyfile, strerror(errno));
|
||||
ERR_print_errors_fp(stderr);
|
||||
RSA_free(rsa);
|
||||
free(key) ;
|
||||
return NULL;
|
||||
goto out_free_rsa;
|
||||
}
|
||||
|
||||
if (BN_num_bytes(rsa->e) > 4)
|
||||
{
|
||||
RSA_free(rsa);
|
||||
fprintf(stderr, "RSA public exponent too large in %s", keyfile);
|
||||
free(key) ;
|
||||
return NULL;
|
||||
fprintf(stderr, "%s: RSA public exponent too large in %s\n", __FUNCTION__, keyfile);
|
||||
goto out_free_rsa;
|
||||
}
|
||||
|
||||
key->ModulusLength = BN_num_bytes(rsa->n);
|
||||
key->Modulus = (BYTE*) malloc(key->ModulusLength);
|
||||
key->Modulus = (BYTE *)malloc(key->ModulusLength);
|
||||
if (!key->Modulus)
|
||||
goto out_free_rsa;
|
||||
BN_bn2bin(rsa->n, key->Modulus);
|
||||
crypto_reverse(key->Modulus, key->ModulusLength);
|
||||
|
||||
key->PrivateExponentLength = BN_num_bytes(rsa->d);
|
||||
key->PrivateExponent = (BYTE*) malloc(key->PrivateExponentLength);
|
||||
key->PrivateExponent = (BYTE *)malloc(key->PrivateExponentLength);
|
||||
if (!key->PrivateExponent)
|
||||
goto out_free_modulus;
|
||||
BN_bn2bin(rsa->d, key->PrivateExponent);
|
||||
crypto_reverse(key->PrivateExponent, key->PrivateExponentLength);
|
||||
|
||||
@ -677,18 +693,26 @@ rdpRsaKey* key_new(const char* keyfile)
|
||||
crypto_reverse(key->exponent, sizeof(key->exponent));
|
||||
|
||||
RSA_free(rsa);
|
||||
|
||||
return key;
|
||||
|
||||
out_free_modulus:
|
||||
free(key->Modulus);
|
||||
out_free_rsa:
|
||||
RSA_free(rsa);
|
||||
out_free:
|
||||
free(key);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void key_free(rdpRsaKey* key)
|
||||
{
|
||||
if (key != NULL)
|
||||
{
|
||||
if (!key)
|
||||
return;
|
||||
|
||||
if (key->Modulus)
|
||||
free(key->Modulus);
|
||||
free(key->PrivateExponent);
|
||||
free(key);
|
||||
}
|
||||
free(key->PrivateExponent);
|
||||
free(key);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -701,13 +725,9 @@ rdpCertificate* certificate_new()
|
||||
{
|
||||
rdpCertificate* certificate;
|
||||
|
||||
certificate = (rdpCertificate*) malloc(sizeof(rdpCertificate));
|
||||
ZeroMemory(certificate, sizeof(rdpCertificate));
|
||||
|
||||
if (certificate != NULL)
|
||||
{
|
||||
certificate->x509_cert_chain = NULL;
|
||||
}
|
||||
certificate = (rdpCertificate*) calloc(1, sizeof(rdpCertificate));
|
||||
if (!certificate)
|
||||
return NULL;
|
||||
|
||||
return certificate;
|
||||
}
|
||||
@ -719,13 +739,13 @@ rdpCertificate* certificate_new()
|
||||
|
||||
void certificate_free(rdpCertificate* certificate)
|
||||
{
|
||||
if (certificate != NULL)
|
||||
{
|
||||
certificate_free_x509_certificate_chain(certificate->x509_cert_chain);
|
||||
if (!certificate)
|
||||
return;
|
||||
|
||||
if (certificate->cert_info.Modulus != NULL)
|
||||
free(certificate->cert_info.Modulus);
|
||||
certificate_free_x509_certificate_chain(certificate->x509_cert_chain);
|
||||
|
||||
free(certificate);
|
||||
}
|
||||
if (certificate->cert_info.Modulus)
|
||||
free(certificate->cert_info.Modulus);
|
||||
|
||||
free(certificate);
|
||||
}
|
||||
|
@ -178,6 +178,8 @@ BOOL rdp_client_connect(rdpRdp* rdp)
|
||||
}
|
||||
|
||||
rdp->settingsCopy = freerdp_settings_clone(settings);
|
||||
if (!rdp->settingsCopy)
|
||||
return FALSE;
|
||||
|
||||
nego_init(rdp->nego);
|
||||
nego_set_target(rdp->nego, settings->ServerHostname, settings->ServerPort);
|
||||
@ -421,17 +423,13 @@ static BOOL rdp_client_establish_keys(rdpRdp* rdp)
|
||||
Stream_SealLength(s);
|
||||
|
||||
if (transport_write(rdp->mcs->transport, s) < 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Stream_Free(s, TRUE);
|
||||
|
||||
/* now calculate encrypt / decrypt and update keys */
|
||||
if (!security_establish_keys(rdp->settings->ClientRandom, rdp))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rdp->do_crypt = TRUE;
|
||||
|
||||
@ -441,15 +439,40 @@ static BOOL rdp_client_establish_keys(rdpRdp* rdp)
|
||||
if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS)
|
||||
{
|
||||
rdp->fips_encrypt = crypto_des3_encrypt_init(rdp->fips_encrypt_key, fips_ivec);
|
||||
if (!rdp->fips_encrypt)
|
||||
{
|
||||
fprintf(stderr, "%s: unable to allocate des3 encrypt key\n", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
rdp->fips_decrypt = crypto_des3_decrypt_init(rdp->fips_decrypt_key, fips_ivec);
|
||||
if (!rdp->fips_decrypt)
|
||||
{
|
||||
fprintf(stderr, "%s: unable to allocate des3 decrypt key\n", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rdp->fips_hmac = crypto_hmac_new();
|
||||
if (!rdp->fips_hmac)
|
||||
{
|
||||
fprintf(stderr, "%s: unable to allocate fips hmac\n", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
rdp->rc4_decrypt_key = crypto_rc4_init(rdp->decrypt_key, rdp->rc4_key_len);
|
||||
rdp->rc4_encrypt_key = crypto_rc4_init(rdp->encrypt_key, rdp->rc4_key_len);
|
||||
if (!rdp->rc4_decrypt_key)
|
||||
{
|
||||
fprintf(stderr, "%s: unable to allocate rc4 decrypt key\n", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rdp->rc4_encrypt_key = crypto_rc4_init(rdp->encrypt_key, rdp->rc4_key_len);
|
||||
if (!rdp->rc4_encrypt_key)
|
||||
{
|
||||
fprintf(stderr, "%s: unable to allocate rc4 encrypt key\n", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -470,7 +493,7 @@ BOOL rdp_server_establish_keys(rdpRdp* rdp, wStream* s)
|
||||
|
||||
if (!rdp_read_header(rdp, s, &length, &channel_id))
|
||||
{
|
||||
fprintf(stderr, "rdp_server_establish_keys: invalid RDP header\n");
|
||||
fprintf(stderr, "%s: invalid RDP header\n", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -479,7 +502,7 @@ BOOL rdp_server_establish_keys(rdpRdp* rdp, wStream* s)
|
||||
|
||||
if ((sec_flags & SEC_EXCHANGE_PKT) == 0)
|
||||
{
|
||||
fprintf(stderr, "rdp_server_establish_keys: missing SEC_EXCHANGE_PKT in security header\n");
|
||||
fprintf(stderr, "%s: missing SEC_EXCHANGE_PKT in security header\n", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -488,21 +511,21 @@ BOOL rdp_server_establish_keys(rdpRdp* rdp, wStream* s)
|
||||
|
||||
Stream_Read_UINT32(s, rand_len);
|
||||
|
||||
if (Stream_GetRemainingLength(s) < rand_len + 8) /* include 8 bytes of padding */
|
||||
/* rand_len already includes 8 bytes of padding */
|
||||
if (Stream_GetRemainingLength(s) < rand_len)
|
||||
return FALSE;
|
||||
|
||||
key_len = rdp->settings->RdpServerRsaKey->ModulusLength;
|
||||
|
||||
if (rand_len != key_len + 8)
|
||||
{
|
||||
fprintf(stderr, "rdp_server_establish_keys: invalid encrypted client random length\n");
|
||||
fprintf(stderr, "%s: invalid encrypted client random length\n", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ZeroMemory(crypt_client_random, sizeof(crypt_client_random));
|
||||
Stream_Read(s, crypt_client_random, rand_len);
|
||||
/* 8 zero bytes of padding */
|
||||
Stream_Seek(s, 8);
|
||||
|
||||
mod = rdp->settings->RdpServerRsaKey->Modulus;
|
||||
priv_exp = rdp->settings->RdpServerRsaKey->PrivateExponent;
|
||||
crypto_rsa_private_decrypt(crypt_client_random, rand_len - 8, key_len, mod, priv_exp, client_random);
|
||||
@ -521,14 +544,41 @@ BOOL rdp_server_establish_keys(rdpRdp* rdp, wStream* s)
|
||||
if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS)
|
||||
{
|
||||
rdp->fips_encrypt = crypto_des3_encrypt_init(rdp->fips_encrypt_key, fips_ivec);
|
||||
if (!rdp->fips_encrypt)
|
||||
{
|
||||
fprintf(stderr, "%s: unable to allocate des3 encrypt key\n", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rdp->fips_decrypt = crypto_des3_decrypt_init(rdp->fips_decrypt_key, fips_ivec);
|
||||
if (!rdp->fips_decrypt)
|
||||
{
|
||||
fprintf(stderr, "%s: unable to allocate des3 decrypt key\n", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rdp->fips_hmac = crypto_hmac_new();
|
||||
if (!rdp->fips_hmac)
|
||||
{
|
||||
fprintf(stderr, "%s: unable to allocate fips hmac\n", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
rdp->rc4_decrypt_key = crypto_rc4_init(rdp->decrypt_key, rdp->rc4_key_len);
|
||||
if (!rdp->rc4_decrypt_key)
|
||||
{
|
||||
fprintf(stderr, "%s: unable to allocate rc4 decrypt key\n", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rdp->rc4_encrypt_key = crypto_rc4_init(rdp->encrypt_key, rdp->rc4_key_len);
|
||||
if (!rdp->rc4_encrypt_key)
|
||||
{
|
||||
fprintf(stderr, "%s: unable to allocate rc4 encrypt key\n", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -872,33 +922,35 @@ BOOL rdp_server_accept_nego(rdpRdp* rdp, wStream* s)
|
||||
{
|
||||
BOOL status;
|
||||
rdpSettings* settings = rdp->settings;
|
||||
rdpNego *nego = rdp->nego;
|
||||
|
||||
transport_set_blocking_mode(rdp->transport, TRUE);
|
||||
|
||||
if (!nego_read_request(rdp->nego, s))
|
||||
if (!nego_read_request(nego, s))
|
||||
return FALSE;
|
||||
|
||||
rdp->nego->selected_protocol = 0;
|
||||
nego->selected_protocol = 0;
|
||||
|
||||
fprintf(stderr, "Client Security: NLA:%d TLS:%d RDP:%d\n",
|
||||
(rdp->nego->requested_protocols & PROTOCOL_NLA) ? 1 : 0,
|
||||
(rdp->nego->requested_protocols & PROTOCOL_TLS) ? 1 : 0,
|
||||
(rdp->nego->requested_protocols == PROTOCOL_RDP) ? 1: 0);
|
||||
(nego->requested_protocols & PROTOCOL_NLA) ? 1 : 0,
|
||||
(nego->requested_protocols & PROTOCOL_TLS) ? 1 : 0,
|
||||
(nego->requested_protocols == PROTOCOL_RDP) ? 1 : 0
|
||||
);
|
||||
|
||||
fprintf(stderr, "Server Security: NLA:%d TLS:%d RDP:%d\n",
|
||||
settings->NlaSecurity, settings->TlsSecurity, settings->RdpSecurity);
|
||||
|
||||
if ((settings->NlaSecurity) && (rdp->nego->requested_protocols & PROTOCOL_NLA))
|
||||
if ((settings->NlaSecurity) && (nego->requested_protocols & PROTOCOL_NLA))
|
||||
{
|
||||
rdp->nego->selected_protocol = PROTOCOL_NLA;
|
||||
nego->selected_protocol = PROTOCOL_NLA;
|
||||
}
|
||||
else if ((settings->TlsSecurity) && (rdp->nego->requested_protocols & PROTOCOL_TLS))
|
||||
else if ((settings->TlsSecurity) && (nego->requested_protocols & PROTOCOL_TLS))
|
||||
{
|
||||
rdp->nego->selected_protocol = PROTOCOL_TLS;
|
||||
nego->selected_protocol = PROTOCOL_TLS;
|
||||
}
|
||||
else if ((settings->RdpSecurity) && (rdp->nego->selected_protocol == PROTOCOL_RDP))
|
||||
else if ((settings->RdpSecurity) && (nego->selected_protocol == PROTOCOL_RDP))
|
||||
{
|
||||
rdp->nego->selected_protocol = PROTOCOL_RDP;
|
||||
nego->selected_protocol = PROTOCOL_RDP;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -906,20 +958,21 @@ BOOL rdp_server_accept_nego(rdpRdp* rdp, wStream* s)
|
||||
}
|
||||
|
||||
fprintf(stderr, "Negotiated Security: NLA:%d TLS:%d RDP:%d\n",
|
||||
(rdp->nego->selected_protocol & PROTOCOL_NLA) ? 1 : 0,
|
||||
(rdp->nego->selected_protocol & PROTOCOL_TLS) ? 1 : 0,
|
||||
(rdp->nego->selected_protocol == PROTOCOL_RDP) ? 1: 0);
|
||||
(nego->selected_protocol & PROTOCOL_NLA) ? 1 : 0,
|
||||
(nego->selected_protocol & PROTOCOL_TLS) ? 1 : 0,
|
||||
(nego->selected_protocol == PROTOCOL_RDP) ? 1: 0
|
||||
);
|
||||
|
||||
if (!nego_send_negotiation_response(rdp->nego))
|
||||
if (!nego_send_negotiation_response(nego))
|
||||
return FALSE;
|
||||
|
||||
status = FALSE;
|
||||
|
||||
if (rdp->nego->selected_protocol & PROTOCOL_NLA)
|
||||
if (nego->selected_protocol & PROTOCOL_NLA)
|
||||
status = transport_accept_nla(rdp->transport);
|
||||
else if (rdp->nego->selected_protocol & PROTOCOL_TLS)
|
||||
else if (nego->selected_protocol & PROTOCOL_TLS)
|
||||
status = transport_accept_tls(rdp->transport);
|
||||
else if (rdp->nego->selected_protocol == PROTOCOL_RDP) /* 0 */
|
||||
else if (nego->selected_protocol == PROTOCOL_RDP) /* 0 */
|
||||
status = transport_accept_rdp(rdp->transport);
|
||||
|
||||
if (!status)
|
||||
|
@ -1167,11 +1167,17 @@ void gcc_write_server_security_data(wStream* s, rdpMcs* mcs)
|
||||
sigDataLen = Stream_Pointer(s) - sigData;
|
||||
|
||||
Stream_Write_UINT16(s, BB_RSA_SIGNATURE_BLOB); /* wSignatureBlobType */
|
||||
Stream_Write_UINT16(s, keyLen + 8); /* wSignatureBlobLen */
|
||||
Stream_Write_UINT16(s, sizeof(encryptedSignature) + 8); /* wSignatureBlobLen */
|
||||
|
||||
memcpy(signature, initial_signature, sizeof(initial_signature));
|
||||
|
||||
md5 = crypto_md5_init();
|
||||
if (!md5)
|
||||
{
|
||||
fprintf(stderr, "%s: unable to allocate a md5\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
crypto_md5_update(md5, sigData, sigDataLen);
|
||||
crypto_md5_final(md5, signature);
|
||||
|
||||
|
@ -248,6 +248,11 @@ void rdp_write_extended_info_packet(wStream* s, rdpSettings* settings)
|
||||
clientCookie->logonId = serverCookie->logonId;
|
||||
|
||||
hmac = crypto_hmac_new();
|
||||
if (!hmac)
|
||||
{
|
||||
fprintf(stderr, "%s: unable to allocate hmac\n", __FUNCTION__);
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
crypto_hmac_md5_init(hmac, serverCookie->arcRandomBits, 16);
|
||||
|
||||
@ -270,11 +275,12 @@ void rdp_write_extended_info_packet(wStream* s, rdpSettings* settings)
|
||||
rdp_write_client_auto_reconnect_cookie(s, settings); /* autoReconnectCookie */
|
||||
/* mark as used */
|
||||
settings->ServerAutoReconnectCookie->cbLen = 0;
|
||||
crypto_hmac_free(hmac);
|
||||
}
|
||||
|
||||
/* reserved1 (2 bytes) */
|
||||
/* reserved2 (2 bytes) */
|
||||
|
||||
out_free:
|
||||
free(clientAddress);
|
||||
free(clientDir);
|
||||
}
|
||||
|
@ -392,6 +392,12 @@ void license_generate_hwid(rdpLicense* license)
|
||||
mac_address = license->rdp->transport->TcpIn->mac_address;
|
||||
|
||||
md5 = crypto_md5_init();
|
||||
if (!md5)
|
||||
{
|
||||
fprintf(stderr, "%s: unable to allocate a md5\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
crypto_md5_update(md5, mac_address, 6);
|
||||
crypto_md5_final(md5, &license->HardwareId[HWID_PLATFORM_ID_LENGTH]);
|
||||
}
|
||||
@ -458,6 +464,11 @@ void license_decrypt_platform_challenge(rdpLicense* license)
|
||||
license->PlatformChallenge->length = license->EncryptedPlatformChallenge->length;
|
||||
|
||||
rc4 = crypto_rc4_init(license->LicensingEncryptionKey, LICENSING_ENCRYPTION_KEY_LENGTH);
|
||||
if (!rc4)
|
||||
{
|
||||
fprintf(stderr, "%s: unable to allocate a rc4\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
crypto_rc4(rc4, license->EncryptedPlatformChallenge->length,
|
||||
license->EncryptedPlatformChallenge->data,
|
||||
@ -1042,6 +1053,11 @@ void license_send_platform_challenge_response_packet(rdpLicense* license)
|
||||
|
||||
buffer = (BYTE*) malloc(HWID_LENGTH);
|
||||
rc4 = crypto_rc4_init(license->LicensingEncryptionKey, LICENSING_ENCRYPTION_KEY_LENGTH);
|
||||
if (!rc4)
|
||||
{
|
||||
fprintf(stderr, "%s: unable to allocate a rc4\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
crypto_rc4(rc4, HWID_LENGTH, license->HardwareId, buffer);
|
||||
crypto_rc4_free(rc4);
|
||||
|
||||
|
@ -497,9 +497,10 @@ BOOL nego_recv_response(rdpNego* nego)
|
||||
wStream* s;
|
||||
|
||||
s = Stream_New(NULL, 1024);
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
status = transport_read(nego->transport, s);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
Stream_Free(s, TRUE);
|
||||
@ -869,6 +870,8 @@ BOOL nego_send_negotiation_response(rdpNego* nego)
|
||||
settings = nego->transport->settings;
|
||||
|
||||
s = Stream_New(NULL, 512);
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
length = TPDU_CONNECTION_CONFIRM_LENGTH;
|
||||
bm = Stream_GetPosition(s);
|
||||
@ -899,7 +902,7 @@ BOOL nego_send_negotiation_response(rdpNego* nego)
|
||||
* TODO: Check for other possibilities,
|
||||
* like SSL_NOT_ALLOWED_BY_SERVER.
|
||||
*/
|
||||
fprintf(stderr, "nego_send_negotiation_response: client supports only Standard RDP Security\n");
|
||||
fprintf(stderr, "%s: client supports only Standard RDP Security\n", __FUNCTION__);
|
||||
Stream_Write_UINT32(s, SSL_REQUIRED_BY_SERVER);
|
||||
length += 8;
|
||||
status = FALSE;
|
||||
@ -940,7 +943,7 @@ BOOL nego_send_negotiation_response(rdpNego* nego)
|
||||
settings->EncryptionLevel = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE;
|
||||
}
|
||||
|
||||
if (settings->DisableEncryption && settings->RdpServerRsaKey == NULL && settings->RdpKeyFile == NULL)
|
||||
if (settings->DisableEncryption && !settings->RdpServerRsaKey && !settings->RdpKeyFile)
|
||||
return FALSE;
|
||||
}
|
||||
else if (settings->SelectedProtocol == PROTOCOL_TLS)
|
||||
@ -990,15 +993,13 @@ void nego_init(rdpNego* nego)
|
||||
|
||||
rdpNego* nego_new(rdpTransport* transport)
|
||||
{
|
||||
rdpNego* nego = (rdpNego*) malloc(sizeof(rdpNego));
|
||||
rdpNego* nego = (rdpNego*) calloc(1, sizeof(rdpNego));
|
||||
if (!nego)
|
||||
return NULL;
|
||||
|
||||
if (nego)
|
||||
{
|
||||
ZeroMemory(nego, sizeof(rdpNego));
|
||||
|
||||
nego->transport = transport;
|
||||
nego_init(nego);
|
||||
}
|
||||
nego->transport = transport;
|
||||
nego_init(nego);
|
||||
|
||||
return nego;
|
||||
}
|
||||
|
@ -36,15 +36,22 @@ extern const char* DATA_PDU_TYPE_STRINGS[80];
|
||||
|
||||
static BOOL freerdp_peer_initialize(freerdp_peer* client)
|
||||
{
|
||||
client->context->rdp->settings->ServerMode = TRUE;
|
||||
client->context->rdp->settings->FrameAcknowledge = 0;
|
||||
client->context->rdp->settings->LocalConnection = client->local;
|
||||
client->context->rdp->state = CONNECTION_STATE_INITIAL;
|
||||
rdpRdp *rdp = client->context->rdp;
|
||||
rdpSettings *settings = rdp->settings;
|
||||
|
||||
if (client->context->rdp->settings->RdpKeyFile != NULL)
|
||||
settings->ServerMode = TRUE;
|
||||
settings->FrameAcknowledge = 0;
|
||||
settings->LocalConnection = client->local;
|
||||
rdp->state = CONNECTION_STATE_INITIAL;
|
||||
|
||||
if (settings->RdpKeyFile != NULL)
|
||||
{
|
||||
client->context->rdp->settings->RdpServerRsaKey =
|
||||
key_new(client->context->rdp->settings->RdpKeyFile);
|
||||
settings->RdpServerRsaKey = key_new(settings->RdpKeyFile);
|
||||
if (!settings->RdpServerRsaKey)
|
||||
{
|
||||
fprintf(stderr, "%s: inavlid RDP key file %s\n", __FUNCTION__, settings->RdpKeyFile);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
@ -304,8 +311,8 @@ static int peer_recv_callback(rdpTransport* transport, wStream* s, void* extra)
|
||||
}
|
||||
|
||||
rdp_server_transition_to_state(rdp, CONNECTION_STATE_SECURE_SETTINGS_EXCHANGE);
|
||||
return peer_recv_callback(transport, s, extra);
|
||||
|
||||
if (Stream_GetRemainingLength(s) > 0)
|
||||
return peer_recv_callback(transport, s, extra);
|
||||
break;
|
||||
|
||||
case CONNECTION_STATE_SECURE_SETTINGS_EXCHANGE:
|
||||
|
@ -129,6 +129,11 @@ static void security_salted_hash(const BYTE* salt, const BYTE* input, int length
|
||||
|
||||
/* SHA1_Digest = SHA1(Input + Salt + Salt1 + Salt2) */
|
||||
sha1 = crypto_sha1_init();
|
||||
if (!sha1)
|
||||
{
|
||||
fprintf(stderr, "%s: unable to allocate a sha1\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
crypto_sha1_update(sha1, input, length); /* Input */
|
||||
crypto_sha1_update(sha1, salt, 48); /* Salt (48 bytes) */
|
||||
crypto_sha1_update(sha1, salt1, 32); /* Salt1 (32 bytes) */
|
||||
@ -137,6 +142,11 @@ static void security_salted_hash(const BYTE* salt, const BYTE* input, int length
|
||||
|
||||
/* SaltedHash(Salt, Input, Salt1, Salt2) = MD5(S + SHA1_Digest) */
|
||||
md5 = crypto_md5_init();
|
||||
if (!md5)
|
||||
{
|
||||
fprintf(stderr, "%s: unable to allocate a md5\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
crypto_md5_update(md5, salt, 48); /* Salt (48 bytes) */
|
||||
crypto_md5_update(md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */
|
||||
crypto_md5_final(md5, output);
|
||||
@ -185,6 +195,11 @@ void security_md5_16_32_32(const BYTE* in0, const BYTE* in1, const BYTE* in2, BY
|
||||
CryptoMd5 md5;
|
||||
|
||||
md5 = crypto_md5_init();
|
||||
if (!md5)
|
||||
{
|
||||
fprintf(stderr, "%s: unable to allocate a md5\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
crypto_md5_update(md5, in0, 16);
|
||||
crypto_md5_update(md5, in1, 32);
|
||||
crypto_md5_update(md5, in2, 32);
|
||||
@ -220,6 +235,11 @@ void security_mac_data(const BYTE* mac_salt_key, const BYTE* data, UINT32 length
|
||||
|
||||
/* SHA1_Digest = SHA1(MacSaltKey + pad1 + length + data) */
|
||||
sha1 = crypto_sha1_init();
|
||||
if (!sha1)
|
||||
{
|
||||
fprintf(stderr, "%s: unable to allocate a sha1\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
crypto_sha1_update(sha1, mac_salt_key, 16); /* MacSaltKey */
|
||||
crypto_sha1_update(sha1, pad1, sizeof(pad1)); /* pad1 */
|
||||
crypto_sha1_update(sha1, length_le, sizeof(length_le)); /* length */
|
||||
@ -228,6 +248,11 @@ void security_mac_data(const BYTE* mac_salt_key, const BYTE* data, UINT32 length
|
||||
|
||||
/* MacData = MD5(MacSaltKey + pad2 + SHA1_Digest) */
|
||||
md5 = crypto_md5_init();
|
||||
if (!md5)
|
||||
{
|
||||
fprintf(stderr, "%s: unable to allocate a md5\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
crypto_md5_update(md5, mac_salt_key, 16); /* MacSaltKey */
|
||||
crypto_md5_update(md5, pad2, sizeof(pad2)); /* pad2 */
|
||||
crypto_md5_update(md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */
|
||||
@ -246,6 +271,11 @@ void security_mac_signature(rdpRdp *rdp, const BYTE* data, UINT32 length, BYTE*
|
||||
|
||||
/* SHA1_Digest = SHA1(MACKeyN + pad1 + length + data) */
|
||||
sha1 = crypto_sha1_init();
|
||||
if (!sha1)
|
||||
{
|
||||
fprintf(stderr, "%s: unable to allocate a sha1\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
crypto_sha1_update(sha1, rdp->sign_key, rdp->rc4_key_len); /* MacKeyN */
|
||||
crypto_sha1_update(sha1, pad1, sizeof(pad1)); /* pad1 */
|
||||
crypto_sha1_update(sha1, length_le, sizeof(length_le)); /* length */
|
||||
@ -254,6 +284,11 @@ void security_mac_signature(rdpRdp *rdp, const BYTE* data, UINT32 length, BYTE*
|
||||
|
||||
/* MACSignature = First64Bits(MD5(MACKeyN + pad2 + SHA1_Digest)) */
|
||||
md5 = crypto_md5_init();
|
||||
if (!md5)
|
||||
{
|
||||
fprintf(stderr, "%s: unable to allocate a md5\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
crypto_md5_update(md5, rdp->sign_key, rdp->rc4_key_len); /* MacKeyN */
|
||||
crypto_md5_update(md5, pad2, sizeof(pad2)); /* pad2 */
|
||||
crypto_md5_update(md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */
|
||||
@ -289,6 +324,11 @@ void security_salted_mac_signature(rdpRdp *rdp, const BYTE* data, UINT32 length,
|
||||
|
||||
/* SHA1_Digest = SHA1(MACKeyN + pad1 + length + data) */
|
||||
sha1 = crypto_sha1_init();
|
||||
if (!sha1)
|
||||
{
|
||||
fprintf(stderr, "%s: unable to allocate a sha1\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
crypto_sha1_update(sha1, rdp->sign_key, rdp->rc4_key_len); /* MacKeyN */
|
||||
crypto_sha1_update(sha1, pad1, sizeof(pad1)); /* pad1 */
|
||||
crypto_sha1_update(sha1, length_le, sizeof(length_le)); /* length */
|
||||
@ -298,6 +338,11 @@ void security_salted_mac_signature(rdpRdp *rdp, const BYTE* data, UINT32 length,
|
||||
|
||||
/* MACSignature = First64Bits(MD5(MACKeyN + pad2 + SHA1_Digest)) */
|
||||
md5 = crypto_md5_init();
|
||||
if (!md5)
|
||||
{
|
||||
fprintf(stderr, "%s: unable to allocate a md5\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
crypto_md5_update(md5, rdp->sign_key, rdp->rc4_key_len); /* MacKeyN */
|
||||
crypto_md5_update(md5, pad2, sizeof(pad2)); /* pad2 */
|
||||
crypto_md5_update(md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */
|
||||
@ -379,6 +424,11 @@ BOOL security_establish_keys(const BYTE* client_random, rdpRdp* rdp)
|
||||
rdp->settings->FastPathInput = FALSE;
|
||||
|
||||
sha1 = crypto_sha1_init();
|
||||
if (!sha1)
|
||||
{
|
||||
fprintf(stderr, "%s: unable to allocate a sha1\n", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
crypto_sha1_update(sha1, client_random + 16, 16);
|
||||
crypto_sha1_update(sha1, server_random + 16, 16);
|
||||
crypto_sha1_final(sha1, client_encrypt_key_t);
|
||||
@ -387,6 +437,11 @@ BOOL security_establish_keys(const BYTE* client_random, rdpRdp* rdp)
|
||||
fips_expand_key_bits(client_encrypt_key_t, rdp->fips_encrypt_key);
|
||||
|
||||
sha1 = crypto_sha1_init();
|
||||
if (!sha1)
|
||||
{
|
||||
fprintf(stderr, "%s: unable to allocate a sha1\n", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
crypto_sha1_update(sha1, client_random, 16);
|
||||
crypto_sha1_update(sha1, server_random, 16);
|
||||
crypto_sha1_final(sha1, client_decrypt_key_t);
|
||||
@ -395,6 +450,11 @@ BOOL security_establish_keys(const BYTE* client_random, rdpRdp* rdp)
|
||||
fips_expand_key_bits(client_decrypt_key_t, rdp->fips_decrypt_key);
|
||||
|
||||
sha1 = crypto_sha1_init();
|
||||
if (!sha1)
|
||||
{
|
||||
fprintf(stderr, "%s: unable to allocate a sha1\n", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
crypto_sha1_update(sha1, client_decrypt_key_t, 20);
|
||||
crypto_sha1_update(sha1, client_encrypt_key_t, 20);
|
||||
crypto_sha1_final(sha1, rdp->fips_sign_key);
|
||||
@ -454,18 +514,33 @@ BOOL security_key_update(BYTE* key, BYTE* update_key, int key_len)
|
||||
BYTE salt40[] = { 0xD1, 0x26, 0x9E };
|
||||
|
||||
sha1 = crypto_sha1_init();
|
||||
if (!sha1)
|
||||
{
|
||||
fprintf(stderr, "%s: unable to allocate a sha1\n", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
crypto_sha1_update(sha1, update_key, key_len);
|
||||
crypto_sha1_update(sha1, pad1, sizeof(pad1));
|
||||
crypto_sha1_update(sha1, key, key_len);
|
||||
crypto_sha1_final(sha1, sha1h);
|
||||
|
||||
md5 = crypto_md5_init();
|
||||
if (!md5)
|
||||
{
|
||||
fprintf(stderr, "%s: unable to allocate a md5\n", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
crypto_md5_update(md5, update_key, key_len);
|
||||
crypto_md5_update(md5, pad2, sizeof(pad2));
|
||||
crypto_md5_update(md5, sha1h, sizeof(sha1h));
|
||||
crypto_md5_final(md5, key);
|
||||
|
||||
rc4 = crypto_rc4_init(key, key_len);
|
||||
if (!rc4)
|
||||
{
|
||||
fprintf(stderr, "%s: unable to allocate a rc4\n", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
crypto_rc4(rc4, key_len, key, key);
|
||||
crypto_rc4_free(rc4);
|
||||
|
||||
@ -482,6 +557,11 @@ BOOL security_encrypt(BYTE* data, int length, rdpRdp* rdp)
|
||||
security_key_update(rdp->encrypt_key, rdp->encrypt_update_key, rdp->rc4_key_len);
|
||||
crypto_rc4_free(rdp->rc4_encrypt_key);
|
||||
rdp->rc4_encrypt_key = crypto_rc4_init(rdp->encrypt_key, rdp->rc4_key_len);
|
||||
if (!rdp->rc4_encrypt_key)
|
||||
{
|
||||
fprintf(stderr, "%s: unable to allocate rc4 encrypt key\n", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
rdp->encrypt_use_count = 0;
|
||||
}
|
||||
crypto_rc4(rdp->rc4_encrypt_key, length, data, data);
|
||||
@ -499,6 +579,12 @@ BOOL security_decrypt(BYTE* data, int length, rdpRdp* rdp)
|
||||
security_key_update(rdp->decrypt_key, rdp->decrypt_update_key, rdp->rc4_key_len);
|
||||
crypto_rc4_free(rdp->rc4_decrypt_key);
|
||||
rdp->rc4_decrypt_key = crypto_rc4_init(rdp->decrypt_key, rdp->rc4_key_len);
|
||||
if (!rdp->rc4_decrypt_key)
|
||||
{
|
||||
fprintf(stderr, "%s: unable to allocate rc4 decrypt key\n", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rdp->decrypt_use_count = 0;
|
||||
}
|
||||
crypto_rc4(rdp->rc4_decrypt_key, length, data, data);
|
||||
|
@ -231,17 +231,23 @@ rdpCertificateData* certificate_data_new(char* hostname, char* fingerprint)
|
||||
{
|
||||
rdpCertificateData* certdata;
|
||||
|
||||
certdata = (rdpCertificateData*) malloc(sizeof(rdpCertificateData));
|
||||
|
||||
if (certdata != NULL)
|
||||
{
|
||||
ZeroMemory(certdata, sizeof(rdpCertificateData));
|
||||
|
||||
certdata->hostname = _strdup(hostname);
|
||||
certdata->fingerprint = _strdup(fingerprint);
|
||||
}
|
||||
certdata = (rdpCertificateData *)calloc(1, sizeof(rdpCertificateData));
|
||||
if (!certdata)
|
||||
return NULL;
|
||||
|
||||
certdata->hostname = _strdup(hostname);
|
||||
if (!certdata->hostname)
|
||||
goto out_free;
|
||||
certdata->fingerprint = _strdup(fingerprint);
|
||||
if (!certdata->fingerprint)
|
||||
goto out_free_hostname;
|
||||
return certdata;
|
||||
|
||||
out_free_hostname:
|
||||
free(certdata->hostname);
|
||||
out_free:
|
||||
free(certdata);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void certificate_data_free(rdpCertificateData* certificate_data)
|
||||
|
@ -28,6 +28,8 @@
|
||||
CryptoSha1 crypto_sha1_init(void)
|
||||
{
|
||||
CryptoSha1 sha1 = malloc(sizeof(*sha1));
|
||||
if (!sha1)
|
||||
return NULL;
|
||||
SHA1_Init(&sha1->sha_ctx);
|
||||
return sha1;
|
||||
}
|
||||
@ -46,6 +48,8 @@ void crypto_sha1_final(CryptoSha1 sha1, BYTE* out_data)
|
||||
CryptoMd5 crypto_md5_init(void)
|
||||
{
|
||||
CryptoMd5 md5 = malloc(sizeof(*md5));
|
||||
if (!md5)
|
||||
return NULL;
|
||||
MD5_Init(&md5->md5_ctx);
|
||||
return md5;
|
||||
}
|
||||
@ -64,6 +68,8 @@ void crypto_md5_final(CryptoMd5 md5, BYTE* out_data)
|
||||
CryptoRc4 crypto_rc4_init(const BYTE* key, UINT32 length)
|
||||
{
|
||||
CryptoRc4 rc4 = malloc(sizeof(*rc4));
|
||||
if (!rc4)
|
||||
return NULL;
|
||||
RC4_set_key(&rc4->rc4_key, length, key);
|
||||
return rc4;
|
||||
}
|
||||
@ -82,6 +88,9 @@ void crypto_rc4_free(CryptoRc4 rc4)
|
||||
CryptoDes3 crypto_des3_encrypt_init(const BYTE* key, const BYTE* ivec)
|
||||
{
|
||||
CryptoDes3 des3 = malloc(sizeof(*des3));
|
||||
if (!des3)
|
||||
return NULL;
|
||||
|
||||
EVP_CIPHER_CTX_init(&des3->des3_ctx);
|
||||
EVP_EncryptInit_ex(&des3->des3_ctx, EVP_des_ede3_cbc(), NULL, key, ivec);
|
||||
EVP_CIPHER_CTX_set_padding(&des3->des3_ctx, 0);
|
||||
@ -91,6 +100,9 @@ CryptoDes3 crypto_des3_encrypt_init(const BYTE* key, const BYTE* ivec)
|
||||
CryptoDes3 crypto_des3_decrypt_init(const BYTE* key, const BYTE* ivec)
|
||||
{
|
||||
CryptoDes3 des3 = malloc(sizeof(*des3));
|
||||
if (!des3)
|
||||
return NULL;
|
||||
|
||||
EVP_CIPHER_CTX_init(&des3->des3_ctx);
|
||||
EVP_DecryptInit_ex(&des3->des3_ctx, EVP_des_ede3_cbc(), NULL, key, ivec);
|
||||
EVP_CIPHER_CTX_set_padding(&des3->des3_ctx, 0);
|
||||
@ -123,6 +135,9 @@ void crypto_des3_free(CryptoDes3 des3)
|
||||
CryptoHmac crypto_hmac_new(void)
|
||||
{
|
||||
CryptoHmac hmac = malloc(sizeof(*hmac));
|
||||
if (!hmac)
|
||||
return NULL;
|
||||
|
||||
HMAC_CTX_init(&hmac->hmac_ctx);
|
||||
return hmac;
|
||||
}
|
||||
@ -159,6 +174,9 @@ void crypto_hmac_free(CryptoHmac hmac)
|
||||
CryptoCert crypto_cert_read(BYTE* data, UINT32 length)
|
||||
{
|
||||
CryptoCert cert = malloc(sizeof(*cert));
|
||||
if (!cert)
|
||||
return NULL;
|
||||
|
||||
/* this will move the data pointer but we don't care, we don't use it again */
|
||||
cert->px509 = d2i_X509(NULL, (D2I_X509_CONST BYTE **) &data, length);
|
||||
return cert;
|
||||
@ -182,19 +200,17 @@ BOOL crypto_cert_get_public_key(CryptoCert cert, BYTE** PublicKey, DWORD* Public
|
||||
EVP_PKEY* pkey = NULL;
|
||||
|
||||
pkey = X509_get_pubkey(cert->px509);
|
||||
|
||||
if (!pkey)
|
||||
{
|
||||
fprintf(stderr, "crypto_cert_get_public_key: X509_get_pubkey() failed\n");
|
||||
fprintf(stderr, "%s: X509_get_pubkey() failed\n", __FUNCTION__);
|
||||
status = FALSE;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
length = i2d_PublicKey(pkey, NULL);
|
||||
|
||||
if (length < 1)
|
||||
{
|
||||
fprintf(stderr, "crypto_cert_get_public_key: i2d_PublicKey() failed\n");
|
||||
fprintf(stderr, "%s: i2d_PublicKey() failed\n", __FUNCTION__);
|
||||
status = FALSE;
|
||||
goto exit;
|
||||
}
|
||||
@ -215,13 +231,15 @@ exit:
|
||||
static int crypto_rsa_common(const BYTE* input, int length, UINT32 key_length, const BYTE* modulus, const BYTE* exponent, int exponent_size, BYTE* output)
|
||||
{
|
||||
BN_CTX* ctx;
|
||||
int output_length;
|
||||
int output_length = -1;
|
||||
BYTE* input_reverse;
|
||||
BYTE* modulus_reverse;
|
||||
BYTE* exponent_reverse;
|
||||
BIGNUM mod, exp, x, y;
|
||||
|
||||
input_reverse = (BYTE*) malloc(2 * key_length + exponent_size);
|
||||
if (!input_reverse)
|
||||
return -1;
|
||||
modulus_reverse = input_reverse + key_length;
|
||||
exponent_reverse = modulus_reverse + key_length;
|
||||
|
||||
@ -233,6 +251,8 @@ static int crypto_rsa_common(const BYTE* input, int length, UINT32 key_length, c
|
||||
crypto_reverse(input_reverse, length);
|
||||
|
||||
ctx = BN_CTX_new();
|
||||
if (!ctx)
|
||||
goto out_free_input_reverse;
|
||||
BN_init(&mod);
|
||||
BN_init(&exp);
|
||||
BN_init(&x);
|
||||
@ -254,6 +274,8 @@ static int crypto_rsa_common(const BYTE* input, int length, UINT32 key_length, c
|
||||
BN_free(&exp);
|
||||
BN_free(&mod);
|
||||
BN_CTX_free(ctx);
|
||||
|
||||
out_free_input_reverse:
|
||||
free(input_reverse);
|
||||
|
||||
return output_length;
|
||||
@ -322,11 +344,11 @@ char* crypto_cert_fingerprint(X509* xcert)
|
||||
|
||||
X509_digest(xcert, EVP_sha1(), fp, &fp_len);
|
||||
|
||||
fp_buffer = (char*) malloc(3 * fp_len);
|
||||
ZeroMemory(fp_buffer, 3 * fp_len);
|
||||
fp_buffer = (char*) calloc(3, fp_len);
|
||||
if (!fp_buffer)
|
||||
return NULL;
|
||||
|
||||
p = fp_buffer;
|
||||
|
||||
for (i = 0; i < (int) (fp_len - 1); i++)
|
||||
{
|
||||
sprintf(p, "%02x:", fp[i]);
|
||||
@ -527,6 +549,9 @@ rdpCertificateData* crypto_get_certificate_data(X509* xcert, char* hostname)
|
||||
rdpCertificateData* certdata;
|
||||
|
||||
fp = crypto_cert_fingerprint(xcert);
|
||||
if (!fp)
|
||||
return NULL;
|
||||
|
||||
certdata = certificate_data_new(hostname, fp);
|
||||
free(fp);
|
||||
|
||||
@ -542,6 +567,11 @@ void crypto_cert_print_info(X509* xcert)
|
||||
subject = crypto_cert_subject(xcert);
|
||||
issuer = crypto_cert_issuer(xcert);
|
||||
fp = crypto_cert_fingerprint(xcert);
|
||||
if (!fp)
|
||||
{
|
||||
fprintf(stderr, "%s: error computing fingerprint\n", __FUNCTION__);
|
||||
goto out_free_issuer;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Certificate details:\n");
|
||||
fprintf(stderr, "\tSubject: %s\n", subject);
|
||||
@ -551,7 +581,8 @@ void crypto_cert_print_info(X509* xcert)
|
||||
"the CA certificate in your certificate store, or the certificate has expired. "
|
||||
"Please look at the documentation on how to create local certificate store for a private CA.\n");
|
||||
|
||||
free(subject);
|
||||
free(issuer);
|
||||
free(fp);
|
||||
out_free_issuer:
|
||||
free(issuer);
|
||||
free(subject);
|
||||
}
|
||||
|
@ -332,7 +332,7 @@ WINPR_API LPSTR FilePatternFindNextWildcardA(LPCSTR lpPattern, DWORD* pFlags);
|
||||
WINPR_API int UnixChangeFileMode(const char* filename, int flags);
|
||||
|
||||
WINPR_API char* GetNamedPipeNameWithoutPrefixA(LPCSTR lpName);
|
||||
WINPR_API char* GetNamedPipeUnixDomainSocketBaseFilePathA();
|
||||
WINPR_API char* GetNamedPipeUnixDomainSocketBaseFilePathA(void);
|
||||
WINPR_API char* GetNamedPipeUnixDomainSocketFilePathA(LPCSTR lpName);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
Loading…
Reference in New Issue
Block a user