From 521f956c005a7162a10e376dfff901eeafccb541 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 2 Feb 2012 18:20:02 -0500 Subject: [PATCH] libfreerdp-core: merging certificate.c with certstore.c --- include/freerdp/utils/certstore.h | 39 ------ libfreerdp-core/certificate.c | 166 ++++++++++++++++++++++++- libfreerdp-core/certificate.h | 31 ++++- libfreerdp-core/credssp.c | 2 +- libfreerdp-core/crypto.h | 5 +- libfreerdp-core/tls.c | 70 ++++++----- libfreerdp-core/tls.h | 13 +- libfreerdp-core/transport.c | 8 +- libfreerdp-utils/CMakeLists.txt | 1 - libfreerdp-utils/certstore.c | 196 ------------------------------ 10 files changed, 249 insertions(+), 282 deletions(-) delete mode 100644 include/freerdp/utils/certstore.h delete mode 100644 libfreerdp-utils/certstore.c diff --git a/include/freerdp/utils/certstore.h b/include/freerdp/utils/certstore.h deleted file mode 100644 index 45b8bd9b8..000000000 --- a/include/freerdp/utils/certstore.h +++ /dev/null @@ -1,39 +0,0 @@ - -#ifndef __CERTSTORE_UTILS_H -#define __CERTSTORE_UTILS_H - -typedef struct rdp_certificate_data rdpCertificateData; -typedef struct rdp_certificate_store rdpCertificateStore; - -#include -#include -#include -#include -#include -#include - -struct rdp_certificate_data -{ - char* hostname; - char* fingerprint; -}; - -struct rdp_certificate_store -{ - FILE* fp; - int match; - char* path; - char* file; - rdpSettings* settings; - rdpCertificateData* certificate_data; -}; - -FREERDP_API char* certificate_store_get_path(rdpCertificateStore* certificate_store); -FREERDP_API rdpCertificateData* certificate_data_new(char* hostname, char* fingerprint); -FREERDP_API void certificate_data_free(rdpCertificateData* certificate_data); -FREERDP_API rdpCertificateStore* certificate_store_new(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 void certificate_data_print(rdpCertificateStore* certificate_store, rdpCertificateData* certificate_data); - -#endif /* __CERTSTORE_UTILS_H */ diff --git a/libfreerdp-core/certificate.c b/libfreerdp-core/certificate.c index 8103fcf82..67c06a6cf 100644 --- a/libfreerdp-core/certificate.c +++ b/libfreerdp-core/certificate.c @@ -2,6 +2,7 @@ * FreeRDP: A Remote Desktop Protocol Client * Certificate Handling * + * Copyright 2011 Jiten Pathy * Copyright 2011 Marc-Andre Moreau * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,6 +25,11 @@ #include #include +#include + +static const char certificate_store_dir[] = "cacert"; +static const char certificate_known_hosts_file[] = "known_hosts"; + #include "certificate.h" /** @@ -550,13 +556,171 @@ void key_free(rdpKey* key) } } +void certificate_store_init(rdpCertificateStore* certificate_store) +{ + char* config_path; + rdpSettings* settings; + + settings = certificate_store->settings; + + config_path = freerdp_get_config_path(settings); + certificate_store->path = freerdp_construct_path(config_path, (char*) certificate_store_dir); + + if (freerdp_check_file_exists(certificate_store->path) == false) + { + freerdp_mkdir(certificate_store->path); + printf("creating directory %s\n", certificate_store->path); + } + + certificate_store->file = freerdp_construct_path(config_path, (char*) certificate_known_hosts_file); + + if (freerdp_check_file_exists(certificate_store->file) == false) + { + certificate_store->fp = fopen((char*) certificate_store->file, "w+"); + + if (certificate_store->fp == NULL) + { + printf("certificate_store_open: error opening [%s] for writing\n", certificate_store->file); + return; + } + + fflush(certificate_store->fp); + } + else + { + certificate_store->fp = fopen((char*) certificate_store->file, "r+"); + } +} + +int certificate_data_match(rdpCertificateStore* certificate_store, rdpCertificateData* certificate_data) +{ + FILE* fp; + int length; + char* data; + char* pline; + int match = 1; + long int size; + + fp = certificate_store->fp; + + if (!fp) + return match; + + fseek(fp, 0, SEEK_END); + size = ftell(fp); + fseek(fp, 0, SEEK_SET); + + data = (char*) xmalloc(size + 1); + length = fread(data, size, 1, fp); + + if (size < 1) + return match; + + data[size] = '\n'; + pline = strtok(data, "\n"); + + while (pline != NULL) + { + length = strlen(pline); + + if (length > 0) + { + length = strcspn(pline, " \t"); + pline[length] = '\0'; + + if (strcmp(pline, certificate_data->hostname) == 0) + { + pline = &pline[length + 1]; + + if (strcmp(pline, certificate_data->fingerprint) == 0) + match = 0; + else + match = -1; + break; + } + } + + pline = strtok(NULL, "\n"); + } + xfree(data); + + return match; +} + +void certificate_data_print(rdpCertificateStore* certificate_store, rdpCertificateData* certificate_data) +{ + FILE* fp; + + /* reopen in append mode */ + fp = fopen(certificate_store->file, "a"); + + if (!fp) + return; + + fprintf(certificate_store->fp,"%s %s\n", certificate_data->hostname, certificate_data->fingerprint); + fclose(fp); +} + +rdpCertificateData* certificate_data_new(char* hostname, char* fingerprint) +{ + rdpCertificateData* certdata; + + certdata = (rdpCertificateData*) xzalloc(sizeof(rdpCertificateData)); + + if (certdata != NULL) + { + certdata->hostname = xstrdup(hostname); + certdata->fingerprint = xstrdup(fingerprint); + } + + return certdata; +} + +void certificate_data_free(rdpCertificateData* certificate_data) +{ + if (certificate_data != NULL) + { + xfree(certificate_data->hostname); + xfree(certificate_data->fingerprint); + xfree(certificate_data); + } +} + +rdpCertificateStore* certificate_store_new(rdpSettings* settings) +{ + rdpCertificateStore* certificate_store; + + certificate_store = (rdpCertificateStore*) xzalloc(sizeof(rdpCertificateStore)); + + if (certificate_store != NULL) + { + certificate_store->settings = settings; + certificate_store_init(certificate_store); + } + + return certificate_store; +} + +void certificate_store_free(rdpCertificateStore* certstore) +{ + if (certstore != NULL) + { + if (certstore->fp != NULL) + fclose(certstore->fp); + + xfree(certstore->path); + xfree(certstore->file); + xfree(certstore); + } +} + /** * Instantiate new certificate module.\n * @param rdp RDP module * @return new certificate module */ -rdpCertificate* certificate_new(void) +rdpCertificate* certificate_new() { rdpCertificate* certificate; diff --git a/libfreerdp-core/certificate.h b/libfreerdp-core/certificate.h index a1e7ef006..2451dd471 100644 --- a/libfreerdp-core/certificate.h +++ b/libfreerdp-core/certificate.h @@ -20,6 +20,9 @@ #ifndef __CERTIFICATE_H #define __CERTIFICATE_H +typedef struct rdp_certificate_data rdpCertificateData; +typedef struct rdp_certificate_store rdpCertificateStore; + #include "rdp.h" #include "ber.h" #include "crypto.h" @@ -36,8 +39,8 @@ #define CERT_PERMANENTLY_ISSUED 0x00000000 #define CERT_TEMPORARILY_ISSUED 0x80000000 -#define SIGNATURE_ALG_RSA 0x00000001 -#define KEY_EXCHANGE_ALG_RSA 0x00000001 +#define SIGNATURE_ALG_RSA 0x00000001 +#define KEY_EXCHANGE_ALG_RSA 0x00000001 #define BB_RSA_KEY_BLOB 6 #define BB_RSA_SIGNATURE_BLOB 8 @@ -49,6 +52,28 @@ struct rdp_key uint8 exponent[4]; }; +struct rdp_certificate_data +{ + char* hostname; + char* fingerprint; +}; + +struct rdp_certificate_store +{ + FILE* fp; + char* path; + char* file; + rdpSettings* settings; + rdpCertificateData* certificate_data; +}; + +rdpCertificateData* certificate_data_new(char* hostname, char* fingerprint); +void certificate_data_free(rdpCertificateData* certificate_data); +rdpCertificateStore* certificate_store_new(rdpSettings* settings); +void certificate_store_free(rdpCertificateStore* certificate_store); +int certificate_data_match(rdpCertificateStore* certificate_store, rdpCertificateData* certificate_data); +void certificate_data_print(rdpCertificateStore* certificate_store, rdpCertificateData* certificate_data); + void certificate_read_x509_certificate(rdpCertBlob* cert, rdpCertInfo* info); rdpX509CertChain* certificate_new_x509_certificate_chain(uint32 count); @@ -58,7 +83,7 @@ boolean certificate_read_server_proprietary_certificate(rdpCertificate* certific boolean certificate_read_server_x509_certificate_chain(rdpCertificate* certificate, STREAM* s); boolean certificate_read_server_certificate(rdpCertificate* certificate, uint8* server_cert, int length); -rdpCertificate* certificate_new(void); +rdpCertificate* certificate_new(); void certificate_free(rdpCertificate* certificate); rdpKey* key_new(const char *keyfile); diff --git a/libfreerdp-core/credssp.c b/libfreerdp-core/credssp.c index 956473dd8..64aa1f0b2 100644 --- a/libfreerdp-core/credssp.c +++ b/libfreerdp-core/credssp.c @@ -136,7 +136,7 @@ int credssp_get_public_key(rdpCredssp* credssp) return 0; } - if (tls_verify_certificate(cert, credssp->transport->settings, credssp->transport->settings->hostname)) + if (tls_verify_certificate(credssp->transport->tls, cert, credssp->transport->settings->hostname)) tls_disconnect(credssp->transport->tls); status = crypto_cert_get_public_key(cert, &credssp->public_key); diff --git a/libfreerdp-core/crypto.h b/libfreerdp-core/crypto.h index bc0248178..9253305ae 100644 --- a/libfreerdp-core/crypto.h +++ b/libfreerdp-core/crypto.h @@ -46,7 +46,6 @@ #include #include #include -#include struct crypto_sha1_struct { @@ -110,12 +109,16 @@ void crypto_hmac_final(CryptoHmac hmac, uint8 *out_data, uint32 length); void crypto_hmac_free(CryptoHmac hmac); typedef struct crypto_cert_struct* CryptoCert; + +#include "certificate.h" + CryptoCert crypto_cert_read(uint8* data, uint32 length); char* crypto_cert_fingerprint(X509* xcert); char* crypto_cert_subject(X509* xcert); char* crypto_cert_issuer(X509* xcert); void crypto_cert_print_info(X509* xcert); void crypto_cert_free(CryptoCert cert); + boolean x509_verify_certificate(CryptoCert cert, char* certificate_store_path); rdpCertificateData* crypto_get_certificate_data(X509* xcert, char* hostname); boolean crypto_cert_get_public_key(CryptoCert cert, rdpBlob* public_key); diff --git a/libfreerdp-core/tls.c b/libfreerdp-core/tls.c index 5fde2b8ae..22137b2de 100644 --- a/libfreerdp-core/tls.c +++ b/libfreerdp-core/tls.c @@ -176,7 +176,7 @@ int tls_write(rdpTls* tls, uint8* data, int length) return status; } -boolean tls_print_error(char *func, SSL *connection, int value) +boolean tls_print_error(char* func, SSL* connection, int value) { switch (SSL_get_error(connection, value)) { @@ -206,7 +206,7 @@ boolean tls_print_error(char *func, SSL *connection, int value) } } -CryptoCert tls_get_certificate(rdpTls * tls) +CryptoCert tls_get_certificate(rdpTls* tls) { CryptoCert cert; X509* server_cert; @@ -227,29 +227,12 @@ CryptoCert tls_get_certificate(rdpTls * tls) return cert; } -rdpTls* tls_new() -{ - rdpTls* tls; - - tls = (rdpTls*) xzalloc(sizeof(rdpTls)); - - if (tls != NULL) - { - SSL_load_error_strings(); - SSL_library_init(); - } - - return tls; -} - -int tls_verify_certificate(CryptoCert cert, rdpSettings* settings, char* hostname) +int tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname) { + int match; boolean status; - rdpCertificateStore* certificate_store; - certificate_store = certificate_store_new(settings); - - status = x509_verify_certificate(cert, certificate_store->path); + status = x509_verify_certificate(cert, tls->certificate_store->path); if (status != true) { @@ -260,20 +243,22 @@ int tls_verify_certificate(CryptoCert cert, rdpSettings* settings, char* hostnam certificate_data = crypto_get_certificate_data(cert->px509, hostname); - if (certificate_data_match(certificate_store, certificate_data) == 0) + match = certificate_data_match(tls->certificate_store, certificate_data); + + if (match == 0) return 0; issuer = crypto_cert_issuer(cert->px509); subject = crypto_cert_subject(cert->px509); fingerprint = crypto_cert_fingerprint(cert->px509); - if (certificate_store->match == 1) + if (match == 1) { - boolean accept_certificate = settings->ignore_certificate; + boolean accept_certificate = tls->settings->ignore_certificate; if (!accept_certificate) { - freerdp* instance = (freerdp*) settings->instance; + freerdp* instance = (freerdp*) tls->settings->instance; if (instance->VerifyCertificate) accept_certificate = instance->VerifyCertificate(instance, subject, issuer, fingerprint); @@ -286,22 +271,19 @@ int tls_verify_certificate(CryptoCert cert, rdpSettings* settings, char* hostnam if (!accept_certificate) return 1; - certificate_data_print(certificate_store, certificate_data); + certificate_data_print(tls->certificate_store, certificate_data); } - else if (certificate_store->match == -1) + else if (match == -1) { - tls_print_cert_error(hostname, fingerprint); - certificate_store_free(certificate_store); + tls_print_certificate_error(hostname, fingerprint); return 1; } } - certificate_store_free(certificate_store); - return 0; } -void tls_print_cert_error(char* hostname, char* fingerprint) +void tls_print_certificate_error(char* hostname, char* fingerprint) { printf("The host key for %s has changed\n", hostname); printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"); @@ -317,14 +299,36 @@ void tls_print_cert_error(char* hostname, char* fingerprint) printf("Host key verification failed.\n"); } +rdpTls* tls_new(rdpSettings* settings) +{ + rdpTls* tls; + + tls = (rdpTls*) xzalloc(sizeof(rdpTls)); + + if (tls != NULL) + { + SSL_load_error_strings(); + SSL_library_init(); + + tls->settings = settings; + tls->certificate_store = certificate_store_new(settings); + } + + return tls; +} + void tls_free(rdpTls* tls) { if (tls != NULL) { if (tls->ssl) SSL_free(tls->ssl); + if (tls->ctx) SSL_CTX_free(tls->ctx); + + certificate_store_free(tls->certificate_store); + xfree(tls); } } diff --git a/libfreerdp-core/tls.h b/libfreerdp-core/tls.h index 369cd3260..06e565971 100644 --- a/libfreerdp-core/tls.h +++ b/libfreerdp-core/tls.h @@ -21,6 +21,7 @@ #define __TLS_H #include "crypto.h" +#include "certificate.h" #include #include @@ -35,18 +36,24 @@ struct rdp_tls SSL* ssl; int sockfd; SSL_CTX* ctx; + rdpSettings* settings; + rdpCertificateStore* certificate_store; }; boolean tls_connect(rdpTls* tls); boolean tls_accept(rdpTls* tls, const char* cert_file, const char* privatekey_file); boolean tls_disconnect(rdpTls* tls); + int tls_read(rdpTls* tls, uint8* data, int length); int tls_write(rdpTls* tls, uint8* data, int length); + CryptoCert tls_get_certificate(rdpTls* tls); -int tls_verify_certificate(CryptoCert cert, rdpSettings* settings, char* hostname); -void tls_print_cert_error(); +int tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname); +void tls_print_certificate_error(); + boolean tls_print_error(char* func, SSL* connection, int value); -rdpTls* tls_new(); + +rdpTls* tls_new(rdpSettings* settings); void tls_free(rdpTls* tls); #endif /* __TLS_H */ diff --git a/libfreerdp-core/transport.c b/libfreerdp-core/transport.c index d52449a51..0ec9d77c6 100644 --- a/libfreerdp-core/transport.c +++ b/libfreerdp-core/transport.c @@ -85,7 +85,7 @@ boolean transport_connect_rdp(rdpTransport* transport) boolean transport_connect_tls(rdpTransport* transport) { if (transport->tls == NULL) - transport->tls = tls_new(); + transport->tls = tls_new(transport->settings); transport->layer = TRANSPORT_LAYER_TLS; transport->tls->sockfd = transport->tcp->sockfd; @@ -99,7 +99,7 @@ boolean transport_connect_tls(rdpTransport* transport) boolean transport_connect_nla(rdpTransport* transport) { if (transport->tls == NULL) - transport->tls = tls_new(); + transport->tls = tls_new(transport->settings); transport->layer = TRANSPORT_LAYER_TLS; transport->tls->sockfd = transport->tcp->sockfd; @@ -139,7 +139,7 @@ boolean transport_accept_rdp(rdpTransport* transport) boolean transport_accept_tls(rdpTransport* transport) { if (transport->tls == NULL) - transport->tls = tls_new(); + transport->tls = tls_new(transport->settings); transport->layer = TRANSPORT_LAYER_TLS; transport->tls->sockfd = transport->tcp->sockfd; @@ -153,7 +153,7 @@ boolean transport_accept_tls(rdpTransport* transport) boolean transport_accept_nla(rdpTransport* transport) { if (transport->tls == NULL) - transport->tls = tls_new(); + transport->tls = tls_new(transport->settings); transport->layer = TRANSPORT_LAYER_TLS; transport->tls->sockfd = transport->tcp->sockfd; diff --git a/libfreerdp-utils/CMakeLists.txt b/libfreerdp-utils/CMakeLists.txt index 34020418f..6757afcd8 100644 --- a/libfreerdp-utils/CMakeLists.txt +++ b/libfreerdp-utils/CMakeLists.txt @@ -38,7 +38,6 @@ set(FREERDP_UTILS_SRCS rail.c rect.c registry.c - certstore.c semaphore.c signal.c sleep.c diff --git a/libfreerdp-utils/certstore.c b/libfreerdp-utils/certstore.c deleted file mode 100644 index 702618dbb..000000000 --- a/libfreerdp-utils/certstore.c +++ /dev/null @@ -1,196 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Client - * certstore Utils - * - * Copyright 2011 Jiten Pathy - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include - -static const char certificate_store_subdir[] = "cacert"; -static const char certificate_store_file[] = "known_hosts"; - -void certificate_store_open(rdpCertificateStore* certificate_store) -{ - if (freerdp_check_file_exists(certificate_store->file) == false) - { - certificate_store->fp = fopen((char*) certificate_store->file, "w+"); - - if (certificate_store->fp == NULL) - { - printf("certificate_store_open: error opening [%s] for writing\n", certificate_store->file); - return; - } - - fflush(certificate_store->fp); - } - else - { - certificate_store->fp = fopen((char*) certificate_store->file, "r+"); - } -} - -void certificate_store_close(rdpCertificateStore* certstore) -{ - if (certstore->fp != NULL) - fclose(certstore->fp); -} - -char* certificate_store_get_path(rdpCertificateStore* certificate_store) -{ - return certificate_store->path; -} - -void certificate_store_init(rdpCertificateStore* certificate_store) -{ - char* config_path; - rdpSettings* settings; - - certificate_store->match = 1; - settings = certificate_store->settings; - - config_path = freerdp_get_config_path(settings); - certificate_store->path = freerdp_construct_path(config_path, (char*) certificate_store_subdir); - - if (freerdp_check_file_exists(certificate_store->path) == false) - { - freerdp_mkdir(certificate_store->path); - printf("creating directory %s\n", certificate_store->path); - } - - certificate_store->file = freerdp_construct_path(certificate_store->path, (char*) certificate_store_file); - - certificate_store_open(certificate_store); -} - -int certificate_data_match(rdpCertificateStore* certificate_store, rdpCertificateData* certificate_data) -{ - FILE* fp; - int length; - char* data; - char* pline; - long int size; - - fp = certificate_store->fp; - - if (!fp) - return certificate_store->match; - - fseek(fp, 0, SEEK_END); - size = ftell(fp); - fseek(fp, 0, SEEK_SET); - - data = (char*) xmalloc(size + 1); - length = fread(data, size, 1, fp); - - if (size < 1) - return certificate_store->match; - - data[size] = '\n'; - pline = strtok(data, "\n"); - - while (pline != NULL) - { - length = strlen(pline); - - if (length > 0) - { - length = strcspn(pline, " \t"); - pline[length] = '\0'; - - if (strcmp(pline, certificate_data->hostname) == 0) - { - pline = &pline[length + 1]; - - if (strcmp(pline, certificate_data->fingerprint) == 0) - certificate_store->match = 0; - else - certificate_store->match = -1; - break; - } - } - - pline = strtok(NULL, "\n"); - } - xfree(data); - - return certificate_store->match; -} - -void certificate_data_print(rdpCertificateStore* certificate_store, rdpCertificateData* certificate_data) -{ - FILE* fp; - - /* reopen in append mode */ - fp = fopen(certificate_store->file, "a"); - - if (!fp) - return; - - fprintf(certificate_store->fp,"%s %s\n", certificate_data->hostname, certificate_data->fingerprint); - fclose(fp); -} - -rdpCertificateData* certificate_data_new(char* hostname, char* fingerprint) -{ - rdpCertificateData* certdata; - - certdata = (rdpCertificateData*) xzalloc(sizeof(rdpCertificateData)); - - if (certdata != NULL) - { - certdata->hostname = xstrdup(hostname); - certdata->fingerprint = xstrdup(fingerprint); - } - - return certdata; -} - -void certificate_data_free(rdpCertificateData* certificate_data) -{ - if (certificate_data != NULL) - { - xfree(certificate_data->hostname); - xfree(certificate_data->fingerprint); - xfree(certificate_data); - } -} - -rdpCertificateStore* certificate_store_new(rdpSettings* settings) -{ - rdpCertificateStore* certificate_store; - - certificate_store = (rdpCertificateStore*) xzalloc(sizeof(rdpCertificateStore)); - - if (certificate_store != NULL) - { - certificate_store->settings = settings; - certificate_store_init(certificate_store); - } - - return certificate_store; -} - -void certificate_store_free(rdpCertificateStore* certstore) -{ - if (certstore != NULL) - { - certificate_store_close(certstore); - xfree(certstore->path); - xfree(certstore->file); - xfree(certstore); - } -}