]> git.proxmox.com Git - proxmox-backup.git/commitdiff
server/rest.rs: verify auth cookie
authorDietmar Maurer <dietmar@proxmox.com>
Thu, 31 Jan 2019 11:22:00 +0000 (12:22 +0100)
committerDietmar Maurer <dietmar@proxmox.com>
Thu, 31 Jan 2019 11:22:00 +0000 (12:22 +0100)
src/api2/access.rs
src/server/rest.rs
src/tools.rs

index 390e54cf38be18dd7fd9a023cb6ea461aec9c20b..3ffc4dcd9001f7c311b40b42b98851b2ac5e9093 100644 (file)
@@ -29,7 +29,7 @@ fn create_ticket(
     match authenticate_user(username, password) {
         Ok(_) => {
 
-            let ticket = assemble_rsa_ticket( private_auth_key(), "PBS", None, None)?;
+            let ticket = assemble_rsa_ticket( private_auth_key(), "PBS", Some(username), None)?;
 
             let token = assemble_csrf_prevention_token(csrf_secret(), username);
 
index d9263778f1347dc5cae35ef985877e01771c8e77..787bf20fe62a5753b6259f6df8c8b72ac9ebd4f8 100644 (file)
@@ -2,6 +2,7 @@ use crate::tools;
 use crate::api::schema::*;
 use crate::api::router::*;
 use crate::api::config::*;
+use crate::auth_helpers::*;
 use super::environment::RestEnvironment;
 use super::formatter::*;
 
@@ -421,6 +422,20 @@ pub fn handle_request(api: Arc<ApiConfig>, req: Request<Body>) -> BoxFut {
     let env_type = api.env_type();
     let mut rpcenv = RestEnvironment::new(env_type);
 
+    let delay_unauth_time = std::time::Instant::now() + std::time::Duration::from_millis(3000);
+
+    if let Some(raw_cookie) = parts.headers.get("COOKIE") {
+        if let Ok(cookie) = raw_cookie.to_str() {
+            if let Some(ticket) = tools::extract_auth_cookie(cookie, "PBSAuthCookie") {
+                if let Ok((_, Some(username))) = tools::ticket::verify_rsa_ticket(
+                    public_auth_key(), "PBS", &ticket, None, -300, 3600*2) {
+                    rpcenv.set_user(Some(username));
+                }
+            }
+        }
+    }
+
+
     if comp_len >= 1 && components[0] == "api2" {
         println!("GOT API REQUEST");
         if comp_len >= 2 {
@@ -435,8 +450,21 @@ pub fn handle_request(api: Arc<ApiConfig>, req: Request<Body>) -> BoxFut {
 
             let mut uri_param = HashMap::new();
 
-            // fixme: handle auth
-            rpcenv.set_user(Some(String::from("root@pam")));
+            if comp_len == 4 && components[2] == "access" && components[3] == "ticket" {
+                // explicitly allow those calls without auth
+            } else {
+                if let Some(_username) = rpcenv.get_user() {
+                    // fixme: check permissions
+                } else {
+                    // always delay unauthorized calls by 3 seconds (from start of request)
+                    let resp = (formatter.format_error)(http_err!(UNAUTHORIZED, "permission check failed.".into()));
+                    let delayed_response = tokio::timer::Delay::new(delay_unauth_time)
+                        .map_err(|err| http_err!(INTERNAL_SERVER_ERROR, format!("tokio timer delay error: {}", err)))
+                        .and_then(|_| Ok(resp));
+
+                    return Box::new(delayed_response);
+                }
+            }
 
             match api.find_method(&components[2..], method, &mut uri_param) {
                 MethodDefinition::None => {}
index 8b522cd3feb00d518f77b901b0f202cea6adbba3..6932fc56f0c39ef6bb903e3dd529fa11566f30c4 100644 (file)
@@ -416,3 +416,27 @@ pub fn assert_if_modified(digest1: &str, digest2: &str) -> Result<(), Error> {
     }
     Ok(())
 }
+
+/// Extract authentication cookie from cookie header.
+/// We assume cookie_name is already url encoded.
+pub fn extract_auth_cookie(cookie: &str, cookie_name: &str) -> Option<String> {
+
+    for pair in cookie.split(';') {
+
+        let (name, value) = match pair.find('=') {
+            Some(i) => (pair[..i].trim(), pair[(i + 1)..].trim()),
+            None => return None, // Cookie format error
+        };
+
+        if name == cookie_name {
+            use url::percent_encoding::percent_decode;
+            if let Ok(value) = percent_decode(value.as_bytes()).decode_utf8() {
+                return Some(value.into());
+            } else {
+                return None; // Cookie format error
+            }
+        }
+    }
+
+    None
+}