mod tests { use super::*; #[test] fn rejects_ambiguous_headers_and_injection() { let mut h = HeaderMap::new(); h.insert( "authorization", HeaderValue::from_static("Basic dXNlcjpwYXNz"), ); assert_eq!(credentials(&h).unwrap().0, "user"); h.append( "authorization", HeaderValue::from_static("Basic dXNlcjpwYXNz"), ); assert!(credentials(&h).is_none()); assert!(Settings { realm: "bad\r\nheader".into(), ..Default::default() } .compile() .is_err()); assert!(Settings { enabled: true, ..Default::default() } .compile() .is_err()); } #[tokio::test] async fn validates_and_strips_or_forwards_only_verified_credentials() { let hash = crate::auth::hash_password_offline("sufficiently-long-password".into()) .await .unwrap(); let mut settings = Settings { enabled: true, users: vec![User { username: "alice".into(), password_hash: hash, }], ..Default::default() }; for forward in [false, true] { settings.forward_credentials = forward; let auth = settings.compile().unwrap().unwrap(); let mut h = HeaderMap::new(); let raw = HeaderValue::from_str(&format!( "Basic {}", STANDARD.encode("alice:sufficiently-long-password") )) .unwrap(); h.insert("authorization", raw.clone()); h.insert("remote-user", HeaderValue::from_static("spoof")); let verified = auth .authorize( &mut h, true, "127.0.0.1".parse().unwrap(), Arc::new(Semaphore::new(2)), &Limits::default(), ) .await .unwrap(); assert!(!h.contains_key("authorization")); auth.apply_upstream(&mut h, verified); assert_eq!(h.get("authorization"), forward.then_some(&raw)); assert!(!h.contains_key("remote-user")); } } #[test] fn bounds_ip_limiter() { let limits = Limits::default(); let ip = "127.0.0.1".parse().unwrap(); for _ in 0..10 { limits.failed(ip); } assert!(limits.blocked(ip)); assert!(!limits.blocked("127.0.0.2".parse().unwrap())); } }