git hanging on waiting passphrase from stdin
What steps will reproduce the problem?
- Install Win32-OpenSSH_8.9p1
- Configure a remote repo with passphrase protected public key auth
- Test in Command Prompt
git clone
works, and asking for passphrase:
>git clone ...
Enter passphrase for key 'xxx.pem'
- Using TortoiseGit to clone this repo
What is the expected output? What do you see instead?
Expected
Ask passphrase dialog popup, once passphrase entered progress continue
See
No dialog for passphrase, ssh hanging waiting passphrase from stdin
git.exe clone --progress --recursive -v "git@github.com:TortoiseGit/TortoiseGit.git" "D:\TortoiseGit"
Cloning into 'D:\TortoiseGit'...
What version of TortoiseGit and Git are you using? On what operating system?
TortoiseGit 2.13.01
Git for Windows 2.37.2
Win32-OpenSSH_8.9p1
Please provide any additional information below.
Environment variable SSH_ASKPASS
and SSH_ASKPASS_REQUIRE
are not set.
If I set SSH_ASKPASS_REQUIRE=prefer
then the issue is mitigated.
I've cloned Win32-OpenSSH to see what's going on, in read_passphrase()
of readpass.c
, it uses 2 flags allow_askpass
and use_askpass
to decide either read passphrase from stdin or use prompt.
Since in TortoiseGit only SSH_ASKPASS
is set in m_Environment.SetEnv(L"SSH_ASKPASS",sAskPass);
, it decide to read passphrase from stdin and hang forever.
I propose to set also SSH_ASKPASS_REQUIRE=force
char *
read_passphrase(const char *prompt, int flags)
{
char cr = '\r', *askpass = NULL, *ret, buf[1024];
int rppflags, ttyfd, use_askpass = 0, allow_askpass = 0;
const char *askpass_hint = NULL;
const char *s;
if ((s = getenv("DISPLAY")) != NULL)
allow_askpass = *s != '\0';
if ((s = getenv(SSH_ASKPASS_REQUIRE_ENV)) != NULL) {
if (strcasecmp(s, "force") == 0) {
use_askpass = 1;
allow_askpass = 1;
} else if (strcasecmp(s, "prefer") == 0)
use_askpass = allow_askpass;
else if (strcasecmp(s, "never") == 0)
allow_askpass = 0;
}
rppflags = (flags & RP_ECHO) ? RPP_ECHO_ON : RPP_ECHO_OFF;
if (use_askpass)
debug_f("requested to askpass");
else if (flags & RP_USE_ASKPASS)
use_askpass = 1;
else if (flags & RP_ALLOW_STDIN) {
if (!isatty(STDIN_FILENO)) {
debug_f("stdin is not a tty");
use_askpass = 1;
}
} else {
rppflags |= RPP_REQUIRE_TTY;
ttyfd = open(_PATH_TTY, O_RDWR);
if (ttyfd >= 0) {
/*
* If we're on a tty, ensure that show the prompt at
* the beginning of the line. This will hopefully
* clobber any password characters the user has
* optimistically typed before echo is disabled.
*/
(void)write(ttyfd, &cr, 1);
close(ttyfd);
} else {
debug_f("can't open %s: %s", _PATH_TTY,
strerror(errno));
use_askpass = 1;
}
}
if ((flags & RP_USE_ASKPASS) && !allow_askpass)
return (flags & RP_ALLOW_EOF) ? NULL : xstrdup("");
if (use_askpass && allow_askpass) {
if (getenv(SSH_ASKPASS_ENV))
askpass = getenv(SSH_ASKPASS_ENV);
else
askpass = _PATH_SSH_ASKPASS_DEFAULT;
#ifdef WINDOWS
if (getenv(SSH_ASKPASS_ENV)) {
#endif
if ((flags & RP_ASK_PERMISSION) != 0)
askpass_hint = "confirm";
if ((ret = ssh_askpass(askpass, prompt, askpass_hint)) == NULL)
if (!(flags & RP_ALLOW_EOF))
return xstrdup("");
return ret;
#ifdef WINDOWS
}
#endif
}
if (readpassphrase(prompt, buf, sizeof buf, rppflags) == NULL) {
if (flags & RP_ALLOW_EOF)
return NULL;
return xstrdup("");
}
ret = xstrdup(buf);
explicit_bzero(buf, sizeof(buf));
return ret;
}