start impl. access permissions
This commit is contained in:
@ -19,7 +19,7 @@ use url::form_urlencoded;
|
||||
|
||||
use proxmox::http_err;
|
||||
use proxmox::api::{ApiHandler, ApiMethod, HttpError};
|
||||
use proxmox::api::{RpcEnvironment, RpcEnvironmentType};
|
||||
use proxmox::api::{RpcEnvironment, RpcEnvironmentType, check_api_permission};
|
||||
use proxmox::api::schema::{ObjectSchema, parse_simple_value, verify_json_object, parse_parameter_strings};
|
||||
|
||||
use super::environment::RestEnvironment;
|
||||
@ -28,6 +28,7 @@ use super::ApiConfig;
|
||||
|
||||
use crate::auth_helpers::*;
|
||||
use crate::tools;
|
||||
use crate::config::cached_user_info::CachedUserInfo;
|
||||
|
||||
extern "C" { fn tzset(); }
|
||||
|
||||
@ -468,7 +469,12 @@ fn extract_auth_data(headers: &http::HeaderMap) -> (Option<String>, Option<Strin
|
||||
(ticket, token)
|
||||
}
|
||||
|
||||
fn check_auth(method: &hyper::Method, ticket: &Option<String>, token: &Option<String>) -> Result<String, Error> {
|
||||
fn check_auth(
|
||||
method: &hyper::Method,
|
||||
ticket: &Option<String>,
|
||||
token: &Option<String>,
|
||||
user_info: &CachedUserInfo,
|
||||
) -> Result<String, Error> {
|
||||
|
||||
let ticket_lifetime = tools::ticket::TICKET_LIFETIME;
|
||||
|
||||
@ -481,6 +487,10 @@ fn check_auth(method: &hyper::Method, ticket: &Option<String>, token: &Option<St
|
||||
None => bail!("missing ticket"),
|
||||
};
|
||||
|
||||
if !user_info.is_active_user(&username) {
|
||||
bail!("user account disabled or expired.");
|
||||
}
|
||||
|
||||
if method != hyper::Method::GET {
|
||||
if let Some(token) = token {
|
||||
println!("CSRF prevention token: {:?}", token);
|
||||
@ -508,6 +518,8 @@ pub async fn handle_request(api: Arc<ApiConfig>, req: Request<Body>) -> Result<R
|
||||
let env_type = api.env_type();
|
||||
let mut rpcenv = RestEnvironment::new(env_type);
|
||||
|
||||
let user_info = CachedUserInfo::new()?;
|
||||
|
||||
let delay_unauth_time = std::time::Instant::now() + std::time::Duration::from_millis(3000);
|
||||
|
||||
if comp_len >= 1 && components[0] == "api2" {
|
||||
@ -531,16 +543,11 @@ pub async fn handle_request(api: Arc<ApiConfig>, req: Request<Body>) -> Result<R
|
||||
// explicitly allow those calls without auth
|
||||
} else {
|
||||
let (ticket, token) = extract_auth_data(&parts.headers);
|
||||
match check_auth(&method, &ticket, &token) {
|
||||
Ok(username) => {
|
||||
|
||||
// fixme: check permissions
|
||||
|
||||
rpcenv.set_user(Some(username));
|
||||
}
|
||||
match check_auth(&method, &ticket, &token, &user_info) {
|
||||
Ok(username) => rpcenv.set_user(Some(username)),
|
||||
Err(err) => {
|
||||
// always delay unauthorized calls by 3 seconds (from start of request)
|
||||
let err = http_err!(UNAUTHORIZED, format!("permission check failed - {}", err));
|
||||
let err = http_err!(UNAUTHORIZED, format!("authentication failed - {}", err));
|
||||
tokio::time::delay_until(Instant::from_std(delay_unauth_time)).await;
|
||||
return Ok((formatter.format_error)(err));
|
||||
}
|
||||
@ -553,6 +560,13 @@ pub async fn handle_request(api: Arc<ApiConfig>, req: Request<Body>) -> Result<R
|
||||
return Ok((formatter.format_error)(err));
|
||||
}
|
||||
Some(api_method) => {
|
||||
let user = rpcenv.get_user();
|
||||
if !check_api_permission(api_method.access.permission, user.as_deref(), &uri_param, &user_info) {
|
||||
let err = http_err!(FORBIDDEN, format!("permission check failed"));
|
||||
tokio::time::delay_until(Instant::from_std(delay_unauth_time)).await;
|
||||
return Ok((formatter.format_error)(err));
|
||||
}
|
||||
|
||||
let result = if api_method.protected && env_type == RpcEnvironmentType::PUBLIC {
|
||||
proxy_protected_request(api_method, parts, body).await
|
||||
} else {
|
||||
@ -577,7 +591,7 @@ pub async fn handle_request(api: Arc<ApiConfig>, req: Request<Body>) -> Result<R
|
||||
if comp_len == 0 {
|
||||
let (ticket, token) = extract_auth_data(&parts.headers);
|
||||
if ticket != None {
|
||||
match check_auth(&method, &ticket, &token) {
|
||||
match check_auth(&method, &ticket, &token, &user_info) {
|
||||
Ok(username) => {
|
||||
let new_token = assemble_csrf_prevention_token(csrf_secret(), &username);
|
||||
return Ok(get_index(Some(username), Some(new_token)));
|
||||
|
Reference in New Issue
Block a user