From bae5de89e1bc7f35925c983217fcdbe094edb722 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 2 Feb 2012 17:36:07 -0500 Subject: [PATCH] libfreerdp-utils: refactoring of certificate store --- include/freerdp/utils/certstore.h | 32 ++-- libfreerdp-core/certificate.c | 164 ++++++++++++--------- libfreerdp-core/credssp.c | 2 +- libfreerdp-core/crypto.c | 35 +++-- libfreerdp-core/crypto.h | 4 +- libfreerdp-core/tls.c | 29 ++-- libfreerdp-utils/certstore.c | 235 ++++++++++++------------------ 7 files changed, 239 insertions(+), 262 deletions(-) diff --git a/include/freerdp/utils/certstore.h b/include/freerdp/utils/certstore.h index 2a5f9bda2..45b8bd9b8 100644 --- a/include/freerdp/utils/certstore.h +++ b/include/freerdp/utils/certstore.h @@ -1,8 +1,9 @@ + #ifndef __CERTSTORE_UTILS_H #define __CERTSTORE_UTILS_H -typedef struct rdp_cert_store rdpCertStore; -typedef struct rdp_cert_data rdpCertData; +typedef struct rdp_certificate_data rdpCertificateData; +typedef struct rdp_certificate_store rdpCertificateStore; #include #include @@ -11,33 +12,28 @@ typedef struct rdp_cert_data rdpCertData; #include #include -struct rdp_cert_data +struct rdp_certificate_data { char* hostname; char* fingerprint; }; -struct rdp_cert_store +struct rdp_certificate_store { FILE* fp; int match; char* path; char* file; - char* home_path; - rdpCertData* certdata; + rdpSettings* settings; + rdpCertificateData* certificate_data; }; -FREERDP_API void certstore_create(rdpCertStore* certstore); -FREERDP_API void certstore_open(rdpCertStore* certstore); -FREERDP_API void certstore_load(rdpCertStore* certstore); -FREERDP_API void certstore_close(rdpCertStore* certstore); -FREERDP_API char* get_local_certloc(); -FREERDP_API rdpCertData* certdata_new(char* hostname, char* fingerprint); -FREERDP_API void certdata_free(rdpCertData* certdata); -FREERDP_API void certstore_init(rdpCertStore* certstore); -FREERDP_API rdpCertStore* certstore_new(rdpCertData* certdata, char* home_path); -FREERDP_API void certstore_free(rdpCertStore* certstore); -FREERDP_API int cert_data_match(rdpCertStore* certstore); -FREERDP_API void cert_data_print(rdpCertStore* certstore); +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 9c91f15d5..8103fcf82 100644 --- a/libfreerdp-core/certificate.c +++ b/libfreerdp-core/certificate.c @@ -281,31 +281,41 @@ static boolean certificate_process_server_public_signature(rdpCertificate* certi crypto_md5_final(md5ctx, md5hash); stream_read(s, encsig, siglen); + /* Last 8 bytes shall be all zero. */ + for (sum = 0, i = sizeof(encsig) - 8; i < sizeof(encsig); i++) sum += encsig[i]; - if (sum != 0) { + + if (sum != 0) + { printf("certificate_process_server_public_signature: invalid signature\n"); //return false; } + siglen -= 8; crypto_rsa_public_decrypt(encsig, siglen, TSSK_KEY_LENGTH, tssk_modulus, tssk_exponent, sig); /* Verify signature. */ - if (memcmp(md5hash, sig, sizeof(md5hash)) != 0) { + if (memcmp(md5hash, sig, sizeof(md5hash)) != 0) + { printf("certificate_process_server_public_signature: invalid signature\n"); //return false; } + /* * Verify rest of decrypted data: * The 17th byte is 0x00. * The 18th through 62nd bytes are each 0xFF. * The 63rd byte is 0x01. */ + for (sum = 0, i = 17; i < 62; i++) sum += sig[i]; - if (sig[16] != 0x00 || sum != 0xFF * (62 - 17) || sig[62] != 0x01) { + + if (sig[16] != 0x00 || sum != 0xFF * (62 - 17) || sig[62] != 0x01) + { printf("certificate_process_server_public_signature: invalid signature\n"); //return false; } @@ -461,6 +471,85 @@ boolean certificate_read_server_certificate(rdpCertificate* certificate, uint8* return true; } +rdpKey* key_new(const char* keyfile) +{ + rdpKey* key; + RSA *rsa; + FILE *fp; + + key = (rdpKey*) xzalloc(sizeof(rdpKey)); + + if (key == NULL) + return NULL; + + fp = fopen(keyfile, "r"); + + if (fp == NULL) + { + printf("unable to load RSA key from %s: %s.", keyfile, strerror(errno)); + return NULL; + } + + rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); + + if (rsa == NULL) + { + ERR_print_errors_fp(stdout); + fclose(fp); + return NULL; + } + + fclose(fp); + + switch (RSA_check_key(rsa)) + { + case 0: + RSA_free(rsa); + printf("invalid RSA key in %s", keyfile); + return NULL; + + case 1: + /* Valid key. */ + break; + + default: + ERR_print_errors_fp(stdout); + RSA_free(rsa); + return NULL; + } + + if (BN_num_bytes(rsa->e) > 4) + { + RSA_free(rsa); + printf("RSA public exponent too large in %s", keyfile); + return NULL; + } + + freerdp_blob_alloc(&key->modulus, BN_num_bytes(rsa->n)); + BN_bn2bin(rsa->n, key->modulus.data); + crypto_reverse(key->modulus.data, key->modulus.length); + freerdp_blob_alloc(&key->private_exponent, BN_num_bytes(rsa->d)); + BN_bn2bin(rsa->d, key->private_exponent.data); + crypto_reverse(key->private_exponent.data, key->private_exponent.length); + memset(key->exponent, 0, sizeof(key->exponent)); + BN_bn2bin(rsa->e, key->exponent + sizeof(key->exponent) - BN_num_bytes(rsa->e)); + crypto_reverse(key->exponent, sizeof(key->exponent)); + + RSA_free(rsa); + + return key; +} + +void key_free(rdpKey* key) +{ + if (key != NULL) + { + freerdp_blob_free(&key->modulus); + freerdp_blob_free(&key->private_exponent); + xfree(key); + } +} + /** * Instantiate new certificate module.\n * @param rdp RDP module @@ -498,72 +587,3 @@ void certificate_free(rdpCertificate* certificate) xfree(certificate); } } - -rdpKey* key_new(const char *keyfile) -{ - rdpKey* key; - RSA *rsa; - FILE *fp; - - key = (rdpKey*) xzalloc(sizeof(rdpKey)); - if (key == NULL) - return NULL; - - fp = fopen(keyfile, "r"); - if (fp == NULL) { - printf("unable to load RSA key from %s: %s.", keyfile, - strerror(errno)); - return NULL; - } - rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); - if (rsa == NULL) { - ERR_print_errors_fp(stdout); - fclose(fp); - return NULL; - } - fclose(fp); - - switch (RSA_check_key(rsa)) { - case 0: - RSA_free(rsa); - printf("invalid RSA key in %s", keyfile); - return NULL; - case 1: - /* Valid key. */ - break; - default: - ERR_print_errors_fp(stdout); - RSA_free(rsa); - return NULL; - } - - if (BN_num_bytes(rsa->e) > 4) { - RSA_free(rsa); - printf("RSA public exponent too large in %s", keyfile); - return NULL; - } - - freerdp_blob_alloc(&key->modulus, BN_num_bytes(rsa->n)); - BN_bn2bin(rsa->n, key->modulus.data); - crypto_reverse(key->modulus.data, key->modulus.length); - freerdp_blob_alloc(&key->private_exponent, BN_num_bytes(rsa->d)); - BN_bn2bin(rsa->d, key->private_exponent.data); - crypto_reverse(key->private_exponent.data, key->private_exponent.length); - memset(key->exponent, 0, sizeof(key->exponent)); - BN_bn2bin(rsa->e, key->exponent + sizeof(key->exponent) - BN_num_bytes(rsa->e)); - crypto_reverse(key->exponent, sizeof(key->exponent)); - - RSA_free(rsa); - - return key; -} - -void key_free(rdpKey* key) -{ - if (key != NULL) - { - freerdp_blob_free(&key->modulus); - freerdp_blob_free(&key->private_exponent); - xfree(key); - } -} diff --git a/libfreerdp-core/credssp.c b/libfreerdp-core/credssp.c index 2b4952be6..956473dd8 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(cert, credssp->transport->settings, 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.c b/libfreerdp-core/crypto.c index 426481c92..1b1ada5fb 100644 --- a/libfreerdp-core/crypto.c +++ b/libfreerdp-core/crypto.c @@ -100,8 +100,9 @@ void crypto_des3_decrypt(CryptoDes3 des3, uint32 length, const uint8* in_data, u { int len; EVP_DecryptUpdate(&des3->des3_ctx, out_data, &len, in_data, length); + if (length != len) - abort(); // TODO + abort(); /* TODO */ } void crypto_des3_free(CryptoDes3 des3) @@ -190,9 +191,11 @@ exit: /* * Terminal Services Signing Keys. - * Yes, Terminal Services Private Key is publically available. + * Yes, Terminal Services Private Key is publicly available. */ -const uint8 tssk_modulus[] = { + +const uint8 tssk_modulus[] = +{ 0x3d, 0x3a, 0x5e, 0xbd, 0x72, 0x43, 0x3e, 0xc9, 0x4d, 0xbb, 0xc1, 0x1e, 0x4a, 0xba, 0x5f, 0xcb, 0x3e, 0x88, 0x20, 0x87, 0xef, 0xf5, 0xc1, 0xe2, @@ -202,7 +205,9 @@ const uint8 tssk_modulus[] = { 0x6c, 0x5e, 0x06, 0x09, 0x1a, 0xf5, 0x61, 0xbb, 0x20, 0x93, 0x09, 0x5f, 0x05, 0x6d, 0xea, 0x87 }; -const uint8 tssk_privateExponent[] = { + +const uint8 tssk_privateExponent[] = +{ 0x87, 0xa7, 0x19, 0x32, 0xda, 0x11, 0x87, 0x55, 0x58, 0x00, 0x16, 0x16, 0x25, 0x65, 0x68, 0xf8, 0x24, 0x3e, 0xe6, 0xfa, 0xe9, 0x67, 0x49, 0x94, @@ -212,7 +217,9 @@ const uint8 tssk_privateExponent[] = { 0x35, 0x07, 0x79, 0x17, 0x0b, 0x51, 0x9b, 0xb3, 0xc7, 0x10, 0x01, 0x13, 0xe7, 0x3f, 0xf3, 0x5f }; -const uint8 tssk_exponent[] = { + +const uint8 tssk_exponent[] = +{ 0x5b, 0x7b, 0x88, 0xc0 }; @@ -263,7 +270,6 @@ static void crypto_rsa_common(const uint8* input, int length, uint32 key_length, static void crypto_rsa_public(const uint8* input, int length, uint32 key_length, const uint8* modulus, const uint8* exponent, uint8* output) { - crypto_rsa_common(input, length, key_length, modulus, exponent, EXPONENT_MAX_SIZE, output); } @@ -372,9 +378,8 @@ char* crypto_cert_issuer(X509* xcert) return crypto_print_name(X509_get_issuer_name(xcert)); } -boolean x509_verify_cert(CryptoCert cert, rdpSettings* settings) +boolean x509_verify_certificate(CryptoCert cert, char* certificate_store_path) { - char* cert_loc; X509_STORE_CTX* csc; boolean status = false; X509_STORE* cert_ctx = NULL; @@ -398,12 +403,10 @@ boolean x509_verify_cert(CryptoCert cert, rdpSettings* settings) goto end; X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); - cert_loc = get_local_certloc(settings->home_path); - if(cert_loc != NULL) + if (certificate_store_path != NULL) { - X509_LOOKUP_add_dir(lookup, cert_loc, X509_FILETYPE_ASN1); - xfree(cert_loc); + X509_LOOKUP_add_dir(lookup, certificate_store_path, X509_FILETYPE_ASN1); } csc = X509_STORE_CTX_new(); @@ -413,7 +416,7 @@ boolean x509_verify_cert(CryptoCert cert, rdpSettings* settings) X509_STORE_set_flags(cert_ctx, 0); - if(!X509_STORE_CTX_init(csc, cert_ctx, xcert, 0)) + if (!X509_STORE_CTX_init(csc, cert_ctx, xcert, 0)) goto end; if (X509_verify_cert(csc) == 1) @@ -426,13 +429,13 @@ end: return status; } -rdpCertData* crypto_get_cert_data(X509* xcert, char* hostname) +rdpCertificateData* crypto_get_certificate_data(X509* xcert, char* hostname) { char* fp; - rdpCertData* certdata; + rdpCertificateData* certdata; fp = crypto_cert_fingerprint(xcert); - certdata = certdata_new(hostname, fp); + certdata = certificate_data_new(hostname, fp); xfree(fp); return certdata; diff --git a/libfreerdp-core/crypto.h b/libfreerdp-core/crypto.h index 6b4d30b74..bc0248178 100644 --- a/libfreerdp-core/crypto.h +++ b/libfreerdp-core/crypto.h @@ -116,8 +116,8 @@ 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_cert(CryptoCert cert, rdpSettings* settings); -rdpCertData* crypto_get_cert_data(X509* xcert, char* hostname); +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); #define TSSK_KEY_LENGTH 64 diff --git a/libfreerdp-core/tls.c b/libfreerdp-core/tls.c index bab86969b..5fde2b8ae 100644 --- a/libfreerdp-core/tls.c +++ b/libfreerdp-core/tls.c @@ -245,27 +245,29 @@ rdpTls* tls_new() int tls_verify_certificate(CryptoCert cert, rdpSettings* settings, char* hostname) { boolean status; - rdpCertStore* certstore; - status = x509_verify_cert(cert, settings); + rdpCertificateStore* certificate_store; + + certificate_store = certificate_store_new(settings); + + status = x509_verify_certificate(cert, certificate_store->path); if (status != true) { char* issuer; char* subject; char* fingerprint; - rdpCertData* certdata; + rdpCertificateData* certificate_data; - certdata = crypto_get_cert_data(cert->px509, hostname); - certstore = certstore_new(certdata, settings->home_path); + certificate_data = crypto_get_certificate_data(cert->px509, hostname); - if (cert_data_match(certstore) == 0) - goto end; + if (certificate_data_match(certificate_store, certificate_data) == 0) + return 0; issuer = crypto_cert_issuer(cert->px509); subject = crypto_cert_subject(cert->px509); fingerprint = crypto_cert_fingerprint(cert->px509); - if (certstore->match == 1) + if (certificate_store->match == 1) { boolean accept_certificate = settings->ignore_certificate; @@ -284,19 +286,18 @@ int tls_verify_certificate(CryptoCert cert, rdpSettings* settings, char* hostnam if (!accept_certificate) return 1; - cert_data_print(certstore); + certificate_data_print(certificate_store, certificate_data); } - else if (certstore->match == -1) + else if (certificate_store->match == -1) { tls_print_cert_error(hostname, fingerprint); - certstore_free(certstore); + certificate_store_free(certificate_store); return 1; } - -end: - certstore_free(certstore); } + certificate_store_free(certificate_store); + return 0; } diff --git a/libfreerdp-utils/certstore.c b/libfreerdp-utils/certstore.c index 3288e06a2..702618dbb 100644 --- a/libfreerdp-utils/certstore.c +++ b/libfreerdp-utils/certstore.c @@ -20,168 +20,74 @@ #include #include -static const char cert_dir[] = "freerdp"; -static const char cert_loc[] = "cacert"; -static const char certstore_file[] = "known_hosts"; +static const char certificate_store_subdir[] = "cacert"; +static const char certificate_store_file[] = "known_hosts"; -void certstore_create(rdpCertStore* certstore) +void certificate_store_open(rdpCertificateStore* certificate_store) { - certstore->fp = fopen((char*) certstore->file, "w+"); - - if (certstore->fp == NULL) + if (freerdp_check_file_exists(certificate_store->file) == false) { - printf("certstore_create: error opening [%s] for writing\n", certstore->file); - return; + 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); } - - fflush(certstore->fp); -} - -void certstore_load(rdpCertStore* certstore) -{ - certstore->fp = fopen((char*) certstore->file, "r+"); -} - -void certstore_open(rdpCertStore* certstore) -{ - struct stat stat_info; - - if (stat((char*) certstore->file, &stat_info) != 0) - certstore_create(certstore); else - certstore_load(certstore); + { + certificate_store->fp = fopen((char*) certificate_store->file, "r+"); + } } -void certstore_close(rdpCertStore* certstore) +void certificate_store_close(rdpCertificateStore* certstore) { if (certstore->fp != NULL) fclose(certstore->fp); } -char* get_local_certloc(char* home_path) +char* certificate_store_get_path(rdpCertificateStore* certificate_store) { - char* certloc; - struct stat stat_info; + return certificate_store->path; +} - if (home_path == NULL) - home_path = getenv("HOME"); - - certloc = (char*) xmalloc(strlen(home_path) + 2 + strlen(cert_dir) + 1 + strlen(cert_loc) + 1); - sprintf(certloc, "%s/.%s/%s", home_path, cert_dir, cert_loc); - - if(stat((char*) certloc, &stat_info) != 0) - freerdp_mkdir(certloc); +void certificate_store_init(rdpCertificateStore* certificate_store) +{ + char* config_path; + rdpSettings* settings; - return certloc; -} + certificate_store->match = 1; + settings = certificate_store->settings; -void certstore_init(rdpCertStore* certstore) -{ - int length; - char* home_path; - struct stat stat_info; - - certstore->match = 1; + config_path = freerdp_get_config_path(settings); + certificate_store->path = freerdp_construct_path(config_path, (char*) certificate_store_subdir); - if (certstore->home_path == NULL) - home_path = getenv("HOME"); - else - home_path = certstore->home_path; - - if (home_path == NULL) + if (freerdp_check_file_exists(certificate_store->path) == false) { - printf("could not get home path\n"); - return; + freerdp_mkdir(certificate_store->path); + printf("creating directory %s\n", certificate_store->path); } - certstore->home_path = (char*) xstrdup(home_path); + certificate_store->file = freerdp_construct_path(certificate_store->path, (char*) certificate_store_file); - certstore->path = (char*) xmalloc(strlen(certstore->home_path) + 2 + strlen(cert_dir) + 1); - sprintf(certstore->path, "%s/.%s", certstore->home_path, cert_dir); - - if (stat(certstore->path, &stat_info) != 0) - { - freerdp_mkdir(certstore->path); - printf("creating directory %s\n", certstore->path); - } - - length = strlen(certstore->path); - certstore->file = (char*) xmalloc(strlen(certstore->path) + 1 + strlen(certstore_file) + 1); - sprintf(certstore->file, "%s/%s", certstore->path, certstore_file); - - certstore_open(certstore); + certificate_store_open(certificate_store); } -rdpCertData* certdata_new(char* hostname, char* fingerprint) -{ - rdpCertData* certdata; - - certdata = (rdpCertData*) xzalloc(sizeof(rdpCertData)); - - if (certdata != NULL) - { - certdata->hostname = xzalloc(strlen(hostname) + 1); - certdata->fingerprint = xzalloc(strlen(fingerprint) + 1); - sprintf(certdata->hostname, "%s", hostname); - sprintf(certdata->fingerprint, "%s", fingerprint); - } - - return certdata; -} - -void certdata_free(rdpCertData* certdata) -{ - if(certdata != NULL) - { - xfree(certdata->hostname); - xfree(certdata->fingerprint); - xfree(certdata); - } -} - -rdpCertStore* certstore_new(rdpCertData* certdata, char* home_path) -{ - rdpCertStore* certstore; - - certstore = (rdpCertStore*) xzalloc(sizeof(rdpCertStore)); - - if (certstore != NULL) - { - certstore->home_path = home_path; - certstore->certdata = certdata; - certstore_init(certstore); - } - - return certstore; -} - -void certstore_free(rdpCertStore* certstore) -{ - if (certstore != NULL) - { - certstore_close(certstore); - xfree(certstore->path); - xfree(certstore->file); - xfree(certstore->home_path); - certdata_free(certstore->certdata); - xfree(certstore); - } -} - -int cert_data_match(rdpCertStore* certstore) +int certificate_data_match(rdpCertificateStore* certificate_store, rdpCertificateData* certificate_data) { FILE* fp; int length; char* data; char* pline; long int size; - rdpCertData* cert_data; - fp = certstore->fp; - cert_data = certstore->certdata; + fp = certificate_store->fp; if (!fp) - return certstore->match; + return certificate_store->match; fseek(fp, 0, SEEK_END); size = ftell(fp); @@ -191,7 +97,7 @@ int cert_data_match(rdpCertStore* certstore) length = fread(data, size, 1, fp); if (size < 1) - return certstore->match; + return certificate_store->match; data[size] = '\n'; pline = strtok(data, "\n"); @@ -205,14 +111,14 @@ int cert_data_match(rdpCertStore* certstore) length = strcspn(pline, " \t"); pline[length] = '\0'; - if (strcmp(pline, cert_data->hostname) == 0) + if (strcmp(pline, certificate_data->hostname) == 0) { pline = &pline[length + 1]; - if (strcmp(pline, cert_data->fingerprint) == 0) - certstore->match = 0; + if (strcmp(pline, certificate_data->fingerprint) == 0) + certificate_store->match = 0; else - certstore->match = -1; + certificate_store->match = -1; break; } } @@ -221,19 +127,70 @@ int cert_data_match(rdpCertStore* certstore) } xfree(data); - return certstore->match; + return certificate_store->match; } -void cert_data_print(rdpCertStore* certstore) +void certificate_data_print(rdpCertificateStore* certificate_store, rdpCertificateData* certificate_data) { FILE* fp; /* reopen in append mode */ - fp = fopen(certstore->file, "a"); + fp = fopen(certificate_store->file, "a"); if (!fp) return; - fprintf(certstore->fp,"%s %s\n", certstore->certdata->hostname, certstore->certdata->fingerprint); + 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); + } +}