Drop test-libs.patch, fixed upstream.
[debian/iodine.git] / debian / patches / 0001-Fix-authentication-bypass-bug.patch
1 From 9e265625a1ac8aafbe2812c67de7ddbbf1793a0e Mon Sep 17 00:00:00 2001
2 From: Erik Ekman <erik@kryo.se>
3 Date: Mon, 16 Jun 2014 21:12:49 +0200
4 Subject: [PATCH] Fix authentication bypass bug
5
6 The client could bypass the password check by continuing after getting error
7 from the server and guessing the network parameters. The server would still
8 accept the rest of the setup and also network traffic.
9
10 Add checks for normal and raw mode that user has authenticated before allowing
11 any other communication.
12
13 Problem found by Oscar Reparaz.
14
15 Backported to iodine 0.6 branch.
16 ---
17  CHANGELOG     |  5 ++++-
18  src/iodined.c | 46 ++++++++++++++++++++++++++++++++++------------
19  src/user.c    |  8 +++++++-
20  src/user.h    |  2 ++
21  tests/user.c  |  9 +++++++++
22  5 files changed, 56 insertions(+), 14 deletions(-)
23
24 --- a/CHANGELOG
25 +++ b/CHANGELOG
26 @@ -5,7 +5,10 @@ iodine - http://code.kryo.se/iodine
27  
28  CHANGES:
29  
30 -2010-02-13: 0.6.0-rc1 "Hotspotify"
31 +2014-06-17: 0.6.0
32 +       - Fix authentication bypass vulnerability; found by Oscar Reparaz.
33 +
34 +2010-02-06: 0.6.0-rc1 "Hotspotify"
35         - Fixed tunnel not working on Windows.
36         - Any device name is now supported on Windows, fixes #47.
37         - Multiple installed TAP32 interfaces are now supported, fixes #46.
38 --- a/src/iodined.c
39 +++ b/src/iodined.c
40 @@ -116,6 +116,7 @@ syslog(int a, const char *str, ...)
41  }
42  #endif
43  
44 +/* This will not check that user has passed login challenge */
45  static int
46  check_user_and_ip(int userid, struct query *q)
47  {
48 @@ -142,6 +143,20 @@ check_user_and_ip(int userid, struct que
49         return memcmp(&(users[userid].host), &(tempin->sin_addr), sizeof(struct in_addr));
50  }
51  
52 +/* This checks that user has passed normal (non-raw) login challenge */
53 +static int
54 +check_authenticated_user_and_ip(int userid, struct query *q)
55 +{
56 +       int res = check_user_and_ip(userid, q);
57 +       if (res)
58 +               return res;
59 +
60 +       if (!users[userid].authenticated)
61 +               return 1;
62 +
63 +       return 0;
64 +}
65 +
66  static void
67  send_raw(int fd, char *buf, int buflen, int user, int cmd, struct query *q)
68  {
69 @@ -780,8 +795,10 @@ handle_null_request(int tun_fd, int dns_
70                         login_calculate(logindata, 16, password, users[userid].seed);
71  
72                         if (read >= 18 && (memcmp(logindata, unpacked+1, 16) == 0)) {
73 -                               /* Login ok, send ip/mtu/netmask info */
74 +                               /* Store login ok */
75 +                               users[userid].authenticated = 1;
76  
77 +                               /* Send ip/mtu/netmask info */
78                                 tempip.s_addr = my_ip;
79                                 tmp[0] = strdup(inet_ntoa(tempip));
80                                 tempip.s_addr = users[userid].tun_ip;
81 @@ -810,7 +827,7 @@ handle_null_request(int tun_fd, int dns_
82                 char reply[5];
83                 
84                 userid = b32_8to5(in[1]);
85 -               if (check_user_and_ip(userid, q) != 0) {
86 +               if (check_authenticated_user_and_ip(userid, q) != 0) {
87                         write_dns(dns_fd, q, "BADIP", 5, 'T');
88                         return; /* illegal id */
89                 }
90 @@ -846,8 +863,8 @@ handle_null_request(int tun_fd, int dns_
91                 }
92  
93                 userid = b32_8to5(in[1]);
94 -               
95 -               if (check_user_and_ip(userid, q) != 0) {
96 +
97 +               if (check_authenticated_user_and_ip(userid, q) != 0) {
98                         write_dns(dns_fd, q, "BADIP", 5, 'T');
99                         return; /* illegal id */
100                 }
101 @@ -888,7 +905,7 @@ handle_null_request(int tun_fd, int dns_
102  
103                 userid = b32_8to5(in[1]);
104  
105 -               if (check_user_and_ip(userid, q) != 0) {
106 +               if (check_authenticated_user_and_ip(userid, q) != 0) {
107                         write_dns(dns_fd, q, "BADIP", 5, 'T');
108                         return; /* illegal id */
109                 }
110 @@ -1016,7 +1033,7 @@ handle_null_request(int tun_fd, int dns_
111  
112                 /* Downstream fragsize probe packet */
113                 userid = (b32_8to5(in[1]) >> 1) & 15;
114 -               if (check_user_and_ip(userid, q) != 0) {
115 +               if (check_authenticated_user_and_ip(userid, q) != 0) {
116                         write_dns(dns_fd, q, "BADIP", 5, 'T');
117                         return; /* illegal id */
118                 }
119 @@ -1051,7 +1068,7 @@ handle_null_request(int tun_fd, int dns_
120  
121                 /* Downstream fragsize packet */
122                 userid = unpacked[0];
123 -               if (check_user_and_ip(userid, q) != 0) {
124 +               if (check_authenticated_user_and_ip(userid, q) != 0) {
125                         write_dns(dns_fd, q, "BADIP", 5, 'T');
126                         return; /* illegal id */
127                 }
128 @@ -1084,7 +1101,7 @@ handle_null_request(int tun_fd, int dns_
129  
130                 /* Ping packet, store userid */
131                 userid = unpacked[0];
132 -               if (check_user_and_ip(userid, q) != 0) {
133 +               if (check_authenticated_user_and_ip(userid, q) != 0) {
134                         write_dns(dns_fd, q, "BADIP", 5, 'T');
135                         return; /* illegal id */
136                 }
137 @@ -1214,7 +1231,7 @@ handle_null_request(int tun_fd, int dns_
138  
139                 userid = code;
140                 /* Check user and sending ip number */
141 -               if (check_user_and_ip(userid, q) != 0) {
142 +               if (check_authenticated_user_and_ip(userid, q) != 0) {
143                         write_dns(dns_fd, q, "BADIP", 5, 'T');
144                         return; /* illegal id */
145                 }
146 @@ -1785,10 +1802,11 @@ handle_raw_login(char *packet, int len,
147         
148         if (len < 16) return;
149  
150 -       /* can't use check_user_and_ip() since IP address will be different,
151 +       /* can't use check_authenticated_user_and_ip() since IP address will be different,
152            so duplicate here except IP address */
153         if (userid < 0 || userid >= created_users) return;
154         if (!users[userid].active || users[userid].disabled) return;
155 +       if (!users[userid].authenticated) return;
156         if (users[userid].last_pkt + 60 < time(NULL)) return;
157  
158         if (debug >= 1) {
159 @@ -1813,15 +1831,18 @@ handle_raw_login(char *packet, int len,
160                 user_set_conn_type(userid, CONN_RAW_UDP);
161                 login_calculate(myhash, 16, password, users[userid].seed - 1);
162                 send_raw(fd, myhash, 16, userid, RAW_HDR_CMD_LOGIN, q);
163 +
164 +               users[userid].authenticated_raw = 1;
165         }
166  }
167  
168  static void
169  handle_raw_data(char *packet, int len, struct query *q, int dns_fd, int tun_fd, int userid)
170  {
171 -       if (check_user_and_ip(userid, q) != 0) {
172 +       if (check_authenticated_user_and_ip(userid, q) != 0) {
173                 return;
174         }
175 +       if (!users[userid].authenticated_raw) return;
176  
177         /* Update query and time info for user */
178         users[userid].last_pkt = time(NULL);
179 @@ -1843,9 +1864,10 @@ handle_raw_data(char *packet, int len, s
180  static void
181  handle_raw_ping(struct query *q, int dns_fd, int userid)
182  {
183 -       if (check_user_and_ip(userid, q) != 0) {
184 +       if (check_authenticated_user_and_ip(userid, q) != 0) {
185                 return;
186         }
187 +       if (!users[userid].authenticated_raw) return;
188  
189         /* Update query and time info for user */
190         users[userid].last_pkt = time(NULL);
191 --- a/src/user.c
192 +++ b/src/user.c
193 @@ -78,6 +78,8 @@ init_users(in_addr_t my_ip, int netbits)
194                         users[i].disabled = 0;
195                         created_users++;
196                 }
197 +               users[i].authenticated = 0;
198 +               users[i].authenticated_raw = 0;
199                 users[i].active = 0;
200                 /* Rest is reset on login ('V' packet) */
201         }
202 @@ -119,7 +121,9 @@ find_user_by_ip(uint32_t ip)
203  
204         ret = -1;
205         for (i = 0; i < USERS; i++) {
206 -               if (users[i].active && !users[i].disabled &&
207 +               if (users[i].active &&
208 +                       users[i].authenticated &&
209 +                       !users[i].disabled &&
210                         users[i].last_pkt + 60 > time(NULL) &&
211                         ip == users[i].tun_ip) {
212                         ret = i;
213 @@ -171,6 +175,8 @@ find_available_user()
214                 /* Not used at all or not used in one minute */
215                 if ((!users[i].active || users[i].last_pkt + 60 < time(NULL)) && !users[i].disabled) {
216                         users[i].active = 1;
217 +                       users[i].authenticated = 0;
218 +                       users[i].authenticated_raw = 0;
219                         users[i].last_pkt = time(NULL);
220                         users[i].fragsize = 4096;
221                         users[i].conn = CONN_DNS_NULL;
222 --- a/src/user.h
223 +++ b/src/user.h
224 @@ -39,6 +39,8 @@
225  struct _user {
226         char id;
227         int active;
228 +       int authenticated;
229 +       int authenticated_raw;
230         int disabled;
231         time_t last_pkt;
232         int seed;
233 --- a/tests/user.c
234 +++ b/tests/user.c
235 @@ -93,6 +93,11 @@ START_TEST(test_find_user_by_ip)
236         users[0].last_pkt = time(NULL);
237         
238         testip = (unsigned int) inet_addr("127.0.0.2");
239 +       fail_unless(find_user_by_ip(testip) == -1);
240 +
241 +       users[0].authenticated = 1;
242 +
243 +       testip = (unsigned int) inet_addr("127.0.0.2");
244         fail_unless(find_user_by_ip(testip) == 0);
245  }
246  END_TEST
247 @@ -135,7 +140,11 @@ START_TEST(test_find_available_user)
248         init_users(ip, 27);
249  
250         for (i = 0; i < USERS; i++) {
251 +               users[i].authenticated = 1;
252 +               users[i].authenticated_raw = 1;
253                 fail_unless(find_available_user() == i);
254 +               fail_if(users[i].authenticated);
255 +               fail_if(users[i].authenticated_raw);
256         }
257  
258         for (i = 0; i < USERS; i++) {