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.98 2001/07/04 08:41:36 guus Exp $
25 #include <sys/types.h>
30 #include <sys/socket.h>
41 #include <netinet/in.h>
43 #include <openssl/sha.h>
44 #include <openssl/rand.h>
45 #include <openssl/evp.h>
47 #ifndef HAVE_RAND_PSEUDO_BYTES
48 #define RAND_pseudo_bytes RAND_bytes
56 #include "connection.h"
62 int check_id(char *id)
66 for (i = 0; i < strlen(id); i++)
67 if(!isalnum(id[i]) && id[i] != '_')
73 /* Generic request routines - takes care of logging and error
76 int send_request(connection_t *cl, const char *format, ...)
79 char buffer[MAXBUFSIZE];
83 /* Use vsnprintf instead of vasprintf: faster, no memory
84 fragmentation, cleanup is automatic, and there is a limit on the
85 input buffer anyway */
87 va_start(args, format);
88 len = vsnprintf(buffer, MAXBUFSIZE, format, args);
89 request = va_arg(args, int);
92 if(len < 0 || len > MAXBUFSIZE-1)
94 syslog(LOG_ERR, _("Output buffer overflow while sending %s to %s (%s)"), request_name[request], cl->name, cl->hostname);
98 if(debug_lvl >= DEBUG_PROTOCOL)
100 if(debug_lvl >= DEBUG_META)
101 syslog(LOG_DEBUG, _("Sending %s to %s (%s): %s"), request_name[request], cl->name, cl->hostname, buffer);
103 syslog(LOG_DEBUG, _("Sending %s to %s (%s)"), request_name[request], cl->name, cl->hostname);
106 buffer[len++] = '\n';
108 return send_meta(cl, buffer, len);
111 int receive_request(connection_t *cl)
115 if(sscanf(cl->buffer, "%d", &request) == 1)
117 if((request < 0) || (request >= LAST) || (request_handlers[request] == NULL))
119 if(debug_lvl >= DEBUG_META)
120 syslog(LOG_DEBUG, _("Unknown request from %s (%s): %s"),
121 cl->name, cl->hostname, cl->buffer);
123 syslog(LOG_ERR, _("Unknown request from %s (%s)"),
124 cl->name, cl->hostname);
130 if(debug_lvl >= DEBUG_PROTOCOL)
132 if(debug_lvl >= DEBUG_META)
133 syslog(LOG_DEBUG, _("Got %s from %s (%s): %s"),
134 request_name[request], cl->name, cl->hostname, cl->buffer);
136 syslog(LOG_DEBUG, _("Got %s from %s (%s)"),
137 request_name[request], cl->name, cl->hostname);
141 if((cl->allow_request != ALL) && (cl->allow_request != request))
143 syslog(LOG_ERR, _("Unauthorized request from %s (%s)"), cl->name, cl->hostname);
147 if(request_handlers[request](cl))
148 /* Something went wrong. Probably scriptkiddies. Terminate. */
150 syslog(LOG_ERR, _("Error while processing %s from %s (%s)"),
151 request_name[request], cl->name, cl->hostname);
157 syslog(LOG_ERR, _("Bogus data received from %s (%s)"),
158 cl->name, cl->hostname);
165 /* The authentication protocol is described in detail in doc/SECURITY2,
166 the rest will be described in doc/PROTOCOL. */
168 int send_id(connection_t *cl)
171 return send_request(cl, "%d %s %d %lx %hd", ID, myself->name, myself->protocol_version, myself->options, myself->port);
174 int id_h(connection_t *cl)
177 unsigned short int port;
178 char name[MAX_STRING_SIZE];
181 if(sscanf(cl->buffer, "%*d "MAX_STRING" %d %lx %hd", name, &cl->protocol_version, &cl->options, &port) != 4)
183 syslog(LOG_ERR, _("Got bad ID from %s"), cl->hostname);
187 /* Check if version matches */
189 if(cl->protocol_version != myself->protocol_version)
191 syslog(LOG_ERR, _("Peer %s (%s) uses incompatible version %d"),
192 cl->name, cl->hostname, cl->protocol_version);
196 /* Check if identity is a valid name */
200 syslog(LOG_ERR, _("Peer %s uses invalid identity name"), cl->hostname);
204 /* Copy string to cl */
209 cl->name = xstrdup(name);
211 /* Load information about peer */
213 if(read_host_config(cl))
215 syslog(LOG_ERR, _("Peer %s had unknown identity (%s)"), cl->hostname, cl->name);
219 /* First check if the host is already in our
220 connection list. If so, we are probably making a loop, which
224 if((old = lookup_id(cl->name)))
226 if(debug_lvl >= DEBUG_CONNECTIONS)
227 syslog(LOG_NOTICE, _("%s (%s) is already in our connection list"), cl->name, cl->hostname);
228 if(cl->status.outgoing)
230 cl->status.outgoing = 0;
231 old->status.outgoing = 1;
233 terminate_connection(cl);
237 /* Now we can add the name to the id tree */
241 /* And uhr... cl->port just changed so we have to unlink it from the connection tree and re-insert... */
243 node = avl_unlink(connection_tree, cl);
245 if(!avl_insert_node(connection_tree, node))
247 old = avl_search_node(connection_tree, node)->data;
248 syslog(LOG_ERR, _("%s is listening on %s:%hd, which is already in use by %s!"),
249 cl->name, cl->hostname, cl->port, old->name);
253 /* Read in the public key, so that we can send a metakey */
255 if(read_rsa_public_key(cl))
258 cl->allow_request = METAKEY;
260 return send_metakey(cl);
263 int ack_h(connection_t *cl)
266 connection_t *old, *p;
268 avl_node_t *node, *node2;
270 /* Okay, before we active the connection, we check if there is another entry
271 in the connection list with the same name. If so, it presumably is an
272 old connection that has timed out but we don't know it yet.
275 while((old = lookup_id(cl->name)))
277 if(debug_lvl >= DEBUG_CONNECTIONS)
278 syslog(LOG_NOTICE, _("Removing old entry for %s at %s in favour of new connection from %s"),
279 cl->name, old->hostname, cl->hostname);
281 terminate_connection(old);
284 /* Activate this connection */
286 cl->allow_request = ALL;
287 cl->status.active = 1;
289 cl->cipher_pkttype = EVP_bf_cbc();
290 cl->cipher_pktkeylength = cl->cipher_pkttype->key_len + cl->cipher_pkttype->iv_len;
292 if(debug_lvl >= DEBUG_CONNECTIONS)
293 syslog(LOG_NOTICE, _("Connection with %s (%s) activated"), cl->name, cl->hostname);
295 if(cl->status.outgoing)
296 seconds_till_retry = 5; /* Reset retry timeout */
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_pseudo_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_pseudo_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.
1101 if(from==myself && !mykeyused)
1104 for(node = connection_tree->head; node; node = node->next)
1106 p = (connection_t *)node->data;
1107 if(p != cl && p->status.meta && p->status.active)
1108 if(!(p->options & OPTION_INDIRECT) || from == myself)
1109 send_request(p, "%d %s", KEY_CHANGED, from->name);
1115 int key_changed_h(connection_t *cl)
1117 char from_id[MAX_STRING_SIZE];
1120 if(sscanf(cl->buffer, "%*d "MAX_STRING, from_id) != 1)
1122 syslog(LOG_ERR, _("Got bad KEY_CHANGED from %s (%s)"),
1123 cl->name, cl->hostname);
1127 if(!(from = lookup_id(from_id)))
1129 syslog(LOG_ERR, _("Got KEY_CHANGED from %s (%s) origin %s which does not exist in our connection list"),
1130 cl->name, cl->hostname, from_id);
1134 from->status.validkey = 0;
1135 from->status.waitingforkey = 0;
1137 if(!(from->options | cl->options | myself->options) & OPTION_INDIRECT)
1138 send_key_changed(from, cl);
1143 int send_req_key(connection_t *from, connection_t *to)
1146 return send_request(to->nexthop, "%d %s %s", REQ_KEY,
1147 from->name, to->name);
1150 int req_key_h(connection_t *cl)
1152 char from_id[MAX_STRING_SIZE];
1153 char to_id[MAX_STRING_SIZE];
1154 connection_t *from, *to;
1157 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING, from_id, to_id) != 2)
1159 syslog(LOG_ERR, _("Got bad REQ_KEY from %s (%s)"),
1160 cl->name, cl->hostname);
1164 if(!(from = lookup_id(from_id)))
1166 syslog(LOG_ERR, _("Got REQ_KEY from %s (%s) origin %s which does not exist in our connection list"),
1167 cl->name, cl->hostname, from_id);
1171 /* Check if this key request is for us */
1173 if(!strcmp(to_id, myself->name)) /* Yes, send our own key back */
1175 bin2hex(myself->cipher_pktkey, pktkey, myself->cipher_pktkeylength);
1176 pktkey[myself->cipher_pktkeylength*2] = '\0';
1177 send_ans_key(myself, from, pktkey);
1182 if(!(to = lookup_id(to_id)))
1184 syslog(LOG_ERR, _("Got REQ_KEY from %s (%s) destination %s which does not exist in our connection list"),
1185 cl->name, cl->hostname, to_id);
1189 if(to->status.validkey) /* Proxy keys */
1191 bin2hex(to->cipher_pktkey, pktkey, to->cipher_pktkeylength);
1192 pktkey[to->cipher_pktkeylength*2] = '\0';
1193 send_ans_key(to, from, pktkey);
1196 send_req_key(from, to);
1203 int send_ans_key(connection_t *from, connection_t *to, char *pktkey)
1206 return send_request(to->nexthop, "%d %s %s %s", ANS_KEY,
1207 from->name, to->name, pktkey);
1210 int ans_key_h(connection_t *cl)
1212 char from_id[MAX_STRING_SIZE];
1213 char to_id[MAX_STRING_SIZE];
1214 char pktkey[MAX_STRING_SIZE];
1216 connection_t *from, *to;
1218 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING, from_id, to_id, pktkey) != 3)
1220 syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s)"),
1221 cl->name, cl->hostname);
1225 if(!(from = lookup_id(from_id)))
1227 syslog(LOG_ERR, _("Got ANS_KEY from %s (%s) origin %s which does not exist in our connection list"),
1228 cl->name, cl->hostname, from_id);
1232 /* Check correctness of packet key */
1234 keylength = strlen(pktkey);
1236 if(keylength != from->cipher_pktkeylength*2)
1238 syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s) origin %s: invalid key length"),
1239 cl->name, cl->hostname, from->name);
1243 /* Forward it if necessary */
1245 if(strcmp(to_id, myself->name))
1247 if(!(to = lookup_id(to_id)))
1249 syslog(LOG_ERR, _("Got ANS_KEY from %s (%s) destination %s which does not exist in our connection list"),
1250 cl->name, cl->hostname, to_id);
1253 send_ans_key(from, to, pktkey);
1256 /* Update our copy of the origin's packet key */
1258 if(from->cipher_pktkey)
1259 free(from->cipher_pktkey);
1261 from->cipher_pktkey = xstrdup(pktkey);
1263 hex2bin(from->cipher_pktkey, from->cipher_pktkey, keylength);
1264 from->cipher_pktkey[keylength] = '\0';
1266 from->status.validkey = 1;
1267 from->status.waitingforkey = 0;
1274 int send_tcppacket(connection_t *cl, vpn_packet_t *packet)
1280 x = send_request(cl->nexthop, "%d %hd", PACKET, packet->len);
1285 return send_meta(cl, packet->data, packet->len);
1288 int tcppacket_h(connection_t *cl)
1292 if(sscanf(cl->buffer, "%*d %hd", &len) != 1)
1294 syslog(LOG_ERR, _("Got bad PACKET from %s (%s)"), cl->name, cl->hostname);
1298 /* Set reqlen to len, this will tell receive_meta() that a tcppacket is coming. */
1305 /* Jumptable for the request handlers */
1307 int (*request_handlers[])(connection_t*) = {
1308 id_h, metakey_h, challenge_h, chal_reply_h,
1309 status_h, error_h, termreq_h,
1311 add_host_h, del_host_h,
1312 add_subnet_h, del_subnet_h,
1313 key_changed_h, req_key_h, ans_key_h,
1319 char (*request_name[]) = {
1320 "ID", "METAKEY", "CHALLENGE", "CHAL_REPLY",
1321 "STATUS", "ERROR", "TERMREQ",
1323 "ADD_HOST", "DEL_HOST",
1324 "ADD_SUBNET", "DEL_SUBNET",
1325 "KEY_CHANGED", "REQ_KEY", "ANS_KEY",
1329 /* Status strings */
1331 char (*status_text[]) = {
1337 char (*error_text[]) = {