@ -76,6 +76,7 @@ impl AccessControl {
path : & str ,
path : & str ,
method : & Method ,
method : & Method ,
authorization : Option < & HeaderValue > ,
authorization : Option < & HeaderValue > ,
auth_method : AuthMethod ,
) -> GuardType {
) -> GuardType {
if self . rules . is_empty ( ) {
if self . rules . is_empty ( ) {
return GuardType ::ReadWrite ;
return GuardType ::ReadWrite ;
@ -86,7 +87,10 @@ impl AccessControl {
controls . push ( control ) ;
controls . push ( control ) ;
if let Some ( authorization ) = authorization {
if let Some ( authorization ) = authorization {
let Account { user , pass } = & control . readwrite ;
let Account { user , pass } = & control . readwrite ;
if valid_digest ( authorization , method . as_str ( ) , user , pass ) . is_some ( ) {
if auth_method
. validate ( authorization , method . as_str ( ) , user , pass )
. is_some ( )
{
return GuardType ::ReadWrite ;
return GuardType ::ReadWrite ;
}
}
}
}
@ -99,7 +103,10 @@ impl AccessControl {
}
}
if let Some ( authorization ) = authorization {
if let Some ( authorization ) = authorization {
if let Some ( Account { user , pass } ) = & control . readonly {
if let Some ( Account { user , pass } ) = & control . readonly {
if valid_digest ( authorization , method . as_str ( ) , user , pass ) . is_some ( ) {
if auth_method
. validate ( authorization , method . as_str ( ) , user , pass )
. is_some ( )
{
return GuardType ::ReadOnly ;
return GuardType ::ReadOnly ;
}
}
}
}
@ -167,7 +174,19 @@ impl Account {
}
}
}
}
pub fn generate_www_auth ( stale : bool ) -> String {
#[ derive(Debug, Clone) ]
pub enum AuthMethod {
Basic ,
Digest ,
}
impl AuthMethod {
pub fn www_auth ( & self , stale : bool ) -> String {
match self {
AuthMethod ::Basic = > {
format! ( "Basic realm=\"{}\"" , REALM )
}
AuthMethod ::Digest = > {
let str_stale = if stale { "stale=true," } else { "" } ;
let str_stale = if stale { "stale=true," } else { "" } ;
format! (
format! (
"Digest realm=\"{}\",nonce=\"{}\",{}qop=\"auth\"" ,
"Digest realm=\"{}\",nonce=\"{}\",{}qop=\"auth\"" ,
@ -176,13 +195,38 @@ pub fn generate_www_auth(stale: bool) -> String {
str_stale
str_stale
)
)
}
}
}
pub fn valid_digest (
}
pub fn validate (
& self ,
authorization : & HeaderValue ,
authorization : & HeaderValue ,
method : & str ,
method : & str ,
auth_user : & str ,
auth_user : & str ,
auth_pass : & str ,
auth_pass : & str ,
) -> Option < ( ) > {
) -> Option < ( ) > {
match self {
AuthMethod ::Basic = > {
let value : Vec < u8 > =
base64 ::decode ( strip_prefix ( authorization . as_bytes ( ) , b" Basic " ) . unwrap ( ) )
. unwrap ( ) ;
let parts : Vec < & str > = std ::str ::from_utf8 ( & value ) . unwrap ( ) . split ( ':' ) . collect ( ) ;
if parts [ 0 ] ! = auth_user {
return None ;
}
let mut h = Context ::new ( ) ;
h . consume ( format! ( "{}:{}:{}" , parts [ 0 ] , REALM , parts [ 1 ] ) . as_bytes ( ) ) ;
let http_pass = format! ( "{:x}" , h . compute ( ) ) ;
if http_pass = = auth_pass {
return Some ( ( ) ) ;
}
None
}
AuthMethod ::Digest = > {
let digest_value = strip_prefix ( authorization . as_bytes ( ) , b" Digest " ) ? ;
let digest_value = strip_prefix ( authorization . as_bytes ( ) , b" Digest " ) ? ;
let user_vals = to_headermap ( digest_value ) . ok ( ) ? ;
let user_vals = to_headermap ( digest_value ) . ok ( ) ? ;
if let ( Some ( username ) , Some ( nonce ) , Some ( user_response ) ) = (
if let ( Some ( username ) , Some ( nonce ) , Some ( user_response ) ) = (
@ -249,6 +293,9 @@ pub fn valid_digest(
}
}
None
None
}
}
}
}
}
/// Check if a nonce is still valid.
/// Check if a nonce is still valid.
/// Return an error if it was never valid
/// Return an error if it was never valid