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.45 2000/10/24 15:46:17 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);
474 if(cl->status.outgoing)
480 /* Address and subnet information exchange */
482 int send_add_subnet(conn_list_t *cl, conn_list_t *other, subnet_t *subnet)
487 x = send_request(cl, "%d %s %s", ADD_SUBNET,
488 other->name, netstr = net2str(subnet));
494 int add_subnet_h(conn_list_t *cl)
499 subnet_t *subnet, *old;
501 if(sscanf(cl->buffer, "%*d %as %as", &name, &subnetstr) != 3)
503 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s)"), cl->name, cl->hostname);
504 free(name); free(subnetstr);
508 /* Check if owner name is a valid */
512 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s): invalid identity name"), cl->name, cl->hostname);
513 free(name); free(subnetstr);
517 /* Check if subnet string is valid */
519 if(!(subnet = str2net(subnetstr)))
521 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s): invalid subnet string"), cl->name, cl->hostname);
522 free(name); free(subnetstr);
528 /* Check if somebody tries to add a subnet of ourself */
530 if(!strcmp(name, myself->name))
532 syslog(LOG_ERR, _("Warning: got ADD_SUBNET from %s (%s) for ourself, restarting"),
533 cl->name, cl->hostname);
539 /* Check if the owner of the new subnet is in the connection list */
541 if(!(owner = lookup_id(name)))
543 syslog(LOG_ERR, _("Got ADD_SUBNET for %s from %s (%s) which is not in our connection list"),
544 name, cl->name, cl->hostname);
549 /* If everything is correct, add the subnet to the list of the owner */
551 subnet_add(owner, subnet);
556 int send_del_subnet(conn_list_t *cl, conn_list_t *other, subnet_t *subnet)
559 return send_request(cl, "%d %s %s", DEL_SUBNET, other->name, net2str(subnet));
562 int del_subnet_h(conn_list_t *cl)
567 subnet_t *subnet, *old;
569 if(sscanf(cl->buffer, "%*d %as %as", &name, &subnetstr) != 3)
571 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s)"), cl->name, cl->hostname);
572 free(name); free(subnetstr);
576 /* Check if owner name is a valid */
580 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s): invalid identity name"), cl->name, cl->hostname);
581 free(name); free(subnetstr);
585 /* Check if subnet string is valid */
587 if(!(subnet = str2net(subnetstr)))
589 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s): invalid subnet string"), cl->name, cl->hostname);
590 free(name); free(subnetstr);
596 /* Check if somebody tries to add a subnet of ourself */
598 if(!strcmp(name, myself->name))
600 syslog(LOG_ERR, _("Warning: got DEL_SUBNET from %s (%s) for ourself, restarting"),
601 cl->name, cl->hostname);
607 /* Check if the owner of the new subnet is in the connection list */
609 if(!(owner = lookup_id(name)))
611 syslog(LOG_ERR, _("Got DEL_SUBNET for %s from %s (%s) which is not in our connection list"),
612 name, cl->name, cl->hostname);
617 /* If everything is correct, delete the subnet from the list of the owner */
624 /* New and closed connections notification */
626 int send_add_host(conn_list_t *cl, conn_list_t *other)
629 return send_request(cl, "%d %s %s %lx:%d %lx", ADD_HOST,
630 myself->name, other->name, other->address, other->port, other->options);
633 int add_host_h(conn_list_t *cl)
636 conn_list_t *old, *new, *hisuplink;
638 new = new_conn_list();
640 if(sscanf(cl->buffer, "%*d %as %as %lx:%d %lx", &sender, &new->name, &new->address, &new->port, &new->options) != 5)
642 syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s)"), cl->name, cl->hostname);
646 /* Check if identity is a valid name */
648 if(check_id(new->name) || check_id(sender))
650 syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s): invalid identity name"), cl->name, cl->hostname);
655 /* Check if somebody tries to add ourself */
657 if(!strcmp(new->name, myself->name))
659 syslog(LOG_ERR, _("Warning: got ADD_HOST from %s (%s) for ourself, restarting"), cl->name, cl->hostname);
665 /* We got an ADD_HOST from ourself!? */
667 if(!strcmp(sender, myself->name))
669 syslog(LOG_ERR, _("Warning: got ADD_HOST from %s (%s) from ourself, restarting"), cl->name, cl->hostname);
675 /* Lookup his uplink */
677 if(!(new->hisuplink = lookup_id(sender)))
679 syslog(LOG_ERR, _("Got ADD_HOST from %s (%s) with origin %s which is not in our connection list"),
680 sender, cl->name, cl->hostname);
687 /* Fill in more of the new conn_list structure */
689 new->hostname = hostlookup(htonl(new->address));
691 /* Check if the new host already exists in the connnection list */
693 if((old = lookup_id(new->name)))
695 if((new->address == old->address) && (new->port == old->port))
697 if(debug_lvl >= DEBUG_CONNECTIONS)
698 syslog(LOG_NOTICE, _("Got duplicate ADD_HOST for %s (%s) from %s (%s)"),
699 old->name, old->hostname, new->name, new->hostname);
704 if(debug_lvl >= DEBUG_CONNECTIONS)
705 syslog(LOG_NOTICE, _("Removing old entry for %s (%s)"),
706 old->name, old->hostname);
707 old->status.active = 0;
708 terminate_connection(old);
712 /* Fill in rest of conn_list structure */
715 new->status.active = 1;
717 /* Hook it up into the conn_list */
719 conn_list_add(conn_list, new);
721 /* Tell the rest about the new host */
722 /* FIXME: reprogram this.
723 notify_others(new, cl, send_add_host);
729 int send_del_host(conn_list_t *cl, conn_list_t *other)
732 return send_request(cl, "%d %s %s %lx:%d %lx", DEL_HOST,
733 myself->name, other->name, other->address, other->port, other->options);
736 int del_host_h(conn_list_t *cl)
743 conn_list_t *old, *hisuplink;
746 if(sscanf(cl->buffer, "%*d %as %as %lx:%d %lx", &sender, &name, &address, &port, &options) != 5)
748 syslog(LOG_ERR, _("Got bad DEL_HOST from %s (%s)"),
749 cl->name, cl->hostname);
753 /* Check if identity is a valid name */
755 if(check_id(name) || check_id(sender))
757 syslog(LOG_ERR, _("Got bad DEL_HOST from %s (%s): invalid identity name"), cl->name, cl->hostname);
758 free(name); free(sender);
762 /* Check if somebody tries to delete ourself */
764 if(!strcmp(name, myself->name))
766 syslog(LOG_ERR, _("Warning: got DEL_HOST from %s (%s) for ourself, restarting"),
767 cl->name, cl->hostname);
768 free(name); free(sender);
773 /* We got an ADD_HOST from ourself!? */
775 if(!strcmp(sender, myself->name))
777 syslog(LOG_ERR, _("Warning: got DEL_HOST from %s (%s) from ourself, restarting"), cl->name, cl->hostname);
779 free(name); free(sender);
783 /* Lookup his uplink */
785 if(!(hisuplink = lookup_id(sender)))
787 syslog(LOG_ERR, _("Got DEL_HOST from %s (%s) with origin %s which is not in our connection list"),
788 cl->name, cl->hostname, sender);
789 free(name); free(sender);
795 /* Check if the new host already exists in the connnection list */
797 if(!(old = lookup_id(name)))
799 syslog(LOG_ERR, _("Got DEL_HOST from %s (%s) for %s which is not in our connection list"),
800 name, cl->name, cl->hostname);
805 /* Check if the rest matches */
807 if(address!=old->address || port!=old->port || options!=old->options || hisuplink!=old->hisuplink || cl!=old->myuplink)
809 syslog(LOG_WARNING, _("Got DEL_HOST from %s (%s) for %s which doesn't match"), cl->name, cl->hostname, old->name);
813 /* Ok, since EVERYTHING seems to check out all right, delete it */
815 old->status.termreq = 1;
816 old->status.active = 0;
818 terminate_connection(old);
823 /* Status and error notification routines */
825 int send_status(conn_list_t *cl, int statusno, char *statusstring)
829 statusstring = status_text[statusno];
831 return send_request(cl, "%d %d %s", STATUS, statusno, statusstring);
834 int status_h(conn_list_t *cl)
839 if(sscanf(cl->buffer, "%*d %d %as", &statusno, &statusstring) != 2)
841 syslog(LOG_ERR, _("Got bad STATUS from %s (%s)"),
842 cl->name, cl->hostname);
846 if(debug_lvl >= DEBUG_STATUS)
848 syslog(LOG_NOTICE, _("Status message from %s (%s): %s: %s"),
849 cl->name, cl->hostname, status_text[statusno], statusstring);
857 int send_error(conn_list_t *cl, int errno, char *errstring)
861 errstring = strerror(errno);
862 return send_request(cl, "%d %d %s", ERROR, errno, errstring);
865 int error_h(conn_list_t *cl)
870 if(sscanf(cl->buffer, "%*d %d %as", &errno, &errorstring) != 2)
872 syslog(LOG_ERR, _("Got bad ERROR from %s (%s)"),
873 cl->name, cl->hostname);
877 if(debug_lvl >= DEBUG_ERROR)
879 syslog(LOG_NOTICE, _("Error message from %s (%s): %s: %s"),
880 cl->name, cl->hostname, strerror(errno), errorstring);
884 cl->status.termreq = 1;
885 terminate_connection(cl);
890 int send_termreq(conn_list_t *cl)
893 return send_request(cl, "%d", TERMREQ);
896 int termreq_h(conn_list_t *cl)
899 cl->status.termreq = 1;
900 terminate_connection(cl);
905 /* Keepalive routines - FIXME: needs a closer look */
907 int send_ping(conn_list_t *cl)
909 cl->status.pinged = 1;
911 return send_request(cl, "%d", PING);
914 int ping_h(conn_list_t *cl)
917 return send_pong(cl);
920 int send_pong(conn_list_t *cl)
923 return send_request(cl, "%d", PONG);
926 int pong_h(conn_list_t *cl)
929 cl->status.got_pong = 1;
936 int send_key_changed(conn_list_t *from, conn_list_t *cl)
940 for(p = conn_list; p != NULL; p = p->next)
942 if(p!=cl && p->status.meta && p->status.active)
943 send_request(p, "%d %s", KEY_CHANGED,
950 int key_changed_h(conn_list_t *cl)
955 if(sscanf(cl->buffer, "%*d %as", &from_id) != 1)
957 syslog(LOG_ERR, _("Got bad KEY_CHANGED from %s (%s)"),
958 cl->name, cl->hostname);
962 if(!(from = lookup_id(from_id)))
964 syslog(LOG_ERR, _("Got KEY_CHANGED from %s (%s) origin %s which does not exist in our connection list"),
965 cl->name, cl->hostname, from_id);
972 from->status.validkey = 0;
973 from->status.waitingforkey = 0;
975 send_key_changed(from, cl);
980 int send_req_key(conn_list_t *from, conn_list_t *to)
983 return send_request(to->nexthop, "%d %s %s", REQ_KEY,
984 from->name, to->name);
987 int req_key_h(conn_list_t *cl)
989 char *from_id, *to_id;
990 conn_list_t *from, *to;
992 if(sscanf(cl->buffer, "%*d %as %as", &from_id, &to_id) != 2)
994 syslog(LOG_ERR, _("Got bad REQ_KEY from %s (%s)"),
995 cl->name, cl->hostname);
999 if(!(from = lookup_id(from_id)))
1001 syslog(LOG_ERR, _("Got REQ_KEY from %s (%s) origin %s which does not exist in our connection list"),
1002 cl->name, cl->hostname, from_id);
1003 free(from_id); free(to_id);
1007 /* Check if this key request is for us */
1009 if(!strcmp(to_id, myself->name))
1011 send_ans_key(myself, from, myself->cipher_pktkey);
1015 if(!(to = lookup_id(to_id)))
1017 syslog(LOG_ERR, _("Got REQ_KEY from %s (%s) destination %s which does not exist in our connection list"),
1018 cl->name, cl->hostname, to_id);
1019 free(from_id); free(to_id);
1022 send_req_key(from, to);
1025 free(from_id); free(to_id);
1030 int send_ans_key(conn_list_t *from, conn_list_t *to, char *pktkey)
1033 return send_request(to->nexthop, "%d %s %s %s", ANS_KEY,
1034 from->name, to->name, pktkey);
1037 int ans_key_h(conn_list_t *cl)
1039 char *from_id, *to_id, *pktkey;
1041 conn_list_t *from, *to;
1043 if(sscanf(cl->buffer, "%*d %as %as %as", &from_id, &to_id, &pktkey) != 3)
1045 syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s)"),
1046 cl->name, cl->hostname);
1050 if(!(from = lookup_id(from_id)))
1052 syslog(LOG_ERR, _("Got ANS_KEY from %s (%s) origin %s which does not exist in our connection list"),
1053 cl->name, cl->hostname, from_id);
1054 free(from_id); free(to_id); free(pktkey);
1058 /* Check if this key request is for us */
1060 if(!strcmp(to_id, myself->name))
1062 /* It is for us, convert it to binary and set the key with it. */
1064 keylength = strlen(pktkey);
1066 if((keylength%2) || (keylength <= 0))
1068 syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s) origin %s: invalid key"),
1069 cl->name, cl->hostname, from->name);
1070 free(from_id); free(to_id); free(pktkey);
1074 hex2bin(pktkey, pktkey, keylength);
1075 BF_set_key(cl->cipher_pktkey, keylength, pktkey);
1079 if(!(to = lookup_id(to_id)))
1081 syslog(LOG_ERR, _("Got ANS_KEY from %s (%s) destination %s which does not exist in our connection list"),
1082 cl->name, cl->hostname, to_id);
1083 free(from_id); free(to_id); free(pktkey);
1086 send_ans_key(from, to, pktkey);
1089 free(from_id); free(to_id); free(pktkey);
1094 /* Jumptable for the request handlers */
1096 int (*request_handlers[])(conn_list_t*) = {
1097 id_h, challenge_h, chal_reply_h, ack_h,
1098 status_h, error_h, termreq_h,
1100 add_host_h, del_host_h,
1101 add_subnet_h, del_subnet_h,
1102 key_changed_h, req_key_h, ans_key_h,
1107 char (*request_name[]) = {
1108 "ID", "CHALLENGE", "CHAL_REPLY", "ACK",
1109 "STATUS", "ERROR", "TERMREQ",
1111 "ADD_HOST", "DEL_HOST",
1112 "ADD_SUBNET", "DEL_SUBNET",
1113 "KEY_CHANGED", "REQ_KEY", "ANS_KEY",
1116 /* Status strings */
1118 char (*status_text[]) = {
1124 char (*error_text[]) = {