Пример #1
0
        /// <summary>
        /// Performs the initial handshake with the remote debugging server, verifying signature and version number and setting up SSL,
        /// and returns the opened socket and the SSL stream for that socket.
        /// </summary>
        /// <param name="hostName">Name of the host to connect to.</param>
        /// <param name="portNumber">Port number to connect to.</param>
        /// <param name="secret">Secret to authenticate with.</param>
        /// <param name="useSsl">Whether to use SSL for this connection.</param>
        /// <param name="sslErrorHandling">If using SSL, specifies how SSL certificate errors should be handled.</param>
        /// <param name="socket">Opened socket to the remote debugging server. The returned socket is owned by <paramref name="stream"/>.</param>
        /// <param name="stream">Opened SSL network stream to the remote debugging server. This stream owns the <paramref name="socket"/>, and will automatically close it.</param>
        /// <returns>Error code.</returns>
        /// <remarks><paramref name="socket"/> should not be used to send or receive data, since it is wrapped in a stream, and is owned by that stream.
        /// It is exposed solely to enable querying it for endpoint information and connectivity status.</remarks>
        public static ConnErrorMessages TryConnect(string hostName, ushort portNumber, string secret, bool useSsl, SslErrorHandling sslErrorHandling, out Socket socket, out Stream stream)
        {
            stream = null;
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            bool connected = false;
            try {
                socket.Connect(hostName, portNumber);
                var rawStream = new NetworkStream(socket, ownsSocket: true);
                if (useSsl) {
                    var sslStream = new SslStream(rawStream, false, (sender, cert, chain, errs) => {
                        if (errs == SslPolicyErrors.None || sslErrorHandling == SslErrorHandling.Ignore) {
                            return true;
                        } else if (sslErrorHandling == SslErrorHandling.Fail) {
                            return false;
                        }

                        string errText = string.Format("Could not establish secure connection to {0}:{1} because of the following SSL issues:\n\n", hostName, portNumber);
                        if ((errs & SslPolicyErrors.RemoteCertificateNotAvailable) != 0) {
                            errText += "- no remote certificate provided\n";
                        }
                        if ((errs & SslPolicyErrors.RemoteCertificateNameMismatch) != 0) {
                            errText += "- remote certificate name does not match hostname\n";
                        }
                        if ((errs & SslPolicyErrors.RemoteCertificateChainErrors) != 0) {
                            errText += "- remote certificate is not trusted\n";
                        }

                        errText += "\nConnect anyway?";

                        var dlgRes = MessageBox.Show(errText, null, MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
                        return dlgRes == DialogResult.Yes;
                    });
                    try {
                        sslStream.AuthenticateAsClient(hostName);
                    } catch (AuthenticationException) {
                        return ConnErrorMessages.RemoteSslError;
                    }
                    stream = sslStream;
                } else {
                    stream = rawStream;
                }

                var buf = new byte[8];
                int bufLen = stream.Read(buf, 0, DebuggerSignature.Length);
                string sig = Encoding.ASCII.GetString(buf, 0, bufLen);
                if (sig != DebuggerSignature) {
                    return ConnErrorMessages.RemoteUnsupportedServer;
                }

                long ver = stream.ReadInt64();
                if (ver != DebuggerProtocolVersion) {
                    return ConnErrorMessages.RemoteUnsupportedServer;
                }

                stream.Write(DebuggerSignatureBytes);
                stream.WriteInt64(DebuggerProtocolVersion);

                stream.WriteString(secret);
                bufLen = stream.Read(buf, 0, Accepted.Length);
                string secretResp = Encoding.ASCII.GetString(buf, 0, bufLen);
                if (secretResp != Accepted) {
                    return ConnErrorMessages.RemoteSecretMismatch;
                }

                connected = true;
            } catch (IOException) {
                return ConnErrorMessages.RemoteNetworkError;
            } catch (SocketException) {
                return ConnErrorMessages.RemoteNetworkError;
            } finally {
                if (!connected) {
                    if (stream != null) {
                        stream.Close();
                    }
                    socket.Close();
                    socket = null;
                    stream = null;
                }
            }

            return ConnErrorMessages.None;
        }
Пример #2
0
 /// <summary>
 /// Same as the static version of this method, but uses the same <c>hostName</c>, <c>portNumber</c> and <c>secret</c> values
 /// that were originally used to create this instance of <see cref="JRemoteProcess"/>.
 /// </summary>
 public ConnErrorMessages TryConnect(SslErrorHandling sslErrorHandling, out Socket socket, out Stream stream)
 {
     return TryConnect(_hostName, _portNumber, _secret, _useSsl, sslErrorHandling, out socket, out stream);
 }
Пример #3
0
        public static ConnErrorMessages TryAttach(string hostName, ushort portNumber, string secret, bool useSsl, SslErrorHandling sslErrorHandling, out JProcess process)
        {
            process = null;

            Socket socket;
            Stream stream;
            ConnErrorMessages err = TryConnect(hostName, portNumber, secret, useSsl, sslErrorHandling, out socket, out stream);
            if (err == ConnErrorMessages.None) {
                bool attached = false;
                JLanguageVersion langVer;
                try {
                    stream.Write(AttachCommandBytes);

                    var buf = new byte[8];
                    int bufLen = stream.Read(buf, 0, Accepted.Length);
                    string attachResp = Encoding.ASCII.GetString(buf, 0, bufLen);
                    if (attachResp != Accepted) {
                        return ConnErrorMessages.RemoteAttachRejected;
                    }

                    int langMajor = stream.ReadInt32();
                    int langMinor = stream.ReadInt32();
                    int langMicro = stream.ReadInt32();
                    langVer = (JLanguageVersion)((langMajor << 8) | langMinor);
                    if (!Enum.IsDefined(typeof(JLanguageVersion), langVer)) {
                        langVer = JLanguageVersion.None;
                    }

                    attached = true;
                } catch (IOException) {
                    return ConnErrorMessages.RemoteNetworkError;
                } finally {
                    if (!attached) {
                        if (stream != null) {
                            stream.Close();
                        }
                        socket.Close();
                        socket = null;
                        stream = null;
                    }
                }

                process = new JRemoteProcess(hostName, portNumber, secret, useSsl, langVer);
                process.Connected(socket, stream);
            }

            return err;
        }