Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [egit-dev] [Bug] Passphrases not cached in Oxygen

On January 4, 2018 1:51 PM, Matthias Sohn wrote:
>On Thu, Jan 4, 2018 at 7:50 PM, Matthias Sohn <mailto:matthias.sohn@xxxxxxxxx> wrote:
>>On Sun, Dec 31, 2017 at 1:29 AM, Randall S. Becker <mailto:rsbecker@xxxxxxxxxxxxx> wrote:
>>Hi EGit Devs,
>>I've been trying to figure out why in 4.9.2 (with Eclipse Oxygen), SSH
>>passphrases are no longer cached. I opened a case
>>https://bugs.eclipse.org/bugs/show_bug.cgi?id=529173 on this, but would like
>>to follow up to see whether I can debug the situation. I have a .ssh/config
>>in play with mixed-case hosts names. Any pointers on which class/method to
>>break on would help.

>JschConfigSessionFactory.getSession() creates the ssh session. It seems when
>the host entry in ~/.ssh/config configures the IdentityFile the JSch session is cached
>and reused, otherwise a new one seems to be created for each remote call over ssh.
>I don't know yet why.

>com.jcraft.jsch.UserAuthPublicKey.start() initiates prompting for the passphrase in line 121
>which is implemented by org.eclipse.jgit.transport.CredentialsProviderUserInfo
>The passphrase dialog is implemented in EGitCredentialsProvider.get().
>no, the other way round:
>It seems when the host entry in ~/.ssh/config does not configure the IdentityFile the JSch session is cached
>and reused, otherwise a new one seems to be created for each remote call over ssh.

Basically, to confirm, here is the difference in behaviour when using config vs. not using config relating to IdentityFile, discovered so far. This seems to have little to do with whether there are multiple entries in config or not - it's just whether there is a config file at all, which selects whether EGit or JSch manages the list of cached identities.

In the Session code:
  IdentityRepository getIdentityRepository(){
    if(identityRepository == null)
      return jsch.getIdentityRepository();
    return identityRepository;
  }

Without a config file, jsch.getIdentityRepository() is returned while if there is a config file, identityRepository is used from EGit. 

In the caller (UserAuthPublicKey), a different path is also taken:
          if(!identity.isEncrypted() || passphrase!=null){
            if(identity.setPassphrase(passphrase)){
              if(passphrase!=null &&
                 (session.getIdentityRepository() instanceof IdentityRepository.Wrapper)){
                ((IdentityRepository.Wrapper)session.getIdentityRepository()).check();
              }
              break;
            }
          }
Without a config file, the .check() method is not invoked because session.getIdentityRepository() is not a Wrapper. With a config file, .check() is called (not that that matters much). In both cases, identity.setPassphrase is used and sets the key properly, but the identity object seems to be dropped since Jsch is not managing the caching, it does not find the identity in the implemented repository, on subsequent passes through authentication. I'm not finding any code path where the identity is actually cached anywhere in EGit that is supplied back to JSch nor a mechanism to do so within its code - but that's probably just a miss on my part.

So, at the top of start(session), Vector identities=session.getIdentityRepository().getIdentities() does not include the identity because it is not stored by JSch through any path executed when config is in play.

Cheers,
Randall



Back to the top