Exemple #1
0
        // Populates the client certificate.  The result may be null if there is no client cert.
        // TODO: Does it make sense for this to be invoked multiple times (e.g. renegotiate)? Client and server code appear to
        // enable this, but it's unclear what Http.Sys would do.
        public async Task <X509Certificate2> GetClientCertificateAsync(CancellationToken cancellationToken = default(CancellationToken))
        {
            if (SslStatus == SslStatus.Insecure)
            {
                // Non-SSL
                return(null);
            }
            // TODO: Verbose log
            if (_clientCert != null)
            {
                return(_clientCert);
            }
            cancellationToken.ThrowIfCancellationRequested();

            ClientCertLoader certLoader = new ClientCertLoader(RequestContext, cancellationToken);

            try
            {
                await certLoader.LoadClientCertificateAsync().SupressContext();

                // Populate the environment.
                if (certLoader.ClientCert != null)
                {
                    _clientCert = certLoader.ClientCert;
                }
                // TODO: Expose errors and exceptions?
            }
            catch (Exception)
            {
                if (certLoader != null)
                {
                    certLoader.Dispose();
                }
                throw;
            }
            return(_clientCert);
        }
Exemple #2
0
        private static unsafe void IOCompleted(ClientCertLoader asyncResult, uint errorCode, uint numBytes)
        {
            RequestContext requestContext = asyncResult.RequestContext;

            try
            {
                if (errorCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_MORE_DATA)
                {
                    // There is a bug that has existed in http.sys since w2k3.  Bytesreceived will only
                    // return the size of the initial cert structure.  To get the full size,
                    // we need to add the certificate encoding size as well.

                    UnsafeNclNativeMethods.HttpApi.HTTP_SSL_CLIENT_CERT_INFO *pClientCertInfo = asyncResult.RequestBlob;
                    asyncResult.Reset(numBytes + pClientCertInfo->CertEncodedSize);

                    uint bytesReceived = 0;
                    errorCode =
                        UnsafeNclNativeMethods.HttpApi.HttpReceiveClientCertificate(
                            requestContext.RequestQueueHandle,
                            requestContext.Request.ConnectionId,
                            (uint)UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE,
                            asyncResult._memoryBlob,
                            asyncResult._size,
                            &bytesReceived,
                            asyncResult._overlapped);

                    if (errorCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_IO_PENDING ||
                        (errorCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS && !WebListener.SkipIOCPCallbackOnSuccess))
                    {
                        return;
                    }
                }

                if (errorCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_NOT_FOUND)
                {
                    // The client did not send a cert.
                    asyncResult.Complete(0, null);
                }
                else if (errorCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS)
                {
                    asyncResult.Fail(new WebListenerException((int)errorCode));
                }
                else
                {
                    UnsafeNclNativeMethods.HttpApi.HTTP_SSL_CLIENT_CERT_INFO *pClientCertInfo = asyncResult._memoryBlob;
                    if (pClientCertInfo == null)
                    {
                        asyncResult.Complete(0, null);
                    }
                    else
                    {
                        if (pClientCertInfo->pCertEncoded != null)
                        {
                            try
                            {
                                byte[] certEncoded = new byte[pClientCertInfo->CertEncodedSize];
                                Marshal.Copy((IntPtr)pClientCertInfo->pCertEncoded, certEncoded, 0, certEncoded.Length);
                                asyncResult.Complete((int)pClientCertInfo->CertFlags, new X509Certificate2(certEncoded));
                            }
                            catch (CryptographicException exception)
                            {
                                // TODO: Log
                                asyncResult.Fail(exception);
                            }
                            catch (SecurityException exception)
                            {
                                // TODO: Log
                                asyncResult.Fail(exception);
                            }
                        }
                    }
                }
            }
            catch (Exception exception)
            {
                asyncResult.Fail(exception);
            }
        }