]>
Commit | Line | Data |
---|---|---|
34f956bc DM |
1 | use failure::*; |
2 | ||
3 | use crate::tools; | |
ef2f2efb | 4 | use crate::api_schema::*; |
dc9a007b | 5 | use crate::api_schema::router::*; |
34f956bc DM |
6 | use crate::tools::ticket::*; |
7 | use crate::auth_helpers::*; | |
8 | ||
a154a8e8 DM |
9 | use hyper::StatusCode; |
10 | ||
34f956bc DM |
11 | use serde_json::{json, Value}; |
12 | ||
13 | fn authenticate_user(username: &str, password: &str) -> Result<(), Error> { | |
14 | ||
f8f94534 DM |
15 | let ticket_lifetime = tools::ticket::TICKET_LIFETIME; |
16 | ||
17 | if password.starts_with("PBS:") { | |
18 | if let Ok((_age, Some(ticket_username))) = tools::ticket::verify_rsa_ticket(public_auth_key(), "PBS", password, None, -300, ticket_lifetime) { | |
19 | if ticket_username == username { | |
20 | return Ok(()); | |
21 | } else { | |
22 | bail!("ticket login failed - wrong username"); | |
23 | } | |
24 | } | |
25 | } | |
26 | ||
c82bc1a1 | 27 | if username == "root@pam" { |
1d77b6cf WB |
28 | let mut auth = pam::Authenticator::with_password("proxmox-backup-auth").unwrap(); |
29 | auth.get_handler().set_credentials("root", password); | |
c82bc1a1 | 30 | auth.authenticate()?; |
34f956bc DM |
31 | return Ok(()); |
32 | } | |
33 | ||
34 | bail!("inavlid credentials"); | |
35 | } | |
36 | ||
37 | fn create_ticket( | |
38 | param: Value, | |
39 | _info: &ApiMethod, | |
dd5495d6 | 40 | _rpcenv: &mut dyn RpcEnvironment, |
34f956bc DM |
41 | ) -> Result<Value, Error> { |
42 | ||
43 | let username = tools::required_string_param(¶m, "username")?; | |
44 | let password = tools::required_string_param(¶m, "password")?; | |
45 | ||
46 | match authenticate_user(username, password) { | |
47 | Ok(_) => { | |
48 | ||
b9903d63 | 49 | let ticket = assemble_rsa_ticket( private_auth_key(), "PBS", Some(username), None)?; |
34f956bc DM |
50 | |
51 | let token = assemble_csrf_prevention_token(csrf_secret(), username); | |
52 | ||
53 | log::info!("successful auth for user '{}'", username); | |
54 | ||
55 | return Ok(json!({ | |
56 | "username": username, | |
57 | "ticket": ticket, | |
58 | "CSRFPreventionToken": token, | |
59 | })); | |
60 | } | |
61 | Err(err) => { | |
62 | let client_ip = "unknown"; // $rpcenv->get_client_ip() || ''; | |
63 | log::error!("authentication failure; rhost={} user={} msg={}", client_ip, username, err.to_string()); | |
a154a8e8 | 64 | return Err(http_err!(UNAUTHORIZED, "permission check failed.".into())); |
34f956bc DM |
65 | } |
66 | } | |
67 | } | |
68 | ||
69 | pub fn router() -> Router { | |
70 | ||
71 | let route = Router::new() | |
34f956bc DM |
72 | .subdir( |
73 | "ticket", | |
74 | Router::new() | |
75 | .post( | |
76 | ApiMethod::new( | |
77 | create_ticket, | |
78 | ObjectSchema::new("Create or verify authentication ticket.") | |
79 | .required( | |
80 | "username", | |
81 | StringSchema::new("User name.") | |
82 | .max_length(64) | |
83 | ) | |
84 | .required( | |
85 | "password", | |
86 | StringSchema::new("The secret password. This can also be a valid ticket.") | |
87 | ) | |
88 | ).returns( | |
89 | ObjectSchema::new("Returns authentication ticket with additional infos.") | |
90 | .required("username", StringSchema::new("User name.")) | |
91 | .required("ticket", StringSchema::new("Auth ticket.")) | |
92 | .required("CSRFPreventionToken", StringSchema::new("Cross Site Request Forgery Prevention Token.")) | |
93 | ).protected(true) | |
94 | ) | |
13f1cc17 DM |
95 | ) |
96 | .list_subdirs(); | |
34f956bc DM |
97 | |
98 | route | |
99 | } |