X-Git-Url: https://www.tinc-vpn.org/git/browse?p=tinc;a=blobdiff_plain;f=src%2Fnet.c;h=3328863e633d160df1cee8d6e18f096880e98136;hp=544bf63568eb6614e9b2f71ebdfc7cda5b6b1d2d;hb=f64b41a73b3b432aae17ba990414e0be2f61ce62;hpb=f0aa9641e82fb6e09c1e485366d14dddaa7f7c36 diff --git a/src/net.c b/src/net.c index 544bf635..3328863e 100644 --- a/src/net.c +++ b/src/net.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: net.c,v 1.35.4.152 2002/02/10 21:57:54 guus Exp $ + $Id: net.c,v 1.35.4.155 2002/02/12 14:36:45 guus Exp $ */ #include "config.h" @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -55,6 +54,8 @@ #define RAND_pseudo_bytes RAND_bytes #endif +#include + #include #include #include @@ -96,11 +97,16 @@ int sigalrm = 0; void receive_udppacket(node_t *n, vpn_packet_t *inpkt) { - vpn_packet_t outpkt; + vpn_packet_t pkt1, pkt2; + vpn_packet_t *pkt[] = {&pkt1, &pkt2, &pkt1, &pkt2}; + int nextpkt = 0; + vpn_packet_t *outpkt = pkt[0]; int outlen, outpad; + long int complen = MTU + 12; EVP_CIPHER_CTX ctx; char hmac[EVP_MAX_MD_SIZE]; cp + /* Check the message authentication code */ if(myself->digest && myself->maclength) { @@ -117,30 +123,49 @@ cp if(myself->cipher) { + outpkt = pkt[nextpkt++]; + EVP_DecryptInit(&ctx, myself->cipher, myself->key, myself->key + myself->cipher->key_len); - EVP_DecryptUpdate(&ctx, (char *)&outpkt.seqno, &outlen, (char *)&inpkt->seqno, inpkt->len); - EVP_DecryptFinal(&ctx, (char *)&outpkt.seqno + outlen, &outpad); - outlen += outpad; - outpkt.len = outlen - sizeof(outpkt.seqno); - } - else - { - memcpy((char *)&outpkt.seqno, (char *)&inpkt->seqno, inpkt->len); - outpkt.len = inpkt->len - sizeof(outpkt.seqno); + EVP_DecryptUpdate(&ctx, (char *)&outpkt->seqno, &outlen, (char *)&inpkt->seqno, inpkt->len); + EVP_DecryptFinal(&ctx, (char *)&outpkt->seqno + outlen, &outpad); + + outpkt->len = outlen + outpad; + inpkt = outpkt; } - if (ntohl(outpkt.seqno) <= n->received_seqno) + /* Check the sequence number */ + + inpkt->len -= sizeof(inpkt->seqno); + inpkt->seqno = ntohl(inpkt->seqno); + + if(inpkt->seqno <= n->received_seqno) { - syslog(LOG_DEBUG, _("Got late or replayed packet from %s (%s), seqno %d"), n->name, n->hostname, ntohl(*(unsigned int *)&outpkt.seqno)); + syslog(LOG_DEBUG, _("Got late or replayed packet from %s (%s), seqno %d"), n->name, n->hostname, inpkt->seqno); return; } - n->received_seqno = ntohl(outpkt.seqno); + n->received_seqno = inpkt->seqno; if(n->received_seqno > MAX_SEQNO) keyexpires = 0; - receive_packet(n, &outpkt); + /* Decompress the packet */ + + if(myself->compression) + { + outpkt = pkt[nextpkt++]; + + if(uncompress(outpkt->data, &complen, inpkt->data, inpkt->len) != Z_OK) + { + syslog(LOG_ERR, _("Error while uncompressing packet from %s (%s)"), n->name, n->hostname); + return; + } + + outpkt->len = complen; + inpkt = outpkt; + } + + receive_packet(n, inpkt); cp } @@ -167,8 +192,12 @@ cp void send_udppacket(node_t *n, vpn_packet_t *inpkt) { - vpn_packet_t outpkt; + vpn_packet_t pkt1, pkt2; + vpn_packet_t *pkt[] = {&pkt1, &pkt2, &pkt1, &pkt2}; + int nextpkt = 0; + vpn_packet_t *outpkt; int outlen, outpad; + long int complen = MTU + 12; EVP_CIPHER_CTX ctx; struct sockaddr_in to; socklen_t tolen = sizeof(to); @@ -190,37 +219,60 @@ cp if(!n->status.waitingforkey) send_req_key(n->nexthop->connection, myself, n); + + return; + } + + /* Compress the packet */ + + if(n->compression) + { + outpkt = pkt[nextpkt++]; + + if(compress2(outpkt->data, &complen, inpkt->data, inpkt->len, n->compression) != Z_OK) + { + syslog(LOG_ERR, _("Error while compressing packet to %s (%s)"), n->name, n->hostname); return; } + + outpkt->len = complen; + inpkt = outpkt; + } - /* Encrypt the packet. */ + /* Add sequence number */ inpkt->seqno = htonl(++(n->sent_seqno)); + inpkt->len += sizeof(inpkt->seqno); + + /* Encrypt the packet */ if(n->cipher) { + outpkt = pkt[nextpkt++]; + EVP_EncryptInit(&ctx, n->cipher, n->key, n->key + n->cipher->key_len); - EVP_EncryptUpdate(&ctx, (char *)&outpkt.seqno, &outlen, (char *)&inpkt->seqno, inpkt->len + sizeof(inpkt->seqno)); - EVP_EncryptFinal(&ctx, (char *)&outpkt.seqno + outlen, &outpad); - outlen += outpad; - } - else - { - memcpy((char *)&outpkt.seqno, (char *)&inpkt->seqno, inpkt->len + sizeof(inpkt->seqno)); - outlen = inpkt->len + sizeof(inpkt->seqno); + EVP_EncryptUpdate(&ctx, (char *)&outpkt->seqno, &outlen, (char *)&inpkt->seqno, inpkt->len); + EVP_EncryptFinal(&ctx, (char *)&outpkt->seqno + outlen, &outpad); + + outpkt->len = outlen + outpad; + inpkt = outpkt; } + /* Add the message authentication code */ + if(n->digest && n->maclength) { - HMAC(n->digest, n->key, n->keylength, (char *)&outpkt.seqno, outlen, (char *)&outpkt.seqno + outlen, &outpad); - outlen += n->maclength; + HMAC(n->digest, n->key, n->keylength, (char *)&inpkt->seqno, inpkt->len, (char *)&inpkt->seqno + inpkt->len, &outlen); + inpkt->len += n->maclength; } + /* Send the packet */ + to.sin_family = AF_INET; to.sin_addr.s_addr = htonl(n->address); to.sin_port = htons(n->port); - if((sendto(udp_socket, (char *)&outpkt.seqno, outlen, 0, (const struct sockaddr *)&to, tolen)) < 0) + if((sendto(udp_socket, (char *)&inpkt->seqno, inpkt->len, 0, (const struct sockaddr *)&to, tolen)) < 0) { syslog(LOG_ERR, _("Error sending packet to %s (%s): %m"), n->name, n->hostname); @@ -596,6 +648,7 @@ cp { BN_hex2bn(&c->rsa_key->n, key); BN_hex2bn(&c->rsa_key->e, "FFFF"); + free(key); return 0; } @@ -609,8 +662,10 @@ cp { syslog(LOG_ERR, _("Error reading RSA public key file `%s': %m"), fname); + free(fname); return -1; } + free(fname); c->rsa_key = PEM_read_RSAPublicKey(fp, &c->rsa_key, NULL, NULL); fclose(fp); if(!c->rsa_key) @@ -622,7 +677,10 @@ cp return 0; } else - return -1; + { + free(fname); + return -1; + } } /* Else, check if a harnessed public key is in the config file */ @@ -655,15 +713,23 @@ cp myself->connection->rsa_key = RSA_new(); BN_hex2bn(&myself->connection->rsa_key->d, key); BN_hex2bn(&myself->connection->rsa_key->e, "FFFF"); + free(key); + return 0; } - else if(get_config_string(lookup_config(config_tree, "PrivateKeyFile"), &fname)) + + if(!get_config_string(lookup_config(config_tree, "PrivateKeyFile"), &fname)) + asprintf(&fname, "%s/rsa_key.priv", confbase); + + if(is_safe_path(fname)) { if((fp = fopen(fname, "r")) == NULL) { syslog(LOG_ERR, _("Error reading RSA private key file `%s': %m"), fname); + free(fname); return -1; } + free(fname); myself->connection->rsa_key = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); fclose(fp); if(!myself->connection->rsa_key) @@ -672,11 +738,36 @@ cp fname); return -1; } + return 0; + } + + free(fname); + return -1; +} + +int check_rsa_key(RSA *rsa_key) +{ + char *test1, *test2, *test3; +cp + if(rsa_key->p && rsa_key->q) + { + if(RSA_check_key(rsa_key) != 1) + return -1; } else { - syslog(LOG_ERR, _("No private key for tinc daemon specified!")); - return -1; + test1 = xmalloc(RSA_size(rsa_key)); + test2 = xmalloc(RSA_size(rsa_key)); + test3 = xmalloc(RSA_size(rsa_key)); + + if(RSA_public_encrypt(RSA_size(rsa_key), test1, test2, rsa_key, RSA_NO_PADDING) != RSA_size(rsa_key)) + return -1; + + if(RSA_private_decrypt(RSA_size(rsa_key), test2, test3, rsa_key, RSA_NO_PADDING) != RSA_size(rsa_key)) + return -1; + + if(memcmp(test1, test3, RSA_size(rsa_key))) + return -1; } cp return 0; @@ -732,13 +823,12 @@ cp return -1; cp -/* - if(RSA_check_key(rsa_key) != 1) + if(check_rsa_key(myself->connection->rsa_key)) { syslog(LOG_ERR, _("Invalid public/private keypair!")); return -1; } -*/ + if(!get_config_port(lookup_config(myself->connection->config_tree, "Port"), &myself->port)) myself->port = 655; @@ -883,6 +973,19 @@ cp } else myself->maclength = 4; + + /* Compression */ + + if(get_config_int(lookup_config(myself->connection->config_tree, "Compression"), &myself->compression)) + { + if(myself->compression < 0 || myself->compression > 9) + { + syslog(LOG_ERR, _("Bogus compression level!")); + return -1; + } + } + else + myself->compression = 0; cp /* Done */