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.102 by root, Thu Jul 18 13:35:16 2013 UTC vs.
Revision 1.107 by root, Fri Sep 20 11:57:03 2013 UTC

33 33
34#include <list> 34#include <list>
35#include <queue> 35#include <queue>
36#include <utility> 36#include <utility>
37 37
38#include <openssl/opensslv.h>
38#include <openssl/rand.h> 39#include <openssl/rand.h>
39#include <openssl/evp.h> 40#include <openssl/evp.h>
40#include <openssl/rsa.h> 41#include <openssl/rsa.h>
41#include <openssl/err.h> 42#include <openssl/err.h>
43
44// openssl 0.9.8 compatibility
45#if OPENSSL_VERSION_NUMBER < 0x10100000
46 #define require101(exp) exp
47#else
48 #define require101(exp) equire (exp)
49#endif
42 50
43#include "conf.h" 51#include "conf.h"
44#include "slog.h" 52#include "slog.h"
45#include "device.h" 53#include "device.h"
46#include "vpn.h" 54#include "vpn.h"
126 kdf.extract (s, sizeof (s)); 134 kdf.extract (s, sizeof (s));
127 kdf.extract_done (HKDF_PRF_HASH ()); 135 kdf.extract_done (HKDF_PRF_HASH ());
128 kdf.expand (mac_key, sizeof (mac_key), mac_info, sizeof (mac_info)); 136 kdf.expand (mac_key, sizeof (mac_key), mac_info, sizeof (mac_info));
129 137
130 HMAC_CTX_init (&hctx); 138 HMAC_CTX_init (&hctx);
131 require (HMAC_Init_ex (&hctx, mac_key, MAC_KEYSIZE, MAC_DIGEST (), 0)); 139 require101 (HMAC_Init_ex (&hctx, mac_key, MAC_KEYSIZE, MAC_DIGEST (), 0));
132 } 140 }
133 141
134 { 142 {
135 u8 cipher_key[CIPHER_KEYSIZE]; 143 u8 cipher_key[CIPHER_KEYSIZE];
136 static const unsigned char cipher_info[] = "gvpe cipher key"; 144 static const unsigned char cipher_info[] = "gvpe cipher key";
178 186
179 return 1; 187 return 1;
180} 188}
181 189
182static void 190static void
183auth_hash (const auth_data &auth, auth_mac &mac) 191auth_hash (const auth_data &auth, const ecdh_key &b, auth_mac &mac)
184{ 192{
185 HMAC_CTX ctx; 193 hkdf kdf (b, sizeof b, AUTH_DIGEST ()); // use response ecdh b as salt
186 194 kdf.extract (&auth.rsa, sizeof (auth.rsa));
187 HMAC_CTX_init (&ctx); 195 kdf.extract_done ();
188 require (HMAC_Init_ex (&ctx, auth.rsa.auth_key, sizeof (auth.rsa.auth_key), AUTH_DIGEST (), 0)); 196 kdf.expand (mac, sizeof mac, auth.ecdh, sizeof (auth.ecdh)); // use challenge ecdh b as info
189 require (HMAC_Update (&ctx, (const unsigned char *)&auth, sizeof auth));
190 require (HMAC_Final (&ctx, (unsigned char *)&mac, 0));
191 HMAC_CTX_cleanup (&ctx);
192} 197}
193 198
194void 199void
195connection::generate_auth_data () 200connection::generate_auth_data ()
196{ 201{
197 if (auth_expire < ev_now ()) 202 if (auth_expire < ev_now ())
198 { 203 {
199 // request data 204 // request data
200 rand_fill (snd_auth.rsa); 205 rand_fill (snd_auth.rsa);
201 curve25519_generate (snd_ecdh_a, snd_auth.ecdh); 206 curve25519_generate (snd_ecdh_a, snd_auth.ecdh);
202 auth_hash (snd_auth, snd_auth_mac);
203 207
204 // eventual response data 208 // eventual response data
205 curve25519_generate (rcv_ecdh_a, rcv_ecdh_b); 209 curve25519_generate (rcv_ecdh_a, rcv_ecdh_b);
206 } 210 }
207 211
363 } 367 }
364} 368}
365 369
366///////////////////////////////////////////////////////////////////////////// 370/////////////////////////////////////////////////////////////////////////////
367 371
368unsigned char hmac_packet::hmac_digest[EVP_MAX_MD_SIZE];
369
370void 372void
371hmac_packet::hmac_gen (crypto_ctx *ctx) 373hmac_packet::hmac_gen (crypto_ctx *ctx, u8 *hmac_digest)
372{ 374{
373 unsigned int xlen;
374
375 HMAC_CTX *hctx = &ctx->hctx; 375 HMAC_CTX *hctx = &ctx->hctx;
376 376
377 require (HMAC_Init_ex (hctx, 0, 0, 0, 0)); 377 require101 (HMAC_Init_ex (hctx, 0, 0, 0, 0));
378 require (HMAC_Update (hctx, ((unsigned char *) this) + sizeof (hmac_packet), 378 require101 (HMAC_Update (hctx, ((unsigned char *) this) + sizeof (hmac_packet), len - sizeof (hmac_packet)));
379 len - sizeof (hmac_packet)));
380 require (HMAC_Final (hctx, (unsigned char *) &hmac_digest, &xlen)); 379 require101 (HMAC_Final (hctx, hmac_digest, 0));
381} 380}
382 381
383void 382void
384hmac_packet::hmac_set (crypto_ctx *ctx) 383hmac_packet::hmac_set (crypto_ctx *ctx)
385{ 384{
386 hmac_gen (ctx); 385 unsigned char hmac_digest[EVP_MAX_MD_SIZE];
387 386 hmac_gen (ctx, hmac_digest);
388 memcpy (hmac, hmac_digest, HMACLENGTH); 387 memcpy (hmac, hmac_digest, HMACLENGTH);
389} 388}
390 389
391bool 390bool
392hmac_packet::hmac_chk (crypto_ctx *ctx) 391hmac_packet::hmac_chk (crypto_ctx *ctx)
393{ 392{
394 hmac_gen (ctx); 393 unsigned char hmac_digest[EVP_MAX_MD_SIZE];
395 394 hmac_gen (ctx, hmac_digest);
396 return !memcmp (hmac, hmac_digest, HMACLENGTH); 395 return !memcmp (hmac, hmac_digest, HMACLENGTH);
397} 396}
398 397
399void 398void
400vpn_packet::set_hdr (ptype type_, unsigned int dst) 399vpn_packet::set_hdr (ptype type_, unsigned int dst)
552 } 551 }
553}; 552};
554 553
555struct config_packet : vpn_packet 554struct config_packet : vpn_packet
556{ 555{
556 u8 serial[SERIAL_SIZE];
557 u8 prot_major, prot_minor, randsize; 557 u8 prot_major, prot_minor, randsize;
558 u8 flags, features, pad6, pad7, pad8; 558 u8 flags, features, pad6, pad7, pad8;
559 u32 cipher_nid, mac_nid, auth_nid; 559 u32 cipher_nid, mac_nid, auth_nid;
560 560
561 void setup (ptype type, int dst); 561 void setup (ptype type, int dst);
562 bool chk_config () const; 562 bool chk_config (const conf_node *conf, const sockinfo &rsi) const;
563 563
564 static u8 get_features () 564 static u8 get_features ()
565 { 565 {
566 u8 f = 0; 566 u8 f = 0;
567#if ENABLE_COMPRESSION 567#if ENABLE_COMPRESSION
584 prot_minor = PROTOCOL_MINOR; 584 prot_minor = PROTOCOL_MINOR;
585 randsize = RAND_SIZE; 585 randsize = RAND_SIZE;
586 flags = 0; 586 flags = 0;
587 features = get_features (); 587 features = get_features ();
588 588
589 strncpy ((char *)serial, conf.serial, sizeof (serial));
590
589 cipher_nid = htonl (EVP_CIPHER_nid (CIPHER ())); 591 cipher_nid = htonl (EVP_CIPHER_nid (CIPHER ()));
590 mac_nid = htonl (EVP_MD_type (MAC_DIGEST ())); 592 mac_nid = htonl (EVP_MD_type (MAC_DIGEST ()));
591 auth_nid = htonl (EVP_MD_type (AUTH_DIGEST ())); 593 auth_nid = htonl (EVP_MD_type (AUTH_DIGEST ()));
592 594
593 len = sizeof (*this) - sizeof (net_packet); 595 len = sizeof (*this) - sizeof (net_packet);
594 set_hdr (type, dst); 596 set_hdr (type, dst);
595} 597}
596 598
597bool 599bool
598config_packet::chk_config () const 600config_packet::chk_config (const conf_node *conf, const sockinfo &rsi) const
599{ 601{
600 if (prot_major != PROTOCOL_MAJOR) 602 if (prot_major != PROTOCOL_MAJOR)
601 slog (L_WARN, _("major version mismatch (remote %d <=> local %d)"), prot_major, PROTOCOL_MAJOR); 603 slog (L_WARN, _("%s(%s): major version mismatch (remote %d <=> local %d)"),
604 conf->nodename, (const char *)rsi, prot_major, PROTOCOL_MAJOR);
602 else if (randsize != RAND_SIZE) 605 else if (randsize != RAND_SIZE)
603 slog (L_WARN, _("rand size mismatch (remote %d <=> local %d)"), randsize, RAND_SIZE); 606 slog (L_WARN, _("%s(%s): rand size mismatch (remote %d <=> local %d)"),
607 conf->nodename, (const char *)rsi, randsize, RAND_SIZE);
604 else if (cipher_nid != htonl (EVP_CIPHER_nid (CIPHER ()))) 608 else if (cipher_nid != htonl (EVP_CIPHER_nid (CIPHER ())))
605 slog (L_WARN, _("cipher algo mismatch (remote %x <=> local %x)"), ntohl (cipher_nid), EVP_CIPHER_nid (CIPHER ())); 609 slog (L_WARN, _("%s(%s): cipher algo mismatch (remote %x <=> local %x)"),
610 conf->nodename, (const char *)rsi, ntohl (cipher_nid), EVP_CIPHER_nid (CIPHER ()));
606 else if (mac_nid != htonl (EVP_MD_type (MAC_DIGEST ()))) 611 else if (mac_nid != htonl (EVP_MD_type (MAC_DIGEST ())))
607 slog (L_WARN, _("mac algo mismatch (remote %x <=> local %x)"), ntohl (mac_nid), EVP_MD_type (MAC_DIGEST ())); 612 slog (L_WARN, _("%s(%s): mac algo mismatch (remote %x <=> local %x)"),
613 conf->nodename, (const char *)rsi, ntohl (mac_nid), EVP_MD_type (MAC_DIGEST ()));
608 else if (auth_nid != htonl (EVP_MD_type (AUTH_DIGEST ()))) 614 else if (auth_nid != htonl (EVP_MD_type (AUTH_DIGEST ())))
609 slog (L_WARN, _("auth algo mismatch (remote %x <=> local %x)"), ntohl (auth_nid), EVP_MD_type (AUTH_DIGEST ())); 615 slog (L_WARN, _("%s(%s): auth algo mismatch (remote %x <=> local %x)"),
616 conf->nodename, (const char *)rsi, ntohl (auth_nid), EVP_MD_type (AUTH_DIGEST ()));
610 else 617 else
618 {
619 int cmp = memcmp (serial, ::conf.serial, sizeof (serial));
620
621 if (cmp > 0)
622 slog (L_WARN, _("%s(%s): remote serial newer than local serial - outdated config?"),
623 conf->nodename, (const char *)rsi);
624 else if (cmp == 0)
611 return true; 625 return true;
626 }
612 627
613 return false; 628 return false;
614} 629}
615 630
616struct auth_req_packet : config_packet // UNPROTECTED 631struct auth_req_packet : config_packet // UNPROTECTED
630 645
631 len = sizeof (*this) - sizeof (net_packet); 646 len = sizeof (*this) - sizeof (net_packet);
632 } 647 }
633}; 648};
634 649
635struct auth_res_packet : config_packet // UNPROTECTED 650struct auth_res_packet : vpn_packet // UNPROTECTED
636{ 651{
637 auth_response response; 652 auth_response response;
638 653
639 auth_res_packet (int dst) 654 auth_res_packet (int dst)
640 { 655 {
641 config_packet::setup (PT_AUTH_RES, dst); 656 set_hdr (PT_AUTH_RES, dst);
642 657
643 len = sizeof (*this) - sizeof (net_packet); 658 len = sizeof (*this) - sizeof (net_packet);
644 } 659 }
645}; 660};
646 661
820void 835void
821connection::send_auth_response (const sockinfo &si) 836connection::send_auth_response (const sockinfo &si)
822{ 837{
823 auth_res_packet *pkt = new auth_res_packet (conf->id); 838 auth_res_packet *pkt = new auth_res_packet (conf->id);
824 839
825 auth_hash (rcv_auth, pkt->response.mac);
826 memcpy (pkt->response.ecdh, rcv_ecdh_b, sizeof (rcv_ecdh_b)); 840 memcpy (pkt->response.ecdh, rcv_ecdh_b, sizeof rcv_ecdh_b);
841 auth_hash (rcv_auth, rcv_ecdh_b, pkt->response.mac);
827 842
828 slog (L_TRACE, "%s << PT_AUTH_RES [%s]", conf->nodename, (const char *)si); 843 slog (L_TRACE, "%s << PT_AUTH_RES [%s]", conf->nodename, (const char *)si);
829 send_vpn_packet (pkt, si, IPTOS_RELIABILITY); // rsa is very very costly 844 send_vpn_packet (pkt, si, IPTOS_RELIABILITY); // rsa is very very costly
830 845
831 delete pkt; 846 delete pkt;
1056 { 1071 {
1057 reset_connection (); 1072 reset_connection ();
1058 1073
1059 config_packet *p = (config_packet *) pkt; 1074 config_packet *p = (config_packet *) pkt;
1060 1075
1061 if (!p->chk_config ()) 1076 if (p->chk_config (conf, rsi) && connectmode == conf_node::C_ALWAYS)
1062 {
1063 slog (L_WARN, _("%s(%s): protocol mismatch, disabling node."),
1064 conf->nodename, (const char *)rsi);
1065 connectmode = conf_node::C_DISABLED;
1066 }
1067 else if (connectmode == conf_node::C_ALWAYS)
1068 establish_connection (); 1077 establish_connection ();
1069 } 1078 }
1070 break; 1079 break;
1071 1080
1072 case vpn_packet::PT_AUTH_REQ: 1081 case vpn_packet::PT_AUTH_REQ:
1076 1085
1077 slog (L_TRACE, "%s >> PT_AUTH_REQ(%s,p%02x,f%02x)", 1086 slog (L_TRACE, "%s >> PT_AUTH_REQ(%s,p%02x,f%02x)",
1078 conf->nodename, p->initiate ? "initiate" : "reply", 1087 conf->nodename, p->initiate ? "initiate" : "reply",
1079 p->protocols, p->features); 1088 p->protocols, p->features);
1080 1089
1081 if (p->chk_config () && !memcmp (p->magic, MAGIC, 8)) 1090 if (memcmp (p->magic, MAGIC, 8))
1091 {
1092 slog (L_WARN, _("%s(%s): protocol magic mismatch - stray packet?"),
1093 conf->nodename, (const char *)rsi);
1094 }
1095 else if (p->chk_config (conf, rsi))
1082 { 1096 {
1083 if (p->prot_minor != PROTOCOL_MINOR) 1097 if (p->prot_minor != PROTOCOL_MINOR)
1084 slog (L_INFO, _("%s(%s): protocol minor version mismatch: ours is %d, %s's is %d."), 1098 slog (L_INFO, _("%s(%s): protocol minor version mismatch: ours is %d, %s's is %d."),
1085 conf->nodename, (const char *)rsi, 1099 conf->nodename, (const char *)rsi,
1086 PROTOCOL_MINOR, conf->nodename, p->prot_minor); 1100 PROTOCOL_MINOR, conf->nodename, p->prot_minor);
1113 } 1127 }
1114 } 1128 }
1115 1129
1116 break; 1130 break;
1117 } 1131 }
1118 else
1119 slog (L_WARN, _("%s(%s): protocol mismatch."),
1120 conf->nodename, (const char *)rsi);
1121 1132
1122 send_reset (rsi); 1133 send_reset (rsi);
1123 } 1134 }
1124 1135
1125 break; 1136 break;
1128 { 1139 {
1129 auth_res_packet *p = (auth_res_packet *)pkt; 1140 auth_res_packet *p = (auth_res_packet *)pkt;
1130 1141
1131 slog (L_TRACE, "%s >> PT_AUTH_RES", conf->nodename); 1142 slog (L_TRACE, "%s >> PT_AUTH_RES", conf->nodename);
1132 1143
1133 if (p->chk_config ()) 1144 auth_mac local_mac;
1145 auth_hash (snd_auth, p->response.ecdh, local_mac);
1146
1147 if (memcmp (&p->response.mac, local_mac, sizeof local_mac))
1134 { 1148 {
1135 if (memcmp (&p->response.mac, snd_auth_mac, sizeof (snd_auth_mac)))
1136 {
1137 slog (L_ERR, _("%s(%s): unrequested or outdated auth response, ignoring."), 1149 slog (L_ERR, _("%s(%s): unrequested or outdated auth response, ignoring."),
1138 conf->nodename, (const char *)rsi); 1150 conf->nodename, (const char *)rsi);
1139 } 1151 }
1140 else if (!have_snd_auth) 1152 else if (!have_snd_auth)
1141 { 1153 {
1142 if (p->prot_minor != PROTOCOL_MINOR)
1143 slog (L_INFO, _("%s(%s): protocol minor version mismatch: ours is %d, %s's is %d."),
1144 conf->nodename, (const char *)rsi,
1145 PROTOCOL_MINOR, conf->nodename, p->prot_minor);
1146
1147 prot_minor = p->prot_minor;
1148 memcpy (snd_ecdh_b, p->response.ecdh, sizeof (snd_ecdh_b)); 1154 memcpy (snd_ecdh_b, p->response.ecdh, sizeof snd_ecdh_b);
1149 1155
1150 have_snd_auth = true; 1156 have_snd_auth = true;
1151 connection_established (rsi); 1157 connection_established (rsi);
1152 }
1153
1154 break;
1155 } 1158 }
1156 } 1159 }
1157
1158 send_reset (rsi);
1159 break; 1160 break;
1160 1161
1161 case vpn_packet::PT_DATA_COMPRESSED: 1162 case vpn_packet::PT_DATA_COMPRESSED:
1162#if !ENABLE_COMPRESSION 1163#if !ENABLE_COMPRESSION
1163 send_reset (rsi); 1164 send_reset (rsi);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines