You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

117 lines
3.6 KiB

use rocket::Route;
use rocket::serde::json::Json;
use serde_json::Value;
use crate::{
CONFIG,
api::{EmptyResult, JsonResult},
auth::Headers,
db::{
DbConn,
models::{Membership, MembershipType, UserId},
},
};
pub fn routes() -> Vec<Route> {
routes![post_set_key_connector_key, post_convert_to_key_connector, get_confirmation_details,]
}
#[derive(Debug, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct KeyPairData {
encrypted_private_key: String,
public_key: String,
}
#[derive(Debug, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SetKeyConnectorKeyData {
key: String,
keys: KeyPairData,
kdf: i32,
kdf_iterations: i32,
kdf_memory: Option<i32>,
kdf_parallelism: Option<i32>,
#[allow(dead_code)]
org_identifier: String,
}
async fn can_use_key_connector(user_uuid: &UserId, conn: &DbConn) -> EmptyResult {
if Membership::find_by_user(user_uuid, conn).await.iter().any(|m| m.atype >= MembershipType::Admin) {
err!("Owners and admins cannot use Key Connector and must keep a master password");
}
Ok(())
}
// Called by the client to finish provisioning a new SSO user whose master key
// was just stored on the key connector.
#[post("/accounts/set-key-connector-key", data = "<data>")]
async fn post_set_key_connector_key(data: Json<SetKeyConnectorKeyData>, headers: Headers, conn: DbConn) -> EmptyResult {
if !CONFIG.key_connector_enabled() {
err!("Key Connector is not enabled on this server");
}
let data = data.into_inner();
let mut user = headers.user;
if user.private_key.is_some() {
err!("Account already initialized, cannot set Key Connector key");
}
can_use_key_connector(&user.uuid, &conn).await?;
user.client_kdf_type = data.kdf;
user.client_kdf_iter = data.kdf_iterations;
user.client_kdf_memory = data.kdf_memory;
user.client_kdf_parallelism = data.kdf_parallelism;
user.akey = data.key;
user.private_key = Some(data.keys.encrypted_private_key);
user.public_key = Some(data.keys.public_key);
// Key connector users don't have a master password
user.password_hash = Vec::new();
user.uses_key_connector = true;
user.save(&conn).await
}
// Migrates an existing password user to the key connector. The client has already
// uploaded the current master key to the connector at this point.
#[post("/accounts/convert-to-key-connector")]
async fn post_convert_to_key_connector(headers: Headers, conn: DbConn) -> EmptyResult {
if !CONFIG.key_connector_enabled() {
err!("Key Connector is not enabled on this server");
}
let mut user = headers.user;
if user.private_key.is_none() {
err!("Account is not initialized, cannot convert to Key Connector");
}
can_use_key_connector(&user.uuid, &conn).await?;
user.password_hash = Vec::new();
user.password_hint = None;
user.uses_key_connector = true;
user.save(&conn).await
}
#[get("/accounts/key-connector/confirmation-details/<_org_identifier>")]
fn get_confirmation_details(_org_identifier: &str, _headers: Headers) -> JsonResult {
if !CONFIG.key_connector_enabled() {
err!("Key Connector is not enabled on this server");
}
// SSO (and therefore the key connector) is global, so there is no real org to look up
Ok(Json(serde_json::json!({
"OrganizationName": CONFIG.key_connector_org_name(),
"Object": "keyConnectorUserDecryptionOptionConfirmationDetails"
})))
}
pub fn key_connector_user_decryption_option() -> Value {
serde_json::json!({ "KeyConnectorUrl": CONFIG.key_connector_url() })
}