📄 stun.c
字号:
username->sizeValue = l; memcpy(username->value,buffer,l); username->value[l]=0; /* if (verbose) ortp_message("stun: computed username=%s\n", username.value ); */}voidstunCreatePassword(const StunAtrString *username, StunAtrString* password){ char hmac[20]; char key[] = "Fluffy"; /* char buffer[STUN_MAX_STRING]; */ computeHmac(hmac, username->value, strlen(username->value), key, strlen(key)); toHex(hmac, 20, password->value); password->sizeValue = 40; password->value[40]=0; /* ortp_message("stun: password=%s\n", password->value ); */}UInt64stunGetSystemTimeSecs(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( 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( 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 = BindErrorResponseMsg; 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);}#endifstatic voidstunCreateSharedSecretResponse(const StunMessage *request, const StunAddress4 *source, StunMessage *response){ response->msgHdr.msgType = SharedSecretResponseMsg; response->msgHdr.id = request->msgHdr.id; response->hasUsername = TRUE; stunCreateUserName( source, &response->username); response->hasPassword = TRUE; stunCreatePassword( &response->username, &response->password);}/* 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 *secondary, StunAddress4 *myAddr, StunAddress4 *altAddr, StunMessage *resp, StunAddress4 *destination, StunAtrString *hmacPassword, bool_t* changePort, bool_t* changeIp, bool_t verbose){ int i; StunMessage req; StunAddress4 mapped; StunAddress4 respondTo; UInt32 flags; bool_t ok; /* set up information for default response */ memset( &req, 0 , sizeof(req) ); memset( resp, 0 , sizeof(*resp) ); *changeIp = FALSE; *changePort = FALSE; ok = stunParseMessage( buf,bufLen, &req, verbose); if (!ok) /* Complete garbage, drop it on the floor */ { if (verbose) ortp_error("stun: Request did not parse"); return FALSE; } if (verbose) ortp_message("stun: Request parsed ok"); mapped = req.mappedAddress.ipv4; respondTo = req.responseAddress.ipv4; flags = req.changeRequest.value; if (req.msgHdr.msgType==SharedSecretRequestMsg) { if(verbose) ortp_message("stun: Received SharedSecretRequestMsg on udp. send error 433."); /* !cj! - should fix so you know if this came over TLS or UDP */ stunCreateSharedSecretResponse(&req, from, resp); /* stunCreateSharedSecretErrorResponse(*resp, 4, 33, "this request must be over TLS"); */ return TRUE; } else if (req.msgHdr.msgType==BindRequestMsg) { if (!req.hasMessageIntegrity) { if (verbose) ortp_message("stun: BindRequest does not contain MessageIntegrity"); if (0) /* !jf! mustAuthenticate */ { if(verbose) ortp_message("stun: Received BindRequest with no MessageIntegrity. Sending 401."); stunCreateErrorResponse(resp, 4, 1, "Missing MessageIntegrity"); return TRUE; } } else { if (!req.hasUsername) { if (verbose) ortp_message("stun: No UserName. Send 432."); stunCreateErrorResponse(resp, 4, 32, "No UserName and contains MessageIntegrity"); return TRUE; } else { if (verbose) ortp_message("stun: Validating username: %s", req.username.value ); /* !jf! could retrieve associated password from provisioning here */ if (strcmp(req.username.value, "test") == 0) { if (0) { /* !jf! if the credentials are stale */ stunCreateErrorResponse(resp, 4, 30, "Stale credentials on BindRequest"); return TRUE; } else { unsigned char hmac[20]; if (verbose) ortp_message("stun: Validating MessageIntegrity"); /* need access to shared secret */#ifndef NOSSL { unsigned int hmacSize=20; HMAC(EVP_sha1(), "1234", 4, (const unsigned char*) buf, bufLen-20-4, hmac, &hmacSize); /*HMAC(EVP_sha1(), "1234", 4, reinterpret_cast<const unsigned char*>(buf), bufLen-20-4, hmac, &hmacSize); //assert(hmacSize == 20); */ }#endif if (memcmp(buf, hmac, 20) != 0) { if (verbose) ortp_warning("stun: MessageIntegrity is bad. Sending "); stunCreateErrorResponse(resp, 4, 3, "Unknown username. Try test with password 1234"); return TRUE; } /* need to compute this later after message is filled in */ resp->hasMessageIntegrity = TRUE; /* assert(req.hasUsername); */ resp->hasUsername = TRUE; resp->username = req.username; /* copy username in */ } } else { if (verbose) ortp_message("stun: Invalid username: %s Send 430", req.username.value); } } } /* TODO !jf! should check for unknown attributes here and send 420 listing the unknown attributes. */ if ( respondTo.port == 0 ) { /* respondTo = from; */ memcpy(&respondTo, from, sizeof(StunAddress4)); } if ( mapped.port == 0 ) { /* mapped = from; */ memcpy(&mapped, from, sizeof(StunAddress4)); } *changeIp = ( flags & ChangeIpFlag )?TRUE:FALSE; *changePort = ( flags & ChangePortFlag )?TRUE:FALSE; if (verbose) { ortp_message("stun: Request is valid:\n"); ortp_message("stun: \t flags= %i\n", flags ); ortp_message("stun: \t changeIp= %i\n", *changeIp ); ortp_message("stun: \t changePort=%i\n", *changePort ); ortp_message("stun: \t from= %i\n", from->addr ); ortp_message("stun: \t respond to= %i\n", respondTo.addr ); ortp_message("stun: \t mapped= %i\n", mapped.addr ); } /* form the outgoing message */ resp->msgHdr.msgType = BindResponseMsg; for (i=0; i<16; i++ ) { resp->msgHdr.id.octet[i] = req.msgHdr.id.octet[i]; } if ( req.xorOnly == FALSE ) { resp->hasMappedAddress = TRUE; resp->mappedAddress.ipv4.port = mapped.port; resp->mappedAddress.ipv4.addr = mapped.addr; } if (1) /* do xorMapped address or not */ { UInt16 id16; UInt32 id32; resp->hasXorMappedAddress = TRUE; id16 = req.msgHdr.id.octet[7]<<8 | req.msgHdr.id.octet[6]; id32 = req.msgHdr.id.octet[7]<<24 | req.msgHdr.id.octet[6]<<16 | req.msgHdr.id.octet[5]<<8 | req.msgHdr.id.octet[4]; resp->xorMappedAddress.ipv4.port = mapped.port^id16; resp->xorMappedAddress.ipv4.addr = mapped.addr^id32; } resp->hasSourceAddress = TRUE; resp->sourceAddress.ipv4.port = (*changePort) ? altAddr->port : myAddr->port; resp->sourceAddress.ipv4.addr = (*changeIp) ? altAddr->addr : myAddr->addr; resp->hasChangedAddress = TRUE; resp->changedAddress.ipv4.port = altAddr->port; resp->changedAddress.ipv4.addr = altAddr->addr; if ( secondary->port != 0 ) { resp->hasSecondaryAddress = TRUE; resp->secondaryAddress.ipv4.port = secondary->port; resp->secondaryAddress.ipv4.addr = secondary->addr; } if ( req.hasUsername && req.username.sizeValue > 0 ) { /* copy username in */ resp->hasUsername = TRUE; /* assert( req.username.sizeValue % 4 == 0 ); */ /* assert( req.username.sizeValue < STUN_MAX_STRING ); */ memcpy( resp->username.value, req.username.value, req.username.sizeValue ); resp->username.sizeValue = req.username.sizeValue; } if (1) /* add ServerName */ { const char serverName[] = "Vovida.org " STUN_VERSION; /* must pad to mult of 4 */ resp->hasServerName = TRUE; /* assert( sizeof(serverName) < STUN_MAX_STRING ); */ /* cerr << "sizeof serverName is " << sizeof(serverName) ); */ /* assert( sizeof(serverName)%4 == 0 ); */ memcpy( resp->serverName.value, serverName, sizeof(serverName)); resp->serverName.sizeValue = sizeof(serverName); } if ( req.hasMessageIntegrity & req.hasUsername ) { /* this creates the password that will be used in the HMAC when then */ /* messages is sent */ stunCreatePassword( &req.username, hmacPassword ); } if (req.hasUsername && (req.username.sizeValue > 64 ) ) { UInt32 source; /* assert( sizeof(int) == sizeof(UInt32) ); */ sscanf(req.username.value, "%x", &source); resp->hasReflectedFrom = TRUE; resp->reflectedFrom.ipv4.port = 0; resp->reflectedFrom.ipv4.addr = source; } destination->port = respondTo.port; destination->addr = respondTo.addr; return TRUE; } else { if (verbose) ortp_error("stun: Unknown or unsupported request "); return FALSE; } /* assert(0); */ return FALSE;}bool_tstunInitServer(StunServerInfo *info, const StunAddress4 *myAddr, const StunAddress4 *altAddr, int startMediaPort, bool_t verbose ){ /* assert( myAddr.port != 0 ); */ /* assert( altAddr.port!= 0 ); */ /* assert( myAddr.addr != 0 ); */ /* assert( altAddr.addr != 0 ); */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -