mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-15 00:44:19 +09:00
Merge pull request #3073 from davewheel/cert_key_in_memory
Allow to specify the raw content of crypto materials
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user