Skip to content

Commit

Permalink
Refactored certificate API:
Browse files Browse the repository at this point in the history
* Proper encapsulation
* known_hosts2 backend extended (storing PEM)
* New backend storing each host certificate in a file
  • Loading branch information
akallabeth committed May 11, 2021
1 parent c3171b9 commit b494a19
Show file tree
Hide file tree
Showing 21 changed files with 1,696 additions and 663 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ endif()

if(BUILD_TESTING)
set(EXPORT_ALL_SYMBOLS TRUE)
set(CTEST_OUTPUT_ON_FAILURE TRUE)
elseif(NOT DEFINED EXPORT_ALL_SYMBOLS)
set(EXPORT_ALL_SYMBOLS FALSE)
endif()
Expand Down
6 changes: 3 additions & 3 deletions channels/printer/client/printer_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ static char* get_printer_config_path(const rdpSettings* settings, const WCHAR* n
{
const char* path = settings->ConfigPath;
char* dir = GetCombinedPath(path, "printers");
char* bname = crypto_base64_encode((const BYTE*)name, (int)length);
char* bname = crypto_base64_encode((const BYTE*)name, length);
char* config = GetCombinedPath(dir, bname);

if (config && !PathFileExistsA(config))
Expand Down Expand Up @@ -197,8 +197,8 @@ static BOOL printer_read_setting(const char* path, prn_conf_t type, void** data,

if (rc && (lowSize <= INT_MAX))
{
int blen = 0;
crypto_base64_decode(fdata, (int)lowSize, (BYTE**)data, &blen);
size_t blen = 0;
crypto_base64_decode(fdata, lowSize, (BYTE**)data, &blen);

if (*data && (blen > 0))
*length = (UINT32)blen;
Expand Down
37 changes: 33 additions & 4 deletions client/common/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -540,7 +540,6 @@ DWORD client_cli_verify_certificate_ex(freerdp* instance, const char* host, UINT
const char* issuer, const char* fingerprint, DWORD flags)
{
const char* type = "RDP-Server";

if (flags & VERIFY_CERT_FLAG_GATEWAY)
type = "RDP-Gateway";

Expand All @@ -551,7 +550,17 @@ DWORD client_cli_verify_certificate_ex(freerdp* instance, const char* host, UINT
printf("\tCommon Name: %s\n", common_name);
printf("\tSubject: %s\n", subject);
printf("\tIssuer: %s\n", issuer);
printf("\tThumbprint: %s\n", fingerprint);
/* Newer versions of FreeRDP allow exposing the whole PEM by setting
* FreeRDP_CertificateCallbackPreferPEM to TRUE
*/
if (flags & VERIFY_CERT_FLAG_FP_IS_PEM)
{
printf("\t----------- Certificate --------------\n");
printf("%s\n", fingerprint);
printf("\t--------------------------------------\n");
}
else
printf("\tThumbprint: %s\n", fingerprint);

printf("The above X.509 certificate could not be verified, possibly because you do not have\n"
"the CA certificate in your certificate store, or the certificate has expired.\n"
Expand Down Expand Up @@ -641,12 +650,32 @@ DWORD client_cli_verify_changed_certificate_ex(freerdp* instance, const char* ho
printf("\tCommon Name: %s\n", common_name);
printf("\tSubject: %s\n", subject);
printf("\tIssuer: %s\n", issuer);
printf("\tThumbprint: %s\n", fingerprint);
/* Newer versions of FreeRDP allow exposing the whole PEM by setting
* FreeRDP_CertificateCallbackPreferPEM to TRUE
*/
if (flags & VERIFY_CERT_FLAG_FP_IS_PEM)
{
printf("\t----------- Certificate --------------\n");
printf("%s\n", fingerprint);
printf("\t--------------------------------------\n");
}
else
printf("\tThumbprint: %s\n", fingerprint);
printf("\n");
printf("Old Certificate details:\n");
printf("\tSubject: %s\n", old_subject);
printf("\tIssuer: %s\n", old_issuer);
printf("\tThumbprint: %s\n", old_fingerprint);
/* Newer versions of FreeRDP allow exposing the whole PEM by setting
* FreeRDP_CertificateCallbackPreferPEM to TRUE
*/
if (flags & VERIFY_CERT_FLAG_FP_IS_PEM)
{
printf("\t----------- Certificate --------------\n");
printf("%s\n", old_fingerprint);
printf("\t--------------------------------------\n");
}
else
printf("\tThumbprint: %s\n", old_fingerprint);
printf("\n");
if (flags & VERIFY_CERT_FLAG_MATCH_LEGACY_SHA1)
{
Expand Down
7 changes: 3 additions & 4 deletions client/common/cmdline.c
Original file line number Diff line number Diff line change
Expand Up @@ -3116,16 +3116,15 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
CommandLineSwitchCase(arg, "reconnect-cookie")
{
BYTE* base64 = NULL;
int length;
size_t length;
if (!arg->Value)
return COMMAND_LINE_ERROR_UNEXPECTED_VALUE;

crypto_base64_decode((const char*)(arg->Value), (int)strlen(arg->Value), &base64,
&length);
crypto_base64_decode((const char*)(arg->Value), strlen(arg->Value), &base64, &length);

if ((base64 != NULL) && (length == sizeof(ARC_SC_PRIVATE_PACKET)))
{
memcpy(settings->ServerAutoReconnectCookie, base64, (size_t)length);
memcpy(settings->ServerAutoReconnectCookie, base64, length);
}
else
{
Expand Down
63 changes: 33 additions & 30 deletions include/freerdp/crypto/certificate.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,43 +32,46 @@ typedef struct rdp_certificate_store rdpCertificateStore;
#include <winpr/print.h>
#include <winpr/stream.h>

struct rdp_certificate_data
{
char* hostname;
UINT16 port;
char* subject;
char* issuer;
char* fingerprint;
};

struct rdp_certificate_store
{
char* path;
char* file;
rdpSettings* settings;
rdpCertificateData* certificate_data;
};

#ifdef __cplusplus
extern "C"
{
#endif

FREERDP_API rdpCertificateData* certificate_data_new(const char* hostname, UINT16 port,
const char* subject, const char* issuer,
const char* fingerprint);
FREERDP_API rdpCertificateData* certificate_data_new(const char* hostname, UINT16 port);
FREERDP_API void certificate_data_free(rdpCertificateData* certificate_data);
FREERDP_API rdpCertificateStore* certificate_store_new(rdpSettings* settings);
FREERDP_API BOOL certificate_data_replace(rdpCertificateStore* certificate_store,
rdpCertificateData* certificate_data);

FREERDP_API const char* certificate_data_get_host(const rdpCertificateData* cert);
FREERDP_API UINT16 certificate_data_get_port(const rdpCertificateData* cert);

FREERDP_API BOOL certificate_data_set_pem(rdpCertificateData* cert, const char* pem);
FREERDP_API BOOL certificate_data_set_subject(rdpCertificateData* cert, const char* subject);
FREERDP_API BOOL certificate_data_set_issuer(rdpCertificateData* cert, const char* issuer);
FREERDP_API BOOL certificate_data_set_fingerprint(rdpCertificateData* cert,
const char* fingerprint);
FREERDP_API const char* certificate_data_get_pem(const rdpCertificateData* cert);
FREERDP_API const char* certificate_data_get_subject(const rdpCertificateData* cert);
FREERDP_API const char* certificate_data_get_issuer(const rdpCertificateData* cert);
FREERDP_API const char* certificate_data_get_fingerprint(const rdpCertificateData* cert);

FREERDP_API rdpCertificateStore* certificate_store_new(const rdpSettings* settings);
FREERDP_API void certificate_store_free(rdpCertificateStore* certificate_store);
FREERDP_API int certificate_data_match(rdpCertificateStore* certificate_store,
rdpCertificateData* certificate_data);
FREERDP_API BOOL certificate_data_print(rdpCertificateStore* certificate_store,
rdpCertificateData* certificate_data);
FREERDP_API BOOL certificate_get_stored_data(rdpCertificateStore* certificate_store,
rdpCertificateData* certificate_data,
char** subject, char** issuer, char** fingerprint);

FREERDP_API int certificate_store_contains_data(rdpCertificateStore* certificate_store,
const rdpCertificateData* certificate_data);
FREERDP_API rdpCertificateData*
certificate_store_load_data(rdpCertificateStore* certificate_store, const char* host,
UINT16 port);
FREERDP_API BOOL certificate_store_save_data(rdpCertificateStore* certificate_store,
const rdpCertificateData* certificate_data);
FREERDP_API BOOL certificate_store_remove_data(rdpCertificateStore* certificate_store,
const rdpCertificateData* certificate_data);

FREERDP_API const char*
certificate_store_get_hosts_file(const rdpCertificateStore* certificate_store);
FREERDP_API const char*
certificate_store_get_certs_path(const rdpCertificateStore* certificate_store);
FREERDP_API const char*
certificate_store_get_hosts_path(const rdpCertificateStore* certificate_store);

#ifdef __cplusplus
}
Expand Down
8 changes: 5 additions & 3 deletions include/freerdp/crypto/crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ extern "C"
FREERDP_API BYTE* crypto_cert_hash(X509* xcert, const char* hash, UINT32* length);
FREERDP_API char* crypto_cert_fingerprint_by_hash(X509* xcert, const char* hash);
FREERDP_API char* crypto_cert_fingerprint(X509* xcert);
FREERDP_API BYTE* crypto_cert_pem(X509* xcert, STACK_OF(X509) * chain, size_t* length);
FREERDP_API X509* crypto_cert_from_pem(const char* data, size_t length, BOOL fromFile);
FREERDP_API char* crypto_cert_subject(X509* xcert);
FREERDP_API char* crypto_cert_subject_common_name(X509* xcert, int* length);
FREERDP_API char** crypto_cert_get_dns_names(X509* xcert, int* count, int** lengths);
Expand Down Expand Up @@ -102,9 +104,9 @@ extern "C"
BYTE* output);
FREERDP_API void crypto_reverse(BYTE* data, int length);

FREERDP_API char* crypto_base64_encode(const BYTE* data, int length);
FREERDP_API void crypto_base64_decode(const char* enc_data, int length, BYTE** dec_data,
int* res_length);
FREERDP_API char* crypto_base64_encode(const BYTE* data, size_t length);
FREERDP_API void crypto_base64_decode(const char* enc_data, size_t length, BYTE** dec_data,
size_t* res_length);

#ifdef __cplusplus
}
Expand Down
15 changes: 10 additions & 5 deletions include/freerdp/freerdp.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ extern "C"
#define VERIFY_CERT_FLAG_CHANGED 0x40
#define VERIFY_CERT_FLAG_MISMATCH 0x80
#define VERIFY_CERT_FLAG_MATCH_LEGACY_SHA1 0x100
#define VERIFY_CERT_FLAG_FP_IS_PEM 0x200

/* Message types used by gateway messaging callback */
#define GATEWAY_MESSAGE_CONSENT 1
Expand All @@ -91,7 +92,8 @@ extern "C"
* @param common_name The certificate registered hostname.
* @param subject The common name of the certificate.
* @param issuer The issuer of the certificate.
* @param fingerprint The fingerprint of the certificate.
* @param fingerprint The fingerprint of the certificate (old) or the certificate in PEM
* format
* @param host_mismatch A flag indicating the certificate
* subject does not match the host connecting to.
*
Expand All @@ -110,7 +112,8 @@ extern "C"
* @param common_name The certificate registered hostname.
* @param subject The common name of the certificate.
* @param issuer The issuer of the certificate.
* @param fingerprint The fingerprint of the certificate.
* @param fingerprint The fingerprint of the certificate (old) or the certificate in PEM
* format (VERIFY_CERT_FLAG_FP_IS_PEM set)
* @param flags Flags of type VERIFY_CERT_FLAG*
*
* @return 1 to accept and store a certificate, 2 to accept
Expand Down Expand Up @@ -149,10 +152,12 @@ extern "C"
* @param common_name The certificate registered hostname.
* @param subject The common name of the new certificate.
* @param issuer The issuer of the new certificate.
* @param fingerprint The fingerprint of the new certificate.
* @param fingerprint The fingerprint of the new certificate (old) or the certificate in
* PEM format (VERIFY_CERT_FLAG_FP_IS_PEM set)
* @param old_subject The common name of the old certificate.
* @param old_issuer The issuer of the new certificate.
* @param old_fingerprint The fingerprint of the old certificate.
* @param old_fingerprint The fingerprint of the old certificate (old) or the certificate in
* PEM format (VERIFY_CERT_FLAG_FP_IS_PEM set)
* @param flags Flags of type VERIFY_CERT_FLAG*
*
* @return 1 to accept and store a certificate, 2 to accept
Expand All @@ -169,7 +174,7 @@ extern "C"
* a certificate.
*
* @param instance Pointer to the freerdp instance.
* @param data Pointer to certificate data in PEM format.
* @param data Pointer to certificate data (full chain) in PEM format.
* @param length The length of the certificate data.
* @param hostname The hostname connecting to.
* @param port The port connecting to.
Expand Down
6 changes: 5 additions & 1 deletion include/freerdp/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -700,6 +700,8 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL;
#define FreeRDP_AutoAcceptCertificate (1419)
#define FreeRDP_AutoDenyCertificate (1420)
#define FreeRDP_CertificateAcceptedFingerprints (1421)
#define FreeRDP_CertificateUseKnownHosts (1422)
#define FreeRDP_CertificateCallbackPreferPEM (1423)
#define FreeRDP_Workarea (1536)
#define FreeRDP_Fullscreen (1537)
#define FreeRDP_PercentScreen (1538)
Expand Down Expand Up @@ -1176,7 +1178,9 @@ struct rdp_settings
ALIGN64 BOOL AutoAcceptCertificate; /* 1419 */
ALIGN64 BOOL AutoDenyCertificate; /* 1420 */
ALIGN64 char* CertificateAcceptedFingerprints; /* 1421 */
UINT64 padding1472[1472 - 1422]; /* 1422 */
ALIGN64 BOOL CertificateUseKnownHosts; /* 1422 */
ALIGN64 BOOL CertificateCallbackPreferPEM; /* 1423 */
UINT64 padding1472[1472 - 1424]; /* 1424 */
UINT64 padding1536[1536 - 1472]; /* 1472 */

/**
Expand Down
14 changes: 14 additions & 0 deletions libfreerdp/common/settings_getters.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ BOOL freerdp_settings_get_bool(const rdpSettings* settings, size_t id)
case FreeRDP_BitmapCompressionDisabled:
return settings->BitmapCompressionDisabled;

case FreeRDP_CertificateCallbackPreferPEM:
return settings->CertificateCallbackPreferPEM;

case FreeRDP_CertificateUseKnownHosts:
return settings->CertificateUseKnownHosts;

case FreeRDP_ColorPointerFlag:
return settings->ColorPointerFlag;

Expand Down Expand Up @@ -602,6 +608,14 @@ BOOL freerdp_settings_set_bool(rdpSettings* settings, size_t id, BOOL val)
settings->BitmapCompressionDisabled = val;
break;

case FreeRDP_CertificateCallbackPreferPEM:
settings->CertificateCallbackPreferPEM = val;
break;

case FreeRDP_CertificateUseKnownHosts:
settings->CertificateUseKnownHosts = val;
break;

case FreeRDP_ColorPointerFlag:
settings->ColorPointerFlag = val;
break;
Expand Down
2 changes: 2 additions & 0 deletions libfreerdp/common/settings_str.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ static const struct settings_str_entry settings_map[] = {
{ FreeRDP_BitmapCachePersistEnabled, 0, "FreeRDP_BitmapCachePersistEnabled" },
{ FreeRDP_BitmapCacheV3Enabled, 0, "FreeRDP_BitmapCacheV3Enabled" },
{ FreeRDP_BitmapCompressionDisabled, 0, "FreeRDP_BitmapCompressionDisabled" },
{ FreeRDP_CertificateCallbackPreferPEM, 0, "FreeRDP_CertificateCallbackPreferPEM" },
{ FreeRDP_CertificateUseKnownHosts, 0, "FreeRDP_CertificateUseKnownHosts" },
{ FreeRDP_ColorPointerFlag, 0, "FreeRDP_ColorPointerFlag" },
{ FreeRDP_CompressionEnabled, 0, "FreeRDP_CompressionEnabled" },
{ FreeRDP_ConsoleSession, 0, "FreeRDP_ConsoleSession" },
Expand Down
4 changes: 2 additions & 2 deletions libfreerdp/core/gateway/ncacn_http.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ BOOL rpc_ncacn_http_send_in_channel_request(RpcChannel* inChannel)
BOOL rpc_ncacn_http_recv_in_channel_response(RpcChannel* inChannel, HttpResponse* response)
{
const char* token64 = NULL;
int ntlmTokenLength = 0;
size_t ntlmTokenLength = 0;
BYTE* ntlmTokenData = NULL;
rdpNtlm* ntlm;

Expand Down Expand Up @@ -259,7 +259,7 @@ BOOL rpc_ncacn_http_send_out_channel_request(RpcChannel* outChannel, BOOL replac
BOOL rpc_ncacn_http_recv_out_channel_response(RpcChannel* outChannel, HttpResponse* response)
{
const char* token64 = NULL;
int ntlmTokenLength = 0;
size_t ntlmTokenLength = 0;
BYTE* ntlmTokenData = NULL;
rdpNtlm* ntlm;

Expand Down
13 changes: 2 additions & 11 deletions libfreerdp/core/gateway/rdg.c
Original file line number Diff line number Diff line change
Expand Up @@ -1181,7 +1181,7 @@ static BOOL rdg_handle_ntlm_challenge(rdpNtlm* ntlm, HttpResponse* response)
BOOL continueNeeded = FALSE;
size_t len;
const char* token64 = NULL;
int ntlmTokenLength = 0;
size_t ntlmTokenLength = 0;
BYTE* ntlmTokenData = NULL;
long StatusCode;

Expand All @@ -1203,16 +1203,7 @@ static BOOL rdg_handle_ntlm_challenge(rdpNtlm* ntlm, HttpResponse* response)

len = strlen(token64);

if (len > INT_MAX)
return FALSE;

crypto_base64_decode(token64, (int)len, &ntlmTokenData, &ntlmTokenLength);

if (ntlmTokenLength < 0)
{
free(ntlmTokenData);
return FALSE;
}
crypto_base64_decode(token64, len, &ntlmTokenData, &ntlmTokenLength);

if (ntlmTokenData && ntlmTokenLength)
{
Expand Down
4 changes: 3 additions & 1 deletion libfreerdp/core/settings.c
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,9 @@ rdpSettings* freerdp_settings_new(DWORD flags)
!freerdp_settings_set_bool(settings, FreeRDP_DisableCredentialsDelegation, FALSE) ||
!freerdp_settings_set_uint32(settings, FreeRDP_AuthenticationLevel, 2) ||
!freerdp_settings_set_uint32(settings, FreeRDP_ChannelCount, 0) ||
!freerdp_settings_set_uint32(settings, FreeRDP_ChannelDefArraySize, 32))
!freerdp_settings_set_uint32(settings, FreeRDP_ChannelDefArraySize, 32) ||
!freerdp_settings_set_bool(settings, FreeRDP_CertificateUseKnownHosts, TRUE) ||
!freerdp_settings_set_bool(settings, FreeRDP_CertificateCallbackPreferPEM, FALSE))
goto out_fail;

settings->ChannelDefArray = (CHANNEL_DEF*)calloc(
Expand Down
2 changes: 2 additions & 0 deletions libfreerdp/core/test/settings_property_lists.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ static const size_t bool_list_indices[] = {
FreeRDP_BitmapCachePersistEnabled,
FreeRDP_BitmapCacheV3Enabled,
FreeRDP_BitmapCompressionDisabled,
FreeRDP_CertificateCallbackPreferPEM,
FreeRDP_CertificateUseKnownHosts,
FreeRDP_ColorPointerFlag,
FreeRDP_CompressionEnabled,
FreeRDP_ConsoleSession,
Expand Down
Loading

0 comments on commit b494a19

Please sign in to comment.