4 * uAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
5 * featured implementation uAnytun has no support for multiple connections
6 * or synchronisation. It is a small single threaded implementation intended
7 * to act as a client on small platforms.
8 * The secure anycast tunneling protocol (satp) defines a protocol used
9 * for communication between any combination of unicast and anycast
10 * tunnel endpoints. It has less protocol overhead than IPSec in Tunnel
11 * mode and allows tunneling of every ETHER TYPE protocol (e.g.
12 * ethernet, ip, arp ...). satp directly includes cryptography and
13 * message authentication based on the methodes used by SRTP. It is
14 * intended to deliver a generic, scaleable and secure solution for
15 * tunneling and relaying of packets of any protocol.
18 * Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
20 * This file is part of uAnytun.
22 * uAnytun is free software: you can redistribute it and/or modify
23 * it under the terms of the GNU General Public License as published by
24 * the Free Software Foundation, either version 3 of the License, or
27 * uAnytun is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU General Public License for more details.
32 * You should have received a copy of the GNU General Public License
33 * along with uAnytun. If not, see <http://www.gnu.org/licenses/>.
36 #include "datatypes.h"
44 #include "sig_handler.h"
50 #include "plain_packet.h"
51 #include "encrypted_packet.h"
53 #include "seq_window.h"
57 #include "key_derivation.h"
58 #include "auth_algo.h"
60 #ifndef USE_SSL_CRYPTO
70 #ifndef USE_SSL_CRYPTO
72 #define MIN_GCRYPT_VERSION "1.2.0"
76 if(!gcry_check_version(MIN_GCRYPT_VERSION)) {
77 log_printf(NOTICE, "invalid Version of libgcrypt, should be >= %s", MIN_GCRYPT_VERSION);
81 gcry_error_t err = gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
83 log_printf(ERROR, "failed to disable secure memory: %s", gcry_strerror(err));
87 err = gcry_control(GCRYCTL_INITIALIZATION_FINISHED);
89 log_printf(ERROR, "failed to finish libgcrypt initialization: %s", gcry_strerror(err));
93 log_printf(NOTICE, "libgcrypt init finished");
100 typedef u_int8_t auth_algo_t;
103 int init_main_loop(options_t* opt, cipher_t* c, auth_algo_t* aa, key_derivation_t* kd, seq_win_t* seq_win)
105 int ret = cipher_init(c, opt->cipher_);
107 log_printf(ERROR, "could not initialize cipher of type %s", opt->cipher_);
112 ret = auth_algo_init(aa, opt->auth_algo_);
114 log_printf(ERROR, "could not initialize auth algo of type %s", opt->auth_algo_);
119 ret = key_derivation_init(kd, opt->kd_prf_, opt->role_, opt->passphrase_, opt->key_.buf_, opt->key_.length_, opt->salt_.buf_, opt->salt_.length_);
121 log_printf(ERROR, "could not initialize key derivation of type %s", opt->kd_prf_);
128 ret = seq_win_init(seq_win, opt->seq_window_size_);
130 printf("could not initialize sequence window");
134 key_derivation_close(kd);
141 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,
142 cipher_t* c, auth_algo_t* aa, key_derivation_t* kd, seq_nr_t seq_nr)
144 plain_packet_set_payload_length(plain_packet, -1);
145 encrypted_packet_set_length(encrypted_packet, -1);
147 int len = tun_read(dev, plain_packet_get_payload(plain_packet), plain_packet_get_payload_length(plain_packet));
149 log_printf(ERROR, "error on reading from device: %s", strerror(errno));
153 plain_packet_set_payload_length(plain_packet, len);
155 if(dev->type_ == TYPE_TUN)
156 plain_packet_set_type(plain_packet, PAYLOAD_TYPE_TUN);
157 else if(dev->type_ == TYPE_TAP)
158 plain_packet_set_type(plain_packet, PAYLOAD_TYPE_TAP);
160 plain_packet_set_type(plain_packet, PAYLOAD_TYPE_UNKNOWN);
162 if(!sock->remote_end_set_)
165 cipher_encrypt(c, kd, kd_outbound, plain_packet, encrypted_packet, seq_nr, opt->sender_id_, opt->mux_);
168 auth_algo_generate(aa, kd, kd_outbound, encrypted_packet);
171 len = udp_write(sock, encrypted_packet_get_packet(encrypted_packet), encrypted_packet_get_length(encrypted_packet));
173 log_printf(ERROR, "error on sending udp packet: %s", strerror(errno));
178 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,
179 cipher_t* c, auth_algo_t* aa, key_derivation_t* kd, seq_win_t* seq_win)
181 plain_packet_set_payload_length(plain_packet, -1);
182 encrypted_packet_set_length(encrypted_packet, -1);
184 udp_endpoint_t remote;
185 memset(&remote, 0, sizeof(udp_endpoint_t));
186 int len = udp_read(sock, encrypted_packet_get_packet(encrypted_packet), encrypted_packet_get_length(encrypted_packet), &remote);
188 log_printf(ERROR, "error on receiving udp packet: %s", strerror(errno));
191 else if(len < encrypted_packet_get_minimum_length(encrypted_packet)) {
192 log_printf(WARNING, "received packet is to short");
195 encrypted_packet_set_length(encrypted_packet, len);
198 if(!auth_algo_check_tag(aa, kd, kd_inbound, encrypted_packet)) {
199 log_printf(WARNING, "wrong authentication tag, discarding packet");
204 if(encrypted_packet_get_mux(encrypted_packet) != opt->mux_) {
205 log_printf(WARNING, "wrong mux value, discarding packet");
209 int result = seq_win_check_and_add(seq_win, encrypted_packet_get_sender_id(encrypted_packet), encrypted_packet_get_seq_nr(encrypted_packet));
211 log_printf(WARNING, "detected replay attack, discarding packet");
214 else if(result < 0) {
215 log_printf(ERROR, "memory error at sequence window");
219 if(memcmp(&remote, &(sock->remote_end_), sizeof(remote))) {
220 memcpy(&(sock->remote_end_), &remote, sizeof(remote));
221 sock->remote_end_set_ = 1;
222 char* addrstring = udp_endpoint_to_string(remote);
223 log_printf(NOTICE, "autodetected remote host changed %s", addrstring);
227 if(encrypted_packet_get_payload_length(encrypted_packet) <= plain_packet_get_header_length()) {
228 log_printf(WARNING, "ignoring packet with zero length payload");
232 int ret = cipher_decrypt(c, kd, kd_inbound, encrypted_packet, plain_packet);
236 len = tun_write(dev, plain_packet_get_payload(plain_packet), plain_packet_get_payload_length(plain_packet));
238 log_printf(ERROR, "error on writing to device: %s", strerror(errno));
244 int main_loop(tun_device_t* dev, udp_socket_t* sock, options_t* opt)
246 log_printf(INFO, "entering main loop");
248 plain_packet_t plain_packet;
249 plain_packet_init(&plain_packet);
250 encrypted_packet_t encrypted_packet;
251 encrypted_packet_init(&encrypted_packet, opt->auth_tag_length_);
253 fd_set readfds, readyfds;
260 int ret = init_main_loop(opt, &c, &aa, &kd, &seq_win);
265 FD_SET(dev->fd_, &readfds);
266 FD_SET(sock->fd_, &readfds);
267 int nfds = dev->fd_ > sock->fd_ ? dev->fd_ : sock->fd_;
269 int return_value = 0;
270 int sig_fd = signal_init();
274 FD_SET(sig_fd, &readfds);
275 nfds = (nfds < sig_fd) ? sig_fd : nfds;
277 while(!return_value) {
278 memcpy(&readyfds, &readfds, sizeof(readyfds));
279 int ret = select(nfds + 1, &readyfds, NULL, NULL, NULL);
280 if(ret == -1 && errno != EINTR) {
281 log_printf(ERROR, "select returned with error: %s", strerror(errno));
285 if(!ret || ret == -1)
288 if(FD_ISSET(sig_fd, &readyfds)) {
289 if(signal_handle()) {
295 if(FD_ISSET(dev->fd_, &readyfds)) {
296 return_value = process_tun_data(dev, sock, opt, &plain_packet, &encrypted_packet, &c, &aa, &kd, seq_nr);
302 if(FD_ISSET(sock->fd_, &readyfds)) {
303 return_value = process_sock_data(dev, sock, opt, &plain_packet, &encrypted_packet, &c, &aa, &kd, &seq_win);
311 auth_algo_close(&aa);
312 key_derivation_close(&kd);
314 seq_win_clear(&seq_win);
320 int main(int argc, char* argv[])
325 int ret = options_parse(&opt, argc, argv);
328 fprintf(stderr, "syntax error near: %s\n\n", argv[ret]);
331 fprintf(stderr, "memory error on options_parse, exitting\n");
334 fprintf(stderr, "syntax error: -4 and -6 are mutual exclusive\n\n");
337 fprintf(stderr, "syntax error: unknown role name\n\n");
341 options_print_usage();
347 string_list_element_t* tmp = opt.log_targets_.first_;
349 log_add_target("syslog:3,uanytun,daemon");
353 ret = log_add_target(tmp->string_);
356 case -2: fprintf(stderr, "memory error on log_add_target, exitting\n"); break;
357 case -3: fprintf(stderr, "unknown log target: '%s', exitting\n", tmp->string_); break;
358 case -4: fprintf(stderr, "this log target is only allowed once: '%s', exitting\n", tmp->string_); break;
359 default: fprintf(stderr, "syntax error near: '%s', exitting\n", tmp->string_); break;
370 log_printf(NOTICE, "just started...");
371 options_parse_post(&opt);
375 if(priv_init(&priv, opt.username_, opt.groupname_)) {
382 #ifndef USE_SSL_CRYPTO
383 ret = init_libgcrypt();
385 log_printf(ERROR, "error on libgcrpyt initialization, exitting");
394 ret = tun_init(&dev, opt.dev_name_, opt.dev_type_, opt.ifconfig_param_.net_addr_, opt.ifconfig_param_.prefix_length_);
396 log_printf(ERROR, "error on tun_init, exitting");
401 log_printf(NOTICE, "dev of type '%s' opened, actual name is '%s'", tun_get_type_string(&dev), dev.actual_name_);
403 if(opt.post_up_script_) {
404 log_printf(NOTICE, "executing post-up script '%s'", opt.post_up_script_);
405 char* const argv[] = { opt.post_up_script_, dev.actual_name_, NULL };
406 char* const evp[] = { NULL };
407 int ret = uanytun_exec(opt.post_up_script_, argv, evp);
412 ret = udp_init(&sock, opt.local_addr_, opt.local_port_, opt.resolv_addr_type_);
414 log_printf(ERROR, "error on udp_init, exitting");
420 char* local_string = udp_get_local_end_string(&sock);
422 log_printf(NOTICE, "listening on: %s", local_string);
427 if(opt.remote_addr_) {
428 if(!udp_set_remote(&sock, opt.remote_addr_, opt.remote_port_, opt.resolv_addr_type_)) {
429 char* remote_string = udp_get_remote_end_string(&sock);
431 log_printf(NOTICE, "set remote end to: %s", remote_string);
438 FILE* pid_file = NULL;
440 pid_file = fopen(opt.pid_file_, "w");
442 log_printf(WARNING, "unable to open pid file: %s", strerror(errno));
447 if(do_chroot(opt.chroot_dir_)) {
455 if(priv_drop(&priv)) {
464 pid_t oldpid = getpid();
466 log_printf(INFO, "running in background now (old pid: %d)", oldpid);
470 pid_t pid = getpid();
471 fprintf(pid_file, "%d", pid);
475 ret = main_loop(&dev, &sock, &opt);
482 log_printf(NOTICE, "normal shutdown");
484 log_printf(NOTICE, "shutdown after error");
486 log_printf(NOTICE, "shutdown after signal");