summaryrefslogtreecommitdiff
path: root/src/libcharon/bus/bus.h
blob: b6757b140939118176633a40bb25411893d63805 (plain)
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
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
/*
 * Copyright (C) 2012-2015 Tobias Brunner
 * Copyright (C) 2006-2009 Martin Willi
 * Hochschule fuer Technik Rapperswil
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 */

/**
 * @defgroup bus bus
 * @{ @ingroup libcharon
 */

#ifndef BUS_H_
#define BUS_H_

typedef enum alert_t alert_t;
typedef enum narrow_hook_t narrow_hook_t;
typedef struct bus_t bus_t;

#include <stdarg.h>

#include <utils/debug.h>
#include <sa/ike_sa.h>
#include <sa/child_sa.h>
#include <processing/jobs/job.h>
#include <bus/listeners/logger.h>
#include <bus/listeners/listener.h>

/* undefine the definitions from libstrongswan */
#undef DBG0
#undef DBG1
#undef DBG2
#undef DBG3
#undef DBG4

#ifndef DEBUG_LEVEL
# define DEBUG_LEVEL 4
#endif /* DEBUG_LEVEL */

#if DEBUG_LEVEL >= 0
#define DBG0(group, format, ...) charon->bus->log(charon->bus, group, 0, format, ##__VA_ARGS__)
#endif /* DEBUG_LEVEL >= 0 */
#if DEBUG_LEVEL >= 1
#define DBG1(group, format, ...) charon->bus->log(charon->bus, group, 1, format, ##__VA_ARGS__)
#endif /* DEBUG_LEVEL >= 1 */
#if DEBUG_LEVEL >= 2
#define DBG2(group, format, ...) charon->bus->log(charon->bus, group, 2, format, ##__VA_ARGS__)
#endif /* DEBUG_LEVEL >= 2 */
#if DEBUG_LEVEL >= 3
#define DBG3(group, format, ...) charon->bus->log(charon->bus, group, 3, format, ##__VA_ARGS__)
#endif /* DEBUG_LEVEL >= 3 */
#if DEBUG_LEVEL >= 4
#define DBG4(group, format, ...) charon->bus->log(charon->bus, group, 4, format, ##__VA_ARGS__)
#endif /* DEBUG_LEVEL >= 4 */

#ifndef DBG0
# define DBG0(...) {}
#endif /* DBG0 */
#ifndef DBG1
# define DBG1(...) {}
#endif /* DBG1 */
#ifndef DBG2
# define DBG2(...) {}
#endif /* DBG2 */
#ifndef DBG3
# define DBG3(...) {}
#endif /* DBG3 */
#ifndef DBG4
# define DBG4(...) {}
#endif /* DBG4 */

/**
 * Kind of alerts to raise.
 */
