1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/mtransport/third_party/nICEr/src/stun/stun_proc.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,568 @@ 1.4 +/* 1.5 +Copyright (c) 2007, Adobe Systems, Incorporated 1.6 +All rights reserved. 1.7 + 1.8 +Redistribution and use in source and binary forms, with or without 1.9 +modification, are permitted provided that the following conditions are 1.10 +met: 1.11 + 1.12 +* Redistributions of source code must retain the above copyright 1.13 + notice, this list of conditions and the following disclaimer. 1.14 + 1.15 +* Redistributions in binary form must reproduce the above copyright 1.16 + notice, this list of conditions and the following disclaimer in the 1.17 + documentation and/or other materials provided with the distribution. 1.18 + 1.19 +* Neither the name of Adobe Systems, Network Resonance nor the names of its 1.20 + contributors may be used to endorse or promote products derived from 1.21 + this software without specific prior written permission. 1.22 + 1.23 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.24 +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.25 +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.26 +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.27 +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.28 +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.29 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.30 +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.31 +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.32 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.33 +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.34 +*/ 1.35 + 1.36 + 1.37 +static char *RCSSTRING __UNUSED__="$Id: stun_proc.c,v 1.2 2008/04/28 18:21:30 ekr Exp $"; 1.38 + 1.39 +#include <errno.h> 1.40 +#include <csi_platform.h> 1.41 + 1.42 +#ifdef WIN32 1.43 +#include <winsock2.h> 1.44 +#include <stdlib.h> 1.45 +#include <io.h> 1.46 +#include <time.h> 1.47 +#else /* UNIX */ 1.48 +#include <string.h> 1.49 +#endif /* end UNIX */ 1.50 +#include <assert.h> 1.51 + 1.52 +#include "stun.h" 1.53 +#include "stun_reg.h" 1.54 +#include "registry.h" 1.55 + 1.56 +static int 1.57 +nr_stun_add_realm_and_nonce(int new_nonce, nr_stun_server_client *clnt, nr_stun_message *res); 1.58 + 1.59 +/* draft-ietf-behave-rfc3489bis-10.txt S 7.3 */ 1.60 +int 1.61 +nr_stun_receive_message(nr_stun_message *req, nr_stun_message *msg) 1.62 +{ 1.63 + int _status; 1.64 + nr_stun_message_attribute *attr; 1.65 + 1.66 +#ifdef USE_RFC_3489_BACKWARDS_COMPATIBLE 1.67 + /* if this message was generated by an RFC 3489 impementation, 1.68 + * the call to nr_is_stun_message will fail, so skip that 1.69 + * check and puke elsewhere if the message can't be decoded */ 1.70 + if (msg->header.magic_cookie == NR_STUN_MAGIC_COOKIE 1.71 + || msg->header.magic_cookie == NR_STUN_MAGIC_COOKIE2) { 1.72 +#endif /* USE_RFC_3489_BACKWARDS_COMPATIBLE */ 1.73 + if (!nr_is_stun_message(msg->buffer, msg->length)) { 1.74 + r_log(NR_LOG_STUN, LOG_WARNING, "Not a STUN message"); 1.75 + ABORT(R_REJECTED); 1.76 + } 1.77 +#ifdef USE_RFC_3489_BACKWARDS_COMPATIBLE 1.78 + } 1.79 +#endif /* USE_RFC_3489_BACKWARDS_COMPATIBLE */ 1.80 + 1.81 + if (req == 0) { 1.82 + if (NR_STUN_GET_TYPE_CLASS(msg->header.type) != NR_CLASS_REQUEST) { 1.83 + r_log(NR_LOG_STUN,LOG_WARNING,"Illegal message type: %03x", msg->header.type); 1.84 + ABORT(R_REJECTED); 1.85 + } 1.86 + } 1.87 + else { 1.88 + if (NR_STUN_GET_TYPE_CLASS(msg->header.type) != NR_CLASS_RESPONSE 1.89 + && NR_STUN_GET_TYPE_CLASS(msg->header.type) != NR_CLASS_ERROR_RESPONSE) { 1.90 + r_log(NR_LOG_STUN,LOG_WARNING,"Illegal message class: %03x", msg->header.type); 1.91 + ABORT(R_REJECTED); 1.92 + } 1.93 + 1.94 + if (NR_STUN_GET_TYPE_METHOD(req->header.type) != NR_STUN_GET_TYPE_METHOD(msg->header.type)) { 1.95 + r_log(NR_LOG_STUN,LOG_WARNING,"Inconsistent message method: %03x expected %03x", msg->header.type, req->header.type); 1.96 + ABORT(R_REJECTED); 1.97 + } 1.98 + 1.99 + if (nr_stun_different_transaction(msg->buffer, msg->length, req)) { 1.100 + r_log(NR_LOG_STUN, LOG_DEBUG, "Unrecognized STUN transaction"); 1.101 + ABORT(R_REJECTED); 1.102 + } 1.103 + } 1.104 + 1.105 + switch (msg->header.magic_cookie) { 1.106 + case NR_STUN_MAGIC_COOKIE: 1.107 + /* basically draft-ietf-behave-rfc3489bis-10.txt S 6 rules */ 1.108 + 1.109 + if (nr_stun_message_has_attribute(msg, NR_STUN_ATTR_FINGERPRINT, &attr) 1.110 + && !attr->u.fingerprint.valid) { 1.111 + r_log(NR_LOG_STUN, LOG_WARNING, "Invalid fingerprint"); 1.112 + ABORT(R_REJECTED); 1.113 + } 1.114 + 1.115 + break; 1.116 + 1.117 +#ifdef USE_STUND_0_96 1.118 + case NR_STUN_MAGIC_COOKIE2: 1.119 + /* nothing to check in this case */ 1.120 + break; 1.121 +#endif /* USE_STUND_0_96 */ 1.122 + 1.123 + default: 1.124 +#ifdef USE_RFC_3489_BACKWARDS_COMPATIBLE 1.125 + /* in RFC 3489 there is no magic cookie, it's part of the transaction ID */ 1.126 +#else 1.127 +#ifdef NDEBUG 1.128 + /* in deployment builds we should always see a recognized magic cookie */ 1.129 + r_log(NR_LOG_STUN, LOG_WARNING, "Missing Magic Cookie"); 1.130 + ABORT(R_REJECTED); 1.131 +#else 1.132 + /* ignore this condition because sometimes we like to pretend we're 1.133 + * a server talking to old clients and their messages don't contain 1.134 + * a magic cookie at all but rather the magic cookie field is part 1.135 + * of their ID and therefore random */ 1.136 +#endif /* NDEBUG */ 1.137 +#endif /* USE_RFC_3489_BACKWARDS_COMPATIBLE */ 1.138 + break; 1.139 + } 1.140 + 1.141 + _status=0; 1.142 + abort: 1.143 + return _status; 1.144 +} 1.145 + 1.146 +/* draft-ietf-behave-rfc3489bis-10.txt S 7.3.1 */ 1.147 +int 1.148 +nr_stun_process_request(nr_stun_message *req, nr_stun_message *res) 1.149 +{ 1.150 + int _status; 1.151 +#ifdef USE_STUN_PEDANTIC 1.152 + int r; 1.153 + nr_stun_attr_unknown_attributes unknown_attributes = { { 0 } }; 1.154 + nr_stun_message_attribute *attr; 1.155 + 1.156 + if (req->comprehension_required_unknown_attributes > 0) { 1.157 + nr_stun_form_error_response(req, res, 420, "Unknown Attributes"); 1.158 + 1.159 + TAILQ_FOREACH(attr, &req->attributes, entry) { 1.160 + if (attr->name == 0) { 1.161 + /* unrecognized attribute */ 1.162 + 1.163 + /* should never happen, but truncate if it ever were to occur */ 1.164 + if (unknown_attributes.num_attributes > NR_STUN_MAX_UNKNOWN_ATTRIBUTES) 1.165 + break; 1.166 + 1.167 + unknown_attributes.attribute[unknown_attributes.num_attributes++] = attr->type; 1.168 + } 1.169 + } 1.170 + 1.171 + assert(req->comprehension_required_unknown_attributes + req->comprehension_optional_unknown_attributes == unknown_attributes.num_attributes); 1.172 + 1.173 + if ((r=nr_stun_message_add_unknown_attributes_attribute(res, &unknown_attributes))) 1.174 + ABORT(R_ALREADY); 1.175 + 1.176 + ABORT(R_ALREADY); 1.177 + } 1.178 +#endif /* USE_STUN_PEDANTIC */ 1.179 + 1.180 + _status=0; 1.181 +#ifdef USE_STUN_PEDANTIC 1.182 + abort: 1.183 +#endif /* USE_STUN_PEDANTIC */ 1.184 + return _status; 1.185 +} 1.186 + 1.187 +/* draft-ietf-behave-rfc3489bis-10.txt S 7.3.2 */ 1.188 +int 1.189 +nr_stun_process_indication(nr_stun_message *ind) 1.190 +{ 1.191 + int _status; 1.192 +#ifdef USE_STUN_PEDANTIC 1.193 + 1.194 + if (ind->comprehension_required_unknown_attributes > 0) 1.195 + ABORT(R_REJECTED); 1.196 +#endif /* USE_STUN_PEDANTIC */ 1.197 + 1.198 + _status=0; 1.199 +#ifdef USE_STUN_PEDANTIC 1.200 + abort: 1.201 +#endif /* USE_STUN_PEDANTIC */ 1.202 + return _status; 1.203 +} 1.204 + 1.205 +/* RFC5389 S 7.3.3, except that we *also* allow a MAPPED_ADDRESS 1.206 + to compensate for a bug in Google's STUN server where it 1.207 + always returns MAPPED_ADDRESS. 1.208 + 1.209 + Mozilla bug: 888274. 1.210 + */ 1.211 +int 1.212 +nr_stun_process_success_response(nr_stun_message *res) 1.213 +{ 1.214 + int _status; 1.215 + 1.216 +#ifdef USE_STUN_PEDANTIC 1.217 + if (res->comprehension_required_unknown_attributes > 0) 1.218 + ABORT(R_REJECTED); 1.219 +#endif /* USE_STUN_PEDANTIC */ 1.220 + 1.221 + if (NR_STUN_GET_TYPE_METHOD(res->header.type) == NR_METHOD_BINDING) { 1.222 + if (! nr_stun_message_has_attribute(res, NR_STUN_ATTR_XOR_MAPPED_ADDRESS, 0) && 1.223 + ! nr_stun_message_has_attribute(res, NR_STUN_ATTR_MAPPED_ADDRESS, 0)) { 1.224 + r_log(NR_LOG_STUN, LOG_WARNING, "Missing XOR-MAPPED-ADDRESS and MAPPED_ADDRESS"); 1.225 + ABORT(R_REJECTED); 1.226 + } 1.227 + } 1.228 + 1.229 + _status=0; 1.230 + abort: 1.231 + return _status; 1.232 +} 1.233 + 1.234 +/* draft-ietf-behave-rfc3489bis-10.txt S 7.3.4 */ 1.235 +int 1.236 +nr_stun_process_error_response(nr_stun_message *res, UINT2 *error_code) 1.237 +{ 1.238 + int _status; 1.239 + nr_stun_message_attribute *attr; 1.240 + 1.241 + if (res->comprehension_required_unknown_attributes > 0) { 1.242 + ABORT(R_REJECTED); 1.243 + } 1.244 + 1.245 + if (! nr_stun_message_has_attribute(res, NR_STUN_ATTR_ERROR_CODE, &attr)) { 1.246 + r_log(NR_LOG_STUN, LOG_WARNING, "Missing ERROR-CODE"); 1.247 + ABORT(R_REJECTED); 1.248 + } 1.249 + 1.250 + *error_code = attr->u.error_code.number; 1.251 + 1.252 + switch (attr->u.error_code.number / 100) { 1.253 + case 3: 1.254 + /* If the error code is 300 through 399, the client SHOULD consider 1.255 + * the transaction as failed unless the ALTERNATE-SERVER extension is 1.256 + * being used. See Section 11. */ 1.257 + 1.258 + if (attr->u.error_code.number == 300) { 1.259 + if (!nr_stun_message_has_attribute(res, NR_STUN_ATTR_ALTERNATE_SERVER, 0)) { 1.260 + r_log(NR_LOG_STUN, LOG_WARNING, "Missing ALTERNATE-SERVER"); 1.261 + ABORT(R_REJECTED); 1.262 + } 1.263 + 1.264 + /* draft-ietf-behave-rfc3489bis-10.txt S 11 */ 1.265 + if (!nr_stun_message_has_attribute(res, NR_STUN_ATTR_MESSAGE_INTEGRITY, 0)) { 1.266 + r_log(NR_LOG_STUN, LOG_WARNING, "Missing MESSAGE-INTEGRITY"); 1.267 + ABORT(R_REJECTED); 1.268 + } 1.269 + 1.270 + ABORT(R_RETRY); 1.271 + } 1.272 + 1.273 + ABORT(R_REJECTED); 1.274 + break; 1.275 + 1.276 + case 4: 1.277 + /* If the error code is 400 through 499, the client declares the 1.278 + * transaction failed; in the case of 420 (Unknown Attribute), the 1.279 + * response should contain a UNKNOWN-ATTRIBUTES attribute that gives 1.280 + * additional information. */ 1.281 + if (attr->u.error_code.number == 420) 1.282 + ABORT(R_REJECTED); 1.283 + 1.284 + /* it may be possible to restart given the info that was received in 1.285 + * this response, so retry */ 1.286 + ABORT(R_RETRY); 1.287 + break; 1.288 + 1.289 + case 5: 1.290 + /* If the error code is 500 through 599, the client MAY resend the 1.291 + * request; clients that do so MUST limit the number of times they do 1.292 + * this. */ 1.293 + /* let the retransmit mechanism handle resending the request */ 1.294 + break; 1.295 + 1.296 + default: 1.297 + ABORT(R_REJECTED); 1.298 + break; 1.299 + } 1.300 + 1.301 + /* the spec says: "The client then does any processing specified by the authentication 1.302 + * mechanism (see Section 10). This may result in a new transaction 1.303 + * attempt." -- but this is handled already elsewhere, so needn't be repeated 1.304 + * in this function */ 1.305 + 1.306 + _status=0; 1.307 + abort: 1.308 + return _status; 1.309 +} 1.310 + 1.311 +/* draft-ietf-behave-rfc3489bis-10.txt S 10.1.2 */ 1.312 +int 1.313 +nr_stun_receive_request_or_indication_short_term_auth(nr_stun_message *msg, 1.314 + nr_stun_message *res) 1.315 +{ 1.316 + int _status; 1.317 + nr_stun_message_attribute *attr; 1.318 + 1.319 + switch (msg->header.magic_cookie) { 1.320 + default: 1.321 + /* in RFC 3489 there is no magic cookie, it's part of the transaction ID */ 1.322 + /* drop thru */ 1.323 + case NR_STUN_MAGIC_COOKIE: 1.324 + if (!nr_stun_message_has_attribute(msg, NR_STUN_ATTR_MESSAGE_INTEGRITY, &attr)) { 1.325 + nr_stun_form_error_response(msg, res, 400, "Missing MESSAGE-INTEGRITY"); 1.326 + ABORT(R_ALREADY); 1.327 + } 1.328 + 1.329 + if (!nr_stun_message_has_attribute(msg, NR_STUN_ATTR_USERNAME, 0)) { 1.330 + nr_stun_form_error_response(msg, res, 400, "Missing USERNAME"); 1.331 + ABORT(R_ALREADY); 1.332 + } 1.333 + 1.334 + if (attr->u.message_integrity.unknown_user) { 1.335 + nr_stun_form_error_response(msg, res, 401, "Unrecognized USERNAME"); 1.336 + ABORT(R_ALREADY); 1.337 + } 1.338 + 1.339 + if (!attr->u.message_integrity.valid) { 1.340 + nr_stun_form_error_response(msg, res, 401, "Bad MESSAGE-INTEGRITY"); 1.341 + ABORT(R_ALREADY); 1.342 + } 1.343 + 1.344 + break; 1.345 + 1.346 +#ifdef USE_STUND_0_96 1.347 + case NR_STUN_MAGIC_COOKIE2: 1.348 + /* nothing to check in this case */ 1.349 + break; 1.350 +#endif /* USE_STUND_0_96 */ 1.351 + } 1.352 + 1.353 + _status=0; 1.354 + abort: 1.355 + return _status; 1.356 +} 1.357 + 1.358 +/* draft-ietf-behave-rfc3489bis-10.txt S 10.1.3 */ 1.359 +int 1.360 +nr_stun_receive_response_short_term_auth(nr_stun_message *res) 1.361 +{ 1.362 + int _status; 1.363 + nr_stun_message_attribute *attr; 1.364 + 1.365 + switch (res->header.magic_cookie) { 1.366 + default: 1.367 + /* in RFC 3489 there is no magic cookie, it's part of the transaction ID */ 1.368 + /* drop thru */ 1.369 + case NR_STUN_MAGIC_COOKIE: 1.370 + if (!nr_stun_message_has_attribute(res, NR_STUN_ATTR_MESSAGE_INTEGRITY, &attr)) { 1.371 + r_log(NR_LOG_STUN, LOG_WARNING, "Missing MESSAGE-INTEGRITY"); 1.372 + ABORT(R_REJECTED); 1.373 + } 1.374 + 1.375 + if (!attr->u.message_integrity.valid) { 1.376 + r_log(NR_LOG_STUN, LOG_WARNING, "Bad MESSAGE-INTEGRITY"); 1.377 + ABORT(R_REJECTED); 1.378 + } 1.379 + 1.380 + break; 1.381 + 1.382 +#ifdef USE_STUND_0_96 1.383 + case NR_STUN_MAGIC_COOKIE2: 1.384 + /* nothing to check in this case */ 1.385 + break; 1.386 +#endif /* USE_STUND_0_96 */ 1.387 + } 1.388 + 1.389 + _status=0; 1.390 + abort: 1.391 + return _status; 1.392 +} 1.393 + 1.394 +static int 1.395 +nr_stun_add_realm_and_nonce(int new_nonce, nr_stun_server_client *clnt, nr_stun_message *res) 1.396 +{ 1.397 + int r,_status; 1.398 + char *realm = 0; 1.399 + char *nonce; 1.400 + UINT2 size; 1.401 + 1.402 + if ((r=NR_reg_alloc_string(NR_STUN_REG_PREF_SERVER_REALM, &realm))) 1.403 + ABORT(r); 1.404 + 1.405 + if ((r=nr_stun_message_add_realm_attribute(res, realm))) 1.406 + ABORT(r); 1.407 + 1.408 + if (clnt) { 1.409 + if (strlen(clnt->nonce) < 1) 1.410 + new_nonce = 1; 1.411 + 1.412 + if (new_nonce) { 1.413 + if (NR_reg_get_uint2(NR_STUN_REG_PREF_SERVER_NONCE_SIZE, &size)) 1.414 + size = 48; 1.415 + 1.416 + if (size > (sizeof(clnt->nonce) - 1)) 1.417 + size = sizeof(clnt->nonce) - 1; 1.418 + 1.419 + nr_random_alphanum(clnt->nonce, size); 1.420 + clnt->nonce[size] = '\0'; 1.421 + } 1.422 + 1.423 + nonce = clnt->nonce; 1.424 + } 1.425 + else { 1.426 + /* user is not known, so use a bogus nonce since there's no way to 1.427 + * store a good nonce with the client-specific data -- this nonce 1.428 + * will be recognized as stale if the client attempts another 1.429 + * request */ 1.430 + nonce = "STALE"; 1.431 + } 1.432 + 1.433 + if ((r=nr_stun_message_add_nonce_attribute(res, nonce))) 1.434 + ABORT(r); 1.435 + 1.436 + _status=0; 1.437 + abort: 1.438 +#ifdef USE_TURN 1.439 +assert(_status == 0); /* TODO: !nn! cleanup after I reimplmement TURN */ 1.440 +#endif 1.441 + RFREE(realm); 1.442 + return _status; 1.443 +} 1.444 + 1.445 +/* draft-ietf-behave-rfc3489bis-10.txt S 10.2.1 - 10.2.2 */ 1.446 +int 1.447 +nr_stun_receive_request_long_term_auth(nr_stun_message *req, nr_stun_server_ctx *ctx, nr_stun_message *res) 1.448 +{ 1.449 + int r,_status; 1.450 + nr_stun_message_attribute *mi; 1.451 + nr_stun_message_attribute *n; 1.452 + nr_stun_server_client *clnt = 0; 1.453 + 1.454 + switch (req->header.magic_cookie) { 1.455 + default: 1.456 + /* in RFC 3489 there is no magic cookie, it's part of the transaction ID */ 1.457 + /* drop thru */ 1.458 + case NR_STUN_MAGIC_COOKIE: 1.459 + if (!nr_stun_message_has_attribute(req, NR_STUN_ATTR_USERNAME, 0)) { 1.460 + nr_stun_form_error_response(req, res, 400, "Missing USERNAME"); 1.461 + nr_stun_add_realm_and_nonce(0, 0, res); 1.462 + ABORT(R_ALREADY); 1.463 + } 1.464 + 1.465 + if ((r=nr_stun_get_message_client(ctx, req, &clnt))) { 1.466 + nr_stun_form_error_response(req, res, 401, "Unrecognized USERNAME"); 1.467 + nr_stun_add_realm_and_nonce(0, 0, res); 1.468 + ABORT(R_ALREADY); 1.469 + } 1.470 + 1.471 + if (!nr_stun_message_has_attribute(req, NR_STUN_ATTR_MESSAGE_INTEGRITY, &mi)) { 1.472 + nr_stun_form_error_response(req, res, 401, "Missing MESSAGE-INTEGRITY"); 1.473 + nr_stun_add_realm_and_nonce(0, clnt, res); 1.474 + ABORT(R_ALREADY); 1.475 + } 1.476 + 1.477 + assert(!mi->u.message_integrity.unknown_user); 1.478 + 1.479 + if (!nr_stun_message_has_attribute(req, NR_STUN_ATTR_REALM, 0)) { 1.480 + nr_stun_form_error_response(req, res, 400, "Missing REALM"); 1.481 + ABORT(R_ALREADY); 1.482 + } 1.483 + 1.484 + if (!nr_stun_message_has_attribute(req, NR_STUN_ATTR_NONCE, &n)) { 1.485 + nr_stun_form_error_response(req, res, 400, "Missing NONCE"); 1.486 + ABORT(R_ALREADY); 1.487 + } 1.488 + 1.489 + assert(sizeof(clnt->nonce) == sizeof(n->u.nonce)); 1.490 + if (strncmp(clnt->nonce, n->u.nonce, sizeof(n->u.nonce))) { 1.491 + nr_stun_form_error_response(req, res, 438, "Stale NONCE"); 1.492 + nr_stun_add_realm_and_nonce(1, clnt, res); 1.493 + ABORT(R_ALREADY); 1.494 + } 1.495 + 1.496 + if (!mi->u.message_integrity.valid) { 1.497 + nr_stun_form_error_response(req, res, 401, "Bad MESSAGE-INTEGRITY"); 1.498 + nr_stun_add_realm_and_nonce(0, clnt, res); 1.499 + ABORT(R_ALREADY); 1.500 + } 1.501 + 1.502 + break; 1.503 + 1.504 +#ifdef USE_STUND_0_96 1.505 + case NR_STUN_MAGIC_COOKIE2: 1.506 + /* nothing to do in this case */ 1.507 + break; 1.508 +#endif /* USE_STUND_0_96 */ 1.509 + } 1.510 + 1.511 + _status=0; 1.512 + abort: 1.513 + 1.514 + return _status; 1.515 +} 1.516 + 1.517 +/* draft-ietf-behave-rfc3489bis-10.txt S 10.2.3 */ 1.518 +int 1.519 +nr_stun_receive_response_long_term_auth(nr_stun_message *res, nr_stun_client_ctx *ctx) 1.520 +{ 1.521 + int _status; 1.522 + nr_stun_message_attribute *attr; 1.523 + 1.524 + switch (res->header.magic_cookie) { 1.525 + default: 1.526 + /* in RFC 3489 there is no magic cookie, it's part of the transaction ID */ 1.527 + /* drop thru */ 1.528 + case NR_STUN_MAGIC_COOKIE: 1.529 + if (nr_stun_message_has_attribute(res, NR_STUN_ATTR_REALM, &attr)) { 1.530 + RFREE(ctx->realm); 1.531 + ctx->realm = r_strdup(attr->u.realm); 1.532 + if (!ctx->realm) 1.533 + ABORT(R_NO_MEMORY); 1.534 + } 1.535 + else { 1.536 + r_log(NR_LOG_STUN, LOG_WARNING, "Missing REALM"); 1.537 + ABORT(R_REJECTED); 1.538 + } 1.539 + 1.540 + if (nr_stun_message_has_attribute(res, NR_STUN_ATTR_NONCE, &attr)) { 1.541 + RFREE(ctx->nonce); 1.542 + ctx->nonce = r_strdup(attr->u.nonce); 1.543 + if (!ctx->nonce) 1.544 + ABORT(R_NO_MEMORY); 1.545 + } 1.546 + else { 1.547 + r_log(NR_LOG_STUN, LOG_WARNING, "Missing NONCE"); 1.548 + ABORT(R_REJECTED); 1.549 + } 1.550 + 1.551 + if (nr_stun_message_has_attribute(res, NR_STUN_ATTR_MESSAGE_INTEGRITY, &attr)) { 1.552 + if (!attr->u.message_integrity.valid) { 1.553 + r_log(NR_LOG_STUN, LOG_WARNING, "Bad MESSAGE-INTEGRITY"); 1.554 + ABORT(R_REJECTED); 1.555 + } 1.556 + } 1.557 + 1.558 + break; 1.559 + 1.560 +#ifdef USE_STUND_0_96 1.561 + case NR_STUN_MAGIC_COOKIE2: 1.562 + /* nothing to check in this case */ 1.563 + break; 1.564 +#endif /* USE_STUND_0_96 */ 1.565 + } 1.566 + 1.567 + _status=0; 1.568 + abort: 1.569 + return _status; 1.570 +} 1.571 +