Exemple #1
0
        private int ReadCore(byte[] buffer, int offset, int size)
        {
            uint dataRead = 0;

            if (_dataChunkIndex != -1)
            {
                dataRead = Interop.HttpApi.GetChunks(_httpContext.Request.RequestBuffer, _httpContext.Request.OriginalBlobAddress, ref _dataChunkIndex, ref _dataChunkOffset, buffer, offset, size);
            }

            if (_dataChunkIndex == -1 && dataRead < size)
            {
                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Info(this, "size:" + size + " offset:" + offset);
                }
                uint statusCode    = 0;
                uint extraDataRead = 0;
                offset += (int)dataRead;
                size   -= (int)dataRead;

                //the http.sys team recommends that we limit the size to 128kb
                if (size > MaxReadSize)
                {
                    size = MaxReadSize;
                }

                fixed(byte *pBuffer = buffer)
                {
                    // issue unmanaged blocking call
                    if (NetEventSource.IsEnabled)
                    {
                        NetEventSource.Info(this, "Calling Interop.HttpApi.HttpReceiveRequestEntityBody");
                    }

                    uint flags = 0;

                    if (!_inOpaqueMode)
                    {
                        flags = (uint)Interop.HttpApi.HTTP_FLAGS.HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY;
                    }

                    statusCode =
                        Interop.HttpApi.HttpReceiveRequestEntityBody(
                            _httpContext.RequestQueueHandle,
                            _httpContext.RequestId,
                            flags,
                            (void *)(pBuffer + offset),
                            (uint)size,
                            out extraDataRead,
                            null);

                    dataRead += extraDataRead;
                    if (NetEventSource.IsEnabled)
                    {
                        NetEventSource.Info(this, "Call to Interop.HttpApi.HttpReceiveRequestEntityBody returned:" + statusCode + " dataRead:" + dataRead);
                    }
                }

                if (statusCode != Interop.HttpApi.ERROR_SUCCESS && statusCode != Interop.HttpApi.ERROR_HANDLE_EOF)
                {
                    Exception exception = new HttpListenerException((int)statusCode);
                    if (NetEventSource.IsEnabled)
                    {
                        NetEventSource.Error(this, exception.ToString());
                    }
                    throw exception;
                }
                UpdateAfterRead(statusCode, dataRead);
            }
            if (NetEventSource.IsEnabled)
            {
                NetEventSource.DumpBuffer(this, buffer, offset, (int)dataRead);
                NetEventSource.Info(this, "returning dataRead:" + dataRead);
                NetEventSource.Exit(this, "dataRead:" + dataRead);
            }
            return((int)dataRead);
        }
        protected override void Dispose(bool disposing)
        {
            if (NetEventSource.IsEnabled)
            {
                NetEventSource.Enter(this);
            }

            try
            {
                if (disposing)
                {
                    if (NetEventSource.IsEnabled)
                    {
                        NetEventSource.Info(this, "_closed:" + _closed);
                    }
                    if (_closed)
                    {
                        if (NetEventSource.IsEnabled)
                        {
                            NetEventSource.Exit(this);
                        }
                        return;
                    }
                    _closed = true;
                    Interop.HttpApi.HTTP_FLAGS flags = ComputeLeftToWrite();
                    if (_leftToWrite > 0 && !_inOpaqueMode)
                    {
                        throw new InvalidOperationException(SR.net_io_notenoughbyteswritten);
                    }
                    bool sentHeaders = _httpContext.Response.SentHeaders;
                    if (sentHeaders && _leftToWrite == 0)
                    {
                        if (NetEventSource.IsEnabled)
                        {
                            NetEventSource.Exit(this);
                        }
                        return;
                    }

                    uint statusCode = 0;
                    if ((_httpContext.Response.BoundaryType == BoundaryType.Chunked || _httpContext.Response.BoundaryType == BoundaryType.None) && (String.Compare(_httpContext.Request.HttpMethod, "HEAD", StringComparison.OrdinalIgnoreCase) != 0))
                    {
                        if (_httpContext.Response.BoundaryType == BoundaryType.None)
                        {
                            flags |= Interop.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_DISCONNECT;
                        }
                        fixed(void *pBuffer = &s_chunkTerminator[0])
                        {
                            Interop.HttpApi.HTTP_DATA_CHUNK *pDataChunk = null;
                            if (_httpContext.Response.BoundaryType == BoundaryType.Chunked)
                            {
                                Interop.HttpApi.HTTP_DATA_CHUNK dataChunk = new Interop.HttpApi.HTTP_DATA_CHUNK();
                                dataChunk.DataChunkType = Interop.HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory;
                                dataChunk.pBuffer       = (byte *)pBuffer;
                                dataChunk.BufferLength  = (uint)s_chunkTerminator.Length;
                                pDataChunk = &dataChunk;
                            }
                            if (!sentHeaders)
                            {
                                statusCode = _httpContext.Response.SendHeaders(pDataChunk, null, flags, false);
                            }
                            else
                            {
                                if (NetEventSource.IsEnabled)
                                {
                                    NetEventSource.Info(this, "Calling Interop.HttpApi.HttpSendResponseEntityBody");
                                }

                                statusCode =
                                    Interop.HttpApi.HttpSendResponseEntityBody(
                                        _httpContext.RequestQueueHandle,
                                        _httpContext.RequestId,
                                        (uint)flags,
                                        pDataChunk != null ? (ushort)1 : (ushort)0,
                                        pDataChunk,
                                        null,
                                        SafeLocalAllocHandle.Zero,
                                        0,
                                        null,
                                        null);

                                if (NetEventSource.IsEnabled)
                                {
                                    NetEventSource.Info(this, "Call to Interop.HttpApi.HttpSendResponseEntityBody returned:" + statusCode);
                                }
                                if (_httpContext.Listener.IgnoreWriteExceptions)
                                {
                                    if (NetEventSource.IsEnabled)
                                    {
                                        NetEventSource.Info(this, "Suppressing error");
                                    }
                                    statusCode = Interop.HttpApi.ERROR_SUCCESS;
                                }
                            }
                        }
                    }
                    else
                    {
                        if (!sentHeaders)
                        {
                            statusCode = _httpContext.Response.SendHeaders(null, null, flags, false);
                        }
                    }
                    if (statusCode != Interop.HttpApi.ERROR_SUCCESS && statusCode != Interop.HttpApi.ERROR_HANDLE_EOF)
                    {
                        Exception exception = new HttpListenerException((int)statusCode);
                        if (NetEventSource.IsEnabled)
                        {
                            NetEventSource.Error(this, exception.ToString());
                        }
                        _httpContext.Abort();
                        throw exception;
                    }
                    _leftToWrite = 0;
                }
            }
            finally
            {
                base.Dispose(disposing);
            }
            if (NetEventSource.IsEnabled)
            {
                NetEventSource.Exit(this);
            }
        }
