Coverage Report

Created: 2025-07-01 06:46

/src/FreeRDP/libfreerdp/crypto/certificate_store.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * FreeRDP: A Remote Desktop Protocol Implementation
3
 * Certificate Handling
4
 *
5
 * Copyright 2011 Jiten Pathy
6
 * Copyright 2011-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
7
 * Copyright 2023 Armin Novak <anovak@thincast.com>
8
 * Copyright 2023 Thincast Technologies GmbH
9
 *
10
 * Licensed under the Apache License, Version 2.0 (the "License");
11
 * you may not use this file except in compliance with the License.
12
 * You may obtain a copy of the License at
13
 *
14
 *     http://www.apache.org/licenses/LICENSE-2.0
15
 *
16
 * Unless required by applicable law or agreed to in writing, software
17
 * distributed under the License is distributed on an "AS IS" BASIS,
18
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
 * See the License for the specific language governing permissions and
20
 * limitations under the License.
21
 */
22
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
0
{
53
0
  const char* hosts = freerdp_certificate_store_get_hosts_path(store);
54
55
0
  if (!hosts || !hash)
56
0
    return NULL;
57
58
0
  return GetCombinedPath(hosts, hash);
59
0
}
60
61
freerdp_certificate_store_result
62
freerdp_certificate_store_contains_data(rdpCertificateStore* store, const rdpCertificateData* data)
63
0
{
64
0
  freerdp_certificate_store_result rc = CERT_STORE_NOT_FOUND;
65
0
  const char* host = freerdp_certificate_data_get_host(data);
66
0
  const UINT16 port = freerdp_certificate_data_get_port(data);
67
68
0
  rdpCertificateData* loaded = freerdp_certificate_store_load_data(store, host, port);
69
0
  if (!loaded)
70
0
    goto fail;
71
72
0
  rc = freerdp_certificate_data_equal(data, loaded) ? CERT_STORE_MATCH : CERT_STORE_MISMATCH;
73
74
0
fail:
75
0
  freerdp_certificate_data_free(loaded);
76
0
  return rc;
77
0
}
78
79
BOOL freerdp_certificate_store_remove_data(rdpCertificateStore* store,
80
                                           const rdpCertificateData* data)
81
0
{
82
0
  BOOL rc = TRUE;
83
84
0
  WINPR_ASSERT(store);
85
86
0
  const char* hash = freerdp_certificate_data_get_hash(data);
87
0
  if (!hash)
88
0
    return FALSE;
89
0
  char* path = freerdp_certificate_store_file_path(store, hash);
90
91
0
  if (!path)
92
0
    return FALSE;
93
94
0
  if (winpr_PathFileExists(path))
95
0
    rc = winpr_DeleteFile(path);
96
0
  free(path);
97
0
  return rc;
98
0
}
99
100
BOOL freerdp_certificate_store_save_data(rdpCertificateStore* store, const rdpCertificateData* data)
101
0
{
102
0
  BOOL rc = FALSE;
103
0
  const char* base = freerdp_certificate_store_get_hosts_path(store);
104
0
  const char* hash = freerdp_certificate_data_get_hash(data);
105
0
  char* path = freerdp_certificate_store_file_path(store, hash);
106
0
  FILE* fp = NULL;
107
108
0
  if (!winpr_PathFileExists(base))
109
0
  {
110
0
    if (!winpr_PathMakePath(base, NULL))
111
0
      goto fail;
112
0
  }
113
114
0
  fp = winpr_fopen(path, "w");
115
0
  if (!fp)
116
0
    goto fail;
117
118
0
  (void)fprintf(fp, "%s", freerdp_certificate_data_get_pem_ex(data, FALSE));
119
120
0
  rc = TRUE;
121
0
fail:
122
0
  if (fp)
123
0
    (void)fclose(fp);
124
0
  free(path);
125
0
  return rc;
126
0
}
127
128
rdpCertificateData* freerdp_certificate_store_load_data(rdpCertificateStore* store,
129
                                                        const char* host, UINT16 port)
130
0
{
131
0
  char* path = NULL;
132
0
  rdpCertificateData* data = NULL;
133
134
0
  WINPR_ASSERT(store);
135
136
0
  path = freerdp_certificate_store_get_cert_path(store, host, port);
137
0
  if (!path)
138
0
    goto fail;
139
140
0
  data = freerdp_certificate_data_new_from_file(host, port, path);
141
142
0
fail:
143
0
  free(path);
144
0
  return data;
145
0
}
146
147
rdpCertificateStore* freerdp_certificate_store_new(const rdpSettings* settings)
148
0
{
149
0
  rdpCertificateStore* store = (rdpCertificateStore*)calloc(1, sizeof(rdpCertificateStore));
150
151
0
  if (!store)
152
0
    return NULL;
153
154
0
  const char* base = freerdp_settings_get_string(settings, FreeRDP_ConfigPath);
155
0
  if (!base)
156
0
    goto fail;
157
158
0
  store->certs_path = GetCombinedPath(base, certificate_store_dir);
159
0
  store->server_path = GetCombinedPath(base, certificate_server_dir);
160
0
  if (!store->certs_path || !store->server_path)
161
0
    goto fail;
162
163
0
  return store;
164
165
0
fail:
166
0
  WINPR_PRAGMA_DIAG_PUSH
167
0
  WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
168
0
  freerdp_certificate_store_free(store);
169
0
  WINPR_PRAGMA_DIAG_POP
170
0
  return NULL;
171
0
}
172
173
void freerdp_certificate_store_free(rdpCertificateStore* store)
174
0
{
175
0
  if (!store)
176
0
    return;
177
178
0
  free(store->certs_path);
179
0
  free(store->server_path);
180
0
  free(store);
181
0
}
182
183
const char* freerdp_certificate_store_get_certs_path(const rdpCertificateStore* store)
184
0
{
185
0
  WINPR_ASSERT(store);
186
0
  return store->certs_path;
187
0
}
188
189
const char* freerdp_certificate_store_get_hosts_path(const rdpCertificateStore* store)
190
0
{
191
0
  WINPR_ASSERT(store);
192
0
  return store->server_path;
193
0
}
194
195
char* freerdp_certificate_store_get_cert_path(const rdpCertificateStore* store, const char* host,
196
                                              UINT16 port)
197
0
{
198
0
  WINPR_ASSERT(store);
199
200
0
  char* hash = freerdp_certificate_data_hash(host, port);
201
0
  if (!hash)
202
0
    return NULL;
203
0
  char* path = freerdp_certificate_store_file_path(store, hash);
204
0
  free(hash);
205
0
  return path;
206
0
}