Merge pull request #5085 from akallabeth/cert_callbacks_update
Refactored Certificate callbacks (but keep compatible)
This commit is contained in:
commit
8c7f8eb395
@ -107,11 +107,9 @@ static BOOL tf_pre_connect(freerdp* instance)
|
||||
/* Optional OS identifier sent to server */
|
||||
settings->OsMajorType = OSMAJORTYPE_UNIX;
|
||||
settings->OsMinorType = OSMINORTYPE_NATIVE_XSERVER;
|
||||
|
||||
/* settings->OrderSupport is initialized at this point.
|
||||
* Only override it if you plan to implement custom order
|
||||
* callbacks or deactiveate certain features. */
|
||||
|
||||
/* Register the channel listeners.
|
||||
* They are required to set up / tear down channels if they are loaded. */
|
||||
PubSub_SubscribeChannelConnected(instance->context->pubSub,
|
||||
@ -262,8 +260,8 @@ static BOOL tf_client_new(freerdp* instance, rdpContext* context)
|
||||
instance->PostDisconnect = tf_post_disconnect;
|
||||
instance->Authenticate = client_cli_authenticate;
|
||||
instance->GatewayAuthenticate = client_cli_gw_authenticate;
|
||||
instance->VerifyCertificate = client_cli_verify_certificate;
|
||||
instance->VerifyChangedCertificate = client_cli_verify_changed_certificate;
|
||||
instance->VerifyCertificateEx = client_cli_verify_certificate_ex;
|
||||
instance->VerifyChangedCertificateEx = client_cli_verify_changed_certificate_ex;
|
||||
instance->LogonErrorInfo = tf_logon_error_info;
|
||||
/* TODO: Client display set up */
|
||||
return TRUE;
|
||||
|
@ -386,8 +386,8 @@ static BOOL wlf_client_new(freerdp* instance, rdpContext* context)
|
||||
instance->PostDisconnect = wl_post_disconnect;
|
||||
instance->Authenticate = client_cli_authenticate;
|
||||
instance->GatewayAuthenticate = client_cli_gw_authenticate;
|
||||
instance->VerifyCertificate = client_cli_verify_certificate;
|
||||
instance->VerifyChangedCertificate = client_cli_verify_changed_certificate;
|
||||
instance->VerifyCertificateEx = client_cli_verify_certificate_ex;
|
||||
instance->VerifyChangedCertificateEx = client_cli_verify_changed_certificate_ex;
|
||||
instance->LogonErrorInfo = wlf_logon_error_info;
|
||||
wfl->display = UwacOpenDisplay(NULL, &status);
|
||||
|
||||
|
@ -1763,8 +1763,8 @@ static BOOL xfreerdp_client_new(freerdp* instance, rdpContext* context)
|
||||
instance->PostDisconnect = xf_post_disconnect;
|
||||
instance->Authenticate = client_cli_authenticate;
|
||||
instance->GatewayAuthenticate = client_cli_gw_authenticate;
|
||||
instance->VerifyCertificate = client_cli_verify_certificate;
|
||||
instance->VerifyChangedCertificate = client_cli_verify_changed_certificate;
|
||||
instance->VerifyCertificateEx = client_cli_verify_certificate_ex;
|
||||
instance->VerifyChangedCertificateEx = client_cli_verify_changed_certificate_ex;
|
||||
instance->LogonErrorInfo = xf_logon_error_info;
|
||||
PubSub_SubscribeTerminate(context->pubSub,
|
||||
xf_TerminateEventHandler);
|
||||
|
@ -506,6 +506,7 @@ static DWORD client_cli_accept_certificate(rdpSettings* settings)
|
||||
* when the connection requires it.
|
||||
* This function will actually be called by tls_verify_certificate().
|
||||
* @see rdp_client_connect() and tls_connect()
|
||||
* @deprecated Use client_cli_verify_certificate_ex
|
||||
* @param instance - pointer to the rdp_freerdp structure that contains the connection settings
|
||||
* @param common_name
|
||||
* @param subject
|
||||
@ -518,6 +519,7 @@ DWORD client_cli_verify_certificate(freerdp* instance, const char* common_name,
|
||||
const char* subject, const char* issuer,
|
||||
const char* fingerprint, BOOL host_mismatch)
|
||||
{
|
||||
printf("WARNING: This callback is deprecated, migrate to client_cli_verify_certificate_ex\n");
|
||||
printf("Certificate details:\n");
|
||||
printf("\tSubject: %s\n", subject);
|
||||
printf("\tIssuer: %s\n", issuer);
|
||||
@ -528,10 +530,50 @@ DWORD client_cli_verify_certificate(freerdp* instance, const char* common_name,
|
||||
return client_cli_accept_certificate(instance->settings);
|
||||
}
|
||||
|
||||
/** Callback set in the rdp_freerdp structure, and used to make a certificate validation
|
||||
* when the connection requires it.
|
||||
* This function will actually be called by tls_verify_certificate().
|
||||
* @see rdp_client_connect() and tls_connect()
|
||||
* @param instance pointer to the rdp_freerdp structure that contains the connection settings
|
||||
* @param host The host currently connecting to
|
||||
* @param port The port currently connecting to
|
||||
* @param common_name The common name of the certificate, should match host or an alias of it
|
||||
* @param subject The subject of the certificate
|
||||
* @param issuer The certificate issuer name
|
||||
* @param fingerprint The fingerprint of the certificate
|
||||
* @param flags See VERIFY_CERT_FLAG_* for possible values.
|
||||
*
|
||||
* @return 1 if the certificate is trusted, 2 if temporary trusted, 0 otherwise.
|
||||
*/
|
||||
DWORD client_cli_verify_certificate_ex(freerdp* instance, const char* host, UINT16 port,
|
||||
const char* common_name,
|
||||
const char* subject, const char* issuer,
|
||||
const char* fingerprint, DWORD flags)
|
||||
{
|
||||
const char* type = "RDP-Server";
|
||||
|
||||
if (flags & VERIFY_CERT_FLAG_GATEWAY)
|
||||
type = "RDP-Gateway";
|
||||
|
||||
if (flags & VERIFY_CERT_FLAG_REDIRECT)
|
||||
type = "RDP-Redirect";
|
||||
|
||||
printf("Certificate details for %s:%"PRIu16" (%s):\n", host, port, type);
|
||||
printf("\tCommon Name: %s\n", common_name);
|
||||
printf("\tSubject: %s\n", subject);
|
||||
printf("\tIssuer: %s\n", issuer);
|
||||
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"
|
||||
"Please look at the OpenSSL documentation on how to add a private CA to the store.\n");
|
||||
return client_cli_accept_certificate(instance->settings);
|
||||
}
|
||||
|
||||
/** Callback set in the rdp_freerdp structure, and used to make a certificate validation
|
||||
* when a stored certificate does not match the remote counterpart.
|
||||
* This function will actually be called by tls_verify_certificate().
|
||||
* @see rdp_client_connect() and tls_connect()
|
||||
* @deprecated Use client_cli_verify_changed_certificate_ex
|
||||
* @param instance - pointer to the rdp_freerdp structure that contains the connection settings
|
||||
* @param common_name
|
||||
* @param subject
|
||||
@ -549,6 +591,7 @@ DWORD client_cli_verify_changed_certificate(freerdp* instance,
|
||||
const char* old_subject, const char* old_issuer,
|
||||
const char* old_fingerprint)
|
||||
{
|
||||
printf("WARNING: This callback is deprecated, migrate to client_cli_verify_changed_certificate_ex\n");
|
||||
printf("!!! Certificate has changed !!!\n");
|
||||
printf("\n");
|
||||
printf("New Certificate details:\n");
|
||||
@ -567,6 +610,59 @@ DWORD client_cli_verify_changed_certificate(freerdp* instance,
|
||||
return client_cli_accept_certificate(instance->settings);
|
||||
}
|
||||
|
||||
/** Callback set in the rdp_freerdp structure, and used to make a certificate validation
|
||||
* when a stored certificate does not match the remote counterpart.
|
||||
* This function will actually be called by tls_verify_certificate().
|
||||
* @see rdp_client_connect() and tls_connect()
|
||||
* @param instance pointer to the rdp_freerdp structure that contains the connection settings
|
||||
* @param host The host currently connecting to
|
||||
* @param port The port currently connecting to
|
||||
* @param common_name The common name of the certificate, should match host or an alias of it
|
||||
* @param subject The subject of the certificate
|
||||
* @param issuer The certificate issuer name
|
||||
* @param fingerprint The fingerprint of the certificate
|
||||
* @param old_subject The subject of the previous certificate
|
||||
* @param old_issuer The previous certificate issuer name
|
||||
* @param old_fingerprint The fingerprint of the previous certificate
|
||||
* @param flags See VERIFY_CERT_FLAG_* for possible values.
|
||||
*
|
||||
* @return 1 if the certificate is trusted, 2 if temporary trusted, 0 otherwise.
|
||||
*/
|
||||
DWORD client_cli_verify_changed_certificate_ex(freerdp* instance,
|
||||
const char* host, UINT16 port,
|
||||
const char* common_name,
|
||||
const char* subject, const char* issuer,
|
||||
const char* fingerprint,
|
||||
const char* old_subject, const char* old_issuer,
|
||||
const char* old_fingerprint, DWORD flags)
|
||||
{
|
||||
const char* type = "RDP-Server";
|
||||
|
||||
if (flags & VERIFY_CERT_FLAG_GATEWAY)
|
||||
type = "RDP-Gateway";
|
||||
|
||||
if (flags & VERIFY_CERT_FLAG_REDIRECT)
|
||||
type = "RDP-Redirect";
|
||||
|
||||
printf("!!!Certificate for %s:%"PRIu16" (%s) has changed!!!\n", host, port, type);
|
||||
printf("\n");
|
||||
printf("New Certificate details:\n");
|
||||
printf("\tCommon Name: %s\n", common_name);
|
||||
printf("\tSubject: %s\n", subject);
|
||||
printf("\tIssuer: %s\n", issuer);
|
||||
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);
|
||||
printf("\n");
|
||||
printf("The above X.509 certificate does not match the certificate used for previous connections.\n"
|
||||
"This may indicate that the certificate has been tampered with.\n"
|
||||
"Please contact the administrator of the RDP server and clarify.\n");
|
||||
return client_cli_accept_certificate(instance->settings);
|
||||
}
|
||||
|
||||
BOOL client_auto_reconnect(freerdp* instance)
|
||||
{
|
||||
return client_auto_reconnect_ex(instance, NULL);
|
||||
|
@ -107,11 +107,25 @@ FREERDP_API DWORD client_cli_verify_certificate(freerdp* instance, const char* c
|
||||
const char* subject, const char* issuer,
|
||||
const char* fingerprint, BOOL host_mismatch);
|
||||
|
||||
FREERDP_API DWORD client_cli_verify_certificate_ex(freerdp* instance,
|
||||
const char* host, UINT16 port,
|
||||
const char* common_name,
|
||||
const char* subject, const char* issuer,
|
||||
const char* fingerprint, DWORD flags);
|
||||
|
||||
FREERDP_API DWORD client_cli_verify_changed_certificate(freerdp* instance, const char* common_name,
|
||||
const char* subject, const char* issuer,
|
||||
const char* fingerprint,
|
||||
const char* old_subject, const char* old_issuer,
|
||||
const char* old_fingerprint);
|
||||
|
||||
FREERDP_API DWORD client_cli_verify_changed_certificate_ex(freerdp* instance,
|
||||
const char* host, UINT16 port,
|
||||
const char* common_name,
|
||||
const char* subject, const char* issuer,
|
||||
const char* fingerprint,
|
||||
const char* old_subject, const char* old_issuer,
|
||||
const char* old_fingerprint, DWORD flags);
|
||||
FREERDP_API BOOL client_auto_reconnect(freerdp* instance);
|
||||
FREERDP_API BOOL client_auto_reconnect_ex(freerdp* instance,
|
||||
BOOL(*window_events)(freerdp* instance));
|
||||
|
@ -51,35 +51,35 @@ struct rdp_certificate_store
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
FREERDP_API rdpCertificateData* certificate_data_new(
|
||||
char* hostname, UINT16 port, char* subject,
|
||||
char* issuer, char* fingerprint);
|
||||
const char* hostname, UINT16 port, const char* subject,
|
||||
const char* issuer, const char* fingerprint);
|
||||
FREERDP_API void certificate_data_free(
|
||||
rdpCertificateData* certificate_data);
|
||||
rdpCertificateData* certificate_data);
|
||||
FREERDP_API rdpCertificateStore* certificate_store_new(
|
||||
rdpSettings* settings);
|
||||
rdpSettings* settings);
|
||||
FREERDP_API BOOL certificate_data_replace(
|
||||
rdpCertificateStore* certificate_store,
|
||||
rdpCertificateData* certificate_data);
|
||||
rdpCertificateStore* certificate_store,
|
||||
rdpCertificateData* certificate_data);
|
||||
FREERDP_API void certificate_store_free(
|
||||
rdpCertificateStore* certificate_store);
|
||||
rdpCertificateStore* certificate_store);
|
||||
FREERDP_API int certificate_data_match(
|
||||
rdpCertificateStore* certificate_store,
|
||||
rdpCertificateData* certificate_data);
|
||||
rdpCertificateStore* certificate_store,
|
||||
rdpCertificateData* certificate_data);
|
||||
FREERDP_API BOOL certificate_data_print(
|
||||
rdpCertificateStore* certificate_store,
|
||||
rdpCertificateData* certificate_data);
|
||||
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);
|
||||
rdpCertificateStore* certificate_store,
|
||||
rdpCertificateData* certificate_data,
|
||||
char** subject, char** issuer,
|
||||
char** fingerprint);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FREERDP_CRYPTO_CERTIFICATE_H */
|
||||
|
@ -72,10 +72,10 @@ Note: email and upn amongst others are also alt_names,
|
||||
but the old crypto_cert_get_alt_names returned only the dns_names
|
||||
*/
|
||||
FREERDP_API char** crypto_cert_subject_alt_name(X509* xcert, int* count, int** lengths);
|
||||
FREERDP_API void crypto_cert_subject_alt_name_free(int count, int *lengths, char** alt_names);
|
||||
FREERDP_API void crypto_cert_subject_alt_name_free(int count, int* lengths, char** alt_names);
|
||||
|
||||
FREERDP_API BOOL x509_verify_certificate(CryptoCert cert, char* certificate_store_path);
|
||||
FREERDP_API rdpCertificateData* crypto_get_certificate_data(X509* xcert, char* hostname,
|
||||
FREERDP_API BOOL x509_verify_certificate(CryptoCert cert, const char* certificate_store_path);
|
||||
FREERDP_API rdpCertificateData* crypto_get_certificate_data(X509* xcert, const char* hostname,
|
||||
UINT16 port);
|
||||
FREERDP_API BOOL crypto_cert_get_public_key(CryptoCert cert, BYTE** PublicKey,
|
||||
DWORD* PublicKeyLength);
|
||||
|
@ -96,16 +96,6 @@ FREERDP_API int tls_write_all(rdpTls* tls, const BYTE* data, int length);
|
||||
|
||||
FREERDP_API int tls_set_alert_code(rdpTls* tls, int level, int description);
|
||||
|
||||
FREERDP_API BOOL tls_match_hostname(char* pattern, int pattern_length, char* hostname);
|
||||
FREERDP_API int tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int port);
|
||||
FREERDP_API void tls_print_certificate_error(char* hostname, UINT16 port,
|
||||
char* fingerprint, char* hosts_file);
|
||||
FREERDP_API void tls_print_certificate_name_mismatch_error(
|
||||
char* hostname, UINT16 port, char* common_name, char** alt_names,
|
||||
int alt_names_count);
|
||||
|
||||
FREERDP_API BOOL tls_print_error(char* func, SSL* connection, int value);
|
||||
|
||||
FREERDP_API rdpTls* tls_new(rdpSettings* settings);
|
||||
FREERDP_API void tls_free(rdpTls* tls);
|
||||
|
||||
|
@ -59,6 +59,14 @@ typedef RDP_CLIENT_ENTRY_POINTS_V1 RDP_CLIENT_ENTRY_POINTS;
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Flags used by certificate callbacks */
|
||||
#define VERIFY_CERT_FLAG_NONE 0x00
|
||||
#define VERIFY_CERT_FLAG_LEGACY 0x02
|
||||
#define VERIFY_CERT_FLAG_REDIRECT 0x10
|
||||
#define VERIFY_CERT_FLAG_GATEWAY 0x20
|
||||
#define VERIFY_CERT_FLAG_CHANGED 0x40
|
||||
#define VERIFY_CERT_FLAG_MISMATCH 0x80
|
||||
|
||||
typedef BOOL (*pContextNew)(freerdp* instance, rdpContext* context);
|
||||
typedef void (*pContextFree)(freerdp* instance, rdpContext* context);
|
||||
|
||||
@ -71,6 +79,7 @@ typedef BOOL (*pAuthenticate)(freerdp* instance, char** username,
|
||||
/** @brief Callback used if user interaction is required to accept
|
||||
* an unknown certificate.
|
||||
*
|
||||
* @deprecated Use pVerifyCertificateEx
|
||||
* @param common_name The certificate registered hostname.
|
||||
* @param subject The common name of the certificate.
|
||||
* @param issuer The issuer of the certificate.
|
||||
@ -88,9 +97,33 @@ typedef DWORD (*pVerifyCertificate)(freerdp* instance,
|
||||
const char* fingerprint,
|
||||
BOOL host_mismatch);
|
||||
|
||||
/** @brief Callback used if user interaction is required to accept
|
||||
* an unknown certificate.
|
||||
*
|
||||
* @param host The hostname connecting to.
|
||||
* @param port The port connecting to.
|
||||
* @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 flags Flags of type VERIFY_CERT_FLAG*
|
||||
*
|
||||
* @return 1 to accept and store a certificate, 2 to accept
|
||||
* a certificate only for this session, 0 otherwise.
|
||||
*/
|
||||
typedef DWORD (*pVerifyCertificateEx)(freerdp* instance,
|
||||
const char* host,
|
||||
UINT16 port,
|
||||
const char* common_name,
|
||||
const char* subject,
|
||||
const char* issuer,
|
||||
const char* fingerprint,
|
||||
DWORD flags);
|
||||
|
||||
/** @brief Callback used if user interaction is required to accept
|
||||
* a changed certificate.
|
||||
*
|
||||
* @deprecated Use pVerifyChangedCertificateEx
|
||||
* @param common_name The certificate registered hostname.
|
||||
* @param subject The common name of the new certificate.
|
||||
* @param issuer The issuer of the new certificate.
|
||||
@ -111,9 +144,53 @@ typedef DWORD (*pVerifyChangedCertificate)(freerdp* instance,
|
||||
const char* old_subject,
|
||||
const char* old_issuer,
|
||||
const char* old_fingerprint);
|
||||
typedef int (*pVerifyX509Certificate)(freerdp* instance, BYTE* data,
|
||||
int length, const char* hostname,
|
||||
int port, DWORD flags);
|
||||
|
||||
/** @brief Callback used if user interaction is required to accept
|
||||
* a changed certificate.
|
||||
*
|
||||
* @param host The hostname connecting to.
|
||||
* @param port The port connecting to.
|
||||
* @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 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 flags Flags of type VERIFY_CERT_FLAG*
|
||||
*
|
||||
* @return 1 to accept and store a certificate, 2 to accept
|
||||
* a certificate only for this session, 0 otherwise.
|
||||
*/
|
||||
|
||||
typedef DWORD (*pVerifyChangedCertificateEx)(freerdp* instance,
|
||||
const char* host,
|
||||
UINT16 port,
|
||||
const char* common_name,
|
||||
const char* subject,
|
||||
const char* issuer,
|
||||
const char* new_fingerprint,
|
||||
const char* old_subject,
|
||||
const char* old_issuer,
|
||||
const char* old_fingerprint,
|
||||
DWORD flags);
|
||||
|
||||
/** @brief Callback used if user interaction is required to accept
|
||||
* a certificate.
|
||||
*
|
||||
* @param instance Pointer to the freerdp instance.
|
||||
* @param data Pointer to certificate data in PEM format.
|
||||
* @param length The length of the certificate data.
|
||||
* @param hostname The hostname connecting to.
|
||||
* @param port The port connecting to.
|
||||
* @param flags Flags of type VERIFY_CERT_FLAG*
|
||||
*
|
||||
* @return 1 to accept and store a certificate, 2 to accept
|
||||
* a certificate only for this session, 0 otherwise.
|
||||
*/
|
||||
typedef int (*pVerifyX509Certificate)(freerdp* instance, const BYTE* data,
|
||||
size_t length, const char* hostname,
|
||||
UINT16 port, DWORD flags);
|
||||
|
||||
typedef int (*pLogonErrorInfo)(freerdp* instance, UINT32 data, UINT32 type);
|
||||
|
||||
@ -274,11 +351,12 @@ struct rdp_freerdp
|
||||
It is used to get the username/password when it was not provided at connection time. */
|
||||
ALIGN64 pVerifyCertificate VerifyCertificate; /**< (offset 51)
|
||||
Callback for certificate validation.
|
||||
Used to verify that an unknown certificate is trusted. */
|
||||
Used to verify that an unknown certificate is trusted.
|
||||
DEPRECATED: Use VerifyChangedCertificateEx*/
|
||||
ALIGN64 pVerifyChangedCertificate VerifyChangedCertificate; /**< (offset 52)
|
||||
Callback for changed certificate validation.
|
||||
Used when a certificate differs from stored fingerprint.
|
||||
If returns TRUE, the new fingerprint will be trusted and old thrown out. */
|
||||
DEPRECATED: Use VerifyChangedCertificateEx */
|
||||
|
||||
ALIGN64 pVerifyX509Certificate
|
||||
VerifyX509Certificate; /**< (offset 53) Callback for X509 certificate verification (PEM format) */
|
||||
@ -305,7 +383,13 @@ struct rdp_freerdp
|
||||
This is called by freerdp_channel_process() (if not NULL).
|
||||
Clients will typically use a function that calls freerdp_channels_data() to perform the needed tasks. */
|
||||
|
||||
UINT64 paddingE[80 - 66]; /* 66 */
|
||||
ALIGN64 pVerifyCertificateEx VerifyCertificateEx; /**< (offset 66)
|
||||
Callback for certificate validation.
|
||||
Used to verify that an unknown certificate is trusted. */
|
||||
ALIGN64 pVerifyChangedCertificateEx VerifyChangedCertificateEx; /**< (offset 67)
|
||||
Callback for changed certificate validation.
|
||||
Used when a certificate differs from stored fingerprint. */
|
||||
UINT64 paddingE[80 - 68]; /* 68 */
|
||||
};
|
||||
|
||||
struct rdp_channel_handles
|
||||
|
@ -46,23 +46,25 @@ static const char certificate_legacy_hosts_file[] = "known_hosts";
|
||||
#define TAG FREERDP_TAG("crypto")
|
||||
|
||||
static BOOL certificate_split_line(char* line, char** host, UINT16* port,
|
||||
char**subject, char**issuer,
|
||||
char** fingerprint);
|
||||
char** subject, char** issuer,
|
||||
char** fingerprint);
|
||||
static BOOL certificate_line_is_comment(const char* line, size_t length)
|
||||
{
|
||||
while(length > 0)
|
||||
while (length > 0)
|
||||
{
|
||||
switch(*line)
|
||||
switch (*line)
|
||||
{
|
||||
case ' ':
|
||||
case '\t':
|
||||
line++;
|
||||
length--;
|
||||
break;
|
||||
case '#':
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
case ' ':
|
||||
case '\t':
|
||||
line++;
|
||||
length--;
|
||||
break;
|
||||
|
||||
case '#':
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -76,7 +78,6 @@ BOOL certificate_store_init(rdpCertificateStore* certificate_store)
|
||||
{
|
||||
char* server_path = NULL;
|
||||
rdpSettings* settings;
|
||||
|
||||
settings = certificate_store->settings;
|
||||
|
||||
if (!PathFileExistsA(settings->ConfigPath))
|
||||
@ -86,10 +87,12 @@ BOOL certificate_store_init(rdpCertificateStore* certificate_store)
|
||||
WLog_ERR(TAG, "error creating directory '%s'", settings->ConfigPath);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
WLog_INFO(TAG, "creating directory %s", settings->ConfigPath);
|
||||
}
|
||||
|
||||
if (!(certificate_store->path = GetCombinedPath(settings->ConfigPath, (char*) certificate_store_dir)))
|
||||
if (!(certificate_store->path = GetCombinedPath(settings->ConfigPath,
|
||||
(char*) certificate_store_dir)))
|
||||
goto fail;
|
||||
|
||||
if (!PathFileExistsA(certificate_store->path))
|
||||
@ -99,6 +102,7 @@ BOOL certificate_store_init(rdpCertificateStore* certificate_store)
|
||||
WLog_ERR(TAG, "error creating directory [%s]", certificate_store->path);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
WLog_INFO(TAG, "creating directory [%s]", certificate_store->path);
|
||||
}
|
||||
|
||||
@ -112,20 +116,20 @@ BOOL certificate_store_init(rdpCertificateStore* certificate_store)
|
||||
WLog_ERR(TAG, "error creating directory [%s]", server_path);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
WLog_INFO(TAG, "created directory [%s]", server_path);
|
||||
}
|
||||
|
||||
if (!(certificate_store->file = GetCombinedPath(settings->ConfigPath, (char*) certificate_known_hosts_file)))
|
||||
if (!(certificate_store->file = GetCombinedPath(settings->ConfigPath,
|
||||
(char*) certificate_known_hosts_file)))
|
||||
goto fail;
|
||||
|
||||
if (!(certificate_store->legacy_file = GetCombinedPath(settings->ConfigPath,
|
||||
(char*) certificate_legacy_hosts_file)))
|
||||
(char*) certificate_legacy_hosts_file)))
|
||||
goto fail;
|
||||
|
||||
free(server_path);
|
||||
|
||||
return TRUE;
|
||||
|
||||
fail:
|
||||
WLog_ERR(TAG, "certificate store initialization failed");
|
||||
free(server_path);
|
||||
@ -137,7 +141,7 @@ fail:
|
||||
}
|
||||
|
||||
static int certificate_data_match_legacy(rdpCertificateStore* certificate_store,
|
||||
rdpCertificateData* certificate_data)
|
||||
rdpCertificateData* certificate_data)
|
||||
{
|
||||
HANDLE fp;
|
||||
int match = 1;
|
||||
@ -149,12 +153,11 @@ static int certificate_data_match_legacy(rdpCertificateStore* certificate_store,
|
||||
UINT64 size;
|
||||
size_t length;
|
||||
DWORD read;
|
||||
|
||||
/* Assure POSIX style paths, CreateFile expects either '/' or '\\' */
|
||||
PathCchConvertStyleA(certificate_store->legacy_file, strlen(certificate_store->legacy_file), PATH_STYLE_UNIX);
|
||||
|
||||
PathCchConvertStyleA(certificate_store->legacy_file, strlen(certificate_store->legacy_file),
|
||||
PATH_STYLE_UNIX);
|
||||
fp = CreateFileA(certificate_store->legacy_file, GENERIC_READ, FILE_SHARE_READ,
|
||||
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if (fp == INVALID_HANDLE_VALUE)
|
||||
return match;
|
||||
@ -162,10 +165,11 @@ static int certificate_data_match_legacy(rdpCertificateStore* certificate_store,
|
||||
if ((lowSize = GetFileSize(fp, &highSize)) == INVALID_FILE_SIZE)
|
||||
{
|
||||
WLog_ERR(TAG, "GetFileSize(%s) returned %s [0x%08"PRIX32"]",
|
||||
certificate_store->legacy_file, strerror(errno), GetLastError());
|
||||
certificate_store->legacy_file, strerror(errno), GetLastError());
|
||||
CloseHandle(fp);
|
||||
return match;
|
||||
}
|
||||
|
||||
size = (UINT64)lowSize | ((UINT64)highSize << 32);
|
||||
|
||||
if (size < 1)
|
||||
@ -175,6 +179,7 @@ static int certificate_data_match_legacy(rdpCertificateStore* certificate_store,
|
||||
}
|
||||
|
||||
mdata = (char*) malloc(size + 2);
|
||||
|
||||
if (!mdata)
|
||||
{
|
||||
CloseHandle(fp);
|
||||
@ -182,6 +187,7 @@ static int certificate_data_match_legacy(rdpCertificateStore* certificate_store,
|
||||
}
|
||||
|
||||
data = mdata;
|
||||
|
||||
if (!ReadFile(fp, data, size, &read, NULL) || (read != size))
|
||||
{
|
||||
free(data);
|
||||
@ -190,7 +196,6 @@ static int certificate_data_match_legacy(rdpCertificateStore* certificate_store,
|
||||
}
|
||||
|
||||
CloseHandle(fp);
|
||||
|
||||
data[size] = '\n';
|
||||
data[size + 1] = '\0';
|
||||
pline = StrSep(&data, "\r\n");
|
||||
@ -202,13 +207,13 @@ static int certificate_data_match_legacy(rdpCertificateStore* certificate_store,
|
||||
if (length > 0)
|
||||
{
|
||||
hostname = StrSep(&pline, " \t");
|
||||
|
||||
if (!hostname || !pline)
|
||||
WLog_WARN(TAG, "Invalid %s entry %s %s!", certificate_legacy_hosts_file,
|
||||
hostname, pline);
|
||||
hostname, pline);
|
||||
else if (strcmp(hostname, certificate_data->hostname) == 0)
|
||||
{
|
||||
const int diff = strcmp(pline, certificate_data->fingerprint);
|
||||
|
||||
match = (diff == 0) ? 0 : -1;
|
||||
break;
|
||||
}
|
||||
@ -222,44 +227,49 @@ static int certificate_data_match_legacy(rdpCertificateStore* certificate_store,
|
||||
if (0 == match)
|
||||
{
|
||||
rdpCertificateData* data = certificate_data_new(
|
||||
hostname,
|
||||
certificate_data->port,
|
||||
NULL, NULL,
|
||||
certificate_data->fingerprint);
|
||||
hostname,
|
||||
certificate_data->port,
|
||||
NULL, NULL,
|
||||
certificate_data->fingerprint);
|
||||
|
||||
if (data)
|
||||
{
|
||||
free (data->subject);
|
||||
free (data->issuer);
|
||||
|
||||
free(data->subject);
|
||||
free(data->issuer);
|
||||
data->subject = NULL;
|
||||
data->issuer = NULL;
|
||||
|
||||
if (certificate_data->subject)
|
||||
{
|
||||
data->subject = _strdup(certificate_data->subject);
|
||||
|
||||
if (!data->subject)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (certificate_data->issuer)
|
||||
{
|
||||
data->issuer = _strdup(certificate_data->issuer);
|
||||
|
||||
if (!data->issuer)
|
||||
goto out;
|
||||
}
|
||||
|
||||
match = certificate_data_print(certificate_store, data) ? 0 : 1;
|
||||
}
|
||||
out:
|
||||
|
||||
out:
|
||||
certificate_data_free(data);
|
||||
}
|
||||
|
||||
free(mdata);
|
||||
|
||||
return match;
|
||||
|
||||
}
|
||||
|
||||
static int certificate_data_match_raw(rdpCertificateStore* certificate_store,
|
||||
rdpCertificateData* certificate_data,
|
||||
char** psubject, char** pissuer,
|
||||
char** fprint)
|
||||
rdpCertificateData* certificate_data,
|
||||
char** psubject, char** pissuer,
|
||||
char** fprint)
|
||||
{
|
||||
BOOL found = FALSE;
|
||||
HANDLE fp;
|
||||
@ -276,11 +286,10 @@ static int certificate_data_match_raw(rdpCertificateStore* certificate_store,
|
||||
char* fingerprint = NULL;
|
||||
unsigned short port = 0;
|
||||
DWORD read;
|
||||
|
||||
/* Assure POSIX style paths, CreateFile expects either '/' or '\\' */
|
||||
PathCchConvertStyleA(certificate_store->file, strlen(certificate_store->file), PATH_STYLE_UNIX);
|
||||
fp = CreateFileA(certificate_store->file, GENERIC_READ, FILE_SHARE_READ,
|
||||
NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if (fp == INVALID_HANDLE_VALUE)
|
||||
return match;
|
||||
@ -288,10 +297,11 @@ static int certificate_data_match_raw(rdpCertificateStore* certificate_store,
|
||||
if ((lowSize = GetFileSize(fp, &highSize)) == INVALID_FILE_SIZE)
|
||||
{
|
||||
WLog_ERR(TAG, "GetFileSize(%s) returned %s [0x%08"PRIX32"]",
|
||||
certificate_store->legacy_file, strerror(errno), GetLastError());
|
||||
certificate_store->legacy_file, strerror(errno), GetLastError());
|
||||
CloseHandle(fp);
|
||||
return match;
|
||||
}
|
||||
|
||||
size = (UINT64)lowSize | ((UINT64)highSize << 32);
|
||||
|
||||
if (size < 1)
|
||||
@ -301,6 +311,7 @@ static int certificate_data_match_raw(rdpCertificateStore* certificate_store,
|
||||
}
|
||||
|
||||
mdata = (char*) malloc(size + 2);
|
||||
|
||||
if (!mdata)
|
||||
{
|
||||
CloseHandle(fp);
|
||||
@ -308,14 +319,15 @@ static int certificate_data_match_raw(rdpCertificateStore* certificate_store,
|
||||
}
|
||||
|
||||
data = mdata;
|
||||
|
||||
if (!ReadFile(fp, data, size, &read, NULL) || (read != size))
|
||||
{
|
||||
free(data);
|
||||
CloseHandle(fp);
|
||||
return match;
|
||||
}
|
||||
CloseHandle(fp);
|
||||
|
||||
CloseHandle(fp);
|
||||
data[size] = '\n';
|
||||
data[size + 1] = '\0';
|
||||
pline = StrSep(&data, "\r\n");
|
||||
@ -330,9 +342,9 @@ static int certificate_data_match_raw(rdpCertificateStore* certificate_store,
|
||||
{
|
||||
}
|
||||
else if (!certificate_split_line(pline, &hostname, &port,
|
||||
&subject, &issuer, &fingerprint))
|
||||
&subject, &issuer, &fingerprint))
|
||||
WLog_WARN(TAG, "Invalid %s entry %s!",
|
||||
certificate_known_hosts_file, pline);
|
||||
certificate_known_hosts_file, pline);
|
||||
else if (strcmp(pline, certificate_data->hostname) == 0)
|
||||
{
|
||||
int outLen;
|
||||
@ -340,16 +352,21 @@ static int certificate_data_match_raw(rdpCertificateStore* certificate_store,
|
||||
if (port == certificate_data->port)
|
||||
{
|
||||
found = TRUE;
|
||||
|
||||
if (fingerprint)
|
||||
{
|
||||
match = (strcmp(certificate_data->fingerprint, fingerprint) == 0) ? 0 : -1;
|
||||
|
||||
if (fprint)
|
||||
*fprint = _strdup(fingerprint);
|
||||
}
|
||||
|
||||
if (subject && psubject)
|
||||
crypto_base64_decode(subject, strlen(subject), (BYTE**)psubject, &outLen);
|
||||
|
||||
if (issuer && pissuer)
|
||||
crypto_base64_decode(issuer, strlen(issuer), (BYTE**)pissuer, &outLen);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -357,6 +374,7 @@ static int certificate_data_match_raw(rdpCertificateStore* certificate_store,
|
||||
|
||||
pline = StrSep(&data, "\r\n");
|
||||
}
|
||||
|
||||
free(mdata);
|
||||
|
||||
if ((match != 0) && !found)
|
||||
@ -366,27 +384,28 @@ static int certificate_data_match_raw(rdpCertificateStore* certificate_store,
|
||||
}
|
||||
|
||||
BOOL certificate_get_stored_data(rdpCertificateStore* certificate_store,
|
||||
rdpCertificateData* certificate_data,
|
||||
char** subject, char** issuer,
|
||||
char** fingerprint)
|
||||
rdpCertificateData* certificate_data,
|
||||
char** subject, char** issuer,
|
||||
char** fingerprint)
|
||||
{
|
||||
int rc = certificate_data_match_raw(certificate_store, certificate_data,
|
||||
subject, issuer, fingerprint);
|
||||
subject, issuer, fingerprint);
|
||||
|
||||
if ((rc == 0) || (rc == -1))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int certificate_data_match(rdpCertificateStore* certificate_store,
|
||||
rdpCertificateData* certificate_data)
|
||||
rdpCertificateData* certificate_data)
|
||||
{
|
||||
return certificate_data_match_raw(certificate_store, certificate_data,
|
||||
NULL, NULL, NULL);
|
||||
NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
BOOL certificate_data_replace(rdpCertificateStore* certificate_store,
|
||||
rdpCertificateData* certificate_data)
|
||||
rdpCertificateData* certificate_data)
|
||||
{
|
||||
HANDLE fp;
|
||||
BOOL rc = FALSE;
|
||||
@ -397,11 +416,10 @@ BOOL certificate_data_replace(rdpCertificateStore* certificate_store,
|
||||
UINT64 size;
|
||||
DWORD read, written;
|
||||
DWORD lowSize, highSize;
|
||||
|
||||
/* Assure POSIX style paths, CreateFile expects either '/' or '\\' */
|
||||
PathCchConvertStyleA(certificate_store->file, strlen(certificate_store->file), PATH_STYLE_UNIX);
|
||||
fp = CreateFileA(certificate_store->file, GENERIC_READ | GENERIC_WRITE, 0,
|
||||
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if (fp == INVALID_HANDLE_VALUE)
|
||||
return FALSE;
|
||||
@ -409,10 +427,11 @@ BOOL certificate_data_replace(rdpCertificateStore* certificate_store,
|
||||
if ((lowSize = GetFileSize(fp, &highSize)) == INVALID_FILE_SIZE)
|
||||
{
|
||||
WLog_ERR(TAG, "GetFileSize(%s) returned %s [0x%08"PRIX32"]",
|
||||
certificate_store->legacy_file, strerror(errno), GetLastError());
|
||||
certificate_store->legacy_file, strerror(errno), GetLastError());
|
||||
CloseHandle(fp);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
size = (UINT64)lowSize | ((UINT64)highSize << 32);
|
||||
|
||||
if (size < 1)
|
||||
@ -422,6 +441,7 @@ BOOL certificate_data_replace(rdpCertificateStore* certificate_store,
|
||||
}
|
||||
|
||||
data = (char*) malloc(size + 2);
|
||||
|
||||
if (!data)
|
||||
{
|
||||
fclose(fp);
|
||||
@ -438,7 +458,7 @@ BOOL certificate_data_replace(rdpCertificateStore* certificate_store,
|
||||
if (SetFilePointer(fp, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
|
||||
{
|
||||
WLog_ERR(TAG, "SetFilePointer(%s) returned %s [0x%08"PRIX32"]",
|
||||
certificate_store->file, strerror(errno), GetLastError());
|
||||
certificate_store->file, strerror(errno), GetLastError());
|
||||
free(data);
|
||||
CloseHandle(fp);
|
||||
return FALSE;
|
||||
@ -447,7 +467,7 @@ BOOL certificate_data_replace(rdpCertificateStore* certificate_store,
|
||||
if (!SetEndOfFile(fp))
|
||||
{
|
||||
WLog_ERR(TAG, "SetEndOfFile(%s) returned %s [0x%08"PRIX32"]",
|
||||
certificate_store->file, strerror(errno), GetLastError());
|
||||
certificate_store->file, strerror(errno), GetLastError());
|
||||
free(data);
|
||||
CloseHandle(fp);
|
||||
return FALSE;
|
||||
@ -477,12 +497,12 @@ BOOL certificate_data_replace(rdpCertificateStore* certificate_store,
|
||||
}
|
||||
else if (!certificate_split_line(pline, &hostname, &port, &subject, &issuer, &fingerprint))
|
||||
WLog_WARN(TAG, "Skipping invalid %s entry %s!",
|
||||
certificate_known_hosts_file, pline);
|
||||
certificate_known_hosts_file, pline);
|
||||
else
|
||||
{
|
||||
/* If this is the replaced hostname, use the updated fingerprint. */
|
||||
if ((strcmp(hostname, certificate_data->hostname) == 0) &&
|
||||
(port == certificate_data->port))
|
||||
(port == certificate_data->port))
|
||||
{
|
||||
fingerprint = certificate_data->fingerprint;
|
||||
rc = TRUE;
|
||||
@ -490,33 +510,37 @@ BOOL certificate_data_replace(rdpCertificateStore* certificate_store,
|
||||
|
||||
size = _snprintf(NULL, 0, "%s %"PRIu16" %s %s %s\n", hostname, port, fingerprint, subject, issuer);
|
||||
tdata = malloc(size + 1);
|
||||
|
||||
if (!tdata)
|
||||
{
|
||||
WLog_ERR(TAG, "malloc(%s) returned %s [0x%08X]",
|
||||
certificate_store->file, strerror(errno), errno);
|
||||
certificate_store->file, strerror(errno), errno);
|
||||
free(data);
|
||||
CloseHandle(fp);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (_snprintf(tdata, size + 1, "%s %"PRIu16" %s %s %s\n", hostname, port, fingerprint, subject, issuer) != size)
|
||||
if (_snprintf(tdata, size + 1, "%s %"PRIu16" %s %s %s\n", hostname, port, fingerprint, subject,
|
||||
issuer) != size)
|
||||
{
|
||||
WLog_ERR(TAG, "_snprintf(%s) returned %s [0x%08X]",
|
||||
certificate_store->file, strerror(errno), errno);
|
||||
certificate_store->file, strerror(errno), errno);
|
||||
free(tdata);
|
||||
free(data);
|
||||
CloseHandle(fp);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!WriteFile(fp, tdata, size, &written, NULL) || (written != size))
|
||||
{
|
||||
WLog_ERR(TAG, "WriteFile(%s) returned %s [0x%08X]",
|
||||
certificate_store->file, strerror(errno), errno);
|
||||
certificate_store->file, strerror(errno), errno);
|
||||
free(tdata);
|
||||
free(data);
|
||||
CloseHandle(fp);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
free(tdata);
|
||||
}
|
||||
}
|
||||
@ -526,64 +550,65 @@ BOOL certificate_data_replace(rdpCertificateStore* certificate_store,
|
||||
|
||||
CloseHandle(fp);
|
||||
free(data);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
BOOL certificate_split_line(char* line, char** host, UINT16* port, char** subject,
|
||||
char** issuer, char** fingerprint)
|
||||
char** issuer, char** fingerprint)
|
||||
{
|
||||
char* cur;
|
||||
size_t length = strlen(line);
|
||||
char* cur;
|
||||
size_t length = strlen(line);
|
||||
|
||||
if (length <= 0)
|
||||
return FALSE;
|
||||
if (length <= 0)
|
||||
return FALSE;
|
||||
|
||||
cur = StrSep(&line, " \t");
|
||||
if (!cur)
|
||||
return FALSE;
|
||||
*host = cur;
|
||||
cur = StrSep(&line, " \t");
|
||||
|
||||
cur = StrSep(&line, " \t");
|
||||
if (!cur)
|
||||
return FALSE;
|
||||
if (!cur)
|
||||
return FALSE;
|
||||
|
||||
if(sscanf(cur, "%hu", port) != 1)
|
||||
return FALSE;
|
||||
*host = cur;
|
||||
cur = StrSep(&line, " \t");
|
||||
|
||||
cur = StrSep(&line, " \t");
|
||||
if (!cur)
|
||||
return FALSE;
|
||||
if (!cur)
|
||||
return FALSE;
|
||||
|
||||
*fingerprint = cur;
|
||||
if (sscanf(cur, "%hu", port) != 1)
|
||||
return FALSE;
|
||||
|
||||
cur = StrSep(&line, " \t");
|
||||
if (!cur)
|
||||
return FALSE;
|
||||
cur = StrSep(&line, " \t");
|
||||
|
||||
*subject = cur;
|
||||
if (!cur)
|
||||
return FALSE;
|
||||
|
||||
cur = StrSep(&line, " \t");
|
||||
if (!cur)
|
||||
return FALSE;
|
||||
*fingerprint = cur;
|
||||
cur = StrSep(&line, " \t");
|
||||
|
||||
*issuer = cur;
|
||||
if (!cur)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
*subject = cur;
|
||||
cur = StrSep(&line, " \t");
|
||||
|
||||
if (!cur)
|
||||
return FALSE;
|
||||
|
||||
*issuer = cur;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL certificate_data_print(rdpCertificateStore* certificate_store, rdpCertificateData* certificate_data)
|
||||
BOOL certificate_data_print(rdpCertificateStore* certificate_store,
|
||||
rdpCertificateData* certificate_data)
|
||||
{
|
||||
HANDLE fp;
|
||||
char* tdata;
|
||||
UINT64 size;
|
||||
DWORD written;
|
||||
|
||||
/* reopen in append mode */
|
||||
/* Assure POSIX style paths, CreateFile expects either '/' or '\\' */
|
||||
PathCchConvertStyleA(certificate_store->file, strlen(certificate_store->file), PATH_STYLE_UNIX);
|
||||
fp = CreateFileA(certificate_store->file, GENERIC_WRITE, 0,
|
||||
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if (fp == INVALID_HANDLE_VALUE)
|
||||
return FALSE;
|
||||
@ -591,48 +616,53 @@ BOOL certificate_data_print(rdpCertificateStore* certificate_store, rdpCertifica
|
||||
if (SetFilePointer(fp, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER)
|
||||
{
|
||||
WLog_ERR(TAG, "SetFilePointer(%s) returned %s [0x%08"PRIX32"]",
|
||||
certificate_store->file, strerror(errno), GetLastError());
|
||||
certificate_store->file, strerror(errno), GetLastError());
|
||||
CloseHandle(fp);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
size = _snprintf(NULL, 0, "%s %"PRIu16" %s %s %s\n", certificate_data->hostname, certificate_data->port,
|
||||
certificate_data->fingerprint, certificate_data->subject,
|
||||
certificate_data->issuer);
|
||||
size = _snprintf(NULL, 0, "%s %"PRIu16" %s %s %s\n", certificate_data->hostname,
|
||||
certificate_data->port,
|
||||
certificate_data->fingerprint, certificate_data->subject,
|
||||
certificate_data->issuer);
|
||||
tdata = malloc(size + 1);
|
||||
|
||||
if (!tdata)
|
||||
{
|
||||
WLog_ERR(TAG, "malloc(%s) returned %s [0x%08X]",
|
||||
certificate_store->file, strerror(errno), errno);
|
||||
certificate_store->file, strerror(errno), errno);
|
||||
CloseHandle(fp);
|
||||
return FALSE;
|
||||
}
|
||||
if (_snprintf(tdata, size + 1, "%s %"PRIu16" %s %s %s\n", certificate_data->hostname, certificate_data->port,
|
||||
certificate_data->fingerprint, certificate_data->subject,
|
||||
certificate_data->issuer) != size)
|
||||
|
||||
if (_snprintf(tdata, size + 1, "%s %"PRIu16" %s %s %s\n", certificate_data->hostname,
|
||||
certificate_data->port,
|
||||
certificate_data->fingerprint, certificate_data->subject,
|
||||
certificate_data->issuer) != size)
|
||||
{
|
||||
WLog_ERR(TAG, "_snprintf(%s) returned %s [0x%08X]",
|
||||
certificate_store->file, strerror(errno), errno);
|
||||
certificate_store->file, strerror(errno), errno);
|
||||
free(tdata);
|
||||
CloseHandle(fp);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!WriteFile(fp, tdata, size, &written, NULL) || (written != size))
|
||||
{
|
||||
WLog_ERR(TAG, "WriteFile(%s) returned %s [0x%08X]",
|
||||
certificate_store->file, strerror(errno), errno);
|
||||
certificate_store->file, strerror(errno), errno);
|
||||
free(tdata);
|
||||
CloseHandle(fp);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
free(tdata);
|
||||
|
||||
CloseHandle(fp);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
rdpCertificateData* certificate_data_new(char* hostname, UINT16 port, char* subject, char* issuer, char* fingerprint)
|
||||
rdpCertificateData* certificate_data_new(const char* hostname, UINT16 port, const char* subject,
|
||||
const char* issuer, const char* fingerprint)
|
||||
{
|
||||
size_t i;
|
||||
rdpCertificateData* certdata;
|
||||
@ -643,31 +673,34 @@ rdpCertificateData* certificate_data_new(char* hostname, UINT16 port, char* subj
|
||||
if (!fingerprint)
|
||||
return NULL;
|
||||
|
||||
certdata = (rdpCertificateData *)calloc(1, sizeof(rdpCertificateData));
|
||||
certdata = (rdpCertificateData*)calloc(1, sizeof(rdpCertificateData));
|
||||
|
||||
if (!certdata)
|
||||
return NULL;
|
||||
|
||||
certdata->port = port;
|
||||
certdata->hostname = _strdup(hostname);
|
||||
|
||||
if (subject)
|
||||
certdata->subject = crypto_base64_encode((BYTE*)subject, strlen(subject));
|
||||
else
|
||||
certdata->subject = crypto_base64_encode((BYTE*)"", 0);
|
||||
|
||||
if (issuer)
|
||||
certdata->issuer = crypto_base64_encode((BYTE*)issuer, strlen(issuer));
|
||||
else
|
||||
certdata->issuer = crypto_base64_encode((BYTE*)"", 0);
|
||||
|
||||
certdata->fingerprint = _strdup(fingerprint);
|
||||
|
||||
if (!certdata->hostname || !certdata->subject ||
|
||||
!certdata->issuer || !certdata->fingerprint)
|
||||
!certdata->issuer || !certdata->fingerprint)
|
||||
goto fail;
|
||||
|
||||
for (i=0; i<strlen(hostname); i++)
|
||||
for (i = 0; i < strlen(hostname); i++)
|
||||
certdata->hostname[i] = tolower(certdata->hostname[i]);
|
||||
|
||||
return certdata;
|
||||
|
||||
fail:
|
||||
free(certdata->hostname);
|
||||
free(certdata->subject);
|
||||
@ -692,7 +725,6 @@ void certificate_data_free(rdpCertificateData* certificate_data)
|
||||
rdpCertificateStore* certificate_store_new(rdpSettings* settings)
|
||||
{
|
||||
rdpCertificateStore* certificate_store;
|
||||
|
||||
certificate_store = (rdpCertificateStore*) calloc(1, sizeof(rdpCertificateStore));
|
||||
|
||||
if (!certificate_store)
|
||||
|
@ -754,9 +754,8 @@ char* crypto_cert_issuer(X509* xcert)
|
||||
return crypto_print_name(X509_get_issuer_name(xcert));
|
||||
}
|
||||
|
||||
BOOL x509_verify_certificate(CryptoCert cert, char* certificate_store_path)
|
||||
BOOL x509_verify_certificate(CryptoCert cert, const char* certificate_store_path)
|
||||
{
|
||||
X509_VERIFY_PARAM* verify_param;
|
||||
X509_STORE_CTX* csc;
|
||||
BOOL status = FALSE;
|
||||
X509_STORE* cert_ctx = NULL;
|
||||
@ -812,7 +811,7 @@ end:
|
||||
return status;
|
||||
}
|
||||
|
||||
rdpCertificateData* crypto_get_certificate_data(X509* xcert, char* hostname, UINT16 port)
|
||||
rdpCertificateData* crypto_get_certificate_data(X509* xcert, const char* hostname, UINT16 port)
|
||||
{
|
||||
char* issuer;
|
||||
char* subject;
|
||||
|
@ -79,6 +79,13 @@ struct _BIO_RDP_TLS
|
||||
};
|
||||
typedef struct _BIO_RDP_TLS BIO_RDP_TLS;
|
||||
|
||||
static int tls_verify_certificate(rdpTls* tls, CryptoCert cert, const char* hostname, UINT16 port);
|
||||
static void tls_print_certificate_name_mismatch_error(const char* hostname, UINT16 port,
|
||||
const char* common_name, char** alt_names,
|
||||
int alt_names_count);
|
||||
static void tls_print_certificate_error(const char* hostname, UINT16 port, const char* fingerprint,
|
||||
const char* hosts_file);
|
||||
|
||||
static int bio_rdp_tls_write(BIO* bio, const char* buf, int size)
|
||||
{
|
||||
int error;
|
||||
@ -654,7 +661,6 @@ static BOOL tls_prepare(rdpTls* tls, BIO* underlying, SSL_METHOD* method,
|
||||
SSL_CTX_set_min_proto_version(tls->ctx, TLS1_VERSION); /* min version */
|
||||
SSL_CTX_set_max_proto_version(tls->ctx, 0); /* highest supported version by library */
|
||||
#endif
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
|
||||
SSL_CTX_set_security_level(tls->ctx, settings->TlsSecLevel);
|
||||
#endif
|
||||
@ -844,7 +850,6 @@ int tls_connect(rdpTls* tls, BIO* underlying)
|
||||
* support empty fragments. This needs to be disabled.
|
||||
*/
|
||||
options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
|
||||
/**
|
||||
* disable SSLv2 and SSLv3
|
||||
@ -1098,7 +1103,8 @@ int tls_set_alert_code(rdpTls* tls, int level, int description)
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL tls_match_hostname(char* pattern, int pattern_length, char* hostname)
|
||||
static BOOL tls_match_hostname(const char* pattern, const size_t pattern_length,
|
||||
const char* hostname)
|
||||
{
|
||||
if (strlen(hostname) == pattern_length)
|
||||
{
|
||||
@ -1107,9 +1113,9 @@ BOOL tls_match_hostname(char* pattern, int pattern_length, char* hostname)
|
||||
}
|
||||
|
||||
if ((pattern_length > 2) && (pattern[0] == '*') && (pattern[1] == '.')
|
||||
&& (((int) strlen(hostname)) >= pattern_length))
|
||||
&& ((strlen(hostname)) >= pattern_length))
|
||||
{
|
||||
char* check_hostname = &hostname[strlen(hostname) - pattern_length + 1];
|
||||
const char* check_hostname = &hostname[strlen(hostname) - pattern_length + 1];
|
||||
|
||||
if (_strnicmp(check_hostname, &pattern[1], pattern_length - 1) == 0)
|
||||
{
|
||||
@ -1183,23 +1189,23 @@ static BOOL is_accepted(rdpTls* tls, const BYTE* pem, size_t length)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL accept_cert(rdpTls* tls, BYTE* pem, UINT32 length)
|
||||
static BOOL accept_cert(rdpTls* tls, const BYTE* pem, UINT32 length)
|
||||
{
|
||||
rdpSettings* settings = tls->settings;
|
||||
|
||||
if (tls->isGatewayTransport)
|
||||
{
|
||||
settings->GatewayAcceptedCert = (char*)pem;
|
||||
settings->GatewayAcceptedCert = _strdup(pem);
|
||||
settings->GatewayAcceptedCertLength = length;
|
||||
}
|
||||
else if (is_redirected(tls))
|
||||
{
|
||||
settings->RedirectionAcceptedCert = (char*)pem;
|
||||
settings->RedirectionAcceptedCert = _strdup(pem);
|
||||
settings->RedirectionAcceptedCertLength = length;
|
||||
}
|
||||
else
|
||||
{
|
||||
settings->AcceptedCert = (char*)pem;
|
||||
settings->AcceptedCert = _strdup(pem);
|
||||
settings->AcceptedCertLength = length;
|
||||
}
|
||||
|
||||
@ -1299,8 +1305,8 @@ fail:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname,
|
||||
int port)
|
||||
int tls_verify_certificate(rdpTls* tls, CryptoCert cert, const char* hostname,
|
||||
UINT16 port)
|
||||
{
|
||||
int match;
|
||||
int index;
|
||||
@ -1312,183 +1318,209 @@ int tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname,
|
||||
BOOL certificate_status;
|
||||
BOOL hostname_match = FALSE;
|
||||
BOOL verification_status = FALSE;
|
||||
rdpCertificateData* certificate_data;
|
||||
rdpCertificateData* certificate_data = NULL;
|
||||
freerdp* instance = (freerdp*) tls->settings->instance;
|
||||
DWORD length;
|
||||
BYTE* pemCert;
|
||||
BYTE* pemCert = NULL;
|
||||
DWORD flags = VERIFY_CERT_FLAG_NONE;
|
||||
|
||||
if (!tls_extract_pem(cert, &pemCert, &length))
|
||||
return -1;
|
||||
goto end;
|
||||
|
||||
/* Check, if we already accepted this key. */
|
||||
if (is_accepted(tls, pemCert, length))
|
||||
{
|
||||
free(pemCert);
|
||||
return 1;
|
||||
}
|
||||
goto end;
|
||||
|
||||
if (tls->isGatewayTransport || is_redirected(tls))
|
||||
flags |= VERIFY_CERT_FLAG_LEGACY;
|
||||
|
||||
if (tls->isGatewayTransport)
|
||||
flags |= VERIFY_CERT_FLAG_GATEWAY;
|
||||
|
||||
if (is_redirected(tls))
|
||||
flags |= VERIFY_CERT_FLAG_REDIRECT;
|
||||
|
||||
/* Certificate management is done by the application */
|
||||
if (tls->settings->ExternalCertificateManagement)
|
||||
{
|
||||
int status = -1;
|
||||
|
||||
if (instance->VerifyX509Certificate)
|
||||
status = instance->VerifyX509Certificate(instance, pemCert, length, hostname,
|
||||
port, tls->isGatewayTransport | is_redirected(tls) ? 2 : 0);
|
||||
port, flags);
|
||||
else
|
||||
WLog_ERR(TAG, "No VerifyX509Certificate callback registered!");
|
||||
|
||||
if (status > 0)
|
||||
{
|
||||
accept_cert(tls, pemCert, length);
|
||||
}
|
||||
else if (status < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "VerifyX509Certificate failed: (length = %d) status: [%d] %s",
|
||||
length, status, pemCert);
|
||||
free(pemCert);
|
||||
return -1;
|
||||
goto end;
|
||||
}
|
||||
else
|
||||
free(pemCert);
|
||||
|
||||
return (status == 0) ? 0 : 1;
|
||||
verification_status = (status == 0) ? FALSE : TRUE;
|
||||
}
|
||||
|
||||
/* ignore certificate verification if user explicitly required it (discouraged) */
|
||||
if (tls->settings->IgnoreCertificate)
|
||||
{
|
||||
free(pemCert);
|
||||
return 1; /* success! */
|
||||
}
|
||||
|
||||
if (!tls->isGatewayTransport && tls->settings->AuthenticationLevel == 0)
|
||||
{
|
||||
free(pemCert);
|
||||
return 1; /* success! */
|
||||
}
|
||||
|
||||
/* if user explicitly specified a certificate name, use it instead of the hostname */
|
||||
if (!tls->isGatewayTransport && tls->settings->CertificateName)
|
||||
hostname = tls->settings->CertificateName;
|
||||
|
||||
/* attempt verification using OpenSSL and the ~/.freerdp/certs certificate store */
|
||||
certificate_status = x509_verify_certificate(cert,
|
||||
tls->certificate_store->path);
|
||||
/* verify certificate name match */
|
||||
certificate_data = crypto_get_certificate_data(cert->px509, hostname, port);
|
||||
/* extra common name and alternative names */
|
||||
common_name = crypto_cert_subject_common_name(cert->px509, &common_name_length);
|
||||
dns_names = crypto_cert_get_dns_names(cert->px509, &dns_names_count,
|
||||
&dns_names_lengths);
|
||||
|
||||
/* compare against common name */
|
||||
|
||||
if (common_name)
|
||||
{
|
||||
if (tls_match_hostname(common_name, common_name_length, hostname))
|
||||
hostname_match = TRUE;
|
||||
}
|
||||
|
||||
/* compare against alternative names */
|
||||
|
||||
if (dns_names)
|
||||
{
|
||||
for (index = 0; index < dns_names_count; index++)
|
||||
{
|
||||
if (tls_match_hostname(dns_names[index], dns_names_lengths[index], hostname))
|
||||
{
|
||||
hostname_match = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if the certificate is valid and the certificate name matches, verification succeeds */
|
||||
if (certificate_status && hostname_match)
|
||||
else if (tls->settings->IgnoreCertificate)
|
||||
verification_status = TRUE; /* success! */
|
||||
|
||||
/* verification could not succeed with OpenSSL, use known_hosts file and prompt user for manual verification */
|
||||
if (!certificate_status || !hostname_match)
|
||||
else if (!tls->isGatewayTransport && (tls->settings->AuthenticationLevel == 0))
|
||||
verification_status = TRUE; /* success! */
|
||||
else
|
||||
{
|
||||
char* issuer;
|
||||
char* subject;
|
||||
char* fingerprint;
|
||||
DWORD accept_certificate = 0;
|
||||
issuer = crypto_cert_issuer(cert->px509);
|
||||
subject = crypto_cert_subject(cert->px509);
|
||||
fingerprint = crypto_cert_fingerprint(cert->px509);
|
||||
/* search for matching entry in known_hosts file */
|
||||
match = certificate_data_match(tls->certificate_store, certificate_data);
|
||||
/* if user explicitly specified a certificate name, use it instead of the hostname */
|
||||
if (!tls->isGatewayTransport && tls->settings->CertificateName)
|
||||
hostname = tls->settings->CertificateName;
|
||||
|
||||
if (match == 1)
|
||||
/* attempt verification using OpenSSL and the ~/.freerdp/certs certificate store */
|
||||
certificate_status = x509_verify_certificate(cert,
|
||||
tls->certificate_store->path);
|
||||
/* verify certificate name match */
|
||||
certificate_data = crypto_get_certificate_data(cert->px509, hostname, port);
|
||||
/* extra common name and alternative names */
|
||||
common_name = crypto_cert_subject_common_name(cert->px509, &common_name_length);
|
||||
dns_names = crypto_cert_get_dns_names(cert->px509, &dns_names_count,
|
||||
&dns_names_lengths);
|
||||
|
||||
/* compare against common name */
|
||||
|
||||
if (common_name)
|
||||
{
|
||||
/* no entry was found in known_hosts file, prompt user for manual verification */
|
||||
if (!hostname_match)
|
||||
tls_print_certificate_name_mismatch_error(
|
||||
hostname, port,
|
||||
common_name, dns_names,
|
||||
dns_names_count);
|
||||
if (tls_match_hostname(common_name, common_name_length, hostname))
|
||||
hostname_match = TRUE;
|
||||
}
|
||||
|
||||
/* Automatically accept certificate on first use */
|
||||
if (tls->settings->AutoAcceptCertificate)
|
||||
/* compare against alternative names */
|
||||
|
||||
if (dns_names)
|
||||
{
|
||||
for (index = 0; index < dns_names_count; index++)
|
||||
{
|
||||
WLog_INFO(TAG, "No certificate stored, automatically accepting.");
|
||||
accept_certificate = 1;
|
||||
}
|
||||
else if (instance->VerifyCertificate)
|
||||
{
|
||||
accept_certificate = instance->VerifyCertificate(
|
||||
instance, common_name,
|
||||
subject, issuer,
|
||||
fingerprint, !hostname_match);
|
||||
}
|
||||
|
||||
switch (accept_certificate)
|
||||
{
|
||||
case 1:
|
||||
/* user accepted certificate, add entry in known_hosts file */
|
||||
verification_status = certificate_data_print(tls->certificate_store,
|
||||
certificate_data);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
/* user did accept temporaty, do not add to known hosts file */
|
||||
verification_status = TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* user did not accept, abort and do not add entry in known_hosts file */
|
||||
verification_status = FALSE; /* failure! */
|
||||
if (tls_match_hostname(dns_names[index], dns_names_lengths[index], hostname))
|
||||
{
|
||||
hostname_match = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (match == -1)
|
||||
|
||||
/* if the certificate is valid and the certificate name matches, verification succeeds */
|
||||
if (certificate_status && hostname_match)
|
||||
verification_status = TRUE; /* success! */
|
||||
|
||||
if (!hostname_match)
|
||||
flags |= VERIFY_CERT_FLAG_MISMATCH;
|
||||
|
||||
/* verification could not succeed with OpenSSL, use known_hosts file and prompt user for manual verification */
|
||||
if (!certificate_status || !hostname_match)
|
||||
{
|
||||
char* old_subject = NULL;
|
||||
char* old_issuer = NULL;
|
||||
char* old_fingerprint = NULL;
|
||||
/* entry was found in known_hosts file, but fingerprint does not match. ask user to use it */
|
||||
tls_print_certificate_error(hostname, port, fingerprint,
|
||||
tls->certificate_store->file);
|
||||
char* issuer;
|
||||
char* subject;
|
||||
char* fingerprint;
|
||||
DWORD accept_certificate = 0;
|
||||
issuer = crypto_cert_issuer(cert->px509);
|
||||
subject = crypto_cert_subject(cert->px509);
|
||||
fingerprint = crypto_cert_fingerprint(cert->px509);
|
||||
/* search for matching entry in known_hosts file */
|
||||
match = certificate_data_match(tls->certificate_store, certificate_data);
|
||||
|
||||
if (!certificate_get_stored_data(tls->certificate_store,
|
||||
certificate_data, &old_subject,
|
||||
&old_issuer, &old_fingerprint))
|
||||
WLog_WARN(TAG, "Failed to get certificate entry for %s:%d",
|
||||
hostname, port);
|
||||
|
||||
if (instance->VerifyChangedCertificate)
|
||||
if (match == 1)
|
||||
{
|
||||
accept_certificate = instance->VerifyChangedCertificate(
|
||||
instance, common_name, subject, issuer,
|
||||
fingerprint, old_subject, old_issuer,
|
||||
old_fingerprint);
|
||||
/* no entry was found in known_hosts file, prompt user for manual verification */
|
||||
if (!hostname_match)
|
||||
tls_print_certificate_name_mismatch_error(
|
||||
hostname, port,
|
||||
common_name, dns_names,
|
||||
dns_names_count);
|
||||
|
||||
/* Automatically accept certificate on first use */
|
||||
if (tls->settings->AutoAcceptCertificate)
|
||||
{
|
||||
WLog_INFO(TAG, "No certificate stored, automatically accepting.");
|
||||
accept_certificate = 1;
|
||||
}
|
||||
else if (instance->VerifyX509Certificate)
|
||||
{
|
||||
int rc = instance->VerifyX509Certificate(instance, pemCert, length, hostname,
|
||||
port, flags);
|
||||
|
||||
if (rc == 1)
|
||||
accept_certificate = 1;
|
||||
else if (rc > 1)
|
||||
accept_certificate = 2;
|
||||
else
|
||||
accept_certificate = 0;
|
||||
}
|
||||
else if (instance->VerifyCertificateEx)
|
||||
{
|
||||
accept_certificate = instance->VerifyCertificateEx(
|
||||
instance, hostname, port, common_name,
|
||||
subject, issuer,
|
||||
fingerprint, flags);
|
||||
}
|
||||
else if (instance->VerifyCertificate)
|
||||
{
|
||||
WLog_WARN(TAG,
|
||||
"The VerifyCertificate callback is deprecated, migrate your application to VerifyCertificateEx");
|
||||
accept_certificate = instance->VerifyCertificate(
|
||||
instance, common_name,
|
||||
subject, issuer,
|
||||
fingerprint, !hostname_match);
|
||||
}
|
||||
}
|
||||
else if (match == -1)
|
||||
{
|
||||
char* old_subject = NULL;
|
||||
char* old_issuer = NULL;
|
||||
char* old_fingerprint = NULL;
|
||||
/* entry was found in known_hosts file, but fingerprint does not match. ask user to use it */
|
||||
tls_print_certificate_error(hostname, port, fingerprint,
|
||||
tls->certificate_store->file);
|
||||
|
||||
free(old_subject);
|
||||
free(old_issuer);
|
||||
free(old_fingerprint);
|
||||
if (!certificate_get_stored_data(tls->certificate_store,
|
||||
certificate_data, &old_subject,
|
||||
&old_issuer, &old_fingerprint))
|
||||
WLog_WARN(TAG, "Failed to get certificate entry for %s:%d",
|
||||
hostname, port);
|
||||
|
||||
if (instance->VerifyX509Certificate)
|
||||
{
|
||||
const int rc = instance->VerifyX509Certificate(instance, pemCert, length, hostname,
|
||||
port, flags | VERIFY_CERT_FLAG_CHANGED);
|
||||
|
||||
if (rc == 1)
|
||||
accept_certificate = 1;
|
||||
else if (rc > 1)
|
||||
accept_certificate = 2;
|
||||
else
|
||||
accept_certificate = 0;
|
||||
}
|
||||
else if (instance->VerifyChangedCertificateEx)
|
||||
{
|
||||
accept_certificate = instance->VerifyChangedCertificateEx(
|
||||
instance, hostname, port, common_name, subject, issuer,
|
||||
fingerprint, old_subject, old_issuer,
|
||||
old_fingerprint, flags | VERIFY_CERT_FLAG_CHANGED);
|
||||
}
|
||||
else if (instance->VerifyChangedCertificate)
|
||||
{
|
||||
WLog_WARN(TAG,
|
||||
"The VerifyChangedCertificate callback is deprecated, migrate your application to VerifyChangedCertificateEx");
|
||||
accept_certificate = instance->VerifyChangedCertificate(
|
||||
instance, common_name, subject, issuer,
|
||||
fingerprint, old_subject, old_issuer,
|
||||
old_fingerprint);
|
||||
}
|
||||
|
||||
free(old_subject);
|
||||
free(old_issuer);
|
||||
free(old_fingerprint);
|
||||
}
|
||||
else if (match == 0)
|
||||
accept_certificate = 2; /* success! */
|
||||
|
||||
/* Save certificate or do a simple accept / reject */
|
||||
switch (accept_certificate)
|
||||
{
|
||||
case 1:
|
||||
@ -1507,15 +1539,17 @@ int tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname,
|
||||
verification_status = FALSE; /* failure! */
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (match == 0)
|
||||
verification_status = TRUE; /* success! */
|
||||
|
||||
free(issuer);
|
||||
free(subject);
|
||||
free(fingerprint);
|
||||
free(issuer);
|
||||
free(subject);
|
||||
free(fingerprint);
|
||||
}
|
||||
|
||||
if (verification_status)
|
||||
accept_cert(tls, pemCert, length);
|
||||
}
|
||||
|
||||
end:
|
||||
certificate_data_free(certificate_data);
|
||||
free(common_name);
|
||||
|
||||
@ -1523,20 +1557,12 @@ int tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname,
|
||||
crypto_cert_dns_names_free(dns_names_count, dns_names_lengths,
|
||||
dns_names);
|
||||
|
||||
if (verification_status > 0)
|
||||
{
|
||||
accept_cert(tls, pemCert, length);
|
||||
}
|
||||
else
|
||||
{
|
||||
free(pemCert);
|
||||
}
|
||||
|
||||
free(pemCert);
|
||||
return (verification_status == 0) ? 0 : 1;
|
||||
}
|
||||
|
||||
void tls_print_certificate_error(char* hostname, UINT16 port, char* fingerprint,
|
||||
char* hosts_file)
|
||||
void tls_print_certificate_error(const char* hostname, UINT16 port, const char* fingerprint,
|
||||
const char* hosts_file)
|
||||
{
|
||||
WLog_ERR(TAG, "The host key for %s:%"PRIu16" has changed", hostname, port);
|
||||
WLog_ERR(TAG, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
||||
@ -1557,8 +1583,8 @@ void tls_print_certificate_error(char* hostname, UINT16 port, char* fingerprint,
|
||||
WLog_ERR(TAG, "Host key verification failed.");
|
||||
}
|
||||
|
||||
void tls_print_certificate_name_mismatch_error(char* hostname, UINT16 port,
|
||||
char* common_name, char** alt_names,
|
||||
void tls_print_certificate_name_mismatch_error(const char* hostname, UINT16 port,
|
||||
const char* common_name, char** alt_names,
|
||||
int alt_names_count)
|
||||
{
|
||||
int index;
|
||||
|
Loading…
Reference in New Issue
Block a user