📄 stun.cxx
字号:
#include <cassert>#include <cstring>#include <iostream>#include <cstdlib> #include <errno.h>#ifdef WIN32#include <winsock2.h>#include <stdlib.h>#include <io.h>#include <time.h>#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#if defined(__sparc__) || defined(WIN32)#define NOSSL#endif#define NOSSL#include "udp.h"#include "stun.h"using namespace std;static voidcomputeHmac(char* hmac, const char* input, int length, const char* key, int keySize);static bool stunParseAtrAddress( char* body, unsigned int hdrLen, StunAtrAddress4& result ){ if ( hdrLen != 8 ) { clog << "hdrLen wrong for Address" <<endl; return false; } result.pad = *body++; result.family = *body++; if (result.family == IPv4Family) { UInt16 nport; memcpy(&nport, body, 2); body+=2; result.ipv4.port = ntohs(nport); UInt32 naddr; memcpy(&naddr, body, 4); body+=4; result.ipv4.addr = ntohl(naddr); return true; } else if (result.family == IPv6Family) { clog << "ipv6 not supported" << endl; } else { clog << "bad address family: " << result.family << endl; } return false;}static bool stunParseAtrChangeRequest( char* body, unsigned int hdrLen, StunAtrChangeRequest& result ){ if ( hdrLen != 4 ) { clog << "hdr length = " << hdrLen << " expecting " << sizeof(result) << endl; clog << "Incorrect size for ChangeRequest" << endl; return false; } else { memcpy(&result.value, body, 4); result.value = ntohl(result.value); return true; }}static bool stunParseAtrError( char* body, unsigned int hdrLen, StunAtrError& result ){ if ( hdrLen >= sizeof(result) ) { clog << "head on Error too large" << endl; 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 stunParseAtrUnknown( char* body, unsigned int hdrLen, StunAtrUnknown& result ){ if ( hdrLen >= sizeof(result) ) { return false; } else { if (hdrLen % 4 != 0) return false; result.numAttributes = hdrLen / 4; for (int 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 stunParseAtrString( char* body, unsigned int hdrLen, StunAtrString& result ){ if ( hdrLen >= STUN_MAX_STRING ) { clog << "String is too large" << endl; return false; } else { if (hdrLen % 4 != 0) { clog << "Bad length string " << hdrLen << endl; return false; } result.sizeValue = hdrLen; memcpy(&result.value, body, hdrLen); result.value[hdrLen] = 0; return true; }}static bool stunParseAtrIntegrity( char* body, unsigned int hdrLen, StunAtrIntegrity& result ){ if ( hdrLen != 20) { clog << "MessageIntegrity must be 20 bytes" << endl; return false; } else { memcpy(&result.hash, body, hdrLen); return true; }}boolstunParseMessage( char* buf, unsigned int bufLen, StunMessage& msg, bool verbose){ if (verbose) clog << "Received stun message: " << bufLen << " bytes" << endl; memset(&msg, 0, sizeof(msg)); if (sizeof(StunMsgHdr) > bufLen) { clog << "Bad message" << endl; 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) { clog << "Message header length doesn't match message size: " << msg.msgHdr.msgLength << " - " << bufLen << endl; return false; } char* body = buf + sizeof(StunMsgHdr); unsigned int size = msg.msgHdr.msgLength; //clog << "bytes after header = " << size << endl; while ( size > 0 ) { // !jf! should check that there are enough bytes left in the buffer StunAtrHdr* attr = reinterpret_cast<StunAtrHdr*>(body); unsigned int attrLen = ntohs(attr->length); int atrType = ntohs(attr->type); //if (verbose) clog << "Found attribute type=" << AttrNames[atrType] << " length=" << attrLen << endl; if ( attrLen+4 > size ) { clog << "claims attribute is larger than size of message " <<"(attribute type="<<atrType<<")"<< endl; return false; } body += 4; // skip the length and type in attribute header size -= 4; switch ( atrType ) { case MappedAddress: msg.hasMappedAddress = true; if ( stunParseAtrAddress( body, attrLen, msg.mappedAddress )== false ) { clog << "problem parsing MappedAddress" << endl; return false; } else { if (verbose) clog << "MappedAddress = " << msg.mappedAddress.ipv4 << endl; } break; case ResponseAddress: msg.hasResponseAddress = true; if ( stunParseAtrAddress( body, attrLen, msg.responseAddress )== false ) { clog << "problem parsing ResponseAddress" << endl; return false; } else { if (verbose) clog << "ResponseAddress = " << msg.responseAddress.ipv4 << endl; } break; case ChangeRequest: msg.hasChangeRequest = true; if (stunParseAtrChangeRequest( body, attrLen, msg.changeRequest) == false) { clog << "problem parsing ChangeRequest" << endl; return false; } else { if (verbose) clog << "ChangeRequest = " << msg.changeRequest.value << endl; } break; case SourceAddress: msg.hasSourceAddress = true; if ( stunParseAtrAddress( body, attrLen, msg.sourceAddress )== false ) { clog << "problem parsing SourceAddress" << endl; return false; } else { if (verbose) clog << "SourceAddress = " << msg.sourceAddress.ipv4 << endl; } break; case ChangedAddress: msg.hasChangedAddress = true; if ( stunParseAtrAddress( body, attrLen, msg.changedAddress )== false ) { clog << "problem parsing ChangedAddress" << endl; return false; } else { if (verbose) clog << "ChangedAddress = " << msg.changedAddress.ipv4 << endl; } break; case Username: msg.hasUsername = true; if (stunParseAtrString( body, attrLen, msg.username) == false) { clog << "problem parsing Username" << endl; return false; } else { if (verbose) clog << "Username = " << msg.username.value << endl; } break; case Password: msg.hasPassword = true; if (stunParseAtrString( body, attrLen, msg.password) == false) { clog << "problem parsing Password" << endl; return false; } else { if (verbose) clog << "Password = " << msg.password.value << endl; } break; case MessageIntegrity: msg.hasMessageIntegrity = true; if (stunParseAtrIntegrity( body, attrLen, msg.messageIntegrity) == false) { clog << "problem parsing MessageIntegrity" << endl; return false; } else { //if (verbose) clog << "MessageIntegrity = " << msg.messageIntegrity.hash << endl; } // 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 break; case ErrorCode: msg.hasErrorCode = true; if (stunParseAtrError(body, attrLen, msg.errorCode) == false) { clog << "problem parsing ErrorCode" << endl; return false; } else { if (verbose) clog << "ErrorCode = " << int(msg.errorCode.errorClass) << " " << int(msg.errorCode.number) << " " << msg.errorCode.reason << endl; } break; case UnknownAttribute: msg.hasUnknownAttributes = true; if (stunParseAtrUnknown(body, attrLen, msg.unknownAttributes) == false) { clog << "problem parsing UnknownAttribute" << endl; return false; } break; case ReflectedFrom: msg.hasReflectedFrom = true; if ( stunParseAtrAddress( body, attrLen, msg.reflectedFrom ) == false ) { clog << "problem parsing ReflectedFrom" << endl; return false; } break; case XorMappedAddress: msg.hasXorMappedAddress = true; if ( stunParseAtrAddress( body, attrLen, msg.xorMappedAddress ) == false ) { clog << "problem parsing XorMappedAddress" << endl; return false; } else { if (verbose) clog << "XorMappedAddress = " << msg.mappedAddress.ipv4 << endl; } break; case XorOnly: msg.xorOnly = true; if (verbose) { clog << "xorOnly = true" << endl; } break; case ServerName: msg.hasServerName = true; if (stunParseAtrString( body, attrLen, msg.serverName) == false) { clog << "problem parsing ServerName" << endl; return false; } else { if (verbose) clog << "ServerName = " << msg.serverName.value << endl; } break; case SecondaryAddress: msg.hasSecondaryAddress = true; if ( stunParseAtrAddress( body, attrLen, msg.secondaryAddress ) == false ) { clog << "problem parsing secondaryAddress" << endl; return false; } else { if (verbose) clog << "SecondaryAddress = " << msg.secondaryAddress.ipv4 << endl; } break; default: if (verbose) clog << "Unknown attribute: " << atrType << endl; if ( atrType <= 0x7FFF ) { return false; } } body += attrLen; size -= attrLen; } return true;}static char* encode16(char* buf, UInt16 data){ UInt16 ndata = htons(data); memcpy(buf, reinterpret_cast<void*>(&ndata), sizeof(UInt16)); return buf + sizeof(UInt16);}static char* encode32(char* buf, UInt32 data){ UInt32 ndata = htonl(data); memcpy(buf, reinterpret_cast<void*>(&ndata), sizeof(UInt32)); return buf + sizeof(UInt32);}static char* encode(char* buf, const char* data, unsigned int length){ memcpy(buf, data, length); return buf + length;}static char* encodeAtrAddress4(char* ptr, UInt16 type, const StunAtrAddress4& atr){ ptr = encode16(ptr, type); ptr = encode16(ptr, 8); *ptr++ = atr.pad; *ptr++ = IPv4Family; ptr = encode16(ptr, atr.ipv4.port); ptr = encode32(ptr, atr.ipv4.addr); return ptr;}static char* encodeAtrChangeRequest(char* ptr, const StunAtrChangeRequest& atr){ ptr = encode16(ptr, ChangeRequest); ptr = encode16(ptr, 4); ptr = encode32(ptr, atr.value); return ptr;}static char* encodeAtrError(char* ptr, const StunAtrError& atr){ ptr = encode16(ptr, ErrorCode);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -