Skip to content

Commit

Permalink
Merge PR #1410
Browse files Browse the repository at this point in the history
  • Loading branch information
AdamVe committed Feb 20, 2024
2 parents 7318c8b + ae6b1ff commit 2d16bf9
Show file tree
Hide file tree
Showing 23 changed files with 264 additions and 158 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/env
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
FLUTTER=3.16.9
PYVER=3.12.1
PYVER=3.12.2
1 change: 1 addition & 0 deletions .github/workflows/linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ jobs:

- name: Install dependencies
run: |
echo "PYVER=3.12.1" >> $GITHUB_ENV # Remove once 3.12.2 is available from PPA
export PYVER_MINOR=${PYVER%.*}
echo "PYVER_MINOR: $PYVER_MINOR"
apt-get update
Expand Down
15 changes: 15 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
* Version 6.4.0 (released 2024-02-20)
** UI: Major UI overhaul, with improvements including:
*** Add new UI layouts for wider windows to better utilize screen space.
*** Add YubiKey personalization through custom naming and theme color.
*** Split FIDO/WebAuthn into multiple sections.
*** Move factory reset functionality into a single dialog, from the individual sections.
** Add support for Yubico OTP provisioning.
** PIV: Display more information about keys and certificates.
** PIV: Add output format for public key when generating keys.
** Desktop: Window hidden/shown state no longer saved when closing the app,
use --hidden to start the app in a hidden to systray state.
** Desktop: Fix FIDO reset over NFC.
** Windows: Add option to launch Windows Settings for FIDO management.
** Android: Increase read timeout for NFC, improving compatibility with older YubiKeys.

