Skip to content

Commit 9f9df59

Browse files
committed
refactor: streamline realm checking in proxy and user authentication
1 parent f511adb commit 9f9df59

10 files changed

Lines changed: 69 additions & 33 deletions

File tree

config.toml.example

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,15 @@ method = "POST"
4040
mode = "auto"
4141
rtp_start_port = 20000
4242
rtp_end_port = 30000
43+
4344
# external_ip = "192.168.1.1" # Set to your external IP
4445
# force_proxy = ["192.168.1.100"] # Optional: IP addresses to always proxy
4546

4647
[proxy.user_backend]
4748
type = "memory"
4849
users = [
4950
{ username = "bob", password = "123456", realm = "127.0.0.1" },
50-
{ username = "alice", password = "123456", realm = "127.0.0.1" },
51+
{ username = "alice", password = "123456" },
5152
]
5253

5354
[callrecord]

src/config.rs

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -253,25 +253,6 @@ impl ProxyConfig {
253253
realm
254254
}
255255
}
256-
pub fn is_same_realm(&self, callee_realm: &str) -> bool {
257-
match callee_realm {
258-
"localhost" | "127.0.0.1" | "::1" => true,
259-
_ => {
260-
if let Some(external_ip) = self.external_ip.as_ref() {
261-
return external_ip.starts_with(callee_realm);
262-
}
263-
if let Some(realms) = self.realms.as_ref() {
264-
for item in realms {
265-
if item == callee_realm {
266-
return true;
267-
}
268-
}
269-
}
270-
false
271-
}
272-
}
273-
}
274-
275256
pub async fn route_invite(
276257
&self,
277258
option: InviteOption,

src/proxy/auth.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ impl AuthModule {
5151
return Ok(None);
5252
}
5353
if let Some(realm) = user.realm.as_ref() {
54-
if !self.server.config.is_same_realm(realm) {
54+
if !self.server.is_same_realm(realm).await {
5555
info!(username = user.username, realm = ?user.realm, "User is not in the same realm");
5656
return Ok(None);
5757
}

src/proxy/call.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ impl CallModule {
120120
let callee = callee_uri.user().unwrap_or_default().to_string();
121121
let callee_realm = callee_uri.host().to_string();
122122

123-
let target_locations = if !self.inner.config.is_same_realm(&callee_realm) {
123+
let target_locations = if !self.inner.server.is_same_realm(&callee_realm).await {
124124
info!(callee_realm, "Forwarding INVITE to external realm");
125125
vec![Location {
126126
aor: callee_uri.clone(),

src/proxy/server.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,3 +452,24 @@ impl Drop for SipServerInner {
452452
info!("SipServerInner dropped");
453453
}
454454
}
455+
456+
impl SipServerInner {
457+
pub async fn is_same_realm(&self, callee_realm: &str) -> bool {
458+
match callee_realm {
459+
"localhost" | "127.0.0.1" | "::1" => true,
460+
_ => {
461+
if let Some(external_ip) = self.config.external_ip.as_ref() {
462+
return external_ip.starts_with(callee_realm);
463+
}
464+
if let Some(realms) = self.config.realms.as_ref() {
465+
for item in realms {
466+
if item == callee_realm {
467+
return true;
468+
}
469+
}
470+
}
471+
self.user_backend.is_same_realm(callee_realm).await
472+
}
473+
}
474+
}
475+
}

src/proxy/user.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ pub trait UserBackend: Send + Sync {
181181
user.to_string()
182182
}
183183
}
184+
async fn is_same_realm(&self, realm: &str) -> bool;
184185
async fn get_user(&self, username: &str, realm: Option<&str>) -> Result<SipUser>;
185186
async fn create_user(&self, _user: SipUser) -> Result<()> {
186187
Ok(())
@@ -283,6 +284,10 @@ impl MemoryUserBackend {
283284

284285
#[async_trait]
285286
impl UserBackend for MemoryUserBackend {
287+
async fn is_same_realm(&self, realm: &str) -> bool {
288+
return realm.is_empty();
289+
}
290+
286291
fn get_identifier(&self, user: &str, realm: Option<&str>) -> String {
287292
Self::get_identifier(user, realm)
288293
}
@@ -292,7 +297,18 @@ impl UserBackend for MemoryUserBackend {
292297
let identifier = self.get_identifier(username, realm);
293298
let mut user = match users.get(&identifier) {
294299
Some(user) => user.clone(),
295-
None => return Err(anyhow::anyhow!("missing user: {}", identifier)),
300+
None => {
301+
match users.get(username) {
302+
Some(user) => {
303+
if user.realm.as_ref().is_some_and(|r| !r.is_empty()) {
304+
return Err(anyhow::anyhow!("missing user: {}", identifier));
305+
}
306+
return Ok(user.clone());
307+
}
308+
None => {}
309+
}
310+
return Err(anyhow::anyhow!("missing user: {}", identifier));
311+
}
296312
};
297313
user.realm = realm.map(|r| r.to_string());
298314
Ok(user)

src/proxy/user_db.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,23 @@ impl DbBackend {
4242

4343
#[async_trait]
4444
impl UserBackend for DbBackend {
45+
async fn is_same_realm(&self, realm: &str) -> bool {
46+
if let Some(ref realm_col) = self.realm_column {
47+
let query = format!(
48+
"SELECT COUNT(*) FROM {} WHERE {} = ?",
49+
self.table_name, realm_col
50+
);
51+
let count = sqlx::query(&query)
52+
.bind(realm)
53+
.fetch_one(&self.db)
54+
.await
55+
.map_err(|e| anyhow!("Database query error: {}", e))
56+
.map(|row| row.get(0))
57+
.unwrap_or(0);
58+
return count > 0;
59+
}
60+
false
61+
}
4562
async fn get_user(&self, username: &str, realm: Option<&str>) -> Result<SipUser> {
4663
// Build SELECT clause with optional columns
4764
let mut select_columns = vec![self.username_column.clone(), self.password_column.clone()];

src/proxy/user_http.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ impl HttpUserBackend {
5353

5454
#[async_trait]
5555
impl UserBackend for HttpUserBackend {
56+
async fn is_same_realm(&self, realm: &str) -> bool {
57+
self.get_user("", Some(realm)).await.is_ok()
58+
}
5659
async fn get_user(&self, username: &str, realm: Option<&str>) -> Result<SipUser> {
5760
let start_time = Instant::now();
5861
let mut request_builder = match self.method {

src/proxy/user_plain.rs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -70,19 +70,16 @@ impl PlainTextBackend {
7070

7171
#[async_trait]
7272
impl UserBackend for PlainTextBackend {
73+
async fn is_same_realm(&self, realm: &str) -> bool {
74+
return realm.is_empty();
75+
}
7376
async fn get_user(&self, username: &str, realm: Option<&str>) -> Result<SipUser> {
74-
let key = if let Some(realm) = realm {
75-
format!("{}@{}", username, realm)
76-
} else {
77-
username.to_string()
78-
};
79-
80-
let mut user = match self.users.lock().unwrap().get(&key) {
77+
let mut user = match self.users.lock().unwrap().get(username) {
8178
Some(user) => user.clone(),
82-
None => return Err(anyhow::anyhow!("missing user: {}", key)),
79+
None => return Err(anyhow::anyhow!("missing user: {}", username)),
8380
};
8481
if !user.enabled {
85-
return Err(anyhow::anyhow!("User is disabled: {}", key));
82+
return Err(anyhow::anyhow!("User is disabled: {}", username));
8683
}
8784
user.realm = realm.map(|r| r.to_string());
8885
Ok(user)

static/phone.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ <h3>Logs</h3>
235235

236236
function log(message) {
237237
const timestamp = new Date().toLocaleTimeString();
238-
logs.innerHTML += `[${timestamp}] ${message}\n`;
238+
logs.innerHTML += `[${timestamp}] ${message}<br>`;
239239
logs.scrollTop = logs.scrollHeight;
240240
console.log(message);
241241
}

0 commit comments

Comments
 (0)