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.92 2001/06/05 16:09:55 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 */
220 cl->name = xstrdup(name);
222 /* Load information about peer */
224 if(read_host_config(cl))
226 syslog(LOG_ERR, _("Peer %s had unknown identity (%s)"), cl->hostname, cl->name);
230 /* First check if the host we connected to is already in our
231 connection list. If so, we are probably making a loop, which
235 if(cl->status.outgoing)
237 if((old = lookup_id(cl->name)))
239 if(debug_lvl >= DEBUG_CONNECTIONS)
240 syslog(LOG_NOTICE, _("Uplink %s (%s) is already in our connection list"), cl->name, cl->hostname);
241 cl->status.outgoing = 0;
242 old->status.outgoing = 1;
243 terminate_connection(cl);
248 /* Now we can add the name to the id tree */
252 /* And uhr... cl->port just changed so we have to unlink it from the connection tree and re-insert... */
254 node = avl_unlink(connection_tree, cl);
256 avl_insert_node(connection_tree, node);
258 /* Read in the public key, so that we can send a metakey */
260 if(read_rsa_public_key(cl))
263 cl->allow_request = METAKEY;
265 return send_metakey(cl);
268 int ack_h(connection_t *cl)
271 connection_t *old, *p;
273 avl_node_t *node, *node2;
275 /* Okay, before we active the connection, we check if there is another entry
276 in the connection list with the same name. If so, it presumably is an
277 old connection that has timed out but we don't know it yet.
280 while((old = lookup_id(cl->name)))
282 if(debug_lvl >= DEBUG_CONNECTIONS)
283 syslog(LOG_NOTICE, _("Removing old entry for %s at %s in favour of new connection from %s"),
284 cl->name, old->hostname, cl->hostname);
286 terminate_connection(old);
289 /* Activate this connection */
291 cl->allow_request = ALL;
292 cl->status.active = 1;
294 cl->cipher_pkttype = EVP_bf_cbc();
295 cl->cipher_pktkeylength = cl->cipher_pkttype->key_len + cl->cipher_pkttype->iv_len;
297 if(debug_lvl >= DEBUG_CONNECTIONS)
298 syslog(LOG_NOTICE, _("Connection with %s (%s) activated"), cl->name, cl->hostname);
301 /* Check some options */
303 if((cfg = get_config_val(cl->config, config_indirectdata)))
305 if(cfg->data.val == stupid_true)
306 cl->options |= OPTION_INDIRECT;
309 if((cfg = get_config_val(cl->config, config_tcponly)))
311 if(cfg->data.val == stupid_true)
312 cl->options |= OPTION_TCPONLY;
315 /* Send him our subnets */
317 for(node = myself->subnet_tree->head; node; node = node->next)
319 subnet = (subnet_t *)node->data;
320 send_add_subnet(cl, subnet);
323 /* And send him all the hosts and their subnets we know... */
325 for(node = connection_tree->head; node; node = node->next)
327 p = (connection_t *)node->data;
329 if(p != cl && p->status.active)
331 /* Notify others of this connection */
334 send_add_host(p, cl);
336 /* Notify new connection of everything we know */
338 send_add_host(cl, p);
340 for(node2 = p->subnet_tree->head; node2; node2 = node2->next)
342 subnet = (subnet_t *)node2->data;
343 send_add_subnet(cl, subnet);
351 int send_challenge(connection_t *cl)
356 /* CHECKME: what is most reasonable value for len? */
358 len = RSA_size(cl->rsa_key);
360 /* Allocate buffers for the challenge */
362 buffer = xmalloc(len*2+1);
365 free(cl->hischallenge);
367 cl->hischallenge = xmalloc(len);
369 /* Copy random data to the buffer */
371 RAND_bytes(cl->hischallenge, len);
376 bin2hex(cl->hischallenge, buffer, len);
377 buffer[len*2] = '\0';
380 /* Send the challenge */
382 x = send_request(cl, "%d %s", CHALLENGE, buffer);
388 int challenge_h(connection_t *cl)
390 char buffer[MAX_STRING_SIZE];
393 if(sscanf(cl->buffer, "%*d "MAX_STRING, buffer) != 1)
395 syslog(LOG_ERR, _("Got bad CHALLENGE from %s (%s)"), cl->name, cl->hostname);
399 len = RSA_size(myself->rsa_key);
401 /* Check if the length of the challenge is all right */
403 if(strlen(buffer) != len*2)
405 syslog(LOG_ERR, _("Intruder: wrong challenge length from %s (%s)"), cl->name, cl->hostname);
409 /* Allocate buffers for the challenge */
412 cl->mychallenge = xmalloc(len);
414 /* Convert the challenge from hexadecimal back to binary */
416 hex2bin(buffer,cl->mychallenge,len);
418 cl->allow_request = CHAL_REPLY;
420 /* Rest is done by send_chal_reply() */
422 return send_chal_reply(cl);
425 int send_chal_reply(connection_t *cl)
427 char hash[SHA_DIGEST_LENGTH*2+1];
431 syslog(LOG_ERR, _("Trying to send CHAL_REPLY to %s (%s) without a valid CHALLENGE"), cl->name, cl->hostname);
435 /* Calculate the hash from the challenge we received */
437 SHA1(cl->mychallenge, RSA_size(myself->rsa_key), hash);
439 /* Convert the hash to a hexadecimal formatted string */
441 bin2hex(hash,hash,SHA_DIGEST_LENGTH);
442 hash[SHA_DIGEST_LENGTH*2] = '\0';
447 return send_request(cl, "%d %s", CHAL_REPLY, hash);
450 int chal_reply_h(connection_t *cl)
452 char hishash[MAX_STRING_SIZE];
453 char myhash[SHA_DIGEST_LENGTH];
455 if(sscanf(cl->buffer, "%*d "MAX_STRING, hishash) != 1)
457 syslog(LOG_ERR, _("Got bad CHAL_REPLY from %s (%s)"), cl->name, cl->hostname);
461 /* Check if the length of the hash is all right */
463 if(strlen(hishash) != SHA_DIGEST_LENGTH*2)
465 syslog(LOG_ERR, _("Intruder: wrong challenge reply length from %s (%s)"), cl->name, cl->hostname);
469 /* Convert the hash to binary format */
471 hex2bin(hishash, hishash, SHA_DIGEST_LENGTH);
473 /* Calculate the hash from the challenge we sent */
475 SHA1(cl->hischallenge, RSA_size(cl->rsa_key), myhash);
477 /* Verify the incoming hash with the calculated hash */
479 if(memcmp(hishash, myhash, SHA_DIGEST_LENGTH))
481 syslog(LOG_ERR, _("Intruder: wrong challenge reply from %s (%s)"), cl->name, cl->hostname);
482 if(debug_lvl >= DEBUG_SCARY_THINGS)
484 bin2hex(myhash, hishash, SHA_DIGEST_LENGTH);
485 hishash[SHA_DIGEST_LENGTH*2] = '\0';
486 syslog(LOG_DEBUG, _("Expected challenge reply: %s"), hishash);
491 /* Identity has now been positively verified.
492 ack_h() handles the rest from now on.
498 int send_metakey(connection_t *cl)
503 len = RSA_size(cl->rsa_key);
505 /* Allocate buffers for the meta key */
507 buffer = xmalloc(len*2+1);
509 if(!cl->cipher_outkey)
510 cl->cipher_outkey = xmalloc(len);
512 if(!cl->cipher_outctx)
513 cl->cipher_outctx = xmalloc(sizeof(*cl->cipher_outctx));
515 /* Copy random data to the buffer */
517 RAND_bytes(cl->cipher_outkey, len);
519 /* The message we send must be smaller than the modulus of the RSA key.
520 By definition, for a key of k bits, the following formula holds:
522 2^(k-1) <= modulus < 2^(k)
524 Where ^ means "to the power of", not "xor".
525 This means that to be sure, we must choose our message < 2^(k-1).
526 This can be done by setting the most significant bit to zero.
529 cl->cipher_outkey[0] &= 0x7F;
531 if(debug_lvl >= DEBUG_SCARY_THINGS)
533 bin2hex(cl->cipher_outkey, buffer, len);
534 buffer[len*2] = '\0';
535 syslog(LOG_DEBUG, _("Generated random meta key (unencrypted): %s"), buffer);
538 /* Encrypt the random data
540 We do not use one of the PKCS padding schemes here.
541 This is allowed, because we encrypt a totally random string
542 with a length equal to that of the modulus of the RSA key.
545 if(RSA_public_encrypt(len, cl->cipher_outkey, buffer, cl->rsa_key, RSA_NO_PADDING) != len)
547 syslog(LOG_ERR, _("Error during encryption of meta key for %s (%s)"), cl->name, cl->hostname);
552 /* Convert the encrypted random data to a hexadecimal formatted string */
554 bin2hex(buffer, buffer, len);
555 buffer[len*2] = '\0';
557 /* Send the meta key */
559 x = send_request(cl, "%d %s", METAKEY, buffer);
562 /* Further outgoing requests are encrypted with the key we just generated */
564 EVP_EncryptInit(cl->cipher_outctx, EVP_bf_cfb(),
565 cl->cipher_outkey + len - EVP_bf_cfb()->key_len,
566 cl->cipher_outkey + len - EVP_bf_cfb()->key_len - EVP_bf_cfb()->iv_len);
568 cl->status.encryptout = 1;
573 int metakey_h(connection_t *cl)
575 char buffer[MAX_STRING_SIZE];
578 if(sscanf(cl->buffer, "%*d "MAX_STRING, buffer) != 1)
580 syslog(LOG_ERR, _("Got bad METAKEY from %s (%s)"), cl->name, cl->hostname);
584 len = RSA_size(myself->rsa_key);
586 /* Check if the length of the meta key is all right */
588 if(strlen(buffer) != len*2)
590 syslog(LOG_ERR, _("Intruder: wrong meta key length from %s (%s)"), cl->name, cl->hostname);
594 /* Allocate buffers for the meta key */
596 if(!cl->cipher_inkey)
597 cl->cipher_inkey = xmalloc(len);
599 if(!cl->cipher_inctx)
600 cl->cipher_inctx = xmalloc(sizeof(*cl->cipher_inctx));
602 /* Convert the challenge from hexadecimal back to binary */
604 hex2bin(buffer,buffer,len);
606 /* Decrypt the meta key */
608 if(RSA_private_decrypt(len, buffer, cl->cipher_inkey, myself->rsa_key, RSA_NO_PADDING) != len) /* See challenge() */
610 syslog(LOG_ERR, _("Error during encryption of meta key for %s (%s)"), cl->name, cl->hostname);
614 if(debug_lvl >= DEBUG_SCARY_THINGS)
616 bin2hex(cl->cipher_inkey, buffer, len);
617 buffer[len*2] = '\0';
618 syslog(LOG_DEBUG, _("Received random meta key (unencrypted): %s"), buffer);
621 /* All incoming requests will now be encrypted. */
623 EVP_DecryptInit(cl->cipher_inctx, EVP_bf_cfb(),
624 cl->cipher_inkey + len - EVP_bf_cfb()->key_len,
625 cl->cipher_inkey + len - EVP_bf_cfb()->key_len - EVP_bf_cfb()->iv_len);
627 cl->status.decryptin = 1;
629 cl->allow_request = CHALLENGE;
631 return send_challenge(cl);
634 /* Address and subnet information exchange */
636 int send_add_subnet(connection_t *cl, subnet_t *subnet)
642 if((cl->options | myself->options | subnet->owner->options) & OPTION_INDIRECT)
643 owner = myself->name;
645 owner = subnet->owner->name;
647 x = send_request(cl, "%d %s %s", ADD_SUBNET,
648 owner, netstr = net2str(subnet));
654 int add_subnet_h(connection_t *cl)
656 char subnetstr[MAX_STRING_SIZE];
657 char name[MAX_STRING_SIZE];
658 connection_t *owner, *p;
662 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING, name, subnetstr) != 2)
664 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s)"), cl->name, cl->hostname);
668 /* Check if owner name is a valid */
672 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s): invalid identity name"), cl->name, cl->hostname);
676 /* Check if subnet string is valid */
678 if(!(subnet = str2net(subnetstr)))
680 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s): invalid subnet string"), cl->name, cl->hostname);
684 /* Check if somebody tries to add a subnet of ourself */
686 if(!strcmp(name, myself->name))
688 syslog(LOG_ERR, _("Warning: got ADD_SUBNET from %s (%s) for ourself, restarting"),
689 cl->name, cl->hostname);
694 /* Check if the owner of the new subnet is in the connection list */
696 if(!(owner = lookup_id(name)))
698 syslog(LOG_ERR, _("Got ADD_SUBNET for %s from %s (%s) which is not in our connection list"),
699 name, cl->name, cl->hostname);
703 /* If everything is correct, add the subnet to the list of the owner */
705 subnet_add(owner, subnet);
709 for(node = connection_tree->head; node; node = node->next)
711 p = (connection_t *)node->data;
712 if(p->status.meta && p->status.active && p!= cl)
713 send_add_subnet(p, subnet);
719 int send_del_subnet(connection_t *cl, subnet_t *subnet)
725 if(cl->options & OPTION_INDIRECT)
726 owner = myself->name;
728 owner = subnet->owner->name;
730 x = send_request(cl, "%d %s %s", DEL_SUBNET, owner, netstr = net2str(subnet));
736 int del_subnet_h(connection_t *cl)
738 char subnetstr[MAX_STRING_SIZE];
739 char name[MAX_STRING_SIZE];
740 connection_t *owner, *p;
744 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING, name, subnetstr) != 3)
746 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s)"), cl->name, cl->hostname);
750 /* Check if owner name is a valid */
754 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s): invalid identity name"), cl->name, cl->hostname);
758 /* Check if subnet string is valid */
760 if(!(subnet = str2net(subnetstr)))
762 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s): invalid subnet string"), cl->name, cl->hostname);
768 /* Check if somebody tries to add a subnet of ourself */
770 if(!strcmp(name, myself->name))
772 syslog(LOG_ERR, _("Warning: got DEL_SUBNET from %s (%s) for ourself, restarting"),
773 cl->name, cl->hostname);
778 /* Check if the owner of the new subnet is in the connection list */
780 if(!(owner = lookup_id(name)))
782 syslog(LOG_ERR, _("Got DEL_SUBNET for %s from %s (%s) which is not in our connection list"),
783 name, cl->name, cl->hostname);
787 /* If everything is correct, delete the subnet from the list of the owner */
793 for(node = connection_tree->head; node; node = node->next)
795 p = (connection_t *)node->data;
796 if(p->status.meta && p->status.active && p!= cl)
797 send_del_subnet(p, subnet);
803 /* New and closed connections notification */
805 int send_add_host(connection_t *cl, connection_t *other)
808 if(!((cl->options | myself->options | other->options) & OPTION_INDIRECT))
809 return send_request(cl, "%d %s %lx:%d %lx", ADD_HOST,
810 other->name, other->address, other->port, other->options);
815 int add_host_h(connection_t *cl)
817 connection_t *old, *new, *p;
818 char name[MAX_STRING_SIZE];
821 new = new_connection();
823 if(sscanf(cl->buffer, "%*d "MAX_STRING" %lx:%hd %lx", name, &new->address, &new->port, &new->options) != 4)
825 syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s)"), cl->name, cl->hostname);
829 /* Check if identity is a valid name */
833 syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s): invalid identity name"), cl->name, cl->hostname);
834 free_connection(new);
838 /* Check if somebody tries to add ourself */
840 if(!strcmp(name, myself->name))
842 syslog(LOG_ERR, _("Warning: got ADD_HOST from %s (%s) for ourself, restarting"), cl->name, cl->hostname);
844 free_connection(new);
848 /* Fill in more of the new connection structure */
850 new->hostname = hostlookup(htonl(new->address));
852 /* Check if the new host already exists in the connnection list */
854 if((old = lookup_id(name)))
856 if((new->address == old->address) && (new->port == old->port))
858 if(debug_lvl >= DEBUG_CONNECTIONS)
859 syslog(LOG_NOTICE, _("Got duplicate ADD_HOST for %s (%s) from %s (%s)"),
860 old->name, old->hostname, name, new->hostname);
861 free_connection(new);
866 if(debug_lvl >= DEBUG_CONNECTIONS)
867 syslog(LOG_NOTICE, _("Removing old entry for %s (%s) in favour of new connection"),
868 old->name, old->hostname);
870 terminate_connection(old);
874 /* Hook it up into the connection */
876 new->name = xstrdup(name);
880 /* Tell the rest about the new host */
882 for(node = connection_tree->head; node; node = node->next)
884 p = (connection_t *)node->data;
885 if(p->status.meta && p->status.active && p!=cl)
886 send_add_host(p, new);
889 /* Fill in rest of connection structure */
892 new->status.active = 1;
893 new->cipher_pkttype = EVP_bf_cbc();
894 new->cipher_pktkeylength = cl->cipher_pkttype->key_len + cl->cipher_pkttype->iv_len;
899 int send_del_host(connection_t *cl, connection_t *other)
902 if(!((cl->options | myself->options) & OPTION_INDIRECT))
903 return send_request(cl, "%d %s %lx:%d %lx", DEL_HOST,
904 other->name, other->address, other->port, other->options);
909 int del_host_h(connection_t *cl)
911 char name[MAX_STRING_SIZE];
915 connection_t *old, *p;
918 if(sscanf(cl->buffer, "%*d "MAX_STRING" %lx:%hd %lx", name, &address, &port, &options) != 4)
920 syslog(LOG_ERR, _("Got bad DEL_HOST from %s (%s)"),
921 cl->name, cl->hostname);
925 /* Check if identity is a valid name */
929 syslog(LOG_ERR, _("Got bad DEL_HOST from %s (%s): invalid identity name"), cl->name, cl->hostname);
933 /* Check if somebody tries to delete ourself */
935 if(!strcmp(name, myself->name))
937 syslog(LOG_ERR, _("Warning: got DEL_HOST from %s (%s) for ourself, restarting"),
938 cl->name, cl->hostname);
943 /* Check if the new host already exists in the connnection list */
945 if(!(old = lookup_id(name)))
947 syslog(LOG_ERR, _("Got DEL_HOST from %s (%s) for %s which is not in our connection list"),
948 name, cl->name, cl->hostname);
952 /* Check if the rest matches */
954 if(address!=old->address || port!=old->port || options!=old->options || cl!=old->nexthop)
956 syslog(LOG_WARNING, _("Got DEL_HOST from %s (%s) for %s which doesn't match"), cl->name, cl->hostname, old->name);
960 /* Ok, since EVERYTHING seems to check out all right, delete it */
962 old->status.active = 0;
963 terminate_connection(old);
965 /* Tell the rest about the new host */
967 for(node = connection_tree->head; node; node = node->next)
969 p = (connection_t *)node->data;
970 if(p->status.meta && p->status.active && p!=cl)
971 send_del_host(p, old);
977 /* Status and error notification routines */
979 int send_status(connection_t *cl, int statusno, char *statusstring)
983 statusstring = status_text[statusno];
985 return send_request(cl, "%d %d %s", STATUS, statusno, statusstring);
988 int status_h(connection_t *cl)
991 char statusstring[MAX_STRING_SIZE];
993 if(sscanf(cl->buffer, "%*d %d "MAX_STRING, &statusno, statusstring) != 2)
995 syslog(LOG_ERR, _("Got bad STATUS from %s (%s)"),
996 cl->name, cl->hostname);
1000 if(debug_lvl >= DEBUG_STATUS)
1002 syslog(LOG_NOTICE, _("Status message from %s (%s): %s: %s"),
1003 cl->name, cl->hostname, status_text[statusno], statusstring);
1010 int send_error(connection_t *cl, int err, char *errstring)
1014 errstring = strerror(err);
1015 return send_request(cl, "%d %d %s", ERROR, err, errstring);
1018 int error_h(connection_t *cl)
1021 char errorstring[MAX_STRING_SIZE];
1023 if(sscanf(cl->buffer, "%*d %d "MAX_STRING, &err, errorstring) != 2)
1025 syslog(LOG_ERR, _("Got bad ERROR from %s (%s)"),
1026 cl->name, cl->hostname);
1030 if(debug_lvl >= DEBUG_ERROR)
1032 syslog(LOG_NOTICE, _("Error message from %s (%s): %s: %s"),
1033 cl->name, cl->hostname, strerror(err), errorstring);
1036 terminate_connection(cl);
1041 int send_termreq(connection_t *cl)
1044 return send_request(cl, "%d", TERMREQ);
1047 int termreq_h(connection_t *cl)
1050 terminate_connection(cl);
1055 int send_ping(connection_t *cl)
1057 char salt[SALTLEN*2+1];
1059 cl->status.pinged = 1;
1060 cl->last_ping_time = time(NULL);
1061 RAND_bytes(salt, SALTLEN);
1062 bin2hex(salt, salt, SALTLEN);
1063 salt[SALTLEN*2] = '\0';
1065 return send_request(cl, "%d %s", PING, salt);
1068 int ping_h(connection_t *cl)
1071 return send_pong(cl);
1074 int send_pong(connection_t *cl)
1076 char salt[SALTLEN*2+1];
1078 RAND_bytes(salt, SALTLEN);
1079 bin2hex(salt, salt, SALTLEN);
1080 salt[SALTLEN*2] = '\0';
1082 return send_request(cl, "%d %s", PONG, salt);
1085 int pong_h(connection_t *cl)
1088 cl->status.pinged = 0;
1095 int send_key_changed(connection_t *from, connection_t *cl)
1100 /* Only send this message if some other daemon requested our key previously.
1101 This reduces unnecessary key_changed broadcasts.
1106 for(node = connection_tree->head; node; node = node->next)
1108 p = (connection_t *)node->data;
1109 if(p != cl && p->status.meta && p->status.active)
1110 if(!(p->options & OPTION_INDIRECT) || from == myself)
1111 send_request(p, "%d %s", KEY_CHANGED, from->name);
1119 int key_changed_h(connection_t *cl)
1121 char from_id[MAX_STRING_SIZE];
1124 if(sscanf(cl->buffer, "%*d "MAX_STRING, from_id) != 1)
1126 syslog(LOG_ERR, _("Got bad KEY_CHANGED from %s (%s)"),
1127 cl->name, cl->hostname);
1131 if(!(from = lookup_id(from_id)))
1133 syslog(LOG_ERR, _("Got KEY_CHANGED from %s (%s) origin %s which does not exist in our connection list"),
1134 cl->name, cl->hostname, from_id);
1138 from->status.validkey = 0;
1139 from->status.waitingforkey = 0;
1141 if(!(from->options | cl->options | myself->options) & OPTION_INDIRECT)
1142 send_key_changed(from, cl);
1147 int send_req_key(connection_t *from, connection_t *to)
1150 return send_request(to->nexthop, "%d %s %s", REQ_KEY,
1151 from->name, to->name);
1154 int req_key_h(connection_t *cl)
1156 char from_id[MAX_STRING_SIZE];
1157 char to_id[MAX_STRING_SIZE];
1158 connection_t *from, *to;
1161 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING, from_id, to_id) != 2)
1163 syslog(LOG_ERR, _("Got bad REQ_KEY from %s (%s)"),
1164 cl->name, cl->hostname);
1168 if(!(from = lookup_id(from_id)))
1170 syslog(LOG_ERR, _("Got REQ_KEY from %s (%s) origin %s which does not exist in our connection list"),
1171 cl->name, cl->hostname, from_id);
1175 /* Check if this key request is for us */
1177 if(!strcmp(to_id, myself->name)) /* Yes, send our own key back */
1179 bin2hex(myself->cipher_pktkey, pktkey, myself->cipher_pktkeylength);
1180 pktkey[myself->cipher_pktkeylength*2] = '\0';
1181 send_ans_key(myself, from, pktkey);
1186 if(!(to = lookup_id(to_id)))
1188 syslog(LOG_ERR, _("Got REQ_KEY from %s (%s) destination %s which does not exist in our connection list"),
1189 cl->name, cl->hostname, to_id);
1193 if(to->status.validkey) /* Proxy keys */
1195 bin2hex(to->cipher_pktkey, pktkey, to->cipher_pktkeylength);
1196 pktkey[to->cipher_pktkeylength*2] = '\0';
1197 send_ans_key(to, from, pktkey);
1200 send_req_key(from, to);
1207 int send_ans_key(connection_t *from, connection_t *to, char *pktkey)
1210 return send_request(to->nexthop, "%d %s %s %s", ANS_KEY,
1211 from->name, to->name, pktkey);
1214 int ans_key_h(connection_t *cl)
1216 char from_id[MAX_STRING_SIZE];
1217 char to_id[MAX_STRING_SIZE];
1218 char pktkey[MAX_STRING_SIZE];
1220 connection_t *from, *to;
1222 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING, from_id, to_id, pktkey) != 3)
1224 syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s)"),
1225 cl->name, cl->hostname);
1229 if(!(from = lookup_id(from_id)))
1231 syslog(LOG_ERR, _("Got ANS_KEY from %s (%s) origin %s which does not exist in our connection list"),
1232 cl->name, cl->hostname, from_id);
1236 /* Check correctness of packet key */
1238 keylength = strlen(pktkey);
1240 if(keylength != from->cipher_pktkeylength*2)
1242 syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s) origin %s: invalid key length"),
1243 cl->name, cl->hostname, from->name);
1247 /* Forward it if necessary */
1249 if(strcmp(to_id, myself->name))
1251 if(!(to = lookup_id(to_id)))
1253 syslog(LOG_ERR, _("Got ANS_KEY from %s (%s) destination %s which does not exist in our connection list"),
1254 cl->name, cl->hostname, to_id);
1257 send_ans_key(from, to, pktkey);
1260 /* Update our copy of the origin's packet key */
1262 if(from->cipher_pktkey)
1263 free(from->cipher_pktkey);
1265 from->cipher_pktkey = xstrdup(pktkey);
1267 hex2bin(from->cipher_pktkey, from->cipher_pktkey, keylength);
1268 from->cipher_pktkey[keylength] = '\0';
1270 from->status.validkey = 1;
1271 from->status.waitingforkey = 0;
1278 int send_tcppacket(connection_t *cl, vpn_packet_t *packet)
1284 x = send_request(cl->nexthop, "%d %hd", PACKET, packet->len);
1289 return send_meta(cl, packet->data, packet->len);
1292 int tcppacket_h(connection_t *cl)
1296 if(sscanf(cl->buffer, "%*d %hd", &len) != 1)
1298 syslog(LOG_ERR, _("Got bad PACKET from %s (%s)"), cl->name, cl->hostname);
1302 /* Set reqlen to len, this will tell receive_meta() that a tcppacket is coming. */
1309 /* Jumptable for the request handlers */
1311 int (*request_handlers[])(connection_t*) = {
1312 id_h, metakey_h, challenge_h, chal_reply_h,
1313 status_h, error_h, termreq_h,
1315 add_host_h, del_host_h,
1316 add_subnet_h, del_subnet_h,
1317 key_changed_h, req_key_h, ans_key_h,
1323 char (*request_name[]) = {
1324 "ID", "METAKEY", "CHALLENGE", "CHAL_REPLY",
1325 "STATUS", "ERROR", "TERMREQ",
1327 "ADD_HOST", "DEL_HOST",
1328 "ADD_SUBNET", "DEL_SUBNET",
1329 "KEY_CHANGED", "REQ_KEY", "ANS_KEY",
1333 /* Status strings */
1335 char (*status_text[]) = {
1341 char (*error_text[]) = {