Exemple #3
0
        public IAsyncResult BeginReadCore(byte[] buffer, int offset, int size, AsyncCallback callback, object state)
        {
            if (size == 0 || _closed)
            {
                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Exit(this);
                }
                HttpRequestStreamAsyncResult result = new HttpRequestStreamAsyncResult(this, state, callback);
                result.InvokeCallback((uint)0);
                return(result);
            }

            HttpRequestStreamAsyncResult asyncResult = null;

            uint dataRead = 0;

            if (_dataChunkIndex != -1)
            {
                dataRead = Interop.HttpApi.GetChunks(_httpContext.Request.RequestBuffer, _httpContext.Request.OriginalBlobAddress, ref _dataChunkIndex, ref _dataChunkOffset, buffer, offset, size);
                if (_dataChunkIndex != -1 && dataRead == size)
                {
                    asyncResult = new HttpRequestStreamAsyncResult(_httpContext.RequestQueueBoundHandle, this, state, callback, buffer, offset, (uint)size, 0);
                    asyncResult.InvokeCallback(dataRead);
                }
            }

            if (_dataChunkIndex == -1 && dataRead < size)
            {
                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Info(this, "size:" + size + " offset:" + offset);
                }
                uint statusCode = 0;
                offset += (int)dataRead;
                size   -= (int)dataRead;

                //the http.sys team recommends that we limit the size to 128kb
                if (size > MaxReadSize)
                {
                    size = MaxReadSize;
                }

                asyncResult = new HttpRequestStreamAsyncResult(_httpContext.RequestQueueBoundHandle, this, state, callback, buffer, offset, (uint)size, dataRead);
                uint bytesReturned;

                try
                {
                    fixed(byte *pBuffer = buffer)
                    {
                        // issue unmanaged blocking call
                        if (NetEventSource.IsEnabled)
                        {
                            NetEventSource.Info(this, "Calling Interop.HttpApi.HttpReceiveRequestEntityBody");
                        }

                        uint flags = 0;

                        if (!_inOpaqueMode)
                        {
                            flags = (uint)Interop.HttpApi.HTTP_FLAGS.HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY;
                        }

                        statusCode =
                            Interop.HttpApi.HttpReceiveRequestEntityBody(
                                _httpContext.RequestQueueHandle,
                                _httpContext.RequestId,
                                flags,
                                asyncResult._pPinnedBuffer,
                                (uint)size,
                                out bytesReturned,
                                asyncResult._pOverlapped);

                        if (NetEventSource.IsEnabled)
                        {
                            NetEventSource.Info(this, "Call to Interop.HttpApi.HttpReceiveRequestEntityBody returned:" + statusCode + " dataRead:" + dataRead);
                        }
                    }
                }
                catch (Exception e)
                {
                    if (NetEventSource.IsEnabled)
                    {
                        NetEventSource.Error(this, e.ToString());
                    }
                    asyncResult.InternalCleanup();
                    throw;
                }

                if (statusCode != Interop.HttpApi.ERROR_SUCCESS && statusCode != Interop.HttpApi.ERROR_IO_PENDING)
                {
                    asyncResult.InternalCleanup();
                    if (statusCode == Interop.HttpApi.ERROR_HANDLE_EOF)
                    {
                        asyncResult = new HttpRequestStreamAsyncResult(this, state, callback, dataRead);
                        asyncResult.InvokeCallback((uint)0);
                    }
                    else
                    {
                        Exception exception = new HttpListenerException((int)statusCode);
                        if (NetEventSource.IsEnabled)
                        {
                            NetEventSource.Error(this, exception.ToString());
                        }
                        asyncResult.InternalCleanup();
                        throw exception;
                    }
                }
                else if (statusCode == Interop.HttpApi.ERROR_SUCCESS &&
                         HttpListener.SkipIOCPCallbackOnSuccess)
                {
                    // IO operation completed synchronously - callback won't be called to signal completion.
                    asyncResult.IOCompleted(statusCode, bytesReturned);
                }
            }
            if (NetEventSource.IsEnabled)
            {
                NetEventSource.Exit(this);
            }
            return(asyncResult);
        }
        public override void Write(byte[] buffer, int offset, int size)
        {
            if (NetEventSource.IsEnabled)
            {
                NetEventSource.Enter(this);
                NetEventSource.Info(this, "buffer.Length:" + buffer.Length + " size:" + size + " offset:" + offset);
            }
            if (buffer == null)
            {
                throw new ArgumentNullException(nameof(buffer));
            }
            if (offset < 0 || offset > buffer.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(offset));
            }
            if (size < 0 || size > buffer.Length - offset)
            {
                throw new ArgumentOutOfRangeException(nameof(size));
            }
            Interop.HttpApi.HTTP_FLAGS flags = ComputeLeftToWrite();
            if (_closed || (size == 0 && _leftToWrite != 0))
            {
                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Exit(this);
                }
                return;
            }
            if (_leftToWrite >= 0 && size > _leftToWrite)
            {
                throw new ProtocolViolationException(SR.net_entitytoobig);
            }

            uint statusCode;
            uint dataToWrite = (uint)size;
            SafeLocalAllocHandle bufferAsIntPtr = null;
            IntPtr pBufferAsIntPtr = IntPtr.Zero;
            bool   sentHeaders     = _httpContext.Response.SentHeaders;

            try
            {
                if (size == 0)
                {
                    statusCode = _httpContext.Response.SendHeaders(null, null, flags, false);
                }
                else
                {
                    fixed(byte *pDataBuffer = buffer)
                    {
                        byte *pBuffer = pDataBuffer;

                        if (_httpContext.Response.BoundaryType == BoundaryType.Chunked)
                        {
                            string chunkHeader = size.ToString("x", CultureInfo.InvariantCulture);
                            dataToWrite     = dataToWrite + (uint)(chunkHeader.Length + 4);
                            bufferAsIntPtr  = SafeLocalAllocHandle.LocalAlloc((int)dataToWrite);
                            pBufferAsIntPtr = bufferAsIntPtr.DangerousGetHandle();
                            for (int i = 0; i < chunkHeader.Length; i++)
                            {
                                Marshal.WriteByte(pBufferAsIntPtr, i, (byte)chunkHeader[i]);
                            }
                            Marshal.WriteInt16(pBufferAsIntPtr, chunkHeader.Length, 0x0A0D);
                            Marshal.Copy(buffer, offset, pBufferAsIntPtr + chunkHeader.Length + 2, size);
                            Marshal.WriteInt16(pBufferAsIntPtr, (int)(dataToWrite - 2), 0x0A0D);
                            pBuffer = (byte *)pBufferAsIntPtr;
                            offset  = 0;
                        }
                        Interop.HttpApi.HTTP_DATA_CHUNK dataChunk = new Interop.HttpApi.HTTP_DATA_CHUNK();
                        dataChunk.DataChunkType = Interop.HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory;
                        dataChunk.pBuffer       = (byte *)(pBuffer + offset);
                        dataChunk.BufferLength  = dataToWrite;

                        flags |= _leftToWrite == size ? Interop.HttpApi.HTTP_FLAGS.NONE : Interop.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA;
                        if (!sentHeaders)
                        {
                            statusCode = _httpContext.Response.SendHeaders(&dataChunk, null, flags, false);
                        }
                        else
                        {
                            if (NetEventSource.IsEnabled)
                            {
                                NetEventSource.Info(this, "Calling Interop.HttpApi.HttpSendResponseEntityBody");
                            }

                            statusCode =
                                Interop.HttpApi.HttpSendResponseEntityBody(
                                    _httpContext.RequestQueueHandle,
                                    _httpContext.RequestId,
                                    (uint)flags,
                                    1,
                                    &dataChunk,
                                    null,
                                    SafeLocalAllocHandle.Zero,
                                    0,
                                    null,
                                    null);

                            if (NetEventSource.IsEnabled)
                            {
                                NetEventSource.Info(this, "Call to Interop.HttpApi.HttpSendResponseEntityBody returned:" + statusCode);
                            }
                            if (_httpContext.Listener.IgnoreWriteExceptions)
                            {
                                if (NetEventSource.IsEnabled)
                                {
                                    NetEventSource.Info(this, "Write() suppressing error");
                                }
                                statusCode = Interop.HttpApi.ERROR_SUCCESS;
                            }
                        }
                    }
                }
            }
            finally
            {
                // free unmanaged buffer
                bufferAsIntPtr?.Close();
            }

            if (statusCode != Interop.HttpApi.ERROR_SUCCESS && statusCode != Interop.HttpApi.ERROR_HANDLE_EOF)
            {
                Exception exception = new HttpListenerException((int)statusCode);
                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Error(this, exception.ToString());
                }
                _closed = true;
                _httpContext.Abort();
                throw exception;
            }
            UpdateAfterWrite(dataToWrite);
            if (NetEventSource.IsEnabled)
            {
                NetEventSource.DumpBuffer(this, buffer, offset, (int)dataToWrite);
            }
            if (NetEventSource.IsEnabled)
            {
                NetEventSource.Exit(this);
            }
        }
        public override IAsyncResult BeginWrite(byte[] buffer, int offset, int size, AsyncCallback callback, object state)
        {
            if (NetEventSource.IsEnabled)
            {
                NetEventSource.Info(this, "buffer.Length:" + buffer.Length + " size:" + size + " offset:" + offset);
            }
            if (buffer == null)
            {
                throw new ArgumentNullException(nameof(buffer));
            }
            if (offset < 0 || offset > buffer.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(offset));
            }
            if (size < 0 || size > buffer.Length - offset)
            {
                throw new ArgumentOutOfRangeException(nameof(size));
            }
            Interop.HttpApi.HTTP_FLAGS flags = ComputeLeftToWrite();
            if (_closed || (size == 0 && _leftToWrite != 0))
            {
                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Exit(this);
                }
                HttpResponseStreamAsyncResult result = new HttpResponseStreamAsyncResult(this, state, callback);
                result.InvokeCallback((uint)0);
                return(result);
            }
            if (_leftToWrite >= 0 && size > _leftToWrite)
            {
                throw new ProtocolViolationException(SR.net_entitytoobig);
            }

            uint statusCode;
            uint bytesSent = 0;

            flags |= _leftToWrite == size ? Interop.HttpApi.HTTP_FLAGS.NONE : Interop.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA;
            bool sentHeaders = _httpContext.Response.SentHeaders;
            HttpResponseStreamAsyncResult asyncResult = new HttpResponseStreamAsyncResult(this, state, callback, buffer, offset, size, _httpContext.Response.BoundaryType == BoundaryType.Chunked, sentHeaders, _httpContext.RequestQueueBoundHandle);

            // Update m_LeftToWrite now so we can queue up additional BeginWrite's without waiting for EndWrite.
            UpdateAfterWrite((uint)((_httpContext.Response.BoundaryType == BoundaryType.Chunked) ? 0 : size));

            try
            {
                if (!sentHeaders)
                {
                    statusCode = _httpContext.Response.SendHeaders(null, asyncResult, flags, false);
                }
                else
                {
                    if (NetEventSource.IsEnabled)
                    {
                        NetEventSource.Info(this, "Calling Interop.HttpApi.HttpSendResponseEntityBody");
                    }

                    statusCode =
                        Interop.HttpApi.HttpSendResponseEntityBody(
                            _httpContext.RequestQueueHandle,
                            _httpContext.RequestId,
                            (uint)flags,
                            asyncResult.dataChunkCount,
                            asyncResult.pDataChunks,
                            &bytesSent,
                            SafeLocalAllocHandle.Zero,
                            0,
                            asyncResult._pOverlapped,
                            null);

                    if (NetEventSource.IsEnabled)
                    {
                        NetEventSource.Info(this, "Call to Interop.HttpApi.HttpSendResponseEntityBody returned:" + statusCode);
                    }
                }
            }
            catch (Exception e)
            {
                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Error(this, e.ToString());
                }
                asyncResult.InternalCleanup();
                _closed = true;
                _httpContext.Abort();
                throw;
            }

            if (statusCode != Interop.HttpApi.ERROR_SUCCESS && statusCode != Interop.HttpApi.ERROR_IO_PENDING)
            {
                asyncResult.InternalCleanup();
                if (_httpContext.Listener.IgnoreWriteExceptions && sentHeaders)
                {
                    if (NetEventSource.IsEnabled)
                    {
                        NetEventSource.Info(this, "BeginWrite() Suppressing error");
                    }
                }
                else
                {
                    Exception exception = new HttpListenerException((int)statusCode);
                    if (NetEventSource.IsEnabled)
                    {
                        NetEventSource.Error(this, exception.ToString());
                    }
                    _closed = true;
                    _httpContext.Abort();
                    throw exception;
                }
            }

            if (statusCode == Interop.HttpApi.ERROR_SUCCESS && HttpListener.SkipIOCPCallbackOnSuccess)
            {
                // IO operation completed synchronously - callback won't be called to signal completion.
                asyncResult.IOCompleted(statusCode, bytesSent);
            }

            // Last write, cache it for special cancelation handling.
            if ((flags & Interop.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA) == 0)
            {
                _lastWrite = asyncResult;
            }

            if (NetEventSource.IsEnabled)
            {
                NetEventSource.Exit(this);
            }
            return(asyncResult);
        }
