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.51 2000/10/29 10:39:08 guus Exp $
25 #include <sys/types.h>
30 #include <sys/socket.h>
37 #include <netinet/in.h>
39 #include <openssl/sha.h>
40 #include <openssl/rand.h>
41 #include <openssl/evp.h>
52 int check_id(char *id)
56 for (i = 0; i < strlen(id); i++)
57 if(!isalnum(id[i]) && id[i] != '_')
63 /* Generic request routines - takes care of logging and error detection as well */
65 int send_request(conn_list_t *cl, const char *format, ...)
68 char buffer[MAXBUFSIZE];
72 /* Use vsnprintf instead of vasprintf: faster, no memory fragmentation, cleanup is automatic,
73 and there is a limit on the input buffer anyway */
75 va_start(args, format);
76 len = vsnprintf(buffer, MAXBUFSIZE, format, args);
77 request = va_arg(args, int);
80 if(len < 0 || len > MAXBUFSIZE-1)
82 syslog(LOG_ERR, _("Output buffer overflow while sending %s to %s (%s)"), request_name[request], cl->name, cl->hostname);
88 if(debug_lvl >= DEBUG_PROTOCOL)
89 syslog(LOG_DEBUG, _("Sending %s to %s (%s)"), request_name[request], cl->name, cl->hostname);
92 return send_meta(cl, buffer, len);
95 int receive_request(conn_list_t *cl)
99 if(sscanf(cl->buffer, "%d", &request) == 1)
101 if((request < 0) || (request > 255) || (request_handlers[request] == NULL))
103 syslog(LOG_ERR, _("Unknown request from %s (%s)"),
104 cl->name, cl->hostname);
109 if(debug_lvl >= DEBUG_PROTOCOL)
110 syslog(LOG_DEBUG, _("Got %s from %s (%s)"),
111 request_name[request], cl->name, cl->hostname);
114 if((cl->allow_request != ALL) && (cl->allow_request != request))
116 syslog(LOG_ERR, _("Unauthorized request from %s (%s)"), cl->name, cl->hostname);
120 if(request_handlers[request](cl))
121 /* Something went wrong. Probably scriptkiddies. Terminate. */
123 syslog(LOG_ERR, _("Error while processing %s from %s (%s)"),
124 request_name[request], cl->name, cl->hostname);
130 syslog(LOG_ERR, _("Bogus data received from %s (%s)"),
131 cl->name, cl->hostname);
138 /* Connection protocol:
147 ---------------------------------------
148 Any negotations about the meta protocol
149 encryption go here(u).
150 ---------------------------------------
153 ---------------------------------------
159 (E) Encrypted with symmetric cipher.
161 Part of the challenge is directly used to set the symmetric cipher key and the initial vector.
162 Since a man-in-the-middle cannot decrypt the RSA challenges, this means that he cannot get or
163 forge the key for the symmetric cipher.
166 int send_id(conn_list_t *cl)
169 cl->allow_request = CHALLENGE;
171 return send_request(cl, "%d %s %d %lx %hd", ID, myself->name, myself->protocol_version, myself->options, myself->port);
174 int id_h(conn_list_t *cl)
179 if(sscanf(cl->buffer, "%*d %as %d %lx %hd", &cl->name, &cl->protocol_version, &cl->options, &cl->port) != 4)
181 syslog(LOG_ERR, _("Got bad ID from %s"), cl->hostname);
185 /* Check if version matches */
187 if(cl->protocol_version != myself->protocol_version)
189 syslog(LOG_ERR, _("Peer %s (%s) uses incompatible version %d"),
190 cl->name, cl->hostname, cl->protocol_version);
194 /* Check if identity is a valid name */
196 if(check_id(cl->name))
198 syslog(LOG_ERR, _("Peer %s uses invalid identity name"), cl->hostname);
202 /* Load information about peer */
204 if(read_host_config(cl))
206 syslog(LOG_ERR, _("Peer %s had unknown identity (%s)"), cl->hostname, cl->name);
210 /* First check if the host we connected to is already in our
211 connection list. If so, we are probably making a loop, which
215 if(cl->status.outgoing)
217 if((old = lookup_id(cl->name)))
219 if(debug_lvl >= DEBUG_CONNECTIONS)
220 syslog(LOG_NOTICE, _("Uplink %s (%s) is already in our connection list"), cl->name, cl->hostname);
221 cl->status.outgoing = 0;
222 old->status.outgoing = 1;
223 terminate_connection(cl);
228 if((cfg = get_config_val(cl->config, publickey)))
230 cl->rsa_key = RSA_new();
231 BN_hex2bn(&cl->rsa_key->n, cfg->data.ptr);
232 BN_hex2bn(&cl->rsa_key->e, "FFFF");
236 syslog(LOG_ERR, _("No public key known for %s (%s)"), cl->name, cl->hostname);
240 return send_challenge(cl);
243 int send_challenge(conn_list_t *cl)
248 len = RSA_size(cl->rsa_key);
250 /* Allocate buffers for the challenge */
252 buffer = xmalloc(len*2+1);
255 free(cl->hischallenge);
257 cl->hischallenge = xmalloc(len);
259 /* Seed the PRNG with urandom (can't afford to block) */
261 RAND_load_file("/dev/urandom", 1024);
263 /* Copy random data to the buffer */
265 RAND_bytes(cl->hischallenge, len);
267 cl->hischallenge[0] &= 0x7F; /* Somehow if the first byte is more than 0xD0 or something like that, decryption fails... */
269 if(debug_lvl >= DEBUG_SCARY_THINGS)
271 bin2hex(cl->hischallenge, buffer, len);
272 buffer[len*2] = '\0';
273 syslog(LOG_DEBUG, _("Generated random challenge (unencrypted): %s"), buffer);
276 /* Encrypt the random data */
278 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 */
280 syslog(LOG_ERR, _("Error during encryption of challenge for %s (%s)"), cl->name, cl->hostname);
285 /* Convert the encrypted random data to a hexadecimal formatted string */
287 bin2hex(buffer, buffer, len);
288 buffer[len*2] = '\0';
290 /* Send the challenge */
292 cl->allow_request = CHAL_REPLY;
293 x = send_request(cl, "%d %s", CHALLENGE, buffer);
299 int challenge_h(conn_list_t *cl)
304 if(sscanf(cl->buffer, "%*d %as", &buffer) != 1)
306 syslog(LOG_ERR, _("Got bad CHALLENGE from %s (%s)"), cl->name, cl->hostname);
310 len = RSA_size(myself->rsa_key);
312 /* Check if the length of the challenge is all right */
314 if(strlen(buffer) != len*2)
316 syslog(LOG_ERR, _("Intruder: wrong challenge length from %s (%s)"), cl->name, cl->hostname);
321 /* Allocate buffers for the challenge */
324 cl->mychallenge = xmalloc(len);
326 /* Convert the challenge from hexadecimal back to binary */
328 hex2bin(buffer,buffer,len);
330 /* Decrypt the challenge */
332 if(RSA_private_decrypt(len, buffer, cl->mychallenge, myself->rsa_key, RSA_NO_PADDING) != len) /* See challenge() */
334 syslog(LOG_ERR, _("Error during encryption of challenge for %s (%s)"), cl->name, cl->hostname);
339 if(debug_lvl >= DEBUG_SCARY_THINGS)
341 bin2hex(cl->mychallenge, buffer, len);
342 buffer[len*2] = '\0';
343 syslog(LOG_DEBUG, _("Received random challenge (unencrypted): %s"), buffer);
348 /* Rest is done by send_chal_reply() */
350 return send_chal_reply(cl);
353 int send_chal_reply(conn_list_t *cl)
355 char hash[SHA_DIGEST_LENGTH*2+1];
359 syslog(LOG_ERR, _("Trying to send CHAL_REPLY to %s (%s) without a valid CHALLENGE"), cl->name, cl->hostname);
363 /* Calculate the hash from the challenge we received */
365 SHA1(cl->mychallenge, RSA_size(myself->rsa_key), hash);
367 /* Convert the hash to a hexadecimal formatted string */
369 bin2hex(hash,hash,SHA_DIGEST_LENGTH);
370 hash[SHA_DIGEST_LENGTH*2] = '\0';
374 if(cl->status.outgoing)
375 cl->allow_request = ID;
377 cl->allow_request = ACK;
380 return send_request(cl, "%d %s", CHAL_REPLY, hash);
383 int chal_reply_h(conn_list_t *cl)
386 char myhash[SHA_DIGEST_LENGTH];
388 if(sscanf(cl->buffer, "%*d %as", &hishash) != 1)
390 syslog(LOG_ERR, _("Got bad CHAL_REPLY from %s (%s)"), cl->name, cl->hostname);
395 /* Check if the length of the hash is all right */
397 if(strlen(hishash) != SHA_DIGEST_LENGTH*2)
399 syslog(LOG_ERR, _("Intruder: wrong challenge reply length from %s (%s)"), cl->name, cl->hostname);
404 /* Convert the hash to binary format */
406 hex2bin(hishash, hishash, SHA_DIGEST_LENGTH);
408 /* Calculate the hash from the challenge we sent */
410 SHA1(cl->hischallenge, RSA_size(cl->rsa_key), myhash);
412 /* Verify the incoming hash with the calculated hash */
414 if(memcmp(hishash, myhash, SHA_DIGEST_LENGTH))
416 syslog(LOG_ERR, _("Intruder: wrong challenge reply from %s (%s)"), cl->name, cl->hostname);
417 if(debug_lvl >= DEBUG_SCARY_THINGS)
419 bin2hex(myhash, hishash, SHA_DIGEST_LENGTH);
420 hishash[SHA_DIGEST_LENGTH*2] = '\0';
421 syslog(LOG_DEBUG, _("Expected challenge reply: %s"), hishash);
430 /* Identity has now been positively verified.
431 If we are accepting this new connection, then send our identity,
432 if we are making this connecting, acknowledge.
435 if(cl->status.outgoing)
441 int send_ack(conn_list_t *cl)
444 if(cl->status.outgoing)
445 cl->allow_request = ACK;
447 return send_request(cl, "%d", ACK);
450 int ack_h(conn_list_t *cl)
452 conn_list_t *old, *p;
455 /* Okay, before we active the connection, we check if there is another entry
456 in the connection list with the same name. If so, it presumably is an
457 old connection that has timed out but we don't know it yet.
460 while((old = lookup_id(cl->name)))
462 if(debug_lvl >= DEBUG_CONNECTIONS)
463 syslog(LOG_NOTICE, _("Removing old entry for %s at %s in favour of new connection from %s"),
464 cl->name, old->hostname, cl->hostname);
466 terminate_connection(old);
469 /* Activate this connection */
471 cl->allow_request = ALL;
472 cl->status.active = 1;
474 cl->cipher_pkttype = EVP_bf_cbc();
476 if(debug_lvl >= DEBUG_CONNECTIONS)
477 syslog(LOG_NOTICE, _("Connection with %s (%s) activated"), cl->name, cl->hostname);
480 if(!cl->status.outgoing)
483 /* Send him our subnets */
485 for(s = myself->subnets; s; s = s->next)
486 send_add_subnet(cl, s);
488 /* And send him all the hosts and their subnets we know... */
490 for(p = conn_list; p; p = p->next)
491 if(p != cl && p->status.active)
493 /* Notify others of this connection */
496 send_add_host(p, cl);
498 /* Notify new connection of everything we know */
500 send_add_host(cl, p);
502 for(s = p->subnets; s; s = s->next)
503 send_add_subnet(cl, s);
509 /* Address and subnet information exchange */
511 int send_add_subnet(conn_list_t *cl, subnet_t *subnet)
516 x = send_request(cl, "%d %s %s", ADD_SUBNET,
517 subnet->owner->name, netstr = net2str(subnet));
523 int add_subnet_h(conn_list_t *cl)
527 conn_list_t *owner, *p;
530 if(sscanf(cl->buffer, "%*d %as %as", &name, &subnetstr) != 2)
532 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s)"), cl->name, cl->hostname);
533 free(name); free(subnetstr);
537 /* Check if owner name is a valid */
541 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s): invalid identity name"), cl->name, cl->hostname);
542 free(name); free(subnetstr);
546 /* Check if subnet string is valid */
548 if(!(subnet = str2net(subnetstr)))
550 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s): invalid subnet string"), cl->name, cl->hostname);
551 free(name); free(subnetstr);
557 /* Check if somebody tries to add a subnet of ourself */
559 if(!strcmp(name, myself->name))
561 syslog(LOG_ERR, _("Warning: got ADD_SUBNET from %s (%s) for ourself, restarting"),
562 cl->name, cl->hostname);
568 /* Check if the owner of the new subnet is in the connection list */
570 if(!(owner = lookup_id(name)))
572 syslog(LOG_ERR, _("Got ADD_SUBNET for %s from %s (%s) which is not in our connection list"),
573 name, cl->name, cl->hostname);
578 /* If everything is correct, add the subnet to the list of the owner */
580 subnet_add(owner, subnet);
584 for(p = conn_list; p; p = p->next)
585 if(p->status.meta && p->status.active && p!= cl)
586 send_add_subnet(p, subnet);
591 int send_del_subnet(conn_list_t *cl, subnet_t *subnet)
596 netstr = net2str(subnet);
597 x = send_request(cl, "%d %s %s", DEL_SUBNET, subnet->owner->name, netstr);
603 int del_subnet_h(conn_list_t *cl)
607 conn_list_t *owner, *p;
610 if(sscanf(cl->buffer, "%*d %as %as", &name, &subnetstr) != 3)
612 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s)"), cl->name, cl->hostname);
613 free(name); free(subnetstr);
617 /* Check if owner name is a valid */
621 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s): invalid identity name"), cl->name, cl->hostname);
622 free(name); free(subnetstr);
626 /* Check if subnet string is valid */
628 if(!(subnet = str2net(subnetstr)))
630 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s): invalid subnet string"), cl->name, cl->hostname);
631 free(name); free(subnetstr);
637 /* Check if somebody tries to add a subnet of ourself */
639 if(!strcmp(name, myself->name))
641 syslog(LOG_ERR, _("Warning: got DEL_SUBNET from %s (%s) for ourself, restarting"),
642 cl->name, cl->hostname);
648 /* Check if the owner of the new subnet is in the connection list */
650 if(!(owner = lookup_id(name)))
652 syslog(LOG_ERR, _("Got DEL_SUBNET for %s from %s (%s) which is not in our connection list"),
653 name, cl->name, cl->hostname);
658 /* If everything is correct, delete the subnet from the list of the owner */
664 for(p = conn_list; p; p = p->next)
665 if(p->status.meta && p->status.active && p!= cl)
666 send_del_subnet(p, subnet);
671 /* New and closed connections notification */
673 int send_add_host(conn_list_t *cl, conn_list_t *other)
676 return send_request(cl, "%d %s %lx:%d %lx", ADD_HOST,
677 other->name, other->address, other->port, other->options);
680 int add_host_h(conn_list_t *cl)
682 conn_list_t *old, *new;
685 new = new_conn_list();
687 if(sscanf(cl->buffer, "%*d %as %lx:%d %lx", &new->name, &new->address, &new->port, &new->options) != 4)
689 syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s)"), cl->name, cl->hostname);
693 /* Check if identity is a valid name */
695 if(check_id(new->name))
697 syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s): invalid identity name"), cl->name, cl->hostname);
702 /* Check if somebody tries to add ourself */
704 if(!strcmp(new->name, myself->name))
706 syslog(LOG_ERR, _("Warning: got ADD_HOST from %s (%s) for ourself, restarting"), cl->name, cl->hostname);
712 /* Fill in more of the new conn_list structure */
714 new->hostname = hostlookup(htonl(new->address));
716 /* Check if the new host already exists in the connnection list */
718 if((old = lookup_id(new->name)))
720 if((new->address == old->address) && (new->port == old->port))
722 if(debug_lvl >= DEBUG_CONNECTIONS)
723 syslog(LOG_NOTICE, _("Got duplicate ADD_HOST for %s (%s) from %s (%s)"),
724 old->name, old->hostname, new->name, new->hostname);
730 if(debug_lvl >= DEBUG_CONNECTIONS)
731 syslog(LOG_NOTICE, _("Removing old entry for %s (%s) in favour of new connection"),
732 old->name, old->hostname);
734 terminate_connection(old);
738 /* Hook it up into the conn_list */
742 /* Tell the rest about the new host */
744 for(p = conn_list; p; p = p->next)
745 if(p->status.meta && p->status.active && p!=cl)
746 send_add_host(p, new);
748 /* Fill in rest of conn_list structure */
751 new->status.active = 1;
757 int send_del_host(conn_list_t *cl, conn_list_t *other)
760 return send_request(cl, "%d %s %lx:%d %lx", DEL_HOST,
761 other->name, other->address, other->port, other->options);
764 int del_host_h(conn_list_t *cl)
770 conn_list_t *old, *p;
772 if(sscanf(cl->buffer, "%*d %as %lx:%d %lx", &name, &address, &port, &options) != 4)
774 syslog(LOG_ERR, _("Got bad DEL_HOST from %s (%s)"),
775 cl->name, cl->hostname);
779 /* Check if identity is a valid name */
783 syslog(LOG_ERR, _("Got bad DEL_HOST from %s (%s): invalid identity name"), cl->name, cl->hostname);
788 /* Check if somebody tries to delete ourself */
790 if(!strcmp(name, myself->name))
792 syslog(LOG_ERR, _("Warning: got DEL_HOST from %s (%s) for ourself, restarting"),
793 cl->name, cl->hostname);
799 /* Check if the new host already exists in the connnection list */
801 if(!(old = lookup_id(name)))
803 syslog(LOG_ERR, _("Got DEL_HOST from %s (%s) for %s which is not in our connection list"),
804 name, cl->name, cl->hostname);
809 /* Check if the rest matches */
811 if(address!=old->address || port!=old->port || options!=old->options || cl!=old->nexthop)
813 syslog(LOG_WARNING, _("Got DEL_HOST from %s (%s) for %s which doesn't match"), cl->name, cl->hostname, old->name);
817 /* Ok, since EVERYTHING seems to check out all right, delete it */
819 old->status.active = 0;
820 terminate_connection(old);
822 /* Tell the rest about the new host */
824 for(p = conn_list; p; p = p->next)
825 if(p->status.meta && p->status.active && p!=cl)
826 send_del_host(p, old);
831 /* Status and error notification routines */
833 int send_status(conn_list_t *cl, int statusno, char *statusstring)
837 statusstring = status_text[statusno];
839 return send_request(cl, "%d %d %s", STATUS, statusno, statusstring);
842 int status_h(conn_list_t *cl)
847 if(sscanf(cl->buffer, "%*d %d %as", &statusno, &statusstring) != 2)
849 syslog(LOG_ERR, _("Got bad STATUS from %s (%s)"),
850 cl->name, cl->hostname);
854 if(debug_lvl >= DEBUG_STATUS)
856 syslog(LOG_NOTICE, _("Status message from %s (%s): %s: %s"),
857 cl->name, cl->hostname, status_text[statusno], statusstring);
865 int send_error(conn_list_t *cl, int errno, char *errstring)
869 errstring = strerror(errno);
870 return send_request(cl, "%d %d %s", ERROR, errno, errstring);
873 int error_h(conn_list_t *cl)
878 if(sscanf(cl->buffer, "%*d %d %as", &errno, &errorstring) != 2)
880 syslog(LOG_ERR, _("Got bad ERROR from %s (%s)"),
881 cl->name, cl->hostname);
885 if(debug_lvl >= DEBUG_ERROR)
887 syslog(LOG_NOTICE, _("Error message from %s (%s): %s: %s"),
888 cl->name, cl->hostname, strerror(errno), errorstring);
892 terminate_connection(cl);
897 int send_termreq(conn_list_t *cl)
900 return send_request(cl, "%d", TERMREQ);
903 int termreq_h(conn_list_t *cl)
906 terminate_connection(cl);
911 /* Keepalive routines - FIXME: needs a closer look */
913 int send_ping(conn_list_t *cl)
915 cl->status.pinged = 1;
917 return send_request(cl, "%d", PING);
920 int ping_h(conn_list_t *cl)
923 return send_pong(cl);
926 int send_pong(conn_list_t *cl)
929 return send_request(cl, "%d", PONG);
932 int pong_h(conn_list_t *cl)
935 cl->status.got_pong = 1;
942 int send_key_changed(conn_list_t *from, conn_list_t *cl)
946 for(p = conn_list; p != NULL; p = p->next)
948 if(p!=cl && p->status.meta && p->status.active)
949 send_request(p, "%d %s", KEY_CHANGED,
956 int key_changed_h(conn_list_t *cl)
961 if(sscanf(cl->buffer, "%*d %as", &from_id) != 1)
963 syslog(LOG_ERR, _("Got bad KEY_CHANGED from %s (%s)"),
964 cl->name, cl->hostname);
968 if(!(from = lookup_id(from_id)))
970 syslog(LOG_ERR, _("Got KEY_CHANGED from %s (%s) origin %s which does not exist in our connection list"),
971 cl->name, cl->hostname, from_id);
978 from->status.validkey = 0;
979 from->status.waitingforkey = 0;
981 send_key_changed(from, cl);
986 int send_req_key(conn_list_t *from, conn_list_t *to)
989 return send_request(to->nexthop, "%d %s %s", REQ_KEY,
990 from->name, to->name);
993 int req_key_h(conn_list_t *cl)
995 char *from_id, *to_id;
996 conn_list_t *from, *to;
999 if(sscanf(cl->buffer, "%*d %as %as", &from_id, &to_id) != 2)
1001 syslog(LOG_ERR, _("Got bad REQ_KEY from %s (%s)"),
1002 cl->name, cl->hostname);
1006 if(!(from = lookup_id(from_id)))
1008 syslog(LOG_ERR, _("Got REQ_KEY from %s (%s) origin %s which does not exist in our connection list"),
1009 cl->name, cl->hostname, from_id);
1010 free(from_id); free(to_id);
1014 /* Check if this key request is for us */
1016 if(!strcmp(to_id, myself->name))
1018 bin2hex(myself->cipher_pktkey, pktkey, 64);
1020 send_ans_key(myself, from, pktkey);
1024 if(!(to = lookup_id(to_id)))
1026 syslog(LOG_ERR, _("Got REQ_KEY from %s (%s) destination %s which does not exist in our connection list"),
1027 cl->name, cl->hostname, to_id);
1028 free(from_id); free(to_id);
1031 send_req_key(from, to);
1034 free(from_id); free(to_id);
1039 int send_ans_key(conn_list_t *from, conn_list_t *to, char *pktkey)
1042 return send_request(to->nexthop, "%d %s %s %s", ANS_KEY,
1043 from->name, to->name, pktkey);
1046 int ans_key_h(conn_list_t *cl)
1048 char *from_id, *to_id, *pktkey;
1050 conn_list_t *from, *to;
1052 if(sscanf(cl->buffer, "%*d %as %as %as", &from_id, &to_id, &pktkey) != 3)
1054 syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s)"),
1055 cl->name, cl->hostname);
1059 if(!(from = lookup_id(from_id)))
1061 syslog(LOG_ERR, _("Got ANS_KEY from %s (%s) origin %s which does not exist in our connection list"),
1062 cl->name, cl->hostname, from_id);
1063 free(from_id); free(to_id); free(pktkey);
1067 /* Update origin's packet key */
1069 keylength = strlen(pktkey);
1071 if((keylength%2)!=0 || (keylength <= 0))
1073 syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s) origin %s: invalid key"),
1074 cl->name, cl->hostname, from->name);
1075 free(from_id); free(to_id); free(pktkey);
1079 if(from->cipher_pktkey)
1080 free(from->cipher_pktkey);
1083 hex2bin(pktkey, pktkey, keylength);
1084 pktkey[keylength] = '\0';
1085 from->cipher_pktkey = pktkey;
1087 from->status.validkey = 1;
1088 from->status.waitingforkey = 0;
1090 if(strcmp(to_id, myself->name))
1092 if(!(to = lookup_id(to_id)))
1094 syslog(LOG_ERR, _("Got ANS_KEY from %s (%s) destination %s which does not exist in our connection list"),
1095 cl->name, cl->hostname, to_id);
1096 free(from_id); free(to_id);
1099 send_ans_key(from, to, pktkey);
1102 free(from_id); free(to_id);
1107 /* Jumptable for the request handlers */
1109 int (*request_handlers[])(conn_list_t*) = {
1110 id_h, challenge_h, chal_reply_h, ack_h,
1111 status_h, error_h, termreq_h,
1113 add_host_h, del_host_h,
1114 add_subnet_h, del_subnet_h,
1115 key_changed_h, req_key_h, ans_key_h,
1120 char (*request_name[]) = {
1121 "ID", "CHALLENGE", "CHAL_REPLY", "ACK",
1122 "STATUS", "ERROR", "TERMREQ",
1124 "ADD_HOST", "DEL_HOST",
1125 "ADD_SUBNET", "DEL_SUBNET",
1126 "KEY_CHANGED", "REQ_KEY", "ANS_KEY",
1129 /* Status strings */
1131 char (*status_text[]) = {
1137 char (*error_text[]) = {