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.76 2001/01/08 20:35:30 guus Exp $
25 #include <sys/types.h>
30 #include <sys/socket.h>
40 #include <netinet/in.h>
42 #ifdef HAVE_OPENSSL_SHA_H
43 # include <openssl/sha.h>
48 #ifdef HAVE_OPENSSL_RAND_H
49 # include <openssl/rand.h>
54 #ifdef HAVE_OPENSSL_EVP_H
55 # include <openssl/evp.h>
66 #include "connection.h"
70 int check_id(char *id)
74 for (i = 0; i < strlen(id); i++)
75 if(!isalnum(id[i]) && id[i] != '_')
81 /* Generic request routines - takes care of logging and error
84 int send_request(connection_t *cl, const char *format, ...)
87 char buffer[MAXBUFSIZE];
91 /* Use vsnprintf instead of vasprintf: faster, no memory
92 fragmentation, cleanup is automatic, and there is a limit on the
93 input buffer anyway */
95 va_start(args, format);
96 len = vsnprintf(buffer, MAXBUFSIZE, format, args);
97 request = va_arg(args, int);
100 if(len < 0 || len > MAXBUFSIZE-1)
102 syslog(LOG_ERR, _("Output buffer overflow while sending %s to %s (%s)"), request_name[request], cl->name, cl->hostname);
108 if(debug_lvl >= DEBUG_PROTOCOL)
109 syslog(LOG_DEBUG, _("Sending %s to %s (%s)"), request_name[request], cl->name, cl->hostname);
112 return send_meta(cl, buffer, len);
115 int receive_request(connection_t *cl)
119 if(sscanf(cl->buffer, "%d", &request) == 1)
121 if((request < 0) || (request > 255) || (request_handlers[request] == NULL))
123 syslog(LOG_ERR, _("Unknown request from %s (%s)"),
124 cl->name, cl->hostname);
129 if(debug_lvl >= DEBUG_PROTOCOL)
130 syslog(LOG_DEBUG, _("Got %s from %s (%s)"),
131 request_name[request], cl->name, cl->hostname);
134 if((cl->allow_request != ALL) && (cl->allow_request != request))
136 syslog(LOG_ERR, _("Unauthorized request from %s (%s)"), cl->name, cl->hostname);
140 if(request_handlers[request](cl))
141 /* Something went wrong. Probably scriptkiddies. Terminate. */
143 syslog(LOG_ERR, _("Error while processing %s from %s (%s)"),
144 request_name[request], cl->name, cl->hostname);
150 syslog(LOG_ERR, _("Bogus data received from %s (%s)"),
151 cl->name, cl->hostname);
158 /* Connection protocol:
167 ---------------------------------------
170 ---------------------------------------
173 ---------------------------------------
179 (E) Encrypted with symmetric cipher.
181 Part of the challenge is directly used to set the symmetric cipher
182 key and the initial vector. Since a man-in-the-middle cannot
183 decrypt the RSA challenges, this means that he cannot get or forge
184 the key for the symmetric cipher.
187 int send_id(connection_t *cl)
190 cl->allow_request = CHALLENGE;
192 return send_request(cl, "%d %s %d %lx %hd", ID, myself->name, myself->protocol_version, myself->options, myself->port);
195 int id_h(connection_t *cl)
198 unsigned short int port;
199 char name[MAX_STRING_SIZE];
202 if(sscanf(cl->buffer, "%*d "MAX_STRING" %d %lx %hd", name, &cl->protocol_version, &cl->options, &port) != 4)
204 syslog(LOG_ERR, _("Got bad ID from %s"), cl->hostname);
208 /* Check if version matches */
210 if(cl->protocol_version != myself->protocol_version)
212 syslog(LOG_ERR, _("Peer %s (%s) uses incompatible version %d"),
213 cl->name, cl->hostname, cl->protocol_version);
217 /* Check if identity is a valid name */
221 syslog(LOG_ERR, _("Peer %s uses invalid identity name"), cl->hostname);
225 /* Copy string to cl */
227 cl->name = xstrdup(name);
229 /* Load information about peer */
231 if(read_host_config(cl))
233 syslog(LOG_ERR, _("Peer %s had unknown identity (%s)"), cl->hostname, cl->name);
237 /* First check if the host we connected to is already in our
238 connection list. If so, we are probably making a loop, which
242 if(cl->status.outgoing)
244 if((old = lookup_id(cl->name)))
246 if(debug_lvl >= DEBUG_CONNECTIONS)
247 syslog(LOG_NOTICE, _("Uplink %s (%s) is already in our connection list"), cl->name, cl->hostname);
248 cl->status.outgoing = 0;
249 old->status.outgoing = 1;
250 terminate_connection(cl);
255 /* Now we can add the name to the id tree */
259 /* And uhr... cl->port just changed so we have to unlink it from the connection tree and re-insert... */
261 node = avl_unlink(connection_tree, cl);
263 avl_insert_node(connection_tree, node);
265 /* Read in the public key, so that we can send a challenge */
267 if(read_rsa_public_key(cl))
271 return send_challenge(cl);
274 int send_challenge(connection_t *cl)
279 len = RSA_size(cl->rsa_key);
281 /* Allocate buffers for the challenge */
283 buffer = xmalloc(len*2+1);
286 free(cl->hischallenge);
288 cl->hischallenge = xmalloc(len);
290 /* Copy random data to the buffer */
292 RAND_bytes(cl->hischallenge, len);
294 cl->hischallenge[0] &= 0x7F; /* Somehow if the first byte is more than 0xD0 or something like that, decryption fails... */
296 if(debug_lvl >= DEBUG_SCARY_THINGS)
298 bin2hex(cl->hischallenge, buffer, len);
299 buffer[len*2] = '\0';
300 syslog(LOG_DEBUG, _("Generated random challenge (unencrypted): %s"), buffer);
303 /* Encrypt the random data */
305 if(RSA_public_encrypt(len, cl->hischallenge, buffer, cl->rsa_key, RSA_NO_PADDING) != len) /* NO_PADDING because the message size equals the RSA key size and it is totally random */
307 syslog(LOG_ERR, _("Error during encryption of challenge for %s (%s)"), cl->name, cl->hostname);
312 /* Convert the encrypted random data to a hexadecimal formatted string */
314 bin2hex(buffer, buffer, len);
315 buffer[len*2] = '\0';
317 /* Send the challenge */
319 cl->allow_request = CHAL_REPLY;
320 x = send_request(cl, "%d %s", CHALLENGE, buffer);
326 int challenge_h(connection_t *cl)
328 char buffer[MAX_STRING_SIZE];
331 if(sscanf(cl->buffer, "%*d "MAX_STRING, buffer) != 1)
333 syslog(LOG_ERR, _("Got bad CHALLENGE from %s (%s)"), cl->name, cl->hostname);
337 len = RSA_size(myself->rsa_key);
339 /* Check if the length of the challenge is all right */
341 if(strlen(buffer) != len*2)
343 syslog(LOG_ERR, _("Intruder: wrong challenge length from %s (%s)"), cl->name, cl->hostname);
347 /* Allocate buffers for the challenge */
350 cl->mychallenge = xmalloc(len);
352 /* Convert the challenge from hexadecimal back to binary */
354 hex2bin(buffer,buffer,len);
356 /* Decrypt the challenge */
358 if(RSA_private_decrypt(len, buffer, cl->mychallenge, myself->rsa_key, RSA_NO_PADDING) != len) /* See challenge() */
360 syslog(LOG_ERR, _("Error during encryption of challenge for %s (%s)"), cl->name, cl->hostname);
364 if(debug_lvl >= DEBUG_SCARY_THINGS)
366 bin2hex(cl->mychallenge, buffer, len);
367 buffer[len*2] = '\0';
368 syslog(LOG_DEBUG, _("Received random challenge (unencrypted): %s"), buffer);
371 /* Rest is done by send_chal_reply() */
373 return send_chal_reply(cl);
376 int send_chal_reply(connection_t *cl)
378 char hash[SHA_DIGEST_LENGTH*2+1];
382 syslog(LOG_ERR, _("Trying to send CHAL_REPLY to %s (%s) without a valid CHALLENGE"), cl->name, cl->hostname);
386 /* Calculate the hash from the challenge we received */
388 SHA1(cl->mychallenge, RSA_size(myself->rsa_key), hash);
390 /* Convert the hash to a hexadecimal formatted string */
392 bin2hex(hash,hash,SHA_DIGEST_LENGTH);
393 hash[SHA_DIGEST_LENGTH*2] = '\0';
397 if(cl->status.outgoing)
398 cl->allow_request = ID;
400 cl->allow_request = METAKEY;
403 return send_request(cl, "%d %s", CHAL_REPLY, hash);
406 int chal_reply_h(connection_t *cl)
408 char hishash[MAX_STRING_SIZE];
409 char myhash[SHA_DIGEST_LENGTH];
411 if(sscanf(cl->buffer, "%*d "MAX_STRING, hishash) != 1)
413 syslog(LOG_ERR, _("Got bad CHAL_REPLY from %s (%s)"), cl->name, cl->hostname);
417 /* Check if the length of the hash is all right */
419 if(strlen(hishash) != SHA_DIGEST_LENGTH*2)
421 syslog(LOG_ERR, _("Intruder: wrong challenge reply length from %s (%s)"), cl->name, cl->hostname);
425 /* Convert the hash to binary format */
427 hex2bin(hishash, hishash, SHA_DIGEST_LENGTH);
429 /* Calculate the hash from the challenge we sent */
431 SHA1(cl->hischallenge, RSA_size(cl->rsa_key), myhash);
433 /* Verify the incoming hash with the calculated hash */
435 if(memcmp(hishash, myhash, SHA_DIGEST_LENGTH))
437 syslog(LOG_ERR, _("Intruder: wrong challenge reply from %s (%s)"), cl->name, cl->hostname);
438 if(debug_lvl >= DEBUG_SCARY_THINGS)
440 bin2hex(myhash, hishash, SHA_DIGEST_LENGTH);
441 hishash[SHA_DIGEST_LENGTH*2] = '\0';
442 syslog(LOG_DEBUG, _("Expected challenge reply: %s"), hishash);
448 /* Identity has now been positively verified.
449 If we are accepting this new connection, then send our identity,
450 if we are making this connecting, acknowledge.
453 if(cl->status.outgoing)
454 return send_metakey(cl);
459 int send_metakey(connection_t *cl)
464 len = RSA_size(cl->rsa_key);
466 /* Allocate buffers for the meta key */
468 buffer = xmalloc(len*2+1);
470 if(!cl->cipher_outkey)
471 cl->cipher_outkey = xmalloc(len);
473 if(!cl->cipher_outctx)
474 cl->cipher_outctx = xmalloc(sizeof(*cl->cipher_outctx));
476 /* Copy random data to the buffer */
478 RAND_bytes(cl->cipher_outkey, len);
480 cl->cipher_outkey[0] &= 0x7F; /* FIXME: Somehow if the first byte is more than 0xD0 or something like that, decryption fails... */
482 if(debug_lvl >= DEBUG_SCARY_THINGS)
484 bin2hex(cl->cipher_outkey, buffer, len);
485 buffer[len*2] = '\0';
486 syslog(LOG_DEBUG, _("Generated random meta key (unencrypted): %s"), buffer);
489 /* Encrypt the random data */
491 if(RSA_public_encrypt(len, cl->cipher_outkey, buffer, cl->rsa_key, RSA_NO_PADDING) != len) /* NO_PADDING because the message size equals the RSA key size and it is totally random */
493 syslog(LOG_ERR, _("Error during encryption of meta key for %s (%s)"), cl->name, cl->hostname);
498 /* Convert the encrypted random data to a hexadecimal formatted string */
500 bin2hex(buffer, buffer, len);
501 buffer[len*2] = '\0';
503 /* Send the meta key */
505 if(cl->status.outgoing)
506 cl->allow_request = METAKEY;
508 cl->allow_request = ACK;
510 x = send_request(cl, "%d %s", METAKEY, buffer);
513 EVP_EncryptInit(cl->cipher_outctx, EVP_bf_cfb(), cl->cipher_outkey, cl->cipher_outkey + EVP_bf_cfb()->key_len);
518 int metakey_h(connection_t *cl)
520 char buffer[MAX_STRING_SIZE];
523 if(sscanf(cl->buffer, "%*d "MAX_STRING, buffer) != 1)
525 syslog(LOG_ERR, _("Got bad METAKEY from %s (%s)"), cl->name, cl->hostname);
529 len = RSA_size(myself->rsa_key);
531 /* Check if the length of the meta key is all right */
533 if(strlen(buffer) != len*2)
535 syslog(LOG_ERR, _("Intruder: wrong meta key length from %s (%s)"), cl->name, cl->hostname);
539 /* Allocate buffers for the meta key */
541 if(!cl->cipher_inkey)
542 cl->cipher_inkey = xmalloc(len);
544 if(!cl->cipher_inctx)
545 cl->cipher_inctx = xmalloc(sizeof(*cl->cipher_inctx));
547 /* Convert the challenge from hexadecimal back to binary */
549 hex2bin(buffer,buffer,len);
551 /* Decrypt the meta key */
553 if(RSA_private_decrypt(len, buffer, cl->cipher_inkey, myself->rsa_key, RSA_NO_PADDING) != len) /* See challenge() */
555 syslog(LOG_ERR, _("Error during encryption of meta key for %s (%s)"), cl->name, cl->hostname);
559 if(debug_lvl >= DEBUG_SCARY_THINGS)
561 bin2hex(cl->cipher_inkey, buffer, len);
562 buffer[len*2] = '\0';
563 syslog(LOG_DEBUG, _("Received random meta key (unencrypted): %s"), buffer);
566 EVP_DecryptInit(cl->cipher_inctx, EVP_bf_cfb(), cl->cipher_inkey, cl->cipher_inkey + EVP_bf_cfb()->key_len);
569 if(cl->status.outgoing)
572 return send_metakey(cl);
575 int send_ack(connection_t *cl)
579 if(cl->status.outgoing)
580 cl->allow_request = ACK;
582 x = send_request(cl, "%d", ACK);
583 cl->status.encryptout = 1;
588 int ack_h(connection_t *cl)
591 connection_t *old, *p;
593 avl_node_t *node, *node2;
595 /* Okay, before we active the connection, we check if there is another entry
596 in the connection list with the same name. If so, it presumably is an
597 old connection that has timed out but we don't know it yet.
600 while((old = lookup_id(cl->name)))
602 if(debug_lvl >= DEBUG_CONNECTIONS)
603 syslog(LOG_NOTICE, _("Removing old entry for %s at %s in favour of new connection from %s"),
604 cl->name, old->hostname, cl->hostname);
606 terminate_connection(old);
609 /* Activate this connection */
611 cl->allow_request = ALL;
612 cl->status.active = 1;
613 cl->status.decryptin = 1;
615 cl->cipher_pkttype = EVP_bf_cfb();
616 cl->cipher_pktkeylength = cl->cipher_pkttype->key_len + cl->cipher_pkttype->iv_len;
618 if(debug_lvl >= DEBUG_CONNECTIONS)
619 syslog(LOG_NOTICE, _("Connection with %s (%s) activated"), cl->name, cl->hostname);
622 if(!cl->status.outgoing)
625 /* Check some options */
627 if((cfg = get_config_val(cl->config, config_indirectdata)))
629 if(cfg->data.val == stupid_true)
630 cl->options |= OPTION_INDIRECT;
633 if((cfg = get_config_val(cl->config, config_tcponly)))
635 if(cfg->data.val == stupid_true)
636 cl->options |= OPTION_TCPONLY;
639 /* Send him our subnets */
641 for(node = myself->subnet_tree->head; node; node = node->next)
643 subnet = (subnet_t *)node->data;
644 send_add_subnet(cl, subnet);
646 /* And send him all the hosts and their subnets we know... */
648 for(node = connection_tree->head; node; node = node->next)
650 p = (connection_t *)node->data;
652 if(p != cl && p->status.active)
654 /* Notify others of this connection */
657 send_add_host(p, cl);
659 /* Notify new connection of everything we know */
661 send_add_host(cl, p);
663 for(node2 = p->subnet_tree->head; node2; node2 = node2->next)
665 subnet = (subnet_t *)node2->data;
666 send_add_subnet(cl, subnet);
674 /* Address and subnet information exchange */
676 int send_add_subnet(connection_t *cl, subnet_t *subnet)
682 if(cl->options & OPTION_INDIRECT)
683 owner = myself->name;
685 owner = subnet->owner->name;
687 x = send_request(cl, "%d %s %s", ADD_SUBNET,
688 owner, netstr = net2str(subnet));
694 int add_subnet_h(connection_t *cl)
696 char subnetstr[MAX_STRING_SIZE];
697 char name[MAX_STRING_SIZE];
698 connection_t *owner, *p;
702 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING, name, subnetstr) != 2)
704 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s)"), cl->name, cl->hostname);
708 /* Check if owner name is a valid */
712 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s): invalid identity name"), cl->name, cl->hostname);
716 /* Check if subnet string is valid */
718 if(!(subnet = str2net(subnetstr)))
720 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s): invalid subnet string"), cl->name, cl->hostname);
724 /* Check if somebody tries to add a subnet of ourself */
726 if(!strcmp(name, myself->name))
728 syslog(LOG_ERR, _("Warning: got ADD_SUBNET from %s (%s) for ourself, restarting"),
729 cl->name, cl->hostname);
734 /* Check if the owner of the new subnet is in the connection list */
736 if(!(owner = lookup_id(name)))
738 syslog(LOG_ERR, _("Got ADD_SUBNET for %s from %s (%s) which is not in our connection list"),
739 name, cl->name, cl->hostname);
743 /* If everything is correct, add the subnet to the list of the owner */
745 subnet_add(owner, subnet);
749 for(node = connection_tree->head; node; node = node->next)
751 p = (connection_t *)node->data;
752 if(p->status.meta && p->status.active && p!= cl)
753 send_add_subnet(p, subnet);
759 int send_del_subnet(connection_t *cl, subnet_t *subnet)
765 if(cl->options & OPTION_INDIRECT)
766 owner = myself->name;
768 owner = subnet->owner->name;
770 x = send_request(cl, "%d %s %s", DEL_SUBNET, owner, netstr = net2str(subnet));
776 int del_subnet_h(connection_t *cl)
778 char subnetstr[MAX_STRING_SIZE];
779 char name[MAX_STRING_SIZE];
780 connection_t *owner, *p;
784 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING, name, subnetstr) != 3)
786 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s)"), cl->name, cl->hostname);
790 /* Check if owner name is a valid */
794 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s): invalid identity name"), cl->name, cl->hostname);
798 /* Check if subnet string is valid */
800 if(!(subnet = str2net(subnetstr)))
802 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s): invalid subnet string"), cl->name, cl->hostname);
808 /* Check if somebody tries to add a subnet of ourself */
810 if(!strcmp(name, myself->name))
812 syslog(LOG_ERR, _("Warning: got DEL_SUBNET from %s (%s) for ourself, restarting"),
813 cl->name, cl->hostname);
818 /* Check if the owner of the new subnet is in the connection list */
820 if(!(owner = lookup_id(name)))
822 syslog(LOG_ERR, _("Got DEL_SUBNET for %s from %s (%s) which is not in our connection list"),
823 name, cl->name, cl->hostname);
827 /* If everything is correct, delete the subnet from the list of the owner */
833 for(node = connection_tree->head; node; node = node->next)
835 p = (connection_t *)node->data;
836 if(p->status.meta && p->status.active && p!= cl)
837 send_del_subnet(p, subnet);
843 /* New and closed connections notification */
845 int send_add_host(connection_t *cl, connection_t *other)
848 if(!(cl->options & OPTION_INDIRECT))
849 return send_request(cl, "%d %s %lx:%d %lx", ADD_HOST,
850 other->name, other->address, other->port, other->options);
853 int add_host_h(connection_t *cl)
855 connection_t *old, *new, *p;
856 char name[MAX_STRING_SIZE];
859 new = new_connection();
861 if(sscanf(cl->buffer, "%*d "MAX_STRING" %lx:%d %lx", name, &new->address, &new->port, &new->options) != 4)
863 syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s)"), cl->name, cl->hostname);
867 /* Check if identity is a valid name */
871 syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s): invalid identity name"), cl->name, cl->hostname);
872 free_connection(new);
876 /* Check if somebody tries to add ourself */
878 if(!strcmp(name, myself->name))
880 syslog(LOG_ERR, _("Warning: got ADD_HOST from %s (%s) for ourself, restarting"), cl->name, cl->hostname);
882 free_connection(new);
886 /* Fill in more of the new connection structure */
888 new->hostname = hostlookup(htonl(new->address));
890 /* Check if the new host already exists in the connnection list */
892 if((old = lookup_id(name)))
894 if((new->address == old->address) && (new->port == old->port))
896 if(debug_lvl >= DEBUG_CONNECTIONS)
897 syslog(LOG_NOTICE, _("Got duplicate ADD_HOST for %s (%s) from %s (%s)"),
898 old->name, old->hostname, name, new->hostname);
899 free_connection(new);
904 if(debug_lvl >= DEBUG_CONNECTIONS)
905 syslog(LOG_NOTICE, _("Removing old entry for %s (%s) in favour of new connection"),
906 old->name, old->hostname);
908 terminate_connection(old);
912 /* Hook it up into the connection */
914 new->name = xstrdup(name);
918 /* Tell the rest about the new host */
920 for(node = connection_tree->head; node; node = node->next)
922 p = (connection_t *)node->data;
923 if(p->status.meta && p->status.active && p!=cl)
924 send_add_host(p, new);
927 /* Fill in rest of connection structure */
930 new->status.active = 1;
931 new->cipher_pkttype = EVP_bf_cfb();
932 new->cipher_pktkeylength = cl->cipher_pkttype->key_len + cl->cipher_pkttype->iv_len;
937 int send_del_host(connection_t *cl, connection_t *other)
940 if(!(cl->options & OPTION_INDIRECT))
941 return send_request(cl, "%d %s %lx:%d %lx", DEL_HOST,
942 other->name, other->address, other->port, other->options);
945 int del_host_h(connection_t *cl)
947 char name[MAX_STRING_SIZE];
951 connection_t *old, *p;
954 if(sscanf(cl->buffer, "%*d "MAX_STRING" %lx:%d %lx", name, &address, &port, &options) != 4)
956 syslog(LOG_ERR, _("Got bad DEL_HOST from %s (%s)"),
957 cl->name, cl->hostname);
961 /* Check if identity is a valid name */
965 syslog(LOG_ERR, _("Got bad DEL_HOST from %s (%s): invalid identity name"), cl->name, cl->hostname);
969 /* Check if somebody tries to delete ourself */
971 if(!strcmp(name, myself->name))
973 syslog(LOG_ERR, _("Warning: got DEL_HOST from %s (%s) for ourself, restarting"),
974 cl->name, cl->hostname);
979 /* Check if the new host already exists in the connnection list */
981 if(!(old = lookup_id(name)))
983 syslog(LOG_ERR, _("Got DEL_HOST from %s (%s) for %s which is not in our connection list"),
984 name, cl->name, cl->hostname);
988 /* Check if the rest matches */
990 if(address!=old->address || port!=old->port || options!=old->options || cl!=old->nexthop)
992 syslog(LOG_WARNING, _("Got DEL_HOST from %s (%s) for %s which doesn't match"), cl->name, cl->hostname, old->name);
996 /* Ok, since EVERYTHING seems to check out all right, delete it */
998 old->status.active = 0;
999 terminate_connection(old);
1001 /* Tell the rest about the new host */
1003 for(node = connection_tree->head; node; node = node->next)
1005 p = (connection_t *)node->data;
1006 if(p->status.meta && p->status.active && p!=cl)
1007 send_del_host(p, old);
1013 /* Status and error notification routines */
1015 int send_status(connection_t *cl, int statusno, char *statusstring)
1019 statusstring = status_text[statusno];
1021 return send_request(cl, "%d %d %s", STATUS, statusno, statusstring);
1024 int status_h(connection_t *cl)
1027 char statusstring[MAX_STRING_SIZE];
1029 if(sscanf(cl->buffer, "%*d %d "MAX_STRING, &statusno, statusstring) != 2)
1031 syslog(LOG_ERR, _("Got bad STATUS from %s (%s)"),
1032 cl->name, cl->hostname);
1036 if(debug_lvl >= DEBUG_STATUS)
1038 syslog(LOG_NOTICE, _("Status message from %s (%s): %s: %s"),
1039 cl->name, cl->hostname, status_text[statusno], statusstring);
1046 int send_error(connection_t *cl, int errno, char *errstring)
1050 errstring = strerror(errno);
1051 return send_request(cl, "%d %d %s", ERROR, errno, errstring);
1054 int error_h(connection_t *cl)
1057 char errorstring[MAX_STRING_SIZE];
1059 if(sscanf(cl->buffer, "%*d %d "MAX_STRING, &errno, errorstring) != 2)
1061 syslog(LOG_ERR, _("Got bad ERROR from %s (%s)"),
1062 cl->name, cl->hostname);
1066 if(debug_lvl >= DEBUG_ERROR)
1068 syslog(LOG_NOTICE, _("Error message from %s (%s): %s: %s"),
1069 cl->name, cl->hostname, strerror(errno), errorstring);
1072 terminate_connection(cl);
1077 int send_termreq(connection_t *cl)
1080 return send_request(cl, "%d", TERMREQ);
1083 int termreq_h(connection_t *cl)
1086 terminate_connection(cl);
1091 int send_ping(connection_t *cl)
1094 cl->status.pinged = 1;
1095 cl->last_ping_time = time(NULL);
1097 return send_request(cl, "%d", PING);
1100 int ping_h(connection_t *cl)
1103 return send_pong(cl);
1106 int send_pong(connection_t *cl)
1109 return send_request(cl, "%d", PONG);
1112 int pong_h(connection_t *cl)
1115 cl->status.pinged = 0;
1122 int send_key_changed(connection_t *from, connection_t *cl)
1127 for(node = connection_tree->head; node; node = node->next)
1129 p = (connection_t *)node->data;
1130 if(p != cl && p->status.meta && p->status.active)
1131 if(!(p->options & OPTION_INDIRECT) || from == myself)
1132 send_request(p, "%d %s", KEY_CHANGED, from->name);
1138 int key_changed_h(connection_t *cl)
1140 char from_id[MAX_STRING_SIZE];
1143 if(sscanf(cl->buffer, "%*d "MAX_STRING, from_id) != 1)
1145 syslog(LOG_ERR, _("Got bad KEY_CHANGED from %s (%s)"),
1146 cl->name, cl->hostname);
1150 if(!(from = lookup_id(from_id)))
1152 syslog(LOG_ERR, _("Got KEY_CHANGED from %s (%s) origin %s which does not exist in our connection list"),
1153 cl->name, cl->hostname, from_id);
1157 from->status.validkey = 0;
1158 from->status.waitingforkey = 0;
1160 send_key_changed(from, cl);
1165 int send_req_key(connection_t *from, connection_t *to)
1168 return send_request(to->nexthop, "%d %s %s", REQ_KEY,
1169 from->name, to->name);
1172 int req_key_h(connection_t *cl)
1174 char from_id[MAX_STRING_SIZE];
1175 char to_id[MAX_STRING_SIZE];
1176 connection_t *from, *to;
1179 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING, from_id, to_id) != 2)
1181 syslog(LOG_ERR, _("Got bad REQ_KEY from %s (%s)"),
1182 cl->name, cl->hostname);
1186 if(!(from = lookup_id(from_id)))
1188 syslog(LOG_ERR, _("Got REQ_KEY from %s (%s) origin %s which does not exist in our connection list"),
1189 cl->name, cl->hostname, from_id);
1193 /* Check if this key request is for us */
1195 if(!strcmp(to_id, myself->name))
1197 bin2hex(myself->cipher_pktkey, pktkey, myself->cipher_pktkeylength);
1198 pktkey[myself->cipher_pktkeylength*2] = '\0';
1199 send_ans_key(myself, from, pktkey);
1203 if(!(to = lookup_id(to_id)))
1205 syslog(LOG_ERR, _("Got REQ_KEY from %s (%s) destination %s which does not exist in our connection list"),
1206 cl->name, cl->hostname, to_id);
1210 if(to->status.validkey) /* Proxy keys */
1212 bin2hex(to->cipher_pktkey, pktkey, to->cipher_pktkeylength);
1213 pktkey[to->cipher_pktkeylength*2] = '\0';
1214 send_ans_key(to, from, pktkey);
1217 send_req_key(from, to);
1224 int send_ans_key(connection_t *from, connection_t *to, char *pktkey)
1227 return send_request(to->nexthop, "%d %s %s %s", ANS_KEY,
1228 from->name, to->name, pktkey);
1231 int ans_key_h(connection_t *cl)
1233 char from_id[MAX_STRING_SIZE];
1234 char to_id[MAX_STRING_SIZE];
1235 char pktkey[MAX_STRING_SIZE];
1237 connection_t *from, *to;
1239 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING, from_id, to_id, pktkey) != 3)
1241 syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s)"),
1242 cl->name, cl->hostname);
1246 if(!(from = lookup_id(from_id)))
1248 syslog(LOG_ERR, _("Got ANS_KEY from %s (%s) origin %s which does not exist in our connection list"),
1249 cl->name, cl->hostname, from_id);
1253 /* Check correctness of packet key */
1255 keylength = strlen(pktkey);
1257 if(keylength != from->cipher_pktkeylength*2)
1259 syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s) origin %s: invalid key length"),
1260 cl->name, cl->hostname, from->name);
1264 /* Forward it if necessary */
1266 if(strcmp(to_id, myself->name))
1268 if(!(to = lookup_id(to_id)))
1270 syslog(LOG_ERR, _("Got ANS_KEY from %s (%s) destination %s which does not exist in our connection list"),
1271 cl->name, cl->hostname, to_id);
1274 send_ans_key(from, to, pktkey);
1277 /* Update our copy of the origin's packet key */
1279 if(from->cipher_pktkey)
1280 free(from->cipher_pktkey);
1282 from->cipher_pktkey = xstrdup(pktkey);
1284 hex2bin(from->cipher_pktkey, from->cipher_pktkey, keylength);
1285 from->cipher_pktkey[keylength] = '\0';
1287 from->status.validkey = 1;
1288 from->status.waitingforkey = 0;
1295 int send_tcppacket(connection_t *cl, vpn_packet_t *packet)
1299 x = send_request(cl->nexthop, "%d %hd", PACKET, packet->len);
1304 return send_meta(cl->nexthop, packet->data, packet->len);
1307 int tcppacket_h(connection_t *cl)
1309 vpn_packet_t packet;
1313 if(sscanf(cl->buffer, "%*d %hd", packet.len) != 1)
1315 syslog(LOG_ERR, _("Got bad PACKET from %s (%s)"), cl->name, cl->hostname);
1326 x = read(cl->meta_socket, p, todo);
1329 syslog(LOG_ERR, _("Error during reception of PACKET from %s (%s): %m"), cl->name, cl->hostname);
1337 return receive_packet(cl, &packet);
1340 /* Jumptable for the request handlers */
1342 int (*request_handlers[])(connection_t*) = {
1343 id_h, challenge_h, chal_reply_h, metakey_h, ack_h,
1344 status_h, error_h, termreq_h,
1346 add_host_h, del_host_h,
1347 add_subnet_h, del_subnet_h,
1348 key_changed_h, req_key_h, ans_key_h,
1354 char (*request_name[]) = {
1355 "ID", "CHALLENGE", "CHAL_REPLY", "METAKEY", "ACK",
1356 "STATUS", "ERROR", "TERMREQ",
1358 "ADD_HOST", "DEL_HOST",
1359 "ADD_SUBNET", "DEL_SUBNET",
1360 "KEY_CHANGED", "REQ_KEY", "ANS_KEY",
1364 /* Status strings */
1366 char (*status_text[]) = {
1372 char (*error_text[]) = {