enum alert_t {
	/** a RADIUS server did not respond, no additional arguments */
	ALERT_RADIUS_NOT_RESPONDING,
	/** a shutdown signal has been received, argument is the signal (int) */
	ALERT_SHUTDOWN_SIGNAL,
	/** local peer authentication failed (by us or by peer), no arguments */
	ALERT_LOCAL_AUTH_FAILED,
	/** peer authentication failed, no arguments */
	ALERT_PEER_AUTH_FAILED,
	/** failed to resolve peer address, no arguments */
	ALERT_PEER_ADDR_FAILED,
	/** peer did not respond to initial message, current try (int, 0-based) */
	ALERT_PEER_INIT_UNREACHABLE,
	/** received IKE message with invalid SPI, argument is message_t* */
	ALERT_INVALID_IKE_SPI,
	/** received IKE message with invalid header, argument is message_t* */
	ALERT_PARSE_ERROR_HEADER,
	/** received IKE message with invalid body, argument is message_t*,
	 *  followed by a status_t result returned by message_t.parse_body(). */
	ALERT_PARSE_ERROR_BODY,
	/** sending a retransmit for a message, argument is packet_t, if the message
	 *  got fragmented only the first fragment is passed */
	ALERT_RETRANSMIT_SEND,
	/** sending retransmits timed out, argument is packet_t, if available and if
	 *  the message got fragmented only the first fragment is passed */
	ALERT_RETRANSMIT_SEND_TIMEOUT,
	/** received a retransmit for a message, argument is message_t */
	ALERT_RETRANSMIT_RECEIVE,
	/** received half-open timeout before IKE_SA established, no argument */
	ALERT_HALF_OPEN_TIMEOUT,
	/** IKE proposals do not match, argument is linked_list_t of proposal_t */
	ALERT_PROPOSAL_MISMATCH_IKE,
	/** CHILD proposals do not match, argument is linked_list_t of proposal_t */
	ALERT_PROPOSAL_MISMATCH_CHILD,
	/** traffic selectors do not match, arguments are two linked_list_t
	 *  containing traffic_selector_t for initiator and for responder */
	ALERT_TS_MISMATCH,
	/** traffic selectors have been narrowed by the peer, arguments are
	 *  an int (TRUE for local TS), a linked_list_t* (final TS list), and the
	 *  child_cfg_t*. */
	ALERT_TS_NARROWED,
	/** Installation of IPsec SAs failed, argument is child_sa_t */
	ALERT_INSTALL_CHILD_SA_FAILED,
	/** Installation of IPsec Policy failed, argument is child_sa_t */
	ALERT_INSTALL_CHILD_POLICY_FAILED,
	/** IKE_SA deleted because of "replace" unique policy, no argument */
	ALERT_UNIQUE_REPLACE,
	/** IKE_SA deleted because of "keep" unique policy, no argument */
	ALERT_UNIQUE_KEEP,
	/** IKE_SA kept on failed child SA establishment, argument is an int (!=0 if
	 * first child SA) */
	ALERT_KEEP_ON_CHILD_SA_FAILURE,
	/** allocating virtual IP failed, linked_list_t of host_t requested */
	ALERT_VIP_FAILURE,
	/** an authorize() hook failed, no argument */
	ALERT_AUTHORIZATION_FAILED,
	/** IKE_SA hit the hard lifetime limit before it could be rekeyed */
	ALERT_IKE_SA_EXPIRED,
	/** Certificate rejected; it has expired, certificate_t */
	ALERT_CERT_EXPIRED,
	/** Certificate rejected; it has been revoked, certificate_t */
	ALERT_CERT_REVOKED,
	/** Validating certificate status failed, certificate_t */
	ALERT_CERT_VALIDATION_FAILED,
	/** Certificate rejected; no trusted issuer found, certificate_t */
	ALERT_CERT_NO_ISSUER,
	/** Certificate rejected; root not trusted, certificate_t */
	ALERT_CERT_UNTRUSTED_ROOT,
	/** Certificate rejected; trustchain length exceeds limit, certificate_t */
	ALERT_CERT_EXCEEDED_PATH_LEN,
	/** Certificate rejected; other policy violation, certificate_t */
	ALERT_CERT_POLICY_VIOLATION,
};

/**
 * Kind of narrow hook.
 *
 * There is a non-authenticated (IKE_AUTH) and a authenticated
 * (CREATE_CHILD_SA) narrowing hook for the initiator. Only one of these
 * hooks is invoked before the exchange.
 * To verify the traffic selectors negotiated, each PRE hook has a POST
 * counterpart that follows. POST hooks are invoked with an authenticated peer.
 * It is usually not a good idea to narrow in the POST hooks,
 * as the resulting traffic selector is not negotiated and results
 * in non-matching policies.
 */
enum narrow_hook_t {
	/** invoked as initiator before exchange, peer is not yet authenticated */
	NARROW_INITIATOR_PRE_NOAUTH,
	/** invoked as initiator before exchange, peer is authenticated */
	NARROW_INITIATOR_PRE_AUTH,
	/** invoked as responder during exchange, peer is authenticated */
	NARROW_RESPONDER,
	/** invoked as responder after exchange, peer is authenticated */
	NARROW_RESPONDER_POST,
	/** invoked as initiator after exchange, follows a INITIATOR_PRE_NOAUTH */
	NARROW_INITIATOR_POST_NOAUTH,
	/** invoked as initiator after exchange, follows a INITIATOR_PRE_AUTH */
	NARROW_INITIATOR_POST_AUTH,
};

/**
 * The bus receives events and sends them to all registered listeners.
 *
 * Loggers are handled separately.
 */
struct bus_t {

	/**
	 * Register a listener to the bus.
	 *
	 * A registered listener receives all events which are sent to the bus.
	 * The listener is passive; the thread which emitted the event
	 * processes the listener routine.
	 *
	 * @param listener	listener to register.
	 */
	void (*add_listener) (bus_t *this, listener_t *listener);

	/**
	 * Unregister a listener from the bus.
	 *
	 * @param listener	listener to unregister.
	 */
	void (*remove_listener) (bus_t *this, listener_t *listener);

