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.89 2001/05/24 21:52:26 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);
1072 return send_request(cl, "%d %s", PING, salt);
1075 int ping_h(connection_t *cl)
1078 return send_pong(cl);
1081 int send_pong(connection_t *cl)
1083 char salt[SALTLEN*2+1];
1085 RAND_bytes(salt, SALTLEN);
1086 bin2hex(salt, salt, SALTLEN);
1088 return send_request(cl, "%d %s", PONG, salt);
1091 int pong_h(connection_t *cl)
1094 cl->status.pinged = 0;
1101 int send_key_changed(connection_t *from, connection_t *cl)
1106 /* Only send this message if some other daemon requested our key previously.
1107 This reduces unnecessary key_changed broadcasts.
1112 for(node = connection_tree->head; node; node = node->next)
1114 p = (connection_t *)node->data;
1115 if(p != cl && p->status.meta && p->status.active)
1116 if(!(p->options & OPTION_INDIRECT) || from == myself)
1117 send_request(p, "%d %s", KEY_CHANGED, from->name);
1125 int key_changed_h(connection_t *cl)
1127 char from_id[MAX_STRING_SIZE];
1130 if(sscanf(cl->buffer, "%*d "MAX_STRING, from_id) != 1)
1132 syslog(LOG_ERR, _("Got bad KEY_CHANGED from %s (%s)"),
1133 cl->name, cl->hostname);
1137 if(!(from = lookup_id(from_id)))
1139 syslog(LOG_ERR, _("Got KEY_CHANGED from %s (%s) origin %s which does not exist in our connection list"),
1140 cl->name, cl->hostname, from_id);
1144 from->status.validkey = 0;
1145 from->status.waitingforkey = 0;
1147 if(!(from->options | cl->options | myself->options) & OPTION_INDIRECT)
1148 send_key_changed(from, cl);
1153 int send_req_key(connection_t *from, connection_t *to)
1156 return send_request(to->nexthop, "%d %s %s", REQ_KEY,
1157 from->name, to->name);
1160 int req_key_h(connection_t *cl)
1162 char from_id[MAX_STRING_SIZE];
1163 char to_id[MAX_STRING_SIZE];
1164 connection_t *from, *to;
1167 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING, from_id, to_id) != 2)
1169 syslog(LOG_ERR, _("Got bad REQ_KEY from %s (%s)"),
1170 cl->name, cl->hostname);
1174 if(!(from = lookup_id(from_id)))
1176 syslog(LOG_ERR, _("Got REQ_KEY from %s (%s) origin %s which does not exist in our connection list"),
1177 cl->name, cl->hostname, from_id);
1181 /* Check if this key request is for us */
1183 if(!strcmp(to_id, myself->name)) /* Yes, send our own key back */
1185 bin2hex(myself->cipher_pktkey, pktkey, myself->cipher_pktkeylength);
1186 pktkey[myself->cipher_pktkeylength*2] = '\0';
1187 send_ans_key(myself, from, pktkey);
1192 if(!(to = lookup_id(to_id)))
1194 syslog(LOG_ERR, _("Got REQ_KEY from %s (%s) destination %s which does not exist in our connection list"),
1195 cl->name, cl->hostname, to_id);
1199 if(to->status.validkey) /* Proxy keys */
1201 bin2hex(to->cipher_pktkey, pktkey, to->cipher_pktkeylength);
1202 pktkey[to->cipher_pktkeylength*2] = '\0';
1203 send_ans_key(to, from, pktkey);
1206 send_req_key(from, to);
1213 int send_ans_key(connection_t *from, connection_t *to, char *pktkey)
1216 return send_request(to->nexthop, "%d %s %s %s", ANS_KEY,
1217 from->name, to->name, pktkey);
1220 int ans_key_h(connection_t *cl)
1222 char from_id[MAX_STRING_SIZE];
1223 char to_id[MAX_STRING_SIZE];
1224 char pktkey[MAX_STRING_SIZE];
1226 connection_t *from, *to;
1228 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING, from_id, to_id, pktkey) != 3)
1230 syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s)"),
1231 cl->name, cl->hostname);
1235 if(!(from = lookup_id(from_id)))
1237 syslog(LOG_ERR, _("Got ANS_KEY from %s (%s) origin %s which does not exist in our connection list"),
1238 cl->name, cl->hostname, from_id);
1242 /* Check correctness of packet key */
1244 keylength = strlen(pktkey);
1246 if(keylength != from->cipher_pktkeylength*2)
1248 syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s) origin %s: invalid key length"),
1249 cl->name, cl->hostname, from->name);
1253 /* Forward it if necessary */
1255 if(strcmp(to_id, myself->name))
1257 if(!(to = lookup_id(to_id)))
1259 syslog(LOG_ERR, _("Got ANS_KEY from %s (%s) destination %s which does not exist in our connection list"),
1260 cl->name, cl->hostname, to_id);
1263 send_ans_key(from, to, pktkey);
1266 /* Update our copy of the origin's packet key */
1268 if(from->cipher_pktkey)
1269 free(from->cipher_pktkey);
1271 from->cipher_pktkey = xstrdup(pktkey);
1273 hex2bin(from->cipher_pktkey, from->cipher_pktkey, keylength);
1274 from->cipher_pktkey[keylength] = '\0';
1276 from->status.validkey = 1;
1277 from->status.waitingforkey = 0;
1284 int send_tcppacket(connection_t *cl, vpn_packet_t *packet)
1288 x = send_request(cl->nexthop, "%d %hd", PACKET, packet->len);
1293 return send_meta(cl->nexthop, packet->data, packet->len);
1296 int tcppacket_h(connection_t *cl)
1298 vpn_packet_t packet;
1302 if(sscanf(cl->buffer, "%*d %hd", &packet.len) != 1)
1304 syslog(LOG_ERR, _("Got bad PACKET from %s (%s)"), cl->name, cl->hostname);
1315 x = read(cl->meta_socket, p, todo);
1320 syslog(LOG_NOTICE, _("Connection closed by %s (%s)"), cl->name, cl->hostname);
1322 if(errno==EINTR || errno==EAGAIN) /* FIXME: select() or poll() or reimplement this evil hack */
1325 syslog(LOG_ERR, _("Error during reception of PACKET from %s (%s): %m"), cl->name, cl->hostname);
1334 receive_packet(cl, &packet);
1339 /* Jumptable for the request handlers */
1341 int (*request_handlers[])(connection_t*) = {
1342 id_h, metakey_h, challenge_h, chal_reply_h,
1343 status_h, error_h, termreq_h,
1345 add_host_h, del_host_h,
1346 add_subnet_h, del_subnet_h,
1347 key_changed_h, req_key_h, ans_key_h,
1353 char (*request_name[]) = {
1354 "ID", "METAKEY", "CHALLENGE", "CHAL_REPLY",
1355 "STATUS", "ERROR", "TERMREQ",
1357 "ADD_HOST", "DEL_HOST",
1358 "ADD_SUBNET", "DEL_SUBNET",
1359 "KEY_CHANGED", "REQ_KEY", "ANS_KEY",
1363 /* Status strings */
1365 char (*status_text[]) = {
1371 char (*error_text[]) = {