uanytun-0.3.3/0000775000175000017500000000000011336622533013170 5ustar equinoxequinoxuanytun-0.3.3/AUTHORS0000664000175000017500000000005011336622524014233 0ustar equinoxequinoxChristian Pointner uanytun-0.3.3/src/0000775000175000017500000000000011336622533013757 5ustar equinoxequinoxuanytun-0.3.3/src/auth_algo.h0000664000175000017500000000572711336622524016106 0ustar equinoxequinox/* * 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 methodes 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-2010 Christian Pointner * * 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 . */ #ifndef UANYTUN_auth_algo_h_INCLUDED #define UANYTUN_auth_algo_h_INCLUDED #ifndef USE_SSL_CRYPTO #include #else #include #endif #include "key_derivation.h" #include "encrypted_packet.h" enum auth_algo_type_enum { aa_unknown, aa_null, aa_sha1 }; typedef enum auth_algo_type_enum auth_algo_type_t; struct auth_algo_struct { auth_algo_type_t type_; buffer_t key_; void* params_; }; typedef struct auth_algo_struct auth_algo_t; auth_algo_type_t auth_algo_get_type(const char* type); u_int32_t auth_algo_get_max_length(const char* type); int auth_algo_init(auth_algo_t* aa, const char* type); void auth_algo_close(auth_algo_t* aa); void auth_algo_generate(auth_algo_t* aa, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* packet); int auth_algo_check_tag(auth_algo_t* aa, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* packet); #define SHA1_LENGTH 20 struct auth_algo_sha1_param_struct { #ifndef USE_SSL_CRYPTO gcry_md_hd_t handle_; #else HMAC_CTX ctx_; #endif }; typedef struct auth_algo_sha1_param_struct auth_algo_sha1_param_t; int auth_algo_sha1_init(auth_algo_t* aa); void auth_algo_sha1_close(auth_algo_t* aa); void auth_algo_sha1_generate(auth_algo_t* aa, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* packet); int auth_algo_sha1_check_tag(auth_algo_t* aa, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* packet); #endif uanytun-0.3.3/src/plain_packet.h0000664000175000017500000000525511336622524016571 0ustar equinoxequinox/* * 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 methodes 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-2010 Christian Pointner * * 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 . */ #ifndef UANYTUN_plain_packet_h_INCLUDED #define UANYTUN_plain_packet_h_INCLUDED #define PLAIN_PACKET_SIZE_MAX 1600 #define PAYLOAD_TYPE_TAP 0x6558 #define PAYLOAD_TYPE_TUN 0x0000 #define PAYLOAD_TYPE_TUN4 0x0800 #define PAYLOAD_TYPE_TUN6 0x86DD #define PAYLOAD_TYPE_UNKNOWN 0xFFFF struct plain_packet_struct { u_int32_t payload_length_; union __attribute__ ((__packed__)) { u_int8_t buf_[PLAIN_PACKET_SIZE_MAX]; payload_type_t payload_type_; } data_; }; typedef struct plain_packet_struct plain_packet_t; void plain_packet_init(plain_packet_t* packet); u_int32_t plain_packet_get_header_length(); u_int8_t* plain_packet_get_packet(plain_packet_t* packet); u_int32_t plain_packet_get_length(plain_packet_t* packet); void plain_packet_set_length(plain_packet_t* packet, u_int32_t len); u_int8_t* plain_packet_get_payload(plain_packet_t* packet); u_int32_t plain_packet_get_payload_length(plain_packet_t* packet); void plain_packet_set_payload_length(plain_packet_t* packet, u_int32_t len); payload_type_t plain_packet_get_type(plain_packet_t* packet); void plain_packet_set_type(plain_packet_t* packet, payload_type_t type); #endif uanytun-0.3.3/src/linux/0000775000175000017500000000000011336622533015116 5ustar equinoxequinoxuanytun-0.3.3/src/linux/tun.c0000664000175000017500000001213211336622524016067 0ustar equinoxequinox/* * 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 methodes 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-2010 Christian Pointner * * 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 . */ #include #include "datatypes.h" #include "tun.h" #include "tun_helper.h" #include #include #include #include #include #include #include #include #include #include #include #define DEFAULT_DEVICE "/dev/net/tun" #include "log.h" #include "sysexec.h" int tun_init(tun_device_t* dev, const char* dev_name, const char* dev_type, const char* ifcfg_addr, u_int16_t ifcfg_prefix){ if(!dev) return -1; tun_conf(dev, dev_name, dev_type, ifcfg_addr, ifcfg_prefix, 1400); dev->actual_name_ = NULL; dev->fd_ = open(DEFAULT_DEVICE, O_RDWR); if(dev->fd_ < 0) { log_printf(ERROR, "can't open device file (%s): %s", DEFAULT_DEVICE, strerror(errno)); tun_close(dev); return -1; } struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); if(dev->type_ == TYPE_TUN) { ifr.ifr_flags = IFF_TUN; dev->with_pi_ = 1; } else if(dev->type_ == TYPE_TAP) { ifr.ifr_flags = IFF_TAP | IFF_NO_PI; dev->with_pi_ = 0; } else { log_printf(ERROR, "unable to recognize type of device (tun or tap)"); tun_close(dev); return -1; } if(dev_name) strncpy(ifr.ifr_name, dev_name, IFNAMSIZ); if(!ioctl(dev->fd_, TUNSETIFF, &ifr)) { dev->actual_name_ = strdup(ifr.ifr_name); } else if(!ioctl(dev->fd_, (('T' << 8) | 202), &ifr)) { dev->actual_name_ = strdup(ifr.ifr_name); } else { log_printf(ERROR, "tun/tap device ioctl failed: %s", strerror(errno)); tun_close(dev); return -1; } if(!dev->actual_name_) { log_printf(ERROR, "can't open device file: memory error"); tun_close(dev); return -2; } if(ifcfg_addr) tun_do_ifconfig(dev); return 0; } int tun_init_post(tun_device_t* dev) { // nothing yet } void tun_close(tun_device_t* dev) { if(!dev) return; if(dev->fd_ > 0) close(dev->fd_); if(dev->actual_name_) free(dev->actual_name_); if(dev->net_addr_) free(dev->net_addr_); if(dev->net_mask_) free(dev->net_mask_); } int tun_read(tun_device_t* dev, u_int8_t* buf, u_int32_t len) { if(!dev || dev->fd_ < 0) return -1; if(dev->with_pi_) { struct iovec iov[2]; struct tun_pi tpi; iov[0].iov_base = &tpi; iov[0].iov_len = sizeof(tpi); iov[1].iov_base = buf; iov[1].iov_len = len; return(tun_fix_return(readv(dev->fd_, iov, 2), sizeof(tpi))); } else return(read(dev->fd_, buf, len)); } int tun_write(tun_device_t* dev, u_int8_t* buf, u_int32_t len) { if(!dev || dev->fd_ < 0) return -1; if(!buf) return 0; if(dev->with_pi_) { struct iovec iov[2]; struct tun_pi tpi; struct iphdr *hdr = (struct iphdr *)buf; tpi.flags = 0; if(hdr->version == 4) tpi.proto = htons(ETH_P_IP); else tpi.proto = htons(ETH_P_IPV6); iov[0].iov_base = &tpi; iov[0].iov_len = sizeof(tpi); iov[1].iov_base = buf; iov[1].iov_len = len; return(tun_fix_return(writev(dev->fd_, iov, 2), sizeof(tpi))); } else return(write(dev->fd_, buf, len)); } void tun_do_ifconfig(tun_device_t* dev) { if(!dev || !dev->actual_name_ || !dev->net_addr_ || !dev->net_mask_) return; char* mtu_str = NULL; asprintf(&mtu_str, "%d", dev->mtu_); if(!mtu_str) { log_printf(ERROR, "Execution of ifconfig failed"); return; } char* const argv[] = { "/sbin/ifconfig", dev->actual_name_, dev->net_addr_, "netmask", dev->net_mask_, "mtu", mtu_str, NULL }; char* const evp[] = { NULL }; uanytun_exec("/sbin/ifconfig", argv, evp); free(mtu_str); } uanytun-0.3.3/src/sig_handler.c0000664000175000017500000001124111336622524016401 0ustar equinoxequinox/* * 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 methodes 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-2010 Christian Pointner * * 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 . */ #include "datatypes.h" #include "log.h" #include "sig_handler.h" #include #include #include #include static int sig_pipe_fds[2]; static void sig_handler(int sig) { sigset_t set; int ret = read(sig_pipe_fds[0], &set, sizeof(sigset_t)); if(ret != sizeof(sigset_t)) sigemptyset(&set); sigaddset(&set, sig); ret = write(sig_pipe_fds[1], &set, sizeof(sigset_t)); } int signal_init() { if(pipe(sig_pipe_fds)) { log_printf(ERROR, "signal handling init failed (pipe error: %s)", strerror(errno)); return -1; } int i; for(i=0; i<2; ++i) { int fd_flags = fcntl(sig_pipe_fds[i], F_GETFL); if(fd_flags == -1) { log_printf(ERROR, "signal handling init failed (pipe fd[%d] read flags error: %s)", i, strerror(errno)); return -1; } if(fcntl(sig_pipe_fds[i], F_SETFL, fd_flags | O_NONBLOCK) == -1){ log_printf(ERROR, "signal handling init failed (pipe fd[%d] write flags error: %s)", i, strerror(errno)); return -1; } } struct sigaction act; act.sa_handler = sig_handler; sigfillset(&act.sa_mask); act.sa_flags = 0; if((sigaction(SIGINT, &act, NULL) < 0) || (sigaction(SIGQUIT, &act, NULL) < 0) || (sigaction(SIGTERM, &act, NULL) < 0) || (sigaction(SIGHUP, &act, NULL) < 0) || (sigaction(SIGUSR1, &act, NULL) < 0) || (sigaction(SIGUSR2, &act, NULL) < 0)) { log_printf(ERROR, "signal handling init failed (sigaction error: %s)", strerror(errno)); close(sig_pipe_fds[0]); close(sig_pipe_fds[1]); } return sig_pipe_fds[0]; } int signal_handle() { sigset_t set, oldset, tmpset; sigemptyset(&tmpset); sigaddset(&tmpset, SIGINT); sigaddset(&tmpset, SIGQUIT); sigaddset(&tmpset, SIGTERM); sigaddset(&tmpset, SIGHUP); sigaddset(&tmpset, SIGUSR1); sigaddset(&tmpset, SIGUSR2); sigprocmask(SIG_BLOCK, &tmpset, &oldset); int ret = read(sig_pipe_fds[0], &set, sizeof(sigset_t)); if(ret != sizeof(sigset_t)) sigemptyset(&set); int return_value = 0; int sig; for(sig=1; sig < NSIG; ++sig) { if(sigismember(&set, sig)) { switch(sig) { case SIGINT: log_printf(NOTICE, "SIG-Int caught, exitting"); return_value = 1; break; case SIGQUIT: log_printf(NOTICE, "SIG-Quit caught, exitting"); return_value = 1; break; case SIGTERM: log_printf(NOTICE, "SIG-Term caught, exitting"); return_value = 1; break; case SIGHUP: log_printf(NOTICE, "SIG-Hup caught"); break; case SIGUSR1: log_printf(NOTICE, "SIG-Usr1 caught"); break; case SIGUSR2: log_printf(NOTICE, "SIG-Usr2 caught"); break; default: log_printf(WARNING, "unknown signal %d caught, ignoring", sig); break; } sigdelset(&set, sig); } } sigprocmask(SIG_SETMASK, &oldset, NULL); return return_value; } void signal_stop() { struct sigaction act; act.sa_handler = SIG_DFL; sigemptyset(&act.sa_mask); act.sa_flags = 0; sigaction(SIGINT, &act, NULL); sigaction(SIGQUIT, &act, NULL); sigaction(SIGTERM, &act, NULL); sigaction(SIGHUP, &act, NULL); sigaction(SIGUSR1, &act, NULL); sigaction(SIGUSR2, &act, NULL); close(sig_pipe_fds[0]); close(sig_pipe_fds[1]); } uanytun-0.3.3/src/cipher.h0000664000175000017500000000773311336622524015414 0ustar equinoxequinox/* * 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 methodes 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-2010 Christian Pointner * * 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 . */ #ifndef UANYTUN_cipher_h_INCLUDED #define UANYTUN_cipher_h_INCLUDED #ifndef NO_CRYPT #ifndef USE_SSL_CRYPTO #include #else #include #endif #include "key_derivation.h" #else enum key_derivation_dir_enum { kd_inbound = 0, kd_outbound = 1 }; typedef enum key_derivation_dir_enum key_derivation_dir_t; typedef u_int8_t key_derivation_t; #endif enum cipher_type_enum { c_unknown, c_null, c_aes_ctr }; typedef enum cipher_type_enum cipher_type_t; struct cipher_struct { cipher_type_t type_; u_int16_t key_length_; buffer_t key_; buffer_t salt_; void* params_; }; typedef struct cipher_struct cipher_t; int cipher_init(cipher_t* c, const char* type); void cipher_close(cipher_t* c); int cipher_encrypt(cipher_t* c, key_derivation_t* kd, key_derivation_dir_t dir, plain_packet_t* in, encrypted_packet_t* out, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux); int cipher_decrypt(cipher_t* c, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* in, plain_packet_t* out); int32_t cipher_null_crypt(u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen); #ifndef NO_CRYPT #define C_AESCTR_DEFAULT_KEY_LENGTH 128 #define C_AESCTR_CTR_LENGTH 16 #define C_AESCTR_SALT_LENGTH 14 union __attribute__((__packed__)) cipher_aesctr_ctr_union { u_int8_t buf_[C_AESCTR_CTR_LENGTH]; struct __attribute__ ((__packed__)) { u_int8_t buf_[C_AESCTR_SALT_LENGTH]; u_int16_t zero_; } salt_; struct __attribute__((__packed__)) { u_int8_t fill_[C_AESCTR_SALT_LENGTH - sizeof(mux_t) - sizeof(sender_id_t) - 2*sizeof(u_int8_t) - sizeof(seq_nr_t)]; mux_t mux_; sender_id_t sender_id_; u_int8_t empty_[2]; seq_nr_t seq_nr_; u_int16_t zero_; } params_; }; typedef union cipher_aesctr_ctr_union cipher_aesctr_ctr_t; struct cipher_aesctr_param_struct { #ifndef USE_SSL_CRYPTO gcry_cipher_hd_t handle_; #else AES_KEY aes_key_; u_int8_t ecount_buf_[AES_BLOCK_SIZE]; #endif cipher_aesctr_ctr_t ctr_; }; typedef struct cipher_aesctr_param_struct cipher_aesctr_param_t; int cipher_aesctr_init(cipher_t* c); void cipher_aesctr_close(cipher_t* c); int cipher_aesctr_calc_ctr(cipher_t* c, key_derivation_t* kd, key_derivation_dir_t dir, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux); int32_t cipher_aesctr_crypt(cipher_t* c, key_derivation_t* kd, key_derivation_dir_t dir, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux); #endif #endif uanytun-0.3.3/src/daemon.h0000664000175000017500000001104311336622524015372 0ustar equinoxequinox/* * 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 methodes 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-2010 Christian Pointner * * 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 . */ #ifndef UANYTUN_daemon_h_INCLUDED #define UANYTUN_daemon_h_INCLUDED #include #include #include #include #include #include #include struct priv_info_struct { struct passwd* pw_; struct group* gr_; }; typedef struct priv_info_struct priv_info_t; int priv_init(priv_info_t* priv, const char* username, const char* groupname) { if(!priv) return -1; priv->pw_ = NULL; priv->gr_ = NULL; priv->pw_ = getpwnam(username); if(!priv->pw_) { log_printf(ERROR, "unkown user %s", username); return -1; } if(groupname) priv->gr_ = getgrnam(groupname); else priv->gr_ = getgrgid(priv->pw_->pw_gid); if(!priv->gr_) { log_printf(ERROR, "unkown group %s", groupname); return -1; } return 0; } int priv_drop(priv_info_t* priv) { if(!priv || !priv->pw_ || !priv->gr_) { log_printf(ERROR, "privileges not initialized properly"); return -1; } if(setgid(priv->gr_->gr_gid)) { log_printf(ERROR, "setgid('%s') failed: %s", priv->gr_->gr_name, strerror(errno)); return -1; } gid_t gr_list[1]; gr_list[0] = priv->gr_->gr_gid; if(setgroups (1, gr_list)) { log_printf(ERROR, "setgroups(['%s']) failed: %s", priv->gr_->gr_name, strerror(errno)); return -1; } if(setuid(priv->pw_->pw_uid)) { log_printf(ERROR, "setuid('%s') failed: %s", priv->pw_->pw_name, strerror(errno)); return -1; } log_printf(NOTICE, "dropped privileges to %s:%s", priv->pw_->pw_name, priv->gr_->gr_name); return 0; } int do_chroot(const char* chrootdir) { if(getuid() != 0) { log_printf(ERROR, "this program has to be run as root in order to run in a chroot"); return -1; } if(chroot(chrootdir)) { log_printf(ERROR, "can't chroot to %s: %s", chrootdir, strerror(errno)); return -1; } log_printf(NOTICE, "we are in chroot jail (%s) now", chrootdir); if(chdir("/")) { log_printf(ERROR, "can't change to /: %s", strerror(errno)); return -1; } } void daemonize() { pid_t pid; pid = fork(); if(pid < 0) { log_printf(ERROR, "daemonizing failed at fork(): %s, exitting", strerror(errno)); exit(-1); } if(pid) exit(0); umask(0); if(setsid() < 0) { log_printf(ERROR, "daemonizing failed at setsid(): %s, exitting", strerror(errno)); exit(-1); } pid = fork(); if(pid < 0) { log_printf(ERROR, "daemonizing failed at fork(): %s, exitting", strerror(errno)); exit(-1); } if(pid) exit(0); if ((chdir("/")) < 0) { log_printf(ERROR, "daemonizing failed at chdir(): %s, exitting", strerror(errno)); exit(-1); } int fd; for (fd=0;fd<=2;fd++) // close all file descriptors close(fd); fd = open("/dev/null",O_RDWR); // stdin if(fd == -1) log_printf(WARNING, "can't open stdin (chroot and no link to /dev/null?)"); else { if(dup(fd) == -1) // stdout log_printf(WARNING, "can't open stdout"); if(dup(fd) == -1) // stderr log_printf(WARNING, "can't open stderr"); } umask(027); } #endif uanytun-0.3.3/src/tun.h0000664000175000017500000000512611336622524014742 0ustar equinoxequinox/* * 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 methodes 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-2010 Christian Pointner * * 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 . */ #ifndef UANYTUN_tun_h_INCLUDED #define UANYTUN_tun_h_INCLUDED #include enum device_type_enum { TYPE_UNDEF, TYPE_TUN, TYPE_TAP }; typedef enum device_type_enum device_type_t; struct tun_device_struct { int fd_; unsigned int with_pi_; char* actual_name_; device_type_t type_; u_int16_t mtu_; char* net_addr_; char* net_mask_; u_int16_t prefix_length_; }; typedef struct tun_device_struct tun_device_t; int tun_init(tun_device_t* dev, const char* dev_name, const char* dev_type, const char* ifcfg_addr, u_int16_t ifcfg_prefix); int tun_init_post(tun_device_t* dev); void tun_do_ifconfig(tun_device_t* dev); void tun_close(tun_device_t* dev); int tun_read(tun_device_t* dev, u_int8_t* buf, u_int32_t len); int tun_write(tun_device_t* dev, u_int8_t* buf, u_int32_t len); // in tun_helper.h void tun_conf(tun_device_t* dev, const char* dev_name, const char* dev_type, const char* ifcfg_addr, u_int16_t ifcfg_prefix, u_int16_t mtu); int tun_fix_return(int ret, size_t pi_length); const char* tun_get_type_string(tun_device_t* dev); #endif uanytun-0.3.3/src/key_derivation.c0000664000175000017500000003053211336622524017142 0ustar equinoxequinox/* * 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 methodes 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-2010 Christian Pointner * * 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 . */ #include "datatypes.h" #include "key_derivation.h" #ifdef USE_SSL_CRYPTO #include #endif #include "log.h" #include #include int key_derivation_init(key_derivation_t* kd, const char* type, role_t role, const char* passphrase, u_int8_t* key, u_int32_t key_len, u_int8_t* salt, u_int32_t salt_len) { if(!kd) return -1; kd->role_ = role; kd->key_length_ = 0; kd->type_ = kd_unknown; if(!strcmp(type, "null")) kd->type_ = kd_null; else if(!strncmp(type, "aes-ctr", 7)) { kd->type_ = kd_aes_ctr; if(type[7] == 0) { kd->key_length_ = KD_AESCTR_DEFAULT_KEY_LENGTH; } else if(type[7] != '-') return -1; else { const char* tmp = &type[8]; kd->key_length_ = atoi(tmp); } } else { log_printf(ERROR, "unknown key derivation type"); return -1; } switch(role) { case ROLE_LEFT: log_printf(NOTICE, "key derivation role: left"); break; case ROLE_RIGHT: log_printf(NOTICE, "key derivation role: right"); break; default: log_printf(NOTICE, "key derivation role: unknown"); break; } kd->params_ = NULL; if(!key) { kd->master_key_.buf_ = NULL; kd->master_key_.length_ = 0; } else { kd->master_key_.buf_ = malloc(key_len); if(!kd->master_key_.buf_) return -2; memcpy(kd->master_key_.buf_, key, key_len); kd->master_key_.length_ = key_len; } if(!salt) { kd->master_salt_.buf_ = NULL; kd->master_salt_.length_ = 0; } else { kd->master_salt_.buf_ = malloc(salt_len); if(!kd->master_salt_.buf_) { if(kd->master_key_.buf_) free(kd->master_key_.buf_); return -2; } memcpy(kd->master_salt_.buf_, salt, salt_len); kd->master_salt_.length_ = salt_len; } int ret = 0; if(kd->type_ == kd_aes_ctr) ret = key_derivation_aesctr_init(kd, passphrase); if(ret) key_derivation_close(kd); return ret; } #ifndef NO_PASSPHRASE int key_derivation_generate_master_key(key_derivation_t* kd, const char* passphrase, u_int16_t key_length) { if(!kd || !passphrase) return -1; if(kd->master_key_.buf_) { log_printf(WARNING, "master key and passphrase provided, ignoring passphrase"); return 0; } log_printf(NOTICE, "using passphrase to generate master key"); if(!key_length || (key_length % 8)) { log_printf(ERROR, "bad master key length"); return -1; } #ifndef USE_SSL_CRYPTO if(key_length > (gcry_md_get_algo_dlen(GCRY_MD_SHA256) * 8)) { #else if(key_length > (SHA256_DIGEST_LENGTH * 8)) { #endif log_printf(ERROR, "master key too long for passphrase algorithm"); return -1; } buffer_t digest; #ifndef USE_SSL_CRYPTO digest.length_ = gcry_md_get_algo_dlen(GCRY_MD_SHA256); #else digest.length_ = SHA256_DIGEST_LENGTH; #endif digest.buf_ = malloc(digest.length_); if(!digest.buf_) return -2; #ifndef USE_SSL_CRYPTO gcry_md_hash_buffer(GCRY_MD_SHA256, digest.buf_, passphrase, strlen(passphrase)); #else SHA256(passphrase, strlen(passphrase), digest.buf_); #endif kd->master_key_.length_ = key_length/8; kd->master_key_.buf_ = malloc(kd->master_key_.length_); if(!kd->master_key_.buf_) { kd->master_key_.length_ = 0; free(digest.buf_); return -2; } memcpy(kd->master_key_.buf_, &digest.buf_[digest.length_ - kd->master_key_.length_], kd->master_key_.length_); free(digest.buf_); return 0; } int key_derivation_generate_master_salt(key_derivation_t* kd, const char* passphrase, u_int16_t salt_length) { if(!kd || !passphrase) return -1; if(kd->master_salt_.buf_) { log_printf(WARNING, "master salt and passphrase provided, ignoring passphrase"); return 0; } log_printf(NOTICE, "using passphrase to generate master salt"); if(!salt_length || (salt_length % 8)) { log_printf(ERROR, "bad master salt length"); return -1; } #ifndef USE_SSL_CRYPTO if(salt_length > (gcry_md_get_algo_dlen(GCRY_MD_SHA1) * 8)) { #else if(salt_length > (SHA_DIGEST_LENGTH * 8)) { #endif log_printf(ERROR, "master salt too long for passphrase algorithm"); return -1; } buffer_t digest; #ifndef USE_SSL_CRYPTO digest.length_ = gcry_md_get_algo_dlen(GCRY_MD_SHA1); #else digest.length_ = SHA_DIGEST_LENGTH; #endif digest.buf_ = malloc(digest.length_); if(!digest.buf_) return -2; #ifndef USE_SSL_CRYPTO gcry_md_hash_buffer(GCRY_MD_SHA1, digest.buf_, passphrase, strlen(passphrase)); #else SHA1(passphrase, strlen(passphrase), digest.buf_); #endif kd->master_salt_.length_ = salt_length/8; kd->master_salt_.buf_ = malloc(kd->master_salt_.length_); if(!kd->master_salt_.buf_) { kd->master_salt_.length_ = 0; free(digest.buf_); return -2; } memcpy(kd->master_salt_.buf_, &digest.buf_[digest.length_ - kd->master_salt_.length_], kd->master_salt_.length_); free(digest.buf_); return 0; } #endif void key_derivation_close(key_derivation_t* kd) { if(!kd) return; if(kd->type_ == kd_aes_ctr) key_derivation_aesctr_close(kd); if(kd->master_key_.buf_) free(kd->master_key_.buf_); if(kd->master_salt_.buf_) free(kd->master_salt_.buf_); } int key_derivation_generate(key_derivation_t* kd, key_derivation_dir_t dir, satp_prf_label_t label, seq_nr_t seq_nr, u_int8_t* key, u_int32_t len) { if(!kd || !key) return -1; if(label >= LABEL_NIL) { log_printf(ERROR, "unknown label 0x%02X", label); return -1; } int ret = 0; if(kd->type_ == kd_null) ret = key_derivation_null_generate(key, len); else if(kd->type_ == kd_aes_ctr) ret = key_derivation_aesctr_generate(kd, dir, label, seq_nr, key, len); else { log_printf(ERROR, "unknown key derivation type"); return -1; } return ret; } satp_prf_label_t convert_label(role_t role, key_derivation_dir_t dir, satp_prf_label_t label) { switch(label) { case LABEL_ENC: { if(dir == kd_outbound) { if(role == ROLE_LEFT) return LABEL_LEFT_ENC; if(role == ROLE_RIGHT) return LABEL_RIGHT_ENC; } else { if(role == ROLE_LEFT) return LABEL_RIGHT_ENC; if(role == ROLE_RIGHT) return LABEL_LEFT_ENC; } break; } case LABEL_SALT: { if(dir == kd_outbound) { if(role == ROLE_LEFT) return LABEL_LEFT_SALT; if(role == ROLE_RIGHT) return LABEL_RIGHT_SALT; } else { if(role == ROLE_LEFT) return LABEL_RIGHT_SALT; if(role == ROLE_RIGHT) return LABEL_LEFT_SALT; } break; } case LABEL_AUTH: { if(dir == kd_outbound) { if(role == ROLE_LEFT) return LABEL_LEFT_AUTH; if(role == ROLE_RIGHT) return LABEL_RIGHT_AUTH; } else { if(role == ROLE_LEFT) return LABEL_RIGHT_AUTH; if(role == ROLE_RIGHT) return LABEL_LEFT_AUTH; } break; } } return label; } /* ---------------- NULL Key Derivation ---------------- */ int key_derivation_null_generate(u_int8_t* key, u_int32_t len) { memset(key, 0, len); return 1; } /* ---------------- AES-Ctr Key Derivation ---------------- */ int key_derivation_aesctr_init(key_derivation_t* kd, const char* passphrase) { if(!kd) return -1; if(kd->params_) free(kd->params_); kd->params_ = malloc(sizeof(key_derivation_aesctr_param_t)); if(!kd->params_) return -2; key_derivation_aesctr_param_t* params = kd->params_; #ifndef USE_SSL_CRYPTO params->handle_ = 0; #endif #ifndef NO_PASSPHRASE if(passphrase) { int ret = key_derivation_generate_master_key(kd, passphrase, kd->key_length_); if(ret) return ret; ret = key_derivation_generate_master_salt(kd, passphrase, KD_AESCTR_SALT_LENGTH*8); if(ret) return ret; } #endif #ifndef USE_SSL_CRYPTO int algo; switch(kd->key_length_) { case 128: algo = GCRY_CIPHER_AES128; break; case 192: algo = GCRY_CIPHER_AES192; break; case 256: algo = GCRY_CIPHER_AES256; break; default: { log_printf(ERROR, "key derivation key length of %d Bits is not supported", kd->key_length_); return -1; } } gcry_error_t err = gcry_cipher_open(¶ms->handle_, algo, GCRY_CIPHER_MODE_CTR, 0); if(err) { log_printf(ERROR, "failed to open key derivation cipher: %s", gcry_strerror(err)); return -1; } err = gcry_cipher_setkey(params->handle_, kd->master_key_.buf_, kd->master_key_.length_); if(err) { log_printf(ERROR, "failed to set key derivation key: %s", gcry_strerror(err)); return -1; } #else int ret = AES_set_encrypt_key(kd->master_key_.buf_, kd->master_key_.length_*8, ¶ms->aes_key_); if(ret) { log_printf(ERROR, "failed to set key derivation ssl aes-key (code: %d)", ret); return -1; } #endif return 0; } void key_derivation_aesctr_close(key_derivation_t* kd) { if(!kd) return; if(kd->params_) { key_derivation_aesctr_param_t* params = kd->params_; #ifndef USE_SSL_CRYPTO if(params->handle_) gcry_cipher_close(params->handle_); #endif free(kd->params_); } } int key_derivation_aesctr_calc_ctr(key_derivation_t* kd, key_derivation_dir_t dir, satp_prf_label_t label, seq_nr_t seq_nr) { if(!kd || !kd->params_) return -1; key_derivation_aesctr_param_t* params = kd->params_; if(kd->master_salt_.length_ != KD_AESCTR_SALT_LENGTH) { log_printf(ERROR, "master salt has wrong length"); return -1; } memcpy(params->ctr_.salt_.buf_, kd->master_salt_.buf_, KD_AESCTR_SALT_LENGTH); params->ctr_.salt_.zero_ = 0; params->ctr_.params_.label_ ^= SATP_PRF_LABEL_T_HTON(convert_label(kd->role_, dir, label)); params->ctr_.params_.seq_ ^= SEQ_NR_T_HTON(seq_nr); return 0; } int key_derivation_aesctr_generate(key_derivation_t* kd, key_derivation_dir_t dir, satp_prf_label_t label, seq_nr_t seq_nr, u_int8_t* key, u_int32_t len) { if(!kd || !kd->params_ || !kd->master_key_.buf_ || !kd->master_salt_.buf_) { log_printf(ERROR, "key derivation not initialized or no key or salt set"); return -1; } key_derivation_aesctr_param_t* params = kd->params_; if(key_derivation_aesctr_calc_ctr(kd, dir, label, seq_nr)) { log_printf(ERROR, "failed to calculate key derivation CTR"); return -1; } #ifndef USE_SSL_CRYPTO gcry_error_t err = gcry_cipher_reset(params->handle_); if(err) { log_printf(ERROR, "failed to reset key derivation cipher: %s", gcry_strerror(err)); return -1; } err = gcry_cipher_setctr(params->handle_, params->ctr_.buf_, KD_AESCTR_CTR_LENGTH); if(err) { log_printf(ERROR, "failed to set key derivation CTR: %s", gcry_strerror(err)); return -1; } memset(key, 0, len); err = gcry_cipher_encrypt(params->handle_, key, len, NULL, 0); if(err) { log_printf(ERROR, "failed to generate key derivation bitstream: %s", gcry_strerror(err)); return -1; } #else if(KD_AESCTR_CTR_LENGTH != AES_BLOCK_SIZE) { log_printf(ERROR, "failed to set key derivation CTR: size don't fits"); return -1; } u_int32_t num = 0; memset(params->ecount_buf_, 0, AES_BLOCK_SIZE); memset(key, 0, len); AES_ctr128_encrypt(key, key, len, ¶ms->aes_key_, params->ctr_.buf_, params->ecount_buf_, &num); #endif return 0; } uanytun-0.3.3/src/encrypted_packet.h0000664000175000017500000000714011336622524017456 0ustar equinoxequinox/* * 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 methodes 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-2010 Christian Pointner * * 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 . */ #ifndef UANYTUN_encrypted_packet_h_INCLUDED #define UANYTUN_encrypted_packet_h_INCLUDED #define ENCRYPTED_PACKET_SIZE_MAX 1600 #define PAYLOAD_TYPE_TAP 0x6558 #define PAYLOAD_TYPE_TUN 0x0000 #define PAYLOAD_TYPE_TUN4 0x0800 #define PAYLOAD_TYPE_TUN6 0x86DD struct __attribute__ ((__packed__)) encrypted_packet_header_struct { seq_nr_t seq_nr_; sender_id_t sender_id_; mux_t mux_; }; typedef struct encrypted_packet_header_struct encrypted_packet_header_t; struct encrypted_packet_struct { u_int32_t payload_length_; u_int32_t auth_tag_length_; union __attribute__ ((__packed__)) { u_int8_t buf_[ENCRYPTED_PACKET_SIZE_MAX]; encrypted_packet_header_t header_; } data_; }; typedef struct encrypted_packet_struct encrypted_packet_t; void encrypted_packet_init(encrypted_packet_t* packet, u_int32_t auth_tag_length); u_int32_t encrypted_packet_get_minimum_length(encrypted_packet_t* packet); u_int8_t* encrypted_packet_get_packet(encrypted_packet_t* packet); u_int32_t encrypted_packet_get_length(encrypted_packet_t* packet); void encrypted_packet_set_length(encrypted_packet_t* packet, u_int32_t len); u_int8_t* encrypted_packet_get_payload(encrypted_packet_t* packet); u_int32_t encrypted_packet_get_payload_length(encrypted_packet_t* packet); void encrypted_packet_set_payload_length(encrypted_packet_t* packet, u_int32_t len); u_int8_t* encrypted_packet_get_auth_portion(encrypted_packet_t* packet); u_int32_t encrypted_packet_get_auth_portion_length(encrypted_packet_t* packet); u_int8_t* encrypted_packet_get_auth_tag(encrypted_packet_t* packet); u_int32_t encrypted_packet_get_auth_tag_length(encrypted_packet_t* packet); seq_nr_t encrypted_packet_get_seq_nr(encrypted_packet_t* packet); void encrypted_packet_set_seq_nr(encrypted_packet_t* packet, seq_nr_t seq_nr); sender_id_t encrypted_packet_get_sender_id(encrypted_packet_t* packet); void encrypted_packet_set_sender_id(encrypted_packet_t* packet, sender_id_t sender_id); mux_t encrypted_packet_get_mux(encrypted_packet_t* packet); void encrypted_packet_set_mux(encrypted_packet_t* packet, mux_t mux); #endif uanytun-0.3.3/src/bsd/0000775000175000017500000000000011336622533014527 5ustar equinoxequinoxuanytun-0.3.3/src/bsd/tun.c0000664000175000017500000002023711336622524015505 0ustar equinoxequinox/* * 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 methodes 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-2010 Christian Pointner * * 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 . */ #include "datatypes.h" #include "tun.h" #include "tun_helper.h" #include "log.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #define DEVICE_FILE_MAX 255 int tun_init(tun_device_t* dev, const char* dev_name, const char* dev_type, const char* ifcfg_addr, u_int16_t ifcfg_prefix) { if(!dev) return -1; tun_conf(dev, dev_name, dev_type, ifcfg_addr, ifcfg_prefix, 1400); dev->actual_name_ = NULL; char* device_file = NULL; char* actual_name_start = NULL; int dynamic = 1; if(dev_name) { asprintf(&device_file, "/dev/%s", dev_name); dynamic = 0; } #if defined(__GNUC__) && defined(__OpenBSD__) else if(dev->type_ == TYPE_TUN || dev->type_ == TYPE_TAP) { asprintf(&device_file, "/dev/tun"); actual_name_start = "tun"; } #else else if(dev->type_ == TYPE_TUN) { asprintf(&device_file, "/dev/tun"); actual_name_start = "tun"; } else if(dev->type_ == TYPE_TAP) { asprintf(&device_file, "/dev/tap"); actual_name_start = "tap"; } #endif else { log_printf(ERROR, "unable to recognize type of device (tun or tap)"); tun_close(dev); return -1; } if(!device_file) { log_printf(ERROR, "can't open device file: memory error"); tun_close(dev); return -2; } u_int32_t dev_id=0; if(dynamic) { for(; dev_id <= DEVICE_FILE_MAX; ++dev_id) { char* device_file_tmp = NULL; asprintf(&device_file_tmp, "%s%d", device_file, dev_id); if(!device_file_tmp) { log_printf(ERROR, "can't open device file: memory error"); free(device_file); tun_close(dev); return -2; } dev->fd_ = open(device_file_tmp, O_RDWR); free(device_file_tmp); if(dev->fd_ >= 0) break; } } else dev->fd_ = open(device_file, O_RDWR); free(device_file); if(dev->fd_ < 0) { if(dynamic) log_printf(ERROR, "can't open device file dynamically: no unused node left"); else log_printf(ERROR, "can't open device file (%s): %s", device_file, strerror(errno)); tun_close(dev); return -1; } if(dynamic) asprintf(&(dev->actual_name_), "%s%d", actual_name_start, dev_id); else dev->actual_name_ = strdup(dev_name); if(!dev->actual_name_) { log_printf(ERROR, "can't open device file: memory error"); tun_close(dev); return -2; } int ret = tun_init_post(dev); if(ret) { tun_close(dev); return ret; } if(ifcfg_addr) tun_do_ifconfig(dev); return 0; } #if defined(__GNUC__) && defined(__OpenBSD__) int tun_init_post(tun_device_t* dev) { if(!dev) return -1; dev->with_pi_ = 1; if(dev->type_ == TYPE_TAP) dev->with_pi_ = 0; struct tuninfo ti; if(ioctl(dev->fd_, TUNGIFINFO, &ti) < 0) { log_printf(ERROR, "can't enable multicast for interface: %s", strerror(errno)); return -1; } ti.flags |= IFF_MULTICAST; if(dev->type_ == TYPE_TUN) ti.flags &= ~IFF_POINTOPOINT; if(ioctl(dev->fd_, TUNSIFINFO, &ti) < 0) { log_printf(ERROR, "can't enable multicast for interface: %s", strerror(errno)); return -1; } return 0; } #elif defined(__GNUC__) && (defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) int tun_init_post(tun_device_t* dev) { if(!dev) return -1; dev->with_pi_ = 1; if(dev->type_ == TYPE_TAP) dev->with_pi_ = 0; if(dev->type_ == TYPE_TUN) { int arg = 0; if(ioctl(dev->fd_, TUNSLMODE, &arg) < 0) { log_printf(ERROR, "can't disable link-layer mode for interface: %s", strerror(errno)); return -1; } arg = 1; if(ioctl(dev->fd_, TUNSIFHEAD, &arg) < 0) { log_printf(ERROR, "can't enable multi-af mode for interface: %s", strerror(errno)); return -1; } arg = IFF_BROADCAST; arg |= IFF_MULTICAST; if(ioctl(dev->fd_, TUNSIFMODE, &arg) < 0) { log_printf(ERROR, "can't enable multicast for interface: %s", strerror(errno)); return -1; } } return 0; } #elif defined(__GNUC__) && defined(__NetBSD__) #warning this device has never been tested on NetBSD and might not work int tun_init_post(tun_device_t* dev) { if(!dev) return -1; dev->with_pi_ = 0; int arg = IFF_POINTOPOINT|IFF_MULTICAST; ioctl(dev->fd_, TUNSIFMODE, &arg); arg = 0; ioctl(dev->fd_, TUNSLMODE, &arg); return 0; } #else #error This Device works just for OpenBSD, FreeBSD or NetBSD #endif void tun_close(tun_device_t* dev) { if(!dev) return; if(dev->fd_ > 0) close(dev->fd_); if(dev->actual_name_) free(dev->actual_name_); if(dev->net_addr_) free(dev->net_addr_); if(dev->net_mask_) free(dev->net_mask_); } int tun_read(tun_device_t* dev, u_int8_t* buf, u_int32_t len) { if(!dev || dev->fd_ < 0) return -1; if(dev->with_pi_) { struct iovec iov[2]; u_int32_t type; iov[0].iov_base = &type; iov[0].iov_len = sizeof(type); iov[1].iov_base = buf; iov[1].iov_len = len; return(tun_fix_return(readv(dev->fd_, iov, 2), sizeof(type))); } else return(read(dev->fd_, buf, len)); } int tun_write(tun_device_t* dev, u_int8_t* buf, u_int32_t len) { if(!dev || dev->fd_ < 0) return -1; if(!buf) return 0; if(dev->with_pi_) { struct iovec iov[2]; u_int32_t type; struct ip *hdr = (struct ip*)buf; type = 0; if(hdr->ip_v == 4) type = htonl(AF_INET); else type = htonl(AF_INET6); iov[0].iov_base = &type; iov[0].iov_len = sizeof(type); iov[1].iov_base = buf; iov[1].iov_len = len; return(tun_fix_return(writev(dev->fd_, iov, 2), sizeof(type))); } else return(write(dev->fd_, buf, len)); } void tun_do_ifconfig(tun_device_t* dev) { if(!dev || !dev->actual_name_ || !dev->net_addr_ || !dev->net_mask_) return; char* end; if(dev->type_ == TYPE_TAP) { #if defined(__GNUC__) && defined(__OpenBSD__) end = "link0"; #elif defined(__GNUC__) && (defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) end = "up"; #elif defined(__GNUC__) && defined(__NetBSD__) end = NULL; #else #error This Device works just for OpenBSD, FreeBSD or NetBSD #endif } else end = "up"; char* mtu_str = NULL; asprintf(&mtu_str, "%d", dev->mtu_); if(!mtu_str) { log_printf(ERROR, "Execution of ifconfig failed"); return; } char* const argv[] = { "/sbin/ifconfig", dev->actual_name_, dev->net_addr_, "netmask", dev->net_mask_, "mtu", mtu_str, end, NULL }; char* const evp[] = { NULL }; uanytun_exec("/sbin/ifconfig", argv, evp); free(mtu_str); } uanytun-0.3.3/src/encrypted_packet.c0000664000175000017500000001241011336622524017445 0ustar equinoxequinox/* * 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 methodes 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-2010 Christian Pointner * * 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 . */ #include "datatypes.h" #include "encrypted_packet.h" #include #include void encrypted_packet_init(encrypted_packet_t* packet, u_int32_t auth_tag_length) { if(!packet) return; memset (packet, 0, sizeof(*packet)); if(auth_tag_length > (ENCRYPTED_PACKET_SIZE_MAX - sizeof(encrypted_packet_header_t))) packet->auth_tag_length_ = ENCRYPTED_PACKET_SIZE_MAX - sizeof(encrypted_packet_header_t); else packet->auth_tag_length_ = auth_tag_length; } u_int32_t encrypted_packet_get_minimum_length(encrypted_packet_t* packet) { if(!packet) return 0; return (sizeof(encrypted_packet_header_t) + packet->auth_tag_length_); } u_int8_t* encrypted_packet_get_packet(encrypted_packet_t* packet) { if(!packet) return NULL; return packet->data_.buf_; } u_int32_t encrypted_packet_get_length(encrypted_packet_t* packet) { if(!packet) return 0; return (packet->payload_length_ + sizeof(encrypted_packet_header_t) + packet->auth_tag_length_); } void encrypted_packet_set_length(encrypted_packet_t* packet, u_int32_t len) { if(!packet) return; if(len > ENCRYPTED_PACKET_SIZE_MAX) len = ENCRYPTED_PACKET_SIZE_MAX - sizeof(encrypted_packet_header_t) - packet->auth_tag_length_; else if(len < (sizeof(encrypted_packet_header_t) + packet->auth_tag_length_)) len = 0; else len -= (sizeof(encrypted_packet_header_t) + packet->auth_tag_length_); packet->payload_length_ = len; } u_int8_t* encrypted_packet_get_payload(encrypted_packet_t* packet) { if(!packet || !packet->payload_length_) return NULL; return (packet->data_.buf_ + sizeof(encrypted_packet_header_t)); } u_int32_t encrypted_packet_get_payload_length(encrypted_packet_t* packet) { if(!packet) return 0; return packet->payload_length_; } void encrypted_packet_set_payload_length(encrypted_packet_t* packet, u_int32_t len) { if(!packet) return; if(len > (ENCRYPTED_PACKET_SIZE_MAX - sizeof(encrypted_packet_header_t) - packet->auth_tag_length_)) len = ENCRYPTED_PACKET_SIZE_MAX - sizeof(encrypted_packet_header_t) - packet->auth_tag_length_; packet->payload_length_ = len; } u_int8_t* encrypted_packet_get_auth_portion(encrypted_packet_t* packet) { if(!packet) return NULL; return packet->data_.buf_; } u_int32_t encrypted_packet_get_auth_portion_length(encrypted_packet_t* packet) { if(!packet) return 0; return packet->payload_length_ + sizeof(encrypted_packet_header_t); } u_int8_t* encrypted_packet_get_auth_tag(encrypted_packet_t* packet) { if(!packet || !packet->auth_tag_length_) return NULL; return (packet->data_.buf_ + sizeof(encrypted_packet_header_t) + packet->payload_length_); } u_int32_t encrypted_packet_get_auth_tag_length(encrypted_packet_t* packet) { if(!packet) return 0; return packet->auth_tag_length_; } seq_nr_t encrypted_packet_get_seq_nr(encrypted_packet_t* packet) { if(!packet) return 0; return SEQ_NR_T_NTOH(packet->data_.header_.seq_nr_); } void encrypted_packet_set_seq_nr(encrypted_packet_t* packet, seq_nr_t seq_nr) { if(!packet) return; packet->data_.header_.seq_nr_ = SEQ_NR_T_HTON(seq_nr); } sender_id_t encrypted_packet_get_sender_id(encrypted_packet_t* packet) { if(!packet) return 0; return SENDER_ID_T_NTOH(packet->data_.header_.sender_id_); } void encrypted_packet_set_sender_id(encrypted_packet_t* packet, sender_id_t sender_id) { if(!packet) return; packet->data_.header_.sender_id_ = SENDER_ID_T_HTON(sender_id); } mux_t encrypted_packet_get_mux(encrypted_packet_t* packet) { if(!packet) return 0; return MUX_T_NTOH(packet->data_.header_.mux_); } void encrypted_packet_set_mux(encrypted_packet_t* packet, mux_t mux) { if(!packet) return; packet->data_.header_.mux_ = MUX_T_HTON(mux); } uanytun-0.3.3/src/cipher.c0000664000175000017500000002153711336622524015405 0ustar equinoxequinox/* * 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 methodes 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-2010 Christian Pointner * * 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 . */ #include "datatypes.h" #include "plain_packet.h" #include "encrypted_packet.h" #include "cipher.h" #include "log.h" #include #include int cipher_init(cipher_t* c, const char* type) { if(!c) return -1; c->key_length_ = 0; c->type_ = c_unknown; if(!strcmp(type, "null")) c->type_ = c_null; #ifndef NO_CRYPT else if(!strncmp(type, "aes-ctr", 7)) { c->type_ = c_aes_ctr; if(type[7] == 0) { c->key_length_ = C_AESCTR_DEFAULT_KEY_LENGTH; } else if(type[7] != '-') return -1; else { const char* tmp = &type[8]; c->key_length_ = atoi(tmp); } } #endif else { log_printf(ERROR, "unknown cipher type"); return -1; } c->params_ = NULL; c->key_.buf_ = NULL; c->key_.length_ = 0; c->salt_.buf_ = NULL; c->salt_.length_ = 0; int ret = 0; #ifndef NO_CRYPT if(c->type_ == c_aes_ctr) ret = cipher_aesctr_init(c); #endif if(ret) cipher_close(c); return ret; } void cipher_close(cipher_t* c) { if(!c) return; #ifndef NO_CRYPT if(c->type_ == c_aes_ctr) cipher_aesctr_close(c); #endif if(c->key_.buf_) free(c->key_.buf_); if(c->salt_.buf_) free(c->salt_.buf_); } int cipher_encrypt(cipher_t* c, key_derivation_t* kd, key_derivation_dir_t dir, plain_packet_t* in, encrypted_packet_t* out, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux) { if(!c) return -1; int32_t len; if(c->type_ == c_null) len = cipher_null_crypt(plain_packet_get_packet(in), plain_packet_get_length(in), encrypted_packet_get_payload(out), encrypted_packet_get_payload_length(out)); #ifndef NO_CRYPT else if(c->type_ == c_aes_ctr) len = cipher_aesctr_crypt(c, kd, dir, plain_packet_get_packet(in), plain_packet_get_length(in), encrypted_packet_get_payload(out), encrypted_packet_get_payload_length(out), seq_nr, sender_id, mux); #endif else { log_printf(ERROR, "unknown cipher type"); return -1; } if(len < 0) return 0; encrypted_packet_set_sender_id(out, sender_id); encrypted_packet_set_seq_nr(out, seq_nr); encrypted_packet_set_mux(out, mux); encrypted_packet_set_payload_length(out, len); return 0; } int cipher_decrypt(cipher_t* c, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* in, plain_packet_t* out) { if(!c) return -1; int32_t len; if(c->type_ == c_null) len = cipher_null_crypt(encrypted_packet_get_payload(in), encrypted_packet_get_payload_length(in), plain_packet_get_packet(out), plain_packet_get_length(out)); #ifndef NO_CRYPT else if(c->type_ == c_aes_ctr) len = cipher_aesctr_crypt(c, kd, dir, encrypted_packet_get_payload(in), encrypted_packet_get_payload_length(in), plain_packet_get_packet(out), plain_packet_get_length(out), encrypted_packet_get_seq_nr(in), encrypted_packet_get_sender_id(in), encrypted_packet_get_mux(in)); #endif else { log_printf(ERROR, "unknown cipher type"); return -1; } if(len < 0) return 0; plain_packet_set_length(out, len); return 0; } /* ---------------- NULL Cipher ---------------- */ int32_t cipher_null_crypt(u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen) { memcpy(out, in, (ilen < olen) ? ilen : olen); return (ilen < olen) ? ilen : olen; } #ifndef NO_CRYPT /* ---------------- AES-Ctr Cipher ---------------- */ int cipher_aesctr_init(cipher_t* c) { if(!c) return -1; if(c->key_.buf_) free(c->key_.buf_); c->key_.length_ = c->key_length_/8; c->key_.buf_ = malloc(c->key_.length_); if(!c->key_.buf_) return -2; if(c->salt_.buf_) free(c->salt_.buf_); c->salt_.length_ = C_AESCTR_SALT_LENGTH; c->salt_.buf_ = malloc(c->salt_.length_); if(!c->salt_.buf_) return -2; if(c->params_) free(c->params_); c->params_ = malloc(sizeof(cipher_aesctr_param_t)); if(!c->params_) return -2; cipher_aesctr_param_t* params = c->params_; #ifndef USE_SSL_CRYPTO int algo; switch(c->key_length_) { case 128: algo = GCRY_CIPHER_AES128; break; case 192: algo = GCRY_CIPHER_AES192; break; case 256: algo = GCRY_CIPHER_AES256; break; default: { log_printf(ERROR, "cipher key length of %d Bits is not supported", c->key_length_); return -1; } } gcry_error_t err = gcry_cipher_open(¶ms->handle_, algo, GCRY_CIPHER_MODE_CTR, 0); if(err) { log_printf(ERROR, "failed to open cipher: %s", gcry_strerror(err)); return -1; } #endif return 0; } void cipher_aesctr_close(cipher_t* c) { if(!c) return; if(c->params_) { cipher_aesctr_param_t* params = c->params_; #ifndef USE_SSL_CRYPTO if(params->handle_) gcry_cipher_close(params->handle_); #endif free(c->params_); } } int cipher_aesctr_calc_ctr(cipher_t* c, key_derivation_t* kd, key_derivation_dir_t dir, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux) { if(!c || !c->params_) return -1; cipher_aesctr_param_t* params = c->params_; int ret = key_derivation_generate(kd, dir, LABEL_SALT, seq_nr, c->salt_.buf_, C_AESCTR_SALT_LENGTH); if(ret < 0) return ret; memcpy(params->ctr_.salt_.buf_, c->salt_.buf_, C_AESCTR_SALT_LENGTH); params->ctr_.salt_.zero_ = 0; params->ctr_.params_.mux_ ^= MUX_T_HTON(mux); params->ctr_.params_.sender_id_ ^= SENDER_ID_T_HTON(sender_id); params->ctr_.params_.seq_nr_ ^= SEQ_NR_T_HTON(seq_nr); return 0; } int32_t cipher_aesctr_crypt(cipher_t* c, key_derivation_t* kd, key_derivation_dir_t dir, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux) { if(!c || !c->params_) { log_printf(ERROR, "cipher not initialized"); return -1; } if(!kd) { log_printf(ERROR, "no key derivation supplied"); return -1; } cipher_aesctr_param_t* params = c->params_; int ret = key_derivation_generate(kd, dir, LABEL_ENC, seq_nr, c->key_.buf_, c->key_.length_); if(ret < 0) return ret; #ifdef USE_SSL_CRYPTO ret = AES_set_encrypt_key(c->key_.buf_, c->key_length_, ¶ms->aes_key_); if(ret) { log_printf(ERROR, "failed to set cipher ssl aes-key (code: %d)", ret); return -1; } #else gcry_error_t err = gcry_cipher_setkey(params->handle_, c->key_.buf_, c->key_.length_); if(err) { log_printf(ERROR, "failed to set cipher key: %s", gcry_strerror(err)); return -1; } #endif ret = cipher_aesctr_calc_ctr(c, kd, dir, seq_nr, sender_id, mux); if(ret < 0) { log_printf(ERROR, "failed to calculate cipher CTR"); return ret; } #ifndef USE_SSL_CRYPTO err = gcry_cipher_setctr(params->handle_, params->ctr_.buf_, C_AESCTR_CTR_LENGTH); if(err) { log_printf(ERROR, "failed to set cipher CTR: %s", gcry_strerror(err)); return -1; } err = gcry_cipher_encrypt(params->handle_, out, olen, in, ilen); if(err) { log_printf(ERROR, "failed to de/encrypt packet: %s", gcry_strerror(err)); return -1; } #else if(C_AESCTR_CTR_LENGTH != AES_BLOCK_SIZE) { log_printf(ERROR, "failed to set cipher CTR: size don't fits"); return -1; } u_int32_t num = 0; memset(params->ecount_buf_, 0, AES_BLOCK_SIZE); AES_ctr128_encrypt(in, out, (ilen < olen) ? ilen : olen, ¶ms->aes_key_, params->ctr_.buf_, params->ecount_buf_, &num); #endif return (ilen < olen) ? ilen : olen; } #endif uanytun-0.3.3/src/configure0000775000175000017500000001377211336622524015700 0ustar equinoxequinox#!/bin/sh # # 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 methodes 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-2010 Christian Pointner # # 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 . # TARGET=`uname -s` EBUILD_COMPAT=0 CFLAGS='-g -O2' LDFLAGS='-g -Wall -O2' CRYPTO_LIB='gcrypt' PASSPHRASE=1 PREFIX='/usr/local' SBINDIR='' ETCDIR='' MANDIR='' INSTALLMANPAGE=1 EXAMPLESDIR='' INSTALLEXAMPLES=1 print_usage() { echo "configure --help print this" echo " --target= build target i.e. Linux (default: autodetect)" echo " --prefix= the installation prefix (default: /usr/local)" echo " --sbindir= the path to the sbin directory (default: $PREFIX/sbin)" echo " --sysconfdir= the path to the system configuration directory (default: $PREFIX/etc" echo " --mandir= the path to the system man pages (default: $PREFIX/share/man)" echo " --no-manpage dont't install manpage" echo " --examplesdir= the path to the examples files (default: $PREFIX/share/examples)" echo " --no-examples dont't install example files" echo " --use-ssl-crypto use ssl crypto library instead of libgcrypt" echo " --no-crypto disable crypto at all (only NULL cipher)" echo " --disable-passphrase disable master key and salt passphrase" echo " --enable-passphrase enable master key and salt passphrase" } for arg do case $arg in --target=*) TARGET=${arg#--target=} ;; --prefix=*) PREFIX=${arg#--prefix=} ;; --sbindir=*) SBINDIR=${arg#--sbindir=} ;; --sysconfdir=*) ETCDIR=${arg#--sysconfdir=} ;; --mandir=*) MANDIR=${arg#--mandir=} ;; --no-manpage) INSTALLMANPAGE=0 ;; --examplesdir=*) EXAMPLESDIR=${arg#--examplesdir=} ;; --no-examples) INSTALLEXAMPLES=0 ;; --use-ssl-crypto) CRYPTO_LIB='ssl' ;; --no-crypto) CRYPTO_LIB='none' ;; --disable-passphrase) PASSPHRASE=0 ;; --enable-passphrase) PASSPHRASE=1 ;; --ebuild-compat) EBUILD_COMPAT=1 ;; --help) print_usage exit 0 ;; *) ERRORS="$ERRORS $arg" ;; esac done if [ -n "$ERRORS" ] && [ $EBUILD_COMPAT -ne 1 ]; then for error in $ERRORS; do echo "Unknown argument: $error" done print_usage exit 1 fi rm -f version.h rm -f include.mk case $TARGET in Linux) rm -f tun.c ln -sf linux/tun.c echo "loading Linux specific TUN Device" ;; OpenBSD|FreeBSD|NetBSD|GNU/kFreeBSD) rm -f tun.c ln -sf bsd/tun.c echo "loading BSD specific TUN Device" CFLAGS=$CFLAGS' -I/usr/local/include' LDFLAGS=$LDFLAGS' -L/usr/local/lib' ;; *) echo "platform not supported" exit 1; ;; esac case $CRYPTO_LIB in gcrypt) LDFLAGS=$LDFLAGS' -lgcrypt' echo "using libgcrypt library" ;; ssl) CFLAGS=$CFLAGS' -DUSE_SSL_CRYPTO' LDFLAGS=$LDFLAGS' -lcrypto' echo "using ssl crypto library" ;; none) CFLAGS=$CFLAGS' -DNO_CRYPT' echo "NO_CRYPT_OBJ = 1" >> include.mk echo "disabling crypto" ;; esac if [ $PASSPHRASE -eq 0 ]; then CFLAGS=$CFLAGS' -DNO_PASSPHRASE' echo "disabling master key and salt passphrase" fi if [ -z "$SBINDIR" ]; then SBINDIR=$PREFIX/sbin fi if [ -z "$ETCDIR" ]; then ETCDIR=$PREFIX/etc fi if [ -z "$MANDIR" ]; then MANDIR=$PREFIX/share/man fi if [ -z "$EXAMPLESDIR" ]; then EXAMPLESDIR=$PREFIX/share/examples fi cat >> include.mk <> include.mk echo "installing manpage" else echo "not installing manpage" fi if [ $INSTALLEXAMPLES -eq 1 ]; then echo "EXAMPLESDIR := $EXAMPLESDIR" >> include.mk echo "installing example files" else echo "not installing example files" fi VERSION=`cat ../version` if which svn >/dev/null; then SVN_REV=`svn info | grep "^Revision: " | awk '{print($2)}'` if [ -n "$SVN_REV" ]; then VERSION="$VERSION (svn$SVN_REV)" fi fi HOSTNAME=`hostname` DATE=`date +"%d.%m.%Y %H:%M:%S %Z"` cat >> version.h < * * 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 . */ #ifndef UANYTUN_sysexec_h_INCLUDED #define UANYTUN_sysexec_h_INCLUDED int uanytun_exec(const char* script, char* const argv[], char* const evp[]); #endif uanytun-0.3.3/src/datatypes.h0000664000175000017500000000511111336622524016124 0ustar equinoxequinox/* * 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 methodes 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-2010 Christian Pointner * * 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 . */ #ifndef UANYTUN_datatypes_h_INCLUDED #define UANYTUN_datatypes_h_INCLUDED #include #include typedef uint8_t u_int8_t; typedef uint16_t u_int16_t; typedef uint32_t u_int32_t; typedef uint64_t u_int64_t; /* typedef int8_t int8_t; */ /* typedef int16_t int16_t; */ /* typedef int32_t int32_t; */ /* typedef int64_t int64_t; */ typedef u_int32_t window_size_t; typedef u_int32_t seq_nr_t; #define SEQ_NR_T_NTOH(a) ntohl(a) #define SEQ_NR_T_HTON(a) htonl(a) #define SEQ_NR_MAX UINT32_MAX typedef u_int16_t sender_id_t; #define SENDER_ID_T_NTOH(a) ntohs(a) #define SENDER_ID_T_HTON(a) htons(a) typedef u_int16_t payload_type_t; #define PAYLOAD_TYPE_T_NTOH(a) ntohs(a) #define PAYLOAD_TYPE_T_HTON(a) htons(a) typedef u_int16_t mux_t; #define MUX_T_NTOH(a) ntohs(a) #define MUX_T_HTON(a) htons(a) typedef u_int32_t satp_prf_label_t; #define SATP_PRF_LABEL_T_NTOH(a) ntohl(a) #define SATP_PRF_LABEL_T_HTON(a) htonl(a) struct buffer_struct { u_int32_t length_; u_int8_t* buf_; }; typedef struct buffer_struct buffer_t; #endif uanytun-0.3.3/src/string_list.h0000664000175000017500000000420211336622524016467 0ustar equinoxequinox/* * 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 methodes 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-2010 Christian Pointner * * 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 . */ #ifndef UANYTUN_string_list_h_INCLUDED #define UANYTUN_string_list_h_INCLUDED struct string_list_element_struct { char* string_; struct string_list_element_struct* next_; }; typedef struct string_list_element_struct string_list_element_t; struct string_list_struct { string_list_element_t* first_; }; typedef struct string_list_struct string_list_t; void string_list_init(string_list_t* list); void string_list_clear(string_list_t* list); int string_list_add(string_list_t* list, const char* string); void string_list_print(string_list_t* list, const char* head, const char* tail); #endif uanytun-0.3.3/src/plain_packet.c0000664000175000017500000000756211336622524016567 0ustar equinoxequinox/* * 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 methodes 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-2010 Christian Pointner * * 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 . */ #include "datatypes.h" #include "plain_packet.h" #include #include #include #include #include #include void plain_packet_init(plain_packet_t* packet) { if(!packet) return; memset (packet, 0, sizeof(*packet)); } u_int32_t plain_packet_get_header_length() { return sizeof(payload_type_t); } u_int8_t* plain_packet_get_packet(plain_packet_t* packet) { if(!packet) return NULL; return packet->data_.buf_; } u_int32_t plain_packet_get_length(plain_packet_t* packet) { if(!packet) return 0; return (packet->payload_length_ + sizeof(payload_type_t)); } void plain_packet_set_length(plain_packet_t* packet, u_int32_t len) { if(!packet) return; if(len > PLAIN_PACKET_SIZE_MAX) len = PLAIN_PACKET_SIZE_MAX - sizeof(payload_type_t); else if(len < sizeof(payload_type_t)) len = 0; else len -= sizeof(payload_type_t); packet->payload_length_ = len; } u_int8_t* plain_packet_get_payload(plain_packet_t* packet) { if(!packet || !packet->payload_length_) return NULL; return (packet->data_.buf_ + sizeof(payload_type_t)); } u_int32_t plain_packet_get_payload_length(plain_packet_t* packet) { if(!packet) return 0; return packet->payload_length_; } void plain_packet_set_payload_length(plain_packet_t* packet, u_int32_t len) { if(!packet) return; if(len > PLAIN_PACKET_SIZE_MAX || (len + sizeof(payload_type_t)) > PLAIN_PACKET_SIZE_MAX) len = PLAIN_PACKET_SIZE_MAX - sizeof(payload_type_t); packet->payload_length_ = len; } payload_type_t plain_packet_get_type(plain_packet_t* packet) { if(!packet) return 0; return PAYLOAD_TYPE_T_NTOH(packet->data_.payload_type_); } void plain_packet_set_type(plain_packet_t* packet, payload_type_t type) { if(!packet) return; if(type == PAYLOAD_TYPE_TUN) { if(!packet->payload_length_) { packet->data_.payload_type_ = PAYLOAD_TYPE_T_HTON(PAYLOAD_TYPE_TUN); return; } struct ip* hdr = (struct ip*)(packet->data_.buf_ + sizeof(payload_type_t)); if(hdr->ip_v == 4) packet->data_.payload_type_ = PAYLOAD_TYPE_T_HTON(PAYLOAD_TYPE_TUN4); else if(hdr->ip_v == 6) packet->data_.payload_type_ = PAYLOAD_TYPE_T_HTON(PAYLOAD_TYPE_TUN6); } else packet->data_.payload_type_ = PAYLOAD_TYPE_T_HTON(type); } uanytun-0.3.3/src/Makefile0000664000175000017500000001317311336622524015424 0ustar equinoxequinox## ## 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 methodes 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-2010 Christian Pointner ## ## 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 . ## ifneq ($(MAKECMDGOALS),distclean) include include.mk endif EXECUTABLE := uanytun CRYPT_OBJ := key_derivation.o \ auth_algo.o OBJ := log.o \ string_list.o \ sig_handler.o \ sysexec.o \ options.o \ tun.o \ udp.o \ plain_packet.o \ encrypted_packet.o \ seq_window.o \ cipher.o \ uanytun.o ifndef NO_CRYPT_OBJ OBJ += $(CRYPT_OBJ) endif SRC := $(OBJ:%.o=%.c) .PHONY: clean cleanall distclean manpage install install-bin install-etc install-man uninstall remove purge all: $(EXECUTABLE) %.d: %.c @set -e; rm -f $@; \ $(CC) -MM $(CFLAGS) $< > $@.$$$$; \ sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ rm -f $@.$$$$; echo '(re)building $@' ifneq ($(MAKECMDGOALS),distclean) -include $(SRC:%.c=%.d) endif $(EXECUTABLE): $(OBJ) $(CC) $(OBJ) -o $@ $(LDFLAGS) %.o: %.c $(CC) $(CFLAGS) -c $< strip: $(EXECUTABLE) $(STRIP) -s $(EXECUTABLE) distclean: cleanall find . -name *.o -exec rm -f {} \; find . -name "*.\~*" -exec rm -rf {} \; rm -f include.mk rm -f version.h rm -f tun.c clean: rm -f *.o rm -f *.d rm -f *.d.* rm -f $(EXECUTABLE) cleanall: clean $(MAKE) --directory="../doc/" clean manpage: $(MAKE) --directory="../doc/" manpage INSTALL_TARGETS := install-bin install-etc REMOVE_TARGETS := remove-bin remove-etc ifdef MANDIR INSTALL_TARGETS += install-man REMOVE_TARGETS += remove-man endif ifdef EXAMPLESDIR INSTALL_TARGETS += install-examples REMOVE_TARGETS += remove-examples endif install: all $(INSTALL_TARGETS) install-bin: $(EXECUTABLE) $(INSTALL) -d $(DESTDIR)$(SBINDIR) $(INSTALL) -m 755 $(EXECUTABLE) $(DESTDIR)$(SBINDIR) install-etc: $(INSTALL) -d $(DESTDIR)$(ETCDIR)/$(EXECUTABLE) @ echo "example configurations can be found at $(EXAMPLESDIR)/$(EXECUTABLE)" > $(DESTDIR)$(ETCDIR)/$(EXECUTABLE)/README $(INSTALL) -d $(DESTDIR)$(ETCDIR)/init.d @ sed -e 's#DAEMON=/usr/sbin/uanytun#DAEMON=$(SBINDIR)/$(EXECUTABLE)#' \ -e 's#CONFIG_DIR=/etc/uanytun#CONFIG_DIR=$(ETCDIR)/uanytun#' ../etc/init.d/uanytun > ../etc/init.d/uanytun.bak $(INSTALL) -m 755 ../etc/init.d/uanytun.bak $(DESTDIR)$(ETCDIR)/init.d/$(EXECUTABLE) rm -f ../etc/init.d/uanytun.bak install-examples: $(INSTALL) -d $(DESTDIR)$(EXAMPLESDIR)/$(EXECUTABLE) $(INSTALL) -m 644 ../etc/uanytun/autostart $(DESTDIR)$(EXAMPLESDIR)/$(EXECUTABLE)/autostart @( cd '../etc/uanytun/' ; \ for dir in `ls`; do \ if [ -d $$dir ]; then \ echo "install $$dir configuration" ; \ cd $$dir ; \ $(INSTALL) -d $(DESTDIR)$(EXAMPLESDIR)/$(EXECUTABLE)/$$dir ; \ $(INSTALL) -m 600 config $(DESTDIR)$(EXAMPLESDIR)/$(EXECUTABLE)/$$dir/config ; \ if [ -e 'post-up.sh' ]; then \ $(INSTALL) -m 755 post-up.sh $(DESTDIR)$(EXAMPLESDIR)/$(EXECUTABLE)/$$dir/post-up.sh ; \ fi ; \ cd .. ; \ fi ; \ done \ ) install-man: manpage $(INSTALL) -d $(DESTDIR)$(MANDIR)/man8/ $(INSTALL) -m 644 ../doc/uanytun.8 $(DESTDIR)$(MANDIR)/man8/$(EXECUTABLE).8 uninstall: remove remove: $(REMOVE_TARGETS) remove-bin: rm -f $(DESTDIR)$(SBINDIR)/$(EXECUTABLE) remove-etc: rm -f $(DESTDIR)$(ETCDIR)/init.d/$(EXECUTABLE) remove-examples: rm -rf $(DESTDIR)$(EXAMPLESDIR)/$(EXECUTABLE)/ remove-man: rm -f $(DESTDIR)$(MANDIR)/man8/$(EXECUTABLE).8 purge: remove rm -rf $(DESTDIR)$(ETCDIR)/$(EXECUTABLE)/ uanytun-0.3.3/src/auth_algo.c0000664000175000017500000001764311336622524016101 0ustar equinoxequinox/* * 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 methodes 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-2010 Christian Pointner * * 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 . */ #include "datatypes.h" #include "encrypted_packet.h" #include "auth_algo.h" #include "log.h" #include #include auth_algo_type_t auth_algo_get_type(const char* type) { if(!strcmp(type, "null")) return aa_null; else if(!strcmp(type, "sha1")) return aa_sha1; return aa_unknown; } u_int32_t auth_algo_get_max_length(const char* type) { switch(auth_algo_get_type(type)) { case aa_null: return 0; case aa_sha1: return SHA1_LENGTH; default: return 0; } } int auth_algo_init(auth_algo_t* aa, const char* type) { if(!aa) return -1; aa->type_ = auth_algo_get_type(type); if(aa->type_ == aa_unknown) { log_printf(ERROR, "unknown auth algo type"); return -1; } aa->params_ = NULL; aa->key_.buf_ = NULL; aa->key_.length_ = 0; int ret = 0; if(aa->type_ == aa_sha1) ret = auth_algo_sha1_init(aa); if(ret) auth_algo_close(aa); return ret; } void auth_algo_close(auth_algo_t* aa) { if(!aa) return; if(aa->type_ == aa_sha1) auth_algo_sha1_close(aa); if(aa->key_.buf_) free(aa->key_.buf_); } void auth_algo_generate(auth_algo_t* aa, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* packet) { if(!aa) return; if(aa->type_ == aa_null) return; else if(aa->type_ == aa_sha1) auth_algo_sha1_generate(aa, kd, dir, packet); else { log_printf(ERROR, "unknown auth algo type"); return; } } int auth_algo_check_tag(auth_algo_t* aa, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* packet) { if(!aa) return 0; if(aa->type_ == aa_null) return 1; else if(aa->type_ == aa_sha1) return auth_algo_sha1_check_tag(aa, kd, dir, packet); else { log_printf(ERROR, "unknown auth algo type"); return 0; } } /* ---------------- HMAC Sha1 Auth Algo ---------------- */ int auth_algo_sha1_init(auth_algo_t* aa) { if(!aa) return -1; if(aa->key_.buf_) free(aa->key_.buf_); aa->key_.length_ = SHA1_LENGTH; aa->key_.buf_ = malloc(aa->key_.length_); if(!aa->key_.buf_) return -2; if(aa->params_) free(aa->params_); aa->params_ = malloc(sizeof(auth_algo_sha1_param_t)); if(!aa->params_) return -2; auth_algo_sha1_param_t* params = aa->params_; #ifndef USE_SSL_CRYPTO gcry_error_t err = gcry_md_open(¶ms->handle_, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC); if(err) { log_printf(ERROR, "failed to open message digest algo: %s", gcry_strerror(err)); return -1; } #else HMAC_CTX_init(¶ms->ctx_); HMAC_Init_ex(¶ms->ctx_, NULL, 0, EVP_sha1(), NULL); #endif return 0; } void auth_algo_sha1_close(auth_algo_t* aa) { if(!aa) return; if(aa->params_) { auth_algo_sha1_param_t* params = aa->params_; #ifndef USE_SSL_CRYPTO if(params->handle_) gcry_md_close(params->handle_); #else HMAC_CTX_cleanup(¶ms->ctx_); #endif free(aa->params_); } } void auth_algo_sha1_generate(auth_algo_t* aa, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* packet) { if(!encrypted_packet_get_auth_tag_length(packet)) return; if(!aa || !aa->params_) { log_printf(ERROR, "auth algo not initialized"); return; } if(!kd) { log_printf(ERROR, "no key derivation supplied"); return; } auth_algo_sha1_param_t* params = aa->params_; int ret = key_derivation_generate(kd, dir, LABEL_AUTH, encrypted_packet_get_seq_nr(packet), aa->key_.buf_, aa->key_.length_); if(ret < 0) return; #ifndef USE_SSL_CRYPTO gcry_error_t err = gcry_md_setkey(params->handle_, aa->key_.buf_, aa->key_.length_); if(err) { log_printf(ERROR, "failed to set hmac key: %s", gcry_strerror(err)); return; } gcry_md_reset(params->handle_); gcry_md_write(params->handle_, encrypted_packet_get_auth_portion(packet), encrypted_packet_get_auth_portion_length(packet)); gcry_md_final(params->handle_); u_int8_t* hmac = gcry_md_read(params->handle_, 0); #else HMAC_Init_ex(¶ms->ctx_, aa->key_.buf_, aa->key_.length_, EVP_sha1(), NULL); u_int8_t hmac[SHA1_LENGTH]; HMAC_Update(¶ms->ctx_, encrypted_packet_get_auth_portion(packet), encrypted_packet_get_auth_portion_length(packet)); HMAC_Final(¶ms->ctx_, hmac, NULL); #endif u_int8_t* tag = encrypted_packet_get_auth_tag(packet); u_int32_t length = (encrypted_packet_get_auth_tag_length(packet) < SHA1_LENGTH) ? encrypted_packet_get_auth_tag_length(packet) : SHA1_LENGTH; if(length > SHA1_LENGTH) memset(tag, 0, encrypted_packet_get_auth_tag_length(packet)); memcpy(&tag[encrypted_packet_get_auth_tag_length(packet) - length], &hmac[SHA1_LENGTH - length], length); } int auth_algo_sha1_check_tag(auth_algo_t* aa, key_derivation_t* kd, key_derivation_dir_t dir, encrypted_packet_t* packet) { if(!encrypted_packet_get_auth_tag_length(packet)) return 1; if(!aa || !aa->params_) { log_printf(ERROR, "auth algo not initialized"); return 0; } if(!kd) { log_printf(ERROR, "no key derivation supplied"); return 0; } auth_algo_sha1_param_t* params = aa->params_; int ret = key_derivation_generate(kd, dir, LABEL_AUTH, encrypted_packet_get_seq_nr(packet), aa->key_.buf_, aa->key_.length_); if(ret < 0) return 0; #ifndef USE_SSL_CRYPTO gcry_error_t err = gcry_md_setkey(params->handle_, aa->key_.buf_, aa->key_.length_); if(err) { log_printf(ERROR, "failed to set hmac key: %s", gcry_strerror(err)); return -1; } gcry_md_reset(params->handle_); gcry_md_write(params->handle_, encrypted_packet_get_auth_portion(packet), encrypted_packet_get_auth_portion_length(packet)); gcry_md_final(params->handle_); u_int8_t* hmac = gcry_md_read(params->handle_, 0); #else HMAC_Init_ex(¶ms->ctx_, aa->key_.buf_, aa->key_.length_, EVP_sha1(), NULL); u_int8_t hmac[SHA1_LENGTH]; HMAC_Update(¶ms->ctx_, encrypted_packet_get_auth_portion(packet), encrypted_packet_get_auth_portion_length(packet)); HMAC_Final(¶ms->ctx_, hmac, NULL); #endif u_int8_t* tag = encrypted_packet_get_auth_tag(packet); u_int32_t length = (encrypted_packet_get_auth_tag_length(packet) < SHA1_LENGTH) ? encrypted_packet_get_auth_tag_length(packet) : SHA1_LENGTH; if(length > SHA1_LENGTH) { u_int32_t i; for(i=0; i < (encrypted_packet_get_auth_tag_length(packet) - SHA1_LENGTH); ++i) if(tag[i]) return 0; } int result = memcmp(&tag[encrypted_packet_get_auth_tag_length(packet) - length], &hmac[SHA1_LENGTH - length], length); if(result) return 0; return 1; } uanytun-0.3.3/src/options.c0000664000175000017500000004434611336622524015631 0ustar equinoxequinox/* * 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 methodes 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-2010 Christian Pointner * * 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 . */ #include "datatypes.h" #include "version.h" #include "options.h" #include #include #include #include #include "log.h" #ifndef NO_CRYPT #include "auth_algo.h" #endif #define PARSE_BOOL_PARAM(SHORT, LONG, VALUE) \ else if(!strcmp(str,SHORT) || !strcmp(str,LONG)) \ VALUE = 1; #define PARSE_INVERSE_BOOL_PARAM(SHORT, LONG, VALUE) \ else if(!strcmp(str,SHORT) || !strcmp(str,LONG)) \ VALUE = 0; #define PARSE_INT_PARAM(SHORT, LONG, VALUE) \ else if(!strcmp(str,SHORT) || !strcmp(str,LONG)) \ { \ if(argc < 1) \ return i; \ VALUE = atoi(argv[i+1]); \ argc--; \ i++; \ } #define PARSE_STRING_PARAM(SHORT, LONG, VALUE) \ else if(!strcmp(str,SHORT) || !strcmp(str,LONG)) \ { \ if(argc < 1 || argv[i+1][0] == '-') \ return i; \ if(VALUE) free(VALUE); \ VALUE = strdup(argv[i+1]); \ if(!VALUE) \ return -2; \ argc--; \ i++; \ } #define PARSE_STRING_PARAM_SEC(SHORT, LONG, VALUE) \ else if(!strcmp(str,SHORT) || !strcmp(str,LONG)) \ { \ if(argc < 1 || argv[i+1][0] == '-') \ return i; \ if(VALUE) free(VALUE); \ VALUE = strdup(argv[i+1]); \ if(!VALUE) \ return -2; \ size_t j; \ for(j=0; j < strlen(argv[i+1]); ++j) \ argv[i+1][j] = '#'; \ argc--; \ i++; \ } #define PARSE_IFCONFIG_PARAM(SHORT, LONG, VALUE) \ else if(!strcmp(str,SHORT) || !strcmp(str,LONG)) \ { \ if(argc < 1 || argv[i+1][0] == '-') \ return i; \ int ret; \ ret = options_parse_ifconfig(argv[i+1], &VALUE); \ if(ret > 0) \ return i+1; \ if(ret < 0) \ return ret; \ argc--; \ i++; \ } #define PARSE_HEXSTRING_PARAM_SEC(SHORT, LONG, VALUE) \ else if(!strcmp(str,SHORT) || !strcmp(str,LONG)) \ { \ if(argc < 1 || argv[i+1][0] == '-') \ return i; \ int ret; \ ret = options_parse_hex_string(argv[i+1], &VALUE); \ if(ret > 0) \ return i+1; \ else if(ret < 0) \ return ret; \ size_t j; \ for(j=0; j < strlen(argv[i+1]); ++j) \ argv[i+1][j] = '#'; \ argc--; \ i++; \ } #define PARSE_STRING_LIST(SHORT, LONG, LIST) \ else if(!strcmp(str,SHORT) || !strcmp(str,LONG)) \ { \ if(argc < 1 || argv[i+1][0] == '-') \ return i; \ int ret = string_list_add(&LIST, argv[i+1]); \ if(ret == -2) \ return ret; \ else if(ret) \ return i+1; \ argc--; \ i++; \ } int options_parse_hex_string(const char* hex, buffer_t* buffer) { if(!hex || !buffer) return -1; u_int32_t hex_len = strlen(hex); if(hex_len%2) return 1; if(buffer->buf_) free(buffer->buf_); buffer->length_ = hex_len/2; buffer->buf_ = malloc(buffer->length_); if(!buffer->buf_) { buffer->length_ = 0; return -2; } const char* ptr = hex; int i; for(i=0;ilength_;++i) { u_int32_t tmp; sscanf(ptr, "%2X", &tmp); buffer->buf_[i] = (u_int8_t)tmp; ptr += 2; } return 0; } int options_parse_ifconfig(const char* arg, ifconfig_param_t* ifcfg) { char* str = strdup(arg); if(!str) return -2; char* ptr = str; for(;*ptr;++ptr) { if(*ptr == '/') { *ptr = 0; ptr++; if(!(*ptr)) { free(str); return 1; } ifcfg->prefix_length_ = atoi(ptr); ifcfg->net_addr_ = strdup(str); free(str); if(!ifcfg->net_addr_) return -2; return 0; } if(!isdigit(*ptr) && *ptr != '.') { free(str); return 1; } } free(str); return 1; } int options_parse(options_t* opt, int argc, char* argv[]) { if(!opt) return -1; options_default(opt); if(opt->progname_) free(opt->progname_); opt->progname_ = strdup(argv[0]); if(!opt->progname_) return -2; argc--; char* role = NULL; int i, ipv4_only = 0, ipv6_only = 0; for(i=1; argc > 0; ++i) { char* str = argv[i]; argc--; if(!strcmp(str,"-h") || !strcmp(str,"--help")) return -1; else if(!strcmp(str,"-v") || !strcmp(str,"--version")) return -5; PARSE_INVERSE_BOOL_PARAM("-D","--nodaemonize", opt->daemonize_) PARSE_STRING_PARAM("-u","--username", opt->username_) PARSE_STRING_PARAM("-g","--groupname", opt->groupname_) PARSE_STRING_PARAM("-C","--chroot", opt->chroot_dir_) PARSE_STRING_PARAM("-P","--write-pid", opt->pid_file_) PARSE_STRING_PARAM("-i","--interface", opt->local_addr_) PARSE_STRING_PARAM("-p","--port", opt->local_port_) PARSE_INT_PARAM("-s","--sender-id", opt->sender_id_) PARSE_STRING_LIST("-L","--log", opt->log_targets_) PARSE_BOOL_PARAM("-U", "--debug", opt->debug_) PARSE_STRING_PARAM("-r","--remote-host", opt->remote_addr_) PARSE_STRING_PARAM("-o","--remote-port", opt->remote_port_) PARSE_BOOL_PARAM("-4","--ipv4-only", ipv4_only) PARSE_BOOL_PARAM("-6","--ipv6-only", ipv6_only) PARSE_STRING_PARAM("-d","--dev", opt->dev_name_) PARSE_STRING_PARAM("-t","--type", opt->dev_type_) PARSE_IFCONFIG_PARAM("-n","--ifconfig", opt->ifconfig_param_) PARSE_STRING_PARAM("-x","--post-up-script", opt->post_up_script_) PARSE_INT_PARAM("-m","--mux", opt->mux_) PARSE_INT_PARAM("-w","--window-size", opt->seq_window_size_) #ifndef NO_CRYPT PARSE_STRING_PARAM("-k","--kd-prf", opt->kd_prf_) #ifndef NO_PASSPHRASE PARSE_STRING_PARAM_SEC("-E","--passphrase", opt->passphrase_) #endif PARSE_STRING_PARAM("-e","--role", role) PARSE_HEXSTRING_PARAM_SEC("-K","--key", opt->key_) PARSE_HEXSTRING_PARAM_SEC("-A","--salt", opt->salt_) PARSE_STRING_PARAM("-c","--cipher", opt->cipher_) PARSE_STRING_PARAM("-a","--auth-algo", opt->auth_algo_) PARSE_INT_PARAM("-b","--auth-tag-length", opt->auth_tag_length_) #endif else return i; } if(ipv4_only && ipv6_only) return -3; if(ipv4_only) opt->resolv_addr_type_ = IPV4_ONLY; if(ipv6_only) opt->resolv_addr_type_ = IPV6_ONLY; if(opt->debug_) { string_list_add(&opt->log_targets_, "stdout:5"); opt->daemonize_ = 0; } if(!opt->log_targets_.first_) string_list_add(&opt->log_targets_, "syslog:3,uanytun,daemon"); #ifndef NO_CRYPT if(role) { if(!strcmp(role, "alice") || !strcmp(role, "server") || !strcmp(role, "left")) opt->role_ = ROLE_LEFT; else if(!strcmp(role, "bob") || !strcmp(role, "client") || !strcmp(role, "right")) opt->role_ = ROLE_RIGHT; else { free(role); return -4; } free(role); } #endif return 0; } void options_parse_post(options_t* opt) { if(!opt) return; #ifndef NO_CRYPT if(!strcmp(opt->cipher_, "null") && !strcmp(opt->auth_algo_, "null") && strcmp(opt->kd_prf_, "null")) { if(opt->kd_prf_) free(opt->kd_prf_); opt->kd_prf_ = strdup("null"); } if((strcmp(opt->cipher_, "null") || strcmp(opt->auth_algo_, "null")) && !strcmp(opt->kd_prf_, "null")) { log_printf(WARNING, "using NULL key derivation with encryption and or authentication enabled!"); } u_int32_t tag_len_max = auth_algo_get_max_length(opt->auth_algo_); if(!tag_len_max) opt->auth_tag_length_ = 0; else if(tag_len_max < opt->auth_tag_length_) { log_printf(WARNING, "%s auth algo can't generate tags of length %d, using maximum tag length(%d)", opt->auth_algo_, opt->auth_tag_length_, tag_len_max); opt->auth_tag_length_ = tag_len_max; } #endif if(!(opt->dev_name_) && !(opt->dev_type_)) opt->dev_type_ = strdup("tun"); } void options_default(options_t* opt) { if(!opt) return; opt->progname_ = strdup("uanytun"); opt->daemonize_ = 1; opt->username_ = NULL; opt->groupname_ = NULL; opt->chroot_dir_ = NULL; opt->pid_file_ = NULL; string_list_init(&opt->log_targets_); opt->debug_ = 0; opt->local_addr_ = NULL; opt->local_port_ = strdup("4444"); opt->sender_id_ = 0; opt->remote_addr_ = NULL; opt->remote_port_ = strdup("4444"); opt->resolv_addr_type_ = ANY; opt->dev_name_ = NULL; opt->dev_type_ = NULL; opt->ifconfig_param_.net_addr_ = NULL; opt->ifconfig_param_.prefix_length_ = 0; opt->post_up_script_ = NULL; opt->mux_ = 0; opt->seq_window_size_ = 0; #ifndef NO_CRYPT opt->kd_prf_ = strdup("aes-ctr"); opt->passphrase_ = NULL; opt->role_ = ROLE_LEFT; opt->cipher_ = strdup("aes-ctr"); opt->auth_algo_ = strdup("sha1"); opt->auth_tag_length_ = 10; #else opt->cipher_ = strdup("null"); opt->auth_tag_length_ = 0; #endif opt->key_.buf_ = NULL; opt->key_.length_ = 0; opt->salt_.buf_ = NULL; opt->salt_.length_ = 0; } void options_clear(options_t* opt) { if(!opt) return; if(opt->progname_) free(opt->progname_); if(opt->username_) free(opt->username_); if(opt->groupname_) free(opt->groupname_); if(opt->chroot_dir_) free(opt->chroot_dir_); if(opt->pid_file_) free(opt->pid_file_); string_list_clear(&opt->log_targets_); if(opt->local_addr_) free(opt->local_addr_); if(opt->local_port_) free(opt->local_port_); if(opt->remote_addr_) free(opt->remote_addr_); if(opt->remote_port_) free(opt->remote_port_); if(opt->dev_name_) free(opt->dev_name_); if(opt->dev_type_) free(opt->dev_type_); if(opt->ifconfig_param_.net_addr_) free(opt->ifconfig_param_.net_addr_); if(opt->post_up_script_) free(opt->post_up_script_); if(opt->cipher_) free(opt->cipher_); #ifndef NO_CRYPT if(opt->auth_algo_) free(opt->auth_algo_); if(opt->kd_prf_) free(opt->kd_prf_); if(opt->passphrase_) free(opt->passphrase_); #endif if(opt->key_.buf_) free(opt->key_.buf_); if(opt->salt_.buf_) free(opt->salt_.buf_); } void options_print_usage() { printf("USAGE:\n"); printf("uanytun [-h|--help] prints this...\n"); printf(" [-v|--version] print version info and exit\n"); printf(" [-D|--nodaemonize] don't run in background\n"); printf(" [-u|--username] change to this user\n"); printf(" [-g|--groupname] change to this group\n"); printf(" [-C|--chroot] chroot to this directory\n"); printf(" [-P|--write-pid] write pid to this file\n"); printf(" [-i|--interface] local ip address to bind to\n"); printf(" [-p|--port] local port to bind to\n"); printf(" [-s|--sender-id ] the sender id to use\n"); printf(" [-L|--log] :[,[,..]]\n"); printf(" add a log target, can be invoked several times\n"); printf(" [-U|--debug] don't daemonize and log to stdout with maximum log level\n"); printf(" [-r|--remote-host] remote host\n"); printf(" [-o|--remote-port] remote port\n"); printf(" [-4|--ipv4-only] always resolv IPv4 addresses\n"); printf(" [-6|--ipv6-only] always resolv IPv6 addresses\n"); printf(" [-d|--dev] device name\n"); printf(" [-t|--type] device type\n"); printf(" [-n|--ifconfig] / the local address for the tun/tap device and the used prefix length\n"); printf(" [-x|--post-up-script]