Page MenuHomePhabricator

ssh_channel_read() incorrectly returns -1 (SSH_ERROR)
Open, Needs TriagePublic

Description

libssh-0.9.0 used with following code on CentOS Linux release 8.1.1911 and OpenSSH_8.0p1 randomly (once in 10-50 attempts) reports SSH_ERROR during the ssh_channel_read() call.

It prints "Remote Channel is Closed" although all the response data was read correctly.

#include <stdio.h>
#include <libssh/libssh.h>

int main()
{

  ssh_session   session;
  int           userauth;
  int           offset;

  char          buffer[1000], userauthlist[64];

  if (NULL == (session = ssh_new()))
  {
        printf("CANNOT INITIALIZE SESSION\n");
        return -1;
  }


  ssh_set_blocking(session, 1);

  int port = 22;
  int verbosity = SSH_LOG_PACKET;

  char* ip = "127.0.0.1";
  char* user = "root";
  char* passwd = "zabbix";

  if (0 != ssh_options_set(session, SSH_OPTIONS_HOST, ip) ||
      0 != ssh_options_set(session, SSH_OPTIONS_PORT, &port) ||
      0 != ssh_options_set(session, SSH_OPTIONS_USER, user)
      //|| 0 != ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity)                                                                                                                                  
      )
  {
        printf("Cannot set SSH session options: %s",
	       ssh_get_error(session));
        return -1;
  }


  if (SSH_OK != ssh_connect(session))
  {
      printf( "Cannot establish SSH session: %s \n", ssh_get_error(session));
      return -1;
  }

  /* check which authentication methods are available */
  if (SSH_AUTH_ERROR == ssh_userauth_none(session, user))
  {
      printf("Error during authentication: %s \n", ssh_get_error(session));
      return -1;
  }

  if (SSH_AUTH_SUCCESS != ssh_userauth_password(session, user, passwd))
  {
      printf( "Password authentication failed: %s", ssh_get_error(session));
      return -1;
  }
  else
  {
      printf("password authentication succeeded");
  }

  ssh_channel channel;
  int rc;
  int nbytes;

  channel = ssh_channel_new(session);
  if (channel == NULL)
    return SSH_ERROR;


  rc = ssh_channel_open_session(channel);
  if (rc != SSH_OK)
  {
   	ssh_channel_free(channel);
        return rc;
  }

  rc = ssh_channel_request_exec(channel, "ls /tmp");
  if (rc != SSH_OK)
  {
      ssh_channel_close(channel);
      ssh_channel_free(channel);
      printf("Channel request exec error");

      return rc;
  }
 nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
  while (nbytes > 0)
  {
      printf("READ OK, nbytes: %d \n",nbytes);
      int x = write(1, buffer, nbytes);

      printf("READ X, x: %d \n",x);

      if (x != (unsigned int) nbytes)
      {
          ssh_channel_close(channel);
          ssh_channel_free(channel);
          printf("write difference");

          return SSH_ERROR;
      }

      printf("CHANNEL CLOSED TEST: %d \n", ssh_channel_is_closed(channel));
      printf("CHANNEL IS EOF TEST: %d", ssh_channel_is_eof(channel));

      nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
  }

  if (nbytes < 0)
  {
      printf("nbytes: %d \n",nbytes);

      printf("ERROR: %s \n",ssh_get_error(session));
      printf("CHANNEL CLOSED: %d \n", ssh_channel_is_closed(channel));
      printf("CHANNEL OPENED: %d \n", ssh_channel_is_open(channel));
      printf("CHANNEL IS EOF: %d", ssh_channel_is_eof(channel));


      ssh_channel_close(channel);
      ssh_channel_free(channel);

      return SSH_ERROR;
  }

 ssh_channel_send_eof(channel);
  ssh_channel_close(channel);
  ssh_channel_free(channel);

  printf("\n\n\n\n\n\n\n");
  return SSH_OK;
}

The issue does not seem to manifest itself with OpenSSH 7.
Note that changing various timeout options (in libssh itself or sshd) did not help.

This issue looks to be identical to the one reported here: http://www.libssh.org/archive/libssh/2019-05/0000003.html

Event Timeline

rimdenok created this task.Fri, May 22, 3:38 PM
rimdenok updated the task description. (Show Details)
rimdenok renamed this task from ssh_channel_read() incorrectly returns SSH_ERROR to ssh_channel_read() incorrectly returns -1 (SSH_ERROR).Fri, May 22, 3:42 PM
rimdenok updated the task description. (Show Details)
rimdenok updated the task description. (Show Details)Fri, May 22, 5:34 PM
Jakuje added a subscriber: Jakuje.Mon, May 25, 12:43 PM

Could it be a duplicate of an issue described and fixed in this commit [1]? It was also discussed in mailing list recently. Does it work with current master?

https://gitlab.com/libssh/libssh-mirror/-/commit/6417f5a3cac8537ac6f6ff7fc1642dfaa0917fb4

It is fixed in the master.

Is it correct that this issue:

  1. affects only 0.9 versions
  2. 0.8 are not affected
  3. next release (1.0 ?) will include a fix for it

?

Right. It affects only 0.9.x versions. The above commit mentions which revision introduced this issue. The commit is already backported in the stable-0.9 branch so it will be in the next 0.9.5 release

https://gitlab.com/libssh/libssh-mirror/-/commits/stable-0.9