4

I am writing a very small C# program designed to allow me to connect remotely to a server via SSH (using SSH .NET Client Library), and execute commands, mainly commands about printers such as 'lpstat'. Until here I used to use Putty for that purpose and check stuff (mainly printers states) manually. I would like to automate some of this. Using Putty I was connecting with user1 (when prompted for a user/password just after connecting) and had to "sudo su - user2" to then be able to execute lpstat and others commands.

Now here is the problem : Once I am connected with SSH .NET, the command "sudo su - " seems to freeze the connection. Why ? Could it be the same problem as this one from Serverfault ? If there is another way to be connected as user2 (ie using SSH .NET differently), that would be fine with me.

Important notes:

  • I don't know user2's or root's password
  • It is a production server. I am not its administrator, and I am not a very advanced Unix user. I do not want to alter that server configuration.
  • I believe the freeze has to do with the command asking for a password, but I'm not sure.

My current code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Renci.SshNet;
using System.IO;
using System.Threading;

namespace SSHChecker
{
    class Program
    {
        static void Main(string[] args)
        {
            SshClient sshClient = new SshClient(
                "IP",
                666, // port
                "user1",
                "user1Password");

            sshClient.Connect();
            SshCommand sshCommand;
            String res;

            //sshCommand = sshClient.RunCommand("ls d /"); // works fine
            sshCommand = sshClient.RunCommand("sudo su - user2"); // freezes ...
            sshCommand = sshClient.RunCommand("ls d /"); // ... so this code is never executed.

            sshClient.Disconnect();
        }
    }
}
Community
  • 1
  • 1
Toto
  • 397
  • 6
  • 17
  • Ноw are you expecting to impersonate user2 without knowing his password? – Eugene Mayevski 'Callback May 15 '13 at 08:43
  • I don't know ... when I do that command using Putty, it "just works". There might be something else I don't know. Please note that if I do "sudo su user2" (no " - ") in Putty I *am* prompted for user2's password. – Toto May 15 '13 at 08:57
  • Try asking server admin about what is the correct way to login. "it just works" won't help you solve the problem. – Eugene Mayevski 'Callback May 15 '13 at 10:03
  • I have found that I don't have this problem if I use a Shell or ShellStream and use xterm instead of term. It seems user1 has the rights to impersonate to user2, but only using xterm (what Putty was already configured to use), not term. If I use term with Putty, the sudo commands outputs the following : tput: numb1-numb2 The terminal "term" is not recognized. tput: numb1-numb2 The terminal "term" is not recognized. As for why : I don't know. PS. Can I add newlines in comments ? This looks ugly. – Toto May 15 '13 at 12:53

2 Answers2

2

Have you fixed your (6 years, 4 months ago) question?

This user kasbst from github answered here

I followed his/her answer and worked very well.

  • I used CentOS 7 server (no need install expect).
  • Visual Studio 2017

Below is his/her code and sample

private static void WriteStream(string cmd, ShellStream stream)
{
      stream.WriteLine(cmd + "; echo this-is-the-end");
      while (stream.Length == 0)
           Thread.Sleep(500);
}

private static string ReadStream(ShellStream stream)
{
      StringBuilder result = new StringBuilder();

      string line;
      while ((line = stream.ReadLine()) != "this-is-the-end")
             result.AppendLine(line);

      return result.ToString();
}

private static void SwithToRoot(string password, ShellStream stream)
{
       // Get logged in and get user prompt
       string prompt = stream.Expect(new Regex(@"[$>]"));
       //Console.WriteLine(prompt);

       // Send command and expect password or user prompt
       stream.WriteLine("su - root");
       prompt = stream.Expect(new Regex(@"([$#>:])"));
       //Console.WriteLine(prompt);

       // Check to send password
       if (prompt.Contains(":"))
       {
            // Send password
            stream.WriteLine(password);
            prompt = stream.Expect(new Regex(@"[$#>]"));
            //Console.WriteLine(prompt);
        }
}

Sample:

using (var client = new SshClient(server, username, password))
{
          client.Connect();

          List<string> commands = new List<string>();
          commands.Add("pwd");
          commands.Add("cat /etc/sudoers");

          ShellStream shellStream = client.CreateShellStream("xterm", 80, 24, 800, 600, 1024);

          // Switch to root
          SwithToRoot("rootpassword", shellStream);

          // Execute commands under root account
          foreach (string command in commands) {
                  WriteStream(command, shellStream);

                  string answer = ReadStream(shellStream);
                  int index = answer.IndexOf(System.Environment.NewLine);
                  answer = answer.Substring(index + System.Environment.NewLine.Length);
                  Console.WriteLine("Command output: " + answer.Trim());
           }

           client.Disconnect();
}

Some other explanation

I don't know user2's or root's password

In setting of server, user can switch account without prompting password.

ls d /

It must be ls -d /.

It just displays result/output on console of server, in order to see result, use ReadStream function.

Ngoc Nam
  • 537
  • 3
  • 13
-1

ssh.RunCommand("echo "" + rootPwd + "" | sudo -S " + command);

prodigy007
  • 339
  • 3
  • 4