Statistics
| Branch: | Revision:

iof-bird-daemon / proto / rip / auth.c @ df49d4e1

History | View | Annotate | Download (4.26 KB)

1
/*
2
 *        Rest in pieces - RIP protocol
3
 *
4
 *        Copyright (c) 1999 Pavel Machek <pavel@ucw.cz>
5
 *
6
 *        Can be freely distributed and used under the terms of the GNU GPL.
7
 */
8

    
9
#define LOCAL_DEBUG
10

    
11
#include "nest/bird.h"
12
#include "nest/iface.h"
13
#include "nest/protocol.h"
14
#include "nest/route.h"
15
#include "lib/socket.h"
16
#include "lib/resource.h"
17
#include "lib/lists.h"
18
#include "lib/timer.h"
19
#include "lib/md5.h"
20
#include "lib/string.h"
21

    
22
#include "rip.h"
23

    
24
#define P ((struct rip_proto *) p)
25
#define P_CF ((struct rip_proto_config *)p->cf)
26

    
27
#define PACKETLEN(num) (num * sizeof(struct rip_block) + sizeof(struct rip_packet_heading))
28

    
29
/* 1 == failed, 0 == ok */
30
int
31
rip_incoming_authentication( struct proto *p, struct rip_block_auth *block, struct rip_packet *packet, int num, ip_addr whotoldme )
32
{
33
  DBG( "Incoming authentication: " );
34
  switch (block->authtype) {        /* Authentication type */
35
  case AT_PLAINTEXT: 
36
    {
37
      struct password_item *passwd = get_best_password( P_CF->passwords, 0 );
38
      DBG( "Plaintext passwd" );
39
      if (!passwd) {
40
        log( L_AUTH "No passwords set and password authentication came" );
41
        return 1;
42
      }
43
      if (strncmp( (char *) (&block->packetlen), passwd->password, 16)) {
44
        log( L_AUTH "Passwd authentication failed!" );
45
        DBG( "Expected %s, got %s\n", passwd->password, &block->packetlen );
46
        return 1;
47
      }
48
    }
49
    return 0;
50
  case AT_MD5:
51
    DBG( "md5 password" );
52
    {
53
      struct password_item *head;
54
      struct rip_md5_tail *tail;
55

    
56
      if (block->packetlen != PACKETLEN(num)) {
57
        log( L_ERR "Packet length in MD5 does not match computed value" );
58
        return 1;
59
      }
60

    
61
      tail = (struct rip_md5_tail *) ((char *) packet + (block->packetlen - sizeof(struct rip_block_auth)));
62
      if ((tail->mustbeFFFF != 0xffff) || (tail->mustbe0001 != 0x0001)) {
63
        log( L_ERR "MD5 tail signature is not there" );
64
        return 1;
65
      }
66

    
67
      head = P_CF->passwords;
68
      while (head) {
69
        DBG( "time, " );
70
        if ((head->from > now) || (head->to < now))
71
          goto skip;
72
        if (block->seq) {
73
          struct neighbor *neigh = neigh_find(p, &whotoldme, 0);
74
          if (!neigh) {
75
            log( L_AUTH "Non-neighbour MD5 checksummed packet?" );
76
          } else {
77
            if (neigh->aux > block->seq) {
78
              log( L_AUTH "MD5 protected packet with lower numbers" );
79
              return 0;
80
            }
81
            neigh->aux = block->seq;
82
          }
83
        }
84
        DBG( "check, " );
85
        if (head->id == block->keyid) {
86
          struct MD5Context ctxt;
87
          char md5sum_packet[16];
88
          char md5sum_computed[16];
89

    
90
          memcpy(md5sum_packet, tail->md5, 16);
91
          password_strncpy(tail->md5, head->password, 16);
92

    
93
          MD5Init(&ctxt);
94
          MD5Update(&ctxt, (char *) packet, block->packetlen );
95
          MD5Final(md5sum_computed, &ctxt);
96

    
97
          if (memcmp(md5sum_packet, md5sum_computed, 16))
98
            return 1;
99
          return 0;
100
        }
101
      skip:
102
        head = head->next;
103
      }
104
      return 1;
105
    }
106
  }
107
    
108
  return 0;
109
}
110

    
111
int
112
rip_outgoing_authentication( struct proto *p, struct rip_block_auth *block, struct rip_packet *packet, int num )
113
{
114
  struct password_item *passwd = get_best_password( P_CF->passwords, 0 );
115

    
116
  if (!P_CF->authtype)
117
    return PACKETLEN(num);
118

    
119
  DBG( "Outgoing authentication: " );
120

    
121
  if (!passwd) {
122
    log( L_ERR "No suitable password found for authentication" );
123
    return PACKETLEN(num);
124
  }
125

    
126
  block->authtype = P_CF->authtype;
127
  block->mustbeFFFF = 0xffff;
128
  switch (P_CF->authtype) {
129
  case AT_PLAINTEXT:
130
    password_strncpy( (char *) (&block->packetlen), passwd->password, 16);
131
    return PACKETLEN(num);
132
  case AT_MD5:
133
    {
134
      struct rip_md5_tail *tail;
135
      struct MD5Context ctxt;
136
      static int sequence = 0;
137

    
138
      if (num > PACKET_MD5_MAX)
139
        bug(  "We can not add MD5 authentication to this long packet" );
140

    
141
      block->keyid = passwd->id;
142
      block->authlen = 20;
143
      block->seq = sequence++;
144
      block->zero0 = 0;
145
      block->zero1 = 0;
146
      block->packetlen = PACKETLEN(num) + block->authlen;
147

    
148
      tail = (struct rip_md5_tail *) ((char *) packet + (block->packetlen - sizeof(struct rip_block_auth)));
149
      tail->mustbeFFFF = 0xffff;
150
      tail->mustbe0001 = 0x0001;
151
      password_strncpy( (char *) (&tail->md5), passwd->password, 16 );
152

    
153
      MD5Init(&ctxt);
154
      MD5Update(&ctxt, (char *) packet, block->packetlen );
155
      MD5Final((char *) (&tail->md5), &ctxt);
156
      return PACKETLEN(num) + block->authlen;
157
    }
158
  default:
159
    bug( "Unknown authtype in outgoing authentication?" );
160
  }
161
}