A request addressed to an administrator is answered through the organization
and stays open for a week, so counting it as the pending request of its device
hid the short lived one the user was actually being shown and made approving
from another device fail for as long as it was open. It is now excluded, along
with requests past their window, as upstream does.
Findings from a review of the earlier commits.
A key rotation dropped the device key pairs along with the wrapped user
keys, so the devices listed in `/devices/update-trust` could never be
trusted again and silently lost their trust on every rotation. Those key
pairs are wrapped with the device key, which a rotation does not touch, so
they now stay and the re-wrap works. The invalidation also moved ahead of
the new user key: failing after it had been written left devices handing
out a key that no longer opens the vault.
The three key blobs are now checked against the shape of an `EncString`
instead of only for emptiness, as upstream does, which also keeps
multi-megabyte values out of those columns.
`/auth-requests/admin-request` is rate limited and reuses the open request
of a device instead of adding one per attempt, which mailed every
administrator again each time. Only confirmed memberships are asked, and
answered: an invitation that was never accepted is not a membership yet, a
revoked one is not one anymore, and neither should learn the address, the
IP and the device of the asker. `UserDecryptionOptions` reports the same
condition, so no way out is announced that would be refused when taken.
The bulk endpoints skip what they cannot answer rather than failing the
whole call after having answered everything before it, matching upstream,
and are bounded. The purge does its work per type in the database instead
of reading the table and deleting row by row, with indexes to go with it.
Also: approving an auth request is limited to the newest one of a device,
`GET /auth-requests/<id>` refuses an expired request like the anonymous
lookup already did, the approval notification addresses the device that
asked rather than the administrator's, and accepting an invitation while
enrolling is tied to the trusted device flow it was meant for.
Completes the trusted device flow for the case it was missing: a member who
unlocks with a trusted device, has no other device of their own left to ask,
and therefore has no way back into their vault. They can now turn to the
administrators of their organization, who hand them their own user key
encrypted for the key pair of the asking device.
New `atype` on auth_requests, mirroring bitwarden/server's AuthRequestType.
It decides who may answer a request and how long it stays open: 15 minutes
between the user's own devices, a week for an administrator, and half a day
for their answer once given. The purge job applies that per type instead of
dropping everything after 15 minutes, and both the answer and the anonymous
lookup now refuse an expired request, which they did not before.
POST /auth-requests/admin-request ask, one request per org
GET /organizations/<id>/auth-requests what is waiting for an answer
POST /organizations/<id>/auth-requests/<id> approve or deny one
POST /organizations/<id>/auth-requests/deny deny several
POST /organizations/<id>/auth-requests answer several
Asking requires authentication, so the anonymous `POST /auth-requests` now
refuses the type. Answering goes through the organization the request was
addressed to and needs admin rights there; the asking user cannot answer
their own request through `PUT /auth-requests/<id>`, which would make the
whole detour pointless. A denial is saved but not announced, so a request
that did not come from the member does not learn that it was seen. The
administrator's view leaves out the access code, which is the asking
device's proof and none of their business.
The administrators are mailed when a request arrives, the member when one of
their devices was let in, so an approval nobody asked for does not pass
unnoticed.
Two fixes without which none of this is reachable from a client:
- `UserDecryptionOptions.TrustedDeviceOption` reported `HasAdminApproval`
and `HasManageResetPasswordPermission` as a flat false. The clients
decide on `hasAdminApproval || hasMasterPassword` whether a login is a
returning user or a brand new one, so a member without a master password
was shown the screen for creating an account, on every device but the
one they first trusted. Both are now derived from the account recovery
enrollment and the role.
- `PUT /organizations/<id>/users/<id>/reset-password-enrollment` demanded a
master password whenever a key was supplied. An account that unlocks
with a trusted device has none, and the clients send nothing but the key
when they enroll during registration, so enrolling was impossible for
exactly the accounts that need it most. Upstream carves out the same
exception, keyed on the organization's SSO configuration rather than on
a server-wide setting as here. Enrolling now also accepts a pending
invitation, as upstream does, so a just-provisioned member does not stay
invited forever with nobody able to confirm them.
* Update to Rust 2024 Edition
Updated to the Rust 2024 Edition and added and fixed several lint checks.
This is a large change which, because of the extra lints, added some possible fixes for issues.
Signed-off-by: BlackDex <black.dex@gmail.com>
* Reorder and merge imports
Signed-off-by: BlackDex <black.dex@gmail.com>
* Remove "db_run!" macro calls where possible
Signed-off-by: BlackDex <black.dex@gmail.com>
---------
Signed-off-by: BlackDex <black.dex@gmail.com>
* Use Diesels MultiConnections Derive
With this PR we remove almost all custom macro's to create the multiple database type code. This is now handled by Diesel it self.
This removed the need of the following functions/macro's:
- `db_object!`
- `::to_db`
- `.from_db()`
It is also possible to just use one schema instead of multiple per type.
Also done:
- Refactored the SQLite backup function
- Some formatting of queries so every call is one a separate line, this looks a bit better
- Declare `conn` as mut inside each `db_run!` instead of having to declare it as `mut` in functions or calls
- Added an `ACTIVE_DB_TYPE` static which holds the currently active database type
- Removed `diesel_logger` crate and use Diesel's `set_default_instrumentation()`
If you want debug queries you can now simply change the log level of `vaultwarden::db::query_logger`
- Use PostgreSQL v17 in the Alpine images to match the Debian Trixie version
- Optimized the Workflows since `diesel_logger` isn't needed anymore
And on the extra plus-side, this lowers the compile-time and binary size too.
Signed-off-by: BlackDex <black.dex@gmail.com>
* Adjust query_logger and some other small items
Signed-off-by: BlackDex <black.dex@gmail.com>
* Remove macro, replaced with an function
Signed-off-by: BlackDex <black.dex@gmail.com>
* Implement custom connection manager
Signed-off-by: BlackDex <black.dex@gmail.com>
* Updated some crates to keep up2date
Signed-off-by: BlackDex <black.dex@gmail.com>
* Small adjustment
Signed-off-by: BlackDex <black.dex@gmail.com>
* crate updates
Signed-off-by: BlackDex <black.dex@gmail.com>
* Update crates
Signed-off-by: BlackDex <black.dex@gmail.com>
---------
Signed-off-by: BlackDex <black.dex@gmail.com>
* Fix several more multi select push issues
There were some more items which would still overload the push endpoint.
This PR fixes the remaining items (I hope).
I also encountered a missing endpoint for restoring multiple ciphers from the trash via the admin console.
Overall, we could improve a lot of these items in a different way. Like bundle all SQL Queries etc...
But that takes more time, and this fixes overloading the Bitwarden push servers, and speeds up these specific actions.
Signed-off-by: BlackDex <black.dex@gmail.com>
* Update src/api/core/ciphers.rs
Co-authored-by: Daniel García <dani-garcia@users.noreply.github.com>
---------
Signed-off-by: BlackDex <black.dex@gmail.com>
Co-authored-by: Daniel García <dani-garcia@users.noreply.github.com>
* WIP Sync with Upstream
WIP on syncing API Responses with upstream.
This to prevent issues with new clients, and find possible current issues like members, collections, groups etc..
Signed-off-by: BlackDex <black.dex@gmail.com>
* More API Response fixes
- Some 2fa checks
- Some org checks
- Reconfigured the experimental flags and noted which are deprecated
Also removed some hard-coded defaults.
- Updated crates
Signed-off-by: BlackDex <black.dex@gmail.com>
* Add avatar color to emergency access api
Signed-off-by: BlackDex <black.dex@gmail.com>
* Fix spelling and some crate updates
Signed-off-by: BlackDex <black.dex@gmail.com>
* Use PushId and always generate the PushId
Signed-off-by: BlackDex <black.dex@gmail.com>
* Fix clippy lints
Signed-off-by: BlackDex <black.dex@gmail.com>
* Fix several Push issues and API's
Signed-off-by: BlackDex <black.dex@gmail.com>
* Check if push_uuid is empty and generate when needed
Signed-off-by: BlackDex <black.dex@gmail.com>
* Updated some comments and removed old export format
Signed-off-by: BlackDex <black.dex@gmail.com>
* cargo update
Signed-off-by: BlackDex <black.dex@gmail.com>
* Fix bulk edit Fixes#5737
Signed-off-by: BlackDex <black.dex@gmail.com>
* Send an email when an account exists already
When you want to change your email address into an account which already exists, upstream sends an email to the existing account.
Lets do the same.
Kinda fixes#5630
Signed-off-by: BlackDex <black.dex@gmail.com>
* Update 2fa removal/revoke email
Signed-off-by: BlackDex <black.dex@gmail.com>
* Allow col managers to import
This commit adds functionality to allow users with manage access to a collection, or managers with all access to import into an organization.
Fixes#5592
Signed-off-by: BlackDex <black.dex@gmail.com>
* Filter deprected flags and only return active flags
Signed-off-by: BlackDex <black.dex@gmail.com>
* Fix grammer
Signed-off-by: BlackDex <black.dex@gmail.com>
* Rename Small to Compact
Signed-off-by: BlackDex <black.dex@gmail.com>
* Rebase with upstream and fix conflicts
Signed-off-by: BlackDex <black.dex@gmail.com>
---------
Signed-off-by: BlackDex <black.dex@gmail.com>
* rename membership
rename UserOrganization to Membership to clarify the relation
and prevent confusion whether something refers to a member(ship) or user
* use newtype pattern
* implement custom derive macro IdFromParam
* add UuidFromParam macro for UUIDs
* add macros to Docker build
Co-authored-by: dfunkt <dfunkt@users.noreply.github.com>
---------
Co-authored-by: dfunkt <dfunkt@users.noreply.github.com>
- Refactored several code to use more modern syntax
- Made some checks a bit more strict
- Updated crates
Signed-off-by: BlackDex <black.dex@gmail.com>
- Updated sqlite crate
- Updated chrono crate
The latter needed a lot of changes done, mostly `Duration` to `TimeDelta`.
And some changes on how to use Naive.
It looks like either something changed in the latest v2023.8.x versions,
or when using Biometrics to login, but the MasterPasswordHash is an
optional value during the Approve action.
This PR makes the MasterPasswordHash an optional value which resolves
this issues. Bitwarden works the same way.
I also changed the EncKey to an Option in the database since empty
strings as a default value is not nice in databases, better to use
`null` in these cases.
Fixes#3819