accounts.rs 56 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645
  1. use std::collections::HashSet;
  2. use crate::db::DbPool;
  3. use chrono::Utc;
  4. use rocket::serde::json::Json;
  5. use serde_json::Value;
  6. use crate::{
  7. api::{
  8. core::{accept_org_invite, log_user_event, two_factor::email},
  9. master_password_policy, register_push_device, unregister_push_device, AnonymousNotify, ApiResult, EmptyResult,
  10. JsonResult, Notify, PasswordOrOtpData, UpdateType,
  11. },
  12. auth::{decode_delete, decode_invite, decode_verify_email, ClientHeaders, Headers},
  13. crypto,
  14. db::{models::*, DbConn},
  15. mail,
  16. util::{format_date, NumberOrString},
  17. CONFIG,
  18. };
  19. use rocket::{
  20. http::Status,
  21. request::{FromRequest, Outcome, Request},
  22. };
  23. pub fn routes() -> Vec<rocket::Route> {
  24. routes![
  25. register,
  26. profile,
  27. put_profile,
  28. post_profile,
  29. put_avatar,
  30. get_public_keys,
  31. post_keys,
  32. post_password,
  33. post_set_password,
  34. post_kdf,
  35. post_rotatekey,
  36. post_sstamp,
  37. post_email_token,
  38. post_email,
  39. post_verify_email,
  40. post_verify_email_token,
  41. post_delete_recover,
  42. post_delete_recover_token,
  43. post_delete_account,
  44. delete_account,
  45. revision_date,
  46. password_hint,
  47. prelogin,
  48. verify_password,
  49. api_key,
  50. rotate_api_key,
  51. get_known_device,
  52. get_all_devices,
  53. get_device,
  54. post_device_token,
  55. put_device_token,
  56. put_clear_device_token,
  57. post_clear_device_token,
  58. post_auth_request,
  59. get_auth_request,
  60. put_auth_request,
  61. get_auth_request_response,
  62. get_auth_requests,
  63. ]
  64. }
  65. #[derive(Debug, Deserialize)]
  66. #[serde(rename_all = "camelCase")]
  67. pub struct KDFData {
  68. kdf: i32,
  69. kdf_iterations: i32,
  70. kdf_memory: Option<i32>,
  71. kdf_parallelism: Option<i32>,
  72. }
  73. #[derive(Debug, Deserialize)]
  74. #[serde(rename_all = "camelCase")]
  75. pub struct RegisterData {
  76. email: String,
  77. #[serde(flatten)]
  78. kdf: KDFData,
  79. #[serde(alias = "userSymmetricKey")]
  80. key: String,
  81. #[serde(alias = "userAsymmetricKeys")]
  82. keys: Option<KeysData>,
  83. master_password_hash: String,
  84. master_password_hint: Option<String>,
  85. name: Option<String>,
  86. #[allow(dead_code)]
  87. organization_user_id: Option<MembershipId>,
  88. // Used only from the register/finish endpoint
  89. email_verification_token: Option<String>,
  90. accept_emergency_access_id: Option<EmergencyAccessId>,
  91. accept_emergency_access_invite_token: Option<String>,
  92. #[serde(alias = "token")]
  93. org_invite_token: Option<String>,
  94. }
  95. #[derive(Debug, Deserialize)]
  96. #[serde(rename_all = "camelCase")]
  97. pub struct SetPasswordData {
  98. #[serde(flatten)]
  99. kdf: KDFData,
  100. key: String,
  101. keys: Option<KeysData>,
  102. master_password_hash: String,
  103. master_password_hint: Option<String>,
  104. org_identifier: Option<String>,
  105. }
  106. #[derive(Debug, Deserialize)]
  107. #[serde(rename_all = "camelCase")]
  108. struct KeysData {
  109. encrypted_private_key: String,
  110. public_key: String,
  111. }
  112. /// Trims whitespace from password hints, and converts blank password hints to `None`.
  113. fn clean_password_hint(password_hint: &Option<String>) -> Option<String> {
  114. match password_hint {
  115. None => None,
  116. Some(h) => match h.trim() {
  117. "" => None,
  118. ht => Some(ht.to_string()),
  119. },
  120. }
  121. }
  122. fn enforce_password_hint_setting(password_hint: &Option<String>) -> EmptyResult {
  123. if password_hint.is_some() && !CONFIG.password_hints_allowed() {
  124. err!("Password hints have been disabled by the administrator. Remove the hint and try again.");
  125. }
  126. Ok(())
  127. }
  128. async fn is_email_2fa_required(member_id: Option<MembershipId>, conn: &mut DbConn) -> bool {
  129. if !CONFIG._enable_email_2fa() {
  130. return false;
  131. }
  132. if CONFIG.email_2fa_enforce_on_verified_invite() {
  133. return true;
  134. }
  135. if let Some(member_id) = member_id {
  136. return OrgPolicy::is_enabled_for_member(&member_id, OrgPolicyType::TwoFactorAuthentication, conn).await;
  137. }
  138. false
  139. }
  140. #[post("/accounts/register", data = "<data>")]
  141. async fn register(data: Json<RegisterData>, conn: DbConn) -> JsonResult {
  142. _register(data, false, conn).await
  143. }
  144. pub async fn _register(data: Json<RegisterData>, email_verification: bool, mut conn: DbConn) -> JsonResult {
  145. let mut data: RegisterData = data.into_inner();
  146. let email = data.email.to_lowercase();
  147. let mut email_verified = false;
  148. let mut pending_emergency_access = None;
  149. // First, validate the provided verification tokens
  150. if email_verification {
  151. match (
  152. &data.email_verification_token,
  153. &data.accept_emergency_access_id,
  154. &data.accept_emergency_access_invite_token,
  155. &data.organization_user_id,
  156. &data.org_invite_token,
  157. ) {
  158. // Normal user registration, when email verification is required
  159. (Some(email_verification_token), None, None, None, None) => {
  160. let claims = crate::auth::decode_register_verify(email_verification_token)?;
  161. if claims.sub != data.email {
  162. err!("Email verification token does not match email");
  163. }
  164. // During this call we don't get the name, so extract it from the claims
  165. if claims.name.is_some() {
  166. data.name = claims.name;
  167. }
  168. email_verified = claims.verified;
  169. }
  170. // Emergency access registration
  171. (None, Some(accept_emergency_access_id), Some(accept_emergency_access_invite_token), None, None) => {
  172. if !CONFIG.emergency_access_allowed() {
  173. err!("Emergency access is not enabled.")
  174. }
  175. let claims = crate::auth::decode_emergency_access_invite(accept_emergency_access_invite_token)?;
  176. if claims.email != data.email {
  177. err!("Claim email does not match email")
  178. }
  179. if &claims.emer_id != accept_emergency_access_id {
  180. err!("Claim emer_id does not match accept_emergency_access_id")
  181. }
  182. pending_emergency_access = Some((accept_emergency_access_id, claims));
  183. email_verified = true;
  184. }
  185. // Org invite
  186. (None, None, None, Some(organization_user_id), Some(org_invite_token)) => {
  187. let claims = decode_invite(org_invite_token)?;
  188. if claims.email != data.email {
  189. err!("Claim email does not match email")
  190. }
  191. if &claims.member_id != organization_user_id {
  192. err!("Claim org_user_id does not match organization_user_id")
  193. }
  194. email_verified = true;
  195. }
  196. _ => {
  197. err!("Registration is missing required parameters")
  198. }
  199. }
  200. }
  201. // Check if the length of the username exceeds 50 characters (Same is Upstream Bitwarden)
  202. // This also prevents issues with very long usernames causing to large JWT's. See #2419
  203. if let Some(ref name) = data.name {
  204. if name.len() > 50 {
  205. err!("The field Name must be a string with a maximum length of 50.");
  206. }
  207. }
  208. // Check against the password hint setting here so if it fails, the user
  209. // can retry without losing their invitation below.
  210. let password_hint = clean_password_hint(&data.master_password_hint);
  211. enforce_password_hint_setting(&password_hint)?;
  212. let mut user = match User::find_by_mail(&email, &mut conn).await {
  213. Some(user) => {
  214. if !user.password_hash.is_empty() {
  215. err!("Registration not allowed or user already exists")
  216. }
  217. if let Some(token) = data.org_invite_token {
  218. let claims = decode_invite(&token)?;
  219. if claims.email == email {
  220. // Verify the email address when signing up via a valid invite token
  221. email_verified = true;
  222. user
  223. } else {
  224. err!("Registration email does not match invite email")
  225. }
  226. } else if Invitation::take(&email, &mut conn).await {
  227. Membership::accept_user_invitations(&user.uuid, &mut conn).await?;
  228. user
  229. } else if CONFIG.is_signup_allowed(&email)
  230. || (CONFIG.emergency_access_allowed()
  231. && EmergencyAccess::find_invited_by_grantee_email(&email, &mut conn).await.is_some())
  232. {
  233. user
  234. } else {
  235. err!("Registration not allowed or user already exists")
  236. }
  237. }
  238. None => {
  239. // Order is important here; the invitation check must come first
  240. // because the vaultwarden admin can invite anyone, regardless
  241. // of other signup restrictions.
  242. if Invitation::take(&email, &mut conn).await
  243. || CONFIG.is_signup_allowed(&email)
  244. || pending_emergency_access.is_some()
  245. {
  246. User::new(email.clone(), None)
  247. } else {
  248. err!("Registration not allowed or user already exists")
  249. }
  250. }
  251. };
  252. // Make sure we don't leave a lingering invitation.
  253. Invitation::take(&email, &mut conn).await;
  254. set_kdf_data(&mut user, data.kdf)?;
  255. user.set_password(&data.master_password_hash, Some(data.key), true, None);
  256. user.password_hint = password_hint;
  257. // Add extra fields if present
  258. if let Some(name) = data.name {
  259. user.name = name;
  260. }
  261. if let Some(keys) = data.keys {
  262. user.private_key = Some(keys.encrypted_private_key);
  263. user.public_key = Some(keys.public_key);
  264. }
  265. if email_verified {
  266. user.verified_at = Some(Utc::now().naive_utc());
  267. }
  268. if CONFIG.mail_enabled() {
  269. if CONFIG.signups_verify() && !email_verified {
  270. if let Err(e) = mail::send_welcome_must_verify(&user.email, &user.uuid).await {
  271. error!("Error sending welcome email: {e:#?}");
  272. }
  273. user.last_verifying_at = Some(user.created_at);
  274. } else if let Err(e) = mail::send_welcome(&user.email).await {
  275. error!("Error sending welcome email: {e:#?}");
  276. }
  277. if email_verified && is_email_2fa_required(data.organization_user_id, &mut conn).await {
  278. email::activate_email_2fa(&user, &mut conn).await.ok();
  279. }
  280. }
  281. user.save(&mut conn).await?;
  282. // accept any open emergency access invitations
  283. if !CONFIG.mail_enabled() && CONFIG.emergency_access_allowed() {
  284. for mut emergency_invite in EmergencyAccess::find_all_invited_by_grantee_email(&user.email, &mut conn).await {
  285. emergency_invite.accept_invite(&user.uuid, &user.email, &mut conn).await.ok();
  286. }
  287. }
  288. Ok(Json(json!({
  289. "object": "register",
  290. "captchaBypassToken": "",
  291. })))
  292. }
  293. #[post("/accounts/set-password", data = "<data>")]
  294. async fn post_set_password(data: Json<SetPasswordData>, headers: Headers, mut conn: DbConn) -> JsonResult {
  295. let data: SetPasswordData = data.into_inner();
  296. let mut user = headers.user;
  297. if user.private_key.is_some() {
  298. err!("Account already initialized, cannot set password")
  299. }
  300. // Check against the password hint setting here so if it fails,
  301. // the user can retry without losing their invitation below.
  302. let password_hint = clean_password_hint(&data.master_password_hint);
  303. enforce_password_hint_setting(&password_hint)?;
  304. set_kdf_data(&mut user, data.kdf)?;
  305. user.set_password(
  306. &data.master_password_hash,
  307. Some(data.key),
  308. false,
  309. Some(vec![String::from("revision_date")]), // We need to allow revision-date to use the old security_timestamp
  310. );
  311. user.password_hint = password_hint;
  312. if let Some(keys) = data.keys {
  313. user.private_key = Some(keys.encrypted_private_key);
  314. user.public_key = Some(keys.public_key);
  315. }
  316. if let Some(identifier) = data.org_identifier {
  317. if identifier != crate::sso::FAKE_IDENTIFIER {
  318. let org = match Organization::find_by_uuid(&identifier.into(), &mut conn).await {
  319. None => err!("Failed to retrieve the associated organization"),
  320. Some(org) => org,
  321. };
  322. let membership = match Membership::find_by_user_and_org(&user.uuid, &org.uuid, &mut conn).await {
  323. None => err!("Failed to retrieve the invitation"),
  324. Some(org) => org,
  325. };
  326. accept_org_invite(&user, membership, None, &mut conn).await?;
  327. }
  328. }
  329. if CONFIG.mail_enabled() {
  330. mail::send_welcome(&user.email.to_lowercase()).await?;
  331. } else {
  332. Membership::accept_user_invitations(&user.uuid, &mut conn).await?;
  333. }
  334. log_user_event(EventType::UserChangedPassword as i32, &user.uuid, headers.device.atype, &headers.ip.ip, &mut conn)
  335. .await;
  336. user.save(&mut conn).await?;
  337. Ok(Json(json!({
  338. "Object": "set-password",
  339. "CaptchaBypassToken": "",
  340. })))
  341. }
  342. #[get("/accounts/profile")]
  343. async fn profile(headers: Headers, mut conn: DbConn) -> Json<Value> {
  344. Json(headers.user.to_json(&mut conn).await)
  345. }
  346. #[derive(Debug, Deserialize)]
  347. #[serde(rename_all = "camelCase")]
  348. struct ProfileData {
  349. // culture: String, // Ignored, always use en-US
  350. name: String,
  351. }
  352. #[put("/accounts/profile", data = "<data>")]
  353. async fn put_profile(data: Json<ProfileData>, headers: Headers, conn: DbConn) -> JsonResult {
  354. post_profile(data, headers, conn).await
  355. }
  356. #[post("/accounts/profile", data = "<data>")]
  357. async fn post_profile(data: Json<ProfileData>, headers: Headers, mut conn: DbConn) -> JsonResult {
  358. let data: ProfileData = data.into_inner();
  359. // Check if the length of the username exceeds 50 characters (Same is Upstream Bitwarden)
  360. // This also prevents issues with very long usernames causing to large JWT's. See #2419
  361. if data.name.len() > 50 {
  362. err!("The field Name must be a string with a maximum length of 50.");
  363. }
  364. let mut user = headers.user;
  365. user.name = data.name;
  366. user.save(&mut conn).await?;
  367. Ok(Json(user.to_json(&mut conn).await))
  368. }
  369. #[derive(Deserialize)]
  370. #[serde(rename_all = "camelCase")]
  371. struct AvatarData {
  372. avatar_color: Option<String>,
  373. }
  374. #[put("/accounts/avatar", data = "<data>")]
  375. async fn put_avatar(data: Json<AvatarData>, headers: Headers, mut conn: DbConn) -> JsonResult {
  376. let data: AvatarData = data.into_inner();
  377. // It looks like it only supports the 6 hex color format.
  378. // If you try to add the short value it will not show that color.
  379. // Check and force 7 chars, including the #.
  380. if let Some(color) = &data.avatar_color {
  381. if color.len() != 7 {
  382. err!("The field AvatarColor must be a HTML/Hex color code with a length of 7 characters")
  383. }
  384. }
  385. let mut user = headers.user;
  386. user.avatar_color = data.avatar_color;
  387. user.save(&mut conn).await?;
  388. Ok(Json(user.to_json(&mut conn).await))
  389. }
  390. #[get("/users/<user_id>/public-key")]
  391. async fn get_public_keys(user_id: UserId, _headers: Headers, mut conn: DbConn) -> JsonResult {
  392. let user = match User::find_by_uuid(&user_id, &mut conn).await {
  393. Some(user) if user.public_key.is_some() => user,
  394. Some(_) => err_code!("User has no public_key", Status::NotFound.code),
  395. None => err_code!("User doesn't exist", Status::NotFound.code),
  396. };
  397. Ok(Json(json!({
  398. "userId": user.uuid,
  399. "publicKey": user.public_key,
  400. "object":"userKey"
  401. })))
  402. }
  403. #[post("/accounts/keys", data = "<data>")]
  404. async fn post_keys(data: Json<KeysData>, headers: Headers, mut conn: DbConn) -> JsonResult {
  405. let data: KeysData = data.into_inner();
  406. let mut user = headers.user;
  407. user.private_key = Some(data.encrypted_private_key);
  408. user.public_key = Some(data.public_key);
  409. user.save(&mut conn).await?;
  410. Ok(Json(json!({
  411. "privateKey": user.private_key,
  412. "publicKey": user.public_key,
  413. "object":"keys"
  414. })))
  415. }
  416. #[derive(Deserialize)]
  417. #[serde(rename_all = "camelCase")]
  418. struct ChangePassData {
  419. master_password_hash: String,
  420. new_master_password_hash: String,
  421. master_password_hint: Option<String>,
  422. key: String,
  423. }
  424. #[post("/accounts/password", data = "<data>")]
  425. async fn post_password(data: Json<ChangePassData>, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult {
  426. let data: ChangePassData = data.into_inner();
  427. let mut user = headers.user;
  428. if !user.check_valid_password(&data.master_password_hash) {
  429. err!("Invalid password")
  430. }
  431. user.password_hint = clean_password_hint(&data.master_password_hint);
  432. enforce_password_hint_setting(&user.password_hint)?;
  433. log_user_event(EventType::UserChangedPassword as i32, &user.uuid, headers.device.atype, &headers.ip.ip, &mut conn)
  434. .await;
  435. user.set_password(
  436. &data.new_master_password_hash,
  437. Some(data.key),
  438. true,
  439. Some(vec![
  440. String::from("post_rotatekey"),
  441. String::from("get_contacts"),
  442. String::from("get_public_keys"),
  443. String::from("get_api_webauthn"),
  444. ]),
  445. );
  446. let save_result = user.save(&mut conn).await;
  447. // Prevent logging out the client where the user requested this endpoint from.
  448. // If you do logout the user it will causes issues at the client side.
  449. // Adding the device uuid will prevent this.
  450. nt.send_logout(&user, Some(headers.device.uuid.clone()), &mut conn).await;
  451. save_result
  452. }
  453. #[derive(Deserialize)]
  454. #[serde(rename_all = "camelCase")]
  455. struct ChangeKdfData {
  456. #[serde(flatten)]
  457. kdf: KDFData,
  458. master_password_hash: String,
  459. new_master_password_hash: String,
  460. key: String,
  461. }
  462. fn set_kdf_data(user: &mut User, data: KDFData) -> EmptyResult {
  463. if data.kdf == UserKdfType::Pbkdf2 as i32 && data.kdf_iterations < 100_000 {
  464. err!("PBKDF2 KDF iterations must be at least 100000.")
  465. }
  466. if data.kdf == UserKdfType::Argon2id as i32 {
  467. if data.kdf_iterations < 1 {
  468. err!("Argon2 KDF iterations must be at least 1.")
  469. }
  470. if let Some(m) = data.kdf_memory {
  471. if !(15..=1024).contains(&m) {
  472. err!("Argon2 memory must be between 15 MB and 1024 MB.")
  473. }
  474. user.client_kdf_memory = data.kdf_memory;
  475. } else {
  476. err!("Argon2 memory parameter is required.")
  477. }
  478. if let Some(p) = data.kdf_parallelism {
  479. if !(1..=16).contains(&p) {
  480. err!("Argon2 parallelism must be between 1 and 16.")
  481. }
  482. user.client_kdf_parallelism = data.kdf_parallelism;
  483. } else {
  484. err!("Argon2 parallelism parameter is required.")
  485. }
  486. } else {
  487. user.client_kdf_memory = None;
  488. user.client_kdf_parallelism = None;
  489. }
  490. user.client_kdf_iter = data.kdf_iterations;
  491. user.client_kdf_type = data.kdf;
  492. Ok(())
  493. }
  494. #[post("/accounts/kdf", data = "<data>")]
  495. async fn post_kdf(data: Json<ChangeKdfData>, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult {
  496. let data: ChangeKdfData = data.into_inner();
  497. let mut user = headers.user;
  498. if !user.check_valid_password(&data.master_password_hash) {
  499. err!("Invalid password")
  500. }
  501. set_kdf_data(&mut user, data.kdf)?;
  502. user.set_password(&data.new_master_password_hash, Some(data.key), true, None);
  503. let save_result = user.save(&mut conn).await;
  504. nt.send_logout(&user, Some(headers.device.uuid.clone()), &mut conn).await;
  505. save_result
  506. }
  507. #[derive(Deserialize)]
  508. #[serde(rename_all = "camelCase")]
  509. struct UpdateFolderData {
  510. // There is a bug in 2024.3.x which adds a `null` item.
  511. // To bypass this we allow a Option here, but skip it during the updates
  512. // See: https://github.com/bitwarden/clients/issues/8453
  513. id: Option<FolderId>,
  514. name: String,
  515. }
  516. #[derive(Deserialize)]
  517. #[serde(rename_all = "camelCase")]
  518. struct UpdateEmergencyAccessData {
  519. id: EmergencyAccessId,
  520. key_encrypted: String,
  521. }
  522. #[derive(Deserialize)]
  523. #[serde(rename_all = "camelCase")]
  524. struct UpdateResetPasswordData {
  525. organization_id: OrganizationId,
  526. reset_password_key: String,
  527. }
  528. use super::ciphers::CipherData;
  529. use super::sends::{update_send_from_data, SendData};
  530. #[derive(Deserialize)]
  531. #[serde(rename_all = "camelCase")]
  532. struct KeyData {
  533. account_unlock_data: RotateAccountUnlockData,
  534. account_keys: RotateAccountKeys,
  535. account_data: RotateAccountData,
  536. old_master_key_authentication_hash: String,
  537. }
  538. #[derive(Deserialize)]
  539. #[serde(rename_all = "camelCase")]
  540. struct RotateAccountUnlockData {
  541. emergency_access_unlock_data: Vec<UpdateEmergencyAccessData>,
  542. master_password_unlock_data: MasterPasswordUnlockData,
  543. organization_account_recovery_unlock_data: Vec<UpdateResetPasswordData>,
  544. }
  545. #[derive(Deserialize)]
  546. #[serde(rename_all = "camelCase")]
  547. struct MasterPasswordUnlockData {
  548. kdf_type: i32,
  549. kdf_iterations: i32,
  550. kdf_parallelism: Option<i32>,
  551. kdf_memory: Option<i32>,
  552. email: String,
  553. master_key_authentication_hash: String,
  554. master_key_encrypted_user_key: String,
  555. }
  556. #[derive(Deserialize)]
  557. #[serde(rename_all = "camelCase")]
  558. struct RotateAccountKeys {
  559. user_key_encrypted_account_private_key: String,
  560. account_public_key: String,
  561. }
  562. #[derive(Deserialize)]
  563. #[serde(rename_all = "camelCase")]
  564. struct RotateAccountData {
  565. ciphers: Vec<CipherData>,
  566. folders: Vec<UpdateFolderData>,
  567. sends: Vec<SendData>,
  568. }
  569. fn validate_keydata(
  570. data: &KeyData,
  571. existing_ciphers: &[Cipher],
  572. existing_folders: &[Folder],
  573. existing_emergency_access: &[EmergencyAccess],
  574. existing_memberships: &[Membership],
  575. existing_sends: &[Send],
  576. user: &User,
  577. ) -> EmptyResult {
  578. if user.client_kdf_type != data.account_unlock_data.master_password_unlock_data.kdf_type
  579. || user.client_kdf_iter != data.account_unlock_data.master_password_unlock_data.kdf_iterations
  580. || user.client_kdf_memory != data.account_unlock_data.master_password_unlock_data.kdf_memory
  581. || user.client_kdf_parallelism != data.account_unlock_data.master_password_unlock_data.kdf_parallelism
  582. || user.email != data.account_unlock_data.master_password_unlock_data.email
  583. {
  584. err!("Changing the kdf variant or email is not supported during key rotation");
  585. }
  586. if user.public_key.as_ref() != Some(&data.account_keys.account_public_key) {
  587. err!("Changing the asymmetric keypair is not possible during key rotation")
  588. }
  589. // Check that we're correctly rotating all the user's ciphers
  590. let existing_cipher_ids = existing_ciphers.iter().map(|c| &c.uuid).collect::<HashSet<&CipherId>>();
  591. let provided_cipher_ids = data
  592. .account_data
  593. .ciphers
  594. .iter()
  595. .filter(|c| c.organization_id.is_none())
  596. .filter_map(|c| c.id.as_ref())
  597. .collect::<HashSet<&CipherId>>();
  598. if !provided_cipher_ids.is_superset(&existing_cipher_ids) {
  599. err!("All existing ciphers must be included in the rotation")
  600. }
  601. // Check that we're correctly rotating all the user's folders
  602. let existing_folder_ids = existing_folders.iter().map(|f| &f.uuid).collect::<HashSet<&FolderId>>();
  603. let provided_folder_ids =
  604. data.account_data.folders.iter().filter_map(|f| f.id.as_ref()).collect::<HashSet<&FolderId>>();
  605. if !provided_folder_ids.is_superset(&existing_folder_ids) {
  606. err!("All existing folders must be included in the rotation")
  607. }
  608. // Check that we're correctly rotating all the user's emergency access keys
  609. let existing_emergency_access_ids =
  610. existing_emergency_access.iter().map(|ea| &ea.uuid).collect::<HashSet<&EmergencyAccessId>>();
  611. let provided_emergency_access_ids = data
  612. .account_unlock_data
  613. .emergency_access_unlock_data
  614. .iter()
  615. .map(|ea| &ea.id)
  616. .collect::<HashSet<&EmergencyAccessId>>();
  617. if !provided_emergency_access_ids.is_superset(&existing_emergency_access_ids) {
  618. err!("All existing emergency access keys must be included in the rotation")
  619. }
  620. // Check that we're correctly rotating all the user's reset password keys
  621. let existing_reset_password_ids =
  622. existing_memberships.iter().map(|m| &m.org_uuid).collect::<HashSet<&OrganizationId>>();
  623. let provided_reset_password_ids = data
  624. .account_unlock_data
  625. .organization_account_recovery_unlock_data
  626. .iter()
  627. .map(|rp| &rp.organization_id)
  628. .collect::<HashSet<&OrganizationId>>();
  629. if !provided_reset_password_ids.is_superset(&existing_reset_password_ids) {
  630. err!("All existing reset password keys must be included in the rotation")
  631. }
  632. // Check that we're correctly rotating all the user's sends
  633. let existing_send_ids = existing_sends.iter().map(|s| &s.uuid).collect::<HashSet<&SendId>>();
  634. let provided_send_ids = data.account_data.sends.iter().filter_map(|s| s.id.as_ref()).collect::<HashSet<&SendId>>();
  635. if !provided_send_ids.is_superset(&existing_send_ids) {
  636. err!("All existing sends must be included in the rotation")
  637. }
  638. Ok(())
  639. }
  640. #[post("/accounts/key-management/rotate-user-account-keys", data = "<data>")]
  641. async fn post_rotatekey(data: Json<KeyData>, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult {
  642. // TODO: See if we can wrap everything within a SQL Transaction. If something fails it should revert everything.
  643. let data: KeyData = data.into_inner();
  644. if !headers.user.check_valid_password(&data.old_master_key_authentication_hash) {
  645. err!("Invalid password")
  646. }
  647. // Validate the import before continuing
  648. // Bitwarden does not process the import if there is one item invalid.
  649. // Since we check for the size of the encrypted note length, we need to do that here to pre-validate it.
  650. // TODO: See if we can optimize the whole cipher adding/importing and prevent duplicate code and checks.
  651. Cipher::validate_cipher_data(&data.account_data.ciphers)?;
  652. let user_id = &headers.user.uuid;
  653. // TODO: Ideally we'd do everything after this point in a single transaction.
  654. let mut existing_ciphers = Cipher::find_owned_by_user(user_id, &mut conn).await;
  655. let mut existing_folders = Folder::find_by_user(user_id, &mut conn).await;
  656. let mut existing_emergency_access = EmergencyAccess::find_all_by_grantor_uuid(user_id, &mut conn).await;
  657. let mut existing_memberships = Membership::find_by_user(user_id, &mut conn).await;
  658. // We only rotate the reset password key if it is set.
  659. existing_memberships.retain(|m| m.reset_password_key.is_some());
  660. let mut existing_sends = Send::find_by_user(user_id, &mut conn).await;
  661. validate_keydata(
  662. &data,
  663. &existing_ciphers,
  664. &existing_folders,
  665. &existing_emergency_access,
  666. &existing_memberships,
  667. &existing_sends,
  668. &headers.user,
  669. )?;
  670. // Update folder data
  671. for folder_data in data.account_data.folders {
  672. // Skip `null` folder id entries.
  673. // See: https://github.com/bitwarden/clients/issues/8453
  674. if let Some(folder_id) = folder_data.id {
  675. let Some(saved_folder) = existing_folders.iter_mut().find(|f| f.uuid == folder_id) else {
  676. err!("Folder doesn't exist")
  677. };
  678. saved_folder.name = folder_data.name;
  679. saved_folder.save(&mut conn).await?
  680. }
  681. }
  682. // Update emergency access data
  683. for emergency_access_data in data.account_unlock_data.emergency_access_unlock_data {
  684. let Some(saved_emergency_access) =
  685. existing_emergency_access.iter_mut().find(|ea| ea.uuid == emergency_access_data.id)
  686. else {
  687. err!("Emergency access doesn't exist or is not owned by the user")
  688. };
  689. saved_emergency_access.key_encrypted = Some(emergency_access_data.key_encrypted);
  690. saved_emergency_access.save(&mut conn).await?
  691. }
  692. // Update reset password data
  693. for reset_password_data in data.account_unlock_data.organization_account_recovery_unlock_data {
  694. let Some(membership) =
  695. existing_memberships.iter_mut().find(|m| m.org_uuid == reset_password_data.organization_id)
  696. else {
  697. err!("Reset password doesn't exist")
  698. };
  699. membership.reset_password_key = Some(reset_password_data.reset_password_key);
  700. membership.save(&mut conn).await?
  701. }
  702. // Update send data
  703. for send_data in data.account_data.sends {
  704. let Some(send) = existing_sends.iter_mut().find(|s| &s.uuid == send_data.id.as_ref().unwrap()) else {
  705. err!("Send doesn't exist")
  706. };
  707. update_send_from_data(send, send_data, &headers, &mut conn, &nt, UpdateType::None).await?;
  708. }
  709. // Update cipher data
  710. use super::ciphers::update_cipher_from_data;
  711. for cipher_data in data.account_data.ciphers {
  712. if cipher_data.organization_id.is_none() {
  713. let Some(saved_cipher) = existing_ciphers.iter_mut().find(|c| &c.uuid == cipher_data.id.as_ref().unwrap())
  714. else {
  715. err!("Cipher doesn't exist")
  716. };
  717. // Prevent triggering cipher updates via WebSockets by settings UpdateType::None
  718. // The user sessions are invalidated because all the ciphers were re-encrypted and thus triggering an update could cause issues.
  719. // We force the users to logout after the user has been saved to try and prevent these issues.
  720. update_cipher_from_data(saved_cipher, cipher_data, &headers, None, &mut conn, &nt, UpdateType::None).await?
  721. }
  722. }
  723. // Update user data
  724. let mut user = headers.user;
  725. user.private_key = Some(data.account_keys.user_key_encrypted_account_private_key);
  726. user.set_password(
  727. &data.account_unlock_data.master_password_unlock_data.master_key_authentication_hash,
  728. Some(data.account_unlock_data.master_password_unlock_data.master_key_encrypted_user_key),
  729. true,
  730. None,
  731. );
  732. let save_result = user.save(&mut conn).await;
  733. // Prevent logging out the client where the user requested this endpoint from.
  734. // If you do logout the user it will causes issues at the client side.
  735. // Adding the device uuid will prevent this.
  736. nt.send_logout(&user, Some(headers.device.uuid.clone()), &mut conn).await;
  737. save_result
  738. }
  739. #[post("/accounts/security-stamp", data = "<data>")]
  740. async fn post_sstamp(data: Json<PasswordOrOtpData>, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult {
  741. let data: PasswordOrOtpData = data.into_inner();
  742. let mut user = headers.user;
  743. data.validate(&user, true, &mut conn).await?;
  744. Device::delete_all_by_user(&user.uuid, &mut conn).await?;
  745. user.reset_security_stamp();
  746. let save_result = user.save(&mut conn).await;
  747. nt.send_logout(&user, None, &mut conn).await;
  748. save_result
  749. }
  750. #[derive(Deserialize)]
  751. #[serde(rename_all = "camelCase")]
  752. struct EmailTokenData {
  753. master_password_hash: String,
  754. new_email: String,
  755. }
  756. #[post("/accounts/email-token", data = "<data>")]
  757. async fn post_email_token(data: Json<EmailTokenData>, headers: Headers, mut conn: DbConn) -> EmptyResult {
  758. if !CONFIG.email_change_allowed() {
  759. err!("Email change is not allowed.");
  760. }
  761. let data: EmailTokenData = data.into_inner();
  762. let mut user = headers.user;
  763. if !user.check_valid_password(&data.master_password_hash) {
  764. err!("Invalid password")
  765. }
  766. if User::find_by_mail(&data.new_email, &mut conn).await.is_some() {
  767. if CONFIG.mail_enabled() {
  768. if let Err(e) = mail::send_change_email_existing(&data.new_email, &user.email).await {
  769. error!("Error sending change-email-existing email: {e:#?}");
  770. }
  771. }
  772. err!("Email already in use");
  773. }
  774. if !CONFIG.is_email_domain_allowed(&data.new_email) {
  775. err!("Email domain not allowed");
  776. }
  777. let token = crypto::generate_email_token(6);
  778. if CONFIG.mail_enabled() {
  779. if let Err(e) = mail::send_change_email(&data.new_email, &token).await {
  780. error!("Error sending change-email email: {e:#?}");
  781. }
  782. } else {
  783. debug!("Email change request for user ({}) to email ({}) with token ({token})", user.uuid, data.new_email);
  784. }
  785. user.email_new = Some(data.new_email);
  786. user.email_new_token = Some(token);
  787. user.save(&mut conn).await
  788. }
  789. #[derive(Deserialize)]
  790. #[serde(rename_all = "camelCase")]
  791. struct ChangeEmailData {
  792. master_password_hash: String,
  793. new_email: String,
  794. key: String,
  795. new_master_password_hash: String,
  796. token: NumberOrString,
  797. }
  798. #[post("/accounts/email", data = "<data>")]
  799. async fn post_email(data: Json<ChangeEmailData>, headers: Headers, mut conn: DbConn, nt: Notify<'_>) -> EmptyResult {
  800. if !CONFIG.email_change_allowed() {
  801. err!("Email change is not allowed.");
  802. }
  803. let data: ChangeEmailData = data.into_inner();
  804. let mut user = headers.user;
  805. if !user.check_valid_password(&data.master_password_hash) {
  806. err!("Invalid password")
  807. }
  808. if User::find_by_mail(&data.new_email, &mut conn).await.is_some() {
  809. err!("Email already in use");
  810. }
  811. match user.email_new {
  812. Some(ref val) => {
  813. if val != &data.new_email {
  814. err!("Email change mismatch");
  815. }
  816. }
  817. None => err!("No email change pending"),
  818. }
  819. if CONFIG.mail_enabled() {
  820. // Only check the token if we sent out an email...
  821. match user.email_new_token {
  822. Some(ref val) => {
  823. if *val != data.token.into_string() {
  824. err!("Token mismatch");
  825. }
  826. }
  827. None => err!("No email change pending"),
  828. }
  829. user.verified_at = Some(Utc::now().naive_utc());
  830. } else {
  831. user.verified_at = None;
  832. }
  833. user.email = data.new_email;
  834. user.email_new = None;
  835. user.email_new_token = None;
  836. user.set_password(&data.new_master_password_hash, Some(data.key), true, None);
  837. let save_result = user.save(&mut conn).await;
  838. nt.send_logout(&user, None, &mut conn).await;
  839. save_result
  840. }
  841. #[post("/accounts/verify-email")]
  842. async fn post_verify_email(headers: Headers) -> EmptyResult {
  843. let user = headers.user;
  844. if !CONFIG.mail_enabled() {
  845. err!("Cannot verify email address");
  846. }
  847. if let Err(e) = mail::send_verify_email(&user.email, &user.uuid).await {
  848. error!("Error sending verify_email email: {e:#?}");
  849. }
  850. Ok(())
  851. }
  852. #[derive(Deserialize)]
  853. #[serde(rename_all = "camelCase")]
  854. struct VerifyEmailTokenData {
  855. user_id: UserId,
  856. token: String,
  857. }
  858. #[post("/accounts/verify-email-token", data = "<data>")]
  859. async fn post_verify_email_token(data: Json<VerifyEmailTokenData>, mut conn: DbConn) -> EmptyResult {
  860. let data: VerifyEmailTokenData = data.into_inner();
  861. let Some(mut user) = User::find_by_uuid(&data.user_id, &mut conn).await else {
  862. err!("User doesn't exist")
  863. };
  864. let Ok(claims) = decode_verify_email(&data.token) else {
  865. err!("Invalid claim")
  866. };
  867. if claims.sub != *user.uuid {
  868. err!("Invalid claim");
  869. }
  870. user.verified_at = Some(Utc::now().naive_utc());
  871. user.last_verifying_at = None;
  872. user.login_verify_count = 0;
  873. if let Err(e) = user.save(&mut conn).await {
  874. error!("Error saving email verification: {e:#?}");
  875. }
  876. Ok(())
  877. }
  878. #[derive(Deserialize)]
  879. #[serde(rename_all = "camelCase")]
  880. struct DeleteRecoverData {
  881. email: String,
  882. }
  883. #[post("/accounts/delete-recover", data = "<data>")]
  884. async fn post_delete_recover(data: Json<DeleteRecoverData>, mut conn: DbConn) -> EmptyResult {
  885. let data: DeleteRecoverData = data.into_inner();
  886. if CONFIG.mail_enabled() {
  887. if let Some(user) = User::find_by_mail(&data.email, &mut conn).await {
  888. if let Err(e) = mail::send_delete_account(&user.email, &user.uuid).await {
  889. error!("Error sending delete account email: {e:#?}");
  890. }
  891. }
  892. Ok(())
  893. } else {
  894. // We don't support sending emails, but we shouldn't allow anybody
  895. // to delete accounts without at least logging in... And if the user
  896. // cannot remember their password then they will need to contact
  897. // the administrator to delete it...
  898. err!("Please contact the administrator to delete your account");
  899. }
  900. }
  901. #[derive(Deserialize)]
  902. #[serde(rename_all = "camelCase")]
  903. struct DeleteRecoverTokenData {
  904. user_id: UserId,
  905. token: String,
  906. }
  907. #[post("/accounts/delete-recover-token", data = "<data>")]
  908. async fn post_delete_recover_token(data: Json<DeleteRecoverTokenData>, mut conn: DbConn) -> EmptyResult {
  909. let data: DeleteRecoverTokenData = data.into_inner();
  910. let Ok(claims) = decode_delete(&data.token) else {
  911. err!("Invalid claim")
  912. };
  913. let Some(user) = User::find_by_uuid(&data.user_id, &mut conn).await else {
  914. err!("User doesn't exist")
  915. };
  916. if claims.sub != *user.uuid {
  917. err!("Invalid claim");
  918. }
  919. user.delete(&mut conn).await
  920. }
  921. #[post("/accounts/delete", data = "<data>")]
  922. async fn post_delete_account(data: Json<PasswordOrOtpData>, headers: Headers, conn: DbConn) -> EmptyResult {
  923. delete_account(data, headers, conn).await
  924. }
  925. #[delete("/accounts", data = "<data>")]
  926. async fn delete_account(data: Json<PasswordOrOtpData>, headers: Headers, mut conn: DbConn) -> EmptyResult {
  927. let data: PasswordOrOtpData = data.into_inner();
  928. let user = headers.user;
  929. data.validate(&user, true, &mut conn).await?;
  930. user.delete(&mut conn).await
  931. }
  932. #[get("/accounts/revision-date")]
  933. fn revision_date(headers: Headers) -> JsonResult {
  934. let revision_date = headers.user.updated_at.and_utc().timestamp_millis();
  935. Ok(Json(json!(revision_date)))
  936. }
  937. #[derive(Deserialize)]
  938. #[serde(rename_all = "camelCase")]
  939. struct PasswordHintData {
  940. email: String,
  941. }
  942. #[post("/accounts/password-hint", data = "<data>")]
  943. async fn password_hint(data: Json<PasswordHintData>, mut conn: DbConn) -> EmptyResult {
  944. if !CONFIG.password_hints_allowed() || (!CONFIG.mail_enabled() && !CONFIG.show_password_hint()) {
  945. err!("This server is not configured to provide password hints.");
  946. }
  947. const NO_HINT: &str = "Sorry, you have no password hint...";
  948. let data: PasswordHintData = data.into_inner();
  949. let email = &data.email;
  950. match User::find_by_mail(email, &mut conn).await {
  951. None => {
  952. // To prevent user enumeration, act as if the user exists.
  953. if CONFIG.mail_enabled() {
  954. // There is still a timing side channel here in that the code
  955. // paths that send mail take noticeably longer than ones that
  956. // don't. Add a randomized sleep to mitigate this somewhat.
  957. use rand::{rngs::SmallRng, Rng, SeedableRng};
  958. let mut rng = SmallRng::from_os_rng();
  959. let delta: i32 = 100;
  960. let sleep_ms = (1_000 + rng.random_range(-delta..=delta)) as u64;
  961. tokio::time::sleep(tokio::time::Duration::from_millis(sleep_ms)).await;
  962. Ok(())
  963. } else {
  964. err!(NO_HINT);
  965. }
  966. }
  967. Some(user) => {
  968. let hint: Option<String> = user.password_hint;
  969. if CONFIG.mail_enabled() {
  970. mail::send_password_hint(email, hint).await?;
  971. Ok(())
  972. } else if let Some(hint) = hint {
  973. err!(format!("Your password hint is: {hint}"));
  974. } else {
  975. err!(NO_HINT);
  976. }
  977. }
  978. }
  979. }
  980. #[derive(Deserialize)]
  981. #[serde(rename_all = "camelCase")]
  982. pub struct PreloginData {
  983. email: String,
  984. }
  985. #[post("/accounts/prelogin", data = "<data>")]
  986. async fn prelogin(data: Json<PreloginData>, conn: DbConn) -> Json<Value> {
  987. _prelogin(data, conn).await
  988. }
  989. pub async fn _prelogin(data: Json<PreloginData>, mut conn: DbConn) -> Json<Value> {
  990. let data: PreloginData = data.into_inner();
  991. let (kdf_type, kdf_iter, kdf_mem, kdf_para) = match User::find_by_mail(&data.email, &mut conn).await {
  992. Some(user) => (user.client_kdf_type, user.client_kdf_iter, user.client_kdf_memory, user.client_kdf_parallelism),
  993. None => (User::CLIENT_KDF_TYPE_DEFAULT, User::CLIENT_KDF_ITER_DEFAULT, None, None),
  994. };
  995. Json(json!({
  996. "kdf": kdf_type,
  997. "kdfIterations": kdf_iter,
  998. "kdfMemory": kdf_mem,
  999. "kdfParallelism": kdf_para,
  1000. }))
  1001. }
  1002. // https://github.com/bitwarden/server/blob/9ebe16587175b1c0e9208f84397bb75d0d595510/src/Api/Auth/Models/Request/Accounts/SecretVerificationRequestModel.cs
  1003. #[derive(Deserialize)]
  1004. #[serde(rename_all = "camelCase")]
  1005. struct SecretVerificationRequest {
  1006. master_password_hash: String,
  1007. }
  1008. // Change the KDF Iterations if necessary
  1009. pub async fn kdf_upgrade(user: &mut User, pwd_hash: &str, conn: &mut DbConn) -> ApiResult<()> {
  1010. if user.password_iterations < CONFIG.password_iterations() {
  1011. user.password_iterations = CONFIG.password_iterations();
  1012. user.set_password(pwd_hash, None, false, None);
  1013. if let Err(e) = user.save(conn).await {
  1014. error!("Error updating user: {e:#?}");
  1015. }
  1016. }
  1017. Ok(())
  1018. }
  1019. #[post("/accounts/verify-password", data = "<data>")]
  1020. async fn verify_password(data: Json<SecretVerificationRequest>, headers: Headers, mut conn: DbConn) -> JsonResult {
  1021. let data: SecretVerificationRequest = data.into_inner();
  1022. let mut user = headers.user;
  1023. if !user.check_valid_password(&data.master_password_hash) {
  1024. err!("Invalid password")
  1025. }
  1026. kdf_upgrade(&mut user, &data.master_password_hash, &mut conn).await?;
  1027. Ok(Json(master_password_policy(&user, &conn).await))
  1028. }
  1029. async fn _api_key(data: Json<PasswordOrOtpData>, rotate: bool, headers: Headers, mut conn: DbConn) -> JsonResult {
  1030. use crate::util::format_date;
  1031. let data: PasswordOrOtpData = data.into_inner();
  1032. let mut user = headers.user;
  1033. data.validate(&user, true, &mut conn).await?;
  1034. if rotate || user.api_key.is_none() {
  1035. user.api_key = Some(crypto::generate_api_key());
  1036. user.save(&mut conn).await.expect("Error saving API key");
  1037. }
  1038. Ok(Json(json!({
  1039. "apiKey": user.api_key,
  1040. "revisionDate": format_date(&user.updated_at),
  1041. "object": "apiKey",
  1042. })))
  1043. }
  1044. #[post("/accounts/api-key", data = "<data>")]
  1045. async fn api_key(data: Json<PasswordOrOtpData>, headers: Headers, conn: DbConn) -> JsonResult {
  1046. _api_key(data, false, headers, conn).await
  1047. }
  1048. #[post("/accounts/rotate-api-key", data = "<data>")]
  1049. async fn rotate_api_key(data: Json<PasswordOrOtpData>, headers: Headers, conn: DbConn) -> JsonResult {
  1050. _api_key(data, true, headers, conn).await
  1051. }
  1052. #[get("/devices/knowndevice")]
  1053. async fn get_known_device(device: KnownDevice, mut conn: DbConn) -> JsonResult {
  1054. let mut result = false;
  1055. if let Some(user) = User::find_by_mail(&device.email, &mut conn).await {
  1056. result = Device::find_by_uuid_and_user(&device.uuid, &user.uuid, &mut conn).await.is_some();
  1057. }
  1058. Ok(Json(json!(result)))
  1059. }
  1060. struct KnownDevice {
  1061. email: String,
  1062. uuid: DeviceId,
  1063. }
  1064. #[rocket::async_trait]
  1065. impl<'r> FromRequest<'r> for KnownDevice {
  1066. type Error = &'static str;
  1067. async fn from_request(req: &'r Request<'_>) -> Outcome<Self, Self::Error> {
  1068. let email = if let Some(email_b64) = req.headers().get_one("X-Request-Email") {
  1069. let Ok(email_bytes) = data_encoding::BASE64URL_NOPAD.decode(email_b64.as_bytes()) else {
  1070. return Outcome::Error((Status::BadRequest, "X-Request-Email value failed to decode as base64url"));
  1071. };
  1072. match String::from_utf8(email_bytes) {
  1073. Ok(email) => email,
  1074. Err(_) => {
  1075. return Outcome::Error((Status::BadRequest, "X-Request-Email value failed to decode as UTF-8"));
  1076. }
  1077. }
  1078. } else {
  1079. return Outcome::Error((Status::BadRequest, "X-Request-Email value is required"));
  1080. };
  1081. let uuid = if let Some(uuid) = req.headers().get_one("X-Device-Identifier") {
  1082. uuid.to_string().into()
  1083. } else {
  1084. return Outcome::Error((Status::BadRequest, "X-Device-Identifier value is required"));
  1085. };
  1086. Outcome::Success(KnownDevice {
  1087. email,
  1088. uuid,
  1089. })
  1090. }
  1091. }
  1092. #[get("/devices")]
  1093. async fn get_all_devices(headers: Headers, mut conn: DbConn) -> JsonResult {
  1094. let devices = Device::find_with_auth_request_by_user(&headers.user.uuid, &mut conn).await;
  1095. let devices = devices.iter().map(|device| device.to_json()).collect::<Vec<Value>>();
  1096. Ok(Json(json!({
  1097. "data": devices,
  1098. "continuationToken": null,
  1099. "object": "list"
  1100. })))
  1101. }
  1102. #[get("/devices/identifier/<device_id>")]
  1103. async fn get_device(device_id: DeviceId, headers: Headers, mut conn: DbConn) -> JsonResult {
  1104. let Some(device) = Device::find_by_uuid_and_user(&device_id, &headers.user.uuid, &mut conn).await else {
  1105. err!("No device found");
  1106. };
  1107. Ok(Json(device.to_json()))
  1108. }
  1109. #[derive(Deserialize)]
  1110. #[serde(rename_all = "camelCase")]
  1111. struct PushToken {
  1112. push_token: String,
  1113. }
  1114. #[post("/devices/identifier/<device_id>/token", data = "<data>")]
  1115. async fn post_device_token(device_id: DeviceId, data: Json<PushToken>, headers: Headers, conn: DbConn) -> EmptyResult {
  1116. put_device_token(device_id, data, headers, conn).await
  1117. }
  1118. #[put("/devices/identifier/<device_id>/token", data = "<data>")]
  1119. async fn put_device_token(
  1120. device_id: DeviceId,
  1121. data: Json<PushToken>,
  1122. headers: Headers,
  1123. mut conn: DbConn,
  1124. ) -> EmptyResult {
  1125. let data = data.into_inner();
  1126. let token = data.push_token;
  1127. let Some(mut device) = Device::find_by_uuid_and_user(&headers.device.uuid, &headers.user.uuid, &mut conn).await
  1128. else {
  1129. err!(format!("Error: device {device_id} should be present before a token can be assigned"))
  1130. };
  1131. // Check if the new token is the same as the registered token
  1132. // Although upstream seems to always register a device on login, we do not.
  1133. // Unless this causes issues, lets keep it this way, else we might need to also register on every login.
  1134. if device.push_token.as_ref() == Some(&token) {
  1135. debug!("Device {device_id} for user {} is already registered and token is identical", headers.user.uuid);
  1136. return Ok(());
  1137. }
  1138. device.push_token = Some(token);
  1139. if let Err(e) = device.save(&mut conn).await {
  1140. err!(format!("An error occurred while trying to save the device push token: {e}"));
  1141. }
  1142. register_push_device(&mut device, &mut conn).await?;
  1143. Ok(())
  1144. }
  1145. #[put("/devices/identifier/<device_id>/clear-token")]
  1146. async fn put_clear_device_token(device_id: DeviceId, mut conn: DbConn) -> EmptyResult {
  1147. // This only clears push token
  1148. // https://github.com/bitwarden/server/blob/9ebe16587175b1c0e9208f84397bb75d0d595510/src/Api/Controllers/DevicesController.cs#L215
  1149. // https://github.com/bitwarden/server/blob/9ebe16587175b1c0e9208f84397bb75d0d595510/src/Core/Services/Implementations/DeviceService.cs#L37
  1150. // This is somehow not implemented in any app, added it in case it is required
  1151. // 2025: Also, it looks like it only clears the first found device upstream, which is probably faulty.
  1152. // This because currently multiple accounts could be on the same device/app and that would cause issues.
  1153. // Vaultwarden removes the push-token for all devices, but this probably means we should also unregister all these devices.
  1154. if !CONFIG.push_enabled() {
  1155. return Ok(());
  1156. }
  1157. if let Some(device) = Device::find_by_uuid(&device_id, &mut conn).await {
  1158. Device::clear_push_token_by_uuid(&device_id, &mut conn).await?;
  1159. unregister_push_device(&device.push_uuid).await?;
  1160. }
  1161. Ok(())
  1162. }
  1163. // On upstream server, both PUT and POST are declared. Implementing the POST method in case it would be useful somewhere
  1164. #[post("/devices/identifier/<device_id>/clear-token")]
  1165. async fn post_clear_device_token(device_id: DeviceId, conn: DbConn) -> EmptyResult {
  1166. put_clear_device_token(device_id, conn).await
  1167. }
  1168. #[derive(Debug, Deserialize)]
  1169. #[serde(rename_all = "camelCase")]
  1170. struct AuthRequestRequest {
  1171. access_code: String,
  1172. device_identifier: DeviceId,
  1173. email: String,
  1174. public_key: String,
  1175. // Not used for now
  1176. // #[serde(alias = "type")]
  1177. // _type: i32,
  1178. }
  1179. #[post("/auth-requests", data = "<data>")]
  1180. async fn post_auth_request(
  1181. data: Json<AuthRequestRequest>,
  1182. client_headers: ClientHeaders,
  1183. mut conn: DbConn,
  1184. nt: Notify<'_>,
  1185. ) -> JsonResult {
  1186. let data = data.into_inner();
  1187. let Some(user) = User::find_by_mail(&data.email, &mut conn).await else {
  1188. err!("AuthRequest doesn't exist", "User not found")
  1189. };
  1190. // Validate device uuid and type
  1191. let device = match Device::find_by_uuid_and_user(&data.device_identifier, &user.uuid, &mut conn).await {
  1192. Some(device) if device.atype == client_headers.device_type => device,
  1193. _ => err!("AuthRequest doesn't exist", "Device verification failed"),
  1194. };
  1195. let mut auth_request = AuthRequest::new(
  1196. user.uuid.clone(),
  1197. data.device_identifier.clone(),
  1198. client_headers.device_type,
  1199. client_headers.ip.ip.to_string(),
  1200. data.access_code,
  1201. data.public_key,
  1202. );
  1203. auth_request.save(&mut conn).await?;
  1204. nt.send_auth_request(&user.uuid, &auth_request.uuid, &device, &mut conn).await;
  1205. log_user_event(
  1206. EventType::UserRequestedDeviceApproval as i32,
  1207. &user.uuid,
  1208. client_headers.device_type,
  1209. &client_headers.ip.ip,
  1210. &mut conn,
  1211. )
  1212. .await;
  1213. Ok(Json(json!({
  1214. "id": auth_request.uuid,
  1215. "publicKey": auth_request.public_key,
  1216. "requestDeviceType": DeviceType::from_i32(auth_request.device_type).to_string(),
  1217. "requestIpAddress": auth_request.request_ip,
  1218. "key": null,
  1219. "masterPasswordHash": null,
  1220. "creationDate": format_date(&auth_request.creation_date),
  1221. "responseDate": null,
  1222. "requestApproved": false,
  1223. "origin": CONFIG.domain_origin(),
  1224. "object": "auth-request"
  1225. })))
  1226. }
  1227. #[get("/auth-requests/<auth_request_id>")]
  1228. async fn get_auth_request(auth_request_id: AuthRequestId, headers: Headers, mut conn: DbConn) -> JsonResult {
  1229. let Some(auth_request) = AuthRequest::find_by_uuid_and_user(&auth_request_id, &headers.user.uuid, &mut conn).await
  1230. else {
  1231. err!("AuthRequest doesn't exist", "Record not found or user uuid does not match")
  1232. };
  1233. let response_date_utc = auth_request.response_date.map(|response_date| format_date(&response_date));
  1234. Ok(Json(json!({
  1235. "id": &auth_request_id,
  1236. "publicKey": auth_request.public_key,
  1237. "requestDeviceType": DeviceType::from_i32(auth_request.device_type).to_string(),
  1238. "requestIpAddress": auth_request.request_ip,
  1239. "key": auth_request.enc_key,
  1240. "masterPasswordHash": auth_request.master_password_hash,
  1241. "creationDate": format_date(&auth_request.creation_date),
  1242. "responseDate": response_date_utc,
  1243. "requestApproved": auth_request.approved,
  1244. "origin": CONFIG.domain_origin(),
  1245. "object":"auth-request"
  1246. })))
  1247. }
  1248. #[derive(Debug, Deserialize)]
  1249. #[serde(rename_all = "camelCase")]
  1250. struct AuthResponseRequest {
  1251. device_identifier: DeviceId,
  1252. key: String,
  1253. master_password_hash: Option<String>,
  1254. request_approved: bool,
  1255. }
  1256. #[put("/auth-requests/<auth_request_id>", data = "<data>")]
  1257. async fn put_auth_request(
  1258. auth_request_id: AuthRequestId,
  1259. data: Json<AuthResponseRequest>,
  1260. headers: Headers,
  1261. mut conn: DbConn,
  1262. ant: AnonymousNotify<'_>,
  1263. nt: Notify<'_>,
  1264. ) -> JsonResult {
  1265. let data = data.into_inner();
  1266. let Some(mut auth_request) =
  1267. AuthRequest::find_by_uuid_and_user(&auth_request_id, &headers.user.uuid, &mut conn).await
  1268. else {
  1269. err!("AuthRequest doesn't exist", "Record not found or user uuid does not match")
  1270. };
  1271. if headers.device.uuid != data.device_identifier {
  1272. err!("AuthRequest doesn't exist", "Device verification failed")
  1273. }
  1274. if auth_request.approved.is_some() {
  1275. err!("An authentication request with the same device already exists")
  1276. }
  1277. let response_date = Utc::now().naive_utc();
  1278. let response_date_utc = format_date(&response_date);
  1279. if data.request_approved {
  1280. auth_request.approved = Some(data.request_approved);
  1281. auth_request.enc_key = Some(data.key);
  1282. auth_request.master_password_hash = data.master_password_hash;
  1283. auth_request.response_device_id = Some(data.device_identifier.clone());
  1284. auth_request.response_date = Some(response_date);
  1285. auth_request.save(&mut conn).await?;
  1286. ant.send_auth_response(&auth_request.user_uuid, &auth_request.uuid).await;
  1287. nt.send_auth_response(&auth_request.user_uuid, &auth_request.uuid, &headers.device, &mut conn).await;
  1288. log_user_event(
  1289. EventType::OrganizationUserApprovedAuthRequest as i32,
  1290. &headers.user.uuid,
  1291. headers.device.atype,
  1292. &headers.ip.ip,
  1293. &mut conn,
  1294. )
  1295. .await;
  1296. } else {
  1297. // If denied, there's no reason to keep the request
  1298. auth_request.delete(&mut conn).await?;
  1299. log_user_event(
  1300. EventType::OrganizationUserRejectedAuthRequest as i32,
  1301. &headers.user.uuid,
  1302. headers.device.atype,
  1303. &headers.ip.ip,
  1304. &mut conn,
  1305. )
  1306. .await;
  1307. }
  1308. Ok(Json(json!({
  1309. "id": &auth_request_id,
  1310. "publicKey": auth_request.public_key,
  1311. "requestDeviceType": DeviceType::from_i32(auth_request.device_type).to_string(),
  1312. "requestIpAddress": auth_request.request_ip,
  1313. "key": auth_request.enc_key,
  1314. "masterPasswordHash": auth_request.master_password_hash,
  1315. "creationDate": format_date(&auth_request.creation_date),
  1316. "responseDate": response_date_utc,
  1317. "requestApproved": auth_request.approved,
  1318. "origin": CONFIG.domain_origin(),
  1319. "object":"auth-request"
  1320. })))
  1321. }
  1322. #[get("/auth-requests/<auth_request_id>/response?<code>")]
  1323. async fn get_auth_request_response(
  1324. auth_request_id: AuthRequestId,
  1325. code: &str,
  1326. client_headers: ClientHeaders,
  1327. mut conn: DbConn,
  1328. ) -> JsonResult {
  1329. let Some(auth_request) = AuthRequest::find_by_uuid(&auth_request_id, &mut conn).await else {
  1330. err!("AuthRequest doesn't exist", "User not found")
  1331. };
  1332. if auth_request.device_type != client_headers.device_type
  1333. || auth_request.request_ip != client_headers.ip.ip.to_string()
  1334. || !auth_request.check_access_code(code)
  1335. {
  1336. err!("AuthRequest doesn't exist", "Invalid device, IP or code")
  1337. }
  1338. let response_date_utc = auth_request.response_date.map(|response_date| format_date(&response_date));
  1339. Ok(Json(json!({
  1340. "id": &auth_request_id,
  1341. "publicKey": auth_request.public_key,
  1342. "requestDeviceType": DeviceType::from_i32(auth_request.device_type).to_string(),
  1343. "requestIpAddress": auth_request.request_ip,
  1344. "key": auth_request.enc_key,
  1345. "masterPasswordHash": auth_request.master_password_hash,
  1346. "creationDate": format_date(&auth_request.creation_date),
  1347. "responseDate": response_date_utc,
  1348. "requestApproved": auth_request.approved,
  1349. "origin": CONFIG.domain_origin(),
  1350. "object":"auth-request"
  1351. })))
  1352. }
  1353. #[get("/auth-requests")]
  1354. async fn get_auth_requests(headers: Headers, mut conn: DbConn) -> JsonResult {
  1355. let auth_requests = AuthRequest::find_by_user(&headers.user.uuid, &mut conn).await;
  1356. Ok(Json(json!({
  1357. "data": auth_requests
  1358. .iter()
  1359. .filter(|request| request.approved.is_none())
  1360. .map(|request| {
  1361. let response_date_utc = request.response_date.map(|response_date| format_date(&response_date));
  1362. json!({
  1363. "id": request.uuid,
  1364. "publicKey": request.public_key,
  1365. "requestDeviceType": DeviceType::from_i32(request.device_type).to_string(),
  1366. "requestIpAddress": request.request_ip,
  1367. "key": request.enc_key,
  1368. "masterPasswordHash": request.master_password_hash,
  1369. "creationDate": format_date(&request.creation_date),
  1370. "responseDate": response_date_utc,
  1371. "requestApproved": request.approved,
  1372. "origin": CONFIG.domain_origin(),
  1373. "object":"auth-request"
  1374. })
  1375. }).collect::<Vec<Value>>(),
  1376. "continuationToken": null,
  1377. "object": "list"
  1378. })))
  1379. }
  1380. pub async fn purge_auth_requests(pool: DbPool) {
  1381. debug!("Purging auth requests");
  1382. if let Ok(mut conn) = pool.get().await {
  1383. AuthRequest::purge_expired_auth_requests(&mut conn).await;
  1384. } else {
  1385. error!("Failed to get DB connection while purging trashed ciphers")
  1386. }
  1387. }