Merge pull request #3073 from davewheel/cert_key_in_memory

Allow to specify the raw content of crypto materials
This commit is contained in:
Hardening
2016-01-27 10:50:38 +01:00
10 changed files with 168 additions and 46 deletions

View File

@@ -89,7 +89,7 @@ struct rdp_tls
#endif
FREERDP_API int tls_connect(rdpTls* tls, BIO *underlying);
FREERDP_API BOOL tls_accept(rdpTls* tls, BIO *underlying, const char* cert_file, const char* privatekey_file);
FREERDP_API BOOL tls_accept(rdpTls* tls, BIO *underlying, rdpSettings *settings);
FREERDP_API BOOL tls_send_alert(rdpTls* tls);
FREERDP_API int tls_write_all(rdpTls* tls, const BYTE* data, int length);

View File

@@ -655,6 +655,10 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL;
#define FreeRDP_RdpServerRsaKey 1413
#define FreeRDP_RdpServerCertificate 1414
#define FreeRDP_ExternalCertificateManagement 1415
#define FreeRDP_CertificateContent 1416
#define FreeRDP_PrivateKeyContent 1417
#define FreeRDP_RdpKeyContent 1418
#define FreeRDP_Workarea 1536
#define FreeRDP_Fullscreen 1537
#define FreeRDP_PercentScreen 1538
@@ -1071,7 +1075,10 @@ struct rdp_settings
ALIGN64 rdpRsaKey* RdpServerRsaKey; /* 1413 */
ALIGN64 rdpCertificate* RdpServerCertificate; /* 1414 */
ALIGN64 BOOL ExternalCertificateManagement; /* 1415 */
UINT64 padding1472[1472 - 1416]; /* 1416 */
ALIGN64 char *CertificateContent; /* 1416 */
ALIGN64 char *PrivateKeyContent; /* 1417 */
ALIGN64 char* RdpKeyContent; /* 1418 */
UINT64 padding1472[1472 - 1419]; /* 1419 */
UINT64 padding1536[1536 - 1472]; /* 1472 */
/**

View File

@@ -2381,6 +2381,15 @@ char* freerdp_get_param_string(rdpSettings* settings, int id)
case FreeRDP_RdpKeyFile:
return settings->RdpKeyFile;
case FreeRDP_CertificateContent:
return settings->CertificateContent;
case FreeRDP_PrivateKeyContent:
return settings->PrivateKeyContent;
case FreeRDP_RdpKeyContent:
return settings->RdpKeyContent;
case FreeRDP_WindowTitle:
return settings->WindowTitle;
@@ -2551,6 +2560,18 @@ int freerdp_set_param_string(rdpSettings* settings, int id, const char* param)
tmp = &settings->PrivateKeyFile;
break;
case FreeRDP_CertificateContent:
tmp = &settings->CertificateContent;
break;
case FreeRDP_PrivateKeyContent:
tmp = &settings->PrivateKeyContent;
break;
case FreeRDP_RdpKeyContent:
tmp = &settings->RdpKeyContent;
break;
case FreeRDP_RdpKeyFile:
tmp = &settings->RdpKeyFile;
break;

View File

@@ -662,54 +662,22 @@ BOOL certificate_read_server_certificate(rdpCertificate* certificate, BYTE* serv
return ret;
}
rdpRsaKey* key_new(const char* keyfile)
rdpRsaKey* key_new_from_content(const char *keycontent, const char *keyfile)
{
BIO* bio = NULL;
FILE* fp = NULL;
RSA* rsa = NULL;
int length;
BYTE* buffer = NULL;
rdpRsaKey* key = NULL;
key = (rdpRsaKey*) calloc(1, sizeof(rdpRsaKey));
if (!key)
return NULL;
fp = fopen(keyfile, "r+b");
if (!fp)
{
WLog_ERR(TAG, "unable to open RSA key file %s: %s.", keyfile, strerror(errno));
goto out_free;
}
if (fseek(fp, 0, SEEK_END) < 0)
goto out_free;
if ((length = ftell(fp)) < 0)
goto out_free;
if (fseek(fp, 0, SEEK_SET) < 0)
goto out_free;
buffer = (BYTE*) malloc(length);
if (!buffer)
goto out_free;
if (fread((void*) buffer, length, 1, fp) != 1)
goto out_free;
fclose(fp);
fp = NULL;
bio = BIO_new_mem_buf((void*) buffer, length);
bio = BIO_new_mem_buf((void *)keycontent, strlen(keycontent));
if (!bio)
goto out_free;
rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL);
BIO_free(bio);
free(buffer);
buffer = NULL;
if (!rsa)
{
@@ -764,11 +732,50 @@ out_free_modulus:
free(key->Modulus);
out_free_rsa:
RSA_free(rsa);
out_free:
free(key);
return NULL;
}
rdpRsaKey* key_new(const char* keyfile)
{
FILE* fp = NULL;
int length;
char* buffer = NULL;
rdpRsaKey* key = NULL;
fp = fopen(keyfile, "r+b");
if (!fp)
{
WLog_ERR(TAG, "unable to open RSA key file %s: %s.", keyfile, strerror(errno));
goto out_free;
}
if (fseek(fp, 0, SEEK_END) < 0)
goto out_free;
if ((length = ftell(fp)) < 0)
goto out_free;
if (fseek(fp, 0, SEEK_SET) < 0)
goto out_free;
buffer = (char *)malloc(length + 1);
if (!buffer)
goto out_free;
if (fread((void*) buffer, length, 1, fp) != 1)
goto out_free;
fclose(fp);
buffer[length] = '\0';
key = key_new_from_content(buffer, keyfile);
free(buffer);
return key;
out_free:
if (fp)
fclose(fp);
free(buffer);
free(key);
return NULL;
}

View File

@@ -59,6 +59,7 @@ rdpCertificate* certificate_new(void);
void certificate_free(rdpCertificate* certificate);
rdpRsaKey* key_new(const char *keyfile);
rdpRsaKey* key_new_from_content(const char *keycontent, const char *keyfile);
void key_free(rdpRsaKey* key);
#define CERTIFICATE_TAG FREERDP_TAG("core.certificate")

View File

@@ -1086,7 +1086,7 @@ BOOL nego_send_negotiation_response(rdpNego* nego)
settings->EncryptionLevel = ENCRYPTION_LEVEL_NONE;
}
if (!settings->RdpServerRsaKey && !settings->RdpKeyFile)
if (!settings->RdpServerRsaKey && !settings->RdpKeyFile && !settings->RdpKeyContent)
{
WLog_ERR(TAG, "Missing server certificate");
return FALSE;

View File

@@ -219,13 +219,21 @@ static BOOL freerdp_peer_initialize(freerdp_peer* client)
if (settings->RdpKeyFile)
{
settings->RdpServerRsaKey = key_new(settings->RdpKeyFile);
if (!settings->RdpServerRsaKey)
{
WLog_ERR(TAG, "invalid RDP key file %s", settings->RdpKeyFile);
return FALSE;
}
}
else if (settings->RdpKeyContent)
{
settings->RdpServerRsaKey = key_new_from_content(settings->RdpKeyContent, NULL);
if (!settings->RdpServerRsaKey)
{
WLog_ERR(TAG, "invalid RDP key content");
return FALSE;
}
}
return TRUE;
}

View File

@@ -598,6 +598,9 @@ rdpSettings* freerdp_settings_clone(rdpSettings* settings)
CHECKED_STRDUP(CertificateFile); /* 1410 */
CHECKED_STRDUP(PrivateKeyFile); /* 1411 */
CHECKED_STRDUP(RdpKeyFile); /* 1412 */
CHECKED_STRDUP(CertificateContent); /* 1416 */
CHECKED_STRDUP(PrivateKeyContent); /* 1417 */
CHECKED_STRDUP(RdpKeyContent); /* 1418 */
CHECKED_STRDUP(WindowTitle); /* 1542 */
CHECKED_STRDUP(WmClass); /* 1549 */
CHECKED_STRDUP(ComputerName); /* 1664 */
@@ -925,6 +928,9 @@ void freerdp_settings_free(rdpSettings* settings)
free(settings->ServerCertificate);
free(settings->RdpKeyFile);
certificate_free(settings->RdpServerCertificate);
free(settings->CertificateContent);
free(settings->PrivateKeyContent);
free(settings->RdpKeyContent);
free(settings->ClientAutoReconnectCookie);
free(settings->ServerAutoReconnectCookie);
free(settings->ClientTimeZone);

