コード例 #1
0
        public static SecurityStatusPal EncryptMessage(SafeDeleteContext securityContext, byte[] input, int offset, int size, int headerSize, int trailerSize, ref byte[] output, out int resultSize)
        {
            // Ensure that there is sufficient space for the message output.
            try
            {
                int bufferSizeNeeded = checked (size + headerSize + trailerSize);

                if (output == null || output.Length < bufferSizeNeeded)
                {
                    output = new byte[bufferSizeNeeded];
                }
            }
            catch (Exception e)
            {
                if (!ExceptionCheck.IsFatal(e))
                {
                    if (GlobalLog.IsEnabled)
                    {
                        GlobalLog.Assert("SslStreamPal.Windows: SecureChannel#" + LoggingHash.HashString(securityContext) + "::Encrypt", "Arguments out of range.");
                    }

                    Debug.Fail("SslStreamPal.Windows: SecureChannel#" + LoggingHash.HashString(securityContext) + "::Encrypt", "Arguments out of range.");
                }

                throw;
            }

            byte[] writeBuffer = output;

            // Copy the input into the output buffer to prepare for SCHANNEL's expectations
            Buffer.BlockCopy(input, offset, writeBuffer, headerSize, size);

            // Encryption using SCHANNEL requires 4 buffers: header, payload, trailer, empty.
            SecurityBuffer[] securityBuffer = new SecurityBuffer[4];

            securityBuffer[0] = new SecurityBuffer(writeBuffer, 0, headerSize, SecurityBufferType.Header);
            securityBuffer[1] = new SecurityBuffer(writeBuffer, headerSize, size, SecurityBufferType.Data);
            securityBuffer[2] = new SecurityBuffer(writeBuffer, headerSize + size, trailerSize, SecurityBufferType.Trailer);
            securityBuffer[3] = new SecurityBuffer(null, SecurityBufferType.Empty);

            int errorCode = SSPIWrapper.EncryptMessage(GlobalSSPI.SSPISecureChannel, securityContext, securityBuffer, 0);

            if (errorCode != 0)
            {
                if (GlobalLog.IsEnabled)
                {
                    GlobalLog.Print("SslStreamPal.Windows: SecureChannel#" + LoggingHash.HashString(securityContext) + "::Encrypt ERROR" + errorCode.ToString("x"));
                }
                resultSize = 0;
            }
            else
            {
                // The full buffer may not be used.
                resultSize = securityBuffer[0].size + securityBuffer[1].size + securityBuffer[2].size;
            }

            return(SecurityStatusAdapterPal.GetSecurityStatusPalFromNativeInt(errorCode));
        }
コード例 #2
0
        private static unsafe void IOCompleted(ListenerClientCertAsyncResult asyncResult, uint errorCode, uint numBytes)
        {
            HttpListenerRequest httpListenerRequest = (HttpListenerRequest)asyncResult.AsyncObject;
            object result = null;

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

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

                    uint bytesReceived = 0;
                    errorCode =
                        Interop.HttpApi.HttpReceiveClientCertificate(
                            httpListenerRequest.HttpListenerContext.RequestQueueHandle,
                            httpListenerRequest._connectionId,
                            (uint)Interop.HttpApi.HTTP_FLAGS.NONE,
                            asyncResult._memoryBlob,
                            asyncResult._size,
                            &bytesReceived,
                            asyncResult._pOverlapped);

                    if (errorCode == Interop.HttpApi.ERROR_IO_PENDING ||
                        (errorCode == Interop.HttpApi.ERROR_SUCCESS && !HttpListener.SkipIOCPCallbackOnSuccess))
                    {
                        return;
                    }
                }

                if (errorCode != Interop.HttpApi.ERROR_SUCCESS)
                {
                    asyncResult.ErrorCode = (int)errorCode;
                    result = new HttpListenerException((int)errorCode);
                }
                else
                {
                    Interop.HttpApi.HTTP_SSL_CLIENT_CERT_INFO *pClientCertInfo = asyncResult._memoryBlob;
                    if (pClientCertInfo != null)
                    {
                        if (NetEventSource.IsEnabled)
                        {
                            NetEventSource.Info(null,
                                                $"pClientCertInfo:{(IntPtr)pClientCertInfo} pClientCertInfo->CertFlags: {pClientCertInfo->CertFlags} pClientCertInfo->CertEncodedSize: {pClientCertInfo->CertEncodedSize} pClientCertInfo->pCertEncoded: {(IntPtr)pClientCertInfo->pCertEncoded} pClientCertInfo->Token: {(IntPtr)pClientCertInfo->Token} pClientCertInfo->CertDeniedByMapper: {pClientCertInfo->CertDeniedByMapper}");
                        }
                        if (pClientCertInfo->pCertEncoded != null)
                        {
                            try
                            {
                                byte[] certEncoded = new byte[pClientCertInfo->CertEncodedSize];
                                Marshal.Copy((IntPtr)pClientCertInfo->pCertEncoded, certEncoded, 0, certEncoded.Length);
                                result = httpListenerRequest.ClientCertificate = new X509Certificate2(certEncoded);
                            }
                            catch (CryptographicException exception)
                            {
                                if (NetEventSource.IsEnabled)
                                {
                                    NetEventSource.Info(null,
                                                        $"HttpListenerRequest: {httpListenerRequest} caught CryptographicException: {exception}");
                                }
                                result = exception;
                            }
                            catch (SecurityException exception)
                            {
                                if (NetEventSource.IsEnabled)
                                {
                                    NetEventSource.Info(null, $"HttpListenerRequest: {httpListenerRequest} caught SecurityException: {exception}");
                                }
                                result = exception;
                            }
                        }
                        httpListenerRequest.SetClientCertificateError((int)pClientCertInfo->CertFlags);
                    }
                }

                // complete the async IO and invoke the callback
                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Info(null, "Calling Complete()");
                }
            }
            catch (Exception exception) when(!ExceptionCheck.IsFatal(exception))
            {
                result = exception;
            }
            finally
            {
                if (errorCode != Interop.HttpApi.ERROR_IO_PENDING)
                {
                    httpListenerRequest.ClientCertState = ListenerClientCertState.Completed;
                }
            }

            asyncResult.InvokeCallback(result);
        }