	/**
	 * Register a logger with the bus.
	 *
	 * The logger is passive; the thread which emitted the event
	 * processes the logger routine.  This routine may be called concurrently
	 * by multiple threads.  Recursive calls are not prevented, so logger that
	 * may cause recursive calls are responsible to avoid infinite loops.
	 *
	 * During registration get_level() is called for all log groups and the
	 * logger is registered to receive log messages for groups for which
	 * the requested log level is > LEVEL_SILENT and whose level is lower
	 * or equal than the requested level.
	 *
	 * To update the registered log levels call add_logger again with the
	 * same logger and return the new levels from get_level().
	 *
	 * @param logger	logger to register.
	 */
	void (*add_logger) (bus_t *this, logger_t *logger);

	/**
	 * Unregister a logger from the bus.
	 *
	 * @param logger	logger to unregister.
	 */
	void (*remove_logger) (bus_t *this, logger_t *logger);

	/**
	 * Set the IKE_SA the calling thread is using.
	 *
	 * To associate a received log message with an IKE_SA without passing it as
	 * parameter each time, the thread registers the currently used IKE_SA
	 * during check-out. Before check-in, the thread unregisters the IKE_SA.
	 * This IKE_SA is stored per-thread, so each thread has its own IKE_SA
	 * registered.
	 *
	 * @param ike_sa	ike_sa to register, or NULL to unregister
	 */
	void (*set_sa) (bus_t *this, ike_sa_t *ike_sa);

	/**
	 * Get the IKE_SA the calling thread is currently using.
	 *
	 * If a thread currently does not know what IKE_SA it is processing,
	 * it can call get_sa() to look up the SA set during checkout via set_sa().
	 *
	 * @return			registered ike_sa, NULL if none registered
	 */
	ike_sa_t* (*get_sa)(bus_t *this);

	/**
	 * Send a log message to the bus.
	 *
	 * The format string specifies an additional informational or error
	 * message with a printf() like variable argument list.
	 * Use the DBG() macros.
	 *
	 * @param group		debugging group
	 * @param level		verbosity level of the signal
	 * @param format	printf() style format string
	 * @param ...		printf() style argument list
	 */
	void (*log)(bus_t *this, debug_t group, level_t level, char* format, ...);

	/**
	 * Send a log message to the bus using va_list arguments.
	 *
	 * Same as bus_t.log(), but uses va_list argument list.
	 *
	 * @param group		kind of the signal (up, down, rekeyed, ...)
	 * @param level		verbosity level of the signal
	 * @param format	printf() style format string
	 * @param args		va_list arguments
	 */
	void (*vlog)(bus_t *this, debug_t group, level_t level,
				 char* format, va_list args);

	/**
	 * Raise an alert over the bus.
	 *
	 * @param alert		kind of alert
	 * @param ...		alert specific arguments
	 */
	void (*alert)(bus_t *this, alert_t alert, ...);

	/**
	 * Send a IKE_SA state change event to the bus.
	 *
	 * @param ike_sa	IKE_SA which changes its state
	 * @param state		new state IKE_SA changes to
	 */
	void (*ike_state_change)(bus_t *this, ike_sa_t *ike_sa,
							 ike_sa_state_t state);
	/**
	 * Send a CHILD_SA state change event to the bus.
	 *
	 * @param child_sa	CHILD_SA which changes its state
	 * @param state		new state CHILD_SA changes to
	 */
	void (*child_state_change)(bus_t *this, child_sa_t *child_sa,
							   child_sa_state_t state);
	/**
	 * Message send/receive hook.
	 *
	 * The hook is invoked twice for each message: Once with plain, parsed data
	 * and once encoded and encrypted.
	 *
	 * @param message	message to send/receive
	 * @param incoming	TRUE for incoming messages, FALSE for outgoing
	 * @param plain		TRUE if message is parsed and decrypted, FALSE it not
	 */
	void (*message)(bus_t *this, message_t *message, bool incoming, bool plain);

	/**
	 * IKE_SA authorization hook.
	 *
	 * @param final		TRUE if this is the final invocation
	 * @return			TRUE to establish IKE_SA, FALSE to send AUTH_FAILED
	 */
	bool (*authorize)(bus_t *this, bool final);

	/**
	 * CHILD_SA traffic selector narrowing hook.
	 *
	 * @param child_sa	CHILD_SA set up with these traffic selectors
	 * @param type		type of hook getting invoked
	 * @param local		list of local traffic selectors to narrow
	 * @param remote	list of remote traffic selectors to narrow
	 */
	void (*narrow)(bus_t *this, child_sa_t *child_sa, narrow_hook_t type,
				   linked_list_t *local, linked_list_t *remote);

