0728ea1a1b104e0f6b9971f40ae0e1ba64538794
[oweals/tinc.git] / src / protocol.c
1 /*
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>
5
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.
10
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.
15
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.
19
20     $Id: protocol.c,v 1.28.4.57 2000/11/04 20:44:28 guus Exp $
21 */
22
23 #include "config.h"
24
25 #include <sys/types.h>
26
27 #include <stdlib.h>
28 #include <string.h>
29 #include <syslog.h>
30 #include <sys/socket.h>
31 #include <unistd.h>
32 #include <stdio.h>
33
34 #include <utils.h>
35 #include <xalloc.h>
36
37 #include <netinet/in.h>
38
39 #include <openssl/sha.h>
40 #include <openssl/rand.h>
41 #include <openssl/evp.h>
42
43 #include "conf.h"
44 #include "net.h"
45 #include "netutl.h"
46 #include "protocol.h"
47 #include "meta.h"
48 #include "connlist.h"
49
50 #include "system.h"
51
52 int check_id(char *id)
53 {
54   int i;
55
56   for (i = 0; i < strlen(id); i++)
57     if(!isalnum(id[i]) && id[i] != '_')
58       return -1;
59           
60   return 0;
61 }
62
63 /* Generic request routines - takes care of logging and error detection as well */
64
65 int send_request(conn_list_t *cl, const char *format, ...)
66 {
67   va_list args;
68   char buffer[MAXBUFSIZE];
69   int len, request;
70
71 cp
72   /* Use vsnprintf instead of vasprintf: faster, no memory fragmentation, cleanup is automatic,
73      and there is a limit on the input buffer anyway */
74
75   va_start(args, format);
76   len = vsnprintf(buffer, MAXBUFSIZE, format, args);
77   request = va_arg(args, int);
78   va_end(args);
79
80   if(len < 0 || len > MAXBUFSIZE-1)
81     {
82       syslog(LOG_ERR, _("Output buffer overflow while sending %s to %s (%s)"), request_name[request], cl->name, cl->hostname);
83       return -1;
84     }
85
86   len++;
87
88   if(debug_lvl >= DEBUG_PROTOCOL)
89     syslog(LOG_DEBUG, _("Sending %s to %s (%s)"), request_name[request], cl->name, cl->hostname);
90
91 cp
92   return send_meta(cl, buffer, len);
93 }
94
95 int receive_request(conn_list_t *cl)
96 {
97   int request;
98 cp  
99   if(sscanf(cl->buffer, "%d", &request) == 1)
100     {
101       if((request < 0) || (request > 255) || (request_handlers[request] == NULL))
102         {
103           syslog(LOG_ERR, _("Unknown request from %s (%s)"),
104                  cl->name, cl->hostname);
105           return -1;
106         }
107       else
108         {
109           if(debug_lvl >= DEBUG_PROTOCOL)
110             syslog(LOG_DEBUG, _("Got %s from %s (%s)"),
111                    request_name[request], cl->name, cl->hostname);
112         }
113
114       if((cl->allow_request != ALL) && (cl->allow_request != request))
115         {
116           syslog(LOG_ERR, _("Unauthorized request from %s (%s)"), cl->name, cl->hostname);
117           return -1;
118         }
119
120       if(request_handlers[request](cl))
121         /* Something went wrong. Probably scriptkiddies. Terminate. */
122         {
123           syslog(LOG_ERR, _("Error while processing %s from %s (%s)"),
124                  request_name[request], cl->name, cl->hostname);
125           return -1;
126         }
127     }
128   else
129     {
130       syslog(LOG_ERR, _("Bogus data received from %s (%s)"),
131              cl->name, cl->hostname);
132       return -1;
133     }
134 cp
135   return 0;
136 }
137
138 /* Connection protocol:
139
140    Client               Server
141    send_id(u)
142                         send_challenge(R)
143    send_chal_reply(H)
144                         send_id(u)
145    send_challenge(R)
146                         send_chal_reply(H)
147    ---------------------------------------
148    send_metakey(R)
149                         send_metakey(R)
150    ---------------------------------------
151    send_ack(u)
152                         send_ack(u)
153    ---------------------------------------
154    Other requests(E)...
155
156    (u) Unencrypted,
157    (R) RSA,
158    (H) SHA1,
159    (E) Encrypted with symmetric cipher.
160
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.
164 */
165
166 int send_id(conn_list_t *cl)
167 {
168 cp
169   cl->allow_request = CHALLENGE;
170 cp
171   return send_request(cl, "%d %s %d %lx %hd", ID, myself->name, myself->protocol_version, myself->options, myself->port);
172 }
173
174 int id_h(conn_list_t *cl)
175 {
176   conn_list_t *old;
177   config_t const *cfg;
178 cp
179   if(sscanf(cl->buffer, "%*d %as %d %lx %hd", &cl->name, &cl->protocol_version, &cl->options, &cl->port) != 4)
180     {
181        syslog(LOG_ERR, _("Got bad ID from %s"), cl->hostname);
182        return -1;
183     }
184
185   /* Check if version matches */
186
187   if(cl->protocol_version != myself->protocol_version)
188     {
189       syslog(LOG_ERR, _("Peer %s (%s) uses incompatible version %d"),
190              cl->name, cl->hostname, cl->protocol_version);
191       return -1;
192     }
193
194   /* Check if identity is a valid name */
195
196   if(check_id(cl->name))
197     {
198       syslog(LOG_ERR, _("Peer %s uses invalid identity name"), cl->hostname);
199       return -1;
200     }
201
202   /* Load information about peer */
203 cp
204   if(read_host_config(cl))
205     {
206       syslog(LOG_ERR, _("Peer %s had unknown identity (%s)"), cl->hostname, cl->name);
207       return -1;
208     }
209
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
212      is not desirable.
213    */
214 cp
215   if(cl->status.outgoing)
216     {
217       if((old = lookup_id(cl->name)))
218         {
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);
224           return 0;
225         }
226     }
227 cp    
228   if((cfg = get_config_val(cl->config, publickey)))
229     {
230       cl->rsa_key = RSA_new();
231       BN_hex2bn(&cl->rsa_key->n, cfg->data.ptr);
232       BN_hex2bn(&cl->rsa_key->e, "FFFF");
233     }
234   else
235     {
236       syslog(LOG_ERR, _("No public key known for %s (%s)"), cl->name, cl->hostname);
237       return -1;
238     }
239 cp
240   return send_challenge(cl);
241 }
242
243 int send_challenge(conn_list_t *cl)
244 {
245   char *buffer;
246   int len, x;
247 cp
248   len = RSA_size(cl->rsa_key);
249
250   /* Allocate buffers for the challenge */
251
252   buffer = xmalloc(len*2+1);
253
254   if(cl->hischallenge)
255     free(cl->hischallenge);
256     
257   cl->hischallenge = xmalloc(len);
258 cp
259   /* Copy random data to the buffer */
260
261   RAND_bytes(cl->hischallenge, len);
262
263   cl->hischallenge[0] &= 0x7F;  /* Somehow if the first byte is more than 0xD0 or something like that, decryption fails... */
264
265   if(debug_lvl >= DEBUG_SCARY_THINGS)
266     {
267       bin2hex(cl->hischallenge, buffer, len);
268       buffer[len*2] = '\0';
269       syslog(LOG_DEBUG, _("Generated random challenge (unencrypted): %s"), buffer);
270     }
271
272   /* Encrypt the random data */
273   
274   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 */
275     {
276       syslog(LOG_ERR, _("Error during encryption of challenge for %s (%s)"), cl->name, cl->hostname);
277       free(buffer);
278       return -1;
279     }
280 cp
281   /* Convert the encrypted random data to a hexadecimal formatted string */
282
283   bin2hex(buffer, buffer, len);
284   buffer[len*2] = '\0';
285
286   /* Send the challenge */
287
288   cl->allow_request = CHAL_REPLY;
289   x = send_request(cl, "%d %s", CHALLENGE, buffer);
290   free(buffer);
291 cp
292   return x;
293 }
294
295 int challenge_h(conn_list_t *cl)
296 {
297   char *buffer;
298   int len;
299 cp
300   if(sscanf(cl->buffer, "%*d %as", &buffer) != 1)
301     {
302        syslog(LOG_ERR, _("Got bad CHALLENGE from %s (%s)"), cl->name, cl->hostname);
303        return -1;
304     }
305
306   len = RSA_size(myself->rsa_key);
307
308   /* Check if the length of the challenge is all right */
309
310   if(strlen(buffer) != len*2)
311     {
312       syslog(LOG_ERR, _("Intruder: wrong challenge length from %s (%s)"), cl->name, cl->hostname);
313       free(buffer);
314       return -1;
315     }
316
317   /* Allocate buffers for the challenge */
318
319   if(!cl->mychallenge)
320     cl->mychallenge = xmalloc(len);
321
322   /* Convert the challenge from hexadecimal back to binary */
323
324   hex2bin(buffer,buffer,len);
325
326   /* Decrypt the challenge */
327   
328   if(RSA_private_decrypt(len, buffer, cl->mychallenge, myself->rsa_key, RSA_NO_PADDING) != len) /* See challenge() */
329     {
330       syslog(LOG_ERR, _("Error during encryption of challenge for %s (%s)"), cl->name, cl->hostname);
331       free(buffer);
332       return -1;
333     }
334
335   if(debug_lvl >= DEBUG_SCARY_THINGS)
336     {
337       bin2hex(cl->mychallenge, buffer, len);
338       buffer[len*2] = '\0';
339       syslog(LOG_DEBUG, _("Received random challenge (unencrypted): %s"), buffer);
340     }
341
342   free(buffer);
343     
344   /* Rest is done by send_chal_reply() */
345 cp
346   return send_chal_reply(cl);
347 }
348
349 int send_chal_reply(conn_list_t *cl)
350 {
351   char hash[SHA_DIGEST_LENGTH*2+1];
352 cp
353   if(!cl->mychallenge)
354     {
355       syslog(LOG_ERR, _("Trying to send CHAL_REPLY to %s (%s) without a valid CHALLENGE"), cl->name, cl->hostname);
356       return -1;
357     }
358      
359   /* Calculate the hash from the challenge we received */
360
361   SHA1(cl->mychallenge, RSA_size(myself->rsa_key), hash);
362
363   /* Convert the hash to a hexadecimal formatted string */
364
365   bin2hex(hash,hash,SHA_DIGEST_LENGTH);
366   hash[SHA_DIGEST_LENGTH*2] = '\0';
367
368   /* Send the reply */
369
370   if(cl->status.outgoing)
371     cl->allow_request = ID;
372   else
373     cl->allow_request = METAKEY;
374
375 cp
376   return send_request(cl, "%d %s", CHAL_REPLY, hash);
377 }
378
379 int chal_reply_h(conn_list_t *cl)
380 {
381   char *hishash;
382   char myhash[SHA_DIGEST_LENGTH];
383 cp
384   if(sscanf(cl->buffer, "%*d %as", &hishash) != 1)
385     {
386        syslog(LOG_ERR, _("Got bad CHAL_REPLY from %s (%s)"), cl->name, cl->hostname);
387        free(hishash);
388        return -1;
389     }
390
391   /* Check if the length of the hash is all right */
392
393   if(strlen(hishash) != SHA_DIGEST_LENGTH*2)
394     {
395       syslog(LOG_ERR, _("Intruder: wrong challenge reply length from %s (%s)"), cl->name, cl->hostname);
396       free(hishash);
397       return -1;
398     }
399
400   /* Convert the hash to binary format */
401
402   hex2bin(hishash, hishash, SHA_DIGEST_LENGTH);
403
404   /* Calculate the hash from the challenge we sent */
405
406   SHA1(cl->hischallenge, RSA_size(cl->rsa_key), myhash);
407
408   /* Verify the incoming hash with the calculated hash */
409
410   if(memcmp(hishash, myhash, SHA_DIGEST_LENGTH))
411     {
412       syslog(LOG_ERR, _("Intruder: wrong challenge reply from %s (%s)"), cl->name, cl->hostname);
413       if(debug_lvl >= DEBUG_SCARY_THINGS)
414         {
415           bin2hex(myhash, hishash, SHA_DIGEST_LENGTH);
416           hishash[SHA_DIGEST_LENGTH*2] = '\0';
417           syslog(LOG_DEBUG, _("Expected challenge reply: %s"), hishash);
418         }
419       free(hishash);
420       return -1;
421     }
422
423
424   free(hishash);
425
426   /* Identity has now been positively verified.
427      If we are accepting this new connection, then send our identity,
428      if we are making this connecting, acknowledge.
429    */
430 cp
431   if(cl->status.outgoing)
432       return send_metakey(cl);
433   else
434       return send_id(cl);
435 }
436
437 int send_metakey(conn_list_t *cl)
438 {
439   char *buffer;
440   int len, x;
441 cp
442   len = RSA_size(cl->rsa_key);
443
444   /* Allocate buffers for the meta key */
445
446   buffer = xmalloc(len*2+1);
447
448   if(!cl->cipher_outkey)
449     cl->cipher_outkey = xmalloc(len);
450     
451   if(!cl->cipher_outctx)
452     cl->cipher_outctx = xmalloc(sizeof(*cl->cipher_outctx));
453 cp
454   /* Copy random data to the buffer */
455
456   RAND_bytes(cl->cipher_outkey, len);
457
458   cl->cipher_outkey[0] &= 0x7F; /* FIXME: Somehow if the first byte is more than 0xD0 or something like that, decryption fails... */
459
460   if(debug_lvl >= DEBUG_SCARY_THINGS)
461     {
462       bin2hex(cl->cipher_outkey, buffer, len);
463       buffer[len*2] = '\0';
464       syslog(LOG_DEBUG, _("Generated random meta key (unencrypted): %s"), buffer);
465     }
466
467   /* Encrypt the random data */
468   
469   if(RSA_public_encrypt(len, cl->cipher_outkey, buffer, cl->rsa_key, RSA_NO_PADDING) != len)    /* NO_PADDING because the message size equals the RSA key size and it is totally random */
470     {
471       syslog(LOG_ERR, _("Error during encryption of meta key for %s (%s)"), cl->name, cl->hostname);
472       free(buffer);
473       return -1;
474     }
475 cp
476   /* Convert the encrypted random data to a hexadecimal formatted string */
477
478   bin2hex(buffer, buffer, len);
479   buffer[len*2] = '\0';
480
481   /* Send the meta key */
482
483   if(cl->status.outgoing)
484     cl->allow_request = METAKEY;
485   else
486     cl->allow_request = ACK;
487     
488   x = send_request(cl, "%d %s", METAKEY, buffer);
489   free(buffer);
490
491   EVP_EncryptInit(cl->cipher_outctx, EVP_bf_cfb(), cl->cipher_outkey, cl->cipher_outkey + EVP_bf_cfb()->key_len);
492 cp
493   return x;
494 }
495
496 int metakey_h(conn_list_t *cl)
497 {
498   char *buffer;
499   int len;
500 cp
501   if(sscanf(cl->buffer, "%*d %as", &buffer) != 1)
502     {
503        syslog(LOG_ERR, _("Got bad METAKEY from %s (%s)"), cl->name, cl->hostname);
504        return -1;
505     }
506
507   len = RSA_size(myself->rsa_key);
508
509   /* Check if the length of the meta key is all right */
510
511   if(strlen(buffer) != len*2)
512     {
513       syslog(LOG_ERR, _("Intruder: wrong meta key length from %s (%s)"), cl->name, cl->hostname);
514       free(buffer);
515       return -1;
516     }
517
518   /* Allocate buffers for the meta key */
519
520   if(!cl->cipher_inkey)
521     cl->cipher_inkey = xmalloc(len);
522
523   if(!cl->cipher_inctx)
524     cl->cipher_inctx = xmalloc(sizeof(*cl->cipher_inctx));
525
526   /* Convert the challenge from hexadecimal back to binary */
527
528   hex2bin(buffer,buffer,len);
529
530   /* Decrypt the meta key */
531   
532   if(RSA_private_decrypt(len, buffer, cl->cipher_inkey, myself->rsa_key, RSA_NO_PADDING) != len)        /* See challenge() */
533     {
534       syslog(LOG_ERR, _("Error during encryption of meta key for %s (%s)"), cl->name, cl->hostname);
535       free(buffer);
536       return -1;
537     }
538
539   if(debug_lvl >= DEBUG_SCARY_THINGS)
540     {
541       bin2hex(cl->cipher_inkey, buffer, len);
542       buffer[len*2] = '\0';
543       syslog(LOG_DEBUG, _("Received random meta key (unencrypted): %s"), buffer);
544     }
545
546   free(buffer);
547
548   EVP_DecryptInit(cl->cipher_inctx, EVP_bf_cfb(), cl->cipher_inkey, cl->cipher_inkey + EVP_bf_cfb()->key_len);
549   
550 cp
551   if(cl->status.outgoing)
552     return send_ack(cl);
553   else
554     return send_metakey(cl);
555 }
556
557 int send_ack(conn_list_t *cl)
558 {
559   int x;
560 cp
561   if(cl->status.outgoing)
562     cl->allow_request = ACK;
563
564   x = send_request(cl, "%d", ACK);
565   cl->status.encryptout = 1;
566 cp
567   return x;
568 }
569
570 int ack_h(conn_list_t *cl)
571 {
572   conn_list_t *old, *p;
573   subnet_t *s;
574 cp
575   /* Okay, before we active the connection, we check if there is another entry
576      in the connection list with the same name. If so, it presumably is an
577      old connection that has timed out but we don't know it yet.
578    */
579
580   while((old = lookup_id(cl->name)))
581     {
582       if(debug_lvl >= DEBUG_CONNECTIONS)
583         syslog(LOG_NOTICE, _("Removing old entry for %s at %s in favour of new connection from %s"),
584         cl->name, old->hostname, cl->hostname);
585
586       terminate_connection(old);
587     }
588
589   /* Activate this connection */
590
591   cl->allow_request = ALL;
592   cl->status.active = 1;
593   cl->status.decryptin = 1;
594   cl->nexthop = cl;
595   cl->cipher_pkttype = EVP_bf_cfb();
596   cl->cipher_pktkeylength = cl->cipher_pkttype->key_len + cl->cipher_pkttype->iv_len;
597
598   if(debug_lvl >= DEBUG_CONNECTIONS)
599     syslog(LOG_NOTICE, _("Connection with %s (%s) activated"), cl->name, cl->hostname);
600
601 cp
602   if(!cl->status.outgoing)
603     send_ack(cl);
604
605   /* Send him our subnets */
606   
607   for(s = myself->subnets; s; s = s->next)
608     send_add_subnet(cl, s);
609
610   /* And send him all the hosts and their subnets we know... */
611   
612   for(p = conn_list; p; p = p->next)
613     if(p != cl && p->status.active)
614       {
615         /* Notify others of this connection */
616   
617         if(p->status.meta)
618           send_add_host(p, cl);
619
620         /* Notify new connection of everything we know */
621
622         send_add_host(cl, p);
623         
624         for(s = p->subnets; s; s = s->next)
625           send_add_subnet(cl, s);
626       }
627 cp
628   return 0;
629 }
630
631 /* Address and subnet information exchange */
632
633 int send_add_subnet(conn_list_t *cl, subnet_t *subnet)
634 {
635   int x;
636   char *netstr;
637 cp
638   x = send_request(cl, "%d %s %s", ADD_SUBNET,
639                       subnet->owner->name, netstr = net2str(subnet));
640   free(netstr);
641 cp
642   return x;
643 }
644
645 int add_subnet_h(conn_list_t *cl)
646 {
647   char *subnetstr;
648   char *name;
649   conn_list_t *owner, *p;
650   subnet_t *subnet;
651 cp
652   if(sscanf(cl->buffer, "%*d %as %as", &name, &subnetstr) != 2)
653     {
654       syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s)"), cl->name, cl->hostname);
655       free(name); free(subnetstr);
656       return -1;
657     }
658
659   /* Check if owner name is a valid */
660
661   if(check_id(name))
662     {
663       syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s): invalid identity name"), cl->name, cl->hostname);
664       free(name); free(subnetstr);
665       return -1;
666     }
667
668   /* Check if subnet string is valid */
669
670   if(!(subnet = str2net(subnetstr)))
671     {
672       syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s): invalid subnet string"), cl->name, cl->hostname);
673       free(name); free(subnetstr);
674       return -1;
675     }
676
677   free(subnetstr);
678   
679   /* Check if somebody tries to add a subnet of ourself */
680
681   if(!strcmp(name, myself->name))
682     {
683       syslog(LOG_ERR, _("Warning: got ADD_SUBNET from %s (%s) for ourself, restarting"),
684              cl->name, cl->hostname);
685       free(name);
686       sighup = 1;
687       return 0;
688     }
689
690   /* Check if the owner of the new subnet is in the connection list */
691
692   if(!(owner = lookup_id(name)))
693     {
694       syslog(LOG_ERR, _("Got ADD_SUBNET for %s from %s (%s) which is not in our connection list"),
695              name, cl->name, cl->hostname);
696       free(name);
697       return -1;
698     }
699
700   /* If everything is correct, add the subnet to the list of the owner */
701
702   subnet_add(owner, subnet);
703
704   /* Tell the rest */
705   
706   for(p = conn_list; p; p = p->next)
707     if(p->status.meta && p->status.active && p!= cl)
708       send_add_subnet(p, subnet);
709 cp
710   return 0;
711 }
712
713 int send_del_subnet(conn_list_t *cl, subnet_t *subnet)
714 {
715   int x;
716   char *netstr;
717 cp
718   netstr = net2str(subnet);
719   x = send_request(cl, "%d %s %s", DEL_SUBNET, subnet->owner->name, netstr);
720   free(netstr);
721 cp
722   return x;
723 }
724
725 int del_subnet_h(conn_list_t *cl)
726 {
727   char *subnetstr;
728   char *name;
729   conn_list_t *owner, *p;
730   subnet_t *subnet;
731 cp
732   if(sscanf(cl->buffer, "%*d %as %as", &name, &subnetstr) != 3)
733     {
734       syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s)"), cl->name, cl->hostname);
735       free(name); free(subnetstr);
736       return -1;
737     }
738
739   /* Check if owner name is a valid */
740
741   if(check_id(name))
742     {
743       syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s): invalid identity name"), cl->name, cl->hostname);
744       free(name); free(subnetstr);
745       return -1;
746     }
747
748   /* Check if subnet string is valid */
749
750   if(!(subnet = str2net(subnetstr)))
751     {
752       syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s): invalid subnet string"), cl->name, cl->hostname);
753       free(name); free(subnetstr);
754       return -1;
755     }
756
757   free(subnetstr);
758   
759   /* Check if somebody tries to add a subnet of ourself */
760
761   if(!strcmp(name, myself->name))
762     {
763       syslog(LOG_ERR, _("Warning: got DEL_SUBNET from %s (%s) for ourself, restarting"),
764              cl->name, cl->hostname);
765       free(name);
766       sighup = 1;
767       return 0;
768     }
769
770   /* Check if the owner of the new subnet is in the connection list */
771
772   if(!(owner = lookup_id(name)))
773     {
774       syslog(LOG_ERR, _("Got DEL_SUBNET for %s from %s (%s) which is not in our connection list"),
775              name, cl->name, cl->hostname);
776       free(name);
777       return -1;
778     }
779
780   /* If everything is correct, delete the subnet from the list of the owner */
781
782   subnet_del(subnet);
783
784   /* Tell the rest */
785   
786   for(p = conn_list; p; p = p->next)
787     if(p->status.meta && p->status.active && p!= cl)
788       send_del_subnet(p, subnet);
789 cp
790   return 0;
791 }
792
793 /* New and closed connections notification */
794
795 int send_add_host(conn_list_t *cl, conn_list_t *other)
796 {
797 cp
798   return send_request(cl, "%d %s %lx:%d %lx", ADD_HOST,
799                       other->name, other->address, other->port, other->options);
800 }
801
802 int add_host_h(conn_list_t *cl)
803 {
804   conn_list_t *old, *new;
805   conn_list_t *p;
806
807 cp
808   new = new_conn_list();
809
810   if(sscanf(cl->buffer, "%*d %as %lx:%d %lx", &new->name, &new->address, &new->port, &new->options) != 4)
811     {
812        syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s)"), cl->name, cl->hostname);
813        return -1;
814     }
815
816   /* Check if identity is a valid name */
817
818   if(check_id(new->name))
819     {
820       syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s): invalid identity name"), cl->name, cl->hostname);
821       free_conn_list(new);
822       return -1;
823     }
824
825   /* Check if somebody tries to add ourself */
826
827   if(!strcmp(new->name, myself->name))
828     {
829       syslog(LOG_ERR, _("Warning: got ADD_HOST from %s (%s) for ourself, restarting"), cl->name, cl->hostname);
830       sighup = 1;
831       free_conn_list(new);
832       return 0;
833     }
834     
835   /* Fill in more of the new conn_list structure */
836
837   new->hostname = hostlookup(htonl(new->address));
838
839   /* Check if the new host already exists in the connnection list */
840
841   if((old = lookup_id(new->name)))
842     {
843       if((new->address == old->address) && (new->port == old->port))
844         {
845           if(debug_lvl >= DEBUG_CONNECTIONS)
846             syslog(LOG_NOTICE, _("Got duplicate ADD_HOST for %s (%s) from %s (%s)"),
847                    old->name, old->hostname, new->name, new->hostname);
848           free_conn_list(new);
849           return 0;
850         }
851       else
852         {
853           if(debug_lvl >= DEBUG_CONNECTIONS)
854             syslog(LOG_NOTICE, _("Removing old entry for %s (%s) in favour of new connection"),
855                    old->name, old->hostname);
856
857           terminate_connection(old);
858         }
859     }
860
861   /* Hook it up into the conn_list */
862
863   conn_list_add(new);
864
865   /* Tell the rest about the new host */
866
867   for(p = conn_list; p; p = p->next)
868     if(p->status.meta && p->status.active && p!=cl)
869       send_add_host(p, new);
870
871   /* Fill in rest of conn_list structure */
872
873   new->nexthop = cl;
874   new->status.active = 1;
875   new->cipher_pkttype = EVP_bf_cfb();
876   new->cipher_pktkeylength = cl->cipher_pkttype->key_len + cl->cipher_pkttype->iv_len;
877
878 cp
879   return 0;
880 }
881
882 int send_del_host(conn_list_t *cl, conn_list_t *other)
883 {
884 cp
885   return send_request(cl, "%d %s %lx:%d %lx", DEL_HOST,
886                       other->name, other->address, other->port, other->options);
887 }
888
889 int del_host_h(conn_list_t *cl)
890 {
891   char *name;
892   ip_t address;
893   port_t port;
894   long int options;
895   conn_list_t *old, *p;
896 cp
897   if(sscanf(cl->buffer, "%*d %as %lx:%d %lx", &name, &address, &port, &options) != 4)
898     {
899       syslog(LOG_ERR, _("Got bad DEL_HOST from %s (%s)"),
900              cl->name, cl->hostname);
901       return -1;
902     }
903
904   /* Check if identity is a valid name */
905
906   if(check_id(name))
907     {
908       syslog(LOG_ERR, _("Got bad DEL_HOST from %s (%s): invalid identity name"), cl->name, cl->hostname);
909       free(name);
910       return -1;
911     }
912
913   /* Check if somebody tries to delete ourself */
914
915   if(!strcmp(name, myself->name))
916     {
917       syslog(LOG_ERR, _("Warning: got DEL_HOST from %s (%s) for ourself, restarting"),
918              cl->name, cl->hostname);
919       free(name);
920       sighup = 1;
921       return 0;
922     }
923
924   /* Check if the new host already exists in the connnection list */
925
926   if(!(old = lookup_id(name)))
927     {
928       syslog(LOG_ERR, _("Got DEL_HOST from %s (%s) for %s which is not in our connection list"),
929              name, cl->name, cl->hostname);
930       free(name);
931       return -1;
932     }
933   
934   /* Check if the rest matches */
935   
936   if(address!=old->address || port!=old->port || options!=old->options || cl!=old->nexthop)
937     {
938       syslog(LOG_WARNING, _("Got DEL_HOST from %s (%s) for %s which doesn't match"), cl->name, cl->hostname, old->name);
939       return 0;
940     }
941
942   /* Ok, since EVERYTHING seems to check out all right, delete it */
943
944   old->status.active = 0;
945   terminate_connection(old);
946
947   /* Tell the rest about the new host */
948
949   for(p = conn_list; p; p = p->next)
950     if(p->status.meta && p->status.active && p!=cl)
951       send_del_host(p, old);
952 cp
953   return 0;
954 }
955
956 /* Status and error notification routines */
957
958 int send_status(conn_list_t *cl, int statusno, char *statusstring)
959 {
960 cp
961   if(!statusstring)
962     statusstring = status_text[statusno];
963 cp
964   return send_request(cl, "%d %d %s", STATUS, statusno, statusstring);
965 }
966
967 int status_h(conn_list_t *cl)
968 {
969   int statusno;
970   char *statusstring;
971 cp
972   if(sscanf(cl->buffer, "%*d %d %as", &statusno, &statusstring) != 2)
973     {
974        syslog(LOG_ERR, _("Got bad STATUS from %s (%s)"),
975               cl->name, cl->hostname);
976        return -1;
977     }
978
979   if(debug_lvl >= DEBUG_STATUS)
980     {
981       syslog(LOG_NOTICE, _("Status message from %s (%s): %s: %s"),
982              cl->name, cl->hostname, status_text[statusno], statusstring);
983     }
984
985 cp
986   free(statusstring);
987   return 0;
988 }
989
990 int send_error(conn_list_t *cl, int errno, char *errstring)
991 {
992 cp
993   if(!errstring)
994     errstring = strerror(errno);
995   return send_request(cl, "%d %d %s", ERROR, errno, errstring);
996 }
997
998 int error_h(conn_list_t *cl)
999 {
1000   int errno;
1001   char *errorstring;
1002 cp
1003   if(sscanf(cl->buffer, "%*d %d %as", &errno, &errorstring) != 2)
1004     {
1005        syslog(LOG_ERR, _("Got bad ERROR from %s (%s)"),
1006               cl->name, cl->hostname);
1007        return -1;
1008     }
1009
1010   if(debug_lvl >= DEBUG_ERROR)
1011     {
1012       syslog(LOG_NOTICE, _("Error message from %s (%s): %s: %s"),
1013              cl->name, cl->hostname, strerror(errno), errorstring);
1014     }
1015
1016   free(errorstring);
1017   terminate_connection(cl);
1018 cp
1019   return 0;
1020 }
1021
1022 int send_termreq(conn_list_t *cl)
1023 {
1024 cp
1025   return send_request(cl, "%d", TERMREQ);
1026 }
1027
1028 int termreq_h(conn_list_t *cl)
1029 {
1030 cp
1031   terminate_connection(cl);
1032 cp
1033   return 0;
1034 }
1035
1036 /* Keepalive routines - FIXME: needs a closer look */
1037
1038 int send_ping(conn_list_t *cl)
1039 {
1040 cp
1041   cl->status.pinged = 1;
1042   cl->last_ping_time = time(NULL);
1043 cp
1044   return send_request(cl, "%d", PING);
1045 }
1046
1047 int ping_h(conn_list_t *cl)
1048 {
1049 cp
1050   return send_pong(cl);
1051 }
1052
1053 int send_pong(conn_list_t *cl)
1054 {
1055 cp
1056   return send_request(cl, "%d", PONG);
1057 }
1058
1059 int pong_h(conn_list_t *cl)
1060 {
1061 cp
1062   cl->status.pinged = 0;
1063 cp
1064   return 0;
1065 }
1066
1067 /* Key exchange */
1068
1069 int send_key_changed(conn_list_t *from, conn_list_t *cl)
1070 {
1071   conn_list_t *p;
1072 cp
1073   for(p = conn_list; p != NULL; p = p->next)
1074     {
1075       if(p!=cl && p->status.meta && p->status.active)
1076         send_request(p, "%d %s", KEY_CHANGED,
1077                      from->name);
1078     }
1079 cp
1080   return 0;
1081 }
1082
1083 int key_changed_h(conn_list_t *cl)
1084 {
1085   char *from_id;
1086   conn_list_t *from;
1087 cp
1088   if(sscanf(cl->buffer, "%*d %as", &from_id) != 1)
1089     {
1090       syslog(LOG_ERR, _("Got bad KEY_CHANGED from %s (%s)"),
1091              cl->name, cl->hostname);
1092       return -1;
1093     }
1094
1095   if(!(from = lookup_id(from_id)))
1096     {
1097       syslog(LOG_ERR, _("Got KEY_CHANGED from %s (%s) origin %s which does not exist in our connection list"),
1098              cl->name, cl->hostname, from_id);
1099       free(from_id);
1100       return -1;
1101     }
1102
1103   free(from_id);
1104
1105   from->status.validkey = 0;
1106   from->status.waitingforkey = 0;
1107
1108   send_key_changed(from, cl);
1109 cp
1110   return 0;
1111 }
1112
1113 int send_req_key(conn_list_t *from, conn_list_t *to)
1114 {
1115 cp
1116   return send_request(to->nexthop, "%d %s %s", REQ_KEY,
1117                       from->name, to->name);
1118 }
1119
1120 int req_key_h(conn_list_t *cl)
1121 {
1122   char *from_id, *to_id;
1123   conn_list_t *from, *to;
1124   char pktkey[129];
1125 cp
1126   if(sscanf(cl->buffer, "%*d %as %as", &from_id, &to_id) != 2)
1127     {
1128        syslog(LOG_ERR, _("Got bad REQ_KEY from %s (%s)"),
1129               cl->name, cl->hostname);
1130        return -1;
1131     }
1132
1133   if(!(from = lookup_id(from_id)))
1134     {
1135       syslog(LOG_ERR, _("Got REQ_KEY from %s (%s) origin %s which does not exist in our connection list"),
1136              cl->name, cl->hostname, from_id);
1137       free(from_id); free(to_id);
1138       return -1;
1139     }
1140
1141   /* Check if this key request is for us */
1142
1143   if(!strcmp(to_id, myself->name))
1144     {
1145       bin2hex(myself->cipher_pktkey, pktkey, myself->cipher_pktkeylength);
1146       pktkey[myself->cipher_pktkeylength*2] = '\0';
1147       send_ans_key(myself, from, pktkey);
1148     }
1149   else
1150     {
1151       if(!(to = lookup_id(to_id)))
1152         {
1153           syslog(LOG_ERR, _("Got REQ_KEY from %s (%s) destination %s which does not exist in our connection list"),
1154                  cl->name, cl->hostname, to_id);
1155           free(from_id); free(to_id);
1156           return -1;
1157         }
1158         
1159       if(to->status.validkey)   /* Proxy keys */
1160         {
1161           bin2hex(to->cipher_pktkey, pktkey, to->cipher_pktkeylength);
1162           pktkey[to->cipher_pktkeylength*2] = '\0';
1163           send_ans_key(to, from, pktkey);
1164         }
1165       else
1166         send_req_key(from, to);
1167     }
1168
1169   free(from_id); free(to_id);
1170 cp
1171   return 0;
1172 }
1173
1174 int send_ans_key(conn_list_t *from, conn_list_t *to, char *pktkey)
1175 {
1176 cp
1177   return send_request(to->nexthop, "%d %s %s %s", ANS_KEY,
1178                       from->name, to->name, pktkey);
1179 }
1180
1181 int ans_key_h(conn_list_t *cl)
1182 {
1183   char *from_id, *to_id, *pktkey;
1184   int keylength;
1185   conn_list_t *from, *to;
1186 cp
1187   if(sscanf(cl->buffer, "%*d %as %as %as", &from_id, &to_id, &pktkey) != 3)
1188     {
1189        syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s)"),
1190               cl->name, cl->hostname);
1191        return -1;
1192     }
1193
1194   if(!(from = lookup_id(from_id)))
1195     {
1196       syslog(LOG_ERR, _("Got ANS_KEY from %s (%s) origin %s which does not exist in our connection list"),
1197              cl->name, cl->hostname, from_id);
1198       free(from_id); free(to_id); free(pktkey);
1199       return -1;
1200     }
1201
1202   /* Check correctness of packet key */
1203
1204   keylength = strlen(pktkey);
1205
1206   if(keylength != from->cipher_pktkeylength*2)
1207     {
1208       syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s) origin %s: invalid key length"),
1209              cl->name, cl->hostname, from->name);
1210       free(from_id); free(to_id); free(pktkey);
1211       return -1;
1212     }
1213
1214   /* Forward it if necessary */
1215
1216   if(strcmp(to_id, myself->name))
1217     {
1218       if(!(to = lookup_id(to_id)))
1219         {
1220           syslog(LOG_ERR, _("Got ANS_KEY from %s (%s) destination %s which does not exist in our connection list"),
1221                  cl->name, cl->hostname, to_id);
1222           free(from_id); free(to_id);
1223           return -1;
1224         }
1225       send_ans_key(from, to, pktkey);
1226     }
1227
1228   /* Update our copy of the origin's packet key */
1229
1230   if(from->cipher_pktkey)
1231     free(from->cipher_pktkey);
1232
1233   keylength /= 2;
1234   hex2bin(pktkey, pktkey, keylength);
1235   pktkey[keylength] = '\0';
1236   from->cipher_pktkey = pktkey;
1237
1238   from->status.validkey = 1;
1239   from->status.waitingforkey = 0;
1240     
1241   free(from_id); free(to_id);
1242 cp
1243   return 0;
1244 }
1245
1246 /* Jumptable for the request handlers */
1247
1248 int (*request_handlers[])(conn_list_t*) = {
1249   id_h, challenge_h, chal_reply_h, metakey_h, ack_h,
1250   status_h, error_h, termreq_h,
1251   ping_h, pong_h,
1252   add_host_h, del_host_h,
1253   add_subnet_h, del_subnet_h,
1254   key_changed_h, req_key_h, ans_key_h,
1255 };
1256
1257 /* Request names */
1258
1259 char (*request_name[]) = {
1260   "ID", "CHALLENGE", "CHAL_REPLY", "METAKEY", "ACK",
1261   "STATUS", "ERROR", "TERMREQ",
1262   "PING", "PONG",
1263   "ADD_HOST", "DEL_HOST",
1264   "ADD_SUBNET", "DEL_SUBNET",
1265   "KEY_CHANGED", "REQ_KEY", "ANS_KEY",
1266 };
1267
1268 /* Status strings */
1269
1270 char (*status_text[]) = {
1271   "Warning",
1272 };
1273
1274 /* Error strings */
1275
1276 char (*error_text[]) = {
1277   "Error",
1278 };