Imported Upstream version 0.3.3
[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 #ifndef _MSC_VER
54 # include "daemonService.h"
55 #else
56 # ifdef WIN_SERVICE
57 #  include "win32/winService.h"
58 # else
59 #  include "nullDaemon.h"
60 # endif
61 #endif
62 #include "packetSource.h"
63 #include "tunDevice.h"
64 #include "options.h"
65 #include "seqWindow.h"
66 #include "connectionList.h"
67 #ifndef NO_ROUTING
68 #include "routingTable.h"
69 #include "networkAddress.h"
70 #endif
71
72 #ifndef ANYTUN_NOSYNC
73 #include "syncQueue.h"
74 #include "syncCommand.h"
75 #include "syncServer.h"
76 #include "syncClient.h"
77 #include "syncOnConnect.hpp"
78 #endif
79
80 #include "cryptinit.hpp"
81 #include "sysExec.h"
82
83 bool disableRouting = false;
84
85 void createConnection(const PacketSourceEndpoint& remote_end, window_size_t seqSize, mux_t mux)
86 {
87         SeqWindow* seq = new SeqWindow(seqSize);
88         seq_nr_t seq_nr_=0;
89   KeyDerivation * kd = KeyDerivationFactory::create(gOpt.getKdPrf());
90   kd->init(gOpt.getKey(), gOpt.getSalt(), gOpt.getPassphrase());
91   kd->setRole(gOpt.getRole());
92   cLog.msg(Log::PRIO_NOTICE) << "added connection remote host " << remote_end;
93
94         ConnectionParam connparam ((*kd), (*seq), seq_nr_, remote_end);
95         gConnectionList.addConnection(connparam,mux);
96 #ifndef ANYTUN_NOSYNC
97   SyncCommand sc (gConnectionList,mux);
98         gSyncQueue.push(sc);
99 #endif
100 }
101
102 void createConnectionResolver(PacketSourceResolverIt& it, window_size_t seqSize, mux_t mux)
103 {
104   createConnection(*it, seqSize, mux);
105 }
106
107 void createConnectionError(const std::exception& e)
108 {
109   gSignalController.inject(SIGERROR, e.what());
110 }
111
112 #ifndef ANYTUN_NOSYNC
113 void syncConnector(const OptionHost& connto)
114 {
115   SyncClient sc(connto.addr, connto.port);
116   sc.run();
117 }
118
119 void syncListener()
120 {
121   try
122   {
123     SyncServer server(gOpt.getLocalSyncAddr(), gOpt.getLocalSyncPort(), boost::bind(syncOnConnect, _1));
124     gSyncQueue.setSyncServerPtr(&server);
125     server.run();
126   }
127   catch(std::runtime_error& e) {
128     cLog.msg(Log::PRIO_ERROR) << "sync listener thread died due to an uncaught runtime_error: " << e.what();
129   }
130   catch(std::exception& e) {
131     cLog.msg(Log::PRIO_ERROR) << "sync listener thread died due to an uncaught exception: " << e.what();
132   }
133 }
134 #endif
135
136 void sender(TunDevice* dev, PacketSource* src)
137 {
138   if(!dev || !src) {
139     cLog.msg(Log::PRIO_ERROR) << "sender thread died because either dev or src pointer is null";    
140     return;
141   }
142
143   try 
144   {
145     std::auto_ptr<Cipher> c(CipherFactory::create(gOpt.getCipher(), KD_OUTBOUND));
146     std::auto_ptr<AuthAlgo> a(AuthAlgoFactory::create(gOpt.getAuthAlgo(), KD_OUTBOUND) );
147     
148     PlainPacket plain_packet(MAX_PACKET_LENGTH);
149     EncryptedPacket encrypted_packet(MAX_PACKET_LENGTH, gOpt.getAuthTagLength());
150     
151     u_int16_t mux = gOpt.getMux();
152     PacketSourceEndpoint emptyEndpoint;
153     while(1) {
154       plain_packet.setLength(MAX_PACKET_LENGTH);
155       encrypted_packet.withAuthTag(false);
156       encrypted_packet.setLength(MAX_PACKET_LENGTH);
157       
158           // read packet from device
159       int len = dev->read(plain_packet.getPayload(), plain_packet.getPayloadLength());
160       if(len < 0)
161         continue; // silently ignore device read errors, this is probably no good idea...
162
163       if(static_cast<u_int32_t>(len) < PlainPacket::getHeaderLength())
164         continue; // ignore short packets
165       plain_packet.setPayloadLength(len);
166           // set payload type
167       if(dev->getType() == TYPE_TUN)
168         plain_packet.setPayloadType(PAYLOAD_TYPE_TUN);
169       else if(dev->getType() == TYPE_TAP)
170         plain_packet.setPayloadType(PAYLOAD_TYPE_TAP);
171       else 
172         plain_packet.setPayloadType(0);
173       
174       if(gConnectionList.empty())
175         continue;
176           //std::cout << "got Packet for plain "<<plain_packet.getDstAddr().toString();
177                         ConnectionMap::iterator cit;
178 #ifndef NO_ROUTING
179                         if (!disableRouting)
180                                 try {
181                                         mux = gRoutingTable.getRoute(plain_packet.getDstAddr());
182                                                         //std::cout << " -> "<<mux << std::endl;
183                                         cit = gConnectionList.getConnection(mux);
184                                 } catch (std::exception&) { continue; } // no route
185                         else
186                                 cit = gConnectionList.getBegin();
187 #else
188                                 cit = gConnectionList.getBegin();
189 #endif
190
191       if(cit==gConnectionList.getEnd())
192         continue; //no connection
193       ConnectionParam & conn = cit->second;
194       
195       if(conn.remote_end_ == emptyEndpoint) {
196         //cLog.msg(Log::PRIO_INFO) << "no remote address set";
197         continue;
198       }
199
200           // encrypt packet
201       c->encrypt(conn.kd_, plain_packet, encrypted_packet, conn.seq_nr_, gOpt.getSenderId(), mux);
202       
203       encrypted_packet.setHeader(conn.seq_nr_, gOpt.getSenderId(), mux);
204       conn.seq_nr_++;
205       
206           // add authentication tag
207       a->generate(conn.kd_, encrypted_packet);
208
209       try {
210         src->send(encrypted_packet.getBuf(), encrypted_packet.getLength(), conn.remote_end_);
211       } catch (std::exception& /*e*/) {
212                                 //TODO: do something here
213                         //cLog.msg(Log::PRIO_ERROR) << "could not send data: " << e.what();
214                 } 
215     }
216   }
217   catch(std::runtime_error& e) {
218     cLog.msg(Log::PRIO_ERROR) << "sender thread died due to an uncaught runtime_error: " << e.what();
219   }
220   catch(std::exception& e) {
221     cLog.msg(Log::PRIO_ERROR) << "sender thread died due to an uncaught exception: " << e.what();
222   }
223 }
224
225 void receiver(TunDevice* dev, PacketSource* src)
226 {
227   if(!dev || !src) {
228     cLog.msg(Log::PRIO_ERROR) << "receiver thread died because either dev or src pointer is null";    
229     return;
230   }
231
232   try 
233   {
234     std::auto_ptr<Cipher> c(CipherFactory::create(gOpt.getCipher(), KD_INBOUND));
235     std::auto_ptr<AuthAlgo> a(AuthAlgoFactory::create(gOpt.getAuthAlgo(), KD_INBOUND));
236     
237     u_int32_t auth_tag_length = gOpt.getAuthTagLength();
238     EncryptedPacket encrypted_packet(MAX_PACKET_LENGTH, auth_tag_length);
239     PlainPacket plain_packet(MAX_PACKET_LENGTH);
240     
241     while(1) {
242       PacketSourceEndpoint remote_end;
243
244       plain_packet.setLength(MAX_PACKET_LENGTH);
245       encrypted_packet.withAuthTag(false);
246       encrypted_packet.setLength(MAX_PACKET_LENGTH);
247       
248           // read packet from socket
249       int len;
250       try {
251         len = src->recv(encrypted_packet.getBuf(), encrypted_packet.getLength(), remote_end);
252       } catch (std::exception& /*e*/) { 
253                                 //TODO: do something here
254                         //cLog.msg(Log::PRIO_ERROR) << "could not recive packet "<< e.what();
255                         continue; 
256                 }
257       if(len < 0)
258         continue; // silently ignore socket recv errors, this is probably no good idea...
259
260       if(static_cast<u_int32_t>(len) < (EncryptedPacket::getHeaderLength() + auth_tag_length))
261         continue; // ignore short packets
262       encrypted_packet.setLength(len);
263       
264       mux_t mux = encrypted_packet.getMux();
265           // autodetect peer
266       if( gConnectionList.empty() && gOpt.getRemoteAddr() == "") {
267         cLog.msg(Log::PRIO_NOTICE) << "autodetected remote host " << remote_end;
268         createConnection(remote_end, gOpt.getSeqWindowSize(),mux);
269       }
270       
271       ConnectionMap::iterator cit = gConnectionList.getConnection(mux);
272       if (cit == gConnectionList.getEnd())
273         continue;
274       ConnectionParam & conn = cit->second;
275       
276           // check whether auth tag is ok or not
277       if(!a->checkTag(conn.kd_, encrypted_packet)) {
278         cLog.msg(Log::PRIO_NOTICE) << "wrong Authentication Tag!";
279         continue;
280       }        
281
282           // Replay Protection
283       if(conn.seq_window_.checkAndAdd(encrypted_packet.getSenderId(), encrypted_packet.getSeqNr())) {
284         cLog.msg(Log::PRIO_NOTICE) << "Replay attack from " << conn.remote_end_ 
285                                    << " seq:"<< encrypted_packet.getSeqNr() << " sid: "<< encrypted_packet.getSenderId();
286         continue;
287       }
288       
289           //Allow dynamic IP changes 
290           //TODO: add command line option to turn this off
291       if (remote_end != conn.remote_end_) {
292         cLog.msg(Log::PRIO_NOTICE) << "connection "<< mux << " autodetected remote host ip changed " << remote_end;
293         conn.remote_end_=remote_end;
294 #ifndef ANYTUN_NOSYNC
295         SyncCommand sc (gConnectionList,mux);
296         gSyncQueue.push(sc);
297 #endif
298       } 
299          // ignore zero length packets
300       if(encrypted_packet.getPayloadLength() <= PlainPacket::getHeaderLength())
301         continue;
302
303           // decrypt packet
304       c->decrypt(conn.kd_, encrypted_packet, plain_packet);
305       
306           // check payload_type
307       if((dev->getType() == TYPE_TUN && plain_packet.getPayloadType() != PAYLOAD_TYPE_TUN4 && 
308                                               plain_packet.getPayloadType() != PAYLOAD_TYPE_TUN6) ||
309          (dev->getType() == TYPE_TAP && plain_packet.getPayloadType() != PAYLOAD_TYPE_TAP))
310         continue;
311       
312           // write it on the device
313       dev->write(plain_packet.getPayload(), plain_packet.getLength());
314     }
315   }
316   catch(std::runtime_error& e) {
317     cLog.msg(Log::PRIO_ERROR) << "receiver thread died due to an uncaught runtime_error: " << e.what();
318   }
319   catch(std::exception& e) {
320     cLog.msg(Log::PRIO_ERROR) << "receiver thread died due to an uncaught exception: " << e.what();
321   }
322 }
323
324 void startSendRecvThreads(TunDevice* dev, PacketSource* src)
325 {
326   src->waitUntilReady();
327   
328   boost::thread(boost::bind(sender, dev, src));
329   boost::thread(boost::bind(receiver, dev, src)); 
330 }
331
332
333 #ifdef WIN_SERVICE
334 int main(int argc, char* argv[])
335 {
336   try {
337     if(argc > 1) {
338       if(std::string(argv[1]) == "install") {
339         WinService::install();  
340         return 0;
341       }
342       else if(std::string(argv[1]) == "uninstall") {
343         WinService::uninstall();  
344         return 0;
345       }
346     }
347     WinService::start();
348     return 0;
349   }
350   catch(std::runtime_error& e)
351   {
352     std::cout << "caught runtime error, exiting: " << e.what() << std::endl;
353   }
354   catch(std::exception& e)
355   {
356     std::cout << "caught exception, exiting: " << e.what() << std::endl;
357   }
358 }
359
360 int real_main(int argc, char* argv[], WinService& service)
361 {
362 #else
363 int main(int argc, char* argv[])
364 {
365   DaemonService service;
366 #endif  
367   try 
368   {
369     try 
370     {
371       if(!gOpt.parse(argc, argv))
372         exit(0);
373
374       StringList targets = gOpt.getLogTargets();
375       for(StringList::const_iterator it = targets.begin();it != targets.end(); ++it)
376         cLog.addTarget(*it);
377     }
378     catch(syntax_error& e)
379     {
380       std::cerr << e << std::endl;
381       gOpt.printUsage();
382       exit(-1);
383     }
384
385     cLog.msg(Log::PRIO_NOTICE) << "anytun started...";
386     gOpt.parse_post(); // print warnings
387
388         // daemonizing has to done before any thread gets started
389     service.initPrivs(gOpt.getUsername(), gOpt.getGroupname());
390     if(gOpt.getDaemonize())
391       service.daemonize();
392
393     OptionNetwork net = gOpt.getIfconfigParam();
394     TunDevice dev(gOpt.getDevName(), gOpt.getDevType(), net.net_addr, net.prefix_length);
395     cLog.msg(Log::PRIO_NOTICE) << "dev opened - name '" << dev.getActualName() << "', node '" << dev.getActualNode() << "'";
396     cLog.msg(Log::PRIO_NOTICE) << "dev type is '" << dev.getTypeString() << "'";
397
398     SysExec * postup_script = NULL;
399     if(gOpt.getPostUpScript() != "") {
400       cLog.msg(Log::PRIO_NOTICE) << "executing post-up script '" << gOpt.getPostUpScript() << "'";
401       StringVector args = boost::assign::list_of(dev.getActualName())(dev.getActualNode());
402       postup_script = new SysExec(gOpt.getPostUpScript(), args);
403     }
404
405     if(gOpt.getChrootDir() != "") {
406       try {
407         service.chroot(gOpt.getChrootDir());
408       }
409       catch(const std::runtime_error& e) {
410         cLog.msg(Log::PRIO_WARNING) << "ignoring chroot error: " << e.what();
411       }
412     }
413     service.dropPrivs();
414
415     // this has to be called before the first thread is started
416     gSignalController.init(service);
417     gResolver.init();
418     boost::thread(boost::bind(&TunDevice::waitUntilReady,&dev));
419     if (postup_script)
420       boost::thread(boost::bind(&SysExec::waitAndDestroy,postup_script));
421
422     initCrypto();   
423  
424     PacketSource* src = new UDPPacketSource(gOpt.getLocalAddr(), gOpt.getLocalPort());
425
426     if(gOpt.getRemoteAddr() != "")
427       gResolver.resolveUdp(gOpt.getRemoteAddr(), gOpt.getRemotePort(), boost::bind(createConnectionResolver, _1, gOpt.getSeqWindowSize(), gOpt.getMux()), boost::bind(createConnectionError, _1), gOpt.getResolvAddrType());
428
429     HostList connect_to = gOpt.getRemoteSyncHosts();
430 #ifndef NO_ROUTING
431     NetworkList routes = gOpt.getRoutes();
432                 NetworkList::const_iterator rit;
433                 for(rit = routes.begin(); rit != routes.end(); ++rit) {
434                         NetworkAddress addr( rit->net_addr );
435                         NetworkPrefix prefix( addr, static_cast<u_int8_t>(rit->prefix_length));
436                         gRoutingTable.addRoute( prefix, gOpt.getMux() );
437                 }
438                 if (connect_to.begin() == connect_to.end() || gOpt.getDevType()!="tun") {
439         cLog.msg(Log::PRIO_NOTICE) << "No sync/control host defined or not a tun device. Disabling multi connection support (routing)";
440                         disableRouting=true;
441                 }
442 #endif
443
444 #ifndef ANYTUN_NOSYNC
445     boost::thread* syncListenerThread = NULL;
446     if(gOpt.getLocalSyncPort() != "")
447       syncListenerThread = new boost::thread(boost::bind(syncListener));
448     
449     boost::thread_group connectThreads;
450     for(HostList::const_iterator it = connect_to.begin() ;it != connect_to.end(); ++it)
451       connectThreads.create_thread(boost::bind(syncConnector, *it));
452 #endif
453
454     // wait for packet source to finish in a seperate thread in order
455     // to be still able to process signals while waiting
456     boost::thread(boost::bind(startSendRecvThreads, &dev, src));
457
458     int ret = gSignalController.run();  
459
460 // TODO: stop all threads and cleanup
461 // 
462 //     if(src)
463 //       delete src;
464 //     if(connTo)
465 //       delete connTo;
466     return ret; 
467   }
468   catch(std::runtime_error& e)
469   {
470     cLog.msg(Log::PRIO_ERROR) << "uncaught runtime error, exiting: " << e.what();
471     if(!service.isDaemonized())
472       std::cout << "uncaught runtime error, exiting: " << e.what() << std::endl;
473   }
474   catch(std::exception& e)
475   {
476     cLog.msg(Log::PRIO_ERROR) << "uncaught exception, exiting: " << e.what();
477     if(!service.isDaemonized())
478       std::cout << "uncaught exception, exiting: " << e.what() << std::endl;
479   }
480   return -1;
481 }
482   
483