diff options
Diffstat (limited to 'src/uanytun.c')
-rw-r--r-- | src/uanytun.c | 171 |
1 files changed, 93 insertions, 78 deletions
diff --git a/src/uanytun.c b/src/uanytun.c index 609a873..b857afd 100644 --- a/src/uanytun.c +++ b/src/uanytun.c @@ -93,11 +93,11 @@ int init_libgcrypt() #endif #endif -#ifndef NO_CRYPT -int init_main_loop(options_t* opt, cipher_t* c, auth_algo_t* aa, key_derivation_t* kd_in, key_derivation_t* kd_out, seq_win_t* seq_win) -#else -int init_main_loop(options_t* opt, cipher_t* c, key_derivation_t* kd_in, key_derivation_t* kd_out, seq_win_t* seq_win) +#ifdef NO_CRYPT +typedef u_int8_t auth_algo_t; #endif + +int init_main_loop(options_t* opt, cipher_t* c, auth_algo_t* aa, key_derivation_t* kd_in, key_derivation_t* kd_out, seq_win_t* seq_win) { int ret = cipher_init(c, opt->cipher_); if(ret) { @@ -145,6 +145,91 @@ int init_main_loop(options_t* opt, cipher_t* c, key_derivation_t* kd_in, key_der return 0; } +int process_tun_data(tun_device_t* dev, udp_socket_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_out, seq_nr_t seq_nr) +{ + int len = tun_read(dev, plain_packet_get_payload(plain_packet), plain_packet_get_payload_length(plain_packet)); + if(len == -1) { + log_printf(ERR, "error on reading from device: %m"); + 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); + else + plain_packet_set_type(plain_packet, PAYLOAD_TYPE_UNKNOWN); + + cipher_encrypt(c, kd_out, plain_packet, encrypted_packet, seq_nr, opt->sender_id_, opt->mux_); + +#ifndef NO_CRYPT + auth_algo_generate(aa, kd_out, encrypted_packet); +#endif + + len = udp_write(sock, encrypted_packet_get_packet(encrypted_packet), encrypted_packet_get_length(encrypted_packet)); + if(len == -1) + log_printf(ERR, "error on sending udp packet: %m"); + + return 0; +} + +int process_sock_data(tun_device_t* dev, udp_socket_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_in, seq_win_t* seq_win) +{ + udp_endpoint_t remote; + memset(&remote, 0, sizeof(udp_endpoint_t)); + int len = udp_read(sock, encrypted_packet_get_packet(encrypted_packet), encrypted_packet_get_length(encrypted_packet), &remote); + if(len == -1) { + log_printf(ERR, "error on receiving udp packet: %m"); + return 0; + } + + encrypted_packet_set_length(encrypted_packet, len); + +#ifndef NO_CRYPT + if(!auth_algo_check_tag(aa, kd_in, 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) { + log_printf(ERR, "memory error at sequence window"); + return -2; + } + + if(memcmp(&remote, &(sock->remote_end_), sizeof(remote))) { + memcpy(&(sock->remote_end_), &remote, sizeof(remote)); + char* addrstring = udp_endpoint_to_string(remote); + log_printf(NOTICE, "autodetected remote host changed %s", addrstring); + free(addrstring); + } + + int ret = cipher_decrypt(c, kd_in, 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(ERR, "error on writing to device: %m"); + + return 0; +} + + int main_loop(tun_device_t* dev, udp_socket_t* sock, options_t* opt) { log_printf(INFO, "entering main loop"); @@ -153,23 +238,15 @@ int main_loop(tun_device_t* dev, udp_socket_t* sock, options_t* opt) plain_packet_init(&plain_packet); encrypted_packet_t encrypted_packet; encrypted_packet_init(&encrypted_packet); - int len = 0; - udp_endpoint_t remote; seq_nr_t seq_nr = 0; fd_set readfds; cipher_t c; -#ifndef NO_CRYPT auth_algo_t aa; -#endif key_derivation_t kd_in, kd_out; seq_win_t seq_win; -#ifndef NO_CRYPT int ret = init_main_loop(opt, &c, &aa, &kd_in, &kd_out, &seq_win); -#else - int ret = init_main_loop(opt, &c, &kd_in, &kd_out, &seq_win); -#endif if(ret) return ret; @@ -198,76 +275,14 @@ int main_loop(tun_device_t* dev, udp_socket_t* sock, options_t* opt) } if(FD_ISSET(dev->fd_, &readfds)) { - len = tun_read(dev, plain_packet_get_payload(&plain_packet), plain_packet_get_payload_length(&plain_packet)); - if(len == -1) { - log_printf(ERR, "error on reading from device: %m"); - continue; - } - - 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); - else - plain_packet_set_type(&plain_packet, PAYLOAD_TYPE_UNKNOWN); - - cipher_encrypt(&c, &kd_out, &plain_packet, &encrypted_packet, seq_nr, opt->sender_id_, opt->mux_); + return_value = process_tun_data(dev, sock, opt, &plain_packet, &encrypted_packet, &c, &aa, &kd_out, seq_nr); seq_nr++; - -#ifndef NO_CRYPT - auth_algo_generate(&aa, &kd_out, &encrypted_packet); -#endif - - len = udp_write(sock, encrypted_packet_get_packet(&encrypted_packet), encrypted_packet_get_length(&encrypted_packet)); - if(len == -1) - log_printf(ERR, "error on sending udp packet: %m"); + continue; } if(FD_ISSET(sock->fd_, &readfds)) { - len = udp_read(sock, encrypted_packet_get_packet(&encrypted_packet), encrypted_packet_get_length(&encrypted_packet), &remote); - if(len == -1) { - log_printf(ERR, "error on receiving udp packet: %m"); - continue; - } - - encrypted_packet_set_length(&encrypted_packet, len); - -#ifndef NO_CRYPT - if(!auth_algo_check_tag(&aa, &kd_out, &encrypted_packet)) { - log_printf(WARNING, "wrong authentication tag, discarding packet"); - continue; - } -#endif - - if(encrypted_packet_get_mux(&encrypted_packet) != opt->mux_) - continue; - - 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"); - continue; - } - else if(result < 0) { - log_printf(ERR, "memory error at sequence window"); - return_value -1; - break; - } - - - if(memcmp(&remote, &(sock->remote_end_), sizeof(remote))) { - memcpy(&(sock->remote_end_), &remote, sizeof(remote)); - char* addrstring = udp_endpoint_to_string(remote); - log_printf(NOTICE, "autodetected remote host changed %s", addrstring); - free(addrstring); - } - - cipher_decrypt(&c, &kd_in, &encrypted_packet, &plain_packet); - - len = tun_write(dev, plain_packet_get_payload(&plain_packet), plain_packet_get_payload_length(&plain_packet)); - if(len == -1) - log_printf(ERR, "error on writing to device: %m"); + return_value = process_sock_data(dev, sock, opt, &plain_packet, &encrypted_packet, &c, &aa, &kd_in, &seq_win); + continue; } } |