Exemple #6
0
        private IAsyncResult BeginWriteCore(byte[] buffer, int offset, int size, AsyncCallback?callback, object?state)
        {
            Interop.HttpApi.HTTP_FLAGS flags = ComputeLeftToWrite();
            if (_closed || (size == 0 && _leftToWrite != 0))
            {
                HttpResponseStreamAsyncResult result = new HttpResponseStreamAsyncResult(this, state, callback);
                result.InvokeCallback((uint)0);
                return(result);
            }
            if (_leftToWrite >= 0 && size > _leftToWrite)
            {
                throw new ProtocolViolationException(SR.net_entitytoobig);
            }

            uint statusCode;
            uint bytesSent = 0;

            flags |= _leftToWrite == size ? Interop.HttpApi.HTTP_FLAGS.NONE : Interop.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA;
            bool sentHeaders = _httpContext.Response.SentHeaders;
            HttpResponseStreamAsyncResult asyncResult = new HttpResponseStreamAsyncResult(this, state, callback, buffer, offset, size, _httpContext.Response.BoundaryType == BoundaryType.Chunked, sentHeaders, _httpContext.RequestQueueBoundHandle);

            // Update m_LeftToWrite now so we can queue up additional BeginWrite's without waiting for EndWrite.
            UpdateAfterWrite((uint)((_httpContext.Response.BoundaryType == BoundaryType.Chunked) ? 0 : size));

            try
            {
                if (!sentHeaders)
                {
                    statusCode = _httpContext.Response.SendHeaders(null, asyncResult, flags, false);
                }
                else
                {
                    if (NetEventSource.Log.IsEnabled())
                    {
                        NetEventSource.Info(this, "Calling Interop.HttpApi.HttpSendResponseEntityBody");
                    }

                    statusCode =
                        Interop.HttpApi.HttpSendResponseEntityBody(
                            _httpContext.RequestQueueHandle,
                            _httpContext.RequestId,
                            (uint)flags,
                            asyncResult.dataChunkCount,
                            asyncResult.pDataChunks,
                            &bytesSent,
                            SafeLocalAllocHandle.Zero,
                            0,
                            asyncResult._pOverlapped,
                            null);

                    if (NetEventSource.Log.IsEnabled())
                    {
                        NetEventSource.Info(this, "Call to Interop.HttpApi.HttpSendResponseEntityBody returned:" + statusCode);
                    }
                }
            }
            catch (Exception e)
            {
                if (NetEventSource.Log.IsEnabled())
                {
                    NetEventSource.Error(this, e.ToString());
                }
                asyncResult.InternalCleanup();
                _closed = true;
                _httpContext.Abort();
                throw;
            }

            if (statusCode != Interop.HttpApi.ERROR_SUCCESS && statusCode != Interop.HttpApi.ERROR_IO_PENDING)
            {
                asyncResult.InternalCleanup();
                if (_httpContext.Listener !.IgnoreWriteExceptions && sentHeaders)
                {
                    if (NetEventSource.Log.IsEnabled())
                    {
                        NetEventSource.Info(this, "BeginWrite() Suppressing error");
                    }
                }
                else
                {
                    Exception exception = new HttpListenerException((int)statusCode);
                    if (NetEventSource.Log.IsEnabled())
                    {
                        NetEventSource.Error(this, exception.ToString());
                    }
                    _closed = true;
                    _httpContext.Abort();
                    throw exception;
                }
            }
Exemple #7
0
        //
        // Security: We temporarily reset thread token to open the cert store under process account.
        //
        internal static X509Store EnsureStoreOpened(bool isMachineStore)
        {
            X509Store store = isMachineStore ? s_myMachineCertStoreEx : s_myCertStoreEx;

            // TODO #3862 Investigate if this can be switched to either the static or Lazy<T> patterns.
            if (store == null)
            {
                lock (s_syncObject)
                {
                    store = isMachineStore ? s_myMachineCertStoreEx : s_myCertStoreEx;
                    if (store == null)
                    {
                        // NOTE: that if this call fails we won't keep track and the next time we enter we will try to open the store again.
                        StoreLocation storeLocation = isMachineStore ? StoreLocation.LocalMachine : StoreLocation.CurrentUser;
                        store = new X509Store(StoreName.My, storeLocation);
                        try
                        {
                            // For app-compat We want to ensure the store is opened under the **process** account.
                            try
                            {
                                WindowsIdentity.RunImpersonated(SafeAccessTokenHandle.InvalidHandle, () =>
                                {
                                    store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
                                    if (NetEventSource.IsEnabled)
                                    {
                                        NetEventSource.Info(null, $"storeLocation {storeLocation} returned store: {store}");
                                    }
                                });
                            }
                            catch
                            {
                                throw;
                            }

                            if (isMachineStore)
                            {
                                s_myMachineCertStoreEx = store;
                            }
                            else
                            {
                                s_myCertStoreEx = store;
                            }

                            return(store);
                        }
                        catch (Exception exception)
                        {
                            if (exception is CryptographicException || exception is SecurityException)
                            {
                                NetEventSource.Fail(null, $"Failed to open cert store, location: {storeLocation} exception: {exception}");
                                return(null);
                            }

                            if (NetEventSource.IsEnabled)
                            {
                                NetEventSource.Error(null, SR.Format(SR.net_log_open_store_failed, storeLocation, exception));
                            }
                            throw;
                        }
                    }
                }
            }

            return(store);
        }
Exemple #8
0
        /// <summary>
        /// <para>Thread for the timer.  Ignores all exceptions.  If no activity occurs for a while,
        /// the thread will shut down.</para>
        /// </summary>
        private static void ThreadProc()
        {
            if (NetEventSource.IsEnabled)
            {
                NetEventSource.Enter(null);
            }
#if DEBUG
            DebugThreadTracking.SetThreadSource(ThreadKinds.Timer);
            using (DebugThreadTracking.SetThreadKind(ThreadKinds.System | ThreadKinds.Async))
            {
#endif
            // Set this thread as a background thread.  On AppDomain/Process shutdown, the thread will just be killed.
            Thread.CurrentThread.IsBackground = true;

            // Keep a permanent lock on s_Queues.  This lets for example Shutdown() know when this thread isn't running.
            lock (s_queues)
            {
                // If shutdown was recently called, abort here.
                if (Interlocked.CompareExchange(ref s_threadState, (int)TimerThreadState.Running, (int)TimerThreadState.Running) !=
                    (int)TimerThreadState.Running)
                {
                    return;
                }

                bool running = true;
                while (running)
                {
                    try
                    {
                        s_threadReadyEvent.Reset();

                        while (true)
                        {
                            // Copy all the new queues to the real queues.  Since only this thread modifies the real queues, it doesn't have to lock it.
                            if (s_newQueues.Count > 0)
                            {
                                lock (s_newQueues)
                                {
                                    for (LinkedListNode <WeakReference> node = s_newQueues.First; node != null; node = s_newQueues.First)
                                    {
                                        s_newQueues.Remove(node);
                                        s_queues.AddLast(node);
                                    }
                                }
                            }

                            int  now          = Environment.TickCount;
                            int  nextTick     = 0;
                            bool haveNextTick = false;
                            for (LinkedListNode <WeakReference> node = s_queues.First; node != null; /* node = node.Next must be done in the body */)
                            {
                                TimerQueue queue = (TimerQueue)node.Value.Target;
                                if (queue == null)
                                {
                                    LinkedListNode <WeakReference> next = node.Next;
                                    s_queues.Remove(node);
                                    node = next;
                                    continue;
                                }

                                // Fire() will always return values that should be interpreted as later than 'now' (that is, even if 'now' is
                                // returned, it is 0x100000000 milliseconds in the future).  There's also a chance that Fire() will return a value
                                // intended as > 0x100000000 milliseconds from 'now'.  Either case will just cause an extra scan through the timers.
                                int nextTickInstance;
                                if (queue.Fire(out nextTickInstance) && (!haveNextTick || IsTickBetween(now, nextTick, nextTickInstance)))
                                {
                                    nextTick     = nextTickInstance;
                                    haveNextTick = true;
                                }

                                node = node.Next;
                            }

                            // Figure out how long to wait, taking into account how long the loop took.
                            // Add 15 ms to compensate for poor TickCount resolution (want to guarantee a firing).
                            int newNow       = Environment.TickCount;
                            int waitDuration = haveNextTick ?
                                               (int)(IsTickBetween(now, nextTick, newNow) ?
                                                     Math.Min(unchecked ((uint)(nextTick - newNow)), (uint)(int.MaxValue - TickCountResolution)) + TickCountResolution :
                                                     0) :
                                               ThreadIdleTimeoutMilliseconds;

                            if (NetEventSource.IsEnabled)
                            {
                                NetEventSource.Info(null, $"Waiting for {waitDuration}ms");
                            }

                            int waitResult = WaitHandle.WaitAny(s_threadEvents, waitDuration, false);

                            // 0 is s_ThreadShutdownEvent - die.
                            if (waitResult == 0)
                            {
                                if (NetEventSource.IsEnabled)
                                {
                                    NetEventSource.Info(null, "Awoke, cause: Shutdown");
                                }
                                running = false;
                                break;
                            }

                            if (NetEventSource.IsEnabled)
                            {
                                NetEventSource.Info(null, $"Awoke, cause {(waitResult == WaitHandle.WaitTimeout ? "Timeout" : "Prod")}");
                            }

                            // If we timed out with nothing to do, shut down.
                            if (waitResult == WaitHandle.WaitTimeout && !haveNextTick)
                            {
                                Interlocked.CompareExchange(ref s_threadState, (int)TimerThreadState.Idle, (int)TimerThreadState.Running);
                                // There could have been one more prod between the wait and the exchange.  Check, and abort if necessary.
                                if (s_threadReadyEvent.WaitOne(0, false))
                                {
                                    if (Interlocked.CompareExchange(ref s_threadState, (int)TimerThreadState.Running, (int)TimerThreadState.Idle) ==
                                        (int)TimerThreadState.Idle)
                                    {
                                        continue;
                                    }
                                }

                                running = false;
                                break;
                            }
                        }
                    }
                    catch (Exception exception)
                    {
                        if (ExceptionCheck.IsFatal(exception))
                        {
                            throw;
                        }

                        if (NetEventSource.IsEnabled)
                        {
                            NetEventSource.Error(null, exception);
                        }

                        // The only options are to continue processing and likely enter an error-loop,
                        // shut down timers for this AppDomain, or shut down the AppDomain.  Go with shutting
                        // down the AppDomain in debug, and going into a loop in retail, but try to make the
                        // loop somewhat slow.  Note that in retail, this can only be triggered by OutOfMemory or StackOverflow,
                        // or an exception thrown within TimerThread - the rest are caught in Fire().
#if !DEBUG
                        Thread.Sleep(1000);
#else
                        throw;
#endif
                    }
                }
            }

            if (NetEventSource.IsEnabled)
            {
                NetEventSource.Info(null, "Stop");
            }
#if DEBUG
        }
#endif
        }
Exemple #9
0
            /// <summary>
            /// <para>Fires the timer if it is still active and has expired.  Returns
            /// true if it can be deleted, or false if it is still timing.</para>
            /// </summary>
            internal bool Fire()
            {
                if (_timerState == TimerState.Sentinel)
                {
                    if (NetEventSource.IsEnabled)
                    {
                        NetEventSource.Info(this, "TimerQueue tried to Fire a Sentinel.");
                    }
                }

                if (_timerState != TimerState.Ready)
                {
                    return(true);
                }

                // Must get the current tick count within this method so it is guaranteed not to be before
                // StartTime, which is set in the constructor.
                int nowMilliseconds = Environment.TickCount;

                if (IsTickBetween(StartTime, Expiration, nowMilliseconds))
                {
                    if (NetEventSource.IsEnabled)
                    {
                        NetEventSource.Info(this, $"TimerThreadTimer#{StartTime}::Fire() Not firing ({StartTime} <= {nowMilliseconds} < {Expiration})");
                    }
                    return(false);
                }

                bool needCallback = false;

                lock (_queueLock)
                {
                    if (_timerState == TimerState.Ready)
                    {
                        if (NetEventSource.IsEnabled)
                        {
                            NetEventSource.Info(this, $"TimerThreadTimer#{StartTime}::Fire() Firing ({StartTime} <= {nowMilliseconds} >= " + Expiration + ")");
                        }
                        _timerState = TimerState.Fired;

                        // Remove it from the list.
                        Next.Prev = Prev;
                        Prev.Next = Next;

                        Next         = null;
                        Prev         = null;
                        needCallback = _callback != null;
                    }
                }

                if (needCallback)
                {
                    try
                    {
                        Callback callback = _callback;
                        object   context  = _context;
                        _callback = null;
                        _context  = null;
                        callback(this, nowMilliseconds, context);
                    }
                    catch (Exception exception)
                    {
                        if (ExceptionCheck.IsFatal(exception))
                        {
                            throw;
                        }

                        if (NetEventSource.IsEnabled)
                        {
                            NetEventSource.Error(this, $"exception in callback: {exception}");
                        }

                        // This thread is not allowed to go into user code, so we should never get an exception here.
                        // So, in debug, throw it up, killing the AppDomain.  In release, we'll just ignore it.
#if DEBUG
                        throw;
#endif
                    }
                }

                return(true);
            }
Exemple #10
0
        } // GetHostByAddress

        // Does internal IPAddress reverse and then forward lookups (for Legacy and current public methods).
        private static IPHostEntry InternalGetHostByAddress(IPAddress address, bool includeIPv6)
        {
            if (NetEventSource.IsEnabled)
            {
                NetEventSource.Info(null, address);
            }

            //
            // IPv6 Changes: We need to use the new getnameinfo / getaddrinfo functions
            //               for resolution of IPv6 addresses.
            //

            if (SocketProtocolSupportPal.OSSupportsIPv6 || includeIPv6)
            {
                //
                // Try to get the data for the host from it's address
                //
                // We need to call getnameinfo first, because getaddrinfo w/ the ipaddress string
                // will only return that address and not the full list.

                // Do a reverse lookup to get the host name.
                SocketError errorCode;
                int         nativeErrorCode;
                string      name = NameResolutionPal.TryGetNameInfo(address, out errorCode, out nativeErrorCode);
                if (errorCode == SocketError.Success)
                {
                    // Do the forward lookup to get the IPs for that host name
                    IPHostEntry hostEntry;
                    errorCode = NameResolutionPal.TryGetAddrInfo(name, out hostEntry, out nativeErrorCode);
                    if (errorCode == SocketError.Success)
                    {
                        return(hostEntry);
                    }

                    if (NetEventSource.IsEnabled)
                    {
                        NetEventSource.Error(null, SocketExceptionFactory.CreateSocketException(errorCode, nativeErrorCode));
                    }

                    // One of two things happened:
                    // 1. There was a ptr record in dns, but not a corollary A/AAA record.
                    // 2. The IP was a local (non-loopback) IP that resolved to a connection specific dns suffix.
                    //    - Workaround, Check "Use this connection's dns suffix in dns registration" on that network
                    //      adapter's advanced dns settings.

                    // Just return the resolved host name and no IPs.
                    return(hostEntry);
                }

                throw SocketExceptionFactory.CreateSocketException(errorCode, nativeErrorCode);
            }

            //
            // If IPv6 is not enabled (maybe config switch) but we've been
            // given an IPv6 address then we need to bail out now.
            //
            else
            {
                if (address.AddressFamily == AddressFamily.InterNetworkV6)
                {
                    //
                    // Protocol not supported
                    //
                    throw new SocketException((int)SocketError.ProtocolNotSupported);
                }
                //
                // Use gethostbyaddr() to try to resolve the IP address
                //
                // End IPv6 Changes
                //
                return(NameResolutionPal.GetHostByAddr(address));
            }
        } // InternalGetHostByAddress
        internal static X509Store?EnsureStoreOpened(bool isMachineStore)
        {
            X509Store?store = isMachineStore ? s_myMachineCertStoreEx : s_myCertStoreEx;

            if (store == null)
            {
                StoreLocation storeLocation = isMachineStore ? StoreLocation.LocalMachine : StoreLocation.CurrentUser;

                // On Windows and OSX CheckSupportsStore is not defined, so the call is eliminated and the
                // if should be folded out.
                //
                // On Unix it will prevent the lock from being held and released over and over for the LocalMachine store.
                bool supportsStore = true;
                CheckSupportsStore(storeLocation, ref supportsStore);

                if (!supportsStore)
                {
                    return(null);
                }

                lock (s_syncObject)
                {
                    store = isMachineStore ? s_myMachineCertStoreEx : s_myCertStoreEx;

                    if (store == null)
                    {
                        try
                        {
                            // NOTE: that if this call fails we won't keep track and the next time we enter we will try to open the store again.
                            store = OpenStore(storeLocation);

                            if (NetEventSource.Log.IsEnabled())
                            {
                                NetEventSource.Info(null, $"storeLocation: {storeLocation} returned store {store}");
                            }

                            if (isMachineStore)
                            {
                                s_myMachineCertStoreEx = store;
                            }
                            else
                            {
                                s_myCertStoreEx = store;
                            }
                        }
                        catch (Exception exception)
                        {
                            if (exception is CryptographicException || exception is SecurityException)
                            {
                                Debug.Fail($"Failed to open cert store, location: {storeLocation} exception: {exception}");
                                return(null);
                            }

                            if (NetEventSource.Log.IsEnabled())
                            {
                                NetEventSource.Error(null, SR.Format(SR.net_log_open_store_failed, storeLocation, exception));
                            }

                            throw;
                        }
                    }
                }
            }

            return(store);
        }
