-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdaemon_structs.h
399 lines (275 loc) · 14.1 KB
/
daemon_structs.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
#ifndef SSA_DAEMON_STRUCTS_H
#define SSA_DAEMON_STRUCTS_H
#include <event2/util.h>
#include <openssl/ssl.h>
#include <openssl/ocsp.h>
#include <semaphore.h>
#include <sys/socket.h>
#include <sys/types.h>
#include "hashmap.h"
#include "hashmap_str.h"
#include "hashmap_crl.h"
#include "inotify.h"
/** The maximum length that an error string may be (not including '\0') */
#define MAX_ERR_STRING 128
/** The maximum length that a hostname may be (not including '\0') */
#define MAX_HOSTNAME 255
#define MAX_CERTS 5
#define NO_FD -1 /** Designation for bufferevent with no set fd */
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
/** Flag to disable any revocation checks from being performed */
#define SF_NO_REV_CHECKS (1 << 0)
/** Flag to disable the OCSP stapled response from being used */
#define SF_NO_STAPLED_CHECKS (1 << 1)
/** Flag to disable OCSP checks from being launched (not including stapled) */
#define SF_NO_OCSP_CHECKS (1 << 2)
/** Flag to disagle CRL checks from being launched */
#define SF_NO_CRL_CHECKS (1 << 3)
/** Flag to disable cached responses from being used */
#define SF_NO_CACHE_CHECKS (1 << 4)
/** Flag to determine if the SSL_CTX of the given socket is shared */
#define SF_SHARED_CONTEXT (1 << 5)
#define SF_SERVER_STAPLING (1 << 6)
/**
* Disables any revocation checks from being performed, and passes all TLS
* handshakes (even if a revoked certificate is in use)
*/
#define turn_off_revocation_checks(flags) (flags |= SF_NO_REV_CHECKS)
/**
* Sets the connection so that the certificate chain must be fully checked for
* any revoked certificates. If some certificates are unable to be checked,
* this will mean that the connection will fail
*/
#define turn_on_revocation_checks(flags) (flags &= ~SF_NO_REV_CHECKS)
/** Checks to determine whether revocation checks are required & enabled. */
#define has_revocation_checks(flags) !(flags & SF_NO_REV_CHECKS)
/** Disables OCSP stapled responses from being used when checking revocation. */
#define turn_off_stapled_checks(flags) (flags |= SF_NO_STAPLED_CHECKS)
/** Allows OCSP stapled responses to be used as part of revocation checks. */
#define turn_on_stapled_checks(flags) (flags &= ~SF_NO_STAPLED_CHECKS)
/** Determines whether OCSP stapled response checks are enabled or not. */
#define has_stapled_checks(flags) !(flags & SF_NO_STAPLED_CHECKS)
/** Disables OCSP responders from being queried when checking revocation. */
#define turn_off_ocsp_checks(flags) (flags |= SF_NO_OCSP_CHECKS)
/** Allows OCSP responders to be queried when checking revocation. */
#define turn_on_ocsp_checks(flags) (flags &= ~SF_NO_OCSP_CHECKS)
/** Determines whether OCSP responders are enabled or not. */
#define has_ocsp_checks(flags) !(flags & SF_NO_OCSP_CHECKS)
/** Disables CRL responders from being queried when checking revocation. */
#define turn_off_crl_checks(flags) (flags |= SF_NO_CRL_CHECKS)
/** Allows CRL responders to be queried when checking revocation. */
#define turn_on_crl_checks(flags) (flags &= ~SF_NO_CRL_CHECKS)
/** Determines whether CRL responders are enabled or not. */
#define has_crl_checks(flags) !(flags & SF_NO_CRL_CHECKS)
/**
* Disables cached responses from being used when checking revocation.
* Note that this does not disable the daemon from actively caching responses.
*/
#define turn_off_cached_checks(flags) (flags |= SF_NO_CACHE_CHECKS)
/** Allows cached responses to be used when checkin revocation. */
#define turn_on_cached_checks(flags) (flags &= ~SF_NO_CACHE_CHECKS)
/** Determines whether cached responses are checked or not. */
#define has_cached_checks(flags) !(flags & SF_NO_CACHE_CHECKS)
#define has_shared_context(flags) (flags & SF_SHARED_CONTEXT)
#define set_shared_context(flags) (flags |= SF_SHARED_CONTEXT)
#define server_stapling_enabled(flags) (flags & SF_SERVER_STAPLING)
#define enable_server_stapling(flags) (flags |= SF_SERVER_STAPLING)
#define disable_server_stapling(flags) (flags &= ~SF_SERVER_STAPLING)
struct daemon_ctx_st;
struct global_config_st;
struct revocation_ctx_st;
struct crl_responder_st;
struct ocsp_responder_st;
struct socket_ctx_st;
struct channel_st;
typedef struct global_config_st global_config;
typedef struct daemon_ctx_st daemon_ctx;
typedef struct revocation_ctx_st revocation_ctx;
typedef struct crl_responder_st crl_responder;
typedef struct ocsp_responder_st ocsp_responder;
typedef struct socket_ctx_st socket_ctx;
typedef struct channel_st channel;
enum socket_state {
SOCKET_ERROR = 0, /** Socket unrecoverably failed operation */
SOCKET_NEW, /** Fresh socket ready for `connect` or `listen` */
SOCKET_CONNECTING, /** Performing TCP or TLS handshake */
SOCKET_FINISHING_CONN, /** revocation checks/connecting internally */
SOCKET_CONNECTED, /** Both endpoints connected (client) */
SOCKET_LISTENING, /** Socket listening/accepting connections */
SOCKET_DISCONNECTED /** Both endpoints closed cleanly (client/server) */
};
enum tls_version {
TLS_DEFAULT_ENUM = 0, /** Default TLS version selected (TLS 1.3) */
TLS1_0_ENUM, /** TLS 1.0 version selected */
TLS1_1_ENUM, /** TLS 1.1 version selected */
TLS1_2_ENUM, /** TLS 1.2 version selected */
TLS1_3_ENUM /** TLS 1.3 version selected */
};
struct daemon_ctx_st {
struct event_base* ev_base; /** Multiplexer that handles all events */
struct evdns_base* dns_base; /** Handles all DNS lookups */
struct nl_sock* netlink_sock; /** For transmitting to/from kernel module */
int netlink_family; /** Netlink protocol; should be SSA family */
int port; /** Port for incoming connections/Netlink */
hmap_t* sock_map; /** Hashmap for pending server connections */
hmap_t* sock_map_port; /** Hashmap for sockets currently in use */
global_config* settings; /** Settings loaded in from config file */
hsmap_t* revocation_cache; /** Stores OCSP cert revocation statuses */
hcmap_t* crl_cache; /** Stores downloaded CRLs' URLs and revoked serial numbers */
sem_t* cache_sem; /** Semaphore to protect write operations to CRL cache */
inotify_ctx* inotify; /** Inotify information */
/*
hsmap_t* ssl_ctx_cache;
*/
};
struct global_config_st {
char* ca_path;
/* WARNING: make sure each only contains one cipher (eg AES_GCM:NULL). */
/* ANOTHER WARNING: also watch out for '\b' */
char** cipher_list; /** List of acceptable TLS 1.2 ciphers to use */
int cipher_list_cnt; /** Length of \p cipher_list */
char** ciphersuites; /** List of acceptable TLS 1.3 ciphers to use */
int ciphersuite_cnt; /** Length of \p ciphersuites */
int session_tickets; /** 1 if session tickets enabled, 0 otherwise */
int session_timeout; /** Length of time before session will expire */
int max_chain_depth; /** Number of certificates acceptable in cert chain */
int ct_checks; /** 1 if Certificate Transparency enabled, 0 if not */
enum tls_version min_tls_version; /** minimum accepted TLS version */
enum tls_version max_tls_version; /** maximum accepted TLS version */
char* certificates[MAX_CERTS]; /** list of files/folders of certs to use */
int cert_cnt; /** Size of \p certificates list */
char* private_keys[MAX_CERTS]; /** list of files/folders of keys to use */
int key_cnt; /** Size of \p private_keys list */
unsigned int revocation_checks; /** bitset of revocation settings */
int session_resumption; /** 1 if sockets will reuse sessions, 0 if not */
};
typedef struct channel_st {
struct bufferevent* bev; /** The bufferevent of a given endpoint */
int closed; /** 1 if the endpoint is done communicating */
} channel;
/**
* Contains data directly related to performing revocation checks.
* This struct is only really used if revocation checks are turned on.
*/
struct revocation_ctx_st {
daemon_ctx *daemon; /** The daemon's context */
socket_ctx* sock_ctx; /** The parent socket_ctx of the rev context */
unsigned long id; /** The ID of the parent socket_ctx */
unsigned int checks; /** bitmap of rev checks; options #define'd above */
/** The number of active, authoritative responders performing revocation
* checks for the certificate at the corresponding index in the cert chain.
* For example, responders_at[0] would represent the number of responders
* checking the leaf certificate of a chain, responders_at[1] would be the
* number of responders checking the certificate that signed the leaf
* certificate, and so on. An `authoritative` responder would be any one
* OCSP responder for a certificate; CRL responders can collectively be
* considered as one authoritative responder, but individually they are not.
* Thus, if there were 2 OCSP responders and 2 CRL responders for the leaf
* certificate, responders_at[0] would return '3'.
*/
int *responders_at;
/** The number of active CRL responders peforming revocation check for the
* certificate at the corresponding index in the cert chain.
* For example, crl_responders_at[0] would return the number of CRL
* responders checking the leaf certificate of a chain.
* @see responders_at.
*/
int *crl_responders_at;
int total_to_check; /** Total # certificates in chain that need checking */
int left_to_check; /** # certificates in chain not yet checked */
ocsp_responder* ocsp_responders; /** Array of ocsp responders */
crl_responder* crl_responders; /** Linked list of crl responders */
X509_STORE* store; /** Trusted CA certs to verify responses against */
STACK_OF(X509)* certs; /** Chain of certificates received from peer */
};
/** ocsp_responder and crl_responder are different structs but share a similar purpose
* therefore they share some simple functions. In order to make this possible,
* the two structs' shared attributes should be kept at the beginning of their
* definitions (because they are passed in as void pointers and cast as ocsp_responder
* structs in these functions).
*/
struct ocsp_responder_st {
revocation_ctx* rev_ctx; /** ctx of revocation check being performed */
struct bufferevent* bev; /** Bufferevent reading/writing OCSP response */
char* url; /** OCSP responder's url */
int cert_position; /** cert chain position of cert being verified */
unsigned char* buffer; /** byte buffer to store HTTP response in */
int buf_size; /** # of bytes that can be stored in buffer */
int tot_read; /** # of bytes currently stored in buffer */
int is_reading_body; /** 0 if HTTP header being read, 1 otherwise */
ocsp_responder* next; /** Pointer to the next responder in the list */
OCSP_CERTID* certid; /** certificate's ID for the OCSP request/resp */
};
struct crl_responder_st {
revocation_ctx* rev_ctx;
struct bufferevent* bev; /** Bufferevent reading/writing CRL response */
char* url;
int cert_position;
unsigned char* buffer;
int buf_size;
int tot_read;
int is_reading_body;
crl_responder* next; /** Pointer to the next responder in the list */
const char* hostname;
};
struct socket_ctx_st {
daemon_ctx* daemon; /** The daemon's context */
unsigned long id; /** The unique id associated with the socket */
evutil_socket_t sockfd; /** The file descriptor of the socket */
enum socket_state state; /** The socket's current state @see socket_state */
unsigned long flags; /** Revocation check flags, along with other options */
SSL_CTX* ssl_ctx; /** The context of the SSL object (useful for server) */
SSL* ssl; /** The SSL instance associated with \p sockfd */
channel plain; /** The non-encrypted channel to the calling program */
channel secure; /** The encrypted channel to the external peer */
struct evconnlistener* listener; /** Libevent struct for listening socket */
revocation_ctx* rev_ctx; /** Settings/data structs to do with revocation */
struct sockaddr_storage int_addr; /** Internal address--the program using SSA */
int int_addrlen; /** The size of \p int_addr */
union {
struct sockaddr_storage ext_addr; /** External address--the remote peer */
struct sockaddr_storage rem_addr; /** Remote address--the remote host */
};
union {
int ext_addrlen; /** The size of \p ext_addr */
int rem_addrlen; /** The size of \p rem_addr */
};
int local_port; /** Used for temporarily storing connections in daemon */
char rem_hostname[MAX_HOSTNAME+1]; /** The hostname being connected to */
char err_string[MAX_ERR_STRING+1]; /** String describing TLS/daemon error */
unsigned int handshake_err_code; /** TLS error code for verify failure */
};
daemon_ctx *daemon_context_new(char* config_path, int port);
void daemon_context_free(daemon_ctx* daemon);
int socket_context_new(socket_ctx** sock, int fd,
daemon_ctx* ctx, unsigned long id);
socket_ctx* accepting_socket_ctx_new(socket_ctx* listener_ctx, int fd);
void socket_shutdown(socket_ctx* sock_ctx);
void socket_context_free(socket_ctx* sock_ctx);
void socket_context_erase(socket_ctx* sock_ctx, int port);
revocation_ctx* revocation_context_setup(socket_ctx* sock_ctx);
void revocation_context_cleanup(revocation_ctx* ctx);
void ocsp_responder_shutdown(ocsp_responder* resp);
void ocsp_responder_free(ocsp_responder* resp);
void crl_responder_shutdown(crl_responder* resp);
void crl_responder_free(crl_responder* resp);
int check_socket_state(socket_ctx* sock_ctx, int num, ...);
/**
* Creates a string of the format "<hostname>:<port>".
* @param sock_ctx The socket to retrieve hostname and port information from.
* @returns A newly allocated null-terminated string.
*/
char* get_hostname_port_str(socket_ctx* sock_ctx);
/**
* Retrieves an integer port number from a given sockaddr struct.
* @param addr The sockaddr struct to retrieve the port number of.
* @returns The port number.
*/
int get_port(struct sockaddr* addr);
struct sockaddr_storage get_loopback_address(sa_family_t family);
#endif