Update debian/rules; Add post{inst,rm}; Bump Standards-Version; Add adduser to Depend...
[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 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.
16  *  
17  *
18  *  Copyright (C) 2007-2008 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
36 #include "datatypes.h"
37
38 #include <stdlib.h>
39 #include <stdio.h>
40 #include <string.h>
41 #include <errno.h>
42
43 #include "log.h"
44 #include "sig_handler.h"
45 #include "options.h"
46
47 #include "tun.h"
48 #include "udp.h"
49
50 #include "plain_packet.h"
51 #include "encrypted_packet.h"
52
53 #include "seq_window.h"
54
55 #include "cipher.h"
56 #ifndef NO_CRYPT
57 #include "key_derivation.h"
58 #include "auth_algo.h"
59
60 #ifndef USE_SSL_CRYPTO
61 #include <gcrypt.h>
62 #endif
63 #endif
64
65
66 #include "daemon.h"
67 #include "sysexec.h"
68
69 #ifndef NO_CRYPT
70 #ifndef USE_SSL_CRYPTO
71
72 #define MIN_GCRYPT_VERSION "1.2.0"
73
74 int init_libgcrypt()
75 {
76   if(!gcry_check_version(MIN_GCRYPT_VERSION)) {
77     log_printf(NOTICE, "invalid Version of libgcrypt, should be >= %s", MIN_GCRYPT_VERSION);
78     return -1;
79   }
80
81   gcry_error_t err = gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
82   if(err) {
83     log_printf(ERROR, "failed to disable secure memory: %s", gcry_strerror(err));
84     return -1;
85   }
86
87   err = gcry_control(GCRYCTL_INITIALIZATION_FINISHED);
88   if(err) {
89     log_printf(ERROR, "failed to finish libgcrypt initialization: %s", gcry_strerror(err));
90     return -1;
91   }
92
93   log_printf(NOTICE, "libgcrypt init finished");
94   return 0;
95 }
96 #endif
97 #endif
98
99 #ifdef NO_CRYPT
100 typedef u_int8_t auth_algo_t;
101 #endif
102
103 int init_main_loop(options_t* opt, cipher_t* c, auth_algo_t* aa, key_derivation_t* kd, seq_win_t* seq_win)
104 {
105   int ret = cipher_init(c, opt->cipher_);
106   if(ret) {
107     log_printf(ERROR, "could not initialize cipher of type %s", opt->cipher_);
108     return ret;
109   }
110   
111 #ifndef NO_CRYPT
112   ret = auth_algo_init(aa, opt->auth_algo_);
113   if(ret) {
114     log_printf(ERROR, "could not initialize auth algo of type %s", opt->auth_algo_);
115     cipher_close(c);
116     return ret;
117   }
118
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_);
120   if(ret) {
121     log_printf(ERROR, "could not initialize key derivation of type %s", opt->kd_prf_);
122     cipher_close(c);
123     auth_algo_close(aa);
124     return ret;
125   }
126 #endif
127
128   ret = seq_win_init(seq_win, opt->seq_window_size_);
129   if(ret) {
130     printf("could not initialize sequence window");
131     cipher_close(c);
132 #ifndef NO_CRYPT
133     auth_algo_close(aa);
134     key_derivation_close(kd);
135 #endif
136     return ret;
137   }
138   return 0;
139 }
140
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)
143 {
144   plain_packet_set_payload_length(plain_packet, -1);
145   encrypted_packet_set_length(encrypted_packet, -1);
146
147   int len = tun_read(dev, plain_packet_get_payload(plain_packet), plain_packet_get_payload_length(plain_packet));
148   if(len == -1) {
149     log_printf(ERROR, "error on reading from device: %s", strerror(errno));
150     return 0;
151   }
152   
153   plain_packet_set_payload_length(plain_packet, len);
154   
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);    
159   else
160     plain_packet_set_type(plain_packet, PAYLOAD_TYPE_UNKNOWN);
161
162   if(!sock->remote_end_set_)
163     return 0;
164   
165   cipher_encrypt(c, kd, kd_outbound, plain_packet, encrypted_packet, seq_nr, opt->sender_id_, opt->mux_); 
166   
167 #ifndef NO_CRYPT
168   auth_algo_generate(aa, kd, kd_outbound, encrypted_packet);
169 #endif
170   
171   len = udp_write(sock, encrypted_packet_get_packet(encrypted_packet), encrypted_packet_get_length(encrypted_packet));
172   if(len == -1)
173     log_printf(ERROR, "error on sending udp packet: %s", strerror(errno));
174
175   return 0;
176 }
177
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)
180 {
181   plain_packet_set_payload_length(plain_packet, -1);
182   encrypted_packet_set_length(encrypted_packet, -1);
183
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);
187   if(len == -1) {
188     log_printf(ERROR, "error on receiving udp packet: %s", strerror(errno));
189     return 0;
190   }
191   else if(len < encrypted_packet_get_minimum_length(encrypted_packet)) {
192     log_printf(WARNING, "received packet is to short");
193     return 0;
194   }
195   encrypted_packet_set_length(encrypted_packet, len);
196
197 #ifndef NO_CRYPT
198   if(!auth_algo_check_tag(aa, kd, kd_inbound, encrypted_packet)) {
199     log_printf(WARNING, "wrong authentication tag, discarding packet");
200     return 0;
201   }
202 #endif
203   
204   if(encrypted_packet_get_mux(encrypted_packet) != opt->mux_) {
205     log_printf(WARNING, "wrong mux value, discarding packet");
206     return 0;
207   }
208   
209   int result = seq_win_check_and_add(seq_win, encrypted_packet_get_sender_id(encrypted_packet), encrypted_packet_get_seq_nr(encrypted_packet));
210   if(result > 0) {
211     log_printf(WARNING, "detected replay attack, discarding packet");
212     return 0;
213   }
214   else if(result < 0) {
215     log_printf(ERROR, "memory error at sequence window");
216     return -2;
217   }
218    
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);
224     free(addrstring);
225   }
226
227   if(encrypted_packet_get_payload_length(encrypted_packet) <= plain_packet_get_header_length()) {
228     log_printf(WARNING, "ignoring packet with zero length payload");
229     return 0;
230   }
231
232   int ret = cipher_decrypt(c, kd, kd_inbound, encrypted_packet, plain_packet); 
233   if(ret) 
234     return ret;
235  
236   len = tun_write(dev, plain_packet_get_payload(plain_packet), plain_packet_get_payload_length(plain_packet));
237   if(len == -1)
238     log_printf(ERROR, "error on writing to device: %s", strerror(errno));
239   
240   return 0;
241 }
242
243
244 int main_loop(tun_device_t* dev, udp_socket_t* sock, options_t* opt)
245 {
246   log_printf(INFO, "entering main loop");
247
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_);
252   seq_nr_t seq_nr = 0;
253   fd_set readfds, readyfds;
254
255   cipher_t c;
256   auth_algo_t aa;
257   key_derivation_t kd;
258   seq_win_t seq_win;
259
260   int ret = init_main_loop(opt, &c, &aa, &kd, &seq_win);
261   if(ret)
262     return ret;
263
264   FD_ZERO(&readfds);
265   FD_SET(dev->fd_, &readfds);
266   FD_SET(sock->fd_, &readfds);
267   int nfds = dev->fd_ > sock->fd_ ? dev->fd_ : sock->fd_;
268
269   int return_value = 0;
270   int sig_fd = signal_init();
271   if(sig_fd < 0)
272     return_value -1;
273
274   FD_SET(sig_fd, &readfds);
275   nfds = (nfds < sig_fd) ? sig_fd : nfds;
276
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));
282       return_value = -1;
283       break;
284     }
285     if(!ret || ret == -1)
286       continue;
287
288     if(FD_ISSET(sig_fd, &readyfds)) {
289       if(signal_handle()) {
290         return_value = 1;
291         break;
292       }
293     }
294
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);
297       seq_nr++;
298       if(return_value)
299         break;
300     }
301
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); 
304       if(return_value)
305         break;
306     }
307   }
308
309   cipher_close(&c);
310 #ifndef NO_CRYPT
311   auth_algo_close(&aa);
312   key_derivation_close(&kd);
313 #endif
314   seq_win_clear(&seq_win);
315   signal_stop();
316
317   return return_value;
318 }
319
320 int main(int argc, char* argv[])
321 {
322   log_init();
323
324   options_t opt;
325   int ret = options_parse(&opt, argc, argv);
326   if(ret) {
327     if(ret > 0) {
328       fprintf(stderr, "syntax error near: %s\n\n", argv[ret]);
329     }
330     if(ret == -2) {
331       fprintf(stderr, "memory error on options_parse, exitting\n");
332     }
333     if(ret == -3) {
334       fprintf(stderr, "syntax error: -4 and -6 are mutual exclusive\n\n");
335     }
336     if(ret == -4) {
337       fprintf(stderr, "syntax error: unknown role name\n\n");
338     }
339
340     if(ret != -2) 
341       options_print_usage();
342
343     options_clear(&opt);
344     log_close();
345     exit(ret);
346   }
347   string_list_element_t* tmp = opt.log_targets_.first_;
348   if(!tmp) {
349     log_add_target("syslog:3,uanytun,daemon");
350   }
351   else {
352     while(tmp) {
353       ret = log_add_target(tmp->string_);
354       if(ret) {
355         switch(ret) {
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;
360         }
361         
362         options_clear(&opt);
363         log_close();
364         exit(ret);
365       }
366       tmp = tmp->next_;
367     }
368   }
369
370   log_printf(NOTICE, "just started...");
371   options_parse_post(&opt);
372
373   priv_info_t priv;
374   if(opt.username_)
375     if(priv_init(&priv, opt.username_, opt.groupname_)) {
376       options_clear(&opt);
377       log_close();
378       exit(-1);
379     }
380
381 #ifndef NO_CRYPT
382 #ifndef USE_SSL_CRYPTO
383   ret = init_libgcrypt();
384   if(ret) {
385     log_printf(ERROR, "error on libgcrpyt initialization, exitting");
386     options_clear(&opt);
387     log_close();
388     exit(ret);
389   }
390 #endif
391 #endif
392
393   tun_device_t dev;
394   ret = tun_init(&dev, opt.dev_name_, opt.dev_type_, opt.ifconfig_param_.net_addr_, opt.ifconfig_param_.prefix_length_);
395   if(ret) {
396     log_printf(ERROR, "error on tun_init, exitting");
397     options_clear(&opt);
398     log_close();
399     exit(ret);
400   }
401   log_printf(NOTICE, "dev of type '%s' opened, actual name is '%s'", tun_get_type_string(&dev), dev.actual_name_);
402
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);
408   }
409
410
411   udp_socket_t sock;
412   ret = udp_init(&sock, opt.local_addr_, opt.local_port_, opt.resolv_addr_type_);
413   if(ret) {
414     log_printf(ERROR, "error on udp_init, exitting");
415     tun_close(&dev);
416     options_clear(&opt);
417     log_close();
418     exit(ret);
419   }
420   char* local_string = udp_get_local_end_string(&sock);
421   if(local_string) {
422     log_printf(NOTICE, "listening on: %s", local_string);
423     free(local_string);
424   }
425
426
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);
430       if(remote_string) {
431         log_printf(NOTICE, "set remote end to: %s", remote_string);
432         free(remote_string);
433       }
434     }
435   }
436
437
438   FILE* pid_file = NULL;
439   if(opt.pid_file_) {
440     pid_file = fopen(opt.pid_file_, "w");
441     if(!pid_file) {
442       log_printf(WARNING, "unable to open pid file: %s", strerror(errno));
443     }
444   }
445
446   if(opt.chroot_dir_)
447     if(do_chroot(opt.chroot_dir_)) {
448       tun_close(&dev);
449       udp_close(&sock);
450       options_clear(&opt);
451       log_close();
452       exit(-1);
453     }
454   if(opt.username_)
455     if(priv_drop(&priv)) {
456       tun_close(&dev);
457       udp_close(&sock);
458       options_clear(&opt);
459       log_close();
460       exit(-1);
461     }  
462
463   if(opt.daemonize_) {
464     pid_t oldpid = getpid();
465     daemonize();
466     log_printf(INFO, "running in background now (old pid: %d)", oldpid);
467   }
468
469   if(pid_file) {
470     pid_t pid = getpid();
471     fprintf(pid_file, "%d", pid);
472     fclose(pid_file);
473   }
474
475   ret = main_loop(&dev, &sock, &opt);
476
477   tun_close(&dev);
478   udp_close(&sock);
479   options_clear(&opt);
480
481   if(!ret)
482     log_printf(NOTICE, "normal shutdown");
483   else if(ret < 0)
484     log_printf(NOTICE, "shutdown after error");
485   else
486     log_printf(NOTICE, "shutdown after signal");
487
488   log_close();
489
490   return ret;
491 }