@ -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,87 +174,127 @@ impl Account {
}
}
}
}
pub fn generate_www_auth ( stale : bool ) -> String {
#[ derive(Debug, Clone) ]
let str_stale = if stale { "stale=true," } else { "" } ;
pub enum AuthMethod {
format! (
Basic ,
"Digest realm=\"{}\",nonce=\"{}\",{}qop=\"auth\"" ,
Digest ,
REALM ,
create_nonce ( ) ,
str_stale
)
}
}
pub fn valid_digest (
impl AuthMethod {
authorization : & HeaderValue ,
pub fn www_auth ( & self , stale : bool ) -> String {
method : & str ,
match self {
auth_user : & str ,
AuthMethod ::Basic = > {
auth_pass : & str ,
format! ( "Basic realm=\"{}\"" , REALM )
) -> Option < ( ) > {
}
let digest_value = strip_prefix ( authorization . as_bytes ( ) , b" Digest " ) ? ;
AuthMethod ::Digest = > {
let user_vals = to_headermap ( digest_value ) . ok ( ) ? ;
let str_stale = if stale { "stale=true," } else { "" } ;
if let ( Some ( username ) , Some ( nonce ) , Some ( user_response ) ) = (
format! (
user_vals
"Digest realm=\"{}\",nonce=\"{}\",{}qop=\"auth\"" ,
. get ( b" username " . as_ref ( ) )
REALM ,
. and_then ( | b | std ::str ::from_utf8 ( * b ) . ok ( ) ) ,
create_nonce ( ) ,
user_vals . get ( b" nonce " . as_ref ( ) ) ,
str_stale
user_vals . get ( b" response " . as_ref ( ) ) ,
)
) {
}
match validate_nonce ( nonce ) {
Ok ( true ) = > { }
_ = > return None ,
}
if auth_user ! = username {
return None ;
}
let mut ha = Context ::new ( ) ;
ha . consume ( method ) ;
ha . consume ( b" : " ) ;
if let Some ( uri ) = user_vals . get ( b" uri " . as_ref ( ) ) {
ha . consume ( uri ) ;
}
}
let ha = format! ( "{:x}" , ha . compute ( ) ) ;
}
let mut correct_response = None ;
pub fn validate (
if let Some ( qop ) = user_vals . get ( b" qop " . as_ref ( ) ) {
& self ,
if qop = = & b" auth " . as_ref ( ) | | qop = = & b" auth-int " . as_ref ( ) {
authorization : & HeaderValue ,
correct_response = Some ( {
method : & str ,
let mut c = Context ::new ( ) ;
auth_user : & str ,
c . consume ( & auth_pass ) ;
auth_pass : & str ,
c . consume ( b" : " ) ;
) -> Option < ( ) > {
c . consume ( nonce ) ;
match self {
c . consume ( b" : " ) ;
AuthMethod ::Basic = > {
if let Some ( nc ) = user_vals . get ( b" nc " . as_ref ( ) ) {
let value : Vec < u8 > =
c . consume ( nc ) ;
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 user_vals = to_headermap ( digest_value ) . ok ( ) ? ;
if let ( Some ( username ) , Some ( nonce ) , Some ( user_response ) ) = (
user_vals
. get ( b" username " . as_ref ( ) )
. and_then ( | b | std ::str ::from_utf8 ( * b ) . ok ( ) ) ,
user_vals . get ( b" nonce " . as_ref ( ) ) ,
user_vals . get ( b" response " . as_ref ( ) ) ,
) {
match validate_nonce ( nonce ) {
Ok ( true ) = > { }
_ = > return None ,
}
}
c . consume ( b" : " ) ;
if auth_user ! = username {
if let Some ( cnonce ) = user_vals . get ( b" cnonce " . as_ref ( ) ) {
return None ;
c . consume ( cnonce ) ;
}
}
c . consume ( b" : " ) ;
let mut ha = Context ::new ( ) ;
c . consume ( qop ) ;
ha . consume ( method ) ;
c . consume ( b" : " ) ;
ha . consume ( b" : " ) ;
c . consume ( & * ha ) ;
if let Some ( uri ) = user_vals . get ( b" uri " . as_ref ( ) ) {
format! ( "{:x}" , c . compute ( ) )
ha . consume ( uri ) ;
} ) ;
}
}
let ha = format! ( "{:x}" , ha . compute ( ) ) ;
}
let mut correct_response = None ;
let correct_response = match correct_response {
if let Some ( qop ) = user_vals . get ( b" qop " . as_ref ( ) ) {
Some ( r ) = > r ,
if qop = = & b" auth " . as_ref ( ) | | qop = = & b" auth-int " . as_ref ( ) {
None = > {
correct_response = Some ( {
let mut c = Context ::new ( ) ;
let mut c = Context ::new ( ) ;
c . consume ( & auth_pass ) ;
c . consume ( & auth_pass ) ;
c . consume ( b" : " ) ;
c . consume ( b" : " ) ;
c . consume ( nonce ) ;
c . consume ( nonce ) ;
c . consume ( b" : " ) ;
c . consume ( b" : " ) ;
c . consume ( & * ha ) ;
if let Some ( nc ) = user_vals . get ( b" nc " . as_ref ( ) ) {
format! ( "{:x}" , c . compute ( ) )
c . consume ( nc ) ;
}
c . consume ( b" : " ) ;
if let Some ( cnonce ) = user_vals . get ( b" cnonce " . as_ref ( ) ) {
c . consume ( cnonce ) ;
}
c . consume ( b" : " ) ;
c . consume ( qop ) ;
c . consume ( b" : " ) ;
c . consume ( & * ha ) ;
format! ( "{:x}" , c . compute ( ) )
} ) ;
}
}
let correct_response = match correct_response {
Some ( r ) = > r ,
None = > {
let mut c = Context ::new ( ) ;
c . consume ( & auth_pass ) ;
c . consume ( b" : " ) ;
c . consume ( nonce ) ;
c . consume ( b" : " ) ;
c . consume ( & * ha ) ;
format! ( "{:x}" , c . compute ( ) )
}
} ;
if correct_response . as_bytes ( ) = = * user_response {
// grant access
return Some ( ( ) ) ;
}
}
None
}
}
} ;
if correct_response . as_bytes ( ) = = * user_response {
// grant access
return Some ( ( ) ) ;
}
}
}
}
None
}
}
/// Check if a nonce is still valid.
/// Check if a nonce is still valid.