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 methods 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-2014 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/>.
35 * In addition, as a special exception, the copyright holders give
36 * permission to link the code of portions of this program with the
37 * OpenSSL library under certain conditions as described in each
38 * individual source file, and distribute linked combinations
40 * You must obey the GNU General Public License in all respects
41 * for all of the code used other than OpenSSL. If you modify
42 * file(s) with this exception, you may extend this exception to your
43 * version of the file(s), but you are not obligated to do so. If you
44 * do not wish to do so, delete this exception statement from your
45 * version. If you delete this exception statement from all source
46 * files in the program, then also delete it here.
49 #include "datatypes.h"
57 #include "sig_handler.h"
63 #include "plain_packet.h"
64 #include "encrypted_packet.h"
66 #include "seq_window.h"
70 #include "key_derivation.h"
71 #include "auth_algo.h"
73 typedef u_int8_t auth_algo_t;
75 #include "init_crypt.h"
81 int init_main_loop(options_t* opt, cipher_t* c, auth_algo_t* aa, key_derivation_t* kd, seq_win_t* seq_win)
83 int ret = cipher_init(c, opt->cipher_);
85 log_printf(ERROR, "could not initialize cipher of type %s", opt->cipher_);
90 ret = auth_algo_init(aa, opt->auth_algo_);
92 log_printf(ERROR, "could not initialize auth algo of type %s", opt->auth_algo_);
97 ret = key_derivation_init(kd, opt->kd_prf_, opt->role_, opt->passphrase_, opt->key_.buf_, opt->key_.length_, opt->salt_.buf_, opt->salt_.length_);
99 log_printf(ERROR, "could not initialize key derivation of type %s", opt->kd_prf_);
106 ret = seq_win_init(seq_win, opt->seq_window_size_);
108 printf("could not initialize sequence window");
112 key_derivation_close(kd);
119 int process_tun_data(tun_device_t* dev, udp_t* sock, options_t* opt, plain_packet_t* plain_packet, encrypted_packet_t* encrypted_packet,
120 cipher_t* c, auth_algo_t* aa, key_derivation_t* kd, seq_nr_t* seq_nr)
122 plain_packet_set_payload_length(plain_packet, -1);
123 encrypted_packet_set_length(encrypted_packet, -1);
125 int len = tun_read(dev, plain_packet_get_payload(plain_packet), plain_packet_get_payload_length(plain_packet));
127 log_printf(ERROR, "error on reading from device: %s", strerror(errno));
131 plain_packet_set_payload_length(plain_packet, len);
133 if(dev->type_ == TYPE_TUN)
134 plain_packet_set_type(plain_packet, PAYLOAD_TYPE_TUN);
135 else if(dev->type_ == TYPE_TAP)
136 plain_packet_set_type(plain_packet, PAYLOAD_TYPE_TAP);
138 plain_packet_set_type(plain_packet, PAYLOAD_TYPE_UNKNOWN);
140 if(!udp_has_remote(sock))
143 cipher_encrypt(c, kd, kd_outbound, plain_packet, encrypted_packet, *seq_nr, opt->sender_id_, opt->mux_);
146 auth_algo_generate(aa, kd, kd_outbound, encrypted_packet);
149 len = udp_write(sock, encrypted_packet_get_packet(encrypted_packet), encrypted_packet_get_length(encrypted_packet));
151 log_printf(ERROR, "error on sending udp packet: %s", strerror(errno));
156 int process_sock_data(tun_device_t* dev, int fd, udp_t* sock, options_t* opt, plain_packet_t* plain_packet, encrypted_packet_t* encrypted_packet,
157 cipher_t* c, auth_algo_t* aa, key_derivation_t* kd, seq_win_t* seq_win)
159 plain_packet_set_payload_length(plain_packet, -1);
160 encrypted_packet_set_length(encrypted_packet, -1);
162 udp_endpoint_t remote;
163 memset(&(remote.addr_), 0, sizeof(remote.addr_));
164 remote.len_ = sizeof(remote.addr_);
165 int len = udp_read(sock, fd, encrypted_packet_get_packet(encrypted_packet), encrypted_packet_get_length(encrypted_packet), &remote);
167 log_printf(ERROR, "error on receiving udp packet: %s", strerror(errno));
169 } else if(len < encrypted_packet_get_minimum_length(encrypted_packet)) {
170 log_printf(WARNING, "received packet is too short");
173 encrypted_packet_set_length(encrypted_packet, len);
175 if(encrypted_packet_get_mux(encrypted_packet) != opt->mux_) {
176 log_printf(WARNING, "wrong mux value, discarding packet");
181 if(!auth_algo_check_tag(aa, kd, kd_inbound, encrypted_packet)) {
182 log_printf(WARNING, "wrong authentication tag, discarding packet");
187 int result = seq_win_check_and_add(seq_win, encrypted_packet_get_sender_id(encrypted_packet), encrypted_packet_get_seq_nr(encrypted_packet));
189 log_printf(WARNING, "detected replay attack, discarding packet");
191 } else if(result < 0) {
192 log_printf(ERROR, "memory error at sequence window");
196 udp_update_remote(sock, fd, &remote);
198 if(encrypted_packet_get_payload_length(encrypted_packet) <= plain_packet_get_header_length()) {
199 log_printf(WARNING, "ignoring packet with zero length payload");
203 int ret = cipher_decrypt(c, kd, kd_inbound, encrypted_packet, plain_packet);
207 len = tun_write(dev, plain_packet_get_payload(plain_packet), plain_packet_get_payload_length(plain_packet));
209 log_printf(ERROR, "error on writing to device: %s", strerror(errno));
215 int main_loop(tun_device_t* dev, udp_t* sock, options_t* opt)
217 log_printf(INFO, "entering main loop");
219 plain_packet_t plain_packet;
220 plain_packet_init(&plain_packet);
221 encrypted_packet_t encrypted_packet;
222 encrypted_packet_init(&encrypted_packet, opt->auth_tag_length_);
224 fd_set readfds, readyfds;
231 int ret = init_main_loop(opt, &c, &aa, &kd, &seq_win);
236 FD_SET(dev->fd_, &readfds);
237 int nfds = udp_fill_fd_set(sock, &readfds);
238 nfds = dev->fd_ > nfds ? dev->fd_ : nfds;
240 int return_value = 0;
241 int sig_fd = signal_init();
245 FD_SET(sig_fd, &readfds);
246 nfds = (nfds < sig_fd) ? sig_fd : nfds;
248 while(!return_value) {
249 memcpy(&readyfds, &readfds, sizeof(readyfds));
250 int ret = select(nfds + 1, &readyfds, NULL, NULL, NULL);
251 if(ret == -1 && errno != EINTR) {
252 log_printf(ERROR, "select returned with error: %s", strerror(errno));
256 if(!ret || ret == -1)
259 if(FD_ISSET(sig_fd, &readyfds)) {
260 return_value = signal_handle();
261 if(return_value == 1)
263 else if(return_value == 2) {
264 seq_win_clear(&seq_win);
266 log_printf(NOTICE, "sequence window cleared");
273 if(FD_ISSET(dev->fd_, &readyfds)) {
274 return_value = process_tun_data(dev, sock, opt, &plain_packet, &encrypted_packet, &c, &aa, &kd, &seq_nr);
279 udp_socket_t* s = sock->socks_;
281 if(FD_ISSET(s->fd_, &readyfds)) {
282 return_value = process_sock_data(dev, s->fd_, sock, opt, &plain_packet, &encrypted_packet, &c, &aa, &kd, &seq_win);
292 auth_algo_close(&aa);
293 key_derivation_close(&kd);
295 seq_win_clear(&seq_win);
301 int main(int argc, char* argv[])
306 int ret = options_parse(&opt, argc, argv);
309 fprintf(stderr, "syntax error near: %s\n\n", argv[ret]);
312 fprintf(stderr, "memory error on options_parse, exitting\n");
315 fprintf(stderr, "syntax error: -4 and -6 are mutual exclusive\n\n");
318 fprintf(stderr, "syntax error: unknown role name\n\n");
321 options_print_version();
324 if(ret != -2 && ret != -5)
325 options_print_usage();
327 if(ret == -1 || ret == -5)
334 string_list_element_t* tmp = opt.log_targets_.first_;
336 ret = log_add_target(tmp->string_);
339 case -2: fprintf(stderr, "memory error on log_add_target, exitting\n"); break;
340 case -3: fprintf(stderr, "unknown log target: '%s', exitting\n", tmp->string_); break;
341 case -4: fprintf(stderr, "this log target is only allowed once: '%s', exitting\n", tmp->string_); break;
342 default: fprintf(stderr, "syntax error near: '%s', exitting\n", tmp->string_); break;
352 log_printf(NOTICE, "just started...");
353 options_parse_post(&opt);
357 if(priv_init(&priv, opt.username_, opt.groupname_)) {
365 log_printf(ERROR, "error on crpyto initialization, exitting");
372 ret = tun_init(&dev, opt.dev_name_, opt.dev_type_, opt.ifconfig_param_.net_addr_, opt.ifconfig_param_.prefix_length_);
374 log_printf(ERROR, "error on tun_init, exitting");
379 log_printf(NOTICE, "dev of type '%s' opened, actual name is '%s'", tun_get_type_string(&dev), dev.actual_name_);
381 if(opt.post_up_script_) {
382 log_printf(NOTICE, "executing post-up script '%s'", opt.post_up_script_);
383 char* const argv[] = { opt.post_up_script_, dev.actual_name_, NULL };
384 char* const evp[] = { NULL };
385 uanytun_exec(opt.post_up_script_, argv, evp);
390 ret = udp_init(&sock, opt.local_addr_, opt.local_port_, opt.resolv_addr_type_);
392 log_printf(ERROR, "error on udp_init, exitting");
400 udp_resolv_remote(&sock, opt.remote_addr_, opt.remote_port_, opt.resolv_addr_type_);
403 FILE* pid_file = NULL;
405 pid_file = fopen(opt.pid_file_, "w");
407 log_printf(WARNING, "unable to open pid file: %s", strerror(errno));
412 if(do_chroot(opt.chroot_dir_)) {
420 if(priv_drop(&priv)) {
429 pid_t oldpid = getpid();
431 log_printf(INFO, "running in background now (old pid: %d)", oldpid);
435 pid_t pid = getpid();
436 fprintf(pid_file, "%d", pid);
440 ret = main_loop(&dev, &sock, &opt);
447 log_printf(NOTICE, "normal shutdown");
449 log_printf(NOTICE, "shutdown after error");
451 log_printf(NOTICE, "shutdown after signal");