From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- .../third_party/nICEr/src/stun/stun_build.c | 611 +++++++++++++++++++++ 1 file changed, 611 insertions(+) create mode 100644 dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_build.c (limited to 'dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_build.c') diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_build.c b/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_build.c new file mode 100644 index 0000000000..001b38e7c4 --- /dev/null +++ b/dom/media/webrtc/transport/third_party/nICEr/src/stun/stun_build.c @@ -0,0 +1,611 @@ +/* +Copyright (c) 2007, Adobe Systems, Incorporated +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +* Neither the name of Adobe Systems, Network Resonance nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +#include +#include +#include +#include + +#include "nr_api.h" +#include "stun.h" +#include "registry.h" +#include "stun_reg.h" +#include "nr_crypto.h" + + +/* draft-ietf-behave-rfc3489bis-10.txt S 7.1 */ +/* draft-ietf-behave-rfc3489bis-10.txt S 10.1.1 */ +/* note that S 10.1.1 states the message MUST include MESSAGE-INTEGRITY + * and USERNAME, but that's not correct -- for instance ICE keepalive + * messages don't include these (See draft-ietf-mmusic-ice-18.txt S 10: + * "If STUN is being used for keepalives, a STUN Binding Indication is + * used. The Indication MUST NOT utilize any authentication mechanism") + */ +int +nr_stun_form_request_or_indication(int mode, int msg_type, nr_stun_message **msg) +{ + int r,_status; + nr_stun_message *req = 0; + + assert(NR_STUN_GET_TYPE_CLASS(msg_type) == NR_CLASS_REQUEST + || NR_STUN_GET_TYPE_CLASS(msg_type) == NR_CLASS_INDICATION); + + *msg = 0; + + if ((r=nr_stun_message_create(&req))) + ABORT(r); + + req->header.type = msg_type; + + nr_crypto_random_bytes((UCHAR*)&req->header.id,sizeof(req->header.id)); + + switch (mode) { + default: + if ((r=nr_stun_message_add_fingerprint_attribute(req))) + ABORT(r); + /* fall through */ + case NR_STUN_MODE_STUN_NO_AUTH: + req->header.magic_cookie = NR_STUN_MAGIC_COOKIE; + break; + +#ifdef USE_STUND_0_96 + case NR_STUN_MODE_STUND_0_96: + req->header.magic_cookie = NR_STUN_MAGIC_COOKIE2; + + /* actually, stund 0.96 just ignores the fingerprint + * attribute, but don't bother to send it */ + + break; +#endif /* USE_STUND_0_96 */ + + } + + *msg = req; + + _status=0; + abort: + if (_status) RFREE(req); + return _status; +} + +int +nr_stun_build_req_lt_auth(nr_stun_client_stun_binding_request_params *params, nr_stun_message **msg) +{ + int r,_status; + nr_stun_message *req = 0; + + if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_BINDING_REQUEST, &req))) + ABORT(r); + + if ((r=nr_stun_message_add_username_attribute(req, params->username))) + ABORT(r); + + if (params->realm && params->nonce) { + if ((r=nr_stun_message_add_realm_attribute(req, params->realm))) + ABORT(r); + + if ((r=nr_stun_message_add_nonce_attribute(req, params->nonce))) + ABORT(r); + + if ((r=nr_stun_message_add_message_integrity_attribute(req, params->password))) + ABORT(r); + } + + *msg = req; + + _status=0; + abort: + if (_status) nr_stun_message_destroy(&req); + return _status; +} + +int +nr_stun_build_req_st_auth(nr_stun_client_stun_binding_request_params *params, nr_stun_message **msg) +{ + int r,_status; + nr_stun_message *req = 0; + + if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_BINDING_REQUEST, &req))) + ABORT(r); + + if ((r=nr_stun_message_add_username_attribute(req, params->username))) + ABORT(r); + + if (params->password) { + if ((r=nr_stun_message_add_message_integrity_attribute(req, params->password))) + ABORT(r); + } + + *msg = req; + + _status=0; + abort: + if (_status) nr_stun_message_destroy(&req); + return _status; +} + +int +nr_stun_build_req_no_auth(nr_stun_client_stun_binding_request_params *params, nr_stun_message **msg) +{ + int r,_status; + nr_stun_message *req = 0; + + if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN_NO_AUTH, NR_STUN_MSG_BINDING_REQUEST, &req))) + ABORT(r); + + *msg = req; + + _status=0; + abort: + if (_status) nr_stun_message_destroy(&req); + return _status; +} + +int +nr_stun_build_keepalive(nr_stun_client_stun_keepalive_params *params, nr_stun_message **msg) +{ + int r,_status; + nr_stun_message *ind = 0; + + if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_BINDING_INDICATION, &ind))) + ABORT(r); + + *msg = ind; + + _status=0; + abort: + if (_status) nr_stun_message_destroy(&ind); + return _status; +} + +#ifdef USE_STUND_0_96 +int +nr_stun_build_req_stund_0_96(nr_stun_client_stun_binding_request_stund_0_96_params *params, nr_stun_message **msg) +{ + int r,_status; + nr_stun_message *req = 0; + + if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUND_0_96, NR_STUN_MSG_BINDING_REQUEST, &req))) + ABORT(r); + + if ((r=nr_stun_message_add_change_request_attribute(req, 0))) + ABORT(r); + + assert(! nr_stun_message_has_attribute(req, NR_STUN_ATTR_USERNAME, 0)); + assert(! nr_stun_message_has_attribute(req, NR_STUN_ATTR_MESSAGE_INTEGRITY, 0)); + + *msg = req; + + _status=0; + abort: + if (_status) nr_stun_message_destroy(&req); + return _status; +} +#endif /* USE_STUND_0_96 */ + +#ifdef USE_ICE +int +nr_stun_build_use_candidate(nr_stun_client_ice_binding_request_params *params, nr_stun_message **msg) +{ + int r,_status; + nr_stun_message *req = 0; + + if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_BINDING_REQUEST, &req))) + ABORT(r); + + if ((r=nr_stun_message_add_username_attribute(req, params->username))) + ABORT(r); + + if ((r=nr_stun_message_add_message_integrity_attribute(req, ¶ms->password))) + ABORT(r); + + if ((r=nr_stun_message_add_use_candidate_attribute(req))) + ABORT(r); + + if ((r=nr_stun_message_add_priority_attribute(req, params->priority))) + ABORT(r); + + if ((r=nr_stun_message_add_ice_controlling_attribute(req, params->tiebreaker))) + ABORT(r); + + *msg = req; + + _status=0; + abort: + if (_status) nr_stun_message_destroy(&req); + return _status; +} + +int +nr_stun_build_req_ice(nr_stun_client_ice_binding_request_params *params, nr_stun_message **msg) +{ + int r,_status; + nr_stun_message *req = 0; + + if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_BINDING_REQUEST, &req))) + ABORT(r); + + if ((r=nr_stun_message_add_username_attribute(req, params->username))) + ABORT(r); + + if ((r=nr_stun_message_add_message_integrity_attribute(req, ¶ms->password))) + ABORT(r); + + if ((r=nr_stun_message_add_priority_attribute(req, params->priority))) + ABORT(r); + + switch (params->control) { + case NR_ICE_CONTROLLING: + if ((r=nr_stun_message_add_ice_controlling_attribute(req, params->tiebreaker))) + ABORT(r); + break; + case NR_ICE_CONTROLLED: + if ((r=nr_stun_message_add_ice_controlled_attribute(req, params->tiebreaker))) + ABORT(r); + break; + default: + assert(0); + ABORT(R_INTERNAL); + } + + *msg = req; + + _status=0; + abort: + if (_status) nr_stun_message_destroy(&req); + return _status; +} +#endif /* USE_ICE */ + +#ifdef USE_TURN + +#ifndef __isascii +#define __isascii(c) (((c) & ~0x7F) == 0) +#endif + +/* Long-term passwords are computed over the key: + + key = MD5(username ":" realm ":" SASLprep(password)) + + Per RFC 5389 S 15.4 +*/ +int +nr_stun_compute_lt_message_integrity_password(const char *username, const char *realm, + Data *password, Data *hmac_key) +{ + char digest_input[1000]; + size_t i; + int r, _status; + size_t len; + + /* First check that the password is ASCII. We are supposed to + SASLprep but we don't support this yet + TODO(ekr@rtfm.com): Add SASLprep for password. + */ + for (i=0; ilen; i++) { + if (!__isascii(password->data[i])) + ABORT(R_BAD_DATA); + } + + if (hmac_key->len < 16) + ABORT(R_BAD_ARGS); + + snprintf(digest_input, sizeof(digest_input), "%s:%s:", username, realm); + if ((sizeof(digest_input) - strlen(digest_input)) < password->len) + ABORT(R_BAD_DATA); + + len = strlen(digest_input); + memcpy(digest_input + len, password->data, password->len); + + + if (r=nr_crypto_md5((UCHAR *)digest_input, len + password->len, hmac_key->data)) + ABORT(r); + hmac_key->len=16; + + _status=0; +abort: + return(_status); +} + +static int +nr_stun_build_auth_params(nr_stun_client_auth_params *auth, nr_stun_message *req) +{ + int r, _status; + UCHAR hmac_key_d[16]; + Data hmac_key; + + ATTACH_DATA(hmac_key, hmac_key_d); + + if (!auth->authenticate) + goto done; + + assert(auth->username); + assert(auth->password.len); + assert(auth->realm); + assert(auth->nonce); + + if (r=nr_stun_compute_lt_message_integrity_password(auth->username, + auth->realm, + &auth->password, + &hmac_key)) + ABORT(r); + + if (!auth->username) { + r_log(NR_LOG_STUN, LOG_WARNING, "STUN authentication requested but no username provided"); + ABORT(R_INTERNAL); + } + + if (!auth->password.len) { + r_log(NR_LOG_STUN, LOG_WARNING, "STUN authentication requested but no password provided"); + ABORT(R_INTERNAL); + } + + if (!auth->realm) { + r_log(NR_LOG_STUN, LOG_WARNING, "STUN authentication requested but no realm provided"); + ABORT(R_INTERNAL); + } + + if (!auth->nonce) { + r_log(NR_LOG_STUN, LOG_WARNING, "STUN authentication requested but no nonce provided"); + ABORT(R_INTERNAL); + } + + if ((r=nr_stun_message_add_username_attribute(req, auth->username))) + ABORT(r); + + if ((r=nr_stun_message_add_realm_attribute(req, auth->realm))) + ABORT(r); + + if ((r=nr_stun_message_add_nonce_attribute(req, auth->nonce))) + ABORT(r); + + if ((r=nr_stun_message_add_message_integrity_attribute(req, &hmac_key))) + ABORT(r); + +done: + _status=0; +abort: + return(_status); +} + +int +nr_stun_build_allocate_request(nr_stun_client_auth_params *auth, nr_stun_client_allocate_request_params *params, nr_stun_message **msg) +{ + int r,_status; + nr_stun_message *req = 0; + + if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_ALLOCATE_REQUEST, &req))) + ABORT(r); + + if ((r=nr_stun_message_add_requested_transport_attribute(req, NR_STUN_ATTR_REQUESTED_TRANSPORT_UDP))) + ABORT(r); + + if ((r=nr_stun_message_add_lifetime_attribute(req, params->lifetime_secs))) + ABORT(r); + + /* TODO(ekr@rtfm.com): Add the SOFTWARE attribute (Firefox bug 857666) */ + + if ((r=nr_stun_build_auth_params(auth, req))) + ABORT(r); + + *msg = req; + + _status=0; + abort: + if (_status) nr_stun_message_destroy(&req); + return _status; +} + + +int nr_stun_build_refresh_request(nr_stun_client_auth_params *auth, nr_stun_client_refresh_request_params *params, nr_stun_message **msg) +{ + int r,_status; + nr_stun_message *req = 0; + + if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_REFRESH_REQUEST, &req))) + ABORT(r); + + if ((r=nr_stun_message_add_lifetime_attribute(req, params->lifetime_secs))) + ABORT(r); + + + /* TODO(ekr@rtfm.com): Add the SOFTWARE attribute (Firefox bug 857666) */ + + if ((r=nr_stun_build_auth_params(auth, req))) + ABORT(r); + + *msg = req; + + _status=0; + abort: + if (_status) nr_stun_message_destroy(&req); + return _status; +} + + +int nr_stun_build_permission_request(nr_stun_client_auth_params *auth, nr_stun_client_permission_request_params *params, nr_stun_message **msg) +{ + int r,_status; + nr_stun_message *req = 0; + + if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_PERMISSION_REQUEST, &req))) + ABORT(r); + + if ((r=nr_stun_message_add_xor_peer_address_attribute(req, ¶ms->remote_addr))) + ABORT(r); + + if ((r=nr_stun_build_auth_params(auth, req))) + ABORT(r); + + *msg = req; + + _status=0; + abort: + if (_status) nr_stun_message_destroy(&req); + return _status; +} + +int +nr_stun_build_send_indication(nr_stun_client_send_indication_params *params, nr_stun_message **msg) +{ + int r,_status; + nr_stun_message *ind = 0; + + if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_SEND_INDICATION, &ind))) + ABORT(r); + + if ((r=nr_stun_message_add_xor_peer_address_attribute(ind, ¶ms->remote_addr))) + ABORT(r); + + if ((r=nr_stun_message_add_data_attribute(ind, params->data.data, params->data.len))) + ABORT(r); + + *msg = ind; + + _status=0; + abort: + if (_status) nr_stun_message_destroy(&ind); + return _status; +} + +int +nr_stun_build_data_indication(nr_stun_client_data_indication_params *params, nr_stun_message **msg) +{ + int r,_status; + nr_stun_message *ind = 0; + + if ((r=nr_stun_form_request_or_indication(NR_STUN_MODE_STUN, NR_STUN_MSG_DATA_INDICATION, &ind))) + ABORT(r); + + if ((r=nr_stun_message_add_xor_peer_address_attribute(ind, ¶ms->remote_addr))) + ABORT(r); + + if ((r=nr_stun_message_add_data_attribute(ind, params->data.data, params->data.len))) + ABORT(r); + + *msg = ind; + + _status=0; + abort: + if (_status) nr_stun_message_destroy(&ind); + return _status; +} + +#endif /* USE_TURN */ + +/* draft-ietf-behave-rfc3489bis-10.txt S 7.3.1.1 */ +int +nr_stun_form_success_response(nr_stun_message *req, nr_transport_addr *from, Data *password, nr_stun_message *res) +{ + int r,_status; + int request_method; + char server_name[NR_STUN_MAX_SERVER_BYTES+1]; /* +1 for \0 */ + + /* set up information for default response */ + + request_method = NR_STUN_GET_TYPE_METHOD(req->header.type); + res->header.type = NR_STUN_TYPE(request_method, NR_CLASS_RESPONSE); + res->header.magic_cookie = req->header.magic_cookie; + memcpy(&res->header.id, &req->header.id, sizeof(res->header.id)); + + r_log(NR_LOG_STUN, LOG_DEBUG, "Mapped Address = %s", from->as_string); + + if ((r=nr_stun_message_add_xor_mapped_address_attribute(res, from))) + ABORT(r); + + if (!NR_reg_get_string(NR_STUN_REG_PREF_SERVER_NAME, server_name, sizeof(server_name))) { + if ((r=nr_stun_message_add_server_attribute(res, server_name))) + ABORT(r); + } + + if (res->header.magic_cookie == NR_STUN_MAGIC_COOKIE) { + if (password != 0) { + if ((r=nr_stun_message_add_message_integrity_attribute(res, password))) + ABORT(r); + } + + if ((r=nr_stun_message_add_fingerprint_attribute(res))) + ABORT(r); + } + + _status=0; + abort: + return _status; +} + +/* draft-ietf-behave-rfc3489bis-10.txt S 7.3.1.1 */ +void +nr_stun_form_error_response(nr_stun_message *req, nr_stun_message* res, int number, char* msg) +{ + char *str; + int request_method; + char server_name[NR_STUN_MAX_SERVER_BYTES+1]; /* +1 for \0 */ + + if (number < 300 || number > 699) + number = 500; + + r_log(NR_LOG_STUN, LOG_INFO, "Responding with error %d: %s", number, msg); + + request_method = NR_STUN_GET_TYPE_METHOD(req->header.type); + res->header.type = NR_STUN_TYPE(request_method, NR_CLASS_ERROR_RESPONSE); + res->header.magic_cookie = req->header.magic_cookie; + memcpy(&res->header.id, &req->header.id, sizeof(res->header.id)); + + /* during development we should never see 500s (hopefully not in deployment either) */ + + str = 0; + switch (number) { + case 300: str = "Try Alternate"; break; + case 400: str = "Bad Request"; break; + case 401: str = "Unauthorized"; break; + case 420: str = "Unknown Attribute"; break; + case 438: str = "Stale Nonce"; break; +#ifdef USE_ICE + case 487: str = "Role Conflict"; break; +#endif + case 500: str = "Server Error"; break; + } + if (str == 0) { + str = "Unknown"; + } + + if (nr_stun_message_add_error_code_attribute(res, number, str)) { + assert(0); /* should never happen */ + } + + if (!NR_reg_get_string(NR_STUN_REG_PREF_SERVER_NAME, server_name, sizeof(server_name))) { + nr_stun_message_add_server_attribute(res, server_name); + } +} + -- cgit v1.2.3