mirror of
https://github.com/dani-garcia/vaultwarden.git
synced 2026-05-31 01:46:28 +00:00
Support for webauthn and u2f->webauthn migrations
This commit is contained in:
Generated
+111
-66
File diff suppressed because it is too large
Load Diff
+13
-9
@@ -28,8 +28,8 @@ syslog = "4.0.1"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# Web framework for nightly with a focus on ease-of-use, expressibility, and speed.
|
# Web framework for nightly with a focus on ease-of-use, expressibility, and speed.
|
||||||
rocket = { version = "0.5.0-dev", features = ["tls"], default-features = false }
|
rocket = { version = "=0.5.0-dev", features = ["tls"], default-features = false }
|
||||||
rocket_contrib = "0.5.0-dev"
|
rocket_contrib = "=0.5.0-dev"
|
||||||
|
|
||||||
# HTTP client
|
# HTTP client
|
||||||
reqwest = { version = "0.11.3", features = ["blocking", "json", "gzip", "brotli", "socks", "cookies"] }
|
reqwest = { version = "0.11.3", features = ["blocking", "json", "gzip", "brotli", "socks", "cookies"] }
|
||||||
@@ -41,7 +41,7 @@ bytes = "1.0.1"
|
|||||||
url = "2.2.2"
|
url = "2.2.2"
|
||||||
|
|
||||||
# multipart/form-data support
|
# multipart/form-data support
|
||||||
multipart = { version = "0.17.1", features = ["server"], default-features = false }
|
multipart = { version = "0.18.0", features = ["server"], default-features = false }
|
||||||
|
|
||||||
# WebSockets library
|
# WebSockets library
|
||||||
ws = { version = "0.10.0", package = "parity-ws" }
|
ws = { version = "0.10.0", package = "parity-ws" }
|
||||||
@@ -77,7 +77,7 @@ uuid = { version = "0.8.2", features = ["v4"] }
|
|||||||
# Date and time libraries
|
# Date and time libraries
|
||||||
chrono = { version = "0.4.19", features = ["serde"] }
|
chrono = { version = "0.4.19", features = ["serde"] }
|
||||||
chrono-tz = "0.5.3"
|
chrono-tz = "0.5.3"
|
||||||
time = "0.2.26"
|
time = "0.2.27"
|
||||||
|
|
||||||
# Job scheduler
|
# Job scheduler
|
||||||
job_scheduler = "1.2.1"
|
job_scheduler = "1.2.1"
|
||||||
@@ -93,6 +93,7 @@ jsonwebtoken = "7.2.0"
|
|||||||
|
|
||||||
# U2F library
|
# U2F library
|
||||||
u2f = "0.2.0"
|
u2f = "0.2.0"
|
||||||
|
webauthn-rs = "0.3.0-alpha.7"
|
||||||
|
|
||||||
# Yubico Library
|
# Yubico Library
|
||||||
yubico = { version = "0.10.0", features = ["online-tokio"], default-features = false }
|
yubico = { version = "0.10.0", features = ["online-tokio"], default-features = false }
|
||||||
@@ -101,7 +102,7 @@ yubico = { version = "0.10.0", features = ["online-tokio"], default-features = f
|
|||||||
dotenv = { version = "0.15.0", default-features = false }
|
dotenv = { version = "0.15.0", default-features = false }
|
||||||
|
|
||||||
# Lazy initialization
|
# Lazy initialization
|
||||||
once_cell = "1.7.2"
|
once_cell = "1.8.0"
|
||||||
|
|
||||||
# Numerical libraries
|
# Numerical libraries
|
||||||
num-traits = "0.2.14"
|
num-traits = "0.2.14"
|
||||||
@@ -109,10 +110,10 @@ num-derive = "0.3.3"
|
|||||||
|
|
||||||
# Email libraries
|
# Email libraries
|
||||||
tracing = { version = "0.1.26", features = ["log"] } # Needed to have lettre trace logging used when SMTP_DEBUG is enabled.
|
tracing = { version = "0.1.26", features = ["log"] } # Needed to have lettre trace logging used when SMTP_DEBUG is enabled.
|
||||||
lettre = { version = "0.10.0-rc.1", features = ["smtp-transport", "builder", "serde", "native-tls", "hostname", "tracing"], default-features = false }
|
lettre = { version = "0.10.0-rc.3", features = ["smtp-transport", "builder", "serde", "native-tls", "hostname", "tracing"], default-features = false }
|
||||||
|
|
||||||
# Template library
|
# Template library
|
||||||
handlebars = { version = "3.5.5", features = ["dir_source"] }
|
handlebars = { version = "4.0.0", features = ["dir_source"] }
|
||||||
|
|
||||||
# For favicon extraction from main website
|
# For favicon extraction from main website
|
||||||
html5ever = "0.25.1"
|
html5ever = "0.25.1"
|
||||||
@@ -129,10 +130,10 @@ percent-encoding = "2.1.0"
|
|||||||
idna = "0.2.3"
|
idna = "0.2.3"
|
||||||
|
|
||||||
# CLI argument parsing
|
# CLI argument parsing
|
||||||
pico-args = "0.4.1"
|
pico-args = "0.4.2"
|
||||||
|
|
||||||
# Logging panics to logfile instead stderr only
|
# Logging panics to logfile instead stderr only
|
||||||
backtrace = "0.3.59"
|
backtrace = "0.3.60"
|
||||||
|
|
||||||
# Macro ident concatenation
|
# Macro ident concatenation
|
||||||
paste = "1.0.5"
|
paste = "1.0.5"
|
||||||
@@ -151,3 +152,6 @@ data-url = { git = 'https://github.com/servo/rust-url', package="data-url", rev
|
|||||||
# In particular, `cron` has since implemented parsing of some common syntax
|
# In particular, `cron` has since implemented parsing of some common syntax
|
||||||
# that wasn't previously supported (https://github.com/zslayton/cron/pull/64).
|
# that wasn't previously supported (https://github.com/zslayton/cron/pull/64).
|
||||||
job_scheduler = { git = 'https://github.com/jjlin/job_scheduler', rev = 'ee023418dbba2bfe1e30a5fd7d937f9e33739806' }
|
job_scheduler = { git = 'https://github.com/jjlin/job_scheduler', rev = 'ee023418dbba2bfe1e30a5fd7d937f9e33739806' }
|
||||||
|
|
||||||
|
# Add support for U2F appid extension compatibility
|
||||||
|
webauthn-rs = { git = 'https://github.com/dani-garcia/webauthn-rs', rev = '70b458f246d207e5b6333ada9f1d5794c5e01da1' }
|
||||||
|
|||||||
@@ -44,8 +44,8 @@
|
|||||||
# https://docs.docker.com/develop/develop-images/multistage-build/
|
# https://docs.docker.com/develop/develop-images/multistage-build/
|
||||||
# https://whitfin.io/speeding-up-rust-docker-builds/
|
# https://whitfin.io/speeding-up-rust-docker-builds/
|
||||||
####################### VAULT BUILD IMAGE #######################
|
####################### VAULT BUILD IMAGE #######################
|
||||||
{% set vault_version = "2.19.0d" %}
|
{% set vault_version = "2.20.4" %}
|
||||||
{% set vault_image_digest = "sha256:a7bd6bc4db33bd45f723c4b1ac90918b7f80204560683cfc8efd9efd03a9b233" %}
|
{% set vault_image_digest = "sha256:810919341388a50d3a88225ce234333f72eb80382953997e9fd5590cca829e1b" %}
|
||||||
# The web-vault digest specifies a particular web-vault build on Docker Hub.
|
# The web-vault digest specifies a particular web-vault build on Docker Hub.
|
||||||
# Using the digest instead of the tag name provides better security,
|
# 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
|
# as the digest of an image is immutable, whereas a tag name can later
|
||||||
|
|||||||
@@ -14,15 +14,15 @@
|
|||||||
# - From https://hub.docker.com/r/vaultwarden/web-vault/tags,
|
# - 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.
|
# click the tag name to view the digest of the image it currently points to.
|
||||||
# - From the command line:
|
# - From the command line:
|
||||||
# $ docker pull vaultwarden/web-vault:v2.19.0d
|
# $ docker pull vaultwarden/web-vault:v2.20.4
|
||||||
# $ docker image inspect --format "{{.RepoDigests}}" vaultwarden/web-vault:v2.19.0d
|
# $ docker image inspect --format "{{.RepoDigests}}" vaultwarden/web-vault:v2.20.4
|
||||||
# [vaultwarden/web-vault@sha256:a7bd6bc4db33bd45f723c4b1ac90918b7f80204560683cfc8efd9efd03a9b233]
|
# [vaultwarden/web-vault@sha256:810919341388a50d3a88225ce234333f72eb80382953997e9fd5590cca829e1b]
|
||||||
#
|
#
|
||||||
# - Conversely, to get the tag name from the digest:
|
# - Conversely, to get the tag name from the digest:
|
||||||
# $ docker image inspect --format "{{.RepoTags}}" vaultwarden/web-vault@sha256:a7bd6bc4db33bd45f723c4b1ac90918b7f80204560683cfc8efd9efd03a9b233
|
# $ docker image inspect --format "{{.RepoTags}}" vaultwarden/web-vault@sha256:810919341388a50d3a88225ce234333f72eb80382953997e9fd5590cca829e1b
|
||||||
# [vaultwarden/web-vault:v2.19.0d]
|
# [vaultwarden/web-vault:v2.20.4]
|
||||||
#
|
#
|
||||||
FROM vaultwarden/web-vault@sha256:a7bd6bc4db33bd45f723c4b1ac90918b7f80204560683cfc8efd9efd03a9b233 as vault
|
FROM vaultwarden/web-vault@sha256:810919341388a50d3a88225ce234333f72eb80382953997e9fd5590cca829e1b as vault
|
||||||
|
|
||||||
########################## BUILD IMAGE ##########################
|
########################## BUILD IMAGE ##########################
|
||||||
FROM rust:1.51 as build
|
FROM rust:1.51 as build
|
||||||
|
|||||||
@@ -14,15 +14,15 @@
|
|||||||
# - From https://hub.docker.com/r/vaultwarden/web-vault/tags,
|
# - 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.
|
# click the tag name to view the digest of the image it currently points to.
|
||||||
# - From the command line:
|
# - From the command line:
|
||||||
# $ docker pull vaultwarden/web-vault:v2.19.0d
|
# $ docker pull vaultwarden/web-vault:v2.20.4
|
||||||
# $ docker image inspect --format "{{.RepoDigests}}" vaultwarden/web-vault:v2.19.0d
|
# $ docker image inspect --format "{{.RepoDigests}}" vaultwarden/web-vault:v2.20.4
|
||||||
# [vaultwarden/web-vault@sha256:a7bd6bc4db33bd45f723c4b1ac90918b7f80204560683cfc8efd9efd03a9b233]
|
# [vaultwarden/web-vault@sha256:810919341388a50d3a88225ce234333f72eb80382953997e9fd5590cca829e1b]
|
||||||
#
|
#
|
||||||
# - Conversely, to get the tag name from the digest:
|
# - Conversely, to get the tag name from the digest:
|
||||||
# $ docker image inspect --format "{{.RepoTags}}" vaultwarden/web-vault@sha256:a7bd6bc4db33bd45f723c4b1ac90918b7f80204560683cfc8efd9efd03a9b233
|
# $ docker image inspect --format "{{.RepoTags}}" vaultwarden/web-vault@sha256:810919341388a50d3a88225ce234333f72eb80382953997e9fd5590cca829e1b
|
||||||
# [vaultwarden/web-vault:v2.19.0d]
|
# [vaultwarden/web-vault:v2.20.4]
|
||||||
#
|
#
|
||||||
FROM vaultwarden/web-vault@sha256:a7bd6bc4db33bd45f723c4b1ac90918b7f80204560683cfc8efd9efd03a9b233 as vault
|
FROM vaultwarden/web-vault@sha256:810919341388a50d3a88225ce234333f72eb80382953997e9fd5590cca829e1b as vault
|
||||||
|
|
||||||
########################## BUILD IMAGE ##########################
|
########################## BUILD IMAGE ##########################
|
||||||
FROM clux/muslrust:nightly-2021-04-14 as build
|
FROM clux/muslrust:nightly-2021-04-14 as build
|
||||||
|
|||||||
@@ -14,15 +14,15 @@
|
|||||||
# - From https://hub.docker.com/r/vaultwarden/web-vault/tags,
|
# - 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.
|
# click the tag name to view the digest of the image it currently points to.
|
||||||
# - From the command line:
|
# - From the command line:
|
||||||
# $ docker pull vaultwarden/web-vault:v2.19.0d
|
# $ docker pull vaultwarden/web-vault:v2.20.4
|
||||||
# $ docker image inspect --format "{{.RepoDigests}}" vaultwarden/web-vault:v2.19.0d
|
# $ docker image inspect --format "{{.RepoDigests}}" vaultwarden/web-vault:v2.20.4
|
||||||
# [vaultwarden/web-vault@sha256:a7bd6bc4db33bd45f723c4b1ac90918b7f80204560683cfc8efd9efd03a9b233]
|
# [vaultwarden/web-vault@sha256:810919341388a50d3a88225ce234333f72eb80382953997e9fd5590cca829e1b]
|
||||||
#
|
#
|
||||||
# - Conversely, to get the tag name from the digest:
|
# - Conversely, to get the tag name from the digest:
|
||||||
# $ docker image inspect --format "{{.RepoTags}}" vaultwarden/web-vault@sha256:a7bd6bc4db33bd45f723c4b1ac90918b7f80204560683cfc8efd9efd03a9b233
|
# $ docker image inspect --format "{{.RepoTags}}" vaultwarden/web-vault@sha256:810919341388a50d3a88225ce234333f72eb80382953997e9fd5590cca829e1b
|
||||||
# [vaultwarden/web-vault:v2.19.0d]
|
# [vaultwarden/web-vault:v2.20.4]
|
||||||
#
|
#
|
||||||
FROM vaultwarden/web-vault@sha256:a7bd6bc4db33bd45f723c4b1ac90918b7f80204560683cfc8efd9efd03a9b233 as vault
|
FROM vaultwarden/web-vault@sha256:810919341388a50d3a88225ce234333f72eb80382953997e9fd5590cca829e1b as vault
|
||||||
|
|
||||||
########################## BUILD IMAGE ##########################
|
########################## BUILD IMAGE ##########################
|
||||||
FROM rust:1.51 as build
|
FROM rust:1.51 as build
|
||||||
|
|||||||
@@ -14,15 +14,15 @@
|
|||||||
# - From https://hub.docker.com/r/vaultwarden/web-vault/tags,
|
# - 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.
|
# click the tag name to view the digest of the image it currently points to.
|
||||||
# - From the command line:
|
# - From the command line:
|
||||||
# $ docker pull vaultwarden/web-vault:v2.19.0d
|
# $ docker pull vaultwarden/web-vault:v2.20.4
|
||||||
# $ docker image inspect --format "{{.RepoDigests}}" vaultwarden/web-vault:v2.19.0d
|
# $ docker image inspect --format "{{.RepoDigests}}" vaultwarden/web-vault:v2.20.4
|
||||||
# [vaultwarden/web-vault@sha256:a7bd6bc4db33bd45f723c4b1ac90918b7f80204560683cfc8efd9efd03a9b233]
|
# [vaultwarden/web-vault@sha256:810919341388a50d3a88225ce234333f72eb80382953997e9fd5590cca829e1b]
|
||||||
#
|
#
|
||||||
# - Conversely, to get the tag name from the digest:
|
# - Conversely, to get the tag name from the digest:
|
||||||
# $ docker image inspect --format "{{.RepoTags}}" vaultwarden/web-vault@sha256:a7bd6bc4db33bd45f723c4b1ac90918b7f80204560683cfc8efd9efd03a9b233
|
# $ docker image inspect --format "{{.RepoTags}}" vaultwarden/web-vault@sha256:810919341388a50d3a88225ce234333f72eb80382953997e9fd5590cca829e1b
|
||||||
# [vaultwarden/web-vault:v2.19.0d]
|
# [vaultwarden/web-vault:v2.20.4]
|
||||||
#
|
#
|
||||||
FROM vaultwarden/web-vault@sha256:a7bd6bc4db33bd45f723c4b1ac90918b7f80204560683cfc8efd9efd03a9b233 as vault
|
FROM vaultwarden/web-vault@sha256:810919341388a50d3a88225ce234333f72eb80382953997e9fd5590cca829e1b as vault
|
||||||
|
|
||||||
########################## BUILD IMAGE ##########################
|
########################## BUILD IMAGE ##########################
|
||||||
FROM rust:1.51 as build
|
FROM rust:1.51 as build
|
||||||
|
|||||||
@@ -14,15 +14,15 @@
|
|||||||
# - From https://hub.docker.com/r/vaultwarden/web-vault/tags,
|
# - 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.
|
# click the tag name to view the digest of the image it currently points to.
|
||||||
# - From the command line:
|
# - From the command line:
|
||||||
# $ docker pull vaultwarden/web-vault:v2.19.0d
|
# $ docker pull vaultwarden/web-vault:v2.20.4
|
||||||
# $ docker image inspect --format "{{.RepoDigests}}" vaultwarden/web-vault:v2.19.0d
|
# $ docker image inspect --format "{{.RepoDigests}}" vaultwarden/web-vault:v2.20.4
|
||||||
# [vaultwarden/web-vault@sha256:a7bd6bc4db33bd45f723c4b1ac90918b7f80204560683cfc8efd9efd03a9b233]
|
# [vaultwarden/web-vault@sha256:810919341388a50d3a88225ce234333f72eb80382953997e9fd5590cca829e1b]
|
||||||
#
|
#
|
||||||
# - Conversely, to get the tag name from the digest:
|
# - Conversely, to get the tag name from the digest:
|
||||||
# $ docker image inspect --format "{{.RepoTags}}" vaultwarden/web-vault@sha256:a7bd6bc4db33bd45f723c4b1ac90918b7f80204560683cfc8efd9efd03a9b233
|
# $ docker image inspect --format "{{.RepoTags}}" vaultwarden/web-vault@sha256:810919341388a50d3a88225ce234333f72eb80382953997e9fd5590cca829e1b
|
||||||
# [vaultwarden/web-vault:v2.19.0d]
|
# [vaultwarden/web-vault:v2.20.4]
|
||||||
#
|
#
|
||||||
FROM vaultwarden/web-vault@sha256:a7bd6bc4db33bd45f723c4b1ac90918b7f80204560683cfc8efd9efd03a9b233 as vault
|
FROM vaultwarden/web-vault@sha256:810919341388a50d3a88225ce234333f72eb80382953997e9fd5590cca829e1b as vault
|
||||||
|
|
||||||
########################## BUILD IMAGE ##########################
|
########################## BUILD IMAGE ##########################
|
||||||
FROM rust:1.51 as build
|
FROM rust:1.51 as build
|
||||||
|
|||||||
@@ -14,15 +14,15 @@
|
|||||||
# - From https://hub.docker.com/r/vaultwarden/web-vault/tags,
|
# - 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.
|
# click the tag name to view the digest of the image it currently points to.
|
||||||
# - From the command line:
|
# - From the command line:
|
||||||
# $ docker pull vaultwarden/web-vault:v2.19.0d
|
# $ docker pull vaultwarden/web-vault:v2.20.4
|
||||||
# $ docker image inspect --format "{{.RepoDigests}}" vaultwarden/web-vault:v2.19.0d
|
# $ docker image inspect --format "{{.RepoDigests}}" vaultwarden/web-vault:v2.20.4
|
||||||
# [vaultwarden/web-vault@sha256:a7bd6bc4db33bd45f723c4b1ac90918b7f80204560683cfc8efd9efd03a9b233]
|
# [vaultwarden/web-vault@sha256:810919341388a50d3a88225ce234333f72eb80382953997e9fd5590cca829e1b]
|
||||||
#
|
#
|
||||||
# - Conversely, to get the tag name from the digest:
|
# - Conversely, to get the tag name from the digest:
|
||||||
# $ docker image inspect --format "{{.RepoTags}}" vaultwarden/web-vault@sha256:a7bd6bc4db33bd45f723c4b1ac90918b7f80204560683cfc8efd9efd03a9b233
|
# $ docker image inspect --format "{{.RepoTags}}" vaultwarden/web-vault@sha256:810919341388a50d3a88225ce234333f72eb80382953997e9fd5590cca829e1b
|
||||||
# [vaultwarden/web-vault:v2.19.0d]
|
# [vaultwarden/web-vault:v2.20.4]
|
||||||
#
|
#
|
||||||
FROM vaultwarden/web-vault@sha256:a7bd6bc4db33bd45f723c4b1ac90918b7f80204560683cfc8efd9efd03a9b233 as vault
|
FROM vaultwarden/web-vault@sha256:810919341388a50d3a88225ce234333f72eb80382953997e9fd5590cca829e1b as vault
|
||||||
|
|
||||||
########################## BUILD IMAGE ##########################
|
########################## BUILD IMAGE ##########################
|
||||||
FROM messense/rust-musl-cross:armv7-musleabihf as build
|
FROM messense/rust-musl-cross:armv7-musleabihf as build
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ pub mod authenticator;
|
|||||||
pub mod duo;
|
pub mod duo;
|
||||||
pub mod email;
|
pub mod email;
|
||||||
pub mod u2f;
|
pub mod u2f;
|
||||||
|
pub mod webauthn;
|
||||||
pub mod yubikey;
|
pub mod yubikey;
|
||||||
|
|
||||||
pub fn routes() -> Vec<Route> {
|
pub fn routes() -> Vec<Route> {
|
||||||
@@ -26,6 +27,7 @@ pub fn routes() -> Vec<Route> {
|
|||||||
routes.append(&mut duo::routes());
|
routes.append(&mut duo::routes());
|
||||||
routes.append(&mut email::routes());
|
routes.append(&mut email::routes());
|
||||||
routes.append(&mut u2f::routes());
|
routes.append(&mut u2f::routes());
|
||||||
|
routes.append(&mut webauthn::routes());
|
||||||
routes.append(&mut yubikey::routes());
|
routes.append(&mut yubikey::routes());
|
||||||
|
|
||||||
routes
|
routes
|
||||||
|
|||||||
@@ -94,13 +94,14 @@ struct RegistrationDef {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
struct U2FRegistration {
|
pub struct U2FRegistration {
|
||||||
id: i32,
|
pub id: i32,
|
||||||
name: String,
|
pub name: String,
|
||||||
#[serde(with = "RegistrationDef")]
|
#[serde(with = "RegistrationDef")]
|
||||||
reg: Registration,
|
pub reg: Registration,
|
||||||
counter: u32,
|
pub counter: u32,
|
||||||
compromised: bool,
|
compromised: bool,
|
||||||
|
pub migrated: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl U2FRegistration {
|
impl U2FRegistration {
|
||||||
@@ -168,6 +169,7 @@ fn activate_u2f(data: JsonUpcase<EnableU2FData>, headers: Headers, conn: DbConn)
|
|||||||
reg: registration,
|
reg: registration,
|
||||||
compromised: false,
|
compromised: false,
|
||||||
counter: 0,
|
counter: 0,
|
||||||
|
migrated: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut regs = get_u2f_registrations(&user.uuid, &conn)?.1;
|
let mut regs = get_u2f_registrations(&user.uuid, &conn)?.1;
|
||||||
@@ -273,6 +275,7 @@ fn get_u2f_registrations(user_uuid: &str, conn: &DbConn) -> Result<(bool, Vec<U2
|
|||||||
reg: old_regs.remove(0),
|
reg: old_regs.remove(0),
|
||||||
compromised: false,
|
compromised: false,
|
||||||
counter: 0,
|
counter: 0,
|
||||||
|
migrated: None,
|
||||||
}];
|
}];
|
||||||
|
|
||||||
// Save new format
|
// Save new format
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -240,6 +240,7 @@ fn twofactor_auth(
|
|||||||
_tf::authenticator::validate_totp_code_str(user_uuid, twofactor_code, &selected_data?, ip, conn)?
|
_tf::authenticator::validate_totp_code_str(user_uuid, twofactor_code, &selected_data?, ip, conn)?
|
||||||
}
|
}
|
||||||
Some(TwoFactorType::U2f) => _tf::u2f::validate_u2f_login(user_uuid, twofactor_code, conn)?,
|
Some(TwoFactorType::U2f) => _tf::u2f::validate_u2f_login(user_uuid, twofactor_code, conn)?,
|
||||||
|
Some(TwoFactorType::Webauthn) => _tf::webauthn::validate_webauthn_login(user_uuid, twofactor_code, conn)?,
|
||||||
Some(TwoFactorType::YubiKey) => _tf::yubikey::validate_yubikey_login(twofactor_code, &selected_data?)?,
|
Some(TwoFactorType::YubiKey) => _tf::yubikey::validate_yubikey_login(twofactor_code, &selected_data?)?,
|
||||||
Some(TwoFactorType::Duo) => {
|
Some(TwoFactorType::Duo) => {
|
||||||
_tf::duo::validate_duo_login(data.username.as_ref().unwrap(), twofactor_code, conn)?
|
_tf::duo::validate_duo_login(data.username.as_ref().unwrap(), twofactor_code, conn)?
|
||||||
@@ -309,6 +310,11 @@ fn _json_err_twofactor(providers: &[i32], user_uuid: &str, conn: &DbConn) -> Api
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Some(TwoFactorType::Webauthn) if CONFIG.domain_set() => {
|
||||||
|
let request = two_factor::webauthn::generate_webauthn_login(user_uuid, conn)?;
|
||||||
|
result["TwoFactorProviders2"][provider.to_string()] = request.0;
|
||||||
|
}
|
||||||
|
|
||||||
Some(TwoFactorType::Duo) => {
|
Some(TwoFactorType::Duo) => {
|
||||||
let email = match User::find_by_uuid(user_uuid, &conn) {
|
let email = match User::find_by_uuid(user_uuid, &conn) {
|
||||||
Some(u) => u.email,
|
Some(u) => u.email,
|
||||||
|
|||||||
+2
-2
@@ -51,10 +51,10 @@ impl NumberOrString {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn into_i32(self) -> ApiResult<i32> {
|
fn into_i32(&self) -> ApiResult<i32> {
|
||||||
use std::num::ParseIntError as PIE;
|
use std::num::ParseIntError as PIE;
|
||||||
match self {
|
match self {
|
||||||
NumberOrString::Number(n) => Ok(n),
|
NumberOrString::Number(n) => Ok(*n),
|
||||||
NumberOrString::String(s) => {
|
NumberOrString::String(s) => {
|
||||||
s.parse().map_err(|e: PIE| crate::Error::new("Can't convert to number", e.to_string()))
|
s.parse().map_err(|e: PIE| crate::Error::new("Can't convert to number", e.to_string()))
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -114,7 +114,7 @@ macro_rules! db_run {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Different code for each db
|
// Different code for each db
|
||||||
( $conn:ident: $( $($db:ident),+ $body:block )+ ) => {
|
( $conn:ident: $( $($db:ident),+ $body:block )+ ) => {{
|
||||||
#[allow(unused)] use diesel::prelude::*;
|
#[allow(unused)] use diesel::prelude::*;
|
||||||
match $conn {
|
match $conn {
|
||||||
$($(
|
$($(
|
||||||
@@ -128,7 +128,7 @@ macro_rules! db_run {
|
|||||||
$body
|
$body
|
||||||
},
|
},
|
||||||
)+)+
|
)+)+
|
||||||
}
|
}}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Same for all dbs
|
// Same for all dbs
|
||||||
|
|||||||
@@ -31,11 +31,14 @@ pub enum TwoFactorType {
|
|||||||
U2f = 4,
|
U2f = 4,
|
||||||
Remember = 5,
|
Remember = 5,
|
||||||
OrganizationDuo = 6,
|
OrganizationDuo = 6,
|
||||||
|
Webauthn = 7,
|
||||||
|
|
||||||
// These are implementation details
|
// These are implementation details
|
||||||
U2fRegisterChallenge = 1000,
|
U2fRegisterChallenge = 1000,
|
||||||
U2fLoginChallenge = 1001,
|
U2fLoginChallenge = 1001,
|
||||||
EmailVerificationChallenge = 1002,
|
EmailVerificationChallenge = 1002,
|
||||||
|
WebauthnRegisterChallenge = 1003,
|
||||||
|
WebauthnLoginChallenge = 1004,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Local methods
|
/// Local methods
|
||||||
@@ -146,4 +149,73 @@ impl TwoFactor {
|
|||||||
.map_res("Error deleting twofactors")
|
.map_res("Error deleting twofactors")
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn migrate_u2f_to_webauthn(conn: &DbConn) -> EmptyResult {
|
||||||
|
let u2f_factors = db_run! { conn: {
|
||||||
|
twofactor::table
|
||||||
|
.filter(twofactor::atype.eq(TwoFactorType::U2f as i32))
|
||||||
|
.load::<TwoFactorDb>(conn)
|
||||||
|
.expect("Error loading twofactor")
|
||||||
|
.from_db()
|
||||||
|
}};
|
||||||
|
|
||||||
|
use crate::api::core::two_factor::u2f::U2FRegistration;
|
||||||
|
use crate::api::core::two_factor::webauthn::{get_webauthn_registrations, WebauthnRegistration};
|
||||||
|
use std::convert::TryInto;
|
||||||
|
use webauthn_rs::proto::*;
|
||||||
|
|
||||||
|
for mut u2f in u2f_factors {
|
||||||
|
let mut regs: Vec<U2FRegistration> = serde_json::from_str(&u2f.data)?;
|
||||||
|
// If there are no registrations or they are migrated (we do the migration in batch so we can consider them all migrated when the first one is)
|
||||||
|
if regs.is_empty() || regs[0].migrated == Some(true) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let (_, mut webauthn_regs) = get_webauthn_registrations(&u2f.user_uuid, &conn)?;
|
||||||
|
|
||||||
|
// If the user already has webauthn registrations saved, don't overwrite them
|
||||||
|
if !webauthn_regs.is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for reg in &mut regs {
|
||||||
|
let x: [u8; 32] = reg.reg.pub_key[1..33].try_into().unwrap();
|
||||||
|
let y: [u8; 32] = reg.reg.pub_key[33..65].try_into().unwrap();
|
||||||
|
|
||||||
|
let key = COSEKey {
|
||||||
|
type_: COSEAlgorithm::ES256,
|
||||||
|
key: COSEKeyType::EC_EC2(COSEEC2Key {
|
||||||
|
curve: ECDSACurve::SECP256R1,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
let new_reg = WebauthnRegistration {
|
||||||
|
id: reg.id,
|
||||||
|
migrated: true,
|
||||||
|
name: reg.name.clone(),
|
||||||
|
credential: Credential {
|
||||||
|
counter: reg.counter,
|
||||||
|
verified: false,
|
||||||
|
cred: key,
|
||||||
|
cred_id: reg.reg.key_handle.clone(),
|
||||||
|
registration_policy: UserVerificationPolicy::Discouraged,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
webauthn_regs.push(new_reg);
|
||||||
|
|
||||||
|
reg.migrated = Some(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
u2f.data = serde_json::to_string(®s)?;
|
||||||
|
u2f.save(&conn)?;
|
||||||
|
|
||||||
|
TwoFactor::new(u2f.user_uuid.clone(), TwoFactorType::Webauthn, serde_json::to_string(&webauthn_regs)?)
|
||||||
|
.save(&conn)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-5
@@ -39,19 +39,18 @@ use diesel::ConnectionError as DieselConErr;
|
|||||||
use diesel_migrations::RunMigrationsError as DieselMigErr;
|
use diesel_migrations::RunMigrationsError as DieselMigErr;
|
||||||
use handlebars::RenderError as HbErr;
|
use handlebars::RenderError as HbErr;
|
||||||
use jsonwebtoken::errors::Error as JwtErr;
|
use jsonwebtoken::errors::Error as JwtErr;
|
||||||
|
use lettre::address::AddressError as AddrErr;
|
||||||
|
use lettre::error::Error as LettreErr;
|
||||||
|
use lettre::transport::smtp::Error as SmtpErr;
|
||||||
use regex::Error as RegexErr;
|
use regex::Error as RegexErr;
|
||||||
use reqwest::Error as ReqErr;
|
use reqwest::Error as ReqErr;
|
||||||
use serde_json::{Error as SerdeErr, Value};
|
use serde_json::{Error as SerdeErr, Value};
|
||||||
use std::io::Error as IoErr;
|
use std::io::Error as IoErr;
|
||||||
|
|
||||||
use std::time::SystemTimeError as TimeErr;
|
use std::time::SystemTimeError as TimeErr;
|
||||||
use u2f::u2ferror::U2fError as U2fErr;
|
use u2f::u2ferror::U2fError as U2fErr;
|
||||||
|
use webauthn_rs::error::WebauthnError as WebauthnErr;
|
||||||
use yubico::yubicoerror::YubicoError as YubiErr;
|
use yubico::yubicoerror::YubicoError as YubiErr;
|
||||||
|
|
||||||
use lettre::address::AddressError as AddrErr;
|
|
||||||
use lettre::error::Error as LettreErr;
|
|
||||||
use lettre::transport::smtp::Error as SmtpErr;
|
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct Empty {}
|
pub struct Empty {}
|
||||||
|
|
||||||
@@ -86,6 +85,7 @@ make_error! {
|
|||||||
|
|
||||||
DieselConError(DieselConErr): _has_source, _api_error,
|
DieselConError(DieselConErr): _has_source, _api_error,
|
||||||
DieselMigError(DieselMigErr): _has_source, _api_error,
|
DieselMigError(DieselMigErr): _has_source, _api_error,
|
||||||
|
WebauthnError(WebauthnErr): _has_source, _api_error,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Debug for Error {
|
impl std::fmt::Debug for Error {
|
||||||
|
|||||||
@@ -60,6 +60,8 @@ fn main() {
|
|||||||
|
|
||||||
let pool = create_db_pool();
|
let pool = create_db_pool();
|
||||||
schedule_jobs(pool.clone());
|
schedule_jobs(pool.clone());
|
||||||
|
crate::db::models::TwoFactor::migrate_u2f_to_webauthn(&pool.get().unwrap()).unwrap();
|
||||||
|
|
||||||
launch_rocket(pool, extra_debug); // Blocks until program termination.
|
launch_rocket(pool, extra_debug); // Blocks until program termination.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user