--- gvpe/src/connection.h 2003/04/05 02:32:40 1.5 +++ gvpe/src/connection.h 2013/07/18 13:35:16 1.38 @@ -1,23 +1,36 @@ /* connection.h -- header for connection.C + Copyright (C) 2003-2008,2013 Marc Lehmann - 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. - - 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. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + This file is part of GVPE. + + GVPE 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 3 of the License, or (at your + option) any later version. + + 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. + + You should have received a copy of the GNU General Public License along + with this program; if not, see . + + Additional permission under GNU GPL version 3 section 7 + + If you modify this Program, or any covered work, by linking or + combining it with the OpenSSL project's OpenSSL library (or a modified + version of that library), containing parts covered by the terms of the + OpenSSL or SSLeay licenses, the licensors of this Program grant you + additional permission to convey the resulting work. Corresponding + Source for a non-source form of such a combination shall include the + source code for the parts of OpenSSL used as well as that of the + covered work. */ -#ifndef VPE_CONNECTION_H__ -#define VPE_CONNECTION_H__ +#ifndef GVPE_CONNECTION_H__ +#define GVPE_CONNECTION_H__ #include @@ -26,25 +39,62 @@ #include "sockinfo.h" #include "util.h" #include "device.h" +#include "curve25519.h" +#include "iv_gen.h" struct vpn; // called after HUP etc. to (re-)initialize global data structures void connection_init (); -struct rsaid { - u8 id[RSA_IDLEN]; // the challenge id +typedef curve25519_key ecdh_key; + +struct rsa_data +{ + u32 seqno; + u8 auth_key[AUTH_SIZE]; + u8 mac_key[MAC_KEYSIZE]; // used to generate hmac key + u8 cipher_key[CIPHER_KEYSIZE]; // used to generate cipher key + u8 hkdf_salt[HKDF_SALT]; // used as hkdf salt + u8 pad[ + (RSABITS >> 3) + - 41 // OAEP + - sizeof (u32) // seqno + - AUTH_SIZE + - MAC_KEYSIZE + - CIPHER_KEYSIZE + - HKDF_SALT + - 3 // struct alignment... + ]; +}; + +struct auth_data +{ + rsa_data rsa; + ecdh_key ecdh; +}; + +typedef u8 rsa_crypt[RSA_KEYLEN]; // encrypted challenge + +struct auth_encr +{ + rsa_crypt rsa; + ecdh_key ecdh; }; -typedef u8 rsachallenge[RSA_KEYLEN - RSA_OVERHEAD]; // challenge data; -typedef u8 rsaencrdata[RSA_KEYLEN]; // encrypted challenge -typedef u8 rsaresponse[RSA_RESLEN]; // the encrypted ripemd160 hash +typedef u8 auth_mac[AUTH_SIZE]; + +struct auth_response +{ + auth_mac mac; + ecdh_key ecdh; +}; //////////////////////////////////////////////////////////////////////////////////////// struct crypto_ctx; -struct hmac_packet:net_packet +struct hmac_packet : net_packet { u8 hmac[HMACLENGTH]; // each and every packet has a hmac field, but that is not (yet) checked everywhere @@ -58,108 +108,164 @@ }; struct vpn_packet : hmac_packet +{ + enum ptype { - enum ptype - { - PT_RESET = 0, - PT_DATA_UNCOMPRESSED, - PT_DATA_COMPRESSED, - PT_PING, PT_PONG, // wasting namespace space? ;) - PT_AUTH_REQ, // authentification request - PT_AUTH_RES, // authentification response - PT_CONNECT_REQ, // want other host to contact me - PT_CONNECT_INFO, // request connection to some node - PT_MAX - }; - - u8 type; - u8 srcdst, src1, dst1; - - void set_hdr (ptype type_, unsigned int dst); - - unsigned int src () const - { - return src1 | ((srcdst >> 4) << 8); - } - - unsigned int dst () const - { - return dst1 | ((srcdst & 0xf) << 8); - } - - ptype typ () const - { - return (ptype) type; - } + PT_RESET = 0, + PT_DATA_UNCOMPRESSED, + PT_DATA_COMPRESSED, + PT_PING, PT_PONG, // wasting namespace space? ;) + PT_AUTH_REQ, // authentification request + PT_AUTH_RES, // authentification response + PT_CONNECT_REQ, // want other node to contact me + PT_CONNECT_INFO, // request connection to some node + PT_DATA_BRIDGED, // uncompressed packet with foreign mac pot. larger than path mtu (NYI) + PT_MAX }; + u8 type; + u8 srcdst, src1, dst1; + + void set_hdr (ptype type_, unsigned int dst); + + unsigned int src () const + { + return src1 | ((srcdst >> 4) << 8); + } + + unsigned int dst () const + { + return dst1 | ((srcdst & 0xf) << 8); + } + + ptype typ () const + { + return (ptype) type; + } +}; + //////////////////////////////////////////////////////////////////////////////////////// // a very simple fifo pkt-queue class pkt_queue - { - tap_packet *queue[QUEUEDEPTH]; - int i, j; +{ + int i, j; + int max_queue; + double max_ttl; - public: + struct pkt { + ev_tstamp tstamp; + net_packet *pkt; + } *queue; - void put (tap_packet *p); - tap_packet *get (); + void expire_cb (ev::timer &w, int revents); ev::timer expire; - pkt_queue (); - ~pkt_queue (); - }; +public: -struct connection + void put (net_packet *p); + net_packet *get (); + + bool empty () { - conf_node *conf; - struct vpn *vpn; + return i == j; + } - sockinfo si; // the current(!) destination ip to send packets to - int retry_cnt; + pkt_queue (double max_ttl, int max_queue); + ~pkt_queue (); +}; - tstamp last_activity; // time of last packet received +enum +{ + FEATURE_COMPRESSION = 0x01, + FEATURE_ROHC = 0x02, + FEATURE_BRIDGING = 0x04, +}; - u32 oseqno; - sliding_window iseqno; +struct connection +{ + conf_node *conf; + struct vpn *vpn; - u8 protocol; + sockinfo si; // the current(!) destination ip to send packets to + int retry_cnt; - pkt_queue queue; + tstamp last_activity; // time of last packet received + tstamp last_establish_attempt; + //tstamp last_si_change; // time we last changed the socket address - crypto_ctx *octx, *ictx; + u32 oseqno; + sliding_window iseqno; - enum conf_node::connectmode connectmode; - u8 prot_minor; // minor number of other side + u8 protocol; + u8 features; + bool is_direct; // current connection (si) is direct? - void reset_dstaddr (); + pkt_queue data_queue, vpn_queue; - void shutdown (); - void reset_connection (); - void establish_connection_cb (time_watcher &w); time_watcher establish_connection; - void rekey_cb (time_watcher &w); time_watcher rekey; // next rekying (actually current reset + reestablishing) - void keepalive_cb (time_watcher &w); time_watcher keepalive; // next keepalive probe + crypto_ctx *octx, *ictx; + iv_gen oiv; // generator for random byte prefix - void send_auth_request (const sockinfo &si, bool initiate); - void send_auth_response (const sockinfo &si, const rsaid &id, const rsachallenge &chg); - void send_connect_info (int rid, const sockinfo &rsi, u8 rprotocols); - void send_reset (const sockinfo &dsi); - void send_ping (const sockinfo &dsi, u8 pong = 0); - void send_data_packet (tap_packet *pkt, bool broadcast = false); - void inject_data_packet (tap_packet *pkt, bool broadcast = false); - void connect_request (int id); + void generate_auth_data (); - void recv_vpn_packet (vpn_packet *pkt, const sockinfo &rsi); + ev_tstamp auth_expire; // when the snd_* and *_ecdh values expire - void script_node (); - const char *script_node_up (); - const char *script_node_down (); + // send auth data - used for octx + auth_data snd_auth; + auth_mac snd_auth_mac; // expected response mac + ecdh_key snd_ecdh_a; // the secret ecdh key we used for our request + ecdh_key snd_ecdh_b; // the public ecdh key we received in the response + bool have_snd_auth; // received response for our req - void dump_status (); + // receive auth data - used for ictx + auth_data rcv_auth; + ecdh_key rcv_ecdh_a; // the secret ecdh key we used for our response + ecdh_key rcv_ecdh_b; // the public ecdh key we sent in our response + bool have_rcv_auth; // received auth from other side - connection(struct vpn *vpn_); - ~connection (); - }; +#if ENABLE_DNS + struct dns_connection *dns; +#endif + + enum conf_node::connectmode connectmode; + u8 prot_minor; // minor number of other side + + void reset_si (); + const sockinfo &forward_si (const sockinfo &si) const; + + void shutdown (); + void connection_established (const sockinfo &rsi); + void reset_connection (); + + void establish_connection_cb (ev::timer &w, int revents); ev::timer establish_connection; + void rekey_cb (ev::timer &w, int revents); ev::timer rekey; // next rekying (actually current reset + reestablishing) + void keepalive_cb (ev::timer &w, int revents); ev::timer keepalive; // next keepalive probe + + void send_connect_request (int id); + void send_auth_request (const sockinfo &si, bool initiate); + void send_auth_response (const sockinfo &si); + void send_connect_info (int rid, const sockinfo &rsi, u8 rprotocols); + void send_reset (const sockinfo &dsi); + void send_ping (const sockinfo &dsi, u8 pong = 0); + void send_data_packet (tap_packet *pkt); + + void post_inject_queue (); + void inject_data_packet (tap_packet *pkt); + void inject_vpn_packet (vpn_packet *pkt, int tos = 0); // for forwarding + + void recv_vpn_packet (vpn_packet *pkt, const sockinfo &rsi); + void send_vpn_packet (vpn_packet *pkt, const sockinfo &si, int tos = 0); + + void script_init_env (const char *ext); + void script_init_connect_env (); + const char *script_node_up (); + const char *script_node_change (); + const char *script_node_down (); + + void dump_status (); + + connection (struct vpn *vpn, conf_node *conf); + ~connection (); +}; #endif