X-Git-Url: https://git.syn-net.org/?p=debian%2Fuanytun.git;a=blobdiff_plain;f=src%2Fuanytun.c;h=159f77359fa1716e254e2bd62ac0b67864173f6f;hp=53acbaf072fc70825864cd60c1c183e33d103004;hb=71f6f666a3d69c6e1e7a77e238362c5bbe288e66;hpb=aa74a4fd24d8e8537f76531e6257fa90145355d3 diff --git a/src/uanytun.c b/src/uanytun.c index 53acbaf..159f773 100644 --- a/src/uanytun.c +++ b/src/uanytun.c @@ -10,12 +10,12 @@ * 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 + * message authentication based on the methods used by SRTP. It is * intended to deliver a generic, scaleable and secure solution for * tunneling and relaying of packets of any protocol. - * * - * Copyright (C) 2007-2010 Christian Pointner + * + * Copyright (C) 2007-2014 Christian Pointner * * This file is part of uAnytun. * @@ -31,6 +31,19 @@ * * You should have received a copy of the GNU General Public License * along with uAnytun. If not, see . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. */ #include "datatypes.h" @@ -72,7 +85,7 @@ int init_main_loop(options_t* opt, cipher_t* c, auth_algo_t* aa, key_derivation_ log_printf(ERROR, "could not initialize cipher of type %s", opt->cipher_); return ret; } - + #ifndef NO_CRYPT ret = auth_algo_init(aa, opt->auth_algo_); if(ret) { @@ -104,7 +117,7 @@ int init_main_loop(options_t* opt, cipher_t* c, auth_algo_t* aa, key_derivation_ } int process_tun_data(tun_device_t* dev, udp_t* sock, options_t* opt, plain_packet_t* plain_packet, encrypted_packet_t* encrypted_packet, - cipher_t* c, auth_algo_t* aa, key_derivation_t* kd, seq_nr_t seq_nr) + cipher_t* c, auth_algo_t* aa, key_derivation_t* kd, seq_nr_t* seq_nr) { plain_packet_set_payload_length(plain_packet, -1); encrypted_packet_set_length(encrypted_packet, -1); @@ -114,25 +127,25 @@ int process_tun_data(tun_device_t* dev, udp_t* sock, options_t* opt, plain_packe log_printf(ERROR, "error on reading from device: %s", strerror(errno)); return 0; } - + plain_packet_set_payload_length(plain_packet, len); - + if(dev->type_ == TYPE_TUN) plain_packet_set_type(plain_packet, PAYLOAD_TYPE_TUN); else if(dev->type_ == TYPE_TAP) - plain_packet_set_type(plain_packet, PAYLOAD_TYPE_TAP); + plain_packet_set_type(plain_packet, PAYLOAD_TYPE_TAP); else plain_packet_set_type(plain_packet, PAYLOAD_TYPE_UNKNOWN); - if(!sock->remote_end_set_) + if(!udp_has_remote(sock)) return 0; - - cipher_encrypt(c, kd, kd_outbound, plain_packet, encrypted_packet, seq_nr, opt->sender_id_, opt->mux_); - + + cipher_encrypt(c, kd, kd_outbound, plain_packet, encrypted_packet, *seq_nr, opt->sender_id_, opt->mux_); + (*seq_nr)++; #ifndef NO_CRYPT auth_algo_generate(aa, kd, kd_outbound, encrypted_packet); #endif - + len = udp_write(sock, encrypted_packet_get_packet(encrypted_packet), encrypted_packet_get_length(encrypted_packet)); if(len == -1) log_printf(ERROR, "error on sending udp packet: %s", strerror(errno)); @@ -147,62 +160,54 @@ int process_sock_data(tun_device_t* dev, int fd, udp_t* sock, options_t* opt, pl encrypted_packet_set_length(encrypted_packet, -1); udp_endpoint_t remote; - memset(&remote, 0, sizeof(udp_endpoint_t)); + memset(&(remote.addr_), 0, sizeof(remote.addr_)); + remote.len_ = sizeof(remote.addr_); int len = udp_read(sock, fd, encrypted_packet_get_packet(encrypted_packet), encrypted_packet_get_length(encrypted_packet), &remote); if(len == -1) { log_printf(ERROR, "error on receiving udp packet: %s", strerror(errno)); return 0; - } - else if(len < encrypted_packet_get_minimum_length(encrypted_packet)) { + } else if(len < encrypted_packet_get_minimum_length(encrypted_packet)) { log_printf(WARNING, "received packet is too short"); return 0; } encrypted_packet_set_length(encrypted_packet, len); + if(encrypted_packet_get_mux(encrypted_packet) != opt->mux_) { + log_printf(WARNING, "wrong mux value, discarding packet"); + return 0; + } + #ifndef NO_CRYPT if(!auth_algo_check_tag(aa, kd, kd_inbound, encrypted_packet)) { log_printf(WARNING, "wrong authentication tag, discarding packet"); return 0; } #endif - - if(encrypted_packet_get_mux(encrypted_packet) != opt->mux_) { - log_printf(WARNING, "wrong mux value, discarding packet"); - return 0; - } - + int result = seq_win_check_and_add(seq_win, encrypted_packet_get_sender_id(encrypted_packet), encrypted_packet_get_seq_nr(encrypted_packet)); if(result > 0) { log_printf(WARNING, "detected replay attack, discarding packet"); return 0; - } - else if(result < 0) { + } else if(result < 0) { log_printf(ERROR, "memory error at sequence window"); return -2; } - - udp_set_active_sock(sock, fd); - if(memcmp(&remote, &(sock->remote_end_), sizeof(remote))) { - memcpy(&(sock->remote_end_), &remote, sizeof(remote)); - sock->remote_end_set_ = 1; - char* addrstring = udp_endpoint_to_string(remote); - log_printf(NOTICE, "autodetected remote host changed %s", addrstring); - free(addrstring); - } + + udp_update_remote(sock, fd, &remote); if(encrypted_packet_get_payload_length(encrypted_packet) <= plain_packet_get_header_length()) { log_printf(WARNING, "ignoring packet with zero length payload"); return 0; } - int ret = cipher_decrypt(c, kd, kd_inbound, encrypted_packet, plain_packet); - if(ret) + int ret = cipher_decrypt(c, kd, kd_inbound, encrypted_packet, plain_packet); + if(ret) return ret; - + len = tun_write(dev, plain_packet_get_payload(plain_packet), plain_packet_get_payload_length(plain_packet)); if(len == -1) log_printf(ERROR, "error on writing to device: %s", strerror(errno)); - + return 0; } @@ -229,13 +234,13 @@ int main_loop(tun_device_t* dev, udp_t* sock, options_t* opt) FD_ZERO(&readfds); FD_SET(dev->fd_, &readfds); - int nfds = udp_init_fd_set(sock, &readfds); + int nfds = udp_fill_fd_set(sock, &readfds); nfds = dev->fd_ > nfds ? dev->fd_ : nfds; int return_value = 0; int sig_fd = signal_init(); if(sig_fd < 0) - return_value -1; + return_value = -1; FD_SET(sig_fd, &readfds); nfds = (nfds < sig_fd) ? sig_fd : nfds; @@ -252,15 +257,21 @@ int main_loop(tun_device_t* dev, udp_t* sock, options_t* opt) continue; if(FD_ISSET(sig_fd, &readyfds)) { - if(signal_handle()) { - return_value = 1; + return_value = signal_handle(); + if(return_value == 1) break; + else if(return_value == 2) { + seq_win_clear(&seq_win); + seq_nr = 0; + log_printf(NOTICE, "sequence window cleared"); + return_value = 0; } + else + return_value = 0; } if(FD_ISSET(dev->fd_, &readyfds)) { - return_value = process_tun_data(dev, sock, opt, &plain_packet, &encrypted_packet, &c, &aa, &kd, seq_nr); - seq_nr++; + return_value = process_tun_data(dev, sock, opt, &plain_packet, &encrypted_packet, &c, &aa, &kd, &seq_nr); if(return_value) break; } @@ -268,7 +279,7 @@ int main_loop(tun_device_t* dev, udp_t* sock, options_t* opt) udp_socket_t* s = sock->socks_; while(s) { if(FD_ISSET(s->fd_, &readyfds)) { - return_value = process_sock_data(dev, s->fd_, sock, opt, &plain_packet, &encrypted_packet, &c, &aa, &kd, &seq_win); + return_value = process_sock_data(dev, s->fd_, sock, opt, &plain_packet, &encrypted_packet, &c, &aa, &kd, &seq_win); if(return_value) break; } @@ -310,7 +321,7 @@ int main(int argc, char* argv[]) options_print_version(); } - if(ret != -2 && ret != -5) + if(ret != -2 && ret != -5) options_print_usage(); if(ret == -1 || ret == -5) @@ -330,7 +341,7 @@ int main(int argc, char* argv[]) case -4: fprintf(stderr, "this log target is only allowed once: '%s', exitting\n", tmp->string_); break; default: fprintf(stderr, "syntax error near: '%s', exitting\n", tmp->string_); break; } - + options_clear(&opt); log_close(); exit(ret); @@ -371,7 +382,7 @@ int main(int argc, char* argv[]) log_printf(NOTICE, "executing post-up script '%s'", opt.post_up_script_); char* const argv[] = { opt.post_up_script_, dev.actual_name_, NULL }; char* const evp[] = { NULL }; - int ret = uanytun_exec(opt.post_up_script_, argv, evp); + uanytun_exec(opt.post_up_script_, argv, evp); } @@ -385,15 +396,8 @@ int main(int argc, char* argv[]) exit(ret); } - if(opt.remote_addr_) { - if(!udp_set_remote(&sock, opt.remote_addr_, opt.remote_port_, opt.resolv_addr_type_)) { - char* remote_string = udp_get_remote_end_string(&sock); - if(remote_string) { - log_printf(NOTICE, "set remote end to: %s", remote_string); - free(remote_string); - } - } - } + if(opt.remote_addr_) + udp_resolv_remote(&sock, opt.remote_addr_, opt.remote_port_, opt.resolv_addr_type_); FILE* pid_file = NULL; @@ -419,7 +423,7 @@ int main(int argc, char* argv[]) options_clear(&opt); log_close(); exit(-1); - } + } if(opt.daemonize_) { pid_t oldpid = getpid();