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.91 2001/05/25 11:54:28 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 */
217 cl->name = xstrdup(name);
219 /* Load information about peer */
221 if(read_host_config(cl))
223 syslog(LOG_ERR, _("Peer %s had unknown identity (%s)"), cl->hostname, cl->name);
227 /* First check if the host we connected to is already in our
228 connection list. If so, we are probably making a loop, which
232 if(cl->status.outgoing)
234 if((old = lookup_id(cl->name)))
236 if(debug_lvl >= DEBUG_CONNECTIONS)
237 syslog(LOG_NOTICE, _("Uplink %s (%s) is already in our connection list"), cl->name, cl->hostname);
238 cl->status.outgoing = 0;
239 old->status.outgoing = 1;
240 terminate_connection(cl);
245 /* Now we can add the name to the id tree */
249 /* And uhr... cl->port just changed so we have to unlink it from the connection tree and re-insert... */
251 node = avl_unlink(connection_tree, cl);
253 avl_insert_node(connection_tree, node);
255 /* Read in the public key, so that we can send a metakey */
257 if(read_rsa_public_key(cl))
260 cl->allow_request = METAKEY;
262 return send_metakey(cl);
265 int ack_h(connection_t *cl)
268 connection_t *old, *p;
270 avl_node_t *node, *node2;
272 /* Okay, before we active the connection, we check if there is another entry
273 in the connection list with the same name. If so, it presumably is an
274 old connection that has timed out but we don't know it yet.
277 while((old = lookup_id(cl->name)))
279 if(debug_lvl >= DEBUG_CONNECTIONS)
280 syslog(LOG_NOTICE, _("Removing old entry for %s at %s in favour of new connection from %s"),
281 cl->name, old->hostname, cl->hostname);
283 terminate_connection(old);
286 /* Activate this connection */
288 cl->allow_request = ALL;
289 cl->status.active = 1;
291 cl->cipher_pkttype = EVP_bf_cbc();
292 cl->cipher_pktkeylength = cl->cipher_pkttype->key_len + cl->cipher_pkttype->iv_len;
294 if(debug_lvl >= DEBUG_CONNECTIONS)
295 syslog(LOG_NOTICE, _("Connection with %s (%s) activated"), cl->name, cl->hostname);
298 /* Check some options */
300 if((cfg = get_config_val(cl->config, config_indirectdata)))
302 if(cfg->data.val == stupid_true)
303 cl->options |= OPTION_INDIRECT;
306 if((cfg = get_config_val(cl->config, config_tcponly)))
308 if(cfg->data.val == stupid_true)
309 cl->options |= OPTION_TCPONLY;
312 /* Send him our subnets */
314 for(node = myself->subnet_tree->head; node; node = node->next)
316 subnet = (subnet_t *)node->data;
317 send_add_subnet(cl, subnet);
320 /* And send him all the hosts and their subnets we know... */
322 for(node = connection_tree->head; node; node = node->next)
324 p = (connection_t *)node->data;
326 if(p != cl && p->status.active)
328 /* Notify others of this connection */
331 send_add_host(p, cl);
333 /* Notify new connection of everything we know */
335 send_add_host(cl, p);
337 for(node2 = p->subnet_tree->head; node2; node2 = node2->next)
339 subnet = (subnet_t *)node2->data;
340 send_add_subnet(cl, subnet);
348 int send_challenge(connection_t *cl)
353 /* CHECKME: what is most reasonable value for len? */
355 len = RSA_size(cl->rsa_key);
357 /* Allocate buffers for the challenge */
359 buffer = xmalloc(len*2+1);
362 free(cl->hischallenge);
364 cl->hischallenge = xmalloc(len);
366 /* Copy random data to the buffer */
368 RAND_bytes(cl->hischallenge, len);
373 bin2hex(cl->hischallenge, buffer, len);
374 buffer[len*2] = '\0';
377 /* Send the challenge */
379 x = send_request(cl, "%d %s", CHALLENGE, buffer);
385 int challenge_h(connection_t *cl)
387 char buffer[MAX_STRING_SIZE];
390 if(sscanf(cl->buffer, "%*d "MAX_STRING, buffer) != 1)
392 syslog(LOG_ERR, _("Got bad CHALLENGE from %s (%s)"), cl->name, cl->hostname);
396 len = RSA_size(myself->rsa_key);
398 /* Check if the length of the challenge is all right */
400 if(strlen(buffer) != len*2)
402 syslog(LOG_ERR, _("Intruder: wrong challenge length from %s (%s)"), cl->name, cl->hostname);
406 /* Allocate buffers for the challenge */
409 cl->mychallenge = xmalloc(len);
411 /* Convert the challenge from hexadecimal back to binary */
413 hex2bin(buffer,cl->mychallenge,len);
415 cl->allow_request = CHAL_REPLY;
417 /* Rest is done by send_chal_reply() */
419 return send_chal_reply(cl);
422 int send_chal_reply(connection_t *cl)
424 char hash[SHA_DIGEST_LENGTH*2+1];
428 syslog(LOG_ERR, _("Trying to send CHAL_REPLY to %s (%s) without a valid CHALLENGE"), cl->name, cl->hostname);
432 /* Calculate the hash from the challenge we received */
434 SHA1(cl->mychallenge, RSA_size(myself->rsa_key), hash);
436 /* Convert the hash to a hexadecimal formatted string */
438 bin2hex(hash,hash,SHA_DIGEST_LENGTH);
439 hash[SHA_DIGEST_LENGTH*2] = '\0';
444 return send_request(cl, "%d %s", CHAL_REPLY, hash);
447 int chal_reply_h(connection_t *cl)
449 char hishash[MAX_STRING_SIZE];
450 char myhash[SHA_DIGEST_LENGTH];
452 if(sscanf(cl->buffer, "%*d "MAX_STRING, hishash) != 1)
454 syslog(LOG_ERR, _("Got bad CHAL_REPLY from %s (%s)"), cl->name, cl->hostname);
458 /* Check if the length of the hash is all right */
460 if(strlen(hishash) != SHA_DIGEST_LENGTH*2)
462 syslog(LOG_ERR, _("Intruder: wrong challenge reply length from %s (%s)"), cl->name, cl->hostname);
466 /* Convert the hash to binary format */
468 hex2bin(hishash, hishash, SHA_DIGEST_LENGTH);
470 /* Calculate the hash from the challenge we sent */
472 SHA1(cl->hischallenge, RSA_size(cl->rsa_key), myhash);
474 /* Verify the incoming hash with the calculated hash */
476 if(memcmp(hishash, myhash, SHA_DIGEST_LENGTH))
478 syslog(LOG_ERR, _("Intruder: wrong challenge reply from %s (%s)"), cl->name, cl->hostname);
479 if(debug_lvl >= DEBUG_SCARY_THINGS)
481 bin2hex(myhash, hishash, SHA_DIGEST_LENGTH);
482 hishash[SHA_DIGEST_LENGTH*2] = '\0';
483 syslog(LOG_DEBUG, _("Expected challenge reply: %s"), hishash);
488 /* Identity has now been positively verified.
489 ack_h() handles the rest from now on.
495 int send_metakey(connection_t *cl)
500 len = RSA_size(cl->rsa_key);
502 /* Allocate buffers for the meta key */
504 buffer = xmalloc(len*2+1);
506 if(!cl->cipher_outkey)
507 cl->cipher_outkey = xmalloc(len);
509 if(!cl->cipher_outctx)
510 cl->cipher_outctx = xmalloc(sizeof(*cl->cipher_outctx));
512 /* Copy random data to the buffer */
514 RAND_bytes(cl->cipher_outkey, len);
516 /* The message we send must be smaller than the modulus of the RSA key.
517 By definition, for a key of k bits, the following formula holds:
519 2^(k-1) <= modulus < 2^(k)
521 Where ^ means "to the power of", not "xor".
522 This means that to be sure, we must choose our message < 2^(k-1).
523 This can be done by setting the most significant bit to zero.
526 cl->cipher_outkey[0] &= 0x7F;
528 if(debug_lvl >= DEBUG_SCARY_THINGS)
530 bin2hex(cl->cipher_outkey, buffer, len);
531 buffer[len*2] = '\0';
532 syslog(LOG_DEBUG, _("Generated random meta key (unencrypted): %s"), buffer);
535 /* Encrypt the random data
537 We do not use one of the PKCS padding schemes here.
538 This is allowed, because we encrypt a totally random string
539 with a length equal to that of the modulus of the RSA key.
542 if(RSA_public_encrypt(len, cl->cipher_outkey, buffer, cl->rsa_key, RSA_NO_PADDING) != len)
544 syslog(LOG_ERR, _("Error during encryption of meta key for %s (%s)"), cl->name, cl->hostname);
549 /* Convert the encrypted random data to a hexadecimal formatted string */
551 bin2hex(buffer, buffer, len);
552 buffer[len*2] = '\0';
554 /* Send the meta key */
556 x = send_request(cl, "%d %s", METAKEY, buffer);
559 /* Further outgoing requests are encrypted with the key we just generated */
561 EVP_EncryptInit(cl->cipher_outctx, EVP_bf_cfb(),
562 cl->cipher_outkey + len - EVP_bf_cfb()->key_len,
563 cl->cipher_outkey + len - EVP_bf_cfb()->key_len - EVP_bf_cfb()->iv_len);
565 cl->status.encryptout = 1;
570 int metakey_h(connection_t *cl)
572 char buffer[MAX_STRING_SIZE];
575 if(sscanf(cl->buffer, "%*d "MAX_STRING, buffer) != 1)
577 syslog(LOG_ERR, _("Got bad METAKEY from %s (%s)"), cl->name, cl->hostname);
581 len = RSA_size(myself->rsa_key);
583 /* Check if the length of the meta key is all right */
585 if(strlen(buffer) != len*2)
587 syslog(LOG_ERR, _("Intruder: wrong meta key length from %s (%s)"), cl->name, cl->hostname);
591 /* Allocate buffers for the meta key */
593 if(!cl->cipher_inkey)
594 cl->cipher_inkey = xmalloc(len);
596 if(!cl->cipher_inctx)
597 cl->cipher_inctx = xmalloc(sizeof(*cl->cipher_inctx));
599 /* Convert the challenge from hexadecimal back to binary */
601 hex2bin(buffer,buffer,len);
603 /* Decrypt the meta key */
605 if(RSA_private_decrypt(len, buffer, cl->cipher_inkey, myself->rsa_key, RSA_NO_PADDING) != len) /* See challenge() */
607 syslog(LOG_ERR, _("Error during encryption of meta key for %s (%s)"), cl->name, cl->hostname);
611 if(debug_lvl >= DEBUG_SCARY_THINGS)
613 bin2hex(cl->cipher_inkey, buffer, len);
614 buffer[len*2] = '\0';
615 syslog(LOG_DEBUG, _("Received random meta key (unencrypted): %s"), buffer);
618 /* All incoming requests will now be encrypted. */
620 EVP_DecryptInit(cl->cipher_inctx, EVP_bf_cfb(),
621 cl->cipher_inkey + len - EVP_bf_cfb()->key_len,
622 cl->cipher_inkey + len - EVP_bf_cfb()->key_len - EVP_bf_cfb()->iv_len);
624 cl->status.decryptin = 1;
626 cl->allow_request = CHALLENGE;
628 return send_challenge(cl);
631 /* Address and subnet information exchange */
633 int send_add_subnet(connection_t *cl, subnet_t *subnet)
639 if((cl->options | myself->options | subnet->owner->options) & OPTION_INDIRECT)
640 owner = myself->name;
642 owner = subnet->owner->name;
644 x = send_request(cl, "%d %s %s", ADD_SUBNET,
645 owner, netstr = net2str(subnet));
651 int add_subnet_h(connection_t *cl)
653 char subnetstr[MAX_STRING_SIZE];
654 char name[MAX_STRING_SIZE];
655 connection_t *owner, *p;
659 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING, name, subnetstr) != 2)
661 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s)"), cl->name, cl->hostname);
665 /* Check if owner name is a valid */
669 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s): invalid identity name"), cl->name, cl->hostname);
673 /* Check if subnet string is valid */
675 if(!(subnet = str2net(subnetstr)))
677 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s): invalid subnet string"), cl->name, cl->hostname);
681 /* Check if somebody tries to add a subnet of ourself */
683 if(!strcmp(name, myself->name))
685 syslog(LOG_ERR, _("Warning: got ADD_SUBNET from %s (%s) for ourself, restarting"),
686 cl->name, cl->hostname);
691 /* Check if the owner of the new subnet is in the connection list */
693 if(!(owner = lookup_id(name)))
695 syslog(LOG_ERR, _("Got ADD_SUBNET for %s from %s (%s) which is not in our connection list"),
696 name, cl->name, cl->hostname);
700 /* If everything is correct, add the subnet to the list of the owner */
702 subnet_add(owner, subnet);
706 for(node = connection_tree->head; node; node = node->next)
708 p = (connection_t *)node->data;
709 if(p->status.meta && p->status.active && p!= cl)
710 send_add_subnet(p, subnet);
716 int send_del_subnet(connection_t *cl, subnet_t *subnet)
722 if(cl->options & OPTION_INDIRECT)
723 owner = myself->name;
725 owner = subnet->owner->name;
727 x = send_request(cl, "%d %s %s", DEL_SUBNET, owner, netstr = net2str(subnet));
733 int del_subnet_h(connection_t *cl)
735 char subnetstr[MAX_STRING_SIZE];
736 char name[MAX_STRING_SIZE];
737 connection_t *owner, *p;
741 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING, name, subnetstr) != 3)
743 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s)"), cl->name, cl->hostname);
747 /* Check if owner name is a valid */
751 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s): invalid identity name"), cl->name, cl->hostname);
755 /* Check if subnet string is valid */
757 if(!(subnet = str2net(subnetstr)))
759 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s): invalid subnet string"), cl->name, cl->hostname);
765 /* Check if somebody tries to add a subnet of ourself */
767 if(!strcmp(name, myself->name))
769 syslog(LOG_ERR, _("Warning: got DEL_SUBNET from %s (%s) for ourself, restarting"),
770 cl->name, cl->hostname);
775 /* Check if the owner of the new subnet is in the connection list */
777 if(!(owner = lookup_id(name)))
779 syslog(LOG_ERR, _("Got DEL_SUBNET for %s from %s (%s) which is not in our connection list"),
780 name, cl->name, cl->hostname);
784 /* If everything is correct, delete the subnet from the list of the owner */
790 for(node = connection_tree->head; node; node = node->next)
792 p = (connection_t *)node->data;
793 if(p->status.meta && p->status.active && p!= cl)
794 send_del_subnet(p, subnet);
800 /* New and closed connections notification */
802 int send_add_host(connection_t *cl, connection_t *other)
805 if(!((cl->options | myself->options | other->options) & OPTION_INDIRECT))
806 return send_request(cl, "%d %s %lx:%d %lx", ADD_HOST,
807 other->name, other->address, other->port, other->options);
812 int add_host_h(connection_t *cl)
814 connection_t *old, *new, *p;
815 char name[MAX_STRING_SIZE];
818 new = new_connection();
820 if(sscanf(cl->buffer, "%*d "MAX_STRING" %lx:%hd %lx", name, &new->address, &new->port, &new->options) != 4)
822 syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s)"), cl->name, cl->hostname);
826 /* Check if identity is a valid name */
830 syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s): invalid identity name"), cl->name, cl->hostname);
831 free_connection(new);
835 /* Check if somebody tries to add ourself */
837 if(!strcmp(name, myself->name))
839 syslog(LOG_ERR, _("Warning: got ADD_HOST from %s (%s) for ourself, restarting"), cl->name, cl->hostname);
841 free_connection(new);
845 /* Fill in more of the new connection structure */
847 new->hostname = hostlookup(htonl(new->address));
849 /* Check if the new host already exists in the connnection list */
851 if((old = lookup_id(name)))
853 if((new->address == old->address) && (new->port == old->port))
855 if(debug_lvl >= DEBUG_CONNECTIONS)
856 syslog(LOG_NOTICE, _("Got duplicate ADD_HOST for %s (%s) from %s (%s)"),
857 old->name, old->hostname, name, new->hostname);
858 free_connection(new);
863 if(debug_lvl >= DEBUG_CONNECTIONS)
864 syslog(LOG_NOTICE, _("Removing old entry for %s (%s) in favour of new connection"),
865 old->name, old->hostname);
867 terminate_connection(old);
871 /* Hook it up into the connection */
873 new->name = xstrdup(name);
877 /* Tell the rest about the new host */
879 for(node = connection_tree->head; node; node = node->next)
881 p = (connection_t *)node->data;
882 if(p->status.meta && p->status.active && p!=cl)
883 send_add_host(p, new);
886 /* Fill in rest of connection structure */
889 new->status.active = 1;
890 new->cipher_pkttype = EVP_bf_cbc();
891 new->cipher_pktkeylength = cl->cipher_pkttype->key_len + cl->cipher_pkttype->iv_len;
896 int send_del_host(connection_t *cl, connection_t *other)
899 if(!((cl->options | myself->options) & OPTION_INDIRECT))
900 return send_request(cl, "%d %s %lx:%d %lx", DEL_HOST,
901 other->name, other->address, other->port, other->options);
906 int del_host_h(connection_t *cl)
908 char name[MAX_STRING_SIZE];
912 connection_t *old, *p;
915 if(sscanf(cl->buffer, "%*d "MAX_STRING" %lx:%hd %lx", name, &address, &port, &options) != 4)
917 syslog(LOG_ERR, _("Got bad DEL_HOST from %s (%s)"),
918 cl->name, cl->hostname);
922 /* Check if identity is a valid name */
926 syslog(LOG_ERR, _("Got bad DEL_HOST from %s (%s): invalid identity name"), cl->name, cl->hostname);
930 /* Check if somebody tries to delete ourself */
932 if(!strcmp(name, myself->name))
934 syslog(LOG_ERR, _("Warning: got DEL_HOST from %s (%s) for ourself, restarting"),
935 cl->name, cl->hostname);
940 /* Check if the new host already exists in the connnection list */
942 if(!(old = lookup_id(name)))
944 syslog(LOG_ERR, _("Got DEL_HOST from %s (%s) for %s which is not in our connection list"),
945 name, cl->name, cl->hostname);
949 /* Check if the rest matches */
951 if(address!=old->address || port!=old->port || options!=old->options || cl!=old->nexthop)
953 syslog(LOG_WARNING, _("Got DEL_HOST from %s (%s) for %s which doesn't match"), cl->name, cl->hostname, old->name);
957 /* Ok, since EVERYTHING seems to check out all right, delete it */
959 old->status.active = 0;
960 terminate_connection(old);
962 /* Tell the rest about the new host */
964 for(node = connection_tree->head; node; node = node->next)
966 p = (connection_t *)node->data;
967 if(p->status.meta && p->status.active && p!=cl)
968 send_del_host(p, old);
974 /* Status and error notification routines */
976 int send_status(connection_t *cl, int statusno, char *statusstring)
980 statusstring = status_text[statusno];
982 return send_request(cl, "%d %d %s", STATUS, statusno, statusstring);
985 int status_h(connection_t *cl)
988 char statusstring[MAX_STRING_SIZE];
990 if(sscanf(cl->buffer, "%*d %d "MAX_STRING, &statusno, statusstring) != 2)
992 syslog(LOG_ERR, _("Got bad STATUS from %s (%s)"),
993 cl->name, cl->hostname);
997 if(debug_lvl >= DEBUG_STATUS)
999 syslog(LOG_NOTICE, _("Status message from %s (%s): %s: %s"),
1000 cl->name, cl->hostname, status_text[statusno], statusstring);
1007 int send_error(connection_t *cl, int err, char *errstring)
1011 errstring = strerror(err);
1012 return send_request(cl, "%d %d %s", ERROR, err, errstring);
1015 int error_h(connection_t *cl)
1018 char errorstring[MAX_STRING_SIZE];
1020 if(sscanf(cl->buffer, "%*d %d "MAX_STRING, &err, errorstring) != 2)
1022 syslog(LOG_ERR, _("Got bad ERROR from %s (%s)"),
1023 cl->name, cl->hostname);
1027 if(debug_lvl >= DEBUG_ERROR)
1029 syslog(LOG_NOTICE, _("Error message from %s (%s): %s: %s"),
1030 cl->name, cl->hostname, strerror(err), errorstring);
1033 terminate_connection(cl);
1038 int send_termreq(connection_t *cl)
1041 return send_request(cl, "%d", TERMREQ);
1044 int termreq_h(connection_t *cl)
1047 terminate_connection(cl);
1052 int send_ping(connection_t *cl)
1054 char salt[SALTLEN*2+1];
1056 cl->status.pinged = 1;
1057 cl->last_ping_time = time(NULL);
1058 RAND_bytes(salt, SALTLEN);
1059 bin2hex(salt, salt, SALTLEN);
1060 salt[SALTLEN*2] = '\0';
1062 return send_request(cl, "%d %s", PING, salt);
1065 int ping_h(connection_t *cl)
1068 return send_pong(cl);
1071 int send_pong(connection_t *cl)
1073 char salt[SALTLEN*2+1];
1075 RAND_bytes(salt, SALTLEN);
1076 bin2hex(salt, salt, SALTLEN);
1077 salt[SALTLEN*2] = '\0';
1079 return send_request(cl, "%d %s", PONG, salt);
1082 int pong_h(connection_t *cl)
1085 cl->status.pinged = 0;
1092 int send_key_changed(connection_t *from, connection_t *cl)
1097 /* Only send this message if some other daemon requested our key previously.
1098 This reduces unnecessary key_changed broadcasts.
1103 for(node = connection_tree->head; node; node = node->next)
1105 p = (connection_t *)node->data;
1106 if(p != cl && p->status.meta && p->status.active)
1107 if(!(p->options & OPTION_INDIRECT) || from == myself)
1108 send_request(p, "%d %s", KEY_CHANGED, from->name);
1116 int key_changed_h(connection_t *cl)
1118 char from_id[MAX_STRING_SIZE];
1121 if(sscanf(cl->buffer, "%*d "MAX_STRING, from_id) != 1)
1123 syslog(LOG_ERR, _("Got bad KEY_CHANGED from %s (%s)"),
1124 cl->name, cl->hostname);
1128 if(!(from = lookup_id(from_id)))
1130 syslog(LOG_ERR, _("Got KEY_CHANGED from %s (%s) origin %s which does not exist in our connection list"),
1131 cl->name, cl->hostname, from_id);
1135 from->status.validkey = 0;
1136 from->status.waitingforkey = 0;
1138 if(!(from->options | cl->options | myself->options) & OPTION_INDIRECT)
1139 send_key_changed(from, cl);
1144 int send_req_key(connection_t *from, connection_t *to)
1147 return send_request(to->nexthop, "%d %s %s", REQ_KEY,
1148 from->name, to->name);
1151 int req_key_h(connection_t *cl)
1153 char from_id[MAX_STRING_SIZE];
1154 char to_id[MAX_STRING_SIZE];
1155 connection_t *from, *to;
1158 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING, from_id, to_id) != 2)
1160 syslog(LOG_ERR, _("Got bad REQ_KEY from %s (%s)"),
1161 cl->name, cl->hostname);
1165 if(!(from = lookup_id(from_id)))
1167 syslog(LOG_ERR, _("Got REQ_KEY from %s (%s) origin %s which does not exist in our connection list"),
1168 cl->name, cl->hostname, from_id);
1172 /* Check if this key request is for us */
1174 if(!strcmp(to_id, myself->name)) /* Yes, send our own key back */
1176 bin2hex(myself->cipher_pktkey, pktkey, myself->cipher_pktkeylength);
1177 pktkey[myself->cipher_pktkeylength*2] = '\0';
1178 send_ans_key(myself, from, pktkey);
1183 if(!(to = lookup_id(to_id)))
1185 syslog(LOG_ERR, _("Got REQ_KEY from %s (%s) destination %s which does not exist in our connection list"),
1186 cl->name, cl->hostname, to_id);
1190 if(to->status.validkey) /* Proxy keys */
1192 bin2hex(to->cipher_pktkey, pktkey, to->cipher_pktkeylength);
1193 pktkey[to->cipher_pktkeylength*2] = '\0';
1194 send_ans_key(to, from, pktkey);
1197 send_req_key(from, to);
1204 int send_ans_key(connection_t *from, connection_t *to, char *pktkey)
1207 return send_request(to->nexthop, "%d %s %s %s", ANS_KEY,
1208 from->name, to->name, pktkey);
1211 int ans_key_h(connection_t *cl)
1213 char from_id[MAX_STRING_SIZE];
1214 char to_id[MAX_STRING_SIZE];
1215 char pktkey[MAX_STRING_SIZE];
1217 connection_t *from, *to;
1219 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING, from_id, to_id, pktkey) != 3)
1221 syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s)"),
1222 cl->name, cl->hostname);
1226 if(!(from = lookup_id(from_id)))
1228 syslog(LOG_ERR, _("Got ANS_KEY from %s (%s) origin %s which does not exist in our connection list"),
1229 cl->name, cl->hostname, from_id);
1233 /* Check correctness of packet key */
1235 keylength = strlen(pktkey);
1237 if(keylength != from->cipher_pktkeylength*2)
1239 syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s) origin %s: invalid key length"),
1240 cl->name, cl->hostname, from->name);
1244 /* Forward it if necessary */
1246 if(strcmp(to_id, myself->name))
1248 if(!(to = lookup_id(to_id)))
1250 syslog(LOG_ERR, _("Got ANS_KEY from %s (%s) destination %s which does not exist in our connection list"),
1251 cl->name, cl->hostname, to_id);
1254 send_ans_key(from, to, pktkey);
1257 /* Update our copy of the origin's packet key */
1259 if(from->cipher_pktkey)
1260 free(from->cipher_pktkey);
1262 from->cipher_pktkey = xstrdup(pktkey);
1264 hex2bin(from->cipher_pktkey, from->cipher_pktkey, keylength);
1265 from->cipher_pktkey[keylength] = '\0';
1267 from->status.validkey = 1;
1268 from->status.waitingforkey = 0;
1275 int send_tcppacket(connection_t *cl, vpn_packet_t *packet)
1281 x = send_request(cl->nexthop, "%d %hd", PACKET, packet->len);
1286 return send_meta(cl, packet->data, packet->len);
1289 int tcppacket_h(connection_t *cl)
1293 if(sscanf(cl->buffer, "%*d %hd", &len) != 1)
1295 syslog(LOG_ERR, _("Got bad PACKET from %s (%s)"), cl->name, cl->hostname);
1299 /* Set reqlen to len, this will tell receive_meta() that a tcppacket is coming. */
1306 /* Jumptable for the request handlers */
1308 int (*request_handlers[])(connection_t*) = {
1309 id_h, metakey_h, challenge_h, chal_reply_h,
1310 status_h, error_h, termreq_h,
1312 add_host_h, del_host_h,
1313 add_subnet_h, del_subnet_h,
1314 key_changed_h, req_key_h, ans_key_h,
1320 char (*request_name[]) = {
1321 "ID", "METAKEY", "CHALLENGE", "CHAL_REPLY",
1322 "STATUS", "ERROR", "TERMREQ",
1324 "ADD_HOST", "DEL_HOST",
1325 "ADD_SUBNET", "DEL_SUBNET",
1326 "KEY_CHANGED", "REQ_KEY", "ANS_KEY",
1330 /* Status strings */
1332 char (*status_text[]) = {
1338 char (*error_text[]) = {