Coverage Report

Created: 2024-05-20 06:11

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