2 protocol.c -- handle the meta-protocol
3 Copyright (C) 1999,2000 Ivo Timmermans <itimmermans@bigfoot.com>,
4 2000 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.44 2000/10/21 11:52:07 guus Exp $
25 #include <sys/types.h>
30 #include <sys/socket.h>
37 #include <netinet/in.h>
39 #include <openssl/sha.h>
50 int check_id(char *id)
54 for (i = 0; i < strlen(id); i++)
55 if(!isalnum(id[i]) && id[i] != '_')
61 /* Generic request routines - takes care of logging and error detection as well */
63 int send_request(conn_list_t *cl, const char *format, ...)
66 char buffer[MAXBUFSIZE];
70 /* Use vsnprintf instead of vasprintf: faster, no memory fragmentation, cleanup is automatic,
71 and there is a limit on the input buffer anyway */
73 va_start(args, format);
74 len = vsnprintf(buffer, MAXBUFSIZE, format, args);
75 request = va_arg(args, int);
78 if(len < 0 || len > MAXBUFSIZE-1)
80 syslog(LOG_ERR, _("Output buffer overflow while sending %s to %s (%s)"), request_name[request], cl->name, cl->hostname);
86 if(debug_lvl >= DEBUG_PROTOCOL)
87 syslog(LOG_DEBUG, _("Sending %s to %s (%s)"), request_name[request], cl->name, cl->hostname);
90 return send_meta(cl, buffer, len);
93 int receive_request(conn_list_t *cl)
97 if(sscanf(cl->buffer, "%d", &request) == 1)
99 if((request < 0) || (request > 255) || (request_handlers[request] == NULL))
101 syslog(LOG_ERR, _("Unknown request from %s (%s)"),
102 cl->name, cl->hostname);
107 if(debug_lvl >= DEBUG_PROTOCOL)
108 syslog(LOG_DEBUG, _("Got %s from %s (%s)"),
109 request_name[request], cl->name, cl->hostname);
111 if(request_handlers[request](cl))
112 /* Something went wrong. Probably scriptkiddies. Terminate. */
114 syslog(LOG_ERR, _("Error while processing %s from %s (%s)"),
115 request_name[request], cl->name, cl->hostname);
121 syslog(LOG_ERR, _("Bogus data received from %s (%s)"),
122 cl->name, cl->hostname);
127 /* Connection protocol:
136 ---------------------------------------
137 Any negotations about the meta protocol
138 encryption go here(u).
139 ---------------------------------------
142 ---------------------------------------
148 (E) Encrypted with symmetric cipher.
150 Part of the challenge is directly used to set the symmetric cipher key and the initial vector.
151 Since a man-in-the-middle cannot decrypt the RSA challenges, this means that he cannot get or
152 forge the key for the symmetric cipher.
155 int send_id(conn_list_t *cl)
158 cl->allow_request = CHALLENGE;
160 return send_request(cl, "%d %s %d %lx %hd", ID, myself->name, myself->protocol_version, myself->options, myself->port);
163 int id_h(conn_list_t *cl)
168 if(sscanf(cl->buffer, "%*d %as %d %lx %hd", &cl->name, &cl->protocol_version, &cl->options, &cl->port) != 4)
170 syslog(LOG_ERR, _("Got bad ID from %s"), cl->hostname);
174 /* Check if version matches */
176 if(cl->protocol_version != myself->protocol_version)
178 syslog(LOG_ERR, _("Peer %s (%s) uses incompatible version %d"),
179 cl->name, cl->hostname, cl->protocol_version);
183 /* Check if identity is a valid name */
185 if(check_id(cl->name))
187 syslog(LOG_ERR, _("Peer %s uses invalid identity name"), cl->hostname);
191 /* Load information about peer */
193 if(read_host_config(cl))
195 syslog(LOG_ERR, _("Peer %s had unknown identity (%s)"), cl->hostname, cl->name);
199 /* First check if the host we connected to is already in our
200 connection list. If so, we are probably making a loop, which
204 if(cl->status.outgoing)
206 if((old = lookup_id(cl->name)))
208 if(debug_lvl >= DEBUG_CONNECTIONS)
209 syslog(LOG_NOTICE, _("Uplink %s (%s) is already in our connection list"), cl->name, cl->hostname);
210 cl->status.outgoing = 0;
211 old->status.outgoing = 1;
212 terminate_connection(cl);
217 if(!(cfg = get_config_val(cl->config, publickey)))
219 syslog(LOG_ERR, _("No public key known for %s (%s)"), cl->name, cl->hostname);
225 cl->rsa_key = RSA_new();
226 BN_hex2bn(&cl->rsa_key->n, cfg->data.ptr);
227 BN_hex2bn(&cl->rsa_key->e, "FFFF");
231 return send_challenge(cl);
234 int send_challenge(conn_list_t *cl)
239 len = RSA_size(cl->rsa_key);
241 /* Allocate buffers for the challenge */
243 buffer = xmalloc(len*2+1);
246 free(cl->hischallenge);
248 cl->hischallenge = xmalloc(len);
250 /* Seed the PRNG with urandom (can't afford to block) */
252 RAND_load_file("/dev/urandom", 1024);
254 /* Copy random data to the buffer */
256 RAND_bytes(cl->hischallenge, len);
258 cl->hischallenge[0] &= 0x7F; /* Somehow if the first byte is more than 0xD0 or something like that, decryption fails... */
260 if(debug_lvl >= DEBUG_SCARY_THINGS)
262 bin2hex(cl->hischallenge, buffer, len);
263 buffer[len*2] = '\0';
264 syslog(LOG_DEBUG, _("Generated random challenge (unencrypted): %s"), buffer);
267 /* Encrypt the random data */
269 if(RSA_public_encrypt(len, cl->hischallenge, buffer, cl->rsa_key, RSA_NO_PADDING) != len) /* NO_PADDING because the message size equals the RSA key size and it is totally random */
271 syslog(LOG_ERR, _("Error during encryption of challenge for %s (%s)"), cl->name, cl->hostname);
276 /* Convert the encrypted random data to a hexadecimal formatted string */
278 bin2hex(buffer, buffer, len);
279 buffer[len*2] = '\0';
281 /* Send the challenge */
283 cl->allow_request = CHAL_REPLY;
284 x = send_request(cl, "%d %s", CHALLENGE, buffer);
290 int challenge_h(conn_list_t *cl)
295 if(sscanf(cl->buffer, "%*d %as", &buffer) != 1)
297 syslog(LOG_ERR, _("Got bad CHALLENGE from %s (%s)"), cl->name, cl->hostname);
301 len = RSA_size(myself->rsa_key);
303 /* Check if the length of the challenge is all right */
305 if(strlen(buffer) != len*2)
307 syslog(LOG_ERR, _("Intruder: wrong challenge length from %s (%s)"), cl->name, cl->hostname);
312 /* Allocate buffers for the challenge */
315 cl->mychallenge = xmalloc(len);
317 /* Convert the challenge from hexadecimal back to binary */
319 hex2bin(buffer,buffer,len);
321 /* Decrypt the challenge */
323 if(RSA_private_decrypt(len, buffer, cl->mychallenge, myself->rsa_key, RSA_NO_PADDING) != len) /* See challenge() */
325 syslog(LOG_ERR, _("Error during encryption of challenge for %s (%s)"), cl->name, cl->hostname);
330 if(debug_lvl >= DEBUG_SCARY_THINGS)
332 bin2hex(cl->mychallenge, buffer, len);
333 buffer[len*2] = '\0';
334 syslog(LOG_DEBUG, _("Received random challenge (unencrypted): %s"), buffer);
339 /* Rest is done by send_chal_reply() */
341 return send_chal_reply(cl);
344 int send_chal_reply(conn_list_t *cl)
346 char hash[SHA_DIGEST_LENGTH*2+1];
350 syslog(LOG_ERR, _("Trying to send CHAL_REPLY to %s (%s) without a valid CHALLENGE"), cl->name, cl->hostname);
354 /* Calculate the hash from the challenge we received */
356 SHA1(cl->mychallenge, RSA_size(myself->rsa_key), hash);
358 /* Convert the hash to a hexadecimal formatted string */
360 bin2hex(hash,hash,SHA_DIGEST_LENGTH);
361 hash[SHA_DIGEST_LENGTH*2] = '\0';
365 if(cl->status.outgoing)
366 cl->allow_request = ID;
368 cl->allow_request = ACK;
371 return send_request(cl, "%d %s", CHAL_REPLY, hash);
374 int chal_reply_h(conn_list_t *cl)
377 char myhash[SHA_DIGEST_LENGTH];
379 if(sscanf(cl->buffer, "%*d %as", &hishash) != 1)
381 syslog(LOG_ERR, _("Got bad CHAL_REPLY from %s (%s)"), cl->name, cl->hostname);
386 /* Check if the length of the hash is all right */
388 if(strlen(hishash) != SHA_DIGEST_LENGTH*2)
390 syslog(LOG_ERR, _("Intruder: wrong challenge reply length from %s (%s)"), cl->name, cl->hostname);
395 /* Convert the hash to binary format */
397 hex2bin(hishash, hishash, SHA_DIGEST_LENGTH);
399 /* Calculate the hash from the challenge we sent */
401 SHA1(cl->hischallenge, RSA_size(cl->rsa_key), myhash);
403 /* Verify the incoming hash with the calculated hash */
405 if(memcmp(hishash, myhash, SHA_DIGEST_LENGTH))
407 syslog(LOG_ERR, _("Intruder: wrong challenge reply from %s (%s)"), cl->name, cl->hostname);
408 if(debug_lvl >= DEBUG_SCARY_THINGS)
410 bin2hex(myhash, hishash, SHA_DIGEST_LENGTH);
411 hishash[SHA_DIGEST_LENGTH*2] = '\0';
412 syslog(LOG_DEBUG, _("Expected challenge reply: %s"), hishash);
421 /* Identity has now been positively verified.
422 If we are accepting this new connection, then send our identity,
423 if we are making this connecting, acknowledge.
426 if(cl->status.outgoing)
432 int send_ack(conn_list_t *cl)
435 cl->allow_request = ACK;
437 return send_request(cl, "%d", ACK);
440 int ack_h(conn_list_t *cl)
444 /* Okay, before we active the connection, we check if there is another entry
445 in the connection list with the same name. If so, it presumably is an
446 old connection that has timed out but we don't know it yet.
449 while((old = lookup_id(cl->name)))
451 if(debug_lvl >= DEBUG_CONNECTIONS)
452 syslog(LOG_NOTICE, _("Removing old entry for %s at %s in favour of new connection from %s"),
453 cl->name, old->hostname, cl->hostname);
454 old->status.active = 0;
455 terminate_connection(old);
458 /* Activate this connection */
460 cl->allow_request = ALL;
461 cl->status.active = 1;
463 if(debug_lvl >= DEBUG_CONNECTIONS)
464 syslog(LOG_NOTICE, _("Connection with %s (%s) activated"), cl->name, cl->hostname);
466 /* Exchange information about other tinc daemons */
468 /* FIXME: reprogram this.
469 notify_others(cl, NULL, send_add_host);
475 if(cl->status.outgoing)
481 /* Address and subnet information exchange */
483 int send_add_subnet(conn_list_t *cl, conn_list_t *other, subnet_t *subnet)
488 x = send_request(cl, "%d %s %s", ADD_SUBNET,
489 other->name, netstr = net2str(subnet));
495 int add_subnet_h(conn_list_t *cl)
500 subnet_t *subnet, *old;
502 if(sscanf(cl->buffer, "%*d %as %as", &name, &subnetstr) != 3)
504 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s)"), cl->name, cl->hostname);
505 free(name); free(subnetstr);
509 /* Check if owner name is a valid */
513 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s): invalid identity name"), cl->name, cl->hostname);
514 free(name); free(subnetstr);
518 /* Check if subnet string is valid */
520 if(!(subnet = str2net(subnetstr)))
522 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s): invalid subnet string"), cl->name, cl->hostname);
523 free(name); free(subnetstr);
529 /* Check if somebody tries to add a subnet of ourself */
531 if(!strcmp(name, myself->name))
533 syslog(LOG_ERR, _("Warning: got ADD_SUBNET from %s (%s) for ourself, restarting"),
534 cl->name, cl->hostname);
540 /* Check if the owner of the new subnet is in the connection list */
542 if(!(owner = lookup_id(name)))
544 syslog(LOG_ERR, _("Got ADD_SUBNET for %s from %s (%s) which is not in our connection list"),
545 name, cl->name, cl->hostname);
550 /* If everything is correct, add the subnet to the list of the owner */
552 subnet_add(owner, subnet);
557 int send_del_subnet(conn_list_t *cl, conn_list_t *other, subnet_t *subnet)
560 return send_request(cl, "%d %s %s", DEL_SUBNET, other->name, net2str(subnet));
563 int del_subnet_h(conn_list_t *cl)
568 subnet_t *subnet, *old;
570 if(sscanf(cl->buffer, "%*d %as %as", &name, &subnetstr) != 3)
572 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s)"), cl->name, cl->hostname);
573 free(name); free(subnetstr);
577 /* Check if owner name is a valid */
581 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s): invalid identity name"), cl->name, cl->hostname);
582 free(name); free(subnetstr);
586 /* Check if subnet string is valid */
588 if(!(subnet = str2net(subnetstr)))
590 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s): invalid subnet string"), cl->name, cl->hostname);
591 free(name); free(subnetstr);
597 /* Check if somebody tries to add a subnet of ourself */
599 if(!strcmp(name, myself->name))
601 syslog(LOG_ERR, _("Warning: got DEL_SUBNET from %s (%s) for ourself, restarting"),
602 cl->name, cl->hostname);
608 /* Check if the owner of the new subnet is in the connection list */
610 if(!(owner = lookup_id(name)))
612 syslog(LOG_ERR, _("Got DEL_SUBNET for %s from %s (%s) which is not in our connection list"),
613 name, cl->name, cl->hostname);
618 /* If everything is correct, delete the subnet from the list of the owner */
625 /* New and closed connections notification */
627 int send_add_host(conn_list_t *cl, conn_list_t *other)
630 return send_request(cl, "%d %s %s %lx:%d %lx", ADD_HOST,
631 myself->name, other->name, other->address, other->port, other->options);
634 int add_host_h(conn_list_t *cl)
637 conn_list_t *old, *new, *hisuplink;
639 new = new_conn_list();
641 if(sscanf(cl->buffer, "%*d %as %as %lx:%d %lx", &sender, &new->name, &new->address, &new->port, &new->options) != 5)
643 syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s)"), cl->name, cl->hostname);
647 /* Check if identity is a valid name */
649 if(check_id(new->name) || check_id(sender))
651 syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s): invalid identity name"), cl->name, cl->hostname);
656 /* Check if somebody tries to add ourself */
658 if(!strcmp(new->name, myself->name))
660 syslog(LOG_ERR, _("Warning: got ADD_HOST from %s (%s) for ourself, restarting"), cl->name, cl->hostname);
666 /* We got an ADD_HOST from ourself!? */
668 if(!strcmp(sender, myself->name))
670 syslog(LOG_ERR, _("Warning: got ADD_HOST from %s (%s) from ourself, restarting"), cl->name, cl->hostname);
676 /* Lookup his uplink */
678 if(!(new->hisuplink = lookup_id(sender)))
680 syslog(LOG_ERR, _("Got ADD_HOST from %s (%s) with origin %s which is not in our connection list"),
681 sender, cl->name, cl->hostname);
688 /* Fill in more of the new conn_list structure */
690 new->hostname = hostlookup(htonl(new->address));
692 /* Check if the new host already exists in the connnection list */
694 if((old = lookup_id(new->name)))
696 if((new->address == old->address) && (new->port == old->port))
698 if(debug_lvl >= DEBUG_CONNECTIONS)
699 syslog(LOG_NOTICE, _("Got duplicate ADD_HOST for %s (%s) from %s (%s)"),
700 old->name, old->hostname, new->name, new->hostname);
705 if(debug_lvl >= DEBUG_CONNECTIONS)
706 syslog(LOG_NOTICE, _("Removing old entry for %s (%s)"),
707 old->name, old->hostname);
708 old->status.active = 0;
709 terminate_connection(old);
713 /* Fill in rest of conn_list structure */
716 new->status.active = 1;
718 /* Hook it up into the conn_list */
720 conn_list_add(conn_list, new);
722 /* Tell the rest about the new host */
723 /* FIXME: reprogram this.
724 notify_others(new, cl, send_add_host);
730 int send_del_host(conn_list_t *cl, conn_list_t *other)
733 return send_request(cl, "%d %s %s %lx:%d %lx", DEL_HOST,
734 myself->name, other->name, other->address, other->port, other->options);
737 int del_host_h(conn_list_t *cl)
744 conn_list_t *old, *hisuplink;
747 if(sscanf(cl->buffer, "%*d %as %as %lx:%d %lx", &sender, &name, &address, &port, &options) != 5)
749 syslog(LOG_ERR, _("Got bad DEL_HOST from %s (%s)"),
750 cl->name, cl->hostname);
754 /* Check if identity is a valid name */
756 if(check_id(name) || check_id(sender))
758 syslog(LOG_ERR, _("Got bad DEL_HOST from %s (%s): invalid identity name"), cl->name, cl->hostname);
759 free(name); free(sender);
763 /* Check if somebody tries to delete ourself */
765 if(!strcmp(name, myself->name))
767 syslog(LOG_ERR, _("Warning: got DEL_HOST from %s (%s) for ourself, restarting"),
768 cl->name, cl->hostname);
769 free(name); free(sender);
774 /* We got an ADD_HOST from ourself!? */
776 if(!strcmp(sender, myself->name))
778 syslog(LOG_ERR, _("Warning: got DEL_HOST from %s (%s) from ourself, restarting"), cl->name, cl->hostname);
780 free(name); free(sender);
784 /* Lookup his uplink */
786 if(!(hisuplink = lookup_id(sender)))
788 syslog(LOG_ERR, _("Got DEL_HOST from %s (%s) with origin %s which is not in our connection list"),
789 cl->name, cl->hostname, sender);
790 free(name); free(sender);
796 /* Check if the new host already exists in the connnection list */
798 if(!(old = lookup_id(name)))
800 syslog(LOG_ERR, _("Got DEL_HOST from %s (%s) for %s which is not in our connection list"),
801 name, cl->name, cl->hostname);
806 /* Check if the rest matches */
808 if(address!=old->address || port!=old->port || options!=old->options || hisuplink!=old->hisuplink || cl!=old->myuplink)
810 syslog(LOG_WARNING, _("Got DEL_HOST from %s (%s) for %s which doesn't match"), cl->name, cl->hostname, old->name);
814 /* Ok, since EVERYTHING seems to check out all right, delete it */
816 old->status.termreq = 1;
817 old->status.active = 0;
819 terminate_connection(old);
824 /* Status and error notification routines */
826 int send_status(conn_list_t *cl, int statusno, char *statusstring)
830 statusstring = status_text[statusno];
832 return send_request(cl, "%d %d %s", STATUS, statusno, statusstring);
835 int status_h(conn_list_t *cl)
840 if(sscanf(cl->buffer, "%*d %d %as", &statusno, &statusstring) != 2)
842 syslog(LOG_ERR, _("Got bad STATUS from %s (%s)"),
843 cl->name, cl->hostname);
847 if(debug_lvl >= DEBUG_STATUS)
849 syslog(LOG_NOTICE, _("Status message from %s (%s): %s: %s"),
850 cl->name, cl->hostname, status_text[statusno], statusstring);
858 int send_error(conn_list_t *cl, int errno, char *errstring)
862 errstring = strerror(errno);
863 return send_request(cl, "%d %d %s", ERROR, errno, errstring);
866 int error_h(conn_list_t *cl)
871 if(sscanf(cl->buffer, "%*d %d %as", &errno, &errorstring) != 2)
873 syslog(LOG_ERR, _("Got bad ERROR from %s (%s)"),
874 cl->name, cl->hostname);
878 if(debug_lvl >= DEBUG_ERROR)
880 syslog(LOG_NOTICE, _("Error message from %s (%s): %s: %s"),
881 cl->name, cl->hostname, strerror(errno), errorstring);
885 cl->status.termreq = 1;
886 terminate_connection(cl);
891 int send_termreq(conn_list_t *cl)
894 return send_request(cl, "%d", TERMREQ);
897 int termreq_h(conn_list_t *cl)
900 cl->status.termreq = 1;
901 terminate_connection(cl);
906 /* Keepalive routines - FIXME: needs a closer look */
908 int send_ping(conn_list_t *cl)
910 cl->status.pinged = 1;
912 return send_request(cl, "%d", PING);
915 int ping_h(conn_list_t *cl)
918 return send_pong(cl);
921 int send_pong(conn_list_t *cl)
924 return send_request(cl, "%d", PONG);
927 int pong_h(conn_list_t *cl)
930 cl->status.got_pong = 1;
937 int send_key_changed(conn_list_t *from, conn_list_t *cl)
941 for(p = conn_list; p != NULL; p = p->next)
943 if(p!=cl && p->status.meta && p->status.active)
944 send_request(p, "%d %s", KEY_CHANGED,
951 int key_changed_h(conn_list_t *cl)
956 if(sscanf(cl->buffer, "%*d %as", &from_id) != 1)
958 syslog(LOG_ERR, _("Got bad KEY_CHANGED from %s (%s)"),
959 cl->name, cl->hostname);
963 if(!(from = lookup_id(from_id)))
965 syslog(LOG_ERR, _("Got KEY_CHANGED from %s (%s) origin %s which does not exist in our connection list"),
966 cl->name, cl->hostname, from_id);
973 from->status.validkey = 0;
974 from->status.waitingforkey = 0;
976 send_key_changed(from, cl);
981 int send_req_key(conn_list_t *from, conn_list_t *to)
984 return send_request(to->nexthop, "%d %s %s", REQ_KEY,
985 from->name, to->name);
988 int req_key_h(conn_list_t *cl)
990 char *from_id, *to_id;
991 conn_list_t *from, *to;
993 if(sscanf(cl->buffer, "%*d %as %as", &from_id, &to_id) != 2)
995 syslog(LOG_ERR, _("Got bad REQ_KEY from %s (%s)"),
996 cl->name, cl->hostname);
1000 if(!(from = lookup_id(from_id)))
1002 syslog(LOG_ERR, _("Got REQ_KEY from %s (%s) origin %s which does not exist in our connection list"),
1003 cl->name, cl->hostname, from_id);
1004 free(from_id); free(to_id);
1008 /* Check if this key request is for us */
1010 if(!strcmp(to_id, myself->name))
1012 send_ans_key(myself, from, myself->cipher_pktkey);
1016 if(!(to = lookup_id(to_id)))
1018 syslog(LOG_ERR, _("Got REQ_KEY from %s (%s) destination %s which does not exist in our connection list"),
1019 cl->name, cl->hostname, to_id);
1020 free(from_id); free(to_id);
1023 send_req_key(from, to);
1026 free(from_id); free(to_id);
1031 int send_ans_key(conn_list_t *from, conn_list_t *to, char *pktkey)
1034 return send_request(to->nexthop, "%d %s %s %s", ANS_KEY,
1035 from->name, to->name, pktkey);
1038 int ans_key_h(conn_list_t *cl)
1040 char *from_id, *to_id, *pktkey;
1042 conn_list_t *from, *to;
1044 if(sscanf(cl->buffer, "%*d %as %as %as", &from_id, &to_id, &pktkey) != 3)
1046 syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s)"),
1047 cl->name, cl->hostname);
1051 if(!(from = lookup_id(from_id)))
1053 syslog(LOG_ERR, _("Got ANS_KEY from %s (%s) origin %s which does not exist in our connection list"),
1054 cl->name, cl->hostname, from_id);
1055 free(from_id); free(to_id); free(pktkey);
1059 /* Check if this key request is for us */
1061 if(!strcmp(to_id, myself->name))
1063 /* It is for us, convert it to binary and set the key with it. */
1065 keylength = strlen(pktkey);
1067 if((keylength%2) || (keylength <= 0))
1069 syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s) origin %s: invalid key"),
1070 cl->name, cl->hostname, from->name);
1071 free(from_id); free(to_id); free(pktkey);
1075 hex2bin(pktkey, pktkey, keylength);
1076 BF_set_key(cl->cipher_pktkey, keylength, pktkey);
1080 if(!(to = lookup_id(to_id)))
1082 syslog(LOG_ERR, _("Got ANS_KEY from %s (%s) destination %s which does not exist in our connection list"),
1083 cl->name, cl->hostname, to_id);
1084 free(from_id); free(to_id); free(pktkey);
1087 send_ans_key(from, to, pktkey);
1090 free(from_id); free(to_id); free(pktkey);
1095 /* Jumptable for the request handlers */
1097 int (*request_handlers[])(conn_list_t*) = {
1098 id_h, challenge_h, chal_reply_h, ack_h,
1099 status_h, error_h, termreq_h,
1101 add_host_h, del_host_h,
1102 add_subnet_h, del_subnet_h,
1103 key_changed_h, req_key_h, ans_key_h,
1108 char (*request_name[]) = {
1109 "ID", "CHALLENGE", "CHAL_REPLY", "ACK",
1110 "STATUS", "ERROR", "TERMREQ",
1112 "ADD_HOST", "DEL_HOST",
1113 "ADD_SUBNET", "DEL_SUBNET",
1114 "KEY_CHANGED", "REQ_KEY", "ANS_KEY",
1117 /* Status strings */
1119 char (*status_text[]) = {
1125 char (*error_text[]) = {