Correctly hunt agents in plugin mode
This commit is contained in:
@@ -11,6 +11,10 @@ to 0.3.0 are beta releases.
|
|||||||
- The "sharing violation" logic now also sends SIGHUP to any `yubikey-agent`
|
- The "sharing violation" logic now also sends SIGHUP to any `yubikey-agent`
|
||||||
that is running, to have them release any YubiKey locks they are holding.
|
that is running, to have them release any YubiKey locks they are holding.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- The "sharing violation" logic now runs during plugin mode as intended. In the
|
||||||
|
previous release it only ran during direct `age-plugin-yubikey` usage.
|
||||||
|
|
||||||
## [0.3.1] - 2022-12-30
|
## [0.3.1] - 2022-12-30
|
||||||
### Changed
|
### Changed
|
||||||
- If a "sharing violation" error is encountered while opening a connection to a
|
- If a "sharing violation" error is encountered while opening a connection to a
|
||||||
|
|||||||
+44
-2
@@ -8,7 +8,7 @@ use age_core::{
|
|||||||
use age_plugin::{identity, Callbacks};
|
use age_plugin::{identity, Callbacks};
|
||||||
use bech32::{ToBase32, Variant};
|
use bech32::{ToBase32, Variant};
|
||||||
use dialoguer::Password;
|
use dialoguer::Password;
|
||||||
use log::{debug, warn};
|
use log::{debug, error, warn};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
@@ -156,7 +156,49 @@ pub(crate) fn open_connection(reader: &Reader) -> Result<YubiKey, yubikey::Error
|
|||||||
/// This is equivalent to [`YubiKey::open_by_serial`], but additionally handles the
|
/// This is equivalent to [`YubiKey::open_by_serial`], but additionally handles the
|
||||||
/// presence of agents (which can indefinitely hold exclusive access to a YubiKey).
|
/// presence of agents (which can indefinitely hold exclusive access to a YubiKey).
|
||||||
fn open_by_serial(serial: Serial) -> Result<YubiKey, yubikey::Error> {
|
fn open_by_serial(serial: Serial) -> Result<YubiKey, yubikey::Error> {
|
||||||
open_sesame(|| YubiKey::open_by_serial(serial))
|
// `YubiKey::open_by_serial` has a bug where it ignores all opening errors, even if
|
||||||
|
// it potentially could have found a matching YubiKey if not for an error, and thus
|
||||||
|
// returns `Error::NotFound` if another agent is holding exclusive access to the
|
||||||
|
// required YubiKey. This gives misleading UX behaviour where age-plugin-yubikey asks
|
||||||
|
// the user to insert a YubiKey they have already inserted.
|
||||||
|
//
|
||||||
|
// For now, we instead implement the correct behaviour manually. Once MSRV has been
|
||||||
|
// raised to 1.60, we can upstream this into the `yubikey` crate.
|
||||||
|
open_sesame(|| {
|
||||||
|
let mut readers = Context::open()?;
|
||||||
|
|
||||||
|
let mut open_error = None;
|
||||||
|
|
||||||
|
for reader in readers.iter()? {
|
||||||
|
let yubikey = match reader.open() {
|
||||||
|
Ok(yk) => yk,
|
||||||
|
Err(e) => {
|
||||||
|
// Save the first error we see that indicates we might have been able
|
||||||
|
// to find a matching YubiKey.
|
||||||
|
if open_error.is_none() {
|
||||||
|
if let yubikey::Error::PcscError {
|
||||||
|
inner: Some(pcsc::Error::SharingViolation),
|
||||||
|
} = e
|
||||||
|
{
|
||||||
|
open_error = Some(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if serial == yubikey.serial() {
|
||||||
|
return Ok(yubikey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(if let Some(e) = open_error {
|
||||||
|
e
|
||||||
|
} else {
|
||||||
|
error!("no YubiKey detected with serial: {}", serial);
|
||||||
|
yubikey::Error::NotFound
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn open(serial: Option<Serial>) -> Result<YubiKey, Error> {
|
pub(crate) fn open(serial: Option<Serial>) -> Result<YubiKey, Error> {
|
||||||
|
|||||||
Reference in New Issue
Block a user