SSL/TLS handshake from .NET to APNs - remote certificate is invalid : <p>I'm connecting to <em>Apple Push Notification Service (APNs)</em> from the <em>.NET Framework</em> using a <code>SslStream</code>. I'm connecting using the <code>Binary Provider API</code>. As part of the initial handshake, the <code>SslStream</code> does an <code>AuthenticateAsClient</code> on the network stream. This is the code for that:</p>

<pre><code>_sslStream = new SslStream(_tcpClient.GetStream());
_sslStream.AuthenticateAsClient(_url,
    new X509CertificateCollection { _certificate },
    SslProtocols.Tls,
    true);
</code></pre>

<p>Where <code>_url</code> is the <em>APNs</em> hostname and <code>_certificate</code> the push certificate of the app. On most machines (running a version of Windows Server), this is accepted and communication can continue. However, on some machines, this will fail. This is the exact error:</p>

<pre><code>The remote certificate is invalid according to the validation procedure.
</code></pre>

<p>The code runs as <em>Windows Service</em> under the <em>Local System</em> privileges. When the <strong>exact same code</strong> runs as command-line application under a local user, the <strong>handshake is accepted</strong> and communication can continue. Running the same command-line application under <em>Local System</em> using <code>pexec -i -s</code> causes the same error . I've checked if there are differences in the certificate stores between <em>Local Computer</em> and the <em>Current User</em>, but there are none.</p>

<p>A "workaround" was also tested. In this changed form, the code shown earlier was adapted to completely ignore certificates. This does exactly as you'd expect; the received certificates are not checked and communication can continue. This is what that looks like:</p>

<pre><code>_sslStream = new SslStream(_tcpClient.GetStream(), false, (sender, certificate, chain, errors) =&gt; true);
_sslStream.AuthenticateAsClient(_url,
    new X509CertificateCollection { _certificate },
    SslProtocols.Tls,
    false);
</code></pre>

<p>Of course, disabling security is a bad idea. What could be causing the handshake to break?!</p>
