mirror of
				https://github.com/dani-garcia/vaultwarden.git
				synced 2025-10-31 22:01:15 +00:00 
			
		
		
		
	Implement user duo, initial version
TODO: - At the moment each user needs to configure a DUO application and input the API keys, we need to check if multiple users can register with the same keys correctly and if so we could implement a global setting. - Sometimes the Duo frame doesn't load correctly, but canceling, reloading the page and logging in again seems to fix it for me.
This commit is contained in:
		
					parent
					
						
							
								3bb46ce496
							
						
					
				
			
			
				commit
				
					
						cfbeb56371
					
				
			
		
					 5 changed files with 312 additions and 62 deletions
				
			
		
							
								
								
									
										112
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										112
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							|  | @ -61,7 +61,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| 
 | ||||
| [[package]] | ||||
| name = "backtrace" | ||||
| version = "0.3.14" | ||||
| version = "0.3.15" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  | @ -69,7 +69,7 @@ dependencies = [ | |||
|  "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
|  | @ -77,7 +77,7 @@ name = "backtrace-sys" | |||
| version = "0.1.28" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "cc 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "cc 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
|  | @ -139,8 +139,8 @@ dependencies = [ | |||
|  "rmpv 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "rocket 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "rocket_contrib 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "soup 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "syslog 4.0.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  | @ -245,7 +245,7 @@ dependencies = [ | |||
| 
 | ||||
| [[package]] | ||||
| name = "cc" | ||||
| version = "1.0.32" | ||||
| version = "1.0.34" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| 
 | ||||
| [[package]] | ||||
|  | @ -594,7 +594,7 @@ name = "error-chain" | |||
| version = "0.11.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
|  | @ -602,7 +602,7 @@ name = "failure" | |||
| version = "0.1.5" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
|  | @ -771,7 +771,7 @@ dependencies = [ | |||
|  "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  | @ -790,7 +790,7 @@ dependencies = [ | |||
|  "pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "regex 1.1.5 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
|  | @ -838,7 +838,7 @@ dependencies = [ | |||
| 
 | ||||
| [[package]] | ||||
| name = "http" | ||||
| version = "0.1.16" | ||||
| version = "0.1.17" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  | @ -878,7 +878,7 @@ dependencies = [ | |||
|  "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "h2 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  | @ -969,7 +969,7 @@ dependencies = [ | |||
|  "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "redox_syscall 0.1.52 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
|  | @ -985,8 +985,8 @@ dependencies = [ | |||
|  "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
|  | @ -1029,8 +1029,8 @@ dependencies = [ | |||
|  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
|  | @ -1059,7 +1059,7 @@ name = "libsqlite3-sys" | |||
| version = "0.12.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "cc 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "cc 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
|  | @ -1106,8 +1106,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| dependencies = [ | ||||
|  "phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  | @ -1198,7 +1198,7 @@ name = "miniz_oxide_c_api" | |||
| version = "0.2.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "cc 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "cc 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "miniz_oxide 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  | @ -1285,7 +1285,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| dependencies = [ | ||||
|  "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
|  | @ -1322,7 +1322,7 @@ dependencies = [ | |||
|  "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
|  | @ -1404,7 +1404,7 @@ name = "openssl-sys" | |||
| version = "0.9.43" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "cc 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "cc 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  | @ -1453,7 +1453,7 @@ dependencies = [ | |||
|  "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
|  | @ -1465,7 +1465,7 @@ dependencies = [ | |||
|  "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
|  | @ -1627,7 +1627,7 @@ dependencies = [ | |||
|  "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
|  | @ -1645,7 +1645,7 @@ dependencies = [ | |||
|  "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
|  | @ -1693,7 +1693,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| dependencies = [ | ||||
|  "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
|  | @ -1706,7 +1706,7 @@ dependencies = [ | |||
|  "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
|  | @ -1764,7 +1764,7 @@ name = "remove_dir_all" | |||
| version = "0.5.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
|  | @ -1777,14 +1777,14 @@ dependencies = [ | |||
|  "encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "flate2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "hyper 0.12.25 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "tokio 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  | @ -1801,7 +1801,7 @@ name = "ring" | |||
| version = "0.13.5" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "cc 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "cc 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  | @ -1866,7 +1866,7 @@ dependencies = [ | |||
|  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "notify 4.0.10 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "rocket 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
|  | @ -1948,7 +1948,7 @@ version = "0.1.15" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
|  | @ -2009,12 +2009,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| 
 | ||||
| [[package]] | ||||
| name = "serde" | ||||
| version = "1.0.89" | ||||
| version = "1.0.90" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "serde_derive" | ||||
| version = "1.0.89" | ||||
| version = "1.0.90" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  | @ -2029,7 +2029,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| dependencies = [ | ||||
|  "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
|  | @ -2039,7 +2039,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| dependencies = [ | ||||
|  "dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
|  | @ -2142,7 +2142,7 @@ dependencies = [ | |||
|  "new_debug_unreachable 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
|  | @ -2234,7 +2234,7 @@ dependencies = [ | |||
|  "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "redox_syscall 0.1.52 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
|  | @ -2270,7 +2270,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| dependencies = [ | ||||
|  "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "redox_syscall 0.1.52 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
|  | @ -2399,7 +2399,7 @@ name = "toml" | |||
| version = "0.4.10" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
|  | @ -2440,8 +2440,8 @@ dependencies = [ | |||
|  "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  | @ -2549,7 +2549,7 @@ version = "2.2.7" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
|  | @ -2588,7 +2588,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| 
 | ||||
| [[package]] | ||||
| name = "winapi" | ||||
| version = "0.3.6" | ||||
| version = "0.3.7" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  | @ -2610,7 +2610,7 @@ name = "winapi-util" | |||
| version = "0.1.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
|  | @ -2623,7 +2623,7 @@ name = "winutil" | |||
| version = "0.1.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | ||||
|  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
|  "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
|  | @ -2691,7 +2691,7 @@ dependencies = [ | |||
| "checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" | ||||
| "checksum ascii_utils 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "71938f30533e4d95a6d17aa530939da3842c2ab6f4f84b9dae68447e4129f74a" | ||||
| "checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" | ||||
| "checksum backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "cd5a90e2b463010cd0e0ce9a11d4a9d5d58d9f41d4a6ba3dcaf9e68b466e88b4" | ||||
| "checksum backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f106c02a3604afcdc0df5d36cc47b44b55917dbaf3d808f71c163a0ddba64637" | ||||
| "checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" | ||||
| "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" | ||||
| "checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" | ||||
|  | @ -2710,7 +2710,7 @@ dependencies = [ | |||
| "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" | ||||
| "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" | ||||
| "checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" | ||||
| "checksum cc 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)" = "ad0daef304fa0b4238f5f7ed7178774b43b06f6a9b6509f6642bef4ff1f7b9b2" | ||||
| "checksum cc 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)" = "30f813bf45048a18eda9190fd3c6b78644146056740c43172a5a3699118588fd" | ||||
| "checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" | ||||
| "checksum chashmap 2.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ff41a3c2c1e39921b9003de14bf0439c7b63a9039637c291e1a64925d8ddfa45" | ||||
| "checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" | ||||
|  | @ -2778,7 +2778,7 @@ dependencies = [ | |||
| "checksum hmac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f127a908633569f208325f86f71255d3363c79721d7f9fe31cd5569908819771" | ||||
| "checksum hostname 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "21ceb46a83a85e824ef93669c8b390009623863b5c195d1ba747292c0c72f94e" | ||||
| "checksum html5ever 0.22.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c213fa6a618dc1da552f54f85cba74b05d8e883c92ec4e89067736938084c26e" | ||||
| "checksum http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "fe67e3678f2827030e89cc4b9e7ecd16d52f132c0b940ab5005f88e821500f6a" | ||||
| "checksum http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "eed324f0f0daf6ec10c474f150505af2c143f251722bf9dbd1261bd1f2ee2c1a" | ||||
| "checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" | ||||
| "checksum hyper 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)" = "df0caae6b71d266b91b4a83111a61d2b94ed2e2bea024c532b933dcff867e58c" | ||||
| "checksum hyper 0.12.25 (registry+https://github.com/rust-lang/crates.io-index)" = "7d5b6658b016965ae301fa995306db965c93677880ea70765a84235a96eae896" | ||||
|  | @ -2902,8 +2902,8 @@ dependencies = [ | |||
| "checksum security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3d6696852716b589dff9e886ff83778bb635150168e83afa8ac6b8a78cb82abc" | ||||
| "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" | ||||
| "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" | ||||
| "checksum serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "92514fb95f900c9b5126e32d020f5c6d40564c27a5ea6d1d7d9f157a96623560" | ||||
| "checksum serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6eabf4b5914e88e24eea240bb7c9f9a2cbc1bbbe8d961d381975ec3c6b806c" | ||||
| "checksum serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)" = "aa5f7c20820475babd2c077c3ab5f8c77a31c15e16ea38687b4c02d3e48680f4" | ||||
| "checksum serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)" = "58fc82bec244f168b23d1963b45c8bf5726e9a15a9d146a067f9081aeed2de79" | ||||
| "checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" | ||||
| "checksum serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d48f9f99cd749a2de71d29da5f948de7f2764cc5a9d7f3c97e3514d4ee6eabf2" | ||||
| "checksum sha-1 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8347606816471548cd60f0abd5ef0d513a81f5202dbdab9c09f17a15b5248484" | ||||
|  | @ -2970,7 +2970,7 @@ dependencies = [ | |||
| "checksum webpki 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)" = "17d7967316d8411ca3b01821ee6c332bde138ba4363becdb492f12e514daa17f" | ||||
| "checksum webpki-roots 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85d1f408918fd590908a70d36b7ac388db2edc221470333e4d6e5b598e44cabf" | ||||
| "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" | ||||
| "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" | ||||
| "checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" | ||||
| "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" | ||||
| "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" | ||||
| "checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" | ||||
|  |  | |||
|  | @ -38,8 +38,8 @@ rmpv = "0.4.0" | |||
| chashmap = "2.2.2" | ||||
| 
 | ||||
| # A generic serialization/deserialization framework | ||||
| serde = "1.0.89" | ||||
| serde_derive = "1.0.89" | ||||
| serde = "1.0.90" | ||||
| serde_derive = "1.0.90" | ||||
| serde_json = "1.0.39" | ||||
| 
 | ||||
| # Logging | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| use data_encoding::BASE32; | ||||
| use data_encoding::{BASE32, BASE64}; | ||||
| use rocket_contrib::json::Json; | ||||
| use serde_json; | ||||
| use serde_json::Value; | ||||
|  | @ -31,6 +31,9 @@ pub fn routes() -> Vec<Route> { | |||
|         generate_yubikey, | ||||
|         activate_yubikey, | ||||
|         activate_yubikey_put, | ||||
|         get_duo, | ||||
|         activate_duo, | ||||
|         activate_duo_put, | ||||
|     ] | ||||
| } | ||||
| 
 | ||||
|  | @ -231,7 +234,6 @@ pub fn validate_totp_code_str(totp_code: &str, secret: &str) -> EmptyResult { | |||
| } | ||||
| 
 | ||||
| pub fn validate_totp_code(totp_code: u64, secret: &str) -> EmptyResult { | ||||
|     use data_encoding::BASE32; | ||||
|     use oath::{totp_raw_now, HashType}; | ||||
| 
 | ||||
|     let decoded_secret = match BASE32.decode(secret.as_bytes()) { | ||||
|  | @ -714,3 +716,217 @@ pub fn validate_yubikey_login(response: &str, twofactor_data: &str) -> EmptyResu | |||
|         Err(_e) => err!("Failed to verify Yubikey against OTP server"), | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Serialize, Deserialize, Default)] | ||||
| pub struct DuoData { | ||||
|     pub host: String, | ||||
|     sk: String, | ||||
|     ik: String, | ||||
|     ak: String, | ||||
| } | ||||
| 
 | ||||
| #[post("/two-factor/get-duo", data = "<data>")] | ||||
| fn get_duo(data: JsonUpcase<PasswordData>, headers: Headers, conn: DbConn) -> JsonResult { | ||||
|     let data: PasswordData = data.into_inner().data; | ||||
| 
 | ||||
|     if !headers.user.check_valid_password(&data.MasterPasswordHash) { | ||||
|         err!("Invalid password"); | ||||
|     } | ||||
| 
 | ||||
|     let type_ = TwoFactorType::Duo as i32; | ||||
|     let twofactor = TwoFactor::find_by_user_and_type(&headers.user.uuid, type_, &conn); | ||||
| 
 | ||||
|     let (enabled, data) = match twofactor { | ||||
|         Some(tf) => (true, serde_json::from_str(&tf.data)?), | ||||
|         _ => (false, DuoData::default()), | ||||
|     }; | ||||
| 
 | ||||
|     // TODO: It's probably not the best idea to return the keys here
 | ||||
| 
 | ||||
|     Ok(Json(json!({ | ||||
|         "Enabled": enabled, | ||||
|         "Host": data.host, | ||||
|         "SecretKey": data.sk, | ||||
|         "IntegrationKey": data.ik, | ||||
|         "Object": "twoFactorDuo" | ||||
|     }))) | ||||
| } | ||||
| 
 | ||||
| #[derive(Deserialize)] | ||||
| #[allow(non_snake_case)] | ||||
| struct EnableDuoData { | ||||
|     MasterPasswordHash: String, | ||||
|     Host: String, | ||||
|     SecretKey: String, | ||||
|     IntegrationKey: String, | ||||
| } | ||||
| 
 | ||||
| #[post("/two-factor/duo", data = "<data>")] | ||||
| fn activate_duo(data: JsonUpcase<EnableDuoData>, headers: Headers, conn: DbConn) -> JsonResult { | ||||
|     let data: EnableDuoData = data.into_inner().data; | ||||
| 
 | ||||
|     if !headers.user.check_valid_password(&data.MasterPasswordHash) { | ||||
|         err!("Invalid password"); | ||||
|     } | ||||
| 
 | ||||
|     let data = DuoData { | ||||
|         host: data.Host, | ||||
|         sk: data.SecretKey, | ||||
|         ik: data.IntegrationKey, | ||||
|         ak: BASE64.encode(&crypto::get_random_64()), | ||||
|     }; | ||||
| 
 | ||||
|     // Validate parameters with the server
 | ||||
|     duo_api_request("GET", "/auth/v2/check", "", &data)?; | ||||
| 
 | ||||
|     let data_json = serde_json::to_string(&data)?; | ||||
|     let type_ = TwoFactorType::Duo; | ||||
|     let twofactor = TwoFactor::new(headers.user.uuid.clone(), type_, data_json); | ||||
|     twofactor.save(&conn)?; | ||||
| 
 | ||||
|     // TODO: It's probably not the best idea to return the keys here
 | ||||
|     Ok(Json(json!({ | ||||
|         "Enabled": true, | ||||
|         "Host": data.host, | ||||
|         "SecretKey": data.sk, | ||||
|         "IntegrationKey": data.ik, | ||||
|         "Object": "twoFactorDuo" | ||||
|     }))) | ||||
| } | ||||
| 
 | ||||
| #[put("/two-factor/duo", data = "<data>")] | ||||
| fn activate_duo_put(data: JsonUpcase<EnableDuoData>, headers: Headers, conn: DbConn) -> JsonResult { | ||||
|     activate_duo(data, headers, conn) | ||||
| } | ||||
| 
 | ||||
| fn duo_api_request(method: &str, path: &str, params: &str, data: &DuoData) -> EmptyResult { | ||||
|     const AGENT: &str = "bitwarden_rs:Duo/1.0 (Rust)"; | ||||
| 
 | ||||
|     use std::str::FromStr; | ||||
| 
 | ||||
|     use chrono::Utc; | ||||
|     use reqwest::{header::*, Client, Method}; | ||||
| 
 | ||||
|     let url = format!("https://{}{}", data.host, path); | ||||
| 
 | ||||
|     let date = Utc::now().to_rfc2822(); | ||||
| 
 | ||||
|     let username = &data.ik; | ||||
|     let fields = [&date, method, &data.host, path, params]; | ||||
|     let password = crypto::hmac_sign(&data.sk, &fields.join("\n")); | ||||
| 
 | ||||
|     let m = Method::from_str(method).unwrap_or_default(); | ||||
| 
 | ||||
|     Client::new() | ||||
|         .request(m, &url) | ||||
|         .basic_auth(username, Some(password)) | ||||
|         .header(USER_AGENT, AGENT) | ||||
|         .header(DATE, date) | ||||
|         .send()? | ||||
|         .error_for_status()?; | ||||
| 
 | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| const DUO_EXPIRE: i64 = 300; | ||||
| const APP_EXPIRE: i64 = 3600; | ||||
| 
 | ||||
| const AUTH_PREFIX: &str = "AUTH"; | ||||
| const DUO_PREFIX: &str = "TX"; | ||||
| const APP_PREFIX: &str = "APP"; | ||||
| 
 | ||||
| use chrono::Utc; | ||||
| 
 | ||||
| pub fn generate_duo_signature(data: &DuoData, email: &str) -> String { | ||||
|     let now = Utc::now().timestamp(); | ||||
| 
 | ||||
|     let duo_sign = sign_duo_values(&data.sk, email, &data.ik, DUO_PREFIX, now + DUO_EXPIRE); | ||||
|     let app_sign = sign_duo_values(&data.ak, email, &data.ik, APP_PREFIX, now + APP_EXPIRE); | ||||
| 
 | ||||
|     format!("{}:{}", duo_sign, app_sign) | ||||
| } | ||||
| 
 | ||||
| fn sign_duo_values(key: &str, email: &str, ikey: &str, prefix: &str, expire: i64) -> String { | ||||
|     let val = format!("{}|{}|{}", email, ikey, expire); | ||||
|     let cookie = format!("{}|{}", prefix, BASE64.encode(val.as_bytes())); | ||||
| 
 | ||||
|     format!("{}|{}", cookie, crypto::hmac_sign(key, &cookie)) | ||||
| } | ||||
| 
 | ||||
| pub fn validate_duo_login(response: &str, twofactor_data: &str) -> EmptyResult { | ||||
|     let data: DuoData = serde_json::from_str(twofactor_data)?; | ||||
| 
 | ||||
|     let split: Vec<&str> = response.split(":").collect(); | ||||
|     if split.len() != 2 { | ||||
|         err!("Invalid response length"); | ||||
|     } | ||||
| 
 | ||||
|     let auth_sig = split[0]; | ||||
|     let app_sig = split[1]; | ||||
| 
 | ||||
|     let now = Utc::now().timestamp(); | ||||
| 
 | ||||
|     let auth_user = parse_duo_values(&data.sk, auth_sig, &data.ik, AUTH_PREFIX, now)?; | ||||
|     let app_user = parse_duo_values(&data.ak, app_sig, &data.ik, APP_PREFIX, now)?; | ||||
| 
 | ||||
|     if !crypto::ct_eq(auth_user, app_user) { | ||||
|         err!("Error validating duo authentication") | ||||
|     } | ||||
| 
 | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| fn parse_duo_values(key: &str, val: &str, ikey: &str, prefix: &str, time: i64) -> ApiResult<String> { | ||||
|     let split: Vec<&str> = val.split("|").collect(); | ||||
|     if split.len() != 3 { | ||||
|         err!("Invalid value length") | ||||
|     } | ||||
| 
 | ||||
|     let u_prefix = split[0]; | ||||
|     let u_b64 = split[1]; | ||||
|     let u_sig = split[2]; | ||||
| 
 | ||||
|     let sig = crypto::hmac_sign(key, &format!("{}|{}", u_prefix, u_b64)); | ||||
| 
 | ||||
|     if !crypto::ct_eq(crypto::hmac_sign(key, &sig), crypto::hmac_sign(key, u_sig)) { | ||||
|         err!("Duo signatures don't match") | ||||
|     } | ||||
| 
 | ||||
|     if u_prefix != prefix { | ||||
|         err!("Prefixes don't match") | ||||
|     } | ||||
| 
 | ||||
|     let cookie_vec = match BASE64.decode(u_b64.as_bytes()) { | ||||
|         Ok(c) => c, | ||||
|         Err(_) => err!("Invalid Duo cookie encoding"), | ||||
|     }; | ||||
| 
 | ||||
|     let cookie = match String::from_utf8(cookie_vec) { | ||||
|         Ok(c) => c, | ||||
|         Err(_) => err!("Invalid Duo cookie encoding"), | ||||
|     }; | ||||
| 
 | ||||
|     let cookie_split: Vec<&str> = cookie.split("|").collect(); | ||||
|     if cookie_split.len() != 3 { | ||||
|         err!("Invalid cookie length") | ||||
|     } | ||||
| 
 | ||||
|     let username = cookie_split[0]; | ||||
|     let u_ikey = cookie_split[1]; | ||||
|     let expire = cookie_split[2]; | ||||
| 
 | ||||
|     if !crypto::ct_eq(ikey, u_ikey) { | ||||
|         err!("Invalid ikey") | ||||
|     } | ||||
| 
 | ||||
|     let expire = match expire.parse() { | ||||
|         Ok(e) => e, | ||||
|         Err(_) => err!("Invalid expire time"), | ||||
|     }; | ||||
| 
 | ||||
|     if time >= expire { | ||||
|         err!("Expired authorization") | ||||
|     } | ||||
| 
 | ||||
|     Ok(username.into()) | ||||
| } | ||||
|  |  | |||
|  | @ -178,6 +178,7 @@ fn twofactor_auth( | |||
|         Some(TwoFactorType::Authenticator) => _tf::validate_totp_code_str(twofactor_code, &selected_data?)?, | ||||
|         Some(TwoFactorType::U2f) => _tf::validate_u2f_login(user_uuid, twofactor_code, conn)?, | ||||
|         Some(TwoFactorType::YubiKey) => _tf::validate_yubikey_login(twofactor_code, &selected_data?)?, | ||||
|         Some(TwoFactorType::Duo) => _tf::validate_duo_login(twofactor_code, &selected_data?)?, | ||||
| 
 | ||||
|         Some(TwoFactorType::Remember) => { | ||||
|             match device.twofactor_remember { | ||||
|  | @ -237,13 +238,33 @@ fn _json_err_twofactor(providers: &[i32], user_uuid: &str, conn: &DbConn) -> Api | |||
|                 } | ||||
| 
 | ||||
|                 let mut map = JsonMap::new(); | ||||
|                 use serde_json; | ||||
|                 let challenge_list_str = serde_json::to_string(&challenge_list).unwrap(); | ||||
| 
 | ||||
|                 map.insert("Challenges".into(), Value::String(challenge_list_str)); | ||||
|                 result["TwoFactorProviders2"][provider.to_string()] = Value::Object(map); | ||||
|             } | ||||
| 
 | ||||
|             Some(tf_type @ TwoFactorType::Duo) => { | ||||
|                 let twofactor = match TwoFactor::find_by_user_and_type(user_uuid, tf_type as i32, &conn) { | ||||
|                     Some(tf) => tf, | ||||
|                     None => err!("No Duo devices registered"), | ||||
|                 };        
 | ||||
| 
 | ||||
|                 let duo_data: two_factor::DuoData = serde_json::from_str(&twofactor.data)?; | ||||
| 
 | ||||
|                 let email = match User::find_by_uuid(user_uuid, &conn) { | ||||
|                     Some(u) => u.email, | ||||
|                     None => err!("User does not exist") | ||||
|                 }; | ||||
| 
 | ||||
|                 let signature = two_factor::generate_duo_signature(&duo_data, &email); | ||||
| 
 | ||||
|                 let mut map = JsonMap::new(); | ||||
|                 map.insert("Host".into(), Value::String(duo_data.host)); | ||||
|                 map.insert("Signature".into(), Value::String(signature)); | ||||
|                 result["TwoFactorProviders2"][provider.to_string()] = Value::Object(map);     
 | ||||
|             } | ||||
| 
 | ||||
|             Some(tf_type @ TwoFactorType::YubiKey) => { | ||||
|                 let twofactor = match TwoFactor::find_by_user_and_type(user_uuid, tf_type as i32, &conn) { | ||||
|                     Some(tf) => tf, | ||||
|  | @ -251,7 +272,7 @@ fn _json_err_twofactor(providers: &[i32], user_uuid: &str, conn: &DbConn) -> Api | |||
|                 }; | ||||
| 
 | ||||
|                 let yubikey_metadata: two_factor::YubikeyMetadata = | ||||
|                     serde_json::from_str(&twofactor.data).expect("Can't parse Yubikey Metadata"); | ||||
|                     serde_json::from_str(&twofactor.data)?; | ||||
| 
 | ||||
|                 let mut map = JsonMap::new(); | ||||
|                 map.insert("Nfc".into(), Value::Bool(yubikey_metadata.Nfc)); | ||||
|  |  | |||
|  | @ -19,6 +19,19 @@ pub fn verify_password_hash(secret: &[u8], salt: &[u8], previous: &[u8], iterati | |||
|     pbkdf2::verify(DIGEST_ALG, iterations, salt, secret, previous).is_ok() | ||||
| } | ||||
| 
 | ||||
| //
 | ||||
| // HMAC
 | ||||
| //
 | ||||
| pub fn hmac_sign(key: &str, data:&str) -> String { | ||||
|     use data_encoding::HEXLOWER; | ||||
|     use ring::{digest, hmac}; | ||||
| 
 | ||||
|     let key = hmac::SigningKey::new(&digest::SHA1, key.as_bytes()); | ||||
|     let signature = hmac::sign(&key, data.as_bytes()); | ||||
| 
 | ||||
|     HEXLOWER.encode(signature.as_ref()) | ||||
| } | ||||
| 
 | ||||
| //
 | ||||
| // Random values
 | ||||
| //
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue