File: | root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_codec.c |
Warning: | line 1348, column 14 Although the value stored to 'r' is used in the enclosing expression, the value is never actually read from 'r' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* |
2 | Copyright (c) 2007, Adobe Systems, Incorporated |
3 | All rights reserved. |
4 | |
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted provided that the following conditions are |
7 | met: |
8 | |
9 | * Redistributions of source code must retain the above copyright |
10 | notice, this list of conditions and the following disclaimer. |
11 | |
12 | * Redistributions in binary form must reproduce the above copyright |
13 | notice, this list of conditions and the following disclaimer in the |
14 | documentation and/or other materials provided with the distribution. |
15 | |
16 | * Neither the name of Adobe Systems, Network Resonance nor the names of its |
17 | contributors may be used to endorse or promote products derived from |
18 | this software without specific prior written permission. |
19 | |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
24 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
31 | */ |
32 | |
33 | #include <errno(*__errno_location ()).h> |
34 | #include <csi_platform.h> |
35 | |
36 | #ifdef WIN32 |
37 | #include <winsock2.h> |
38 | #include <stdlib.h> |
39 | #include <io.h> |
40 | #include <time.h> |
41 | #else /* UNIX */ |
42 | #include <string.h> |
43 | #endif /* end UNIX */ |
44 | #include <assert.h> |
45 | #include <stddef.h> |
46 | |
47 | #include "nr_api.h" |
48 | #include "stun.h" |
49 | #include "byteorder.h" |
50 | #include "r_crc32.h" |
51 | #include "nr_crypto.h" |
52 | |
53 | #define NR_STUN_IPV4_FAMILY0x01 0x01 |
54 | #define NR_STUN_IPV6_FAMILY0x02 0x02 |
55 | |
56 | #define SKIP_ATTRIBUTE_DECODE-1 -1 |
57 | |
58 | static int nr_stun_find_attr_info(UINT2 type, nr_stun_attr_info **info); |
59 | |
60 | static int nr_stun_fix_attribute_ordering(nr_stun_message *msg); |
61 | |
62 | static int nr_stun_encode_htons(UINT2 data, size_t buflen, UCHAR *buf, size_t *offset); |
63 | static int nr_stun_encode_htonl(UINT4 data, size_t buflen, UCHAR *buf, size_t *offset); |
64 | static int nr_stun_encode_htonll(UINT8 data, size_t buflen, UCHAR *buf, size_t *offset); |
65 | static int nr_stun_encode(UCHAR *data, size_t length, size_t buflen, UCHAR *buf, size_t *offset); |
66 | |
67 | static int nr_stun_decode_htons(UCHAR *buf, size_t buflen, size_t *offset, UINT2 *data); |
68 | static int nr_stun_decode_htonl(UCHAR *buf, size_t buflen, size_t *offset, UINT4 *data); |
69 | static int nr_stun_decode_htonll(UCHAR *buf, size_t buflen, size_t *offset, UINT8 *data); |
70 | static int nr_stun_decode(size_t length, UCHAR *buf, size_t buflen, size_t *offset, UCHAR *data); |
71 | |
72 | static int nr_stun_attr_string_illegal(nr_stun_attr_info *attr_info, size_t len, void *data, size_t max_bytes, size_t max_chars); |
73 | |
74 | static int nr_stun_attr_error_code_illegal(nr_stun_attr_info *attr_info, size_t attrlen, void *data); |
75 | static int nr_stun_attr_nonce_illegal(nr_stun_attr_info *attr_info, size_t attrlen, void *data); |
76 | static int nr_stun_attr_realm_illegal(nr_stun_attr_info *attr_info, size_t attrlen, void *data); |
77 | static int nr_stun_attr_server_illegal(nr_stun_attr_info *attr_info, size_t attrlen, void *data); |
78 | static int nr_stun_attr_username_illegal(nr_stun_attr_info *attr_info, size_t attrlen, void *data); |
79 | static int |
80 | nr_stun_attr_codec_fingerprint_decode(nr_stun_attr_info *attr_info, size_t attrlen, UCHAR *buf, size_t offset, size_t buflen, void *data); |
81 | |
82 | |
83 | int |
84 | nr_stun_encode_htons(UINT2 data, size_t buflen, UCHAR *buf, size_t *offset) |
85 | { |
86 | UINT2 d = htons(data)__bswap_16 (data); |
87 | |
88 | if (*offset + sizeof(d) >= buflen) { |
89 | r_log(NR_LOG_STUN, LOG_WARNING4, "Attempted buffer overrun: %d + %zd >= %d", *offset, sizeof(d), buflen); |
90 | return R_BAD_DATA7; |
91 | } |
92 | |
93 | memcpy(&buf[*offset], &d, sizeof(d)); |
94 | *offset += sizeof(d); |
95 | |
96 | return 0; |
97 | } |
98 | |
99 | int |
100 | nr_stun_encode_htonl(UINT4 data, size_t buflen, UCHAR *buf, size_t *offset) |
101 | { |
102 | UINT4 d = htonl(data)__bswap_32 (data); |
103 | |
104 | if (*offset + sizeof(d) > buflen) { |
105 | r_log(NR_LOG_STUN, LOG_WARNING4, "Attempted buffer overrun: %d + %zd > %d", *offset, sizeof(d), buflen); |
106 | return R_BAD_DATA7; |
107 | } |
108 | |
109 | memcpy(&buf[*offset], &d, sizeof(d)); |
110 | *offset += sizeof(d); |
111 | |
112 | return 0; |
113 | } |
114 | |
115 | int |
116 | nr_stun_encode_htonll(UINT8 data, size_t buflen, UCHAR *buf, size_t *offset) |
117 | { |
118 | UINT8 d = nr_htonll(data); |
119 | |
120 | if (*offset + sizeof(d) > buflen) { |
121 | r_log(NR_LOG_STUN, LOG_WARNING4, "Attempted buffer overrun: %d + %zd > %d", *offset, sizeof(d), buflen); |
122 | return R_BAD_DATA7; |
123 | } |
124 | |
125 | memcpy(&buf[*offset], &d, sizeof(d)); |
126 | *offset += sizeof(d); |
127 | |
128 | return 0; |
129 | } |
130 | |
131 | int |
132 | nr_stun_encode(UCHAR *data, size_t length, size_t buflen, UCHAR *buf, size_t *offset) |
133 | { |
134 | if (*offset + length > buflen) { |
135 | r_log(NR_LOG_STUN, LOG_WARNING4, "Attempted buffer overrun: %d + %d > %d", *offset, length, buflen); |
136 | return R_BAD_DATA7; |
137 | } |
138 | |
139 | memcpy(&buf[*offset], data, length); |
140 | *offset += length; |
141 | |
142 | return 0; |
143 | } |
144 | |
145 | |
146 | int |
147 | nr_stun_decode_htons(UCHAR *buf, size_t buflen, size_t *offset, UINT2 *data) |
148 | { |
149 | UINT2 d; |
150 | |
151 | if (*offset + sizeof(d) > buflen) { |
152 | r_log(NR_LOG_STUN, LOG_WARNING4, "Attempted buffer overrun: %d + %zd > %d", *offset, sizeof(d), buflen); |
153 | return R_BAD_DATA7; |
154 | } |
155 | |
156 | memcpy(&d, &buf[*offset], sizeof(d)); |
157 | *offset += sizeof(d); |
158 | *data = htons(d)__bswap_16 (d); |
159 | |
160 | return 0; |
161 | } |
162 | |
163 | int |
164 | nr_stun_decode_htonl(UCHAR *buf, size_t buflen, size_t *offset, UINT4 *data) |
165 | { |
166 | UINT4 d; |
167 | |
168 | if (*offset + sizeof(d) > buflen) { |
169 | r_log(NR_LOG_STUN, LOG_WARNING4, "Attempted buffer overrun: %d + %zd > %d", *offset, sizeof(d), buflen); |
170 | return R_BAD_DATA7; |
171 | } |
172 | |
173 | memcpy(&d, &buf[*offset], sizeof(d)); |
174 | *offset += sizeof(d); |
175 | *data = htonl(d)__bswap_32 (d); |
176 | |
177 | return 0; |
178 | } |
179 | |
180 | int |
181 | nr_stun_decode_htonll(UCHAR *buf, size_t buflen, size_t *offset, UINT8 *data) |
182 | { |
183 | UINT8 d; |
184 | |
185 | if (*offset + sizeof(d) > buflen) { |
186 | r_log(NR_LOG_STUN, LOG_WARNING4, "Attempted buffer overrun: %d + %zd > %d", *offset, sizeof(d), buflen); |
187 | return R_BAD_DATA7; |
188 | } |
189 | |
190 | memcpy(&d, &buf[*offset], sizeof(d)); |
191 | *offset += sizeof(d); |
192 | *data = nr_htonll(d); |
193 | |
194 | return 0; |
195 | } |
196 | |
197 | int |
198 | nr_stun_decode(size_t length, UCHAR *buf, size_t buflen, size_t *offset, UCHAR *data) |
199 | { |
200 | if (*offset + length > buflen) { |
201 | r_log(NR_LOG_STUN, LOG_WARNING4, "Attempted buffer overrun: %d + %d > %d", *offset, length, buflen); |
202 | return R_BAD_DATA7; |
203 | } |
204 | |
205 | memcpy(data, &buf[*offset], length); |
206 | *offset += length; |
207 | |
208 | return 0; |
209 | } |
210 | |
211 | /** |
212 | * The argument must be a non-null pointer to a zero-terminated string. |
213 | * |
214 | * If the argument is valid UTF-8, returns the number of code points in the |
215 | * string excluding the zero-terminator. |
216 | * |
217 | * If the argument is invalid UTF-8, returns a lower bound for the number of |
218 | * code points in the string. (If UTF-8 error handling was performed on the |
219 | * string, new REPLACEMENT CHARACTER code points could be introduced in |
220 | * a way that would increase the total number of code points compared to |
221 | * what this function counts.) |
222 | */ |
223 | size_t |
224 | nr_count_utf8_code_points_without_validation(const char *s) { |
225 | size_t nchars = 0; |
226 | char c; |
227 | while ((c = *s)) { |
228 | if ((c & 0xC0) != 0x80) { |
229 | ++nchars; |
230 | } |
231 | ++s; |
232 | } |
233 | return nchars; |
234 | } |
235 | |
236 | int |
237 | nr_stun_attr_string_illegal(nr_stun_attr_info *attr_info, size_t len, void *data, size_t max_bytes, size_t max_chars) |
238 | { |
239 | int _status; |
240 | char *s = data; |
241 | size_t nchars; |
242 | |
243 | if (len > max_bytes) { |
244 | r_log(NR_LOG_STUN, LOG_WARNING4, "%s is too large: %d bytes", attr_info->name, len); |
245 | ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
246 | } |
247 | |
248 | nchars = nr_count_utf8_code_points_without_validation(s); |
249 | if (nchars > max_chars) { |
250 | r_log(NR_LOG_STUN, LOG_WARNING4, "%s is too large: %zd characters", attr_info->name, nchars); |
251 | ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
252 | } |
253 | |
254 | _status = 0; |
255 | abort: |
256 | return _status; |
257 | } |
258 | |
259 | int |
260 | nr_stun_attr_error_code_illegal(nr_stun_attr_info *attr_info, size_t attrlen, void *data) |
261 | { |
262 | int r,_status; |
263 | nr_stun_attr_error_code *ec = data; |
264 | |
265 | if (ec->number < 300 || ec->number > 699) |
266 | ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
267 | |
268 | if ((r=nr_stun_attr_string_illegal(attr_info, strlen(ec->reason), ec->reason, NR_STUN_MAX_ERROR_CODE_REASON_BYTES763, NR_STUN_MAX_ERROR_CODE_REASON_CHARS128))) |
269 | ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
270 | |
271 | _status = 0; |
272 | abort: |
273 | return _status; |
274 | } |
275 | |
276 | int |
277 | nr_stun_attr_nonce_illegal(nr_stun_attr_info *attr_info, size_t attrlen, void *data) |
278 | { |
279 | return nr_stun_attr_string_illegal(attr_info, attrlen, data, NR_STUN_MAX_NONCE_BYTES763, NR_STUN_MAX_NONCE_CHARS128); |
280 | } |
281 | |
282 | int |
283 | nr_stun_attr_realm_illegal(nr_stun_attr_info *attr_info, size_t attrlen, void *data) |
284 | { |
285 | return nr_stun_attr_string_illegal(attr_info, attrlen, data, NR_STUN_MAX_REALM_BYTES763, NR_STUN_MAX_REALM_CHARS128); |
286 | } |
287 | |
288 | int |
289 | nr_stun_attr_server_illegal(nr_stun_attr_info *attr_info, size_t attrlen, void *data) |
290 | { |
291 | return nr_stun_attr_string_illegal(attr_info, attrlen, data, NR_STUN_MAX_SERVER_BYTES763, NR_STUN_MAX_SERVER_CHARS128); |
292 | } |
293 | |
294 | int |
295 | nr_stun_attr_username_illegal(nr_stun_attr_info *attr_info, size_t attrlen, void *data) |
296 | { |
297 | return nr_stun_attr_string_illegal(attr_info, attrlen, data, NR_STUN_MAX_USERNAME_BYTES513, -1); |
298 | } |
299 | |
300 | static int |
301 | nr_stun_attr_codec_UCHAR_print(nr_stun_attr_info *attr_info, char *msg, void *data) |
302 | { |
303 | r_log(NR_LOG_STUN, LOG_DEBUG7, "%s %s: %u", msg, attr_info->name, *(UCHAR*)data); |
304 | return 0; |
305 | } |
306 | |
307 | static int |
308 | nr_stun_attr_codec_UCHAR_encode(nr_stun_attr_info *attr_info, void *data, size_t offset, size_t buflen, UCHAR *buf, size_t *attrlen) |
309 | { |
310 | int start = offset; |
311 | UINT4 tmp = *((UCHAR *)data); |
312 | tmp <<= 24; |
313 | |
314 | if (nr_stun_encode_htons(attr_info->type , buflen, buf, &offset) |
315 | || nr_stun_encode_htons(sizeof(UINT4) , buflen, buf, &offset) |
316 | || nr_stun_encode_htonl(tmp , buflen, buf, &offset)) |
317 | return R_FAILED10; |
318 | |
319 | *attrlen = offset - start; |
320 | |
321 | return 0; |
322 | } |
323 | |
324 | static int |
325 | nr_stun_attr_codec_UCHAR_decode(nr_stun_attr_info *attr_info, size_t attrlen, UCHAR *buf, size_t offset, size_t buflen, void *data) |
326 | { |
327 | UINT4 tmp; |
328 | |
329 | if (attrlen != sizeof(UINT4)) { |
330 | r_log(NR_LOG_STUN, LOG_WARNING4, "Integer is illegal size: %d", attrlen); |
331 | return R_FAILED10; |
332 | } |
333 | |
334 | if (nr_stun_decode_htonl(buf, buflen, &offset, &tmp)) |
335 | return R_FAILED10; |
336 | |
337 | *((UCHAR *)data) = (tmp >> 24) & 0xff; |
338 | |
339 | return 0; |
340 | } |
341 | |
342 | nr_stun_attr_codec nr_stun_attr_codec_UCHAR = { |
343 | "UCHAR", |
344 | nr_stun_attr_codec_UCHAR_print, |
345 | nr_stun_attr_codec_UCHAR_encode, |
346 | nr_stun_attr_codec_UCHAR_decode |
347 | }; |
348 | |
349 | static int |
350 | nr_stun_attr_codec_UINT4_print(nr_stun_attr_info *attr_info, char *msg, void *data) |
351 | { |
352 | r_log(NR_LOG_STUN, LOG_DEBUG7, "%s %s: %u", msg, attr_info->name, *(UINT4*)data); |
353 | return 0; |
354 | } |
355 | |
356 | static int |
357 | nr_stun_attr_codec_UINT4_encode(nr_stun_attr_info *attr_info, void *data, size_t offset, size_t buflen, UCHAR *buf, size_t *attrlen) |
358 | { |
359 | int start = offset; |
360 | |
361 | if (nr_stun_encode_htons(attr_info->type , buflen, buf, &offset) |
362 | || nr_stun_encode_htons(sizeof(UINT4) , buflen, buf, &offset) |
363 | || nr_stun_encode_htonl(*(UINT4*)data , buflen, buf, &offset)) |
364 | return R_FAILED10; |
365 | |
366 | *attrlen = offset - start; |
367 | |
368 | return 0; |
369 | } |
370 | |
371 | static int |
372 | nr_stun_attr_codec_UINT4_decode(nr_stun_attr_info *attr_info, size_t attrlen, UCHAR *buf, size_t offset, size_t buflen, void *data) |
373 | { |
374 | if (attrlen != sizeof(UINT4)) { |
375 | r_log(NR_LOG_STUN, LOG_WARNING4, "Integer is illegal size: %d", attrlen); |
376 | return R_FAILED10; |
377 | } |
378 | |
379 | if (nr_stun_decode_htonl(buf, buflen, &offset, (UINT4*)data)) |
380 | return R_FAILED10; |
381 | |
382 | return 0; |
383 | } |
384 | |
385 | nr_stun_attr_codec nr_stun_attr_codec_UINT4 = { |
386 | "UINT4", |
387 | nr_stun_attr_codec_UINT4_print, |
388 | nr_stun_attr_codec_UINT4_encode, |
389 | nr_stun_attr_codec_UINT4_decode |
390 | }; |
391 | |
392 | static int |
393 | nr_stun_attr_codec_UINT8_print(nr_stun_attr_info *attr_info, char *msg, void *data) |
394 | { |
395 | r_log(NR_LOG_STUN, LOG_DEBUG7, "%s %s: %llu", msg, attr_info->name, *(UINT8*)data); |
396 | return 0; |
397 | } |
398 | |
399 | static int |
400 | nr_stun_attr_codec_UINT8_encode(nr_stun_attr_info *attr_info, void *data, size_t offset, size_t buflen, UCHAR *buf, size_t *attrlen) |
401 | { |
402 | int start = offset; |
403 | |
404 | if (nr_stun_encode_htons(attr_info->type , buflen, buf, &offset) |
405 | || nr_stun_encode_htons(sizeof(UINT8) , buflen, buf, &offset) |
406 | || nr_stun_encode_htonll(*(UINT8*)data , buflen, buf, &offset)) |
407 | return R_FAILED10; |
408 | |
409 | *attrlen = offset - start; |
410 | |
411 | return 0; |
412 | } |
413 | |
414 | static int |
415 | nr_stun_attr_codec_UINT8_decode(nr_stun_attr_info *attr_info, size_t attrlen, UCHAR *buf, size_t offset, size_t buflen, void *data) |
416 | { |
417 | if (attrlen != sizeof(UINT8)) { |
418 | r_log(NR_LOG_STUN, LOG_WARNING4, "Integer is illegal size: %d", attrlen); |
419 | return R_FAILED10; |
420 | } |
421 | |
422 | if (nr_stun_decode_htonll(buf, buflen, &offset, (UINT8*)data)) |
423 | return R_FAILED10; |
424 | |
425 | return 0; |
426 | } |
427 | |
428 | nr_stun_attr_codec nr_stun_attr_codec_UINT8 = { |
429 | "UINT8", |
430 | nr_stun_attr_codec_UINT8_print, |
431 | nr_stun_attr_codec_UINT8_encode, |
432 | nr_stun_attr_codec_UINT8_decode |
433 | }; |
434 | |
435 | static int |
436 | nr_stun_attr_codec_addr_print(nr_stun_attr_info *attr_info, char *msg, void *data) |
437 | { |
438 | r_log(NR_LOG_STUN, LOG_DEBUG7, "%s %s: %s", msg, attr_info->name, ((nr_transport_addr*)data)->as_string); |
439 | return 0; |
440 | } |
441 | |
442 | static int |
443 | nr_stun_attr_codec_addr_encode(nr_stun_attr_info *attr_info, void *data, size_t offset, size_t buflen, UCHAR *buf, size_t *attrlen) |
444 | { |
445 | int r,_status; |
446 | int start = offset; |
447 | nr_transport_addr *addr = data; |
448 | UCHAR pad = '\0'; |
449 | UCHAR family; |
450 | |
451 | if ((r=nr_stun_encode_htons(attr_info->type, buflen, buf, &offset))) |
452 | ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
453 | |
454 | switch (addr->ip_version) { |
455 | case NR_IPV44: |
456 | family = NR_STUN_IPV4_FAMILY0x01; |
457 | if (nr_stun_encode_htons(8 , buflen, buf, &offset) |
458 | || nr_stun_encode(&pad, 1 , buflen, buf, &offset) |
459 | || nr_stun_encode(&family, 1 , buflen, buf, &offset) |
460 | || nr_stun_encode_htons(ntohs(addr->u.addr4.sin_port)__bswap_16 (addr->u.addr4.sin_port), buflen, buf, &offset) |
461 | || nr_stun_encode_htonl(ntohl(addr->u.addr4.sin_addr.s_addr)__bswap_32 (addr->u.addr4.sin_addr.s_addr), buflen, buf, &offset)) |
462 | ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
463 | break; |
464 | |
465 | case NR_IPV66: |
466 | family = NR_STUN_IPV6_FAMILY0x02; |
467 | if (nr_stun_encode_htons(20 , buflen, buf, &offset) |
468 | || nr_stun_encode(&pad, 1 , buflen, buf, &offset) |
469 | || nr_stun_encode(&family, 1 , buflen, buf, &offset) |
470 | || nr_stun_encode_htons(ntohs(addr->u.addr6.sin6_port)__bswap_16 (addr->u.addr6.sin6_port), buflen, buf, &offset) |
471 | || nr_stun_encode(addr->u.addr6.sin6_addr.s6_addr__in6_u.__u6_addr8, 16, buflen, buf, &offset)) |
472 | ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
473 | break; |
474 | |
475 | default: |
476 | assert(0)((void) sizeof ((0) ? 1 : 0), __extension__ ({ if (0) ; else __assert_fail ("0", "/root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_codec.c" , 476, __extension__ __PRETTY_FUNCTION__); })); |
477 | ABORT(R_INTERNAL)do { int _r=3; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
478 | break; |
479 | } |
480 | |
481 | *attrlen = offset - start; |
482 | |
483 | _status = 0; |
484 | abort: |
485 | return _status; |
486 | } |
487 | |
488 | static int |
489 | nr_stun_attr_codec_addr_decode(nr_stun_attr_info *attr_info, size_t attrlen, UCHAR *buf, size_t offset, size_t buflen, void *data) |
490 | { |
491 | int _status; |
492 | UCHAR pad; |
493 | UCHAR family; |
494 | UINT2 port; |
495 | UINT4 addr4; |
496 | struct in6_addr addr6; |
497 | nr_transport_addr *result = data; |
498 | |
499 | if (nr_stun_decode(1, buf, buflen, &offset, &pad) |
500 | || nr_stun_decode(1, buf, buflen, &offset, &family)) |
501 | ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
502 | |
503 | switch (family) { |
504 | case NR_STUN_IPV4_FAMILY0x01: |
505 | if (attrlen != 8) { |
506 | r_log(NR_LOG_STUN, LOG_WARNING4, "Illegal attribute length: %d", attrlen); |
507 | ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
508 | } |
509 | |
510 | if (nr_stun_decode_htons(buf, buflen, &offset, &port) |
511 | || nr_stun_decode_htonl(buf, buflen, &offset, &addr4)) |
512 | ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
513 | |
514 | if (nr_ip4_port_to_transport_addr(addr4, port, IPPROTO_UDPIPPROTO_UDP, result)) |
515 | ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
516 | break; |
517 | |
518 | case NR_STUN_IPV6_FAMILY0x02: |
519 | if (attrlen != 20) { |
520 | r_log(NR_LOG_STUN, LOG_WARNING4, "Illegal attribute length: %d", attrlen); |
521 | ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
522 | } |
523 | |
524 | if (nr_stun_decode_htons(buf, buflen, &offset, &port) |
525 | || nr_stun_decode(16, buf, buflen, &offset, addr6.s6_addr__in6_u.__u6_addr8)) |
526 | ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
527 | |
528 | if (nr_ip6_port_to_transport_addr(&addr6, port, IPPROTO_UDPIPPROTO_UDP, result)) |
529 | ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
530 | break; |
531 | |
532 | default: |
533 | r_log(NR_LOG_STUN, LOG_WARNING4, "Illegal address family: %d", family); |
534 | ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
535 | break; |
536 | } |
537 | |
538 | _status = 0; |
539 | abort: |
540 | return _status; |
541 | } |
542 | |
543 | nr_stun_attr_codec nr_stun_attr_codec_addr = { |
544 | "addr", |
545 | nr_stun_attr_codec_addr_print, |
546 | nr_stun_attr_codec_addr_encode, |
547 | nr_stun_attr_codec_addr_decode |
548 | }; |
549 | |
550 | static int |
551 | nr_stun_attr_codec_data_print(nr_stun_attr_info *attr_info, char *msg, void *data) |
552 | { |
553 | nr_stun_attr_data *d = data; |
554 | r_dump(NR_LOG_STUN, LOG_DEBUG7, attr_info->name, (char*)d->data, d->length); |
555 | return 0; |
556 | } |
557 | |
558 | static int |
559 | nr_stun_attr_codec_data_encode(nr_stun_attr_info *attr_info, void *data, size_t offset, size_t buflen, UCHAR *buf, size_t *attrlen) |
560 | { |
561 | nr_stun_attr_data *d = data; |
562 | int start = offset; |
563 | |
564 | if (nr_stun_encode_htons(attr_info->type , buflen, buf, &offset) |
565 | || nr_stun_encode_htons(d->length , buflen, buf, &offset) |
566 | || nr_stun_encode(d->data, d->length , buflen, buf, &offset)) |
567 | return R_FAILED10; |
568 | |
569 | *attrlen = offset - start; |
570 | |
571 | return 0; |
572 | } |
573 | |
574 | static int |
575 | nr_stun_attr_codec_data_decode(nr_stun_attr_info *attr_info, size_t attrlen, UCHAR *buf, size_t offset, size_t buflen, void *data) |
576 | { |
577 | int _status; |
578 | nr_stun_attr_data *result = data; |
579 | |
580 | /* -1 because it is going to be null terminated just to be safe */ |
581 | if (attrlen >= (sizeof(result->data) - 1)) { |
582 | r_log(NR_LOG_STUN, LOG_WARNING4, "Too much data: %d bytes", attrlen); |
583 | ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
584 | } |
585 | |
586 | if (nr_stun_decode(attrlen, buf, buflen, &offset, result->data)) |
587 | ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
588 | |
589 | result->length = attrlen; |
590 | result->data[attrlen] = '\0'; /* just to be nice */ |
591 | |
592 | _status=0; |
593 | abort: |
594 | return _status; |
595 | } |
596 | |
597 | nr_stun_attr_codec nr_stun_attr_codec_data = { |
598 | "data", |
599 | nr_stun_attr_codec_data_print, |
600 | nr_stun_attr_codec_data_encode, |
601 | nr_stun_attr_codec_data_decode |
602 | }; |
603 | |
604 | static int |
605 | nr_stun_attr_codec_error_code_print(nr_stun_attr_info *attr_info, char *msg, void *data) |
606 | { |
607 | nr_stun_attr_error_code *error_code = data; |
608 | r_log(NR_LOG_STUN, LOG_DEBUG7, "%s %s: %d %s", |
609 | msg, attr_info->name, error_code->number, |
610 | error_code->reason); |
611 | return 0; |
612 | } |
613 | |
614 | static int |
615 | nr_stun_attr_codec_error_code_encode(nr_stun_attr_info *attr_info, void *data, size_t offset, size_t buflen, UCHAR *buf, size_t *attrlen) |
616 | { |
617 | nr_stun_attr_error_code *error_code = data; |
618 | int start = offset; |
619 | int length = strlen(error_code->reason); |
620 | UCHAR pad[2] = { 0 }; |
621 | UCHAR class = error_code->number / 100; |
622 | UCHAR number = error_code->number % 100; |
623 | |
624 | if (nr_stun_encode_htons(attr_info->type , buflen, buf, &offset) |
625 | || nr_stun_encode_htons(4 + length , buflen, buf, &offset) |
626 | || nr_stun_encode(pad, 2 , buflen, buf, &offset) |
627 | || nr_stun_encode(&class, 1 , buflen, buf, &offset) |
628 | || nr_stun_encode(&number, 1 , buflen, buf, &offset) |
629 | || nr_stun_encode((UCHAR*)error_code->reason, length, buflen, buf, &offset)) |
630 | return R_FAILED10; |
631 | |
632 | *attrlen = offset - start; |
633 | |
634 | return 0; |
635 | } |
636 | |
637 | static int |
638 | nr_stun_attr_codec_error_code_decode(nr_stun_attr_info *attr_info, size_t attrlen, UCHAR *buf, size_t offset, size_t buflen, void *data) |
639 | { |
640 | int _status; |
641 | nr_stun_attr_error_code *result = data; |
642 | UCHAR pad[2]; |
643 | UCHAR class; |
644 | UCHAR number; |
645 | size_t size_reason; |
646 | |
647 | if (nr_stun_decode(2, buf, buflen, &offset, pad) |
648 | || nr_stun_decode(1, buf, buflen, &offset, &class) |
649 | || nr_stun_decode(1, buf, buflen, &offset, &number)) |
650 | ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
651 | |
652 | result->number = (class * 100) + number; |
653 | |
654 | size_reason = attrlen - 4; |
655 | |
656 | /* -1 because the string will be null terminated */ |
657 | if (size_reason > (sizeof(result->reason) - 1)) { |
658 | r_log(NR_LOG_STUN, LOG_WARNING4, "Reason is too large, truncating"); |
659 | /* don't fail, but instead truncate the reason */ |
660 | size_reason = sizeof(result->reason) - 1; |
661 | } |
662 | |
663 | if (nr_stun_decode(size_reason, buf, buflen, &offset, (UCHAR*)result->reason)) |
664 | ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
665 | result->reason[size_reason] = '\0'; |
666 | |
667 | _status=0; |
668 | abort: |
669 | return _status; |
670 | } |
671 | |
672 | nr_stun_attr_codec nr_stun_attr_codec_error_code = { |
673 | "error_code", |
674 | nr_stun_attr_codec_error_code_print, |
675 | nr_stun_attr_codec_error_code_encode, |
676 | nr_stun_attr_codec_error_code_decode |
677 | }; |
678 | |
679 | static int |
680 | nr_stun_attr_codec_fingerprint_print(nr_stun_attr_info *attr_info, char *msg, void *data) |
681 | { |
682 | nr_stun_attr_fingerprint *fingerprint = data; |
683 | r_log(NR_LOG_STUN, LOG_DEBUG7, "%s %s: %08x", msg, attr_info->name, fingerprint->checksum); |
684 | return 0; |
685 | } |
686 | |
687 | static int |
688 | nr_stun_attr_codec_fingerprint_encode(nr_stun_attr_info *attr_info, void *data, size_t offset, size_t buflen, UCHAR *buf, size_t *attrlen) |
689 | { |
690 | UINT4 checksum; |
691 | nr_stun_attr_fingerprint *fingerprint = data; |
692 | nr_stun_message_header *header = (nr_stun_message_header*)buf; |
693 | |
694 | /* the length must include the FINGERPRINT attribute when computing |
695 | * the fingerprint */ |
696 | header->length = ntohs(header->length)__bswap_16 (header->length); |
697 | header->length += 8; /* Fingerprint */ |
698 | header->length = htons(header->length)__bswap_16 (header->length); |
699 | |
700 | if (r_crc32((char*)buf, offset, &checksum)) { |
701 | r_log(NR_LOG_STUN, LOG_WARNING4, "Unable to compute fingerprint"); |
702 | return R_FAILED10; |
703 | } |
704 | |
705 | fingerprint->checksum = checksum ^ 0x5354554e; |
706 | |
707 | r_log(NR_LOG_STUN, LOG_DEBUG7, "Computed FINGERPRINT %08x", fingerprint->checksum); |
708 | |
709 | fingerprint->valid = 1; |
710 | return nr_stun_attr_codec_UINT4.encode(attr_info, &fingerprint->checksum, offset, buflen, buf, attrlen); |
711 | } |
712 | |
713 | static int |
714 | nr_stun_attr_codec_fingerprint_decode(nr_stun_attr_info *attr_info, size_t attrlen, UCHAR *buf, size_t offset, size_t buflen, void *data) |
715 | { |
716 | int r,_status; |
717 | nr_stun_attr_fingerprint *fingerprint = data; |
718 | nr_stun_message_header *header = (nr_stun_message_header*)buf; |
719 | size_t length; |
720 | UINT4 checksum; |
721 | |
722 | if ((r=nr_stun_attr_codec_UINT4.decode(attr_info, attrlen, buf, offset, buflen, &fingerprint->checksum))) |
723 | ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
724 | |
725 | offset -= 4; /* rewind to before the length and type fields */ |
726 | |
727 | /* the length must include the FINGERPRINT attribute when computing |
728 | * the fingerprint */ |
729 | length = offset; /* right before FINGERPRINT */ |
730 | length -= sizeof(*header); /* remove header length */ |
731 | length += 8; /* add length of Fingerprint */ |
732 | header->length = htons(length)__bswap_16 (length); |
733 | |
734 | /* make sure FINGERPRINT is final attribute in message */ |
735 | if (length + sizeof(*header) != buflen) { |
736 | r_log(NR_LOG_STUN, LOG_WARNING4, "Fingerprint is not final attribute in message"); |
737 | ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
738 | } |
739 | |
740 | if (r_crc32((char*)buf, offset, &checksum)) { |
741 | r_log(NR_LOG_STUN, LOG_WARNING4, "Unable to compute fingerprint"); |
742 | ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
743 | } |
744 | |
745 | fingerprint->valid = (fingerprint->checksum == (checksum ^ 0x5354554e)); |
746 | |
747 | r_log(NR_LOG_STUN, LOG_DEBUG7, "Computed FINGERPRINT %08x", (checksum ^ 0x5354554e)); |
748 | if (! fingerprint->valid) |
749 | r_log(NR_LOG_STUN, LOG_WARNING4, "Invalid FINGERPRINT %08x", fingerprint->checksum); |
750 | |
751 | _status=0; |
752 | abort: |
753 | return _status; |
754 | } |
755 | |
756 | nr_stun_attr_codec nr_stun_attr_codec_fingerprint = { |
757 | "fingerprint", |
758 | nr_stun_attr_codec_fingerprint_print, |
759 | nr_stun_attr_codec_fingerprint_encode, |
760 | nr_stun_attr_codec_fingerprint_decode |
761 | }; |
762 | |
763 | static int |
764 | nr_stun_attr_codec_flag_print(nr_stun_attr_info *attr_info, char *msg, void *data) |
765 | { |
766 | r_log(NR_LOG_STUN, LOG_DEBUG7, "%s %s: on", msg, attr_info->name); |
767 | return 0; |
768 | } |
769 | |
770 | static int |
771 | nr_stun_attr_codec_flag_encode(nr_stun_attr_info *attr_info, void *data, size_t offset, size_t buflen, UCHAR *buf, size_t *attrlen) |
772 | { |
773 | int start = offset; |
774 | |
775 | if (nr_stun_encode_htons(attr_info->type , buflen, buf, &offset) |
776 | || nr_stun_encode_htons(0 , buflen, buf, &offset)) |
777 | return R_FAILED10; |
778 | |
779 | *attrlen = offset - start; |
780 | |
781 | return 0; |
782 | } |
783 | |
784 | static int |
785 | nr_stun_attr_codec_flag_decode(nr_stun_attr_info *attr_info, size_t attrlen, UCHAR *buf, size_t offset, size_t buflen, void *data) |
786 | { |
787 | if (attrlen != 0) { |
788 | r_log(NR_LOG_STUN, LOG_WARNING4, "Illegal flag length: %d", attrlen); |
789 | return R_FAILED10; |
790 | } |
791 | |
792 | return 0; |
793 | } |
794 | |
795 | nr_stun_attr_codec nr_stun_attr_codec_flag = { |
796 | "flag", |
797 | nr_stun_attr_codec_flag_print, |
798 | nr_stun_attr_codec_flag_encode, |
799 | nr_stun_attr_codec_flag_decode |
800 | }; |
801 | |
802 | static int |
803 | nr_stun_attr_codec_message_integrity_print(nr_stun_attr_info *attr_info, char *msg, void *data) |
804 | { |
805 | nr_stun_attr_message_integrity *integrity = data; |
806 | r_dump(NR_LOG_STUN, LOG_DEBUG7, attr_info->name, (char*)integrity->hash, sizeof(integrity->hash)); |
807 | return 0; |
808 | } |
809 | |
810 | static int |
811 | nr_stun_compute_message_integrity(UCHAR *buf, int offset, UCHAR *password, int passwordlen, UCHAR *computedHMAC) |
812 | { |
813 | int r,_status; |
814 | UINT2 hold; |
815 | UINT2 length; |
816 | nr_stun_message_header *header; |
817 | |
818 | r_log(NR_LOG_STUN, LOG_DEBUG7, "Computing MESSAGE-INTEGRITY"); |
819 | |
820 | header = (nr_stun_message_header*)buf; |
821 | hold = header->length; |
822 | |
823 | /* adjust the length of the message */ |
824 | length = offset; |
825 | length -= sizeof(*header); |
826 | length += 24; /* for MESSAGE-INTEGRITY attribute */ |
827 | header->length = htons(length)__bswap_16 (length); |
828 | |
829 | if ((r=nr_crypto_hmac_sha1((UCHAR*)password, passwordlen,nr_crypto_vtbl->hmac_sha1((UCHAR*)password,passwordlen,buf ,offset,computedHMAC) |
830 | buf, offset, computedHMAC)nr_crypto_vtbl->hmac_sha1((UCHAR*)password,passwordlen,buf ,offset,computedHMAC))) |
831 | ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
832 | |
833 | r_dump(NR_LOG_STUN, LOG_DEBUG7, "Computed MESSAGE-INTEGRITY ", (char*)computedHMAC, 20); |
834 | |
835 | _status=0; |
836 | abort: |
837 | header->length = hold; |
838 | return _status; |
839 | } |
840 | |
841 | static int |
842 | nr_stun_attr_codec_message_integrity_encode(nr_stun_attr_info *attr_info, void *data, size_t offset, size_t buflen, UCHAR *buf, size_t *attrlen) |
843 | { |
844 | int start = offset; |
845 | nr_stun_attr_message_integrity *integrity = data; |
846 | |
847 | if (nr_stun_compute_message_integrity(buf, offset, integrity->password, integrity->passwordlen, integrity->hash)) |
848 | return R_FAILED10; |
849 | |
850 | if (nr_stun_encode_htons(attr_info->type , buflen, buf, &offset) |
851 | || nr_stun_encode_htons(sizeof(integrity->hash) , buflen, buf, &offset) |
852 | || nr_stun_encode(integrity->hash, sizeof(integrity->hash) , buflen, buf, &offset)) |
853 | return R_FAILED10; |
854 | |
855 | *attrlen = offset - start; |
856 | |
857 | return 0; |
858 | } |
859 | |
860 | static int |
861 | nr_stun_attr_codec_message_integrity_decode(nr_stun_attr_info *attr_info, size_t attrlen, UCHAR *buf, size_t offset, size_t buflen, void *data) |
862 | { |
863 | int _status; |
864 | int start; |
865 | nr_stun_attr_message_integrity *result = data; |
866 | UCHAR computedHMAC[20]; |
867 | |
868 | result->valid = 0; |
869 | |
870 | if (attrlen != 20) { |
871 | r_log(NR_LOG_STUN, LOG_WARNING4, "%s must be 20 bytes, not %d", attr_info->name, attrlen); |
872 | ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
873 | } |
874 | |
875 | start = offset - 4; /* rewind to before the length and type fields */ |
876 | if (start < 0) |
877 | ABORT(R_INTERNAL)do { int _r=3; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
878 | |
879 | if (nr_stun_decode(attrlen, buf, buflen, &offset, result->hash)) |
880 | ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
881 | |
882 | if (result->unknown_user) { |
883 | result->valid = 0; |
884 | } |
885 | else { |
886 | if (nr_stun_compute_message_integrity(buf, start, result->password, result->passwordlen, computedHMAC)) |
887 | ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
888 | |
889 | assert(sizeof(computedHMAC) == sizeof(result->hash))((void) sizeof ((sizeof(computedHMAC) == sizeof(result->hash )) ? 1 : 0), __extension__ ({ if (sizeof(computedHMAC) == sizeof (result->hash)) ; else __assert_fail ("sizeof(computedHMAC) == sizeof(result->hash)" , "/root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_codec.c" , 889, __extension__ __PRETTY_FUNCTION__); })); |
890 | |
891 | result->valid = (memcmp(computedHMAC, result->hash, 20) == 0); |
892 | } |
893 | |
894 | _status=0; |
895 | abort: |
896 | return _status; |
897 | } |
898 | |
899 | nr_stun_attr_codec nr_stun_attr_codec_message_integrity = { |
900 | "message_integrity", |
901 | nr_stun_attr_codec_message_integrity_print, |
902 | nr_stun_attr_codec_message_integrity_encode, |
903 | nr_stun_attr_codec_message_integrity_decode |
904 | }; |
905 | |
906 | static int |
907 | nr_stun_attr_codec_noop_decode(nr_stun_attr_info *attr_info, size_t attrlen, UCHAR *buf, size_t offset, size_t buflen, void *data) |
908 | { |
909 | return SKIP_ATTRIBUTE_DECODE-1; |
910 | } |
911 | |
912 | nr_stun_attr_codec nr_stun_attr_codec_noop = { |
913 | "NOOP", |
914 | 0, /* ignore, never print these attributes */ |
915 | 0, /* ignore, never encode these attributes */ |
916 | nr_stun_attr_codec_noop_decode |
917 | }; |
918 | |
919 | static int |
920 | nr_stun_attr_codec_quoted_string_print(nr_stun_attr_info *attr_info, char *msg, void *data) |
921 | { |
922 | r_log(NR_LOG_STUN, LOG_DEBUG7, "%s %s: %s", |
923 | msg, attr_info->name, (char*)data); |
924 | return 0; |
925 | } |
926 | |
927 | static int |
928 | nr_stun_attr_codec_quoted_string_encode(nr_stun_attr_info *attr_info, void *data, size_t offset, size_t buflen, UCHAR *buf, size_t *attrlen) |
929 | { |
930 | //TODO: !nn! syntax check, conversion if not quoted already? |
931 | //We'll just restrict this in the API -- EKR |
932 | return nr_stun_attr_codec_string.encode(attr_info, data, offset, buflen, buf, attrlen); |
933 | } |
934 | |
935 | static int |
936 | nr_stun_attr_codec_quoted_string_decode(nr_stun_attr_info *attr_info, size_t attrlen, UCHAR *buf, size_t offset, size_t buflen, void *data) |
937 | { |
938 | //TODO: !nn! I don't see any need to unquote this but we may |
939 | //find one later -- EKR |
940 | return nr_stun_attr_codec_string.decode(attr_info, attrlen, buf, offset, buflen, data); |
941 | } |
942 | |
943 | nr_stun_attr_codec nr_stun_attr_codec_quoted_string = { |
944 | "quoted_string", |
945 | nr_stun_attr_codec_quoted_string_print, |
946 | nr_stun_attr_codec_quoted_string_encode, |
947 | nr_stun_attr_codec_quoted_string_decode |
948 | }; |
949 | |
950 | static int |
951 | nr_stun_attr_codec_string_print(nr_stun_attr_info *attr_info, char *msg, void *data) |
952 | { |
953 | r_log(NR_LOG_STUN, LOG_DEBUG7, "%s %s: %s", |
954 | msg, attr_info->name, (char*)data); |
955 | return 0; |
956 | } |
957 | |
958 | static int |
959 | nr_stun_attr_codec_string_encode(nr_stun_attr_info *attr_info, void *data, size_t offset, size_t buflen, UCHAR *buf, size_t *attrlen) |
960 | { |
961 | int start = offset; |
962 | char *str = data; |
963 | int length = strlen(str); |
964 | |
965 | if (nr_stun_encode_htons(attr_info->type , buflen, buf, &offset) |
966 | || nr_stun_encode_htons(length , buflen, buf, &offset) |
967 | || nr_stun_encode((UCHAR*)str, length , buflen, buf, &offset)) |
968 | return R_FAILED10; |
969 | |
970 | *attrlen = offset - start; |
971 | |
972 | return 0; |
973 | } |
974 | |
975 | static int |
976 | nr_stun_attr_codec_string_decode(nr_stun_attr_info *attr_info, size_t attrlen, UCHAR *buf, size_t offset, size_t buflen, void *data) |
977 | { |
978 | int _status; |
979 | char *result = data; |
980 | |
981 | /* actual enforcement of the specific string size happens elsewhere */ |
982 | if (attrlen >= NR_STUN_MAX_STRING_SIZE763) { |
983 | r_log(NR_LOG_STUN, LOG_WARNING4, "String is too large: %d bytes", attrlen); |
984 | ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
985 | } |
986 | |
987 | if (nr_stun_decode(attrlen, buf, buflen, &offset, (UCHAR*)result)) |
988 | ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
989 | result[attrlen] = '\0'; /* just to be nice */ |
990 | |
991 | if (strlen(result) != attrlen) { |
992 | /* stund 0.96 sends a final null in the Server attribute, so |
993 | * only error if the null appears anywhere else in a string */ |
994 | if (strlen(result) != attrlen-1) { |
995 | r_log(NR_LOG_STUN, LOG_WARNING4, "Error in string: %zd/%d", strlen(result), attrlen); |
996 | ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
997 | } |
998 | } |
999 | |
1000 | _status = 0; |
1001 | abort: |
1002 | return _status; |
1003 | } |
1004 | |
1005 | nr_stun_attr_codec nr_stun_attr_codec_string = { |
1006 | "string", |
1007 | nr_stun_attr_codec_string_print, |
1008 | nr_stun_attr_codec_string_encode, |
1009 | nr_stun_attr_codec_string_decode |
1010 | }; |
1011 | |
1012 | static int |
1013 | nr_stun_attr_codec_unknown_attributes_print(nr_stun_attr_info *attr_info, char *msg, void *data) |
1014 | { |
1015 | nr_stun_attr_unknown_attributes *unknown_attributes = data; |
1016 | char type[9]; |
1017 | char str[64 + (NR_STUN_MAX_UNKNOWN_ATTRIBUTES16 * sizeof(type))]; |
1018 | int i; |
1019 | |
1020 | snprintf(str, sizeof(str), "%s %s:", msg, attr_info->name); |
1021 | for (i = 0; i < unknown_attributes->num_attributes; ++i) { |
1022 | snprintf(type, sizeof(type), "%s 0x%04x", ((i>0)?",":""), unknown_attributes->attribute[i]); |
1023 | strlcat(str, type, sizeof(str)); |
1024 | } |
1025 | |
1026 | r_log(NR_LOG_STUN, LOG_DEBUG7, "%s", str); |
1027 | return 0; |
1028 | } |
1029 | |
1030 | static int |
1031 | nr_stun_attr_codec_unknown_attributes_encode(nr_stun_attr_info *attr_info, void *data, size_t offset, size_t buflen, UCHAR *buf, size_t *attrlen) |
1032 | { |
1033 | int _status; |
1034 | int start = offset; |
1035 | nr_stun_attr_unknown_attributes *unknown_attributes = data; |
1036 | int length = (2 * unknown_attributes->num_attributes); |
1037 | int i; |
1038 | |
1039 | if (unknown_attributes->num_attributes > NR_STUN_MAX_UNKNOWN_ATTRIBUTES16) { |
1040 | r_log(NR_LOG_STUN, LOG_WARNING4, "Too many UNKNOWN-ATTRIBUTES: %d", unknown_attributes->num_attributes); |
1041 | ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
1042 | } |
1043 | |
1044 | if (nr_stun_encode_htons(attr_info->type , buflen, buf, &offset) |
1045 | || nr_stun_encode_htons(length , buflen, buf, &offset)) |
1046 | ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
1047 | |
1048 | for (i = 0; i < unknown_attributes->num_attributes; ++i) { |
1049 | if (nr_stun_encode_htons(unknown_attributes->attribute[i], buflen, buf, &offset)) |
1050 | ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
1051 | } |
1052 | |
1053 | *attrlen = offset - start; |
1054 | |
1055 | _status = 0; |
1056 | abort: |
1057 | return _status; |
1058 | } |
1059 | |
1060 | static int |
1061 | nr_stun_attr_codec_unknown_attributes_decode(nr_stun_attr_info *attr_info, size_t attrlen, UCHAR *buf, size_t offset, size_t buflen, void *data) |
1062 | { |
1063 | int _status; |
1064 | nr_stun_attr_unknown_attributes *unknown_attributes = data; |
1065 | int i; |
1066 | UINT2 *a; |
1067 | |
1068 | if ((attrlen % 4) != 0) { |
1069 | r_log(NR_LOG_STUN, LOG_WARNING4, "Attribute is illegal size: %d", attrlen); |
1070 | ABORT(R_REJECTED)do { int _r=11; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
1071 | } |
1072 | |
1073 | unknown_attributes->num_attributes = attrlen / 2; |
1074 | |
1075 | if (unknown_attributes->num_attributes > NR_STUN_MAX_UNKNOWN_ATTRIBUTES16) { |
1076 | r_log(NR_LOG_STUN, LOG_WARNING4, "Too many UNKNOWN-ATTRIBUTES: %d", unknown_attributes->num_attributes); |
1077 | ABORT(R_REJECTED)do { int _r=11; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
1078 | } |
1079 | |
1080 | for (i = 0; i < unknown_attributes->num_attributes; ++i) { |
1081 | a = &(unknown_attributes->attribute[i]); |
1082 | if (nr_stun_decode_htons(buf, buflen, &offset, a)) |
1083 | return R_FAILED10; |
1084 | } |
1085 | |
1086 | _status = 0; |
1087 | abort: |
1088 | return _status; |
1089 | } |
1090 | |
1091 | nr_stun_attr_codec nr_stun_attr_codec_unknown_attributes = { |
1092 | "unknown_attributes", |
1093 | nr_stun_attr_codec_unknown_attributes_print, |
1094 | nr_stun_attr_codec_unknown_attributes_encode, |
1095 | nr_stun_attr_codec_unknown_attributes_decode |
1096 | }; |
1097 | |
1098 | static int |
1099 | nr_stun_attr_codec_xor_mapped_address_print(nr_stun_attr_info *attr_info, char *msg, void *data) |
1100 | { |
1101 | nr_stun_attr_xor_mapped_address *xor_mapped_address = data; |
1102 | r_log(NR_LOG_STUN, LOG_DEBUG7, "%s %s: %s (unmasked) %s (masked)", |
1103 | msg, attr_info->name, |
1104 | xor_mapped_address->unmasked.as_string, |
1105 | xor_mapped_address->masked.as_string); |
1106 | return 0; |
1107 | } |
1108 | |
1109 | static int |
1110 | nr_stun_attr_codec_xor_mapped_address_encode(nr_stun_attr_info *attr_info, void *data, size_t offset, size_t buflen, UCHAR *buf, size_t *attrlen) |
1111 | { |
1112 | nr_stun_attr_xor_mapped_address *xor_mapped_address = data; |
1113 | nr_stun_message_header *header = (nr_stun_message_header*)buf; |
1114 | UINT4 magic_cookie; |
1115 | |
1116 | r_log(NR_LOG_STUN, LOG_DEBUG7, "Unmasked XOR-MAPPED-ADDRESS = %s", xor_mapped_address->unmasked.as_string); |
1117 | |
1118 | /* this needs to be the magic cookie in the header and not |
1119 | * the MAGIC_COOKIE constant because if we're talking to |
1120 | * older servers (that don't have a magic cookie) they use |
1121 | * message ID for this */ |
1122 | magic_cookie = ntohl(header->magic_cookie)__bswap_32 (header->magic_cookie); |
1123 | |
1124 | nr_stun_xor_mapped_address(magic_cookie, header->id, &xor_mapped_address->unmasked, &xor_mapped_address->masked); |
1125 | |
1126 | r_log(NR_LOG_STUN, LOG_DEBUG7, "Masked XOR-MAPPED-ADDRESS = %s", xor_mapped_address->masked.as_string); |
1127 | |
1128 | if (nr_stun_attr_codec_addr.encode(attr_info, &xor_mapped_address->masked, offset, buflen, buf, attrlen)) |
1129 | return R_FAILED10; |
1130 | |
1131 | return 0; |
1132 | } |
1133 | |
1134 | static int |
1135 | nr_stun_attr_codec_xor_mapped_address_decode(nr_stun_attr_info *attr_info, size_t attrlen, UCHAR *buf, size_t offset, size_t buflen, void *data) |
1136 | { |
1137 | int r,_status; |
1138 | nr_stun_attr_xor_mapped_address *xor_mapped_address = data; |
1139 | nr_stun_message_header *header = (nr_stun_message_header*)buf; |
1140 | UINT4 magic_cookie; |
1141 | |
1142 | if ((r=nr_stun_attr_codec_addr.decode(attr_info, attrlen, buf, offset, buflen, &xor_mapped_address->masked))) |
1143 | ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
1144 | |
1145 | r_log(NR_LOG_STUN, LOG_DEBUG7, "Masked XOR-MAPPED-ADDRESS = %s", xor_mapped_address->masked.as_string); |
1146 | |
1147 | /* this needs to be the magic cookie in the header and not |
1148 | * the MAGIC_COOKIE constant because if we're talking to |
1149 | * older servers (that don't have a magic cookie) they use |
1150 | * message ID for this */ |
1151 | magic_cookie = ntohl(header->magic_cookie)__bswap_32 (header->magic_cookie); |
1152 | |
1153 | nr_stun_xor_mapped_address(magic_cookie, header->id, &xor_mapped_address->masked, &xor_mapped_address->unmasked); |
1154 | |
1155 | r_log(NR_LOG_STUN, LOG_DEBUG7, "Unmasked XOR-MAPPED-ADDRESS = %s", xor_mapped_address->unmasked.as_string); |
1156 | |
1157 | _status = 0; |
1158 | abort: |
1159 | return _status; |
1160 | } |
1161 | |
1162 | nr_stun_attr_codec nr_stun_attr_codec_xor_mapped_address = { |
1163 | "xor_mapped_address", |
1164 | nr_stun_attr_codec_xor_mapped_address_print, |
1165 | nr_stun_attr_codec_xor_mapped_address_encode, |
1166 | nr_stun_attr_codec_xor_mapped_address_decode |
1167 | }; |
1168 | |
1169 | nr_stun_attr_codec nr_stun_attr_codec_old_xor_mapped_address = { |
1170 | "xor_mapped_address", |
1171 | nr_stun_attr_codec_xor_mapped_address_print, |
1172 | 0, /* never encode this type */ |
1173 | nr_stun_attr_codec_xor_mapped_address_decode |
1174 | }; |
1175 | |
1176 | nr_stun_attr_codec nr_stun_attr_codec_xor_peer_address = { |
1177 | "xor_peer_address", |
1178 | nr_stun_attr_codec_xor_mapped_address_print, |
1179 | nr_stun_attr_codec_xor_mapped_address_encode, |
1180 | nr_stun_attr_codec_xor_mapped_address_decode |
1181 | }; |
1182 | |
1183 | #define NR_ADD_STUN_ATTRIBUTE(type, name, codec, illegal){ (type), (name), &(codec), illegal }, \ |
1184 | { (type), (name), &(codec), illegal }, |
1185 | |
1186 | #define NR_ADD_STUN_ATTRIBUTE_IGNORE(type, name){ (type), (name), &nr_stun_attr_codec_noop, 0 }, \ |
1187 | { (type), (name), &nr_stun_attr_codec_noop, 0 }, |
1188 | |
1189 | |
1190 | static nr_stun_attr_info attrs[] = { |
1191 | NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_ALTERNATE_SERVER, "ALTERNATE-SERVER", nr_stun_attr_codec_addr, 0){ (0x8023), ("ALTERNATE-SERVER"), &(nr_stun_attr_codec_addr ), 0 }, |
1192 | #ifdef USE_STUND_0_961 |
1193 | NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_OLD_CHANGE_REQUEST, "CHANGE-REQUEST", nr_stun_attr_codec_UINT4, 0){ (0x0003), ("CHANGE-REQUEST"), &(nr_stun_attr_codec_UINT4 ), 0 }, |
1194 | #endif |
1195 | NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_ERROR_CODE, "ERROR-CODE", nr_stun_attr_codec_error_code, nr_stun_attr_error_code_illegal){ (0x0009), ("ERROR-CODE"), &(nr_stun_attr_codec_error_code ), nr_stun_attr_error_code_illegal }, |
1196 | NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_FINGERPRINT, "FINGERPRINT", nr_stun_attr_codec_fingerprint, 0){ (0x8028), ("FINGERPRINT"), &(nr_stun_attr_codec_fingerprint ), 0 }, |
1197 | NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_MAPPED_ADDRESS, "MAPPED-ADDRESS", nr_stun_attr_codec_addr, 0){ (0x0001), ("MAPPED-ADDRESS"), &(nr_stun_attr_codec_addr ), 0 }, |
1198 | NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_MESSAGE_INTEGRITY, "MESSAGE-INTEGRITY", nr_stun_attr_codec_message_integrity, 0){ (0x0008), ("MESSAGE-INTEGRITY"), &(nr_stun_attr_codec_message_integrity ), 0 }, |
1199 | NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_NONCE, "NONCE", nr_stun_attr_codec_quoted_string, nr_stun_attr_nonce_illegal){ (0x0015), ("NONCE"), &(nr_stun_attr_codec_quoted_string ), nr_stun_attr_nonce_illegal }, |
1200 | NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_REALM, "REALM", nr_stun_attr_codec_quoted_string, nr_stun_attr_realm_illegal){ (0x0014), ("REALM"), &(nr_stun_attr_codec_quoted_string ), nr_stun_attr_realm_illegal }, |
1201 | NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_SERVER, "SERVER", nr_stun_attr_codec_string, nr_stun_attr_server_illegal){ (0x8022), ("SERVER"), &(nr_stun_attr_codec_string), nr_stun_attr_server_illegal }, |
1202 | NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_UNKNOWN_ATTRIBUTES, "UNKNOWN-ATTRIBUTES", nr_stun_attr_codec_unknown_attributes, 0){ (0x000A), ("UNKNOWN-ATTRIBUTES"), &(nr_stun_attr_codec_unknown_attributes ), 0 }, |
1203 | NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_USERNAME, "USERNAME", nr_stun_attr_codec_string, nr_stun_attr_username_illegal){ (0x0006), ("USERNAME"), &(nr_stun_attr_codec_string), nr_stun_attr_username_illegal }, |
1204 | NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_XOR_MAPPED_ADDRESS, "XOR-MAPPED-ADDRESS", nr_stun_attr_codec_xor_mapped_address, 0){ (0x0020), ("XOR-MAPPED-ADDRESS"), &(nr_stun_attr_codec_xor_mapped_address ), 0 }, |
1205 | |
1206 | #ifdef USE_ICE1 |
1207 | NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_ICE_CONTROLLED, "ICE-CONTROLLED", nr_stun_attr_codec_UINT8, 0){ (0x8029), ("ICE-CONTROLLED"), &(nr_stun_attr_codec_UINT8 ), 0 }, |
1208 | NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_ICE_CONTROLLING, "ICE-CONTROLLING", nr_stun_attr_codec_UINT8, 0){ (0x802A), ("ICE-CONTROLLING"), &(nr_stun_attr_codec_UINT8 ), 0 }, |
1209 | NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_PRIORITY, "PRIORITY", nr_stun_attr_codec_UINT4, 0){ (0x0024), ("PRIORITY"), &(nr_stun_attr_codec_UINT4), 0 } , |
1210 | NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_USE_CANDIDATE, "USE-CANDIDATE", nr_stun_attr_codec_flag, 0){ (0x0025), ("USE-CANDIDATE"), &(nr_stun_attr_codec_flag) , 0 }, |
1211 | #endif |
1212 | |
1213 | #ifdef USE_TURN1 |
1214 | NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_DATA, "DATA", nr_stun_attr_codec_data, 0){ (0x0013), ("DATA"), &(nr_stun_attr_codec_data), 0 }, |
1215 | NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_LIFETIME, "LIFETIME", nr_stun_attr_codec_UINT4, 0){ (0x000d), ("LIFETIME"), &(nr_stun_attr_codec_UINT4), 0 } , |
1216 | NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_XOR_RELAY_ADDRESS, "XOR-RELAY-ADDRESS", nr_stun_attr_codec_xor_mapped_address, 0){ (0x0016), ("XOR-RELAY-ADDRESS"), &(nr_stun_attr_codec_xor_mapped_address ), 0 }, |
1217 | NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_XOR_PEER_ADDRESS, "XOR-PEER-ADDRESS", nr_stun_attr_codec_xor_peer_address, 0){ (0x0012), ("XOR-PEER-ADDRESS"), &(nr_stun_attr_codec_xor_peer_address ), 0 }, |
1218 | NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_REQUESTED_TRANSPORT, "REQUESTED-TRANSPORT", nr_stun_attr_codec_UCHAR, 0){ (0x0019), ("REQUESTED-TRANSPORT"), &(nr_stun_attr_codec_UCHAR ), 0 }, |
1219 | NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_BANDWIDTH, "BANDWIDTH", nr_stun_attr_codec_UINT4, 0){ (0x0010), ("BANDWIDTH"), &(nr_stun_attr_codec_UINT4), 0 }, |
1220 | #endif /* USE_TURN */ |
1221 | |
1222 | /* for backwards compatibilty */ |
1223 | NR_ADD_STUN_ATTRIBUTE(NR_STUN_ATTR_OLD_XOR_MAPPED_ADDRESS, "Old XOR-MAPPED-ADDRESS", nr_stun_attr_codec_old_xor_mapped_address, 0){ (0x8020), ("Old XOR-MAPPED-ADDRESS"), &(nr_stun_attr_codec_old_xor_mapped_address ), 0 }, |
1224 | #ifdef USE_RFC_3489_BACKWARDS_COMPATIBLE1 |
1225 | NR_ADD_STUN_ATTRIBUTE_IGNORE(NR_STUN_ATTR_OLD_RESPONSE_ADDRESS, "RESPONSE-ADDRESS"){ (0x0002), ("RESPONSE-ADDRESS"), &nr_stun_attr_codec_noop , 0 }, |
1226 | NR_ADD_STUN_ATTRIBUTE_IGNORE(NR_STUN_ATTR_OLD_SOURCE_ADDRESS, "SOURCE-ADDRESS"){ (0x0004), ("SOURCE-ADDRESS"), &nr_stun_attr_codec_noop, 0 }, |
1227 | NR_ADD_STUN_ATTRIBUTE_IGNORE(NR_STUN_ATTR_OLD_CHANGED_ADDRESS, "CHANGED-ADDRESS"){ (0x0005), ("CHANGED-ADDRESS"), &nr_stun_attr_codec_noop , 0 }, |
1228 | NR_ADD_STUN_ATTRIBUTE_IGNORE(NR_STUN_ATTR_OLD_PASSWORD, "PASSWORD"){ (0x0007), ("PASSWORD"), &nr_stun_attr_codec_noop, 0 }, |
1229 | #endif /* USE_RFC_3489_BACKWARDS_COMPATIBLE */ |
1230 | }; |
1231 | |
1232 | |
1233 | int |
1234 | nr_stun_find_attr_info(UINT2 type, nr_stun_attr_info **info) |
1235 | { |
1236 | int _status; |
1237 | size_t i; |
1238 | |
1239 | *info = 0; |
1240 | for (i = 0; i < sizeof(attrs)/sizeof(*attrs); ++i) { |
1241 | if (type == attrs[i].type) { |
1242 | *info = &attrs[i]; |
1243 | break; |
1244 | } |
1245 | } |
1246 | |
1247 | if (*info == 0) |
1248 | ABORT(R_NOT_FOUND)do { int _r=2; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
1249 | |
1250 | _status=0; |
1251 | abort: |
1252 | return(_status); |
1253 | } |
1254 | |
1255 | int |
1256 | nr_stun_fix_attribute_ordering(nr_stun_message *msg) |
1257 | { |
1258 | nr_stun_message_attribute *message_integrity; |
1259 | nr_stun_message_attribute *fingerprint; |
1260 | |
1261 | /* 2nd to the last */ |
1262 | if (nr_stun_message_has_attribute(msg, NR_STUN_ATTR_MESSAGE_INTEGRITY0x0008, &message_integrity)) { |
1263 | TAILQ_REMOVE(&msg->attributes, message_integrity, entry)do { if (((((message_integrity))->entry.tqe_next)) != ((void *)0)) (((message_integrity))->entry.tqe_next)->entry.tqe_prev = (message_integrity)->entry.tqe_prev; else { (&msg-> attributes)->tqh_last = (message_integrity)->entry.tqe_prev ; ; } *(message_integrity)->entry.tqe_prev = (((message_integrity ))->entry.tqe_next); ; ; ; } while (0); |
1264 | TAILQ_INSERT_TAIL(&msg->attributes, message_integrity, entry)do { (((message_integrity))->entry.tqe_next) = ((void*)0); (message_integrity)->entry.tqe_prev = (&msg->attributes )->tqh_last; *(&msg->attributes)->tqh_last = (message_integrity ); (&msg->attributes)->tqh_last = &(((message_integrity ))->entry.tqe_next); ; ; } while (0); |
1265 | } |
1266 | |
1267 | /* last */ |
1268 | if (nr_stun_message_has_attribute(msg, NR_STUN_ATTR_FINGERPRINT0x8028, &fingerprint)) { |
1269 | TAILQ_REMOVE(&msg->attributes, fingerprint, entry)do { if (((((fingerprint))->entry.tqe_next)) != ((void*)0) ) (((fingerprint))->entry.tqe_next)->entry.tqe_prev = ( fingerprint)->entry.tqe_prev; else { (&msg->attributes )->tqh_last = (fingerprint)->entry.tqe_prev; ; } *(fingerprint )->entry.tqe_prev = (((fingerprint))->entry.tqe_next); ; ; ; } while (0); |
1270 | TAILQ_INSERT_TAIL(&msg->attributes, fingerprint, entry)do { (((fingerprint))->entry.tqe_next) = ((void*)0); (fingerprint )->entry.tqe_prev = (&msg->attributes)->tqh_last ; *(&msg->attributes)->tqh_last = (fingerprint); (& msg->attributes)->tqh_last = &(((fingerprint))-> entry.tqe_next); ; ; } while (0); |
1271 | } |
1272 | |
1273 | return 0; |
1274 | } |
1275 | |
1276 | // Since this sanity check is only a collection of assert statements and those |
1277 | // assert statements are compiled out in non-debug builds, undef SANITY_CHECKS |
1278 | // so we can avoid the warning that padding_bytes is never used in opt builds. |
1279 | #ifdef NDEBUG |
1280 | #undef SANITY_CHECKS1 |
1281 | #endif |
1282 | |
1283 | #ifdef SANITY_CHECKS1 |
1284 | static void sanity_check_encoding_stuff(nr_stun_message *msg) |
1285 | { |
1286 | nr_stun_message_attribute *attr = 0; |
1287 | int padding_bytes; |
1288 | int l; |
1289 | |
1290 | r_log(NR_LOG_STUN, LOG_DEBUG7, "Starting to sanity check encoding"); |
1291 | |
1292 | l = 0; |
1293 | TAILQ_FOREACH(attr, &msg->attributes, entry)for ((attr) = (((&msg->attributes))->tqh_first); (attr ); (attr) = (((attr))->entry.tqe_next)) { |
1294 | padding_bytes = 0; |
1295 | if ((attr->length % 4) != 0) { |
1296 | padding_bytes = 4 - (attr->length % 4); |
1297 | } |
1298 | assert(attr->length == (attr->encoding_length - (4 + padding_bytes)))((void) sizeof ((attr->length == (attr->encoding_length - (4 + padding_bytes))) ? 1 : 0), __extension__ ({ if (attr-> length == (attr->encoding_length - (4 + padding_bytes))) ; else __assert_fail ("attr->length == (attr->encoding_length - (4 + padding_bytes))" , "/root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_codec.c" , 1298, __extension__ __PRETTY_FUNCTION__); })); |
1299 | assert(((void*)attr->encoding) == (msg->buffer + 20 + l))((void) sizeof ((((void*)attr->encoding) == (msg->buffer + 20 + l)) ? 1 : 0), __extension__ ({ if (((void*)attr->encoding ) == (msg->buffer + 20 + l)) ; else __assert_fail ("((void*)attr->encoding) == (msg->buffer + 20 + l)" , "/root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_codec.c" , 1299, __extension__ __PRETTY_FUNCTION__); })); |
1300 | l += attr->encoding_length; |
1301 | assert((l % 4) == 0)((void) sizeof (((l % 4) == 0) ? 1 : 0), __extension__ ({ if ( (l % 4) == 0) ; else __assert_fail ("(l % 4) == 0", "/root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_codec.c" , 1301, __extension__ __PRETTY_FUNCTION__); })); |
1302 | } |
1303 | assert(l == msg->header.length)((void) sizeof ((l == msg->header.length) ? 1 : 0), __extension__ ({ if (l == msg->header.length) ; else __assert_fail ("l == msg->header.length" , "/root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_codec.c" , 1303, __extension__ __PRETTY_FUNCTION__); })); |
1304 | } |
1305 | #endif /* SANITY_CHECKS */ |
1306 | |
1307 | |
1308 | int |
1309 | nr_stun_encode_message(nr_stun_message *msg) |
1310 | { |
1311 | int r,_status; |
1312 | size_t length_offset; |
1313 | size_t length_offset_hold; |
1314 | nr_stun_attr_info *attr_info; |
1315 | nr_stun_message_attribute *attr; |
1316 | int padding_bytes; |
1317 | |
1318 | r_log(NR_LOG_STUN, LOG_DEBUG7, "Encoding STUN message"); |
1319 | |
1320 | nr_stun_fix_attribute_ordering(msg); |
1321 | |
1322 | msg->name = nr_stun_msg_type(msg->header.type); |
1323 | msg->length = 0; |
1324 | msg->header.length = 0; |
1325 | |
1326 | if ((r=nr_stun_encode_htons(msg->header.type, sizeof(msg->buffer), msg->buffer, &msg->length))) |
1327 | ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
1328 | if (msg->name) |
1329 | r_log(NR_LOG_STUN, LOG_DEBUG7, "Encoded MsgType: %s", msg->name); |
1330 | else |
1331 | r_log(NR_LOG_STUN, LOG_DEBUG7, "Encoded MsgType: 0x%03x", msg->header.type); |
1332 | |
1333 | /* grab the offset to be used later to re-write the header length field */ |
1334 | length_offset_hold = msg->length; |
1335 | |
1336 | if ((r=nr_stun_encode_htons(msg->header.length, sizeof(msg->buffer), msg->buffer, &msg->length))) |
1337 | ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
1338 | |
1339 | if ((r=nr_stun_encode_htonl(msg->header.magic_cookie, sizeof(msg->buffer), msg->buffer, &msg->length))) |
1340 | ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
1341 | r_log(NR_LOG_STUN, LOG_DEBUG7, "Encoded Cookie: %08x", msg->header.magic_cookie); |
1342 | |
1343 | if ((r=nr_stun_encode((UCHAR*)(&msg->header.id), sizeof(msg->header.id), sizeof(msg->buffer), msg->buffer, &msg->length))) |
1344 | ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
1345 | r_dump(NR_LOG_STUN, LOG_DEBUG7, "Encoded ID", (void*)&msg->header.id, sizeof(msg->header.id)); |
1346 | |
1347 | TAILQ_FOREACH(attr, &msg->attributes, entry)for ((attr) = (((&msg->attributes))->tqh_first); (attr ); (attr) = (((attr))->entry.tqe_next)) { |
1348 | if ((r=nr_stun_find_attr_info(attr->type, &attr_info))) { |
Although the value stored to 'r' is used in the enclosing expression, the value is never actually read from 'r' | |
1349 | r_log(NR_LOG_STUN, LOG_WARNING4, "Unrecognized attribute: 0x%04x", attr->type); |
1350 | ABORT(R_INTERNAL)do { int _r=3; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
1351 | } |
1352 | |
1353 | attr->name = attr_info->name; |
1354 | attr->type_name = attr_info->codec->name; |
1355 | attr->encoding = (nr_stun_encoded_attribute*)&msg->buffer[msg->length]; |
1356 | |
1357 | if (attr_info->codec->encode != 0) { |
1358 | if ((r=attr_info->codec->encode(attr_info, &attr->u, msg->length, sizeof(msg->buffer), msg->buffer, &attr->encoding_length))) { |
1359 | r_log(NR_LOG_STUN, LOG_WARNING4, "Unable to encode %s", attr_info->name); |
1360 | ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
1361 | } |
1362 | |
1363 | msg->length += attr->encoding_length; |
1364 | attr->length = attr->encoding_length - 4; /* -4 for type and length fields */ |
1365 | |
1366 | if (attr_info->illegal) { |
1367 | if ((r=attr_info->illegal(attr_info, attr->length, &attr->u))) |
1368 | ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
1369 | } |
1370 | |
1371 | attr_info->codec->print(attr_info, "Encoded", &attr->u); |
1372 | |
1373 | if ((attr->length % 4) == 0) { |
1374 | padding_bytes = 0; |
1375 | } |
1376 | else { |
1377 | padding_bytes = 4 - (attr->length % 4); |
1378 | nr_stun_encode((UCHAR*)"\0\0\0\0", padding_bytes, sizeof(msg->buffer), msg->buffer, &msg->length); |
1379 | attr->encoding_length += padding_bytes; |
1380 | } |
1381 | |
1382 | msg->header.length += attr->encoding_length; |
1383 | length_offset = length_offset_hold; |
1384 | (void)nr_stun_encode_htons(msg->header.length, sizeof(msg->buffer), msg->buffer, &length_offset); |
1385 | } |
1386 | else { |
1387 | r_log(NR_LOG_STUN, LOG_WARNING4, "Missing encode function for attribute: %s", attr_info->name); |
1388 | } |
1389 | } |
1390 | |
1391 | r_log(NR_LOG_STUN, LOG_DEBUG7, "Encoded Length: %d", msg->header.length); |
1392 | |
1393 | assert(msg->length < NR_STUN_MAX_MESSAGE_SIZE)((void) sizeof ((msg->length < 2048) ? 1 : 0), __extension__ ({ if (msg->length < 2048) ; else __assert_fail ("msg->length < NR_STUN_MAX_MESSAGE_SIZE" , "/root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_codec.c" , 1393, __extension__ __PRETTY_FUNCTION__); })); |
1394 | |
1395 | #ifdef SANITY_CHECKS1 |
1396 | sanity_check_encoding_stuff(msg); |
1397 | #endif /* SANITY_CHECKS */ |
1398 | |
1399 | _status=0; |
1400 | abort: |
1401 | return _status; |
1402 | } |
1403 | |
1404 | int |
1405 | nr_stun_decode_message(nr_stun_message *msg, int (*get_password)(void *arg, nr_stun_message *msg, Data **password), void *arg) |
1406 | { |
1407 | int r,_status; |
1408 | int offset; |
1409 | int size; |
1410 | int padding_bytes; |
1411 | nr_stun_message_attribute *attr; |
1412 | nr_stun_attr_info *attr_info; |
1413 | Data *password; |
1414 | |
1415 | r_log(NR_LOG_STUN, LOG_DEBUG7, "Parsing STUN message of %d bytes", msg->length); |
1416 | |
1417 | if (!TAILQ_EMPTY(&msg->attributes)((&msg->attributes)->tqh_first == ((void*)0))) |
1418 | ABORT(R_BAD_ARGS)do { int _r=6; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
1419 | |
1420 | if (sizeof(nr_stun_message_header) > msg->length) { |
1421 | r_log(NR_LOG_STUN, LOG_WARNING4, "Message too small"); |
1422 | ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
1423 | } |
1424 | |
1425 | memcpy(&msg->header, msg->buffer, sizeof(msg->header)); |
1426 | msg->header.type = ntohs(msg->header.type)__bswap_16 (msg->header.type); |
1427 | msg->header.length = ntohs(msg->header.length)__bswap_16 (msg->header.length); |
1428 | msg->header.magic_cookie = ntohl(msg->header.magic_cookie)__bswap_32 (msg->header.magic_cookie); |
1429 | |
1430 | msg->name = nr_stun_msg_type(msg->header.type); |
1431 | |
1432 | if (msg->name) |
1433 | r_log(NR_LOG_STUN, LOG_DEBUG7, "Parsed MsgType: %s", msg->name); |
1434 | else |
1435 | r_log(NR_LOG_STUN, LOG_DEBUG7, "Parsed MsgType: 0x%03x", msg->header.type); |
1436 | r_log(NR_LOG_STUN, LOG_DEBUG7, "Parsed Length: %d", msg->header.length); |
1437 | r_log(NR_LOG_STUN, LOG_DEBUG7, "Parsed Cookie: %08x", msg->header.magic_cookie); |
1438 | r_dump(NR_LOG_STUN, LOG_DEBUG7, "Parsed ID", (void*)&msg->header.id, sizeof(msg->header.id)); |
1439 | |
1440 | if (msg->header.length + sizeof(msg->header) != msg->length) { |
1441 | r_log(NR_LOG_STUN, LOG_WARNING4, "Inconsistent message header length: %d/%d", |
1442 | msg->header.length, msg->length); |
1443 | ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
1444 | } |
1445 | |
1446 | size = msg->header.length; |
1447 | |
1448 | if ((size % 4) != 0) { |
1449 | r_log(NR_LOG_STUN, LOG_WARNING4, "Illegal message size: %d", msg->header.length); |
1450 | ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
1451 | } |
1452 | |
1453 | offset = sizeof(msg->header); |
1454 | |
1455 | while (size > 0) { |
1456 | r_log(NR_LOG_STUN, LOG_DEBUG7, "size = %d", size); |
1457 | |
1458 | if (size < 4) { |
1459 | r_log(NR_LOG_STUN, LOG_WARNING4, "Illegal message length: %d", size); |
1460 | ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
1461 | } |
1462 | |
1463 | if ((r=nr_stun_message_attribute_create(msg, &attr))) |
1464 | ABORT(R_NO_MEMORY)do { int _r=1; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
1465 | |
1466 | attr->encoding = (nr_stun_encoded_attribute*)&msg->buffer[offset]; |
1467 | attr->type = ntohs(attr->encoding->type)__bswap_16 (attr->encoding->type); |
1468 | attr->length = ntohs(attr->encoding->length)__bswap_16 (attr->encoding->length); |
1469 | attr->encoding_length = attr->length + 4; |
1470 | |
1471 | if ((attr->length % 4) != 0) { |
1472 | padding_bytes = 4 - (attr->length % 4); |
1473 | attr->encoding_length += padding_bytes; |
1474 | } |
1475 | |
1476 | if ((attr->encoding_length) > (size_t)size) { |
1477 | r_log(NR_LOG_STUN, LOG_WARNING4, "Attribute length larger than remaining message size: %d/%d", attr->encoding_length, size); |
1478 | ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
1479 | } |
1480 | |
1481 | if ((r=nr_stun_find_attr_info(attr->type, &attr_info))) { |
1482 | if (attr->type <= 0x7FFF) |
1483 | ++msg->comprehension_required_unknown_attributes; |
1484 | else |
1485 | ++msg->comprehension_optional_unknown_attributes; |
1486 | r_log(NR_LOG_STUN, LOG_INFO6, "Unrecognized attribute: 0x%04x", attr->type); |
1487 | } |
1488 | else { |
1489 | attr_info->name = attr_info->name; |
1490 | attr->type_name = attr_info->codec->name; |
1491 | |
1492 | if (attr->type == NR_STUN_ATTR_MESSAGE_INTEGRITY0x0008) { |
1493 | if (get_password && get_password(arg, msg, &password) == 0) { |
1494 | if (password->len > sizeof(attr->u.message_integrity.password)) { |
1495 | r_log(NR_LOG_STUN, LOG_WARNING4, "Password too long: %d bytes", password->len); |
1496 | ABORT(R_FAILED)do { int _r=10; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
1497 | } |
1498 | |
1499 | memcpy(attr->u.message_integrity.password, password->data, password->len); |
1500 | attr->u.message_integrity.passwordlen = password->len; |
1501 | } |
1502 | else { |
1503 | /* set to user "not found" */ |
1504 | attr->u.message_integrity.unknown_user = 1; |
1505 | } |
1506 | } |
1507 | else if (attr->type == NR_STUN_ATTR_OLD_XOR_MAPPED_ADDRESS0x8020) { |
1508 | attr->type = NR_STUN_ATTR_XOR_MAPPED_ADDRESS0x0020; |
1509 | r_log(NR_LOG_STUN, LOG_INFO6, "Translating obsolete XOR-MAPPED-ADDRESS type"); |
1510 | } |
1511 | |
1512 | if ((r=attr_info->codec->decode(attr_info, attr->length, msg->buffer, offset+4, msg->length, &attr->u))) { |
1513 | if (r == SKIP_ATTRIBUTE_DECODE-1) { |
1514 | r_log(NR_LOG_STUN, LOG_INFO6, "Skipping %s", attr_info->name); |
1515 | } |
1516 | else { |
1517 | r_log(NR_LOG_STUN, LOG_WARNING4, "Unable to parse %s", attr_info->name); |
1518 | } |
1519 | |
1520 | attr->invalid = 1; |
1521 | } |
1522 | else { |
1523 | attr_info->codec->print(attr_info, "Parsed", &attr->u); |
1524 | |
1525 | #ifdef USE_STUN_PEDANTIC1 |
1526 | r_log(NR_LOG_STUN, LOG_DEBUG7, "Before pedantic attr_info checks"); |
1527 | if (attr_info->illegal) { |
1528 | if ((r=attr_info->illegal(attr_info, attr->length, &attr->u))) { |
1529 | r_log(NR_LOG_STUN, LOG_WARNING4, "Failed pedantic attr_info checks"); |
1530 | ABORT(r)do { int _r=r; if(!_r) _r=-1; ; _status=_r; goto abort;} while (0); |
1531 | } |
1532 | } |
1533 | r_log(NR_LOG_STUN, LOG_DEBUG7, "After pedantic attr_info checks"); |
1534 | #endif /* USE_STUN_PEDANTIC */ |
1535 | } |
1536 | } |
1537 | |
1538 | offset += attr->encoding_length; |
1539 | size -= attr->encoding_length; |
1540 | } |
1541 | |
1542 | #ifdef SANITY_CHECKS1 |
1543 | sanity_check_encoding_stuff(msg); |
1544 | #endif /* SANITY_CHECKS */ |
1545 | |
1546 | _status=0; |
1547 | abort: |
1548 | return _status; |
1549 | } |
1550 |