Skip to content

Commit e31cecd

Browse files
committed
Make it possible to retry setting a PIN, if previous entry does not conform to the PIN policy
1 parent a768258 commit e31cecd

9 files changed

Lines changed: 86 additions & 36 deletions

File tree

credentialsd-common/src/model.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,13 +112,18 @@ pub struct RequestingParty {
112112
#[derive(Debug, Clone, Serialize, Deserialize)]
113113
pub enum ViewUpdateFailure {
114114
GeneralFailure(String),
115+
/// Request required UV, but it was not set on the device yet
115116
PinNotSet(String),
117+
/// User tried to set PIN, but it was too short
118+
PinPolicyViolation(String),
116119
}
117120

118121
impl ViewUpdateFailure {
119122
pub fn into_string(self) -> String {
120123
match self {
121-
ViewUpdateFailure::GeneralFailure(msg) | ViewUpdateFailure::PinNotSet(msg) => msg,
124+
ViewUpdateFailure::GeneralFailure(msg)
125+
| ViewUpdateFailure::PinNotSet(msg)
126+
| ViewUpdateFailure::PinPolicyViolation(msg) => msg,
122127
}
123128
}
124129
}
@@ -276,6 +281,8 @@ pub enum Error {
276281
PinAttemptsExhausted,
277282
/// The RP requires user verification, but the device has no PIN/Biometrics set.
278283
PinNotSet,
284+
/// The device declined the entered PIN, as it violates the PIN policy (e.g. PIN too short)
285+
PinPolicyViolation,
279286
// TODO: We may want to hide the details on this variant from the public API.
280287
/// Something went wrong with the credential service itself, not the authenticator.
281288
Internal(String),
@@ -288,6 +295,7 @@ impl Display for Error {
288295
match self {
289296
Self::AuthenticatorError => f.write_str("AuthenticatorError"),
290297
Self::PinNotSet => f.write_str("PinNotSet"),
298+
Self::PinPolicyViolation => f.write_str("PinPolicyViolation"),
291299
Self::NoCredentials => f.write_str("NoCredentials"),
292300
Self::CredentialExcluded => f.write_str("CredentialExcluded"),
293301
Self::PinAttemptsExhausted => f.write_str("PinAttemptsExhausted"),

credentialsd-common/src/server.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ impl TryFrom<&Value<'_>> for crate::model::Error {
220220
let err = match err_code {
221221
"AuthenticatorError" => crate::model::Error::AuthenticatorError,
222222
"PinNotSet" => crate::model::Error::PinNotSet,
223+
"PinPolicyViolation" => crate::model::Error::PinPolicyViolation,
223224
"NoCredentials" => crate::model::Error::NoCredentials,
224225
"CredentialExcluded" => crate::model::Error::CredentialExcluded,
225226
"PinAttemptsExhausted" => crate::model::Error::PinAttemptsExhausted,
@@ -438,6 +439,7 @@ impl TryFrom<&Structure<'_>> for crate::model::UsbState {
438439
let err = match err_code {
439440
"AuthenticatorError" => crate::model::Error::AuthenticatorError,
440441
"PinNotSet" => crate::model::Error::PinNotSet,
442+
"PinPolicyViolation" => crate::model::Error::PinPolicyViolation,
441443
"NoCredentials" => crate::model::Error::NoCredentials,
442444
"CredentialExcluded" => crate::model::Error::CredentialExcluded,
443445
"PinAttemptsExhausted" => crate::model::Error::PinAttemptsExhausted,
@@ -561,6 +563,7 @@ impl TryFrom<&Structure<'_>> for crate::model::NfcState {
561563
let err = match err_code {
562564
"AuthenticatorError" => crate::model::Error::AuthenticatorError,
563565
"PinNotSet" => crate::model::Error::PinNotSet,
566+
"PinPolicyViolation" => crate::model::Error::PinPolicyViolation,
564567
"NoCredentials" => crate::model::Error::NoCredentials,
565568
"CredentialExcluded" => crate::model::Error::CredentialExcluded,
566569
"PinAttemptsExhausted" => crate::model::Error::PinAttemptsExhausted,

credentialsd-ui/po/credentialsd-ui.pot

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ msgstr ""
99
"Project-Id-Version: credentialsd-ui\n"
1010
"Report-Msgid-Bugs-To: \"https://github.com/linux-credentials/credentialsd/"
1111
"issues\"\n"
12-
"POT-Creation-Date: 2026-02-11 14:31+0100\n"
12+
"POT-Creation-Date: 2026-02-12 14:18+0100\n"
1313
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
1414
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1515
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -21,7 +21,7 @@ msgstr ""
2121

2222
#: data/xyz.iinuwa.credentialsd.CredentialsUi.desktop.in.in:2
2323
#: data/xyz.iinuwa.credentialsd.CredentialsUi.metainfo.xml.in.in:8
24-
#: src/gui/view_model/gtk/mod.rs:400
24+
#: src/gui/view_model/gtk/mod.rs:401
2525
msgid "Credential Manager"
2626
msgstr ""
2727

@@ -140,8 +140,8 @@ msgstr ""
140140
msgid "Something went wrong."
141141
msgstr ""
142142

143-
#: data/resources/ui/window.ui:304 src/gui/view_model/mod.rs:310
144-
#: src/gui/view_model/mod.rs:370
143+
#: data/resources/ui/window.ui:304 src/gui/view_model/mod.rs:315
144+
#: src/gui/view_model/mod.rs:380
145145
msgid ""
146146
"Something went wrong while retrieving a credential. Please try again later "
147147
"or use a different authenticator."
@@ -189,11 +189,11 @@ msgstr ""
189189
msgid "Device connected. Follow the instructions on your device"
190190
msgstr ""
191191

192-
#: src/gui/view_model/gtk/mod.rs:332
192+
#: src/gui/view_model/gtk/mod.rs:333
193193
msgid "Insert your security key."
194194
msgstr ""
195195

196-
#: src/gui/view_model/gtk/mod.rs:351
196+
#: src/gui/view_model/gtk/mod.rs:352
197197
msgid "Multiple devices found. Please select with which to proceed."
198198
msgstr ""
199199

@@ -259,26 +259,32 @@ msgstr ""
259259
msgid "Failed to select credential from device."
260260
msgstr ""
261261

262-
#: src/gui/view_model/mod.rs:298 src/gui/view_model/mod.rs:358
262+
#: src/gui/view_model/mod.rs:298 src/gui/view_model/mod.rs:363
263263
msgid "No matching credentials found on this authenticator."
264264
msgstr ""
265265

266-
#: src/gui/view_model/mod.rs:302 src/gui/view_model/mod.rs:362
266+
#: src/gui/view_model/mod.rs:302 src/gui/view_model/mod.rs:367
267267
msgid ""
268268
"No more PIN attempts allowed. Try removing your device and plugging it back "
269269
"in."
270270
msgstr ""
271271

272-
#: src/gui/view_model/mod.rs:306 src/gui/view_model/mod.rs:366
272+
#: src/gui/view_model/mod.rs:306 src/gui/view_model/mod.rs:371
273273
msgid ""
274274
"This server requires your device to have additional protection like a PIN, "
275275
"which is not set. Please set a PIN for this device and try again."
276276
msgstr ""
277277

278-
#: src/gui/view_model/mod.rs:315 src/gui/view_model/mod.rs:375
278+
#: src/gui/view_model/mod.rs:310 src/gui/view_model/mod.rs:375
279+
msgid ""
280+
"The entered PIN violates the PIN-policy of this device (likely too short). "
281+
"Please try again."
282+
msgstr ""
283+
284+
#: src/gui/view_model/mod.rs:320 src/gui/view_model/mod.rs:385
279285
msgid "This credential is already registered on this authenticator."
280286
msgstr ""
281287

282-
#: src/gui/view_model/mod.rs:424
288+
#: src/gui/view_model/mod.rs:434
283289
msgid "Something went wrong. Try again later or use a different authenticator."
284290
msgstr ""

credentialsd-ui/po/de_DE.po

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ msgstr ""
33
"Project-Id-Version: PACKAGE VERSION\n"
44
"Report-Msgid-Bugs-To: \"https://github.com/linux-credentials/credentialsd/"
55
"issues\"\n"
6-
"POT-Creation-Date: 2026-02-11 14:31+0100\n"
6+
"POT-Creation-Date: 2026-02-12 14:18+0100\n"
77
"PO-Revision-Date: 2025-10-10 14:45+0200\n"
88
"Last-Translator: Martin Sirringhaus <martin.sirringhaus@suse.com>\n"
99
"Language: de_DE\n"
@@ -14,7 +14,7 @@ msgstr ""
1414

1515
#: data/xyz.iinuwa.credentialsd.CredentialsUi.desktop.in.in:2
1616
#: data/xyz.iinuwa.credentialsd.CredentialsUi.metainfo.xml.in.in:8
17-
#: src/gui/view_model/gtk/mod.rs:400
17+
#: src/gui/view_model/gtk/mod.rs:401
1818
msgid "Credential Manager"
1919
msgstr "Zugangsdatenmanager"
2020

@@ -128,8 +128,8 @@ msgstr "Fertig!"
128128
msgid "Something went wrong."
129129
msgstr "Etwas ist schief gegangen."
130130

131-
#: data/resources/ui/window.ui:304 src/gui/view_model/mod.rs:310
132-
#: src/gui/view_model/mod.rs:370
131+
#: data/resources/ui/window.ui:304 src/gui/view_model/mod.rs:315
132+
#: src/gui/view_model/mod.rs:380
133133
msgid ""
134134
"Something went wrong while retrieving a credential. Please try again later "
135135
"or use a different authenticator."
@@ -183,11 +183,11 @@ msgstr ""
183183
msgid "Device connected. Follow the instructions on your device"
184184
msgstr "Verbindung hergestellt. Folgen Sie den Anweisungen auf Ihrem Gerät."
185185

186-
#: src/gui/view_model/gtk/mod.rs:332
186+
#: src/gui/view_model/gtk/mod.rs:333
187187
msgid "Insert your security key."
188188
msgstr "Stecken Sie Ihren Security-Token ein."
189189

190-
#: src/gui/view_model/gtk/mod.rs:351
190+
#: src/gui/view_model/gtk/mod.rs:352
191191
msgid "Multiple devices found. Please select with which to proceed."
192192
msgstr "Mehrere Geräte gefunden. Bitte wählen Sie einen aus, um fortzufahren."
193193

@@ -259,19 +259,19 @@ msgstr ""
259259
msgid "Failed to select credential from device."
260260
msgstr "Zugangsdaten vom Gerät konnten nicht ausgewählt werden."
261261

262-
#: src/gui/view_model/mod.rs:298 src/gui/view_model/mod.rs:358
262+
#: src/gui/view_model/mod.rs:298 src/gui/view_model/mod.rs:363
263263
msgid "No matching credentials found on this authenticator."
264264
msgstr "Keine passenden Zugangsdaten auf diesem Gerät gefunden."
265265

266-
#: src/gui/view_model/mod.rs:302 src/gui/view_model/mod.rs:362
266+
#: src/gui/view_model/mod.rs:302 src/gui/view_model/mod.rs:367
267267
msgid ""
268268
"No more PIN attempts allowed. Try removing your device and plugging it back "
269269
"in."
270270
msgstr ""
271271
"Keine weiteren PIN-Eingaben erlaubt. Versuchen Sie ihr Gerät aus- und wieder "
272272
"einzustecken."
273273

274-
#: src/gui/view_model/mod.rs:306 src/gui/view_model/mod.rs:366
274+
#: src/gui/view_model/mod.rs:306 src/gui/view_model/mod.rs:371
275275
msgid ""
276276
"This server requires your device to have additional protection like a PIN, "
277277
"which is not set. Please set a PIN for this device and try again."
@@ -280,11 +280,19 @@ msgstr ""
280280
"einen PIN. Bitte setzen Sie einen PIN für ihr Gerät und versuchen Sie es "
281281
"erneut."
282282

283-
#: src/gui/view_model/mod.rs:315 src/gui/view_model/mod.rs:375
283+
#: src/gui/view_model/mod.rs:310 src/gui/view_model/mod.rs:375
284+
msgid ""
285+
"The entered PIN violates the PIN-policy of this device (likely too short). "
286+
"Please try again."
287+
msgstr ""
288+
"Der eingegebene PIN entspricht nicht den PIN-Bestimmungen des Geräts (z.B. "
289+
"zu kurz). Bitte versuchen Sie es erneut."
290+
291+
#: src/gui/view_model/mod.rs:320 src/gui/view_model/mod.rs:385
284292
msgid "This credential is already registered on this authenticator."
285293
msgstr "Diese Zugangsdaten sind bereits auf diesem Gerät registriert."
286294

287-
#: src/gui/view_model/mod.rs:424
295+
#: src/gui/view_model/mod.rs:434
288296
msgid "Something went wrong. Try again later or use a different authenticator."
289297
msgstr ""
290298
"Es ist ein Fehler aufgetreten. Bitte versuchen Sie es später noch einmal, "

credentialsd-ui/po/en_US.po

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ msgid ""
22
msgstr ""
33
"Report-Msgid-Bugs-To: \"https://github.com/linux-credentials/credentialsd/"
44
"issues\"\n"
5-
"POT-Creation-Date: 2026-02-11 14:31+0100\n"
5+
"POT-Creation-Date: 2026-02-12 14:18+0100\n"
66
"PO-Revision-Date: 2025-10-10 14:45+0200\n"
77
"Last-Translator: Martin Sirringhaus <martin.sirringhaus@suse.com>\n"
88
"Language: en_US\n"
@@ -13,7 +13,7 @@ msgstr ""
1313

1414
#: data/xyz.iinuwa.credentialsd.CredentialsUi.desktop.in.in:2
1515
#: data/xyz.iinuwa.credentialsd.CredentialsUi.metainfo.xml.in.in:8
16-
#: src/gui/view_model/gtk/mod.rs:400
16+
#: src/gui/view_model/gtk/mod.rs:401
1717
msgid "Credential Manager"
1818
msgstr "Credential Manager"
1919

@@ -129,8 +129,8 @@ msgstr "Done!"
129129
msgid "Something went wrong."
130130
msgstr "Something went wrong."
131131

132-
#: data/resources/ui/window.ui:304 src/gui/view_model/mod.rs:310
133-
#: src/gui/view_model/mod.rs:370
132+
#: data/resources/ui/window.ui:304 src/gui/view_model/mod.rs:315
133+
#: src/gui/view_model/mod.rs:380
134134
msgid ""
135135
"Something went wrong while retrieving a credential. Please try again later "
136136
"or use a different authenticator."
@@ -182,11 +182,11 @@ msgstr ""
182182
msgid "Device connected. Follow the instructions on your device"
183183
msgstr "Device connected. Follow the instructions on your device"
184184

185-
#: src/gui/view_model/gtk/mod.rs:332
185+
#: src/gui/view_model/gtk/mod.rs:333
186186
msgid "Insert your security key."
187187
msgstr "Insert your security key."
188188

189-
#: src/gui/view_model/gtk/mod.rs:351
189+
#: src/gui/view_model/gtk/mod.rs:352
190190
msgid "Multiple devices found. Please select with which to proceed."
191191
msgstr "Multiple devices found. Please select with which to proceed."
192192

@@ -256,31 +256,39 @@ msgstr ""
256256
msgid "Failed to select credential from device."
257257
msgstr "Failed to select credential from device."
258258

259-
#: src/gui/view_model/mod.rs:298 src/gui/view_model/mod.rs:358
259+
#: src/gui/view_model/mod.rs:298 src/gui/view_model/mod.rs:363
260260
msgid "No matching credentials found on this authenticator."
261261
msgstr "No matching credentials found on this authenticator."
262262

263-
#: src/gui/view_model/mod.rs:302 src/gui/view_model/mod.rs:362
263+
#: src/gui/view_model/mod.rs:302 src/gui/view_model/mod.rs:367
264264
msgid ""
265265
"No more PIN attempts allowed. Try removing your device and plugging it back "
266266
"in."
267267
msgstr ""
268268
"No more PIN attempts allowed. Try removing your device and plugging it back "
269269
"in."
270270

271-
#: src/gui/view_model/mod.rs:306 src/gui/view_model/mod.rs:366
271+
#: src/gui/view_model/mod.rs:306 src/gui/view_model/mod.rs:371
272272
msgid ""
273273
"This server requires your device to have additional protection like a PIN, "
274274
"which is not set. Please set a PIN for this device and try again."
275275
msgstr ""
276276
"This server requires your device to have additional protection like a PIN, "
277277
"which is not set. Please set a PIN for this device and try again."
278278

279-
#: src/gui/view_model/mod.rs:315 src/gui/view_model/mod.rs:375
279+
#: src/gui/view_model/mod.rs:310 src/gui/view_model/mod.rs:375
280+
msgid ""
281+
"The entered PIN violates the PIN-policy of this device (likely too short). "
282+
"Please try again."
283+
msgstr ""
284+
"The entered PIN violates the PIN-policy of this device (likely too short). "
285+
"Please try again."
286+
287+
#: src/gui/view_model/mod.rs:320 src/gui/view_model/mod.rs:385
280288
msgid "This credential is already registered on this authenticator."
281289
msgstr "This credential is already registered on this authenticator."
282290

283-
#: src/gui/view_model/mod.rs:424
291+
#: src/gui/view_model/mod.rs:434
284292
msgid "Something went wrong. Try again later or use a different authenticator."
285293
msgstr ""
286294
"Something went wrong. Try again later or use a different authenticator."

credentialsd-ui/src/gui/view_model/gtk/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ impl ViewModel {
213213
view_model.set_start_setting_new_pin_visible(matches!(
214214
&error,
215215
ViewUpdateFailure::PinNotSet(_)
216+
| ViewUpdateFailure::PinPolicyViolation(_)
216217
));
217218
// These are already gettext messages
218219
view_model.set_prompt(error.into_string());

credentialsd-ui/src/gui/view_model/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,11 @@ impl<F: FlowController + Send> ViewModel<F> {
305305
Error::PinNotSet => ViewUpdateFailure::PinNotSet(gettext(
306306
"This server requires your device to have additional protection like a PIN, which is not set. Please set a PIN for this device and try again.",
307307
)),
308+
Error::PinPolicyViolation => {
309+
ViewUpdateFailure::PinPolicyViolation(gettext(
310+
"The entered PIN violates the PIN-policy of this device (likely too short). Please try again.",
311+
))
312+
}
308313
Error::AuthenticatorError | Error::Internal(_) => {
309314
ViewUpdateFailure::GeneralFailure(gettext(
310315
"Something went wrong while retrieving a credential. Please try again later or use a different authenticator.",
@@ -365,6 +370,11 @@ impl<F: FlowController + Send> ViewModel<F> {
365370
Error::PinNotSet => ViewUpdateFailure::PinNotSet(gettext(
366371
"This server requires your device to have additional protection like a PIN, which is not set. Please set a PIN for this device and try again.",
367372
)),
373+
Error::PinPolicyViolation => {
374+
ViewUpdateFailure::PinPolicyViolation(gettext(
375+
"The entered PIN violates the PIN-policy of this device (likely too short). Please try again.",
376+
))
377+
}
368378
Error::AuthenticatorError | Error::Internal(_) => {
369379
ViewUpdateFailure::GeneralFailure(gettext(
370380
"Something went wrong while retrieving a credential. Please try again later or use a different authenticator.",

credentialsd/src/credential_service/nfc.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use libwebauthn::{
88
pin::PinManagement,
99
proto::CtapError,
1010
transport::{nfc::device::NfcDevice, Channel, Device},
11-
webauthn::{Error as WebAuthnError, WebAuthn},
11+
webauthn::{Error as WebAuthnError, PlatformError, WebAuthn},
1212
UvUpdate,
1313
};
1414
use tokio::sync::broadcast;
@@ -261,6 +261,9 @@ async fn handle_events(
261261
.map_err(|err| match err {
262262
WebAuthnError::Ctap(CtapError::PINAuthBlocked) => Error::PinAttemptsExhausted,
263263
WebAuthnError::Ctap(CtapError::PINNotSet) => Error::PinNotSet,
264+
WebAuthnError::Platform(PlatformError::PinTooShort)
265+
| WebAuthnError::Platform(PlatformError::PinTooLong)
266+
| WebAuthnError::Ctap(CtapError::PINPolicyViolation) => Error::PinPolicyViolation,
264267
WebAuthnError::Ctap(CtapError::NoCredentials) => Error::NoCredentials,
265268
WebAuthnError::Ctap(CtapError::CredentialExcluded) => Error::CredentialExcluded,
266269
_ => Error::AuthenticatorError,

credentialsd/src/credential_service/usb.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use libwebauthn::{
1111
hid::{channel::HidChannelHandle, HidDevice},
1212
Channel, Device,
1313
},
14-
webauthn::{Error as WebAuthnError, WebAuthn},
14+
webauthn::{Error as WebAuthnError, PlatformError, WebAuthn},
1515
UvUpdate,
1616
};
1717
use tokio::sync::broadcast;
@@ -351,6 +351,9 @@ async fn handle_events(
351351
.map_err(|err| match err {
352352
WebAuthnError::Ctap(CtapError::PINAuthBlocked) => Error::PinAttemptsExhausted,
353353
WebAuthnError::Ctap(CtapError::PINNotSet) => Error::PinNotSet,
354+
WebAuthnError::Platform(PlatformError::PinTooShort)
355+
| WebAuthnError::Platform(PlatformError::PinTooLong)
356+
| WebAuthnError::Ctap(CtapError::PINPolicyViolation) => Error::PinPolicyViolation,
354357
WebAuthnError::Ctap(CtapError::NoCredentials) => Error::NoCredentials,
355358
WebAuthnError::Ctap(CtapError::CredentialExcluded) => Error::CredentialExcluded,
356359
_ => Error::AuthenticatorError,

0 commit comments

Comments
 (0)