src/vsl.h

Go to the documentation of this file.
00001 /*
00002  * Copyright 2006, Internet2
00003  * Legal conditions are in file LICENSE
00004  * (MD5 = c434f2e53b8089d8b4d0172c7ce07360).
00005  */
00006 
00007 /**
00008  * @file   vsl.h
00009  * @author Nikolaus Rath
00010  * @brief  Common headers for the VSL API
00011  *
00012  **/
00013 
00014 
00015 #ifndef VSL_H
00016 #define VSL_H
00017 
00018 #include "vsl_api.h"
00019 #include <stdio.h>
00020 #include <stdbool.h>
00021 #include <stdlib.h>
00022 #include <string.h>
00023 
00024 //! Log message
00025 #define LOG(...) do { if (debug != NULL) { \
00026                      fprintf(debug, "[ %-15s ] ", __func__); \
00027                      fprintf(debug, __VA_ARGS__); \
00028                      fprintf(debug, "\n"); \
00029                      fflush(debug); \
00030                  } } while (false)
00031 
00032 //! Log failure and return from function, preserving errno
00033 #define LOGFAIL(ERR, ...) do { \
00034     int err = errno; \
00035     LOG(__VA_ARGS__); \
00036     errno = err; \
00037     return (ERR); \
00038 } while (false)
00039 
00040 
00041 //! Internal error in library code, log and abort
00042 #define LOGFATAL(...) do { \
00043     if (debug == NULL) \
00044         debug = stderr; \
00045         fprintf(debug, "internal error in %s, %s line %d:\n", __func__, __FILE__, __LINE__); \
00046         fprintf(debug, __VA_ARGS__); \
00047         fprintf(debug, "\n"); \
00048         fflush(debug); \
00049         abort(); \
00050     } while (false)
00051 
00052 //! Call function, escalate a nonzero return value
00053 #define TRY(S)   do { int ret; if ( (ret = (S)) != 0 ) return ret; } while (false)
00054 
00055 //! \brief To print VSL Keys in hex
00056 /** Usage: \code printf(KEY_STR, KEY_VEC); \endcode */
00057 #define KEY_STR       "%.2hhX%.2hhX-%.2hhX%.2hhX-%.2hhX%.2hhX-%.2hhX%.2hhX-" \
00058                       "%.2hhX%.2hhX-%.2hhX%.2hhX-%.2hhX%.2hhX-%.2hhX%.2hhX"
00059 
00060 //! \brief To print VSL Keys in hex
00061 /** Usage: \code printf(KEY_STR, KEY_VEC); \endcode */
00062 #define KEY_VEC(K) \
00063    (K)[0], (K)[1], (K)[2], (K)[3], (K)[4], (K)[5], (K)[6], (K)[7], \
00064    (K)[8], (K)[9], (K)[10], (K)[11], (K)[12], (K)[13], (K)[14], (K)[15]
00065 
00066 
00067 /*
00068  * VSL packet types:
00069  */
00070 //! VSL data packet
00071 #define P_DATA        0x00
00072 
00073 
00074 /**
00075  * Magic bytes in the VSL packet header
00076  **/
00077 //! Length of the magic VSL packet header prefix
00078 #define P_MAGIC_SIZE 4
00079 //! Fill a VSL packet header prefix
00080 #define FILL_MAGIC(X) do { (X)[0] = 'V'; (X)[1] = 'S'; (X)[2] = 'L'; (X)[3] = '1'; } while(0)
00081 //! Check a VSL packet header prefix
00082 #define CHECK_MAGIC(X) ((X)[0] == 'V' && (X)[1] == 'S' && (X)[2] == 'L' && (X)[3] == '1')
00083 
00084 //! VSL Connection Status
00085 /**
00086  * Lower 5 bits indicate whether the socket is
00087  * waiting for a specific pending event
00088  **/
00089 typedef enum {
00090     C_WAIT_FD_R=1,
00091     C_WAIT_FD_W=2,
00092     C_WAIT_VFD_R=4,
00093     C_WAIT_VFD_W=8,
00094     C_WAIT_PID=16,
00095     C_INITIALIZED = (1 << 5),
00096     C_ESTABLISHED = (2 << 5),
00097     C_SSH_FORKED = (3 << 5),
00098     C_SSH_WROTE_SEC = (4 << 5),
00099     C_SSH_VF_CON = (5 << 5),
00100 } connstat_t;
00101 
00102 //! Get precise status
00103 #define CONSTAT(X)   (X >> 5) << 5
00104 
00105 //! Get pending event
00106 #define CONWAIT(X)   (X & 0x1F)
00107 
00108 //! VSL packet header
00109 typedef struct phead_t {
00110     uint64_t msgnr;             //!< Packet number
00111     unsigned char hash[VSL_MACLEN];      //!< MAC
00112     char magic[P_MAGIC_SIZE];   //!< Packet header prefix
00113     char type;                  //!< Packet type
00114     uint32_t datalen;           //!< Length of payload data
00115 } phead_t;
00116 
00117 //! Size of the packet header without aligning
00118 #define PHEAD_SIZE (sizeof(uint64_t)+\
00119                     VSL_MACLEN+\
00120                     P_MAGIC_SIZE+\
00121                     sizeof(char)+\
00122                     sizeof(uint32_t))
00123 
00124 
00125 
00126 #endif
00127 
00128 
00129 /**
00130  * \page vsl VFER SECURITY LAYER (VSL) SPECIFICATION
00131  *
00132  *
00133  * \section handshake Handshake
00134  *
00135  * The handshake establishes a shared secret between server and
00136  * client. This secret is used in the key generation phase to generate
00137  * session keys which are then used for encryption and verification of
00138  * messages. The shared secret is generated using random data and has
00139  * a length of #VSL_KEYLEN bytes.
00140  *
00141  * The following methods are available to share the secret:
00142  *
00143  * \subsection sshm SSH Starting Mode
00144  *
00145  * - the client connects to the server host using ssh and starts the
00146  *   server process. Path of the executable and neccessary arguments
00147  *   have to be supplied to the client API function.
00148  *
00149  * - The client generates the shared secret and writes it into stdin
00150  *   of the ssh and thereby also the server process.
00151  *
00152  *   The message has the following format:
00153  *   \dontinclude vsl_ssh.c
00154  *   \skip struct ssh_msg_secret
00155  *   \until }
00156  *   \a magic is a char array describing the protocoll version and has
00157  *   to be set to \c VSL1 (not zero terminated).
00158  *
00159  * - The server process reads the key, initializes a vfer socket
00160  *   to listen on a free port and prints the port number to stdout.
00161  *
00162  *   The message has the following format:
00163  *   \dontinclude vsl_ssh.c
00164  *   \skip struct ssh_msg_port
00165  *   \until }
00166  *   \a magic is a char array describing the protocoll version and has
00167  *   to be set to \c VSL1 (not zero terminated). \a port is in network
00168  *   byte order.
00169  *
00170  * - The client reads the port number from the ssh connection and
00171  *   initiates a vfer connection to the port.
00172  *
00173  * - When the server has accepted the connection, it daemonizes so
00174  *   that the ssh connection is closed.
00175  *
00176  * - The client waits for the ssh connection to close.
00177  *
00178  * - Server and client generate session keys from the shared secret
00179  *   and set up VSL sockets using the VFER connection as the transport
00180  *   layer.
00181  *
00182  * \note To prevent deadlocks, the server must not try to write
00183  * anything to stderr or stdout before it has read the shared
00184  * secret from stdin.
00185  *
00186  * The server process has to exit with one of the following return
00187  * codes:
00188  * - 0 if the vfer connection was established and the fork for
00189  *   daemonization successfull.
00190  * - #VSL_PERM if there is a permanent error
00191  * - #VSL_TEMP if there is a temporary error
00192  *
00193  * If the server encouters an error, it can additionally write a
00194  * descriptive message of up to 512 bytes to stderr. This has to be
00195  * done before daemonization.
00196  *
00197  * \subsection cr Challenge Response Mode
00198  *
00199  * In challenge response mode, the entire authentication is done over
00200  * an existing vfer connection. First, a shared secret is established
00201  * using Diffie-Hellman key exchange. The secure channel is then used
00202  * to ask the client for a username and a password. The login data is
00203  * then checked by the server using a function supplied by the
00204  * application developer.
00205  *
00206  * \section keygen Session Key Generation
00207  *
00208  * The session keys are generated from the shared secret. There are 4
00209  * different session keys derived for each VSL connection:
00210  *
00211  * - An authentication key to send packets from server to client. This
00212  *   key is generated as SHA256(\a secret || "SRVAUT"), where \a
00213  *   secret is the the shared secret.
00214  *
00215  * - An authentication key to send packets from server to client. This
00216  *   key is generated as SHA256(\a secret || "CLTAUT"), where \a
00217  *   secret is the the shared secret.
00218  *
00219  * - An encryption key to send packets from server to client. This
00220  *   key is generated as MD5(\a secret || "SRVENC"), where \a
00221  *   secret is the the shared secret.
00222  *
00223  * - An encryption key to send packets from client to server. This
00224  *   key is generated as MD5(\a secret || "CLTENC"), where \a
00225  *   secret is the the shared secret.
00226  *
00227  * \a a || \a b means that \a a and \a b are concatenated. All the
00228  * strings are \b not \c @\0 terminated.
00229  *
00230  * \section enc Packet Encryption
00231  *
00232  * Each VSL packet has a header with the structure:
00233  * \dontinclude vsl.h
00234  * \skip phead_t
00235  * \until }
00236  * followed by \a datalen bytes of data. VSL packets are send as
00237  * VFER datagrams. All integer values are in network byte order.
00238  *
00239  * \subsection send Sending a Data Packet
00240  *
00241  * If a message \a msg is to be send, the procedure is as follows:
00242  * - a packet is created containing the described header followed
00243  *   by \a msg.
00244  * - \a magic is set to \c "VSL1" (not \c @\0 terminated)
00245  * - \a type is set to #P_DATA
00246  * - \a datalen is set to the length of \a msg.  The maximum length
00247  *   is 2^30 bytes (1 GB) (due to the used
00248  *   Poly1305 MAC algorithm) or the maximum size of a vfer frame,
00249  *   whatever value is smaller.
00250  * - \a hash is set to a string of 0 bytes.
00251  * - \a msgnr is set to the number of the last sent message plus 1
00252  *   (for each VSL connection, both client and server store the
00253  *   numbers of the last received and last sent message). If msgnr
00254  *   overflows, no more messages can be send.
00255  * - the body of the packet (length \a datalen), is encrypted
00256  *   using AES-128 in CTR mode. The initial (128 bit) counter is set
00257  *   to \a msgnr << 64. The used key is the encryption key (either
00258  *   for server to client or client to server messages)
00259  * - \a hash is set to the MAC calculated by Poly1305-AES
00260  *   (http://cr.yp.to/mac.html) from (\a key, \a packet). \a key is the
00261  *   authentication key (either for client to server or for server to
00262  *   client packets) and \a packet is the complete packet, including
00263  *   \a hash itself, which is still set to 0.
00264  * - the packet is send using the underlying VFER connection.
00265  *
00266  * \subsection recv Receiving a Data Packet
00267  *
00268  * If a packet \a pkg has been received, the procedure to obtain
00269  * the message \a msg is as follows (the packet is dropped if any of
00270  * the assertions fail):
00271  * - the packet is split into the described packet header and the
00272  *   message \a msg. Splitting can always be done since the header
00273  *   has a fixed size.
00274  * - assert: \a magic is set to \c "VSL1" (not \c @\0 terminated)
00275  * - assert: \a type is set to #P_DATA
00276  * - assert: \a msgnr is larger than the number of the last message
00277  *   received (for each VSL connection, both client and server store
00278  *   the numbers of the last received and last sent message).
00279  * - \a hash is copied to \a hash_o. In the packet, \a hash is then
00280  *   set to 0.
00281  * - assert: \a hash_o is identical to
00282  *   Poly1305-AES(\a key, \a packet) (see http://cr.yp.to/mac.html). \a
00283  *   key is the authentication key (either for client to server or for
00284  *   server to client packets) and \a packet is the complete packet,
00285  *   where \a hash has been set to 0.
00286  * - the packet body, is decrypted using
00287  *   AES-128 in CTR mode. The initial (128 bit) counter is set to \a
00288  *   msgnr << 64. The used key is the encryption key (either for
00289  *   server to client or client to server messages)
00290  * - the message \a msg is returned.
00291  *
00292  **/
00293 
00294 
00295 /*
00296  * Local Variables:
00297  * compile-command: "cd ..; make tests file_xfer"
00298  * compilation-search-path: ("..")
00299  * End:
00300  */

Generated on Tue Aug 8 16:07:19 2006 for VFER by  doxygen 1.4.7