public override Stream EndGetRequestStream(IAsyncResult asyncResult) { GlobalLog.Enter("FileWebRequest::EndGetRequestStream"); Stream stream; try { LazyAsyncResult ar = asyncResult as LazyAsyncResult; if (asyncResult == null || ar == null) { Exception e = asyncResult == null? new ArgumentNullException("asyncResult"): new ArgumentException(SR.GetString(SR.InvalidAsyncResult), "asyncResult"); GlobalLog.LeaveException("FileWebRequest::EndGetRequestStream", e); throw e; } object result = ar.InternalWaitForCompletion(); if (result is Exception) { throw (Exception)result; } stream = (Stream)result; m_writePending = false; } catch (Exception exception) { if (Logging.On) { Logging.Exception(Logging.Web, this, "EndGetRequestStream", exception); } throw; } finally { GlobalLog.Leave("FileWebRequest::EndGetRequestStream"); } FrameworkEventSource.Log.EndGetRequestStream(this); return(stream); }
/// <include file='doc\IPEndPoint.uex' path='docs/doc[@for="IPEndPoint.Create"]/*' /> /// <devdoc> /// <para>[To be supplied.]</para> /// </devdoc> public override EndPoint Create(SocketAddress socketAddress) { // // validate SocketAddress // if (socketAddress.Family != this.AddressFamily) { throw new ArgumentException(SR.GetString(SR.net_InvalidAddressFamily, socketAddress.Family.ToString(), this.GetType().FullName, this.AddressFamily.ToString())); } if (socketAddress.Size < 8) { throw new ArgumentException(SR.GetString(SR.net_InvalidSocketAddressSize, socketAddress.GetType().FullName, this.GetType().FullName)); } // // strip out of SocketAddress information on the EndPoint // int port = ((int)socketAddress[2] << 8) | ((int)socketAddress[3]); long address = (long)( ((int)socketAddress[4]) | ((int)socketAddress[5] << 8) | ((int)socketAddress[6] << 16) | ((int)socketAddress[7] << 24) ) & 0x00000000FFFFFFFF; IPEndPoint created = new IPEndPoint(address, port); GlobalLog.Print("IPEndPoint::Create: " + this.ToString() + " -> " + created.ToString()); // // return it // return(created); }
// This will return a client token when conducted authentication on server side. // This token can be used for impersonation. We use it to create a WindowsIdentity and hand it out to the server app. internal SecurityContextTokenHandle GetContextToken(out Interop.SecurityStatus status) { if (!(IsCompleted && IsValidContext)) { if (GlobalLog.IsEnabled) { GlobalLog.AssertFormat("NTAuthentication#{0}::GetContextToken|Should be called only when completed with success, currently is not!", LoggingHash.HashString(this)); } Debug.Fail("NTAuthentication#" + LoggingHash.HashString(this) + "::GetContextToken |Should be called only when completed with success, currently is not!"); } if (!IsServer) { if (GlobalLog.IsEnabled) { GlobalLog.AssertFormat("NTAuthentication#{0}::GetContextToken|The method must not be called by the client side!", LoggingHash.HashString(this)); } Debug.Fail("NTAuthentication#" + LoggingHash.HashString(this) + "::GetContextToken |The method must not be called by the client side!"); } if (!IsValidContext) { throw new Win32Exception((int)Interop.SecurityStatus.InvalidHandle); } SecurityContextTokenHandle token = null; status = (Interop.SecurityStatus)SSPIWrapper.QuerySecurityContextToken( GlobalSSPI.SSPIAuth, _securityContext, out token); return(token); }
/// <summary> /// <para>Creates new timers. This method is thread-safe.</para> /// </summary> internal override Timer CreateTimer(Callback callback, object context) { TimerNode timer = new TimerNode(callback, context, Duration, m_Timers); // Add this on the tail. (Actually, one before the tail - m_Timers is the sentinel tail.) bool needProd = false; lock (m_Timers) { GlobalLog.Assert(m_Timers.Prev.Next == m_Timers, "TimerThread#{0}::CreateTimer()|m_Tail corruption.", Thread.CurrentThread.ManagedThreadId.ToString()); // If this is the first timer in the list, we need to create a queue handle and prod the timer thread. if (m_Timers.Next == m_Timers) { if (m_ThisHandle == IntPtr.Zero) { m_ThisHandle = (IntPtr)GCHandle.Alloc(this); } needProd = true; } timer.Next = m_Timers; timer.Prev = m_Timers.Prev; m_Timers.Prev.Next = timer; m_Timers.Prev = timer; } // If, after we add the new tail, there is a chance that the tail is the next // node to be processed, we need to wake up the timer thread. if (needProd) { TimerThread.Prod(); } return(timer); }
/// <devdoc> /// <para> /// Adds a <see cref='System.Net.NetworkCredential'/> instance to the credential cache. /// </para> /// </devdoc> public void Add(Uri uriPrefix, string authenticationType, NetworkCredential credential) { // Parameter validation if (uriPrefix == null) { throw new ArgumentNullException("uriPrefix"); } if (authenticationType == null) { throw new ArgumentNullException("authenticationType"); } ++_version; CredentialKey key = new CredentialKey(uriPrefix, authenticationType); GlobalLog.Print("CredentialCache::Add() Adding key:[" + key.ToString() + "], cred:[" + credential.Domain + "],[" + credential.UserName + "]"); _cache.Add(key, credential); if (credential is SystemNetworkCredential) { ++_numbDefaultCredInCache; } }
// Allows creating a pre-completed result with less interlockeds. Beware! Constructor calls the callback. // If a derived class ever uses this and overloads Cleanup, this may need to change. internal LazyAsyncResult(object myObject, object myState, AsyncCallback myCallBack, object result) { if (result == DBNull.Value) { if (GlobalLog.IsEnabled) { GlobalLog.AssertFormat("LazyAsyncResult#{0}::.ctor()|Result can't be set to DBNull - it's a special internal value.", LoggingHash.HashString(this)); } Debug.Fail("LazyAsyncResult#" + LoggingHash.HashString(this) + "::.ctor()|Result can't be set to DBNull - it's a special internal value."); } _asyncObject = myObject; _asyncState = myState; _asyncCallback = myCallBack; _result = result; _intCompleted = 1; if (_asyncCallback != null) { if (GlobalLog.IsEnabled) { GlobalLog.Print("LazyAsyncResult#" + LoggingHash.HashString(this) + "::Complete() invoking callback"); } _asyncCallback(this); } else if (GlobalLog.IsEnabled) { GlobalLog.Print("LazyAsyncResult#" + LoggingHash.HashString(this) + "::Complete() no callback to invoke"); } if (GlobalLog.IsEnabled) { GlobalLog.Print("LazyAsyncResult#" + LoggingHash.HashString(this) + "::.ctor() (pre-completed)"); } }
/// <devdoc> /// <para>[To be supplied.]</para> /// </devdoc> public Uri GetProxy(Uri destination) { GlobalLog.Print("WebProxy#" + ValidationHelper.HashString(this) + "::GetProxy() destination:" + ValidationHelper.ToString(destination)); if (destination == null) { throw new ArgumentNullException("destination"); } AutoWebProxyState autoWebProxyState; Uri result = GetProxyAuto(destination, out autoWebProxyState); if (autoWebProxyState == AutoWebProxyState.ExecutionSuccess) { return(result); } if (IsBypassedManual(destination)) { return(destination); } Hashtable proxyHostAddresses = _ProxyHostAddresses; Uri proxy = proxyHostAddresses != null ? proxyHostAddresses[destination.Scheme] as Uri : _ProxyAddress; return(proxy != null? proxy : destination); }
public Authorization Authenticate(string challenge, WebRequest webRequest, ICredentials credentials) { GlobalLog.Print("BasicClient::Authenticate(): " + challenge); GlobalLog.Assert(credentials != null, "BasicClient::Authenticate()|credentials == null"); #if !FEATURE_PAL if (credentials == null || credentials is SystemNetworkCredential) { #else if (credentials == null) { #endif // !FEATURE_PAL return(null); } HttpWebRequest httpWebRequest = webRequest as HttpWebRequest; GlobalLog.Assert(httpWebRequest != null, "BasicClient::Authenticate()|httpWebRequest == null"); if (httpWebRequest == null || httpWebRequest.ChallengedUri == null) { // // there has been no challenge: // 1) the request never went on the wire // 2) somebody other than us is calling into AuthenticationManager // return(null); } int index = AuthenticationManager.FindSubstringNotInQuotes(challenge, Signature); if (index < 0) { return(null); } return(Lookup(httpWebRequest, credentials)); }
// private static SecurityPackageInfoClass[] m_SecurityPackages; private static SecurityPackageInfoClass[] EnumerateSecurityPackages(SSPIInterface SecModule) { GlobalLog.Enter("EnumerateSecurityPackages"); int moduleCount = 0; IntPtr arrayBase = IntPtr.Zero; int errorCode = SecModule.EnumerateSecurityPackages( out moduleCount, out arrayBase); GlobalLog.Print("SSPIWrapper::arrayBase: " + ((long)arrayBase).ToString()); if (errorCode != 0) { throw new Win32Exception(errorCode); } SecurityPackageInfoClass[] securityPackages = new SecurityPackageInfoClass[moduleCount]; int i; IntPtr unmanagedPointer = arrayBase; for (i = 0; i < moduleCount; i++) { GlobalLog.Print("SSPIWrapper::unmanagedPointer: " + ((long)unmanagedPointer).ToString()); securityPackages[i] = new SecurityPackageInfoClass(SecModule, unmanagedPointer); unmanagedPointer = IntPtrHelper.Add(unmanagedPointer, SecurityPackageInfo.Size); } SecModule.FreeContextBuffer(arrayBase); GlobalLog.Leave("EnumerateSecurityPackages"); return(securityPackages); }
public static byte[] QueryContextAttributes( SSPIInterface SecModule, SecurityContext securityContext, ContextAttribute contextAttribute, int bytesRequired) { GlobalLog.Enter("QueryContextAttributes#1"); byte[] attributeBuffer = new byte[bytesRequired]; GCHandle pinnedBuffer = GCHandle.Alloc(attributeBuffer, GCHandleType.Pinned); IntPtr addrOfPinnedBuffer = pinnedBuffer.AddrOfPinnedObject(); int errorCode = SecModule.QueryContextAttributes( ref securityContext.Handle, (int)contextAttribute, addrOfPinnedBuffer); pinnedBuffer.Free(); GlobalLog.Leave("QueryContextAttributes#1"); return(attributeBuffer); }
private void BeginWriteCallback(IAsyncResult transportResult) { GlobalLog.Assert(transportResult.AsyncState is WorkerAsyncResult, "StreamFramer::BeginWriteCallback|The state expected to be WorkerAsyncResult, received:{0}.", transportResult.AsyncState.GetType().FullName); if (transportResult.CompletedSynchronously) { return; } WorkerAsyncResult workerResult = (WorkerAsyncResult)transportResult.AsyncState; try { BeginWriteComplete(transportResult); } catch (Exception e) { if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) { throw; } workerResult.InvokeCallback(e); } }
/*++ * * ResponseStream - Return the response stream. * * This property returns the response stream for this response. The * response stream will do de-chunking, etc. as needed. * * Input: Nothing. Property is readonly. * * Returns: Response stream for response. * * --*/ /// <devdoc> /// <para>Gets the stream used for reading the body of the response from the /// server.</para> /// </devdoc> public override Stream GetResponseStream() { if (Logging.On) { Logging.Enter(Logging.Web, this, "GetResponseStream", ""); } CheckDisposed(); if (Logging.On) { Logging.PrintInfo(Logging.Web, "ContentLength=" + m_ContentLength); } Stream result; if (m_IsWebSocketResponse && m_StatusCode == HttpStatusCode.SwitchingProtocols) // HTTP 101 { if (this.m_WebSocketConnectionStream == null) { ConnectStream connectStream = m_ConnectStream as ConnectStream; GlobalLog.Assert(connectStream != null, "HttpWebResponse.m_ConnectStream should always be a ConnectStream in WebSocket cases."); GlobalLog.Assert(connectStream.Connection != null, "HttpWebResponse.m_ConnectStream.Connection should never be null in WebSocket cases."); this.m_WebSocketConnectionStream = new WebSocketConnectionStream(connectStream, this.ConnectionGroupName); } result = this.m_WebSocketConnectionStream; } else { result = m_ConnectStream; } if (Logging.On) { Logging.Exit(Logging.Web, this, "GetResponseStream", result); } return(result); }
internal override void MultipleWrite(BufferOffsetSize[] buffers) { GlobalLog.Print("TlsStream#" + ValidationHelper.HashString(this) + "::MultipleWrite() SecureWorker#" + ValidationHelper.HashString(m_Worker) + " buffers.Length:" + buffers.Length.ToString()); if (!m_Worker.IsAuthenticated) { ProcessAuthentication(null); } try { m_Worker.SecureStream.Write(buffers); } catch { //HttpWbeRequest depends on the physical stream to be dropped on a write error. Socket chkSocket = this.Socket; if (chkSocket != null) { chkSocket.InternalShutdown(SocketShutdown.Both); } // We preserve the original status of a failure because the read // side will now fail with object dispose error. if (m_Worker.IsCertValidationFailed) { m_ExceptionStatus = WebExceptionStatus.TrustFailure; } else if (m_Worker.LastSecurityStatus != SecurityStatus.OK) { m_ExceptionStatus = WebExceptionStatus.SecureChannelFailure; } else { m_ExceptionStatus = WebExceptionStatus.SendFailure; } throw; } }
internal unsafe SecSizes(byte[] memory) { fixed(void *voidPtr = memory) { IntPtr unmanagedAddress = new IntPtr(voidPtr); try { // TODO (Issue #3114): replace with Marshal.PtrToStructure. MaxToken = (int)checked ((uint)Marshal.ReadInt32(unmanagedAddress)); MaxSignature = (int)checked ((uint)Marshal.ReadInt32(unmanagedAddress, 4)); BlockSize = (int)checked ((uint)Marshal.ReadInt32(unmanagedAddress, 8)); SecurityTrailer = (int)checked ((uint)Marshal.ReadInt32(unmanagedAddress, 12)); } catch (OverflowException) { if (GlobalLog.IsEnabled) { GlobalLog.Assert("SecSizes::.ctor", "Negative size."); } throw; } } }
/// <devdoc> /// <para> /// Removes a <see cref='System.Net.NetworkCredential'/> instance from the credential cache. /// </para> /// </devdoc> public void Remove(Uri uriPrefix, string authenticationType) { if (uriPrefix == null || authenticationType == null) { // These couldn't possibly have been inserted into // the cache because of the test in Add(). return; } ++_version; CredentialKey key = new CredentialKey(uriPrefix, authenticationType); if (GlobalLog.IsEnabled) { GlobalLog.Print("CredentialCache::Remove() Removing key:[" + key.ToString() + "]"); } if (_cache[key] is SystemNetworkCredential) { --_numbDefaultCredInCache; } _cache.Remove(key); }
/* * This is to support SSL with no client cert. * Important: safeHandle should not be Disposed during construction of this object. * * _SecPkgInfoW in sspi.h */ internal SecurityPackageInfoClass(SafeHandle safeHandle, int index) { if (safeHandle.IsInvalid) { GlobalLog.Print("SecurityPackageInfoClass::.ctor() the pointer is invalid: " + (safeHandle.DangerousGetHandle()).ToString("x")); return; } IntPtr unmanagedAddress = IntPtrHelper.Add(safeHandle.DangerousGetHandle(), SecurityPackageInfo.Size * index); GlobalLog.Print("SecurityPackageInfoClass::.ctor() unmanagedPointer: " + ((long)unmanagedAddress).ToString("x")); // TODO (Issue #3114): replace with Marshal.PtrToStructure. Capabilities = Marshal.ReadInt32(unmanagedAddress, (int)Marshal.OffsetOf <SecurityPackageInfo>("Capabilities")); Version = Marshal.ReadInt16(unmanagedAddress, (int)Marshal.OffsetOf <SecurityPackageInfo>("Version")); RPCID = Marshal.ReadInt16(unmanagedAddress, (int)Marshal.OffsetOf <SecurityPackageInfo>("RPCID")); MaxToken = Marshal.ReadInt32(unmanagedAddress, (int)Marshal.OffsetOf <SecurityPackageInfo>("MaxToken")); IntPtr unmanagedString; unmanagedString = Marshal.ReadIntPtr(unmanagedAddress, (int)Marshal.OffsetOf <SecurityPackageInfo>("Name")); if (unmanagedString != IntPtr.Zero) { Name = Marshal.PtrToStringUni(unmanagedString); GlobalLog.Print("Name: " + Name); } unmanagedString = Marshal.ReadIntPtr(unmanagedAddress, (int)Marshal.OffsetOf <SecurityPackageInfo>("Comment")); if (unmanagedString != IntPtr.Zero) { Comment = Marshal.PtrToStringUni(unmanagedString); GlobalLog.Print("Comment: " + Comment); } GlobalLog.Print("SecurityPackageInfoClass::.ctor(): " + ToString()); }
} // Position public override int Read( [In, Out] byte[] buffer, int offset, int count) { GlobalLog.Print("ListenerRequestStream.ReadCore() offset: " + Convert.ToString(offset) + " count:" + Convert.ToString(count)); int DataCopiedFromBuffer = 0; int DataCopiedFromDriver = 0; // // see if we still have some data in the buffer // if (m_BufferedDataExists) { // // start sending data in the buffer // DataCopiedFromBuffer = Math.Min( m_DataBuffer.Length - m_DataBufferOffset, count); Buffer.BlockCopy( m_DataBuffer, m_DataBufferOffset, buffer, offset, DataCopiedFromBuffer); // // update the offset for the buffered data for subsequent calls // m_DataBufferOffset += DataCopiedFromBuffer; m_BufferedDataExists = m_DataBuffer.Length > m_DataBufferOffset; // // update offset and count in the buffer for subsequent calls // offset += DataCopiedFromBuffer; count -= DataCopiedFromBuffer; } // // if all the data requested was handled by the buffered data we don't // need to call the driver for more, so we just return here // if (count <= 0 || !m_MoreToRead) { return(DataCopiedFromBuffer); } // // otherwise pin the buffer and make an unmanaged call to the driver to // read more entity body // GCHandle PinnedBuffer; IntPtr AddrOfPinnedBuffer = IntPtr.Zero; PinnedBuffer = GCHandle.Alloc(buffer, GCHandleType.Pinned); AddrOfPinnedBuffer = PinnedBuffer.AddrOfPinnedObject(); // // issue unmanaged blocking call // int result = ComNetOS.IsWinNt ? UlSysApi.UlReceiveEntityBody( m_AppPoolHandle, m_RequestId, UlConstants.UL_RECEIVE_REQUEST_FLAG_COPY_BODY, AddrOfPinnedBuffer, count, ref DataCopiedFromDriver, IntPtr.Zero) : UlVxdApi.UlReceiveHttpRequestEntityBody( m_AppPoolHandle, m_RequestId, 0, AddrOfPinnedBuffer, count, ref DataCopiedFromDriver, IntPtr.Zero); PinnedBuffer.Free(); if (result != NativeMethods.ERROR_SUCCESS && result != NativeMethods.ERROR_HANDLE_EOF) { // // Consider: move all Exception string to system.txt for localization // throw new InvalidOperationException("UlReceiveEntityBody() failed, err#" + Convert.ToString(result)); } return(DataCopiedFromBuffer + DataCopiedFromDriver); } // Read()
// // Handshake - the Handshake is perhaps the most important part of the SSL process, // this is a Handshake protocol between server & client, where we send a // a HELLO message / server responds, we respond back, and after a few round trips, // we have an SSL connection with the server. But this process may be repeated, // if a higher level of security is required for by the server, therefore, // this function may be called several times in the life of the connection. // // returns an Exception on error, containing the error code of the failure // private Exception Handshake(ProtocolToken message) { // // With some SSPI APIs, the SSPI wrapper may throw // uncaught Win32Exceptions, so we need to add // this try - catch here. // try { int round = 0; byte[] incoming = null; // will be null == message on connection creation/otherwise should be // renegotation if (message == null) { GlobalLog.Assert( (SecureChannel == null), "had assembed a null SecureChannel at this point", "SecureChannel != null"); m_SecureChannel = new SecureChannel(m_DestinationHost, m_ClientCertificates); } else { incoming = message.Payload; } do { GlobalLog.Print("Handshake::Round #" + round); // // this code runs in the constructor, hence there's no // way SecureChannel can become null // message = SecureChannel.NextMessage(incoming); #if TRAVE GlobalLog.Print("Handshake::generating TLS message(Status:" + SecureChannel.MapSecurityStatus((uint)message.Status) + " Done:" + message.Done.ToString() + ")"); #endif if (message.Failed) { break; } if (message.Payload != null) { GlobalLog.Print("Handshake::Outgoing message size: " + message.Payload.Length); GlobalLog.Dump(message.Payload); base.Write(message.Payload, 0, message.Payload.Length); } else { GlobalLog.Print("Handshake::No message necessary."); } if (message.Done) { break; } // // ReadFullRecord attempts to parse read data // from the byte stream, this can be dangerous as its not // always sure about protocols, at this point // incoming = ReadFullRecord(null, 0); if (incoming == null) { // // Handshake failed // GlobalLog.Print("Handshake::ReadFullRecord is null, Handshake failed"); GlobalLog.Assert( (!message.Done), "attempted bad return / must always fail", "message.Done"); return(message.GetException()); } GlobalLog.Print("Handshake::Incoming message size: " + incoming.Length); round++; } while (!message.Done); if (message.Done) { SecureChannel.ProcessHandshakeSuccess(); GlobalLog.Print("Handshake::Handshake completed successfully."); } else { // SEC_I_CONTINUE_NEEDED #if TRAVE GlobalLog.Print("Handshake::FAILED Handshake, last error: " + SecureChannel.MapSecurityStatus((uint)message.Status)); #endif } return(message.GetException()); } catch (Exception exception) { return(exception); } }
/* * // * internal void SetPattern(string pattern) * { * GlobalLog.Print("ShellServices.ShellExpression#" + ValidationHelper.HashString(this) + "::SetPattern() pattern:" + ValidationHelper.ToString(pattern)); * Parse(pattern); * } */ internal bool IsMatch(string target) { GlobalLog.Print("ShellServices.ShellExpression#" + ValidationHelper.HashString(this) + "::IsMatch() target:" + ValidationHelper.ToString(target)); int i = 0; int j = 0; bool reverse = false; bool matched = false; while (true) { if (!reverse) { if (j > target.Length) { break; } switch (pattern[i]) { case ShExpTokens.Asterisk: match[i++] = j = target.Length; continue; case ShExpTokens.Question: if (j == target.Length) { reverse = true; } else { match[i++] = ++j; } continue; case ShExpTokens.AugmentedDot: if (j == target.Length) { match[i++] = j; } else if (target[j] == '.') { match[i++] = ++j; } else { reverse = true; } continue; case ShExpTokens.AugmentedAsterisk: if (j == target.Length || target[j] == '.') { reverse = true; } else { match[i++] = ++j; } continue; case ShExpTokens.AugmentedQuestion: if (j == target.Length || target[j] == '.') { match[i++] = j; } else { match[i++] = ++j; } continue; case ShExpTokens.Start: if (j != 0) { break; } match[i++] = 0; continue; case ShExpTokens.End: if (j == target.Length) { matched = true; break; } reverse = true; continue; default: if (j < target.Length && (int)pattern[i] == (int)char.ToLowerInvariant(target[j])) { match[i++] = ++j; } else { reverse = true; } continue; } } else { switch (pattern[--i]) { case ShExpTokens.Asterisk: case ShExpTokens.AugmentedQuestion: if (match[i] != match[i - 1]) { j = --match[i++]; reverse = false; } continue; case ShExpTokens.Start: case ShExpTokens.End: break; case ShExpTokens.Question: case ShExpTokens.AugmentedDot: case ShExpTokens.AugmentedAsterisk: default: continue; } } break; } GlobalLog.Print("ShellServices.ShellExpression#" + ValidationHelper.HashString(this) + "::IsMatch() return:" + matched.ToString()); return(matched); }
// // BeginWrite - // // Write the bytes to the write - while encrypting // // copy plain text data to a temporary buffer // encrypt the data // once the data is encrypted clear the plain text for security // public override IAsyncResult BeginWrite(byte[] buffer, int offset, int size, AsyncCallback asyncCallback, object asyncState) { GlobalLog.Print("TlsStream#" + ValidationHelper.HashString(this) + "::BeginWrite() SecureChannel#" + ValidationHelper.HashString(SecureChannel) + " offset:" + offset.ToString() + " size:" + size.ToString()); return(InnerWrite(true /*async*/, buffer, offset, size, asyncCallback, asyncState)); }
private IAsyncResult InnerWrite(bool async, byte[] buffer, int offset, int size, AsyncCallback asyncCallback, object asyncState) { // after shutdown/Close throw an exception if (m_ShutDown > 0) { throw new ObjectDisposedException(this.GetType().FullName); } // on earlier error throw an exception if (InnerException != null) { throw InnerException; } // // parameter validation // if (buffer == null) { throw new ArgumentNullException("buffer"); } if (offset < 0 || offset > buffer.Length) { throw new ArgumentOutOfRangeException("offset"); } if (size < 0 || size > buffer.Length - offset) { throw new ArgumentOutOfRangeException("size"); } // // Lock the Write: this is inefficent, but we need to prevent // writing data while the Stream is doing a handshake with the server. // writing other data during the handshake would cause the server to // fail and close the connection. // lock (this) { // // encrypt the data // byte[] ciphertext = null; GlobalLog.Print("Encrypt[" + Encoding.ASCII.GetString(buffer, 0, Math.Min(buffer.Length, 512)) + "]"); SecureChannel chkSecureChannel = SecureChannel; if (chkSecureChannel == null) { InnerException = new IOException(SR.GetString(SR.net_io_writefailure)); throw InnerException; } if (size > chkSecureChannel.MaxDataSize) { BufferOffsetSize [] buffers = new BufferOffsetSize[1]; buffers[0] = new BufferOffsetSize(buffer, offset, size, false); if (async) { return(BeginMultipleWrite(buffers, asyncCallback, asyncState)); } else { MultipleWrite(buffers); return(null); } } int errorCode = chkSecureChannel.Encrypt(buffer, offset, size, ref ciphertext); if (errorCode != (int)SecurityStatus.OK) { ProtocolToken message = new ProtocolToken(null, errorCode); InnerException = message.GetException(); throw InnerException; } try { if (async) { IAsyncResult asyncResult = base.BeginWrite( ciphertext, 0, ciphertext.Length, asyncCallback, asyncState); return(asyncResult); } else { base.Write(ciphertext, 0, ciphertext.Length); return(null); } } catch (Exception exception) { // // some sort of error occured Writing to the Trasport, // set the Exception as InnerException and throw // InnerException = new IOException(SR.GetString(SR.net_io_writefailure), exception); throw InnerException; } } }
public override IAsyncResult BeginRead(byte[] buffer, int offset, int size, AsyncCallback asyncCallback, object asyncState) { GlobalLog.Print("TlsStream#" + ValidationHelper.HashString(this) + "::BeginRead() SecureChannel#" + ValidationHelper.HashString(SecureChannel) + " offset:" + offset.ToString() + " size:" + size.ToString()); // after shutdown/Close throw an exception if (m_ShutDown > 0) { throw new ObjectDisposedException(this.GetType().FullName); } // on earlier error throw an exception if (InnerException != null) { throw InnerException; } // // parameter validation // if (buffer == null) { throw new ArgumentNullException("buffer"); } if (offset < 0 || offset > buffer.Length) { throw new ArgumentOutOfRangeException("offset"); } if (size < 0 || size > buffer.Length - offset) { throw new ArgumentOutOfRangeException("size"); } // cannot handle nested BeginRead, BeginRead calls without corrsponding EndRead //GlobalLog.Assert(Interlocked.Increment( ref m_NestCounter ) == 1, // "TlsStream::BeginRead m_NestCounter!=1, nesting not allowed of BeginRead", // m_NestCounter.ToString()); if (Interlocked.Increment(ref m_NestCounter) != 1) { throw new ArgumentException("TlsStream"); } NestedSingleAsyncResult asyncResult = new NestedSingleAsyncResult(this, asyncState, asyncCallback, buffer, offset, size); // check if there is already data present if (m_ExistingAmount > 0) { GlobalLog.Print("BeginReceive: data already present in buffer!"); // In this case no I/O is performed-- data is copied // from internal buffer to the user space asyncResult.InvokeCallback(true); } else { // otherwise we have to read data from the network and decrypt // to preserve asynchronous mode, the I/O operation will be // qued as a work item for the runtime thread pool GlobalLog.Print("BeginReceive: must issue read from network"); SecureChannel chkSecureChannel = SecureChannel; if (chkSecureChannel == null) { //this object was disposed from other thread throw new ObjectDisposedException(this.GetType().FullName); } int bufferLength = chkSecureChannel.HeaderSize; m_AsyncResponseBuffer = new byte[bufferLength]; try { asyncResult.NestedAsyncResult = base.BeginRead( m_AsyncResponseBuffer, 0, bufferLength, new AsyncCallback(AsyncReceiveComplete), asyncResult ); } catch (Exception exception) { GlobalLog.Print("TlsStream#" + ValidationHelper.HashString(this) + "::BeginRead() exception: " + exception); InnerException = new IOException(SR.GetString(SR.net_io_readfailure), exception); throw; } if (asyncResult.NestedAsyncResult == null) { GlobalLog.Print("TlsStream#" + ValidationHelper.HashString(this) + "::BeginRead(): base.BeginRead() returns null"); } } return(asyncResult); }
// // Write, all flavours: synchrnous and asynchrnous // public override void Write(byte[] buffer, int offset, int size) { GlobalLog.Print("TlsStream#" + ValidationHelper.HashString(this) + "::Write() SecureChannel#" + ValidationHelper.HashString(SecureChannel) + " offset:" + offset.ToString() + " size:" + size.ToString()); InnerWrite(false /*async*/, buffer, offset, size, null, null); }
// // ReadFullRecord - reads a block of bytes, // attemps to ascertain, how much to read, by // assuming block encoding of the byte stream. // // This can be dangerous as these things // tend to change from protocol to protocol // // WARNING: Can throw! // public byte[] ReadFullRecord(byte[] buffer, int length) { // after shutdown/Close throw an exception if (m_ShutDown > 0) { throw new ObjectDisposedException(this.GetType().FullName); } SecureChannel chkSecureChannel = SecureChannel; if (chkSecureChannel == null) { return(null); } int headerSize = chkSecureChannel.HeaderSize; byte[] header = new byte[headerSize]; int read = length; if (buffer != null) { GlobalLog.Assert(length <= headerSize, "length > headerSize", ""); Buffer.BlockCopy(buffer, 0, header, 0, Math.Min(length, headerSize)); } if (length < headerSize) { GlobalLog.Print("RecordLayer::ReadFullRecord Reading " + headerSize + " byte header from the stream"); read += ForceRead(header, length, headerSize - length); } GlobalLog.Dump(header); if (read != headerSize) { GlobalLog.Print("RecordLayer::ReadFullRecord returning null"); return(null); } // if we can't verify, just return what we can find if (!verifyRecordFormat(header)) { return(header); } // WARNING this line, I find worrisome, because it // can differ on new protocols int payloadSize = (0x100 * header[3]) + header[4]; byte[] record = new byte[payloadSize + headerSize]; Buffer.BlockCopy(header, 0, record, 0, headerSize); int received = ForceRead(record, headerSize, payloadSize); GlobalLog.Dump(record); if (received < payloadSize) { GlobalLog.Print("RecordLayer::ReadFullRecord returning null"); return(null); } return(record); }
/*++ * * Close method for this class. Closes the TlsStream * * Input: Nothing. * * Returns: Nothing. * * --*/ public override void Close() { GlobalLog.Print("TlsStream::Close()"); ((IDisposable)this).Dispose(); }
// // NextRecord - called typically in Callback // to indicate that we need more bytes from the wire // to be decrypted. It is called either by a worker // thread or by the Read directly, it reads one chunk // of data, and attempts to decrypt. As soon as it has // the chunk of unencrypted data, it returns it in // m_ArrivingData and m_ExistingAmount contains, // the amount data that was decrypted. // // ASSUMES: we have an empty buffer of unencrypted bytes // RETURNS: upon error, by either leaving this buffer empty (0), // with an Exception set on this object, or on success, // by updating the global state (m_ArrivingData) // with unencrypted bytes // // WARNING: Can Throw! // private void NextRecord(byte[] buffer, int length) { byte[] packet = null; GlobalLog.Assert( (m_ExistingAmount == 0), "m_ExistingAmount != 0", "Has assumed internal SSL buffer would be empty"); // // This LOOP below will keep going until (EITHER): // 1) we have ONE succesful chunk of unencrypted data // 2) we have an error either from a renegotiate handhake (OR) Read (OR) Decrypt // do { packet = ReadFullRecord(buffer, length); if (packet == null) { return; } lock (this) { SecureChannel chkSecureChannel = SecureChannel; if (chkSecureChannel == null) { return; } int errorCode = chkSecureChannel.Decrypt(packet, ref m_ArrivingData); if (errorCode == (int)SecurityStatus.OK) { // SUCCESS - we have our decrypted Bytes GlobalLog.Print("TlsStream::NextRecord called (success) Decrypt[" + (m_ArrivingData != null ? (Encoding.ASCII.GetString(m_ArrivingData, 0, Math.Min(m_ArrivingData.Length, 512))) : "null") + "]"); break; } else { // ERROR - examine what kind ProtocolToken message = new ProtocolToken(packet, errorCode); GlobalLog.Print("TlsStream:: Decrypt errorCode = " + errorCode.ToString()); if (message.Renegotiate) { // HANDSHAKE - do a handshake between us and server InnerException = Handshake(message); if (InnerException != null) { return; // failure } // CONTINUE - Read On! we pick up from where // we were before the handshake and try to get // one block of unencrypted bytes, the earlier block // of data was control information for the handshake. // We need to read in the new header. if (ForceRead(buffer, 0, length) < length) { InnerException = new IOException(SR.GetString(SR.net_io_readfailure)); return; //failure } } else if (message.CloseConnection) { // CLOSE - server ordered us to shut down Close(); // close down the socket return; } else { // EXCEPTION - throw later on InnerException = message.GetException(); return; } } } // continue here in the case where we had a handshake, and needed // to reget new Data } while (true); // m_ExistingAmount was 0 on entry! if (m_ArrivingData == null) { return; } m_ExistingAmount = m_ArrivingData.Length; return; }
/// <devdoc> /// <para>Pre-authenticates a request.</para> /// </devdoc> public override Authorization PreAuthenticate(WebRequest request, ICredentials credentials) { GlobalLog.Print( "AuthenticationManager::PreAuthenticate() request:" + ValidationHelper.HashString(request) + " credentials:" + ValidationHelper.HashString(credentials)); if (request == null) { throw new ArgumentNullException("request"); } if (credentials == null) { return(null); } HttpWebRequest httpWebRequest = request as HttpWebRequest; IAuthenticationModule authenticationModule; if (httpWebRequest == null) { return(null); } // // PrefixLookup is thread-safe // string moduleName = moduleBinding.Lookup(httpWebRequest.ChallengedUri.AbsoluteUri) as string; GlobalLog.Print( "AuthenticationManager::PreAuthenticate() s_ModuleBinding.Lookup returns:" + ValidationHelper.ToString(moduleName)); if (moduleName == null) { return(null); } authenticationModule = findModule(moduleName); if (authenticationModule == null) { // The module could have been unregistered. No preauthentication is possible. return(null); } // Prepopulate the channel binding token so we can try preauth // (but only for modules that actually need it!). if (httpWebRequest.ChallengedUri.Scheme == Uri.UriSchemeHttps) { object binding = httpWebRequest.ServicePoint.CachedChannelBinding; #if DEBUG // The ModuleRequiresChannelBinding method is only compiled in DEBUG so the assert must be restricted // to DEBUG as well. // If the authentication module does CBT, we require that it also caches channel bindings. System.Diagnostics.Debug.Assert( !(binding == null && ModuleRequiresChannelBinding(authenticationModule))); #endif // can also be DBNull.Value, indicating "we previously succeeded without getting a CBT." // (ie, unpatched SSP talking to a partially-hardened server) ChannelBinding channelBinding = binding as ChannelBinding; if (channelBinding != null) { httpWebRequest.CurrentAuthenticationState.TransportContext = new CachedTransportContext(channelBinding); } } // Otherwise invoke the PreAuthenticate method. // We're guaranteed that CanPreAuthenticate is true because we check before calling BindModule(). Authorization authorization = authenticationModule.PreAuthenticate(request, credentials); if (authorization != null && !authorization.Complete && httpWebRequest != null) { httpWebRequest.CurrentAuthenticationState.Module = authenticationModule; } GlobalLog.Print( "AuthenticationManager::PreAuthenticate() " + "IAuthenticationModule.PreAuthenticate() returned authorization:" + ValidationHelper.HashString(authorization)); return(authorization); }
/// <devdoc> /// <para>Call each registered authentication module to determine the first module that /// can respond to the authentication request.</para> /// </devdoc> public override Authorization Authenticate(string challenge, WebRequest request, ICredentials credentials) { if (request == null) { throw new ArgumentNullException("request"); } if (credentials == null) { throw new ArgumentNullException("credentials"); } if (challenge == null) { throw new ArgumentNullException("challenge"); } GlobalLog.Print("AuthenticationManager::Authenticate() challenge:[" + challenge + "]"); Authorization response = null; HttpWebRequest httpWebRequest = request as HttpWebRequest; if (httpWebRequest != null && httpWebRequest.CurrentAuthenticationState.Module != null) { response = httpWebRequest.CurrentAuthenticationState.Module.Authenticate(challenge, request, credentials); } else { // This is the case where we would try to find the module on the first server challenge lock (moduleBinding) { // // fastest way of iterating on the ArrayList // for (int i = 0; i < ModuleList.Count; i++) { IAuthenticationModule authenticationModule = (IAuthenticationModule)ModuleList[i]; // // the AuthenticationModule will // 1) return a valid string on success // 2) return null if it knows it cannot respond // 3) throw if it could have responded but unexpectedly failed to do so // if (httpWebRequest != null) { httpWebRequest.CurrentAuthenticationState.Module = authenticationModule; } response = authenticationModule.Authenticate(challenge, request, credentials); if (response != null) { // // found the Authentication Module, return it // GlobalLog.Print("AuthenticationManager::Authenticate() found IAuthenticationModule:[" + authenticationModule.AuthenticationType + "]"); break; } } } } return(response); }
internal static int FindSubstringNotInQuotes(string challenge, string signature) { int index = -1; Debug.Assert(signature.ToLowerInvariant().Equals(signature, StringComparison.Ordinal), "'signature' parameter must be lower case"); if (challenge != null && signature != null && challenge.Length >= signature.Length) { int firstQuote = -1, secondQuote = -1; for (int i = 0; i < challenge.Length && index < 0; i++) { // Search for the quotes if (challenge[i] == '\"') { if (firstQuote <= secondQuote) { firstQuote = i; } else { secondQuote = i; } } // We've found both ends of an unquoted segment (could be whole challenge), search inside for the signature. if (i == challenge.Length - 1 || (challenge[i] == '\"' && firstQuote > secondQuote)) { // see if the portion of challenge out of the quotes contains // the signature of the IAuthenticationModule if (i == challenge.Length - 1) { firstQuote = challenge.Length; } // unquoted segment is too small to hold a scheme name, ie: scheme param="value",a="" if (firstQuote < secondQuote + 3) { continue; } int checkstart = secondQuote + 1; int checkLength = firstQuote - secondQuote - 1; do { // Search for the next (partial match) occurance of the signature index = IndexOf(challenge, signature, checkstart, checkLength); if (index >= 0) { // Verify the signature is a full scheme name match, not a partial match or a parameter name: if ((index == 0 || challenge[index - 1] == ' ' || challenge[index - 1] == ',') && (index + signature.Length == challenge.Length || challenge[index + signature.Length] == ' ' || challenge[index + signature.Length] == ',')) { break; } // Only a partial match / param name, but maybe there is another occurance of the signature later? checkLength -= index - checkstart + 1; checkstart = index + 1; } } while (index >= 0); } } } GlobalLog.Print("AuthenticationManager::FindSubstringNotInQuotes(" + challenge + ", " + signature + ")=" + index.ToString()); return(index); }
internal InternalException() { GlobalLog.Assert("InternalException thrown."); }