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.79 2001/02/25 11:09:29 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"
71 int check_id(char *id)
75 for (i = 0; i < strlen(id); i++)
76 if(!isalnum(id[i]) && id[i] != '_')
82 /* Generic request routines - takes care of logging and error
85 int send_request(connection_t *cl, const char *format, ...)
88 char buffer[MAXBUFSIZE];
92 /* Use vsnprintf instead of vasprintf: faster, no memory
93 fragmentation, cleanup is automatic, and there is a limit on the
94 input buffer anyway */
96 va_start(args, format);
97 len = vsnprintf(buffer, MAXBUFSIZE, format, args);
98 request = va_arg(args, int);
101 if(len < 0 || len > MAXBUFSIZE-1)
103 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)
110 syslog(LOG_DEBUG, _("Sending %s to %s (%s)"), request_name[request], cl->name, cl->hostname);
113 return send_meta(cl, buffer, len);
116 int receive_request(connection_t *cl)
120 if(sscanf(cl->buffer, "%d", &request) == 1)
122 if((request < 0) || (request > 255) || (request_handlers[request] == NULL))
124 syslog(LOG_ERR, _("Unknown request from %s (%s)"),
125 cl->name, cl->hostname);
130 if(debug_lvl >= DEBUG_PROTOCOL)
131 syslog(LOG_DEBUG, _("Got %s from %s (%s)"),
132 request_name[request], cl->name, cl->hostname);
135 if((cl->allow_request != ALL) && (cl->allow_request != request))
137 syslog(LOG_ERR, _("Unauthorized request from %s (%s)"), cl->name, cl->hostname);
141 if(request_handlers[request](cl))
142 /* Something went wrong. Probably scriptkiddies. Terminate. */
144 syslog(LOG_ERR, _("Error while processing %s from %s (%s)"),
145 request_name[request], cl->name, cl->hostname);
151 syslog(LOG_ERR, _("Bogus data received from %s (%s)"),
152 cl->name, cl->hostname);
159 /* Connection protocol:
168 ---------------------------------------
171 ---------------------------------------
174 ---------------------------------------
180 (E) Encrypted with symmetric cipher.
182 Part of the challenge is directly used to set the symmetric cipher
183 key and the initial vector. Since a man-in-the-middle cannot
184 decrypt the RSA challenges, this means that he cannot get or forge
185 the key for the symmetric cipher.
188 int send_id(connection_t *cl)
191 cl->allow_request = CHALLENGE;
193 return send_request(cl, "%d %s %d %lx %hd", ID, myself->name, myself->protocol_version, myself->options, myself->port);
196 int id_h(connection_t *cl)
199 unsigned short int port;
200 char name[MAX_STRING_SIZE];
203 if(sscanf(cl->buffer, "%*d "MAX_STRING" %d %lx %hd", name, &cl->protocol_version, &cl->options, &port) != 4)
205 syslog(LOG_ERR, _("Got bad ID from %s"), cl->hostname);
209 /* Check if version matches */
211 if(cl->protocol_version != myself->protocol_version)
213 syslog(LOG_ERR, _("Peer %s (%s) uses incompatible version %d"),
214 cl->name, cl->hostname, cl->protocol_version);
218 /* Check if identity is a valid name */
222 syslog(LOG_ERR, _("Peer %s uses invalid identity name"), cl->hostname);
226 /* Copy string to cl */
228 cl->name = xstrdup(name);
230 /* Load information about peer */
232 if(read_host_config(cl))
234 syslog(LOG_ERR, _("Peer %s had unknown identity (%s)"), cl->hostname, cl->name);
238 /* First check if the host we connected to is already in our
239 connection list. If so, we are probably making a loop, which
243 if(cl->status.outgoing)
245 if((old = lookup_id(cl->name)))
247 if(debug_lvl >= DEBUG_CONNECTIONS)
248 syslog(LOG_NOTICE, _("Uplink %s (%s) is already in our connection list"), cl->name, cl->hostname);
249 cl->status.outgoing = 0;
250 old->status.outgoing = 1;
251 terminate_connection(cl);
256 /* Now we can add the name to the id tree */
260 /* And uhr... cl->port just changed so we have to unlink it from the connection tree and re-insert... */
262 node = avl_unlink(connection_tree, cl);
264 avl_insert_node(connection_tree, node);
266 /* Read in the public key, so that we can send a challenge */
268 if(read_rsa_public_key(cl))
272 return send_challenge(cl);
275 int send_challenge(connection_t *cl)
280 len = RSA_size(cl->rsa_key);
282 /* Allocate buffers for the challenge */
284 buffer = xmalloc(len*2+1);
287 free(cl->hischallenge);
289 cl->hischallenge = xmalloc(len);
291 /* Copy random data to the buffer */
293 RAND_bytes(cl->hischallenge, len);
295 cl->hischallenge[0] &= 0x7F; /* Somehow if the first byte is more than 0xD0 or something like that, decryption fails... */
297 if(debug_lvl >= DEBUG_SCARY_THINGS)
299 bin2hex(cl->hischallenge, buffer, len);
300 buffer[len*2] = '\0';
301 syslog(LOG_DEBUG, _("Generated random challenge (unencrypted): %s"), buffer);
304 /* Encrypt the random data */
306 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 */
308 syslog(LOG_ERR, _("Error during encryption of challenge for %s (%s)"), cl->name, cl->hostname);
313 /* Convert the encrypted random data to a hexadecimal formatted string */
315 bin2hex(buffer, buffer, len);
316 buffer[len*2] = '\0';
318 /* Send the challenge */
320 cl->allow_request = CHAL_REPLY;
321 x = send_request(cl, "%d %s", CHALLENGE, buffer);
327 int challenge_h(connection_t *cl)
329 char buffer[MAX_STRING_SIZE];
332 if(sscanf(cl->buffer, "%*d "MAX_STRING, buffer) != 1)
334 syslog(LOG_ERR, _("Got bad CHALLENGE from %s (%s)"), cl->name, cl->hostname);
338 len = RSA_size(myself->rsa_key);
340 /* Check if the length of the challenge is all right */
342 if(strlen(buffer) != len*2)
344 syslog(LOG_ERR, _("Intruder: wrong challenge length from %s (%s)"), cl->name, cl->hostname);
348 /* Allocate buffers for the challenge */
351 cl->mychallenge = xmalloc(len);
353 /* Convert the challenge from hexadecimal back to binary */
355 hex2bin(buffer,buffer,len);
357 /* Decrypt the challenge */
359 if(RSA_private_decrypt(len, buffer, cl->mychallenge, myself->rsa_key, RSA_NO_PADDING) != len) /* See challenge() */
361 syslog(LOG_ERR, _("Error during encryption of challenge for %s (%s)"), cl->name, cl->hostname);
365 if(debug_lvl >= DEBUG_SCARY_THINGS)
367 bin2hex(cl->mychallenge, buffer, len);
368 buffer[len*2] = '\0';
369 syslog(LOG_DEBUG, _("Received random challenge (unencrypted): %s"), buffer);
372 /* Rest is done by send_chal_reply() */
374 return send_chal_reply(cl);
377 int send_chal_reply(connection_t *cl)
379 char hash[SHA_DIGEST_LENGTH*2+1];
383 syslog(LOG_ERR, _("Trying to send CHAL_REPLY to %s (%s) without a valid CHALLENGE"), cl->name, cl->hostname);
387 /* Calculate the hash from the challenge we received */
389 SHA1(cl->mychallenge, RSA_size(myself->rsa_key), hash);
391 /* Convert the hash to a hexadecimal formatted string */
393 bin2hex(hash,hash,SHA_DIGEST_LENGTH);
394 hash[SHA_DIGEST_LENGTH*2] = '\0';
398 if(cl->status.outgoing)
399 cl->allow_request = ID;
401 cl->allow_request = METAKEY;
404 return send_request(cl, "%d %s", CHAL_REPLY, hash);
407 int chal_reply_h(connection_t *cl)
409 char hishash[MAX_STRING_SIZE];
410 char myhash[SHA_DIGEST_LENGTH];
412 if(sscanf(cl->buffer, "%*d "MAX_STRING, hishash) != 1)
414 syslog(LOG_ERR, _("Got bad CHAL_REPLY from %s (%s)"), cl->name, cl->hostname);
418 /* Check if the length of the hash is all right */
420 if(strlen(hishash) != SHA_DIGEST_LENGTH*2)
422 syslog(LOG_ERR, _("Intruder: wrong challenge reply length from %s (%s)"), cl->name, cl->hostname);
426 /* Convert the hash to binary format */
428 hex2bin(hishash, hishash, SHA_DIGEST_LENGTH);
430 /* Calculate the hash from the challenge we sent */
432 SHA1(cl->hischallenge, RSA_size(cl->rsa_key), myhash);
434 /* Verify the incoming hash with the calculated hash */
436 if(memcmp(hishash, myhash, SHA_DIGEST_LENGTH))
438 syslog(LOG_ERR, _("Intruder: wrong challenge reply from %s (%s)"), cl->name, cl->hostname);
439 if(debug_lvl >= DEBUG_SCARY_THINGS)
441 bin2hex(myhash, hishash, SHA_DIGEST_LENGTH);
442 hishash[SHA_DIGEST_LENGTH*2] = '\0';
443 syslog(LOG_DEBUG, _("Expected challenge reply: %s"), hishash);
449 /* Identity has now been positively verified.
450 If we are accepting this new connection, then send our identity,
451 if we are making this connecting, acknowledge.
454 if(cl->status.outgoing)
455 return send_metakey(cl);
460 int send_metakey(connection_t *cl)
465 len = RSA_size(cl->rsa_key);
467 /* Allocate buffers for the meta key */
469 buffer = xmalloc(len*2+1);
471 if(!cl->cipher_outkey)
472 cl->cipher_outkey = xmalloc(len);
474 if(!cl->cipher_outctx)
475 cl->cipher_outctx = xmalloc(sizeof(*cl->cipher_outctx));
477 /* Copy random data to the buffer */
479 RAND_bytes(cl->cipher_outkey, len);
481 cl->cipher_outkey[0] &= 0x7F; /* FIXME: Somehow if the first byte is more than 0xD0 or something like that, decryption fails... */
483 if(debug_lvl >= DEBUG_SCARY_THINGS)
485 bin2hex(cl->cipher_outkey, buffer, len);
486 buffer[len*2] = '\0';
487 syslog(LOG_DEBUG, _("Generated random meta key (unencrypted): %s"), buffer);
490 /* Encrypt the random data */
492 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 */
494 syslog(LOG_ERR, _("Error during encryption of meta key for %s (%s)"), cl->name, cl->hostname);
499 /* Convert the encrypted random data to a hexadecimal formatted string */
501 bin2hex(buffer, buffer, len);
502 buffer[len*2] = '\0';
504 /* Send the meta key */
506 if(cl->status.outgoing)
507 cl->allow_request = METAKEY;
509 cl->allow_request = ACK;
511 x = send_request(cl, "%d %s", METAKEY, buffer);
514 EVP_EncryptInit(cl->cipher_outctx, EVP_bf_cfb(), cl->cipher_outkey, cl->cipher_outkey + EVP_bf_cfb()->key_len);
519 int metakey_h(connection_t *cl)
521 char buffer[MAX_STRING_SIZE];
524 if(sscanf(cl->buffer, "%*d "MAX_STRING, buffer) != 1)
526 syslog(LOG_ERR, _("Got bad METAKEY from %s (%s)"), cl->name, cl->hostname);
530 len = RSA_size(myself->rsa_key);
532 /* Check if the length of the meta key is all right */
534 if(strlen(buffer) != len*2)
536 syslog(LOG_ERR, _("Intruder: wrong meta key length from %s (%s)"), cl->name, cl->hostname);
540 /* Allocate buffers for the meta key */
542 if(!cl->cipher_inkey)
543 cl->cipher_inkey = xmalloc(len);
545 if(!cl->cipher_inctx)
546 cl->cipher_inctx = xmalloc(sizeof(*cl->cipher_inctx));
548 /* Convert the challenge from hexadecimal back to binary */
550 hex2bin(buffer,buffer,len);
552 /* Decrypt the meta key */
554 if(RSA_private_decrypt(len, buffer, cl->cipher_inkey, myself->rsa_key, RSA_NO_PADDING) != len) /* See challenge() */
556 syslog(LOG_ERR, _("Error during encryption of meta key for %s (%s)"), cl->name, cl->hostname);
560 if(debug_lvl >= DEBUG_SCARY_THINGS)
562 bin2hex(cl->cipher_inkey, buffer, len);
563 buffer[len*2] = '\0';
564 syslog(LOG_DEBUG, _("Received random meta key (unencrypted): %s"), buffer);
567 EVP_DecryptInit(cl->cipher_inctx, EVP_bf_cfb(), cl->cipher_inkey, cl->cipher_inkey + EVP_bf_cfb()->key_len);
570 if(cl->status.outgoing)
573 return send_metakey(cl);
576 int send_ack(connection_t *cl)
580 if(cl->status.outgoing)
581 cl->allow_request = ACK;
583 x = send_request(cl, "%d", ACK);
584 cl->status.encryptout = 1;
589 int ack_h(connection_t *cl)
592 connection_t *old, *p;
594 avl_node_t *node, *node2;
596 /* Okay, before we active the connection, we check if there is another entry
597 in the connection list with the same name. If so, it presumably is an
598 old connection that has timed out but we don't know it yet.
601 while((old = lookup_id(cl->name)))
603 if(debug_lvl >= DEBUG_CONNECTIONS)
604 syslog(LOG_NOTICE, _("Removing old entry for %s at %s in favour of new connection from %s"),
605 cl->name, old->hostname, cl->hostname);
607 terminate_connection(old);
610 /* Activate this connection */
612 cl->allow_request = ALL;
613 cl->status.active = 1;
614 cl->status.decryptin = 1;
616 cl->cipher_pkttype = EVP_bf_cfb();
617 cl->cipher_pktkeylength = cl->cipher_pkttype->key_len + cl->cipher_pkttype->iv_len;
619 if(debug_lvl >= DEBUG_CONNECTIONS)
620 syslog(LOG_NOTICE, _("Connection with %s (%s) activated"), cl->name, cl->hostname);
623 if(!cl->status.outgoing)
626 /* Check some options */
628 if((cfg = get_config_val(cl->config, config_indirectdata)))
630 if(cfg->data.val == stupid_true)
631 cl->options |= OPTION_INDIRECT;
634 if((cfg = get_config_val(cl->config, config_tcponly)))
636 if(cfg->data.val == stupid_true)
637 cl->options |= OPTION_TCPONLY;
640 /* Send him our subnets */
642 for(node = myself->subnet_tree->head; node; node = node->next)
644 subnet = (subnet_t *)node->data;
645 send_add_subnet(cl, subnet);
647 /* And send him all the hosts and their subnets we know... */
649 for(node = connection_tree->head; node; node = node->next)
651 p = (connection_t *)node->data;
653 if(p != cl && p->status.active)
655 /* Notify others of this connection */
658 send_add_host(p, cl);
660 /* Notify new connection of everything we know */
662 send_add_host(cl, p);
664 for(node2 = p->subnet_tree->head; node2; node2 = node2->next)
666 subnet = (subnet_t *)node2->data;
667 send_add_subnet(cl, subnet);
675 /* Address and subnet information exchange */
677 int send_add_subnet(connection_t *cl, subnet_t *subnet)
683 if(cl->options & OPTION_INDIRECT)
684 owner = myself->name;
686 owner = subnet->owner->name;
688 x = send_request(cl, "%d %s %s", ADD_SUBNET,
689 owner, netstr = net2str(subnet));
695 int add_subnet_h(connection_t *cl)
697 char subnetstr[MAX_STRING_SIZE];
698 char name[MAX_STRING_SIZE];
699 connection_t *owner, *p;
703 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING, name, subnetstr) != 2)
705 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s)"), cl->name, cl->hostname);
709 /* Check if owner name is a valid */
713 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s): invalid identity name"), cl->name, cl->hostname);
717 /* Check if subnet string is valid */
719 if(!(subnet = str2net(subnetstr)))
721 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s): invalid subnet string"), cl->name, cl->hostname);
725 /* Check if somebody tries to add a subnet of ourself */
727 if(!strcmp(name, myself->name))
729 syslog(LOG_ERR, _("Warning: got ADD_SUBNET from %s (%s) for ourself, restarting"),
730 cl->name, cl->hostname);
735 /* Check if the owner of the new subnet is in the connection list */
737 if(!(owner = lookup_id(name)))
739 syslog(LOG_ERR, _("Got ADD_SUBNET for %s from %s (%s) which is not in our connection list"),
740 name, cl->name, cl->hostname);
744 /* If everything is correct, add the subnet to the list of the owner */
746 subnet_add(owner, subnet);
750 for(node = connection_tree->head; node; node = node->next)
752 p = (connection_t *)node->data;
753 if(p->status.meta && p->status.active && p!= cl)
754 send_add_subnet(p, subnet);
760 int send_del_subnet(connection_t *cl, subnet_t *subnet)
766 if(cl->options & OPTION_INDIRECT)
767 owner = myself->name;
769 owner = subnet->owner->name;
771 x = send_request(cl, "%d %s %s", DEL_SUBNET, owner, netstr = net2str(subnet));
777 int del_subnet_h(connection_t *cl)
779 char subnetstr[MAX_STRING_SIZE];
780 char name[MAX_STRING_SIZE];
781 connection_t *owner, *p;
785 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING, name, subnetstr) != 3)
787 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s)"), cl->name, cl->hostname);
791 /* Check if owner name is a valid */
795 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s): invalid identity name"), cl->name, cl->hostname);
799 /* Check if subnet string is valid */
801 if(!(subnet = str2net(subnetstr)))
803 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s): invalid subnet string"), cl->name, cl->hostname);
809 /* Check if somebody tries to add a subnet of ourself */
811 if(!strcmp(name, myself->name))
813 syslog(LOG_ERR, _("Warning: got DEL_SUBNET from %s (%s) for ourself, restarting"),
814 cl->name, cl->hostname);
819 /* Check if the owner of the new subnet is in the connection list */
821 if(!(owner = lookup_id(name)))
823 syslog(LOG_ERR, _("Got DEL_SUBNET for %s from %s (%s) which is not in our connection list"),
824 name, cl->name, cl->hostname);
828 /* If everything is correct, delete the subnet from the list of the owner */
834 for(node = connection_tree->head; node; node = node->next)
836 p = (connection_t *)node->data;
837 if(p->status.meta && p->status.active && p!= cl)
838 send_del_subnet(p, subnet);
844 /* New and closed connections notification */
846 int send_add_host(connection_t *cl, connection_t *other)
849 if(!(cl->options & OPTION_INDIRECT))
850 return send_request(cl, "%d %s %lx:%d %lx", ADD_HOST,
851 other->name, other->address, other->port, other->options);
854 int add_host_h(connection_t *cl)
856 connection_t *old, *new, *p;
857 char name[MAX_STRING_SIZE];
860 new = new_connection();
862 if(sscanf(cl->buffer, "%*d "MAX_STRING" %lx:%d %lx", name, &new->address, &new->port, &new->options) != 4)
864 syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s)"), cl->name, cl->hostname);
868 /* Check if identity is a valid name */
872 syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s): invalid identity name"), cl->name, cl->hostname);
873 free_connection(new);
877 /* Check if somebody tries to add ourself */
879 if(!strcmp(name, myself->name))
881 syslog(LOG_ERR, _("Warning: got ADD_HOST from %s (%s) for ourself, restarting"), cl->name, cl->hostname);
883 free_connection(new);
887 /* Fill in more of the new connection structure */
889 new->hostname = hostlookup(htonl(new->address));
891 /* Check if the new host already exists in the connnection list */
893 if((old = lookup_id(name)))
895 if((new->address == old->address) && (new->port == old->port))
897 if(debug_lvl >= DEBUG_CONNECTIONS)
898 syslog(LOG_NOTICE, _("Got duplicate ADD_HOST for %s (%s) from %s (%s)"),
899 old->name, old->hostname, name, new->hostname);
900 free_connection(new);
905 if(debug_lvl >= DEBUG_CONNECTIONS)
906 syslog(LOG_NOTICE, _("Removing old entry for %s (%s) in favour of new connection"),
907 old->name, old->hostname);
909 terminate_connection(old);
913 /* Hook it up into the connection */
915 new->name = xstrdup(name);
919 /* Tell the rest about the new host */
921 for(node = connection_tree->head; node; node = node->next)
923 p = (connection_t *)node->data;
924 if(p->status.meta && p->status.active && p!=cl)
925 send_add_host(p, new);
928 /* Fill in rest of connection structure */
931 new->status.active = 1;
932 new->cipher_pkttype = EVP_bf_cfb();
933 new->cipher_pktkeylength = cl->cipher_pkttype->key_len + cl->cipher_pkttype->iv_len;
938 int send_del_host(connection_t *cl, connection_t *other)
941 if(!(cl->options & OPTION_INDIRECT))
942 return send_request(cl, "%d %s %lx:%d %lx", DEL_HOST,
943 other->name, other->address, other->port, other->options);
946 int del_host_h(connection_t *cl)
948 char name[MAX_STRING_SIZE];
952 connection_t *old, *p;
955 if(sscanf(cl->buffer, "%*d "MAX_STRING" %lx:%d %lx", name, &address, &port, &options) != 4)
957 syslog(LOG_ERR, _("Got bad DEL_HOST from %s (%s)"),
958 cl->name, cl->hostname);
962 /* Check if identity is a valid name */
966 syslog(LOG_ERR, _("Got bad DEL_HOST from %s (%s): invalid identity name"), cl->name, cl->hostname);
970 /* Check if somebody tries to delete ourself */
972 if(!strcmp(name, myself->name))
974 syslog(LOG_ERR, _("Warning: got DEL_HOST from %s (%s) for ourself, restarting"),
975 cl->name, cl->hostname);
980 /* Check if the new host already exists in the connnection list */
982 if(!(old = lookup_id(name)))
984 syslog(LOG_ERR, _("Got DEL_HOST from %s (%s) for %s which is not in our connection list"),
985 name, cl->name, cl->hostname);
989 /* Check if the rest matches */
991 if(address!=old->address || port!=old->port || options!=old->options || cl!=old->nexthop)
993 syslog(LOG_WARNING, _("Got DEL_HOST from %s (%s) for %s which doesn't match"), cl->name, cl->hostname, old->name);
997 /* Ok, since EVERYTHING seems to check out all right, delete it */
999 old->status.active = 0;
1000 terminate_connection(old);
1002 /* Tell the rest about the new host */
1004 for(node = connection_tree->head; node; node = node->next)
1006 p = (connection_t *)node->data;
1007 if(p->status.meta && p->status.active && p!=cl)
1008 send_del_host(p, old);
1014 /* Status and error notification routines */
1016 int send_status(connection_t *cl, int statusno, char *statusstring)
1020 statusstring = status_text[statusno];
1022 return send_request(cl, "%d %d %s", STATUS, statusno, statusstring);
1025 int status_h(connection_t *cl)
1028 char statusstring[MAX_STRING_SIZE];
1030 if(sscanf(cl->buffer, "%*d %d "MAX_STRING, &statusno, statusstring) != 2)
1032 syslog(LOG_ERR, _("Got bad STATUS from %s (%s)"),
1033 cl->name, cl->hostname);
1037 if(debug_lvl >= DEBUG_STATUS)
1039 syslog(LOG_NOTICE, _("Status message from %s (%s): %s: %s"),
1040 cl->name, cl->hostname, status_text[statusno], statusstring);
1047 int send_error(connection_t *cl, int err, char *errstring)
1051 errstring = strerror(err);
1052 return send_request(cl, "%d %d %s", ERROR, err, errstring);
1055 int error_h(connection_t *cl)
1058 char errorstring[MAX_STRING_SIZE];
1060 if(sscanf(cl->buffer, "%*d %d "MAX_STRING, &err, errorstring) != 2)
1062 syslog(LOG_ERR, _("Got bad ERROR from %s (%s)"),
1063 cl->name, cl->hostname);
1067 if(debug_lvl >= DEBUG_ERROR)
1069 syslog(LOG_NOTICE, _("Error message from %s (%s): %s: %s"),
1070 cl->name, cl->hostname, strerror(err), errorstring);
1073 terminate_connection(cl);
1078 int send_termreq(connection_t *cl)
1081 return send_request(cl, "%d", TERMREQ);
1084 int termreq_h(connection_t *cl)
1087 terminate_connection(cl);
1092 int send_ping(connection_t *cl)
1095 cl->status.pinged = 1;
1096 cl->last_ping_time = time(NULL);
1098 return send_request(cl, "%d", PING);
1101 int ping_h(connection_t *cl)
1104 return send_pong(cl);
1107 int send_pong(connection_t *cl)
1110 return send_request(cl, "%d", PONG);
1113 int pong_h(connection_t *cl)
1116 cl->status.pinged = 0;
1123 int send_key_changed(connection_t *from, connection_t *cl)
1128 for(node = connection_tree->head; node; node = node->next)
1130 p = (connection_t *)node->data;
1131 if(p != cl && p->status.meta && p->status.active)
1132 if(!(p->options & OPTION_INDIRECT) || from == myself)
1133 send_request(p, "%d %s", KEY_CHANGED, from->name);
1139 int key_changed_h(connection_t *cl)
1141 char from_id[MAX_STRING_SIZE];
1144 if(sscanf(cl->buffer, "%*d "MAX_STRING, from_id) != 1)
1146 syslog(LOG_ERR, _("Got bad KEY_CHANGED from %s (%s)"),
1147 cl->name, cl->hostname);
1151 if(!(from = lookup_id(from_id)))
1153 syslog(LOG_ERR, _("Got KEY_CHANGED from %s (%s) origin %s which does not exist in our connection list"),
1154 cl->name, cl->hostname, from_id);
1158 from->status.validkey = 0;
1159 from->status.waitingforkey = 0;
1161 send_key_changed(from, cl);
1166 int send_req_key(connection_t *from, connection_t *to)
1169 return send_request(to->nexthop, "%d %s %s", REQ_KEY,
1170 from->name, to->name);
1173 int req_key_h(connection_t *cl)
1175 char from_id[MAX_STRING_SIZE];
1176 char to_id[MAX_STRING_SIZE];
1177 connection_t *from, *to;
1180 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING, from_id, to_id) != 2)
1182 syslog(LOG_ERR, _("Got bad REQ_KEY from %s (%s)"),
1183 cl->name, cl->hostname);
1187 if(!(from = lookup_id(from_id)))
1189 syslog(LOG_ERR, _("Got REQ_KEY from %s (%s) origin %s which does not exist in our connection list"),
1190 cl->name, cl->hostname, from_id);
1194 /* Check if this key request is for us */
1196 if(!strcmp(to_id, myself->name))
1198 bin2hex(myself->cipher_pktkey, pktkey, myself->cipher_pktkeylength);
1199 pktkey[myself->cipher_pktkeylength*2] = '\0';
1200 send_ans_key(myself, from, pktkey);
1204 if(!(to = lookup_id(to_id)))
1206 syslog(LOG_ERR, _("Got REQ_KEY from %s (%s) destination %s which does not exist in our connection list"),
1207 cl->name, cl->hostname, to_id);
1211 if(to->status.validkey) /* Proxy keys */
1213 bin2hex(to->cipher_pktkey, pktkey, to->cipher_pktkeylength);
1214 pktkey[to->cipher_pktkeylength*2] = '\0';
1215 send_ans_key(to, from, pktkey);
1218 send_req_key(from, to);
1225 int send_ans_key(connection_t *from, connection_t *to, char *pktkey)
1228 return send_request(to->nexthop, "%d %s %s %s", ANS_KEY,
1229 from->name, to->name, pktkey);
1232 int ans_key_h(connection_t *cl)
1234 char from_id[MAX_STRING_SIZE];
1235 char to_id[MAX_STRING_SIZE];
1236 char pktkey[MAX_STRING_SIZE];
1238 connection_t *from, *to;
1240 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING, from_id, to_id, pktkey) != 3)
1242 syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s)"),
1243 cl->name, cl->hostname);
1247 if(!(from = lookup_id(from_id)))
1249 syslog(LOG_ERR, _("Got ANS_KEY from %s (%s) origin %s which does not exist in our connection list"),
1250 cl->name, cl->hostname, from_id);
1254 /* Check correctness of packet key */
1256 keylength = strlen(pktkey);
1258 if(keylength != from->cipher_pktkeylength*2)
1260 syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s) origin %s: invalid key length"),
1261 cl->name, cl->hostname, from->name);
1265 /* Forward it if necessary */
1267 if(strcmp(to_id, myself->name))
1269 if(!(to = lookup_id(to_id)))
1271 syslog(LOG_ERR, _("Got ANS_KEY from %s (%s) destination %s which does not exist in our connection list"),
1272 cl->name, cl->hostname, to_id);
1275 send_ans_key(from, to, pktkey);
1278 /* Update our copy of the origin's packet key */
1280 if(from->cipher_pktkey)
1281 free(from->cipher_pktkey);
1283 from->cipher_pktkey = xstrdup(pktkey);
1285 hex2bin(from->cipher_pktkey, from->cipher_pktkey, keylength);
1286 from->cipher_pktkey[keylength] = '\0';
1288 from->status.validkey = 1;
1289 from->status.waitingforkey = 0;
1296 int send_tcppacket(connection_t *cl, vpn_packet_t *packet)
1300 x = send_request(cl->nexthop, "%d %hd", PACKET, packet->len);
1305 return send_meta(cl->nexthop, packet->data, packet->len);
1308 int tcppacket_h(connection_t *cl)
1310 vpn_packet_t packet;
1314 if(sscanf(cl->buffer, "%*d %hd", packet.len) != 1)
1316 syslog(LOG_ERR, _("Got bad PACKET from %s (%s)"), cl->name, cl->hostname);
1327 x = read(cl->meta_socket, p, todo);
1332 syslog(LOG_NOTICE, _("Connection closed by %s (%s)"), cl->name, cl->hostname);
1337 syslog(LOG_ERR, _("Error during reception of PACKET from %s (%s): %m"), cl->name, cl->hostname);
1346 return receive_packet(cl, &packet);
1349 /* Jumptable for the request handlers */
1351 int (*request_handlers[])(connection_t*) = {
1352 id_h, challenge_h, chal_reply_h, metakey_h, ack_h,
1353 status_h, error_h, termreq_h,
1355 add_host_h, del_host_h,
1356 add_subnet_h, del_subnet_h,
1357 key_changed_h, req_key_h, ans_key_h,
1363 char (*request_name[]) = {
1364 "ID", "CHALLENGE", "CHAL_REPLY", "METAKEY", "ACK",
1365 "STATUS", "ERROR", "TERMREQ",
1367 "ADD_HOST", "DEL_HOST",
1368 "ADD_SUBNET", "DEL_SUBNET",
1369 "KEY_CHANGED", "REQ_KEY", "ANS_KEY",
1373 /* Status strings */
1375 char (*status_text[]) = {
1381 char (*error_text[]) = {