media/mtransport/third_party/nICEr/src/stun/stun_proc.c

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

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

mercurial