2 protocol.c -- handle the meta-protocol
3 Copyright (C) 1999-2001 Ivo Timmermans <itimmermans@bigfoot.com>,
4 2000,2001 Guus Sliepen <guus@sliepen.warande.net>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 $Id: protocol.c,v 1.28.4.96 2001/07/01 09:21:01 guus Exp $
25 #include <sys/types.h>
30 #include <sys/socket.h>
41 #include <netinet/in.h>
43 #ifdef HAVE_OPENSSL_SHA_H
44 # include <openssl/sha.h>
49 #ifdef HAVE_OPENSSL_RAND_H
50 # include <openssl/rand.h>
55 #ifdef HAVE_OPENSSL_EVP_H
56 # include <openssl/evp.h>
67 #include "connection.h"
73 int check_id(char *id)
77 for (i = 0; i < strlen(id); i++)
78 if(!isalnum(id[i]) && id[i] != '_')
84 /* Generic request routines - takes care of logging and error
87 int send_request(connection_t *cl, const char *format, ...)
90 char buffer[MAXBUFSIZE];
94 /* Use vsnprintf instead of vasprintf: faster, no memory
95 fragmentation, cleanup is automatic, and there is a limit on the
96 input buffer anyway */
98 va_start(args, format);
99 len = vsnprintf(buffer, MAXBUFSIZE, format, args);
100 request = va_arg(args, int);
103 if(len < 0 || len > MAXBUFSIZE-1)
105 syslog(LOG_ERR, _("Output buffer overflow while sending %s to %s (%s)"), request_name[request], cl->name, cl->hostname);
109 if(debug_lvl >= DEBUG_PROTOCOL)
111 if(debug_lvl >= DEBUG_META)
112 syslog(LOG_DEBUG, _("Sending %s to %s (%s): %s"), request_name[request], cl->name, cl->hostname, buffer);
114 syslog(LOG_DEBUG, _("Sending %s to %s (%s)"), request_name[request], cl->name, cl->hostname);
117 buffer[len++] = '\n';
119 return send_meta(cl, buffer, len);
122 int receive_request(connection_t *cl)
126 if(sscanf(cl->buffer, "%d", &request) == 1)
128 if((request < 0) || (request >= LAST) || (request_handlers[request] == NULL))
130 if(debug_lvl >= DEBUG_META)
131 syslog(LOG_DEBUG, _("Unknown request from %s (%s): %s"),
132 cl->name, cl->hostname, cl->buffer);
134 syslog(LOG_ERR, _("Unknown request from %s (%s)"),
135 cl->name, cl->hostname);
141 if(debug_lvl >= DEBUG_PROTOCOL)
143 if(debug_lvl >= DEBUG_META)
144 syslog(LOG_DEBUG, _("Got %s from %s (%s): %s"),
145 request_name[request], cl->name, cl->hostname, cl->buffer);
147 syslog(LOG_DEBUG, _("Got %s from %s (%s)"),
148 request_name[request], cl->name, cl->hostname);
152 if((cl->allow_request != ALL) && (cl->allow_request != request))
154 syslog(LOG_ERR, _("Unauthorized request from %s (%s)"), cl->name, cl->hostname);
158 if(request_handlers[request](cl))
159 /* Something went wrong. Probably scriptkiddies. Terminate. */
161 syslog(LOG_ERR, _("Error while processing %s from %s (%s)"),
162 request_name[request], cl->name, cl->hostname);
168 syslog(LOG_ERR, _("Bogus data received from %s (%s)"),
169 cl->name, cl->hostname);
176 /* The authentication protocol is described in detail in doc/SECURITY2,
177 the rest will be described in doc/PROTOCOL. */
179 int send_id(connection_t *cl)
182 return send_request(cl, "%d %s %d %lx %hd", ID, myself->name, myself->protocol_version, myself->options, myself->port);
185 int id_h(connection_t *cl)
188 unsigned short int port;
189 char name[MAX_STRING_SIZE];
192 if(sscanf(cl->buffer, "%*d "MAX_STRING" %d %lx %hd", name, &cl->protocol_version, &cl->options, &port) != 4)
194 syslog(LOG_ERR, _("Got bad ID from %s"), cl->hostname);
198 /* Check if version matches */
200 if(cl->protocol_version != myself->protocol_version)
202 syslog(LOG_ERR, _("Peer %s (%s) uses incompatible version %d"),
203 cl->name, cl->hostname, cl->protocol_version);
207 /* Check if identity is a valid name */
211 syslog(LOG_ERR, _("Peer %s uses invalid identity name"), cl->hostname);
215 /* Copy string to cl */
220 cl->name = xstrdup(name);
222 /* Load information about peer */
224 if(read_host_config(cl))
226 syslog(LOG_ERR, _("Peer %s had unknown identity (%s)"), cl->hostname, cl->name);
230 /* First check if the host we connected to is already in our
231 connection list. If so, we are probably making a loop, which
235 if(cl->status.outgoing)
237 if((old = lookup_id(cl->name)))
239 if(debug_lvl >= DEBUG_CONNECTIONS)
240 syslog(LOG_NOTICE, _("Uplink %s (%s) is already in our connection list"), cl->name, cl->hostname);
241 cl->status.outgoing = 0;
242 old->status.outgoing = 1;
243 terminate_connection(cl);
248 /* Now we can add the name to the id tree */
252 /* And uhr... cl->port just changed so we have to unlink it from the connection tree and re-insert... */
254 node = avl_unlink(connection_tree, cl);
256 if(!avl_insert_node(connection_tree, node))
258 old = avl_search_node(connection_tree, node)->data;
259 syslog(LOG_ERR, _("%s is listening on %s:%hd, which is already in use by %s!"),
260 cl->name, cl->hostname, cl->port, old->name);
264 /* Read in the public key, so that we can send a metakey */
266 if(read_rsa_public_key(cl))
269 cl->allow_request = METAKEY;
271 return send_metakey(cl);
274 int ack_h(connection_t *cl)
277 connection_t *old, *p;
279 avl_node_t *node, *node2;
281 /* Okay, before we active the connection, we check if there is another entry
282 in the connection list with the same name. If so, it presumably is an
283 old connection that has timed out but we don't know it yet.
286 while((old = lookup_id(cl->name)))
288 if(debug_lvl >= DEBUG_CONNECTIONS)
289 syslog(LOG_NOTICE, _("Removing old entry for %s at %s in favour of new connection from %s"),
290 cl->name, old->hostname, cl->hostname);
292 terminate_connection(old);
295 /* Activate this connection */
297 cl->allow_request = ALL;
298 cl->status.active = 1;
300 cl->cipher_pkttype = EVP_bf_cbc();
301 cl->cipher_pktkeylength = cl->cipher_pkttype->key_len + cl->cipher_pkttype->iv_len;
303 if(debug_lvl >= DEBUG_CONNECTIONS)
304 syslog(LOG_NOTICE, _("Connection with %s (%s) activated"), cl->name, cl->hostname);
306 if(cl->status.outgoing)
307 seconds_till_retry = 5; /* Reset retry timeout */
309 /* Check some options */
311 if((cfg = get_config_val(cl->config, config_indirectdata)))
313 if(cfg->data.val == stupid_true)
314 cl->options |= OPTION_INDIRECT;
317 if((cfg = get_config_val(cl->config, config_tcponly)))
319 if(cfg->data.val == stupid_true)
320 cl->options |= OPTION_TCPONLY;
323 /* Send him our subnets */
325 for(node = myself->subnet_tree->head; node; node = node->next)
327 subnet = (subnet_t *)node->data;
328 send_add_subnet(cl, subnet);
331 /* And send him all the hosts and their subnets we know... */
333 for(node = connection_tree->head; node; node = node->next)
335 p = (connection_t *)node->data;
337 if(p != cl && p->status.active)
339 /* Notify others of this connection */
342 send_add_host(p, cl);
344 /* Notify new connection of everything we know */
346 send_add_host(cl, p);
348 for(node2 = p->subnet_tree->head; node2; node2 = node2->next)
350 subnet = (subnet_t *)node2->data;
351 send_add_subnet(cl, subnet);
359 int send_challenge(connection_t *cl)
364 /* CHECKME: what is most reasonable value for len? */
366 len = RSA_size(cl->rsa_key);
368 /* Allocate buffers for the challenge */
370 buffer = xmalloc(len*2+1);
373 free(cl->hischallenge);
375 cl->hischallenge = xmalloc(len);
377 /* Copy random data to the buffer */
379 RAND_bytes(cl->hischallenge, len);
384 bin2hex(cl->hischallenge, buffer, len);
385 buffer[len*2] = '\0';
388 /* Send the challenge */
390 x = send_request(cl, "%d %s", CHALLENGE, buffer);
396 int challenge_h(connection_t *cl)
398 char buffer[MAX_STRING_SIZE];
401 if(sscanf(cl->buffer, "%*d "MAX_STRING, buffer) != 1)
403 syslog(LOG_ERR, _("Got bad CHALLENGE from %s (%s)"), cl->name, cl->hostname);
407 len = RSA_size(myself->rsa_key);
409 /* Check if the length of the challenge is all right */
411 if(strlen(buffer) != len*2)
413 syslog(LOG_ERR, _("Intruder: wrong challenge length from %s (%s)"), cl->name, cl->hostname);
417 /* Allocate buffers for the challenge */
420 cl->mychallenge = xmalloc(len);
422 /* Convert the challenge from hexadecimal back to binary */
424 hex2bin(buffer,cl->mychallenge,len);
426 cl->allow_request = CHAL_REPLY;
428 /* Rest is done by send_chal_reply() */
430 return send_chal_reply(cl);
433 int send_chal_reply(connection_t *cl)
435 char hash[SHA_DIGEST_LENGTH*2+1];
439 syslog(LOG_ERR, _("Trying to send CHAL_REPLY to %s (%s) without a valid CHALLENGE"), cl->name, cl->hostname);
443 /* Calculate the hash from the challenge we received */
445 SHA1(cl->mychallenge, RSA_size(myself->rsa_key), hash);
447 /* Convert the hash to a hexadecimal formatted string */
449 bin2hex(hash,hash,SHA_DIGEST_LENGTH);
450 hash[SHA_DIGEST_LENGTH*2] = '\0';
455 return send_request(cl, "%d %s", CHAL_REPLY, hash);
458 int chal_reply_h(connection_t *cl)
460 char hishash[MAX_STRING_SIZE];
461 char myhash[SHA_DIGEST_LENGTH];
463 if(sscanf(cl->buffer, "%*d "MAX_STRING, hishash) != 1)
465 syslog(LOG_ERR, _("Got bad CHAL_REPLY from %s (%s)"), cl->name, cl->hostname);
469 /* Check if the length of the hash is all right */
471 if(strlen(hishash) != SHA_DIGEST_LENGTH*2)
473 syslog(LOG_ERR, _("Intruder: wrong challenge reply length from %s (%s)"), cl->name, cl->hostname);
477 /* Convert the hash to binary format */
479 hex2bin(hishash, hishash, SHA_DIGEST_LENGTH);
481 /* Calculate the hash from the challenge we sent */
483 SHA1(cl->hischallenge, RSA_size(cl->rsa_key), myhash);
485 /* Verify the incoming hash with the calculated hash */
487 if(memcmp(hishash, myhash, SHA_DIGEST_LENGTH))
489 syslog(LOG_ERR, _("Intruder: wrong challenge reply from %s (%s)"), cl->name, cl->hostname);
490 if(debug_lvl >= DEBUG_SCARY_THINGS)
492 bin2hex(myhash, hishash, SHA_DIGEST_LENGTH);
493 hishash[SHA_DIGEST_LENGTH*2] = '\0';
494 syslog(LOG_DEBUG, _("Expected challenge reply: %s"), hishash);
499 /* Identity has now been positively verified.
500 ack_h() handles the rest from now on.
506 int send_metakey(connection_t *cl)
511 len = RSA_size(cl->rsa_key);
513 /* Allocate buffers for the meta key */
515 buffer = xmalloc(len*2+1);
517 if(!cl->cipher_outkey)
518 cl->cipher_outkey = xmalloc(len);
520 if(!cl->cipher_outctx)
521 cl->cipher_outctx = xmalloc(sizeof(*cl->cipher_outctx));
523 /* Copy random data to the buffer */
525 RAND_bytes(cl->cipher_outkey, len);
527 /* The message we send must be smaller than the modulus of the RSA key.
528 By definition, for a key of k bits, the following formula holds:
530 2^(k-1) <= modulus < 2^(k)
532 Where ^ means "to the power of", not "xor".
533 This means that to be sure, we must choose our message < 2^(k-1).
534 This can be done by setting the most significant bit to zero.
537 cl->cipher_outkey[0] &= 0x7F;
539 if(debug_lvl >= DEBUG_SCARY_THINGS)
541 bin2hex(cl->cipher_outkey, buffer, len);
542 buffer[len*2] = '\0';
543 syslog(LOG_DEBUG, _("Generated random meta key (unencrypted): %s"), buffer);
546 /* Encrypt the random data
548 We do not use one of the PKCS padding schemes here.
549 This is allowed, because we encrypt a totally random string
550 with a length equal to that of the modulus of the RSA key.
553 if(RSA_public_encrypt(len, cl->cipher_outkey, buffer, cl->rsa_key, RSA_NO_PADDING) != len)
555 syslog(LOG_ERR, _("Error during encryption of meta key for %s (%s)"), cl->name, cl->hostname);
560 /* Convert the encrypted random data to a hexadecimal formatted string */
562 bin2hex(buffer, buffer, len);
563 buffer[len*2] = '\0';
565 /* Send the meta key */
567 x = send_request(cl, "%d %s", METAKEY, buffer);
570 /* Further outgoing requests are encrypted with the key we just generated */
572 EVP_EncryptInit(cl->cipher_outctx, EVP_bf_cfb(),
573 cl->cipher_outkey + len - EVP_bf_cfb()->key_len,
574 cl->cipher_outkey + len - EVP_bf_cfb()->key_len - EVP_bf_cfb()->iv_len);
576 cl->status.encryptout = 1;
581 int metakey_h(connection_t *cl)
583 char buffer[MAX_STRING_SIZE];
586 if(sscanf(cl->buffer, "%*d "MAX_STRING, buffer) != 1)
588 syslog(LOG_ERR, _("Got bad METAKEY from %s (%s)"), cl->name, cl->hostname);
592 len = RSA_size(myself->rsa_key);
594 /* Check if the length of the meta key is all right */
596 if(strlen(buffer) != len*2)
598 syslog(LOG_ERR, _("Intruder: wrong meta key length from %s (%s)"), cl->name, cl->hostname);
602 /* Allocate buffers for the meta key */
604 if(!cl->cipher_inkey)
605 cl->cipher_inkey = xmalloc(len);
607 if(!cl->cipher_inctx)
608 cl->cipher_inctx = xmalloc(sizeof(*cl->cipher_inctx));
610 /* Convert the challenge from hexadecimal back to binary */
612 hex2bin(buffer,buffer,len);
614 /* Decrypt the meta key */
616 if(RSA_private_decrypt(len, buffer, cl->cipher_inkey, myself->rsa_key, RSA_NO_PADDING) != len) /* See challenge() */
618 syslog(LOG_ERR, _("Error during encryption of meta key for %s (%s)"), cl->name, cl->hostname);
622 if(debug_lvl >= DEBUG_SCARY_THINGS)
624 bin2hex(cl->cipher_inkey, buffer, len);
625 buffer[len*2] = '\0';
626 syslog(LOG_DEBUG, _("Received random meta key (unencrypted): %s"), buffer);
629 /* All incoming requests will now be encrypted. */
631 EVP_DecryptInit(cl->cipher_inctx, EVP_bf_cfb(),
632 cl->cipher_inkey + len - EVP_bf_cfb()->key_len,
633 cl->cipher_inkey + len - EVP_bf_cfb()->key_len - EVP_bf_cfb()->iv_len);
635 cl->status.decryptin = 1;
637 cl->allow_request = CHALLENGE;
639 return send_challenge(cl);
642 /* Address and subnet information exchange */
644 int send_add_subnet(connection_t *cl, subnet_t *subnet)
650 if((cl->options | myself->options | subnet->owner->options) & OPTION_INDIRECT)
651 owner = myself->name;
653 owner = subnet->owner->name;
655 x = send_request(cl, "%d %s %s", ADD_SUBNET,
656 owner, netstr = net2str(subnet));
662 int add_subnet_h(connection_t *cl)
664 char subnetstr[MAX_STRING_SIZE];
665 char name[MAX_STRING_SIZE];
666 connection_t *owner, *p;
670 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING, name, subnetstr) != 2)
672 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s)"), cl->name, cl->hostname);
676 /* Check if owner name is a valid */
680 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s): invalid identity name"), cl->name, cl->hostname);
684 /* Check if subnet string is valid */
686 if(!(subnet = str2net(subnetstr)))
688 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s): invalid subnet string"), cl->name, cl->hostname);
692 /* Check if somebody tries to add a subnet of ourself */
694 if(!strcmp(name, myself->name))
696 syslog(LOG_ERR, _("Warning: got ADD_SUBNET from %s (%s) for ourself, restarting"),
697 cl->name, cl->hostname);
702 /* Check if the owner of the new subnet is in the connection list */
704 if(!(owner = lookup_id(name)))
706 syslog(LOG_ERR, _("Got ADD_SUBNET for %s from %s (%s) which is not in our connection list"),
707 name, cl->name, cl->hostname);
711 /* If everything is correct, add the subnet to the list of the owner */
713 subnet_add(owner, subnet);
717 for(node = connection_tree->head; node; node = node->next)
719 p = (connection_t *)node->data;
720 if(p->status.meta && p->status.active && p!= cl)
721 send_add_subnet(p, subnet);
727 int send_del_subnet(connection_t *cl, subnet_t *subnet)
733 if(cl->options & OPTION_INDIRECT)
734 owner = myself->name;
736 owner = subnet->owner->name;
738 x = send_request(cl, "%d %s %s", DEL_SUBNET, owner, netstr = net2str(subnet));
744 int del_subnet_h(connection_t *cl)
746 char subnetstr[MAX_STRING_SIZE];
747 char name[MAX_STRING_SIZE];
748 connection_t *owner, *p;
752 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING, name, subnetstr) != 3)
754 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s)"), cl->name, cl->hostname);
758 /* Check if owner name is a valid */
762 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s): invalid identity name"), cl->name, cl->hostname);
766 /* Check if subnet string is valid */
768 if(!(subnet = str2net(subnetstr)))
770 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s): invalid subnet string"), cl->name, cl->hostname);
776 /* Check if somebody tries to add a subnet of ourself */
778 if(!strcmp(name, myself->name))
780 syslog(LOG_ERR, _("Warning: got DEL_SUBNET from %s (%s) for ourself, restarting"),
781 cl->name, cl->hostname);
786 /* Check if the owner of the new subnet is in the connection list */
788 if(!(owner = lookup_id(name)))
790 syslog(LOG_ERR, _("Got DEL_SUBNET for %s from %s (%s) which is not in our connection list"),
791 name, cl->name, cl->hostname);
795 /* If everything is correct, delete the subnet from the list of the owner */
801 for(node = connection_tree->head; node; node = node->next)
803 p = (connection_t *)node->data;
804 if(p->status.meta && p->status.active && p!= cl)
805 send_del_subnet(p, subnet);
811 /* New and closed connections notification */
813 int send_add_host(connection_t *cl, connection_t *other)
816 if(!((cl->options | myself->options | other->options) & OPTION_INDIRECT))
817 return send_request(cl, "%d %s %lx:%d %lx", ADD_HOST,
818 other->name, other->address, other->port, other->options);
823 int add_host_h(connection_t *cl)
825 connection_t *old, *new, *p;
826 char name[MAX_STRING_SIZE];
829 new = new_connection();
831 if(sscanf(cl->buffer, "%*d "MAX_STRING" %lx:%hd %lx", name, &new->address, &new->port, &new->options) != 4)
833 syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s)"), cl->name, cl->hostname);
837 /* Check if identity is a valid name */
841 syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s): invalid identity name"), cl->name, cl->hostname);
842 free_connection(new);
846 /* Check if somebody tries to add ourself */
848 if(!strcmp(name, myself->name))
850 syslog(LOG_ERR, _("Warning: got ADD_HOST from %s (%s) for ourself, restarting"), cl->name, cl->hostname);
852 free_connection(new);
856 /* Fill in more of the new connection structure */
858 new->hostname = hostlookup(htonl(new->address));
860 /* Check if the new host already exists in the connnection list */
862 if((old = lookup_id(name)))
864 if((new->address == old->address) && (new->port == old->port))
866 if(debug_lvl >= DEBUG_CONNECTIONS)
867 syslog(LOG_NOTICE, _("Got duplicate ADD_HOST for %s (%s) from %s (%s)"),
868 old->name, old->hostname, name, new->hostname);
869 free_connection(new);
874 if(debug_lvl >= DEBUG_CONNECTIONS)
875 syslog(LOG_NOTICE, _("Removing old entry for %s (%s) in favour of new connection"),
876 old->name, old->hostname);
878 terminate_connection(old);
882 /* Hook it up into the connection */
884 new->name = xstrdup(name);
888 /* Tell the rest about the new host */
890 for(node = connection_tree->head; node; node = node->next)
892 p = (connection_t *)node->data;
893 if(p->status.meta && p->status.active && p!=cl)
894 send_add_host(p, new);
897 /* Fill in rest of connection structure */
900 new->status.active = 1;
901 new->cipher_pkttype = EVP_bf_cbc();
902 new->cipher_pktkeylength = cl->cipher_pkttype->key_len + cl->cipher_pkttype->iv_len;
907 int send_del_host(connection_t *cl, connection_t *other)
910 if(!((cl->options | myself->options) & OPTION_INDIRECT))
911 return send_request(cl, "%d %s %lx:%d %lx", DEL_HOST,
912 other->name, other->address, other->port, other->options);
917 int del_host_h(connection_t *cl)
919 char name[MAX_STRING_SIZE];
923 connection_t *old, *p;
926 if(sscanf(cl->buffer, "%*d "MAX_STRING" %lx:%hd %lx", name, &address, &port, &options) != 4)
928 syslog(LOG_ERR, _("Got bad DEL_HOST from %s (%s)"),
929 cl->name, cl->hostname);
933 /* Check if identity is a valid name */
937 syslog(LOG_ERR, _("Got bad DEL_HOST from %s (%s): invalid identity name"), cl->name, cl->hostname);
941 /* Check if somebody tries to delete ourself */
943 if(!strcmp(name, myself->name))
945 syslog(LOG_ERR, _("Warning: got DEL_HOST from %s (%s) for ourself, restarting"),
946 cl->name, cl->hostname);
951 /* Check if the new host already exists in the connnection list */
953 if(!(old = lookup_id(name)))
955 syslog(LOG_ERR, _("Got DEL_HOST from %s (%s) for %s which is not in our connection list"),
956 name, cl->name, cl->hostname);
960 /* Check if the rest matches */
962 if(address!=old->address || port!=old->port || options!=old->options || cl!=old->nexthop)
964 syslog(LOG_WARNING, _("Got DEL_HOST from %s (%s) for %s which doesn't match"), cl->name, cl->hostname, old->name);
968 /* Ok, since EVERYTHING seems to check out all right, delete it */
970 old->status.active = 0;
971 terminate_connection(old);
973 /* Tell the rest about the new host */
975 for(node = connection_tree->head; node; node = node->next)
977 p = (connection_t *)node->data;
978 if(p->status.meta && p->status.active && p!=cl)
979 send_del_host(p, old);
985 /* Status and error notification routines */
987 int send_status(connection_t *cl, int statusno, char *statusstring)
991 statusstring = status_text[statusno];
993 return send_request(cl, "%d %d %s", STATUS, statusno, statusstring);
996 int status_h(connection_t *cl)
999 char statusstring[MAX_STRING_SIZE];
1001 if(sscanf(cl->buffer, "%*d %d "MAX_STRING, &statusno, statusstring) != 2)
1003 syslog(LOG_ERR, _("Got bad STATUS from %s (%s)"),
1004 cl->name, cl->hostname);
1008 if(debug_lvl >= DEBUG_STATUS)
1010 syslog(LOG_NOTICE, _("Status message from %s (%s): %s: %s"),
1011 cl->name, cl->hostname, status_text[statusno], statusstring);
1018 int send_error(connection_t *cl, int err, char *errstring)
1022 errstring = strerror(err);
1023 return send_request(cl, "%d %d %s", ERROR, err, errstring);
1026 int error_h(connection_t *cl)
1029 char errorstring[MAX_STRING_SIZE];
1031 if(sscanf(cl->buffer, "%*d %d "MAX_STRING, &err, errorstring) != 2)
1033 syslog(LOG_ERR, _("Got bad ERROR from %s (%s)"),
1034 cl->name, cl->hostname);
1038 if(debug_lvl >= DEBUG_ERROR)
1040 syslog(LOG_NOTICE, _("Error message from %s (%s): %s: %s"),
1041 cl->name, cl->hostname, strerror(err), errorstring);
1044 terminate_connection(cl);
1049 int send_termreq(connection_t *cl)
1052 return send_request(cl, "%d", TERMREQ);
1055 int termreq_h(connection_t *cl)
1058 terminate_connection(cl);
1063 int send_ping(connection_t *cl)
1065 char salt[SALTLEN*2+1];
1067 cl->status.pinged = 1;
1068 cl->last_ping_time = time(NULL);
1069 RAND_bytes(salt, SALTLEN);
1070 bin2hex(salt, salt, SALTLEN);
1071 salt[SALTLEN*2] = '\0';
1073 return send_request(cl, "%d %s", PING, salt);
1076 int ping_h(connection_t *cl)
1079 return send_pong(cl);
1082 int send_pong(connection_t *cl)
1084 char salt[SALTLEN*2+1];
1086 RAND_bytes(salt, SALTLEN);
1087 bin2hex(salt, salt, SALTLEN);
1088 salt[SALTLEN*2] = '\0';
1090 return send_request(cl, "%d %s", PONG, salt);
1093 int pong_h(connection_t *cl)
1096 cl->status.pinged = 0;
1103 int send_key_changed(connection_t *from, connection_t *cl)
1108 /* Only send this message if some other daemon requested our key previously.
1109 This reduces unnecessary key_changed broadcasts.
1112 if(from==myself && !mykeyused)
1115 for(node = connection_tree->head; node; node = node->next)
1117 p = (connection_t *)node->data;
1118 if(p != cl && p->status.meta && p->status.active)
1119 if(!(p->options & OPTION_INDIRECT) || from == myself)
1120 send_request(p, "%d %s", KEY_CHANGED, from->name);
1126 int key_changed_h(connection_t *cl)
1128 char from_id[MAX_STRING_SIZE];
1131 if(sscanf(cl->buffer, "%*d "MAX_STRING, from_id) != 1)
1133 syslog(LOG_ERR, _("Got bad KEY_CHANGED from %s (%s)"),
1134 cl->name, cl->hostname);
1138 if(!(from = lookup_id(from_id)))
1140 syslog(LOG_ERR, _("Got KEY_CHANGED from %s (%s) origin %s which does not exist in our connection list"),
1141 cl->name, cl->hostname, from_id);
1145 from->status.validkey = 0;
1146 from->status.waitingforkey = 0;
1148 if(!(from->options | cl->options | myself->options) & OPTION_INDIRECT)
1149 send_key_changed(from, cl);
1154 int send_req_key(connection_t *from, connection_t *to)
1157 return send_request(to->nexthop, "%d %s %s", REQ_KEY,
1158 from->name, to->name);
1161 int req_key_h(connection_t *cl)
1163 char from_id[MAX_STRING_SIZE];
1164 char to_id[MAX_STRING_SIZE];
1165 connection_t *from, *to;
1168 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING, from_id, to_id) != 2)
1170 syslog(LOG_ERR, _("Got bad REQ_KEY from %s (%s)"),
1171 cl->name, cl->hostname);
1175 if(!(from = lookup_id(from_id)))
1177 syslog(LOG_ERR, _("Got REQ_KEY from %s (%s) origin %s which does not exist in our connection list"),
1178 cl->name, cl->hostname, from_id);
1182 /* Check if this key request is for us */
1184 if(!strcmp(to_id, myself->name)) /* Yes, send our own key back */
1186 bin2hex(myself->cipher_pktkey, pktkey, myself->cipher_pktkeylength);
1187 pktkey[myself->cipher_pktkeylength*2] = '\0';
1188 send_ans_key(myself, from, pktkey);
1193 if(!(to = lookup_id(to_id)))
1195 syslog(LOG_ERR, _("Got REQ_KEY from %s (%s) destination %s which does not exist in our connection list"),
1196 cl->name, cl->hostname, to_id);
1200 if(to->status.validkey) /* Proxy keys */
1202 bin2hex(to->cipher_pktkey, pktkey, to->cipher_pktkeylength);
1203 pktkey[to->cipher_pktkeylength*2] = '\0';
1204 send_ans_key(to, from, pktkey);
1207 send_req_key(from, to);
1214 int send_ans_key(connection_t *from, connection_t *to, char *pktkey)
1217 return send_request(to->nexthop, "%d %s %s %s", ANS_KEY,
1218 from->name, to->name, pktkey);
1221 int ans_key_h(connection_t *cl)
1223 char from_id[MAX_STRING_SIZE];
1224 char to_id[MAX_STRING_SIZE];
1225 char pktkey[MAX_STRING_SIZE];
1227 connection_t *from, *to;
1229 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING, from_id, to_id, pktkey) != 3)
1231 syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s)"),
1232 cl->name, cl->hostname);
1236 if(!(from = lookup_id(from_id)))
1238 syslog(LOG_ERR, _("Got ANS_KEY from %s (%s) origin %s which does not exist in our connection list"),
1239 cl->name, cl->hostname, from_id);
1243 /* Check correctness of packet key */
1245 keylength = strlen(pktkey);
1247 if(keylength != from->cipher_pktkeylength*2)
1249 syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s) origin %s: invalid key length"),
1250 cl->name, cl->hostname, from->name);
1254 /* Forward it if necessary */
1256 if(strcmp(to_id, myself->name))
1258 if(!(to = lookup_id(to_id)))
1260 syslog(LOG_ERR, _("Got ANS_KEY from %s (%s) destination %s which does not exist in our connection list"),
1261 cl->name, cl->hostname, to_id);
1264 send_ans_key(from, to, pktkey);
1267 /* Update our copy of the origin's packet key */
1269 if(from->cipher_pktkey)
1270 free(from->cipher_pktkey);
1272 from->cipher_pktkey = xstrdup(pktkey);
1274 hex2bin(from->cipher_pktkey, from->cipher_pktkey, keylength);
1275 from->cipher_pktkey[keylength] = '\0';
1277 from->status.validkey = 1;
1278 from->status.waitingforkey = 0;
1285 int send_tcppacket(connection_t *cl, vpn_packet_t *packet)
1291 x = send_request(cl->nexthop, "%d %hd", PACKET, packet->len);
1296 return send_meta(cl, packet->data, packet->len);
1299 int tcppacket_h(connection_t *cl)
1303 if(sscanf(cl->buffer, "%*d %hd", &len) != 1)
1305 syslog(LOG_ERR, _("Got bad PACKET from %s (%s)"), cl->name, cl->hostname);
1309 /* Set reqlen to len, this will tell receive_meta() that a tcppacket is coming. */
1316 /* Jumptable for the request handlers */
1318 int (*request_handlers[])(connection_t*) = {
1319 id_h, metakey_h, challenge_h, chal_reply_h,
1320 status_h, error_h, termreq_h,
1322 add_host_h, del_host_h,
1323 add_subnet_h, del_subnet_h,
1324 key_changed_h, req_key_h, ans_key_h,
1330 char (*request_name[]) = {
1331 "ID", "METAKEY", "CHALLENGE", "CHAL_REPLY",
1332 "STATUS", "ERROR", "TERMREQ",
1334 "ADD_HOST", "DEL_HOST",
1335 "ADD_SUBNET", "DEL_SUBNET",
1336 "KEY_CHANGED", "REQ_KEY", "ANS_KEY",
1340 /* Status strings */
1342 char (*status_text[]) = {
1348 char (*error_text[]) = {