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