Imported Upstream version 0.3.2
[anytun.git] / src / anytun.cpp
1 /*
2  *  anytun
3  *
4  *  The secure anycast tunneling protocol (satp) defines a protocol used
5  *  for communication between any combination of unicast and anycast
6  *  tunnel endpoints.  It has less protocol overhead than IPSec in Tunnel
7  *  mode and allows tunneling of every ETHER TYPE protocol (e.g.
8  *  ethernet, ip, arp ...). satp directly includes cryptography and
9  *  message authentication based on the methodes used by SRTP.  It is
10  *  intended to deliver a generic, scaleable and secure solution for
11  *  tunneling and relaying of packets of any protocol.
12  *
13  *
14  *  Copyright (C) 2007-2009 Othmar Gsenger, Erwin Nindl, 
15  *                          Christian Pointner <satp@wirdorange.org>
16  *
17  *  This file is part of Anytun.
18  *
19  *  Anytun is free software: you can redistribute it and/or modify
20  *  it under the terms of the GNU General Public License as published by
21  *  the Free Software Foundation, either version 3 of the License, or
22  *  any later version.
23  *
24  *  Anytun is distributed in the hope that it will be useful,
25  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
26  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27  *  GNU General Public License for more details.
28  *
29  *  You should have received a copy of the GNU General Public License
30  *  along with anytun.  If not, see <http://www.gnu.org/licenses/>.
31  */
32
33 #include <boost/bind.hpp>
34 #include <boost/thread.hpp>
35 #include <boost/assign.hpp>
36 #include <iostream>
37 #include <fstream>
38
39 #include "datatypes.h"
40
41 #include "log.h"
42 #include "resolver.h"
43 #include "buffer.h"
44 #include "plainPacket.h"
45 #include "encryptedPacket.h"
46 #include "cipher.h"
47 #include "keyDerivation.h"
48 #include "authAlgo.h"
49 #include "cipherFactory.h"
50 #include "authAlgoFactory.h"
51 #include "keyDerivationFactory.h"
52 #include "signalController.h"
53 #ifdef WIN_SERVICE
54 #include "win32/winService.h"
55 #endif
56 #include "packetSource.h"
57 #include "tunDevice.h"
58 #include "options.h"
59 #include "seqWindow.h"
60 #include "connectionList.h"
61 #ifndef NO_ROUTING
62 #include "routingTable.h"
63 #include "networkAddress.h"
64 #endif
65
66
67 #ifndef ANYTUN_NOSYNC
68 #include "syncQueue.h"
69 #include "syncCommand.h"
70 #include "syncServer.h"
71 #include "syncClient.h"
72 #include "syncOnConnect.hpp"
73 #endif
74
75 #define MAX_PACKET_LENGTH 1600
76
77 #include "cryptinit.hpp"
78 #include "daemon.hpp"
79 #include "sysExec.h"
80
81 bool disableRouting = false;
82
83 void createConnection(const PacketSourceEndpoint& remote_end, window_size_t seqSize, mux_t mux)
84 {
85         SeqWindow* seq = new SeqWindow(seqSize);
86         seq_nr_t seq_nr_=0;
87   KeyDerivation * kd = KeyDerivationFactory::create(gOpt.getKdPrf());
88   kd->init(gOpt.getKey(), gOpt.getSalt(), gOpt.getPassphrase());
89   kd->setRole(gOpt.getRole());
90   cLog.msg(Log::PRIO_NOTICE) << "added connection remote host " << remote_end;
91
92         ConnectionParam connparam ((*kd), (*seq), seq_nr_, remote_end);
93         gConnectionList.addConnection(connparam,mux);
94 #ifndef ANYTUN_NOSYNC
95   SyncCommand sc (gConnectionList,mux);
96         gSyncQueue.push(sc);
97 #endif
98 }
99
100 void createConnectionError(const std::exception& e)
101 {
102   gSignalController.inject(SIGERROR, e.what());
103 }
104
105 #ifndef ANYTUN_NOSYNC
106 void syncConnector(const OptionHost& connto)
107 {
108   SyncClient sc(connto.addr, connto.port);
109   sc.run();
110 }
111
112 void syncListener()
113 {
114   try
115   {
116     SyncServer server(gOpt.getLocalSyncAddr(), gOpt.getLocalSyncPort(), boost::bind(syncOnConnect, _1));
117     gSyncQueue.setSyncServerPtr(&server);
118     server.run();
119   }
120   catch(std::runtime_error& e) {
121     cLog.msg(Log::PRIO_ERROR) << "sync listener thread died due to an uncaught runtime_error: " << e.what();
122   }
123   catch(std::exception& e) {
124     cLog.msg(Log::PRIO_ERROR) << "sync listener thread died due to an uncaught exception: " << e.what();
125   }
126 }
127 #endif
128
129 void sender(TunDevice* dev, PacketSource* src)
130 {
131   if(!dev || !src) {
132     cLog.msg(Log::PRIO_ERROR) << "sender thread died because either dev or src pointer is null";    
133     return;
134   }
135
136   try 
137   {
138     std::auto_ptr<Cipher> c(CipherFactory::create(gOpt.getCipher(), KD_OUTBOUND));
139     std::auto_ptr<AuthAlgo> a(AuthAlgoFactory::create(gOpt.getAuthAlgo(), KD_OUTBOUND) );
140     
141     PlainPacket plain_packet(MAX_PACKET_LENGTH);
142     EncryptedPacket encrypted_packet(MAX_PACKET_LENGTH, gOpt.getAuthTagLength());
143     
144     u_int16_t mux = gOpt.getMux();
145     PacketSourceEndpoint emptyEndpoint;
146     while(1) {
147       plain_packet.setLength(MAX_PACKET_LENGTH);
148       encrypted_packet.withAuthTag(false);
149       encrypted_packet.setLength(MAX_PACKET_LENGTH);
150       
151           // read packet from device
152       int len = dev->read(plain_packet.getPayload(), plain_packet.getPayloadLength());
153       if(len < 0)
154         continue; // silently ignore device read errors, this is probably no good idea...
155
156       if(static_cast<u_int32_t>(len) < PlainPacket::getHeaderLength())
157         continue; // ignore short packets
158       plain_packet.setPayloadLength(len);
159           // set payload type
160       if(dev->getType() == TYPE_TUN)
161         plain_packet.setPayloadType(PAYLOAD_TYPE_TUN);
162       else if(dev->getType() == TYPE_TAP)
163         plain_packet.setPayloadType(PAYLOAD_TYPE_TAP);
164       else 
165         plain_packet.setPayloadType(0);
166       
167       if(gConnectionList.empty())
168         continue;
169           //std::cout << "got Packet for plain "<<plain_packet.getDstAddr().toString();
170                         ConnectionMap::iterator cit;
171 #ifndef NO_ROUTING
172                         if (!disableRouting)
173                                 try {
174                                         mux = gRoutingTable.getRoute(plain_packet.getDstAddr());
175                                                         //std::cout << " -> "<<mux << std::endl;
176                                         cit = gConnectionList.getConnection(mux);
177                                 } catch (std::exception&) { continue; } // no route
178                         else
179                                 cit = gConnectionList.getBegin();
180 #else
181                                 cit = gConnectionList.getBegin();
182 #endif
183
184       if(cit==gConnectionList.getEnd())
185         continue; //no connection
186       ConnectionParam & conn = cit->second;
187       
188       if(conn.remote_end_ == emptyEndpoint) {
189         //cLog.msg(Log::PRIO_INFO) << "no remote address set";
190         continue;
191       }
192
193           // encrypt packet
194       c->encrypt(conn.kd_, plain_packet, encrypted_packet, conn.seq_nr_, gOpt.getSenderId(), mux);
195       
196       encrypted_packet.setHeader(conn.seq_nr_, gOpt.getSenderId(), mux);
197       conn.seq_nr_++;
198       
199           // add authentication tag
200       a->generate(conn.kd_, encrypted_packet);
201
202       try {
203         src->send(encrypted_packet.getBuf(), encrypted_packet.getLength(), conn.remote_end_);
204       } catch (std::exception& /*e*/) {
205                                 //TODO: do something here
206                         //cLog.msg(Log::PRIO_ERROR) << "could not send data: " << e.what();
207                 } 
208     }
209   }
210   catch(std::runtime_error& e) {
211     cLog.msg(Log::PRIO_ERROR) << "sender thread died due to an uncaught runtime_error: " << e.what();
212   }
213   catch(std::exception& e) {
214     cLog.msg(Log::PRIO_ERROR) << "sender thread died due to an uncaught exception: " << e.what();
215   }
216 }
217
218 void receiver(TunDevice* dev, PacketSource* src)
219 {
220   if(!dev || !src) {
221     cLog.msg(Log::PRIO_ERROR) << "receiver thread died because either dev or src pointer is null";    
222     return;
223   }
224
225   try 
226   {
227     std::auto_ptr<Cipher> c(CipherFactory::create(gOpt.getCipher(), KD_INBOUND));
228     std::auto_ptr<AuthAlgo> a(AuthAlgoFactory::create(gOpt.getAuthAlgo(), KD_INBOUND));
229     
230     EncryptedPacket encrypted_packet(MAX_PACKET_LENGTH, gOpt.getAuthTagLength());
231     PlainPacket plain_packet(MAX_PACKET_LENGTH);
232     
233     while(1) {
234       PacketSourceEndpoint remote_end;
235
236       plain_packet.setLength(MAX_PACKET_LENGTH);
237       encrypted_packet.withAuthTag(false);
238       encrypted_packet.setLength(MAX_PACKET_LENGTH);
239       
240           // read packet from socket
241       int len;
242       try {
243         len = src->recv(encrypted_packet.getBuf(), encrypted_packet.getLength(), remote_end);
244       } catch (std::exception& /*e*/) { 
245                                 //TODO: do something here
246                         //cLog.msg(Log::PRIO_ERROR) << "could not recive packet "<< e.what();
247                         continue; 
248                 }
249       if(len < 0)
250         continue; // silently ignore socket recv errors, this is probably no good idea...
251
252       if(static_cast<u_int32_t>(len) < EncryptedPacket::getHeaderLength())
253         continue; // ignore short packets
254       encrypted_packet.setLength(len);
255       
256       mux_t mux = encrypted_packet.getMux();
257           // autodetect peer
258       if( gConnectionList.empty() && gOpt.getRemoteAddr() == "") {
259         cLog.msg(Log::PRIO_NOTICE) << "autodetected remote host " << remote_end;
260         createConnection(remote_end, gOpt.getSeqWindowSize(),mux);
261       }
262       
263       ConnectionMap::iterator cit = gConnectionList.getConnection(mux);
264       if (cit == gConnectionList.getEnd())
265         continue;
266       ConnectionParam & conn = cit->second;
267       
268           // check whether auth tag is ok or not
269       if(!a->checkTag(conn.kd_, encrypted_packet)) {
270         cLog.msg(Log::PRIO_NOTICE) << "wrong Authentication Tag!" << std::endl;
271         continue;
272       }        
273
274           // Replay Protection
275       if(conn.seq_window_.checkAndAdd(encrypted_packet.getSenderId(), encrypted_packet.getSeqNr())) {
276         cLog.msg(Log::PRIO_NOTICE) << "Replay attack from " << conn.remote_end_ 
277                                    << " seq:"<< encrypted_packet.getSeqNr() << " sid: "<< encrypted_packet.getSenderId();
278         continue;
279       }
280       
281           //Allow dynamic IP changes 
282           //TODO: add command line option to turn this off
283       if (remote_end != conn.remote_end_) {
284         cLog.msg(Log::PRIO_NOTICE) << "connection "<< mux << " autodetected remote host ip changed " << remote_end;
285         conn.remote_end_=remote_end;
286 #ifndef ANYTUN_NOSYNC
287         SyncCommand sc (gConnectionList,mux);
288         gSyncQueue.push(sc);
289 #endif
290       } 
291          // ignore zero length packets
292       if(encrypted_packet.getPayloadLength() <= PlainPacket::getHeaderLength())
293         continue;
294
295           // decrypt packet
296       c->decrypt(conn.kd_, encrypted_packet, plain_packet);
297       
298           // check payload_type
299       if((dev->getType() == TYPE_TUN && plain_packet.getPayloadType() != PAYLOAD_TYPE_TUN4 && 
300                                               plain_packet.getPayloadType() != PAYLOAD_TYPE_TUN6) ||
301          (dev->getType() == TYPE_TAP && plain_packet.getPayloadType() != PAYLOAD_TYPE_TAP))
302         continue;
303       
304           // write it on the device
305       dev->write(plain_packet.getPayload(), plain_packet.getLength());
306     }
307   }
308   catch(std::runtime_error& e) {
309     cLog.msg(Log::PRIO_ERROR) << "receiver thread died due to an uncaught runtime_error: " << e.what();
310   }
311   catch(std::exception& e) {
312     cLog.msg(Log::PRIO_ERROR) << "receiver thread died due to an uncaught exception: " << e.what();
313   }
314 }
315
316 #ifndef NO_DAEMON
317 void startSendRecvThreads(PrivInfo& privs, TunDevice* dev, PacketSource* src)
318 #else
319 void startSendRecvThreads(TunDevice* dev, PacketSource* src)
320 #endif
321 {
322   src->waitUntilReady();
323   
324 #ifndef NO_DAEMON
325   if(gOpt.getChrootDir() != "") {
326     try {
327       do_chroot(gOpt.getChrootDir());
328     }
329     catch(const std::runtime_error& e) {
330       cLog.msg(Log::PRIO_WARNING) << "ignoring chroot error: " << e.what();
331     }
332   }
333 #ifndef NO_PRIVDROP
334   privs.drop();
335 #endif
336 #endif
337   
338   boost::thread(boost::bind(sender, dev, src));
339   boost::thread(boost::bind(receiver, dev, src)); 
340 }
341
342
343
344 #ifdef WIN_SERVICE
345 int main(int argc, char* argv[])
346 {
347   try {
348     if(argc > 1) {
349       if(std::string(argv[1]) == "install") {
350         WinService::install();  
351         return 0;
352       }
353       else if(std::string(argv[1]) == "uninstall") {
354         WinService::uninstall();  
355         return 0;
356       }
357     }
358     WinService::start();
359     return 0;
360   }
361   catch(std::runtime_error& e)
362   {
363     std::cout << "caught runtime error, exiting: " << e.what() << std::endl;
364   }
365   catch(std::exception& e)
366   {
367     std::cout << "caught exception, exiting: " << e.what() << std::endl;
368   }
369 }
370
371 int real_main(int argc, char* argv[])
372 #else
373 int main(int argc, char* argv[])
374 #endif
375 {
376 #ifdef WIN_SERVICE
377   bool daemonized=true;
378 #else
379   bool daemonized=false;
380 #endif  
381   try 
382   {
383     try 
384     {
385       bool result = gOpt.parse(argc, argv);
386       if(!result) {
387         gOpt.printUsage();
388         exit(0);
389       }
390       StringList targets = gOpt.getLogTargets();
391       if(targets.empty()) {
392 #ifndef _MSC_VER
393         cLog.addTarget("syslog:3,anytun,daemon");
394 #else
395  #ifdef WIN_SERVICE
396         cLog.addTarget("eventlog:3,anytun");
397  #else
398         cLog.addTarget("stdout:3");
399  #endif
400 #endif
401       }
402       else {
403         StringList::const_iterator it;
404         for(it = targets.begin();it != targets.end(); ++it)
405           cLog.addTarget(*it);
406       }
407     }
408     catch(syntax_error& e)
409     {
410       std::cerr << e << std::endl;
411       gOpt.printUsage();
412       exit(-1);
413     }
414
415     cLog.msg(Log::PRIO_NOTICE) << "anytun started...";
416     gOpt.parse_post(); // print warnings
417
418         // daemonizing has to done before any thread gets started
419 #ifndef NO_DAEMON
420 #ifndef NO_PRIVDROP
421                 PrivInfo privs(gOpt.getUsername(), gOpt.getGroupname());
422 #endif
423     if(gOpt.getDaemonize()) {
424       daemonize();
425       daemonized = true;
426     }
427 #endif
428
429         // this has to be called before the first thread is started
430     gSignalController.init();
431     gResolver.init();
432    
433 #ifndef NO_CRYPT
434 #ifndef USE_SSL_CRYPTO
435 // this must be called before any other libgcrypt call
436     if(!initLibGCrypt())
437       return -1;
438 #endif
439 #endif
440
441     OptionNetwork net = gOpt.getIfconfigParam();
442     TunDevice dev(gOpt.getDevName(), gOpt.getDevType(), net.net_addr, net.prefix_length);
443     cLog.msg(Log::PRIO_NOTICE) << "dev opened - name '" << dev.getActualName() << "', node '" << dev.getActualNode() << "'";
444     cLog.msg(Log::PRIO_NOTICE) << "dev type is '" << dev.getTypeString() << "'";
445 #ifndef NO_EXEC
446     if(gOpt.getPostUpScript() != "") {
447       cLog.msg(Log::PRIO_NOTICE) << "executing post-up script '" << gOpt.getPostUpScript() << "'";
448       StringVector args = boost::assign::list_of(dev.getActualName())(dev.getActualNode());
449       anytun_exec(gOpt.getPostUpScript(), args);
450     }
451 #endif
452     
453     PacketSource* src = new UDPPacketSource(gOpt.getLocalAddr(), gOpt.getLocalPort());
454
455     if(gOpt.getRemoteAddr() != "")
456       gResolver.resolveUdp(gOpt.getRemoteAddr(), gOpt.getRemotePort(), boost::bind(createConnection, _1, gOpt.getSeqWindowSize(), gOpt.getMux()), boost::bind(createConnectionError, _1), gOpt.getResolvAddrType());
457
458     HostList connect_to = gOpt.getRemoteSyncHosts();
459 #ifndef NO_ROUTING
460     NetworkList routes = gOpt.getRoutes();
461                 NetworkList::const_iterator rit;
462                 for(rit = routes.begin(); rit != routes.end(); ++rit) {
463                         NetworkAddress addr( rit->net_addr );
464                         NetworkPrefix prefix( addr, static_cast<u_int8_t>(rit->prefix_length));
465                         gRoutingTable.addRoute( prefix, gOpt.getMux() );
466                 }
467                 if (connect_to.begin() == connect_to.end() || gOpt.getDevType()!="tun") {
468         cLog.msg(Log::PRIO_NOTICE) << "No sync/control host defined or not a tun device. Disabling multi connection support (routing)";
469                         disableRouting=true;
470                 }
471 #endif
472
473 #ifndef ANYTUN_NOSYNC
474     boost::thread* syncListenerThread = NULL;
475     if(gOpt.getLocalSyncPort() != "")
476       syncListenerThread = new boost::thread(boost::bind(syncListener));
477     
478     boost::thread_group connectThreads;
479     for(HostList::const_iterator it = connect_to.begin() ;it != connect_to.end(); ++it)
480       connectThreads.create_thread(boost::bind(syncConnector, *it));
481 #endif
482
483         // wait for packet source to finish in a seperate thread in order
484         // to be still able to process signals while waiting
485 #ifndef NO_DAEMON
486     boost::thread(boost::bind(startSendRecvThreads, privs, &dev, src));
487 #else
488     boost::thread(boost::bind(startSendRecvThreads, &dev, src));
489 #endif
490
491 #if defined(WIN_SERVICE)
492     int ret = 0;
493     gWinService.waitForStop();
494 #else
495     int ret = gSignalController.run();  
496 #endif
497
498 // TODO: stop all threads and cleanup
499 // 
500 //     if(src)
501 //       delete src;
502 //     if(connTo)
503 //       delete connTo;
504
505 #if defined(WIN_SERVICE)
506     gWinService.stop();
507 #endif
508     return ret; 
509   }
510   catch(std::runtime_error& e)
511   {
512     cLog.msg(Log::PRIO_ERROR) << "uncaught runtime error, exiting: " << e.what();
513     if(!daemonized)
514       std::cout << "uncaught runtime error, exiting: " << e.what() << std::endl;
515   }
516   catch(std::exception& e)
517   {
518     cLog.msg(Log::PRIO_ERROR) << "uncaught exception, exiting: " << e.what();
519     if(!daemonized)
520       std::cout << "uncaught exception, exiting: " << e.what() << std::endl;
521   }
522 #if defined(WIN_SERVICE)
523   gWinService.stop();
524 #endif
525   return -1;
526 }
527   
528