Imported Upstream version 0.1.17
[platform/upstream/libnice.git] / stun / tests / test-conncheck.c
1 /*
2  * This file is part of the Nice GLib ICE library.
3  *
4  * (C) 2007 Nokia Corporation. All rights reserved.
5  *  Contact: Rémi Denis-Courmont
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * The Original Code is the Nice GLib ICE library.
18  *
19  * The Initial Developers of the Original Code are Collabora Ltd and Nokia
20  * Corporation. All Rights Reserved.
21  *
22  * Contributors:
23  *   Rémi Denis-Courmont, Nokia
24  *
25  * Alternatively, the contents of this file may be used under the terms of the
26  * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
27  * case the provisions of LGPL are applicable instead of those above. If you
28  * wish to allow use of your version of this file only under the terms of the
29  * LGPL and not to allow others to use your version of this file under the
30  * MPL, indicate your decision by deleting the provisions above and replace
31  * them with the notice and other provisions required by the LGPL. If you do
32  * not delete the provisions above, a recipient may use your version of this
33  * file under either the MPL or the LGPL.
34  */
35
36 #ifdef HAVE_CONFIG_H
37 # include <config.h>
38 #endif
39
40 #include <sys/types.h>
41 #include "stun/stunagent.h"
42 #include "stun/usages/ice.h"
43
44 #include <stdlib.h>
45 #include <stdio.h>
46 #include <string.h>
47
48 #ifdef HAVE_UNISTD_H
49 #include <unistd.h>
50 #endif
51
52 #ifdef _WIN32
53 #include <winsock2.h>
54 #include <ws2tcpip.h>
55 #define MSG_DONTWAIT 0
56 #define MSG_NOSIGNAL 0
57
58 #define alarm(...)
59 #else
60 #include <sys/types.h>
61 #include <sys/socket.h>
62 #include <arpa/inet.h>
63 #include <netinet/in.h>
64 #include <netdb.h>
65 #endif
66
67 #undef NDEBUG /* ensure assertions are built-in */
68 #include <assert.h>
69
70
71 int main (void)
72 {
73   union {
74     struct sockaddr sa;
75     struct sockaddr_storage storage;
76     struct sockaddr_in ip4;
77   } addr;
78   uint8_t req_buf[STUN_MAX_MESSAGE_SIZE];
79   uint8_t resp_buf[STUN_MAX_MESSAGE_SIZE];
80   const uint64_t tie = 0x8000000000000000LL;
81   StunMessageReturn val;
82   StunUsageIceReturn val2;
83   size_t len;
84   size_t rlen;
85   static char username[] = "L:R";
86   static uint8_t ufrag[] = "L", pass[] = "secret";
87   size_t ufrag_len = strlen ((char*) ufrag);
88   size_t pass_len = strlen ((char*) pass);
89   int code;
90   bool control = false;
91   StunAgent agent;
92   StunMessage req;
93   StunMessage resp;
94   StunDefaultValidaterData validater_data[] = {
95     {ufrag, ufrag_len, pass, pass_len},
96     {(uint8_t *) username, strlen (username), pass, pass_len},
97     {NULL, 0, NULL, 0}};
98   StunValidationStatus valid;
99
100   stun_agent_init (&agent, STUN_ALL_KNOWN_ATTRIBUTES,
101       STUN_COMPATIBILITY_RFC5389,
102       STUN_AGENT_USAGE_USE_FINGERPRINT |
103       STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS);
104
105   memset (&addr, 0, sizeof (addr));
106   addr.ip4.sin_family = AF_INET;
107 #ifdef HAVE_SA_LEN
108   addr.ip4.sin_len = sizeof (addr);
109 #endif
110   addr.ip4.sin_port = htons (12345);
111   addr.ip4.sin_addr.s_addr = htonl (0x7f000001);
112
113   /* Incorrect message class */
114   assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
115   assert (stun_agent_init_response (&agent, &req, req_buf, sizeof (req_buf), &req));
116
117   rlen = stun_agent_finish_message (&agent, &req, NULL, 0);
118   assert (rlen > 0);
119
120   len = sizeof (resp_buf);
121   val2 = stun_usage_ice_conncheck_create_reply (&agent, &req,
122       &resp, resp_buf, &len, &addr.storage,
123       sizeof (addr.ip4), &control, tie, STUN_USAGE_ICE_COMPATIBILITY_RFC5245);
124   assert (val2 == STUN_USAGE_ICE_RETURN_INVALID_REQUEST);
125   assert (len == 0);
126
127   /* Incorrect message method */
128   assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), 0x666));
129   val = stun_message_append_string (&req, STUN_ATTRIBUTE_USERNAME, username);
130   assert (val == STUN_MESSAGE_RETURN_SUCCESS);
131   rlen = stun_agent_finish_message (&agent, &req, pass, pass_len);
132   assert (rlen > 0);
133
134   len = sizeof (resp_buf);
135   val2 = stun_usage_ice_conncheck_create_reply (&agent, &req,
136       &resp, resp_buf, &len, &addr.storage,
137       sizeof (addr.ip4), &control, tie, STUN_USAGE_ICE_COMPATIBILITY_RFC5245);
138   assert (val2 == STUN_USAGE_ICE_RETURN_INVALID_METHOD);
139   assert (len > 0);
140
141   /* Unknown attribute */
142   assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
143   val = stun_message_append_string (&req, 0x666, "The evil unknown attribute!");
144   assert (val == STUN_MESSAGE_RETURN_SUCCESS);
145   val = stun_message_append_string (&req, STUN_ATTRIBUTE_USERNAME, username);
146   assert (val == STUN_MESSAGE_RETURN_SUCCESS);
147   rlen = stun_agent_finish_message (&agent, &req, pass, pass_len);
148   assert (rlen > 0);
149
150   valid = stun_agent_validate (&agent, &req, req_buf, rlen,
151       stun_agent_default_validater, validater_data);
152
153   assert (valid == STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE);
154
155   /* Unauthenticated message */
156   assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
157   rlen = stun_agent_finish_message (&agent, &req, NULL, 0);
158   assert (rlen > 0);
159
160   valid = stun_agent_validate (&agent, &req, req_buf, rlen,
161       stun_agent_default_validater, validater_data);
162
163   assert (valid == STUN_VALIDATION_UNAUTHORIZED_BAD_REQUEST);
164
165   /* No username */
166   assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
167   rlen = stun_agent_finish_message (&agent, &req, pass, pass_len);
168   assert (rlen > 0);
169
170   valid = stun_agent_validate (&agent, &req, req_buf, rlen,
171       stun_agent_default_validater, validater_data);
172
173   assert (valid == STUN_VALIDATION_UNAUTHORIZED_BAD_REQUEST);
174   assert (stun_usage_ice_conncheck_priority (&req) == 0);
175   assert (stun_usage_ice_conncheck_use_candidate (&req) == false);
176
177   /* Good message */
178   assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
179   val = stun_message_append32 (&req, STUN_ATTRIBUTE_PRIORITY, 0x12345678);
180   assert (val == STUN_MESSAGE_RETURN_SUCCESS);
181   val = stun_message_append_flag (&req, STUN_ATTRIBUTE_USE_CANDIDATE);
182   assert (val == STUN_MESSAGE_RETURN_SUCCESS);
183   val = stun_message_append_string (&req, STUN_ATTRIBUTE_USERNAME,
184       (char*) ufrag);
185   assert (val == STUN_MESSAGE_RETURN_SUCCESS);
186   rlen = stun_agent_finish_message (&agent, &req, pass, pass_len);
187   assert (rlen > 0);
188
189   len = sizeof (resp_buf);
190   val2 = stun_usage_ice_conncheck_create_reply (&agent, &req,
191       &resp, resp_buf, &len, &addr.storage,
192       sizeof (addr.ip4), &control, tie, STUN_USAGE_ICE_COMPATIBILITY_RFC5245);
193   assert (val2 == STUN_USAGE_ICE_RETURN_SUCCESS);
194   assert (len > 0);
195   assert (stun_agent_validate (&agent, &resp, resp_buf, len,
196           stun_agent_default_validater, validater_data) == STUN_VALIDATION_SUCCESS);
197   assert (stun_message_get_class (&resp) == STUN_RESPONSE);
198   assert (stun_usage_ice_conncheck_priority (&req) == 0x12345678);
199   assert (stun_usage_ice_conncheck_use_candidate (&req) == true);
200
201   /* Invalid socket address */
202   assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
203   val = stun_message_append_string (&req, STUN_ATTRIBUTE_USERNAME,
204       (char *) ufrag);
205   assert (val == STUN_MESSAGE_RETURN_SUCCESS);
206   rlen = stun_agent_finish_message (&agent, &req, pass, pass_len);
207   assert (rlen > 0);
208
209   addr.ip4.sin_family = AF_UNSPEC;
210   len = sizeof (resp_buf);
211   val2 = stun_usage_ice_conncheck_create_reply (&agent, &req,
212       &resp, resp_buf, &len, &addr.storage,
213       sizeof (addr.ip4), &control, tie, STUN_USAGE_ICE_COMPATIBILITY_RFC5245);
214   assert (val2 == STUN_USAGE_ICE_RETURN_INVALID_ADDRESS);
215   assert (len == 0);
216
217   addr.ip4.sin_family = AF_INET;
218
219   /* Role conflict, controlling + ICE-CONTROLLING, switching controlled */
220   assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
221   val = stun_message_append64 (&req, STUN_ATTRIBUTE_ICE_CONTROLLING, tie + 1);
222   assert (val == STUN_MESSAGE_RETURN_SUCCESS);
223   val = stun_message_append_string (&req, STUN_ATTRIBUTE_USERNAME,
224      (char *) ufrag);
225   assert (val == STUN_MESSAGE_RETURN_SUCCESS);
226   rlen = stun_agent_finish_message (&agent, &req, pass, pass_len);
227   assert (rlen > 0);
228
229   len = sizeof (resp_buf);
230   control = true;
231   val2 = stun_usage_ice_conncheck_create_reply (&agent, &req,
232       &resp, resp_buf, &len, &addr.storage,
233       sizeof (addr.ip4), &control, tie, STUN_USAGE_ICE_COMPATIBILITY_RFC5245);
234   assert (val2 == STUN_USAGE_ICE_RETURN_ROLE_CONFLICT);
235   assert (len > 0);
236   assert (control == false);
237   assert (stun_agent_validate (&agent, &resp, resp_buf, len,
238           stun_agent_default_validater, validater_data) == STUN_VALIDATION_SUCCESS);
239   assert (stun_message_get_class (&resp) == STUN_RESPONSE);
240
241   /* Role conflict, controlled + ICE-CONTROLLED, switching controlling */
242   assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
243   val = stun_message_append64 (&req, STUN_ATTRIBUTE_ICE_CONTROLLED, tie - 1);
244   assert (val == STUN_MESSAGE_RETURN_SUCCESS);
245   val = stun_message_append_string (&req, STUN_ATTRIBUTE_USERNAME,
246       (char *) ufrag);
247   assert (val == STUN_MESSAGE_RETURN_SUCCESS);
248   rlen = stun_agent_finish_message (&agent, &req, pass, pass_len);
249   assert (rlen > 0);
250
251   len = sizeof (resp_buf);
252   control = false;
253   val2 = stun_usage_ice_conncheck_create_reply (&agent, &req,
254       &resp, resp_buf, &len, &addr.storage,
255       sizeof (addr.ip4), &control, tie, STUN_USAGE_ICE_COMPATIBILITY_RFC5245);
256   assert (val2 == STUN_USAGE_ICE_RETURN_ROLE_CONFLICT);
257   assert (len > 0);
258   assert (control == true);
259   assert (stun_agent_validate (&agent, &resp, resp_buf, len,
260           stun_agent_default_validater, validater_data) == STUN_VALIDATION_SUCCESS);
261   assert (stun_message_get_class (&resp) == STUN_RESPONSE);
262
263   /* Role conflict, controlling + ICE-CONTROLLING, staying controlling */
264   assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
265   val = stun_message_append64 (&req, STUN_ATTRIBUTE_ICE_CONTROLLING, tie - 1);
266   assert (val == STUN_MESSAGE_RETURN_SUCCESS);
267   val = stun_message_append_string (&req, STUN_ATTRIBUTE_USERNAME,
268      (char *) ufrag);
269   assert (val == STUN_MESSAGE_RETURN_SUCCESS);
270   rlen = stun_agent_finish_message (&agent, &req, pass, pass_len);
271   assert (rlen > 0);
272
273   len = sizeof (resp_buf);
274   control = true;
275   val2 = stun_usage_ice_conncheck_create_reply (&agent, &req,
276       &resp, resp_buf, &len, &addr.storage,
277       sizeof (addr.ip4), &control, tie, STUN_USAGE_ICE_COMPATIBILITY_RFC5245);
278   assert (val2 == STUN_USAGE_ICE_RETURN_ROLE_CONFLICT);
279   assert (len > 0);
280   assert (control == true);
281   assert (stun_agent_validate (&agent, &resp, resp_buf, len,
282           stun_agent_default_validater, validater_data) == STUN_VALIDATION_SUCCESS);
283   assert (stun_message_get_class (&resp) == STUN_ERROR);
284   stun_message_find_error (&resp, &code);
285   assert (code == STUN_ERROR_ROLE_CONFLICT);
286
287   /* Role conflict, controlled + ICE-CONTROLLED, staying controlling */
288   assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
289   val = stun_message_append64 (&req, STUN_ATTRIBUTE_ICE_CONTROLLED, tie + 1);
290   assert (val == STUN_MESSAGE_RETURN_SUCCESS);
291   val = stun_message_append_string (&req, STUN_ATTRIBUTE_USERNAME,
292       (char *) ufrag);
293   assert (val == STUN_MESSAGE_RETURN_SUCCESS);
294   rlen = stun_agent_finish_message (&agent, &req, pass, pass_len);
295   assert (rlen > 0);
296
297   len = sizeof (resp_buf);
298   control = false;
299   val2 = stun_usage_ice_conncheck_create_reply (&agent, &req,
300       &resp, resp_buf, &len, &addr.storage,
301       sizeof (addr.ip4), &control, tie, STUN_USAGE_ICE_COMPATIBILITY_RFC5245);
302   assert (val2 == STUN_USAGE_ICE_RETURN_ROLE_CONFLICT);
303   assert (len > 0);
304   assert (control == false);
305   assert (stun_agent_validate (&agent, &resp, resp_buf, len,
306           stun_agent_default_validater, validater_data) == STUN_VALIDATION_SUCCESS);
307   assert (stun_message_get_class (&resp) == STUN_ERROR);
308   stun_message_find_error (&resp, &code);
309   assert (code == STUN_ERROR_ROLE_CONFLICT);
310
311   return 0;
312 }