Skip to content

Commit

Permalink
fix: auth is not possible without enabling hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
mycrl committed Dec 31, 2024
1 parent 70f356c commit fc2b39b
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 39 deletions.
50 changes: 41 additions & 9 deletions turn-server/src/observer.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use std::sync::Arc;

use base64::{prelude::BASE64_STANDARD, Engine};

use crate::{config::Config, statistics::Statistics};

#[cfg(feature = "hooks")]
Expand All @@ -14,6 +16,7 @@ use turn::SessionAddr;

#[derive(Clone)]
pub struct Observer {
config: Arc<Config>,
#[cfg(feature = "hooks")]
hooks: Arc<HooksService>,
#[cfg(feature = "api")]
Expand All @@ -25,28 +28,45 @@ impl Observer {
pub async fn new(config: Arc<Config>, statistics: Statistics) -> Result<Self> {
Ok(Self {
#[cfg(feature = "hooks")]
hooks: Arc::new(HooksService::new(config)?),
hooks: Arc::new(HooksService::new(config.clone())?),
#[cfg(feature = "api")]
statistics,
config,
})
}
}

#[async_trait]
impl turn::Observer for Observer {
#[cfg(feature = "hooks")]
async fn get_password(&self, addr: &SessionAddr, name: &str) -> Option<String> {
let pwd = self.hooks.get_password(addr, name).await;

async fn get_password(&self, addr: &SessionAddr, username: &str) -> Option<String> {
log::info!(
"auth: address={:?}, interface={:?}, username={:?}, password={:?}",
"auth: address={:?}, interface={:?}, username={:?}",
addr.address,
addr.interface,
name,
pwd
username,
);

pwd
// Match the static authentication information first.
if let Some(pwd) = self.config.auth.static_credentials.get(username) {
return Some(pwd.clone());
}

// Try again to match the static authentication key.
if let Some(secret) = &self.config.auth.static_auth_secret {
// Because (TURN REST api) this RFC does not mandate the format of the username,
// only suggested values. In principle, the RFC also indicates that the
// timestamp part of username can be set at will, so the timestamp is not
// verified here, and the external web service guarantees its security by
// itself.
return encode_password(secret, username);
}

#[cfg(feature = "hooks")]
if let Some(pwd) = self.hooks.get_password(addr, username).await {
return Some(pwd);
}

None
}

/// allocate request
Expand Down Expand Up @@ -307,3 +327,15 @@ impl turn::Observer for Observer {
}
}
}

// https://datatracker.ietf.org/doc/html/draft-uberti-behave-turn-rest-00#section-2.2
fn encode_password(key: &str, username: &str) -> Option<String> {
Some(
BASE64_STANDARD.encode(
stun::util::hmac_sha1(key.as_bytes(), &[username.as_bytes()])
.ok()?
.into_bytes()
.as_slice(),
),
)
}
32 changes: 2 additions & 30 deletions turn-server/src/publicly.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,6 @@ pub mod hooks {
use std::{sync::Arc, time::Duration};

use axum::http::{HeaderMap, HeaderValue};
use base64::{prelude::BASE64_STANDARD, Engine};
use reqwest::{Client, ClientBuilder};
use serde_json::Value;
use tokio::sync::mpsc::{unbounded_channel, UnboundedSender};
Expand Down Expand Up @@ -241,24 +240,9 @@ pub mod hooks {
Ok(Self { client, config, tx })
}

// There are no matching static entries, get the password from an external hook
// service.
pub async fn get_password(&self, addr: &SessionAddr, username: &str) -> Option<String> {
// Match the static authentication information first.
if let Some(pwd) = self.config.auth.static_credentials.get(username) {
return Some(pwd.clone());
}

// Try again to match the static authentication key.
if let Some(secret) = &self.config.auth.static_auth_secret {
// Because (TURN REST api) this RFC does not mandate the format of the username,
// only suggested values. In principle, the RFC also indicates that the
// timestamp part of username can be set at will, so the timestamp is not
// verified here, and the external web service guarantees its security by
// itself.
return encode_password(secret, username);
}

// There are no matching static entries, get the password from an external hook
// service.
if let Some(server) = &self.config.api.hooks {
if let Ok(res) = self
.client
Expand Down Expand Up @@ -289,18 +273,6 @@ pub mod hooks {
}
}
}

// https://datatracker.ietf.org/doc/html/draft-uberti-behave-turn-rest-00#section-2.2
fn encode_password(key: &str, username: &str) -> Option<String> {
Some(
BASE64_STANDARD.encode(
stun::util::hmac_sha1(key.as_bytes(), &[username.as_bytes()])
.ok()?
.into_bytes()
.as_slice(),
),
)
}
}

fn random_string(len: usize) -> String {
Expand Down

0 comments on commit fc2b39b

Please sign in to comment.