From 2956559f7d12caa9779207525419801e0e9ab3e3 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Sun, 13 Apr 2014 00:20:55 +0200 Subject: [PATCH] Remove support for the legacy protocol. We only allow SPTPS connections. --- src/Makefile.am | 6 +- src/cipher.h | 1 - src/connection.c | 9 -- src/connection.h | 14 +-- src/graph.c | 17 +-- src/invitation.c | 13 -- src/libmeshlink.c | 59 +-------- src/meta.c | 114 +---------------- src/net.h | 1 - src/net_packet.c | 250 ++----------------------------------- src/net_setup.c | 142 +-------------------- src/net_socket.c | 6 - src/node.c | 5 - src/node.h | 8 +- src/openssl/rsa.c | 111 ----------------- src/openssl/rsagen.c | 81 ------------ src/protocol.c | 4 +- src/protocol.h | 9 -- src/protocol_auth.c | 290 ++----------------------------------------- src/protocol_key.c | 173 +++++--------------------- src/rsa.h | 36 ------ src/rsagen.h | 29 ----- 22 files changed, 64 insertions(+), 1314 deletions(-) delete mode 100644 src/openssl/rsa.c delete mode 100644 src/openssl/rsagen.c delete mode 100644 src/rsa.h delete mode 100644 src/rsagen.h diff --git a/src/Makefile.am b/src/Makefile.am index b9a83071..58d7b2de 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -58,8 +58,6 @@ libmeshlink_la_SOURCES = \ protocol_key.c \ protocol_misc.c \ route.c route.h \ - rsa.h \ - rsagen.h \ splay_tree.c splay_tree.h \ sptps.c sptps.h \ system.h \ @@ -78,9 +76,7 @@ libmeshlink_la_SOURCES += \ openssl/ecdh.c \ openssl/ecdsa.c \ openssl/ecdsagen.c \ - openssl/prf.c \ - openssl/rsa.c \ - openssl/rsagen.c + openssl/prf.c sptps_test_SOURCES += \ openssl/cipher.c \ openssl/crypto.c \ diff --git a/src/cipher.h b/src/cipher.h index c2a8e068..b7d8f4b0 100644 --- a/src/cipher.h +++ b/src/cipher.h @@ -33,7 +33,6 @@ extern void cipher_close(cipher_t *); extern size_t cipher_keylength(const cipher_t *); extern void cipher_get_key(const cipher_t *, void *); extern bool cipher_set_key(cipher_t *, void *, bool) __attribute__ ((__warn_unused_result__)); -extern bool cipher_set_key_from_rsa(cipher_t *, void *, size_t, bool) __attribute__ ((__warn_unused_result__)); extern bool cipher_set_counter(cipher_t *, const void *, size_t) __attribute__ ((__warn_unused_result__)); extern bool cipher_set_counter_key(cipher_t *, void *) __attribute__ ((__warn_unused_result__)); extern bool cipher_encrypt(cipher_t *, const void *indata, size_t inlen, void *outdata, size_t *outlen, bool oneshot) __attribute__ ((__warn_unused_result__)); diff --git a/src/connection.c b/src/connection.c index 02e1a84d..d25159e6 100644 --- a/src/connection.c +++ b/src/connection.c @@ -25,7 +25,6 @@ #include "connection.h" #include "list.h" #include "logger.h" -#include "rsa.h" #include "utils.h" #include "xalloc.h" @@ -52,16 +51,8 @@ void free_connection(connection_t *c) { if(!c) return; - cipher_close(c->incipher); - digest_close(c->indigest); - cipher_close(c->outcipher); - digest_close(c->outdigest); - sptps_stop(&c->sptps); ecdsa_free(c->ecdsa); - rsa_free(c->rsa); - - free(c->hischallenge); buffer_clear(&c->inbuf); buffer_clear(&c->outbuf); diff --git a/src/connection.h b/src/connection.h index f8eb56b7..e1b270b3 100644 --- a/src/connection.h +++ b/src/connection.h @@ -23,7 +23,6 @@ #include "buffer.h" #include "cipher.h" #include "digest.h" -#include "rsa.h" #include "list.h" #include "sptps.h" @@ -40,8 +39,8 @@ typedef struct connection_status_t { unsigned int unused_termreq:1; /* the termination of this connection was requested */ unsigned int remove_unused:1; /* Set to 1 if you want this connection removed */ unsigned int timeout_unused:1; /* 1 if gotten timeout */ - unsigned int encryptout:1; /* 1 if we can encrypt outgoing traffic */ - unsigned int decryptin:1; /* 1 if we have to decrypt incoming traffic */ + unsigned int unused_encryptout:1; /* 1 if we can encrypt outgoing traffic */ + unsigned int unused_decryptin:1; /* 1 if we have to decrypt incoming traffic */ unsigned int mst:1; /* 1 if this connection is part of a minimum spanning tree */ unsigned int control:1; /* 1 if this is a control connection */ unsigned int pcap:1; /* 1 if this is a control connection requesting packet capture */ @@ -74,21 +73,12 @@ typedef struct connection_t { struct node_t *node; /* node associated with the other end */ struct edge_t *edge; /* edge associated with this connection */ - rsa_t *rsa; /* his public RSA key */ ecdsa_t *ecdsa; /* his public ECDSA key */ - cipher_t *incipher; /* Cipher he will use to send data to us */ - cipher_t *outcipher; /* Cipher we will use to send data to him */ - digest_t *indigest; - digest_t *outdigest; sptps_t sptps; - int inmaclength; - int outmaclength; int incompression; int outcompression; - char *hischallenge; /* The challenge we sent to him */ - struct buffer_t inbuf; struct buffer_t outbuf; io_t io; /* input/output event on this metadata connection */ diff --git a/src/graph.c b/src/graph.c index d3ac4e6b..233cf544 100644 --- a/src/graph.c +++ b/src/graph.c @@ -208,16 +208,11 @@ static void check_reachability(void) { n->name, n->hostname); } - if(experimental && OPTION_VERSION(n->options) >= 2) - n->status.sptps = true; - /* TODO: only clear status.validkey if node is unreachable? */ n->status.validkey = false; - if(n->status.sptps) { - sptps_stop(&n->sptps); - n->status.waitingforkey = false; - } + sptps_stop(&n->sptps); + n->status.waitingforkey = false; n->last_req_key = 0; n->status.udp_confirmed = false; @@ -234,12 +229,8 @@ static void check_reachability(void) { memset(&n->status, 0, sizeof n->status); n->options = 0; } else if(n->connection) { - if(n->status.sptps) { - if(n->connection->outgoing) - send_req_key(n); - } else { - send_ans_key(n); - } + if(n->connection->outgoing) + send_req_key(n); } } } diff --git a/src/invitation.c b/src/invitation.c index f75bf409..6c0b0afb 100644 --- a/src/invitation.c +++ b/src/invitation.c @@ -25,7 +25,6 @@ #include "ecdsagen.h" #include "invitation.h" #include "netutl.h" -#include "rsagen.h" #include "sptps.h" #include "tincctl.h" #include "utils.h" @@ -712,19 +711,7 @@ make_names: sptps_send_record(&sptps, 1, b64key, strlen(b64key)); free(b64key); - - rsa_t *rsa = rsa_generate(2048, 0x1001); - xasprintf(&filename, "%s" SLASH "rsa_key.priv", confbase); - f = fopenmask(filename, "w", 0600); - - rsa_write_pem_private_key(rsa, f); - fclose(f); - - rsa_write_pem_public_key(rsa, fh); - fclose(fh); - ecdsa_free(key); - rsa_free(rsa); check_port(name); diff --git a/src/libmeshlink.c b/src/libmeshlink.c index a1fef4cc..761b3a41 100644 --- a/src/libmeshlink.c +++ b/src/libmeshlink.c @@ -263,63 +263,6 @@ bool ecdsa_keygen(bool ask) { return true; } -/* - Generate a public/private RSA keypair, and ask for a file to store - them in. -*/ -bool rsa_keygen(int bits, bool ask) { - rsa_t *key; - FILE *f; - char *pubname, *privname; - - fprintf(stderr, "Generating %d bits keys:\n", bits); - - if(!(key = rsa_generate(bits, 0x10001))) { - fprintf(stderr, "Error during key generation!\n"); - return false; - } else - fprintf(stderr, "Done.\n"); - - xasprintf(&privname, "%s" SLASH "rsa_key.priv", confbase); - f = ask_and_open(privname, "private RSA key", "a", ask, 0600); - free(privname); - - if(!f) - return false; - - if(!rsa_write_pem_private_key(key, f)) { - fprintf(stderr, "Error writing private key!\n"); - fclose(f); - rsa_free(key); - return false; - } - - fclose(f); - - if(name) - xasprintf(&pubname, "%s" SLASH "hosts" SLASH "%s", confbase, name); - else - xasprintf(&pubname, "%s" SLASH "rsa_key.pub", confbase); - - f = ask_and_open(pubname, "public RSA key", "a", ask, 0666); - free(pubname); - - if(!f) - return false; - - if(!rsa_write_pem_public_key(key, f)) { - fprintf(stderr, "Error writing public key!\n"); - fclose(f); - rsa_free(key); - return false; - } - - fclose(f); - rsa_free(key); - - return true; -} - static bool try_bind(int port) { struct addrinfo *ai = NULL; struct addrinfo hint = { @@ -411,7 +354,7 @@ bool tinc_setup(const char* confbaseapi, const char* name) { fprintf(f, "Name = %s\n", name); fclose(f); - if(!rsa_keygen(2048, false) || !ecdsa_keygen(false)) + if(!ecdsa_keygen(false)) return false; check_port(name); diff --git a/src/meta.c b/src/meta.c index 945a740a..b15ed837 100644 --- a/src/meta.c +++ b/src/meta.c @@ -51,25 +51,7 @@ bool send_meta(connection_t *c, const char *buffer, int length) { logger(DEBUG_META, LOG_DEBUG, "Sending %d bytes of metadata to %s (%s)", length, c->name, c->hostname); - if(c->protocol_minor >= 2) - return sptps_send_record(&c->sptps, 0, buffer, length); - - /* Add our data to buffer */ - if(c->status.encryptout) { - size_t outlen = length; - - if(!cipher_encrypt(c->outcipher, buffer, length, buffer_prepare(&c->outbuf, length), &outlen, false) || outlen != length) { - logger(DEBUG_ALWAYS, LOG_ERR, "Error while encrypting metadata to %s (%s)", - c->name, c->hostname); - return false; - } - } else { - buffer_add(&c->outbuf, buffer, length); - } - - io_set(&c->io, IO_READ | IO_WRITE); - - return true; + return sptps_send_record(&c->sptps, 0, buffer, length); } void broadcast_meta(connection_t *from, const char *buffer, int length) { @@ -151,97 +133,5 @@ bool receive_meta(connection_t *c) { return false; } - do { - if(c->protocol_minor >= 2) - return sptps_receive_data(&c->sptps, bufp, inlen); - - if(!c->status.decryptin) { - endp = memchr(bufp, '\n', inlen); - if(endp) - endp++; - else - endp = bufp + inlen; - - buffer_add(&c->inbuf, bufp, endp - bufp); - - inlen -= endp - bufp; - bufp = endp; - } else { - size_t outlen = inlen; - - if(!cipher_decrypt(c->incipher, bufp, inlen, buffer_prepare(&c->inbuf, inlen), &outlen, false) || inlen != outlen) { - logger(DEBUG_ALWAYS, LOG_ERR, "Error while decrypting metadata from %s (%s)", - c->name, c->hostname); - return false; - } - - inlen = 0; - } - - while(c->inbuf.len) { - /* Are we receiving a TCPpacket? */ - - if(c->tcplen) { - char *tcpbuffer = buffer_read(&c->inbuf, c->tcplen); - if(!tcpbuffer) - break; - - if(!c->node) { - if(c->outgoing && proxytype == PROXY_SOCKS4 && c->allow_request == ID) { - if(tcpbuffer[0] == 0 && tcpbuffer[1] == 0x5a) { - logger(DEBUG_CONNECTIONS, LOG_DEBUG, "Proxy request granted"); - } else { - logger(DEBUG_CONNECTIONS, LOG_ERR, "Proxy request rejected"); - return false; - } - } else if(c->outgoing && proxytype == PROXY_SOCKS5 && c->allow_request == ID) { - if(tcpbuffer[0] != 5) { - logger(DEBUG_CONNECTIONS, LOG_ERR, "Invalid response from proxy server"); - return false; - } - if(tcpbuffer[1] == (char)0xff) { - logger(DEBUG_CONNECTIONS, LOG_ERR, "Proxy request rejected: unsuitable authentication method"); - return false; - } - if(tcpbuffer[2] != 5) { - logger(DEBUG_CONNECTIONS, LOG_ERR, "Invalid response from proxy server"); - return false; - } - if(tcpbuffer[3] == 0) { - logger(DEBUG_CONNECTIONS, LOG_DEBUG, "Proxy request granted"); - } else { - logger(DEBUG_CONNECTIONS, LOG_DEBUG, "Proxy request rejected"); - return false; - } - } else { - logger(DEBUG_CONNECTIONS, LOG_ERR, "c->tcplen set but c->node is NULL!"); - abort(); - } - } else { - if(c->allow_request == ALL) { - receive_tcppacket(c, tcpbuffer, c->tcplen); - } else { - logger(DEBUG_CONNECTIONS, LOG_ERR, "Got unauthorized TCP packet from %s (%s)", c->name, c->hostname); - return false; - } - } - - c->tcplen = 0; - } - - /* Otherwise we are waiting for a request */ - - char *request = buffer_readline(&c->inbuf); - if(request) { - bool result = receive_request(c, request); - if(!result) - return false; - continue; - } else { - break; - } - } - } while(inlen); - - return true; + return sptps_receive_data(&c->sptps, bufp, inlen); } diff --git a/src/net.h b/src/net.h index 2dceb300..c49f0bd4 100644 --- a/src/net.h +++ b/src/net.h @@ -181,7 +181,6 @@ extern int main_loop(void); extern void terminate_connection(struct connection_t *, bool); extern bool node_read_ecdsa_public_key(struct node_t *); extern bool read_ecdsa_public_key(struct connection_t *); -extern bool read_rsa_public_key(struct connection_t *); extern void send_mtu_probe(struct node_t *); extern void handle_device_data(void *, int); extern void handle_meta_connection_data(struct connection_t *); diff --git a/src/net_packet.c b/src/net_packet.c index 8ff8e61b..818dd388 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -285,13 +285,7 @@ static void receive_packet(node_t *n, vpn_packet_t *packet) { } static bool try_mac(node_t *n, const vpn_packet_t *inpkt) { - if(n->status.sptps) - return sptps_verify_datagram(&n->sptps, (char *)&inpkt->seqno, inpkt->len); - - if(!digest_active(n->indigest) || inpkt->len < sizeof inpkt->seqno + digest_length(n->indigest)) - return false; - - return digest_verify(n->indigest, &inpkt->seqno, inpkt->len - digest_length(n->indigest), (const char *)&inpkt->seqno + inpkt->len - digest_length(n->indigest)); + return sptps_verify_datagram(&n->sptps, (char *)&inpkt->seqno, inpkt->len); } static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) { @@ -301,115 +295,16 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) { vpn_packet_t *outpkt = pkt[0]; size_t outlen; - if(n->status.sptps) { - if(!n->sptps.state) { - if(!n->status.waitingforkey) { - logger(DEBUG_TRAFFIC, LOG_DEBUG, "Got packet from %s (%s) but we haven't exchanged keys yet", n->name, n->hostname); - send_req_key(n); - } else { - logger(DEBUG_TRAFFIC, LOG_DEBUG, "Got packet from %s (%s) but he hasn't got our key yet", n->name, n->hostname); - } - return; + if(!n->sptps.state) { + if(!n->status.waitingforkey) { + logger(DEBUG_TRAFFIC, LOG_DEBUG, "Got packet from %s (%s) but we haven't exchanged keys yet", n->name, n->hostname); + send_req_key(n); + } else { + logger(DEBUG_TRAFFIC, LOG_DEBUG, "Got packet from %s (%s) but he hasn't got our key yet", n->name, n->hostname); } - sptps_receive_data(&n->sptps, (char *)&inpkt->seqno, inpkt->len); - return; - } - - if(!cipher_active(n->incipher)) { - logger(DEBUG_TRAFFIC, LOG_DEBUG, "Got packet from %s (%s) but he hasn't got our key yet", n->name, n->hostname); - return; - } - - /* Check packet length */ - - if(inpkt->len < sizeof inpkt->seqno + digest_length(n->indigest)) { - logger(DEBUG_TRAFFIC, LOG_DEBUG, "Got too short packet from %s (%s)", - n->name, n->hostname); return; } - - /* Check the message authentication code */ - - if(digest_active(n->indigest)) { - inpkt->len -= digest_length(n->indigest); - if(!digest_verify(n->indigest, &inpkt->seqno, inpkt->len, (const char *)&inpkt->seqno + inpkt->len)) { - logger(DEBUG_TRAFFIC, LOG_DEBUG, "Got unauthenticated packet from %s (%s)", n->name, n->hostname); - return; - } - } - /* Decrypt the packet */ - - if(cipher_active(n->incipher)) { - outpkt = pkt[nextpkt++]; - outlen = MAXSIZE; - - if(!cipher_decrypt(n->incipher, &inpkt->seqno, inpkt->len, &outpkt->seqno, &outlen, true)) { - logger(DEBUG_TRAFFIC, LOG_DEBUG, "Error decrypting packet from %s (%s)", n->name, n->hostname); - return; - } - - outpkt->len = outlen; - inpkt = outpkt; - } - - /* Check the sequence number */ - - inpkt->len -= sizeof inpkt->seqno; - inpkt->seqno = ntohl(inpkt->seqno); - - if(replaywin) { - if(inpkt->seqno != n->received_seqno + 1) { - if(inpkt->seqno >= n->received_seqno + replaywin * 8) { - logger(DEBUG_ALWAYS, LOG_WARNING, "Lost %d packets from %s (%s)", - inpkt->seqno - n->received_seqno - 1, n->name, n->hostname); - memset(n->late, 0, replaywin); - } else if (inpkt->seqno <= n->received_seqno) { - if((n->received_seqno >= replaywin * 8 && inpkt->seqno <= n->received_seqno - replaywin * 8) || !(n->late[(inpkt->seqno / 8) % replaywin] & (1 << inpkt->seqno % 8))) { - logger(DEBUG_ALWAYS, LOG_WARNING, "Got late or replayed packet from %s (%s), seqno %d, last received %d", - n->name, n->hostname, inpkt->seqno, n->received_seqno); - return; - } - } else { - for(int i = n->received_seqno + 1; i < inpkt->seqno; i++) - n->late[(i / 8) % replaywin] |= 1 << i % 8; - } - } - - n->late[(inpkt->seqno / 8) % replaywin] &= ~(1 << inpkt->seqno % 8); - } - - if(inpkt->seqno > n->received_seqno) - n->received_seqno = inpkt->seqno; - - n->received++; - - if(n->received_seqno > MAX_SEQNO) - regenerate_key(); - - /* Decompress the packet */ - - length_t origlen = inpkt->len; - - if(n->incompression) { - outpkt = pkt[nextpkt++]; - - if((outpkt->len = uncompress_packet(outpkt->data, inpkt->data, inpkt->len, n->incompression)) < 0) { - logger(DEBUG_TRAFFIC, LOG_ERR, "Error while uncompressing packet from %s (%s)", - n->name, n->hostname); - return; - } - - inpkt = outpkt; - - origlen -= MTU/64 + 20; - } - - inpkt->priority = 0; - - if(!inpkt->data[12] && !inpkt->data[13]) - mtu_probe_h(n, inpkt, origlen); - else - receive_packet(n, inpkt); + sptps_receive_data(&n->sptps, (char *)&inpkt->seqno, inpkt->len); } void receive_tcppacket(connection_t *c, const char *buffer, int len) { @@ -581,116 +476,7 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) { return; } - if(n->status.sptps) - return send_sptps_packet(n, origpkt); - - /* Make sure we have a valid key */ - - if(!n->status.validkey) { - logger(DEBUG_TRAFFIC, LOG_INFO, - "No valid key known yet for %s (%s), forwarding via TCP", - n->name, n->hostname); - - if(n->last_req_key + 10 <= now.tv_sec) { - send_req_key(n); - n->last_req_key = now.tv_sec; - } - - send_tcppacket(n->nexthop->connection, origpkt); - - return; - } - - if(n->options & OPTION_PMTU_DISCOVERY && inpkt->len > n->minmtu && (inpkt->data[12] | inpkt->data[13])) { - logger(DEBUG_TRAFFIC, LOG_INFO, - "Packet for %s (%s) larger than minimum MTU, forwarding via %s", - n->name, n->hostname, n != n->nexthop ? n->nexthop->name : "TCP"); - - if(n != n->nexthop) - send_packet(n->nexthop, origpkt); - else - send_tcppacket(n->nexthop->connection, origpkt); - - return; - } - - /* Compress the packet */ - - if(n->outcompression) { - outpkt = pkt[nextpkt++]; - - if((outpkt->len = compress_packet(outpkt->data, inpkt->data, inpkt->len, n->outcompression)) < 0) { - logger(DEBUG_TRAFFIC, LOG_ERR, "Error while compressing packet to %s (%s)", - n->name, n->hostname); - return; - } - - inpkt = outpkt; - } - - /* Add sequence number */ - - inpkt->seqno = htonl(++(n->sent_seqno)); - inpkt->len += sizeof inpkt->seqno; - - /* Encrypt the packet */ - - if(cipher_active(n->outcipher)) { - outpkt = pkt[nextpkt++]; - outlen = MAXSIZE; - - if(!cipher_encrypt(n->outcipher, &inpkt->seqno, inpkt->len, &outpkt->seqno, &outlen, true)) { - logger(DEBUG_TRAFFIC, LOG_ERR, "Error while encrypting packet to %s (%s)", n->name, n->hostname); - goto end; - } - - outpkt->len = outlen; - inpkt = outpkt; - } - - /* Add the message authentication code */ - - if(digest_active(n->outdigest)) { - if(!digest_create(n->outdigest, &inpkt->seqno, inpkt->len, (char *)&inpkt->seqno + inpkt->len)) { - logger(DEBUG_TRAFFIC, LOG_ERR, "Error while encrypting packet to %s (%s)", n->name, n->hostname); - goto end; - } - - inpkt->len += digest_length(n->outdigest); - } - - /* Send the packet */ - - const sockaddr_t *sa; - int sock; - - if(n->status.broadcast) - choose_broadcast_address(n, &sa, &sock); - else - choose_udp_address(n, &sa, &sock); - -#if defined(SOL_IP) && defined(IP_TOS) - if(priorityinheritance && origpriority != priority - && listen_socket[n->sock].sa.sa.sa_family == AF_INET) { - priority = origpriority; - logger(DEBUG_TRAFFIC, LOG_DEBUG, "Setting outgoing packet priority to %d", priority); - if(setsockopt(listen_socket[n->sock].udp.fd, SOL_IP, IP_TOS, &priority, sizeof(priority))) /* SO_PRIORITY doesn't seem to work */ - logger(DEBUG_ALWAYS, LOG_ERR, "System call `%s' failed: %s", "setsockopt", strerror(errno)); - } -#endif - - if(sendto(listen_socket[sock].udp.fd, (char *) &inpkt->seqno, inpkt->len, 0, &sa->sa, SALEN(sa->sa)) < 0 && !sockwouldblock(sockerrno)) { - if(sockmsgsize(sockerrno)) { - if(n->maxmtu >= origlen) - n->maxmtu = origlen - 1; - if(n->mtu >= origlen) - n->mtu = origlen - 1; - } else - logger(DEBUG_TRAFFIC, LOG_WARNING, "Error sending packet to %s (%s): %s", n->name, n->hostname, sockstrerror(sockerrno)); - } - -end: - origpkt->len = origlen; + return send_sptps_packet(n, origpkt); } bool send_sptps_data(void *handle, uint8_t type, const char *data, size_t len) { @@ -838,22 +624,8 @@ void send_packet(node_t *n, vpn_packet_t *packet) { n->out_packets++; n->out_bytes += packet->len; - if(n->status.sptps) { - send_sptps_packet(n, packet); - return; - } - - via = (packet->priority == -1 || n->via == myself) ? n->nexthop : n->via; - - if(via != n) - logger(DEBUG_TRAFFIC, LOG_INFO, "Sending packet to %s via %s (%s)", - n->name, via->name, n->via->hostname); - - if(packet->priority == -1 || ((myself->options | via->options) & OPTION_TCPONLY)) { - if(!send_tcppacket(via->connection, packet)) - terminate_connection(via->connection, true); - } else - send_udppacket(via, packet); + send_sptps_packet(n, packet); + return; } /* Broadcast a packet using the minimum spanning tree */ diff --git a/src/net_setup.c b/src/net_setup.c index 32946dab..91c71c3f 100644 --- a/src/net_setup.c +++ b/src/net_setup.c @@ -30,7 +30,6 @@ #include "netutl.h" #include "protocol.h" #include "route.h" -#include "rsa.h" #include "utils.h" #include "xalloc.h" @@ -129,44 +128,6 @@ bool read_ecdsa_public_key(connection_t *c) { return c->ecdsa; } -bool read_rsa_public_key(connection_t *c) { - if(ecdsa_active(c->ecdsa)) - return true; - - FILE *fp; - char *fname; - char *n; - - /* First, check for simple PublicKey statement */ - - if(get_config_string(lookup_config(c->config_tree, "PublicKey"), &n)) { - c->rsa = rsa_set_hex_public_key(n, "FFFF"); - free(n); - return c->rsa; - } - - /* Else, check for PublicKeyFile statement and read it */ - - if(!get_config_string(lookup_config(c->config_tree, "PublicKeyFile"), &fname)) - xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, c->name); - - fp = fopen(fname, "r"); - - if(!fp) { - logger(DEBUG_ALWAYS, LOG_ERR, "Error reading RSA public key file `%s': %s", fname, strerror(errno)); - free(fname); - return false; - } - - c->rsa = rsa_read_pem_public_key(fp); - fclose(fp); - - if(!c->rsa) - logger(DEBUG_ALWAYS, LOG_ERR, "Reading RSA public key file `%s' failed: %s", fname, strerror(errno)); - free(fname); - return c->rsa; -} - static bool read_ecdsa_private_key(void) { FILE *fp; char *fname; @@ -232,61 +193,6 @@ static bool read_invitation_key(void) { return invitation_key; } -static bool read_rsa_private_key(void) { - FILE *fp; - char *fname; - char *n, *d; - - /* First, check for simple PrivateKey statement */ - - if(get_config_string(lookup_config(config_tree, "PrivateKey"), &d)) { - if(!get_config_string(lookup_config(config_tree, "PublicKey"), &n)) { - logger(DEBUG_ALWAYS, LOG_ERR, "PrivateKey used but no PublicKey found!"); - free(d); - return false; - } - myself->connection->rsa = rsa_set_hex_private_key(n, "FFFF", d); - free(n); - free(d); - return myself->connection->rsa; - } - - /* Else, check for PrivateKeyFile statement and read it */ - - if(!get_config_string(lookup_config(config_tree, "PrivateKeyFile"), &fname)) - xasprintf(&fname, "%s" SLASH "rsa_key.priv", confbase); - - fp = fopen(fname, "r"); - - if(!fp) { - logger(DEBUG_ALWAYS, LOG_ERR, "Error reading RSA private key file `%s': %s", - fname, strerror(errno)); - free(fname); - return false; - } - -#if !defined(HAVE_MINGW) && !defined(HAVE_CYGWIN) - struct stat s; - - if(fstat(fileno(fp), &s)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Could not stat RSA private key file `%s': %s'", fname, strerror(errno)); - free(fname); - return false; - } - - if(s.st_mode & ~0100700) - logger(DEBUG_ALWAYS, LOG_WARNING, "Warning: insecure file permissions for RSA private key file `%s'!", fname); -#endif - - myself->connection->rsa = rsa_read_pem_private_key(fp); - fclose(fp); - - if(!myself->connection->rsa) - logger(DEBUG_ALWAYS, LOG_ERR, "Reading RSA private key file `%s' failed: %s", fname, strerror(errno)); - free(fname); - return myself->connection->rsa; -} - static timeout_t keyexpire_timeout; static void keyexpire_handler(void *data) { @@ -671,16 +577,7 @@ bool setup_myself(void) { myself->options |= PROT_MINOR << 24; - if(!get_config_bool(lookup_config(config_tree, "ExperimentalProtocol"), &experimental)) { - experimental = read_ecdsa_private_key(); - if(!experimental) - logger(DEBUG_ALWAYS, LOG_WARNING, "Support for SPTPS disabled."); - } else { - if(experimental && !read_ecdsa_private_key()) - return false; - } - - if(!read_rsa_private_key()) + if(!read_ecdsa_private_key()) return false; /* Ensure myport is numeric */ @@ -717,44 +614,8 @@ bool setup_myself(void) { sptps_replaywin = replaywin; } - /* Generate packet encryption key */ - - if(!get_config_string(lookup_config(config_tree, "Cipher"), &cipher)) - cipher = xstrdup("blowfish"); - - if(!strcasecmp(cipher, "none")) { - myself->incipher = NULL; - } else if(!(myself->incipher = cipher_open_by_name(cipher))) { - logger(DEBUG_ALWAYS, LOG_ERR, "Unrecognized cipher type!"); - return false; - } - - free(cipher); - timeout_add(&keyexpire_timeout, keyexpire_handler, &keyexpire_timeout, &(struct timeval){keylifetime, rand() % 100000}); - /* Check if we want to use message authentication codes... */ - - int maclength = 4; - get_config_int(lookup_config(config_tree, "MACLength"), &maclength); - - if(maclength < 0) { - logger(DEBUG_ALWAYS, LOG_ERR, "Bogus MAC length!"); - return false; - } - - if(!get_config_string(lookup_config(config_tree, "Digest"), &digest)) - digest = xstrdup("sha1"); - - if(!strcasecmp(digest, "none")) { - myself->indigest = NULL; - } else if(!(myself->indigest = digest_open_by_name(digest, maclength))) { - logger(DEBUG_ALWAYS, LOG_ERR, "Unrecognized digest type!"); - return false; - } - - free(digest); - /* Compression */ if(get_config_int(lookup_config(config_tree, "Compression"), &myself->incompression)) { @@ -773,7 +634,6 @@ bool setup_myself(void) { myself->via = myself; myself->status.reachable = true; myself->last_state_change = now.tv_sec; - myself->status.sptps = experimental; node_add(myself); graph(); diff --git a/src/net_socket.c b/src/net_socket.c index a2bc5b93..6a859f15 100644 --- a/src/net_socket.c +++ b/src/net_socket.c @@ -481,9 +481,6 @@ begin: c->status.connecting = true; c->name = xstrdup(outgoing->name); - c->outcipher = myself->connection->outcipher; - c->outdigest = myself->connection->outdigest; - c->outmaclength = myself->connection->outmaclength; c->outcompression = myself->connection->outcompression; c->last_ping_time = now.tv_sec; @@ -628,9 +625,6 @@ void handle_new_meta_connection(void *data, int flags) { c = new_connection(); c->name = xstrdup(""); - c->outcipher = myself->connection->outcipher; - c->outdigest = myself->connection->outdigest; - c->outmaclength = myself->connection->outmaclength; c->outcompression = myself->connection->outcompression; c->address = sa; diff --git a/src/node.c b/src/node.c index 79531e46..52797054 100644 --- a/src/node.c +++ b/src/node.c @@ -64,11 +64,6 @@ void free_node(node_t *n) { sockaddrfree(&n->address); - cipher_close(n->incipher); - digest_close(n->indigest); - cipher_close(n->outcipher); - digest_close(n->outdigest); - ecdsa_free(n->ecdsa); sptps_stop(&n->sptps); diff --git a/src/node.h b/src/node.h index 7a2ed1ee..ebe0b9d5 100644 --- a/src/node.h +++ b/src/node.h @@ -33,7 +33,7 @@ typedef struct node_status_t { unsigned int visited:1; /* 1 if this node has been visited by one of the graph algorithms */ unsigned int reachable:1; /* 1 if this node is reachable in the graph */ unsigned int indirect:1; /* 1 if this node is not directly reachable by us */ - unsigned int sptps:1; /* 1 if this node supports SPTPS */ + unsigned int unused_sptps:1; /* 1 if this node supports SPTPS */ unsigned int udp_confirmed:1; /* 1 if the address is one that we received UDP traffic on */ unsigned int broadcast:1; /* 1 if the next UDP packet should be broadcast to the local network */ unsigned int unused:23; @@ -54,12 +54,6 @@ typedef struct node_t { ecdsa_t *ecdsa; /* His public ECDSA key */ sptps_t sptps; - cipher_t *incipher; /* Cipher for UDP packets */ - digest_t *indigest; /* Digest for UDP packets */ - - cipher_t *outcipher; /* Cipher for UDP packets */ - digest_t *outdigest; /* Digest for UDP packets */ - int incompression; /* Compressionlevel, 0 = no compression */ int outcompression; /* Compressionlevel, 0 = no compression */ diff --git a/src/openssl/rsa.c b/src/openssl/rsa.c deleted file mode 100644 index 618e75c1..00000000 --- a/src/openssl/rsa.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - rsa.c -- RSA key handling - Copyright (C) 2014 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "../system.h" - -#include -#include - -#define __TINC_RSA_INTERNAL__ -typedef RSA rsa_t; - -#include "../logger.h" -#include "../rsa.h" - -// Set RSA keys - -rsa_t *rsa_set_hex_public_key(char *n, char *e) { - rsa_t *rsa = RSA_new(); - if(!rsa) - return NULL; - - if(BN_hex2bn(&rsa->n, n) != strlen(n) || BN_hex2bn(&rsa->e, e) != strlen(e)) { - RSA_free(rsa); - return false; - } - - return rsa; -} - -rsa_t *rsa_set_hex_private_key(char *n, char *e, char *d) { - rsa_t *rsa = RSA_new(); - if(!rsa) - return NULL; - - if(BN_hex2bn(&rsa->n, n) != strlen(n) || BN_hex2bn(&rsa->e, e) != strlen(e) || BN_hex2bn(&rsa->d, d) != strlen(d)) { - RSA_free(rsa); - return false; - } - - return rsa; -} - -// Read PEM RSA keys - -rsa_t *rsa_read_pem_public_key(FILE *fp) { - rsa_t *rsa = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL); - - if(!rsa) { - rewind(fp); - rsa = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL); - } - - if(!rsa) - logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read RSA public key: %s", ERR_error_string(ERR_get_error(), NULL)); - - return rsa; -} - -rsa_t *rsa_read_pem_private_key(FILE *fp) { - rsa_t *rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); - - if(!rsa) - logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read RSA private key: %s", ERR_error_string(ERR_get_error(), NULL)); - - return rsa; -} - -size_t rsa_size(rsa_t *rsa) { - return RSA_size(rsa); -} - -bool rsa_public_encrypt(rsa_t *rsa, void *in, size_t len, void *out) { - if(RSA_public_encrypt(len, in, out, rsa, RSA_NO_PADDING) == len) - return true; - - logger(DEBUG_ALWAYS, LOG_ERR, "Unable to perform RSA encryption: %s", ERR_error_string(ERR_get_error(), NULL)); - return false; -} - -bool rsa_private_decrypt(rsa_t *rsa, void *in, size_t len, void *out) { - if(RSA_private_decrypt(len, in, out, rsa, RSA_NO_PADDING) == len) - return true; - - logger(DEBUG_ALWAYS, LOG_ERR, "Unable to perform RSA decryption: %s", ERR_error_string(ERR_get_error(), NULL)); - return false; -} - -bool rsa_active(rsa_t *rsa) { - return rsa; -} - -void rsa_free(rsa_t *rsa) { - if(rsa) - RSA_free(rsa); -} diff --git a/src/openssl/rsagen.c b/src/openssl/rsagen.c deleted file mode 100644 index b7f168e2..00000000 --- a/src/openssl/rsagen.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - rsagen.c -- RSA key generation and export - Copyright (C) 2014 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "../system.h" - -#include -#include - -#define __TINC_RSA_INTERNAL__ -typedef RSA rsa_t; - -#include "../logger.h" -#include "../rsagen.h" - -/* This function prettyprints the key generation process */ - -static void indicator(int a, int b, void *p) { - switch (a) { - case 0: - fprintf(stderr, "."); - break; - - case 1: - fprintf(stderr, "+"); - break; - - case 2: - fprintf(stderr, "-"); - break; - - case 3: - switch (b) { - case 0: - fprintf(stderr, " p\n"); - break; - - case 1: - fprintf(stderr, " q\n"); - break; - - default: - fprintf(stderr, "?"); - } - break; - - default: - fprintf(stderr, "?"); - } -} - -// Generate RSA key - -rsa_t *rsa_generate(size_t bits, unsigned long exponent) { - return RSA_generate_key(bits, exponent, indicator, NULL); -} - -// Write PEM RSA keys - -bool rsa_write_pem_public_key(rsa_t *rsa, FILE *fp) { - return PEM_write_RSAPublicKey(fp, rsa); -} - -bool rsa_write_pem_private_key(rsa_t *rsa, FILE *fp) { - return PEM_write_RSAPrivateKey(fp, rsa, NULL, NULL, 0, NULL, NULL); -} diff --git a/src/protocol.c b/src/protocol.c index 94454745..eb406544 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -27,12 +27,10 @@ #include "utils.h" #include "xalloc.h" -bool experimental = true; - /* Jumptable for the request handlers */ static bool (*request_handlers[])(connection_t *, const char *) = { - id_h, metakey_h, challenge_h, chal_reply_h, ack_h, + id_h, NULL, NULL, NULL /* metakey_h, challenge_h, chal_reply_h */, ack_h, status_h, error_h, termreq_h, ping_h, pong_h, NULL, NULL, //add_subnet_h, del_subnet_h, diff --git a/src/protocol.h b/src/protocol.h index 68a5f1c9..68b11462 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -56,8 +56,6 @@ typedef struct past_request_t { time_t firstseen; } past_request_t; -extern bool experimental; - extern ecdsa_t *invitation_key; /* Maximum size of strings in a request. @@ -86,10 +84,6 @@ extern bool seen_request(const char *); /* Requests */ extern bool send_id(struct connection_t *); -extern bool send_metakey(struct connection_t *); -extern bool send_metakey_ec(struct connection_t *); -extern bool send_challenge(struct connection_t *); -extern bool send_chal_reply(struct connection_t *); extern bool send_ack(struct connection_t *); extern bool send_status(struct connection_t *, int, const char *); extern bool send_error(struct connection_t *, int, const char *); @@ -106,9 +100,6 @@ extern bool send_tcppacket(struct connection_t *, const struct vpn_packet_t *); /* Request handlers */ extern bool id_h(struct connection_t *, const char *); -extern bool metakey_h(struct connection_t *, const char *); -extern bool challenge_h(struct connection_t *, const char *); -extern bool chal_reply_h(struct connection_t *, const char *); extern bool ack_h(struct connection_t *, const char *); extern bool status_h(struct connection_t *, const char *); extern bool error_h(struct connection_t *, const char *); diff --git a/src/protocol_auth.c b/src/protocol_auth.c index fe87323b..670bfbc2 100644 --- a/src/protocol_auth.c +++ b/src/protocol_auth.c @@ -34,7 +34,6 @@ #include "node.h" #include "prf.h" #include "protocol.h" -#include "rsa.h" #include "sptps.h" #include "utils.h" #include "xalloc.h" @@ -130,14 +129,7 @@ static bool send_proxyrequest(connection_t *c) { bool send_id(connection_t *c) { gettimeofday(&c->start, NULL); - int minor = 0; - - if(experimental) { - if(c->outgoing && !read_ecdsa_public_key(c)) - minor = 1; - else - minor = myself->connection->protocol_minor; - } + int minor = myself->connection->protocol_minor; if(proxytype && c->outgoing) if(!send_proxyrequest(c)) @@ -335,9 +327,6 @@ bool id_h(connection_t *c, const char *request) { return send_ack(c); } - if(!experimental) - c->protocol_minor = 0; - if(!c->config_tree) { init_configuration(&c->config_tree); @@ -346,8 +335,7 @@ bool id_h(connection_t *c, const char *request) { return false; } - if(experimental) - read_ecdsa_public_key(c); + read_ecdsa_public_key(c); } else { if(c->protocol_minor && !ecdsa_active(c->ecdsa)) c->protocol_minor = 1; @@ -363,256 +351,18 @@ bool id_h(connection_t *c, const char *request) { c->allow_request = METAKEY; - if(c->protocol_minor >= 2) { - c->allow_request = ACK; - char label[25 + strlen(myself->name) + strlen(c->name)]; - - if(c->outgoing) - snprintf(label, sizeof label, "tinc TCP key expansion %s %s", myself->name, c->name); - else - snprintf(label, sizeof label, "tinc TCP key expansion %s %s", c->name, myself->name); - - return sptps_start(&c->sptps, c, c->outgoing, false, myself->connection->ecdsa, c->ecdsa, label, sizeof label, send_meta_sptps, receive_meta_sptps); - } else { - return send_metakey(c); - } -} - -bool send_metakey(connection_t *c) { - if(!read_rsa_public_key(c)) - return false; - - if(!(c->outcipher = cipher_open_blowfish_ofb())) - return false; - - if(!(c->outdigest = digest_open_sha1(-1))) - return false; - - size_t len = rsa_size(c->rsa); - char key[len]; - char enckey[len]; - char hexkey[2 * len + 1]; - - /* Create a random key */ - - randomize(key, len); - - /* The message we send must be smaller than the modulus of the RSA key. - By definition, for a key of k bits, the following formula holds: - - 2^(k-1) <= modulus < 2^(k) - - Where ^ means "to the power of", not "xor". - This means that to be sure, we must choose our message < 2^(k-1). - This can be done by setting the most significant bit to zero. - */ - - key[0] &= 0x7F; - - if(!cipher_set_key_from_rsa(c->outcipher, key, len, true)) - return false; - - if(debug_level >= DEBUG_SCARY_THINGS) { - bin2hex(key, hexkey, len); - logger(DEBUG_SCARY_THINGS, LOG_DEBUG, "Generated random meta key (unencrypted): %s", hexkey); - } - - /* Encrypt the random data - - We do not use one of the PKCS padding schemes here. - This is allowed, because we encrypt a totally random string - with a length equal to that of the modulus of the RSA key. - */ - - if(!rsa_public_encrypt(c->rsa, key, len, enckey)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Error during encryption of meta key for %s (%s)", c->name, c->hostname); - return false; - } - - /* Convert the encrypted random data to a hexadecimal formatted string */ - - bin2hex(enckey, hexkey, len); - - /* Send the meta key */ - - bool result = send_request(c, "%d %d %d %d %d %s", METAKEY, - cipher_get_nid(c->outcipher), - digest_get_nid(c->outdigest), c->outmaclength, - c->outcompression, hexkey); - - c->status.encryptout = true; - return result; -} - -bool metakey_h(connection_t *c, const char *request) { - char hexkey[MAX_STRING_SIZE]; - int cipher, digest, maclength, compression; - size_t len = rsa_size(myself->connection->rsa); - char enckey[len]; - char key[len]; - - if(sscanf(request, "%*d %d %d %d %d " MAX_STRING, &cipher, &digest, &maclength, &compression, hexkey) != 5) { - logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "METAKEY", c->name, c->hostname); - return false; - } - - /* Convert the challenge from hexadecimal back to binary */ - - int inlen = hex2bin(hexkey, enckey, sizeof enckey); - - /* Check if the length of the meta key is all right */ - - if(inlen != len) { - logger(DEBUG_ALWAYS, LOG_ERR, "Possible intruder %s (%s): %s", c->name, c->hostname, "wrong keylength"); - return false; - } - - /* Decrypt the meta key */ - - if(!rsa_private_decrypt(myself->connection->rsa, enckey, len, key)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Error during decryption of meta key for %s (%s)", c->name, c->hostname); - return false; - } - - if(debug_level >= DEBUG_SCARY_THINGS) { - bin2hex(key, hexkey, len); - logger(DEBUG_SCARY_THINGS, LOG_DEBUG, "Received random meta key (unencrypted): %s", hexkey); - } - - /* Check and lookup cipher and digest algorithms */ - - if(!(c->incipher = cipher_open_by_nid(cipher)) || !cipher_set_key_from_rsa(c->incipher, key, len, false)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Error during initialisation of cipher from %s (%s)", c->name, c->hostname); - return false; - } - - if(!(c->indigest = digest_open_by_nid(digest, -1))) { - logger(DEBUG_ALWAYS, LOG_ERR, "Error during initialisation of digest from %s (%s)", c->name, c->hostname); - return false; - } - - c->status.decryptin = true; - - c->allow_request = CHALLENGE; - - return send_challenge(c); -} - -bool send_challenge(connection_t *c) { - size_t len = rsa_size(c->rsa); - char buffer[len * 2 + 1]; - - if(!c->hischallenge) - c->hischallenge = xrealloc(c->hischallenge, len); - - /* Copy random data to the buffer */ - - randomize(c->hischallenge, len); - - /* Convert to hex */ - - bin2hex(c->hischallenge, buffer, len); - - /* Send the challenge */ - - return send_request(c, "%d %s", CHALLENGE, buffer); -} - -bool challenge_h(connection_t *c, const char *request) { - char buffer[MAX_STRING_SIZE]; - size_t len = rsa_size(myself->connection->rsa); - size_t digestlen = digest_length(c->indigest); - char digest[digestlen]; - - if(sscanf(request, "%*d " MAX_STRING, buffer) != 1) { - logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "CHALLENGE", c->name, c->hostname); - return false; - } - - /* Convert the challenge from hexadecimal back to binary */ - - int inlen = hex2bin(buffer, buffer, sizeof buffer); - - /* Check if the length of the challenge is all right */ - - if(inlen != len) { - logger(DEBUG_ALWAYS, LOG_ERR, "Possible intruder %s (%s): %s", c->name, c->hostname, "wrong challenge length"); - return false; - } - - /* Calculate the hash from the challenge we received */ - - if(!digest_create(c->indigest, buffer, len, digest)) - return false; - - /* Convert the hash to a hexadecimal formatted string */ - - bin2hex(digest, buffer, digestlen); - - /* Send the reply */ - - c->allow_request = CHAL_REPLY; - - return send_request(c, "%d %s", CHAL_REPLY, buffer); -} - -bool chal_reply_h(connection_t *c, const char *request) { - char hishash[MAX_STRING_SIZE]; - - if(sscanf(request, "%*d " MAX_STRING, hishash) != 1) { - logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "CHAL_REPLY", c->name, - c->hostname); - return false; - } - - /* Convert the hash to binary format */ - - int inlen = hex2bin(hishash, hishash, sizeof hishash); - - /* Check if the length of the hash is all right */ - - if(inlen != digest_length(c->outdigest)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Possible intruder %s (%s): %s", c->name, c->hostname, "wrong challenge reply length"); - return false; - } - - - /* Verify the hash */ - - if(!digest_verify(c->outdigest, c->hischallenge, rsa_size(c->rsa), hishash)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Possible intruder %s (%s): %s", c->name, c->hostname, "wrong challenge reply"); - return false; - } - - /* Identity has now been positively verified. - Send an acknowledgement with the rest of the information needed. - */ - - free(c->hischallenge); - c->hischallenge = NULL; c->allow_request = ACK; + char label[25 + strlen(myself->name) + strlen(c->name)]; - return send_ack(c); -} - -static bool send_upgrade(connection_t *c) { - /* Special case when protocol_minor is 1: the other end is ECDSA capable, - * but doesn't know our key yet. So send it now. */ - - char *pubkey = ecdsa_get_base64_public_key(myself->connection->ecdsa); - - if(!pubkey) - return false; + if(c->outgoing) + snprintf(label, sizeof label, "tinc TCP key expansion %s %s", myself->name, c->name); + else + snprintf(label, sizeof label, "tinc TCP key expansion %s %s", c->name, myself->name); - bool result = send_request(c, "%d %s", ACK, pubkey); - free(pubkey); - return result; + return sptps_start(&c->sptps, c, c->outgoing, false, myself->connection->ecdsa, c->ecdsa, label, sizeof label, send_meta_sptps, receive_meta_sptps); } bool send_ack(connection_t *c) { - if(c->protocol_minor == 1) - return send_upgrade(c); - /* ACK message contains rest of the information the other end needs to create node_t and edge_t structures. */ @@ -643,7 +393,7 @@ bool send_ack(connection_t *c) { if(!get_config_int(lookup_config(c->config_tree, "Weight"), &c->estimated_weight)) get_config_int(lookup_config(config_tree, "Weight"), &c->estimated_weight); - return send_request(c, "%d %s %d %x", ACK, myport, c->estimated_weight, (c->options & 0xffffff) | (experimental ? (PROT_MINOR << 24) : 0)); + return send_request(c, "%d %s %d %x", ACK, myport, c->estimated_weight, (c->options & 0xffffff) | (PROT_MINOR << 24)); } static void send_everything(connection_t *c) { @@ -667,29 +417,7 @@ static void send_everything(connection_t *c) { } } -static bool upgrade_h(connection_t *c, const char *request) { - char pubkey[MAX_STRING_SIZE]; - - if(sscanf(request, "%*d " MAX_STRING, pubkey) != 1) { - logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "ACK", c->name, c->hostname); - return false; - } - - if(ecdsa_active(c->ecdsa) || read_ecdsa_public_key(c)) { - logger(DEBUG_ALWAYS, LOG_INFO, "Already have ECDSA public key from %s (%s), not upgrading.", c->name, c->hostname); - return false; - } - - logger(DEBUG_ALWAYS, LOG_INFO, "Got ECDSA public key from %s (%s), upgrading!", c->name, c->hostname); - append_config_file(c->name, "ECDSAPublicKey", pubkey); - c->allow_request = TERMREQ; - return send_termreq(c); -} - bool ack_h(connection_t *c, const char *request) { - if(c->protocol_minor == 1) - return upgrade_h(c, request); - char hisport[MAX_STRING_SIZE]; char *hisaddress; int weight, mtu; diff --git a/src/protocol_key.c b/src/protocol_key.c index fe069f58..5cfa060b 100644 --- a/src/protocol_key.c +++ b/src/protocol_key.c @@ -37,19 +37,11 @@ static bool mykeyused = false; void send_key_changed(void) { send_request(everyone, "%d %x %s", KEY_CHANGED, rand(), myself->name); - /* Immediately send new keys to directly connected nodes to keep UDP mappings alive */ - - for list_each(connection_t, c, connection_list) - if(c->status.active && c->node && c->node->status.reachable && !c->node->status.sptps) - send_ans_key(c->node); - /* Force key exchange for connections using SPTPS */ - if(experimental) { - for splay_each(node_t, n, node_tree) - if(n->status.reachable && n->status.validkey && n->status.sptps) - sptps_force_kex(&n->sptps); - } + for splay_each(node_t, n, node_tree) + if(n->status.reachable && n->status.validkey) + sptps_force_kex(&n->sptps); } bool key_changed_h(connection_t *c, const char *request) { @@ -73,11 +65,6 @@ bool key_changed_h(connection_t *c, const char *request) { return true; } - if(!n->status.sptps) { - n->status.validkey = false; - n->last_req_key = 0; - } - /* Tell the others */ forward_request(c, request); @@ -94,27 +81,23 @@ static bool send_initial_sptps_data(void *handle, uint8_t type, const char *data } bool send_req_key(node_t *to) { - if(to->status.sptps) { - if(!node_read_ecdsa_public_key(to)) { - logger(DEBUG_PROTOCOL, LOG_DEBUG, "No ECDSA key known for %s (%s)", to->name, to->hostname); - send_request(to->nexthop->connection, "%d %s %s %d", REQ_KEY, myself->name, to->name, REQ_PUBKEY); - return true; - } - - if(to->sptps.label) - logger(DEBUG_ALWAYS, LOG_DEBUG, "send_req_key(%s) called while sptps->label != NULL!", to->name); - - char label[25 + strlen(myself->name) + strlen(to->name)]; - snprintf(label, sizeof label, "tinc UDP key expansion %s %s", myself->name, to->name); - sptps_stop(&to->sptps); - to->status.validkey = false; - to->status.waitingforkey = true; - to->last_req_key = now.tv_sec; - to->incompression = myself->incompression; - return sptps_start(&to->sptps, to, true, true, myself->connection->ecdsa, to->ecdsa, label, sizeof label, send_initial_sptps_data, receive_sptps_record); + if(!node_read_ecdsa_public_key(to)) { + logger(DEBUG_PROTOCOL, LOG_DEBUG, "No ECDSA key known for %s (%s)", to->name, to->hostname); + send_request(to->nexthop->connection, "%d %s %s %d", REQ_KEY, myself->name, to->name, REQ_PUBKEY); + return true; } - return send_request(to->nexthop->connection, "%d %s %s", REQ_KEY, myself->name, to->name); + if(to->sptps.label) + logger(DEBUG_ALWAYS, LOG_DEBUG, "send_req_key(%s) called while sptps->label != NULL!", to->name); + + char label[25 + strlen(myself->name) + strlen(to->name)]; + snprintf(label, sizeof label, "tinc UDP key expansion %s %s", myself->name, to->name); + sptps_stop(&to->sptps); + to->status.validkey = false; + to->status.waitingforkey = true; + to->last_req_key = now.tv_sec; + to->incompression = myself->incompression; + return sptps_start(&to->sptps, to, true, true, myself->connection->ecdsa, to->ecdsa, label, sizeof label, send_initial_sptps_data, receive_sptps_record); } /* REQ_KEY is overloaded to allow arbitrary requests to be routed between two nodes. */ @@ -233,7 +216,7 @@ bool req_key_h(connection_t *c, const char *request) { if(to == myself) { /* Yes */ /* Is this an extended REQ_KEY message? */ - if(experimental && reqno) + if(reqno) return req_key_ext_h(c, request, from, reqno); /* No, just send our key back */ @@ -252,42 +235,7 @@ bool req_key_h(connection_t *c, const char *request) { } bool send_ans_key(node_t *to) { - if(to->status.sptps) - abort(); - - size_t keylen = cipher_keylength(myself->incipher); - char key[keylen * 2 + 1]; - - cipher_close(to->incipher); - digest_close(to->indigest); - - to->incipher = cipher_open_by_nid(cipher_get_nid(myself->incipher)); - to->indigest = digest_open_by_nid(digest_get_nid(myself->indigest), digest_length(myself->indigest)); - to->incompression = myself->incompression; - - if(!to->incipher || !to->indigest) - abort(); - - randomize(key, keylen); - if(!cipher_set_key(to->incipher, key, false)) - abort(); - if(!digest_set_key(to->indigest, key, keylen)) - abort(); - - bin2hex(key, key, keylen); - - // Reset sequence number and late packet window - mykeyused = true; - to->received_seqno = 0; - to->received = 0; - if(replaywin) memset(to->late, 0, replaywin); - - return send_request(to->nexthop->connection, "%d %s %s %s %d %d %d %d", ANS_KEY, - myself->name, to->name, key, - cipher_get_nid(to->incipher), - digest_get_nid(to->indigest), - (int)digest_length(to->indigest), - to->incompression); + abort(); } bool ans_key_h(connection_t *c, const char *request) { @@ -351,8 +299,6 @@ bool ans_key_h(connection_t *c, const char *request) { } /* Don't use key material until every check has passed. */ - cipher_close(from->outcipher); - digest_close(from->outdigest); from->status.validkey = false; if(compression < 0 || compression > 11) { @@ -364,79 +310,22 @@ bool ans_key_h(connection_t *c, const char *request) { /* SPTPS or old-style key exchange? */ - if(from->status.sptps) { - char buf[strlen(key)]; - int len = b64decode(key, buf, strlen(key)); - - if(!len || !sptps_receive_data(&from->sptps, buf, len)) - logger(DEBUG_ALWAYS, LOG_ERR, "Error processing SPTPS data from %s (%s)", from->name, from->hostname); - - if(from->status.validkey) { - if(*address && *port) { - logger(DEBUG_PROTOCOL, LOG_DEBUG, "Using reflexive UDP address from %s: %s port %s", from->name, address, port); - sockaddr_t sa = str2sockaddr(address, port); - update_node_udp(from, &sa); - } - - if(from->options & OPTION_PMTU_DISCOVERY && !(from->options & OPTION_TCPONLY)) - send_mtu_probe(from); - } - - return true; - } - - /* Check and lookup cipher and digest algorithms */ + char buf[strlen(key)]; + int len = b64decode(key, buf, strlen(key)); - if(cipher) { - if(!(from->outcipher = cipher_open_by_nid(cipher))) { - logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses unknown cipher!", from->name, from->hostname); - return false; - } - } else { - from->outcipher = NULL; - } + if(!len || !sptps_receive_data(&from->sptps, buf, len)) + logger(DEBUG_ALWAYS, LOG_ERR, "Error processing SPTPS data from %s (%s)", from->name, from->hostname); - if(digest) { - if(!(from->outdigest = digest_open_by_nid(digest, maclength))) { - logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses unknown digest!", from->name, from->hostname); - return false; + if(from->status.validkey) { + if(*address && *port) { + logger(DEBUG_PROTOCOL, LOG_DEBUG, "Using reflexive UDP address from %s: %s port %s", from->name, address, port); + sockaddr_t sa = str2sockaddr(address, port); + update_node_udp(from, &sa); } - } else { - from->outdigest = NULL; - } - - if(maclength != digest_length(from->outdigest)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus MAC length!", from->name, from->hostname); - return false; - } - /* Process key */ - - keylen = hex2bin(key, key, sizeof key); - - if(keylen != cipher_keylength(from->outcipher)) { - logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses wrong keylength!", from->name, from->hostname); - return true; + if(from->options & OPTION_PMTU_DISCOVERY && !(from->options & OPTION_TCPONLY)) + send_mtu_probe(from); } - /* Update our copy of the origin's packet key */ - - if(!cipher_set_key(from->outcipher, key, true)) - return false; - if(!digest_set_key(from->outdigest, key, keylen)) - return false; - - from->status.validkey = true; - from->sent_seqno = 0; - - if(*address && *port) { - logger(DEBUG_PROTOCOL, LOG_DEBUG, "Using reflexive UDP address from %s: %s port %s", from->name, address, port); - sockaddr_t sa = str2sockaddr(address, port); - update_node_udp(from, &sa); - } - - if(from->options & OPTION_PMTU_DISCOVERY && !(from->options & OPTION_TCPONLY)) - send_mtu_probe(from); - return true; } diff --git a/src/rsa.h b/src/rsa.h deleted file mode 100644 index 64bd2e92..00000000 --- a/src/rsa.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - rsa.h -- RSA key handling - Copyright (C) 2014 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#ifndef __TINC_RSA_H__ -#define __TINC_RSA_H__ - -#ifndef __TINC_RSA_INTERNAL__ -typedef struct rsa rsa_t; -#endif - -extern void rsa_free(rsa_t *rsa); -extern rsa_t *rsa_set_hex_public_key(char *n, char *e) __attribute__ ((__malloc__)); -extern rsa_t *rsa_set_hex_private_key(char *n, char *e, char *d) __attribute__ ((__malloc__)); -extern rsa_t *rsa_read_pem_public_key(FILE *fp) __attribute__ ((__malloc__)); -extern rsa_t *rsa_read_pem_private_key(FILE *fp) __attribute__ ((__malloc__)); -extern size_t rsa_size(rsa_t *rsa); -extern bool rsa_public_encrypt(rsa_t *rsa, void *in, size_t len, void *out) __attribute__ ((__warn_unused_result__)); -extern bool rsa_private_decrypt(rsa_t *rsa, void *in, size_t len, void *out) __attribute__ ((__warn_unused_result__)); - -#endif diff --git a/src/rsagen.h b/src/rsagen.h deleted file mode 100644 index 380f3bda..00000000 --- a/src/rsagen.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - rsagen.h -- RSA key generation and export - Copyright (C) 2014 Guus Sliepen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#ifndef __TINC_RSAGEN_H__ -#define __TINC_RSAGEN_H__ - -#include "rsa.h" - -extern rsa_t *rsa_generate(size_t bits, unsigned long exponent) __attribute__ ((__malloc__)); -extern bool rsa_write_pem_public_key(rsa_t *rsa, FILE *fp) __attribute__ ((__warn_unused_result__)); -extern bool rsa_write_pem_private_key(rsa_t *rsa, FILE *fp) __attribute__ ((__warn_unused_result__)); - -#endif -- 2.39.5