Fix nested runtime panic during SSH key authentication
Dependency security audit / rustsec (push) Successful in 23s
Dependency security audit / rustsec (push) Successful in 23s
This commit is contained in:
1 parent
aec3f237a9
commit
71a4f289cf
2 files changed
+36
-14
No files matched your search
@@ -755,8 +755,21 @@ fn non_fast_forward_and_cancellation_fail_without_blind_replay() {
|
||||
local.add_remote("origin", remote.url()).expect("remote");
|
||||
let control = GitOperationControl::default();
|
||||
let cancel = control.clone();
|
||||
let observed = server.observed.clone();
|
||||
let cancellation = thread::spawn(move || {
|
||||
thread::sleep(Duration::from_millis(100));
|
||||
let deadline = std::time::Instant::now() + Duration::from_secs(5);
|
||||
while observed
|
||||
.lock()
|
||||
.expect("observed")
|
||||
.receive_requests
|
||||
.is_empty()
|
||||
{
|
||||
assert!(
|
||||
std::time::Instant::now() < deadline,
|
||||
"push request not received"
|
||||
);
|
||||
thread::sleep(Duration::from_millis(1));
|
||||
}
|
||||
cancel.cancel();
|
||||
});
|
||||
assert!(matches!(
|
||||
|
||||
+22
-13
@@ -162,13 +162,11 @@ impl SshSession {
|
||||
control.report(GitProgressPhase::Authenticating)?;
|
||||
let user = connection.user.as_deref().unwrap_or("git");
|
||||
let authenticated = match &connection.identity {
|
||||
SshIdentitySource::KeyFile(path) => runtime.block_on(authenticate_key_file(
|
||||
&mut handle,
|
||||
user,
|
||||
path,
|
||||
passphrases,
|
||||
control,
|
||||
))?,
|
||||
SshIdentitySource::KeyFile(path) => {
|
||||
// Synchronous secret stores may drive their own runtime.
|
||||
let key = load_identity(path, passphrases)?;
|
||||
runtime.block_on(authenticate_key_file(&mut handle, user, key, control))?
|
||||
}
|
||||
SshIdentitySource::Agent {
|
||||
fingerprint,
|
||||
socket,
|
||||
@@ -770,13 +768,10 @@ impl client::Handler for HostVerifier {
|
||||
}
|
||||
}
|
||||
|
||||
async fn authenticate_key_file(
|
||||
handle: &mut client::Handle<HostVerifier>,
|
||||
user: &str,
|
||||
fn load_identity(
|
||||
path: &Path,
|
||||
passphrases: &dyn SshPassphraseProvider,
|
||||
control: &GitOperationControl,
|
||||
) -> Result<bool, GitError> {
|
||||
) -> Result<PrivateKey, GitError> {
|
||||
let metadata = fs::symlink_metadata(path).map_err(|_| GitError::SshIdentityMissing {
|
||||
path: path.to_owned(),
|
||||
})?;
|
||||
@@ -802,6 +797,15 @@ async fn authenticate_key_file(
|
||||
fingerprint: fingerprint.clone(),
|
||||
})?;
|
||||
}
|
||||
Ok(key)
|
||||
}
|
||||
|
||||
async fn authenticate_key_file(
|
||||
handle: &mut client::Handle<HostVerifier>,
|
||||
user: &str,
|
||||
key: PrivateKey,
|
||||
control: &GitOperationControl,
|
||||
) -> Result<bool, GitError> {
|
||||
let hash = rsa_hash(handle, key.public_key(), control).await?;
|
||||
let result = controlled(
|
||||
handle.authenticate_publickey(user, PrivateKeyWithHashAlg::new(Arc::new(key), hash)),
|
||||
@@ -1230,7 +1234,12 @@ mod tests {
|
||||
&self,
|
||||
fingerprint: &SshFingerprint,
|
||||
) -> Result<SecretBytes, GitError> {
|
||||
self.0
|
||||
// Model a synchronous secret store that drives its own async backend.
|
||||
static RUNTIME: std::sync::OnceLock<tokio::runtime::Runtime> =
|
||||
std::sync::OnceLock::new();
|
||||
RUNTIME
|
||||
.get_or_init(|| tokio::runtime::Runtime::new().expect("secret store runtime"))
|
||||
.block_on(async { self.0 })
|
||||
.map(|value| SecretBytes::new(value.to_vec()))
|
||||
.ok_or_else(|| GitError::SshKeyPassphraseUnavailable {
|
||||
fingerprint: fingerprint.clone(),
|
||||
|
||||
Reference in new issue
Block a user