Line data Source code
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 :
34 : static char *RCSSTRING __UNUSED__="$Id: stun_proc.c,v 1.2 2008/04/28 18:21:30 ekr Exp $";
35 :
36 : #include <errno.h>
37 : #include <csi_platform.h>
38 :
39 : #ifdef WIN32
40 : #include <winsock2.h>
41 : #include <stdlib.h>
42 : #include <io.h>
43 : #include <time.h>
44 : #else /* UNIX */
45 : #include <string.h>
46 : #endif /* end UNIX */
47 : #include <assert.h>
48 :
49 : #include "stun.h"
50 : #include "stun_reg.h"
51 : #include "registry.h"
52 :
53 : static int
54 : nr_stun_add_realm_and_nonce(int new_nonce, nr_stun_server_client *clnt, nr_stun_message *res);
55 :
56 : /* draft-ietf-behave-rfc3489bis-10.txt S 7.3 */
57 : int
58 0 : nr_stun_receive_message(nr_stun_message *req, nr_stun_message *msg)
59 : {
60 : int _status;
61 : nr_stun_message_attribute *attr;
62 :
63 : #ifdef USE_RFC_3489_BACKWARDS_COMPATIBLE
64 : /* if this message was generated by an RFC 3489 impementation,
65 : * the call to nr_is_stun_message will fail, so skip that
66 : * check and puke elsewhere if the message can't be decoded */
67 0 : if (msg->header.magic_cookie == NR_STUN_MAGIC_COOKIE
68 0 : || msg->header.magic_cookie == NR_STUN_MAGIC_COOKIE2) {
69 : #endif /* USE_RFC_3489_BACKWARDS_COMPATIBLE */
70 0 : if (!nr_is_stun_message(msg->buffer, msg->length)) {
71 0 : r_log(NR_LOG_STUN, LOG_WARNING, "Not a STUN message");
72 0 : ABORT(R_REJECTED);
73 : }
74 : #ifdef USE_RFC_3489_BACKWARDS_COMPATIBLE
75 : }
76 : #endif /* USE_RFC_3489_BACKWARDS_COMPATIBLE */
77 :
78 0 : if (req == 0) {
79 0 : if (NR_STUN_GET_TYPE_CLASS(msg->header.type) != NR_CLASS_REQUEST) {
80 0 : r_log(NR_LOG_STUN,LOG_WARNING,"Illegal message type: %03x", msg->header.type);
81 0 : ABORT(R_REJECTED);
82 : }
83 : }
84 : else {
85 0 : if (NR_STUN_GET_TYPE_CLASS(msg->header.type) != NR_CLASS_RESPONSE
86 0 : && NR_STUN_GET_TYPE_CLASS(msg->header.type) != NR_CLASS_ERROR_RESPONSE) {
87 0 : r_log(NR_LOG_STUN,LOG_WARNING,"Illegal message class: %03x", msg->header.type);
88 0 : ABORT(R_REJECTED);
89 : }
90 :
91 0 : if (NR_STUN_GET_TYPE_METHOD(req->header.type) != NR_STUN_GET_TYPE_METHOD(msg->header.type)) {
92 0 : r_log(NR_LOG_STUN,LOG_WARNING,"Inconsistent message method: %03x expected %03x", msg->header.type, req->header.type);
93 0 : ABORT(R_REJECTED);
94 : }
95 :
96 0 : if (nr_stun_different_transaction(msg->buffer, msg->length, req)) {
97 0 : r_log(NR_LOG_STUN, LOG_DEBUG, "Unrecognized STUN transaction");
98 0 : ABORT(R_REJECTED);
99 : }
100 : }
101 :
102 0 : switch (msg->header.magic_cookie) {
103 : case NR_STUN_MAGIC_COOKIE:
104 : /* basically draft-ietf-behave-rfc3489bis-10.txt S 6 rules */
105 :
106 0 : if (nr_stun_message_has_attribute(msg, NR_STUN_ATTR_FINGERPRINT, &attr)
107 0 : && !attr->u.fingerprint.valid) {
108 0 : r_log(NR_LOG_STUN, LOG_WARNING, "Invalid fingerprint");
109 0 : ABORT(R_REJECTED);
110 : }
111 :
112 0 : break;
113 :
114 : #ifdef USE_STUND_0_96
115 : case NR_STUN_MAGIC_COOKIE2:
116 : /* nothing to check in this case */
117 0 : break;
118 : #endif /* USE_STUND_0_96 */
119 :
120 : default:
121 : #ifdef USE_RFC_3489_BACKWARDS_COMPATIBLE
122 : /* in RFC 3489 there is no magic cookie, it's part of the transaction ID */
123 : #else
124 : #ifdef NDEBUG
125 : /* in deployment builds we should always see a recognized magic cookie */
126 : r_log(NR_LOG_STUN, LOG_WARNING, "Missing Magic Cookie");
127 : ABORT(R_REJECTED);
128 : #else
129 : /* ignore this condition because sometimes we like to pretend we're
130 : * a server talking to old clients and their messages don't contain
131 : * a magic cookie at all but rather the magic cookie field is part
132 : * of their ID and therefore random */
133 : #endif /* NDEBUG */
134 : #endif /* USE_RFC_3489_BACKWARDS_COMPATIBLE */
135 0 : break;
136 : }
137 :
138 0 : _status=0;
139 : abort:
140 0 : return _status;
141 : }
142 :
143 : /* draft-ietf-behave-rfc3489bis-10.txt S 7.3.1 */
144 : int
145 0 : nr_stun_process_request(nr_stun_message *req, nr_stun_message *res)
146 : {
147 : int _status;
148 : #ifdef USE_STUN_PEDANTIC
149 : int r;
150 0 : nr_stun_attr_unknown_attributes unknown_attributes = { { 0 } };
151 : nr_stun_message_attribute *attr;
152 :
153 0 : if (req->comprehension_required_unknown_attributes > 0) {
154 0 : nr_stun_form_error_response(req, res, 420, "Unknown Attributes");
155 0 : r_log(NR_LOG_STUN, LOG_WARNING, "Request contains comprehension required but unknown attributes");
156 :
157 0 : TAILQ_FOREACH(attr, &req->attributes, entry) {
158 0 : if (attr->name == 0) {
159 : /* unrecognized attribute */
160 :
161 : /* should never happen, but truncate if it ever were to occur */
162 0 : if (unknown_attributes.num_attributes > NR_STUN_MAX_UNKNOWN_ATTRIBUTES)
163 0 : break;
164 :
165 0 : unknown_attributes.attribute[unknown_attributes.num_attributes++] = attr->type;
166 : }
167 : }
168 :
169 0 : assert(req->comprehension_required_unknown_attributes + req->comprehension_optional_unknown_attributes == unknown_attributes.num_attributes);
170 :
171 0 : if ((r=nr_stun_message_add_unknown_attributes_attribute(res, &unknown_attributes)))
172 0 : ABORT(R_ALREADY);
173 :
174 0 : ABORT(R_ALREADY);
175 : }
176 : #endif /* USE_STUN_PEDANTIC */
177 :
178 0 : _status=0;
179 : #ifdef USE_STUN_PEDANTIC
180 : abort:
181 : #endif /* USE_STUN_PEDANTIC */
182 0 : return _status;
183 : }
184 :
185 : /* draft-ietf-behave-rfc3489bis-10.txt S 7.3.2 */
186 : int
187 0 : nr_stun_process_indication(nr_stun_message *ind)
188 : {
189 : int _status;
190 : #ifdef USE_STUN_PEDANTIC
191 :
192 0 : if (ind->comprehension_required_unknown_attributes > 0) {
193 0 : r_log(NR_LOG_STUN, LOG_WARNING, "Indication contains comprehension required but unknown attributes");
194 0 : ABORT(R_REJECTED);
195 : }
196 : #endif /* USE_STUN_PEDANTIC */
197 :
198 0 : _status=0;
199 : #ifdef USE_STUN_PEDANTIC
200 : abort:
201 : #endif /* USE_STUN_PEDANTIC */
202 0 : return _status;
203 : }
204 :
205 : /* RFC5389 S 7.3.3, except that we *also* allow a MAPPED_ADDRESS
206 : to compensate for a bug in Google's STUN server where it
207 : always returns MAPPED_ADDRESS.
208 :
209 : Mozilla bug: 888274.
210 : */
211 : int
212 0 : nr_stun_process_success_response(nr_stun_message *res)
213 : {
214 : int _status;
215 :
216 : #ifdef USE_STUN_PEDANTIC
217 0 : if (res->comprehension_required_unknown_attributes > 0) {
218 0 : r_log(NR_LOG_STUN, LOG_WARNING, "Response contains comprehension required but unknown attributes");
219 0 : ABORT(R_REJECTED);
220 : }
221 : #endif /* USE_STUN_PEDANTIC */
222 :
223 0 : if (NR_STUN_GET_TYPE_METHOD(res->header.type) == NR_METHOD_BINDING) {
224 0 : if (! nr_stun_message_has_attribute(res, NR_STUN_ATTR_XOR_MAPPED_ADDRESS, 0) &&
225 0 : ! nr_stun_message_has_attribute(res, NR_STUN_ATTR_MAPPED_ADDRESS, 0)) {
226 0 : r_log(NR_LOG_STUN, LOG_WARNING, "Missing XOR-MAPPED-ADDRESS and MAPPED_ADDRESS");
227 0 : ABORT(R_REJECTED);
228 : }
229 : }
230 :
231 0 : _status=0;
232 : abort:
233 0 : return _status;
234 : }
235 :
236 : /* draft-ietf-behave-rfc3489bis-10.txt S 7.3.4 */
237 : int
238 0 : nr_stun_process_error_response(nr_stun_message *res, UINT2 *error_code)
239 : {
240 : int _status;
241 : nr_stun_message_attribute *attr;
242 :
243 0 : if (res->comprehension_required_unknown_attributes > 0) {
244 0 : r_log(NR_LOG_STUN, LOG_WARNING, "Error response contains comprehension required but unknown attributes");
245 0 : ABORT(R_REJECTED);
246 : }
247 :
248 0 : if (! nr_stun_message_has_attribute(res, NR_STUN_ATTR_ERROR_CODE, &attr)) {
249 0 : r_log(NR_LOG_STUN, LOG_WARNING, "Missing ERROR-CODE");
250 0 : ABORT(R_REJECTED);
251 : }
252 :
253 0 : *error_code = attr->u.error_code.number;
254 :
255 0 : switch (attr->u.error_code.number / 100) {
256 : case 3:
257 : /* If the error code is 300 through 399, the client SHOULD consider
258 : * the transaction as failed unless the ALTERNATE-SERVER extension is
259 : * being used. See Section 11. */
260 :
261 0 : if (attr->u.error_code.number == 300) {
262 0 : if (!nr_stun_message_has_attribute(res, NR_STUN_ATTR_ALTERNATE_SERVER, 0)) {
263 0 : r_log(NR_LOG_STUN, LOG_WARNING, "Missing ALTERNATE-SERVER");
264 0 : ABORT(R_REJECTED);
265 : }
266 :
267 : /* draft-ietf-behave-rfc3489bis-10.txt S 11 */
268 0 : if (!nr_stun_message_has_attribute(res, NR_STUN_ATTR_MESSAGE_INTEGRITY, 0)) {
269 0 : r_log(NR_LOG_STUN, LOG_WARNING, "Missing MESSAGE-INTEGRITY");
270 0 : ABORT(R_REJECTED);
271 : }
272 :
273 0 : ABORT(R_RETRY);
274 : }
275 :
276 0 : ABORT(R_REJECTED);
277 : break;
278 :
279 : case 4:
280 : /* If the error code is 400 through 499, the client declares the
281 : * transaction failed; in the case of 420 (Unknown Attribute), the
282 : * response should contain a UNKNOWN-ATTRIBUTES attribute that gives
283 : * additional information. */
284 0 : if (attr->u.error_code.number == 420)
285 0 : ABORT(R_REJECTED);
286 :
287 : /* it may be possible to restart given the info that was received in
288 : * this response, so retry */
289 0 : ABORT(R_RETRY);
290 : break;
291 :
292 : case 5:
293 : /* If the error code is 500 through 599, the client MAY resend the
294 : * request; clients that do so MUST limit the number of times they do
295 : * this. */
296 : /* let the retransmit mechanism handle resending the request */
297 0 : break;
298 :
299 : default:
300 0 : ABORT(R_REJECTED);
301 : break;
302 : }
303 :
304 : /* the spec says: "The client then does any processing specified by the authentication
305 : * mechanism (see Section 10). This may result in a new transaction
306 : * attempt." -- but this is handled already elsewhere, so needn't be repeated
307 : * in this function */
308 :
309 0 : _status=0;
310 : abort:
311 0 : return _status;
312 : }
313 :
314 : /* draft-ietf-behave-rfc3489bis-10.txt S 10.1.2 */
315 : int
316 0 : nr_stun_receive_request_or_indication_short_term_auth(nr_stun_message *msg,
317 : nr_stun_message *res)
318 : {
319 : int _status;
320 : nr_stun_message_attribute *attr;
321 :
322 0 : switch (msg->header.magic_cookie) {
323 : default:
324 : /* in RFC 3489 there is no magic cookie, it's part of the transaction ID */
325 : /* drop thru */
326 : case NR_STUN_MAGIC_COOKIE:
327 0 : if (!nr_stun_message_has_attribute(msg, NR_STUN_ATTR_MESSAGE_INTEGRITY, &attr)) {
328 0 : nr_stun_form_error_response(msg, res, 400, "Missing MESSAGE-INTEGRITY");
329 0 : ABORT(R_ALREADY);
330 : }
331 :
332 0 : if (!nr_stun_message_has_attribute(msg, NR_STUN_ATTR_USERNAME, 0)) {
333 0 : nr_stun_form_error_response(msg, res, 400, "Missing USERNAME");
334 0 : ABORT(R_ALREADY);
335 : }
336 :
337 0 : if (attr->u.message_integrity.unknown_user) {
338 0 : nr_stun_form_error_response(msg, res, 401, "Unrecognized USERNAME");
339 0 : ABORT(R_ALREADY);
340 : }
341 :
342 0 : if (!attr->u.message_integrity.valid) {
343 0 : nr_stun_form_error_response(msg, res, 401, "Bad MESSAGE-INTEGRITY");
344 0 : ABORT(R_ALREADY);
345 : }
346 :
347 0 : break;
348 :
349 : #ifdef USE_STUND_0_96
350 : case NR_STUN_MAGIC_COOKIE2:
351 : /* nothing to check in this case */
352 0 : break;
353 : #endif /* USE_STUND_0_96 */
354 : }
355 :
356 0 : _status=0;
357 : abort:
358 0 : return _status;
359 : }
360 :
361 : /* draft-ietf-behave-rfc3489bis-10.txt S 10.1.3 */
362 : int
363 0 : nr_stun_receive_response_short_term_auth(nr_stun_message *res)
364 : {
365 : int _status;
366 : nr_stun_message_attribute *attr;
367 :
368 0 : switch (res->header.magic_cookie) {
369 : default:
370 : /* in RFC 3489 there is no magic cookie, it's part of the transaction ID */
371 : /* drop thru */
372 : case NR_STUN_MAGIC_COOKIE:
373 0 : if (!nr_stun_message_has_attribute(res, NR_STUN_ATTR_MESSAGE_INTEGRITY, &attr)) {
374 0 : r_log(NR_LOG_STUN, LOG_WARNING, "Missing MESSAGE-INTEGRITY");
375 0 : ABORT(R_REJECTED);
376 : }
377 :
378 0 : if (!attr->u.message_integrity.valid) {
379 0 : r_log(NR_LOG_STUN, LOG_WARNING, "Bad MESSAGE-INTEGRITY");
380 0 : ABORT(R_REJECTED);
381 : }
382 :
383 0 : break;
384 :
385 : #ifdef USE_STUND_0_96
386 : case NR_STUN_MAGIC_COOKIE2:
387 : /* nothing to check in this case */
388 0 : break;
389 : #endif /* USE_STUND_0_96 */
390 : }
391 :
392 0 : _status=0;
393 : abort:
394 0 : return _status;
395 : }
396 :
397 : static int
398 0 : nr_stun_add_realm_and_nonce(int new_nonce, nr_stun_server_client *clnt, nr_stun_message *res)
399 : {
400 : int r,_status;
401 0 : char *realm = 0;
402 : char *nonce;
403 : UINT2 size;
404 :
405 0 : if ((r=NR_reg_alloc_string(NR_STUN_REG_PREF_SERVER_REALM, &realm)))
406 0 : ABORT(r);
407 :
408 0 : if ((r=nr_stun_message_add_realm_attribute(res, realm)))
409 0 : ABORT(r);
410 :
411 0 : if (clnt) {
412 0 : if (strlen(clnt->nonce) < 1)
413 0 : new_nonce = 1;
414 :
415 0 : if (new_nonce) {
416 0 : if (NR_reg_get_uint2(NR_STUN_REG_PREF_SERVER_NONCE_SIZE, &size))
417 0 : size = 48;
418 :
419 0 : if (size > (sizeof(clnt->nonce) - 1))
420 0 : size = sizeof(clnt->nonce) - 1;
421 :
422 0 : nr_random_alphanum(clnt->nonce, size);
423 0 : clnt->nonce[size] = '\0';
424 : }
425 :
426 0 : nonce = clnt->nonce;
427 : }
428 : else {
429 : /* user is not known, so use a bogus nonce since there's no way to
430 : * store a good nonce with the client-specific data -- this nonce
431 : * will be recognized as stale if the client attempts another
432 : * request */
433 0 : nonce = "STALE";
434 : }
435 :
436 0 : if ((r=nr_stun_message_add_nonce_attribute(res, nonce)))
437 0 : ABORT(r);
438 :
439 0 : _status=0;
440 : abort:
441 : #ifdef USE_TURN
442 0 : assert(_status == 0); /* TODO: !nn! cleanup after I reimplmement TURN */
443 : #endif
444 0 : RFREE(realm);
445 0 : return _status;
446 : }
447 :
448 : /* draft-ietf-behave-rfc3489bis-10.txt S 10.2.1 - 10.2.2 */
449 : int
450 0 : nr_stun_receive_request_long_term_auth(nr_stun_message *req, nr_stun_server_ctx *ctx, nr_stun_message *res)
451 : {
452 : int r,_status;
453 : nr_stun_message_attribute *mi;
454 : nr_stun_message_attribute *n;
455 0 : nr_stun_server_client *clnt = 0;
456 :
457 0 : switch (req->header.magic_cookie) {
458 : default:
459 : /* in RFC 3489 there is no magic cookie, it's part of the transaction ID */
460 : /* drop thru */
461 : case NR_STUN_MAGIC_COOKIE:
462 0 : if (!nr_stun_message_has_attribute(req, NR_STUN_ATTR_USERNAME, 0)) {
463 0 : nr_stun_form_error_response(req, res, 400, "Missing USERNAME");
464 0 : nr_stun_add_realm_and_nonce(0, 0, res);
465 0 : ABORT(R_ALREADY);
466 : }
467 :
468 0 : if ((r=nr_stun_get_message_client(ctx, req, &clnt))) {
469 0 : nr_stun_form_error_response(req, res, 401, "Unrecognized USERNAME");
470 0 : nr_stun_add_realm_and_nonce(0, 0, res);
471 0 : ABORT(R_ALREADY);
472 : }
473 :
474 0 : if (!nr_stun_message_has_attribute(req, NR_STUN_ATTR_MESSAGE_INTEGRITY, &mi)) {
475 0 : nr_stun_form_error_response(req, res, 401, "Missing MESSAGE-INTEGRITY");
476 0 : nr_stun_add_realm_and_nonce(0, clnt, res);
477 0 : ABORT(R_ALREADY);
478 : }
479 :
480 0 : assert(!mi->u.message_integrity.unknown_user);
481 :
482 0 : if (!nr_stun_message_has_attribute(req, NR_STUN_ATTR_REALM, 0)) {
483 0 : nr_stun_form_error_response(req, res, 400, "Missing REALM");
484 0 : ABORT(R_ALREADY);
485 : }
486 :
487 0 : if (!nr_stun_message_has_attribute(req, NR_STUN_ATTR_NONCE, &n)) {
488 0 : nr_stun_form_error_response(req, res, 400, "Missing NONCE");
489 0 : ABORT(R_ALREADY);
490 : }
491 :
492 : assert(sizeof(clnt->nonce) == sizeof(n->u.nonce));
493 0 : if (strncmp(clnt->nonce, n->u.nonce, sizeof(n->u.nonce))) {
494 0 : nr_stun_form_error_response(req, res, 438, "Stale NONCE");
495 0 : nr_stun_add_realm_and_nonce(1, clnt, res);
496 0 : ABORT(R_ALREADY);
497 : }
498 :
499 0 : if (!mi->u.message_integrity.valid) {
500 0 : nr_stun_form_error_response(req, res, 401, "Bad MESSAGE-INTEGRITY");
501 0 : nr_stun_add_realm_and_nonce(0, clnt, res);
502 0 : ABORT(R_ALREADY);
503 : }
504 :
505 0 : break;
506 :
507 : #ifdef USE_STUND_0_96
508 : case NR_STUN_MAGIC_COOKIE2:
509 : /* nothing to do in this case */
510 0 : break;
511 : #endif /* USE_STUND_0_96 */
512 : }
513 :
514 0 : _status=0;
515 : abort:
516 :
517 0 : return _status;
518 : }
519 :
520 : /* draft-ietf-behave-rfc3489bis-10.txt S 10.2.3 */
521 : int
522 0 : nr_stun_receive_response_long_term_auth(nr_stun_message *res, nr_stun_client_ctx *ctx)
523 : {
524 : int _status;
525 : nr_stun_message_attribute *attr;
526 :
527 0 : switch (res->header.magic_cookie) {
528 : default:
529 : /* in RFC 3489 there is no magic cookie, it's part of the transaction ID */
530 : /* drop thru */
531 : case NR_STUN_MAGIC_COOKIE:
532 0 : if (nr_stun_message_has_attribute(res, NR_STUN_ATTR_REALM, &attr)) {
533 0 : RFREE(ctx->realm);
534 0 : ctx->realm = r_strdup(attr->u.realm);
535 0 : if (!ctx->realm)
536 0 : ABORT(R_NO_MEMORY);
537 : }
538 : else {
539 0 : r_log(NR_LOG_STUN, LOG_WARNING, "Missing REALM");
540 0 : ABORT(R_REJECTED);
541 : }
542 :
543 0 : if (nr_stun_message_has_attribute(res, NR_STUN_ATTR_NONCE, &attr)) {
544 0 : RFREE(ctx->nonce);
545 0 : ctx->nonce = r_strdup(attr->u.nonce);
546 0 : if (!ctx->nonce)
547 0 : ABORT(R_NO_MEMORY);
548 : }
549 : else {
550 0 : r_log(NR_LOG_STUN, LOG_WARNING, "Missing NONCE");
551 0 : ABORT(R_REJECTED);
552 : }
553 :
554 0 : if (nr_stun_message_has_attribute(res, NR_STUN_ATTR_MESSAGE_INTEGRITY, &attr)) {
555 0 : if (!attr->u.message_integrity.valid) {
556 0 : r_log(NR_LOG_STUN, LOG_WARNING, "Bad MESSAGE-INTEGRITY");
557 0 : ABORT(R_REJECTED);
558 : }
559 : }
560 :
561 0 : break;
562 :
563 : #ifdef USE_STUND_0_96
564 : case NR_STUN_MAGIC_COOKIE2:
565 : /* nothing to check in this case */
566 0 : break;
567 : #endif /* USE_STUND_0_96 */
568 : }
569 :
570 0 : _status=0;
571 : abort:
572 0 : return _status;
573 : }
574 :
|