📄 stun.c
字号:
/* The oRTP library is an RTP (Realtime Transport Protocol - rfc3550) stack. Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*//* ==================================================================== * The Vovida Software License, Version 1.0 * * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. 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. * * 3. The names "VOCAL", "Vovida Open Communication Application Library", * and "Vovida Open Communication Application Library (VOCAL)" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact vocal@vovida.org. * * 4. Products derived from this software may not be called "VOCAL", nor * may "VOCAL" appear in their name, without prior written * permission of Vovida Networks, Inc. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES * IN EXCESS OF $1,000, NOR FOR ANY 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. * * ==================================================================== * * This software consists of voluntary contributions made by Vovida * Networks, Inc. and many individuals on behalf of Vovida Networks, * Inc. For more information on Vovida Networks, Inc., please see * <http://www.vovida.org/>. * */#ifndef _WIN32_WCE#include <errno.h>#endif#include <assert.h>#if defined(WIN32) || defined(_WIN32_WCE)#include <winsock2.h>#include <stdlib.h>/* #include <io.h> */#include <time.h>#include <ctype.h> /*for isdigit() */#else#include <stdlib.h>#include <unistd.h>#include <string.h>#include <sys/ioctl.h>#include <sys/socket.h>#include <sys/time.h>#include <sys/types.h> #include <arpa/inet.h>#include <fcntl.h>#include <netdb.h>#include <netinet/in.h>#include <arpa/nameser.h>#include <resolv.h>#include <net/if.h>#endif#define NOSSL/* #if defined(__sparc__) || defined(WIN32) #define NOSSL #endif #define NOSSL*/#include "ortp/stun_udp.h"#include "ortp/stun.h"#include "ortp/ortp.h"static char *ipaddr(const StunAddress4 *addr){ static char tmp[512]; struct in_addr inaddr; char *atmp; inaddr.s_addr = htonl(addr->addr); atmp = (char *)inet_ntoa(inaddr); snprintf(tmp, 512, "%s:%i", atmp, addr->port); return tmp;}static voidcomputeHmac(char* hmac, const char* input, int length, const char* key, int keySize);static bool_t stunParseAtrAddress( char* body, unsigned int hdrLen, StunAtrAddress4 *result ){ if ( hdrLen != 8 ) { ortp_error("stun: hdrLen wrong for Address\n"); return FALSE; } result->pad = *body++; result->family = *body++; if (result->family == IPv4Family) { UInt16 nport; UInt32 naddr; memcpy(&nport, body, 2); body+=2; result->ipv4.port = ntohs(nport); memcpy(&naddr, body, 4); body+=4; result->ipv4.addr = ntohl(naddr); return TRUE; } else if (result->family == IPv6Family) { ortp_error("stun: ipv6 not supported\n"); } else { ortp_error("stun: bad address family: %i\n", result->family); } return FALSE;}static bool_t stunParseAtrChangeRequest( char* body, unsigned int hdrLen, StunAtrChangeRequest *result ){ if ( hdrLen != 4 ) { /* ortp_error("stun: hdr length = %i expecting %i\n",hdrLen, sizeof(result)); */ ortp_error("stun: Incorrect size for ChangeRequest"); return FALSE; } else { memcpy(&result->value, body, 4); result->value = ntohl(result->value); return TRUE; }}static bool_t stunParseAtrError( char* body, unsigned int hdrLen, StunAtrError *result ){ if ( hdrLen >= sizeof(result) ) { ortp_error("stun: head on Error too large"); return FALSE; } else { memcpy(&result->pad, body, 2); body+=2; result->pad = ntohs(result->pad); result->errorClass = *body++; result->number = *body++; result->sizeReason = hdrLen - 4; memcpy(&result->reason, body, result->sizeReason); result->reason[result->sizeReason] = 0; return TRUE; }}static bool_t stunParseAtrUnknown( char* body, unsigned int hdrLen, StunAtrUnknown *result ){ if ( hdrLen >= sizeof(result) ) { return FALSE; } else { int i; if (hdrLen % 4 != 0) return FALSE; result->numAttributes = hdrLen / 4; for (i=0; i<result->numAttributes; i++) { memcpy(&result->attrType[i], body, 2); body+=2; result->attrType[i] = ntohs(result->attrType[i]); } return TRUE; }}static bool_t stunParseAtrString( char* body, unsigned int hdrLen, StunAtrString *result ){ if ( hdrLen >= STUN_MAX_STRING ) { ortp_error("stun: String is too large"); return FALSE; } else { if (hdrLen % 4 != 0) { ortp_error("stun: Bad length string %i\n", hdrLen); return FALSE; } result->sizeValue = hdrLen; memcpy(&result->value, body, hdrLen); result->value[hdrLen] = 0; return TRUE; }}static bool_t stunParseAtrIntegrity( char* body, unsigned int hdrLen, StunAtrIntegrity *result ){ if ( hdrLen != 20) { ortp_error("stun: MessageIntegrity must be 20 bytes"); return FALSE; } else { memcpy(&result->hash, body, hdrLen); return TRUE; }}bool_tstunParseMessage( char* buf, unsigned int bufLen, StunMessage *msg, bool_t verbose){ char* body; unsigned int size; if (verbose) ortp_message("stun: Received stun message: %i bytes\n", bufLen); memset(msg, 0, sizeof(msg)); if (sizeof(StunMsgHdr) > bufLen) { ortp_warning("stun: Bad message\n"); return FALSE; } memcpy(&msg->msgHdr, buf, sizeof(StunMsgHdr)); msg->msgHdr.msgType = ntohs(msg->msgHdr.msgType); msg->msgHdr.msgLength = ntohs(msg->msgHdr.msgLength); if (msg->msgHdr.msgLength + sizeof(StunMsgHdr) != bufLen) { ortp_warning("stun: Message header length doesn't match message size: %i - %i\n", msg->msgHdr.msgLength, bufLen); return FALSE; } body = buf + sizeof(StunMsgHdr); size = msg->msgHdr.msgLength; /*ortp_message("stun: bytes after header = %i\n", size); */ while ( size > 0 ) { /* !jf! should check that there are enough bytes left in the buffer */ StunAtrHdr* attr = (StunAtrHdr*)body; /*reinterpret_cast<StunAtrHdr*>(body);*/ unsigned int attrLen = ntohs(attr->length); int atrType = ntohs(attr->type); /*if (verbose) ortp_message("stun: Found attribute type=" << AttrNames[atrType] << " length=" << attrLen << endl;*/ if ( attrLen+4 > size ) { ortp_error("stun: claims attribute is larger than size of message (attribute type=%i)\n", atrType); return FALSE; } body += 4; /* skip the length and type in attribute header */ size -= 4; if (atrType == MappedAddress) { msg->hasMappedAddress = TRUE; if ( stunParseAtrAddress( body, attrLen, &msg->mappedAddress )== FALSE ) { ortp_error("stun: problem parsing MappedAddress\n"); return FALSE; } else { if (verbose) ortp_message("stun: MappedAddress = %s\n", ipaddr(&msg->mappedAddress.ipv4)); } } else if (atrType == ResponseAddress) { msg->hasResponseAddress = TRUE; if ( stunParseAtrAddress( body, attrLen, &msg->responseAddress )== FALSE ) { ortp_error("stun: problem parsing ResponseAddress"); return FALSE; } else { if (verbose) ortp_message("stun: ResponseAddress = %s\n", ipaddr(&msg->responseAddress.ipv4)); } } else if (atrType == ChangeRequest) { msg->hasChangeRequest = TRUE; if (stunParseAtrChangeRequest( body, attrLen, &msg->changeRequest) == FALSE) { ortp_error("stun: problem parsing ChangeRequest\n"); return FALSE; } else { if (verbose) ortp_message("stun: ChangeRequest = %i\n", msg->changeRequest.value); } } else if (atrType == SourceAddress) { msg->hasSourceAddress = TRUE; if ( stunParseAtrAddress( body, attrLen, &msg->sourceAddress )== FALSE ) { ortp_error("stun: problem parsing SourceAddress\n"); return FALSE; } else { if (verbose) ortp_message("stun: SourceAddress = %s\n", ipaddr(&msg->sourceAddress.ipv4) ); } } else if (atrType == ChangedAddress) { msg->hasChangedAddress = TRUE; if ( stunParseAtrAddress( body, attrLen, &msg->changedAddress )== FALSE ) { ortp_error("stun: problem parsing ChangedAddress\n"); return FALSE; } else { if (verbose) ortp_message("stun: ChangedAddress = %s\n", ipaddr(&msg->changedAddress.ipv4)); } } else if (atrType == Username) { msg->hasUsername = TRUE; if (stunParseAtrString( body, attrLen, &msg->username) == FALSE) { ortp_error("stun: problem parsing Username"); return FALSE; } else { if (verbose) ortp_message("stun: Username = %s\n", msg->username.value ); } } else if (atrType == Password) { msg->hasPassword = TRUE; if (stunParseAtrString( body, attrLen, &msg->password) == FALSE) { ortp_error("stun: problem parsing Password"); return FALSE; } else { if (verbose) ortp_message("stun: Password = %s\n", msg->password.value ); } } else if (atrType == MessageIntegrity) { msg->hasMessageIntegrity = TRUE; if (stunParseAtrIntegrity( body, attrLen, &msg->messageIntegrity) == FALSE) { ortp_error("stun: problem parsing MessageIntegrity"); return FALSE; } else { /*if (verbose) ortp_message("stun: MessageIntegrity = " << msg->messageIntegrity.hash ); */ } /* read the current HMAC look up the password given the user of given the transaction id compute the HMAC on the buffer decide if they match or not */ } else if (atrType == ErrorCode) { msg->hasErrorCode = TRUE; if (stunParseAtrError(body, attrLen, &msg->errorCode) == FALSE) { ortp_error("stun: problem parsing ErrorCode"); return FALSE; } else { if (verbose) ortp_message("stun: ErrorCode = %i %i %s\n", msg->errorCode.errorClass , msg->errorCode.number , msg->errorCode.reason ); } } else if (atrType == UnknownAttribute) { msg->hasUnknownAttributes = TRUE; if (stunParseAtrUnknown(body, attrLen, &msg->unknownAttributes) == FALSE) { ortp_error("stun: problem parsing UnknownAttribute"); return FALSE; } } else if (atrType == ReflectedFrom) { msg->hasReflectedFrom = TRUE; if ( stunParseAtrAddress( body, attrLen, &msg->reflectedFrom ) == FALSE ) { ortp_error("stun: problem parsing ReflectedFrom"); return FALSE; } } else if (atrType == XorMappedAddress) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -