ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/connection.C
(Generate patch)

Comparing gvpe/src/connection.C (file contents):
Revision 1.16 by pcg, Mon Sep 1 15:52:03 2003 UTC vs.
Revision 1.26 by pcg, Sat Jan 17 14:08:57 2004 UTC

1/* 1/*
2 connection.C -- manage a single connection 2 connection.C -- manage a single connection
3 Copyright (C) 2003-2004 Marc Lehmann <pcg@goof.com>
3 4
4 This program is free software; you can redistribute it and/or modify 5 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 6 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or 7 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version. 8 (at your option) any later version.
20 21
21extern "C" { 22extern "C" {
22# include "lzf/lzf.h" 23# include "lzf/lzf.h"
23} 24}
24 25
26#include <cassert>
27
25#include <list> 28#include <list>
26 29
27#include <openssl/rand.h> 30#include <openssl/rand.h>
28#include <openssl/evp.h> 31#include <openssl/evp.h>
29#include <openssl/rsa.h> 32#include <openssl/rsa.h>
34#include "conf.h" 37#include "conf.h"
35#include "slog.h" 38#include "slog.h"
36#include "device.h" 39#include "device.h"
37#include "vpn.h" 40#include "vpn.h"
38#include "connection.h" 41#include "connection.h"
42
43#include "netcompat.h"
39 44
40#if !HAVE_RAND_PSEUDO_BYTES 45#if !HAVE_RAND_PSEUDO_BYTES
41# define RAND_pseudo_bytes RAND_bytes 46# define RAND_pseudo_bytes RAND_bytes
42#endif 47#endif
43 48
131 136
132} rsa_cache; 137} rsa_cache;
133 138
134void rsa_cache::cleaner_cb (time_watcher &w) 139void rsa_cache::cleaner_cb (time_watcher &w)
135{ 140{
136 if (empty ()) 141 if (!empty ())
137 w.at = TSTAMP_CANCEL;
138 else
139 { 142 {
140 w.at = NOW + RSA_TTL; 143 w.start (NOW + RSA_TTL);
141 144
142 for (iterator i = begin (); i != end (); ) 145 for (iterator i = begin (); i != end (); )
143 if (i->expire <= NOW) 146 if (i->expire <= NOW)
144 i = erase (i); 147 i = erase (i);
145 else 148 else
476} 479}
477 480
478bool config_packet::chk_config () const 481bool config_packet::chk_config () const
479{ 482{
480 if (prot_major != PROTOCOL_MAJOR) 483 if (prot_major != PROTOCOL_MAJOR)
481 slog (L_WARN, _("major version mismatch (%d <=> %d)"), prot_major, PROTOCOL_MAJOR); 484 slog (L_WARN, _("major version mismatch (remote %d <=> local %d)"), prot_major, PROTOCOL_MAJOR);
482 else if (randsize != RAND_SIZE) 485 else if (randsize != RAND_SIZE)
483 slog (L_WARN, _("rand size mismatch (%d <=> %d)"), randsize, RAND_SIZE); 486 slog (L_WARN, _("rand size mismatch (remote %d <=> local %d)"), randsize, RAND_SIZE);
484 else if (hmaclen != HMACLENGTH) 487 else if (hmaclen != HMACLENGTH)
485 slog (L_WARN, _("hmac length mismatch (%d <=> %d)"), hmaclen, HMACLENGTH); 488 slog (L_WARN, _("hmac length mismatch (remote %d <=> local %d)"), hmaclen, HMACLENGTH);
486 else if (flags != curflags ()) 489 else if (flags != curflags ())
487 slog (L_WARN, _("flag mismatch (%x <=> %x)"), flags, curflags ()); 490 slog (L_WARN, _("flag mismatch (remote %x <=> local %x)"), flags, curflags ());
488 else if (challengelen != sizeof (rsachallenge)) 491 else if (challengelen != sizeof (rsachallenge))
489 slog (L_WARN, _("challenge length mismatch (%d <=> %d)"), challengelen, sizeof (rsachallenge)); 492 slog (L_WARN, _("challenge length mismatch (remote %d <=> local %d)"), challengelen, sizeof (rsachallenge));
490 else if (cipher_nid != htonl (EVP_CIPHER_nid (CIPHER))) 493 else if (cipher_nid != htonl (EVP_CIPHER_nid (CIPHER)))
491 slog (L_WARN, _("cipher mismatch (%x <=> %x)"), ntohl (cipher_nid), EVP_CIPHER_nid (CIPHER)); 494 slog (L_WARN, _("cipher mismatch (remote %x <=> local %x)"), ntohl (cipher_nid), EVP_CIPHER_nid (CIPHER));
492 else if (digest_nid != htonl (EVP_MD_type (RSA_HASH))) 495 else if (digest_nid != htonl (EVP_MD_type (RSA_HASH)))
493 slog (L_WARN, _("digest mismatch (%x <=> %x)"), ntohl (digest_nid), EVP_MD_type (RSA_HASH)); 496 slog (L_WARN, _("digest mismatch (remote %x <=> local %x)"), ntohl (digest_nid), EVP_MD_type (RSA_HASH));
494 else if (hmac_nid != htonl (EVP_MD_type (DIGEST))) 497 else if (hmac_nid != htonl (EVP_MD_type (DIGEST)))
495 slog (L_WARN, _("hmac mismatch (%x <=> %x)"), ntohl (hmac_nid), EVP_MD_type (DIGEST)); 498 slog (L_WARN, _("hmac mismatch (remote %x <=> local %x)"), ntohl (hmac_nid), EVP_MD_type (DIGEST));
496 else 499 else
497 return true; 500 return true;
498 501
499 return false; 502 return false;
500} 503}
595 } 598 }
596 else 599 else
597 { 600 {
598 retry_cnt = 0; 601 retry_cnt = 0;
599 establish_connection.start (NOW + 5); 602 establish_connection.start (NOW + 5);
600 keepalive.reset (); 603 keepalive.stop ();
601 rekey.reset (); 604 rekey.stop ();
602 } 605 }
603} 606}
604 607
605void 608void
606connection::reset_si () 609connection::reset_si ()
672connection::send_auth_request (const sockinfo &si, bool initiate) 675connection::send_auth_request (const sockinfo &si, bool initiate)
673{ 676{
674 auth_req_packet *pkt = new auth_req_packet (conf->id, initiate, THISNODE->protocols); 677 auth_req_packet *pkt = new auth_req_packet (conf->id, initiate, THISNODE->protocols);
675 678
676 rsachallenge chg; 679 rsachallenge chg;
677
678 rsa_cache.gen (pkt->id, chg); 680 rsa_cache.gen (pkt->id, chg);
679 681 rsa_encrypt (conf->rsa_key, chg, pkt->encr);
680 if (0 > RSA_public_encrypt (sizeof chg,
681 (unsigned char *)&chg, (unsigned char *)&pkt->encr,
682 conf->rsa_key, RSA_PKCS1_OAEP_PADDING))
683 fatal ("RSA_public_encrypt error");
684 682
685 slog (L_TRACE, ">>%d PT_AUTH_REQ [%s]", conf->id, (const char *)si); 683 slog (L_TRACE, ">>%d PT_AUTH_REQ [%s]", conf->id, (const char *)si);
686 684
687 send_vpn_packet (pkt, si, IPTOS_RELIABILITY | IPTOS_LOWDELAY); // rsa is very very costly 685 send_vpn_packet (pkt, si, IPTOS_RELIABILITY | IPTOS_LOWDELAY); // rsa is very very costly
688 686
722} 720}
723 721
724void 722void
725connection::establish_connection_cb (time_watcher &w) 723connection::establish_connection_cb (time_watcher &w)
726{ 724{
727 if (ictx || conf == THISNODE 725 if (!ictx
726 && conf != THISNODE
728 || connectmode == conf_node::C_NEVER 727 && connectmode != conf_node::C_NEVER
729 || connectmode == conf_node::C_DISABLED) 728 && connectmode != conf_node::C_DISABLED
730 w.at = TSTAMP_CANCEL; 729 && NOW > w.at)
731 else if (w.at <= NOW)
732 { 730 {
733 double retry_int = double (retry_cnt & 3 ? (retry_cnt & 3) : 1 << (retry_cnt >> 2)) * 0.6; 731 double retry_int = double (retry_cnt & 3 ? (retry_cnt & 3) : 1 << (retry_cnt >> 2)) * 0.6;
734 732
735 if (retry_int < 3600 * 8) 733 if (retry_int < 3600 * 8)
736 retry_cnt++; 734 retry_cnt++;
737 735
738 w.at = NOW + retry_int; 736 w.start (NOW + retry_int);
739 737
740 reset_si (); 738 reset_si ();
741 739
742 if (si.prot && !si.host) 740 if (si.prot && !si.host)
743 vpn->send_connect_request (conf->id); 741 vpn->send_connect_request (conf->id);
774 si.host= 0; 772 si.host= 0;
775 773
776 last_activity = 0; 774 last_activity = 0;
777 retry_cnt = 0; 775 retry_cnt = 0;
778 776
779 rekey.reset (); 777 rekey.stop ();
780 keepalive.reset (); 778 keepalive.stop ();
781 establish_connection.reset (); 779 establish_connection.stop ();
782} 780}
783 781
784void 782void
785connection::shutdown () 783connection::shutdown ()
786{ 784{
791} 789}
792 790
793void 791void
794connection::rekey_cb (time_watcher &w) 792connection::rekey_cb (time_watcher &w)
795{ 793{
796 w.at = TSTAMP_CANCEL;
797
798 reset_connection (); 794 reset_connection ();
799 establish_connection (); 795 establish_connection ();
800} 796}
801 797
802void 798void
803connection::send_data_packet (tap_packet *pkt, bool broadcast) 799connection::send_data_packet (tap_packet *pkt)
804{ 800{
805 vpndata_packet *p = new vpndata_packet; 801 vpndata_packet *p = new vpndata_packet;
806 int tos = 0; 802 int tos = 0;
807 803
808 // I am not hilarious about peeking into packets, but so be it. 804 // I am not hilarious about peeking into packets, but so be it.
809 if (conf->inherit_tos 805 if (conf->inherit_tos && pkt->is_ipv4 ())
810 && (*pkt)[12] == 0x08 && (*pkt)[13] == 0x00 // IP
811 && ((*pkt)[14] & 0xf0) == 0x40) // IPv4
812 tos = (*pkt)[15] & IPTOS_TOS_MASK; 806 tos = (*pkt)[15] & IPTOS_TOS_MASK;
813 807
814 p->setup (this, broadcast ? 0 : conf->id, &((*pkt)[6 + 6]), pkt->len - 6 - 6, ++oseqno); // skip 2 macs 808 p->setup (this, conf->id, &((*pkt)[6 + 6]), pkt->len - 6 - 6, ++oseqno); // skip 2 macs
815 send_vpn_packet (p, si, tos); 809 send_vpn_packet (p, si, tos);
816 810
817 delete p; 811 delete p;
818 812
819 if (oseqno > MAX_SEQNO) 813 if (oseqno > MAX_SEQNO)
820 rekey (); 814 rekey ();
821} 815}
822 816
823void 817void
824connection::inject_data_packet (tap_packet *pkt, bool broadcast) 818connection::inject_data_packet (tap_packet *pkt, bool broadcast/*TODO DDD*/)
825{ 819{
826 if (ictx && octx) 820 if (ictx && octx)
827 send_data_packet (pkt, broadcast); 821 send_data_packet (pkt);
828 else 822 else
829 { 823 {
830 if (!broadcast)//DDDD 824 if (!broadcast)//DDDD
831 data_queue.put (new tap_packet (*pkt)); 825 data_queue.put (new tap_packet (*pkt));
832 826
907 if (p->initiate) 901 if (p->initiate)
908 send_auth_request (rsi, false); 902 send_auth_request (rsi, false);
909 903
910 rsachallenge k; 904 rsachallenge k;
911 905
912 if (0 > RSA_private_decrypt (sizeof (p->encr), 906 if (!rsa_decrypt (::conf.rsa_key, p->encr, k))
913 (unsigned char *)&p->encr, (unsigned char *)&k, 907 {
914 ::conf.rsa_key, RSA_PKCS1_OAEP_PADDING))
915 slog (L_ERR, _("%s(%s): challenge illegal or corrupted"), 908 slog (L_ERR, _("%s(%s): challenge illegal or corrupted (%s). mismatched key or config file?"),
916 conf->nodename, (const char *)rsi); 909 conf->nodename, (const char *)rsi, ERR_error_string (ERR_get_error (), 0));
910 break;
911 }
917 else 912 else
918 { 913 {
919 delete octx; 914 delete octx;
920 915
921 octx = new crypto_ctx (k, 1); 916 octx = new crypto_ctx (k, 1);
954 949
955 rsachallenge chg; 950 rsachallenge chg;
956 951
957 if (!rsa_cache.find (p->id, chg)) 952 if (!rsa_cache.find (p->id, chg))
958 { 953 {
959 slog (L_ERR, _("%s(%s): unrequested auth response"), 954 slog (L_ERR, _("%s(%s): unrequested auth response ignored"),
960 conf->nodename, (const char *)rsi); 955 conf->nodename, (const char *)rsi);
961 break; 956 break;
962 } 957 }
963 else 958 else
964 { 959 {
965 crypto_ctx *cctx = new crypto_ctx (chg, 0); 960 crypto_ctx *cctx = new crypto_ctx (chg, 0);
966 961
967 if (!p->hmac_chk (cctx)) 962 if (!p->hmac_chk (cctx))
963 {
968 slog (L_ERR, _("%s(%s): hmac authentication error on auth response, received invalid packet\n" 964 slog (L_ERR, _("%s(%s): hmac authentication error on auth response, received invalid packet\n"
969 "could be an attack, or just corruption or an synchronization error"), 965 "could be an attack, or just corruption or an synchronization error"),
970 conf->nodename, (const char *)rsi); 966 conf->nodename, (const char *)rsi);
967 break;
968 }
971 else 969 else
972 { 970 {
973 rsaresponse h; 971 rsaresponse h;
974 972
975 rsa_hash (p->id, chg, h); 973 rsa_hash (p->id, chg, h);
1031 tap_packet *d = p->unpack (this, seqno); 1029 tap_packet *d = p->unpack (this, seqno);
1032 1030
1033 if (iseqno.recv_ok (seqno)) 1031 if (iseqno.recv_ok (seqno))
1034 { 1032 {
1035 vpn->tap->send (d); 1033 vpn->tap->send (d);
1036
1037 if (p->dst () == 0) // re-broadcast
1038 for (vpn::conns_vector::iterator i = vpn->conns.begin (); i != vpn->conns.end (); ++i)
1039 {
1040 connection *c = *i;
1041
1042 if (c->conf != THISNODE && c->conf != conf)
1043 c->inject_data_packet (d);
1044 }
1045 1034
1046 if (si != rsi) 1035 if (si != rsi)
1047 { 1036 {
1048 // fast re-sync on connection changes, useful especially for tcp/ip 1037 // fast re-sync on connection changes, useful especially for tcp/ip
1049 si = rsi; 1038 si = rsi;
1123 { 1112 {
1124 reset_connection (); 1113 reset_connection ();
1125 establish_connection (); 1114 establish_connection ();
1126 } 1115 }
1127 else if (NOW < last_activity + ::conf.keepalive) 1116 else if (NOW < last_activity + ::conf.keepalive)
1128 w.at = last_activity + ::conf.keepalive; 1117 w.start (last_activity + ::conf.keepalive);
1129 else if (conf->connectmode != conf_node::C_ONDEMAND 1118 else if (conf->connectmode != conf_node::C_ONDEMAND
1130 || THISNODE->connectmode != conf_node::C_ONDEMAND) 1119 || THISNODE->connectmode != conf_node::C_ONDEMAND)
1131 { 1120 {
1132 send_ping (si); 1121 send_ping (si);
1133 w.at = NOW + 5; 1122 w.start (NOW + 5);
1134 } 1123 }
1135 else if (NOW < last_activity + ::conf.keepalive + 10) 1124 else if (NOW < last_activity + ::conf.keepalive + 10)
1136 // hold ondemand connections implicitly a few seconds longer 1125 // hold ondemand connections implicitly a few seconds longer
1137 // should delete octx, though, or something like that ;) 1126 // should delete octx, though, or something like that ;)
1138 w.at = last_activity + ::conf.keepalive + 10; 1127 w.start (last_activity + ::conf.keepalive + 10);
1139 else 1128 else
1140 reset_connection (); 1129 reset_connection ();
1141} 1130}
1142 1131
1143void connection::send_connect_request (int id) 1132void connection::send_connect_request (int id)

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines