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