📄 stun.c
字号:
ptr = encodeAtrRequestedTransport (ptr, &msg->requestedTransport); } if (msg->hasLifetimeAttributes) { ortp_debug("stun: Encoding TA_LIFETIME: %i\n", msg->lifetimeAttributes.lifetime ); ptr = encodeAtrLifeTime (ptr, &msg->lifetimeAttributes); } if (msg->hasDontFragment) { ortp_debug("stun: Encoding TA_DONTFRAGMENT: DF\n"); ptr = encodeAtrDontFragment (ptr); } if (msg->hasMappedAddress) { ortp_debug("stun: Encoding SA_MAPPEDADDRESS: %s\n", ipaddr(&msg->mappedAddress.ipv4) ); ptr = encodeAtrAddress4 (ptr, SA_MAPPEDADDRESS, &msg->mappedAddress); } if (msg->hasResponseAddress) { ortp_debug("stun: Encoding SA_RESPONSEADDRESS: %s\n", ipaddr(&msg->responseAddress.ipv4) ); ptr = encodeAtrAddress4(ptr, SA_RESPONSEADDRESS, &msg->responseAddress); } if (msg->hasChangeRequest) { ortp_debug("stun: Encoding SA_CHANGEREQUEST: %i\n", msg->changeRequest.value ); ptr = encodeAtrChangeRequest(ptr, &msg->changeRequest); } if (msg->hasSourceAddress) { ortp_debug("stun: Encoding SA_SOURCEADDRESS: %s\n", ipaddr(&msg->sourceAddress.ipv4) ); ptr = encodeAtrAddress4(ptr, SA_SOURCEADDRESS, &msg->sourceAddress); } if (msg->hasChangedAddress) { ortp_debug("stun: Encoding SA_CHANGEDADDRESS: %s\n", ipaddr(&msg->changedAddress.ipv4) ); ptr = encodeAtrAddress4(ptr, SA_CHANGEDADDRESS, &msg->changedAddress); } if (msg->hasUsername) { ortp_debug("stun: Encoding SA_USERNAME: %s\n", msg->username.value ); ptr = encodeAtrString(ptr, SA_USERNAME, &msg->username); } //if (msg->hasPassword) //{ // ortp_debug("stun: Encoding SA_PASSWORD: %s\n", msg->password.value ); // ptr = encodeAtrString(ptr, SA_PASSWORD, &msg->password); //} if (msg->hasErrorCode) { ortp_debug("stun: Encoding SA_ERRORCODE: class=%i number=%i reason=%s\n" , msg->errorCode.errorClass , msg->errorCode.number , msg->errorCode.reason ); ptr = encodeAtrError(ptr, &msg->errorCode); } if (msg->hasUnknownAttributes) { ortp_debug("stun: Encoding SA_UNKNOWNATTRIBUTE: ???"); ptr = encodeAtrUnknown(ptr, &msg->unknownAttributes); } if (msg->hasReflectedFrom) { ortp_debug("stun: Encoding SA_REFLECTEDFROM: %s\n", ipaddr(&msg->reflectedFrom.ipv4) ); ptr = encodeAtrAddress4(ptr, SA_REFLECTEDFROM, &msg->reflectedFrom); } if (msg->hasNonce) { ortp_debug("stun: Encoding SA_NONCE: %s\n", msg->nonceName.value ); ptr = encodeAtrString(ptr, SA_NONCE, &msg->nonceName); } if (msg->hasRealm) { ortp_debug("stun: Encoding SA_REALM: %s\n", msg->realmName.value ); ptr = encodeAtrString(ptr, SA_REALM, &msg->realmName); } if (msg->hasXorMappedAddress) { ortp_debug("stun: Encoding SA_XORMAPPEDADDRESS: %s\n", ipaddr(&msg->xorMappedAddress.ipv4) ); ptr = encodeAtrAddress4 (ptr, SA_XORMAPPEDADDRESS, &msg->xorMappedAddress); } if (msg->hasSoftware) { ortp_debug("stun: Encoding SA_SOFTWARE: %s\n", msg->softwareName.value ); ptr = encodeAtrString(ptr, SA_SOFTWARE, &msg->softwareName); } if (msg->hasMessageIntegrity &&password!=NULL && password->sizeValue > 0 &&msg->username.sizeValue>0 &&msg->realmName.sizeValue>0) { StunAtrIntegrity integrity; //ortp_debug("stun: HMAC with password: %s\n", password->value ); encode16(lengthp, (UInt16)(ptr - buf - sizeof(StunMsgHdr)+24)); computeHmac_longterm(integrity.hash, buf, (int)(ptr-buf) , msg->username.value, msg->realmName.value, password->value); ptr = encodeAtrIntegrity(ptr, &integrity); } else if (msg->hasMessageIntegrity &&password!=NULL && password->sizeValue > 0 &&msg->username.sizeValue>0) { StunAtrIntegrity integrity; //ortp_debug("stun: HMAC with password: %s\n", password->value ); encode16(lengthp, (UInt16)(ptr - buf - sizeof(StunMsgHdr)+24)); computeHmac_shortterm(integrity.hash, buf, (int)(ptr-buf) , password->value); ptr = encodeAtrIntegrity(ptr, &integrity); } encode16(lengthp, (UInt16)(ptr - buf - sizeof(StunMsgHdr))); return (int)(ptr - buf);}int stunRand(void){ /* return 32 bits of random stuff */ /* assert( sizeof(int) == 4 ); */ static bool_t init=FALSE; if ( !init ) { UInt64 tick; int seed; init = TRUE;#if defined(_WIN32_WCE) tick = GetTickCount ();#elif defined(_MSC_VER) { volatile unsigned int lowtick=0,hightick=0; __asm { rdtsc mov lowtick, eax mov hightick, edx } tick = hightick; tick <<= 32; tick |= lowtick; }#elif defined(__GNUC__) && ( defined(__i686__) || defined(__i386__) ) asm("rdtsc" : "=A" (tick));#elif defined(__GNUC__) && defined(__amd64__) asm("rdtsc" : "=A" (tick));#elif defined (__SUNPRO_CC) && defined( __sparc__ ) tick = gethrtime();#elif defined(__MACH__) { int fd=open("/dev/random",O_RDONLY); read(fd,&tick,sizeof(tick)); closesocket(fd); }#elif defined(__linux) || defined(HAVE_DEV_RANDOM) { fd_set fdSet; int maxFd=0; struct timeval tv; int e; int fd=open("/dev/random",O_RDONLY); if (fd<0) { ortp_message("stun: Failed to open random device\n"); return random(); } FD_ZERO(&fdSet); FD_SET(fd,&fdSet); maxFd=fd+1; tv.tv_sec = 0; tv.tv_usec = 500; e = select( maxFd, &fdSet, NULL,NULL, &tv ); if (e <= 0) { ortp_error("stun: Failed to get data from random device\n"); closesocket(fd); return random(); } read(fd,&tick,sizeof(tick)); closesocket(fd); }#else# error Need some way to seed the random number generator #endif seed = (int)(tick);#if defined(_WIN32) || defined(_WIN32_WCE) srand(seed);#else srandom(seed);#endif } #if defined(_WIN32) || defined(_WIN32_WCE) /* assert( RAND_MAX == 0x7fff ); */ { int r1 = rand(); int r2 = rand(); int ret = (r1<<16) + r2; return ret; }#else return random(); #endif}/* return a random number to use as a port */static intrandomPort(){ int min=0x4000; int max=0x7FFF; int ret = stunRand(); ret = ret|min; ret = ret&max; return ret;}#ifdef NOSSLstatic voidcomputeHmac_longterm(char* hmac, const char* input, int length, const char *username, const char *realm, const char *password){ strncpy(hmac,"hmac-not-implemented",20);}static voidcomputeHmac_shortterm(char* hmac, const char* input, int length, const char* key){ strncpy(hmac,"hmac-not-implemented",20);}#else#include <openssl/hmac.h>#include <openssl/md5.h>static voidcomputeHmac_longterm(char* hmac, const char* input, int length, const char *username, const char *realm, const char *password){ unsigned int resultSize=0; unsigned char HA1[16]; char HA1_text[1024]; snprintf(HA1_text, sizeof(HA1_text), "%s:%s:%s", username, realm, password); MD5((unsigned char *)HA1_text, strlen(HA1_text), HA1); HMAC(EVP_sha1(), HA1, 16, (const unsigned char*) input, length, (unsigned char*)hmac, &resultSize);}static voidcomputeHmac_shortterm(char* hmac, const char* input, int length, const char* key){ unsigned int resultSize=0; HMAC(EVP_sha1(), key, strlen(key), (const unsigned char*) input, length, (unsigned char*)hmac, &resultSize);}#endifUInt64stunGetSystemTimeSecs(void){ UInt64 time=0;#if defined(_WIN32) || defined(_WIN32_WCE) SYSTEMTIME t; /* CJ TODO - this probably has bug on wrap around every 24 hours */ GetSystemTime( &t ); time = (t.wHour*60+t.wMinute)*60+t.wSecond; #else struct timeval now; gettimeofday( &now , NULL ); /* assert( now ); */ time = now.tv_sec;#endif return time;}/* returns TRUE if it scucceeded */bool_t stunParseHostName( const char* peerName, UInt32* ip, UInt16* portVal, UInt16 defaultPort ){ struct in_addr sin_addr; char host[512]; char* port = NULL; int portNum = defaultPort; char* sep; struct hostent* h; strncpy(host,peerName,512); host[512-1]='\0'; /* pull out the port part if present. */ sep = strchr(host,':'); if ( sep == NULL ) { portNum = defaultPort; } else { char* endPtr=NULL; *sep = '\0'; port = sep + 1; /* set port part */ portNum = strtol(port,&endPtr,10); if ( endPtr != NULL ) { if ( *endPtr != '\0' ) { portNum = defaultPort; } } } if ( portNum < 1024 ) return FALSE; if ( portNum >= 0xFFFF ) return FALSE; /* figure out the host part */ #if defined(_WIN32) || defined(_WIN32_WCE) /* assert( strlen(host) >= 1 ); */ if ( isdigit( host[0] ) ) { /* assume it is a ip address */ unsigned long a = inet_addr(host); /* cerr << "a=0x" << hex << a << dec ); */ *ip = ntohl( a ); } else { /* assume it is a host name */ h = gethostbyname( host ); if ( h == NULL ) { /*int err = getErrno();*/ /* ortp_message("stun: error was %i\n", err); */ /* std::cerr << "error was " << err << std::endl; */ /* assert( err != WSANOTINITIALISED ); */ *ip = ntohl( 0x7F000001L ); return FALSE; } else { sin_addr = *(struct in_addr*)h->h_addr; *ip = ntohl( sin_addr.s_addr ); } } #else h = gethostbyname( host ); if ( h == NULL ) { /* int err = getErrno(); ortp_message("stun: error was %i\n", err); */ *ip = ntohl( 0x7F000001L ); return FALSE; } else { sin_addr = *(struct in_addr*)h->h_addr; *ip = ntohl( sin_addr.s_addr ); }#endif *portVal = portNum; return TRUE;}bool_tstunParseServerName( const char* name, StunAddress4 *addr){ /* assert(name); */ /* TODO - put in DNS SRV stuff. */ bool_t ret = stunParseHostName( name, &addr->addr, &addr->port, 3478); if ( ret != TRUE ) { addr->port=0xFFFF; } return ret;}static voidstunCreateErrorResponse(StunMessage *response, int cl, int number, const char* msg){ response->msgHdr.msgType = (STUN_METHOD_BINDING | STUN_ERR_RESP); response->hasErrorCode = TRUE; response->errorCode.errorClass = cl; response->errorCode.number = number; strcpy(response->errorCode.reason, msg);}#if 0static voidstunCreateSharedSecretErrorResponse(StunMessage& response, int cl, int number, const char* msg){ response.msgHdr.msgType = SharedSecretErrorResponseMsg; response.hasErrorCode = TRUE; response.errorCode.errorClass = cl; response.errorCode.number = number; strcpy(response.errorCode.reason, msg);}#endif#if 0static voidstunCreateSharedSecretResponse(const StunMessage *request, const StunAddress4 *source, StunMessage *response){ response->msgHdr.msgType = SharedSecretResponseMsg; response->msgHdr.tr_id = request->msgHdr.tr_id; response->hasUsername = TRUE; stunCreateUserName( source, &response->username); response->hasPassword = TRUE; stunCreatePassword( &response->username, &response->password);}#endif/* This funtion takes a single message sent to a stun server, parses and constructs an apropriate repsonse - returns TRUE if message is valid */bool_tstunServerProcessMsg( char* buf, unsigned int bufLen, StunAddress4 *from, StunAddress4 *myAddr, StunAddress4 *altAddr, StunMessage *resp, StunAddress4 *destination, StunAtrString *hmacPassword, bool_t* changePort, bool_t* changeIp){ int i; StunMessage req; StunAddress4 mapped; StunAddress4 respondTo; UInt32 flags; bool_t ok;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -