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.11 by pcg, Sun Apr 13 00:35:46 2003 UTC vs.
Revision 1.25 by pcg, Sat Jan 17 01:18:36 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
147 } 150 }
148} 151}
149 152
150////////////////////////////////////////////////////////////////////////////// 153//////////////////////////////////////////////////////////////////////////////
151 154
152void pkt_queue::put (tap_packet *p) 155void pkt_queue::put (net_packet *p)
153{ 156{
154 if (queue[i]) 157 if (queue[i])
155 { 158 {
156 delete queue[i]; 159 delete queue[i];
157 j = (j + 1) % QUEUEDEPTH; 160 j = (j + 1) % QUEUEDEPTH;
160 queue[i] = p; 163 queue[i] = p;
161 164
162 i = (i + 1) % QUEUEDEPTH; 165 i = (i + 1) % QUEUEDEPTH;
163} 166}
164 167
165tap_packet *pkt_queue::get () 168net_packet *pkt_queue::get ()
166{ 169{
167 tap_packet *p = queue[j]; 170 net_packet *p = queue[j];
168 171
169 if (p) 172 if (p)
170 { 173 {
171 queue[j] = 0; 174 queue[j] = 0;
172 j = (j + 1) % QUEUEDEPTH; 175 j = (j + 1) % QUEUEDEPTH;
197// only do action once every x seconds per host whole allowing bursts. 200// only do action once every x seconds per host whole allowing bursts.
198// this implementation ("splay list" ;) is inefficient, 201// this implementation ("splay list" ;) is inefficient,
199// but low on resources. 202// but low on resources.
200struct net_rate_limiter : list<net_rateinfo> 203struct net_rate_limiter : list<net_rateinfo>
201{ 204{
202 static const double ALPHA = 1. - 1. / 180.; // allow bursts 205 static const double ALPHA = 1. - 1. / 600.; // allow bursts
203 static const double CUTOFF = 10.; // one event every CUTOFF seconds 206 static const double CUTOFF = 10.; // one event every CUTOFF seconds
204 static const double EXPIRE = CUTOFF * 30.; // expire entries after this time 207 static const double EXPIRE = CUTOFF * 30.; // expire entries after this time
205 static const double MAXDIF = CUTOFF * (1. / (1. - ALPHA)); // maximum diff /count value 208 static const double MAXDIF = CUTOFF * (1. / (1. - ALPHA)); // maximum diff /count value
206 209
207 bool can (const sockinfo &si) { return can((u32)si.host); } 210 bool can (const sockinfo &si) { return can((u32)si.host); }
208 bool can (u32 host); 211 bool can (u32 host);
209}; 212};
210 213
211net_rate_limiter auth_rate_limiter, reset_rate_limiter; 214net_rate_limiter auth_rate_limiter, reset_rate_limiter;
212 215
475 set_hdr (type, dst); 478 set_hdr (type, dst);
476} 479}
477 480
478bool config_packet::chk_config () const 481bool config_packet::chk_config () const
479{ 482{
480 return prot_major == PROTOCOL_MAJOR 483 if (prot_major != PROTOCOL_MAJOR)
481 && randsize == RAND_SIZE 484 slog (L_WARN, _("major version mismatch (remote %d <=> local %d)"), prot_major, PROTOCOL_MAJOR);
482 && hmaclen == HMACLENGTH 485 else if (randsize != RAND_SIZE)
483 && flags == curflags () 486 slog (L_WARN, _("rand size mismatch (remote %d <=> local %d)"), randsize, RAND_SIZE);
487 else if (hmaclen != HMACLENGTH)
488 slog (L_WARN, _("hmac length mismatch (remote %d <=> local %d)"), hmaclen, HMACLENGTH);
489 else if (flags != curflags ())
490 slog (L_WARN, _("flag mismatch (remote %x <=> local %x)"), flags, curflags ());
484 && challengelen == sizeof (rsachallenge) 491 else if (challengelen != sizeof (rsachallenge))
492 slog (L_WARN, _("challenge length mismatch (remote %d <=> local %d)"), challengelen, sizeof (rsachallenge));
485 && cipher_nid == htonl (EVP_CIPHER_nid (CIPHER)) 493 else if (cipher_nid != htonl (EVP_CIPHER_nid (CIPHER)))
494 slog (L_WARN, _("cipher mismatch (remote %x <=> local %x)"), ntohl (cipher_nid), EVP_CIPHER_nid (CIPHER));
486 && digest_nid == htonl (EVP_MD_type (RSA_HASH)) 495 else if (digest_nid != htonl (EVP_MD_type (RSA_HASH)))
496 slog (L_WARN, _("digest mismatch (remote %x <=> local %x)"), ntohl (digest_nid), EVP_MD_type (RSA_HASH));
487 && hmac_nid == htonl (EVP_MD_type (DIGEST)); 497 else if (hmac_nid != htonl (EVP_MD_type (DIGEST)))
498 slog (L_WARN, _("hmac mismatch (remote %x <=> local %x)"), ntohl (hmac_nid), EVP_MD_type (DIGEST));
499 else
500 return true;
501
502 return false;
488} 503}
489 504
490struct auth_req_packet : config_packet 505struct auth_req_packet : config_packet
491{ 506{
492 char magic[8]; 507 char magic[8];
565 rekey.start (NOW + ::conf.rekey); 580 rekey.start (NOW + ::conf.rekey);
566 keepalive.start (NOW + ::conf.keepalive); 581 keepalive.start (NOW + ::conf.keepalive);
567 582
568 // send queued packets 583 // send queued packets
569 if (ictx && octx) 584 if (ictx && octx)
585 {
570 while (tap_packet *p = queue.get ()) 586 while (tap_packet *p = (tap_packet *)data_queue.get ())
571 { 587 {
572 send_data_packet (p); 588 send_data_packet (p);
573 delete p; 589 delete p;
574 } 590 }
591
592 while (vpn_packet *p = (vpn_packet *)vpn_queue.get ())
593 {
594 send_vpn_packet (p, si, IPTOS_RELIABILITY);
595 delete p;
596 }
597 }
575 } 598 }
576 else 599 else
577 { 600 {
578 retry_cnt = 0; 601 retry_cnt = 0;
579 establish_connection.start (NOW + 5); 602 establish_connection.start (NOW + 5);
580 keepalive.reset (); 603 keepalive.stop ();
581 rekey.reset (); 604 rekey.stop ();
582 } 605 }
583} 606}
584 607
585void 608void
586connection::reset_si () 609connection::reset_si ()
652connection::send_auth_request (const sockinfo &si, bool initiate) 675connection::send_auth_request (const sockinfo &si, bool initiate)
653{ 676{
654 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);
655 678
656 rsachallenge chg; 679 rsachallenge chg;
657
658 rsa_cache.gen (pkt->id, chg); 680 rsa_cache.gen (pkt->id, chg);
659 681 rsa_encrypt (conf->rsa_key, chg, pkt->encr);
660 if (0 > RSA_public_encrypt (sizeof chg,
661 (unsigned char *)&chg, (unsigned char *)&pkt->encr,
662 conf->rsa_key, RSA_PKCS1_OAEP_PADDING))
663 fatal ("RSA_public_encrypt error");
664 682
665 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);
666 684
667 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
668 686
702} 720}
703 721
704void 722void
705connection::establish_connection_cb (time_watcher &w) 723connection::establish_connection_cb (time_watcher &w)
706{ 724{
707 if (ictx || conf == THISNODE 725 if (!ictx
726 && conf != THISNODE
708 || connectmode == conf_node::C_NEVER 727 && connectmode != conf_node::C_NEVER
709 || connectmode == conf_node::C_DISABLED) 728 && connectmode != conf_node::C_DISABLED
710 w.at = TSTAMP_CANCEL; 729 && w.at <= NOW)
711 else if (w.at <= NOW)
712 { 730 {
713 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;
714 732
715 if (retry_int < 3600 * 8) 733 if (retry_int < 3600 * 8)
716 retry_cnt++; 734 retry_cnt++;
717 735
718 w.at = NOW + retry_int; 736 w.start (NOW + retry_int);
719 737
720 reset_si (); 738 reset_si ();
721 739
722 if (si.prot && !si.host) 740 if (si.prot && !si.host)
723 vpn->send_connect_request (conf->id); 741 vpn->send_connect_request (conf->id);
754 si.host= 0; 772 si.host= 0;
755 773
756 last_activity = 0; 774 last_activity = 0;
757 retry_cnt = 0; 775 retry_cnt = 0;
758 776
759 rekey.reset (); 777 rekey.stop ();
760 keepalive.reset (); 778 keepalive.stop ();
761 establish_connection.reset (); 779 establish_connection.stop ();
762} 780}
763 781
764void 782void
765connection::shutdown () 783connection::shutdown ()
766{ 784{
771} 789}
772 790
773void 791void
774connection::rekey_cb (time_watcher &w) 792connection::rekey_cb (time_watcher &w)
775{ 793{
776 w.at = TSTAMP_CANCEL;
777
778 reset_connection (); 794 reset_connection ();
779 establish_connection (); 795 establish_connection ();
780} 796}
781 797
782void 798void
783connection::send_data_packet (tap_packet *pkt, bool broadcast) 799connection::send_data_packet (tap_packet *pkt)
784{ 800{
785 vpndata_packet *p = new vpndata_packet; 801 vpndata_packet *p = new vpndata_packet;
786 int tos = 0; 802 int tos = 0;
787 803
788 if (conf->inherit_tos 804 // I am not hilarious about peeking into packets, but so be it.
789 && (*pkt)[12] == 0x08 && (*pkt)[13] == 0x00 // IP 805 if (conf->inherit_tos && pkt->is_ipv4 ())
790 && ((*pkt)[14] & 0xf0) == 0x40) // IPv4
791 tos = (*pkt)[15] & IPTOS_TOS_MASK; 806 tos = (*pkt)[15] & IPTOS_TOS_MASK;
792 807
793 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
794 send_vpn_packet (p, si, tos); 809 send_vpn_packet (p, si, tos);
795 810
796 delete p; 811 delete p;
797 812
798 if (oseqno > MAX_SEQNO) 813 if (oseqno > MAX_SEQNO)
799 rekey (); 814 rekey ();
800} 815}
801 816
802void 817void
803connection::inject_data_packet (tap_packet *pkt, bool broadcast) 818connection::inject_data_packet (tap_packet *pkt, bool broadcast/*TODO DDD*/)
804{ 819{
805 if (ictx && octx) 820 if (ictx && octx)
806 send_data_packet (pkt, broadcast); 821 send_data_packet (pkt);
807 else 822 else
808 { 823 {
809 if (!broadcast)//DDDD 824 if (!broadcast)//DDDD
810 queue.put (new tap_packet (*pkt)); 825 data_queue.put (new tap_packet (*pkt));
811 826
812 establish_connection (); 827 establish_connection ();
813 } 828 }
814} 829}
815 830
816void connection::inject_vpn_packet (vpn_packet *pkt, int tos) 831void connection::inject_vpn_packet (vpn_packet *pkt, int tos)
817{ 832{
818 if (ictx && octx) 833 if (ictx && octx)
819 send_vpn_packet (pkt, si, tos); 834 send_vpn_packet (pkt, si, tos);
820 else 835 else
836 {
837 vpn_queue.put (new vpn_packet (*pkt));
838
821 establish_connection (); 839 establish_connection ();
840 }
822} 841}
823 842
824void 843void
825connection::recv_vpn_packet (vpn_packet *pkt, const sockinfo &rsi) 844connection::recv_vpn_packet (vpn_packet *pkt, const sockinfo &rsi)
826{ 845{
882 if (p->initiate) 901 if (p->initiate)
883 send_auth_request (rsi, false); 902 send_auth_request (rsi, false);
884 903
885 rsachallenge k; 904 rsachallenge k;
886 905
887 if (0 > RSA_private_decrypt (sizeof (p->encr), 906 if (!rsa_decrypt (::conf.rsa_key, p->encr, k))
888 (unsigned char *)&p->encr, (unsigned char *)&k, 907 {
889 ::conf.rsa_key, RSA_PKCS1_OAEP_PADDING))
890 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?"),
891 conf->nodename, (const char *)rsi); 909 conf->nodename, (const char *)rsi, ERR_error_string (ERR_get_error (), 0));
910 break;
911 }
892 else 912 else
893 { 913 {
894 delete octx; 914 delete octx;
895 915
896 octx = new crypto_ctx (k, 1); 916 octx = new crypto_ctx (k, 1);
903 connection_established (); 923 connection_established ();
904 924
905 break; 925 break;
906 } 926 }
907 } 927 }
928 else
929 slog (L_WARN, _("%s(%s): protocol mismatch"),
930 conf->nodename, (const char *)rsi);
908 931
909 send_reset (rsi); 932 send_reset (rsi);
910 } 933 }
911 934
912 break; 935 break;
925 PROTOCOL_MINOR, conf->nodename, p->prot_minor); 948 PROTOCOL_MINOR, conf->nodename, p->prot_minor);
926 949
927 rsachallenge chg; 950 rsachallenge chg;
928 951
929 if (!rsa_cache.find (p->id, chg)) 952 if (!rsa_cache.find (p->id, chg))
953 {
930 slog (L_ERR, _("%s(%s): unrequested auth response"), 954 slog (L_ERR, _("%s(%s): unrequested auth response ignored"),
931 conf->nodename, (const char *)rsi); 955 conf->nodename, (const char *)rsi);
956 break;
957 }
932 else 958 else
933 { 959 {
934 crypto_ctx *cctx = new crypto_ctx (chg, 0); 960 crypto_ctx *cctx = new crypto_ctx (chg, 0);
935 961
936 if (!p->hmac_chk (cctx)) 962 if (!p->hmac_chk (cctx))
963 {
937 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"
938 "could be an attack, or just corruption or an synchronization error"), 965 "could be an attack, or just corruption or an synchronization error"),
939 conf->nodename, (const char *)rsi); 966 conf->nodename, (const char *)rsi);
967 break;
968 }
940 else 969 else
941 { 970 {
942 rsaresponse h; 971 rsaresponse h;
943 972
944 rsa_hash (p->id, chg, h); 973 rsa_hash (p->id, chg, h);
1001 1030
1002 if (iseqno.recv_ok (seqno)) 1031 if (iseqno.recv_ok (seqno))
1003 { 1032 {
1004 vpn->tap->send (d); 1033 vpn->tap->send (d);
1005 1034
1006 if (p->dst () == 0) // re-broadcast
1007 for (vpn::conns_vector::iterator i = vpn->conns.begin (); i != vpn->conns.end (); ++i)
1008 {
1009 connection *c = *i;
1010
1011 if (c->conf != THISNODE && c->conf != conf)
1012 c->inject_data_packet (d);
1013 }
1014
1015 if (si != rsi) 1035 if (si != rsi)
1016 { 1036 {
1017 // fast re-sync on conneciton changes, useful especially for tcp/ip 1037 // fast re-sync on connection changes, useful especially for tcp/ip
1018 si = rsi; 1038 si = rsi;
1019 1039
1020 slog (L_INFO, _("%s(%s): socket address changed to %s"), 1040 slog (L_INFO, _("%s(%s): socket address changed to %s"),
1021 conf->nodename, (const char *)si, (const char *)rsi); 1041 conf->nodename, (const char *)si, (const char *)rsi);
1022 } 1042 }
1092 { 1112 {
1093 reset_connection (); 1113 reset_connection ();
1094 establish_connection (); 1114 establish_connection ();
1095 } 1115 }
1096 else if (NOW < last_activity + ::conf.keepalive) 1116 else if (NOW < last_activity + ::conf.keepalive)
1097 w.at = last_activity + ::conf.keepalive; 1117 w.start (last_activity + ::conf.keepalive);
1098 else if (conf->connectmode != conf_node::C_ONDEMAND 1118 else if (conf->connectmode != conf_node::C_ONDEMAND
1099 || THISNODE->connectmode != conf_node::C_ONDEMAND) 1119 || THISNODE->connectmode != conf_node::C_ONDEMAND)
1100 { 1120 {
1101 send_ping (si); 1121 send_ping (si);
1102 w.at = NOW + 5; 1122 w.start (NOW + 5);
1103 } 1123 }
1124 else if (NOW < last_activity + ::conf.keepalive + 10)
1125 // hold ondemand connections implicitly a few seconds longer
1126 // should delete octx, though, or something like that ;)
1127 w.start (last_activity + ::conf.keepalive + 10);
1104 else 1128 else
1105 reset_connection (); 1129 reset_connection ();
1106} 1130}
1107 1131
1108void connection::send_connect_request (int id) 1132void connection::send_connect_request (int id)

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines