diff options
author | Christian Pointner <equinox@anytun.org> | 2014-06-29 21:57:52 +0000 |
---|---|---|
committer | Christian Pointner <equinox@anytun.org> | 2014-06-29 21:57:52 +0000 |
commit | 77808f3fb99ef32830eaa6c2e636b549c1e3dfe0 (patch) | |
tree | 9853db1074e6892c06202a2dcddcf35147e4f3ad | |
parent | dropped plans to set permissions inside generic unixdomain sockets (diff) |
added keyexchange subsystem
-rw-r--r-- | src/Makefile | 1 | ||||
-rw-r--r-- | src/keyexchange.c | 122 | ||||
-rw-r--r-- | src/keyexchange.h | 66 | ||||
-rw-r--r-- | src/uanytun.c | 69 |
4 files changed, 207 insertions, 51 deletions
diff --git a/src/Makefile b/src/Makefile index 1a639ac..fe28bf1 100644 --- a/src/Makefile +++ b/src/Makefile @@ -66,6 +66,7 @@ OBJ := log.o \ seq_window.o \ cipher.o \ unixdomain.o \ + keyexchange.o \ uanytun.o diff --git a/src/keyexchange.c b/src/keyexchange.c new file mode 100644 index 0000000..0302b52 --- /dev/null +++ b/src/keyexchange.c @@ -0,0 +1,122 @@ +/* + * uAnytun + * + * uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full + * featured implementation uAnytun has no support for multiple connections + * or synchronisation. It is a small single threaded implementation intended + * to act as a client on small platforms. + * The secure anycast tunneling protocol (satp) defines a protocol used + * for communication between any combination of unicast and anycast + * tunnel endpoints. It has less protocol overhead than IPSec in Tunnel + * mode and allows tunneling of every ETHER TYPE protocol (e.g. + * ethernet, ip, arp ...). satp directly includes cryptography and + * message authentication based on the methods used by SRTP. It is + * intended to deliver a generic, scaleable and secure solution for + * tunneling and relaying of packets of any protocol. + * + * + * Copyright (C) 2007-2014 Christian Pointner <equinox@anytun.org> + * + * This file is part of uAnytun. + * + * uAnytun 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 + * any later version. + * + * uAnytun 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 uAnytun. If not, see <http://www.gnu.org/licenses/>. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#define _GNU_SOURCE +#include "datatypes.h" + +#include "keyexchange.h" + +#include "log.h" + +int keyexchange_init(keyexchange_t* kx, const char* path_control, const char* path_data) +{ + if(!kx) + return -1; + + int ret = unixdomain_init(&(kx->control_interface_), path_control); + if(ret) return ret; + + ret = unixdomain_init(&(kx->data_interface_), path_data); + if(ret) + unixdomain_close(&(kx->control_interface_)); + + return ret; +} + +int keyexchange_fill_fd_set(keyexchange_t* kx, fd_set* read, fd_set* write) +{ + return unixdomain_fill_fd_set(&(kx->data_interface_), read); + // ignoreing writes and control interface for now +} + +void keyexchange_close(keyexchange_t* kx) +{ + unixdomain_close(&(kx->control_interface_)); + unixdomain_close(&(kx->data_interface_)); +} + +static int keyexchange_handle_read(keyexchange_t* kx, fd_set* readyfds) +{ + if(FD_ISSET(kx->data_interface_.server_fd_, readyfds)) { + int old_fd = kx->data_interface_.client_fd_; + if(unixdomain_accept(&(kx->data_interface_))) { + return -1; + } + if(old_fd != kx->data_interface_.client_fd_) { + log_printf(INFO, "key exchange: new client"); + } + } + if(FD_ISSET(kx->data_interface_.client_fd_, readyfds)) { + u_int8_t buf[100]; + int len = unixdomain_read(&(kx->data_interface_), buf, sizeof(buf)); + if(len < 0) { + log_printf(ERROR, "key exchange: client error!!!!!"); + } if(!len) { + log_printf(INFO, "key exchange: client disconnected"); + kx->data_interface_.client_fd_ = -1; + } else { + buf[len] = 0; + log_printf(DEBUG, "key exchange: received string '%s'", buf); + unixdomain_write(&(kx->data_interface_), buf, len); + } + } + + return 0; +} + +/* static int keyexchange_handle_write(keyexchange_t* kx, fd_set* readyfds) */ +/* { */ +/* // TODO: implement this */ +/* return 0; */ +/* } */ + +int keyexchange_handle(keyexchange_t* kx, fd_set* rreadyfds, fd_set* wreadyfds) +{ + return keyexchange_handle_read(kx, rreadyfds); + // ignoreing writes for now +} diff --git a/src/keyexchange.h b/src/keyexchange.h new file mode 100644 index 0000000..f1d686f --- /dev/null +++ b/src/keyexchange.h @@ -0,0 +1,66 @@ +/* + * uAnytun + * + * uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full + * featured implementation uAnytun has no support for multiple connections + * or synchronisation. It is a small single threaded implementation intended + * to act as a client on small platforms. + * The secure anycast tunneling protocol (satp) defines a protocol used + * for communication between any combination of unicast and anycast + * tunnel endpoints. It has less protocol overhead than IPSec in Tunnel + * mode and allows tunneling of every ETHER TYPE protocol (e.g. + * ethernet, ip, arp ...). satp directly includes cryptography and + * message authentication based on the methods used by SRTP. It is + * intended to deliver a generic, scaleable and secure solution for + * tunneling and relaying of packets of any protocol. + * + * + * Copyright (C) 2007-2014 Christian Pointner <equinox@anytun.org> + * + * This file is part of uAnytun. + * + * uAnytun 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 + * any later version. + * + * uAnytun 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 uAnytun. If not, see <http://www.gnu.org/licenses/>. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#ifndef UANYTUN_keyexchange_h_INCLUDED +#define UANYTUN_keyexchange_h_INCLUDED + +#include "unixdomain.h" + +struct keyexchange_struct { + unixdomain_t data_interface_; + unixdomain_t control_interface_; +}; +typedef struct keyexchange_struct keyexchange_t; + +int keyexchange_init(keyexchange_t* kx, const char* path_control, const char* path_data); +int keyexchange_fill_fd_set(keyexchange_t* kx, fd_set* read, fd_set* write); +void keyexchange_close(keyexchange_t* kx); + +int keyexchange_handle(keyexchange_t* kx, fd_set* rreadyfds, fd_set* wreadyfds); + +#endif diff --git a/src/uanytun.c b/src/uanytun.c index b95996f..da7dc3d 100644 --- a/src/uanytun.c +++ b/src/uanytun.c @@ -65,6 +65,7 @@ #include "seq_window.h" +#include "keyexchange.h" #include "cipher.h" #ifndef NO_CRYPT #include "key_derivation.h" @@ -77,14 +78,19 @@ typedef u_int8_t auth_algo_t; #include "daemon.h" #include "sysexec.h" -#include "unixdomain.h" - -int init_main_loop(options_t* opt, cipher_t* c, auth_algo_t* aa, key_derivation_t* kd, seq_win_t* seq_win) +int init_main_loop(options_t* opt, keyexchange_t* kx, cipher_t* c, auth_algo_t* aa, key_derivation_t* kd, seq_win_t* seq_win) { - int ret = cipher_init(c, opt->cipher_); + int ret = keyexchange_init(kx, opt->kx_control_interface_, opt->kx_data_interface_); + if(ret) { + log_printf(ERROR, "could not initialize key exchange interface"); + return ret; + } + + ret = cipher_init(c, opt->cipher_); if(ret) { log_printf(ERROR, "could not initialize cipher of type %s", opt->cipher_); + keyexchange_close(kx); return ret; } @@ -92,6 +98,7 @@ int init_main_loop(options_t* opt, cipher_t* c, auth_algo_t* aa, key_derivation_ ret = auth_algo_init(aa, opt->auth_algo_); if(ret) { log_printf(ERROR, "could not initialize auth algo of type %s", opt->auth_algo_); + keyexchange_close(kx); cipher_close(c); return ret; } @@ -99,6 +106,7 @@ int init_main_loop(options_t* opt, cipher_t* c, auth_algo_t* aa, key_derivation_ ret = key_derivation_init(kd, opt->kd_prf_, opt->role_, opt->passphrase_, opt->key_.buf_, opt->key_.length_, opt->salt_.buf_, opt->salt_.length_); if(ret) { log_printf(ERROR, "could not initialize key derivation of type %s", opt->kd_prf_); + keyexchange_close(kx); cipher_close(c); auth_algo_close(aa); return ret; @@ -108,6 +116,7 @@ int init_main_loop(options_t* opt, cipher_t* c, auth_algo_t* aa, key_derivation_ ret = seq_win_init(seq_win, opt->seq_window_size_); if(ret) { printf("could not initialize sequence window"); + keyexchange_close(kx); cipher_close(c); #ifndef NO_CRYPT auth_algo_close(aa); @@ -214,38 +223,6 @@ int process_sock_data(tun_device_t* dev, int fd, udp_t* sock, options_t* opt, pl } - -int process_key_exchange(unixdomain_t* sock, fd_set* readyfds) -{ - if(FD_ISSET(sock->server_fd_, readyfds)) { - int old_fd = sock->client_fd_; - if(unixdomain_accept(sock)) { - return -1; - } - if(old_fd != sock->client_fd_) { - log_printf(INFO, "key exchange: new client"); - } - } - if(FD_ISSET(sock->client_fd_, readyfds)) { - u_int8_t buf[100]; - int len = unixdomain_read(sock, buf, sizeof(buf)); - if(len < 0) { - log_printf(ERROR, "key exchange: client error!!!!!"); - } if(!len) { - log_printf(INFO, "key exchange: client disconnected"); - sock->client_fd_ = -1; - } else { - buf[len] = 0; - log_printf(DEBUG, "key exchange: received string '%s'", buf); - unixdomain_write(sock, buf, len); - } - } - - return 0; -} - - - int main_loop(tun_device_t* dev, udp_t* sock, options_t* opt) { log_printf(INFO, "entering main loop"); @@ -257,20 +234,16 @@ int main_loop(tun_device_t* dev, udp_t* sock, options_t* opt) seq_nr_t seq_nr = 0; fd_set readfds, readyfds; + keyexchange_t kx; cipher_t c; auth_algo_t aa; key_derivation_t kd; seq_win_t seq_win; - int ret = init_main_loop(opt, &c, &aa, &kd, &seq_win); + int ret = init_main_loop(opt, &kx, &c, &aa, &kd, &seq_win); if(ret) return ret; - - unixdomain_t kx_data; - unixdomain_init(&kx_data, opt->kx_data_interface_); - - FD_ZERO(&readfds); FD_SET(dev->fd_, &readfds); int nfds = udp_fill_fd_set(sock, &readfds); @@ -286,7 +259,7 @@ int main_loop(tun_device_t* dev, udp_t* sock, options_t* opt) while(!return_value) { memcpy(&readyfds, &readfds, sizeof(readyfds)); - int kx_max_fd = unixdomain_fill_fd_set(&kx_data, &readyfds); + int kx_max_fd = keyexchange_fill_fd_set(&kx, &readyfds, NULL); int tmp = (nfds < kx_max_fd) ? kx_max_fd : nfds; int ret = select(tmp + 1, &readyfds, NULL, NULL, NULL); if(ret == -1 && errno != EINTR) { @@ -317,12 +290,7 @@ int main_loop(tun_device_t* dev, udp_t* sock, options_t* opt) break; } - if(FD_ISSET(kx_data.server_fd_, &readyfds) || FD_ISSET(kx_data.server_fd_, &readyfds) || - FD_ISSET(kx_data.client_fd_, &readyfds) || FD_ISSET(kx_data.client_fd_, &readyfds)) { - return_value = process_key_exchange(&kx_data, &readyfds); - if(return_value) - break; - } + keyexchange_handle(&kx, &readyfds, NULL); udp_socket_t* s = sock->socks_; while(s) { @@ -335,8 +303,7 @@ int main_loop(tun_device_t* dev, udp_t* sock, options_t* opt) } } - unixdomain_close(&kx_data); - + keyexchange_close(&kx); cipher_close(&c); #ifndef NO_CRYPT auth_algo_close(&aa); |