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.90 2001/05/25 08:36:11 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);
111 if(debug_lvl >= DEBUG_PROTOCOL)
112 syslog(LOG_DEBUG, _("Sending %s to %s (%s)"), request_name[request], cl->name, cl->hostname);
115 return send_meta(cl, buffer, len);
118 int receive_request(connection_t *cl)
122 if(sscanf(cl->buffer, "%d", &request) == 1)
124 if((request < 0) || (request >= LAST) || (request_handlers[request] == NULL))
126 syslog(LOG_ERR, _("Unknown request from %s (%s)"),
127 cl->name, cl->hostname);
132 if(debug_lvl >= DEBUG_PROTOCOL)
133 syslog(LOG_DEBUG, _("Got %s from %s (%s)"),
134 request_name[request], cl->name, cl->hostname);
137 if((cl->allow_request != ALL) && (cl->allow_request != request))
139 syslog(LOG_ERR, _("Unauthorized request from %s (%s)"), cl->name, cl->hostname);
143 if(request_handlers[request](cl))
144 /* Something went wrong. Probably scriptkiddies. Terminate. */
146 syslog(LOG_ERR, _("Error while processing %s from %s (%s)"),
147 request_name[request], cl->name, cl->hostname);
153 syslog(LOG_ERR, _("Bogus data received from %s (%s)"),
154 cl->name, cl->hostname);
161 /* Connection protocol:
170 ---------------------------------------
173 ---------------------------------------
176 ---------------------------------------
182 (E) Encrypted with symmetric cipher.
184 Part of the challenge is directly used to set the symmetric cipher
185 key and the initial vector. Since a man-in-the-middle cannot
186 decrypt the RSA challenges, this means that he cannot get or forge
187 the key for the symmetric cipher.
190 int send_id(connection_t *cl)
193 return send_request(cl, "%d %s %d %lx %hd", ID, myself->name, myself->protocol_version, myself->options, myself->port);
196 int id_h(connection_t *cl)
199 unsigned short int port;
200 char name[MAX_STRING_SIZE];
203 if(sscanf(cl->buffer, "%*d "MAX_STRING" %d %lx %hd", name, &cl->protocol_version, &cl->options, &port) != 4)
205 syslog(LOG_ERR, _("Got bad ID from %s"), cl->hostname);
209 /* Check if version matches */
211 if(cl->protocol_version != myself->protocol_version)
213 syslog(LOG_ERR, _("Peer %s (%s) uses incompatible version %d"),
214 cl->name, cl->hostname, cl->protocol_version);
218 /* Check if identity is a valid name */
222 syslog(LOG_ERR, _("Peer %s uses invalid identity name"), cl->hostname);
226 /* Copy string to cl */
228 cl->name = xstrdup(name);
230 /* Load information about peer */
232 if(read_host_config(cl))
234 syslog(LOG_ERR, _("Peer %s had unknown identity (%s)"), cl->hostname, cl->name);
238 /* First check if the host we connected to is already in our
239 connection list. If so, we are probably making a loop, which
243 if(cl->status.outgoing)
245 if((old = lookup_id(cl->name)))
247 if(debug_lvl >= DEBUG_CONNECTIONS)
248 syslog(LOG_NOTICE, _("Uplink %s (%s) is already in our connection list"), cl->name, cl->hostname);
249 cl->status.outgoing = 0;
250 old->status.outgoing = 1;
251 terminate_connection(cl);
256 /* Now we can add the name to the id tree */
260 /* And uhr... cl->port just changed so we have to unlink it from the connection tree and re-insert... */
262 node = avl_unlink(connection_tree, cl);
264 avl_insert_node(connection_tree, node);
266 /* Read in the public key, so that we can send a metakey */
268 if(read_rsa_public_key(cl))
271 cl->allow_request = METAKEY;
273 return send_metakey(cl);
276 int ack_h(connection_t *cl)
279 connection_t *old, *p;
281 avl_node_t *node, *node2;
283 /* Okay, before we active the connection, we check if there is another entry
284 in the connection list with the same name. If so, it presumably is an
285 old connection that has timed out but we don't know it yet.
288 while((old = lookup_id(cl->name)))
290 if(debug_lvl >= DEBUG_CONNECTIONS)
291 syslog(LOG_NOTICE, _("Removing old entry for %s at %s in favour of new connection from %s"),
292 cl->name, old->hostname, cl->hostname);
294 terminate_connection(old);
297 /* Activate this connection */
299 cl->allow_request = ALL;
300 cl->status.active = 1;
302 cl->cipher_pkttype = EVP_bf_cbc();
303 cl->cipher_pktkeylength = cl->cipher_pkttype->key_len + cl->cipher_pkttype->iv_len;
305 if(debug_lvl >= DEBUG_CONNECTIONS)
306 syslog(LOG_NOTICE, _("Connection with %s (%s) activated"), cl->name, cl->hostname);
309 /* Check some options */
311 if((cfg = get_config_val(cl->config, config_indirectdata)))
313 if(cfg->data.val == stupid_true)
314 cl->options |= OPTION_INDIRECT;
317 if((cfg = get_config_val(cl->config, config_tcponly)))
319 if(cfg->data.val == stupid_true)
320 cl->options |= OPTION_TCPONLY;
323 /* Send him our subnets */
325 for(node = myself->subnet_tree->head; node; node = node->next)
327 subnet = (subnet_t *)node->data;
328 send_add_subnet(cl, subnet);
331 /* And send him all the hosts and their subnets we know... */
333 for(node = connection_tree->head; node; node = node->next)
335 p = (connection_t *)node->data;
337 if(p != cl && p->status.active)
339 /* Notify others of this connection */
342 send_add_host(p, cl);
344 /* Notify new connection of everything we know */
346 send_add_host(cl, p);
348 for(node2 = p->subnet_tree->head; node2; node2 = node2->next)
350 subnet = (subnet_t *)node2->data;
351 send_add_subnet(cl, subnet);
359 int send_challenge(connection_t *cl)
364 /* CHECKME: what is most reasonable value for len? */
366 len = RSA_size(cl->rsa_key);
368 /* Allocate buffers for the challenge */
370 buffer = xmalloc(len*2+1);
373 free(cl->hischallenge);
375 cl->hischallenge = xmalloc(len);
377 /* Copy random data to the buffer */
379 RAND_bytes(cl->hischallenge, len);
384 bin2hex(cl->hischallenge, buffer, len);
385 buffer[len*2] = '\0';
388 /* Send the challenge */
390 x = send_request(cl, "%d %s", CHALLENGE, buffer);
396 int challenge_h(connection_t *cl)
398 char buffer[MAX_STRING_SIZE];
401 if(sscanf(cl->buffer, "%*d "MAX_STRING, buffer) != 1)
403 syslog(LOG_ERR, _("Got bad CHALLENGE from %s (%s)"), cl->name, cl->hostname);
407 len = RSA_size(myself->rsa_key);
409 /* Check if the length of the challenge is all right */
411 if(strlen(buffer) != len*2)
413 syslog(LOG_ERR, _("Intruder: wrong challenge length from %s (%s)"), cl->name, cl->hostname);
417 /* Allocate buffers for the challenge */
420 cl->mychallenge = xmalloc(len);
422 /* Convert the challenge from hexadecimal back to binary */
424 hex2bin(buffer,cl->mychallenge,len);
426 cl->allow_request = CHAL_REPLY;
428 /* Rest is done by send_chal_reply() */
430 return send_chal_reply(cl);
433 int send_chal_reply(connection_t *cl)
435 char hash[SHA_DIGEST_LENGTH*2+1];
439 syslog(LOG_ERR, _("Trying to send CHAL_REPLY to %s (%s) without a valid CHALLENGE"), cl->name, cl->hostname);
443 /* Calculate the hash from the challenge we received */
445 SHA1(cl->mychallenge, RSA_size(myself->rsa_key), hash);
447 /* Convert the hash to a hexadecimal formatted string */
449 bin2hex(hash,hash,SHA_DIGEST_LENGTH);
450 hash[SHA_DIGEST_LENGTH*2] = '\0';
455 return send_request(cl, "%d %s", CHAL_REPLY, hash);
458 int chal_reply_h(connection_t *cl)
460 char hishash[MAX_STRING_SIZE];
461 char myhash[SHA_DIGEST_LENGTH];
463 if(sscanf(cl->buffer, "%*d "MAX_STRING, hishash) != 1)
465 syslog(LOG_ERR, _("Got bad CHAL_REPLY from %s (%s)"), cl->name, cl->hostname);
469 /* Check if the length of the hash is all right */
471 if(strlen(hishash) != SHA_DIGEST_LENGTH*2)
473 syslog(LOG_ERR, _("Intruder: wrong challenge reply length from %s (%s)"), cl->name, cl->hostname);
477 /* Convert the hash to binary format */
479 hex2bin(hishash, hishash, SHA_DIGEST_LENGTH);
481 /* Calculate the hash from the challenge we sent */
483 SHA1(cl->hischallenge, RSA_size(cl->rsa_key), myhash);
485 /* Verify the incoming hash with the calculated hash */
487 if(memcmp(hishash, myhash, SHA_DIGEST_LENGTH))
489 syslog(LOG_ERR, _("Intruder: wrong challenge reply from %s (%s)"), cl->name, cl->hostname);
490 if(debug_lvl >= DEBUG_SCARY_THINGS)
492 bin2hex(myhash, hishash, SHA_DIGEST_LENGTH);
493 hishash[SHA_DIGEST_LENGTH*2] = '\0';
494 syslog(LOG_DEBUG, _("Expected challenge reply: %s"), hishash);
499 /* Identity has now been positively verified.
500 ack_h() handles the rest from now on.
506 int send_metakey(connection_t *cl)
511 len = RSA_size(cl->rsa_key);
513 /* Allocate buffers for the meta key */
515 buffer = xmalloc(len*2+1);
517 if(!cl->cipher_outkey)
518 cl->cipher_outkey = xmalloc(len);
520 if(!cl->cipher_outctx)
521 cl->cipher_outctx = xmalloc(sizeof(*cl->cipher_outctx));
523 /* Copy random data to the buffer */
525 RAND_bytes(cl->cipher_outkey, len);
527 /* The message we send must be smaller than the modulus of the RSA key.
528 By definition, for a key of k bits, the following formula holds:
530 2^(k-1) <= modulus < 2^(k)
532 Where ^ means "to the power of", not "xor".
533 This means that to be sure, we must choose our message < 2^(k-1).
534 This can be done by setting the most significant bit to zero.
537 cl->cipher_outkey[0] &= 0x7F;
539 if(debug_lvl >= DEBUG_SCARY_THINGS)
541 bin2hex(cl->cipher_outkey, buffer, len);
542 buffer[len*2] = '\0';
543 syslog(LOG_DEBUG, _("Generated random meta key (unencrypted): %s"), buffer);
546 /* Encrypt the random data
548 We do not use one of the PKCS padding schemes here.
549 This is allowed, because we encrypt a totally random string
550 with a length equal to that of the modulus of the RSA key.
553 if(RSA_public_encrypt(len, cl->cipher_outkey, buffer, cl->rsa_key, RSA_NO_PADDING) != len)
555 syslog(LOG_ERR, _("Error during encryption of meta key for %s (%s)"), cl->name, cl->hostname);
560 /* Convert the encrypted random data to a hexadecimal formatted string */
562 bin2hex(buffer, buffer, len);
563 buffer[len*2] = '\0';
565 /* Send the meta key */
567 x = send_request(cl, "%d %s", METAKEY, buffer);
570 /* Further outgoing requests are encrypted with the key we just generated */
572 EVP_EncryptInit(cl->cipher_outctx, EVP_bf_cfb(),
573 cl->cipher_outkey + len - EVP_bf_cfb()->key_len,
574 cl->cipher_outkey + len - EVP_bf_cfb()->key_len - EVP_bf_cfb()->iv_len);
576 cl->status.encryptout = 1;
581 int metakey_h(connection_t *cl)
583 char buffer[MAX_STRING_SIZE];
586 if(sscanf(cl->buffer, "%*d "MAX_STRING, buffer) != 1)
588 syslog(LOG_ERR, _("Got bad METAKEY from %s (%s)"), cl->name, cl->hostname);
592 len = RSA_size(myself->rsa_key);
594 /* Check if the length of the meta key is all right */
596 if(strlen(buffer) != len*2)
598 syslog(LOG_ERR, _("Intruder: wrong meta key length from %s (%s)"), cl->name, cl->hostname);
602 /* Allocate buffers for the meta key */
604 if(!cl->cipher_inkey)
605 cl->cipher_inkey = xmalloc(len);
607 if(!cl->cipher_inctx)
608 cl->cipher_inctx = xmalloc(sizeof(*cl->cipher_inctx));
610 /* Convert the challenge from hexadecimal back to binary */
612 hex2bin(buffer,buffer,len);
614 /* Decrypt the meta key */
616 if(RSA_private_decrypt(len, buffer, cl->cipher_inkey, myself->rsa_key, RSA_NO_PADDING) != len) /* See challenge() */
618 syslog(LOG_ERR, _("Error during encryption of meta key for %s (%s)"), cl->name, cl->hostname);
622 if(debug_lvl >= DEBUG_SCARY_THINGS)
624 bin2hex(cl->cipher_inkey, buffer, len);
625 buffer[len*2] = '\0';
626 syslog(LOG_DEBUG, _("Received random meta key (unencrypted): %s"), buffer);
629 /* All incoming requests will now be encrypted. */
631 EVP_DecryptInit(cl->cipher_inctx, EVP_bf_cfb(),
632 cl->cipher_inkey + len - EVP_bf_cfb()->key_len,
633 cl->cipher_inkey + len - EVP_bf_cfb()->key_len - EVP_bf_cfb()->iv_len);
635 cl->status.decryptin = 1;
637 cl->allow_request = CHALLENGE;
639 return send_challenge(cl);
642 /* Address and subnet information exchange */
644 int send_add_subnet(connection_t *cl, subnet_t *subnet)
650 if((cl->options | myself->options | subnet->owner->options) & OPTION_INDIRECT)
651 owner = myself->name;
653 owner = subnet->owner->name;
655 x = send_request(cl, "%d %s %s", ADD_SUBNET,
656 owner, netstr = net2str(subnet));
662 int add_subnet_h(connection_t *cl)
664 char subnetstr[MAX_STRING_SIZE];
665 char name[MAX_STRING_SIZE];
666 connection_t *owner, *p;
670 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING, name, subnetstr) != 2)
672 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s)"), cl->name, cl->hostname);
676 /* Check if owner name is a valid */
680 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s): invalid identity name"), cl->name, cl->hostname);
684 /* Check if subnet string is valid */
686 if(!(subnet = str2net(subnetstr)))
688 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s): invalid subnet string"), cl->name, cl->hostname);
692 /* Check if somebody tries to add a subnet of ourself */
694 if(!strcmp(name, myself->name))
696 syslog(LOG_ERR, _("Warning: got ADD_SUBNET from %s (%s) for ourself, restarting"),
697 cl->name, cl->hostname);
702 /* Check if the owner of the new subnet is in the connection list */
704 if(!(owner = lookup_id(name)))
706 syslog(LOG_ERR, _("Got ADD_SUBNET for %s from %s (%s) which is not in our connection list"),
707 name, cl->name, cl->hostname);
711 /* If everything is correct, add the subnet to the list of the owner */
713 subnet_add(owner, subnet);
717 for(node = connection_tree->head; node; node = node->next)
719 p = (connection_t *)node->data;
720 if(p->status.meta && p->status.active && p!= cl)
721 send_add_subnet(p, subnet);
727 int send_del_subnet(connection_t *cl, subnet_t *subnet)
733 if(cl->options & OPTION_INDIRECT)
734 owner = myself->name;
736 owner = subnet->owner->name;
738 x = send_request(cl, "%d %s %s", DEL_SUBNET, owner, netstr = net2str(subnet));
744 int del_subnet_h(connection_t *cl)
746 char subnetstr[MAX_STRING_SIZE];
747 char name[MAX_STRING_SIZE];
748 connection_t *owner, *p;
752 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING, name, subnetstr) != 3)
754 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s)"), cl->name, cl->hostname);
758 /* Check if owner name is a valid */
762 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s): invalid identity name"), cl->name, cl->hostname);
766 /* Check if subnet string is valid */
768 if(!(subnet = str2net(subnetstr)))
770 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s): invalid subnet string"), cl->name, cl->hostname);
776 /* Check if somebody tries to add a subnet of ourself */
778 if(!strcmp(name, myself->name))
780 syslog(LOG_ERR, _("Warning: got DEL_SUBNET from %s (%s) for ourself, restarting"),
781 cl->name, cl->hostname);
786 /* Check if the owner of the new subnet is in the connection list */
788 if(!(owner = lookup_id(name)))
790 syslog(LOG_ERR, _("Got DEL_SUBNET for %s from %s (%s) which is not in our connection list"),
791 name, cl->name, cl->hostname);
795 /* If everything is correct, delete the subnet from the list of the owner */
801 for(node = connection_tree->head; node; node = node->next)
803 p = (connection_t *)node->data;
804 if(p->status.meta && p->status.active && p!= cl)
805 send_del_subnet(p, subnet);
811 /* New and closed connections notification */
813 int send_add_host(connection_t *cl, connection_t *other)
816 if(!((cl->options | myself->options | other->options) & OPTION_INDIRECT))
817 return send_request(cl, "%d %s %lx:%d %lx", ADD_HOST,
818 other->name, other->address, other->port, other->options);
823 int add_host_h(connection_t *cl)
825 connection_t *old, *new, *p;
826 char name[MAX_STRING_SIZE];
829 new = new_connection();
831 if(sscanf(cl->buffer, "%*d "MAX_STRING" %lx:%hd %lx", name, &new->address, &new->port, &new->options) != 4)
833 syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s)"), cl->name, cl->hostname);
837 /* Check if identity is a valid name */
841 syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s): invalid identity name"), cl->name, cl->hostname);
842 free_connection(new);
846 /* Check if somebody tries to add ourself */
848 if(!strcmp(name, myself->name))
850 syslog(LOG_ERR, _("Warning: got ADD_HOST from %s (%s) for ourself, restarting"), cl->name, cl->hostname);
852 free_connection(new);
856 /* Fill in more of the new connection structure */
858 new->hostname = hostlookup(htonl(new->address));
860 /* Check if the new host already exists in the connnection list */
862 if((old = lookup_id(name)))
864 if((new->address == old->address) && (new->port == old->port))
866 if(debug_lvl >= DEBUG_CONNECTIONS)
867 syslog(LOG_NOTICE, _("Got duplicate ADD_HOST for %s (%s) from %s (%s)"),
868 old->name, old->hostname, name, new->hostname);
869 free_connection(new);
874 if(debug_lvl >= DEBUG_CONNECTIONS)
875 syslog(LOG_NOTICE, _("Removing old entry for %s (%s) in favour of new connection"),
876 old->name, old->hostname);
878 terminate_connection(old);
882 /* Hook it up into the connection */
884 new->name = xstrdup(name);
888 /* Tell the rest about the new host */
890 for(node = connection_tree->head; node; node = node->next)
892 p = (connection_t *)node->data;
893 if(p->status.meta && p->status.active && p!=cl)
894 send_add_host(p, new);
897 /* Fill in rest of connection structure */
900 new->status.active = 1;
901 new->cipher_pkttype = EVP_bf_cbc();
902 new->cipher_pktkeylength = cl->cipher_pkttype->key_len + cl->cipher_pkttype->iv_len;
907 int send_del_host(connection_t *cl, connection_t *other)
910 if(!((cl->options | myself->options) & OPTION_INDIRECT))
911 return send_request(cl, "%d %s %lx:%d %lx", DEL_HOST,
912 other->name, other->address, other->port, other->options);
917 int del_host_h(connection_t *cl)
919 char name[MAX_STRING_SIZE];
923 connection_t *old, *p;
926 if(sscanf(cl->buffer, "%*d "MAX_STRING" %lx:%hd %lx", name, &address, &port, &options) != 4)
928 syslog(LOG_ERR, _("Got bad DEL_HOST from %s (%s)"),
929 cl->name, cl->hostname);
933 /* Check if identity is a valid name */
937 syslog(LOG_ERR, _("Got bad DEL_HOST from %s (%s): invalid identity name"), cl->name, cl->hostname);
941 /* Check if somebody tries to delete ourself */
943 if(!strcmp(name, myself->name))
945 syslog(LOG_ERR, _("Warning: got DEL_HOST from %s (%s) for ourself, restarting"),
946 cl->name, cl->hostname);
951 /* Check if the new host already exists in the connnection list */
953 if(!(old = lookup_id(name)))
955 syslog(LOG_ERR, _("Got DEL_HOST from %s (%s) for %s which is not in our connection list"),
956 name, cl->name, cl->hostname);
960 /* Check if the rest matches */
962 if(address!=old->address || port!=old->port || options!=old->options || cl!=old->nexthop)
964 syslog(LOG_WARNING, _("Got DEL_HOST from %s (%s) for %s which doesn't match"), cl->name, cl->hostname, old->name);
968 /* Ok, since EVERYTHING seems to check out all right, delete it */
970 old->status.active = 0;
971 terminate_connection(old);
973 /* Tell the rest about the new host */
975 for(node = connection_tree->head; node; node = node->next)
977 p = (connection_t *)node->data;
978 if(p->status.meta && p->status.active && p!=cl)
979 send_del_host(p, old);
985 /* Status and error notification routines */
987 int send_status(connection_t *cl, int statusno, char *statusstring)
991 statusstring = status_text[statusno];
993 return send_request(cl, "%d %d %s", STATUS, statusno, statusstring);
996 int status_h(connection_t *cl)
999 char statusstring[MAX_STRING_SIZE];
1001 if(sscanf(cl->buffer, "%*d %d "MAX_STRING, &statusno, statusstring) != 2)
1003 syslog(LOG_ERR, _("Got bad STATUS from %s (%s)"),
1004 cl->name, cl->hostname);
1008 if(debug_lvl >= DEBUG_STATUS)
1010 syslog(LOG_NOTICE, _("Status message from %s (%s): %s: %s"),
1011 cl->name, cl->hostname, status_text[statusno], statusstring);
1018 int send_error(connection_t *cl, int err, char *errstring)
1022 errstring = strerror(err);
1023 return send_request(cl, "%d %d %s", ERROR, err, errstring);
1026 int error_h(connection_t *cl)
1029 char errorstring[MAX_STRING_SIZE];
1031 if(sscanf(cl->buffer, "%*d %d "MAX_STRING, &err, errorstring) != 2)
1033 syslog(LOG_ERR, _("Got bad ERROR from %s (%s)"),
1034 cl->name, cl->hostname);
1038 if(debug_lvl >= DEBUG_ERROR)
1040 syslog(LOG_NOTICE, _("Error message from %s (%s): %s: %s"),
1041 cl->name, cl->hostname, strerror(err), errorstring);
1044 terminate_connection(cl);
1049 int send_termreq(connection_t *cl)
1052 return send_request(cl, "%d", TERMREQ);
1055 int termreq_h(connection_t *cl)
1058 terminate_connection(cl);
1063 int send_ping(connection_t *cl)
1065 char salt[SALTLEN*2+1];
1067 cl->status.pinged = 1;
1068 cl->last_ping_time = time(NULL);
1069 RAND_bytes(salt, SALTLEN);
1070 bin2hex(salt, salt, SALTLEN);
1071 salt[SALTLEN*2] = '\0';
1073 return send_request(cl, "%d %s", PING, salt);
1076 int ping_h(connection_t *cl)
1079 return send_pong(cl);
1082 int send_pong(connection_t *cl)
1084 char salt[SALTLEN*2+1];
1086 RAND_bytes(salt, SALTLEN);
1087 bin2hex(salt, salt, SALTLEN);
1088 salt[SALTLEN*2] = '\0';
1090 return send_request(cl, "%d %s", PONG, salt);
1093 int pong_h(connection_t *cl)
1096 cl->status.pinged = 0;
1103 int send_key_changed(connection_t *from, connection_t *cl)
1108 /* Only send this message if some other daemon requested our key previously.
1109 This reduces unnecessary key_changed broadcasts.
1114 for(node = connection_tree->head; node; node = node->next)
1116 p = (connection_t *)node->data;
1117 if(p != cl && p->status.meta && p->status.active)
1118 if(!(p->options & OPTION_INDIRECT) || from == myself)
1119 send_request(p, "%d %s", KEY_CHANGED, from->name);
1127 int key_changed_h(connection_t *cl)
1129 char from_id[MAX_STRING_SIZE];
1132 if(sscanf(cl->buffer, "%*d "MAX_STRING, from_id) != 1)
1134 syslog(LOG_ERR, _("Got bad KEY_CHANGED from %s (%s)"),
1135 cl->name, cl->hostname);
1139 if(!(from = lookup_id(from_id)))
1141 syslog(LOG_ERR, _("Got KEY_CHANGED from %s (%s) origin %s which does not exist in our connection list"),
1142 cl->name, cl->hostname, from_id);
1146 from->status.validkey = 0;
1147 from->status.waitingforkey = 0;
1149 if(!(from->options | cl->options | myself->options) & OPTION_INDIRECT)
1150 send_key_changed(from, cl);
1155 int send_req_key(connection_t *from, connection_t *to)
1158 return send_request(to->nexthop, "%d %s %s", REQ_KEY,
1159 from->name, to->name);
1162 int req_key_h(connection_t *cl)
1164 char from_id[MAX_STRING_SIZE];
1165 char to_id[MAX_STRING_SIZE];
1166 connection_t *from, *to;
1169 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING, from_id, to_id) != 2)
1171 syslog(LOG_ERR, _("Got bad REQ_KEY from %s (%s)"),
1172 cl->name, cl->hostname);
1176 if(!(from = lookup_id(from_id)))
1178 syslog(LOG_ERR, _("Got REQ_KEY from %s (%s) origin %s which does not exist in our connection list"),
1179 cl->name, cl->hostname, from_id);
1183 /* Check if this key request is for us */
1185 if(!strcmp(to_id, myself->name)) /* Yes, send our own key back */
1187 bin2hex(myself->cipher_pktkey, pktkey, myself->cipher_pktkeylength);
1188 pktkey[myself->cipher_pktkeylength*2] = '\0';
1189 send_ans_key(myself, from, pktkey);
1194 if(!(to = lookup_id(to_id)))
1196 syslog(LOG_ERR, _("Got REQ_KEY from %s (%s) destination %s which does not exist in our connection list"),
1197 cl->name, cl->hostname, to_id);
1201 if(to->status.validkey) /* Proxy keys */
1203 bin2hex(to->cipher_pktkey, pktkey, to->cipher_pktkeylength);
1204 pktkey[to->cipher_pktkeylength*2] = '\0';
1205 send_ans_key(to, from, pktkey);
1208 send_req_key(from, to);
1215 int send_ans_key(connection_t *from, connection_t *to, char *pktkey)
1218 return send_request(to->nexthop, "%d %s %s %s", ANS_KEY,
1219 from->name, to->name, pktkey);
1222 int ans_key_h(connection_t *cl)
1224 char from_id[MAX_STRING_SIZE];
1225 char to_id[MAX_STRING_SIZE];
1226 char pktkey[MAX_STRING_SIZE];
1228 connection_t *from, *to;
1230 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING, from_id, to_id, pktkey) != 3)
1232 syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s)"),
1233 cl->name, cl->hostname);
1237 if(!(from = lookup_id(from_id)))
1239 syslog(LOG_ERR, _("Got ANS_KEY from %s (%s) origin %s which does not exist in our connection list"),
1240 cl->name, cl->hostname, from_id);
1244 /* Check correctness of packet key */
1246 keylength = strlen(pktkey);
1248 if(keylength != from->cipher_pktkeylength*2)
1250 syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s) origin %s: invalid key length"),
1251 cl->name, cl->hostname, from->name);
1255 /* Forward it if necessary */
1257 if(strcmp(to_id, myself->name))
1259 if(!(to = lookup_id(to_id)))
1261 syslog(LOG_ERR, _("Got ANS_KEY from %s (%s) destination %s which does not exist in our connection list"),
1262 cl->name, cl->hostname, to_id);
1265 send_ans_key(from, to, pktkey);
1268 /* Update our copy of the origin's packet key */
1270 if(from->cipher_pktkey)
1271 free(from->cipher_pktkey);
1273 from->cipher_pktkey = xstrdup(pktkey);
1275 hex2bin(from->cipher_pktkey, from->cipher_pktkey, keylength);
1276 from->cipher_pktkey[keylength] = '\0';
1278 from->status.validkey = 1;
1279 from->status.waitingforkey = 0;
1286 int send_tcppacket(connection_t *cl, vpn_packet_t *packet)
1290 x = send_request(cl->nexthop, "%d %hd", PACKET, packet->len);
1295 return send_meta(cl->nexthop, packet->data, packet->len);
1298 int tcppacket_h(connection_t *cl)
1300 vpn_packet_t packet;
1304 if(sscanf(cl->buffer, "%*d %hd", &packet.len) != 1)
1306 syslog(LOG_ERR, _("Got bad PACKET from %s (%s)"), cl->name, cl->hostname);
1317 x = read(cl->meta_socket, p, todo);
1322 syslog(LOG_NOTICE, _("Connection closed by %s (%s)"), cl->name, cl->hostname);
1324 if(errno==EINTR || errno==EAGAIN) /* FIXME: select() or poll() or reimplement this evil hack */
1327 syslog(LOG_ERR, _("Error during reception of PACKET from %s (%s): %m"), cl->name, cl->hostname);
1336 receive_packet(cl, &packet);
1341 /* Jumptable for the request handlers */
1343 int (*request_handlers[])(connection_t*) = {
1344 id_h, metakey_h, challenge_h, chal_reply_h,
1345 status_h, error_h, termreq_h,
1347 add_host_h, del_host_h,
1348 add_subnet_h, del_subnet_h,
1349 key_changed_h, req_key_h, ans_key_h,
1355 char (*request_name[]) = {
1356 "ID", "METAKEY", "CHALLENGE", "CHAL_REPLY",
1357 "STATUS", "ERROR", "TERMREQ",
1359 "ADD_HOST", "DEL_HOST",
1360 "ADD_SUBNET", "DEL_SUBNET",
1361 "KEY_CHANGED", "REQ_KEY", "ANS_KEY",
1365 /* Status strings */
1367 char (*status_text[]) = {
1373 char (*error_text[]) = {