View File

@@ -322,7 +322,7 @@ BOOL transport_accept_tls(rdpTransport* transport)
transport->layer = TRANSPORT_LAYER_TLS;
if (!tls_accept(transport->tls, transport->frontBio, settings->CertificateFile, settings->PrivateKeyFile))
if (!tls_accept(transport->tls, transport->frontBio, settings))
return FALSE;
transport->frontBio = transport->tls->bio;
@@ -340,7 +340,7 @@ BOOL transport_accept_nla(rdpTransport* transport)
transport->layer = TRANSPORT_LAYER_TLS;
if (!tls_accept(transport->tls, transport->frontBio, settings->CertificateFile, settings->PrivateKeyFile))
if (!tls_accept(transport->tls, transport->frontBio, settings))
return FALSE;
transport->frontBio = transport->tls->bio;

View File

@@ -823,9 +823,12 @@ static void tls_openssl_tlsext_debug_callback(SSL *s, int client_server,
}
#endif
BOOL tls_accept(rdpTls* tls, BIO* underlying, const char* cert_file, const char* privatekey_file)
BOOL tls_accept(rdpTls* tls, BIO* underlying, rdpSettings *settings)
{
long options = 0;
BIO *bio;
RSA *rsa;
X509 *x509;
/**
* SSL_OP_NO_SSLv2:
@@ -867,16 +870,85 @@ BOOL tls_accept(rdpTls* tls, BIO* underlying, const char* cert_file, const char*
if (!tls_prepare(tls, underlying, SSLv23_server_method(), options, FALSE))
return FALSE;
if (SSL_use_RSAPrivateKey_file(tls->ssl, privatekey_file, SSL_FILETYPE_PEM) <= 0)
if (settings->PrivateKeyFile)
{
WLog_ERR(TAG, "SSL_CTX_use_RSAPrivateKey_file failed");
WLog_ERR(TAG, "PrivateKeyFile: %s", privatekey_file);
bio = BIO_new_file(settings->PrivateKeyFile, "rb+");
if (!bio)
{
WLog_ERR(TAG, "BIO_new_file failed for private key %s", settings->PrivateKeyFile);
return FALSE;
}
}
else if (settings->PrivateKeyContent)
{
bio = BIO_new_mem_buf(settings->PrivateKeyContent, strlen(settings->PrivateKeyContent));
if (!bio)
{
WLog_ERR(TAG, "BIO_new_mem_buf failed for private key");
return FALSE;
}
}
else
{
WLog_ERR(TAG, "no private key defined");
return FALSE;
}
if (SSL_use_certificate_file(tls->ssl, cert_file, SSL_FILETYPE_PEM) <= 0)
rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL);
BIO_free(bio);
if (!rsa)
{
WLog_ERR(TAG, "invalid private key");
return FALSE;
}
if (SSL_use_RSAPrivateKey(tls->ssl, rsa) <= 0)
{
WLog_ERR(TAG, "SSL_CTX_use_RSAPrivateKey_file failed");
RSA_free(rsa);
return FALSE;
}
if (settings->CertificateFile)
{
bio = BIO_new_file(settings->CertificateFile, "rb+");
if (!bio)
{
WLog_ERR(TAG, "BIO_new_file failed for certificate %s", settings->CertificateFile);
return FALSE;
}
}
else if (settings->CertificateContent)
{
bio = BIO_new_mem_buf(settings->CertificateContent, strlen(settings->CertificateContent));
if (!bio)
{
WLog_ERR(TAG, "BIO_new_mem_buf failed for certificate");
return FALSE;
}
}
else
{
WLog_ERR(TAG, "no certificate defined");
return FALSE;
}
x509 = PEM_read_bio_X509(bio, NULL, NULL, 0);
BIO_free(bio);
if (!x509)
{
WLog_ERR(TAG, "invalid certificate");
return FALSE;
}
if (SSL_use_certificate(tls->ssl, x509) <= 0)
{
WLog_ERR(TAG, "SSL_use_certificate_file failed");
X509_free(x509);
return FALSE;
}