c9c6c443349a5de381fad75eff00dbbba8219981
[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 version 3 as
24  *  published by the Free Software Foundation.
25  *
26  *  uAnytun is distributed in the hope that it will be useful,
27  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
28  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
29  *  GNU General Public License for more details.
30  *
31  *  You should have received a copy of the GNU General Public License
32  *  along with uAnytun. If not, see <http://www.gnu.org/licenses/>.
33  */
34
35 #include "datatypes.h"
36
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include <errno.h>
41
42 #include "log.h"
43 #include "sig_handler.h"
44 #include "options.h"
45
46 #include "tun.h"
47 #include "udp.h"
48
49 #include "plain_packet.h"
50 #include "encrypted_packet.h"
51
52 #include "seq_window.h"
53
54 #include "cipher.h"
55 #ifndef NO_CRYPT
56 #include "key_derivation.h"
57 #include "auth_algo.h"
58
59 #ifndef USE_SSL_CRYPTO
60 #include <gcrypt.h>
61 #endif
62 #endif
63
64
65 #include "daemon.h"
66 #include "sysexec.h"
67
68 #ifndef NO_CRYPT
69 #ifndef USE_SSL_CRYPTO
70
71 #define MIN_GCRYPT_VERSION "1.2.0"
72
73 int init_libgcrypt()
74 {
75   if(!gcry_check_version(MIN_GCRYPT_VERSION)) {
76     log_printf(NOTICE, "invalid Version of libgcrypt, should be >= %s", MIN_GCRYPT_VERSION);
77     return -1;
78   }
79
80   gcry_error_t err = gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
81   if(err) {
82     log_printf(ERROR, "failed to disable secure memory: %s", gcry_strerror(err));
83     return -1;
84   }
85
86   err = gcry_control(GCRYCTL_INITIALIZATION_FINISHED);
87   if(err) {
88     log_printf(ERROR, "failed to finish libgcrypt initialization: %s", gcry_strerror(err));
89     return -1;
90   }
91
92   log_printf(NOTICE, "libgcrypt init finished");
93   return 0;
94 }
95 #endif
96 #endif
97
98 #ifdef NO_CRYPT
99 typedef u_int8_t auth_algo_t;
100 #endif
101
102 int init_main_loop(options_t* opt, cipher_t* c, auth_algo_t* aa, key_derivation_t* kd, seq_win_t* seq_win)
103 {
104   int ret = cipher_init(c, opt->cipher_);
105   if(ret) {
106     log_printf(ERROR, "could not initialize cipher of type %s", opt->cipher_);
107     return ret;
108   }
109   
110 #ifndef NO_CRYPT
111   ret = auth_algo_init(aa, opt->auth_algo_);
112   if(ret) {
113     log_printf(ERROR, "could not initialize auth algo of type %s", opt->auth_algo_);
114     cipher_close(c);
115     return ret;
116   }
117
118   ret = key_derivation_init(kd, opt->kd_prf_, opt->role_, opt->passphrase_, opt->key_.buf_, opt->key_.length_, opt->salt_.buf_, opt->salt_.length_);
119   if(ret) {
120     log_printf(ERROR, "could not initialize key derivation of type %s", opt->kd_prf_);
121     cipher_close(c);
122     auth_algo_close(aa);
123     return ret;
124   }
125 #endif
126
127   ret = seq_win_init(seq_win, opt->seq_window_size_);
128   if(ret) {
129     printf("could not initialize sequence window");
130     cipher_close(c);
131 #ifndef NO_CRYPT
132     auth_algo_close(aa);
133     key_derivation_close(kd);
134 #endif
135     return ret;
136   }
137   return 0;
138 }
139
140 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,
141                      cipher_t* c, auth_algo_t* aa, key_derivation_t* kd, seq_nr_t seq_nr)
142 {
143   plain_packet_set_payload_length(plain_packet, -1);
144   encrypted_packet_set_length(encrypted_packet, -1);
145
146   int len = tun_read(dev, plain_packet_get_payload(plain_packet), plain_packet_get_payload_length(plain_packet));
147   if(len == -1) {
148     log_printf(ERROR, "error on reading from device: %s", strerror(errno));
149     return 0;
150   }
151   
152   plain_packet_set_payload_length(plain_packet, len);
153   
154   if(dev->type_ == TYPE_TUN)
155     plain_packet_set_type(plain_packet, PAYLOAD_TYPE_TUN);
156   else if(dev->type_ == TYPE_TAP)
157     plain_packet_set_type(plain_packet, PAYLOAD_TYPE_TAP);    
158   else
159     plain_packet_set_type(plain_packet, PAYLOAD_TYPE_UNKNOWN);
160
161   if(!sock->remote_end_set_)
162     return 0;
163   
164   cipher_encrypt(c, kd, kd_outbound, plain_packet, encrypted_packet, seq_nr, opt->sender_id_, opt->mux_); 
165   
166 #ifndef NO_CRYPT
167   auth_algo_generate(aa, kd, kd_outbound, encrypted_packet);
168 #endif
169   
170   len = udp_write(sock, encrypted_packet_get_packet(encrypted_packet), encrypted_packet_get_length(encrypted_packet));
171   if(len == -1)
172     log_printf(ERROR, "error on sending udp packet: %s", strerror(errno));
173
174   return 0;
175 }
176
177 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,
178                       cipher_t* c, auth_algo_t* aa, key_derivation_t* kd, seq_win_t* seq_win)
179 {
180   plain_packet_set_payload_length(plain_packet, -1);
181   encrypted_packet_set_length(encrypted_packet, -1);
182
183   udp_endpoint_t remote;
184   memset(&remote, 0, sizeof(udp_endpoint_t));
185   int len = udp_read(sock, encrypted_packet_get_packet(encrypted_packet), encrypted_packet_get_length(encrypted_packet), &remote);
186   if(len == -1) {
187     log_printf(ERROR, "error on receiving udp packet: %s", strerror(errno));
188     return 0;
189   }
190   else if(len < encrypted_packet_get_minimum_length(encrypted_packet)) {
191     log_printf(WARNING, "received packet is to short");
192     return 0;
193   }
194   encrypted_packet_set_length(encrypted_packet, len);
195
196 #ifndef NO_CRYPT
197   if(!auth_algo_check_tag(aa, kd, kd_inbound, encrypted_packet)) {
198     log_printf(WARNING, "wrong authentication tag, discarding packet");
199     return 0;
200   }
201 #endif
202   
203   if(encrypted_packet_get_mux(encrypted_packet) != opt->mux_) {
204     log_printf(WARNING, "wrong mux value, discarding packet");
205     return 0;
206   }
207   
208   int result = seq_win_check_and_add(seq_win, encrypted_packet_get_sender_id(encrypted_packet), encrypted_packet_get_seq_nr(encrypted_packet));
209   if(result > 0) {
210     log_printf(WARNING, "detected replay attack, discarding packet");
211     return 0;
212   }
213   else if(result < 0) {
214     log_printf(ERROR, "memory error at sequence window");
215     return -2;
216   }
217    
218   if(memcmp(&remote, &(sock->remote_end_), sizeof(remote))) {
219     memcpy(&(sock->remote_end_), &remote, sizeof(remote));
220     sock->remote_end_set_ = 1;
221     char* addrstring = udp_endpoint_to_string(remote);
222     log_printf(NOTICE, "autodetected remote host changed %s", addrstring);
223     free(addrstring);
224   }
225
226   if(encrypted_packet_get_payload_length(encrypted_packet) <= plain_packet_get_header_length()) {
227     log_printf(WARNING, "ignoring packet with zero length payload");
228     return 0;
229   }
230
231   int ret = cipher_decrypt(c, kd, kd_inbound, encrypted_packet, plain_packet); 
232   if(ret) 
233     return ret;
234  
235   len = tun_write(dev, plain_packet_get_payload(plain_packet), plain_packet_get_payload_length(plain_packet));
236   if(len == -1)
237     log_printf(ERROR, "error on writing to device: %s", strerror(errno));
238   
239   return 0;
240 }
241
242
243 int main_loop(tun_device_t* dev, udp_socket_t* sock, options_t* opt)
244 {
245   log_printf(INFO, "entering main loop");
246
247   plain_packet_t plain_packet;
248   plain_packet_init(&plain_packet);
249   encrypted_packet_t encrypted_packet;
250   encrypted_packet_init(&encrypted_packet, opt->auth_tag_length_);
251   seq_nr_t seq_nr = 0;
252   fd_set readfds;
253
254   cipher_t c;
255   auth_algo_t aa;
256   key_derivation_t kd;
257   seq_win_t seq_win;
258
259   int ret = init_main_loop(opt, &c, &aa, &kd, &seq_win);
260   if(ret)
261     return ret;
262
263   signal_init();
264   int return_value = 0;
265   while(!return_value) {
266     FD_ZERO(&readfds);
267     FD_SET(dev->fd_, &readfds);
268     FD_SET(sock->fd_, &readfds);
269     int nfds = dev->fd_ > sock->fd_ ? dev->fd_+1 : sock->fd_+1;
270
271     int ret = select(nfds, &readfds, NULL, NULL, NULL);
272     if(ret == -1 && errno != EINTR) {
273       log_printf(ERROR, "select returned with error: %s", strerror(errno));
274       return_value = -1;
275       break;
276     }
277     if(!ret)
278       continue;
279
280     if(signal_exit) {
281       return_value = 1;
282       break;
283     }
284
285     if(FD_ISSET(dev->fd_, &readfds)) {
286       return_value = process_tun_data(dev, sock, opt, &plain_packet, &encrypted_packet, &c, &aa, &kd, seq_nr);
287       seq_nr++;
288       if(return_value)
289         break;
290     }
291
292     if(FD_ISSET(sock->fd_, &readfds)) {
293       return_value = process_sock_data(dev, sock, opt, &plain_packet, &encrypted_packet, &c, &aa, &kd, &seq_win); 
294       if(return_value)
295         break;
296     }
297   }
298
299   cipher_close(&c);
300 #ifndef NO_CRYPT
301   auth_algo_close(&aa);
302   key_derivation_close(&kd);
303 #endif
304   seq_win_clear(&seq_win);
305
306   return return_value;
307 }
308
309 int main(int argc, char* argv[])
310 {
311   log_init();
312
313   options_t opt;
314   int ret = options_parse(&opt, argc, argv);
315   if(ret) {
316     if(ret > 0) {
317       fprintf(stderr, "syntax error near: %s\n\n", argv[ret]);
318     }
319     if(ret == -2) {
320       fprintf(stderr, "memory error on options_parse, exitting\n");
321     }
322     if(ret == -3) {
323       fprintf(stderr, "syntax error: -4 and -6 are mutual exclusive\n\n");
324     }
325     if(ret == -4) {
326       fprintf(stderr, "syntax error: unknown role name\n\n");
327     }
328
329     if(ret != -2) 
330       options_print_usage();
331
332     options_clear(&opt);
333     log_close();
334     exit(ret);
335   }
336   string_list_element_t* tmp = opt.log_targets_.first_;
337   if(!tmp) {
338     log_add_target("syslog:3,uanytun,daemon");
339   }
340   else {
341     while(tmp) {
342       ret = log_add_target(tmp->string_);
343       if(ret) {
344         switch(ret) {
345         case -2: fprintf(stderr, "memory error on log_add_target, exitting\n"); break;
346         case -3: fprintf(stderr, "unknown log target: '%s', exitting\n", tmp->string_); break;
347         case -4: fprintf(stderr, "this log target is only allowed once: '%s', exitting\n", tmp->string_); break;
348         default: fprintf(stderr, "syntax error near: '%s', exitting\n", tmp->string_); break;
349         }
350         
351         options_clear(&opt);
352         log_close();
353         exit(ret);
354       }
355       tmp = tmp->next_;
356     }
357   }
358
359   log_printf(NOTICE, "just started...");
360   options_parse_post(&opt);
361
362   priv_info_t priv;
363   if(opt.username_)
364     if(priv_init(&priv, opt.username_, opt.groupname_)) {
365       options_clear(&opt);
366       log_close();
367       exit(-1);
368     }
369
370 #ifndef NO_CRYPT
371 #ifndef USE_SSL_CRYPTO
372   ret = init_libgcrypt();
373   if(ret) {
374     log_printf(ERROR, "error on libgcrpyt initialization, exitting");
375     options_clear(&opt);
376     log_close();
377     exit(ret);
378   }
379 #endif
380 #endif
381
382   tun_device_t dev;
383   ret = tun_init(&dev, opt.dev_name_, opt.dev_type_, opt.ifconfig_param_.net_addr_, opt.ifconfig_param_.prefix_length_);
384   if(ret) {
385     log_printf(ERROR, "error on tun_init, exitting");
386     options_clear(&opt);
387     log_close();
388     exit(ret);
389   }
390   log_printf(NOTICE, "dev of type '%s' opened, actual name is '%s'", tun_get_type_string(&dev), dev.actual_name_);
391
392   if(opt.post_up_script_) {
393     log_printf(NOTICE, "executing post-up script '%s'", opt.post_up_script_);
394     int ret = exec_script(opt.post_up_script_, dev.actual_name_);
395   }
396
397
398   udp_socket_t sock;
399   ret = udp_init(&sock, opt.local_addr_, opt.local_port_, opt.resolv_addr_type_);
400   if(ret) {
401     log_printf(ERROR, "error on udp_init, exitting");
402     tun_close(&dev);
403     options_clear(&opt);
404     log_close();
405     exit(ret);
406   }
407   char* local_string = udp_get_local_end_string(&sock);
408   if(local_string) {
409     log_printf(NOTICE, "listening on: %s", local_string);
410     free(local_string);
411   }
412
413
414   if(opt.remote_addr_) {
415     if(!udp_set_remote(&sock, opt.remote_addr_, opt.remote_port_, opt.resolv_addr_type_)) {
416       char* remote_string = udp_get_remote_end_string(&sock);
417       if(remote_string) {
418         log_printf(NOTICE, "set remote end to: %s", remote_string);
419         free(remote_string);
420       }
421     }
422   }
423
424
425   FILE* pid_file = NULL;
426   if(opt.pid_file_) {
427     pid_file = fopen(opt.pid_file_, "w");
428     if(!pid_file) {
429       log_printf(WARNING, "unable to open pid file: %s", strerror(errno));
430     }
431   }
432
433   if(opt.chroot_dir_)
434     if(do_chroot(opt.chroot_dir_)) {
435       tun_close(&dev);
436       udp_close(&sock);
437       options_clear(&opt);
438       log_close();
439       exit(-1);
440     }
441   if(opt.username_)
442     if(priv_drop(&priv)) {
443       tun_close(&dev);
444       udp_close(&sock);
445       options_clear(&opt);
446       log_close();
447       exit(-1);
448     }  
449
450   if(opt.daemonize_) {
451     pid_t oldpid = getpid();
452     daemonize();
453     log_printf(INFO, "running in background now (old pid: %d)", oldpid);
454   }
455
456   if(pid_file) {
457     pid_t pid = getpid();
458     fprintf(pid_file, "%d", pid);
459     fclose(pid_file);
460   }
461
462   ret = main_loop(&dev, &sock, &opt);
463
464   tun_close(&dev);
465   udp_close(&sock);
466   options_clear(&opt);
467
468   if(!ret)
469     log_printf(NOTICE, "normal shutdown");
470   else if(ret < 0)
471     log_printf(NOTICE, "shutdown after error");
472   else
473     log_printf(NOTICE, "shutdown after signal");
474
475   log_close();
476
477   return ret;
478 }