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.22 by pcg, Thu Oct 16 02:41:21 2003 UTC

1/* 1/*
2 connection.C -- manage a single connection 2 connection.C -- manage a single connection
3 Copyright (C) 2003 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.
35#include "slog.h" 36#include "slog.h"
36#include "device.h" 37#include "device.h"
37#include "vpn.h" 38#include "vpn.h"
38#include "connection.h" 39#include "connection.h"
39 40
41#include "netcompat.h"
42
40#if !HAVE_RAND_PSEUDO_BYTES 43#if !HAVE_RAND_PSEUDO_BYTES
41# define RAND_pseudo_bytes RAND_bytes 44# define RAND_pseudo_bytes RAND_bytes
42#endif 45#endif
43 46
44#define MAGIC "vped\xbd\xc6\xdb\x82" // 8 bytes of magic 47#define MAGIC "vped\xbd\xc6\xdb\x82" // 8 bytes of magic
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 (%d <=> %d)"), prot_major, PROTOCOL_MAJOR);
482 && hmaclen == HMACLENGTH 485 else if (randsize != RAND_SIZE)
483 && flags == curflags () 486 slog (L_WARN, _("rand size mismatch (%d <=> %d)"), randsize, RAND_SIZE);
487 else if (hmaclen != HMACLENGTH)
488 slog (L_WARN, _("hmac length mismatch (%d <=> %d)"), hmaclen, HMACLENGTH);
489 else if (flags != curflags ())
490 slog (L_WARN, _("flag mismatch (%x <=> %x)"), flags, curflags ());
484 && challengelen == sizeof (rsachallenge) 491 else if (challengelen != sizeof (rsachallenge))
492 slog (L_WARN, _("challenge length mismatch (%d <=> %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 (%x <=> %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 (%x <=> %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 (%x <=> %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);
778 reset_connection (); 801 reset_connection ();
779 establish_connection (); 802 establish_connection ();
780} 803}
781 804
782void 805void
783connection::send_data_packet (tap_packet *pkt, bool broadcast) 806connection::send_data_packet (tap_packet *pkt)
784{ 807{
785 vpndata_packet *p = new vpndata_packet; 808 vpndata_packet *p = new vpndata_packet;
786 int tos = 0; 809 int tos = 0;
787 810
788 if (conf->inherit_tos 811 // I am not hilarious about peeking into packets, but so be it.
789 && (*pkt)[12] == 0x08 && (*pkt)[13] == 0x00 // IP 812 if (conf->inherit_tos && pkt->is_ipv4 ())
790 && ((*pkt)[14] & 0xf0) == 0x40) // IPv4
791 tos = (*pkt)[15] & IPTOS_TOS_MASK; 813 tos = (*pkt)[15] & IPTOS_TOS_MASK;
792 814
793 p->setup (this, broadcast ? 0 : conf->id, &((*pkt)[6 + 6]), pkt->len - 6 - 6, ++oseqno); // skip 2 macs 815 p->setup (this, conf->id, &((*pkt)[6 + 6]), pkt->len - 6 - 6, ++oseqno); // skip 2 macs
794 send_vpn_packet (p, si, tos); 816 send_vpn_packet (p, si, tos);
795 817
796 delete p; 818 delete p;
797 819
798 if (oseqno > MAX_SEQNO) 820 if (oseqno > MAX_SEQNO)
799 rekey (); 821 rekey ();
800} 822}
801 823
802void 824void
803connection::inject_data_packet (tap_packet *pkt, bool broadcast) 825connection::inject_data_packet (tap_packet *pkt, bool broadcast/*TODO DDD*/)
804{ 826{
805 if (ictx && octx) 827 if (ictx && octx)
806 send_data_packet (pkt, broadcast); 828 send_data_packet (pkt);
807 else 829 else
808 { 830 {
809 if (!broadcast)//DDDD 831 if (!broadcast)//DDDD
810 queue.put (new tap_packet (*pkt)); 832 data_queue.put (new tap_packet (*pkt));
811 833
812 establish_connection (); 834 establish_connection ();
813 } 835 }
814} 836}
815 837
816void connection::inject_vpn_packet (vpn_packet *pkt, int tos) 838void connection::inject_vpn_packet (vpn_packet *pkt, int tos)
817{ 839{
818 if (ictx && octx) 840 if (ictx && octx)
819 send_vpn_packet (pkt, si, tos); 841 send_vpn_packet (pkt, si, tos);
820 else 842 else
843 {
844 vpn_queue.put (new vpn_packet (*pkt));
845
821 establish_connection (); 846 establish_connection ();
847 }
822} 848}
823 849
824void 850void
825connection::recv_vpn_packet (vpn_packet *pkt, const sockinfo &rsi) 851connection::recv_vpn_packet (vpn_packet *pkt, const sockinfo &rsi)
826{ 852{
885 rsachallenge k; 911 rsachallenge k;
886 912
887 if (0 > RSA_private_decrypt (sizeof (p->encr), 913 if (0 > RSA_private_decrypt (sizeof (p->encr),
888 (unsigned char *)&p->encr, (unsigned char *)&k, 914 (unsigned char *)&p->encr, (unsigned char *)&k,
889 ::conf.rsa_key, RSA_PKCS1_OAEP_PADDING)) 915 ::conf.rsa_key, RSA_PKCS1_OAEP_PADDING))
890 slog (L_ERR, _("%s(%s): challenge illegal or corrupted"), 916 slog (L_ERR, _("%s(%s): challenge illegal or corrupted (%s). mismatched key or config file?"),
891 conf->nodename, (const char *)rsi); 917 conf->nodename, (const char *)rsi, ERR_error_string (ERR_get_error (), 0));
892 else 918 else
893 { 919 {
894 delete octx; 920 delete octx;
895 921
896 octx = new crypto_ctx (k, 1); 922 octx = new crypto_ctx (k, 1);
903 connection_established (); 929 connection_established ();
904 930
905 break; 931 break;
906 } 932 }
907 } 933 }
934 else
935 slog (L_WARN, _("%s(%s): protocol mismatch"),
936 conf->nodename, (const char *)rsi);
908 937
909 send_reset (rsi); 938 send_reset (rsi);
910 } 939 }
911 940
912 break; 941 break;
925 PROTOCOL_MINOR, conf->nodename, p->prot_minor); 954 PROTOCOL_MINOR, conf->nodename, p->prot_minor);
926 955
927 rsachallenge chg; 956 rsachallenge chg;
928 957
929 if (!rsa_cache.find (p->id, chg)) 958 if (!rsa_cache.find (p->id, chg))
959 {
930 slog (L_ERR, _("%s(%s): unrequested auth response"), 960 slog (L_ERR, _("%s(%s): unrequested auth response ignored"),
931 conf->nodename, (const char *)rsi); 961 conf->nodename, (const char *)rsi);
962 break;
963 }
932 else 964 else
933 { 965 {
934 crypto_ctx *cctx = new crypto_ctx (chg, 0); 966 crypto_ctx *cctx = new crypto_ctx (chg, 0);
935 967
936 if (!p->hmac_chk (cctx)) 968 if (!p->hmac_chk (cctx))
969 {
937 slog (L_ERR, _("%s(%s): hmac authentication error on auth response, received invalid packet\n" 970 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"), 971 "could be an attack, or just corruption or an synchronization error"),
939 conf->nodename, (const char *)rsi); 972 conf->nodename, (const char *)rsi);
973 break;
974 }
940 else 975 else
941 { 976 {
942 rsaresponse h; 977 rsaresponse h;
943 978
944 rsa_hash (p->id, chg, h); 979 rsa_hash (p->id, chg, h);
1001 1036
1002 if (iseqno.recv_ok (seqno)) 1037 if (iseqno.recv_ok (seqno))
1003 { 1038 {
1004 vpn->tap->send (d); 1039 vpn->tap->send (d);
1005 1040
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) 1041 if (si != rsi)
1016 { 1042 {
1017 // fast re-sync on conneciton changes, useful especially for tcp/ip 1043 // fast re-sync on connection changes, useful especially for tcp/ip
1018 si = rsi; 1044 si = rsi;
1019 1045
1020 slog (L_INFO, _("%s(%s): socket address changed to %s"), 1046 slog (L_INFO, _("%s(%s): socket address changed to %s"),
1021 conf->nodename, (const char *)si, (const char *)rsi); 1047 conf->nodename, (const char *)si, (const char *)rsi);
1022 } 1048 }
1099 || THISNODE->connectmode != conf_node::C_ONDEMAND) 1125 || THISNODE->connectmode != conf_node::C_ONDEMAND)
1100 { 1126 {
1101 send_ping (si); 1127 send_ping (si);
1102 w.at = NOW + 5; 1128 w.at = NOW + 5;
1103 } 1129 }
1130 else if (NOW < last_activity + ::conf.keepalive + 10)
1131 // hold ondemand connections implicitly a few seconds longer
1132 // should delete octx, though, or something like that ;)
1133 w.at = last_activity + ::conf.keepalive + 10;
1104 else 1134 else
1105 reset_connection (); 1135 reset_connection ();
1106} 1136}
1107 1137
1108void connection::send_connect_request (int id) 1138void connection::send_connect_request (int id)

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines