Beispiel #1
0
        private void Reset(uint size)
        {
            if (size == _size)
            {
                return;
            }
            if (_size != 0)
            {
                _overlapped.Dispose();
            }
            _size = size;
            if (size == 0)
            {
                _overlapped    = null;
                _memoryBlob    = null;
                _backingBuffer = null;
                return;
            }
            _backingBuffer = new byte[checked ((int)size)];
            var boundHandle = RequestContext.Server.BoundHandle;

            _overlapped = new SafeNativeOverlapped(boundHandle,
                                                   boundHandle.AllocateNativeOverlapped(IOCallback, this, _backingBuffer));
            _memoryBlob = (UnsafeNclNativeMethods.HttpApi.HTTP_SSL_CLIENT_CERT_INFO *)Marshal.UnsafeAddrOfPinnedArrayElement(_backingBuffer, 0);
        }
Beispiel #2
0
 internal unsafe void Reset(uint size)
 {
     if (size != this.m_Size)
     {
         if (this.m_Size != 0)
         {
             Overlapped.Free(this.m_pOverlapped);
         }
         this.m_Size = size;
         if (size == 0)
         {
             this.m_pOverlapped   = null;
             this.m_MemoryBlob    = null;
             this.m_BackingBuffer = null;
         }
         else
         {
             this.m_BackingBuffer = new byte[size];
             this.m_pOverlapped   = new Overlapped {
                 AsyncResult = this
             }.Pack(s_IOCallback, this.m_BackingBuffer);
             this.m_MemoryBlob = (UnsafeNclNativeMethods.HttpApi.HTTP_SSL_CLIENT_CERT_INFO *)Marshal.UnsafeAddrOfPinnedArrayElement(this.m_BackingBuffer, 0);
         }
     }
 }
 protected override unsafe void Cleanup()
 {
     if (this.m_pOverlapped != null)
     {
         this.m_MemoryBlob = null;
         Overlapped.Free(this.m_pOverlapped);
         this.m_pOverlapped = null;
     }
     GC.SuppressFinalize(this);
     base.Cleanup();
 }
Beispiel #4
0
 protected override unsafe void Cleanup()
 {
     if (this.m_pOverlapped != null)
     {
         this.m_MemoryBlob = null;
         Overlapped.Free(this.m_pOverlapped);
         this.m_pOverlapped = null;
     }
     GC.SuppressFinalize(this);
     base.Cleanup();
 }
Beispiel #5
0
 private void Dispose(bool disposing)
 {
     if (disposing)
     {
         _cancellationRegistration.Dispose();
         if (_overlapped != null)
         {
             _memoryBlob = null;
             _overlapped.Dispose();
         }
     }
 }
        private unsafe void ProcessClientCertificate()
        {
            byte[] buffer;
            if (this.m_ClientCertState == ListenerClientCertState.InProgress)
            {
                throw new InvalidOperationException(SR.GetString("net_listener_callinprogress", new object[] { "GetClientCertificate()/BeginGetClientCertificate()" }));
            }
            this.m_ClientCertState = ListenerClientCertState.InProgress;
            if (this.m_SslStatus == SslStatus.Insecure)
            {
                goto Label_00FD;
            }
            uint sslClientCertInfoSize = 0x5dc;

Label_0044:
            buffer = new byte[sslClientCertInfoSize];
            fixed(byte *numRef = buffer)
            {
                UnsafeNclNativeMethods.HttpApi.HTTP_SSL_CLIENT_CERT_INFO *pSslClientCertInfo = (UnsafeNclNativeMethods.HttpApi.HTTP_SSL_CLIENT_CERT_INFO *)numRef;
                uint pBytesReceived = 0;
                uint num3           = UnsafeNclNativeMethods.HttpApi.HttpReceiveClientCertificate(this.HttpListenerContext.RequestQueueHandle, this.m_ConnectionId, 0, pSslClientCertInfo, sslClientCertInfoSize, &pBytesReceived, null);

                if (num3 == 0xea)
                {
                    sslClientCertInfoSize = pBytesReceived + pSslClientCertInfo->CertEncodedSize;
                    goto Label_0044;
                }
                if ((num3 == 0) && (pSslClientCertInfo != null))
                {
                    if (pSslClientCertInfo->pCertEncoded != null)
                    {
                        try
                        {
                            byte[] destination = new byte[pSslClientCertInfo->CertEncodedSize];
                            Marshal.Copy((IntPtr)pSslClientCertInfo->pCertEncoded, destination, 0, destination.Length);
                            this.m_ClientCertificate = new X509Certificate2(destination);
                        }
                        catch (CryptographicException)
                        {
                        }
                        catch (SecurityException)
                        {
                        }
                    }
                    this.m_ClientCertificateError = (int)pSslClientCertInfo->CertFlags;
                }
            }

Label_00FD:
            this.m_ClientCertState = ListenerClientCertState.Completed;
        }
