2019-01-30 14:14:20 +00:00
|
|
|
use failure::*;
|
|
|
|
|
2019-11-21 12:10:49 +00:00
|
|
|
use serde_json::{json, Value};
|
|
|
|
|
|
|
|
use proxmox::{sortable, identity};
|
|
|
|
|
2019-01-30 14:14:20 +00:00
|
|
|
use crate::tools;
|
2019-02-17 09:16:33 +00:00
|
|
|
use crate::api_schema::*;
|
2019-02-17 08:59:20 +00:00
|
|
|
use crate::api_schema::router::*;
|
2019-01-30 14:14:20 +00:00
|
|
|
use crate::tools::ticket::*;
|
|
|
|
use crate::auth_helpers::*;
|
|
|
|
|
|
|
|
|
|
|
|
fn authenticate_user(username: &str, password: &str) -> Result<(), Error> {
|
|
|
|
|
2019-03-05 11:53:59 +00:00
|
|
|
let ticket_lifetime = tools::ticket::TICKET_LIFETIME;
|
|
|
|
|
|
|
|
if password.starts_with("PBS:") {
|
|
|
|
if let Ok((_age, Some(ticket_username))) = tools::ticket::verify_rsa_ticket(public_auth_key(), "PBS", password, None, -300, ticket_lifetime) {
|
|
|
|
if ticket_username == username {
|
|
|
|
return Ok(());
|
|
|
|
} else {
|
|
|
|
bail!("ticket login failed - wrong username");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-01 08:30:50 +00:00
|
|
|
if username == "root@pam" {
|
2019-02-15 09:32:14 +00:00
|
|
|
let mut auth = pam::Authenticator::with_password("proxmox-backup-auth").unwrap();
|
|
|
|
auth.get_handler().set_credentials("root", password);
|
2019-02-01 08:30:50 +00:00
|
|
|
auth.authenticate()?;
|
2019-01-30 14:14:20 +00:00
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
|
|
|
|
bail!("inavlid credentials");
|
|
|
|
}
|
|
|
|
|
|
|
|
fn create_ticket(
|
|
|
|
param: Value,
|
|
|
|
_info: &ApiMethod,
|
2019-06-07 11:10:56 +00:00
|
|
|
_rpcenv: &mut dyn RpcEnvironment,
|
2019-01-30 14:14:20 +00:00
|
|
|
) -> Result<Value, Error> {
|
|
|
|
|
|
|
|
let username = tools::required_string_param(¶m, "username")?;
|
|
|
|
let password = tools::required_string_param(¶m, "password")?;
|
|
|
|
|
|
|
|
match authenticate_user(username, password) {
|
|
|
|
Ok(_) => {
|
|
|
|
|
2019-01-31 11:22:00 +00:00
|
|
|
let ticket = assemble_rsa_ticket( private_auth_key(), "PBS", Some(username), None)?;
|
2019-01-30 14:14:20 +00:00
|
|
|
|
|
|
|
let token = assemble_csrf_prevention_token(csrf_secret(), username);
|
|
|
|
|
|
|
|
log::info!("successful auth for user '{}'", username);
|
|
|
|
|
2019-10-26 09:36:01 +00:00
|
|
|
Ok(json!({
|
2019-01-30 14:14:20 +00:00
|
|
|
"username": username,
|
|
|
|
"ticket": ticket,
|
|
|
|
"CSRFPreventionToken": token,
|
2019-10-26 09:36:01 +00:00
|
|
|
}))
|
2019-01-30 14:14:20 +00:00
|
|
|
}
|
|
|
|
Err(err) => {
|
|
|
|
let client_ip = "unknown"; // $rpcenv->get_client_ip() || '';
|
|
|
|
log::error!("authentication failure; rhost={} user={} msg={}", client_ip, username, err.to_string());
|
2019-10-26 09:36:01 +00:00
|
|
|
Err(http_err!(UNAUTHORIZED, "permission check failed.".into()))
|
2019-01-30 14:14:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-21 12:10:49 +00:00
|
|
|
#[sortable]
|
2019-11-21 08:36:41 +00:00
|
|
|
const SUBDIRS: SubdirMap = &[
|
|
|
|
(
|
|
|
|
"ticket", &Router::new()
|
|
|
|
.post(
|
|
|
|
&ApiMethod::new(
|
|
|
|
&ApiHandler::Sync(&create_ticket),
|
|
|
|
&ObjectSchema::new(
|
|
|
|
"Create or verify authentication ticket.",
|
2019-11-21 12:10:49 +00:00
|
|
|
&sorted!([
|
2019-11-21 08:36:41 +00:00
|
|
|
(
|
2019-01-30 14:14:20 +00:00
|
|
|
"username",
|
2019-11-21 08:36:41 +00:00
|
|
|
false,
|
|
|
|
&StringSchema::new("User name.")
|
2019-01-30 14:14:20 +00:00
|
|
|
.max_length(64)
|
2019-11-21 08:36:41 +00:00
|
|
|
.schema()
|
|
|
|
),
|
|
|
|
(
|
2019-01-30 14:14:20 +00:00
|
|
|
"password",
|
2019-11-21 08:36:41 +00:00
|
|
|
false,
|
|
|
|
&StringSchema::new("The secret password. This can also be a valid ticket.")
|
|
|
|
.schema()
|
|
|
|
),
|
2019-11-21 12:10:49 +00:00
|
|
|
]),
|
2019-11-21 08:36:41 +00:00
|
|
|
)
|
|
|
|
).returns(
|
|
|
|
&ObjectSchema::new(
|
|
|
|
"Returns authentication ticket with additional infos.",
|
2019-11-21 12:10:49 +00:00
|
|
|
&sorted!([
|
2019-11-21 08:36:41 +00:00
|
|
|
(
|
|
|
|
"username",
|
|
|
|
false,
|
|
|
|
&StringSchema::new("User name.").schema()
|
|
|
|
),
|
|
|
|
(
|
|
|
|
"ticket",
|
|
|
|
false,
|
|
|
|
&StringSchema::new("Auth ticket.").schema()
|
|
|
|
),
|
|
|
|
(
|
|
|
|
"CSRFPreventionToken",
|
|
|
|
false,
|
|
|
|
&StringSchema::new("Cross Site Request Forgery Prevention Token.")
|
|
|
|
.schema()
|
|
|
|
),
|
2019-11-21 12:10:49 +00:00
|
|
|
]),
|
2019-11-21 08:36:41 +00:00
|
|
|
).schema()
|
|
|
|
).protected(true)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
];
|
|
|
|
|
|
|
|
pub const ROUTER: Router = Router::new()
|
|
|
|
.get(&list_subdirs_api_method!(SUBDIRS))
|
|
|
|
.subdirs(SUBDIRS);
|