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.85 2001/03/04 13:59:28 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"
71 int check_id(char *id)
75 for (i = 0; i < strlen(id); i++)
76 if(!isalnum(id[i]) && id[i] != '_')
82 /* Generic request routines - takes care of logging and error
85 int send_request(connection_t *cl, const char *format, ...)
88 char buffer[MAXBUFSIZE];
92 /* Use vsnprintf instead of vasprintf: faster, no memory
93 fragmentation, cleanup is automatic, and there is a limit on the
94 input buffer anyway */
96 va_start(args, format);
97 len = vsnprintf(buffer, MAXBUFSIZE, format, args);
98 request = va_arg(args, int);
101 if(len < 0 || len > MAXBUFSIZE-1)
103 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)
110 syslog(LOG_DEBUG, _("Sending %s to %s (%s)"), request_name[request], cl->name, cl->hostname);
113 return send_meta(cl, buffer, len);
116 int receive_request(connection_t *cl)
120 if(sscanf(cl->buffer, "%d", &request) == 1)
122 if((request < 0) || (request >= LAST) || (request_handlers[request] == NULL))
124 syslog(LOG_ERR, _("Unknown request from %s (%s)"),
125 cl->name, cl->hostname);
130 if(debug_lvl >= DEBUG_PROTOCOL)
131 syslog(LOG_DEBUG, _("Got %s from %s (%s)"),
132 request_name[request], cl->name, cl->hostname);
135 if((cl->allow_request != ALL) && (cl->allow_request != request))
137 syslog(LOG_ERR, _("Unauthorized request from %s (%s)"), cl->name, cl->hostname);
141 if(request_handlers[request](cl))
142 /* Something went wrong. Probably scriptkiddies. Terminate. */
144 syslog(LOG_ERR, _("Error while processing %s from %s (%s)"),
145 request_name[request], cl->name, cl->hostname);
151 syslog(LOG_ERR, _("Bogus data received from %s (%s)"),
152 cl->name, cl->hostname);
159 /* Connection protocol:
168 ---------------------------------------
171 ---------------------------------------
174 ---------------------------------------
180 (E) Encrypted with symmetric cipher.
182 Part of the challenge is directly used to set the symmetric cipher
183 key and the initial vector. Since a man-in-the-middle cannot
184 decrypt the RSA challenges, this means that he cannot get or forge
185 the key for the symmetric cipher.
188 int send_id(connection_t *cl)
191 return send_request(cl, "%d %s %d %lx %hd", ID, myself->name, myself->protocol_version, myself->options, myself->port);
194 int id_h(connection_t *cl)
197 unsigned short int port;
198 char name[MAX_STRING_SIZE];
201 if(sscanf(cl->buffer, "%*d "MAX_STRING" %d %lx %hd", name, &cl->protocol_version, &cl->options, &port) != 4)
203 syslog(LOG_ERR, _("Got bad ID from %s"), cl->hostname);
207 /* Check if version matches */
209 if(cl->protocol_version != myself->protocol_version)
211 syslog(LOG_ERR, _("Peer %s (%s) uses incompatible version %d"),
212 cl->name, cl->hostname, cl->protocol_version);
216 /* Check if identity is a valid name */
220 syslog(LOG_ERR, _("Peer %s uses invalid identity name"), cl->hostname);
224 /* Copy string to cl */
226 cl->name = xstrdup(name);
228 /* Load information about peer */
230 if(read_host_config(cl))
232 syslog(LOG_ERR, _("Peer %s had unknown identity (%s)"), cl->hostname, cl->name);
236 /* First check if the host we connected to is already in our
237 connection list. If so, we are probably making a loop, which
241 if(cl->status.outgoing)
243 if((old = lookup_id(cl->name)))
245 if(debug_lvl >= DEBUG_CONNECTIONS)
246 syslog(LOG_NOTICE, _("Uplink %s (%s) is already in our connection list"), cl->name, cl->hostname);
247 cl->status.outgoing = 0;
248 old->status.outgoing = 1;
249 terminate_connection(cl);
254 /* Now we can add the name to the id tree */
258 /* And uhr... cl->port just changed so we have to unlink it from the connection tree and re-insert... */
260 node = avl_unlink(connection_tree, cl);
262 avl_insert_node(connection_tree, node);
264 /* Read in the public key, so that we can send a metakey */
266 if(read_rsa_public_key(cl))
269 cl->allow_request = METAKEY;
271 return send_metakey(cl);
274 int ack_h(connection_t *cl)
277 connection_t *old, *p;
279 avl_node_t *node, *node2;
281 /* Okay, before we active the connection, we check if there is another entry
282 in the connection list with the same name. If so, it presumably is an
283 old connection that has timed out but we don't know it yet.
286 while((old = lookup_id(cl->name)))
288 if(debug_lvl >= DEBUG_CONNECTIONS)
289 syslog(LOG_NOTICE, _("Removing old entry for %s at %s in favour of new connection from %s"),
290 cl->name, old->hostname, cl->hostname);
292 terminate_connection(old);
295 /* Activate this connection */
297 cl->allow_request = ALL;
298 cl->status.active = 1;
300 cl->cipher_pkttype = EVP_bf_cbc();
301 cl->cipher_pktkeylength = cl->cipher_pkttype->key_len + cl->cipher_pkttype->iv_len;
303 if(debug_lvl >= DEBUG_CONNECTIONS)
304 syslog(LOG_NOTICE, _("Connection with %s (%s) activated"), cl->name, cl->hostname);
307 /* Check some options */
309 if((cfg = get_config_val(cl->config, config_indirectdata)))
311 if(cfg->data.val == stupid_true)
312 cl->options |= OPTION_INDIRECT;
315 if((cfg = get_config_val(cl->config, config_tcponly)))
317 if(cfg->data.val == stupid_true)
318 cl->options |= OPTION_TCPONLY;
321 /* Send him our subnets */
323 for(node = myself->subnet_tree->head; node; node = node->next)
325 subnet = (subnet_t *)node->data;
326 send_add_subnet(cl, subnet);
328 /* And send him all the hosts and their subnets we know... */
330 for(node = connection_tree->head; node; node = node->next)
332 p = (connection_t *)node->data;
334 if(p != cl && p->status.active)
336 /* Notify others of this connection */
339 send_add_host(p, cl);
341 /* Notify new connection of everything we know */
343 send_add_host(cl, p);
345 for(node2 = p->subnet_tree->head; node2; node2 = node2->next)
347 subnet = (subnet_t *)node2->data;
348 send_add_subnet(cl, subnet);
356 int send_challenge(connection_t *cl)
361 /* CHECKME: what is most reasonable value for len? */
363 len = RSA_size(cl->rsa_key);
365 /* Allocate buffers for the challenge */
367 buffer = xmalloc(len*2+1);
370 free(cl->hischallenge);
372 cl->hischallenge = xmalloc(len);
374 /* Copy random data to the buffer */
376 RAND_bytes(cl->hischallenge, len);
381 bin2hex(cl->hischallenge, buffer, len);
382 buffer[len*2] = '\0';
385 /* Send the challenge */
387 x = send_request(cl, "%d %s", CHALLENGE, buffer);
393 int challenge_h(connection_t *cl)
395 char buffer[MAX_STRING_SIZE];
398 if(sscanf(cl->buffer, "%*d "MAX_STRING, buffer) != 1)
400 syslog(LOG_ERR, _("Got bad CHALLENGE from %s (%s)"), cl->name, cl->hostname);
404 len = RSA_size(myself->rsa_key);
406 /* Check if the length of the challenge is all right */
408 if(strlen(buffer) != len*2)
410 syslog(LOG_ERR, _("Intruder: wrong challenge length from %s (%s)"), cl->name, cl->hostname);
414 /* Allocate buffers for the challenge */
417 cl->mychallenge = xmalloc(len);
419 /* Convert the challenge from hexadecimal back to binary */
421 hex2bin(buffer,cl->mychallenge,len);
423 cl->allow_request = CHAL_REPLY;
425 /* Rest is done by send_chal_reply() */
427 return send_chal_reply(cl);
430 int send_chal_reply(connection_t *cl)
432 char hash[SHA_DIGEST_LENGTH*2+1];
436 syslog(LOG_ERR, _("Trying to send CHAL_REPLY to %s (%s) without a valid CHALLENGE"), cl->name, cl->hostname);
440 /* Calculate the hash from the challenge we received */
442 SHA1(cl->mychallenge, RSA_size(myself->rsa_key), hash);
444 /* Convert the hash to a hexadecimal formatted string */
446 bin2hex(hash,hash,SHA_DIGEST_LENGTH);
447 hash[SHA_DIGEST_LENGTH*2] = '\0';
452 return send_request(cl, "%d %s", CHAL_REPLY, hash);
455 int chal_reply_h(connection_t *cl)
457 char hishash[MAX_STRING_SIZE];
458 char myhash[SHA_DIGEST_LENGTH];
460 if(sscanf(cl->buffer, "%*d "MAX_STRING, hishash) != 1)
462 syslog(LOG_ERR, _("Got bad CHAL_REPLY from %s (%s)"), cl->name, cl->hostname);
466 /* Check if the length of the hash is all right */
468 if(strlen(hishash) != SHA_DIGEST_LENGTH*2)
470 syslog(LOG_ERR, _("Intruder: wrong challenge reply length from %s (%s)"), cl->name, cl->hostname);
474 /* Convert the hash to binary format */
476 hex2bin(hishash, hishash, SHA_DIGEST_LENGTH);
478 /* Calculate the hash from the challenge we sent */
480 SHA1(cl->hischallenge, RSA_size(cl->rsa_key), myhash);
482 /* Verify the incoming hash with the calculated hash */
484 if(memcmp(hishash, myhash, SHA_DIGEST_LENGTH))
486 syslog(LOG_ERR, _("Intruder: wrong challenge reply from %s (%s)"), cl->name, cl->hostname);
487 if(debug_lvl >= DEBUG_SCARY_THINGS)
489 bin2hex(myhash, hishash, SHA_DIGEST_LENGTH);
490 hishash[SHA_DIGEST_LENGTH*2] = '\0';
491 syslog(LOG_DEBUG, _("Expected challenge reply: %s"), hishash);
496 /* Identity has now been positively verified.
497 ack_h() handles the rest from now on.
503 int send_metakey(connection_t *cl)
508 len = RSA_size(cl->rsa_key);
510 /* Allocate buffers for the meta key */
512 buffer = xmalloc(len*2+1);
514 if(!cl->cipher_outkey)
515 cl->cipher_outkey = xmalloc(len);
517 if(!cl->cipher_outctx)
518 cl->cipher_outctx = xmalloc(sizeof(*cl->cipher_outctx));
520 /* Copy random data to the buffer */
522 RAND_bytes(cl->cipher_outkey, len);
524 /* The message we send must be smaller than the modulus of the RSA key.
525 By definition, for a key of k bits, the following formula holds:
527 2^(k-1) <= modulus < 2^(k)
529 Where ^ means "to the power of", not "xor".
530 This means that to be sure, we must choose our message < 2^(k-1).
531 This can be done by setting the most significant bit to zero.
534 cl->cipher_outkey[0] &= 0x7F;
536 if(debug_lvl >= DEBUG_SCARY_THINGS)
538 bin2hex(cl->cipher_outkey, buffer, len);
539 buffer[len*2] = '\0';
540 syslog(LOG_DEBUG, _("Generated random meta key (unencrypted): %s"), buffer);
543 /* Encrypt the random data
545 We do not use one of the PKCS padding schemes here.
546 This is allowed, because we encrypt a totally random string
547 with a length equal to that of the modulus of the RSA key.
550 if(RSA_public_encrypt(len, cl->cipher_outkey, buffer, cl->rsa_key, RSA_NO_PADDING) != len)
552 syslog(LOG_ERR, _("Error during encryption of meta key for %s (%s)"), cl->name, cl->hostname);
557 /* Convert the encrypted random data to a hexadecimal formatted string */
559 bin2hex(buffer, buffer, len);
560 buffer[len*2] = '\0';
562 /* Send the meta key */
564 x = send_request(cl, "%d %s", METAKEY, buffer);
567 /* Further outgoing requests are encrypted with the key we just generated */
569 EVP_EncryptInit(cl->cipher_outctx, EVP_bf_cfb(),
570 cl->cipher_outkey + len - EVP_bf_cfb()->key_len,
571 cl->cipher_outkey + len - EVP_bf_cfb()->key_len - EVP_bf_cfb()->iv_len);
573 cl->status.encryptout = 1;
578 int metakey_h(connection_t *cl)
580 char buffer[MAX_STRING_SIZE];
583 if(sscanf(cl->buffer, "%*d "MAX_STRING, buffer) != 1)
585 syslog(LOG_ERR, _("Got bad METAKEY from %s (%s)"), cl->name, cl->hostname);
589 len = RSA_size(myself->rsa_key);
591 /* Check if the length of the meta key is all right */
593 if(strlen(buffer) != len*2)
595 syslog(LOG_ERR, _("Intruder: wrong meta key length from %s (%s)"), cl->name, cl->hostname);
599 /* Allocate buffers for the meta key */
601 if(!cl->cipher_inkey)
602 cl->cipher_inkey = xmalloc(len);
604 if(!cl->cipher_inctx)
605 cl->cipher_inctx = xmalloc(sizeof(*cl->cipher_inctx));
607 /* Convert the challenge from hexadecimal back to binary */
609 hex2bin(buffer,buffer,len);
611 /* Decrypt the meta key */
613 if(RSA_private_decrypt(len, buffer, cl->cipher_inkey, myself->rsa_key, RSA_NO_PADDING) != len) /* See challenge() */
615 syslog(LOG_ERR, _("Error during encryption of meta key for %s (%s)"), cl->name, cl->hostname);
619 if(debug_lvl >= DEBUG_SCARY_THINGS)
621 bin2hex(cl->cipher_inkey, buffer, len);
622 buffer[len*2] = '\0';
623 syslog(LOG_DEBUG, _("Received random meta key (unencrypted): %s"), buffer);
626 /* All incoming requests will now be encrypted. */
628 EVP_DecryptInit(cl->cipher_inctx, EVP_bf_cfb(),
629 cl->cipher_inkey + len - EVP_bf_cfb()->key_len,
630 cl->cipher_inkey + len - EVP_bf_cfb()->key_len - EVP_bf_cfb()->iv_len);
632 cl->status.decryptin = 1;
634 cl->allow_request = CHALLENGE;
636 return send_challenge(cl);
639 /* Address and subnet information exchange */
641 int send_add_subnet(connection_t *cl, subnet_t *subnet)
647 if(cl->options & OPTION_INDIRECT)
648 owner = myself->name;
650 owner = subnet->owner->name;
652 x = send_request(cl, "%d %s %s", ADD_SUBNET,
653 owner, netstr = net2str(subnet));
659 int add_subnet_h(connection_t *cl)
661 char subnetstr[MAX_STRING_SIZE];
662 char name[MAX_STRING_SIZE];
663 connection_t *owner, *p;
667 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING, name, subnetstr) != 2)
669 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s)"), cl->name, cl->hostname);
673 /* Check if owner name is a valid */
677 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s): invalid identity name"), cl->name, cl->hostname);
681 /* Check if subnet string is valid */
683 if(!(subnet = str2net(subnetstr)))
685 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s): invalid subnet string"), cl->name, cl->hostname);
689 /* Check if somebody tries to add a subnet of ourself */
691 if(!strcmp(name, myself->name))
693 syslog(LOG_ERR, _("Warning: got ADD_SUBNET from %s (%s) for ourself, restarting"),
694 cl->name, cl->hostname);
699 /* Check if the owner of the new subnet is in the connection list */
701 if(!(owner = lookup_id(name)))
703 syslog(LOG_ERR, _("Got ADD_SUBNET for %s from %s (%s) which is not in our connection list"),
704 name, cl->name, cl->hostname);
708 /* If everything is correct, add the subnet to the list of the owner */
710 subnet_add(owner, subnet);
714 for(node = connection_tree->head; node; node = node->next)
716 p = (connection_t *)node->data;
717 if(p->status.meta && p->status.active && p!= cl)
718 send_add_subnet(p, subnet);
724 int send_del_subnet(connection_t *cl, subnet_t *subnet)
730 if(cl->options & OPTION_INDIRECT)
731 owner = myself->name;
733 owner = subnet->owner->name;
735 x = send_request(cl, "%d %s %s", DEL_SUBNET, owner, netstr = net2str(subnet));
741 int del_subnet_h(connection_t *cl)
743 char subnetstr[MAX_STRING_SIZE];
744 char name[MAX_STRING_SIZE];
745 connection_t *owner, *p;
749 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING, name, subnetstr) != 3)
751 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s)"), cl->name, cl->hostname);
755 /* Check if owner name is a valid */
759 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s): invalid identity name"), cl->name, cl->hostname);
763 /* Check if subnet string is valid */
765 if(!(subnet = str2net(subnetstr)))
767 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s): invalid subnet string"), cl->name, cl->hostname);
773 /* Check if somebody tries to add a subnet of ourself */
775 if(!strcmp(name, myself->name))
777 syslog(LOG_ERR, _("Warning: got DEL_SUBNET from %s (%s) for ourself, restarting"),
778 cl->name, cl->hostname);
783 /* Check if the owner of the new subnet is in the connection list */
785 if(!(owner = lookup_id(name)))
787 syslog(LOG_ERR, _("Got DEL_SUBNET for %s from %s (%s) which is not in our connection list"),
788 name, cl->name, cl->hostname);
792 /* If everything is correct, delete the subnet from the list of the owner */
798 for(node = connection_tree->head; node; node = node->next)
800 p = (connection_t *)node->data;
801 if(p->status.meta && p->status.active && p!= cl)
802 send_del_subnet(p, subnet);
808 /* New and closed connections notification */
810 int send_add_host(connection_t *cl, connection_t *other)
813 if(!(cl->options & OPTION_INDIRECT))
814 return send_request(cl, "%d %s %lx:%d %lx", ADD_HOST,
815 other->name, other->address, other->port, other->options);
820 int add_host_h(connection_t *cl)
822 connection_t *old, *new, *p;
823 char name[MAX_STRING_SIZE];
826 new = new_connection();
828 if(sscanf(cl->buffer, "%*d "MAX_STRING" %lx:%hd %lx", name, &new->address, &new->port, &new->options) != 4)
830 syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s)"), cl->name, cl->hostname);
834 /* Check if identity is a valid name */
838 syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s): invalid identity name"), cl->name, cl->hostname);
839 free_connection(new);
843 /* Check if somebody tries to add ourself */
845 if(!strcmp(name, myself->name))
847 syslog(LOG_ERR, _("Warning: got ADD_HOST from %s (%s) for ourself, restarting"), cl->name, cl->hostname);
849 free_connection(new);
853 /* Fill in more of the new connection structure */
855 new->hostname = hostlookup(htonl(new->address));
857 /* Check if the new host already exists in the connnection list */
859 if((old = lookup_id(name)))
861 if((new->address == old->address) && (new->port == old->port))
863 if(debug_lvl >= DEBUG_CONNECTIONS)
864 syslog(LOG_NOTICE, _("Got duplicate ADD_HOST for %s (%s) from %s (%s)"),
865 old->name, old->hostname, name, new->hostname);
866 free_connection(new);
871 if(debug_lvl >= DEBUG_CONNECTIONS)
872 syslog(LOG_NOTICE, _("Removing old entry for %s (%s) in favour of new connection"),
873 old->name, old->hostname);
875 terminate_connection(old);
879 /* Hook it up into the connection */
881 new->name = xstrdup(name);
885 /* Tell the rest about the new host */
887 for(node = connection_tree->head; node; node = node->next)
889 p = (connection_t *)node->data;
890 if(p->status.meta && p->status.active && p!=cl)
891 send_add_host(p, new);
894 /* Fill in rest of connection structure */
897 new->status.active = 1;
898 new->cipher_pkttype = EVP_bf_cbc();
899 new->cipher_pktkeylength = cl->cipher_pkttype->key_len + cl->cipher_pkttype->iv_len;
904 int send_del_host(connection_t *cl, connection_t *other)
907 if(!(cl->options & OPTION_INDIRECT))
908 return send_request(cl, "%d %s %lx:%d %lx", DEL_HOST,
909 other->name, other->address, other->port, other->options);
914 int del_host_h(connection_t *cl)
916 char name[MAX_STRING_SIZE];
920 connection_t *old, *p;
923 if(sscanf(cl->buffer, "%*d "MAX_STRING" %lx:%hd %lx", name, &address, &port, &options) != 4)
925 syslog(LOG_ERR, _("Got bad DEL_HOST from %s (%s)"),
926 cl->name, cl->hostname);
930 /* Check if identity is a valid name */
934 syslog(LOG_ERR, _("Got bad DEL_HOST from %s (%s): invalid identity name"), cl->name, cl->hostname);
938 /* Check if somebody tries to delete ourself */
940 if(!strcmp(name, myself->name))
942 syslog(LOG_ERR, _("Warning: got DEL_HOST from %s (%s) for ourself, restarting"),
943 cl->name, cl->hostname);
948 /* Check if the new host already exists in the connnection list */
950 if(!(old = lookup_id(name)))
952 syslog(LOG_ERR, _("Got DEL_HOST from %s (%s) for %s which is not in our connection list"),
953 name, cl->name, cl->hostname);
957 /* Check if the rest matches */
959 if(address!=old->address || port!=old->port || options!=old->options || cl!=old->nexthop)
961 syslog(LOG_WARNING, _("Got DEL_HOST from %s (%s) for %s which doesn't match"), cl->name, cl->hostname, old->name);
965 /* Ok, since EVERYTHING seems to check out all right, delete it */
967 old->status.active = 0;
968 terminate_connection(old);
970 /* Tell the rest about the new host */
972 for(node = connection_tree->head; node; node = node->next)
974 p = (connection_t *)node->data;
975 if(p->status.meta && p->status.active && p!=cl)
976 send_del_host(p, old);
982 /* Status and error notification routines */
984 int send_status(connection_t *cl, int statusno, char *statusstring)
988 statusstring = status_text[statusno];
990 return send_request(cl, "%d %d %s", STATUS, statusno, statusstring);
993 int status_h(connection_t *cl)
996 char statusstring[MAX_STRING_SIZE];
998 if(sscanf(cl->buffer, "%*d %d "MAX_STRING, &statusno, statusstring) != 2)
1000 syslog(LOG_ERR, _("Got bad STATUS from %s (%s)"),
1001 cl->name, cl->hostname);
1005 if(debug_lvl >= DEBUG_STATUS)
1007 syslog(LOG_NOTICE, _("Status message from %s (%s): %s: %s"),
1008 cl->name, cl->hostname, status_text[statusno], statusstring);
1015 int send_error(connection_t *cl, int err, char *errstring)
1019 errstring = strerror(err);
1020 return send_request(cl, "%d %d %s", ERROR, err, errstring);
1023 int error_h(connection_t *cl)
1026 char errorstring[MAX_STRING_SIZE];
1028 if(sscanf(cl->buffer, "%*d %d "MAX_STRING, &err, errorstring) != 2)
1030 syslog(LOG_ERR, _("Got bad ERROR from %s (%s)"),
1031 cl->name, cl->hostname);
1035 if(debug_lvl >= DEBUG_ERROR)
1037 syslog(LOG_NOTICE, _("Error message from %s (%s): %s: %s"),
1038 cl->name, cl->hostname, strerror(err), errorstring);
1041 terminate_connection(cl);
1046 int send_termreq(connection_t *cl)
1049 return send_request(cl, "%d", TERMREQ);
1052 int termreq_h(connection_t *cl)
1055 terminate_connection(cl);
1060 int send_ping(connection_t *cl)
1063 cl->status.pinged = 1;
1064 cl->last_ping_time = time(NULL);
1066 return send_request(cl, "%d", PING);
1069 int ping_h(connection_t *cl)
1072 return send_pong(cl);
1075 int send_pong(connection_t *cl)
1078 return send_request(cl, "%d", PONG);
1081 int pong_h(connection_t *cl)
1084 cl->status.pinged = 0;
1091 int send_key_changed(connection_t *from, connection_t *cl)
1096 for(node = connection_tree->head; node; node = node->next)
1098 p = (connection_t *)node->data;
1099 if(p != cl && p->status.meta && p->status.active)
1100 if(!(p->options & OPTION_INDIRECT) || from == myself)
1101 send_request(p, "%d %s", KEY_CHANGED, from->name);
1107 int key_changed_h(connection_t *cl)
1109 char from_id[MAX_STRING_SIZE];
1112 if(sscanf(cl->buffer, "%*d "MAX_STRING, from_id) != 1)
1114 syslog(LOG_ERR, _("Got bad KEY_CHANGED from %s (%s)"),
1115 cl->name, cl->hostname);
1119 if(!(from = lookup_id(from_id)))
1121 syslog(LOG_ERR, _("Got KEY_CHANGED from %s (%s) origin %s which does not exist in our connection list"),
1122 cl->name, cl->hostname, from_id);
1126 from->status.validkey = 0;
1127 from->status.waitingforkey = 0;
1129 send_key_changed(from, cl);
1134 int send_req_key(connection_t *from, connection_t *to)
1137 return send_request(to->nexthop, "%d %s %s", REQ_KEY,
1138 from->name, to->name);
1141 int req_key_h(connection_t *cl)
1143 char from_id[MAX_STRING_SIZE];
1144 char to_id[MAX_STRING_SIZE];
1145 connection_t *from, *to;
1148 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING, from_id, to_id) != 2)
1150 syslog(LOG_ERR, _("Got bad REQ_KEY from %s (%s)"),
1151 cl->name, cl->hostname);
1155 if(!(from = lookup_id(from_id)))
1157 syslog(LOG_ERR, _("Got REQ_KEY from %s (%s) origin %s which does not exist in our connection list"),
1158 cl->name, cl->hostname, from_id);
1162 /* Check if this key request is for us */
1164 if(!strcmp(to_id, myself->name))
1166 bin2hex(myself->cipher_pktkey, pktkey, myself->cipher_pktkeylength);
1167 pktkey[myself->cipher_pktkeylength*2] = '\0';
1168 send_ans_key(myself, from, pktkey);
1172 if(!(to = lookup_id(to_id)))
1174 syslog(LOG_ERR, _("Got REQ_KEY from %s (%s) destination %s which does not exist in our connection list"),
1175 cl->name, cl->hostname, to_id);
1179 if(to->status.validkey) /* Proxy keys */
1181 bin2hex(to->cipher_pktkey, pktkey, to->cipher_pktkeylength);
1182 pktkey[to->cipher_pktkeylength*2] = '\0';
1183 send_ans_key(to, from, pktkey);
1186 send_req_key(from, to);
1193 int send_ans_key(connection_t *from, connection_t *to, char *pktkey)
1196 return send_request(to->nexthop, "%d %s %s %s", ANS_KEY,
1197 from->name, to->name, pktkey);
1200 int ans_key_h(connection_t *cl)
1202 char from_id[MAX_STRING_SIZE];
1203 char to_id[MAX_STRING_SIZE];
1204 char pktkey[MAX_STRING_SIZE];
1206 connection_t *from, *to;
1208 if(sscanf(cl->buffer, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING, from_id, to_id, pktkey) != 3)
1210 syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s)"),
1211 cl->name, cl->hostname);
1215 if(!(from = lookup_id(from_id)))
1217 syslog(LOG_ERR, _("Got ANS_KEY from %s (%s) origin %s which does not exist in our connection list"),
1218 cl->name, cl->hostname, from_id);
1222 /* Check correctness of packet key */
1224 keylength = strlen(pktkey);
1226 if(keylength != from->cipher_pktkeylength*2)
1228 syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s) origin %s: invalid key length"),
1229 cl->name, cl->hostname, from->name);
1233 /* Forward it if necessary */
1235 if(strcmp(to_id, myself->name))
1237 if(!(to = lookup_id(to_id)))
1239 syslog(LOG_ERR, _("Got ANS_KEY from %s (%s) destination %s which does not exist in our connection list"),
1240 cl->name, cl->hostname, to_id);
1243 send_ans_key(from, to, pktkey);
1246 /* Update our copy of the origin's packet key */
1248 if(from->cipher_pktkey)
1249 free(from->cipher_pktkey);
1251 from->cipher_pktkey = xstrdup(pktkey);
1253 hex2bin(from->cipher_pktkey, from->cipher_pktkey, keylength);
1254 from->cipher_pktkey[keylength] = '\0';
1256 from->status.validkey = 1;
1257 from->status.waitingforkey = 0;
1264 int send_tcppacket(connection_t *cl, vpn_packet_t *packet)
1268 x = send_request(cl->nexthop, "%d %hd", PACKET, packet->len);
1273 return send_meta(cl->nexthop, packet->data, packet->len);
1276 int tcppacket_h(connection_t *cl)
1278 vpn_packet_t packet;
1282 if(sscanf(cl->buffer, "%*d %hd", &packet.len) != 1)
1284 syslog(LOG_ERR, _("Got bad PACKET from %s (%s)"), cl->name, cl->hostname);
1295 x = read(cl->meta_socket, p, todo);
1300 syslog(LOG_NOTICE, _("Connection closed by %s (%s)"), cl->name, cl->hostname);
1302 if(errno==EINTR || errno==EAGAIN) /* FIXME: select() or poll() or reimplement this evil hack */
1305 syslog(LOG_ERR, _("Error during reception of PACKET from %s (%s): %m"), cl->name, cl->hostname);
1314 receive_packet(cl, &packet);
1319 /* Jumptable for the request handlers */
1321 int (*request_handlers[])(connection_t*) = {
1322 id_h, metakey_h, challenge_h, chal_reply_h,
1323 status_h, error_h, termreq_h,
1325 add_host_h, del_host_h,
1326 add_subnet_h, del_subnet_h,
1327 key_changed_h, req_key_h, ans_key_h,
1333 char (*request_name[]) = {
1334 "ID", "METAKEY", "CHALLENGE", "CHAL_REPLY",
1335 "STATUS", "ERROR", "TERMREQ",
1337 "ADD_HOST", "DEL_HOST",
1338 "ADD_SUBNET", "DEL_SUBNET",
1339 "KEY_CHANGED", "REQ_KEY", "ANS_KEY",
1343 /* Status strings */
1345 char (*status_text[]) = {
1351 char (*error_text[]) = {