Support for Debian/FreeBSD
[olsrd.git] / lib / secure / src / olsrd_secure.c
1
2 /*
3  * Secure OLSR plugin
4  * http://www.olsr.org
5  *
6  * Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org)
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or
10  * without modification, are permitted provided that the following
11  * conditions are met:
12  *
13  * * Redistributions of source code must retain the above copyright
14  *   notice, this list of conditions and the following disclaimer.
15  * * Redistributions in binary form must reproduce the above copyright
16  *   notice, this list of conditions and the following disclaimer in
17  *   the documentation and/or other materials provided with the
18  *   distribution.
19  * * Neither the name of olsrd, olsr.org nor the names of its
20  *   contributors may be used to endorse or promote products derived
21  *   from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  *
36  */
37
38 /*
39  * Dynamic linked library for the olsr.org olsr daemon
40  */
41
42 #include "olsrd_secure.h"
43
44 #include <stdio.h>
45 #include <string.h>
46 #include <stdlib.h>
47 #ifdef linux
48 #include <linux/in_route.h>
49 #endif
50 #include <unistd.h>
51 #include <errno.h>
52 #include <signal.h>
53
54 #include "defs.h"
55 #include "ipcalc.h"
56 #include "olsr.h"
57 #include "socket_parser.h"
58 #include "parser.h"
59 #include "scheduler.h"
60 #include "net_olsr.h"
61
62 #ifdef USE_OPENSSL
63
64 /* OpenSSL stuff */
65 #include <openssl/sha.h>
66
67 #define CHECKSUM SHA1
68 #define SCHEME   SHA1_INCLUDING_KEY
69
70 #else
71
72 /* Homebrewn checksuming */
73 #include "md5.h"
74
75 static void
76 MD5_checksum(const uint8_t * data, const uint16_t data_len, uint8_t * hashbuf)
77 {
78   MD5_CTX context;
79
80   MD5Init(&context);
81   MD5Update(&context, data, data_len);
82   MD5Final(hashbuf, &context);
83 }
84
85 #define CHECKSUM MD5_checksum
86 #define SCHEME   MD5_INCLUDING_KEY
87
88 #endif
89
90 #ifdef OS
91 #undef OS
92 #endif
93
94 #ifdef WIN32
95 #define close(x) closesocket(x)
96 #undef EWOULDBLOCK
97 #define EWOULDBLOCK WSAEWOULDBLOCK
98 #define OS "Windows"
99 #endif
100 #ifdef linux
101 #define OS "GNU/Linux"
102 #endif
103 #if defined __FreeBSD__ || defined __FreeBSD_kernel__
104 #define OS "FreeBSD"
105 #endif
106
107 #ifndef OS
108 #define OS "Undefined"
109 #endif
110
111 static struct timeval now;
112
113 /* Timestamp node */
114 struct stamp {
115   union olsr_ip_addr addr;
116   /* Timestamp difference */
117   int diff;
118   uint32_t challenge;
119   uint8_t validated;
120   uint32_t valtime;                     /* Validity time */
121   uint32_t conftime;                    /* Reconfiguration time */
122   struct stamp *prev;
123   struct stamp *next;
124 };
125
126 /* Seconds to cache a valid timestamp entry */
127 #define TIMESTAMP_HOLD_TIME 30
128
129 /* Seconds to cache a not verified timestamp entry */
130 #define EXCHANGE_HOLD_TIME 5
131
132 static struct stamp timestamps[HASHSIZE];
133
134 char keyfile[FILENAME_MAX + 1];
135 char aes_key[16];
136
137 /* Event function to register with the sceduler */
138 #if 0
139 static void olsr_event(void);
140 #endif
141 static int send_challenge(struct interface *olsr_if, const union olsr_ip_addr *);
142 static int send_cres(struct interface *olsr_if, union olsr_ip_addr *, union olsr_ip_addr *, uint32_t, struct stamp *);
143 static int send_rres(struct interface *olsr_if, union olsr_ip_addr *, union olsr_ip_addr *, uint32_t);
144 static int parse_challenge(struct interface *olsr_if, char *);
145 static int parse_cres(struct interface *olsr_if, char *);
146 static int parse_rres(char *);
147 static int check_auth(struct interface *olsr_if, char *, int *);
148 #if 0
149 static int ipc_send(char *, int);
150 #endif
151 static int add_signature(uint8_t *, int *);
152 static int validate_packet(struct interface *olsr_if, const char *, int *);
153 static char *secure_preprocessor(char *packet, struct interface *olsr_if, union olsr_ip_addr *from_addr, int *length);
154 static void timeout_timestamps(void *);
155 static int check_timestamp(struct interface *olsr_if, const union olsr_ip_addr *, time_t);
156 static struct stamp *lookup_timestamp_entry(const union olsr_ip_addr *);
157 static int read_key_from_file(const char *);
158
159 /**
160  *Do initialization here
161  *
162  *This function is called by the my_init
163  *function in uolsrd_plugin.c
164  */
165
166 int
167 secure_plugin_init(void)
168 {
169   int i;
170
171   /* Initialize the timestamp database */
172   for (i = 0; i < HASHSIZE; i++) {
173     timestamps[i].next = &timestamps[i];
174     timestamps[i].prev = &timestamps[i];
175   }
176   olsr_printf(1, "Timestamp database initialized\n");
177
178   if (!strlen(keyfile))
179     strscpy(keyfile, KEYFILE, sizeof(keyfile));
180
181   i = read_key_from_file(keyfile);
182
183   if (i < 0) {
184     olsr_printf(1, "[ENC]Could not read key from file %s!\nExitting!\n\n", keyfile);
185     exit(1);
186   }
187   if (i == 0) {
188     olsr_printf(1, "[ENC]There was a problem reading key from file %s. Is the key long enough?\nExitting!\n\n", keyfile);
189     exit(1);
190   }
191
192   /* Register the packet transform function */
193   add_ptf(&add_signature);
194
195   olsr_preprocessor_add_function(&secure_preprocessor);
196
197   /* Register timeout - poll every 2 seconds */
198   olsr_start_timer(2 * MSEC_PER_SEC, 0, OLSR_TIMER_PERIODIC, &timeout_timestamps, NULL, 0);
199
200   return 1;
201 }
202
203 int
204 plugin_ipc_init(void)
205 {
206   return 1;
207 }
208
209 /*
210  * destructor - called at unload
211  */
212 void
213 secure_plugin_exit(void)
214 {
215   olsr_preprocessor_remove_function(&secure_preprocessor);
216 }
217
218 #if 0
219
220 /**
221  *Scheduled event
222  */
223 static void
224 olsr_event(void)
225 {
226
227 }
228 #endif
229
230 #if 0
231 static int
232 ipc_send(char *data __attribute__ ((unused)), int size __attribute__ ((unused)))
233 {
234   return 1;
235 }
236 #endif
237
238 static char *
239 secure_preprocessor(char *packet, struct interface *olsr_if, union olsr_ip_addr *from_addr, int *length)
240 {
241   struct olsr *olsr = (struct olsr *)packet;
242   struct ipaddr_str buf;
243
244   /*
245    * Check for challenge/response messages
246    */
247   check_auth(olsr_if, packet, length);
248
249   /*
250    * Check signature
251    */
252
253   if (!validate_packet(olsr_if, packet, length)) {
254     olsr_printf(1, "[ENC]Rejecting packet from %s\n", olsr_ip_to_string(&buf, from_addr));
255     return NULL;
256   }
257
258   olsr_printf(1, "[ENC]Packet from %s OK size %d\n", olsr_ip_to_string(&buf, from_addr), *length);
259
260   /* Fix OLSR packet header */
261   olsr->olsr_packlen = htons(*length);
262   return packet;
263 }
264
265 /**
266  * Check a incoming OLSR packet for
267  * challenge/responses.
268  * They need not be verified as they
269  * are signed in the message.
270  *
271  */
272 static int
273 check_auth(struct interface *olsr_if, char *pck, int *size __attribute__ ((unused)))
274 {
275
276   olsr_printf(3, "[ENC]Checking packet for challenge response message...\n");
277
278   switch (pck[4]) {
279   case (TYPE_CHALLENGE):
280     parse_challenge(olsr_if, &pck[4]);
281     break;
282
283   case (TYPE_CRESPONSE):
284     parse_cres(olsr_if, &pck[4]);
285     break;
286
287   case (TYPE_RRESPONSE):
288     parse_rres(&pck[4]);
289     break;
290
291   default:
292     return 0;
293   }
294
295   return 1;
296 }
297
298 /**
299  * Packet transform function
300  * Build a SHA-1/MD5 hash of the original message
301  * + the signature message(-digest) + key
302  *
303  * Then add the signature message to the packet and
304  * increase the size
305  */
306 int
307 add_signature(uint8_t * pck, int *size)
308 {
309   struct s_olsrmsg *msg;
310 #ifdef DEBUG
311   unsigned int i;
312   int j;
313   const uint8_t *sigmsg;
314 #endif
315
316   olsr_printf(2, "[ENC]Adding signature for packet size %d\n", *size);
317   fflush(stdout);
318
319   msg = (struct s_olsrmsg *)(ARM_NOWARN_ALIGN)&pck[*size];
320   /* Update size */
321   ((struct olsr *)pck)->olsr_packlen = htons(*size + sizeof(struct s_olsrmsg));
322
323   /* Fill packet header */
324   msg->olsr_msgtype = MESSAGE_TYPE;
325   msg->olsr_vtime = 0;
326   msg->olsr_msgsize = htons(sizeof(struct s_olsrmsg));
327   memcpy(&msg->originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
328   msg->ttl = 1;
329   msg->hopcnt = 0;
330   msg->seqno = htons(get_msg_seqno());
331
332   /* Fill subheader */
333   msg->sig.type = ONE_CHECKSUM;
334   msg->sig.algorithm = SCHEME;
335   memset(&msg->sig.reserved, 0, 2);
336
337   /* Add timestamp */
338   msg->sig.timestamp = htonl(now.tv_sec);
339   olsr_printf(3, "[ENC]timestamp: %lld\n", (long long)now.tv_sec);
340
341   /* Set the new size */
342   *size += sizeof(struct s_olsrmsg);
343
344   {
345     uint8_t checksum_cache[512 + KEYLENGTH];
346     /* Create packet + key cache */
347     /* First the OLSR packet + signature message - digest */
348     memcpy(checksum_cache, pck, *size - SIGNATURE_SIZE);
349     /* Then the key */
350     memcpy(&checksum_cache[*size - SIGNATURE_SIZE], aes_key, KEYLENGTH);
351
352     /* Create the hash */
353     CHECKSUM(checksum_cache, (*size - SIGNATURE_SIZE) + KEYLENGTH, &pck[*size - SIGNATURE_SIZE]);
354   }
355
356 #ifdef DEBUG
357   olsr_printf(1, "Signature message:\n");
358
359   j = 0;
360   sigmsg = (uint8_t *) msg;
361
362   for (i = 0; i < sizeof(struct s_olsrmsg); i++) {
363     olsr_printf(1, "  %3i", sigmsg[i]);
364     j++;
365     if (j == 4) {
366       olsr_printf(1, "\n");
367       j = 0;
368     }
369   }
370 #endif
371
372   olsr_printf(3, "[ENC] Message signed\n");
373
374   return 1;
375 }
376
377 static int
378 validate_packet(struct interface *olsr_if, const char *pck, int *size)
379 {
380   int packetsize;
381   uint8_t sha1_hash[SIGNATURE_SIZE];
382   const struct s_olsrmsg *sig;
383   time_t rec_time;
384
385 #ifdef DEBUG
386   unsigned int i;
387   int j;
388   const uint8_t *sigmsg;
389 #endif
390
391   /* Find size - signature message */
392   packetsize = *size - sizeof(struct s_olsrmsg);
393
394   if (packetsize < 4)
395     return 0;
396
397   sig = (const struct s_olsrmsg *)(const ARM_NOWARN_ALIGN)&pck[packetsize];
398
399   //olsr_printf(1, "Size: %d\n", packetsize);
400
401 #ifdef DEBUG
402   olsr_printf(1, "Input message:\n");
403
404   j = 0;
405   sigmsg = (const uint8_t *)sig;
406
407   for (i = 0; i < sizeof(struct s_olsrmsg); i++) {
408     olsr_printf(1, "  %3i", sigmsg[i]);
409     j++;
410     if (j == 4) {
411       olsr_printf(1, "\n");
412       j = 0;
413     }
414   }
415 #endif
416
417   /* Sanity check first */
418   if ((sig->olsr_msgtype != MESSAGE_TYPE) || (sig->olsr_vtime != 0)
419       || (sig->olsr_msgsize != ntohs(sizeof(struct s_olsrmsg))) || (sig->ttl != 1) || (sig->hopcnt != 0)) {
420     olsr_printf(1, "[ENC]Packet not sane!\n");
421     return 0;
422   }
423
424   /* Check scheme and type */
425   switch (sig->sig.type) {
426   case (ONE_CHECKSUM):
427     switch (sig->sig.algorithm) {
428     case (SCHEME):
429       goto one_checksum_SHA;    /* Ahhh... fix this */
430       break;
431
432     }
433     break;
434
435   default:
436     olsr_printf(1, "[ENC]Unsupported sceme: %d enc: %d!\n", sig->sig.type, sig->sig.algorithm);
437     return 0;
438   }
439   //olsr_printf(1, "Packet sane...\n");
440
441 one_checksum_SHA:
442
443   {
444     uint8_t checksum_cache[512 + KEYLENGTH];
445     /* Create packet + key cache */
446     /* First the OLSR packet + signature message - digest */
447     memcpy(checksum_cache, pck, *size - SIGNATURE_SIZE);
448     /* Then the key */
449     memcpy(&checksum_cache[*size - SIGNATURE_SIZE], aes_key, KEYLENGTH);
450
451     /* generate SHA-1 */
452     CHECKSUM(checksum_cache, *size - SIGNATURE_SIZE + KEYLENGTH, sha1_hash);
453   }
454
455 #ifdef DEBUG
456   olsr_printf(1, "Recevied hash:\n");
457
458   sigmsg = (const uint8_t *)sig->sig.signature;
459
460   for (i = 0; i < SIGNATURE_SIZE; i++) {
461     olsr_printf(1, " %3i", sigmsg[i]);
462   }
463   olsr_printf(1, "\n");
464
465   olsr_printf(1, "Calculated hash:\n");
466
467   sigmsg = sha1_hash;
468
469   for (i = 0; i < SIGNATURE_SIZE; i++) {
470     olsr_printf(1, " %3i", sigmsg[i]);
471   }
472   olsr_printf(1, "\n");
473 #endif
474
475   if (memcmp(sha1_hash, sig->sig.signature, SIGNATURE_SIZE) != 0) {
476     olsr_printf(1, "[ENC]Signature missmatch\n");
477     return 0;
478   }
479
480   /* Check timestamp */
481   rec_time = ntohl(sig->sig.timestamp);
482
483   if (!check_timestamp(olsr_if, (const union olsr_ip_addr *)&sig->originator, rec_time)) {
484     struct ipaddr_str buf;
485     olsr_printf(1, "[ENC]Timestamp missmatch in packet from %s!\n",
486                 olsr_ip_to_string(&buf, (const union olsr_ip_addr *)&sig->originator));
487     return 0;
488   }
489
490   olsr_printf(1, "[ENC]Received timestamp %lld diff: %lld\n", (long long)rec_time, (long long)now.tv_sec - (long long)rec_time);
491
492   /* Remove signature message */
493   *size = packetsize;
494   return 1;
495 }
496
497 int
498 check_timestamp(struct interface *olsr_if, const union olsr_ip_addr *originator, time_t tstamp)
499 {
500   struct stamp *entry;
501   int diff;
502
503   entry = lookup_timestamp_entry(originator);
504
505   if (!entry) {
506     /* Initiate timestamp negotiation */
507
508     send_challenge(olsr_if, originator);
509
510     return 0;
511   }
512
513   if (!entry->validated) {
514     olsr_printf(1, "[ENC]Message from non-validated host!\n");
515     return 0;
516   }
517
518   diff = entry->diff - (now.tv_sec - tstamp);
519
520   olsr_printf(3, "[ENC]Timestamp slack: %d\n", diff);
521
522   if ((diff > UPPER_DIFF) || (diff < LOWER_DIFF)) {
523     olsr_printf(1, "[ENC]Timestamp scew detected!!\n");
524     return 0;
525   }
526
527   /* ok - update diff */
528   entry->diff = ((now.tv_sec - tstamp) + entry->diff) ? ((now.tv_sec - tstamp) + entry->diff) / 2 : 0;
529
530   olsr_printf(3, "[ENC]Diff set to : %d\n", entry->diff);
531
532   /* update validtime */
533
534   entry->valtime = GET_TIMESTAMP(TIMESTAMP_HOLD_TIME * 1000);
535
536   return 1;
537 }
538
539 /**
540  * Create and send a timestamp
541  * challenge message to new_host
542  *
543  * The host is registered in the timestamps
544  * repository with valid=0
545  */
546
547 int
548 send_challenge(struct interface *olsr_if, const union olsr_ip_addr *new_host)
549 {
550   struct challengemsg cmsg;
551   struct stamp *entry;
552   uint32_t challenge, hash;
553   struct ipaddr_str buf;
554
555   olsr_printf(1, "[ENC]Building CHALLENGE message\n");
556
557   /* Set the size including OLSR packet size */
558
559   challenge = rand() << 16;
560   challenge |= rand();
561
562   /* Fill challengemessage */
563   cmsg.olsr_msgtype = TYPE_CHALLENGE;
564   cmsg.olsr_vtime = 0;
565   cmsg.olsr_msgsize = htons(sizeof(struct challengemsg));
566   memcpy(&cmsg.originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
567   cmsg.ttl = 1;
568   cmsg.hopcnt = 0;
569   cmsg.seqno = htons(get_msg_seqno());
570
571   /* Fill subheader */
572   memcpy(&cmsg.destination, new_host, olsr_cnf->ipsize);
573   cmsg.challenge = htonl(challenge);
574
575   olsr_printf(3, "[ENC]Size: %lu\n", (unsigned long)sizeof(struct challengemsg));
576
577   {
578     uint8_t checksum_cache[512 + KEYLENGTH];
579     /* Create packet + key cache */
580     /* First the OLSR packet + signature message - digest */
581     memcpy(checksum_cache, &cmsg, sizeof(struct challengemsg) - SIGNATURE_SIZE);
582     /* Then the key */
583     memcpy(&checksum_cache[sizeof(struct challengemsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
584
585     /* Create the hash */
586     CHECKSUM(checksum_cache, (sizeof(struct challengemsg) - SIGNATURE_SIZE) + KEYLENGTH, cmsg.signature);
587   }
588   olsr_printf(3, "[ENC]Sending timestamp request to %s challenge 0x%x\n", olsr_ip_to_string(&buf, new_host), challenge);
589
590   /* Add to buffer */
591   net_outbuffer_push(olsr_if, &cmsg, sizeof(struct challengemsg));
592
593   /* Send the request */
594   net_output(olsr_if);
595
596   /* Create new entry */
597   entry = malloc(sizeof(struct stamp));
598
599   entry->diff = 0;
600   entry->validated = 0;
601   entry->challenge = challenge;
602
603   memcpy(&entry->addr, new_host, olsr_cnf->ipsize);
604
605   /* update validtime - not validated */
606   entry->conftime = GET_TIMESTAMP(EXCHANGE_HOLD_TIME * 1000);
607
608   hash = olsr_ip_hashing(new_host);
609
610   /* Queue */
611   timestamps[hash].next->prev = entry;
612   entry->next = timestamps[hash].next;
613   timestamps[hash].next = entry;
614   entry->prev = &timestamps[hash];
615
616   return 1;
617
618 }
619
620 int
621 parse_cres(struct interface *olsr_if, char *in_msg)
622 {
623   struct c_respmsg *msg;
624   uint8_t sha1_hash[SIGNATURE_SIZE];
625   struct stamp *entry;
626   struct ipaddr_str buf;
627
628   msg = (struct c_respmsg *)(ARM_NOWARN_ALIGN)in_msg;
629
630   olsr_printf(1, "[ENC]Challenge-response message received\n");
631   olsr_printf(3, "[ENC]To: %s\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->destination));
632
633   if (if_ifwithaddr((union olsr_ip_addr *)&msg->destination) == NULL) {
634     olsr_printf(3, "[ENC]Not for us...\n");
635     return 0;
636   }
637
638   olsr_printf(3, "[ENC]Challenge: 0x%lx\n", (unsigned long)ntohl(msg->challenge));      /* ntohl() returns a unsignedlong onwin32 */
639
640   /* Check signature */
641
642   {
643     uint8_t checksum_cache[512 + KEYLENGTH];
644     /* Create packet + key cache */
645     /* First the OLSR packet + signature message - digest */
646     memcpy(checksum_cache, msg, sizeof(struct c_respmsg) - SIGNATURE_SIZE);
647     /* Then the key */
648     memcpy(&checksum_cache[sizeof(struct c_respmsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
649
650     /* Create the hash */
651     CHECKSUM(checksum_cache, (sizeof(struct c_respmsg) - SIGNATURE_SIZE) + KEYLENGTH, sha1_hash);
652   }
653
654   if (memcmp(sha1_hash, &msg->signature, SIGNATURE_SIZE) != 0) {
655     olsr_printf(1, "[ENC]Signature missmatch in challenge-response!\n");
656     return 0;
657   }
658
659   olsr_printf(3, "[ENC]Signature verified\n");
660
661   /* Now to check the digest from the emitted challenge */
662   if ((entry = lookup_timestamp_entry((const union olsr_ip_addr *)&msg->originator)) == NULL) {
663     olsr_printf(1, "[ENC]Received challenge-response from non-registered node %s!\n",
664                 olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator));
665     return 0;
666   }
667
668   /* Generate the digest */
669   olsr_printf(3, "[ENC]Entry-challenge 0x%x\n", entry->challenge);
670
671   {
672     uint8_t checksum_cache[512 + KEYLENGTH];
673     /* First the challenge received */
674     memcpy(checksum_cache, &entry->challenge, 4);
675     /* Then the local IP */
676     memcpy(&checksum_cache[sizeof(uint32_t)], &msg->originator, olsr_cnf->ipsize);
677
678     /* Create the hash */
679     CHECKSUM(checksum_cache, sizeof(uint32_t) + olsr_cnf->ipsize, sha1_hash);
680   }
681
682   if (memcmp(msg->res_sig, sha1_hash, SIGNATURE_SIZE) != 0) {
683     olsr_printf(1, "[ENC]Error in challenge signature from %s!\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator));
684
685     return 0;
686   }
687
688   olsr_printf(3, "[ENC]Challenge-response signature ok\n");
689
690   /* Update entry! */
691
692   entry->challenge = 0;
693   entry->validated = 1;
694   entry->diff = now.tv_sec - msg->timestamp;
695
696   /* update validtime - validated entry */
697   entry->valtime = GET_TIMESTAMP(TIMESTAMP_HOLD_TIME * 1000);
698
699   olsr_printf(1, "[ENC]%s registered with diff %d!\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator),
700               entry->diff);
701
702   /* Send response-response */
703   send_rres(olsr_if, (union olsr_ip_addr *)&msg->originator, (union olsr_ip_addr *)&msg->destination, ntohl(msg->challenge));
704
705   return 1;
706 }
707
708 int
709 parse_rres(char *in_msg)
710 {
711   struct r_respmsg *msg;
712   uint8_t sha1_hash[SIGNATURE_SIZE];
713   struct stamp *entry;
714   struct ipaddr_str buf;
715
716   msg = (struct r_respmsg *)(ARM_NOWARN_ALIGN)in_msg;
717
718   olsr_printf(1, "[ENC]Response-response message received\n");
719   olsr_printf(3, "[ENC]To: %s\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->destination));
720
721   if (if_ifwithaddr((union olsr_ip_addr *)&msg->destination) == NULL) {
722     olsr_printf(1, "[ENC]Not for us...\n");
723     return 0;
724   }
725
726   /* Check signature */
727
728   {
729     uint8_t checksum_cache[512 + KEYLENGTH];
730     /* Create packet + key cache */
731     /* First the OLSR packet + signature message - digest */
732     memcpy(checksum_cache, msg, sizeof(struct r_respmsg) - SIGNATURE_SIZE);
733     /* Then the key */
734     memcpy(&checksum_cache[sizeof(struct r_respmsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
735
736     /* Create the hash */
737     CHECKSUM(checksum_cache, (sizeof(struct r_respmsg) - SIGNATURE_SIZE) + KEYLENGTH, sha1_hash);
738   }
739
740   if (memcmp(sha1_hash, &msg->signature, SIGNATURE_SIZE) != 0) {
741     olsr_printf(1, "[ENC]Signature missmatch in response-response!\n");
742     return 0;
743   }
744
745   olsr_printf(3, "[ENC]Signature verified\n");
746
747   /* Now to check the digest from the emitted challenge */
748   if ((entry = lookup_timestamp_entry((const union olsr_ip_addr *)&msg->originator)) == NULL) {
749     olsr_printf(1, "[ENC]Received response-response from non-registered node %s!\n",
750                 olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator));
751     return 0;
752   }
753
754   /* Generate the digest */
755   olsr_printf(3, "[ENC]Entry-challenge 0x%x\n", entry->challenge);
756
757   {
758     uint8_t checksum_cache[512 + KEYLENGTH];
759     /* First the challenge received */
760     memcpy(checksum_cache, &entry->challenge, 4);
761     /* Then the local IP */
762     memcpy(&checksum_cache[sizeof(uint32_t)], &msg->originator, olsr_cnf->ipsize);
763
764     /* Create the hash */
765     CHECKSUM(checksum_cache, sizeof(uint32_t) + olsr_cnf->ipsize, sha1_hash);
766   }
767
768   if (memcmp(msg->res_sig, sha1_hash, SIGNATURE_SIZE) != 0) {
769     olsr_printf(1, "[ENC]Error in response signature from %s!\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator));
770
771     return 0;
772   }
773
774   olsr_printf(3, "[ENC]Challenge-response signature ok\n");
775
776   /* Update entry! */
777
778   entry->challenge = 0;
779   entry->validated = 1;
780   entry->diff = now.tv_sec - msg->timestamp;
781
782   /* update validtime - validated entry */
783   entry->valtime = GET_TIMESTAMP(TIMESTAMP_HOLD_TIME * 1000);
784
785   olsr_printf(1, "[ENC]%s registered with diff %d!\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator),
786               entry->diff);
787
788   return 1;
789 }
790
791 int
792 parse_challenge(struct interface *olsr_if, char *in_msg)
793 {
794   struct challengemsg *msg;
795   uint8_t sha1_hash[SIGNATURE_SIZE];
796   struct stamp *entry;
797   uint32_t hash;
798   struct ipaddr_str buf;
799
800   msg = (struct challengemsg *)(ARM_NOWARN_ALIGN)in_msg;
801
802   olsr_printf(1, "[ENC]Challenge message received\n");
803   olsr_printf(3, "[ENC]To: %s\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->destination));
804
805   if (if_ifwithaddr((union olsr_ip_addr *)&msg->destination) == NULL) {
806     olsr_printf(1, "[ENC]Not for us...\n");
807     return 0;
808   }
809
810   /* Create entry if not registered */
811   if ((entry = lookup_timestamp_entry((const union olsr_ip_addr *)&msg->originator)) == NULL) {
812     entry = malloc(sizeof(struct stamp));
813     memcpy(&entry->addr, &msg->originator, olsr_cnf->ipsize);
814
815     hash = olsr_ip_hashing((union olsr_ip_addr *)&msg->originator);
816
817     /* Queue */
818     timestamps[hash].next->prev = entry;
819     entry->next = timestamps[hash].next;
820     timestamps[hash].next = entry;
821     entry->prev = &timestamps[hash];
822   } else {
823     /* Check configuration timeout */
824     if (!TIMED_OUT(entry->conftime)) {
825       /* If registered - do not accept! */
826       olsr_printf(1, "[ENC]Challenge from registered node...dropping!\n");
827       return 0;
828     } else {
829       olsr_printf(1, "[ENC]Challenge from registered node...accepted!\n");
830     }
831   }
832
833   olsr_printf(3, "[ENC]Challenge: 0x%lx\n", (unsigned long)ntohl(msg->challenge));      /* ntohl() returns a unsignedlong onwin32 */
834
835   /* Check signature */
836
837   {
838     uint8_t checksum_cache[512 + KEYLENGTH];
839     /* Create packet + key cache */
840     /* First the OLSR packet + signature message - digest */
841     memcpy(checksum_cache, msg, sizeof(struct challengemsg) - SIGNATURE_SIZE);
842     /* Then the key */
843     memcpy(&checksum_cache[sizeof(struct challengemsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
844
845     /* Create the hash */
846     CHECKSUM(checksum_cache, (sizeof(struct challengemsg) - SIGNATURE_SIZE) + KEYLENGTH, sha1_hash);
847   }
848   if (memcmp(sha1_hash, &msg->signature, SIGNATURE_SIZE) != 0) {
849     olsr_printf(1, "[ENC]Signature missmatch in challenge!\n");
850     return 0;
851   }
852
853   olsr_printf(3, "[ENC]Signature verified\n");
854
855   entry->diff = 0;
856   entry->validated = 0;
857
858   /* update validtime - not validated */
859   entry->conftime = GET_TIMESTAMP(EXCHANGE_HOLD_TIME * 1000);
860
861   /* Build and send response */
862
863   send_cres(olsr_if, (union olsr_ip_addr *)&msg->originator, (union olsr_ip_addr *)&msg->destination, ntohl(msg->challenge), entry);
864
865   return 1;
866 }
867
868 /**
869  * Build and transmit a challenge response
870  * message.
871  *
872  */
873 int
874 send_cres(struct interface *olsr_if, union olsr_ip_addr *to, union olsr_ip_addr *from, uint32_t chal_in, struct stamp *entry)
875 {
876   struct c_respmsg crmsg;
877   uint32_t challenge;
878   struct ipaddr_str buf;
879
880   olsr_printf(1, "[ENC]Building CRESPONSE message\n");
881
882   challenge = rand() << 16;
883   challenge |= rand();
884
885   entry->challenge = challenge;
886
887   olsr_printf(3, "[ENC]Challenge-response: 0x%x\n", challenge);
888
889   /* Fill challengemessage */
890   crmsg.olsr_msgtype = TYPE_CRESPONSE;
891   crmsg.olsr_vtime = 0;
892   crmsg.olsr_msgsize = htons(sizeof(struct c_respmsg));
893   memcpy(&crmsg.originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
894   crmsg.ttl = 1;
895   crmsg.hopcnt = 0;
896   crmsg.seqno = htons(get_msg_seqno());
897
898   /* set timestamp */
899   crmsg.timestamp = now.tv_sec;
900   olsr_printf(3, "[ENC]Timestamp %lld\n", (long long)crmsg.timestamp);
901
902   /* Fill subheader */
903   memcpy(&crmsg.destination, to, olsr_cnf->ipsize);
904   crmsg.challenge = htonl(challenge);
905
906   /* Create digest of received challenge + IP */
907
908   {
909     uint8_t checksum_cache[512 + KEYLENGTH];
910     /* Create packet + key cache */
911     /* First the challenge received */
912     memcpy(checksum_cache, &chal_in, 4);
913     /* Then the local IP */
914     memcpy(&checksum_cache[sizeof(uint32_t)], from, olsr_cnf->ipsize);
915
916     /* Create the hash */
917     CHECKSUM(checksum_cache, sizeof(uint32_t) + olsr_cnf->ipsize, crmsg.res_sig);
918   }
919
920   /* Now create the digest of the message and the key */
921
922   {
923     uint8_t checksum_cache[512 + KEYLENGTH];
924     /* Create packet + key cache */
925     /* First the OLSR packet + signature message - digest */
926     memcpy(checksum_cache, &crmsg, sizeof(struct c_respmsg) - SIGNATURE_SIZE);
927     /* Then the key */
928     memcpy(&checksum_cache[sizeof(struct c_respmsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
929
930     /* Create the hash */
931     CHECKSUM(checksum_cache, (sizeof(struct c_respmsg) - SIGNATURE_SIZE) + KEYLENGTH, crmsg.signature);
932   }
933
934   olsr_printf(3, "[ENC]Sending challenge response to %s challenge 0x%x\n", olsr_ip_to_string(&buf, to), challenge);
935
936   /* Add to buffer */
937   net_outbuffer_push(olsr_if, &crmsg, sizeof(struct c_respmsg));
938   /* Send the request */
939   net_output(olsr_if);
940
941   return 1;
942 }
943
944 /**
945  * Build and transmit a response response
946  * message.
947  *
948  */
949 static int
950 send_rres(struct interface *olsr_if, union olsr_ip_addr *to, union olsr_ip_addr *from, uint32_t chal_in)
951 {
952   struct r_respmsg rrmsg;
953   struct ipaddr_str buf;
954
955   olsr_printf(1, "[ENC]Building RRESPONSE message\n");
956
957   /* Fill challengemessage */
958   rrmsg.olsr_msgtype = TYPE_RRESPONSE;
959   rrmsg.olsr_vtime = 0;
960   rrmsg.olsr_msgsize = htons(sizeof(struct r_respmsg));
961   memcpy(&rrmsg.originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
962   rrmsg.ttl = 1;
963   rrmsg.hopcnt = 0;
964   rrmsg.seqno = htons(get_msg_seqno());
965
966   /* set timestamp */
967   rrmsg.timestamp = now.tv_sec;
968   olsr_printf(3, "[ENC]Timestamp %lld\n", (long long)rrmsg.timestamp);
969
970   /* Fill subheader */
971   memcpy(&rrmsg.destination, to, olsr_cnf->ipsize);
972
973   /* Create digest of received challenge + IP */
974
975   {
976     uint8_t checksum_cache[512 + KEYLENGTH];
977     /* Create packet + key cache */
978     /* First the challenge received */
979     memcpy(checksum_cache, &chal_in, 4);
980     /* Then the local IP */
981     memcpy(&checksum_cache[sizeof(uint32_t)], from, olsr_cnf->ipsize);
982
983     /* Create the hash */
984     CHECKSUM(checksum_cache, sizeof(uint32_t) + olsr_cnf->ipsize, rrmsg.res_sig);
985   }
986
987   /* Now create the digest of the message and the key */
988
989   {
990     uint8_t checksum_cache[512 + KEYLENGTH];
991     /* Create packet + key cache */
992     /* First the OLSR packet + signature message - digest */
993     memcpy(checksum_cache, &rrmsg, sizeof(struct r_respmsg) - SIGNATURE_SIZE);
994     /* Then the key */
995     memcpy(&checksum_cache[sizeof(struct r_respmsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
996
997     /* Create the hash */
998     CHECKSUM(checksum_cache, (sizeof(struct r_respmsg) - SIGNATURE_SIZE) + KEYLENGTH, rrmsg.signature);
999   }
1000
1001   olsr_printf(3, "[ENC]Sending response response to %s\n", olsr_ip_to_string(&buf, to));
1002
1003   /* add to buffer */
1004   net_outbuffer_push(olsr_if, &rrmsg, sizeof(struct r_respmsg));
1005
1006   /* Send the request */
1007   net_output(olsr_if);
1008
1009   return 1;
1010 }
1011
1012 static struct stamp *
1013 lookup_timestamp_entry(const union olsr_ip_addr *adr)
1014 {
1015   uint32_t hash;
1016   struct stamp *entry;
1017   struct ipaddr_str buf;
1018
1019   hash = olsr_ip_hashing(adr);
1020
1021   for (entry = timestamps[hash].next; entry != &timestamps[hash]; entry = entry->next) {
1022     if (memcmp(&entry->addr, adr, olsr_cnf->ipsize) == 0) {
1023       olsr_printf(3, "[ENC]Match for %s\n", olsr_ip_to_string(&buf, adr));
1024       return entry;
1025     }
1026   }
1027
1028   olsr_printf(1, "[ENC]No match for %s\n", olsr_ip_to_string(&buf, adr));
1029
1030   return NULL;
1031 }
1032
1033 /**
1034  *Find timed out entries and delete them
1035  *
1036  *@return nada
1037  */
1038 void
1039 timeout_timestamps(void *foo __attribute__ ((unused)))
1040 {
1041   struct stamp *tmp_list;
1042   struct stamp *entry_to_delete;
1043   int idx;
1044
1045   /* Update our local timestamp */
1046   gettimeofday(&now, NULL);
1047
1048   for (idx = 0; idx < HASHSIZE; idx++) {
1049     tmp_list = timestamps[idx].next;
1050     /*Traverse MID list */
1051     while (tmp_list != &timestamps[idx]) {
1052       /*Check if the entry is timed out */
1053       if ((TIMED_OUT(tmp_list->valtime)) && (TIMED_OUT(tmp_list->conftime))) {
1054         struct ipaddr_str buf;
1055         entry_to_delete = tmp_list;
1056         tmp_list = tmp_list->next;
1057
1058         olsr_printf(1, "[ENC]timestamp info for %s timed out.. deleting it\n", olsr_ip_to_string(&buf, &entry_to_delete->addr));
1059
1060         /*Delete it */
1061         entry_to_delete->next->prev = entry_to_delete->prev;
1062         entry_to_delete->prev->next = entry_to_delete->next;
1063
1064         free(entry_to_delete);
1065       } else
1066         tmp_list = tmp_list->next;
1067     }
1068   }
1069
1070   return;
1071 }
1072
1073 static int
1074 read_key_from_file(const char *file)
1075 {
1076   FILE *kf;
1077   size_t keylen;
1078
1079   keylen = 16;
1080   kf = fopen(file, "r");
1081
1082   olsr_printf(1, "[ENC]Reading key from file \"%s\"\n", file);
1083
1084   if (kf == NULL) {
1085     olsr_printf(1, "[ENC]Could not open keyfile %s!\nError: %s\n", file, strerror(errno));
1086     return -1;
1087   }
1088
1089   if (fread(aes_key, 1, keylen, kf) != keylen) {
1090     olsr_printf(1, "[ENC]Could not read key from keyfile %s!\nError: %s\n", file, strerror(errno));
1091     fclose(kf);
1092     return 0;
1093   }
1094
1095   fclose(kf);
1096   return 1;
1097 }
1098
1099 /*
1100  * Local Variables:
1101  * c-basic-offset: 2
1102  * indent-tabs-mode: nil
1103  * End:
1104  */