relay: fix stale nonce error code (#1942)

In the gateway/client we were looking at an error that looked like:

```
firezone-client-1  | 2023-08-23T20:58:50.456400Z ERROR turn::client::relay_conn: fail to refresh permissions: CreatePermission error response (error 401: Unauthorized)    
firezone-client-1  | 2023-08-23T20:58:50.456413Z  WARN turn::client::relay_conn: refresh permissions failed    
```

This was due to a slightly non-compliant behavior on the relay part
where it was responding with a 401 instead of a 438 when a nonce was
stale which is the behavior described by [RFC
5389](https://datatracker.ietf.org/doc/html/rfc5389#section-10.2.2)

This PR should fix this and we should no longer see that refresh
permissions error.
This commit is contained in:
Gabi
2023-08-24 13:50:54 -03:00
committed by GitHub
parent 3316d9098a
commit e216a9e69f

View File

@@ -29,7 +29,7 @@ use std::time::{Duration, SystemTime};
use stun_codec::rfc5389::attributes::{
ErrorCode, MessageIntegrity, Nonce, Realm, Username, XorMappedAddress,
};
use stun_codec::rfc5389::errors::{BadRequest, Unauthorized};
use stun_codec::rfc5389::errors::{BadRequest, StaleNonce, Unauthorized};
use stun_codec::rfc5389::methods::BINDING;
use stun_codec::rfc5766::attributes::{
ChannelNumber, Lifetime, RequestedTransport, XorPeerAddress, XorRelayAddress,
@@ -296,10 +296,12 @@ where
}
fn queue_error_response(&mut self, sender: SocketAddr, mut error_response: Message<Attribute>) {
// In case of a 401 response, attach a realm and nonce.
// In case of a 401 or 438 response, attach a realm and nonce.
if error_response
.get_attribute::<ErrorCode>()
.map_or(false, |error| error == &ErrorCode::from(Unauthorized))
.map_or(false, |error| {
error == &ErrorCode::from(Unauthorized) || error == &ErrorCode::from(StaleNonce)
})
{
let new_nonce = Uuid::from_u128(self.rng.gen());
@@ -760,7 +762,7 @@ where
self.nonces
.handle_nonce_used(nonce)
.map_err(|_| error_response(Unauthorized, request))?;
.map_err(|_| error_response(StaleNonce, request))?;
message_integrity
.verify(&self.auth_secret, username.name(), now)