mirror of
https://github.com/bitwarden/browser
synced 2026-02-03 02:03:53 +00:00
Properly handle uv requirement
This commit is contained in:
@@ -7,6 +7,16 @@ use crate::types::*;
|
||||
use crate::utils::{self as util, delay_load};
|
||||
use crate::com_provider::ExperimentalWebAuthnPluginOperationResponse;
|
||||
|
||||
// Authenticator Options from WebAuthn header
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct EXPERIMENTAL_WEBAUTHN_CTAPCBOR_AUTHENTICATOR_OPTIONS {
|
||||
pub dwVersion: u32,
|
||||
pub lUp: i32, // User presence: +1=TRUE, 0=Not defined, -1=FALSE
|
||||
pub lUv: i32, // User verification: +1=TRUE, 0=Not defined, -1=FALSE
|
||||
pub lRequireResidentKey: i32, // Resident key: +1=TRUE, 0=Not defined, -1=FALSE
|
||||
}
|
||||
|
||||
// Windows API types for WebAuthn (from webauthn.h.sample)
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
@@ -20,6 +30,7 @@ pub struct EXPERIMENTAL_WEBAUTHN_CTAPCBOR_GET_ASSERTION_REQUEST {
|
||||
pub CredentialList: WEBAUTHN_CREDENTIAL_LIST,
|
||||
pub cbCborExtensionsMap: u32,
|
||||
pub pbCborExtensionsMap: *const u8,
|
||||
pub pAuthenticatorOptions: *const EXPERIMENTAL_WEBAUTHN_CTAPCBOR_AUTHENTICATOR_OPTIONS,
|
||||
// Add other fields as needed...
|
||||
}
|
||||
|
||||
@@ -109,7 +120,7 @@ pub unsafe fn decode_get_assertion_request(encoded_request: &[u8]) -> Result<Dec
|
||||
pub struct RequestContext {
|
||||
pub rpid: Option<String>,
|
||||
pub allowed_credentials: Vec<Vec<u8>>,
|
||||
pub user_verification: Option<bool>,
|
||||
pub user_verification: Option<UserVerificationRequirement>,
|
||||
pub user_id: Option<Vec<u8>>,
|
||||
pub user_name: Option<String>,
|
||||
pub user_display_name: Option<String>,
|
||||
@@ -148,7 +159,7 @@ pub fn send_assertion_request(rpid: &str, transaction_id: &str, context: &Reques
|
||||
transaction_id: transaction_id.to_string(),
|
||||
client_data_hash,
|
||||
allowed_credentials: context.allowed_credentials.clone(),
|
||||
user_verification: context.user_verification.unwrap_or(false),
|
||||
user_verification: context.user_verification.unwrap_or_default(),
|
||||
};
|
||||
|
||||
util::message(&format!("Assertion request data - RP ID: {}, Client data hash: {} bytes, Allowed credentials: {}",
|
||||
|
||||
@@ -212,6 +212,18 @@ impl EXPERIMENTAL_IPluginAuthenticator_Impl for PluginAuthenticatorComObject_Imp
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
// Extract user verification requirement from authenticator options
|
||||
let user_verification = if !decoded_request.pAuthenticatorOptions.is_null() {
|
||||
let auth_options = &*decoded_request.pAuthenticatorOptions;
|
||||
match auth_options.lUv {
|
||||
1 => Some(UserVerificationRequirement::Required),
|
||||
-1 => Some(UserVerificationRequirement::Discouraged),
|
||||
0 | _ => Some(UserVerificationRequirement::Preferred), // Default or undefined
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// Create request context from properly decoded data
|
||||
let mut request_context = RequestContext::default();
|
||||
request_context.rpid = Some(rpid.clone());
|
||||
@@ -220,6 +232,7 @@ impl EXPERIMENTAL_IPluginAuthenticator_Impl for PluginAuthenticatorComObject_Imp
|
||||
request_context.user_display_name = user_info.2;
|
||||
request_context.client_data_hash = Some(client_data_hash);
|
||||
request_context.supported_algorithms = supported_algorithms;
|
||||
request_context.user_verification = user_verification;
|
||||
|
||||
util::message(&format!("Make credential request - RP: {}, User: {}",
|
||||
rpid,
|
||||
@@ -336,10 +349,23 @@ impl EXPERIMENTAL_IPluginAuthenticator_Impl for PluginAuthenticatorComObject_Imp
|
||||
hash_slice.to_vec()
|
||||
};
|
||||
|
||||
// Extract user verification requirement from authenticator options
|
||||
let user_verification = if !decoded_request.pAuthenticatorOptions.is_null() {
|
||||
let auth_options = &*decoded_request.pAuthenticatorOptions;
|
||||
match auth_options.lUv {
|
||||
1 => Some(UserVerificationRequirement::Required),
|
||||
-1 => Some(UserVerificationRequirement::Discouraged),
|
||||
0 | _ => Some(UserVerificationRequirement::Preferred), // Default or undefined
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// Create request context from properly decoded data
|
||||
let mut request_context = RequestContext::default();
|
||||
request_context.rpid = Some(rpid.clone());
|
||||
request_context.client_data_hash = Some(client_data_hash);
|
||||
request_context.user_verification = user_verification;
|
||||
// TODO: Extract allowed credentials from CredentialList if available
|
||||
|
||||
util::message(&format!("Get assertion request - RP: {}", rpid));
|
||||
|
||||
@@ -51,6 +51,16 @@ pub struct WEBAUTHN_CREDENTIAL_LIST {
|
||||
pub pCredentials: *const u8, // Placeholder
|
||||
}
|
||||
|
||||
// Authenticator Options from WebAuthn header
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct EXPERIMENTAL_WEBAUTHN_CTAPCBOR_AUTHENTICATOR_OPTIONS {
|
||||
pub dwVersion: u32,
|
||||
pub lUp: i32, // User presence: +1=TRUE, 0=Not defined, -1=FALSE
|
||||
pub lUv: i32, // User verification: +1=TRUE, 0=Not defined, -1=FALSE
|
||||
pub lRequireResidentKey: i32, // Resident key: +1=TRUE, 0=Not defined, -1=FALSE
|
||||
}
|
||||
|
||||
// Make Credential Request structure (from sample header)
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
@@ -66,6 +76,7 @@ pub struct EXPERIMENTAL_WEBAUTHN_CTAPCBOR_MAKE_CREDENTIAL_REQUEST {
|
||||
pub CredentialList: WEBAUTHN_CREDENTIAL_LIST,
|
||||
pub cbCborExtensionsMap: u32,
|
||||
pub pbCborExtensionsMap: *const u8,
|
||||
pub pAuthenticatorOptions: *const EXPERIMENTAL_WEBAUTHN_CTAPCBOR_AUTHENTICATOR_OPTIONS,
|
||||
// Add other fields as needed...
|
||||
}
|
||||
|
||||
@@ -203,7 +214,7 @@ pub fn send_registration_request(rpid: &str, transaction_id: &str, context: &Req
|
||||
user_id,
|
||||
user_name,
|
||||
client_data_hash,
|
||||
user_verification: context.user_verification.unwrap_or(false),
|
||||
user_verification: context.user_verification.unwrap_or_default(),
|
||||
supported_algorithms: context.supported_algorithms.clone(),
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,41 @@
|
||||
use tokio::sync::oneshot;
|
||||
|
||||
/// User verification requirement as defined by WebAuthn spec
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum UserVerificationRequirement {
|
||||
Required,
|
||||
Preferred,
|
||||
Discouraged,
|
||||
}
|
||||
|
||||
impl Default for UserVerificationRequirement {
|
||||
fn default() -> Self {
|
||||
UserVerificationRequirement::Preferred
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for UserVerificationRequirement {
|
||||
fn from(value: u32) -> Self {
|
||||
match value {
|
||||
1 => UserVerificationRequirement::Required,
|
||||
2 => UserVerificationRequirement::Preferred,
|
||||
3 => UserVerificationRequirement::Discouraged,
|
||||
_ => UserVerificationRequirement::Preferred, // Default fallback
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<String> for UserVerificationRequirement {
|
||||
fn into(self) -> String {
|
||||
match self {
|
||||
UserVerificationRequirement::Required => "required".to_string(),
|
||||
UserVerificationRequirement::Preferred => "preferred".to_string(),
|
||||
UserVerificationRequirement::Discouraged => "discouraged".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Assertion request structure
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
@@ -8,7 +44,7 @@ pub struct PasskeyAssertionRequest {
|
||||
pub transaction_id: String,
|
||||
pub client_data_hash: Vec<u8>,
|
||||
pub allowed_credentials: Vec<Vec<u8>>,
|
||||
pub user_verification: bool,
|
||||
pub user_verification: UserVerificationRequirement,
|
||||
}
|
||||
|
||||
/// Registration request structure
|
||||
@@ -20,7 +56,7 @@ pub struct PasskeyRegistrationRequest {
|
||||
pub user_id: Vec<u8>,
|
||||
pub user_name: String,
|
||||
pub client_data_hash: Vec<u8>,
|
||||
pub user_verification: bool,
|
||||
pub user_verification: UserVerificationRequirement,
|
||||
pub supported_algorithms: Vec<i32>, // COSE algorithm identifiers
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user