	/**
	 * IKE_SA keymat hook.
	 *
	 * @param ike_sa	IKE_SA this keymat belongs to
	 * @param dh		diffie hellman shared secret
	 * @param dh_other	others DH public value (IKEv1 only)
	 * @param nonce_i	initiators nonce
	 * @param nonce_r	responders nonce
	 * @param rekey		IKE_SA we are rekeying, if any (IKEv2 only)
	 * @param shared	shared key used for key derivation (IKEv1-PSK only)
	 */
	void (*ike_keys)(bus_t *this, ike_sa_t *ike_sa, diffie_hellman_t *dh,
					 chunk_t dh_other, chunk_t nonce_i, chunk_t nonce_r,
					 ike_sa_t *rekey, shared_key_t *shared);

	/**
	 * CHILD_SA keymat hook.
	 *
	 * @param child_sa	CHILD_SA this keymat is used for
	 * @param initiator	initiator of the CREATE_CHILD_SA exchange
	 * @param dh		diffie hellman shared secret
	 * @param nonce_i	initiators nonce
	 * @param nonce_r	responders nonce
	 */
	void (*child_keys)(bus_t *this, child_sa_t *child_sa, bool initiator,
					   diffie_hellman_t *dh, chunk_t nonce_i, chunk_t nonce_r);

	/**
	 * IKE_SA up/down hook.
	 *
	 * @param ike_sa	IKE_SA coming up/going down
	 * @param up		TRUE for an up event, FALSE for a down event
	 */
	void (*ike_updown)(bus_t *this, ike_sa_t *ike_sa, bool up);

	/**
	 * IKE_SA rekeying hook.
	 *
	 * @param old		rekeyed and obsolete IKE_SA
	 * @param new		new IKE_SA replacing old
	 */
	void (*ike_rekey)(bus_t *this, ike_sa_t *old, ike_sa_t *new);

	/**
	 * IKE_SA peer endpoint update hook.
	 *
	 * @param ike_sa	updated IKE_SA, having old endpoints set
	 * @param local		TRUE if local endpoint gets updated, FALSE for remote
	 * @param new		new endpoint address and port
	 */
	void (*ike_update)(bus_t *this, ike_sa_t *ike_sa, bool local, host_t *new);

	/**
	 * IKE_SA reestablishing hook (before resolving hosts).
	 *
	 * @param old		reestablished and obsolete IKE_SA
	 * @param new		new IKE_SA replacing old
	 */
	void (*ike_reestablish_pre)(bus_t *this, ike_sa_t *old, ike_sa_t *new);

	/**
	 * IKE_SA reestablishing hook (after configuring and initiating the new
	 * IKE_SA).
	 *
	 * @param old		reestablished and obsolete IKE_SA
	 * @param new		new IKE_SA replacing old
	 * @param initiated	TRUE if initiated successfully, FALSE otherwise
	 */
	void (*ike_reestablish_post)(bus_t *this, ike_sa_t *old, ike_sa_t *new,
								 bool initiated);

	/**
	 * CHILD_SA up/down hook.
	 *
	 * @param child_sa	CHILD_SA coming up/going down
	 * @param up		TRUE for an up event, FALSE for a down event
	 */
	void (*child_updown)(bus_t *this, child_sa_t *child_sa, bool up);

	/**
	 * CHILD_SA rekeying hook.
	 *
	 * @param old		rekeyed and obsolete CHILD_SA
	 * @param new		new CHILD_SA replacing old
	 */
	void (*child_rekey)(bus_t *this, child_sa_t *old, child_sa_t *new);

	/**
	 * CHILD_SA migration hook.
	 *
	 * @param new		ID of new SA when called for the old, NULL otherwise
	 * @param uniue		unique ID of new SA when called for the old, 0 otherwise
	 */
	void (*children_migrate)(bus_t *this, ike_sa_id_t *new, u_int32_t unique);

	/**
	 * Virtual IP assignment hook.
	 *
	 * @param ike_sa	IKE_SA the VIPs are assigned to
	 * @param assign	TRUE if assigned to IKE_SA, FALSE if released
	 */
	void (*assign_vips)(bus_t *this, ike_sa_t *ike_sa, bool assign);

	/**
	 * Virtual IP handler hook.
	 *
	 * @param ike_sa	IKE_SA the VIPs/attributes got handled on
	 * @param assign	TRUE after installing attributes, FALSE on release
	 */
	void (*handle_vips)(bus_t *this, ike_sa_t *ike_sa, bool handle);

	/**
	 * Destroy the event bus.
	 */
	void (*destroy) (bus_t *this);
};

/**
 * Create the event bus which forwards events to its listeners.
 *
 * @return		event bus instance
 */
bus_t *bus_create();

#endif /** BUS_H_ @}*/