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
42 #include "stun/stunagent.h"
43 #include <stdio.h>
44 #include <string.h>
45 #include <stdlib.h>
46 #include <stdarg.h>
47 #include <assert.h>
48
49 #ifdef _WIN32
50 #include <winsock2.h>
51 #else
52 #include <sys/types.h>
53 #include <sys/socket.h>
54 #include <arpa/inet.h>
55 #include <netinet/in.h>
56 #endif
57
58
fatal(const char * msg,...)59 static void fatal (const char *msg, ...)
60 {
61 va_list ap;
62 va_start (ap, msg);
63 vfprintf (stderr, msg, ap);
64 va_end (ap);
65 fputc ('\n', stderr);
66 exit (1);
67 }
68
69 static const uint8_t usr[] = "admin";
70 static const uint8_t pwd[] = "s3kr3t";
71
dynamic_check_validater(StunAgent * agent,StunMessage * message,uint8_t * username,uint16_t username_len,uint8_t ** password,size_t * password_len,void * user_data)72 static bool dynamic_check_validater (StunAgent *agent,
73 StunMessage *message, uint8_t *username, uint16_t username_len,
74 uint8_t **password, size_t *password_len, void *user_data)
75 {
76
77 if (username_len != strlen ((char *) usr) ||
78 memcmp (username, usr, strlen ((char *) usr)) != 0)
79 fatal ("vector test : Validater received wrong username!");
80
81 *password = (uint8_t *) pwd;
82 *password_len = strlen ((char *) pwd);
83
84
85 return true;
86 }
87 static void
dynamic_check(StunAgent * agent,StunMessage * msg,size_t len)88 dynamic_check (StunAgent *agent, StunMessage *msg, size_t len)
89 {
90 StunMessage msg2;
91
92 if (stun_agent_validate (agent, &msg2, msg->buffer, len, dynamic_check_validater, NULL) != STUN_VALIDATION_SUCCESS)
93 fatal ("Could not validate message");
94
95 printf ("Built message of %u bytes\n", (unsigned)len);
96 }
97
98
99 static size_t
finish_check(StunAgent * agent,StunMessage * msg)100 finish_check (StunAgent *agent, StunMessage *msg)
101 {
102 uint8_t buf[STUN_MAX_MESSAGE_SIZE + 8];
103 size_t len;
104 uint16_t plen;
105 StunMessage msg2 = {0};
106 StunMessageReturn val;
107
108 msg2.agent = msg->agent;
109 msg2.buffer = buf;
110 msg2.buffer_len = sizeof(buf);
111 memcpy (msg2.buffer, msg->buffer, sizeof(buf) > msg->buffer_len ? msg->buffer_len : sizeof(buf));
112
113 len = stun_agent_finish_message (agent, msg, NULL, 0);
114
115 if (len <= 0)
116 fatal ("Cannot finish message");
117 dynamic_check (agent, msg, len);
118
119 if (stun_message_find (&msg2, STUN_ATTRIBUTE_MESSAGE_INTEGRITY, &plen) != NULL)
120 fatal ("Missing HMAC test failed");
121
122 val = stun_message_append_string (&msg2, STUN_ATTRIBUTE_USERNAME, (char *) usr);
123 assert (val == STUN_MESSAGE_RETURN_SUCCESS);
124
125 len = stun_agent_finish_message (agent, &msg2, pwd, strlen ((char *) pwd));
126
127 if (len <= 0)
128 fatal ("Cannot finish message with short-term creds");
129 dynamic_check (agent, &msg2, len);
130
131 return len;
132 }
133
134 static void
check_af(const char * name,int family,socklen_t addrlen)135 check_af (const char *name, int family, socklen_t addrlen)
136 {
137 struct sockaddr_storage addr;
138 uint8_t buf[100];
139 StunAgent agent;
140 StunMessage msg;
141 uint16_t known_attributes[] = {STUN_ATTRIBUTE_USERNAME, STUN_ATTRIBUTE_MESSAGE_INTEGRITY, STUN_ATTRIBUTE_ERROR_CODE, 0};
142
143 stun_agent_init (&agent, known_attributes,
144 STUN_COMPATIBILITY_RFC5389, STUN_AGENT_USAGE_USE_FINGERPRINT);
145
146 assert (addrlen <= sizeof (addr));
147
148 memset (&addr, 0, sizeof (addr));
149 stun_agent_init_request (&agent, &msg, buf, sizeof(buf), STUN_BINDING);
150
151 if (stun_message_append_addr (&msg, STUN_ATTRIBUTE_MAPPED_ADDRESS,
152 (struct sockaddr *) &addr, addrlen) !=
153 STUN_MESSAGE_RETURN_UNSUPPORTED_ADDRESS)
154 fatal ("Unknown address family test failed");
155 if (stun_message_append_xor_addr (&msg, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
156 &addr, addrlen) !=
157 STUN_MESSAGE_RETURN_UNSUPPORTED_ADDRESS)
158 fatal ("Unknown address family xor test failed");
159
160 addr.ss_family = family;
161 if (stun_message_append_addr (&msg, STUN_ATTRIBUTE_MAPPED_ADDRESS,
162 (struct sockaddr *) &addr, addrlen - 1) !=
163 STUN_MESSAGE_RETURN_INVALID)
164 fatal ("Too small %s sockaddr test failed", name);
165
166 if (stun_message_append_xor_addr (&msg, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
167 &addr, addrlen - 1) != STUN_MESSAGE_RETURN_INVALID)
168 fatal ("Too small %s sockaddr xor test failed", name);
169
170 if (stun_message_append_addr (&msg, STUN_ATTRIBUTE_MAPPED_ADDRESS,
171 (struct sockaddr *) &addr, addrlen) != STUN_MESSAGE_RETURN_SUCCESS)
172 fatal ("%s sockaddr test failed", name);
173
174 if (stun_message_append_xor_addr (&msg, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
175 &addr, addrlen) != STUN_MESSAGE_RETURN_SUCCESS)
176 fatal ("%s sockaddr xor test failed", name);
177 }
178
main(void)179 int main (void)
180 {
181 uint8_t buf[100];
182 size_t len;
183 union {
184 struct sockaddr_storage storage;
185 struct sockaddr addr;
186 } addr;
187
188 StunAgent agent;
189 StunMessage msg;
190 uint16_t known_attributes[] = {STUN_ATTRIBUTE_USERNAME,
191 STUN_ATTRIBUTE_MESSAGE_INTEGRITY,
192 STUN_ATTRIBUTE_ERROR_CODE,
193 0};
194
195 stun_agent_init (&agent, known_attributes,
196 STUN_COMPATIBILITY_RFC5389, STUN_AGENT_USAGE_USE_FINGERPRINT);
197
198 /* Request formatting test */
199 stun_agent_init_request (&agent, &msg, buf, sizeof(buf), STUN_BINDING);
200 finish_check (&agent, &msg);
201 if (memcmp (buf, "\x00\x01", 2))
202 fatal ("Request formatting test failed");
203
204 /* Response formatting test */
205 stun_agent_init_response (&agent, &msg, buf, sizeof (buf), &msg);
206 finish_check (&agent, &msg);
207 if (memcmp (buf, "\x01\x01", 2))
208 fatal ("Response formatting test failed");
209
210 /* Error formatting test */
211 stun_agent_init_request (&agent, &msg, buf, sizeof(buf), STUN_BINDING);
212 finish_check (&agent, &msg);
213 if (!stun_agent_init_error (&agent, &msg, buf, sizeof (buf), &msg, 400))
214 fatal ("Error initialization test failed");
215 finish_check (&agent, &msg);
216 if (memcmp (buf, "\x01\x11", 2))
217 fatal ("Error formatting test failed");
218 /* Unknown error formatting test */
219 stun_agent_init_request (&agent, &msg, buf, sizeof(buf), STUN_BINDING);
220 finish_check (&agent, &msg);
221 if (!stun_agent_init_error (&agent, &msg, buf, sizeof (buf), &msg, 666))
222 fatal ("Unknown error initialization test failed");
223 finish_check (&agent, &msg);
224 if (memcmp (buf, "\x01\x11", 2))
225 fatal ("Unknown error formatting test failed");
226
227 /* Overflow tests */
228 stun_agent_init_request (&agent, &msg, buf, sizeof(buf), STUN_BINDING);
229
230 for (len = 0;
231 stun_message_append_flag (&msg, 0xffff) !=
232 STUN_MESSAGE_RETURN_NOT_ENOUGH_SPACE;
233 len += 4)
234 {
235 if (len > 0xffff)
236 fatal ("Overflow protection test failed");
237 }
238
239 if (stun_message_append32 (&msg, 0xffff, 0x12345678) !=
240 STUN_MESSAGE_RETURN_NOT_ENOUGH_SPACE)
241 fatal ("Double-word overflow test failed");
242 if (stun_message_append64 (&msg, 0xffff,
243 0x123456789abcdef0) != STUN_MESSAGE_RETURN_NOT_ENOUGH_SPACE)
244 fatal ("Quad-word overflow test failed");
245 if (stun_message_append_string (&msg, 0xffff, "foobar") !=
246 STUN_MESSAGE_RETURN_NOT_ENOUGH_SPACE)
247 fatal ("String overflow test failed");
248
249 memset (&addr, 0, sizeof (addr));
250 addr.addr.sa_family = AF_INET;
251 #ifdef HAVE_SS_LEN
252 addr.addr.ss_len = sizeof (addr);
253 #endif
254 if (stun_message_append_xor_addr (&msg, 0xffff, &addr.storage,
255 sizeof (addr)) != STUN_MESSAGE_RETURN_NOT_ENOUGH_SPACE)
256 fatal ("Address overflow test failed");
257
258 if (stun_agent_finish_message (&agent, &msg, NULL, 0) != 0)
259 fatal ("Fingerprint overflow test failed");
260 if (stun_agent_finish_message (&agent, &msg, pwd, strlen ((char *) pwd)) != 0)
261 fatal ("Message integrity overflow test failed");
262
263 /* Address attributes tests */
264 check_af ("IPv4", AF_INET, sizeof (struct sockaddr_in));
265 #ifdef AF_INET6
266 check_af ("IPv6", AF_INET6, sizeof (struct sockaddr_in6));
267 #endif
268
269 return 0;
270 }
271