Add more verbose logging for message integrity :)
This commit is contained in:
parent
d02771b4f8
commit
5486744bee
30
src/auth.rs
30
src/auth.rs
@ -3,7 +3,13 @@
|
|||||||
use crate::config::AuthOptions;
|
use crate::config::AuthOptions;
|
||||||
use crate::constants::{ATTR_NONCE, ATTR_REALM, ATTR_USERNAME};
|
use crate::constants::{ATTR_NONCE, ATTR_REALM, ATTR_USERNAME};
|
||||||
use crate::models::stun::StunMessage;
|
use crate::models::stun::StunMessage;
|
||||||
use crate::stun::{find_message_integrity, validate_message_integrity, validate_message_integrity_len_preserved};
|
use crate::stun::{
|
||||||
|
compute_message_integrity_adjusted,
|
||||||
|
compute_message_integrity_len_preserved as compute_mi_len_preserved,
|
||||||
|
find_message_integrity,
|
||||||
|
validate_message_integrity,
|
||||||
|
validate_message_integrity_len_preserved,
|
||||||
|
};
|
||||||
use crate::traits::CredentialStore;
|
use crate::traits::CredentialStore;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use base64::Engine;
|
use base64::Engine;
|
||||||
@ -204,12 +210,24 @@ impl<S: CredentialStore + Clone> AuthManager<S> {
|
|||||||
return AuthStatus::Granted { username, key };
|
return AuthStatus::Granted { username, key };
|
||||||
}
|
}
|
||||||
|
|
||||||
// No acceptance without MI validation.
|
// No acceptance without MI validation. Emit detailed diagnostics.
|
||||||
let mi_attr = find_message_integrity(msg).map(|a| hex::encode(&a.value));
|
let mi_attr = find_message_integrity(msg).map(|a| hex::encode(&a.value));
|
||||||
let mi_long = hex::encode(&crate::stun::compute_message_integrity(&key, msg.raw.as_slice()));
|
let mi_long_adj = compute_message_integrity_adjusted(msg, &key).map(hex::encode);
|
||||||
let mi_short = hex::encode(&crate::stun::compute_message_integrity(short_key, msg.raw.as_slice()));
|
let mi_long_len = compute_mi_len_preserved(msg, &key).map(hex::encode);
|
||||||
warn!("auth reject: bad credentials username={} realm={} peer={} a1_md5={} mi_attr={:?} mi_long(fullmsg)={} mi_short(fullmsg)={}",
|
let mi_short_adj = compute_message_integrity_adjusted(msg, short_key).map(hex::encode);
|
||||||
username, realm, peer, hex::encode(&key), mi_attr, mi_long, mi_short);
|
let mi_short_len = compute_mi_len_preserved(msg, short_key).map(hex::encode);
|
||||||
|
warn!(
|
||||||
|
"auth reject: bad credentials username={} realm={} peer={} a1_md5={} mi_attr={:?} mi_long_adj={:?} mi_long_len={:?} mi_short_adj={:?} mi_short_len={:?}",
|
||||||
|
username,
|
||||||
|
realm,
|
||||||
|
peer,
|
||||||
|
hex::encode(&key),
|
||||||
|
mi_attr,
|
||||||
|
mi_long_adj,
|
||||||
|
mi_long_len,
|
||||||
|
mi_short_adj,
|
||||||
|
mi_short_len
|
||||||
|
);
|
||||||
AuthStatus::Reject {
|
AuthStatus::Reject {
|
||||||
code: 401,
|
code: 401,
|
||||||
reason: "Bad Credentials",
|
reason: "Bad Credentials",
|
||||||
|
|||||||
45
src/stun.rs
45
src/stun.rs
@ -386,6 +386,51 @@ pub fn validate_message_integrity(msg: &StunMessage, key: &[u8]) -> bool {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Compute the expected MESSAGE-INTEGRITY value following the RFC-adjusted length rule.
|
||||||
|
pub fn compute_message_integrity_adjusted(msg: &StunMessage, key: &[u8]) -> Option<Vec<u8>> {
|
||||||
|
let mi = find_message_integrity(msg)?;
|
||||||
|
if mi.value.len() != HMAC_SHA1_LEN {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let mi_end = mi.offset + 4 + HMAC_SHA1_LEN;
|
||||||
|
if mi_end > msg.raw.len() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut signed = msg.raw[..mi_end].to_vec();
|
||||||
|
let len = (mi_end - 20) as u16;
|
||||||
|
let len_bytes = len.to_be_bytes();
|
||||||
|
signed[2] = len_bytes[0];
|
||||||
|
signed[3] = len_bytes[1];
|
||||||
|
|
||||||
|
let value_start = mi.offset + 4;
|
||||||
|
for b in &mut signed[value_start..value_start + HMAC_SHA1_LEN] {
|
||||||
|
*b = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(crate::stun::compute_message_integrity(key, &signed))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compute MESSAGE-INTEGRITY keeping the original header length (interop len-preserved mode).
|
||||||
|
pub fn compute_message_integrity_len_preserved(msg: &StunMessage, key: &[u8]) -> Option<Vec<u8>> {
|
||||||
|
let mi = find_message_integrity(msg)?;
|
||||||
|
if mi.value.len() != HMAC_SHA1_LEN {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let mi_end = mi.offset + 4 + HMAC_SHA1_LEN;
|
||||||
|
if mi_end > msg.raw.len() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut signed = msg.raw[..mi_end].to_vec();
|
||||||
|
let value_start = mi.offset + 4;
|
||||||
|
for b in &mut signed[value_start..value_start + HMAC_SHA1_LEN] {
|
||||||
|
*b = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(crate::stun::compute_message_integrity(key, &signed))
|
||||||
|
}
|
||||||
|
|
||||||
/// Fallback validator: compute MESSAGE-INTEGRITY without adjusting the STUN header length.
|
/// Fallback validator: compute MESSAGE-INTEGRITY without adjusting the STUN header length.
|
||||||
/// Some clients incorrectly leave the header length unchanged when appending FINGERPRINT;
|
/// Some clients incorrectly leave the header length unchanged when appending FINGERPRINT;
|
||||||
/// this matches that behaviour for interop.
|
/// this matches that behaviour for interop.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user