Beispiel #7
0
        // When you use netsh to configure HTTP.SYS with clientcertnegotiation = enable
        // which means negotiate client certificates, when the client makes the
        // initial SSL connection, the server (HTTP.SYS) requests the client certificate.
        //
        // Some apps may not want to negotiate the client cert at the beginning,
        // perhaps serving the default.htm. In this case the HTTP.SYS is configured
        // with clientcertnegotiation = disabled, which means that the client certificate is
        // optional so initially when SSL is established HTTP.SYS won't ask for client
        // certificate. This works fine for the default.htm in the case above,
        // however, if the app wants to demand a client certificate at a later time
        // perhaps showing "YOUR ORDERS" page, then the server wants to negotiate
        // Client certs. This will in turn makes HTTP.SYS to do the
        // SEC_I_RENOGOTIATE through which the client cert demand is made
        //
        // NOTE: When calling HttpReceiveClientCertificate you can get
        // ERROR_NOT_FOUND - which means the client did not provide the cert
        // If this is important, the server should respond with 403 forbidden
        // HTTP.SYS will not do this for you automatically
        internal Task LoadClientCertificateAsync()
        {
            uint size = CertBoblSize;
            bool retry;

            do
            {
                retry = false;
                uint bytesReceived = 0;

                uint statusCode =
                    UnsafeNclNativeMethods.HttpApi.HttpReceiveClientCertificate(
                        RequestContext.RequestQueueHandle,
                        RequestContext.Request.ConnectionId,
                        (uint)UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE,
                        RequestBlob,
                        size,
                        &bytesReceived,
                        NativeOverlapped);

                if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_MORE_DATA)
                {
                    UnsafeNclNativeMethods.HttpApi.HTTP_SSL_CLIENT_CERT_INFO *pClientCertInfo = RequestBlob;
                    size = bytesReceived + pClientCertInfo->CertEncodedSize;
                    Reset(size);
                    retry = true;
                }
                else if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_NOT_FOUND)
                {
                    // The client did not send a cert.
                    Complete(0, null);
                }
                else if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS &&
                         WebListener.SkipIOCPCallbackOnSuccess)
                {
                    IOCompleted(statusCode, bytesReceived);
                }
                else if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS &&
                         statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_IO_PENDING)
                {
                    // Some other bad error, possible(?) return values are:
                    // ERROR_INVALID_HANDLE, ERROR_INSUFFICIENT_BUFFER, ERROR_OPERATION_ABORTED
                    // Also ERROR_BAD_DATA if we got it twice or it reported smaller size buffer required.
                    Fail(new WebListenerException((int)statusCode));
                }
            }while (retry);

            return(Task);
        }
        private unsafe ListenerClientCertAsyncResult AsyncProcessClientCertificate(AsyncCallback requestCallback, object state)
        {
            if (this.m_ClientCertState == ListenerClientCertState.InProgress)
            {
                throw new InvalidOperationException(SR.GetString("net_listener_callinprogress", new object[] { "GetClientCertificate()/BeginGetClientCertificate()" }));
            }
            this.m_ClientCertState = ListenerClientCertState.InProgress;
            this.HttpListenerContext.EnsureBoundHandle();
            ListenerClientCertAsyncResult result = null;

            if (this.m_SslStatus != SslStatus.Insecure)
            {
                uint size = 0x5dc;
                result = new ListenerClientCertAsyncResult(this, state, requestCallback, size);
                try
                {
                    uint num2;
Label_0058:
                    num2 = 0;
                    uint num3 = UnsafeNclNativeMethods.HttpApi.HttpReceiveClientCertificate(this.HttpListenerContext.RequestQueueHandle, this.m_ConnectionId, 0, result.RequestBlob, size, &num2, result.NativeOverlapped);
                    if (num3 == 0xea)
                    {
                        UnsafeNclNativeMethods.HttpApi.HTTP_SSL_CLIENT_CERT_INFO *requestBlob = result.RequestBlob;
                        size = num2 + requestBlob->CertEncodedSize;
                        result.Reset(size);
                        goto Label_0058;
                    }
                    if ((num3 != 0) && (num3 != 0x3e5))
                    {
                        throw new HttpListenerException((int)num3);
                    }
                    return(result);
                }
                catch
                {
                    if (result != null)
                    {
                        result.InternalCleanup();
                    }
                    throw;
                }
            }
            result = new ListenerClientCertAsyncResult(this, state, requestCallback, 0);
            result.InvokeCallback();
            return(result);
        }
 internal void Reset(uint size) {
     if (size == m_Size)
     {
         return;
     }
     if (m_Size != 0)
     {
         Overlapped.Free(m_pOverlapped);
     }
     m_Size = size;
     if (size == 0)
     {
         m_pOverlapped = null;
         m_MemoryBlob = null;
         m_BackingBuffer = null;
         return;
     }
     m_BackingBuffer = new byte[checked((int) size)];
     Overlapped overlapped = new Overlapped();
     overlapped.AsyncResult = this;
     m_pOverlapped = overlapped.Pack(s_IOCallback, m_BackingBuffer);
     m_MemoryBlob = (UnsafeNclNativeMethods.HttpApi.HTTP_SSL_CLIENT_CERT_INFO*) Marshal.UnsafeAddrOfPinnedArrayElement(m_BackingBuffer, 0);
 }
 internal unsafe void Reset(uint size)
 {
     if (size != this.m_Size)
     {
         if (this.m_Size != 0)
         {
             Overlapped.Free(this.m_pOverlapped);
         }
         this.m_Size = size;
         if (size == 0)
         {
             this.m_pOverlapped = null;
             this.m_MemoryBlob = null;
             this.m_BackingBuffer = null;
         }
         else
         {
             this.m_BackingBuffer = new byte[size];
             this.m_pOverlapped = new Overlapped { AsyncResult = this }.Pack(s_IOCallback, this.m_BackingBuffer);
             this.m_MemoryBlob = (UnsafeNclNativeMethods.HttpApi.HTTP_SSL_CLIENT_CERT_INFO*) Marshal.UnsafeAddrOfPinnedArrayElement(this.m_BackingBuffer, 0);
         }
     }
 }
