11391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen/* 21391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen * libjingle 31391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen * Copyright 2004--2005, Google Inc. 41391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen * 51391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen * Redistribution and use in source and binary forms, with or without 61391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen * modification, are permitted provided that the following conditions are met: 71391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen * 81391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen * 1. Redistributions of source code must retain the above copyright notice, 91391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen * this list of conditions and the following disclaimer. 101391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen * 2. Redistributions in binary form must reproduce the above copyright notice, 111391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen * this list of conditions and the following disclaimer in the documentation 121391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen * and/or other materials provided with the distribution. 131391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen * 3. The name of the author may not be used to endorse or promote products 141391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen * derived from this software without specific prior written permission. 151391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen * 161391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 171391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 181391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 191391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 201391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 211391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 221391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 231391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 241391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 251391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 261391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen */ 271391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen 281391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen#ifdef POSIX 291391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen#include <errno.h> 301391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen#endif // POSIX 311391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen 321391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen#include "talk/p2p/base/stunserver.h" 331391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen#include "talk/base/bytebuffer.h" 341391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen#include "talk/base/logging.h" 351391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen 361391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsennamespace cricket { 371391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen 381391b24619d56bae6ce14bb54ed0fb16a945e853Kristian MonsenStunServer::StunServer(talk_base::AsyncUDPSocket* socket) : socket_(socket) { 391391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen socket_->SignalReadPacket.connect(this, &StunServer::OnPacket); 401391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen} 411391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen 421391b24619d56bae6ce14bb54ed0fb16a945e853Kristian MonsenStunServer::~StunServer() { 431391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen socket_->SignalReadPacket.disconnect(this); 441391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen} 451391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen 461391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsenvoid StunServer::OnPacket( 47dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen talk_base::AsyncPacketSocket* socket, const char* buf, size_t size, 48dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const talk_base::SocketAddress& remote_addr) { 491391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen 501391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen // TODO: If appropriate, look for the magic cookie before parsing. 511391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen 521391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen // Parse the STUN message. 531391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen talk_base::ByteBuffer bbuf(buf, size); 541391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen StunMessage msg; 551391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen if (!msg.Read(&bbuf)) { 561391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen SendErrorResponse(msg, remote_addr, 400, "Bad Request"); 571391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen return; 581391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen } 591391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen 601391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen // TODO: If this is UDP, then we shouldn't allow non-fully-parsed messages. 611391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen 621391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen // TODO: If unknown non-optiional (<= 0x7fff) attributes are found, send a 631391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen // 420 "Unknown Attribute" response. 641391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen 651391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen // TODO: Check that a message-integrity attribute was given (or send 401 661391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen // "Unauthorized"). Check that a username attribute was given (or send 671391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen // 432 "Missing Username"). Look up the username and password. If it 681391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen // is missing or the HMAC is wrong, send 431 "Integrity Check Failure". 691391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen 701391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen // Send the message to the appropriate handler function. 711391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen switch (msg.type()) { 721391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen case STUN_BINDING_REQUEST: 731391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen OnBindingRequest(&msg, remote_addr); 741391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen return; 751391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen 761391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen case STUN_ALLOCATE_REQUEST: 771391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen OnAllocateRequest(&msg, remote_addr); 781391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen return; 791391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen 801391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen default: 811391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen SendErrorResponse(msg, remote_addr, 600, "Operation Not Supported"); 821391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen } 831391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen} 841391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen 851391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsenvoid StunServer::OnBindingRequest( 861391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen StunMessage* msg, const talk_base::SocketAddress& remote_addr) { 871391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen StunMessage response; 881391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen response.SetType(STUN_BINDING_RESPONSE); 891391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen response.SetTransactionID(msg->transaction_id()); 901391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen 911391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen // Tell the user the address that we received their request from. 921391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen StunAddressAttribute* mapped_addr = 931391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS); 941391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen mapped_addr->SetFamily(1); 951391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen mapped_addr->SetPort(remote_addr.port()); 961391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen mapped_addr->SetIP(remote_addr.ip()); 971391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen response.AddAttribute(mapped_addr); 981391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen 991391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen // Tell the user the address that we are sending the response from. 100dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // This method should not be called if socket address is not 101dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // allocated yet. 102dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen bool allocated; 103dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen talk_base::SocketAddress local_addr = socket_->GetLocalAddress(&allocated); 104dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ASSERT(allocated); 105dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1061391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen StunAddressAttribute* source_addr = 1071391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen StunAttribute::CreateAddress(STUN_ATTR_SOURCE_ADDRESS); 1081391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen source_addr->SetFamily(1); 1091391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen source_addr->SetPort(local_addr.port()); 1101391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen source_addr->SetIP(local_addr.ip()); 1111391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen response.AddAttribute(source_addr); 1121391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen 1131391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen // TODO: Add username and message-integrity. 1141391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen 1151391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen // TODO: Add changed-address. (Keep information about three other servers.) 1161391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen 1171391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen SendResponse(response, remote_addr); 1181391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen} 1191391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen 1201391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsenvoid StunServer::OnAllocateRequest( 1211391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen StunMessage* msg, const talk_base::SocketAddress& addr) { 1221391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen SendErrorResponse(*msg, addr, 600, "Operation Not Supported"); 1231391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen} 1241391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen 1251391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsenvoid StunServer::OnSharedSecretRequest( 1261391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen StunMessage* msg, const talk_base::SocketAddress& addr) { 1271391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen SendErrorResponse(*msg, addr, 600, "Operation Not Supported"); 1281391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen} 1291391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen 1301391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsenvoid StunServer::OnSendRequest(StunMessage* msg, 1311391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen const talk_base::SocketAddress& addr) { 1321391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen SendErrorResponse(*msg, addr, 600, "Operation Not Supported"); 1331391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen} 1341391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen 1351391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsenvoid StunServer::SendErrorResponse( 1361391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen const StunMessage& msg, const talk_base::SocketAddress& addr, 1371391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen int error_code, const char* error_desc) { 1381391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen 1391391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen StunMessage err_msg; 1401391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen err_msg.SetType(GetStunErrorResponseType(msg.type())); 1411391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen err_msg.SetTransactionID(msg.transaction_id()); 1421391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen 1431391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen StunErrorCodeAttribute* err_code = StunAttribute::CreateErrorCode(); 1441391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen err_code->SetErrorClass(error_code / 100); 1451391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen err_code->SetNumber(error_code % 100); 1461391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen err_code->SetReason(error_desc); 1471391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen err_msg.AddAttribute(err_code); 1481391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen 1491391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen SendResponse(err_msg, addr); 1501391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen} 1511391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen 1521391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsenvoid StunServer::SendResponse( 1531391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen const StunMessage& msg, const talk_base::SocketAddress& addr) { 1541391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen 1551391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen talk_base::ByteBuffer buf; 1561391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen msg.Write(&buf); 1571391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen 1581391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen // TODO: Allow response addr attribute if sent from another stun server. 1591391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen 1601391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen if (socket_->SendTo(buf.Data(), buf.Length(), addr) < 0) 1611391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen LOG_ERR(LS_ERROR) << "sendto"; 1621391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen} 1631391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen 1641391b24619d56bae6ce14bb54ed0fb16a945e853Kristian Monsen} // namespace cricket 165