diff options
Diffstat (limited to 'src/api/core/accounts.rs')
-rw-r--r-- | src/api/core/accounts.rs | 176 |
1 files changed, 89 insertions, 87 deletions
diff --git a/src/api/core/accounts.rs b/src/api/core/accounts.rs index f9822629..71609b37 100644 --- a/src/api/core/accounts.rs +++ b/src/api/core/accounts.rs @@ -1,5 +1,5 @@ use crate::db::DbPool; -use chrono::{SecondsFormat, Utc}; +use chrono::Utc; use rocket::serde::json::Json; use serde_json::Value; @@ -13,7 +13,7 @@ use crate::{ crypto, db::{models::*, DbConn}, mail, - util::NumberOrString, + util::{format_date, NumberOrString}, CONFIG, }; @@ -901,14 +901,12 @@ pub async fn _prelogin(data: Json<PreloginData>, mut conn: DbConn) -> Json<Value None => (User::CLIENT_KDF_TYPE_DEFAULT, User::CLIENT_KDF_ITER_DEFAULT, None, None), }; - let result = json!({ + Json(json!({ "kdf": kdf_type, "kdfIterations": kdf_iter, "kdfMemory": kdf_mem, "kdfParallelism": kdf_para, - }); - - Json(result) + })) } // https://github.com/bitwarden/server/blob/master/src/Api/Models/Request/Accounts/SecretVerificationRequestModel.cs @@ -1084,14 +1082,15 @@ struct AuthRequestRequest { device_identifier: String, email: String, public_key: String, - #[serde(alias = "type")] - _type: i32, + // Not used for now + // #[serde(alias = "type")] + // _type: i32, } #[post("/auth-requests", data = "<data>")] async fn post_auth_request( data: Json<AuthRequestRequest>, - headers: ClientHeaders, + client_headers: ClientHeaders, mut conn: DbConn, nt: Notify<'_>, ) -> JsonResult { @@ -1099,16 +1098,20 @@ async fn post_auth_request( let user = match User::find_by_mail(&data.email, &mut conn).await { Some(user) => user, - None => { - err!("AuthRequest doesn't exist") - } + None => err!("AuthRequest doesn't exist", "User not found"), }; + // Validate device uuid and type + match Device::find_by_uuid_and_user(&data.device_identifier, &user.uuid, &mut conn).await { + Some(device) if device.atype == client_headers.device_type => {} + _ => err!("AuthRequest doesn't exist", "Device verification failed"), + } + let mut auth_request = AuthRequest::new( user.uuid.clone(), data.device_identifier.clone(), - headers.device_type, - headers.ip.ip.to_string(), + client_headers.device_type, + client_headers.ip.ip.to_string(), data.access_code, data.public_key, ); @@ -1123,7 +1126,7 @@ async fn post_auth_request( "requestIpAddress": auth_request.request_ip, "key": null, "masterPasswordHash": null, - "creationDate": auth_request.creation_date.and_utc().to_rfc3339_opts(SecondsFormat::Micros, true), + "creationDate": format_date(&auth_request.creation_date), "responseDate": null, "requestApproved": false, "origin": CONFIG.domain_origin(), @@ -1132,33 +1135,31 @@ async fn post_auth_request( } #[get("/auth-requests/<uuid>")] -async fn get_auth_request(uuid: &str, mut conn: DbConn) -> JsonResult { +async fn get_auth_request(uuid: &str, headers: Headers, mut conn: DbConn) -> JsonResult { + if headers.user.uuid != uuid { + err!("AuthRequest doesn't exist", "User uuid's do not match") + } + let auth_request = match AuthRequest::find_by_uuid(uuid, &mut conn).await { Some(auth_request) => auth_request, - None => { - err!("AuthRequest doesn't exist") - } + None => err!("AuthRequest doesn't exist", "Record not found"), }; - let response_date_utc = auth_request - .response_date - .map(|response_date| response_date.and_utc().to_rfc3339_opts(SecondsFormat::Micros, true)); - - Ok(Json(json!( - { - "id": uuid, - "publicKey": auth_request.public_key, - "requestDeviceType": DeviceType::from_i32(auth_request.device_type).to_string(), - "requestIpAddress": auth_request.request_ip, - "key": auth_request.enc_key, - "masterPasswordHash": auth_request.master_password_hash, - "creationDate": auth_request.creation_date.and_utc().to_rfc3339_opts(SecondsFormat::Micros, true), - "responseDate": response_date_utc, - "requestApproved": auth_request.approved, - "origin": CONFIG.domain_origin(), - "object":"auth-request" - } - ))) + let response_date_utc = auth_request.response_date.map(|response_date| format_date(&response_date)); + + Ok(Json(json!({ + "id": uuid, + "publicKey": auth_request.public_key, + "requestDeviceType": DeviceType::from_i32(auth_request.device_type).to_string(), + "requestIpAddress": auth_request.request_ip, + "key": auth_request.enc_key, + "masterPasswordHash": auth_request.master_password_hash, + "creationDate": format_date(&auth_request.creation_date), + "responseDate": response_date_utc, + "requestApproved": auth_request.approved, + "origin": CONFIG.domain_origin(), + "object":"auth-request" + }))) } #[derive(Debug, Deserialize)] @@ -1174,6 +1175,7 @@ struct AuthResponseRequest { async fn put_auth_request( uuid: &str, data: Json<AuthResponseRequest>, + headers: Headers, mut conn: DbConn, ant: AnonymousNotify<'_>, nt: Notify<'_>, @@ -1181,11 +1183,13 @@ async fn put_auth_request( let data = data.into_inner(); let mut auth_request: AuthRequest = match AuthRequest::find_by_uuid(uuid, &mut conn).await { Some(auth_request) => auth_request, - None => { - err!("AuthRequest doesn't exist") - } + None => err!("AuthRequest doesn't exist", "Record not found"), }; + if headers.user.uuid != auth_request.user_uuid { + err!("AuthRequest doesn't exist", "User uuid's do not match") + } + auth_request.approved = Some(data.request_approved); auth_request.enc_key = Some(data.key); auth_request.master_password_hash = data.master_password_hash; @@ -1197,59 +1201,57 @@ async fn put_auth_request( nt.send_auth_response(&auth_request.user_uuid, &auth_request.uuid, data.device_identifier, &mut conn).await; } - let response_date_utc = auth_request - .response_date - .map(|response_date| response_date.and_utc().to_rfc3339_opts(SecondsFormat::Micros, true)); - - Ok(Json(json!( - { - "id": uuid, - "publicKey": auth_request.public_key, - "requestDeviceType": DeviceType::from_i32(auth_request.device_type).to_string(), - "requestIpAddress": auth_request.request_ip, - "key": auth_request.enc_key, - "masterPasswordHash": auth_request.master_password_hash, - "creationDate": auth_request.creation_date.and_utc().to_rfc3339_opts(SecondsFormat::Micros, true), - "responseDate": response_date_utc, - "requestApproved": auth_request.approved, - "origin": CONFIG.domain_origin(), - "object":"auth-request" - } - ))) + let response_date_utc = auth_request.response_date.map(|response_date| format_date(&response_date)); + + Ok(Json(json!({ + "id": uuid, + "publicKey": auth_request.public_key, + "requestDeviceType": DeviceType::from_i32(auth_request.device_type).to_string(), + "requestIpAddress": auth_request.request_ip, + "key": auth_request.enc_key, + "masterPasswordHash": auth_request.master_password_hash, + "creationDate": format_date(&auth_request.creation_date), + "responseDate": response_date_utc, + "requestApproved": auth_request.approved, + "origin": CONFIG.domain_origin(), + "object":"auth-request" + }))) } #[get("/auth-requests/<uuid>/response?<code>")] -async fn get_auth_request_response(uuid: &str, code: &str, mut conn: DbConn) -> JsonResult { +async fn get_auth_request_response( + uuid: &str, + code: &str, + client_headers: ClientHeaders, + mut conn: DbConn, +) -> JsonResult { let auth_request = match AuthRequest::find_by_uuid(uuid, &mut conn).await { Some(auth_request) => auth_request, - None => { - err!("AuthRequest doesn't exist") - } + None => err!("AuthRequest doesn't exist", "User not found"), }; - if !auth_request.check_access_code(code) { - err!("Access code invalid doesn't exist") + if auth_request.device_type != client_headers.device_type + && auth_request.request_ip != client_headers.ip.ip.to_string() + && !auth_request.check_access_code(code) + { + err!("AuthRequest doesn't exist", "Invalid device, IP or code") } - let response_date_utc = auth_request - .response_date - .map(|response_date| response_date.and_utc().to_rfc3339_opts(SecondsFormat::Micros, true)); - - Ok(Json(json!( - { - "id": uuid, - "publicKey": auth_request.public_key, - "requestDeviceType": DeviceType::from_i32(auth_request.device_type).to_string(), - "requestIpAddress": auth_request.request_ip, - "key": auth_request.enc_key, - "masterPasswordHash": auth_request.master_password_hash, - "creationDate": auth_request.creation_date.and_utc().to_rfc3339_opts(SecondsFormat::Micros, true), - "responseDate": response_date_utc, - "requestApproved": auth_request.approved, - "origin": CONFIG.domain_origin(), - "object":"auth-request" - } - ))) + let response_date_utc = auth_request.response_date.map(|response_date| format_date(&response_date)); + + Ok(Json(json!({ + "id": uuid, + "publicKey": auth_request.public_key, + "requestDeviceType": DeviceType::from_i32(auth_request.device_type).to_string(), + "requestIpAddress": auth_request.request_ip, + "key": auth_request.enc_key, + "masterPasswordHash": auth_request.master_password_hash, + "creationDate": format_date(&auth_request.creation_date), + "responseDate": response_date_utc, + "requestApproved": auth_request.approved, + "origin": CONFIG.domain_origin(), + "object":"auth-request" + }))) } #[get("/auth-requests")] @@ -1261,7 +1263,7 @@ async fn get_auth_requests(headers: Headers, mut conn: DbConn) -> JsonResult { .iter() .filter(|request| request.approved.is_none()) .map(|request| { - let response_date_utc = request.response_date.map(|response_date| response_date.and_utc().to_rfc3339_opts(SecondsFormat::Micros, true)); + let response_date_utc = request.response_date.map(|response_date| format_date(&response_date)); json!({ "id": request.uuid, @@ -1270,7 +1272,7 @@ async fn get_auth_requests(headers: Headers, mut conn: DbConn) -> JsonResult { "requestIpAddress": request.request_ip, "key": request.enc_key, "masterPasswordHash": request.master_password_hash, - "creationDate": request.creation_date.and_utc().to_rfc3339_opts(SecondsFormat::Micros, true), + "creationDate": format_date(&request.creation_date), "responseDate": response_date_utc, "requestApproved": request.approved, "origin": CONFIG.domain_origin(), |