Compare commits

...

38 Commits

Author SHA1 Message Date
Daniel García c666497130 Update webvault to 2.21.1 2021-07-25 18:56:06 +02:00
Daniel García 2620a1ac8c Merge pull request #1869 from BlackDex/webauthn-plus-updates
Fix WebAuthn issues and some small updates
2021-07-25 17:23:37 +02:00
BlackDex ffdcafa044 Fix WebAuthn issues and some small updates
- Updated some packages
- Updated code related to package updates.
- Disabled User Verification enforcement when WebAuthn Key sends UV=1
  This makes it compatible with upstream and resolves #1840
- Fixed a bug where removing an individual WebAuthn key deleted the wrong key.
2021-07-25 14:49:55 +02:00
Daniel García 56ffec40f4 Formatting 2021-07-15 21:52:17 +02:00
Daniel García 96c2416903 Merge branch 'BlackDex-future-web-vault' into main 2021-07-15 21:51:52 +02:00
Mathijs van Veluw 340d42a1ca Merge branch 'main' into future-web-vault 2021-07-15 21:43:23 +02:00
Daniel García e19420160f Simplify 2fa removed email and remove extra table close in the footer 2021-07-15 21:25:46 +02:00
Daniel García 1741316f42 Merge branch 'olivierIllogika-2fa_enforcement' into main 2021-07-15 19:27:45 +02:00
Daniel García 4f08167d6f Merge branch '2fa_enforcement' of https://github.com/olivierIllogika/bitwarden_rs into olivierIllogika-2fa_enforcement 2021-07-15 19:27:36 +02:00
Daniel García fef76e2f6f Merge branch 'BlackDex-attachment-storage' into main 2021-07-15 19:20:57 +02:00
Daniel García f16d56cb27 Merge branch 'attachment-storage' of https://github.com/BlackDex/vaultwarden into BlackDex-attachment-storage 2021-07-15 19:20:52 +02:00
Daniel García 120b286f2b Merge branch 'umireon-umireon-add-edge-frame-ancestors' into main 2021-07-15 19:20:25 +02:00
Daniel García 7f437b6947 Merge branch 'umireon-add-edge-frame-ancestors' of https://github.com/umireon/vaultwarden into umireon-umireon-add-edge-frame-ancestors 2021-07-15 19:20:19 +02:00
Daniel García 8d6e62e18b Merge branch 'jjlin-password-hints' into main 2021-07-15 19:18:30 +02:00
Daniel García d0ec410b73 Merge branch 'password-hints' of https://github.com/jjlin/vaultwarden into jjlin-password-hints 2021-07-15 19:18:22 +02:00
Daniel García c546a59c38 Dependency updates 2021-07-15 19:18:16 +02:00
Daniel García e5ec245626 Protect namedfile against path traversal, rocket only does it for pathbuf 2021-07-15 19:15:55 +02:00
BlackDex 6ea95d1ede Updated attachment limit descriptions
The user and org attachment limit use `size` as wording while it should
have been `storage` since it isn't per attachment, but the sum of all attachments.

- Changed the wording in the config/env
- Changed the wording of the error messages.

Resolves #1818
2021-07-13 15:17:03 +02:00
Jeremy Lin 88bea44dd8 Prevent user enumeration via password hints
When `show_password_hint` is enabled but mail is not configured, the previous
implementation returned a differentiable response for non-existent email
addresses.

Even if mail is enabled, there is a timing side channel since mail is sent
synchronously. Add a randomized sleep to mitigate this somewhat.
2021-07-10 01:21:27 -07:00
Jeremy Lin 8ee5d51bd4 Disable show_password_hint by default
A setting that provides unauthenticated access to potentially sensitive data
shouldn't be enabled by default.
2021-07-10 01:20:37 -07:00
Kaito Udagawa c640abbcd7 Update src/util.rs
Co-authored-by: William Desportes <williamdes@wdes.fr>
2021-07-08 02:55:58 +09:00
Kaito Udagawa 13598c098f Add links to browser extensions 2021-07-08 02:52:45 +09:00
Kaito Udagawa a622b4d2fb Add Edge's frame-ancestors
Edge's frame-ancestors are required for Edge extension to do WebAuthn.
2021-07-08 01:19:52 +09:00
BlackDex 403f35b571 Added web-vault v2.21.x support + some misc fixes
- The new web-vault v2.21.0+ has support for Master Password Reset. For
this to work it generates a public/private key-pair which needs to be
stored in the database. Currently the Master Password Reset is not
fixed, but there are endpoints which are needed even if we do not
support this feature (yet). This PR fixes those endpoints, and stores
the keys already in the database.

- There was an issue when you want to do a key-rotate when you change
your password, it also called an Emergency Access endpoint, which we do
not yet support. Because this endpoint failed to reply correctly
produced some errors, and also prevent the user from being forced to
logout. This resolves #1826 by adding at least that endpoint.

Because of that extra endpoint check to Emergency Access is done using
an old user stamp, i also modified the stamp exception to allow multiple
rocket routes to be called, and added an expiration timestamp to it.

During these tests i stumbled upon an issue that after my key-change was
done, it triggered the websockets to try and reload my ciphers, because
they were updated. This shouldn't happen when rotating they keys, since
all access should be invalided. Now there will be no websocket
notification for this, which also prevents error toasts.

- Increased Send Size limit to 500MB (with a litle overhead)

