EldoS | Feel safer!

Software components for data protection, secure storage and transfer

ssh send data problem

Also by EldoS: BizCrypto
Components for BizTalk® and SQL Server® Integration Services that let you securely store and transfer information in your business automation solutions.
#30763
Posted: 09/17/2014 11:54:26
by Fernando Del Canio (Standard support level)
Joined: 06/24/2014
Posts: 14

I need to send a command to a server and then the server runs some task.

If i open the client just before send the command the received data is about the connection response and the send command is not executed.

But if move the open command to my class constructor the send command works fine and the response is about the command sended.

The main program is a service and i would like to open the client in each message sent because only one message is sent by day and i would like to avoid the extra code to control the connection state in try catch.

Thanks.

Code
        public virtual string Send(string data)
        {

            try
            {
                byte[] dataToRead = new byte[65280];
                byte[] dataErr = new byte[65280];
                int dataLen = 0, dataErrLen = 0;      

                client.Open();                
                bool canRecv = true;    
                byte[] encoded = System.Text.Encoding.UTF8.GetBytes(data + "\x0d\x0a");
                client.SendData(encoded, encoded.Length);

                while (canRecv)
                {
                    try
                    {
                        canRecv = client.CanReceive(0);
                    }
                    catch
                    {
                        canRecv = false;
                    }

                    if (canRecv)
                    {
                        try
                        {
                            dataLen = dataToRead.Length;
                            dataErrLen = dataErr.Length;
                            client.ReceiveData(ref dataToRead, ref dataLen, ref dataErr, ref dataErrLen);
                        }
                        catch
                        {
                            canRecv = false;
                        }
                    }
                }

                string result = System.Text.Encoding.UTF8.GetString(dataToRead, 0, dataLen);
                log.Warn(result);
                return result;
            }    
            finally
            {
                client.Close(true);
            }
#30766
Posted: 09/18/2014 03:29:10
by Ken Ivanov (EldoS Corp.)

Hi Fernando,

Thank you for contacting us.

Your code is not fully correct. A delay between the moments the server receives your command and sends the reply back will cause your CanReceive() call to return false and terminate the receive loop without receiving the remaining data. Instead, you should run the loop until the connection is closed or until all the application data has been received completely. During the execution of the loop, CanReceive() may occasionally return false due to connection or processing delays.

There is an easier way to run a command if your server is configured to support plain command channels. ExecuteCommand() methods encapsulate all the connection logic, from opening to closure, so you might wish to try them.

Ken
#30784
Posted: 09/22/2014 05:49:07
by Fernando Del Canio (Standard support level)
Joined: 06/24/2014
Posts: 14

Thank you very much Ken,

i can't find how to support plain command channels.
Is this option only for SecureBlackBox ssh libraries?

I'm newbie in SSH.
#30785
Posted: 09/22/2014 06:11:19
by Ken Ivanov (EldoS Corp.)

Hi Fernando,

Just try using the ExecuteSSHCommand() method and it will do all the job for you. It is a really high-level method that encapsulates all the work with tunnels and data exchange. You only supply the command and get the output back.

The only constraint of this method is that it only works with non-interactive commands. It does not support programs that ask user to type anything on the keyboard for them.

Ken
#30786
Posted: 09/22/2014 06:54:38
by Fernando Del Canio (Standard support level)
Joined: 06/24/2014
Posts: 14

Hi Ken,

thanks again.

I'm developing a windows service, to test it i'm debugging a console aplication project in .net.

I have changed my code since your first reply to receive data until a command responses with a "success key" or timeout, now works fine.

i would prefer to use the executeCommand but my code doesn't work, the two first lines response empty byte array, inside the try catch is the code that works, what do you think?

Code

        public virtual string Send(string data)
        {
            var s = client.ExecuteCommand(data, true);
            System.Diagnostics.Debug.WriteLine("SSH; " + s.Length);

            try
            {
                byte[] dataToRead = new byte[65280];
                byte[] dataErr = new byte[65280];
                int dataLen = 0, dataErrLen = 0;


                client.Open();
                byte[] encoded = System.Text.Encoding.UTF8.GetBytes(data + "\x0d\x0a");
                client.SendData(encoded, encoded.Length);

                int elapsed = 0;
                bool success = false;
                TimeSpan timeOut = TimeSpan.FromSeconds(Properties.Settings.Default.SSHResponseTimeOut);
                string successWord = Properties.Settings.Default.SSHSuccessWord;

                StringBuilder resultBuilder = new StringBuilder();
                string resp = string.Empty;
                string respErr = string.Empty;

                while ((!success) && (elapsed < timeOut.TotalMilliseconds))
                {                  
                    dataLen = dataToRead.Length;
                    dataErrLen = dataErr.Length;
                    //client.ReceiveData(ref dataToRead, ref dataLen, ref dataErr, ref dataErrLen);
                    client.ReceiveText(out resp, out respErr);

                    if (respErr != string.Empty)
                    {
                        success = true;                                          
                        throw new ApplicationException("SSH Error: " + respErr);
                    }
                    else if(resp != String.Empty)
                    {
                        resultBuilder.Append(resp);
                        if (resp.Contains(successWord))
                        {
                            success = true;
                        }
                    }
                    System.Threading.Thread.Sleep(250);
                    elapsed += 250;
                }

                string result = resultBuilder.ToString();

                if (elapsed >= timeOut.TotalMilliseconds)
                {
                    log.Warn("SSH Timeout: " + result);
                    throw new ApplicationException("SSH Timeout: " + result);                    
                }
                log.Warn(result);
                return result;
            }
            finally
            {
                client.Close(true);
            }


Thanks
#30787
Posted: 09/22/2014 07:15:39
by Ken Ivanov (EldoS Corp.)

Fernando,

This means that your SSH server is likely to have plain command execution facilities disabled. This way the only option for you is to emulate the terminal by sending commands manually and waiting for the response (this is exactly what your code is doing).

Your receive loop looks much more workable now.

Ken
Also by EldoS: CallbackFilter
A component to monitor and control disk activity, track file and directory operations (create, read, write, rename etc.), alter file data, encrypt files, create virtual files.

Reply

Statistics

Topic viewed 772 times

Number of guests: 2, registered members: 0, in total hidden: 0




|

Back to top

As of July 15, 2016 EldoS Corporation will operate as a division of /n software inc. For more information, please read the announcement.

Got it!