git-for-windows/git

Add an option to omit OpenSSH from the installation

bgshacklett opened this issue ยท 7 comments

  • I was not able to find an open or closed issue matching what I'm seeing

Summary

With Windows now beginning to ship its own distribution of OpenSSH, it would be useful to be able to omit the bundled OpenSSH distribution to allow the systems OpenSSH distribution to be used. At present, the two appear to conflict (the Windows ssh-agent is not detected by GFW's OpenSSH binary).

Setup

  • Which version of Git for Windows are you using? Is it 32-bit or 64-bit?
$ git --version --build-options
git version 2.16.2.windows.1
cpu: x86_64
built from commit: e1848984d1004040ec5199e749b5f282ddf4bb09
sizeof-long: 4
  • Which version of Windows are you running? Vista, 7, 8, 10? Is it 32-bit or 64-bit?
$ cmd.exe /c ver

Microsoft Windows [Version 10.0.17115.1]
(c) 2017 Microsoft Corporation. All rights reserved.
  • What options did you set as part of the installation? Or did you choose the defaults?
# One of the following:
> type "C:\Program Files\Git\etc\install-options.txt"
> type "C:\Program Files (x86)\Git\etc\install-options.txt"
> type "%USERPROFILE%\AppData\Local\Programs\Git\etc\install-options.txt"
$ cat /etc/install-options.txt

Editor Option: VIM
Path Option: Cmd
SSH Option: OpenSSH
CURL Option: WinSSL
CRLF Option: LFOnly
Bash Terminal Option: ConHost
Performance Tweaks FSCache: Enabled
Use Credential Manager: Enabled
Enable Symlinks: Enabled
  • Any other interesting things about your environment that might be related
    to the issue you're seeing?
  • Running Windows Insider Build
  • SSH Available as part of the system:
PS>gcm ssh-agent | Select Name,Version,Source

Name          Version Source
----          ------- ------
ssh-agent.exe 1.0.0.0 C:\Windows\System32\ssh-agent.exe


PS>gcm ssh | Select Name,Version,Source

Name    Version Source
----    ------- ------
ssh.exe 1.0.0.0 C:\Windows\System32\ssh.exe

Details

  • Which terminal/shell are you running Git from? e.g Bash/CMD/PowerShell/other

ConEmu + PowerShell

add-sshkey        # successful
ssh-add -l          # shows key as expected
cd $myGitRepo
git pull
  • What did you expect to occur after running these commands?

My local repository should have been updated

  • What actually happened instead?

Error:

Could not create directory '/Users/brian/.ssh'.
The authenticity of host 'github.com (192.30.253.112)' can't be established.
RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8.
Are you sure you want to continue connecting (yes/no)? yes
Failed to add the host to the list of known hosts (/Users/brian/.ssh/known_hosts).
git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
  • If the problem was occurring with a specific repository, can you provide the
    URL to that repository to help us with testing?

https://github.com/bgshacklett/extropy

Resolution

I was able to resolve the above scenario by renaming ssh.exe in the $gitPath/usr/bin directory to ssh.exe.old, forcing it to use the system's ssh.exe binary.

dscho commented

This is an excellent suggestion! I'll give you enough pointers to get started and then kick the project right back into your court.

Install the Git for Windows SDK

This is now as easy as cloning https://github.com/git-for-windows/git-sdk-64 and double-clicking the git-bash.exe in the cloned worktree. As the repository is a bit big, and you really only need the latest revision, it is best to make a shallow clone:

git clone --depth=1 https://github.com/git-for-windows/git-sdk-64

Build your first installer (just to ensure that it works)

For this, you need to call

sdk build installer

Modify the installer

This is where the fun starts. The program telling the installer what to do is in /usr/src/build-extra/installer/install.iss. You will want to open this in an editor and run sdk build installer in you Git SDK Bash to test.

Add a "component" to use the native OpenSSH

This is in the [Components] part of the program. You will already see the option for the updater (called autoupdate) and you can add the component there. I would suggest to give it the description "Use native OpenSSH".

Remove Git for Windows' bundled ssh.exe if the component is selected

A bit counterintuitively, when this "component" is enabled, we have to remove something. This should be done close to the lines adding the autoupdate feature (look for "Install a scheduled task to try to auto-update Git for Windows") and you'll see it. It should be as straight-forward as

{
    When the user prefers the native OpenSSH, use that instead of our bundled one.
}
if IsComponentInstalled('nativeopenssh') then begin
    if not DeleteFile(AppDir + '/usr/bin/ssh-add.exe') or
        not DeleteFile(AppDir + '/usr/bin/ssh-agent.exe') or
        not DeleteFile(AppDir + '/usr/bin/ssh-copy-id') or
        not DeleteFile(AppDir + '/usr/bin/ssh-keygen.exe') or
        not DeleteFile(AppDir + '/usr/bin/ssh-keyscan.exe') or
        not DeleteFile(AppDir + '/usr/bin/ssh-pageant.exe') or
        not DeleteFile(AppDir + '/usr/bin/ssh.exe') or
        not DeleteFile(AppDir + '/usr/bin/sshd.exe') then
        LogError('Line {#__LINE__}: Unable to uninstall bundled OpenSSH');
end;

Detect whether native ssh.exe is available, and hide the component otherwise

You will only want to offer this option when the native OpenSSH is available, and then make it the default. To this end, you will want to add a [Check parameter] to the component, and implement a function that tests whether native OpenSSH is available. I would imagine that native OpenSSH is installed always into the same location, or has a registry entry we can check?

Enable the component by default if native OpenSSH is available

Of course we will want to use native OpenSSH by default! (I guess...)

If this is something we will want to support, then we should enable the component by default. I found only one way to do this in a quick web search: https://stackoverflow.com/questions/32309002/inno-setup-set-default-component-depending-on-system-language#comment52493771_32309002

Essentially, you will have to add code to InitializeSetup that will cycle through WizardForm.ComponentsList.ItemCaption[i] until you find the one about native OpenSSH, and then call if (WizardForm.ComponentsList.ItemEnabled[i]) WizardForm.ComponentsList.Checked[i]:=True;.

Of course, we may want to be quite a bit more careful about that... for example, we need to make sure that the existing OpenSSH configuration (in %USERPROFILE%\.ssh) will be used by the native OpenSSH, too? Otherwise, we would break existing users' setups, which is no good...

Awesome! I'll see what I can do.

dscho commented

Note: I was just made aware that the GIT_SSH=%SystemRoot%\System32\OpenSSH\ssh.exe method does not work when using a 32-bit Git. The reason is that 32-bit processes see a different %SystemRoot%\System32 than 64-bit processes (provided they're running on a 64-bit Windows). But there is a trick to make it work, still: replace the System32 by SysNative, i.e. GIT_SSH=%SystemRoot%\SysNative\OpenSSH\ssh.exe.

One other caveat: if you have configured anything in your $HOME/.ssh/config via MSYS2-compatible paths (e.g. IdentityFile /d/keys/1st.key), the native OpenSSH won't be able to use that correctly. Users will need to change this to Windows-compatible paths, for example d:/keys/1st.key.

I don't suppose you could give me some advice on how to test a function, by chance? I think I'm about 90% of the way there, but I'm not having much luck working with PascalScript.

I just got the build-extra repo connected to my own fork. Here's a diff of what I have so far:
git-for-windows/build-extra@master...bgshacklett:1556

dscho commented

@bgshacklett my favorite way of testing a function is to call it in the code that builds the custom pages, and then running ./installer/release.sh --debug-wizard-page=Editor.

dscho commented

Hmm. This ticket has stalled. Let's close it.