Bug Summary

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'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_c_third_party_nICEr1.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/dom/media/webrtc/transport/third_party/nICEr/nicer_nicer -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/dom/media/webrtc/transport/third_party/nICEr/nicer_nicer -resource-dir /usr/lib/llvm-21/lib/clang/21 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D _GLIBCXX_ASSERTIONS -D DEBUG=1 -D _FILE_OFFSET_BITS=64 -D CHROMIUM_BUILD -D USE_LIBJPEG_TURBO=1 -D USE_NSS=1 -D ENABLE_ONE_CLICK_SIGNIN -D GTK_DISABLE_SINGLE_INCLUDES=1 -D _ISOC99_SOURCE=1 -D ENABLE_REMOTING=1 -D ENABLE_WEBRTC=1 -D ENABLE_CONFIGURATION_POLICY -D ENABLE_INPUT_SPEECH -D ENABLE_NOTIFICATIONS -D ENABLE_GPU=1 -D ENABLE_EGLIMAGE=1 -D USE_SKIA=1 -D ENABLE_TASK_MANAGER=1 -D ENABLE_WEB_INTENTS=1 -D ENABLE_EXTENSIONS=1 -D ENABLE_PLUGIN_INSTALLATION=1 -D ENABLE_PROTECTOR_SERVICE=1 -D ENABLE_SESSION_SERVICE=1 -D ENABLE_THEMES=1 -D ENABLE_BACKGROUND=1 -D ENABLE_AUTOMATION=1 -D ENABLE_PRINTING=1 -D ENABLE_CAPTIVE_PORTAL_DETECTION=1 -D SANITY_CHECKS -D USE_TURN -D USE_ICE -D USE_RFC_3489_BACKWARDS_COMPATIBLE -D USE_STUND_0_96 -D USE_STUN_PEDANTIC -D NR_SOCKET_IS_VOID_PTR -D restrict= -D R_PLATFORM_INT_TYPES=<stdint.h> -D R_DEFINED_INT2=int16_t -D R_DEFINED_UINT2=uint16_t -D R_DEFINED_INT4=int32_t -D R_DEFINED_UINT4=uint32_t -D R_DEFINED_INT8=int64_t -D R_DEFINED_UINT8=uint64_t -D LINUX -D HAVE_LIBM=1 -D HAVE_STRDUP=1 -D HAVE_STRLCPY=1 -D HAVE_SYS_TIME_H=1 -D HAVE_VFPRINTF=1 -D NEW_STDIORETSIGTYPE=void -D TIME_WITH_SYS_TIME_H=1 -D __UNUSED__=__attribute__((unused)) -D DYNAMIC_ANNOTATIONS_ENABLED=1 -D WTF_USE_DYNAMIC_ANNOTATIONS=1 -D _DEBUG -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dom/media/webrtc/transport/third_party/nICEr/nicer_nicer -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nrappkit/src/event -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nrappkit/src/log -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nrappkit/src/plugin -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nrappkit/src/registry -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nrappkit/src/share -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nrappkit/src/stats -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nrappkit/src/util -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nrappkit/src/util/libekr -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nrappkit/src/port/generic/include -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/crypto -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/ice -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/net -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/stun -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nICEr/src/util -I /root/firefox-clang/dom/media/webrtc/transport/third_party/nrappkit/src/port/linux/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /root/firefox-clang/ipc/chromium/src -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -D MOZILLA_CLIENT -internal-isystem /usr/lib/llvm-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-error=tautological-type-limit-compare -Wno-range-loop-analysis -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-unknown-warning-option -Wno-parentheses -Wno-strict-prototypes -Wno-format -Wno-format-security -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2025-06-27-100320-3286336-1 -x c Unified_c_third_party_nICEr1.c
1/*
2Copyright (c) 2007, Adobe Systems, Incorporated
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are
7met:
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
20THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30OF 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
58static int nr_stun_find_attr_info(UINT2 type, nr_stun_attr_info **info);
59
60static int nr_stun_fix_attribute_ordering(nr_stun_message *msg);
61
62static int nr_stun_encode_htons(UINT2 data, size_t buflen, UCHAR *buf, size_t *offset);
63static int nr_stun_encode_htonl(UINT4 data, size_t buflen, UCHAR *buf, size_t *offset);
64static int nr_stun_encode_htonll(UINT8 data, size_t buflen, UCHAR *buf, size_t *offset);
65static int nr_stun_encode(UCHAR *data, size_t length, size_t buflen, UCHAR *buf, size_t *offset);
66
67static int nr_stun_decode_htons(UCHAR *buf, size_t buflen, size_t *offset, UINT2 *data);
68static int nr_stun_decode_htonl(UCHAR *buf, size_t buflen, size_t *offset, UINT4 *data);
69static int nr_stun_decode_htonll(UCHAR *buf, size_t buflen, size_t *offset, UINT8 *data);
70static int nr_stun_decode(size_t length, UCHAR *buf, size_t buflen, size_t *offset, UCHAR *data);
71
72static 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
74static int nr_stun_attr_error_code_illegal(nr_stun_attr_info *attr_info, size_t attrlen, void *data);
75static int nr_stun_attr_nonce_illegal(nr_stun_attr_info *attr_info, size_t attrlen, void *data);
76static int nr_stun_attr_realm_illegal(nr_stun_attr_info *attr_info, size_t attrlen, void *data);
77static int nr_stun_attr_server_illegal(nr_stun_attr_info *attr_info, size_t attrlen, void *data);
78static int nr_stun_attr_username_illegal(nr_stun_attr_info *attr_info, size_t attrlen, void *data);
79static int
80nr_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
83int
84nr_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
99int
100nr_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
115int
116nr_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
131int
132nr_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
146int
147nr_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
163int
164nr_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
180int
181nr_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
197int
198nr_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 */
223size_t
224nr_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
236int
237nr_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
259int
260nr_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
276int
277nr_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
282int
283nr_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
288int
289nr_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
294int
295nr_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
300static int
301nr_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
307static int
308nr_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
324static int
325nr_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
342nr_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
349static int
350nr_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
356static int
357nr_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
371static int
372nr_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
385nr_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
392static int
393nr_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
399static int
400nr_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
414static int
415nr_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
428nr_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
435static int
436nr_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
442static int
443nr_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
488static int
489nr_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
543nr_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
550static int
551nr_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
558static int
559nr_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
574static int
575nr_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
597nr_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
604static int
605nr_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
614static int
615nr_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
637static int
638nr_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
672nr_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
679static int
680nr_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
687static int
688nr_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
713static int
714nr_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
756nr_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
763static int
764nr_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
770static int
771nr_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
784static int
785nr_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
795nr_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
802static int
803nr_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
810static int
811nr_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
841static int
842nr_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
860static int
861nr_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
899nr_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
906static int
907nr_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
912nr_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
919static int
920nr_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
927static int
928nr_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
935static int
936nr_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
943nr_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
950static int
951nr_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
958static int
959nr_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
975static int
976nr_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
1005nr_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
1012static int
1013nr_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
1030static int
1031nr_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
1060static int
1061nr_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
1091nr_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
1098static int
1099nr_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
1109static int
1110nr_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
1134static int
1135nr_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
1162nr_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
1169nr_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
1176nr_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
1190static 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
1233int
1234nr_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
1255int
1256nr_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
1284static 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
1308int
1309nr_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;
1400abort:
1401 return _status;
1402}
1403
1404int
1405nr_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