start impl. access permissions
This commit is contained in:
parent
423e656163
commit
4b40148caa
@ -2,7 +2,7 @@ use failure::*;
|
|||||||
|
|
||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
|
|
||||||
use proxmox::api::{api, RpcEnvironment};
|
use proxmox::api::{api, RpcEnvironment, Permission};
|
||||||
use proxmox::api::router::{Router, SubdirMap};
|
use proxmox::api::router::{Router, SubdirMap};
|
||||||
use proxmox::{sortable, identity};
|
use proxmox::{sortable, identity};
|
||||||
use proxmox::{http_err, list_subdirs_api_method};
|
use proxmox::{http_err, list_subdirs_api_method};
|
||||||
@ -11,6 +11,7 @@ use crate::tools;
|
|||||||
use crate::tools::ticket::*;
|
use crate::tools::ticket::*;
|
||||||
use crate::auth_helpers::*;
|
use crate::auth_helpers::*;
|
||||||
use crate::api2::types::*;
|
use crate::api2::types::*;
|
||||||
|
use crate::config::cached_user_info::CachedUserInfo;
|
||||||
|
|
||||||
pub mod user;
|
pub mod user;
|
||||||
pub mod domain;
|
pub mod domain;
|
||||||
@ -18,6 +19,12 @@ pub mod acl;
|
|||||||
|
|
||||||
fn authenticate_user(username: &str, password: &str) -> Result<(), Error> {
|
fn authenticate_user(username: &str, password: &str) -> Result<(), Error> {
|
||||||
|
|
||||||
|
let user_info = CachedUserInfo::new()?;
|
||||||
|
|
||||||
|
if !user_info.is_active_user(&username) {
|
||||||
|
bail!("user account disabled or expired.");
|
||||||
|
}
|
||||||
|
|
||||||
let ticket_lifetime = tools::ticket::TICKET_LIFETIME;
|
let ticket_lifetime = tools::ticket::TICKET_LIFETIME;
|
||||||
|
|
||||||
if password.starts_with("PBS:") {
|
if password.starts_with("PBS:") {
|
||||||
@ -61,6 +68,9 @@ fn authenticate_user(username: &str, password: &str) -> Result<(), Error> {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
protected: true,
|
protected: true,
|
||||||
|
access: {
|
||||||
|
permission: &Permission::World,
|
||||||
|
},
|
||||||
)]
|
)]
|
||||||
/// Create or verify authentication ticket.
|
/// Create or verify authentication ticket.
|
||||||
///
|
///
|
||||||
@ -100,6 +110,11 @@ fn create_ticket(username: String, password: String) -> Result<Value, Error> {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
access: {
|
||||||
|
description: "Anybody is allowed to change there own password. The Superuser may change any password.",
|
||||||
|
permission: &Permission::Anybody,
|
||||||
|
},
|
||||||
|
|
||||||
)]
|
)]
|
||||||
/// Change user password
|
/// Change user password
|
||||||
///
|
///
|
||||||
|
@ -2,7 +2,7 @@ use failure::*;
|
|||||||
|
|
||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
|
|
||||||
use proxmox::api::api;
|
use proxmox::api::{api, Permission};
|
||||||
use proxmox::api::router::Router;
|
use proxmox::api::router::Router;
|
||||||
|
|
||||||
use crate::api2::types::*;
|
use crate::api2::types::*;
|
||||||
@ -29,12 +29,13 @@ use crate::api2::types::*;
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
access: {
|
||||||
|
description: "Anyone can access this, because we need that list for the login box (before the user is authenticated).",
|
||||||
|
permission: &Permission::World,
|
||||||
}
|
}
|
||||||
)]
|
)]
|
||||||
/// Authentication domain/realm index.
|
/// Authentication domain/realm index.
|
||||||
///
|
|
||||||
/// Anyone can access this, because we need that list for the login
|
|
||||||
/// box (before the user is authenticated).
|
|
||||||
fn list_domains() -> Result<Value, Error> {
|
fn list_domains() -> Result<Value, Error> {
|
||||||
let mut list = Vec::new();
|
let mut list = Vec::new();
|
||||||
list.push(json!({ "realm": "pam", "comment": "Linux PAM standard authentication", "default": true }));
|
list.push(json!({ "realm": "pam", "comment": "Linux PAM standard authentication", "default": true }));
|
||||||
|
@ -6,11 +6,12 @@ use openssl::sha;
|
|||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
|
|
||||||
use proxmox::api::{api, ApiMethod, Router, RpcEnvironment};
|
use proxmox::api::{api, ApiMethod, Router, RpcEnvironment, Permission};
|
||||||
use proxmox::tools::fs::{file_get_contents, replace_file, CreateOptions};
|
use proxmox::tools::fs::{file_get_contents, replace_file, CreateOptions};
|
||||||
use proxmox::{IPRE, IPV4RE, IPV6RE, IPV4OCTET, IPV6H16, IPV6LS32};
|
use proxmox::{IPRE, IPV4RE, IPV6RE, IPV4OCTET, IPV6H16, IPV6LS32};
|
||||||
|
|
||||||
use crate::api2::types::*;
|
use crate::api2::types::*;
|
||||||
|
use crate::config::acl::{PRIV_SYS_AUDIT, PRIV_SYS_MODIFY};
|
||||||
|
|
||||||
static RESOLV_CONF_FN: &str = "/etc/resolv.conf";
|
static RESOLV_CONF_FN: &str = "/etc/resolv.conf";
|
||||||
|
|
||||||
@ -77,6 +78,9 @@ pub fn read_etc_resolv_conf() -> Result<Value, Error> {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
access: {
|
||||||
|
permission: &Permission::Privilege(&[], PRIV_SYS_MODIFY, false),
|
||||||
|
}
|
||||||
)]
|
)]
|
||||||
/// Update DNS settings
|
/// Update DNS settings
|
||||||
fn update_dns(
|
fn update_dns(
|
||||||
@ -158,6 +162,9 @@ fn update_dns(
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
access: {
|
||||||
|
permission: &Permission::Privilege(&[], PRIV_SYS_AUDIT, false),
|
||||||
|
}
|
||||||
)]
|
)]
|
||||||
/// Read DNS settings.
|
/// Read DNS settings.
|
||||||
fn get_dns(
|
fn get_dns(
|
||||||
|
@ -1,28 +1,37 @@
|
|||||||
use failure::*;
|
use failure::*;
|
||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
|
|
||||||
use proxmox::api::{ApiHandler, ApiMethod, Router, RpcEnvironment};
|
use proxmox::api::{api, Router, Permission};
|
||||||
use proxmox::api::schema::ObjectSchema;
|
|
||||||
|
|
||||||
use crate::api2::types::*;
|
use crate::api2::types::*;
|
||||||
|
use crate::config::acl::{PRIV_SYS_AUDIT};
|
||||||
|
|
||||||
|
#[api(
|
||||||
|
input: {
|
||||||
|
properties: {
|
||||||
|
node: {
|
||||||
|
schema: NODE_SCHEMA,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
returns: {
|
||||||
|
description: "The network configuration from /etc/network/interfaces.",
|
||||||
|
properties: {
|
||||||
|
// fixme
|
||||||
|
},
|
||||||
|
},
|
||||||
|
access: {
|
||||||
|
permission: &Permission::Privilege(&[], PRIV_SYS_AUDIT, false),
|
||||||
|
},
|
||||||
|
)]
|
||||||
|
/// Read network configuration.
|
||||||
fn get_network_config(
|
fn get_network_config(
|
||||||
_param: Value,
|
_param: Value,
|
||||||
_info: &ApiMethod,
|
|
||||||
_rpcenv: &mut dyn RpcEnvironment,
|
|
||||||
) -> Result<Value, Error> {
|
) -> Result<Value, Error> {
|
||||||
|
|
||||||
Ok(json!({}))
|
Ok(json!({}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const ROUTER: Router = Router::new()
|
pub const ROUTER: Router = Router::new()
|
||||||
.get(
|
.get(&API_METHOD_GET_NETWORK_CONFIG);
|
||||||
&ApiMethod::new(
|
|
||||||
&ApiHandler::Sync(&get_network_config),
|
|
||||||
&ObjectSchema::new(
|
|
||||||
"Read network configuration.",
|
|
||||||
&[ ("node", false, &NODE_SCHEMA) ],
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
|
@ -4,9 +4,7 @@ use chrono::prelude::*;
|
|||||||
use failure::*;
|
use failure::*;
|
||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
|
|
||||||
use proxmox::{sortable, identity};
|
use proxmox::api::{api, Router, Permission};
|
||||||
use proxmox::api::{ApiHandler, ApiMethod, Router, RpcEnvironment};
|
|
||||||
use proxmox::api::schema::*;
|
|
||||||
use proxmox::tools::fs::{file_read_firstline, replace_file, CreateOptions};
|
use proxmox::tools::fs::{file_read_firstline, replace_file, CreateOptions};
|
||||||
|
|
||||||
use crate::api2::types::*;
|
use crate::api2::types::*;
|
||||||
@ -41,11 +39,38 @@ fn read_etc_localtime() -> Result<String, Error> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_time(
|
#[api(
|
||||||
_param: Value,
|
input: {
|
||||||
_info: &ApiMethod,
|
properties: {
|
||||||
_rpcenv: &mut dyn RpcEnvironment,
|
node: {
|
||||||
) -> Result<Value, Error> {
|
schema: NODE_SCHEMA,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
returns: {
|
||||||
|
description: "Returns server time and timezone.",
|
||||||
|
properties: {
|
||||||
|
timezone: {
|
||||||
|
schema: TIME_ZONE_SCHEMA,
|
||||||
|
},
|
||||||
|
time: {
|
||||||
|
type: i64,
|
||||||
|
description: "Seconds since 1970-01-01 00:00:00 UTC.",
|
||||||
|
minimum: 1_297_163_644,
|
||||||
|
},
|
||||||
|
localtime: {
|
||||||
|
type: i64,
|
||||||
|
description: "Seconds since 1970-01-01 00:00:00 UTC. (local time)",
|
||||||
|
minimum: 1_297_163_644,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
access: {
|
||||||
|
permission: &Permission::Anybody,
|
||||||
|
},
|
||||||
|
)]
|
||||||
|
/// Read server time and time zone settings.
|
||||||
|
fn get_time(_param: Value) -> Result<Value, Error> {
|
||||||
let datetime = Local::now();
|
let datetime = Local::now();
|
||||||
let offset = datetime.offset();
|
let offset = datetime.offset();
|
||||||
let time = datetime.timestamp();
|
let time = datetime.timestamp();
|
||||||
@ -58,13 +83,25 @@ fn get_time(
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[api(
|
||||||
|
protected: true,
|
||||||
|
reload_timezone: true,
|
||||||
|
input: {
|
||||||
|
properties: {
|
||||||
|
node: {
|
||||||
|
schema: NODE_SCHEMA,
|
||||||
|
},
|
||||||
|
timezone: {
|
||||||
|
schema: TIME_ZONE_SCHEMA,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)]
|
||||||
|
/// Set time zone
|
||||||
fn set_timezone(
|
fn set_timezone(
|
||||||
param: Value,
|
timezone: String,
|
||||||
_info: &ApiMethod,
|
_param: Value,
|
||||||
_rpcenv: &mut dyn RpcEnvironment,
|
|
||||||
) -> Result<Value, Error> {
|
) -> Result<Value, Error> {
|
||||||
let timezone = crate::tools::required_string_param(¶m, "timezone")?;
|
|
||||||
|
|
||||||
let path = std::path::PathBuf::from(format!("/usr/share/zoneinfo/{}", timezone));
|
let path = std::path::PathBuf::from(format!("/usr/share/zoneinfo/{}", timezone));
|
||||||
|
|
||||||
if !path.exists() {
|
if !path.exists() {
|
||||||
@ -81,45 +118,6 @@ fn set_timezone(
|
|||||||
Ok(Value::Null)
|
Ok(Value::Null)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[sortable]
|
|
||||||
pub const ROUTER: Router = Router::new()
|
pub const ROUTER: Router = Router::new()
|
||||||
.get(
|
.get(&API_METHOD_GET_TIME)
|
||||||
&ApiMethod::new(
|
.put(&API_METHOD_SET_TIMEZONE);
|
||||||
&ApiHandler::Sync(&get_time),
|
|
||||||
&ObjectSchema::new(
|
|
||||||
"Read server time and time zone settings.",
|
|
||||||
&sorted!([ ("node", false, &NODE_SCHEMA) ]),
|
|
||||||
)
|
|
||||||
).returns(
|
|
||||||
&ObjectSchema::new(
|
|
||||||
"Returns server time and timezone.",
|
|
||||||
&sorted!([
|
|
||||||
("timezone", false, &StringSchema::new("Time zone").schema()),
|
|
||||||
("time", false, &IntegerSchema::new("Seconds since 1970-01-01 00:00:00 UTC.")
|
|
||||||
.minimum(1_297_163_644)
|
|
||||||
.schema()
|
|
||||||
),
|
|
||||||
("localtime", false, &IntegerSchema::new("Seconds since 1970-01-01 00:00:00 UTC. (local time)")
|
|
||||||
.minimum(1_297_163_644)
|
|
||||||
.schema()
|
|
||||||
),
|
|
||||||
]),
|
|
||||||
).schema()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.put(
|
|
||||||
&ApiMethod::new(
|
|
||||||
&ApiHandler::Sync(&set_timezone),
|
|
||||||
&ObjectSchema::new(
|
|
||||||
"Set time zone.",
|
|
||||||
&sorted!([
|
|
||||||
("node", false, &NODE_SCHEMA),
|
|
||||||
("timezone", false, &StringSchema::new(
|
|
||||||
"Time zone. The file '/usr/share/zoneinfo/zone.tab' contains the list of valid names.")
|
|
||||||
.schema()
|
|
||||||
),
|
|
||||||
]),
|
|
||||||
)
|
|
||||||
).protected(true).reload_timezone(true)
|
|
||||||
);
|
|
||||||
|
|
||||||
|
@ -164,6 +164,13 @@ pub const THIRD_DNS_SERVER_SCHEMA: Schema =
|
|||||||
.format(&IP_FORMAT)
|
.format(&IP_FORMAT)
|
||||||
.schema();
|
.schema();
|
||||||
|
|
||||||
|
pub const TIME_ZONE_SCHEMA: Schema = StringSchema::new(
|
||||||
|
"Time zone. The file '/usr/share/zoneinfo/zone.tab' contains the list of valid names.")
|
||||||
|
.format(&SINGLE_LINE_COMMENT_FORMAT)
|
||||||
|
.min_length(2)
|
||||||
|
.max_length(64)
|
||||||
|
.schema();
|
||||||
|
|
||||||
pub const BACKUP_ARCHIVE_NAME_SCHEMA: Schema =
|
pub const BACKUP_ARCHIVE_NAME_SCHEMA: Schema =
|
||||||
StringSchema::new("Backup archive name.")
|
StringSchema::new("Backup archive name.")
|
||||||
.format(&PROXMOX_SAFE_ID_FORMAT)
|
.format(&PROXMOX_SAFE_ID_FORMAT)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use failure::*;
|
use failure::*;
|
||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
|
|
||||||
use proxmox::api::{ApiHandler, ApiMethod, Router, RpcEnvironment};
|
use proxmox::api::{ApiHandler, ApiMethod, Router, RpcEnvironment, Permission};
|
||||||
use proxmox::api::schema::ObjectSchema;
|
use proxmox::api::schema::ObjectSchema;
|
||||||
|
|
||||||
pub const PROXMOX_PKG_VERSION: &str =
|
pub const PROXMOX_PKG_VERSION: &str =
|
||||||
@ -31,6 +31,6 @@ pub const ROUTER: Router = Router::new()
|
|||||||
&ApiMethod::new(
|
&ApiMethod::new(
|
||||||
&ApiHandler::Sync(&get_version),
|
&ApiHandler::Sync(&get_version),
|
||||||
&ObjectSchema::new("Proxmox Backup Server API version.", &[])
|
&ObjectSchema::new("Proxmox Backup Server API version.", &[])
|
||||||
)
|
).access(None, &Permission::Anybody)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
21
src/auth.rs
21
src/auth.rs
@ -130,6 +130,7 @@ pub fn parse_userid(userid: &str) -> Result<(String, String), Error> {
|
|||||||
Ok((data[1].to_owned(), data[0].to_owned()))
|
Ok((data[1].to_owned(), data[0].to_owned()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Lookup the autenticator for the specified realm
|
||||||
pub fn lookup_authenticator(realm: &str) -> Result<Box<dyn ProxmoxAuthenticator>, Error> {
|
pub fn lookup_authenticator(realm: &str) -> Result<Box<dyn ProxmoxAuthenticator>, Error> {
|
||||||
match realm {
|
match realm {
|
||||||
"pam" => Ok(Box::new(PAM())),
|
"pam" => Ok(Box::new(PAM())),
|
||||||
@ -138,28 +139,10 @@ pub fn lookup_authenticator(realm: &str) -> Result<Box<dyn ProxmoxAuthenticator>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Authenticate users
|
||||||
pub fn authenticate_user(userid: &str, password: &str) -> Result<(), Error> {
|
pub fn authenticate_user(userid: &str, password: &str) -> Result<(), Error> {
|
||||||
let (username, realm) = parse_userid(userid)?;
|
let (username, realm) = parse_userid(userid)?;
|
||||||
|
|
||||||
let (user_config, _digest) = crate::config::user::config()?;
|
|
||||||
let user: Result<crate::config::user::User, Error> = user_config.lookup("user", userid);
|
|
||||||
match user {
|
|
||||||
Ok(user) => {
|
|
||||||
if let Some(false) = user.enable {
|
|
||||||
bail!("account disabled");
|
|
||||||
}
|
|
||||||
if let Some(expire) = user.expire {
|
|
||||||
if expire > 0 {
|
|
||||||
let now = unsafe { libc::time(std::ptr::null_mut()) };
|
|
||||||
if expire <= now {
|
|
||||||
bail!("account expired");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Err(_) => bail!("no such user"),
|
|
||||||
}
|
|
||||||
|
|
||||||
lookup_authenticator(&realm)?
|
lookup_authenticator(&realm)?
|
||||||
.authenticate_user(&username, password)
|
.authenticate_user(&username, password)
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ use url::form_urlencoded;
|
|||||||
|
|
||||||
use proxmox::http_err;
|
use proxmox::http_err;
|
||||||
use proxmox::api::{ApiHandler, ApiMethod, HttpError};
|
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 proxmox::api::schema::{ObjectSchema, parse_simple_value, verify_json_object, parse_parameter_strings};
|
||||||
|
|
||||||
use super::environment::RestEnvironment;
|
use super::environment::RestEnvironment;
|
||||||
@ -28,6 +28,7 @@ use super::ApiConfig;
|
|||||||
|
|
||||||
use crate::auth_helpers::*;
|
use crate::auth_helpers::*;
|
||||||
use crate::tools;
|
use crate::tools;
|
||||||
|
use crate::config::cached_user_info::CachedUserInfo;
|
||||||
|
|
||||||
extern "C" { fn tzset(); }
|
extern "C" { fn tzset(); }
|
||||||
|
|
||||||
@ -468,7 +469,12 @@ fn extract_auth_data(headers: &http::HeaderMap) -> (Option<String>, Option<Strin
|
|||||||
(ticket, token)
|
(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;
|
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"),
|
None => bail!("missing ticket"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if !user_info.is_active_user(&username) {
|
||||||
|
bail!("user account disabled or expired.");
|
||||||
|
}
|
||||||
|
|
||||||
if method != hyper::Method::GET {
|
if method != hyper::Method::GET {
|
||||||
if let Some(token) = token {
|
if let Some(token) = token {
|
||||||
println!("CSRF prevention 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 env_type = api.env_type();
|
||||||
let mut rpcenv = RestEnvironment::new(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);
|
let delay_unauth_time = std::time::Instant::now() + std::time::Duration::from_millis(3000);
|
||||||
|
|
||||||
if comp_len >= 1 && components[0] == "api2" {
|
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
|
// explicitly allow those calls without auth
|
||||||
} else {
|
} else {
|
||||||
let (ticket, token) = extract_auth_data(&parts.headers);
|
let (ticket, token) = extract_auth_data(&parts.headers);
|
||||||
match check_auth(&method, &ticket, &token) {
|
match check_auth(&method, &ticket, &token, &user_info) {
|
||||||
Ok(username) => {
|
Ok(username) => rpcenv.set_user(Some(username)),
|
||||||
|
|
||||||
// fixme: check permissions
|
|
||||||
|
|
||||||
rpcenv.set_user(Some(username));
|
|
||||||
}
|
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
// always delay unauthorized calls by 3 seconds (from start of request)
|
// 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;
|
tokio::time::delay_until(Instant::from_std(delay_unauth_time)).await;
|
||||||
return Ok((formatter.format_error)(err));
|
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));
|
return Ok((formatter.format_error)(err));
|
||||||
}
|
}
|
||||||
Some(api_method) => {
|
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 {
|
let result = if api_method.protected && env_type == RpcEnvironmentType::PUBLIC {
|
||||||
proxy_protected_request(api_method, parts, body).await
|
proxy_protected_request(api_method, parts, body).await
|
||||||
} else {
|
} else {
|
||||||
@ -577,7 +591,7 @@ pub async fn handle_request(api: Arc<ApiConfig>, req: Request<Body>) -> Result<R
|
|||||||
if comp_len == 0 {
|
if comp_len == 0 {
|
||||||
let (ticket, token) = extract_auth_data(&parts.headers);
|
let (ticket, token) = extract_auth_data(&parts.headers);
|
||||||
if ticket != None {
|
if ticket != None {
|
||||||
match check_auth(&method, &ticket, &token) {
|
match check_auth(&method, &ticket, &token, &user_info) {
|
||||||
Ok(username) => {
|
Ok(username) => {
|
||||||
let new_token = assemble_csrf_prevention_token(csrf_secret(), &username);
|
let new_token = assemble_csrf_prevention_token(csrf_secret(), &username);
|
||||||
return Ok(get_index(Some(username), Some(new_token)));
|
return Ok(get_index(Some(username), Some(new_token)));
|
||||||
|
Loading…
Reference in New Issue
Block a user