/* * Copyright (C) 2012-2020 Tobias Brunner * Copyright (C) 2006-2009 Martin Willi * HSR 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 . * * 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 #include #include #include #include #include #include /* 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, arguments are packet_t and number * of the retransmit, if the message got fragmented only the first fragment * is passed */ ALERT_RETRANSMIT_SEND, /** received response for retransmitted request, argument is packet_t, if * the message got fragmented only the first fragment is passed */ ALERT_RETRANSMIT_SEND_CLEARED, /** 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 initiator's nonce * @param nonce_r responder's nonce * @param rekey IKE_SA we are rekeying, if any (IKEv2 only) * @param shared shared key used for key derivation (IKEv1-PSK only) * @param method auth method for key derivation (IKEv1-non-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, auth_method_t method); /** * IKE_SA derived keys hook. * * @param sk_d SK_d, or SKEYID_d for IKEv1 * @param sk_ai SK_ai, or SKEYID_a for IKEv1 * @param sk_ar SK_ar * @param sk_ei SK_ei, or Ka for IKEv1 * @param sk_er SK_er * @param sk_pi SK_pi * @param sk_pr SK_pr */ void (*ike_derived_keys)(bus_t *this, chunk_t sk_d, chunk_t sk_ai, chunk_t sk_ar, chunk_t sk_ei, chunk_t sk_er, chunk_t sk_pi, chunk_t sk_pr); /** * 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 initiator's nonce * @param nonce_r responder's 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); /** * CHILD_SA derived keys hook. * * @param child_sa CHILD_SA these keys are used for * @param initiator initiator of the CREATE_CHILD_SA exchange * @param encr_i initiator's encryption key * @param encr_o responder's encryption key * @param integ_i initiator's integrity key * @param integ_r responder's integrity key */ void (*child_derived_keys)(bus_t *this, child_sa_t *child_sa, bool initiator, chunk_t encr_i, chunk_t encr_r, chunk_t integ_i, chunk_t integ_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 new/current local endpoint address and port * @param remote new/current remote endpoint address and port */ void (*ike_update)(bus_t *this, ike_sa_t *ike_sa, host_t *local, host_t *remote); /** * 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 unique unique ID of new SA when called for the old, 0 otherwise */ void (*children_migrate)(bus_t *this, ike_sa_id_t *new, uint32_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_ @}*/