FreeRDP
certificate_store.c
1 
23 #include <freerdp/config.h>
24 
25 #include <winpr/assert.h>
26 #include <errno.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <ctype.h>
30 
31 #include <winpr/crypto.h>
32 #include <winpr/crt.h>
33 #include <winpr/file.h>
34 #include <winpr/path.h>
35 
36 #include <freerdp/settings.h>
37 
38 #include <freerdp/crypto/crypto.h>
39 #include <freerdp/crypto/certificate_store.h>
40 #include <freerdp/log.h>
41 
42 struct rdp_certificate_store
43 {
44  char* certs_path;
45  char* server_path;
46 };
47 
48 static const char certificate_store_dir[] = "certs";
49 static const char certificate_server_dir[] = "server";
50 
51 static char* freerdp_certificate_store_file_path(const rdpCertificateStore* store, const char* hash)
52 {
53  const char* hosts = freerdp_certificate_store_get_hosts_path(store);
54 
55  if (!hosts || !hash)
56  return NULL;
57 
58  return GetCombinedPath(hosts, hash);
59 }
60 
61 freerdp_certificate_store_result
62 freerdp_certificate_store_contains_data(rdpCertificateStore* store, const rdpCertificateData* data)
63 {
64  freerdp_certificate_store_result rc = CERT_STORE_NOT_FOUND;
65  const char* host = freerdp_certificate_data_get_host(data);
66  const UINT16 port = freerdp_certificate_data_get_port(data);
67 
68  rdpCertificateData* loaded = freerdp_certificate_store_load_data(store, host, port);
69  if (!loaded)
70  goto fail;
71 
72  rc = freerdp_certificate_data_equal(data, loaded) ? CERT_STORE_MATCH : CERT_STORE_MISMATCH;
73 
74 fail:
75  freerdp_certificate_data_free(loaded);
76  return rc;
77 }
78 
79 BOOL freerdp_certificate_store_remove_data(rdpCertificateStore* store,
80  const rdpCertificateData* data)
81 {
82  BOOL rc = TRUE;
83 
84  WINPR_ASSERT(store);
85 
86  const char* hash = freerdp_certificate_data_get_hash(data);
87  if (!hash)
88  return FALSE;
89  char* path = freerdp_certificate_store_file_path(store, hash);
90 
91  if (!path)
92  return FALSE;
93 
94  if (winpr_PathFileExists(path))
95  rc = winpr_DeleteFile(path);
96  free(path);
97  return rc;
98 }
99 
100 BOOL freerdp_certificate_store_save_data(rdpCertificateStore* store, const rdpCertificateData* data)
101 {
102  BOOL rc = FALSE;
103  const char* base = freerdp_certificate_store_get_hosts_path(store);
104  const char* hash = freerdp_certificate_data_get_hash(data);
105  char* path = freerdp_certificate_store_file_path(store, hash);
106  FILE* fp = NULL;
107 
108  if (!winpr_PathFileExists(base))
109  {
110  if (!winpr_PathMakePath(base, NULL))
111  goto fail;
112  }
113 
114  fp = winpr_fopen(path, "w");
115  if (!fp)
116  goto fail;
117 
118  (void)fprintf(fp, "%s", freerdp_certificate_data_get_pem_ex(data, FALSE));
119 
120  rc = TRUE;
121 fail:
122  if (fp)
123  (void)fclose(fp);
124  free(path);
125  return rc;
126 }
127 
128 rdpCertificateData* freerdp_certificate_store_load_data(rdpCertificateStore* store,
129  const char* host, UINT16 port)
130 {
131  char* path = NULL;
132  rdpCertificateData* data = NULL;
133 
134  WINPR_ASSERT(store);
135 
136  path = freerdp_certificate_store_get_cert_path(store, host, port);
137  if (!path)
138  goto fail;
139 
140  data = freerdp_certificate_data_new_from_file(host, port, path);
141 
142 fail:
143  free(path);
144  return data;
145 }
146 
147 rdpCertificateStore* freerdp_certificate_store_new(const rdpSettings* settings)
148 {
149  rdpCertificateStore* store = (rdpCertificateStore*)calloc(1, sizeof(rdpCertificateStore));
150 
151  if (!store)
152  return NULL;
153 
154  const char* base = freerdp_settings_get_string(settings, FreeRDP_ConfigPath);
155  if (!base)
156  goto fail;
157 
158  store->certs_path = GetCombinedPath(base, certificate_store_dir);
159  store->server_path = GetCombinedPath(base, certificate_server_dir);
160  if (!store->certs_path || !store->server_path)
161  goto fail;
162 
163  return store;
164 
165 fail:
166  WINPR_PRAGMA_DIAG_PUSH
167  WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
168  freerdp_certificate_store_free(store);
169  WINPR_PRAGMA_DIAG_POP
170  return NULL;
171 }
172 
173 void freerdp_certificate_store_free(rdpCertificateStore* store)
174 {
175  if (!store)
176  return;
177 
178  free(store->certs_path);
179  free(store->server_path);
180  free(store);
181 }
182 
183 const char* freerdp_certificate_store_get_certs_path(const rdpCertificateStore* store)
184 {
185  WINPR_ASSERT(store);
186  return store->certs_path;
187 }
188 
189 const char* freerdp_certificate_store_get_hosts_path(const rdpCertificateStore* store)
190 {
191  WINPR_ASSERT(store);
192  return store->server_path;
193 }
194 
195 char* freerdp_certificate_store_get_cert_path(const rdpCertificateStore* store, const char* host,
196  UINT16 port)
197 {
198  WINPR_ASSERT(store);
199 
200  char* hash = freerdp_certificate_data_hash(host, port);
201  if (!hash)
202  return NULL;
203  char* path = freerdp_certificate_store_file_path(store, hash);
204  free(hash);
205  return path;
206 }
FREERDP_API const char * freerdp_settings_get_string(const rdpSettings *settings, FreeRDP_Settings_Keys_String id)
Returns a immutable string settings value.