Don't crash if STUN error message is missing ERROR-CODE attribute.
This is something a well-behaving STUN server shouldn't do, but we shouldn't crash if it does happen. Also adding helper function for the common operation of extracting just the error code out of a STUN packet. BUG=chromium:708469 Review-Url: https://codereview.webrtc.org/2837133003 Cr-Commit-Position: refs/heads/master@{#17892}
This commit is contained in:
parent
65881de6c8
commit
996fc6bdb7
@ -1411,12 +1411,7 @@ void Connection::OnConnectionRequestResponse(ConnectionRequest* request,
|
||||
|
||||
void Connection::OnConnectionRequestErrorResponse(ConnectionRequest* request,
|
||||
StunMessage* response) {
|
||||
const StunErrorCodeAttribute* error_attr = response->GetErrorCode();
|
||||
int error_code = STUN_ERROR_GLOBAL_FAILURE;
|
||||
if (error_attr) {
|
||||
error_code = error_attr->code();
|
||||
}
|
||||
|
||||
int error_code = response->GetErrorCodeValue();
|
||||
LOG_J(LS_INFO, this) << "Received STUN error response"
|
||||
<< " id=" << rtc::hex_encode(request->id())
|
||||
<< " code=" << error_code
|
||||
|
||||
@ -824,7 +824,7 @@ void AllocateRequest::OnResponse(StunMessage* response) {
|
||||
void AllocateRequest::OnErrorResponse(StunMessage* response) {
|
||||
const StunErrorCodeAttribute* attr = response->GetErrorCode();
|
||||
if (!attr) {
|
||||
LOG(INFO) << "Bad allocate response error code";
|
||||
LOG(LS_ERROR) << "Missing allocate response error code.";
|
||||
} else {
|
||||
LOG(INFO) << "Allocate error response:"
|
||||
<< " code=" << attr->code()
|
||||
|
||||
@ -115,6 +115,11 @@ const StunErrorCodeAttribute* StunMessage::GetErrorCode() const {
|
||||
GetAttribute(STUN_ATTR_ERROR_CODE));
|
||||
}
|
||||
|
||||
int StunMessage::GetErrorCodeValue() const {
|
||||
const StunErrorCodeAttribute* error_attribute = GetErrorCode();
|
||||
return error_attribute ? error_attribute->code() : STUN_ERROR_GLOBAL_FAILURE;
|
||||
}
|
||||
|
||||
const StunUInt16ListAttribute* StunMessage::GetUnknownAttributes() const {
|
||||
return static_cast<const StunUInt16ListAttribute*>(
|
||||
GetAttribute(STUN_ATTR_UNKNOWN_ATTRIBUTES));
|
||||
|
||||
@ -156,6 +156,9 @@ class StunMessage {
|
||||
|
||||
// Gets these specific attribute values.
|
||||
const StunErrorCodeAttribute* GetErrorCode() const;
|
||||
// Returns the code inside the error code attribute, if present, and
|
||||
// STUN_ERROR_GLOBAL_FAILURE otherwise.
|
||||
int GetErrorCodeValue() const;
|
||||
const StunUInt16ListAttribute* GetUnknownAttributes() const;
|
||||
|
||||
// Takes ownership of the specified attribute and adds it to the message.
|
||||
|
||||
@ -1016,6 +1016,15 @@ TEST_F(StunTest, ReadErrorCodeAttribute) {
|
||||
EXPECT_EQ(kTestErrorNumber, errorcode->number());
|
||||
EXPECT_EQ(kTestErrorReason, errorcode->reason());
|
||||
EXPECT_EQ(kTestErrorCode, errorcode->code());
|
||||
EXPECT_EQ(kTestErrorCode, msg.GetErrorCodeValue());
|
||||
}
|
||||
|
||||
// Test that GetErrorCodeValue returns STUN_ERROR_GLOBAL_FAILURE if the message
|
||||
// in question doesn't have an error code attribute, rather than crashing.
|
||||
TEST_F(StunTest, GetErrorCodeValueWithNoErrorAttribute) {
|
||||
StunMessage msg;
|
||||
ReadStunMessage(&msg, kStunMessageWithIPv6MappedAddress);
|
||||
EXPECT_EQ(STUN_ERROR_GLOBAL_FAILURE, msg.GetErrorCodeValue());
|
||||
}
|
||||
|
||||
TEST_F(StunTest, ReadMessageWithAUInt16ListAttribute) {
|
||||
|
||||
@ -66,7 +66,7 @@ class StunBindingRequest : public StunRequest {
|
||||
virtual void OnErrorResponse(StunMessage* response) override {
|
||||
const StunErrorCodeAttribute* attr = response->GetErrorCode();
|
||||
if (!attr) {
|
||||
LOG(LS_ERROR) << "Bad allocate response error code";
|
||||
LOG(LS_ERROR) << "Missing binding response error code.";
|
||||
} else {
|
||||
LOG(LS_ERROR) << "Binding error response:"
|
||||
<< " class=" << attr->eclass()
|
||||
|
||||
@ -1165,19 +1165,18 @@ void TurnAllocateRequest::OnResponse(StunMessage* response) {
|
||||
|
||||
void TurnAllocateRequest::OnErrorResponse(StunMessage* response) {
|
||||
// Process error response according to RFC5766, Section 6.4.
|
||||
const StunErrorCodeAttribute* error_code = response->GetErrorCode();
|
||||
int error_code = response->GetErrorCodeValue();
|
||||
|
||||
LOG_J(LS_INFO, port_) << "Received TURN allocate error response"
|
||||
<< ", id=" << rtc::hex_encode(id())
|
||||
<< ", code=" << error_code->code()
|
||||
<< ", rtt=" << Elapsed();
|
||||
<< ", code=" << error_code << ", rtt=" << Elapsed();
|
||||
|
||||
switch (error_code->code()) {
|
||||
switch (error_code) {
|
||||
case STUN_ERROR_UNAUTHORIZED: // Unauthrorized.
|
||||
OnAuthChallenge(response, error_code->code());
|
||||
OnAuthChallenge(response, error_code);
|
||||
break;
|
||||
case STUN_ERROR_TRY_ALTERNATE:
|
||||
OnTryAlternate(response, error_code->code());
|
||||
OnTryAlternate(response, error_code);
|
||||
break;
|
||||
case STUN_ERROR_ALLOCATION_MISMATCH:
|
||||
// We must handle this error async because trying to delete the socket in
|
||||
@ -1186,10 +1185,10 @@ void TurnAllocateRequest::OnErrorResponse(StunMessage* response) {
|
||||
TurnPort::MSG_ALLOCATE_MISMATCH);
|
||||
break;
|
||||
default:
|
||||
LOG_J(LS_WARNING, port_) << "Received TURN allocate error response"
|
||||
<< ", id=" << rtc::hex_encode(id())
|
||||
<< ", code=" << error_code->code()
|
||||
<< ", rtt=" << Elapsed();
|
||||
LOG_J(LS_WARNING, port_)
|
||||
<< "Received TURN allocate error response"
|
||||
<< ", id=" << rtc::hex_encode(id()) << ", code=" << error_code
|
||||
<< ", rtt=" << Elapsed();
|
||||
port_->OnAllocateError();
|
||||
}
|
||||
}
|
||||
@ -1321,20 +1320,20 @@ void TurnRefreshRequest::OnResponse(StunMessage* response) {
|
||||
}
|
||||
|
||||
void TurnRefreshRequest::OnErrorResponse(StunMessage* response) {
|
||||
const StunErrorCodeAttribute* error_code = response->GetErrorCode();
|
||||
int error_code = response->GetErrorCodeValue();
|
||||
|
||||
if (error_code->code() == STUN_ERROR_STALE_NONCE) {
|
||||
if (error_code == STUN_ERROR_STALE_NONCE) {
|
||||
if (port_->UpdateNonce(response)) {
|
||||
// Send RefreshRequest immediately.
|
||||
port_->SendRequest(new TurnRefreshRequest(port_), 0);
|
||||
}
|
||||
} else {
|
||||
LOG_J(LS_WARNING, port_) << "Received TURN refresh error response"
|
||||
<< ", id=" << rtc::hex_encode(id())
|
||||
<< ", code=" << error_code->code()
|
||||
<< ", rtt=" << Elapsed();
|
||||
LOG_J(LS_WARNING, port_)
|
||||
<< "Received TURN refresh error response"
|
||||
<< ", id=" << rtc::hex_encode(id()) << ", code=" << error_code
|
||||
<< ", rtt=" << Elapsed();
|
||||
port_->OnRefreshError();
|
||||
port_->SignalTurnRefreshResult(port_, error_code->code());
|
||||
port_->SignalTurnRefreshResult(port_, error_code);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1380,13 +1379,12 @@ void TurnCreatePermissionRequest::OnResponse(StunMessage* response) {
|
||||
}
|
||||
|
||||
void TurnCreatePermissionRequest::OnErrorResponse(StunMessage* response) {
|
||||
const StunErrorCodeAttribute* error_code = response->GetErrorCode();
|
||||
int error_code = response->GetErrorCodeValue();
|
||||
LOG_J(LS_WARNING, port_) << "Received TURN create permission error response"
|
||||
<< ", id=" << rtc::hex_encode(id())
|
||||
<< ", code=" << error_code->code()
|
||||
<< ", rtt=" << Elapsed();
|
||||
<< ", code=" << error_code << ", rtt=" << Elapsed();
|
||||
if (entry_) {
|
||||
entry_->OnCreatePermissionError(response, error_code->code());
|
||||
entry_->OnCreatePermissionError(response, error_code);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1450,13 +1448,12 @@ void TurnChannelBindRequest::OnResponse(StunMessage* response) {
|
||||
}
|
||||
|
||||
void TurnChannelBindRequest::OnErrorResponse(StunMessage* response) {
|
||||
const StunErrorCodeAttribute* error_code = response->GetErrorCode();
|
||||
int error_code = response->GetErrorCodeValue();
|
||||
LOG_J(LS_WARNING, port_) << "Received TURN channel bind error response"
|
||||
<< ", id=" << rtc::hex_encode(id())
|
||||
<< ", code=" << error_code->code()
|
||||
<< ", rtt=" << Elapsed();
|
||||
<< ", code=" << error_code << ", rtt=" << Elapsed();
|
||||
if (entry_) {
|
||||
entry_->OnChannelBindError(response, error_code->code());
|
||||
entry_->OnChannelBindError(response, error_code);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user