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.81 2001/02/25 19:09:43 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 return send_request(cl, "%d %s %d %lx %hd", ID, myself->name, myself->protocol_version, myself->options, myself->port);
194 int id_h(connection_t *cl)
197 unsigned short int port;
198 char name[MAX_STRING_SIZE];
201 if(sscanf(cl->buffer, "%*d "MAX_STRING" %d %lx %hd", name, &cl->protocol_version, &cl->options, &port) != 4)
203 syslog(LOG_ERR, _("Got bad ID from %s"), cl->hostname);
207 /* Check if version matches */
209 if(cl->protocol_version != myself->protocol_version)
211 syslog(LOG_ERR, _("Peer %s (%s) uses incompatible version %d"),
212 cl->name, cl->hostname, cl->protocol_version);
216 /* Check if identity is a valid name */
220 syslog(LOG_ERR, _("Peer %s uses invalid identity name"), cl->hostname);
224 /* Copy string to cl */
226 cl->name = xstrdup(name);
228 /* Load information about peer */
230 if(read_host_config(cl))
232 syslog(LOG_ERR, _("Peer %s had unknown identity (%s)"), cl->hostname, cl->name);
236 /* First check if the host we connected to is already in our
237 connection list. If so, we are probably making a loop, which
241 if(cl->status.outgoing)
243 if((old = lookup_id(cl->name)))
245 if(debug_lvl >= DEBUG_CONNECTIONS)
246 syslog(LOG_NOTICE, _("Uplink %s (%s) is already in our connection list"), cl->name, cl->hostname);
247 cl->status.outgoing = 0;
248 old->status.outgoing = 1;
249 terminate_connection(cl);
254 /* Now we can add the name to the id tree */
258 /* And uhr... cl->port just changed so we have to unlink it from the connection tree and re-insert... */
260 node = avl_unlink(connection_tree, cl);
262 avl_insert_node(connection_tree, node);
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 send_challenge(connection_t *cl)
279 /* CHECKME: what is most reasonable value for len? */
281 len = RSA_size(cl->rsa_key);
283 /* Allocate buffers for the challenge */
285 buffer = xmalloc(len*2+1);
288 free(cl->hischallenge);
290 cl->hischallenge = xmalloc(len);
292 /* Copy random data to the buffer */
294 RAND_bytes(cl->hischallenge, len);
299 bin2hex(cl->hischallenge, buffer, len);
300 buffer[len*2] = '\0';
303 /* Send the challenge */
305 x = send_request(cl, "%d %s", CHALLENGE, buffer);
311 int challenge_h(connection_t *cl)
313 char buffer[MAX_STRING_SIZE];
316 if(sscanf(cl->buffer, "%*d "MAX_STRING, buffer) != 1)
318 syslog(LOG_ERR, _("Got bad CHALLENGE from %s (%s)"), cl->name, cl->hostname);
322 len = RSA_size(myself->rsa_key);
324 /* Check if the length of the challenge is all right */
326 if(strlen(buffer) != len*2)
328 syslog(LOG_ERR, _("Intruder: wrong challenge length from %s (%s)"), cl->name, cl->hostname);
332 /* Allocate buffers for the challenge */
335 cl->mychallenge = xmalloc(len);
337 /* Convert the challenge from hexadecimal back to binary */
339 hex2bin(buffer,cl->mychallenge,len);
341 cl->allow_request = CHAL_REPLY;
343 /* Rest is done by send_chal_reply() */
345 return send_chal_reply(cl);
348 int send_chal_reply(connection_t *cl)
350 char hash[SHA_DIGEST_LENGTH*2+1];
354 syslog(LOG_ERR, _("Trying to send CHAL_REPLY to %s (%s) without a valid CHALLENGE"), cl->name, cl->hostname);
358 /* Calculate the hash from the challenge we received */
360 SHA1(cl->mychallenge, RSA_size(myself->rsa_key), hash);
362 /* Convert the hash to a hexadecimal formatted string */
364 bin2hex(hash,hash,SHA_DIGEST_LENGTH);
365 hash[SHA_DIGEST_LENGTH*2] = '\0';
370 return send_request(cl, "%d %s", CHAL_REPLY, hash);
373 int chal_reply_h(connection_t *cl)
375 char hishash[MAX_STRING_SIZE];
376 char myhash[SHA_DIGEST_LENGTH];
378 if(sscanf(cl->buffer, "%*d "MAX_STRING, hishash) != 1)
380 syslog(LOG_ERR, _("Got bad CHAL_REPLY from %s (%s)"), cl->name, cl->hostname);
384 /* Check if the length of the hash is all right */
386 if(strlen(hishash) != SHA_DIGEST_LENGTH*2)
388 syslog(LOG_ERR, _("Intruder: wrong challenge reply length from %s (%s)"), cl->name, cl->hostname);
392 /* Convert the hash to binary format */
394 hex2bin(hishash, hishash, SHA_DIGEST_LENGTH);
396 /* Calculate the hash from the challenge we sent */
398 SHA1(cl->hischallenge, RSA_size(cl->rsa_key), myhash);
400 /* Verify the incoming hash with the calculated hash */
402 if(memcmp(hishash, myhash, SHA_DIGEST_LENGTH))
404 syslog(LOG_ERR, _("Intruder: wrong challenge reply from %s (%s)"), cl->name, cl->hostname);
405 if(debug_lvl >= DEBUG_SCARY_THINGS)
407 bin2hex(myhash, hishash, SHA_DIGEST_LENGTH);
408 hishash[SHA_DIGEST_LENGTH*2] = '\0';
409 syslog(LOG_DEBUG, _("Expected challenge reply: %s"), hishash);
414 /* Identity has now been positively verified.
415 ack_h() handles the rest from now on.
421 int send_metakey(connection_t *cl)
426 len = RSA_size(cl->rsa_key);
428 /* Allocate buffers for the meta key */
430 buffer = xmalloc(len*2+1);
432 if(!cl->cipher_outkey)
433 cl->cipher_outkey = xmalloc(len);
435 if(!cl->cipher_outctx)
436 cl->cipher_outctx = xmalloc(sizeof(*cl->cipher_outctx));
438 /* Copy random data to the buffer */
440 RAND_bytes(cl->cipher_outkey, len);
442 cl->cipher_outkey[0] &= 0x7F; /* FIXME: Somehow if the first byte is more than 0xD0 or something like that, decryption fails... */
444 if(debug_lvl >= DEBUG_SCARY_THINGS)
446 bin2hex(cl->cipher_outkey, buffer, len);
447 buffer[len*2] = '\0';
448 syslog(LOG_DEBUG, _("Generated random meta key (unencrypted): %s"), buffer);
451 /* Encrypt the random data */
453 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 */
455 syslog(LOG_ERR, _("Error during encryption of meta key for %s (%s)"), cl->name, cl->hostname);
460 /* Convert the encrypted random data to a hexadecimal formatted string */
462 bin2hex(buffer, buffer, len);
463 buffer[len*2] = '\0';
465 /* Send the meta key */
467 x = send_request(cl, "%d %s", METAKEY, buffer);
470 /* Further outgoing requests are encrypted with the key we just generated */
472 EVP_EncryptInit(cl->cipher_outctx, EVP_bf_cfb(), cl->cipher_outkey, cl->cipher_outkey + EVP_bf_cfb()->key_len);
474 cl->status.encryptout = 1;
479 int metakey_h(connection_t *cl)
481 char buffer[MAX_STRING_SIZE];
484 if(sscanf(cl->buffer, "%*d "MAX_STRING, buffer) != 1)
486 syslog(LOG_ERR, _("Got bad METAKEY from %s (%s)"), cl->name, cl->hostname);
490 len = RSA_size(myself->rsa_key);
492 /* Check if the length of the meta key is all right */
494 if(strlen(buffer) != len*2)
496 syslog(LOG_ERR, _("Intruder: wrong meta key length from %s (%s)"), cl->name, cl->hostname);
500 /* Allocate buffers for the meta key */
502 if(!cl->cipher_inkey)
503 cl->cipher_inkey = xmalloc(len);
505 if(!cl->cipher_inctx)
506 cl->cipher_inctx = xmalloc(sizeof(*cl->cipher_inctx));
508 /* Convert the challenge from hexadecimal back to binary */
510 hex2bin(buffer,buffer,len);
512 /* Decrypt the meta key */
514 if(RSA_private_decrypt(len, buffer, cl->cipher_inkey, myself->rsa_key, RSA_NO_PADDING) != len) /* See challenge() */
516 syslog(LOG_ERR, _("Error during encryption of meta key for %s (%s)"), cl->name, cl->hostname);
520 if(debug_lvl >= DEBUG_SCARY_THINGS)
522 bin2hex(cl->cipher_inkey, buffer, len);
523 buffer[len*2] = '\0';
524 syslog(LOG_DEBUG, _("Received random meta key (unencrypted): %s"), buffer);
527 /* All incoming requests will now be encrypted. */
529 EVP_DecryptInit(cl->cipher_inctx, EVP_bf_cfb(), cl->cipher_inkey, cl->cipher_inkey + EVP_bf_cfb()->key_len);
531 cl->status.decryptin = 1;
533 cl->allow_request = CHALLENGE;
535 return send_challenge(cl);
538 int ack_h(connection_t *cl)
541 connection_t *old, *p;
543 avl_node_t *node, *node2;
545 /* Okay, before we active the connection, we check if there is another entry
546 in the connection list with the same name. If so, it presumably is an
547 old connection that has timed out but we don't know it yet.
550 while((old = lookup_id(cl->name)))
552 if(debug_lvl >= DEBUG_CONNECTIONS)
553 syslog(LOG_NOTICE, _("Removing old entry for %s at %s in favour of new connection from %s"),
554 cl->name, old->hostname, cl->hostname);
556 terminate_connection(old);
559 /* Activate this connection */
561 cl->allow_request = ALL;
562 cl->status.active = 1;
564 cl->cipher_pkttype = EVP_bf_cbc();
565 cl->cipher_pktkeylength = cl->cipher_pkttype->key_len + cl->cipher_pkttype->iv_len;
567 if(debug_lvl >= DEBUG_CONNECTIONS)
568 syslog(LOG_NOTICE, _("Connection with %s (%s) activated"), cl->name, cl->hostname);
571 /* Check some options */
573 if((cfg = get_config_val(cl->config, config_indirectdata)))
575 if(cfg->data.val == stupid_true)
576 cl->options |= OPTION_INDIRECT;
579 if((cfg = get_config_val(cl->config, config_tcponly)))
581 if(cfg->data.val == stupid_true)
582 cl->options |= OPTION_TCPONLY;
585 /* Send him our subnets */
587 for(node = myself->subnet_tree->head; node; node = node->next)
589 subnet = (subnet_t *)node->data;
590 send_add_subnet(cl, subnet);
592 /* And send him all the hosts and their subnets we know... */
594 for(node = connection_tree->head; node; node = node->next)
596 p = (connection_t *)node->data;
598 if(p != cl && p->status.active)
600 /* Notify others of this connection */
603 send_add_host(p, cl);
605 /* Notify new connection of everything we know */
607 send_add_host(cl, p);
609 for(node2 = p->subnet_tree->head; node2; node2 = node2->next)
611 subnet = (subnet_t *)node2->data;
612 send_add_subnet(cl, subnet);
620 /* Address and subnet information exchange */
622 int send_add_subnet(connection_t *cl, subnet_t *subnet)
628 if(cl->options & OPTION_INDIRECT)
629 owner = myself->name;
631 owner = subnet->owner->name;
633 x = send_request(cl, "%d %s %s", ADD_SUBNET,
634 owner, netstr = net2str(subnet));
640 int add_subnet_h(connection_t *cl)
642 char subnetstr[MAX_STRING_SIZE];
643 char name[MAX_STRING_SIZE];
644 connection_t *owner, *p;
648 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING, name, subnetstr) != 2)
650 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s)"), cl->name, cl->hostname);
654 /* Check if owner name is a valid */
658 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s): invalid identity name"), cl->name, cl->hostname);
662 /* Check if subnet string is valid */
664 if(!(subnet = str2net(subnetstr)))
666 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s): invalid subnet string"), cl->name, cl->hostname);
670 /* Check if somebody tries to add a subnet of ourself */
672 if(!strcmp(name, myself->name))
674 syslog(LOG_ERR, _("Warning: got ADD_SUBNET from %s (%s) for ourself, restarting"),
675 cl->name, cl->hostname);
680 /* Check if the owner of the new subnet is in the connection list */
682 if(!(owner = lookup_id(name)))
684 syslog(LOG_ERR, _("Got ADD_SUBNET for %s from %s (%s) which is not in our connection list"),
685 name, cl->name, cl->hostname);
689 /* If everything is correct, add the subnet to the list of the owner */
691 subnet_add(owner, subnet);
695 for(node = connection_tree->head; node; node = node->next)
697 p = (connection_t *)node->data;
698 if(p->status.meta && p->status.active && p!= cl)
699 send_add_subnet(p, subnet);
705 int send_del_subnet(connection_t *cl, subnet_t *subnet)
711 if(cl->options & OPTION_INDIRECT)
712 owner = myself->name;
714 owner = subnet->owner->name;
716 x = send_request(cl, "%d %s %s", DEL_SUBNET, owner, netstr = net2str(subnet));
722 int del_subnet_h(connection_t *cl)
724 char subnetstr[MAX_STRING_SIZE];
725 char name[MAX_STRING_SIZE];
726 connection_t *owner, *p;
730 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING, name, subnetstr) != 3)
732 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s)"), cl->name, cl->hostname);
736 /* Check if owner name is a valid */
740 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s): invalid identity name"), cl->name, cl->hostname);
744 /* Check if subnet string is valid */
746 if(!(subnet = str2net(subnetstr)))
748 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s): invalid subnet string"), cl->name, cl->hostname);
754 /* Check if somebody tries to add a subnet of ourself */
756 if(!strcmp(name, myself->name))
758 syslog(LOG_ERR, _("Warning: got DEL_SUBNET from %s (%s) for ourself, restarting"),
759 cl->name, cl->hostname);
764 /* Check if the owner of the new subnet is in the connection list */
766 if(!(owner = lookup_id(name)))
768 syslog(LOG_ERR, _("Got DEL_SUBNET for %s from %s (%s) which is not in our connection list"),
769 name, cl->name, cl->hostname);
773 /* If everything is correct, delete the subnet from the list of the owner */
779 for(node = connection_tree->head; node; node = node->next)
781 p = (connection_t *)node->data;
782 if(p->status.meta && p->status.active && p!= cl)
783 send_del_subnet(p, subnet);
789 /* New and closed connections notification */
791 int send_add_host(connection_t *cl, connection_t *other)
794 if(!(cl->options & OPTION_INDIRECT))
795 return send_request(cl, "%d %s %lx:%d %lx", ADD_HOST,
796 other->name, other->address, other->port, other->options);
799 int add_host_h(connection_t *cl)
801 connection_t *old, *new, *p;
802 char name[MAX_STRING_SIZE];
805 new = new_connection();
807 if(sscanf(cl->buffer, "%*d "MAX_STRING" %lx:%d %lx", name, &new->address, &new->port, &new->options) != 4)
809 syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s)"), cl->name, cl->hostname);
813 /* Check if identity is a valid name */
817 syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s): invalid identity name"), cl->name, cl->hostname);
818 free_connection(new);
822 /* Check if somebody tries to add ourself */
824 if(!strcmp(name, myself->name))
826 syslog(LOG_ERR, _("Warning: got ADD_HOST from %s (%s) for ourself, restarting"), cl->name, cl->hostname);
828 free_connection(new);
832 /* Fill in more of the new connection structure */
834 new->hostname = hostlookup(htonl(new->address));
836 /* Check if the new host already exists in the connnection list */
838 if((old = lookup_id(name)))
840 if((new->address == old->address) && (new->port == old->port))
842 if(debug_lvl >= DEBUG_CONNECTIONS)
843 syslog(LOG_NOTICE, _("Got duplicate ADD_HOST for %s (%s) from %s (%s)"),
844 old->name, old->hostname, name, new->hostname);
845 free_connection(new);
850 if(debug_lvl >= DEBUG_CONNECTIONS)
851 syslog(LOG_NOTICE, _("Removing old entry for %s (%s) in favour of new connection"),
852 old->name, old->hostname);
854 terminate_connection(old);
858 /* Hook it up into the connection */
860 new->name = xstrdup(name);
864 /* Tell the rest about the new host */
866 for(node = connection_tree->head; node; node = node->next)
868 p = (connection_t *)node->data;
869 if(p->status.meta && p->status.active && p!=cl)
870 send_add_host(p, new);
873 /* Fill in rest of connection structure */
876 new->status.active = 1;
877 new->cipher_pkttype = EVP_bf_cbc();
878 new->cipher_pktkeylength = cl->cipher_pkttype->key_len + cl->cipher_pkttype->iv_len;
883 int send_del_host(connection_t *cl, connection_t *other)
886 if(!(cl->options & OPTION_INDIRECT))
887 return send_request(cl, "%d %s %lx:%d %lx", DEL_HOST,
888 other->name, other->address, other->port, other->options);
891 int del_host_h(connection_t *cl)
893 char name[MAX_STRING_SIZE];
897 connection_t *old, *p;
900 if(sscanf(cl->buffer, "%*d "MAX_STRING" %lx:%d %lx", name, &address, &port, &options) != 4)
902 syslog(LOG_ERR, _("Got bad DEL_HOST from %s (%s)"),
903 cl->name, cl->hostname);
907 /* Check if identity is a valid name */
911 syslog(LOG_ERR, _("Got bad DEL_HOST from %s (%s): invalid identity name"), cl->name, cl->hostname);
915 /* Check if somebody tries to delete ourself */
917 if(!strcmp(name, myself->name))
919 syslog(LOG_ERR, _("Warning: got DEL_HOST from %s (%s) for ourself, restarting"),
920 cl->name, cl->hostname);
925 /* Check if the new host already exists in the connnection list */
927 if(!(old = lookup_id(name)))
929 syslog(LOG_ERR, _("Got DEL_HOST from %s (%s) for %s which is not in our connection list"),
930 name, cl->name, cl->hostname);
934 /* Check if the rest matches */
936 if(address!=old->address || port!=old->port || options!=old->options || cl!=old->nexthop)
938 syslog(LOG_WARNING, _("Got DEL_HOST from %s (%s) for %s which doesn't match"), cl->name, cl->hostname, old->name);
942 /* Ok, since EVERYTHING seems to check out all right, delete it */
944 old->status.active = 0;
945 terminate_connection(old);
947 /* Tell the rest about the new host */
949 for(node = connection_tree->head; node; node = node->next)
951 p = (connection_t *)node->data;
952 if(p->status.meta && p->status.active && p!=cl)
953 send_del_host(p, old);
959 /* Status and error notification routines */
961 int send_status(connection_t *cl, int statusno, char *statusstring)
965 statusstring = status_text[statusno];
967 return send_request(cl, "%d %d %s", STATUS, statusno, statusstring);
970 int status_h(connection_t *cl)
973 char statusstring[MAX_STRING_SIZE];
975 if(sscanf(cl->buffer, "%*d %d "MAX_STRING, &statusno, statusstring) != 2)
977 syslog(LOG_ERR, _("Got bad STATUS from %s (%s)"),
978 cl->name, cl->hostname);
982 if(debug_lvl >= DEBUG_STATUS)
984 syslog(LOG_NOTICE, _("Status message from %s (%s): %s: %s"),
985 cl->name, cl->hostname, status_text[statusno], statusstring);
992 int send_error(connection_t *cl, int err, char *errstring)
996 errstring = strerror(err);
997 return send_request(cl, "%d %d %s", ERROR, err, errstring);
1000 int error_h(connection_t *cl)
1003 char errorstring[MAX_STRING_SIZE];
1005 if(sscanf(cl->buffer, "%*d %d "MAX_STRING, &err, errorstring) != 2)
1007 syslog(LOG_ERR, _("Got bad ERROR from %s (%s)"),
1008 cl->name, cl->hostname);
1012 if(debug_lvl >= DEBUG_ERROR)
1014 syslog(LOG_NOTICE, _("Error message from %s (%s): %s: %s"),
1015 cl->name, cl->hostname, strerror(err), errorstring);
1018 terminate_connection(cl);
1023 int send_termreq(connection_t *cl)
1026 return send_request(cl, "%d", TERMREQ);
1029 int termreq_h(connection_t *cl)
1032 terminate_connection(cl);
1037 int send_ping(connection_t *cl)
1040 cl->status.pinged = 1;
1041 cl->last_ping_time = time(NULL);
1043 return send_request(cl, "%d", PING);
1046 int ping_h(connection_t *cl)
1049 return send_pong(cl);
1052 int send_pong(connection_t *cl)
1055 return send_request(cl, "%d", PONG);
1058 int pong_h(connection_t *cl)
1061 cl->status.pinged = 0;
1068 int send_key_changed(connection_t *from, connection_t *cl)
1073 for(node = connection_tree->head; node; node = node->next)
1075 p = (connection_t *)node->data;
1076 if(p != cl && p->status.meta && p->status.active)
1077 if(!(p->options & OPTION_INDIRECT) || from == myself)
1078 send_request(p, "%d %s", KEY_CHANGED, from->name);
1084 int key_changed_h(connection_t *cl)
1086 char from_id[MAX_STRING_SIZE];
1089 if(sscanf(cl->buffer, "%*d "MAX_STRING, from_id) != 1)
1091 syslog(LOG_ERR, _("Got bad KEY_CHANGED from %s (%s)"),
1092 cl->name, cl->hostname);
1096 if(!(from = lookup_id(from_id)))
1098 syslog(LOG_ERR, _("Got KEY_CHANGED from %s (%s) origin %s which does not exist in our connection list"),
1099 cl->name, cl->hostname, from_id);
1103 from->status.validkey = 0;
1104 from->status.waitingforkey = 0;
1106 send_key_changed(from, cl);
1111 int send_req_key(connection_t *from, connection_t *to)
1114 return send_request(to->nexthop, "%d %s %s", REQ_KEY,
1115 from->name, to->name);
1118 int req_key_h(connection_t *cl)
1120 char from_id[MAX_STRING_SIZE];
1121 char to_id[MAX_STRING_SIZE];
1122 connection_t *from, *to;
1125 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING, from_id, to_id) != 2)
1127 syslog(LOG_ERR, _("Got bad REQ_KEY from %s (%s)"),
1128 cl->name, cl->hostname);
1132 if(!(from = lookup_id(from_id)))
1134 syslog(LOG_ERR, _("Got REQ_KEY from %s (%s) origin %s which does not exist in our connection list"),
1135 cl->name, cl->hostname, from_id);
1139 /* Check if this key request is for us */
1141 if(!strcmp(to_id, myself->name))
1143 bin2hex(myself->cipher_pktkey, pktkey, myself->cipher_pktkeylength);
1144 pktkey[myself->cipher_pktkeylength*2] = '\0';
1145 send_ans_key(myself, from, pktkey);
1149 if(!(to = lookup_id(to_id)))
1151 syslog(LOG_ERR, _("Got REQ_KEY from %s (%s) destination %s which does not exist in our connection list"),
1152 cl->name, cl->hostname, to_id);
1156 if(to->status.validkey) /* Proxy keys */
1158 bin2hex(to->cipher_pktkey, pktkey, to->cipher_pktkeylength);
1159 pktkey[to->cipher_pktkeylength*2] = '\0';
1160 send_ans_key(to, from, pktkey);
1163 send_req_key(from, to);
1170 int send_ans_key(connection_t *from, connection_t *to, char *pktkey)
1173 return send_request(to->nexthop, "%d %s %s %s", ANS_KEY,
1174 from->name, to->name, pktkey);
1177 int ans_key_h(connection_t *cl)
1179 char from_id[MAX_STRING_SIZE];
1180 char to_id[MAX_STRING_SIZE];
1181 char pktkey[MAX_STRING_SIZE];
1183 connection_t *from, *to;
1185 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING, from_id, to_id, pktkey) != 3)
1187 syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s)"),
1188 cl->name, cl->hostname);
1192 if(!(from = lookup_id(from_id)))
1194 syslog(LOG_ERR, _("Got ANS_KEY from %s (%s) origin %s which does not exist in our connection list"),
1195 cl->name, cl->hostname, from_id);
1199 /* Check correctness of packet key */
1201 keylength = strlen(pktkey);
1203 if(keylength != from->cipher_pktkeylength*2)
1205 syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s) origin %s: invalid key length"),
1206 cl->name, cl->hostname, from->name);
1210 /* Forward it if necessary */
1212 if(strcmp(to_id, myself->name))
1214 if(!(to = lookup_id(to_id)))
1216 syslog(LOG_ERR, _("Got ANS_KEY from %s (%s) destination %s which does not exist in our connection list"),
1217 cl->name, cl->hostname, to_id);
1220 send_ans_key(from, to, pktkey);
1223 /* Update our copy of the origin's packet key */
1225 if(from->cipher_pktkey)
1226 free(from->cipher_pktkey);
1228 from->cipher_pktkey = xstrdup(pktkey);
1230 hex2bin(from->cipher_pktkey, from->cipher_pktkey, keylength);
1231 from->cipher_pktkey[keylength] = '\0';
1233 from->status.validkey = 1;
1234 from->status.waitingforkey = 0;
1241 int send_tcppacket(connection_t *cl, vpn_packet_t *packet)
1245 x = send_request(cl->nexthop, "%d %hd", PACKET, packet->len);
1250 return send_meta(cl->nexthop, packet->data, packet->len);
1253 int tcppacket_h(connection_t *cl)
1255 vpn_packet_t packet;
1259 if(sscanf(cl->buffer, "%*d %hd", packet.len) != 1)
1261 syslog(LOG_ERR, _("Got bad PACKET from %s (%s)"), cl->name, cl->hostname);
1272 x = read(cl->meta_socket, p, todo);
1277 syslog(LOG_NOTICE, _("Connection closed by %s (%s)"), cl->name, cl->hostname);
1282 syslog(LOG_ERR, _("Error during reception of PACKET from %s (%s): %m"), cl->name, cl->hostname);
1291 return receive_packet(cl, &packet);
1294 /* Jumptable for the request handlers */
1296 int (*request_handlers[])(connection_t*) = {
1297 id_h, metakey_h, challenge_h, chal_reply_h,
1298 status_h, error_h, termreq_h,
1300 add_host_h, del_host_h,
1301 add_subnet_h, del_subnet_h,
1302 key_changed_h, req_key_h, ans_key_h,
1308 char (*request_name[]) = {
1309 "ID", "METAKEY", "CHALLENGE", "CHAL_REPLY",
1310 "STATUS", "ERROR", "TERMREQ",
1312 "ADD_HOST", "DEL_HOST",
1313 "ADD_SUBNET", "DEL_SUBNET",
1314 "KEY_CHANGED", "REQ_KEY", "ANS_KEY",
1318 /* Status strings */
1320 char (*status_text[]) = {
1326 char (*error_text[]) = {