* Version 6.3.1 (released 2023-12-12)
** Add command line options: --hidden/--shown, --log-file FILE.
** Disable autocorrect in text fields.
Expand Down
10 changes: 6 additions & 4 deletions helper/helper/fido.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,12 @@ def _prepare_reset_nfc(device, event, signal):
removed = False
while not event.wait(0.5):
try:
with dev.open_connection(FidoConnection):
if removed:
sleep(1.0) # Wait for the device to settle
return dev.open_connection(FidoConnection)
conn = dev.open_connection(FidoConnection)
if removed:
conn.close()
sleep(1.0) # Wait for the device to settle
return dev.open_connection(FidoConnection)
conn.close()
except CardConnectionException:
pass # Expected, ignore
except NoCardException:
Expand Down
21 changes: 13 additions & 8 deletions helper/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions helper/version_info.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ VSVersionInfo(
ffi=FixedFileInfo(
# filevers and prodvers should be always a tuple with four items: (1, 2, 3, 4)
# Set not needed items to zero 0.
filevers=(6, 4, 0, 0),
prodvers=(6, 4, 0, 0),
filevers=(6, 4, 1, 0),
prodvers=(6, 4, 1, 0),
# Contains a bitmask that specifies the valid bits 'flags'r
mask=0x3f,
# Contains a bitmask that specifies the Boolean attributes of the file.
Expand All @@ -31,11 +31,11 @@ VSVersionInfo(
'040904b0',
[StringStruct('CompanyName', 'Yubico'),
StringStruct('FileDescription', 'Yubico Authenticator Helper'),
StringStruct('FileVersion', '6.4.0-dev.0'),
StringStruct('FileVersion', '6.4.1-dev.0'),
StringStruct('LegalCopyright', 'Copyright (c) Yubico'),
StringStruct('OriginalFilename', 'authenticator-helper.exe'),
StringStruct('ProductName', 'Yubico Authenticator'),
StringStruct('ProductVersion', '6.4.0-dev.0')])
StringStruct('ProductVersion', '6.4.1-dev.0')])
]),
VarFileInfo([VarStruct('Translation', [1033, 1200])])
]
Expand Down
2 changes: 1 addition & 1 deletion lib/app/views/elevate_fido_buttons.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class ElevateFidoButtons extends ConsumerWidget {
duration: const Duration(seconds: 30));
try {
if (await ref.read(rpcProvider).requireValue.elevate()) {
ref.invalidate(rpcProvider);
ref.invalidate(rpcStateProvider);
} else {
await ref.read(withContextProvider)((context) async =>
showMessage(context, l10n.s_permission_denied));
Expand Down
52 changes: 37 additions & 15 deletions lib/app/views/reset_dialog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/

import 'dart:async';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
Expand All @@ -25,6 +26,7 @@ import '../../app/logging.dart';
import '../../core/models.dart';
import '../../core/state.dart';
import '../../desktop/models.dart';
import '../../desktop/state.dart';
import '../../fido/models.dart';
import '../../fido/state.dart';
import '../../management/models.dart';
Expand All @@ -36,6 +38,7 @@ import '../features.dart' as features;
import '../message.dart';
import '../models.dart';
import '../state.dart';
import 'elevate_fido_buttons.dart';
import 'keys.dart';

final _log = Logger('fido.views.reset_dialog');
Expand Down Expand Up @@ -68,12 +71,19 @@ class _ResetDialogState extends ConsumerState<ResetDialog> {
StreamSubscription<InteractionEvent>? _subscription;
InteractionEvent? _interaction;
int _currentStep = -1;
final _totalSteps = 3;
late final int _totalSteps;

@override
void initState() {
super.initState();
final nfc = widget.data.node.transport == Transport.nfc;
_totalSteps = nfc ? 2 : 3;
}

String _getMessage() {
final l10n = AppLocalizations.of(context)!;
final nfc = widget.data.node.transport == Transport.nfc;
if (_currentStep == 3) {
if (_currentStep == _totalSteps) {
return l10n.l_fido_app_reset;
}
return switch (_interaction) {
Expand All @@ -99,20 +109,26 @@ class _ResetDialogState extends ConsumerState<ResetDialog> {
.contains(widget.data.info.formFactor);
final globalReset = isBio && (supported & Capability.piv.value) != 0;
final l10n = AppLocalizations.of(context)!;

double progress = _currentStep == -1 ? 0.0 : _currentStep / (_totalSteps);
final needsElevation = Platform.isWindows &&
_application == Capability.fido2 &&
!ref.watch(rpcStateProvider.select((state) => state.isAdmin));

return ResponsiveDialog(
title: Text(l10n.s_factory_reset),
key: factoryResetCancel,
onCancel: switch (_application) {
Capability.fido2 => _currentStep < 3
Capability.fido2 => _currentStep < _totalSteps
? () {
_currentStep = -1;
_subscription?.cancel();
}
: null,
_ => null,
},
actions: [
if (_currentStep < 3)
if (_currentStep < _totalSteps)
TextButton(
onPressed: switch (_application) {
Capability.fido2 => _subscription == null
Expand Down Expand Up @@ -222,7 +238,8 @@ class _ResetDialogState extends ConsumerState<ResetDialog> {
: null,
tooltip:
!showLabels ? c.getDisplayName(l10n) : null,
enabled: enabled & c.value != 0,
enabled:
enabled & c.value != 0 && (_currentStep == -1),
))
.toList(),
selected: _application != null ? {_application!} : {},
Expand All @@ -247,16 +264,21 @@ class _ResetDialogState extends ConsumerState<ResetDialog> {
.bodyMedium
?.copyWith(fontWeight: FontWeight.w700),
),
Text(
switch (_application) {
Capability.oath => l10n.p_warning_disable_credentials,
Capability.piv => l10n.p_warning_piv_reset_desc,
Capability.fido2 => l10n.p_warning_disable_accounts,
_ => globalReset
? l10n.p_warning_global_reset_desc
: l10n.p_factory_reset_desc,
},
),
if (needsElevation) ...[
Text(l10n.p_elevated_permissions_required),
const ElevateFidoButtons(),
] else ...[
Text(
switch (_application) {
Capability.oath => l10n.p_warning_disable_credentials,
Capability.piv => l10n.p_warning_piv_reset_desc,
Capability.fido2 => l10n.p_warning_disable_accounts,
_ => globalReset
? l10n.p_warning_global_reset_desc
: l10n.p_factory_reset_desc,
},
),
],
if (_application == Capability.fido2 && _currentStep >= 0) ...[
Text('${l10n.s_status}: ${_getMessage()}'),
LinearProgressIndicator(value: progress)
Expand Down
1 change: 1 addition & 0 deletions lib/l10n/app_de.arb
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,7 @@
"l_import_nothing": null,
"l_importing_file": null,
"s_file_imported": null,
"l_unsupported_key_type": null,
"l_delete_certificate": null,
"l_delete_certificate_desc": null,
"s_issuer": null,
Expand Down
1 change: 1 addition & 0 deletions lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,7 @@
"l_import_nothing": "Nothing to import",
"l_importing_file": "Importing file\u2026",
"s_file_imported": "File imported",
"l_unsupported_key_type": "Unsupported key type",
"l_delete_certificate": "Delete certificate",
"l_delete_certificate_desc": "Remove the certificate from your YubiKey",
"s_issuer": "Issuer",
Expand Down
1 change: 1 addition & 0 deletions lib/l10n/app_fr.arb
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,7 @@
"l_import_nothing": null,
"l_importing_file": "Importation d'un fichier\u2026",
"s_file_imported": "Fichier importé",
"l_unsupported_key_type": null,
"l_delete_certificate": "Supprimer un certificat",
"l_delete_certificate_desc": "Supprimer un certificat de votre YubiKey",
"s_issuer": "Émetteur",
Expand Down
1 change: 1 addition & 0 deletions lib/l10n/app_ja.arb
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,7 @@
"l_import_nothing": null,
"l_importing_file": "ファイルのインポート中\u2026",
"s_file_imported": "ファイル をインポートしました",
"l_unsupported_key_type": null,
"l_delete_certificate": "証明書を削除",
"l_delete_certificate_desc": "YubiKeyか証明書の削除",
"s_issuer": "発行者",
Expand Down
1 change: 1 addition & 0 deletions lib/l10n/app_pl.arb
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,7 @@
"l_import_nothing": null,
"l_importing_file": "Importowanie pliku\u2026",
"s_file_imported": "Plik został zaimportowany",
"l_unsupported_key_type": null,
"l_delete_certificate": "Usuń certyfikat",
"l_delete_certificate_desc": "Usuń certyfikat z klucza YubiKey",
"s_issuer": "Wydawca",
Expand Down
2 changes: 1 addition & 1 deletion lib/otp/views/configure_static_dialog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ class _ConfigureStaticDialogState extends ConsumerState<ConfigureStaticDialog> {
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context)!;

final password = _passwordController.text.replaceAll(' ', '');
final password = _passwordController.text;
final passwordLengthValid =
password.isNotEmpty && password.length <= passwordMaxLength;
final passwordFormatValid =
Expand Down
6 changes: 5 additions & 1 deletion lib/piv/models.dart
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,11 @@ enum PinPolicy {
@JsonValue(0x02)
once,
@JsonValue(0x03)
always;
always,
@JsonValue(0x04)
matchOnce,
@JsonValue(0x05)
matchAlways;

const PinPolicy();

Expand Down
2 changes: 2 additions & 0 deletions lib/piv/models.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 3 additions & 14 deletions lib/piv/views/generate_key_dialog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import '../keys.dart' as keys;
import '../models.dart';
import '../state.dart';
import 'overwrite_confirm_dialog.dart';
import 'utils.dart';

class GenerateKeyDialog extends ConsumerStatefulWidget {
final DevicePath devicePath;
Expand Down Expand Up @@ -65,19 +66,6 @@ class _GenerateKeyDialogState extends ConsumerState<GenerateKeyDialog> {
_validToMax = DateTime.utc(now.year + 10, now.month, now.day);
}

List<KeyType> _getSupportedKeyTypes(bool isFips) => [
if (!isFips) KeyType.rsa1024,
KeyType.rsa2048,
if (widget.pivState.version.isAtLeast(5, 7)) ...[
KeyType.rsa3072,
KeyType.rsa4096,
KeyType.ed25519,
if (!isFips) KeyType.x25519,
],
KeyType.eccp256,
KeyType.eccp384,
];

@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context)!;
Expand Down Expand Up @@ -202,7 +190,8 @@ class _GenerateKeyDialogState extends ConsumerState<GenerateKeyDialog> {
runSpacing: 8.0,
children: [
ChoiceFilterChip<KeyType>(
items: _getSupportedKeyTypes(isFips),
items:
getSupportedKeyTypes(widget.pivState.version, isFips),
value: _keyType,
selected: _keyType != defaultKeyType,
itemBuilder: (value) => Text(value.getDisplayName(l10n)),
Expand Down
Loading

0 comments on commit 2d16bf9

Please sign in to comment.