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 */