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