Exemple #12
0
        private static unsafe int EncryptDecryptHelper(OP op, SSPIInterface secModule, SafeDeleteContext context, SecurityBuffer[] input, uint sequenceNumber)
        {
            Interop.SspiCli.SecBufferDesc sdcInOut = new Interop.SspiCli.SecBufferDesc(input.Length);
            var unmanagedBuffer = new Interop.SspiCli.SecBuffer[input.Length];

            fixed(Interop.SspiCli.SecBuffer *unmanagedBufferPtr = unmanagedBuffer)
            {
                sdcInOut.pBuffers = unmanagedBufferPtr;
                GCHandle[] pinnedBuffers = new GCHandle[input.Length];
                byte[][]   buffers       = new byte[input.Length][];
                try
                {
                    for (int i = 0; i < input.Length; i++)
                    {
                        SecurityBuffer iBuffer = input[i];
                        unmanagedBuffer[i].cbBuffer   = iBuffer.size;
                        unmanagedBuffer[i].BufferType = iBuffer.type;
                        if (iBuffer.token == null || iBuffer.token.Length == 0)
                        {
                            unmanagedBuffer[i].pvBuffer = IntPtr.Zero;
                        }
                        else
                        {
                            pinnedBuffers[i]            = GCHandle.Alloc(iBuffer.token, GCHandleType.Pinned);
                            unmanagedBuffer[i].pvBuffer = Marshal.UnsafeAddrOfPinnedArrayElement(iBuffer.token, iBuffer.offset);
                            buffers[i] = iBuffer.token;
                        }
                    }

                    // The result is written in the input Buffer passed as type=BufferType.Data.
                    int errorCode;
                    switch (op)
                    {
                    case OP.Encrypt:
                        errorCode = secModule.EncryptMessage(context, ref sdcInOut, sequenceNumber);
                        break;

                    case OP.Decrypt:
                        errorCode = secModule.DecryptMessage(context, ref sdcInOut, sequenceNumber);
                        break;

                    case OP.MakeSignature:
                        errorCode = secModule.MakeSignature(context, ref sdcInOut, sequenceNumber);
                        break;

                    case OP.VerifySignature:
                        errorCode = secModule.VerifySignature(context, ref sdcInOut, sequenceNumber);
                        break;

                    default:
                        NetEventSource.Fail(null, $"Unknown OP: {op}");
                        throw NotImplemented.ByDesignWithMessage(SR.net_MethodNotImplementedException);
                    }

                    // Marshalling back returned sizes / data.
                    for (int i = 0; i < input.Length; i++)
                    {
                        SecurityBuffer iBuffer = input[i];
                        iBuffer.size = unmanagedBuffer[i].cbBuffer;
                        iBuffer.type = unmanagedBuffer[i].BufferType;

                        if (iBuffer.size == 0)
                        {
                            iBuffer.offset = 0;
                            iBuffer.token  = null;
                        }
                        else
                        {
                            checked
                            {
                                // Find the buffer this is inside of.  Usually they all point inside buffer 0.
                                int j;
                                for (j = 0; j < input.Length; j++)
                                {
                                    if (buffers[j] == null)
                                    {
                                        continue;
                                    }

                                    byte *bufferAddress = (byte *)Marshal.UnsafeAddrOfPinnedArrayElement(buffers[j], 0);
                                    if ((byte *)unmanagedBuffer[i].pvBuffer >= bufferAddress &&
                                        (byte *)unmanagedBuffer[i].pvBuffer + iBuffer.size <= bufferAddress + buffers[j].Length)
                                    {
                                        iBuffer.offset = (int)((byte *)unmanagedBuffer[i].pvBuffer - bufferAddress);
                                        iBuffer.token  = buffers[j];
                                        break;
                                    }
                                }

                                if (j >= input.Length)
                                {
                                    NetEventSource.Fail(null, "Output buffer out of range.");
                                    iBuffer.size   = 0;
                                    iBuffer.offset = 0;
                                    iBuffer.token  = null;
                                }
                            }
                        }

                        // Backup validate the new sizes.
                        if (iBuffer.offset < 0 || iBuffer.offset > (iBuffer.token == null ? 0 : iBuffer.token.Length))
                        {
                            NetEventSource.Fail(null, $"'offset' out of range.  [{iBuffer.offset}]");
                        }

                        if (iBuffer.size < 0 || iBuffer.size > (iBuffer.token == null ? 0 : iBuffer.token.Length - iBuffer.offset))
                        {
                            NetEventSource.Fail(null, $"'size' out of range.  [{iBuffer.size}]");
                        }
                    }

                    if (NetEventSource.IsEnabled && errorCode != 0)
                    {
                        if (errorCode == Interop.SspiCli.SEC_I_RENEGOTIATE)
                        {
                            NetEventSource.Error(null, SR.Format(SR.event_OperationReturnedSomething, op, "SEC_I_RENEGOTIATE"));
                        }
                        else
                        {
                            NetEventSource.Error(null, SR.Format(SR.net_log_operation_failed_with_error, op, $"0x{0:X}"));
                        }
                    }

                    return(errorCode);
                }
                finally
                {
                    for (int i = 0; i < pinnedBuffers.Length; ++i)
                    {
                        if (pinnedBuffers[i].IsAllocated)
                        {
                            pinnedBuffers[i].Free();
                        }
                    }
                }
            }
        }