libfreerdp-core: merging certificate.c with certstore.c

This commit is contained in:
Marc-André Moreau 2012-02-02 18:20:02 -05:00
parent 26d68997eb
commit 521f956c00
10 changed files with 249 additions and 282 deletions

View File

@ -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 <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <freerdp/api.h>
#include <freerdp/freerdp.h>
#include <freerdp/utils/memory.h>
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 */

View File

@ -2,6 +2,7 @@
* FreeRDP: A Remote Desktop Protocol Client
* Certificate Handling
*
* Copyright 2011 Jiten Pathy
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -24,6 +25,11 @@
#include <openssl/pem.h>
#include <openssl/rsa.h>
#include <freerdp/utils/file.h>
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;

View File

@ -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);

View File

@ -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);

View File

@ -46,7 +46,6 @@
#include <freerdp/freerdp.h>
#include <freerdp/utils/blob.h>
#include <freerdp/utils/memory.h>
#include <freerdp/utils/certstore.h>
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);

View File

@ -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);
}
}

View File

@ -21,6 +21,7 @@
#define __TLS_H
#include "crypto.h"
#include "certificate.h"
#include <openssl/ssl.h>
#include <openssl/err.h>
@ -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 */

View File

@ -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;

View File

@ -38,7 +38,6 @@ set(FREERDP_UTILS_SRCS
rail.c
rect.c
registry.c
certstore.c
semaphore.c
signal.c
sleep.c

View File

@ -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 <freerdp/utils/file.h>
#include <freerdp/utils/certstore.h>
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);
}
}