public static void Main() { using (Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) { // Addressing IPAddress ipAddress = IPAddress.Parse(dottedServerIPAddress); IPEndPoint serverEndPoint = new IPEndPoint(ipAddress, port); // Connecting Debug.Print("Connecting to server " + serverEndPoint + "."); clientSocket.Connect(serverEndPoint); Debug.Print("Connected to server."); using (SslStream sslStream = new SslStream(clientSocket)) { X509Certificate rootCA = new X509Certificate(Resources.GetBytes(Resources.BinaryResources.MyRootCA)); X509Certificate clientCert = new X509Certificate(Resources.GetBytes(Resources.BinaryResources.MyRootCA)); sslStream.AuthenticateAsClient("MyServerName", // Hostname needs to match CN of server cert clientCert, // Authenticate client new X509Certificate[] { rootCA }, // CA certs for verification SslVerification.CertificateRequired, // Verify server SslProtocols.Default // Protocols that may be required ); // Sending byte[] messageBytes = Encoding.UTF8.GetBytes("Hello World!"); sslStream.Write(messageBytes, 0, messageBytes.Length); } }// the socket will be closed here }
public void RunClient() { // Create a TCP/IP client socket. clientSocket = new Socket(AddressFamily.InterNetwork, clientSocketType, clientProtocolType); clientSocket.Bind(new IPEndPoint(IPAddress.Loopback, 0)); while (true) { try { // Connect to the server clientSocket.Connect(serverEp); break; } catch (SocketException) { // Server down, try again Thread.Sleep(1000); } } Log.Comment("Client connected."); // Create an SSL stream that will close the client's stream. sslClient = new SslStream(clientSocket); // The server name must match the name on the server certificate. sslClient.AuthenticateAsClient(targetHost, cert, ca, verify, sslProtocols); // Send hello message to the server. Log.Comment("Sending message to Server: " + messageSent); byte[] message = Encoding.UTF8.GetBytes(messageSent); sslClient.Write(message, 0, message.Length); Log.Comment("do we need to flush? after a write?"); sslClient.Flush(); // Read message from the server. messageReceived = ReadMessage(sslClient); Log.Comment("Server says:" + messageReceived); // Do not close the clientSslStream. That is handled by the test case. }
public SecureStream(string host, Socket socket, X509Certificate ca, SslProtocols encryption) { _socket = socket; _sslStream = new SslStream(socket); _sslStream.AuthenticateAsClient(host, null, new[] { ca }, SslVerification.CertificateRequired, encryption); }
/// <summary> /// Returns network stream connected to server. It could be a proxy or a /// real server Uri. /// </summary> /// <param name="proxyServer">Uri that describes the proxy server.</param> /// <param name="targetServer">Uri that describes the target (real) server.</param> /// <returns>Nerwork stream connected to server.</returns> private InputNetworkStreamWrapper EstablishConnection(Uri proxyServer, Uri targetServer) { InputNetworkStreamWrapper retStream = null; // Create a socket and set reuse true. // But before creating new socket we look in the list of existing sockets. If socket for this host already // exist - use it. No need to create new socket. string remoteServer = targetServer.Host + ":" + targetServer.Port; lock (m_ConnectedStreams) { ArrayList removeStreamList = new ArrayList(); for (int i = 0; i < m_ConnectedStreams.Count; i++) { InputNetworkStreamWrapper inputStream = (InputNetworkStreamWrapper)m_ConnectedStreams[i]; if (inputStream.m_rmAddrAndPort == remoteServer && !inputStream.m_InUse) { // Re-use the connected socket. // But first we need to know that socket is not closed. try { // If socket is closed ( from this or other side ) the call throws exception. if (inputStream.m_Socket.Poll(1, SelectMode.SelectWrite)) { // No exception, good we can condtinue and re-use connected stream. // Control flow returning here means persistent connection actually works. inputStream.m_InUse = true; inputStream.m_lastUsed = DateTime.Now; retStream = inputStream; break; } else { removeStreamList.Add(inputStream); } } catch (Exception) { removeStreamList.Add(inputStream); } } } for (int i = 0; i < removeStreamList.Count; i++) { InputNetworkStreamWrapper removeStream = (InputNetworkStreamWrapper)removeStreamList[i]; // Means socket was closed. Remove it from the list. m_ConnectedStreams.Remove(removeStream); removeStream.Dispose(); } } if (retStream == null) { // Existing connection did not worked. Need to establish new one. IPAddress address = null; UriHostNameType hostNameType = proxyServer.HostNameType; if (hostNameType == UriHostNameType.IPv4) { address = IPAddress.Parse(proxyServer.Host); } else if (hostNameType == UriHostNameType.Dns) { IPHostEntry hostEntry = null; try { hostEntry = Dns.GetHostEntry(proxyServer.Host); } catch(SocketException se) { throw new WebException("host not available", se, WebExceptionStatus.ConnectFailure, null); } int addressListSize = hostEntry.AddressList.Length; for (int i = 0; i < addressListSize; i++) { if ((address = hostEntry.AddressList[i]) != null) { break; } } if (address == null) { throw new WebException("Unable to resolve Dns entry to valid IPv4 Address", WebExceptionStatus.NameResolutionFailure); } } else { throw new WebException("Only IPv4 or Dns host names allowed."); } // If socket was not found in waiting connections, then we create new one. Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true); // Connect to remote endpoint try { IPEndPoint remoteEP = new IPEndPoint(address, proxyServer.Port); socket.Connect((EndPoint)remoteEP); } catch (SocketException e) { throw new WebException("connection failed", e, WebExceptionStatus.ConnectFailure, null); } bool isHttps = m_originalUrl.Scheme == "https"; // We have connected socket. Create request stream retStream = new InputNetworkStreamWrapper(new NetworkStream(socket), socket, !isHttps, proxyServer.Host + ":" + proxyServer.Port); // For https proxy works differenly from http. if (isHttps) { // If proxy is set, then for https we need to send "CONNECT" command to proxy. // Once this command is send, the socket from proxy works as if it is the socket to the destination server. if (proxyServer != targetServer) { String request = "CONNECT " + remoteServer + " HTTP/" + ProtocolVersion + "\r\n\r\n"; Byte[] bytesToSend = Encoding.UTF8.GetBytes(request); retStream.Write(bytesToSend, 0, bytesToSend.Length); // Now proxy should respond with the connected status. If it is successul, then we are good to go. CoreResponseData respData = ParseHTTPResponse(retStream, m_keepAlive); if (respData.m_statusCode != (int)HttpStatusCode.OK) { throw new WebException("Proxy returned " + respData.m_statusCode, WebExceptionStatus.ConnectFailure); } } // Once connection estiblished need to create secure stream and authenticate server. SslStream sslStream = new SslStream(retStream.m_Socket); // Throws exception is fails. sslStream.AuthenticateAsClient(m_originalUrl.Host, null, m_caCerts, m_caCerts != null ? SslVerification.CertificateRequired : SslVerification.NoVerification, SslProtocols.Default); // Changes the stream to SSL stream. retStream.m_Stream = sslStream; // Changes the address. Originally socket was connected to proxy, now as if it connected to m_originalUrl.Host on m_originalUrl.Port retStream.m_rmAddrAndPort = m_originalUrl.Host + ":" + m_originalUrl.Port; } lock (m_ConnectedStreams) { m_ConnectedStreams.Add(retStream); // if the current stream list is empty then start the timer that drops unused connections. if (m_ConnectedStreams.Count == 1) { m_DropOldConnectionsTimer.Change(HttpListener.DefaultKeepAliveMilliseconds, System.Threading.Timeout.Infinite); } } } return retStream; }
public MFTestResults RunClient() { MFTestResults testResult = MFTestResults .Pass; try { if (ipAddress == null) Debug.Print("IpAddress must be initialized before calling RunClient()"); else serverEp = new IPEndPoint(ipAddress, port); // Create a TCP/IP client socket. clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); clientSocket.Connect(serverEp); // Create an SSL stream that will close the client's stream. sslClient = new SslStream(clientSocket); Log.Comment("Calling AuthenticateAsClient()"); // The server name must match the name on the server certificate. sslClient.AuthenticateAsClient(targetHost, cert, ca, verify, sslProtocols); // Send hello message to the server. byte[] message = Encoding.UTF8.GetBytes(messageSent); sslClient.Write(message, 0, message.Length); Log.Comment("Sent: " + messageSent); // Read message from the server. messageReceived = ReadMessage(sslClient); Log.Comment("Received: " + messageReceived); if (messageSent != messageReceived) testResult = MFTestResults.Fail; } catch (SocketException e) { if (!expectedException) testResult = MFTestResults.Fail; Log.Comment("ErrorCode: " + e.ErrorCode); Log.Comment("An exception occurred: " + e.Message); } catch (Exception e) { if (!expectedException) testResult = MFTestResults.Fail; Log.Comment("An exception occurred: " + e.Message); } finally { if (sslClient != null) { Thread.Sleep(50); sslClient.Dispose(); sslClient = null; } if (clientSocket != null) { clientSocket.Close(); clientSocket = null; } } return testResult; }
static NetworkStream Connect(string host, int port, bool useSsl) { var ipHostEntry = Dns.GetHostEntry(host); Socket socket = null; SocketException exception = null; foreach (var ipAddress in ipHostEntry.AddressList) { if (ipAddress == null) continue; socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); try { socket.Connect(new IPEndPoint(ipAddress, port)); exception = null; break; } catch (SocketException socketException) { exception = socketException; socket = null; } } if (exception != null) { throw exception; } NetworkStream stream; if (useSsl) { SslStream sslStream = new SslStream(socket); sslStream.AuthenticateAsClient(host, null, SslVerification.VerifyPeer, SslProtocols.Default); stream = sslStream; } else { stream = new NetworkStream(socket, true); } return stream; }