Beispiel #11
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);
            }
        }
Beispiel #12
0
        private static unsafe void WaitCallback(uint errorCode, uint numBytes, System.Threading.NativeOverlapped *nativeOverlapped)
        {
            ListenerClientCertAsyncResult asyncResult = (ListenerClientCertAsyncResult)Overlapped.Unpack(nativeOverlapped).AsyncResult;
            HttpListenerRequest           asyncObject = (HttpListenerRequest)asyncResult.AsyncObject;
            object result = null;

            try
            {
                if (errorCode == 0xea)
                {
                    UnsafeNclNativeMethods.HttpApi.HTTP_SSL_CLIENT_CERT_INFO *requestBlob = asyncResult.RequestBlob;
                    asyncResult.Reset(numBytes + requestBlob->CertEncodedSize);
                    uint pBytesReceived = 0;
                    errorCode = UnsafeNclNativeMethods.HttpApi.HttpReceiveClientCertificate(asyncObject.HttpListenerContext.RequestQueueHandle, asyncObject.m_ConnectionId, 0, asyncResult.m_MemoryBlob, asyncResult.m_Size, &pBytesReceived, asyncResult.m_pOverlapped);
                    if ((errorCode == 0x3e5) || (errorCode == 0))
                    {
                        return;
                    }
                }
                if (errorCode != 0)
                {
                    asyncResult.ErrorCode = (int)errorCode;
                    result = new HttpListenerException((int)errorCode);
                }
                else
                {
                    UnsafeNclNativeMethods.HttpApi.HTTP_SSL_CLIENT_CERT_INFO *memoryBlob = asyncResult.m_MemoryBlob;
                    if (memoryBlob != null)
                    {
                        if (memoryBlob->pCertEncoded != null)
                        {
                            try
                            {
                                byte[] destination = new byte[memoryBlob->CertEncodedSize];
                                Marshal.Copy((IntPtr)memoryBlob->pCertEncoded, destination, 0, destination.Length);
                                result = asyncObject.ClientCertificate = new X509Certificate2(destination);
                            }
                            catch (CryptographicException exception)
                            {
                                result = exception;
                            }
                            catch (SecurityException exception2)
                            {
                                result = exception2;
                            }
                        }
                        asyncObject.SetClientCertificateError((int)memoryBlob->CertFlags);
                    }
                }
            }
            catch (Exception exception3)
            {
                if (NclUtilities.IsFatal(exception3))
                {
                    throw;
                }
                result = exception3;
            }
            finally
            {
                if (errorCode != 0x3e5)
                {
                    asyncObject.ClientCertState = ListenerClientCertState.Completed;
                }
            }
            asyncResult.InvokeCallback(result);
        }