title: "dotnet restore" fails with "SSL peer certificate or SSH remote key was not OK"
body: <p>I've just followed the procedure here:
  <a href="https://www.microsoft.com/net/core#ubuntu" rel="nofollow noreferrer">https://www.microsoft.com/net/core#ubuntu</a></p>
  
  <p>and that's the output of <code>dotnet restore</code></p>
  
  <pre><code>log  : Restoring packages for /home/test/project.json...
  error: Unable to load the service index for source https://api.nuget.org/v3/index.json.
  error:   An error occurred while sending the request.
  error:   SSL peer certificate or SSH remote key was not OK
  </code></pre>
  
  <p>I've added the relevant certificates to the trusted ones in order to make <code>curl</code> work but the error remains for <code>dotnet restore</code>.</p>
  
  <p>I've tried to dig in the core source to find out how Nuget checks the SSL certificates without luck.
  <strong>Versions I've tried:</strong></p>
  
  <ul>
  <li>1.0.0-preview1-002702</li>
  <li>1.0.0-preview2-003100</li>
  </ul>
  
  <p>I've configured curl using the <code>.curlrc</code> :</p>
  
  <pre><code>cacert=/etc/ssl/certs/ca-certificates.crt
  </code></pre>
  
  <p>It has fixed <code>curl -I https://api.nuget.org</code> invocation.</p>
  
  <p>However <code>dotnet restore -v Debug</code> still fails:</p>
  
  <pre><code>trace: Running restore with 8 concurrent jobs.
  trace: Reading project file /home/user/test/project.json.
  log  : Restoring packages for /home/user/test/project.json...
  trace: Restoring packages for .NETCoreApp,Version=v1.0...
  error: Unable to load the service index for source https://api.nuget.org/v3/index.json.
  error:   An error occurred while sending the request.
  error:   SSL peer certificate or SSH remote key was not OK
  trace: System.AggregateException: One or more errors occurred. (Unable to load the service index for source https://api.nuget.org/v3/index.json.) ---&gt; NuGet.Protocol.Core.Types.FatalProtocolException: Unable to load the service index for source https://api.nuget.org/v3/index.json. ---&gt; System.Net.Http.HttpRequestException: An error occurred while sending the request. ---&gt; System.Net.Http.CurlException: SSL peer certificate or SSH remote key was not OK
  trace:    at System.Net.Http.CurlHandler.ThrowIfCURLEError(CURLcode error)
  </code></pre>
  
  <p>So dotnet core uses <code>libcurl</code> but it doesn't use the <code>.curlrc</code> obviously.</p>
  
  <p><strong>EDIT: 21/06/2016</strong></p>
  
  <p>Tried to update the certificates database with mozroots also but it failed to have any effect. (Seems to be more related to mono than to dotnetcore even if dotnet core building page mention it).</p>
  
  <p>After digging into corefx code, Curl handler of System.Net.Http doesn't seem to set the right ssl options in all cases (like in <a href="https://curl.haxx.se/libcurl/c/simplessl.html" rel="nofollow noreferrer">Simple Curl SSL sample</a>).</p>
  
  <p>I've tried <a href="https://stackoverflow.com/users/2879498/tylery86">Tyler</a> solutions:</p>
  
  <pre><code>certmgr -ssl -m https://api.nuget.org
  </code></pre>
  
  <p>This isn't adding the last certificate even if I type <code>'y', 'yes', '1', 'true'</code> or whatever.</p>
  
  <pre><code>mozroots --url https://hg.mozilla.org/mozilla-central/raw-file/tip/security/nss/lib/ckfw/builtins/certdata.txt --sync --import
  </code></pre>
  
  <p>This does something:</p>
  
  <pre><code>Importing certificates into user store...
  194 new root certificates were added to your trust store.
  Import process completed.
  </code></pre>
  
  <p>I'm not convinced that dotnet core used the libcurl nss build (just because their <a href="https://github.com/dotnet/corefx/blob/master/Documentation/building/unix-instructions.md" rel="nofollow noreferrer">development page</a> tells about openssl version (and they're mutually exclusive). By the way, I've tried to use nss build of libcurl and dotnet restore still fails.</p>
  
  <p>IMHO, the problem is not related to bad certificates registration but more on the fact that curl builtin certificate validation is not properly disabled (because the certificate validation is done in System.Net.Http and that is mandatory to offer to client code the ability to customize this validation).</p>
  
  <p>Why is it happening on my machine and not elsewhere ?
  It must be related to my version of libcurl.</p>
  
  <p>However all of these are just assumptions for the moment.</p>
  
  <p><strong>EDIT 22/05/2016:</strong></p>
  
  <p>By looking at the code more thoroughly, especially when comparing master branch and the RC2 release, it's clear that SSL handling code is still changing a lot.</p>
  
  <p>So I just grab the RC2 code and modify it to reflect what master branch does:</p>
  
  <pre><code>easy.SetCurlOption(Interop.Http.CURLoption.CURLOPT_SSL_VERIFYHOST, 0);
  </code></pre>
  
  <p>However, it didn't change anything... But forecasted it was.
  so here the code I used:</p>
  
  <pre><code>easy.SetCurlOption(Interop.Http.CURLoption.CURLOPT_SSL_VERIFYPEER, 0);
  </code></pre>
  
  <p>and then replace System.Net.Http.dll with the ssl certificates check disabled.
  Not safe but unblocking me for the moment.</p>
  
  <p>I didn't add that as an answer because it's more a hack than a fix.</p>
  
  <p>(a real fix would be to disable completely certificates checks done by curl and always handle it in .Net core but in the current code on master, it's still not the case, it's more a kind of mix of both).</p>
  
  <p>For the root cause, I think that I'm on a specific setup :</p>
  
  <ul>
  <li>libcurl built without any default certificate bundle path. <code>curlconfig --ca</code> return an empty string. And it doesn't read the <code>CURL_CA_BUNDLE</code> environment variable or <code>.curlrc</code> file. </li>
  <li>System.Net.Http (of dotnet-core) does neither setup a ca default nor disable the certificate validation.</li>
  </ul>