コード例 #3
0
ファイル: TimerThread.cs プロジェクト: berkaroad/dotnetcorefx
        /// <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)(Int32.MaxValue - c_TickCountResolution)) + c_TickCountResolution :
                                                     0) :
                                               c_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
        }
コード例 #4
0
ファイル: TimerThread.cs プロジェクト: berkaroad/dotnetcorefx
            /// <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);
            }
コード例 #5
0
ファイル: TimerThread.cs プロジェクト: vbegin/corefx
            /// <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 (GlobalLog.IsEnabled)
                    {
                        GlobalLog.AssertFormat("TimerThread#{0}::Fire()|TimerQueue tried to Fire a Sentinel.", Thread.CurrentThread.ManagedThreadId.ToString());
                    }

                    Debug.Fail(string.Format("TimerThread#{0}::Fire()|TimerQueue tried to Fire a Sentinel.", Thread.CurrentThread.ManagedThreadId.ToString()));
                }

                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 (GlobalLog.IsEnabled)
                    {
                        GlobalLog.Print("TimerThreadTimer#" + StartTime + "::Fire() Not firing (" + StartTime + " <= " + nowMilliseconds + " < " + Expiration + ")");
                    }
                    return(false);
                }

                bool needCallback = false;

                lock (_queueLock)
                {
                    if (_timerState == TimerState.Ready)
                    {
                        if (GlobalLog.IsEnabled)
                        {
                            GlobalLog.Print("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.Log.IsEnabled())
                        {
                            NetEventSource.PrintError(NetEventSource.ComponentType.Web, "TimerThreadTimer#" + StartTime.ToString(NumberFormatInfo.InvariantInfo) + "::Fire() - exception in callback: " + exception);
                        }

                        if (GlobalLog.IsEnabled)
                        {
                            GlobalLog.Print("TimerThreadTimer#" + StartTime + "::Fire() 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);
            }
コード例 #6
0
        private static void IOCompleted(ListenerAsyncResult asyncResult, uint errorCode, uint numBytes)
        {
            object result = null;

            try
            {
                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Info(null, $"errorCode:[{errorCode}] numBytes:[{numBytes}]");
                }

                if (errorCode != Interop.HttpApi.ERROR_SUCCESS &&
                    errorCode != Interop.HttpApi.ERROR_MORE_DATA)
                {
                    asyncResult.ErrorCode = (int)errorCode;
                    result = new HttpListenerException((int)errorCode);
                }
                else
                {
                    HttpListener httpWebListener = asyncResult.AsyncObject as HttpListener;
                    if (errorCode == Interop.HttpApi.ERROR_SUCCESS)
                    {
                        // at this point we have received an unmanaged HTTP_REQUEST and memoryBlob
                        // points to it we need to hook up our authentication handling code here.
                        bool stoleBlob = false;
                        try
                        {
                            if (httpWebListener.ValidateRequest(asyncResult._requestContext))
                            {
                                result = httpWebListener.HandleAuthentication(asyncResult._requestContext, out stoleBlob);
                            }
                        }
                        finally
                        {
                            if (stoleBlob)
                            {
                                // The request has been handed to the user, which means this code can't reuse the blob.  Reset it here.
                                asyncResult._requestContext = result == null ? new AsyncRequestContext(httpWebListener.RequestQueueBoundHandle, asyncResult) : null;
                            }
                            else
                            {
                                asyncResult._requestContext.Reset(httpWebListener.RequestQueueBoundHandle, 0, 0);
                            }
                        }
                    }
                    else
                    {
                        asyncResult._requestContext.Reset(httpWebListener.RequestQueueBoundHandle, asyncResult._requestContext.RequestBlob->RequestId, numBytes);
                    }

                    // We need to issue a new request, either because auth failed, or because our buffer was too small the first time.
                    if (result == null)
                    {
                        uint statusCode = asyncResult.QueueBeginGetContext();
                        if (statusCode != Interop.HttpApi.ERROR_SUCCESS &&
                            statusCode != Interop.HttpApi.ERROR_IO_PENDING)
                        {
                            // someother bad error, possible return values are:
                            // ERROR_INVALID_HANDLE, ERROR_INSUFFICIENT_BUFFER, ERROR_OPERATION_ABORTED
                            result = new HttpListenerException((int)statusCode);
                        }
                    }
                    if (result == null)
                    {
                        return;
                    }
                }

                // complete the async IO and invoke the callback
                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Info(null, "Calling Complete()");
                }
            }
            catch (Exception exception) when(!ExceptionCheck.IsFatal(exception))
            {
                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Info(null, $"Caught exception: {exception}");
                }
                result = exception;
            }
            asyncResult.InvokeCallback(result);
        }
コード例 #7
0
ファイル: NTAuthentication.cs プロジェクト: jemmy655/corefx
        internal int Encrypt(byte[] buffer, int offset, int count, ref byte[] output, uint sequenceNumber)
        {
            SecSizes sizes = Sizes;

            try
            {
                int maxCount = checked (Int32.MaxValue - 4 - sizes.BlockSize - sizes.SecurityTrailer);

                if (count > maxCount || count < 0)
                {
                    throw new ArgumentOutOfRangeException("count", SR.Format(SR.net_io_out_range, maxCount));
                }
            }
            catch (Exception e)
            {
                if (!ExceptionCheck.IsFatal(e) && GlobalLog.IsEnabled)
                {
                    GlobalLog.Assert("NTAuthentication#" + LoggingHash.HashString(this) + "::Encrypt", "Arguments out of range.");
                }

                throw;
            }

            int resultSize = count + sizes.SecurityTrailer + sizes.BlockSize;

            if (output == null || output.Length < resultSize + 4)
            {
                output = new byte[resultSize + 4];
            }

            // Make a copy of user data for in-place encryption.
            Buffer.BlockCopy(buffer, offset, output, 4 + sizes.SecurityTrailer, count);

            // Prepare buffers TOKEN(signature), DATA and Padding.
            var securityBuffer = new SecurityBuffer[3];

            securityBuffer[0] = new SecurityBuffer(output, 4, sizes.SecurityTrailer, SecurityBufferType.Token);
            securityBuffer[1] = new SecurityBuffer(output, 4 + sizes.SecurityTrailer, count, SecurityBufferType.Data);
            securityBuffer[2] = new SecurityBuffer(output, 4 + sizes.SecurityTrailer + count, sizes.BlockSize, SecurityBufferType.Padding);

            int errorCode;

            if (IsConfidentialityFlag)
            {
                errorCode = SSPIWrapper.EncryptMessage(GlobalSSPI.SSPIAuth, _securityContext, securityBuffer, sequenceNumber);
            }
            else
            {
                if (IsNTLM)
                {
                    securityBuffer[1].type |= SecurityBufferType.ReadOnlyFlag;
                }

                errorCode = SSPIWrapper.MakeSignature(GlobalSSPI.SSPIAuth, _securityContext, securityBuffer, 0);
            }

            if (errorCode != 0)
            {
                GlobalLog.Print("NTAuthentication#" + LoggingHash.HashString(this) + "::Encrypt() throw Error = " + errorCode.ToString("x", NumberFormatInfo.InvariantInfo));
                throw new Win32Exception(errorCode);
            }

            // Compacting the result.
            resultSize = securityBuffer[0].size;
            bool forceCopy = false;

            if (resultSize != sizes.SecurityTrailer)
            {
                forceCopy = true;
                Buffer.BlockCopy(output, securityBuffer[1].offset, output, 4 + resultSize, securityBuffer[1].size);
            }

            resultSize += securityBuffer[1].size;
            if (securityBuffer[2].size != 0 && (forceCopy || resultSize != (count + sizes.SecurityTrailer)))
            {
                Buffer.BlockCopy(output, securityBuffer[2].offset, output, 4 + resultSize, securityBuffer[2].size);
            }

            resultSize += securityBuffer[2].size;

            unchecked
            {
                output[0] = (byte)((resultSize) & 0xFF);
                output[1] = (byte)(((resultSize) >> 8) & 0xFF);
                output[2] = (byte)(((resultSize) >> 16) & 0xFF);
                output[3] = (byte)(((resultSize) >> 24) & 0xFF);
            }

            return(resultSize + 4);
        }