Closed nycex closed 5 years ago
ugh, that's what I get for stealing code from old cargo, I guess. I'll see about porting the auth code from current cargo, but, for the time being, could you be a love and run an update with this patch to see which auth type git is trying to use?
diff --git a/src/ops/mod.rs b/src/ops/mod.rs
index aa11e32d4..72e7a78fd 100644
--- a/src/ops/mod.rs
+++ b/src/ops/mod.rs
@@ -825,17 +825,27 @@ fn with_authentication<T, F>(url: &str, mut f: F) -> T
let mut cred_helper = git2::CredentialHelper::new(url);
cred_helper.config(&cfg);
- f(&mut |url, username, allowed| if allowed.contains(CredentialType::SSH_KEY) {
- let user = username.map(|s| s.to_string())
- .or_else(|| cred_helper.username.clone())
- .unwrap_or("git".to_string());
- GitCred::ssh_key_from_agent(&user)
- } else if allowed.contains(CredentialType::USER_PASS_PLAINTEXT) {
- GitCred::credential_helper(&cfg, url, username)
- } else if allowed.contains(CredentialType::DEFAULT) {
- GitCred::default()
- } else {
- Err(GitError::from_str("no authentication available")).unwrap()
+ f(&mut |url, username, allowed| {
+ println!("user_pass_plaintext?={}", allowed.is_user_pass_plaintext());
+ println!("ssh_key?={}", allowed.is_ssh_key());
+ println!("ssh_memory?={}", allowed.is_ssh_memory());
+ println!("ssh_custom?={}", allowed.is_ssh_custom());
+ println!("default?={}", allowed.is_default());
+ println!("ssh_interactive?={}", allowed.is_ssh_interactive());
+ println!("username?={}", allowed.is_username());
+
+ if allowed.contains(CredentialType::SSH_KEY) {
+ let user = username.map(|s| s.to_string())
+ .or_else(|| cred_helper.username.clone())
+ .unwrap_or("git".to_string());
+ GitCred::ssh_key_from_agent(&user)
+ } else if allowed.contains(CredentialType::USER_PASS_PLAINTEXT) {
+ GitCred::credential_helper(&cfg, url, username)
+ } else if allowed.contains(CredentialType::DEFAULT) {
+ GitCred::default()
+ } else {
+ Err(GitError::from_str("no authentication available")).unwrap()
+ }
})
}
Ran it with the patch, it outputs the following before the error:
user_pass_plaintext?=false
ssh_key?=false
ssh_memory?=false
ssh_custom?=false
default?=false
ssh_interactive?=false
username?=true
Yep, that's as expected, then. The newest commit referenced above should resolve the issue by having ported over the auth code from the current Cargo master
, so if you would be so kind as to try it out?
It still doesn't work, as i can see from the error message it tries to use my username of my machine instead of git username or ssh key
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error { code: -1, klass: 0, message: "no authentication available: failed to authenticate when downloading repository ssh://gitlab.com/nycex/someprivateproject (tried ssh-agent, but none of the following usernames worked: \"mylocalpcusername\")" }', src/libcore/result.rs:999:5
That's... certainly interesting? Can you try with this diff, which should either fix some ported cargo logic or at least provide some diagnostics?
diff --git a/src/ops/mod.rs b/src/ops/mod.rs
index 1b20528b7..122d8e0d2 100644
--- a/src/ops/mod.rs
+++ b/src/ops/mod.rs
@@ -840,12 +840,14 @@ fn with_authentication<T, F>(url: &str, mut f: F) -> Result<T, GitError>
if allowed.contains(CredentialType::USERNAME) {
ssh_username_requested = true;
+ println!("CredentialType::USERNAME");
Err(GitError::from_str("username to be tried later"))
} else if allowed.contains(CredentialType::SSH_KEY) && !tried_ssh_key {
tried_ssh_key = true;
let username = username.unwrap();
+ println!("first round: {}", username);
ssh_agent_attempts.push(username.to_string());
GitCred::ssh_key_from_agent(username)
@@ -861,10 +863,27 @@ fn with_authentication<T, F>(url: &str, mut f: F) -> Result<T, GitError>
});
if ssh_username_requested {
- for uname in cred_helper.username.into_iter().chain(["USER", "USERNAME"].into_iter().flat_map(env::var)).chain(Some("git".to_string())) {
+ let mut attempts = Vec::new();
+ attempts.push("git".to_string());
+ if let Ok(s) = env::var("USER").or_else(|_| env::var("USERNAME")) {
+ println!("e: {}", s);
+ attempts.push(s);
+ }
+ if let Some(ref s) = cred_helper.username {
+ println!("ch: {}", s);
+ attempts.push(s.clone());
+ }
+ println!("{:?}", attempts);
+
+ while let Some(uname) = attempts.pop() {
let mut ssh_attempts = 0;
res = f(&mut |_, _, allowed| {
+ println!("{}; is_u?={}; is_sk?={}",
+ ssh_attempts,
+ allowed.contains(CredentialType::USERNAME),
+ allowed.contains(CredentialType::SSH_KEY));
+
if allowed.contains(CredentialType::USERNAME) {
return GitCred::username(&uname);
} else if allowed.contains(CredentialType::SSH_KEY) {
@@ -875,7 +894,7 @@ fn with_authentication<T, F>(url: &str, mut f: F) -> Result<T, GitError>
}
}
- Err(GitError::from_str("no authentication available"))
+ Err(GitError::from_str("no authentication available (2)"))
});
if ssh_attempts == 2 {
It doesn't fix it, but i get this output now:
CredentialType::USERNAME
e: mylocalpcusername
["git", "mylocalpcusername"]
0; is_u?=true; is_sk?=false
0; is_u?=false; is_sk?=true
1; is_u?=false; is_sk?=true
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error { code: -1, klass: 0, message: "no authentication available (2): failed to authenticate when downloading repository ssh://gitlab.com/nycex/someprivateproject (tried ssh-agent, but none of the following usernames worked: \"mylocalpcusername\")" }', src/libcore/result.rs:999:5
I don't even know why it gets my local pc username, i have nycex
set as my user.name
in my gitconfig.
That'd mean that, somehow, cargo manages to pick up that variable but we don't?..
The following diff will display whatever we do manage to pick up, and maybe that'll hold some clues, but I'm stumped, quite frankly
diff --git a/src/ops/mod.rs b/src/ops/mod.rs
index 1b20528b7..f6a4bac47 100644
--- a/src/ops/mod.rs
+++ b/src/ops/mod.rs
@@ -825,9 +825,13 @@ fn with_authentication<T, F>(url: &str, mut f: F) -> Result<T, GitError>
where F: FnMut(&mut git2::Credentials) -> Result<T, GitError>
{
let cfg = GitConfig::open_default().unwrap();
+ for ent in cfg.entries(None).unwrap().flatten() {
+ println!("{:?} {:?} {:?}", ent.name(), ent.value(), ent.level());
+ }
let mut cred_helper = git2::CredentialHelper::new(url);
cred_helper.config(&cfg);
+ println!("{:?}", cred_helper.username);
let mut ssh_username_requested = false;
let mut cred_helper_bad = None;
The GitConfig does manage to pick it up, but the CredentialHelper doesn't as i see it:
Some("user.email") Some("nycex@protonmail.com") XDG
Some("user.name") Some("nycex") XDG
Some("user.signingkey") Some("censored") XDG
Some("color.ui") Some("true") XDG
Some("core.editor") Some("nvim") XDG
Some("alias.exclude") Some("update-index --assume-unchanged") XDG
Some("alias.include") Some("update-index --no-assume-unchanged") XDG
Some("filter.lfs.clean") Some("git-lfs clean -- %f") XDG
Some("filter.lfs.smudge") Some("git-lfs smudge -- %f") XDG
Some("filter.lfs.process") Some("git-lfs filter-process") XDG
Some("filter.lfs.required") Some("true") XDG
Some("commit.gpgsign") Some("true") XDG
None
Oh, it looks like CredentialHelper
just doesn't use that key? Interesting how cargo's updater manages to work, then.
Anyway, I added an explicit attempt over the user.name
key in the commit above, so it'd be great if you could try with that.
If it doesn't work, then the following diff will show some diagnostics:
diff --git a/src/ops/mod.rs b/src/ops/mod.rs
index 4fc18030c..7fffe6a3b 100644
--- a/src/ops/mod.rs
+++ b/src/ops/mod.rs
@@ -861,6 +861,16 @@ fn with_authentication<T, F>(url: &str, mut f: F) -> Result<T, GitError>
});
if ssh_username_requested {
+ println!("{:?}", cfg.get_string("user.name"));
+ println!("{:#?}",
+ cred_helper.username
+ .clone()
+ .into_iter()
+ .chain(cfg.get_string("user.name"))
+ .chain(["USERNAME", "USER"].into_iter().flat_map(env::var))
+ .chain(Some("git").into_iter().map(str::to_string))
+ .collect::<Vec<_>>());
+
// NOTE: this is the only divergence from the original cargo code: we also try cfg["user.name"]
// see https://github.com/nabijaczleweli/cargo-update/issues/110#issuecomment-533091965 for explanation
for uname in cred_helper.username
@@ -871,6 +881,12 @@ fn with_authentication<T, F>(url: &str, mut f: F) -> Result<T, GitError>
let mut ssh_attempts = 0;
res = f(&mut |_, _, allowed| {
+ println!("{} {} is_u?={} is_sk?={}",
+ ssh_attempts,
+ uname,
+ allowed.contains(CredentialType::USERNAME),
+ allowed.contains(CredentialType::SSH_KEY));
+
if allowed.contains(CredentialType::USERNAME) {
return GitCred::username(&uname);
} else if allowed.contains(CredentialType::SSH_KEY) {
It does pick up the correct username now, but it still doesn't use the ssh-agent key. That's the output with the last two patches applied, if that helps:
Some("user.email") Some("nycex@protonmail.com") XDG
Some("user.name") Some("nycex") XDG
Some("user.signingkey") Some("censored") XDG
Some("color.ui") Some("true") XDG
Some("core.editor") Some("nvim") XDG
Some("alias.exclude") Some("update-index --assume-unchanged") XDG
Some("alias.include") Some("update-index --no-assume-unchanged") XDG
Some("filter.lfs.clean") Some("git-lfs clean -- %f") XDG
Some("filter.lfs.smudge") Some("git-lfs smudge -- %f") XDG
Some("filter.lfs.process") Some("git-lfs filter-process") XDG
Some("filter.lfs.required") Some("true") XDG
Some("commit.gpgsign") Some("true") XDG
None
Ok("nycex")
[
"nycex",
"localpcusername",
"git",
]
0 nycex is_u?=true is_sk?=false
0 nycex is_u?=false is_sk?=true
1 nycex is_u?=false is_sk?=true
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error { code: -1, klass: 0, message: "no authentication available: failed to authenticate when downloading repository ssh://gitlab.com/nycex/someprivateproject (tried ssh-agent, but none of the following usernames worked: \"nycex\")" }', src/libcore/result.rs:999:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
Maybe ssh_key_from_agent()
is failing somehow? This patch might show why, but I'm grasping at straws, quite frankly
diff --git a/src/ops/mod.rs b/src/ops/mod.rs
index 4fc18030c..a71ed6c9e 100644
--- a/src/ops/mod.rs
+++ b/src/ops/mod.rs
@@ -877,7 +877,10 @@ fn with_authentication<T, F>(url: &str, mut f: F) -> Result<T, GitError>
ssh_attempts += 1;
if ssh_attempts == 1 {
ssh_agent_attempts.push(uname.to_string());
- return git2::Cred::ssh_key_from_agent(&uname);
+ let ret = git2::Cred::ssh_key_from_agent(&uname);
+ println!("agent type: {:?}", ret.as_ref().ok().map(|c| c.credtype()));
+ println!("agent err: {:?}", ret.as_ref().err());
+ return ret;
}
}
well it should be working
agent type: Some(2)
agent err: None
oh damn you're right, I fucked up copying the condition, so with the commit it should work?
And if it doesn't then this patch should?
diff --git a/src/ops/mod.rs b/src/ops/mod.rs
index 4c9b52f8d..57821e0ce 100644
--- a/src/ops/mod.rs
+++ b/src/ops/mod.rs
@@ -883,8 +883,9 @@ fn with_authentication<T, F>(url: &str, mut f: F) -> Result<T, GitError>
Err(GitError::from_str("no authentication available"))
});
+ println!("{:?}", res.as_ref().err());
- if ssh_attempts != 2 {
+ if res.is_ok() || ssh_attempts != 2 {
break;
}
}
Now it works as intended. Thank you (the patch is not needed)
Thanks for sticking with me through this.
Released in v1.8.3
.
I'm using the keepassxc ssh-agent function and it works with
ssh
,git
andcargo install
, but withcargo install-update
i get the following error when doingcargo install-update -ga
:backtrace:
Edit: I'm using
cargo install --git ssh://gitlab.com/nycex/someprivateproject --force
to install the packages