159f77359fa1716e254e2bd62ac0b67864173f6f
[debian/uanytun.git] / src / uanytun.c
1 /*
2  *  uAnytun
3  *
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.
16  *
17  *
18  *  Copyright (C) 2007-2014 Christian Pointner <equinox@anytun.org>
19  *
20  *  This file is part of uAnytun.
21  *
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
25  *  any later version.
26  *
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.
31  *
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/>.
34  *
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
39  *  including the two.
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.
47  */
48
49 #include "datatypes.h"
50
51 #include <stdlib.h>
52 #include <stdio.h>
53 #include <string.h>
54 #include <errno.h>
55
56 #include "log.h"
57 #include "sig_handler.h"
58 #include "options.h"
59
60 #include "tun.h"
61 #include "udp.h"
62
63 #include "plain_packet.h"
64 #include "encrypted_packet.h"
65
66 #include "seq_window.h"
67
68 #include "cipher.h"
69 #ifndef NO_CRYPT
70 #include "key_derivation.h"
71 #include "auth_algo.h"
72 #else
73 typedef u_int8_t auth_algo_t;
74 #endif
75 #include "init_crypt.h"
76
77 #include "daemon.h"
78 #include "sysexec.h"
79
80
81 int init_main_loop(options_t* opt, cipher_t* c, auth_algo_t* aa, key_derivation_t* kd, seq_win_t* seq_win)
82 {
83   int ret = cipher_init(c, opt->cipher_);
84   if(ret) {
85     log_printf(ERROR, "could not initialize cipher of type %s", opt->cipher_);
86     return ret;
87   }
88
89 #ifndef NO_CRYPT
90   ret = auth_algo_init(aa, opt->auth_algo_);
91   if(ret) {
92     log_printf(ERROR, "could not initialize auth algo of type %s", opt->auth_algo_);
93     cipher_close(c);
94     return ret;
95   }
96
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_);
98   if(ret) {
99     log_printf(ERROR, "could not initialize key derivation of type %s", opt->kd_prf_);
100     cipher_close(c);
101     auth_algo_close(aa);
102     return ret;
103   }
104 #endif
105
106   ret = seq_win_init(seq_win, opt->seq_window_size_);
107   if(ret) {
108     printf("could not initialize sequence window");
109     cipher_close(c);
110 #ifndef NO_CRYPT
111     auth_algo_close(aa);
112     key_derivation_close(kd);
113 #endif
114     return ret;
115   }
116   return 0;
117 }
118
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)
121 {
122   plain_packet_set_payload_length(plain_packet, -1);
123   encrypted_packet_set_length(encrypted_packet, -1);
124
125   int len = tun_read(dev, plain_packet_get_payload(plain_packet), plain_packet_get_payload_length(plain_packet));
126   if(len == -1) {
127     log_printf(ERROR, "error on reading from device: %s", strerror(errno));
128     return 0;
129   }
130
131   plain_packet_set_payload_length(plain_packet, len);
132
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);
137   else
138     plain_packet_set_type(plain_packet, PAYLOAD_TYPE_UNKNOWN);
139
140   if(!udp_has_remote(sock))
141     return 0;
142
143   cipher_encrypt(c, kd, kd_outbound, plain_packet, encrypted_packet, *seq_nr, opt->sender_id_, opt->mux_);
144   (*seq_nr)++;
145 #ifndef NO_CRYPT
146   auth_algo_generate(aa, kd, kd_outbound, encrypted_packet);
147 #endif
148
149   len = udp_write(sock, encrypted_packet_get_packet(encrypted_packet), encrypted_packet_get_length(encrypted_packet));
150   if(len == -1)
151     log_printf(ERROR, "error on sending udp packet: %s", strerror(errno));
152
153   return 0;
154 }
155
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)
158 {
159   plain_packet_set_payload_length(plain_packet, -1);
160   encrypted_packet_set_length(encrypted_packet, -1);
161
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);
166   if(len == -1) {
167     log_printf(ERROR, "error on receiving udp packet: %s", strerror(errno));
168     return 0;
169   } else if(len < encrypted_packet_get_minimum_length(encrypted_packet)) {
170     log_printf(WARNING, "received packet is too short");
171     return 0;
172   }
173   encrypted_packet_set_length(encrypted_packet, len);
174
175   if(encrypted_packet_get_mux(encrypted_packet) != opt->mux_) {
176     log_printf(WARNING, "wrong mux value, discarding packet");
177     return 0;
178   }
179
180 #ifndef NO_CRYPT
181   if(!auth_algo_check_tag(aa, kd, kd_inbound, encrypted_packet)) {
182     log_printf(WARNING, "wrong authentication tag, discarding packet");
183     return 0;
184   }
185 #endif
186
187   int result = seq_win_check_and_add(seq_win, encrypted_packet_get_sender_id(encrypted_packet), encrypted_packet_get_seq_nr(encrypted_packet));
188   if(result > 0) {
189     log_printf(WARNING, "detected replay attack, discarding packet");
190     return 0;
191   } else if(result < 0) {
192     log_printf(ERROR, "memory error at sequence window");
193     return -2;
194   }
195
196   udp_update_remote(sock, fd, &remote);
197
198   if(encrypted_packet_get_payload_length(encrypted_packet) <= plain_packet_get_header_length()) {
199     log_printf(WARNING, "ignoring packet with zero length payload");
200     return 0;
201   }
202
203   int ret = cipher_decrypt(c, kd, kd_inbound, encrypted_packet, plain_packet);
204   if(ret)
205     return ret;
206
207   len = tun_write(dev, plain_packet_get_payload(plain_packet), plain_packet_get_payload_length(plain_packet));
208   if(len == -1)
209     log_printf(ERROR, "error on writing to device: %s", strerror(errno));
210
211   return 0;
212 }
213
214
215 int main_loop(tun_device_t* dev, udp_t* sock, options_t* opt)
216 {
217   log_printf(INFO, "entering main loop");
218
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_);
223   seq_nr_t seq_nr = 0;
224   fd_set readfds, readyfds;
225
226   cipher_t c;
227   auth_algo_t aa;
228   key_derivation_t kd;
229   seq_win_t seq_win;
230
231   int ret = init_main_loop(opt, &c, &aa, &kd, &seq_win);
232   if(ret)
233     return ret;
234
235   FD_ZERO(&readfds);
236   FD_SET(dev->fd_, &readfds);
237   int nfds = udp_fill_fd_set(sock, &readfds);
238   nfds = dev->fd_ > nfds ? dev->fd_ : nfds;
239
240   int return_value = 0;
241   int sig_fd = signal_init();
242   if(sig_fd < 0)
243     return_value = -1;
244
245   FD_SET(sig_fd, &readfds);
246   nfds = (nfds < sig_fd) ? sig_fd : nfds;
247
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));
253       return_value = -1;
254       break;
255     }
256     if(!ret || ret == -1)
257       continue;
258
259     if(FD_ISSET(sig_fd, &readyfds)) {
260       return_value = signal_handle();
261       if(return_value == 1)
262         break;
263       else if(return_value == 2) {
264         seq_win_clear(&seq_win);
265         seq_nr = 0;
266         log_printf(NOTICE, "sequence window cleared");
267         return_value = 0;
268       }
269       else
270         return_value = 0;
271     }
272
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);
275       if(return_value)
276         break;
277     }
278
279     udp_socket_t* s = sock->socks_;
280     while(s) {
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);
283         if(return_value)
284           break;
285       }
286       s = s->next_;
287     }
288   }
289
290   cipher_close(&c);
291 #ifndef NO_CRYPT
292   auth_algo_close(&aa);
293   key_derivation_close(&kd);
294 #endif
295   seq_win_clear(&seq_win);
296   signal_stop();
297
298   return return_value;
299 }
300
301 int main(int argc, char* argv[])
302 {
303   log_init();
304
305   options_t opt;
306   int ret = options_parse(&opt, argc, argv);
307   if(ret) {
308     if(ret > 0) {
309       fprintf(stderr, "syntax error near: %s\n\n", argv[ret]);
310     }
311     if(ret == -2) {
312       fprintf(stderr, "memory error on options_parse, exitting\n");
313     }
314     if(ret == -3) {
315       fprintf(stderr, "syntax error: -4 and -6 are mutual exclusive\n\n");
316     }
317     if(ret == -4) {
318       fprintf(stderr, "syntax error: unknown role name\n\n");
319     }
320     if(ret == -5) {
321       options_print_version();
322     }
323
324     if(ret != -2 && ret != -5)
325       options_print_usage();
326
327     if(ret == -1 || ret == -5)
328       ret = 0;
329
330     options_clear(&opt);
331     log_close();
332     exit(ret);
333   }
334   string_list_element_t* tmp = opt.log_targets_.first_;
335   while(tmp) {
336     ret = log_add_target(tmp->string_);
337     if(ret) {
338       switch(ret) {
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;
343       }
344
345       options_clear(&opt);
346       log_close();
347       exit(ret);
348     }
349     tmp = tmp->next_;
350   }
351
352   log_printf(NOTICE, "just started...");
353   options_parse_post(&opt);
354
355   priv_info_t priv;
356   if(opt.username_)
357     if(priv_init(&priv, opt.username_, opt.groupname_)) {
358       options_clear(&opt);
359       log_close();
360       exit(-1);
361     }
362
363   ret = init_crypt();
364   if(ret) {
365     log_printf(ERROR, "error on crpyto initialization, exitting");
366     options_clear(&opt);
367     log_close();
368     exit(ret);
369   }
370
371   tun_device_t dev;
372   ret = tun_init(&dev, opt.dev_name_, opt.dev_type_, opt.ifconfig_param_.net_addr_, opt.ifconfig_param_.prefix_length_);
373   if(ret) {
374     log_printf(ERROR, "error on tun_init, exitting");
375     options_clear(&opt);
376     log_close();
377     exit(ret);
378   }
379   log_printf(NOTICE, "dev of type '%s' opened, actual name is '%s'", tun_get_type_string(&dev), dev.actual_name_);
380
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);
386   }
387
388
389   udp_t sock;
390   ret = udp_init(&sock, opt.local_addr_, opt.local_port_, opt.resolv_addr_type_);
391   if(ret) {
392     log_printf(ERROR, "error on udp_init, exitting");
393     tun_close(&dev);
394     options_clear(&opt);
395     log_close();
396     exit(ret);
397   }
398
399   if(opt.remote_addr_)
400     udp_resolv_remote(&sock, opt.remote_addr_, opt.remote_port_, opt.resolv_addr_type_);
401
402
403   FILE* pid_file = NULL;
404   if(opt.pid_file_) {
405     pid_file = fopen(opt.pid_file_, "w");
406     if(!pid_file) {
407       log_printf(WARNING, "unable to open pid file: %s", strerror(errno));
408     }
409   }
410
411   if(opt.chroot_dir_)
412     if(do_chroot(opt.chroot_dir_)) {
413       tun_close(&dev);
414       udp_close(&sock);
415       options_clear(&opt);
416       log_close();
417       exit(-1);
418     }
419   if(opt.username_)
420     if(priv_drop(&priv)) {
421       tun_close(&dev);
422       udp_close(&sock);
423       options_clear(&opt);
424       log_close();
425       exit(-1);
426     }
427
428   if(opt.daemonize_) {
429     pid_t oldpid = getpid();
430     daemonize();
431     log_printf(INFO, "running in background now (old pid: %d)", oldpid);
432   }
433
434   if(pid_file) {
435     pid_t pid = getpid();
436     fprintf(pid_file, "%d", pid);
437     fclose(pid_file);
438   }
439
440   ret = main_loop(&dev, &sock, &opt);
441
442   tun_close(&dev);
443   udp_close(&sock);
444   options_clear(&opt);
445
446   if(!ret)
447     log_printf(NOTICE, "normal shutdown");
448   else if(ret < 0)
449     log_printf(NOTICE, "shutdown after error");
450   else
451     log_printf(NOTICE, "shutdown after signal");
452
453   log_close();
454
455   return ret;
456 }