225

The sysadmin for a project I'm on has decided that SSH is "too much trouble"; instead, he has set up Git to be accessible via an https:// URL (and username/password authentication). The server for this URL presents a self-signed certificate, so he advised everyone to turn off certificate validation. This does not strike me as a good setup, security-wise.

Is it possible to tell Git that for remote X (or better, any remote in any repository that happens to begin with https://$SERVERNAME/) it is to accept a particular certificate, and only that certificate? Basically reduplicate SSH's server-key behavior.

zwol
  • 135,547
  • 38
  • 252
  • 361
  • You are asking about C Git on Unix, i presume? – Piotr Findeisen Jan 31 '12 at 00:30
  • Yah. Well, conceivably also Windows, but nobody's doing that right now. – zwol Jan 31 '12 at 01:06
  • 5
    WTF? @Zack you are absolute right about the certificate checks. When your admin says you should turn off certificate checks, he can also turn off TLS on the server, since then every one is disabling the protection against a man-in-the-middle attack. – Rudi Feb 06 '12 at 12:17
  • @Rudi, is this still the case if they use an IP address to access the server? (It seems the DNS lookup is how MITM gets inbetween so I think IP address should be immune to this.) – Chris Oct 17 '14 at 10:54
  • 6
    @Chris Yes, it is still the case. A MITM router can pretend to be any IP address they want. (You know those interstitial pages you get on the free wifi in the airport? Those are MITMs. Try accessing a page by IP address sometime.) – zwol Oct 17 '14 at 13:38

3 Answers3

395

Briefly:

  1. Get the self signed certificate
  2. Put it into some (e.g. ~/git-certs/cert.pem) file
  3. Set git to trust this certificate using http.sslCAInfo parameter

In more details:

Get self signed certificate of remote server

Assuming, the server URL is repos.sample.com and you want to access it over port 443.

There are multiple options, how to get it.

Get certificate using openssl

$ openssl s_client -connect repos.sample.com:443

Catch the output into a file cert.pem and delete all but part between (and including) -BEGIN CERTIFICATE- and -END CERTIFICATE-

Content of resulting file ~/git-certs/cert.pem may look like this:

-----BEGIN CERTIFICATE-----
MIIDnzCCAocCBE/xnXAwDQYJKoZIhvcNAQEFBQAwgZMxCzAJBgNVBAYTAkRFMRUw
EwYDVQQIEwxMb3dlciBTYXhvbnkxEjAQBgNVBAcTCVdvbGZzYnVyZzEYMBYGA1UE
ChMPU2FhUy1TZWN1cmUuY29tMRowGAYDVQQDFBEqLnNhYXMtc2VjdXJlLmNvbTEj
MCEGCSqGSIb3DQEJARYUaW5mb0BzYWFzLXNlY3VyZS5jb20wHhcNMTIwNzAyMTMw
OTA0WhcNMTMwNzAyMTMwOTA0WjCBkzELMAkGA1UEBhMCREUxFTATBgNVBAgTDExv
d2VyIFNheG9ueTESMBAGA1UEBxMJV29sZnNidXJnMRgwFgYDVQQKEw9TYWFTLVNl
Y3VyZS5jb20xGjAYBgNVBAMUESouc2Fhcy1zZWN1cmUuY29tMSMwIQYJKoZIhvcN
AQkBFhRpbmZvQHNhYXMtc2VjdXJlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP
ADCCAQoCggEBAMUZ472W3EVFYGSHTgFV0LR2YVE1U//sZimhCKGFBhH3ZfGwqtu7
mzOhlCQef9nqGxgH+U5DG43B6MxDzhoP7R8e1GLbNH3xVqMHqEdcek8jtiJvfj2a
pRSkFTCVJ9i0GYFOQfQYV6RJ4vAunQioiw07OmsxL6C5l3K/r+qJTlStpPK5dv4z
Sy+jmAcQMaIcWv8wgBAxdzo8UVwIL63gLlBz7WfSB2Ti5XBbse/83wyNa5bPJPf1
U+7uLSofz+dehHtgtKfHD8XpPoQBt0Y9ExbLN1ysdR9XfsNfBI5K6Uokq/tVDxNi
SHM4/7uKNo/4b7OP24hvCeXW8oRyRzpyDxMCAwEAATANBgkqhkiG9w0BAQUFAAOC
AQEAp7S/E1ZGCey5Oyn3qwP4q+geQqOhRtaPqdH6ABnqUYHcGYB77GcStQxnqnOZ
MJwIaIZqlz+59taB6U2lG30u3cZ1FITuz+fWXdfELKPWPjDoHkwumkz3zcCVrrtI
ktRzk7AeazHcLEwkUjB5Rm75N9+dOo6Ay89JCcPKb+tNqOszY10y6U3kX3uiSzrJ
ejSq/tRyvMFT1FlJ8tKoZBWbkThevMhx7jk5qsoCpLPmPoYCEoLEtpMYiQnDZgUc
TNoL1GjoDrjgmSen4QN5QZEGTOe/dsv1sGxWC+Tv/VwUl2GqVtKPZdKtGFqI8TLn
/27/jIdVQIKvHok2P/u9tvTUQA==
-----END CERTIFICATE-----

Get certificate using your web browser

I use Redmine with Git repositories and I access the same URL for web UI and for git command line access. This way, I had to add exception for that domain into my web browser.

Using Firefox, I went to Options -> Advanced -> Certificates -> View Certificates -> Servers, found there the selfsigned host, selected it and using Export button I got exactly the same file, as created using openssl.

Note: I was a bit surprised, there is no name of the authority visibly mentioned. This is fine.

Having the trusted certificate in dedicated file

Previous steps shall result in having the certificate in some file. It does not matter, what file it is as long as it is visible to your git when accessing that domain. I used ~/git-certs/cert.pem

Note: If you need more trusted selfsigned certificates, put them into the same file:

-----BEGIN CERTIFICATE-----
MIIDnzCCAocCBE/xnXAwDQYJKoZIhvcNAQEFBQAwgZMxCzAJBgNVBAYTAkRFMRUw
...........
/27/jIdVQIKvHok2P/u9tvTUQA==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
AnOtHeRtRuStEdCeRtIfIcAtEgOeShErExxxxxxxxxxxxxxxxxxxxxxxxxxxxxxw
...........
/27/jIdVQIKvHok2P/u9tvTUQA==
-----END CERTIFICATE-----

This shall work (but I tested it only with single certificate).

Configure git to trust this certificate

$ git config --global http.sslCAInfo /home/javl/git-certs/cert.pem

You may also try to do that system wide, using --system instead of --global.

And test it: You shall now be able communicating with your server without resorting to:

$ git config --global http.sslVerify false #NO NEED TO USE THIS

If you already set your git to ignorance of ssl certificates, unset it:

$ git config --global --unset http.sslVerify

and you may also check, that you did it all correctly, without spelling errors:

$ git config --global --list

what should list all variables, you have set globally. (I mispelled http to htt).

U880D
  • 8,601
  • 6
  • 24
  • 40
Jan Vlcinsky
  • 42,725
  • 12
  • 101
  • 98
  • 3
    i think that this answer is more correct and complete than the accepted one. thank you @Jan Vlcinsky – Alfredo Cavalcanti Sep 03 '13 at 02:52
  • 2
    After that the usual authority-signed certificates stop working, so I can't pull e.g. from Github. Is there a way to add a self-signed certificate without turning off the authority signed ones? – Michael Ivko May 22 '14 at 08:02
  • On OSX 10.9 (Git 1.8.5.2 Apple Git-48) this doesn't seem to work. It looks like Git is ignoring sslCAInfo and the environment variable GIT_SSL_CAINFO. However it is possible to add the generated cert.pem to the OSX Key Ring Application (system keyring) and to set the trust level to always. Git will happily accept the self signed certificate after that. – nob Jun 12 '14 at 09:46
  • @peter_gent As I do not have access to OSX (working on Ubuntu 14.04), I cannot serve with testing on OSX. The only think I can do is to review the solution on Ubuntu, git is in time slowly evolving and some things could have change a bit. Hope to find a time for this within next week. – Jan Vlcinsky Jul 13 '14 at 13:45
  • is there a way to reconfigure git back to default settings ? – peter_gent Jul 13 '14 at 13:49
  • 4
    @MichaelIvko solution that takes into account 'usual authority-signed certificates' descried here (you need to add your certificate to 'curl-ca-bundle.crt' file): http://blogs.msdn.com/b/phkelley/archive/2014/01/20/adding-a-corporate-or-self-signed-certificate-authority-to-git-exe-s-store.aspx – Stanislav Berkov Sep 01 '14 at 12:15
  • If you do not want to add the certificate globally, and you must first clone the repo, you can also use a environment variable for cloning. After cloning, you can add the configuration described above to add the key. # GIT_SSL_CAINFO=yourserver.pem git clone https://YOURSERVER.../ – do3cc Sep 16 '14 at 12:25
  • 5
    The problem with this approach is that it effectively removes all the default CAs that come with git (eg after doing this, you won't be able to pull from github). Most likely that's not what most are looking for. A better example is to add the new root CA to a copy of Git\bin\curl-ca-bundle.crt, and then reference the new copy of curl-ca-bundle.crt from your gitconfig. – crimbo Jul 29 '15 at 21:41
  • so git doesn't use the default ssl certificate location such as /etc/ssl/certs? – Shuliyey Sep 06 '15 at 23:32
  • 3
    it does work on windows! export every cert in the certificate-chain as Base64 coded X.509 file (.CER) Put all the files together and reference this file. Be sure that you don't have spaces in the path to the cert file (use oldschool paths) – pscheit Sep 29 '16 at 13:20
  • 1
    I like the #NO NEED TO USE THIS line :) Useful for quick n dirty git clone – debuti Dec 05 '17 at 11:18
  • The fetching part can be easily taken care of in a single command: `openssl s_client -showcerts -connect example.example:443 /dev/null | openssl x509 -outform PEM >>~/git-certs/cert.pem` but note that using s_client will only work with self-signed certificates(?). I spent way too much time figuring out that there was a separate CA in my case which simply doesn't get spit out by the server. – Caesar May 16 '18 at 02:38
  • I tried this, however the following was the only thing that worked for me: https://tnckb94959.i.lithium.com/t5/image/serverpage/image-id/10845i3A3E82A75060430C/image-dimensions/2500?v=1.0&px=-1 – Skystrider May 28 '18 at 21:33
  • I found that using `--system` did not work, but using `--global` did. – mikeck Apr 30 '19 at 17:57
  • 12
    To not disable all default/system CAs for all domains but only for this one domain use instead: `git config --global http."https://repos.sample.com".sslCAInfo /home/javl/git-certs/cert.pem` and if there are any http urls that get redirected additionally also `git config --global http."http://redirect-source.example.com".sslCAInfo /home/javl/git-certs/cert.pem` – Jan Zerebecki May 03 '19 at 05:49
9

OSX User adjustments.

Following the steps of the Accepted answer worked for me with a small addition when configuring on OSX.

I put the cert.pem file in a directory under my OSX logged in user and thus caused me to adjust the location for the trusted certificate.

Configure git to trust this certificate:

$ git config --global http.sslCAInfo $HOME/git-certs/cert.pem
Trevor Reid
  • 3,310
  • 4
  • 27
  • 46
Chris Langston
  • 211
  • 4
  • 7
9

On windows in a corporate environment where certificates are distributed from a single source, I found this answer solved the issue: https://stackoverflow.com/a/48212753/761755

GKalnytskyi
  • 579
  • 7
  • 16