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.94 2001/06/09 10:00:34 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);
300 if(cl->status.outgoing)
301 seconds_till_retry = 5; /* Reset retry timeout */
303 /* Check some options */
305 if((cfg = get_config_val(cl->config, config_indirectdata)))
307 if(cfg->data.val == stupid_true)
308 cl->options |= OPTION_INDIRECT;
311 if((cfg = get_config_val(cl->config, config_tcponly)))
313 if(cfg->data.val == stupid_true)
314 cl->options |= OPTION_TCPONLY;
317 /* Send him our subnets */
319 for(node = myself->subnet_tree->head; node; node = node->next)
321 subnet = (subnet_t *)node->data;
322 send_add_subnet(cl, subnet);
325 /* And send him all the hosts and their subnets we know... */
327 for(node = connection_tree->head; node; node = node->next)
329 p = (connection_t *)node->data;
331 if(p != cl && p->status.active)
333 /* Notify others of this connection */
336 send_add_host(p, cl);
338 /* Notify new connection of everything we know */
340 send_add_host(cl, p);
342 for(node2 = p->subnet_tree->head; node2; node2 = node2->next)
344 subnet = (subnet_t *)node2->data;
345 send_add_subnet(cl, subnet);
353 int send_challenge(connection_t *cl)
358 /* CHECKME: what is most reasonable value for len? */
360 len = RSA_size(cl->rsa_key);
362 /* Allocate buffers for the challenge */
364 buffer = xmalloc(len*2+1);
367 free(cl->hischallenge);
369 cl->hischallenge = xmalloc(len);
371 /* Copy random data to the buffer */
373 RAND_bytes(cl->hischallenge, len);
378 bin2hex(cl->hischallenge, buffer, len);
379 buffer[len*2] = '\0';
382 /* Send the challenge */
384 x = send_request(cl, "%d %s", CHALLENGE, buffer);
390 int challenge_h(connection_t *cl)
392 char buffer[MAX_STRING_SIZE];
395 if(sscanf(cl->buffer, "%*d "MAX_STRING, buffer) != 1)
397 syslog(LOG_ERR, _("Got bad CHALLENGE from %s (%s)"), cl->name, cl->hostname);
401 len = RSA_size(myself->rsa_key);
403 /* Check if the length of the challenge is all right */
405 if(strlen(buffer) != len*2)
407 syslog(LOG_ERR, _("Intruder: wrong challenge length from %s (%s)"), cl->name, cl->hostname);
411 /* Allocate buffers for the challenge */
414 cl->mychallenge = xmalloc(len);
416 /* Convert the challenge from hexadecimal back to binary */
418 hex2bin(buffer,cl->mychallenge,len);
420 cl->allow_request = CHAL_REPLY;
422 /* Rest is done by send_chal_reply() */
424 return send_chal_reply(cl);
427 int send_chal_reply(connection_t *cl)
429 char hash[SHA_DIGEST_LENGTH*2+1];
433 syslog(LOG_ERR, _("Trying to send CHAL_REPLY to %s (%s) without a valid CHALLENGE"), cl->name, cl->hostname);
437 /* Calculate the hash from the challenge we received */
439 SHA1(cl->mychallenge, RSA_size(myself->rsa_key), hash);
441 /* Convert the hash to a hexadecimal formatted string */
443 bin2hex(hash,hash,SHA_DIGEST_LENGTH);
444 hash[SHA_DIGEST_LENGTH*2] = '\0';
449 return send_request(cl, "%d %s", CHAL_REPLY, hash);
452 int chal_reply_h(connection_t *cl)
454 char hishash[MAX_STRING_SIZE];
455 char myhash[SHA_DIGEST_LENGTH];
457 if(sscanf(cl->buffer, "%*d "MAX_STRING, hishash) != 1)
459 syslog(LOG_ERR, _("Got bad CHAL_REPLY from %s (%s)"), cl->name, cl->hostname);
463 /* Check if the length of the hash is all right */
465 if(strlen(hishash) != SHA_DIGEST_LENGTH*2)
467 syslog(LOG_ERR, _("Intruder: wrong challenge reply length from %s (%s)"), cl->name, cl->hostname);
471 /* Convert the hash to binary format */
473 hex2bin(hishash, hishash, SHA_DIGEST_LENGTH);
475 /* Calculate the hash from the challenge we sent */
477 SHA1(cl->hischallenge, RSA_size(cl->rsa_key), myhash);
479 /* Verify the incoming hash with the calculated hash */
481 if(memcmp(hishash, myhash, SHA_DIGEST_LENGTH))
483 syslog(LOG_ERR, _("Intruder: wrong challenge reply from %s (%s)"), cl->name, cl->hostname);
484 if(debug_lvl >= DEBUG_SCARY_THINGS)
486 bin2hex(myhash, hishash, SHA_DIGEST_LENGTH);
487 hishash[SHA_DIGEST_LENGTH*2] = '\0';
488 syslog(LOG_DEBUG, _("Expected challenge reply: %s"), hishash);
493 /* Identity has now been positively verified.
494 ack_h() handles the rest from now on.
500 int send_metakey(connection_t *cl)
505 len = RSA_size(cl->rsa_key);
507 /* Allocate buffers for the meta key */
509 buffer = xmalloc(len*2+1);
511 if(!cl->cipher_outkey)
512 cl->cipher_outkey = xmalloc(len);
514 if(!cl->cipher_outctx)
515 cl->cipher_outctx = xmalloc(sizeof(*cl->cipher_outctx));
517 /* Copy random data to the buffer */
519 RAND_bytes(cl->cipher_outkey, len);
521 /* The message we send must be smaller than the modulus of the RSA key.
522 By definition, for a key of k bits, the following formula holds:
524 2^(k-1) <= modulus < 2^(k)
526 Where ^ means "to the power of", not "xor".
527 This means that to be sure, we must choose our message < 2^(k-1).
528 This can be done by setting the most significant bit to zero.
531 cl->cipher_outkey[0] &= 0x7F;
533 if(debug_lvl >= DEBUG_SCARY_THINGS)
535 bin2hex(cl->cipher_outkey, buffer, len);
536 buffer[len*2] = '\0';
537 syslog(LOG_DEBUG, _("Generated random meta key (unencrypted): %s"), buffer);
540 /* Encrypt the random data
542 We do not use one of the PKCS padding schemes here.
543 This is allowed, because we encrypt a totally random string
544 with a length equal to that of the modulus of the RSA key.
547 if(RSA_public_encrypt(len, cl->cipher_outkey, buffer, cl->rsa_key, RSA_NO_PADDING) != len)
549 syslog(LOG_ERR, _("Error during encryption of meta key for %s (%s)"), cl->name, cl->hostname);
554 /* Convert the encrypted random data to a hexadecimal formatted string */
556 bin2hex(buffer, buffer, len);
557 buffer[len*2] = '\0';
559 /* Send the meta key */
561 x = send_request(cl, "%d %s", METAKEY, buffer);
564 /* Further outgoing requests are encrypted with the key we just generated */
566 EVP_EncryptInit(cl->cipher_outctx, EVP_bf_cfb(),
567 cl->cipher_outkey + len - EVP_bf_cfb()->key_len,
568 cl->cipher_outkey + len - EVP_bf_cfb()->key_len - EVP_bf_cfb()->iv_len);
570 cl->status.encryptout = 1;
575 int metakey_h(connection_t *cl)
577 char buffer[MAX_STRING_SIZE];
580 if(sscanf(cl->buffer, "%*d "MAX_STRING, buffer) != 1)
582 syslog(LOG_ERR, _("Got bad METAKEY from %s (%s)"), cl->name, cl->hostname);
586 len = RSA_size(myself->rsa_key);
588 /* Check if the length of the meta key is all right */
590 if(strlen(buffer) != len*2)
592 syslog(LOG_ERR, _("Intruder: wrong meta key length from %s (%s)"), cl->name, cl->hostname);
596 /* Allocate buffers for the meta key */
598 if(!cl->cipher_inkey)
599 cl->cipher_inkey = xmalloc(len);
601 if(!cl->cipher_inctx)
602 cl->cipher_inctx = xmalloc(sizeof(*cl->cipher_inctx));
604 /* Convert the challenge from hexadecimal back to binary */
606 hex2bin(buffer,buffer,len);
608 /* Decrypt the meta key */
610 if(RSA_private_decrypt(len, buffer, cl->cipher_inkey, myself->rsa_key, RSA_NO_PADDING) != len) /* See challenge() */
612 syslog(LOG_ERR, _("Error during encryption of meta key for %s (%s)"), cl->name, cl->hostname);
616 if(debug_lvl >= DEBUG_SCARY_THINGS)
618 bin2hex(cl->cipher_inkey, buffer, len);
619 buffer[len*2] = '\0';
620 syslog(LOG_DEBUG, _("Received random meta key (unencrypted): %s"), buffer);
623 /* All incoming requests will now be encrypted. */
625 EVP_DecryptInit(cl->cipher_inctx, EVP_bf_cfb(),
626 cl->cipher_inkey + len - EVP_bf_cfb()->key_len,
627 cl->cipher_inkey + len - EVP_bf_cfb()->key_len - EVP_bf_cfb()->iv_len);
629 cl->status.decryptin = 1;
631 cl->allow_request = CHALLENGE;
633 return send_challenge(cl);
636 /* Address and subnet information exchange */
638 int send_add_subnet(connection_t *cl, subnet_t *subnet)
644 if((cl->options | myself->options | subnet->owner->options) & OPTION_INDIRECT)
645 owner = myself->name;
647 owner = subnet->owner->name;
649 x = send_request(cl, "%d %s %s", ADD_SUBNET,
650 owner, netstr = net2str(subnet));
656 int add_subnet_h(connection_t *cl)
658 char subnetstr[MAX_STRING_SIZE];
659 char name[MAX_STRING_SIZE];
660 connection_t *owner, *p;
664 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING, name, subnetstr) != 2)
666 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s)"), cl->name, cl->hostname);
670 /* Check if owner name is a valid */
674 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s): invalid identity name"), cl->name, cl->hostname);
678 /* Check if subnet string is valid */
680 if(!(subnet = str2net(subnetstr)))
682 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s): invalid subnet string"), cl->name, cl->hostname);
686 /* Check if somebody tries to add a subnet of ourself */
688 if(!strcmp(name, myself->name))
690 syslog(LOG_ERR, _("Warning: got ADD_SUBNET from %s (%s) for ourself, restarting"),
691 cl->name, cl->hostname);
696 /* Check if the owner of the new subnet is in the connection list */
698 if(!(owner = lookup_id(name)))
700 syslog(LOG_ERR, _("Got ADD_SUBNET for %s from %s (%s) which is not in our connection list"),
701 name, cl->name, cl->hostname);
705 /* If everything is correct, add the subnet to the list of the owner */
707 subnet_add(owner, subnet);
711 for(node = connection_tree->head; node; node = node->next)
713 p = (connection_t *)node->data;
714 if(p->status.meta && p->status.active && p!= cl)
715 send_add_subnet(p, subnet);
721 int send_del_subnet(connection_t *cl, subnet_t *subnet)
727 if(cl->options & OPTION_INDIRECT)
728 owner = myself->name;
730 owner = subnet->owner->name;
732 x = send_request(cl, "%d %s %s", DEL_SUBNET, owner, netstr = net2str(subnet));
738 int del_subnet_h(connection_t *cl)
740 char subnetstr[MAX_STRING_SIZE];
741 char name[MAX_STRING_SIZE];
742 connection_t *owner, *p;
746 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING, name, subnetstr) != 3)
748 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s)"), cl->name, cl->hostname);
752 /* Check if owner name is a valid */
756 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s): invalid identity name"), cl->name, cl->hostname);
760 /* Check if subnet string is valid */
762 if(!(subnet = str2net(subnetstr)))
764 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s): invalid subnet string"), cl->name, cl->hostname);
770 /* Check if somebody tries to add a subnet of ourself */
772 if(!strcmp(name, myself->name))
774 syslog(LOG_ERR, _("Warning: got DEL_SUBNET from %s (%s) for ourself, restarting"),
775 cl->name, cl->hostname);
780 /* Check if the owner of the new subnet is in the connection list */
782 if(!(owner = lookup_id(name)))
784 syslog(LOG_ERR, _("Got DEL_SUBNET for %s from %s (%s) which is not in our connection list"),
785 name, cl->name, cl->hostname);
789 /* If everything is correct, delete the subnet from the list of the owner */
795 for(node = connection_tree->head; node; node = node->next)
797 p = (connection_t *)node->data;
798 if(p->status.meta && p->status.active && p!= cl)
799 send_del_subnet(p, subnet);
805 /* New and closed connections notification */
807 int send_add_host(connection_t *cl, connection_t *other)
810 if(!((cl->options | myself->options | other->options) & OPTION_INDIRECT))
811 return send_request(cl, "%d %s %lx:%d %lx", ADD_HOST,
812 other->name, other->address, other->port, other->options);
817 int add_host_h(connection_t *cl)
819 connection_t *old, *new, *p;
820 char name[MAX_STRING_SIZE];
823 new = new_connection();
825 if(sscanf(cl->buffer, "%*d "MAX_STRING" %lx:%hd %lx", name, &new->address, &new->port, &new->options) != 4)
827 syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s)"), cl->name, cl->hostname);
831 /* Check if identity is a valid name */
835 syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s): invalid identity name"), cl->name, cl->hostname);
836 free_connection(new);
840 /* Check if somebody tries to add ourself */
842 if(!strcmp(name, myself->name))
844 syslog(LOG_ERR, _("Warning: got ADD_HOST from %s (%s) for ourself, restarting"), cl->name, cl->hostname);
846 free_connection(new);
850 /* Fill in more of the new connection structure */
852 new->hostname = hostlookup(htonl(new->address));
854 /* Check if the new host already exists in the connnection list */
856 if((old = lookup_id(name)))
858 if((new->address == old->address) && (new->port == old->port))
860 if(debug_lvl >= DEBUG_CONNECTIONS)
861 syslog(LOG_NOTICE, _("Got duplicate ADD_HOST for %s (%s) from %s (%s)"),
862 old->name, old->hostname, name, new->hostname);
863 free_connection(new);
868 if(debug_lvl >= DEBUG_CONNECTIONS)
869 syslog(LOG_NOTICE, _("Removing old entry for %s (%s) in favour of new connection"),
870 old->name, old->hostname);
872 terminate_connection(old);
876 /* Hook it up into the connection */
878 new->name = xstrdup(name);
882 /* Tell the rest about the new host */
884 for(node = connection_tree->head; node; node = node->next)
886 p = (connection_t *)node->data;
887 if(p->status.meta && p->status.active && p!=cl)
888 send_add_host(p, new);
891 /* Fill in rest of connection structure */
894 new->status.active = 1;
895 new->cipher_pkttype = EVP_bf_cbc();
896 new->cipher_pktkeylength = cl->cipher_pkttype->key_len + cl->cipher_pkttype->iv_len;
901 int send_del_host(connection_t *cl, connection_t *other)
904 if(!((cl->options | myself->options) & OPTION_INDIRECT))
905 return send_request(cl, "%d %s %lx:%d %lx", DEL_HOST,
906 other->name, other->address, other->port, other->options);
911 int del_host_h(connection_t *cl)
913 char name[MAX_STRING_SIZE];
917 connection_t *old, *p;
920 if(sscanf(cl->buffer, "%*d "MAX_STRING" %lx:%hd %lx", name, &address, &port, &options) != 4)
922 syslog(LOG_ERR, _("Got bad DEL_HOST from %s (%s)"),
923 cl->name, cl->hostname);
927 /* Check if identity is a valid name */
931 syslog(LOG_ERR, _("Got bad DEL_HOST from %s (%s): invalid identity name"), cl->name, cl->hostname);
935 /* Check if somebody tries to delete ourself */
937 if(!strcmp(name, myself->name))
939 syslog(LOG_ERR, _("Warning: got DEL_HOST from %s (%s) for ourself, restarting"),
940 cl->name, cl->hostname);
945 /* Check if the new host already exists in the connnection list */
947 if(!(old = lookup_id(name)))
949 syslog(LOG_ERR, _("Got DEL_HOST from %s (%s) for %s which is not in our connection list"),
950 name, cl->name, cl->hostname);
954 /* Check if the rest matches */
956 if(address!=old->address || port!=old->port || options!=old->options || cl!=old->nexthop)
958 syslog(LOG_WARNING, _("Got DEL_HOST from %s (%s) for %s which doesn't match"), cl->name, cl->hostname, old->name);
962 /* Ok, since EVERYTHING seems to check out all right, delete it */
964 old->status.active = 0;
965 terminate_connection(old);
967 /* Tell the rest about the new host */
969 for(node = connection_tree->head; node; node = node->next)
971 p = (connection_t *)node->data;
972 if(p->status.meta && p->status.active && p!=cl)
973 send_del_host(p, old);
979 /* Status and error notification routines */
981 int send_status(connection_t *cl, int statusno, char *statusstring)
985 statusstring = status_text[statusno];
987 return send_request(cl, "%d %d %s", STATUS, statusno, statusstring);
990 int status_h(connection_t *cl)
993 char statusstring[MAX_STRING_SIZE];
995 if(sscanf(cl->buffer, "%*d %d "MAX_STRING, &statusno, statusstring) != 2)
997 syslog(LOG_ERR, _("Got bad STATUS from %s (%s)"),
998 cl->name, cl->hostname);
1002 if(debug_lvl >= DEBUG_STATUS)
1004 syslog(LOG_NOTICE, _("Status message from %s (%s): %s: %s"),
1005 cl->name, cl->hostname, status_text[statusno], statusstring);
1012 int send_error(connection_t *cl, int err, char *errstring)
1016 errstring = strerror(err);
1017 return send_request(cl, "%d %d %s", ERROR, err, errstring);
1020 int error_h(connection_t *cl)
1023 char errorstring[MAX_STRING_SIZE];
1025 if(sscanf(cl->buffer, "%*d %d "MAX_STRING, &err, errorstring) != 2)
1027 syslog(LOG_ERR, _("Got bad ERROR from %s (%s)"),
1028 cl->name, cl->hostname);
1032 if(debug_lvl >= DEBUG_ERROR)
1034 syslog(LOG_NOTICE, _("Error message from %s (%s): %s: %s"),
1035 cl->name, cl->hostname, strerror(err), errorstring);
1038 terminate_connection(cl);
1043 int send_termreq(connection_t *cl)
1046 return send_request(cl, "%d", TERMREQ);
1049 int termreq_h(connection_t *cl)
1052 terminate_connection(cl);
1057 int send_ping(connection_t *cl)
1059 char salt[SALTLEN*2+1];
1061 cl->status.pinged = 1;
1062 cl->last_ping_time = time(NULL);
1063 RAND_bytes(salt, SALTLEN);
1064 bin2hex(salt, salt, SALTLEN);
1065 salt[SALTLEN*2] = '\0';
1067 return send_request(cl, "%d %s", PING, salt);
1070 int ping_h(connection_t *cl)
1073 return send_pong(cl);
1076 int send_pong(connection_t *cl)
1078 char salt[SALTLEN*2+1];
1080 RAND_bytes(salt, SALTLEN);
1081 bin2hex(salt, salt, SALTLEN);
1082 salt[SALTLEN*2] = '\0';
1084 return send_request(cl, "%d %s", PONG, salt);
1087 int pong_h(connection_t *cl)
1090 cl->status.pinged = 0;
1097 int send_key_changed(connection_t *from, connection_t *cl)
1102 /* Only send this message if some other daemon requested our key previously.
1103 This reduces unnecessary key_changed broadcasts.
1106 if(from==myself && !mykeyused)
1109 for(node = connection_tree->head; node; node = node->next)
1111 p = (connection_t *)node->data;
1112 if(p != cl && p->status.meta && p->status.active)
1113 if(!(p->options & OPTION_INDIRECT) || from == myself)
1114 send_request(p, "%d %s", KEY_CHANGED, from->name);
1120 int key_changed_h(connection_t *cl)
1122 char from_id[MAX_STRING_SIZE];
1125 if(sscanf(cl->buffer, "%*d "MAX_STRING, from_id) != 1)
1127 syslog(LOG_ERR, _("Got bad KEY_CHANGED from %s (%s)"),
1128 cl->name, cl->hostname);
1132 if(!(from = lookup_id(from_id)))
1134 syslog(LOG_ERR, _("Got KEY_CHANGED from %s (%s) origin %s which does not exist in our connection list"),
1135 cl->name, cl->hostname, from_id);
1139 from->status.validkey = 0;
1140 from->status.waitingforkey = 0;
1142 if(!(from->options | cl->options | myself->options) & OPTION_INDIRECT)
1143 send_key_changed(from, cl);
1148 int send_req_key(connection_t *from, connection_t *to)
1151 return send_request(to->nexthop, "%d %s %s", REQ_KEY,
1152 from->name, to->name);
1155 int req_key_h(connection_t *cl)
1157 char from_id[MAX_STRING_SIZE];
1158 char to_id[MAX_STRING_SIZE];
1159 connection_t *from, *to;
1162 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING, from_id, to_id) != 2)
1164 syslog(LOG_ERR, _("Got bad REQ_KEY from %s (%s)"),
1165 cl->name, cl->hostname);
1169 if(!(from = lookup_id(from_id)))
1171 syslog(LOG_ERR, _("Got REQ_KEY from %s (%s) origin %s which does not exist in our connection list"),
1172 cl->name, cl->hostname, from_id);
1176 /* Check if this key request is for us */
1178 if(!strcmp(to_id, myself->name)) /* Yes, send our own key back */
1180 bin2hex(myself->cipher_pktkey, pktkey, myself->cipher_pktkeylength);
1181 pktkey[myself->cipher_pktkeylength*2] = '\0';
1182 send_ans_key(myself, from, pktkey);
1187 if(!(to = lookup_id(to_id)))
1189 syslog(LOG_ERR, _("Got REQ_KEY from %s (%s) destination %s which does not exist in our connection list"),
1190 cl->name, cl->hostname, to_id);
1194 if(to->status.validkey) /* Proxy keys */
1196 bin2hex(to->cipher_pktkey, pktkey, to->cipher_pktkeylength);
1197 pktkey[to->cipher_pktkeylength*2] = '\0';
1198 send_ans_key(to, from, pktkey);
1201 send_req_key(from, to);
1208 int send_ans_key(connection_t *from, connection_t *to, char *pktkey)
1211 return send_request(to->nexthop, "%d %s %s %s", ANS_KEY,
1212 from->name, to->name, pktkey);
1215 int ans_key_h(connection_t *cl)
1217 char from_id[MAX_STRING_SIZE];
1218 char to_id[MAX_STRING_SIZE];
1219 char pktkey[MAX_STRING_SIZE];
1221 connection_t *from, *to;
1223 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING, from_id, to_id, pktkey) != 3)
1225 syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s)"),
1226 cl->name, cl->hostname);
1230 if(!(from = lookup_id(from_id)))
1232 syslog(LOG_ERR, _("Got ANS_KEY from %s (%s) origin %s which does not exist in our connection list"),
1233 cl->name, cl->hostname, from_id);
1237 /* Check correctness of packet key */
1239 keylength = strlen(pktkey);
1241 if(keylength != from->cipher_pktkeylength*2)
1243 syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s) origin %s: invalid key length"),
1244 cl->name, cl->hostname, from->name);
1248 /* Forward it if necessary */
1250 if(strcmp(to_id, myself->name))
1252 if(!(to = lookup_id(to_id)))
1254 syslog(LOG_ERR, _("Got ANS_KEY from %s (%s) destination %s which does not exist in our connection list"),
1255 cl->name, cl->hostname, to_id);
1258 send_ans_key(from, to, pktkey);
1261 /* Update our copy of the origin's packet key */
1263 if(from->cipher_pktkey)
1264 free(from->cipher_pktkey);
1266 from->cipher_pktkey = xstrdup(pktkey);
1268 hex2bin(from->cipher_pktkey, from->cipher_pktkey, keylength);
1269 from->cipher_pktkey[keylength] = '\0';
1271 from->status.validkey = 1;
1272 from->status.waitingforkey = 0;
1279 int send_tcppacket(connection_t *cl, vpn_packet_t *packet)
1285 x = send_request(cl->nexthop, "%d %hd", PACKET, packet->len);
1290 return send_meta(cl, packet->data, packet->len);
1293 int tcppacket_h(connection_t *cl)
1297 if(sscanf(cl->buffer, "%*d %hd", &len) != 1)
1299 syslog(LOG_ERR, _("Got bad PACKET from %s (%s)"), cl->name, cl->hostname);
1303 /* Set reqlen to len, this will tell receive_meta() that a tcppacket is coming. */
1310 /* Jumptable for the request handlers */
1312 int (*request_handlers[])(connection_t*) = {
1313 id_h, metakey_h, challenge_h, chal_reply_h,
1314 status_h, error_h, termreq_h,
1316 add_host_h, del_host_h,
1317 add_subnet_h, del_subnet_h,
1318 key_changed_h, req_key_h, ans_key_h,
1324 char (*request_name[]) = {
1325 "ID", "METAKEY", "CHALLENGE", "CHAL_REPLY",
1326 "STATUS", "ERROR", "TERMREQ",
1328 "ADD_HOST", "DEL_HOST",
1329 "ADD_SUBNET", "DEL_SUBNET",
1330 "KEY_CHANGED", "REQ_KEY", "ANS_KEY",
1334 /* Status strings */
1336 char (*status_text[]) = {
1342 char (*error_text[]) = {