public void Connect(string hostname, int port) { ThrowIfDisposed(); if (hostname == null) { throw new ArgumentNullException(nameof(hostname)); } if (!TcpValidationHelpers.ValidatePortNumber(port)) { throw new ArgumentOutOfRangeException(nameof(port)); } // We must now look for addresses that use a compatible address family to the client socket. However, in the // case of the <hostname,port> constructor we will have deferred creating the socket and will do that here // instead. IPAddress[] addresses = Dns.GetHostAddresses(hostname); Exception lastex = null; Socket ipv6Socket = null; Socket ipv4Socket = null; try { if (_clientSocket == null) { if (Socket.OSSupportsIPv4) { ipv4Socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); } if (Socket.OSSupportsIPv6) { ipv6Socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp); } } foreach (IPAddress address in addresses) { try { if (_clientSocket == null) { // We came via the <hostname,port> constructor. Set the // address family appropriately, create the socket and // try to connect. if (address.AddressFamily == AddressFamily.InterNetwork && ipv4Socket != null) { ipv4Socket.Connect(address, port); _clientSocket = ipv4Socket; if (ipv6Socket != null) { ipv6Socket.Close(); } } else if (ipv6Socket != null) { ipv6Socket.Connect(address, port); _clientSocket = ipv6Socket; if (ipv4Socket != null) { ipv4Socket.Close(); } } _family = address.AddressFamily; _active = true; break; } else if (IsAddressFamilyCompatible(address.AddressFamily)) { // Only use addresses with a matching family Connect(new IPEndPoint(address, port)); _active = true; break; } } catch (Exception ex) { if (ExceptionCheck.IsFatal(ex)) { throw; } lastex = ex; } } } catch (Exception ex) { if (ExceptionCheck.IsFatal(ex)) { throw; } lastex = ex; } finally { //cleanup temp sockets if failed //main socket gets closed when tcpclient gets closed //did we connect? if (!_active) { if (ipv6Socket != null) { ipv6Socket.Close(); } if (ipv4Socket != null) { ipv4Socket.Close(); } // The connect failed - rethrow the last error we had if (lastex != null) { throw lastex; } else { throw new SocketException((int)SocketError.NotConnected); } } } }
internal static int Encrypt( SafeDeleteContext securityContext, byte[] buffer, int offset, int count, bool isConfidential, bool isNtlm, ref byte[] output, uint sequenceNumber) { SecSizes sizes = SSPIWrapper.QueryContextAttributes( GlobalSSPI.SSPIAuth, securityContext, Interop.SspiCli.ContextAttribute.Sizes ) as SecSizes; try { int maxCount = checked (Int32.MaxValue - 4 - sizes.BlockSize - sizes.SecurityTrailer); if (count > maxCount || count < 0) { throw new ArgumentOutOfRangeException(nameof(count), SR.Format(SR.net_io_out_range, maxCount)); } } catch (Exception e) { if (!ExceptionCheck.IsFatal(e)) { if (GlobalLog.IsEnabled) { GlobalLog.Assert("NTAuthentication#" + LoggingHash.HashString(securityContext) + "::Encrypt", "Arguments out of range."); } Debug.Fail("NTAuthentication#" + LoggingHash.HashString(securityContext) + "::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 (isConfidential) { 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) { if (GlobalLog.IsEnabled) { GlobalLog.Print("NTAuthentication#" + LoggingHash.HashString(securityContext) + "::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); }
internal static int Encrypt( SafeDeleteContext securityContext, byte[] buffer, int offset, int count, bool isConfidential, bool isNtlm, ref byte[]?output, uint sequenceNumber) { SecPkgContext_Sizes sizes = default; bool success = SSPIWrapper.QueryBlittableContextAttributes(GlobalSSPI.SSPIAuth, securityContext, Interop.SspiCli.ContextAttribute.SECPKG_ATTR_SIZES, ref sizes); Debug.Assert(success); try { int maxCount = checked (int.MaxValue - 4 - sizes.cbBlockSize - sizes.cbSecurityTrailer); if (count > maxCount || count < 0) { throw new ArgumentOutOfRangeException(nameof(count), SR.Format(SR.net_io_out_range, maxCount)); } } catch (Exception e) when(!ExceptionCheck.IsFatal(e)) { NetEventSource.Fail(null, "Arguments out of range."); throw; } int resultSize = count + sizes.cbSecurityTrailer + sizes.cbBlockSize; 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.cbSecurityTrailer, count); // Prepare buffers TOKEN(signature), DATA and Padding. ThreeSecurityBuffers buffers = default; var securityBuffer = MemoryMarshal.CreateSpan(ref buffers._item0, 3); securityBuffer[0] = new SecurityBuffer(output, 4, sizes.cbSecurityTrailer, SecurityBufferType.SECBUFFER_TOKEN); securityBuffer[1] = new SecurityBuffer(output, 4 + sizes.cbSecurityTrailer, count, SecurityBufferType.SECBUFFER_DATA); securityBuffer[2] = new SecurityBuffer(output, 4 + sizes.cbSecurityTrailer + count, sizes.cbBlockSize, SecurityBufferType.SECBUFFER_PADDING); int errorCode; if (isConfidential) { errorCode = SSPIWrapper.EncryptMessage(GlobalSSPI.SSPIAuth, securityContext, securityBuffer, sequenceNumber); } else { if (isNtlm) { securityBuffer[1].type |= SecurityBufferType.SECBUFFER_READONLY; } errorCode = SSPIWrapper.MakeSignature(GlobalSSPI.SSPIAuth, securityContext, securityBuffer, 0); } if (errorCode != 0) { Exception e = new Win32Exception(errorCode); if (NetEventSource.IsEnabled) { NetEventSource.Error(null, e); } throw e; } // Compacting the result. resultSize = securityBuffer[0].size; bool forceCopy = false; if (resultSize != sizes.cbSecurityTrailer) { 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.cbSecurityTrailer))) { 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); }
// Establishes a connection to the specified port on the specified host. public void Connect(string hostname, int port) { // Validate input parameters. if (_cleanedUp) { throw new ObjectDisposedException(this.GetType().FullName); } if (hostname == null) { throw new ArgumentNullException("hostname"); } if (!TcpValidationHelpers.ValidatePortNumber(port)) { throw new ArgumentOutOfRangeException("port"); } // IPv6 Changes: instead of just using the first address in the list, // we must now look for addresses that use a compatible // address family to the client socket. // However, in the case of the <hostname,port> constructor // we will have deferred creating the socket and will // do that here instead. // In addition, the redundant CheckForBroadcast call was // removed here since it is called from Connect(). IPAddress[] addresses = Dns.GetHostAddressesAsync(hostname).GetAwaiter().GetResult(); Exception lastex = null; Socket ipv6Socket = null; Socket ipv4Socket = null; try { if (_clientSocket == null) { if (Socket.OSSupportsIPv4) { ipv4Socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); } if (Socket.OSSupportsIPv6) { ipv6Socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp); } } foreach (IPAddress address in addresses) { try { if (_clientSocket == null) { // We came via the <hostname,port> constructor. Set the // address family appropriately, create the socket and // try to connect. if (address.AddressFamily == AddressFamily.InterNetwork && ipv4Socket != null) { ipv4Socket.Connect(address, port); _clientSocket = ipv4Socket; if (ipv6Socket != null) { ipv6Socket.Dispose(); } } else if (ipv6Socket != null) { ipv6Socket.Connect(address, port); _clientSocket = ipv6Socket; if (ipv4Socket != null) { ipv4Socket.Dispose(); } } _family = address.AddressFamily; _active = true; break; } else if (address.AddressFamily == _family) { // Only use addresses with a matching family. Connect(new IPEndPoint(address, port)); _active = true; break; } } catch (Exception ex) { if (ExceptionCheck.IsFatal(ex)) { throw; } lastex = ex; } } } catch (Exception ex) { if (ExceptionCheck.IsFatal(ex)) { throw; } lastex = ex; } finally { // Cleanup temp sockets on failure. The main socket gets closed when the UDPClient // gets closed. // Did we connect? if (!_active) { if (ipv6Socket != null) { ipv6Socket.Dispose(); } if (ipv4Socket != null) { ipv4Socket.Dispose(); } // The connect failed - rethrow the last error we had. if (lastex != null) { throw lastex; } else { throw new SocketException((int)SocketError.NotConnected); } } } }