Mercurial > hg > waaad
view include/waaad/security-api.h @ 129:f185f65e213f
Changed transport prototype for security extensions
author | Sebastien Decugis <sdecugis@nict.go.jp> |
---|---|
date | Mon, 18 Aug 2008 18:28:22 +0900 |
parents | d1cef88ac5f2 |
children | f2cb50f9547c |
line wrap: on
line source
/********************************************************************************************************* * Software License Agreement (BSD License) * * Author: Sebastien Decugis <sdecugis@nict.go.jp> * * * * Copyright (c) 2008, WIDE Project and NICT * * All rights reserved. * * * * Redistribution and use of this software in source and binary forms, with or without modification, are * * permitted provided that the following conditions are met: * * * * * Redistributions of source code must retain the above * * copyright notice, this list of conditions and the * * following disclaimer. * * * * * Redistributions in binary form must reproduce the above * * copyright notice, this list of conditions and the * * following disclaimer in the documentation and/or other * * materials provided with the distribution. * * * * * Neither the name of the WIDE Project or NICT nor the * * names of its contributors may be used to endorse or * * promote products derived from this software without * * specific prior written permission of WIDE Project and * * NICT. * * * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *********************************************************************************************************/ /* This file contains the definitions of types and functions related to the security module * and that can be called by extensions. */ /* The security module handles the messages and connections at the borders of the system, * before any other handling when a message is received, and after all other processing * when a message is emitted. * * The security modules are provided by extensions (only). They have two main roles: * - indicate to the daemon if this security mechanism can handle a given peer or not. * - indicate to the daemon a priority for this module. See bellow for details. * - indicate to the daemon the value of Inband-Security-Id mechanism handled by this extension. * - handle the peer connection through some callbacks (when it indicated it can handle the peer): * - when a message must be sent, callback to encrypt and send it * - when a message must be received, callback to receive and decrypt it * - when the peer state changes, callback to notify the module of the change. * This callback should be used to initialize and terminate the cryptographic sessions. * * Note that when no security module is able to handle a connection to a peer, this connection * will be refused. * * Each security module provides a "priority" setting (that should be configurable by module or * by peer in a configuration file) so that if several modules can handle a peer, the daemon will * use the module with the biggest priority. * * Each security module also registers its value of "Inband-Security-Id". Only one module can * be registered for a given value. This value will be used in the CER/CEA exchanges. * * The following two modules are expected to be part of the waaad package: * - no security (Inband-Security-Id = 0). * This module simply sends the message buffer on the network with no security. * The use of this module is expected when transparent security mechanisms are available (IPsec w/ IKEv2). * The configuration file of the module will list explicitly all the authorized peers. * This is so in order to avoid connecting without security to some remote peers. * A better alternative to this module would be some bindings with the IPsec subsystem or IKE(v2) subsystem. * * - TLS security (Inband-Security-Id = 1). * This module uses TLSv1.1 to protect exchanges with a remote peer. * The module included in waaad will use the GNUtls library to do the actual TLS management. * This library is under the LGPL licence, so for environments where this licence is a problem, * contributors are welcomed to provide a replacement under a different licence. * The callback of state change will be used in this module to initiate the handshake process. * * Note that the callbacks in each module will be called by several threads at the same time, so the callbacks * have to be re-entrant and thread-safe (sends and receives are handled by different threads). * */ #ifndef _SECURITY_API_H #define _SECURITY_API_H #include <sys/types.h> #include <sys/socket.h> #ifndef sSA_ALIASES #define sSS struct sockaddr_storage #define sSA struct sockaddr #define sSA4 struct sockaddr_in #define sSA6 struct sockaddr_in6 #define sSA_ALIASES #endif /* sSA_ALIASES */ /* The following type represents a "connection" object (for example, a socket) */ typedef void sec_conn_t; /* This is the prototype of the function that the daemon uses to send data on a TCP */ /* This function may be blocking. */ /* The parameters and return values are the same as the send() function defined in POSIX. */ typedef ssize_t (*sec_send_tcp_cb) (sec_conn_t *, void *, size_t); /* This is the prototype of the function that the daemon uses to receive data from a TCP connection. * This function may be blocking. */ /* The parameters and return values are the same as the recv() function defined in POSIX. */ typedef ssize_t (*sec_recv_tcp_cb) (sec_conn_t *, void *, size_t); /* This is the prototype of the function that the daemon uses to send data on an SCTP connection */ /* The second parameter is the stream id on which the message is sent. -1 means autorotate the streams, in which case the value is updated to the actual stream it was sent to. otherwise the value is unchanged. */ typedef ssize_t (*sec_send_sctp_cb) (sec_conn_t *, int *, void *, size_t); /* This is the prototype of the function that the daemon uses to receive data from an SCTP connection. * This function may be blocking. */ /* The first argument is a connection handle. * the second argument receives the stream id of a message on return. * the third argument is the data on return. it must be freed after use. * the last argument is the length of data. */ typedef ssize_t (*sec_recv_sctp_cb) (sec_conn_t *, int *, void **, size_t*); /* The following enum represents the possible states of a peer with regards to the security module (PSS = peer security state) */ typedef enum { PSS_CLOSED = 1, /* The peer is not connected */ PSS_INITIAL, /* The connection is in progress (CER/CEA, election, ...). */ PSS_CONNECTED, /* The connection is established, messages MUST be protected in this state */ PSS_CLOSING /* The connection is being shutdown, the security extension must proceed to the cleanup of the session */ } sec_pss_t; /* The following type contains information about the connection to the peer. */ typedef struct { peer_t *peer; /* Reference to the peer to which this session applies */ /* The next 3 fields are valid only in the PSS_INITIAL and PSS_CONNECTED states */ sec_conn_t *conn; /* The connection for sending/receiving to/from this peer */ int proto; /* IPPROTO_TCP or IPPROTO_SCTP */ union { struct { sec_send_tcp_cb send_data; /* The callback function to send data to the peer */ sec_recv_tcp_cb recv_data; /* The callback function to receive data from the peer */ } tcp; struct { sec_send_sctp_cb send_data; /* The callback function to send data to the peer */ sec_recv_sctp_cb recv_data; /* The callback function to receive data from the peer */ } sctp; } cbs; } sec_session_t; /* Bellow are the prototypes of callbacks that the extension must provide. */ /* * CALLBACK: sec_state_change_cb_t * * PARAMETERS: * newstate : The new state of the connection with the peer. * oldstate : The previous state of the connection. * session : pointer to information about the connection. * ext_session: The extension may store additional information on the session in this location. * * DESCRIPTION: * This callback is called when a peer state changes (states are described in sec_pss_t type). * The old and new states are provided. * Notes: * Valid transitions are: * PSS_CLOSED -> PSS_INITIAL ( A new connection has been established ) * PSS_INITIAL -> PSS_CONNECTED ( The CER / CEA exchange is successful ) * PSS_INITIAL -> PSS_CLOSING ( The CER / CEA exchange failed, the connection is terminating ) * PSS_INITIAL -> PSS_CLOSED ( The connection has closed unexpectedly ) * PSS_CONNECTED -> PSS_CLOSING ( The diameter exchange is terminated, connection is terminating ) * PSS_CONNECTED -> PSS_CLOSED ( An unexpected error occurred, the transport-layer connection is not available for clean shutdown ) * PSS_CLOSING -> PSS_CLOSED ( The connection has been closed properly. The ext_session must be freed if not already ) * * The socket and send/receive functions are usable only in the INITIAL, CONNECTED and CLOSING states. * The security module may store data in the ext_session parameter. This data MUST be freed * when the new pss state is PSS_CLOSED. * * The PSS_CLOSING state exists only to allow the security module to terminate a connection cleanly. * When a diameter exchange is being terminated (not aborted), the following sequence occurs: * (peer in PSS_CONNECTED state) * DPR / DPA exchange * Initiate the disconnection of the peer (cleanup pending messages, and so on...) * Last step of the disconnection, this callback is called with the newstate: PSS_CLOSING * (daemon expects that the security session terminates) * When the callback returns, the socket is closed and the callback is called again with the newstate PSS_CLOSED. * Then the session is discarded. * * RETURN VALUE: * 0 : Operation complete. * !0 : An error occurred. If the newstate was not PSS_CLOSED, then a shutdown of the connection will happen * and the callback will be called again with newstate PSS_CLOSED. */ typedef int (*sec_state_change_cb_t) (sec_pss_t newstate, sec_pss_t oldstate, sec_session_t * session, void ** ext_session); /* * CALLBACK: sec_send_protect_cb_t * * PARAMETERS: * session : pointer to information about the connection. The send_data and conn fields are always valid. * ext_session: same pointer that was passed to sec_state_change_cb_t. The security extension may store its state here. * data : the location of the data that must be protected and sent. * length : the size of the data that must be sent. * * DESCRIPTION: * This callback is called when data must be sent to the remote peer. It will be called only when the * peer is in the PSS_CONNECTED state. The function must protect the content of the message * contained in the data parameter and send it using the send_data_fct_t callback provided in the session * parameter (the connection parameter to pass to this callback is also in the session parameter). * * This function may be blocking in case of "head-of-the-line blocking". * * RETURN VALUE: * 0 : Operation complete. * !0 : An error occurred. */ typedef int (*sec_send_protect_cb_t) (sec_session_t * session, void ** ext_session, void * data, size_t length); /* * CALLBACK: sec_recv_unprotect_cb_t * * PARAMETERS: * session : pointer to information about the connection. The recv_data and conn fields are always valid. * ext_session: same pointer that was passed to sec_state_change_cb_t. The security extension may store its state here. * data : upon successful read and decrypt, the location to the malloc'd received message is stored here. * length : the size of the data buffer received. * * DESCRIPTION: * This callback is called when data is available for receiving. Upon successful reception and decryption of the content, * a new buffer must be malloc'd to hold the received data and returned to the daemon. * This callback, like send_protect_cb_t, will be called only in the PSS_CONNECTED state. It must use the recv_data and conn * fields of the session parameter to retrieve the data from the transport layer connection. * * RETURN VALUE: * 0 : Operation complete. * !0 : An error occurred. */ typedef int (*sec_recv_unprotect_cb_t) (sec_session_t * session, void ** ext_session, void ** data, size_t *length); /* The last callback is used to notify the daemon whether a given peer can be handled by the daemon or not. * This can be dependant on the configuration, or pre-established trust material (certificates, ...) or other * mechanism. */ /* * CALLBACK: sec_is_supported_peer_cb_t * * PARAMETERS: * diamid : The supposed diameter-id of the peer. Before CER/CEA exchange, this may also be another fqdn of the peer. * The real diameter-id of the peer is available by using the peer_t pointer from the sec_session_t later. * sa : Information about the location and port of the diameter peer we are wanting to connect to. * priority : Upon success, the priority of this module for handling this peer is written here. * Negative value means that the module can not handle this peer. * * DESCRIPTION: * This function is called when a new connection is established with a remote peer. It must write in the * "priority" parameter if this module can protect an exchange with that peer, and with what priority * this module should be used compared to other modules. * * RETURN VALUE: * 0 : Operation complete. * !0 : An error occurred. The module will not be used for this peer. */ typedef int (*sec_is_supported_peer_cb_t) (char * diamid, sSA * sa, int * priority); /* The following type contains all the information needed to register a security module. */ typedef struct { uint32_t sec_insecid; /* The value of the Inband-Security-Id of this module. The dictionary must contain a DICT_TYPE_ENUM object corresponding to this value. */ /* The callbacks from this module, as defined previously */ sec_is_supported_peer_cb_t sec_is_supported_peer; sec_state_change_cb_t sec_state_change; sec_send_protect_cb_t sec_send_protect; sec_recv_unprotect_cb_t sec_recv_unprotect; } sec_module_t; /* The following type represents a registered module, and must be passed to unregister a module. */ typedef void sec_mod_hdl_t; #ifndef IN_EXTENSION /* * FUNCTION: sec_register * * PARAMETERS: * module : Information about the module that must be registered. * handler : On success, a handler to the registered module is stored here. * This handler will be used to deregister the module. * * DESCRIPTION: * Register a new security module to handle a security mechanism. * * RETURN VALUE: * 0 : The module is registered. * EINVAL : A parameter is invalid. * ENOMEM : Not enough memory to complete the operation * EALREADY : Another module is already registered with the same sec_insecid value. */ int sec_register ( sec_module_t * module, sec_mod_hdl_t ** handler ); /* * FUNCTION: sec_unregister * * PARAMETERS: * handler : The module that must be unregistered. * * DESCRIPTION: * Removes a module from the daemon. * * RETURN VALUE: * 0 : The callback is unregistered. * EINVAL : A parameter is invalid. * EAGAIN : The module is still in use and can not be unregistered yet. Retry when all peers are in the PSS_CLOSED state. */ int sec_unregister ( sec_mod_hdl_t * handler ); #endif /* ! IN_EXTENSION */ /* The version of this API, to check binary compatibility -- increment each time a change is made in api_sec_t */ #define WAAAD_API_SEC_VER 1 /* Now define the type of the structure that contains the callback to pass to extensions */ typedef struct { /* The header is common to all sub-API pieces */ size_t length; /* The size of this structure, may be useful for extensions not using the facility */ int version; /* The version of this API/ABI, must be WAAAD_API_SEC_VER */ /* the remaining is security-specific */ int (*sec_register) ( sec_module_t * module, sec_mod_hdl_t ** handler ); int (*sec_unregister) ( sec_mod_hdl_t * handler ); } api_sec_t; #ifdef IN_EXTENSION /* From within the extensions, we register callbacks in the following global structure */ #ifdef DECLARE_API_POINTERS api_sec_t * g_api_sec=NULL; #else /* DECLARE_API_POINTERS */ extern api_sec_t * g_api_sec; #endif /* DECLARE_API_POINTERS */ /* These defines allow to call functions from extension in the same way as in waaad */ #define sec_register g_api_sec->sec_register #define sec_unregister g_api_sec->sec_unregister #else /* IN_EXTENSION */ /* From the daemon, we must initialize the API object, in extension.c */ # define MY_WAAAD_API_SEC_VER 1 # if MY_WAAAD_API_SEC_VER != WAAAD_API_SEC_VER # error "You must update API_INIT_SEC also" # endif #define API_INIT_SEC( api_sec ) \ { \ (api_sec).length = sizeof(api_sec_t); \ (api_sec).version = WAAAD_API_SEC_VER; \ (api_sec).sec_register = sec_register; \ (api_sec).sec_unregister = sec_unregister; \ } #endif /* IN_EXTENSION */ #endif /* _SECURITY_API_H */