25#include <freerdp/config.h>
27#include <winpr/assert.h>
28#include <winpr/path.h>
30#include <freerdp/settings.h>
32#include <freerdp/crypto/crypto.h>
33#include <freerdp/crypto/certificate_data.h>
35#include "certificate.h"
37struct rdp_certificate_data
43 char cached_hash[MAX_PATH + 10];
46 char* cached_fingerprint;
48 char* cached_pem_chain;
54static char* ensure_lowercase(
char* str,
size_t length)
56 const size_t len = strnlen(str, length);
57 for (
size_t x = 0; x < len; x++)
58 str[x] = (
char)tolower(str[x]);
62static char* ensure_valid_charset(
char* str,
size_t length)
64 const size_t len = strnlen(str, length);
65 for (
size_t x = 0; x < len; x++)
84static const char* freerdp_certificate_data_hash_(
const char* hostname, UINT16 port,
char* name,
87 (void)_snprintf(name, length,
"%s_%" PRIu16
".pem", hostname, port);
88 return ensure_lowercase(ensure_valid_charset(name, length), length);
91static BOOL freerdp_certificate_data_load_cache(rdpCertificateData* data)
97 freerdp_certificate_data_hash_(data->hostname, data->port, data->cached_hash,
98 sizeof(data->cached_hash));
99 if (strnlen(data->cached_hash,
sizeof(data->cached_hash)) == 0)
102 data->cached_subject = freerdp_certificate_get_subject(data->cert);
103 if (!data->cached_subject)
104 data->cached_subject = calloc(1, 1);
107 data->cached_pem = freerdp_certificate_get_pem_ex(data->cert, &pemlen, FALSE);
108 if (!data->cached_pem)
111 size_t pemchainlen = 0;
112 data->cached_pem_chain = freerdp_certificate_get_pem_ex(data->cert, &pemchainlen, TRUE);
113 if (!data->cached_pem_chain)
116 data->cached_fingerprint = freerdp_certificate_get_fingerprint(data->cert);
117 if (!data->cached_fingerprint)
120 data->cached_issuer = freerdp_certificate_get_issuer(data->cert);
121 if (!data->cached_issuer)
122 data->cached_issuer = calloc(1, 1);
129static rdpCertificateData* freerdp_certificate_data_new_nocopy(
const char* hostname, UINT16 port,
130 rdpCertificate* xcert)
132 rdpCertificateData* certdata = NULL;
134 if (!hostname || !xcert)
137 certdata = (rdpCertificateData*)calloc(1,
sizeof(rdpCertificateData));
142 certdata->port = port;
143 certdata->hostname = _strdup(hostname);
144 if (!certdata->hostname)
146 ensure_lowercase(certdata->hostname, strlen(certdata->hostname));
148 certdata->cert = xcert;
149 if (!freerdp_certificate_data_load_cache(certdata))
151 certdata->cert = NULL;
157 freerdp_certificate_data_free(certdata);
161rdpCertificateData* freerdp_certificate_data_new(
const char* hostname, UINT16 port,
162 const rdpCertificate* xcert)
164 rdpCertificate* copy = freerdp_certificate_clone(xcert);
165 rdpCertificateData* data = freerdp_certificate_data_new_nocopy(hostname, port, copy);
167 freerdp_certificate_free(copy);
171rdpCertificateData* freerdp_certificate_data_new_from_pem(
const char* hostname, UINT16 port,
172 const char* pem,
size_t length)
174 if (!pem || (length == 0))
177 rdpCertificate* cert = freerdp_certificate_new_from_pem(pem);
178 rdpCertificateData* data = freerdp_certificate_data_new_nocopy(hostname, port, cert);
180 freerdp_certificate_free(cert);
184rdpCertificateData* freerdp_certificate_data_new_from_file(
const char* hostname, UINT16 port,
190 rdpCertificate* cert = freerdp_certificate_new_from_file(file);
191 rdpCertificateData* data = freerdp_certificate_data_new_nocopy(hostname, port, cert);
193 freerdp_certificate_free(cert);
197void freerdp_certificate_data_free(rdpCertificateData* data)
202 free(data->hostname);
203 freerdp_certificate_free(data->cert);
204 free(data->cached_subject);
205 free(data->cached_issuer);
206 free(data->cached_fingerprint);
207 free(data->cached_pem);
208 free(data->cached_pem_chain);
213const char* freerdp_certificate_data_get_host(
const rdpCertificateData* cert)
217 return cert->hostname;
220UINT16 freerdp_certificate_data_get_port(
const rdpCertificateData* cert)
227const char* freerdp_certificate_data_get_pem(
const rdpCertificateData* cert)
229 return freerdp_certificate_data_get_pem_ex(cert, TRUE);
232const char* freerdp_certificate_data_get_pem_ex(
const rdpCertificateData* cert, BOOL withFullChain)
237 return cert->cached_pem_chain;
238 return cert->cached_pem;
241const char* freerdp_certificate_data_get_subject(
const rdpCertificateData* cert)
246 return cert->cached_subject;
249const char* freerdp_certificate_data_get_issuer(
const rdpCertificateData* cert)
254 return cert->cached_issuer;
256const char* freerdp_certificate_data_get_fingerprint(
const rdpCertificateData* cert)
261 return cert->cached_fingerprint;
264BOOL freerdp_certificate_data_equal(
const rdpCertificateData* a,
const rdpCertificateData* b)
271 if (strcmp(a->hostname, b->hostname) != 0)
273 if (a->port != b->port)
276 const char* pem1 = freerdp_certificate_data_get_fingerprint(a);
277 const char* pem2 = freerdp_certificate_data_get_fingerprint(b);
279 rc = strcmp(pem1, pem2) == 0;
286const char* freerdp_certificate_data_get_hash(
const rdpCertificateData* cert)
291 return cert->cached_hash;
294char* freerdp_certificate_data_hash(
const char* hostname, UINT16 port)
296 char name[MAX_PATH + 10] = { 0 };
297 freerdp_certificate_data_hash_(hostname, port, name,
sizeof(name));
298 return _strdup(name);