As a side note, i tested these changes on both v2.20.4 and v2.21.1 web-vault versions, all keeps working.
2021-07-04 23:02:56 +02:00
Daniel García 3968bc8016 Merge pull request #1800 from BlackDex/pre-commit
Adding pre-commit config
2021-07-04 21:58:43 +02:00
Daniel García ff66368cb6 Merge pull request #1830 from BlackDex/vaultwarden-logo
Storing the original Vaultwarden svg images
2021-07-04 21:58:29 +02:00
BlackDex 3fb419e704 Storing the original Vaultwarden svg images 2021-07-04 18:37:01 +02:00
Daniel García 832f838ddd Merge pull request #1809 from BlackDex/fix-armv7
Fix armv7 alpine build.
2021-06-29 17:16:57 +02:00
BlackDex 18703bf195 Fix armv7 alpine build.
The `messense/rust-musl-cross` has removed OpenSSL in favor of the
vendored option. Enabled vendored openssl to resolve this.

Resolves #1807
2021-06-29 10:37:39 +02:00
BlackDex ff8e88a5df Adding pre-commit config
There is a nice tool called pre-commit: https://pre-commit.com/
It can run actions prior to a commit to validate everything is working.
People can choose to enable this for them selfs, but it would be nice to have a base config by default.
2021-06-27 19:11:22 +02:00
Olivier Martin 39167d333a Merge commit '0d631329873196935ba29db985c5e32def391251' into 2fa_enforcement 2021-05-01 12:35:58 -04:00
Olivier Martin f707f86c8e Merge commit '1e5306b8203a7ebe24047910e6c690c18c6d827a' into 2fa_enforcement 2021-04-29 23:29:28 -04:00
Olivier Martin cc021a4784 project name and links in new email templates 2021-04-27 21:48:07 -04:00
Olivier Martin e3c4609c2a Merge commit '3da44a8d30e76f48b84f5b888e0b33427037037c' into 2fa_enforcement 2021-04-27 21:44:32 -04:00
Olivier Martin 89a68741d6 ran cargo fmt --all 2021-04-16 14:49:59 -04:00
Olivier Martin 2421d49d9a Merge branch 'master' of github.com:dani-garcia/bitwarden_rs into 2fa_enforcement
# Conflicts:
#	src/db/models/org_policy.rs
#	src/db/models/organization.rs
2021-04-16 14:29:28 -04:00
Olivier Martin 1db37bf3d0 make error toast display detailed message
replace invite accept error message with the one from upstream
check if config mail is enabled
2021-04-12 21:54:57 -04:00
Olivier Martin d75a80bd2d Resolves dani-garcia/bitwarden_rs#981
* a user without 2fa trying to join a 2fa org will fail, but user gets an email to enable 2fa
* a user disabling 2fa will be removed from 2fa orgs; user gets an email for each org
* an org enabling 2fa policy will remove users without 2fa; users get an email
2021-04-11 22:57:17 -04:00
45 changed files with 1174 additions and 265 deletions
+10 -6
View File
@@ -194,11 +194,13 @@
## Name shown in the invitation emails that don't come from a specific organization
# INVITATION_ORG_NAME=Vaultwarden
## Per-organization attachment limit (KB)
## Limit in kilobytes for an organization attachments, once the limit is exceeded it won't be possible to upload more
## Per-organization attachment storage limit (KB)
## Max kilobytes of attachment storage allowed per organization.
## When this limit is reached, organization members will not be allowed to upload further attachments for ciphers owned by that organization.
# ORG_ATTACHMENT_LIMIT=
## Per-user attachment limit (KB).
## Limit in kilobytes for a users attachments, once the limit is exceeded it won't be possible to upload more
## Per-user attachment storage limit (KB)
## Max kilobytes of attachment storage allowed per user.
## When this limit is reached, the user will not be allowed to upload further attachments.
# USER_ATTACHMENT_LIMIT=
## Number of days to wait before auto-deleting a trashed item.
@@ -210,8 +212,10 @@
## The change only applies when the password is changed
# PASSWORD_ITERATIONS=100000
## Whether password hint should be sent into the error response when the client request it
# SHOW_PASSWORD_HINT=true
## Controls whether a password hint should be shown directly in the web page if
## SMTP service is not configured. Not recommended for publicly-accessible instances
## as this provides unauthenticated access to potentially sensitive data.
# SHOW_PASSWORD_HINT=false
## Domain settings
## The domain must match the address from where you access the server
+37
View File
@@ -0,0 +1,37 @@
---
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.0.1
hooks:
- id: check-yaml
- id: check-json
- id: check-toml
- id: end-of-file-fixer
- id: check-case-conflict
- id: check-merge-conflict
- id: detect-private-key
- repo: local
hooks:
- id: fmt
name: fmt
description: Format files with cargo fmt.
entry: cargo fmt
language: system
types: [rust]
args: ["--", "--check"]
- id: cargo-test
name: cargo test
description: Test the package for errors.
entry: cargo test
language: system
args: ["--features", "sqlite,mysql,postgresql", "--"]
types: [rust]
pass_filenames: false
- id: cargo-clippy
name: cargo clippy
description: Lint Rust sources
entry: cargo clippy
language: system
args: ["--features", "sqlite,mysql,postgresql", "--", "-D", "warnings"]
types: [rust]
pass_filenames: false
Generated
+101 -106
View File
File diff suppressed because it is too large Load Diff
+5 -8
View File
@@ -35,7 +35,7 @@ rocket_contrib = "=0.5.0-dev"
reqwest = { version = "0.11.4", features = ["blocking", "json", "gzip", "brotli", "socks", "cookies"] }
# Used for custom short lived cookie jar
cookie = "0.15.0"
cookie = "0.15.1"
cookie_store = "0.15.0"
bytes = "1.0.1"
url = "2.2.2"
@@ -44,7 +44,7 @@ url = "2.2.2"
multipart = { version = "0.18.0", features = ["server"], default-features = false }
# WebSockets library
ws = { version = "0.10.0", package = "parity-ws" }
ws = { version = "0.11.0", package = "parity-ws" }
# MessagePack library
rmpv = "0.4.7"
@@ -93,7 +93,7 @@ jsonwebtoken = "7.2.0"
# U2F library
u2f = "0.2.0"
webauthn-rs = "0.3.0-alpha.7"
webauthn-rs = "=0.3.0-alpha.9"
# Yubico Library
yubico = { version = "0.10.0", features = ["online-tokio"], default-features = false }
@@ -113,7 +113,7 @@ tracing = { version = "0.1.26", features = ["log"] } # Needed to have lettre tra
lettre = { version = "0.10.0-rc.3", features = ["smtp-transport", "builder", "serde", "native-tls", "hostname", "tracing"], default-features = false }
# Template library
handlebars = { version = "4.0.1", features = ["dir_source"] }
handlebars = { version = "4.1.0", features = ["dir_source"] }
# For favicon extraction from main website
html5ever = "0.25.1"
@@ -122,7 +122,7 @@ regex = { version = "1.5.4", features = ["std", "perf"], default-features = fals
data-url = "0.1.0"
# Used by U2F, JWT and Postgres
openssl = "0.10.34"
openssl = "0.10.35"
# URL encoding library
percent-encoding = "2.1.0"
@@ -152,6 +152,3 @@ data-url = { git = 'https://github.com/servo/rust-url', package="data-url", rev
# In particular, `cron` has since implemented parsing of some common syntax
# that wasn't previously supported (https://github.com/zslayton/cron/pull/64).
job_scheduler = { git = 'https://github.com/jjlin/job_scheduler', rev = 'ee023418dbba2bfe1e30a5fd7d937f9e33739806' }
# Add support for U2F appid extension compatibility
webauthn-rs = { git = 'https://github.com/kanidm/webauthn-rs', rev = '02a99f534127b30c6f4df7f2d42bc24f76dc4211' }
+4 -3
View File
@@ -44,8 +44,8 @@
# https://docs.docker.com/develop/develop-images/multistage-build/
# https://whitfin.io/speeding-up-rust-docker-builds/
####################### VAULT BUILD IMAGE #######################
{% set vault_version = "2.20.4b" %}
{% set vault_image_digest = "sha256:894e266d4491494dd5a8a736855a6772aa146fa14206853b11b41cf3f3f64d05" %}
{% set vault_version = "2.21.1" %}
{% set vault_image_digest = "sha256:29a4fa7bf3790fff9d908b02ac5a154913491f4bf30c95b87b06d8cf1c5516b5" %}
# The web-vault digest specifies a particular web-vault build on Docker Hub.
# Using the digest instead of the tag name provides better security,
# as the digest of an image is immutable, whereas a tag name can later
@@ -75,7 +75,8 @@ ARG DB=sqlite,postgresql
{% set features = "sqlite,postgresql" %}
{% else %}
# Alpine-based ARM (musl) only supports sqlite during compile time.
ARG DB=sqlite
# We now also need to add vendored_openssl, because the current base image we use to build has OpenSSL removed.
ARG DB=sqlite,vendored_openssl
{% set features = "sqlite" %}
{% endif %}
{% else %}
+6 -6
View File
@@ -14,15 +14,15 @@
# - From https://hub.docker.com/r/vaultwarden/web-vault/tags,
# click the tag name to view the digest of the image it currently points to.
# - From the command line:
# $ docker pull vaultwarden/web-vault:v2.20.4b
# $ docker image inspect --format "{{.RepoDigests}}" vaultwarden/web-vault:v2.20.4b
# [vaultwarden/web-vault@sha256:894e266d4491494dd5a8a736855a6772aa146fa14206853b11b41cf3f3f64d05]
# $ docker pull vaultwarden/web-vault:v2.21.1
# $ docker image inspect --format "{{.RepoDigests}}" vaultwarden/web-vault:v2.21.1
# [vaultwarden/web-vault@sha256:29a4fa7bf3790fff9d908b02ac5a154913491f4bf30c95b87b06d8cf1c5516b5]
#
# - Conversely, to get the tag name from the digest:
# $ docker image inspect --format "{{.RepoTags}}" vaultwarden/web-vault@sha256:894e266d4491494dd5a8a736855a6772aa146fa14206853b11b41cf3f3f64d05
# [vaultwarden/web-vault:v2.20.4b]
# $ docker image inspect --format "{{.RepoTags}}" vaultwarden/web-vault@sha256:29a4fa7bf3790fff9d908b02ac5a154913491f4bf30c95b87b06d8cf1c5516b5
# [vaultwarden/web-vault:v2.21.1]
#
FROM vaultwarden/web-vault@sha256:894e266d4491494dd5a8a736855a6772aa146fa14206853b11b41cf3f3f64d05 as vault
FROM vaultwarden/web-vault@sha256:29a4fa7bf3790fff9d908b02ac5a154913491f4bf30c95b87b06d8cf1c5516b5 as vault
########################## BUILD IMAGE ##########################
FROM rust:1.53 as build
+6 -6
View File
@@ -14,15 +14,15 @@
# - From https://hub.docker.com/r/vaultwarden/web-vault/tags,
# click the tag name to view the digest of the image it currently points to.
# - From the command line:
# $ docker pull vaultwarden/web-vault:v2.20.4b
# $ docker image inspect --format "{{.RepoDigests}}" vaultwarden/web-vault:v2.20.4b
# [vaultwarden/web-vault@sha256:894e266d4491494dd5a8a736855a6772aa146fa14206853b11b41cf3f3f64d05]
# $ docker pull vaultwarden/web-vault:v2.21.1
# $ docker image inspect --format "{{.RepoDigests}}" vaultwarden/web-vault:v2.21.1
# [vaultwarden/web-vault@sha256:29a4fa7bf3790fff9d908b02ac5a154913491f4bf30c95b87b06d8cf1c5516b5]
#
# - Conversely, to get the tag name from the digest:
# $ docker image inspect --format "{{.RepoTags}}" vaultwarden/web-vault@sha256:894e266d4491494dd5a8a736855a6772aa146fa14206853b11b41cf3f3f64d05
# [vaultwarden/web-vault:v2.20.4b]
# $ docker image inspect --format "{{.RepoTags}}" vaultwarden/web-vault@sha256:29a4fa7bf3790fff9d908b02ac5a154913491f4bf30c95b87b06d8cf1c5516b5
# [vaultwarden/web-vault:v2.21.1]
#
FROM vaultwarden/web-vault@sha256:894e266d4491494dd5a8a736855a6772aa146fa14206853b11b41cf3f3f64d05 as vault
FROM vaultwarden/web-vault@sha256:29a4fa7bf3790fff9d908b02ac5a154913491f4bf30c95b87b06d8cf1c5516b5 as vault
########################## BUILD IMAGE ##########################
FROM clux/muslrust:nightly-2021-06-24 as build
+6 -6
View File
@@ -14,15 +14,15 @@
# - From https://hub.docker.com/r/vaultwarden/web-vault/tags,
# click the tag name to view the digest of the image it currently points to.
# - From the command line:
# $ docker pull vaultwarden/web-vault:v2.20.4b
# $ docker image inspect --format "{{.RepoDigests}}" vaultwarden/web-vault:v2.20.4b
# [vaultwarden/web-vault@sha256:894e266d4491494dd5a8a736855a6772aa146fa14206853b11b41cf3f3f64d05]
# $ docker pull vaultwarden/web-vault:v2.21.1
# $ docker image inspect --format "{{.RepoDigests}}" vaultwarden/web-vault:v2.21.1
# [vaultwarden/web-vault@sha256:29a4fa7bf3790fff9d908b02ac5a154913491f4bf30c95b87b06d8cf1c5516b5]
#
# - Conversely, to get the tag name from the digest:
# $ docker image inspect --format "{{.RepoTags}}" vaultwarden/web-vault@sha256:894e266d4491494dd5a8a736855a6772aa146fa14206853b11b41cf3f3f64d05
# [vaultwarden/web-vault:v2.20.4b]
# $ docker image inspect --format "{{.RepoTags}}" vaultwarden/web-vault@sha256:29a4fa7bf3790fff9d908b02ac5a154913491f4bf30c95b87b06d8cf1c5516b5
# [vaultwarden/web-vault:v2.21.1]
#
FROM vaultwarden/web-vault@sha256:894e266d4491494dd5a8a736855a6772aa146fa14206853b11b41cf3f3f64d05 as vault
FROM vaultwarden/web-vault@sha256:29a4fa7bf3790fff9d908b02ac5a154913491f4bf30c95b87b06d8cf1c5516b5 as vault
########################## BUILD IMAGE ##########################
FROM rust:1.53 as build
+6 -6
View File
@@ -14,15 +14,15 @@
# - From https://hub.docker.com/r/vaultwarden/web-vault/tags,
# click the tag name to view the digest of the image it currently points to.
# - From the command line:
# $ docker pull vaultwarden/web-vault:v2.20.4b
# $ docker image inspect --format "{{.RepoDigests}}" vaultwarden/web-vault:v2.20.4b
# [vaultwarden/web-vault@sha256:894e266d4491494dd5a8a736855a6772aa146fa14206853b11b41cf3f3f64d05]
# $ docker pull vaultwarden/web-vault:v2.21.1
# $ docker image inspect --format "{{.RepoDigests}}" vaultwarden/web-vault:v2.21.1
# [vaultwarden/web-vault@sha256:29a4fa7bf3790fff9d908b02ac5a154913491f4bf30c95b87b06d8cf1c5516b5]
#
# - Conversely, to get the tag name from the digest:
# $ docker image inspect --format "{{.RepoTags}}" vaultwarden/web-vault@sha256:894e266d4491494dd5a8a736855a6772aa146fa14206853b11b41cf3f3f64d05
# [vaultwarden/web-vault:v2.20.4b]
# $ docker image inspect --format "{{.RepoTags}}" vaultwarden/web-vault@sha256:29a4fa7bf3790fff9d908b02ac5a154913491f4bf30c95b87b06d8cf1c5516b5
# [vaultwarden/web-vault:v2.21.1]
#
FROM vaultwarden/web-vault@sha256:894e266d4491494dd5a8a736855a6772aa146fa14206853b11b41cf3f3f64d05 as vault
FROM vaultwarden/web-vault@sha256:29a4fa7bf3790fff9d908b02ac5a154913491f4bf30c95b87b06d8cf1c5516b5 as vault
########################## BUILD IMAGE ##########################
FROM rust:1.53 as build
+6 -6
View File
@@ -14,15 +14,15 @@
# - From https://hub.docker.com/r/vaultwarden/web-vault/tags,
# click the tag name to view the digest of the image it currently points to.
# - From the command line:
# $ docker pull vaultwarden/web-vault:v2.20.4b
# $ docker image inspect --format "{{.RepoDigests}}" vaultwarden/web-vault:v2.20.4b
# [vaultwarden/web-vault@sha256:894e266d4491494dd5a8a736855a6772aa146fa14206853b11b41cf3f3f64d05]
# $ docker pull vaultwarden/web-vault:v2.21.1
# $ docker image inspect --format "{{.RepoDigests}}" vaultwarden/web-vault:v2.21.1
# [vaultwarden/web-vault@sha256:29a4fa7bf3790fff9d908b02ac5a154913491f4bf30c95b87b06d8cf1c5516b5]
#
# - Conversely, to get the tag name from the digest:
# $ docker image inspect --format "{{.RepoTags}}" vaultwarden/web-vault@sha256:894e266d4491494dd5a8a736855a6772aa146fa14206853b11b41cf3f3f64d05
# [vaultwarden/web-vault:v2.20.4b]
# $ docker image inspect --format "{{.RepoTags}}" vaultwarden/web-vault@sha256:29a4fa7bf3790fff9d908b02ac5a154913491f4bf30c95b87b06d8cf1c5516b5
# [vaultwarden/web-vault:v2.21.1]
#
FROM vaultwarden/web-vault@sha256:894e266d4491494dd5a8a736855a6772aa146fa14206853b11b41cf3f3f64d05 as vault
FROM vaultwarden/web-vault@sha256:29a4fa7bf3790fff9d908b02ac5a154913491f4bf30c95b87b06d8cf1c5516b5 as vault
########################## BUILD IMAGE ##########################
FROM rust:1.53 as build
+8 -7
View File
@@ -14,21 +14,22 @@
# - From https://hub.docker.com/r/vaultwarden/web-vault/tags,
# click the tag name to view the digest of the image it currently points to.
# - From the command line:
# $ docker pull vaultwarden/web-vault:v2.20.4b
# $ docker image inspect --format "{{.RepoDigests}}" vaultwarden/web-vault:v2.20.4b
# [vaultwarden/web-vault@sha256:894e266d4491494dd5a8a736855a6772aa146fa14206853b11b41cf3f3f64d05]
# $ docker pull vaultwarden/web-vault:v2.21.1
# $ docker image inspect --format "{{.RepoDigests}}" vaultwarden/web-vault:v2.21.1
# [vaultwarden/web-vault@sha256:29a4fa7bf3790fff9d908b02ac5a154913491f4bf30c95b87b06d8cf1c5516b5]
#
# - Conversely, to get the tag name from the digest:
# $ docker image inspect --format "{{.RepoTags}}" vaultwarden/web-vault@sha256:894e266d4491494dd5a8a736855a6772aa146fa14206853b11b41cf3f3f64d05
# [vaultwarden/web-vault:v2.20.4b]
# $ docker image inspect --format "{{.RepoTags}}" vaultwarden/web-vault@sha256:29a4fa7bf3790fff9d908b02ac5a154913491f4bf30c95b87b06d8cf1c5516b5
# [vaultwarden/web-vault:v2.21.1]
#
FROM vaultwarden/web-vault@sha256:894e266d4491494dd5a8a736855a6772aa146fa14206853b11b41cf3f3f64d05 as vault
FROM vaultwarden/web-vault@sha256:29a4fa7bf3790fff9d908b02ac5a154913491f4bf30c95b87b06d8cf1c5516b5 as vault
########################## BUILD IMAGE ##########################
FROM messense/rust-musl-cross:armv7-musleabihf as build
# Alpine-based ARM (musl) only supports sqlite during compile time.
ARG DB=sqlite
# We now also need to add vendored_openssl, because the current base image we use to build has OpenSSL removed.
ARG DB=sqlite,vendored_openssl
# Build time options to avoid dpkg warnings and help with reproducible builds.
ENV DEBIAN_FRONTEND=noninteractive LANG=C.UTF-8 TZ=UTC TERM=xterm-256color
@@ -0,0 +1,5 @@
ALTER TABLE organizations
ADD COLUMN private_key TEXT;
ALTER TABLE organizations
ADD COLUMN public_key TEXT;
@@ -0,0 +1,5 @@
ALTER TABLE organizations
ADD COLUMN private_key TEXT;
ALTER TABLE organizations
ADD COLUMN public_key TEXT;
@@ -0,0 +1,5 @@
ALTER TABLE organizations
ADD COLUMN private_key TEXT;
ALTER TABLE organizations
ADD COLUMN public_key TEXT;
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.7 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.4 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 17 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 12 KiB

+44 -19
View File
@@ -231,7 +231,10 @@ fn post_password(data: JsonUpcase<ChangePassData>, headers: Headers, conn: DbCon
err!("Invalid password")
}
user.set_password(&data.NewMasterPasswordHash, Some("post_rotatekey"));
user.set_password(
&data.NewMasterPasswordHash,
Some(vec![String::from("post_rotatekey"), String::from("get_contacts")]),
);
user.akey = data.Key;
user.save(&conn)
}
@@ -320,7 +323,9 @@ fn post_rotatekey(data: JsonUpcase<KeyData>, headers: Headers, conn: DbConn, nt:
err!("The cipher is not owned by the user")
}
update_cipher_from_data(&mut saved_cipher, cipher_data, &headers, false, &conn, &nt, UpdateType::CipherUpdate)?
// Prevent triggering cipher updates via WebSockets by settings UpdateType::None
// The user sessions are invalidated because all the ciphers were re-encrypted and thus triggering an update could cause issues.
update_cipher_from_data(&mut saved_cipher, cipher_data, &headers, false, &conn, &nt, UpdateType::None)?
}
// Update user data
@@ -329,7 +334,6 @@ fn post_rotatekey(data: JsonUpcase<KeyData>, headers: Headers, conn: DbConn, nt:
user.akey = data.Key;
user.private_key = Some(data.PrivateKey);
user.reset_security_stamp();
user.reset_stamp_exception();
user.save(&conn)
}
@@ -576,24 +580,45 @@ struct PasswordHintData {
#[post("/accounts/password-hint", data = "<data>")]
fn password_hint(data: JsonUpcase<PasswordHintData>, conn: DbConn) -> EmptyResult {
let data: PasswordHintData = data.into_inner().data;
let hint = match User::find_by_mail(&data.Email, &conn) {
Some(user) => user.password_hint,
None => return Ok(()),
};
if CONFIG.mail_enabled() {
mail::send_password_hint(&data.Email, hint)?;
} else if CONFIG.show_password_hint() {
if let Some(hint) = hint {
err!(format!("Your password hint is: {}", &hint));
} else {
err!("Sorry, you have no password hint...");
}
if !CONFIG.mail_enabled() && !CONFIG.show_password_hint() {
err!("This server is not configured to provide password hints.");
}
Ok(())
const NO_HINT: &str = "Sorry, you have no password hint...";
let data: PasswordHintData = data.into_inner().data;
let email = &data.Email;
match User::find_by_mail(email, &conn) {
None => {
// To prevent user enumeration, act as if the user exists.
if CONFIG.mail_enabled() {
// There is still a timing side channel here in that the code
// paths that send mail take noticeably longer than ones that
// don't. Add a randomized sleep to mitigate this somewhat.
use rand::{thread_rng, Rng};
let mut rng = thread_rng();
let base = 1000;
let delta: i32 = 100;
let sleep_ms = (base + rng.gen_range(-delta..=delta)) as u64;
std::thread::sleep(std::time::Duration::from_millis(sleep_ms));
Ok(())
} else {
err!(NO_HINT);
}
}
Some(user) => {
let hint: Option<String> = user.password_hint;
if CONFIG.mail_enabled() {
mail::send_password_hint(email, hint)?;
Ok(())
} else if let Some(hint) = hint {
err!(format!("Your password hint is: {}", hint));
} else {
err!(NO_HINT);
}
}
}
}
#[derive(Deserialize)]
+3 -3
View File
@@ -871,7 +871,7 @@ fn save_attachment(
Some(limit_kb) => {
let left = (limit_kb * 1024) - Attachment::size_by_user(user_uuid, conn) + size_adjust;
if left <= 0 {
err_discard!("Attachment size limit reached! Delete some files to open space", data)
err_discard!("Attachment storage limit reached! Delete some attachments to free up space", data)
}
Some(left as u64)
}
@@ -883,7 +883,7 @@ fn save_attachment(
Some(limit_kb) => {
let left = (limit_kb * 1024) - Attachment::size_by_org(org_uuid, conn) + size_adjust;
if left <= 0 {
err_discard!("Attachment size limit reached! Delete some files to open space", data)
err_discard!("Attachment storage limit reached! Delete some attachments to free up space", data)
}
Some(left as u64)
}
@@ -937,7 +937,7 @@ fn save_attachment(
return;
}
SaveResult::Partial(_, reason) => {
error = Some(format!("Attachment size limit exceeded with this file: {:?}", reason));
error = Some(format!("Attachment storage limit exceeded with this file: {:?}", reason));
return;
}
SaveResult::Error(e) => {
+24
View File
@@ -0,0 +1,24 @@
use rocket::Route;
use rocket_contrib::json::Json;
use crate::{api::JsonResult, auth::Headers, db::DbConn};
pub fn routes() -> Vec<Route> {
routes![get_contacts,]
}
/// This endpoint is expected to return at least something.
/// If we return an error message that will trigger error toasts for the user.
/// To prevent this we just return an empty json result with no Data.
/// When this feature is going to be implemented it also needs to return this empty Data
/// instead of throwing an error/4XX unless it really is an error.
#[get("/emergency-access/trusted")]
fn get_contacts(_headers: Headers, _conn: DbConn) -> JsonResult {
debug!("Emergency access is not supported.");
Ok(Json(json!({
"Data": [],
"Object": "list",
"ContinuationToken": null
})))
}
+2
View File
@@ -1,5 +1,6 @@
mod accounts;
mod ciphers;
mod emergency_access;
mod folders;
mod organizations;
mod sends;
@@ -15,6 +16,7 @@ pub fn routes() -> Vec<Route> {
let mut routes = Vec::new();
routes.append(&mut accounts::routes());
routes.append(&mut ciphers::routes());
routes.append(&mut emergency_access::routes());
routes.append(&mut folders::routes());
routes.append(&mut organizations::routes());
routes.append(&mut two_factor::routes());
+73 -1
View File
@@ -51,6 +51,7 @@ pub fn routes() -> Vec<Route> {
get_plans,
get_plans_tax_rates,
import,
post_org_keys,
]
}
@@ -61,6 +62,7 @@ struct OrgData {
CollectionName: String,
Key: String,
Name: String,
Keys: Option<OrgKeyData>,
#[serde(rename = "PlanType")]
_PlanType: NumberOrString, // Ignored, always use the same plan
}
@@ -78,6 +80,13 @@ struct NewCollectionData {
Name: String,
}
#[derive(Deserialize)]
#[allow(non_snake_case)]
struct OrgKeyData {
EncryptedPrivateKey: String,
PublicKey: String,
}
#[post("/organizations", data = "<data>")]
fn create_organization(headers: Headers, data: JsonUpcase<OrgData>, conn: DbConn) -> JsonResult {
if !CONFIG.is_org_creation_allowed(&headers.user.email) {
@@ -85,8 +94,14 @@ fn create_organization(headers: Headers, data: JsonUpcase<OrgData>, conn: DbConn
}
let data: OrgData = data.into_inner().data;
let (private_key, public_key) = if data.Keys.is_some() {
let keys: OrgKeyData = data.Keys.unwrap();
(Some(keys.EncryptedPrivateKey), Some(keys.PublicKey))
} else {
(None, None)
};
let org = Organization::new(data.Name, data.BillingEmail);
let org = Organization::new(data.Name, data.BillingEmail, private_key, public_key);
let mut user_org = UserOrganization::new(headers.user.uuid, org.uuid.clone());
let collection = Collection::new(org.uuid.clone(), data.CollectionName);
@@ -468,6 +483,32 @@ fn get_org_users(org_id: String, _headers: ManagerHeadersLoose, conn: DbConn) ->
}))
}
#[post("/organizations/<org_id>/keys", data = "<data>")]
fn post_org_keys(org_id: String, data: JsonUpcase<OrgKeyData>, _headers: AdminHeaders, conn: DbConn) -> JsonResult {
let data: OrgKeyData = data.into_inner().data;
let mut org = match Organization::find_by_uuid(&org_id, &conn) {
Some(organization) => {
if organization.private_key.is_some() && organization.public_key.is_some() {
err!("Organization Keys already exist")
}
organization
}
None => err!("Can't find organization details"),
};
org.private_key = Some(data.EncryptedPrivateKey);
org.public_key = Some(data.PublicKey);
org.save(&conn)?;
Ok(Json(json!({
"Object": "organizationKeys",
"PublicKey": org.public_key,
"PrivateKey": org.private_key,
})))
}
#[derive(Deserialize)]
#[allow(non_snake_case)]
struct CollectionData {
@@ -646,6 +687,19 @@ fn accept_invite(_org_id: String, _org_user_id: String, data: JsonUpcase<AcceptD
err!("User already accepted the invitation")
}
let user_twofactor_disabled = TwoFactor::find_by_user(&user_org.user_uuid, &conn).is_empty();
let policy = OrgPolicyType::TwoFactorAuthentication as i32;
let org_twofactor_policy_enabled =
match OrgPolicy::find_by_org_and_type(&user_org.org_uuid, policy, &conn) {
Some(p) => p.enabled,
None => false,
};
if org_twofactor_policy_enabled && user_twofactor_disabled {
err!("You cannot join this organization until you enable two-step login on your user account.")
}
user_org.status = UserOrgStatus::Accepted as i32;
user_org.save(&conn)?;
}
@@ -998,6 +1052,24 @@ fn put_policy(
None => err!("Invalid policy type"),
};
if pol_type_enum == OrgPolicyType::TwoFactorAuthentication && data.enabled {
let org_list = UserOrganization::find_by_org(&org_id, &conn);
for user_org in org_list.into_iter() {
let user_twofactor_disabled = TwoFactor::find_by_user(&user_org.user_uuid, &conn).is_empty();
if user_twofactor_disabled && user_org.atype < UserOrgType::Admin {
if CONFIG.mail_enabled() {
let org = Organization::find_by_uuid(&user_org.org_uuid, &conn).unwrap();
let user = User::find_by_uuid(&user_org.user_uuid, &conn).unwrap();
mail::send_2fa_removed_from_org(&user.email, &org.name)?;
}
user_org.delete(&conn)?;
}
}
}
let mut policy = match OrgPolicy::find_by_org_and_type(&org_id, pol_type, &conn) {
Some(p) => p,
None => OrgPolicy::new(org_id, pol_type_enum, "{}".to_string()),
+8 -7
View File
@@ -10,6 +10,7 @@ use crate::{
api::{ApiResult, EmptyResult, JsonResult, JsonUpcase, Notify, UpdateType},
auth::{Headers, Host},
db::{models::*, DbConn, DbPool},
util::SafeString,
CONFIG,
};
@@ -165,19 +166,19 @@ fn post_send_file(data: Data, content_type: &ContentType, headers: Headers, conn
let data = serde_json::from_str::<crate::util::UpCase<SendData>>(&buf)?;
enforce_disable_hide_email_policy(&data.data, &headers, &conn)?;
// Get the file length and add an extra 10% to avoid issues
const SIZE_110_MB: u64 = 115_343_360;
// Get the file length and add an extra 5% to avoid issues
const SIZE_525_MB: u64 = 550_502_400;
let size_limit = match CONFIG.user_attachment_limit() {
Some(0) => err!("File uploads are disabled"),
Some(limit_kb) => {
let left = (limit_kb * 1024) - Attachment::size_by_user(&headers.user.uuid, &conn);
if left <= 0 {
err!("Attachment size limit reached! Delete some files to open space")
err!("Attachment storage limit reached! Delete some attachments to free up space")
}
std::cmp::Ord::max(left as u64, SIZE_110_MB)
std::cmp::Ord::max(left as u64, SIZE_525_MB)
}
None => SIZE_110_MB,
None => SIZE_525_MB,
};
// Create the Send
@@ -205,7 +206,7 @@ fn post_send_file(data: Data, content_type: &ContentType, headers: Headers, conn
}
SaveResult::Partial(_, reason) => {
std::fs::remove_file(&file_path).ok();
err!(format!("Attachment size limit exceeded with this file: {:?}", reason));
err!(format!("Attachment storage limit exceeded with this file: {:?}", reason));
}
SaveResult::Error(e) => {
std::fs::remove_file(&file_path).ok();
@@ -335,7 +336,7 @@ fn post_access_file(
}
#[get("/sends/<send_id>/<file_id>?<t>")]
fn download_send(send_id: String, file_id: String, t: String) -> Option<NamedFile> {
fn download_send(send_id: SafeString, file_id: SafeString, t: String) -> Option<NamedFile> {
if let Ok(claims) = crate::auth::decode_send(&t) {
if claims.sub == format!("{}/{}", send_id, file_id) {
return NamedFile::open(Path::new(&CONFIG.sends_folder()).join(send_id).join(file_id)).ok();
+19 -4
View File
@@ -7,10 +7,8 @@ use crate::{
api::{JsonResult, JsonUpcase, NumberOrString, PasswordData},
auth::Headers,
crypto,
db::{
models::{TwoFactor, User},
DbConn,
},
db::{models::*, DbConn},
mail, CONFIG,
};
pub mod authenticator;
@@ -130,6 +128,23 @@ fn disable_twofactor(data: JsonUpcase<DisableTwoFactorData>, headers: Headers, c
twofactor.delete(&conn)?;
}
let twofactor_disabled = TwoFactor::find_by_user(&user.uuid, &conn).is_empty();
if twofactor_disabled {
let policy_type = OrgPolicyType::TwoFactorAuthentication;
let org_list = UserOrganization::find_by_user_and_policy(&user.uuid, policy_type, &conn);
for user_org in org_list.into_iter() {
if user_org.atype < UserOrgType::Admin {
if CONFIG.mail_enabled() {
let org = Organization::find_by_uuid(&user_org.org_uuid, &conn).unwrap();
mail::send_2fa_removed_from_org(&user.email, &org.name)?;
}
user_org.delete(&conn)?;
}
}
}
Ok(Json(json!({
"Enabled": false,
"Type": type_,
+7 -15
View File
@@ -51,19 +51,12 @@ impl webauthn_rs::WebauthnConfig for WebauthnConfig {
fn get_relying_party_id(&self) -> &str {
&self.rpid
}
}
impl webauthn_rs::WebauthnConfig for &WebauthnConfig {
fn get_relying_party_name(&self) -> &str {
&self.url
}
fn get_origin(&self) -> &str {
&self.url
}
fn get_relying_party_id(&self) -> &str {
&self.rpid
/// We have WebAuthn configured to discourage user verification
/// if we leave this enabled, it will cause verification issues when a keys send UV=1.
/// Upstream (the library they use) ignores this when set to discouraged, so we should too.
fn get_require_uv_consistency(&self) -> bool {
false
}
}
@@ -289,15 +282,14 @@ fn delete_webauthn(data: JsonUpcase<DeleteU2FData>, headers: Headers, conn: DbCo
err!("Invalid password");
}
let type_ = TwoFactorType::Webauthn as i32;
let mut tf = match TwoFactor::find_by_user_and_type(&headers.user.uuid, type_, &conn) {
let mut tf = match TwoFactor::find_by_user_and_type(&headers.user.uuid, TwoFactorType::Webauthn as i32, &conn) {
Some(tf) => tf,
None => err!("Webauthn data not found!"),
};
let mut data: Vec<WebauthnRegistration> = serde_json::from_str(&tf.data)?;
let item_pos = match data.iter().position(|r| r.id != id) {
let item_pos = match data.iter().position(|r| r.id == id) {
Some(p) => p,
None => err!("Webauthn entry not found"),
};
+4 -6
View File
@@ -408,12 +408,10 @@ pub fn start_notification_server() -> WebSocketUsers {
if CONFIG.websocket_enabled() {
thread::spawn(move || {
let settings = ws::Settings {
max_connections: 500,
queue_size: 2,
panic_on_internal: false,
..Default::default()
};
let mut settings = ws::Settings::default();
settings.max_connections = 500;
settings.queue_size = 2;
settings.panic_on_internal = false;
ws::Builder::new()
.with_settings(settings)

Some files were not shown because too many files have changed in this diff Show More