We only allow SPTPS connections.
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 \
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 \
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__));
#include "connection.h"
#include "list.h"
#include "logger.h"
-#include "rsa.h"
#include "utils.h"
#include "xalloc.h"
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);
#include "buffer.h"
#include "cipher.h"
#include "digest.h"
-#include "rsa.h"
#include "list.h"
#include "sptps.h"
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 */
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 */
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;
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);
}
}
}
#include "ecdsagen.h"
#include "invitation.h"
#include "netutl.h"
-#include "rsagen.h"
#include "sptps.h"
#include "tincctl.h"
#include "utils.h"
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);
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 = {
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);
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) {
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);
}
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 *);
}
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) {
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) {
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) {
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 */
#include "netutl.h"
#include "protocol.h"
#include "route.h"
-#include "rsa.h"
#include "utils.h"
#include "xalloc.h"
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;
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) {
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 */
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)) {
myself->via = myself;
myself->status.reachable = true;
myself->last_state_change = now.tv_sec;
- myself->status.sptps = experimental;
node_add(myself);
graph();
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;
c = new_connection();
c->name = xstrdup("<unknown>");
- c->outcipher = myself->connection->outcipher;
- c->outdigest = myself->connection->outdigest;
- c->outmaclength = myself->connection->outmaclength;
c->outcompression = myself->connection->outcompression;
c->address = sa;
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);
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;
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 */
+++ /dev/null
-/*
- rsa.c -- RSA key handling
- Copyright (C) 2014 Guus Sliepen <guus@meshlink.io>
-
- 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 <openssl/pem.h>
-#include <openssl/err.h>
-
-#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);
-}
+++ /dev/null
-/*
- rsagen.c -- RSA key generation and export
- Copyright (C) 2014 Guus Sliepen <guus@meshlink.io>
-
- 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 <openssl/pem.h>
-#include <openssl/err.h>
-
-#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);
-}
#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,
time_t firstseen;
} past_request_t;
-extern bool experimental;
-
extern ecdsa_t *invitation_key;
/* Maximum size of strings in a request.
/* 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 *);
/* 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 *);
#include "node.h"
#include "prf.h"
#include "protocol.h"
-#include "rsa.h"
#include "sptps.h"
#include "utils.h"
#include "xalloc.h"
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))
return send_ack(c);
}
- if(!experimental)
- c->protocol_minor = 0;
-
if(!c->config_tree) {
init_configuration(&c->config_tree);
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;
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. */
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) {
}
}
-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;
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) {
return true;
}
- if(!n->status.sptps) {
- n->status.validkey = false;
- n->last_req_key = 0;
- }
-
/* Tell the others */
forward_request(c, request);
}
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. */
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 */
}
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) {
}
/* 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) {
/* 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;
}
+++ /dev/null
-/*
- rsa.h -- RSA key handling
- Copyright (C) 2014 Guus Sliepen <guus@meshlink.io>
-
- 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
+++ /dev/null
-/*
- rsagen.h -- RSA key generation and export
- Copyright (C) 2014 Guus Sliepen <guus@meshlink.io>
-
- 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