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

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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_build.c,v 1.2 2008/04/28 18:21:30 ekr Exp $";
michael@0 35
michael@0 36 #include <csi_platform.h>
michael@0 37 #include <assert.h>
michael@0 38 #include <errno.h>
michael@0 39 #include <stdio.h>
michael@0 40 #include <string.h>
michael@0 41 #include <ctype.h>
michael@0 42
michael@0 43 #include "nr_api.h"
michael@0 44 #include "stun.h"
michael@0 45 #include "registry.h"
michael@0 46 #include "stun_reg.h"
michael@0 47 #include "nr_crypto.h"
michael@0 48
michael@0 49
michael@0 50 /* draft-ietf-behave-rfc3489bis-10.txt S 7.1 */
michael@0 51 /* draft-ietf-behave-rfc3489bis-10.txt S 10.1.1 */
michael@0 52 /* note that S 10.1.1 states the message MUST include MESSAGE-INTEGRITY
michael@0 53 * and USERNAME, but that's not correct -- for instance ICE keepalive
michael@0 54 * messages don't include these (See draft-ietf-mmusic-ice-18.txt S 10:
michael@0 55 * "If STUN is being used for keepalives, a STUN Binding Indication is
michael@0 56 * used. The Indication MUST NOT utilize any authentication mechanism")
michael@0 57 */
michael@0 58 int
michael@0 59 nr_stun_form_request_or_indication(int mode, int msg_type, nr_stun_message **msg)
michael@0 60 {
michael@0 61 int r,_status;
michael@0 62 nr_stun_message *req = 0;
michael@0 63
michael@0 64 assert(NR_STUN_GET_TYPE_CLASS(msg_type) == NR_CLASS_REQUEST
michael@0 65 || NR_STUN_GET_TYPE_CLASS(msg_type) == NR_CLASS_INDICATION);
michael@0 66
michael@0 67 *msg = 0;
michael@0 68
michael@0 69 if ((r=nr_stun_message_create(&req)))
michael@0 70 ABORT(r);
michael@0 71
michael@0 72 req->header.type = msg_type;
michael@0 73
michael@0 74 nr_crypto_random_bytes((UCHAR*)&req->header.id,sizeof(req->header.id));
michael@0 75
michael@0 76 switch (mode) {
michael@0 77 default:
michael@0 78 req->header.magic_cookie = NR_STUN_MAGIC_COOKIE;
michael@0 79
michael@0 80 if ((r=nr_stun_message_add_fingerprint_attribute(req)))
michael@0 81 ABORT(r);
michael@0 82
michael@0 83 break;
michael@0 84
michael@0 85 #ifdef USE_STUND_0_96
michael@0 86 case NR_STUN_MODE_STUND_0_96:
michael@0 87 req->header.magic_cookie = NR_STUN_MAGIC_COOKIE2;
michael@0 88
michael@0 89 /* actually, stund 0.96 just ignores the fingerprint
michael@0 90 * attribute, but don't bother to send it */
michael@0 91
michael@0 92 break;
michael@0 93 #endif /* USE_STUND_0_96 */
michael@0 94
michael@0 95 }
michael@0 96
michael@0 97 *msg = req;
michael@0 98
michael@0 99 _status=0;
michael@0 100 abort:
michael@0 101 if (_status) RFREE(req);
michael@0 102 return _status;
michael@0 103 }
michael@0 104
michael@0 105 int
michael@0 106 nr_stun_build_req_lt_auth(nr_stun_client_stun_binding_request_params *params, nr_stun_message **msg)
michael@0 107 {
michael@0 108 int r,_status;
michael@0 109 nr_stun_message *req = 0;
michael@0 110
michael@0 111 if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_BINDING_REQUEST, &req)))
michael@0 112 ABORT(r);
michael@0 113
michael@0 114 if ((r=nr_stun_message_add_username_attribute(req, params->username)))
michael@0 115 ABORT(r);
michael@0 116
michael@0 117 if (params->realm && params->nonce) {
michael@0 118 if ((r=nr_stun_message_add_realm_attribute(req, params->realm)))
michael@0 119 ABORT(r);
michael@0 120
michael@0 121 if ((r=nr_stun_message_add_nonce_attribute(req, params->nonce)))
michael@0 122 ABORT(r);
michael@0 123
michael@0 124 if ((r=nr_stun_message_add_message_integrity_attribute(req, params->password)))
michael@0 125 ABORT(r);
michael@0 126 }
michael@0 127
michael@0 128 *msg = req;
michael@0 129
michael@0 130 _status=0;
michael@0 131 abort:
michael@0 132 if (_status) nr_stun_message_destroy(&req);
michael@0 133 return _status;
michael@0 134 }
michael@0 135
michael@0 136 int
michael@0 137 nr_stun_build_req_st_auth(nr_stun_client_stun_binding_request_params *params, nr_stun_message **msg)
michael@0 138 {
michael@0 139 int r,_status;
michael@0 140 nr_stun_message *req = 0;
michael@0 141
michael@0 142 if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_BINDING_REQUEST, &req)))
michael@0 143 ABORT(r);
michael@0 144
michael@0 145 if ((r=nr_stun_message_add_username_attribute(req, params->username)))
michael@0 146 ABORT(r);
michael@0 147
michael@0 148 if (params->password) {
michael@0 149 if ((r=nr_stun_message_add_message_integrity_attribute(req, params->password)))
michael@0 150 ABORT(r);
michael@0 151 }
michael@0 152
michael@0 153 *msg = req;
michael@0 154
michael@0 155 _status=0;
michael@0 156 abort:
michael@0 157 if (_status) nr_stun_message_destroy(&req);
michael@0 158 return _status;
michael@0 159 }
michael@0 160
michael@0 161 int
michael@0 162 nr_stun_build_req_no_auth(nr_stun_client_stun_binding_request_params *params, nr_stun_message **msg)
michael@0 163 {
michael@0 164 int r,_status;
michael@0 165 nr_stun_message *req = 0;
michael@0 166
michael@0 167 if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_BINDING_REQUEST, &req)))
michael@0 168 ABORT(r);
michael@0 169
michael@0 170 *msg = req;
michael@0 171
michael@0 172 _status=0;
michael@0 173 abort:
michael@0 174 if (_status) nr_stun_message_destroy(&req);
michael@0 175 return _status;
michael@0 176 }
michael@0 177
michael@0 178 int
michael@0 179 nr_stun_build_keepalive(nr_stun_client_stun_keepalive_params *params, nr_stun_message **msg)
michael@0 180 {
michael@0 181 int r,_status;
michael@0 182 nr_stun_message *ind = 0;
michael@0 183
michael@0 184 if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_BINDING_INDICATION, &ind)))
michael@0 185 ABORT(r);
michael@0 186
michael@0 187 *msg = ind;
michael@0 188
michael@0 189 _status=0;
michael@0 190 abort:
michael@0 191 if (_status) nr_stun_message_destroy(&ind);
michael@0 192 return _status;
michael@0 193 }
michael@0 194
michael@0 195 #ifdef USE_STUND_0_96
michael@0 196 int
michael@0 197 nr_stun_build_req_stund_0_96(nr_stun_client_stun_binding_request_stund_0_96_params *params, nr_stun_message **msg)
michael@0 198 {
michael@0 199 int r,_status;
michael@0 200 nr_stun_message *req = 0;
michael@0 201
michael@0 202 if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUND_0_96, NR_STUN_MSG_BINDING_REQUEST, &req)))
michael@0 203 ABORT(r);
michael@0 204
michael@0 205 if ((r=nr_stun_message_add_change_request_attribute(req, 0)))
michael@0 206 ABORT(r);
michael@0 207
michael@0 208 assert(! nr_stun_message_has_attribute(req, NR_STUN_ATTR_USERNAME, 0));
michael@0 209 assert(! nr_stun_message_has_attribute(req, NR_STUN_ATTR_MESSAGE_INTEGRITY, 0));
michael@0 210
michael@0 211 *msg = req;
michael@0 212
michael@0 213 _status=0;
michael@0 214 abort:
michael@0 215 if (_status) nr_stun_message_destroy(&req);
michael@0 216 return _status;
michael@0 217 }
michael@0 218 #endif /* USE_STUND_0_96 */
michael@0 219
michael@0 220 #ifdef USE_ICE
michael@0 221 int
michael@0 222 nr_stun_build_use_candidate(nr_stun_client_ice_use_candidate_params *params, nr_stun_message **msg)
michael@0 223 {
michael@0 224 int r,_status;
michael@0 225 nr_stun_message *req = 0;
michael@0 226
michael@0 227 if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_BINDING_REQUEST, &req)))
michael@0 228 ABORT(r);
michael@0 229
michael@0 230 if ((r=nr_stun_message_add_username_attribute(req, params->username)))
michael@0 231 ABORT(r);
michael@0 232
michael@0 233 if ((r=nr_stun_message_add_message_integrity_attribute(req, &params->password)))
michael@0 234 ABORT(r);
michael@0 235
michael@0 236 if ((r=nr_stun_message_add_use_candidate_attribute(req)))
michael@0 237 ABORT(r);
michael@0 238
michael@0 239 if ((r=nr_stun_message_add_priority_attribute(req, params->priority)))
michael@0 240 ABORT(r);
michael@0 241
michael@0 242 if ((r=nr_stun_message_add_ice_controlling_attribute(req, params->tiebreaker)))
michael@0 243 ABORT(r);
michael@0 244
michael@0 245 *msg = req;
michael@0 246
michael@0 247 _status=0;
michael@0 248 abort:
michael@0 249 if (_status) nr_stun_message_destroy(&req);
michael@0 250 return _status;
michael@0 251 }
michael@0 252
michael@0 253 int
michael@0 254 nr_stun_build_req_ice(nr_stun_client_ice_binding_request_params *params, nr_stun_message **msg)
michael@0 255 {
michael@0 256 int r,_status;
michael@0 257 nr_stun_message *req = 0;
michael@0 258
michael@0 259 if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_BINDING_REQUEST, &req)))
michael@0 260 ABORT(r);
michael@0 261
michael@0 262 if ((r=nr_stun_message_add_username_attribute(req, params->username)))
michael@0 263 ABORT(r);
michael@0 264
michael@0 265 if ((r=nr_stun_message_add_message_integrity_attribute(req, &params->password)))
michael@0 266 ABORT(r);
michael@0 267
michael@0 268 if ((r=nr_stun_message_add_priority_attribute(req, params->priority)))
michael@0 269 ABORT(r);
michael@0 270
michael@0 271 switch (params->control) {
michael@0 272 case NR_ICE_CONTROLLING:
michael@0 273 if ((r=nr_stun_message_add_ice_controlling_attribute(req, params->tiebreaker)))
michael@0 274 ABORT(r);
michael@0 275 break;
michael@0 276 case NR_ICE_CONTROLLED:
michael@0 277 if ((r=nr_stun_message_add_ice_controlled_attribute(req, params->tiebreaker)))
michael@0 278 ABORT(r);
michael@0 279 break;
michael@0 280 default:
michael@0 281 assert(0);
michael@0 282 ABORT(R_INTERNAL);
michael@0 283 }
michael@0 284
michael@0 285 *msg = req;
michael@0 286
michael@0 287 _status=0;
michael@0 288 abort:
michael@0 289 if (_status) nr_stun_message_destroy(&req);
michael@0 290 return _status;
michael@0 291 }
michael@0 292 #endif /* USE_ICE */
michael@0 293
michael@0 294 #ifdef USE_TURN
michael@0 295
michael@0 296 #ifndef __isascii
michael@0 297 #define __isascii(c) (((c) & ~0x7F) == 0)
michael@0 298 #endif
michael@0 299
michael@0 300 /* Long-term passwords are computed over the key:
michael@0 301
michael@0 302 key = MD5(username ":" realm ":" SASLprep(password))
michael@0 303
michael@0 304 Per RFC 5389 S 15.4
michael@0 305 */
michael@0 306 int
michael@0 307 nr_stun_compute_lt_message_integrity_password(const char *username, const char *realm,
michael@0 308 Data *password, Data *hmac_key)
michael@0 309 {
michael@0 310 char digest_input[1000];
michael@0 311 int i;
michael@0 312 int r, _status;
michael@0 313 size_t len;
michael@0 314
michael@0 315 /* First check that the password is ASCII. We are supposed to
michael@0 316 SASLprep but we don't support this yet
michael@0 317 TODO(ekr@rtfm.com): Add SASLprep for password.
michael@0 318 */
michael@0 319 for (i=0; i<password->len; i++) {
michael@0 320 if (!__isascii(password->data[i]))
michael@0 321 ABORT(R_BAD_DATA);
michael@0 322 }
michael@0 323
michael@0 324 if (hmac_key->len < 16)
michael@0 325 ABORT(R_BAD_ARGS);
michael@0 326
michael@0 327 snprintf(digest_input, sizeof(digest_input), "%s:%s:", username, realm);
michael@0 328 if ((sizeof(digest_input) - strlen(digest_input)) < password->len)
michael@0 329 ABORT(R_BAD_DATA);
michael@0 330
michael@0 331 len = strlen(digest_input);
michael@0 332 memcpy(digest_input + len, password->data, password->len);
michael@0 333
michael@0 334
michael@0 335 if (r=nr_crypto_md5((UCHAR *)digest_input, len + password->len, hmac_key->data))
michael@0 336 ABORT(r);
michael@0 337 hmac_key->len=16;
michael@0 338
michael@0 339 _status=0;
michael@0 340 abort:
michael@0 341 return(_status);
michael@0 342 }
michael@0 343
michael@0 344 static int
michael@0 345 nr_stun_build_auth_params(nr_stun_client_auth_params *auth, nr_stun_message *req)
michael@0 346 {
michael@0 347 int r, _status;
michael@0 348 UCHAR hmac_key_d[16];
michael@0 349 Data hmac_key;
michael@0 350
michael@0 351 ATTACH_DATA(hmac_key, hmac_key_d);
michael@0 352
michael@0 353 if (!auth->authenticate)
michael@0 354 goto done;
michael@0 355
michael@0 356 assert(auth->username);
michael@0 357 assert(auth->password.len);
michael@0 358 assert(auth->realm);
michael@0 359 assert(auth->nonce);
michael@0 360
michael@0 361 if (r=nr_stun_compute_lt_message_integrity_password(auth->username,
michael@0 362 auth->realm,
michael@0 363 &auth->password,
michael@0 364 &hmac_key))
michael@0 365 ABORT(r);
michael@0 366
michael@0 367 if (!auth->username) {
michael@0 368 r_log(NR_LOG_STUN, LOG_WARNING, "STUN authentication requested but no username provided");
michael@0 369 ABORT(R_INTERNAL);
michael@0 370 }
michael@0 371
michael@0 372 if (!auth->password.len) {
michael@0 373 r_log(NR_LOG_STUN, LOG_WARNING, "STUN authentication requested but no password provided");
michael@0 374 ABORT(R_INTERNAL);
michael@0 375 }
michael@0 376
michael@0 377 if (!auth->realm) {
michael@0 378 r_log(NR_LOG_STUN, LOG_WARNING, "STUN authentication requested but no realm provided");
michael@0 379 ABORT(R_INTERNAL);
michael@0 380 }
michael@0 381
michael@0 382 if (!auth->nonce) {
michael@0 383 r_log(NR_LOG_STUN, LOG_WARNING, "STUN authentication requested but no nonce provided");
michael@0 384 ABORT(R_INTERNAL);
michael@0 385 }
michael@0 386
michael@0 387 if ((r=nr_stun_message_add_username_attribute(req, auth->username)))
michael@0 388 ABORT(r);
michael@0 389
michael@0 390 if ((r=nr_stun_message_add_realm_attribute(req, auth->realm)))
michael@0 391 ABORT(r);
michael@0 392
michael@0 393 if ((r=nr_stun_message_add_nonce_attribute(req, auth->nonce)))
michael@0 394 ABORT(r);
michael@0 395
michael@0 396 if ((r=nr_stun_message_add_message_integrity_attribute(req, &hmac_key)))
michael@0 397 ABORT(r);
michael@0 398
michael@0 399 done:
michael@0 400 _status=0;
michael@0 401 abort:
michael@0 402 return(_status);
michael@0 403 }
michael@0 404
michael@0 405 int
michael@0 406 nr_stun_build_allocate_request(nr_stun_client_auth_params *auth, nr_stun_client_allocate_request_params *params, nr_stun_message **msg)
michael@0 407 {
michael@0 408 int r,_status;
michael@0 409 nr_stun_message *req = 0;
michael@0 410
michael@0 411 if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_ALLOCATE_REQUEST, &req)))
michael@0 412 ABORT(r);
michael@0 413
michael@0 414 if ((r=nr_stun_message_add_requested_transport_attribute(req, NR_STUN_ATTR_REQUESTED_TRANSPORT_UDP)))
michael@0 415 ABORT(r);
michael@0 416
michael@0 417 if ((r=nr_stun_message_add_lifetime_attribute(req, params->lifetime_secs)))
michael@0 418 ABORT(r);
michael@0 419
michael@0 420 /* TODO(ekr@rtfm.com): Add the SOFTWARE attribute (Firefox bug 857666) */
michael@0 421
michael@0 422 if ((r=nr_stun_build_auth_params(auth, req)))
michael@0 423 ABORT(r);
michael@0 424
michael@0 425 *msg = req;
michael@0 426
michael@0 427 _status=0;
michael@0 428 abort:
michael@0 429 if (_status) nr_stun_message_destroy(&req);
michael@0 430 return _status;
michael@0 431 }
michael@0 432
michael@0 433
michael@0 434 int nr_stun_build_refresh_request(nr_stun_client_auth_params *auth, nr_stun_client_refresh_request_params *params, nr_stun_message **msg)
michael@0 435 {
michael@0 436 int r,_status;
michael@0 437 nr_stun_message *req = 0;
michael@0 438
michael@0 439 if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_REFRESH_REQUEST, &req)))
michael@0 440 ABORT(r);
michael@0 441
michael@0 442 if ((r=nr_stun_message_add_lifetime_attribute(req, params->lifetime_secs)))
michael@0 443 ABORT(r);
michael@0 444
michael@0 445
michael@0 446 /* TODO(ekr@rtfm.com): Add the SOFTWARE attribute (Firefox bug 857666) */
michael@0 447
michael@0 448 if ((r=nr_stun_build_auth_params(auth, req)))
michael@0 449 ABORT(r);
michael@0 450
michael@0 451 *msg = req;
michael@0 452
michael@0 453 _status=0;
michael@0 454 abort:
michael@0 455 if (_status) nr_stun_message_destroy(&req);
michael@0 456 return _status;
michael@0 457 }
michael@0 458
michael@0 459
michael@0 460 int nr_stun_build_permission_request(nr_stun_client_auth_params *auth, nr_stun_client_permission_request_params *params, nr_stun_message **msg)
michael@0 461 {
michael@0 462 int r,_status;
michael@0 463 nr_stun_message *req = 0;
michael@0 464
michael@0 465 if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_PERMISSION_REQUEST, &req)))
michael@0 466 ABORT(r);
michael@0 467
michael@0 468 if ((r=nr_stun_message_add_xor_peer_address_attribute(req, &params->remote_addr)))
michael@0 469 ABORT(r);
michael@0 470
michael@0 471 if ((r=nr_stun_build_auth_params(auth, req)))
michael@0 472 ABORT(r);
michael@0 473
michael@0 474 *msg = req;
michael@0 475
michael@0 476 _status=0;
michael@0 477 abort:
michael@0 478 if (_status) nr_stun_message_destroy(&req);
michael@0 479 return _status;
michael@0 480 }
michael@0 481
michael@0 482 int
michael@0 483 nr_stun_build_send_indication(nr_stun_client_send_indication_params *params, nr_stun_message **msg)
michael@0 484 {
michael@0 485 int r,_status;
michael@0 486 nr_stun_message *ind = 0;
michael@0 487
michael@0 488 if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_SEND_INDICATION, &ind)))
michael@0 489 ABORT(r);
michael@0 490
michael@0 491 if ((r=nr_stun_message_add_xor_peer_address_attribute(ind, &params->remote_addr)))
michael@0 492 ABORT(r);
michael@0 493
michael@0 494 if ((r=nr_stun_message_add_data_attribute(ind, params->data.data, params->data.len)))
michael@0 495 ABORT(r);
michael@0 496
michael@0 497 *msg = ind;
michael@0 498
michael@0 499 _status=0;
michael@0 500 abort:
michael@0 501 if (_status) nr_stun_message_destroy(&ind);
michael@0 502 return _status;
michael@0 503 }
michael@0 504
michael@0 505 int
michael@0 506 nr_stun_build_data_indication(nr_stun_client_data_indication_params *params, nr_stun_message **msg)
michael@0 507 {
michael@0 508 int r,_status;
michael@0 509 nr_stun_message *ind = 0;
michael@0 510
michael@0 511 if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_DATA_INDICATION, &ind)))
michael@0 512 ABORT(r);
michael@0 513
michael@0 514 if ((r=nr_stun_message_add_xor_peer_address_attribute(ind, &params->remote_addr)))
michael@0 515 ABORT(r);
michael@0 516
michael@0 517 if ((r=nr_stun_message_add_data_attribute(ind, params->data.data, params->data.len)))
michael@0 518 ABORT(r);
michael@0 519
michael@0 520 *msg = ind;
michael@0 521
michael@0 522 _status=0;
michael@0 523 abort:
michael@0 524 if (_status) nr_stun_message_destroy(&ind);
michael@0 525 return _status;
michael@0 526 }
michael@0 527
michael@0 528 #endif /* USE_TURN */
michael@0 529
michael@0 530 /* draft-ietf-behave-rfc3489bis-10.txt S 7.3.1.1 */
michael@0 531 int
michael@0 532 nr_stun_form_success_response(nr_stun_message *req, nr_transport_addr *from, Data *password, nr_stun_message *res)
michael@0 533 {
michael@0 534 int r,_status;
michael@0 535 int request_method;
michael@0 536 char server_name[NR_STUN_MAX_SERVER_BYTES+1]; /* +1 for \0 */
michael@0 537
michael@0 538 /* set up information for default response */
michael@0 539
michael@0 540 request_method = NR_STUN_GET_TYPE_METHOD(req->header.type);
michael@0 541 res->header.type = NR_STUN_TYPE(request_method, NR_CLASS_RESPONSE);
michael@0 542 res->header.magic_cookie = req->header.magic_cookie;
michael@0 543 memcpy(&res->header.id, &req->header.id, sizeof(res->header.id));
michael@0 544
michael@0 545 r_log(NR_LOG_STUN, LOG_DEBUG, "Mapped Address = %s", from->as_string);
michael@0 546
michael@0 547 if ((r=nr_stun_message_add_xor_mapped_address_attribute(res, from)))
michael@0 548 ABORT(r);
michael@0 549
michael@0 550 if (!NR_reg_get_string(NR_STUN_REG_PREF_SERVER_NAME, server_name, sizeof(server_name))) {
michael@0 551 if ((r=nr_stun_message_add_server_attribute(res, server_name)))
michael@0 552 ABORT(r);
michael@0 553 }
michael@0 554
michael@0 555 if (res->header.magic_cookie == NR_STUN_MAGIC_COOKIE) {
michael@0 556 if (password != 0) {
michael@0 557 if ((r=nr_stun_message_add_message_integrity_attribute(res, password)))
michael@0 558 ABORT(r);
michael@0 559 }
michael@0 560
michael@0 561 if ((r=nr_stun_message_add_fingerprint_attribute(res)))
michael@0 562 ABORT(r);
michael@0 563 }
michael@0 564
michael@0 565 _status=0;
michael@0 566 abort:
michael@0 567 return _status;
michael@0 568 }
michael@0 569
michael@0 570 /* draft-ietf-behave-rfc3489bis-10.txt S 7.3.1.1 */
michael@0 571 void
michael@0 572 nr_stun_form_error_response(nr_stun_message *req, nr_stun_message* res, int number, char* msg)
michael@0 573 {
michael@0 574 char *str;
michael@0 575 int request_method;
michael@0 576 char server_name[NR_STUN_MAX_SERVER_BYTES+1]; /* +1 for \0 */
michael@0 577
michael@0 578 if (number < 300 || number > 699)
michael@0 579 number = 500;
michael@0 580
michael@0 581 r_log(NR_LOG_STUN, LOG_INFO, "Responding with error %d: %s", number, msg);
michael@0 582
michael@0 583 request_method = NR_STUN_GET_TYPE_METHOD(req->header.type);
michael@0 584 res->header.type = NR_STUN_TYPE(request_method, NR_CLASS_ERROR_RESPONSE);
michael@0 585 res->header.magic_cookie = req->header.magic_cookie;
michael@0 586 memcpy(&res->header.id, &req->header.id, sizeof(res->header.id));
michael@0 587
michael@0 588 /* during development we should never see 500s (hopefully not in deployment either) */
michael@0 589
michael@0 590 str = 0;
michael@0 591 switch (number) {
michael@0 592 case 300: str = "Try Alternate"; break;
michael@0 593 case 400: str = "Bad Request"; break;
michael@0 594 case 401: str = "Unauthorized"; break;
michael@0 595 case 420: str = "Unknown Attribute"; break;
michael@0 596 case 438: str = "Stale Nonce"; break;
michael@0 597 #ifdef USE_ICE
michael@0 598 case 487: str = "Role Conflict"; break;
michael@0 599 #endif
michael@0 600 case 500: str = "Server Error"; break;
michael@0 601 }
michael@0 602 if (str == 0) {
michael@0 603 str = "Unknown";
michael@0 604 }
michael@0 605
michael@0 606 if (nr_stun_message_add_error_code_attribute(res, number, str)) {
michael@0 607 assert(0); /* should never happen */
michael@0 608 }
michael@0 609
michael@0 610 if (!NR_reg_get_string(NR_STUN_REG_PREF_SERVER_NAME, server_name, sizeof(server_name))) {
michael@0 611 nr_stun_message_add_server_attribute(res, server_name);
michael@0 612 }
michael@0 613 }
michael@0 614

mercurial