1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/mtransport/third_party/nICEr/src/stun/stun_build.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,614 @@ 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_build.c,v 1.2 2008/04/28 18:21:30 ekr Exp $"; 1.38 + 1.39 +#include <csi_platform.h> 1.40 +#include <assert.h> 1.41 +#include <errno.h> 1.42 +#include <stdio.h> 1.43 +#include <string.h> 1.44 +#include <ctype.h> 1.45 + 1.46 +#include "nr_api.h" 1.47 +#include "stun.h" 1.48 +#include "registry.h" 1.49 +#include "stun_reg.h" 1.50 +#include "nr_crypto.h" 1.51 + 1.52 + 1.53 +/* draft-ietf-behave-rfc3489bis-10.txt S 7.1 */ 1.54 +/* draft-ietf-behave-rfc3489bis-10.txt S 10.1.1 */ 1.55 +/* note that S 10.1.1 states the message MUST include MESSAGE-INTEGRITY 1.56 + * and USERNAME, but that's not correct -- for instance ICE keepalive 1.57 + * messages don't include these (See draft-ietf-mmusic-ice-18.txt S 10: 1.58 + * "If STUN is being used for keepalives, a STUN Binding Indication is 1.59 + * used. The Indication MUST NOT utilize any authentication mechanism") 1.60 + */ 1.61 +int 1.62 +nr_stun_form_request_or_indication(int mode, int msg_type, nr_stun_message **msg) 1.63 +{ 1.64 + int r,_status; 1.65 + nr_stun_message *req = 0; 1.66 + 1.67 + assert(NR_STUN_GET_TYPE_CLASS(msg_type) == NR_CLASS_REQUEST 1.68 + || NR_STUN_GET_TYPE_CLASS(msg_type) == NR_CLASS_INDICATION); 1.69 + 1.70 + *msg = 0; 1.71 + 1.72 + if ((r=nr_stun_message_create(&req))) 1.73 + ABORT(r); 1.74 + 1.75 + req->header.type = msg_type; 1.76 + 1.77 + nr_crypto_random_bytes((UCHAR*)&req->header.id,sizeof(req->header.id)); 1.78 + 1.79 + switch (mode) { 1.80 + default: 1.81 + req->header.magic_cookie = NR_STUN_MAGIC_COOKIE; 1.82 + 1.83 + if ((r=nr_stun_message_add_fingerprint_attribute(req))) 1.84 + ABORT(r); 1.85 + 1.86 + break; 1.87 + 1.88 +#ifdef USE_STUND_0_96 1.89 + case NR_STUN_MODE_STUND_0_96: 1.90 + req->header.magic_cookie = NR_STUN_MAGIC_COOKIE2; 1.91 + 1.92 + /* actually, stund 0.96 just ignores the fingerprint 1.93 + * attribute, but don't bother to send it */ 1.94 + 1.95 + break; 1.96 +#endif /* USE_STUND_0_96 */ 1.97 + 1.98 + } 1.99 + 1.100 + *msg = req; 1.101 + 1.102 + _status=0; 1.103 + abort: 1.104 + if (_status) RFREE(req); 1.105 + return _status; 1.106 +} 1.107 + 1.108 +int 1.109 +nr_stun_build_req_lt_auth(nr_stun_client_stun_binding_request_params *params, nr_stun_message **msg) 1.110 +{ 1.111 + int r,_status; 1.112 + nr_stun_message *req = 0; 1.113 + 1.114 + if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_BINDING_REQUEST, &req))) 1.115 + ABORT(r); 1.116 + 1.117 + if ((r=nr_stun_message_add_username_attribute(req, params->username))) 1.118 + ABORT(r); 1.119 + 1.120 + if (params->realm && params->nonce) { 1.121 + if ((r=nr_stun_message_add_realm_attribute(req, params->realm))) 1.122 + ABORT(r); 1.123 + 1.124 + if ((r=nr_stun_message_add_nonce_attribute(req, params->nonce))) 1.125 + ABORT(r); 1.126 + 1.127 + if ((r=nr_stun_message_add_message_integrity_attribute(req, params->password))) 1.128 + ABORT(r); 1.129 + } 1.130 + 1.131 + *msg = req; 1.132 + 1.133 + _status=0; 1.134 + abort: 1.135 + if (_status) nr_stun_message_destroy(&req); 1.136 + return _status; 1.137 +} 1.138 + 1.139 +int 1.140 +nr_stun_build_req_st_auth(nr_stun_client_stun_binding_request_params *params, nr_stun_message **msg) 1.141 +{ 1.142 + int r,_status; 1.143 + nr_stun_message *req = 0; 1.144 + 1.145 + if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_BINDING_REQUEST, &req))) 1.146 + ABORT(r); 1.147 + 1.148 + if ((r=nr_stun_message_add_username_attribute(req, params->username))) 1.149 + ABORT(r); 1.150 + 1.151 + if (params->password) { 1.152 + if ((r=nr_stun_message_add_message_integrity_attribute(req, params->password))) 1.153 + ABORT(r); 1.154 + } 1.155 + 1.156 + *msg = req; 1.157 + 1.158 + _status=0; 1.159 + abort: 1.160 + if (_status) nr_stun_message_destroy(&req); 1.161 + return _status; 1.162 +} 1.163 + 1.164 +int 1.165 +nr_stun_build_req_no_auth(nr_stun_client_stun_binding_request_params *params, nr_stun_message **msg) 1.166 +{ 1.167 + int r,_status; 1.168 + nr_stun_message *req = 0; 1.169 + 1.170 + if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_BINDING_REQUEST, &req))) 1.171 + ABORT(r); 1.172 + 1.173 + *msg = req; 1.174 + 1.175 + _status=0; 1.176 + abort: 1.177 + if (_status) nr_stun_message_destroy(&req); 1.178 + return _status; 1.179 +} 1.180 + 1.181 +int 1.182 +nr_stun_build_keepalive(nr_stun_client_stun_keepalive_params *params, nr_stun_message **msg) 1.183 +{ 1.184 + int r,_status; 1.185 + nr_stun_message *ind = 0; 1.186 + 1.187 + if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_BINDING_INDICATION, &ind))) 1.188 + ABORT(r); 1.189 + 1.190 + *msg = ind; 1.191 + 1.192 + _status=0; 1.193 + abort: 1.194 + if (_status) nr_stun_message_destroy(&ind); 1.195 + return _status; 1.196 +} 1.197 + 1.198 +#ifdef USE_STUND_0_96 1.199 +int 1.200 +nr_stun_build_req_stund_0_96(nr_stun_client_stun_binding_request_stund_0_96_params *params, nr_stun_message **msg) 1.201 +{ 1.202 + int r,_status; 1.203 + nr_stun_message *req = 0; 1.204 + 1.205 + if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUND_0_96, NR_STUN_MSG_BINDING_REQUEST, &req))) 1.206 + ABORT(r); 1.207 + 1.208 + if ((r=nr_stun_message_add_change_request_attribute(req, 0))) 1.209 + ABORT(r); 1.210 + 1.211 + assert(! nr_stun_message_has_attribute(req, NR_STUN_ATTR_USERNAME, 0)); 1.212 + assert(! nr_stun_message_has_attribute(req, NR_STUN_ATTR_MESSAGE_INTEGRITY, 0)); 1.213 + 1.214 + *msg = req; 1.215 + 1.216 + _status=0; 1.217 + abort: 1.218 + if (_status) nr_stun_message_destroy(&req); 1.219 + return _status; 1.220 +} 1.221 +#endif /* USE_STUND_0_96 */ 1.222 + 1.223 +#ifdef USE_ICE 1.224 +int 1.225 +nr_stun_build_use_candidate(nr_stun_client_ice_use_candidate_params *params, nr_stun_message **msg) 1.226 +{ 1.227 + int r,_status; 1.228 + nr_stun_message *req = 0; 1.229 + 1.230 + if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_BINDING_REQUEST, &req))) 1.231 + ABORT(r); 1.232 + 1.233 + if ((r=nr_stun_message_add_username_attribute(req, params->username))) 1.234 + ABORT(r); 1.235 + 1.236 + if ((r=nr_stun_message_add_message_integrity_attribute(req, ¶ms->password))) 1.237 + ABORT(r); 1.238 + 1.239 + if ((r=nr_stun_message_add_use_candidate_attribute(req))) 1.240 + ABORT(r); 1.241 + 1.242 + if ((r=nr_stun_message_add_priority_attribute(req, params->priority))) 1.243 + ABORT(r); 1.244 + 1.245 + if ((r=nr_stun_message_add_ice_controlling_attribute(req, params->tiebreaker))) 1.246 + ABORT(r); 1.247 + 1.248 + *msg = req; 1.249 + 1.250 + _status=0; 1.251 + abort: 1.252 + if (_status) nr_stun_message_destroy(&req); 1.253 + return _status; 1.254 +} 1.255 + 1.256 +int 1.257 +nr_stun_build_req_ice(nr_stun_client_ice_binding_request_params *params, nr_stun_message **msg) 1.258 +{ 1.259 + int r,_status; 1.260 + nr_stun_message *req = 0; 1.261 + 1.262 + if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_BINDING_REQUEST, &req))) 1.263 + ABORT(r); 1.264 + 1.265 + if ((r=nr_stun_message_add_username_attribute(req, params->username))) 1.266 + ABORT(r); 1.267 + 1.268 + if ((r=nr_stun_message_add_message_integrity_attribute(req, ¶ms->password))) 1.269 + ABORT(r); 1.270 + 1.271 + if ((r=nr_stun_message_add_priority_attribute(req, params->priority))) 1.272 + ABORT(r); 1.273 + 1.274 + switch (params->control) { 1.275 + case NR_ICE_CONTROLLING: 1.276 + if ((r=nr_stun_message_add_ice_controlling_attribute(req, params->tiebreaker))) 1.277 + ABORT(r); 1.278 + break; 1.279 + case NR_ICE_CONTROLLED: 1.280 + if ((r=nr_stun_message_add_ice_controlled_attribute(req, params->tiebreaker))) 1.281 + ABORT(r); 1.282 + break; 1.283 + default: 1.284 + assert(0); 1.285 + ABORT(R_INTERNAL); 1.286 + } 1.287 + 1.288 + *msg = req; 1.289 + 1.290 + _status=0; 1.291 + abort: 1.292 + if (_status) nr_stun_message_destroy(&req); 1.293 + return _status; 1.294 +} 1.295 +#endif /* USE_ICE */ 1.296 + 1.297 +#ifdef USE_TURN 1.298 + 1.299 +#ifndef __isascii 1.300 +#define __isascii(c) (((c) & ~0x7F) == 0) 1.301 +#endif 1.302 + 1.303 +/* Long-term passwords are computed over the key: 1.304 + 1.305 + key = MD5(username ":" realm ":" SASLprep(password)) 1.306 + 1.307 + Per RFC 5389 S 15.4 1.308 +*/ 1.309 +int 1.310 +nr_stun_compute_lt_message_integrity_password(const char *username, const char *realm, 1.311 + Data *password, Data *hmac_key) 1.312 +{ 1.313 + char digest_input[1000]; 1.314 + int i; 1.315 + int r, _status; 1.316 + size_t len; 1.317 + 1.318 + /* First check that the password is ASCII. We are supposed to 1.319 + SASLprep but we don't support this yet 1.320 + TODO(ekr@rtfm.com): Add SASLprep for password. 1.321 + */ 1.322 + for (i=0; i<password->len; i++) { 1.323 + if (!__isascii(password->data[i])) 1.324 + ABORT(R_BAD_DATA); 1.325 + } 1.326 + 1.327 + if (hmac_key->len < 16) 1.328 + ABORT(R_BAD_ARGS); 1.329 + 1.330 + snprintf(digest_input, sizeof(digest_input), "%s:%s:", username, realm); 1.331 + if ((sizeof(digest_input) - strlen(digest_input)) < password->len) 1.332 + ABORT(R_BAD_DATA); 1.333 + 1.334 + len = strlen(digest_input); 1.335 + memcpy(digest_input + len, password->data, password->len); 1.336 + 1.337 + 1.338 + if (r=nr_crypto_md5((UCHAR *)digest_input, len + password->len, hmac_key->data)) 1.339 + ABORT(r); 1.340 + hmac_key->len=16; 1.341 + 1.342 + _status=0; 1.343 +abort: 1.344 + return(_status); 1.345 +} 1.346 + 1.347 +static int 1.348 +nr_stun_build_auth_params(nr_stun_client_auth_params *auth, nr_stun_message *req) 1.349 +{ 1.350 + int r, _status; 1.351 + UCHAR hmac_key_d[16]; 1.352 + Data hmac_key; 1.353 + 1.354 + ATTACH_DATA(hmac_key, hmac_key_d); 1.355 + 1.356 + if (!auth->authenticate) 1.357 + goto done; 1.358 + 1.359 + assert(auth->username); 1.360 + assert(auth->password.len); 1.361 + assert(auth->realm); 1.362 + assert(auth->nonce); 1.363 + 1.364 + if (r=nr_stun_compute_lt_message_integrity_password(auth->username, 1.365 + auth->realm, 1.366 + &auth->password, 1.367 + &hmac_key)) 1.368 + ABORT(r); 1.369 + 1.370 + if (!auth->username) { 1.371 + r_log(NR_LOG_STUN, LOG_WARNING, "STUN authentication requested but no username provided"); 1.372 + ABORT(R_INTERNAL); 1.373 + } 1.374 + 1.375 + if (!auth->password.len) { 1.376 + r_log(NR_LOG_STUN, LOG_WARNING, "STUN authentication requested but no password provided"); 1.377 + ABORT(R_INTERNAL); 1.378 + } 1.379 + 1.380 + if (!auth->realm) { 1.381 + r_log(NR_LOG_STUN, LOG_WARNING, "STUN authentication requested but no realm provided"); 1.382 + ABORT(R_INTERNAL); 1.383 + } 1.384 + 1.385 + if (!auth->nonce) { 1.386 + r_log(NR_LOG_STUN, LOG_WARNING, "STUN authentication requested but no nonce provided"); 1.387 + ABORT(R_INTERNAL); 1.388 + } 1.389 + 1.390 + if ((r=nr_stun_message_add_username_attribute(req, auth->username))) 1.391 + ABORT(r); 1.392 + 1.393 + if ((r=nr_stun_message_add_realm_attribute(req, auth->realm))) 1.394 + ABORT(r); 1.395 + 1.396 + if ((r=nr_stun_message_add_nonce_attribute(req, auth->nonce))) 1.397 + ABORT(r); 1.398 + 1.399 + if ((r=nr_stun_message_add_message_integrity_attribute(req, &hmac_key))) 1.400 + ABORT(r); 1.401 + 1.402 +done: 1.403 + _status=0; 1.404 +abort: 1.405 + return(_status); 1.406 +} 1.407 + 1.408 +int 1.409 +nr_stun_build_allocate_request(nr_stun_client_auth_params *auth, nr_stun_client_allocate_request_params *params, nr_stun_message **msg) 1.410 +{ 1.411 + int r,_status; 1.412 + nr_stun_message *req = 0; 1.413 + 1.414 + if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_ALLOCATE_REQUEST, &req))) 1.415 + ABORT(r); 1.416 + 1.417 + if ((r=nr_stun_message_add_requested_transport_attribute(req, NR_STUN_ATTR_REQUESTED_TRANSPORT_UDP))) 1.418 + ABORT(r); 1.419 + 1.420 + if ((r=nr_stun_message_add_lifetime_attribute(req, params->lifetime_secs))) 1.421 + ABORT(r); 1.422 + 1.423 + /* TODO(ekr@rtfm.com): Add the SOFTWARE attribute (Firefox bug 857666) */ 1.424 + 1.425 + if ((r=nr_stun_build_auth_params(auth, req))) 1.426 + ABORT(r); 1.427 + 1.428 + *msg = req; 1.429 + 1.430 + _status=0; 1.431 + abort: 1.432 + if (_status) nr_stun_message_destroy(&req); 1.433 + return _status; 1.434 +} 1.435 + 1.436 + 1.437 +int nr_stun_build_refresh_request(nr_stun_client_auth_params *auth, nr_stun_client_refresh_request_params *params, nr_stun_message **msg) 1.438 +{ 1.439 + int r,_status; 1.440 + nr_stun_message *req = 0; 1.441 + 1.442 + if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_REFRESH_REQUEST, &req))) 1.443 + ABORT(r); 1.444 + 1.445 + if ((r=nr_stun_message_add_lifetime_attribute(req, params->lifetime_secs))) 1.446 + ABORT(r); 1.447 + 1.448 + 1.449 + /* TODO(ekr@rtfm.com): Add the SOFTWARE attribute (Firefox bug 857666) */ 1.450 + 1.451 + if ((r=nr_stun_build_auth_params(auth, req))) 1.452 + ABORT(r); 1.453 + 1.454 + *msg = req; 1.455 + 1.456 + _status=0; 1.457 + abort: 1.458 + if (_status) nr_stun_message_destroy(&req); 1.459 + return _status; 1.460 +} 1.461 + 1.462 + 1.463 +int nr_stun_build_permission_request(nr_stun_client_auth_params *auth, nr_stun_client_permission_request_params *params, nr_stun_message **msg) 1.464 +{ 1.465 + int r,_status; 1.466 + nr_stun_message *req = 0; 1.467 + 1.468 + if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_PERMISSION_REQUEST, &req))) 1.469 + ABORT(r); 1.470 + 1.471 + if ((r=nr_stun_message_add_xor_peer_address_attribute(req, ¶ms->remote_addr))) 1.472 + ABORT(r); 1.473 + 1.474 + if ((r=nr_stun_build_auth_params(auth, req))) 1.475 + ABORT(r); 1.476 + 1.477 + *msg = req; 1.478 + 1.479 + _status=0; 1.480 + abort: 1.481 + if (_status) nr_stun_message_destroy(&req); 1.482 + return _status; 1.483 +} 1.484 + 1.485 +int 1.486 +nr_stun_build_send_indication(nr_stun_client_send_indication_params *params, nr_stun_message **msg) 1.487 +{ 1.488 + int r,_status; 1.489 + nr_stun_message *ind = 0; 1.490 + 1.491 + if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_SEND_INDICATION, &ind))) 1.492 + ABORT(r); 1.493 + 1.494 + if ((r=nr_stun_message_add_xor_peer_address_attribute(ind, ¶ms->remote_addr))) 1.495 + ABORT(r); 1.496 + 1.497 + if ((r=nr_stun_message_add_data_attribute(ind, params->data.data, params->data.len))) 1.498 + ABORT(r); 1.499 + 1.500 + *msg = ind; 1.501 + 1.502 + _status=0; 1.503 + abort: 1.504 + if (_status) nr_stun_message_destroy(&ind); 1.505 + return _status; 1.506 +} 1.507 + 1.508 +int 1.509 +nr_stun_build_data_indication(nr_stun_client_data_indication_params *params, nr_stun_message **msg) 1.510 +{ 1.511 + int r,_status; 1.512 + nr_stun_message *ind = 0; 1.513 + 1.514 + if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_DATA_INDICATION, &ind))) 1.515 + ABORT(r); 1.516 + 1.517 + if ((r=nr_stun_message_add_xor_peer_address_attribute(ind, ¶ms->remote_addr))) 1.518 + ABORT(r); 1.519 + 1.520 + if ((r=nr_stun_message_add_data_attribute(ind, params->data.data, params->data.len))) 1.521 + ABORT(r); 1.522 + 1.523 + *msg = ind; 1.524 + 1.525 + _status=0; 1.526 + abort: 1.527 + if (_status) nr_stun_message_destroy(&ind); 1.528 + return _status; 1.529 +} 1.530 + 1.531 +#endif /* USE_TURN */ 1.532 + 1.533 +/* draft-ietf-behave-rfc3489bis-10.txt S 7.3.1.1 */ 1.534 +int 1.535 +nr_stun_form_success_response(nr_stun_message *req, nr_transport_addr *from, Data *password, nr_stun_message *res) 1.536 +{ 1.537 + int r,_status; 1.538 + int request_method; 1.539 + char server_name[NR_STUN_MAX_SERVER_BYTES+1]; /* +1 for \0 */ 1.540 + 1.541 + /* set up information for default response */ 1.542 + 1.543 + request_method = NR_STUN_GET_TYPE_METHOD(req->header.type); 1.544 + res->header.type = NR_STUN_TYPE(request_method, NR_CLASS_RESPONSE); 1.545 + res->header.magic_cookie = req->header.magic_cookie; 1.546 + memcpy(&res->header.id, &req->header.id, sizeof(res->header.id)); 1.547 + 1.548 + r_log(NR_LOG_STUN, LOG_DEBUG, "Mapped Address = %s", from->as_string); 1.549 + 1.550 + if ((r=nr_stun_message_add_xor_mapped_address_attribute(res, from))) 1.551 + ABORT(r); 1.552 + 1.553 + if (!NR_reg_get_string(NR_STUN_REG_PREF_SERVER_NAME, server_name, sizeof(server_name))) { 1.554 + if ((r=nr_stun_message_add_server_attribute(res, server_name))) 1.555 + ABORT(r); 1.556 + } 1.557 + 1.558 + if (res->header.magic_cookie == NR_STUN_MAGIC_COOKIE) { 1.559 + if (password != 0) { 1.560 + if ((r=nr_stun_message_add_message_integrity_attribute(res, password))) 1.561 + ABORT(r); 1.562 + } 1.563 + 1.564 + if ((r=nr_stun_message_add_fingerprint_attribute(res))) 1.565 + ABORT(r); 1.566 + } 1.567 + 1.568 + _status=0; 1.569 + abort: 1.570 + return _status; 1.571 +} 1.572 + 1.573 +/* draft-ietf-behave-rfc3489bis-10.txt S 7.3.1.1 */ 1.574 +void 1.575 +nr_stun_form_error_response(nr_stun_message *req, nr_stun_message* res, int number, char* msg) 1.576 +{ 1.577 + char *str; 1.578 + int request_method; 1.579 + char server_name[NR_STUN_MAX_SERVER_BYTES+1]; /* +1 for \0 */ 1.580 + 1.581 + if (number < 300 || number > 699) 1.582 + number = 500; 1.583 + 1.584 + r_log(NR_LOG_STUN, LOG_INFO, "Responding with error %d: %s", number, msg); 1.585 + 1.586 + request_method = NR_STUN_GET_TYPE_METHOD(req->header.type); 1.587 + res->header.type = NR_STUN_TYPE(request_method, NR_CLASS_ERROR_RESPONSE); 1.588 + res->header.magic_cookie = req->header.magic_cookie; 1.589 + memcpy(&res->header.id, &req->header.id, sizeof(res->header.id)); 1.590 + 1.591 + /* during development we should never see 500s (hopefully not in deployment either) */ 1.592 + 1.593 + str = 0; 1.594 + switch (number) { 1.595 + case 300: str = "Try Alternate"; break; 1.596 + case 400: str = "Bad Request"; break; 1.597 + case 401: str = "Unauthorized"; break; 1.598 + case 420: str = "Unknown Attribute"; break; 1.599 + case 438: str = "Stale Nonce"; break; 1.600 +#ifdef USE_ICE 1.601 + case 487: str = "Role Conflict"; break; 1.602 +#endif 1.603 + case 500: str = "Server Error"; break; 1.604 + } 1.605 + if (str == 0) { 1.606 + str = "Unknown"; 1.607 + } 1.608 + 1.609 + if (nr_stun_message_add_error_code_attribute(res, number, str)) { 1.610 + assert(0); /* should never happen */ 1.611 + } 1.612 + 1.613 + if (!NR_reg_get_string(NR_STUN_REG_PREF_SERVER_NAME, server_name, sizeof(server_name))) { 1.614 + nr_stun_message_add_server_attribute(res, server_name); 1.615 + } 1.616 +} 1.617 +