title: SSL certificate validation - is any caching involved?
body: <p>The case:</p>
  
  <ul>
  <li>A few days ago our integration partner missed a deadline for changing a SSL server certificate, the certificate's valid-to-date was two days back.</li>
  <li>When this happened our client software started throwing exceptions: "The remote certificate is invalid according to the validation procedure". Our client software is written in .NET 4 and runs on Windows Server 2012. The SSL call is done through the WCF stack.</li>
  <li>Yesterday afternoon, our integration partner installed a new valid SSL certificate.</li>
  </ul>
  
  <p>The problem is now that we still get the same exception on the client: "The remote certificate is invalid according to the validation procedure".</p>
  
  <p>My question:</p>
  
  <ul>
  <li>Is SSL certificate verification status cached somehow on the client? Our client software is a long-running process that is seldom restarted.</li>
  <li>Or is this some inherent part of the SSL protocol? I am no expert on SSL or networking, but is it not true that a) Only during the SSL handshake is server certificate checked by the client, and b) The information exchanged in an SSL handshake can be used for several network requests done to the same server ? If this indeed is true, how is it defined for how long an SSL handshake is valid?</li>
  </ul>
  
  <p><strong>Update</strong>: We restarted the client process, and then it works. To me this indicates that some SSL server certificate verification status is cached on the client, per process. I would still very much like to find out more about the details of this: On what level of the stack does this occur? WCF? .NET? Windows API? For how long is this cached? Is there any way to adjust the caching behavior? Can I manually empty the cache? Is this documented somewhere?</p>
  
  <p>Full stack trace:</p>
  
  <pre><code>[E0]: The remote certificate is invalid according to the validation procedure. 
  [T0]: System.Security.Authentication.AuthenticationException    at 
  System.Net.Security.SslState.StartSendAuthResetSignal(ProtocolToken message, 
  AsyncProtocolRequest asyncRequest, Exception exception)     at 
  System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, 
  AsyncProtocolRequest asyncRequest)     at 
  System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, 
  AsyncProtocolRequest asyncRequest)     at 
  System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, 
  AsyncProtocolRequest asyncRequest)     at 
  System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, 
  AsyncProtocolRequest asyncRequest)     at 
  System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, 
  AsyncProtocolRequest asyncRequest)     at 
  System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, 
  AsyncProtocolRequest asyncRequest)     at 
  System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, 
  AsyncProtocolRequest asyncRequest)     at 
  System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, 
  AsyncProtocolRequest asyncRequest)     at 
  System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, 
  AsyncProtocolRequest asyncRequest)     at 
  System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, 
  AsyncProtocolRequest asyncRequest)     at 
  System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, 
  AsyncProtocolRequest asyncRequest)     at 
  System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, 
  AsyncProtocolRequest asyncRequest)     at 
  System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, 
  AsyncProtocolRequest asyncRequest)     at 
  System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, 
  AsyncProtocolRequest asyncRequest)     at 
  System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, 
  AsyncProtocolRequest asyncRequest)     at 
  System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, 
  AsyncProtocolRequest asyncRequest)     at 
  System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, 
  AsyncProtocolRequest asyncRequest)     at 
  System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, 
  AsyncProtocolRequest asyncRequest)     at 
  System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, 
  AsyncProtocolRequest asyncRequest)     at 
  System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byte[] 
  buffer, AsyncProtocolRequest asyncRequest)     at 
  System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult)  
     at System.Threading.ExecutionContext.RunInternal(ExecutionContext 
  executionContext, ContextCallback callback, Object state, Boolean 
  preserveSyncCtx)     at System.Threading.ExecutionContext.Run(ExecutionContext 
  executionContext, ContextCallback callback, Object state, Boolean 
  preserveSyncCtx)     at System.Threading.ExecutionContext.Run(ExecutionContext 
  executionContext, ContextCallback callback, Object state)     at 
  System.Net.TlsStream.ProcessAuthentication(LazyAsyncResult result)     at 
  System.Net.TlsStream.Write(Byte[] buffer, Int32 offset, Int32 size)     at 
  System.Net.ConnectStream.WriteHeaders(Boolean async) [E1]: The underlying 
  connection was closed: Could not establish trust relationship for the SSL/TLS 
  secure channel. [T1]: System.Net.WebException    at 
  System.Net.HttpWebRequest.GetResponse()     at 
  System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannel
  Request.WaitForReply(TimeSpan timeout) [E2]: Could not establish trust 
  relationship for the SSL/TLS secure channel with authority 
  '***removed***'. [T2]: 
  System.ServiceModel.Security.SecurityNegotiationException 
  </code></pre>