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