Beispiel #1
0
static void torture_auth_agent_nonblocking(void **state) {
    struct torture_state *s = *state;
    ssh_session session = s->ssh.session;
    int rc;

    if (!ssh_agent_is_running(session)){
        print_message("*** Agent not running. Test ignored\n");
        return;
    }
    rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE);
    assert_int_equal(rc, SSH_OK);

    rc = ssh_connect(session);
    assert_int_equal(rc, SSH_OK);

    rc = ssh_userauth_none(session,NULL);
    /* This request should return a SSH_REQUEST_DENIED error */
    if (rc == SSH_ERROR) {
        assert_true(ssh_get_error_code(session) == SSH_REQUEST_DENIED);
    }
    rc = ssh_userauth_list(session, NULL);
    assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY);

    ssh_set_blocking(session,0);

    do {
      rc = ssh_userauth_agent(session, NULL);
    } while (rc == SSH_AUTH_AGAIN);
    assert_int_equal(rc, SSH_AUTH_SUCCESS);
}
Beispiel #2
0
static void torture_auth_autopubkey_nonblocking(void **state) {
    ssh_session session = *state;
    char *user = getenv("TORTURE_USER");
    int rc;

    if (user == NULL) {
        print_message("*** Please set the environment variable TORTURE_USER"
                      " to enable this test!!\n");
        return;
    }

    rc = ssh_options_set(session, SSH_OPTIONS_USER, user);
    assert_true(rc == SSH_OK);

    rc = ssh_connect(session);
    assert_true(rc == SSH_OK);

    ssh_set_blocking(session,0);
    do {
      rc = ssh_userauth_none(session, NULL);
    } while (rc == SSH_AUTH_AGAIN);

    /* This request should return a SSH_REQUEST_DENIED error */
    if (rc == SSH_ERROR) {
        assert_true(ssh_get_error_code(session) == SSH_REQUEST_DENIED);
    }

    rc = ssh_userauth_list(session, NULL);
    assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY);

    do {
        rc = ssh_userauth_publickey_auto(session, NULL, NULL);
    } while (rc == SSH_AUTH_AGAIN);
    assert_true(rc == SSH_AUTH_SUCCESS);
}
Beispiel #3
0
static void torture_auth_password_nonblocking(void **state) {
    struct torture_state *s = *state;
    ssh_session session = s->ssh.session;
    int rc;

    rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_BOB);
    assert_int_equal(rc, SSH_OK);

    rc = ssh_connect(session);
    assert_int_equal(rc, SSH_OK);

    ssh_set_blocking(session,0);
    do {
      rc = ssh_userauth_none(session, NULL);
    } while (rc == SSH_AUTH_AGAIN);

    /* This request should return a SSH_REQUEST_DENIED error */
    if (rc == SSH_AUTH_ERROR) {
        assert_true(ssh_get_error_code(session) == SSH_REQUEST_DENIED);
    }

    rc = ssh_userauth_list(session, NULL);
    assert_true(rc & SSH_AUTH_METHOD_PASSWORD);

    do {
      rc = ssh_userauth_password(session, NULL, TORTURE_SSH_USER_BOB_PASSWORD);
    } while(rc==SSH_AUTH_AGAIN);

    assert_int_equal(rc, SSH_AUTH_SUCCESS);
}
Beispiel #4
0
static void torture_auth_none_nonblocking(void **state) {
    struct torture_state *s = *state;
    ssh_session session = s->ssh.session;
    int rc;

    rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE);
    assert_int_equal(rc, SSH_OK);

    rc = ssh_connect(session);
    assert_int_equal(rc, SSH_OK);

    /* This request should return a SSH_REQUEST_DENIED error */
    if (rc == SSH_ERROR) {
        assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED);
    }

    ssh_set_blocking(session,0);

    do {
        rc = ssh_userauth_none(session,NULL);
    } while (rc == SSH_AUTH_AGAIN);
    assert_int_equal(rc, SSH_AUTH_DENIED);
    assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED);

}
Beispiel #5
0
static void torture_auth_kbdint_nonblocking(void **state) {
    ssh_session session = *state;
    char *user = getenv("TORTURE_USER");
    char *password = getenv("TORTURE_PASSWORD");
    int rc;

    if (user == NULL) {
        print_message("*** Please set the environment variable TORTURE_USER"
                      " to enable this test!!\n");
        return;
    }

    if (password == NULL) {
        print_message("*** Please set the environment variable "
                      "TORTURE_PASSWORD to enable this test!!\n");
        return;
    }

    rc = ssh_options_set(session, SSH_OPTIONS_USER, user);
    assert_true(rc == SSH_OK);

    rc = ssh_connect(session);
    assert_true(rc == SSH_OK);

    ssh_set_blocking(session,0);
    do {
      rc = ssh_userauth_none(session, NULL);
    } while (rc == SSH_AUTH_AGAIN);

    /* This request should return a SSH_REQUEST_DENIED error */
    if (rc == SSH_ERROR) {
        assert_true(ssh_get_error_code(session) == SSH_REQUEST_DENIED);
    }
    rc = ssh_userauth_list(session, NULL);
    assert_true(rc & SSH_AUTH_METHOD_INTERACTIVE);

    do {
        rc = ssh_userauth_kbdint(session, NULL, NULL);
    } while (rc == SSH_AUTH_AGAIN);
    assert_true(rc == SSH_AUTH_INFO);
    assert_int_equal(ssh_userauth_kbdint_getnprompts(session), 1);
    do {
        rc = ssh_userauth_kbdint_setanswer(session, 0, password);
    } while (rc == SSH_AUTH_AGAIN);
    assert_false(rc < 0);

    do {
        rc = ssh_userauth_kbdint(session, NULL, NULL);
    } while (rc == SSH_AUTH_AGAIN);
    /* Sometimes, SSH server send an empty query at the end of exchange */
    if(rc == SSH_AUTH_INFO) {
        assert_int_equal(ssh_userauth_kbdint_getnprompts(session), 0);
        do {
            rc = ssh_userauth_kbdint(session, NULL, NULL);
        } while (rc == SSH_AUTH_AGAIN);
    }
    assert_true(rc == SSH_AUTH_SUCCESS);
}
Beispiel #6
0
void clSSH::Connect(int seconds)
{
    m_session = ssh_new();
    if(!m_session) { throw clException("ssh_new failed!"); }

    ssh_set_blocking(m_session, 0);
    int verbosity = SSH_LOG_NOLOG;
    ssh_options_set(m_session, SSH_OPTIONS_HOST, m_host.mb_str(wxConvUTF8).data());
    ssh_options_set(m_session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
    ssh_options_set(m_session, SSH_OPTIONS_PORT, &m_port);
    ssh_options_set(m_session, SSH_OPTIONS_USER, GetUsername().mb_str().data());

    // Connect the session
    int retries = seconds * 100;
    if(retries < 0) { retries = 1; }
    DoConnectWithRetries(retries);
    ssh_set_blocking(m_session, 1);
}
Beispiel #7
0
static void torture_connect_nonblocking(void **state) {
    struct torture_state *s = *state;
    ssh_session session = s->ssh.session;
    int rc;

    rc = ssh_options_set(session, SSH_OPTIONS_HOST, TORTURE_SSH_SERVER);
    assert_true(rc == SSH_OK);
    ssh_set_blocking(session,0);

    do {
        rc = ssh_connect(session);
        assert_true(rc != SSH_ERROR);
    } while(rc == SSH_AGAIN);

    assert_true(rc == SSH_OK);
}
Beispiel #8
0
static void torture_connect_nonblocking(void **state) {
    ssh_session session = *state;

    int rc;

    rc = ssh_options_set(session, SSH_OPTIONS_HOST, HOST);
    assert_true(rc == SSH_OK);
    ssh_set_blocking(session,0);

    do {
        rc = ssh_connect(session);
        assert_true(rc != SSH_ERROR);
    } while(rc == SSH_AGAIN);

    assert_true(rc == SSH_OK);
}
Beispiel #9
0
static void torture_auth_pubkey_types_ed25519_nonblocking(void **state)
{
    struct torture_state *s = *state;
    ssh_session session = s->ssh.session;
    int rc;

    rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE);
    assert_ssh_return_code(session, rc);

    rc = ssh_connect(session);
    assert_ssh_return_code(session, rc);

    ssh_set_blocking(session, 0);
    do {
      rc = ssh_userauth_none(session, NULL);
    } while (rc == SSH_AUTH_AGAIN);

    /* This request should return a SSH_REQUEST_DENIED error */
    if (rc == SSH_ERROR) {
        assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED);
    }

    rc = ssh_userauth_list(session, NULL);
    assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY);

    /* Enable only DSA keys -- authentication should fail */
    rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
                         "ssh-dss");
    assert_ssh_return_code(session, rc);

    do {
        rc = ssh_userauth_publickey_auto(session, NULL, NULL);
    } while (rc == SSH_AUTH_AGAIN);
    assert_int_equal(rc, SSH_AUTH_DENIED);

    /* Verify we can use also ED25519 key to authenticate */
    rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
                         "ssh-ed25519");
    assert_ssh_return_code(session, rc);

    do {
        rc = ssh_userauth_publickey_auto(session, NULL, NULL);
    } while (rc == SSH_AUTH_AGAIN);
    assert_int_equal(rc, SSH_AUTH_SUCCESS);

}
Beispiel #10
0
static void torture_auth_pubkey_types_nonblocking(void **state)
{
    struct torture_state *s = *state;
    ssh_session session = s->ssh.session;
    int rc;

    rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_ALICE);
    assert_ssh_return_code(session, rc);

    rc = ssh_connect(session);
    assert_ssh_return_code(session, rc);

    ssh_set_blocking(session, 0);
    do {
      rc = ssh_userauth_none(session, NULL);
    } while (rc == SSH_AUTH_AGAIN);

    /* This request should return a SSH_REQUEST_DENIED error */
    if (rc == SSH_ERROR) {
        assert_int_equal(ssh_get_error_code(session), SSH_REQUEST_DENIED);
    }

    rc = ssh_userauth_list(session, NULL);
    assert_true(rc & SSH_AUTH_METHOD_PUBLICKEY);

    /* Disable RSA key types for authentication */
    rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
                         "ssh-dss");
    assert_ssh_return_code(session, rc);

    do {
        rc = ssh_userauth_publickey_auto(session, NULL, NULL);
    } while (rc == SSH_AUTH_AGAIN);
    assert_int_equal(rc, SSH_AUTH_DENIED);

    /* Now enable it and retry */
    rc = ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
                         "rsa-sha2-512,ssh-rsa");
    assert_ssh_return_code(session, rc);

    do {
        rc = ssh_userauth_publickey_auto(session, NULL, NULL);
    } while (rc == SSH_AUTH_AGAIN);
    assert_int_equal(rc, SSH_AUTH_SUCCESS);

}
Beispiel #11
0
static void torture_auth_kbdint_nonblocking(void **state) {
    struct torture_state *s = *state;
    ssh_session session = s->ssh.session;
    int rc;

    rc = ssh_options_set(session, SSH_OPTIONS_USER, TORTURE_SSH_USER_BOB);
    assert_int_equal(rc, SSH_OK);

    rc = ssh_connect(session);
    assert_int_equal(rc, SSH_OK);

    ssh_set_blocking(session,0);
    do {
      rc = ssh_userauth_none(session, NULL);
    } while (rc == SSH_AUTH_AGAIN);

    /* This request should return a SSH_REQUEST_DENIED error */
    if (rc == SSH_ERROR) {
        assert_true(ssh_get_error_code(session) == SSH_REQUEST_DENIED);
    }
    rc = ssh_userauth_list(session, NULL);
    assert_true(rc & SSH_AUTH_METHOD_INTERACTIVE);

    do {
        rc = ssh_userauth_kbdint(session, NULL, NULL);
    } while (rc == SSH_AUTH_AGAIN);
    assert_int_equal(rc, SSH_AUTH_INFO);
    assert_int_equal(ssh_userauth_kbdint_getnprompts(session), 1);
    do {
        rc = ssh_userauth_kbdint_setanswer(session, 0, TORTURE_SSH_USER_BOB_PASSWORD);
    } while (rc == SSH_AUTH_AGAIN);
    assert_false(rc < 0);

    do {
        rc = ssh_userauth_kbdint(session, NULL, NULL);
    } while (rc == SSH_AUTH_AGAIN);
    /* Sometimes, SSH server send an empty query at the end of exchange */
    if(rc == SSH_AUTH_INFO) {
        assert_int_equal(ssh_userauth_kbdint_getnprompts(session), 0);
        do {
            rc = ssh_userauth_kbdint(session, NULL, NULL);
        } while (rc == SSH_AUTH_AGAIN);
    }
    assert_int_equal(rc, SSH_AUTH_SUCCESS);
}
Beispiel #12
0
/**
 * @brief Create a new ssh session.
 *
 * @returns             A new ssh_session pointer, NULL on error.
 */
ssh_session ssh_new(void) {
  ssh_session session;
  char *id = NULL;
  int rc;

  session = malloc(sizeof (struct ssh_session_struct));
  if (session == NULL) {
    return NULL;
  }
  ZERO_STRUCTP(session);

  session->next_crypto = crypto_new();
  if (session->next_crypto == NULL) {
    goto err;
  }

  session->socket = ssh_socket_new(session);
  if (session->socket == NULL) {
    goto err;
  }

  session->out_buffer = ssh_buffer_new();
  if (session->out_buffer == NULL) {
    goto err;
  }

  session->in_buffer=ssh_buffer_new();
  if (session->in_buffer == NULL) {
    goto err;
  }

  session->alive = 0;
  session->auth_methods = 0;
  ssh_set_blocking(session, 1);
  session->common.log_indent = 0;
  session->maxchannel = FIRST_CHANNEL;

#ifndef _WIN32
    session->agent = agent_new(session);
    if (session->agent == NULL) {
      goto err;
    }
#endif /* _WIN32 */

    /* OPTIONS */
    session->opts.StrictHostKeyChecking = 1;
    session->opts.port = 22;
    session->opts.fd = -1;
    session->opts.ssh2 = 1;
    session->opts.compressionlevel=7;
#ifdef WITH_SSH1
    session->opts.ssh1 = 1;
#else
    session->opts.ssh1 = 0;
#endif

    session->opts.identity = ssh_list_new();
    if (session->opts.identity == NULL) {
      goto err;
    }

    id = strdup("%d/id_rsa");
    if (id == NULL) {
      goto err;
    }
    rc = ssh_list_append(session->opts.identity, id);
    if (rc == SSH_ERROR) {
      goto err;
    }

    id = strdup("%d/id_dsa");
    if (id == NULL) {
      goto err;
    }
    rc = ssh_list_append(session->opts.identity, id);
    if (rc == SSH_ERROR) {
      goto err;
    }

    id = strdup("%d/identity");
    if (id == NULL) {
      goto err;
    }
    rc = ssh_list_append(session->opts.identity, id);
    if (rc == SSH_ERROR) {
      goto err;
    }

    return session;

err:
    free(id);
    ssh_free(session);
    return NULL;
}
Beispiel #13
0
static gboolean
cockpit_ssh_source_prepare (GSource *source,
                            gint *timeout)
{
  CockpitSshSource *cs = (CockpitSshSource *)source;
  CockpitSshTransport *self = cs->transport;
  GThread *thread;
  gint status;

  *timeout = 1;

  /* Connecting, check if done */
  if (G_UNLIKELY (!self->data))
    {
      if (g_atomic_int_get (&self->connecting))
        return FALSE;

      g_object_ref (self);

      /* Get the result from connecting thread */
      thread = self->connect_thread;
      self->connect_fd = -1;
      self->connect_thread = NULL;
      self->data = g_thread_join (thread);
      g_assert (self->data != NULL);

      if (!self->result_emitted)
        {
          self->result_emitted = TRUE;
          g_signal_emit_by_name (self, "result", self->data->problem);
        }

      if (self->data->problem)
        {
          close_immediately (self, self->data->problem);
          g_object_unref (self);
          return FALSE;
        }

      g_object_unref (self);

      ssh_event_add_session (self->event, self->data->session);
      ssh_set_channel_callbacks (self->data->channel, &self->channel_cbs);

      /* Start watching the fd */
      ssh_set_blocking (self->data->session, 0);
      cs->pfd.fd = ssh_get_fd (self->data->session);
      g_source_add_poll (source, &cs->pfd);

      g_debug ("%s: starting io", self->logname);
    }

  status = ssh_get_status (self->data->session);

  /* Short cut this ... we're ready now */
  if (self->drain_buffer)
    return TRUE;

  /*
   * Channel completely closed, and output buffers
   * are empty. We're in a good place to close the
   * SSH session and thus the transport.
   */
  if (close_maybe (self, status))
    return FALSE;

  cs->pfd.revents = 0;
  cs->pfd.events = G_IO_IN | G_IO_ERR | G_IO_NVAL | G_IO_HUP;

  /* libssh has something in its buffer: want to write */
  if (status & SSH_WRITE_PENDING)
    cs->pfd.events |= G_IO_OUT;

  /* We have something in our queue: want to write */
  else if (!g_queue_is_empty (self->queue))
    cs->pfd.events |= G_IO_OUT;

  /* We are closing and need to send eof: want to write */
  else if (self->closing && !self->sent_eof)
    cs->pfd.events |= G_IO_OUT;

  /* Need to reply to an EOF or close */
  if ((self->received_eof && self->sent_eof && !self->sent_close) ||
      (self->received_close && !self->sent_close))
    cs->pfd.events |= G_IO_OUT;

  return cockpit_ssh_source_check (source);
}
Beispiel #14
0
/**
 * @brief Create a new ssh session.
 *
 * @returns             A new ssh_session pointer, NULL on error.
 */
ssh_session ssh_new(void) {
  ssh_session session;
  char *id = NULL;
  int rc;

  session = malloc(sizeof (struct ssh_session_struct));
  if (session == NULL) {
    return NULL;
  }
  ZERO_STRUCTP(session);

  session->next_crypto = crypto_new();
  if (session->next_crypto == NULL) {
    goto err;
  }

  session->socket = ssh_socket_new(session);
  if (session->socket == NULL) {
    goto err;
  }

  session->out_buffer = ssh_buffer_new();
  if (session->out_buffer == NULL) {
    goto err;
  }

  session->in_buffer=ssh_buffer_new();
  if (session->in_buffer == NULL) {
    goto err;
  }

  session->alive = 0;
  session->auth_methods = 0;
  ssh_set_blocking(session, 1);
  session->maxchannel = FIRST_CHANNEL;

#ifndef _WIN32
    session->agent = ssh_agent_new(session);
    if (session->agent == NULL) {
      goto err;
    }
#endif /* _WIN32 */

    /* OPTIONS */
    session->opts.StrictHostKeyChecking = 1;
    session->opts.port = 0;
    session->opts.fd = -1;
    session->opts.compressionlevel=7;
    session->opts.nodelay = 0;
    session->opts.flags = SSH_OPT_FLAG_PASSWORD_AUTH | SSH_OPT_FLAG_PUBKEY_AUTH |
            SSH_OPT_FLAG_KBDINT_AUTH | SSH_OPT_FLAG_GSSAPI_AUTH;
    session->opts.identity = ssh_list_new();
    if (session->opts.identity == NULL) {
      goto err;
    }

    id = strdup("%d/id_ed25519");
    if (id == NULL) {
      goto err;
    }
    rc = ssh_list_append(session->opts.identity, id);
    if (rc == SSH_ERROR) {
      goto err;
    }

#ifdef HAVE_ECC
    id = strdup("%d/id_ecdsa");
    if (id == NULL) {
      goto err;
    }
    rc = ssh_list_append(session->opts.identity, id);
    if (rc == SSH_ERROR) {
      goto err;
    }
#endif

    id = strdup("%d/id_rsa");
    if (id == NULL) {
      goto err;
    }
    rc = ssh_list_append(session->opts.identity, id);
    if (rc == SSH_ERROR) {
      goto err;
    }

#ifdef HAVE_DSA
    id = strdup("%d/id_dsa");
    if (id == NULL) {
      goto err;
    }
    rc = ssh_list_append(session->opts.identity, id);
    if (rc == SSH_ERROR) {
      goto err;
    }
#endif

    return session;

err:
    free(id);
    ssh_free(session);
    return NULL;
}
Beispiel #15
0
static int my_fd_data_function(UNUSED_PARAM(socket_t fd),
                               int revents,
                               void *userdata)
{
    struct event_fd_data_struct *event_fd_data = (struct event_fd_data_struct *)userdata;
    ssh_channel channel = event_fd_data->channel;
    ssh_session session;
    int len, i, wr;
    char buf[16384];
    int blocking;

    if (channel == NULL) {
        _ssh_log(SSH_LOG_FUNCTIONS, "=== my_fd_data_function", "channel == NULL!");
        return 0;
    }

    session = ssh_channel_get_session(channel);

    if (ssh_channel_is_closed(channel)) {
        _ssh_log(SSH_LOG_FUNCTIONS, "=== my_fd_data_function", "channel is closed!");
        stack_socket_close(session, event_fd_data);
        return 0;
    }

    if (!(revents & POLLIN)) {
        if (revents & POLLPRI) {
            _ssh_log(SSH_LOG_PROTOCOL, "=== my_fd_data_function", "poll revents & POLLPRI");
        }
        if (revents & POLLOUT) {
            _ssh_log(SSH_LOG_PROTOCOL, "=== my_fd_data_function", "poll revents & POLLOUT");
        }
        if (revents & POLLHUP) {
            _ssh_log(SSH_LOG_PROTOCOL, "=== my_fd_data_function", "poll revents & POLLHUP");
        }
        if (revents & POLLNVAL) {
            _ssh_log(SSH_LOG_PROTOCOL, "=== my_fd_data_function", "poll revents & POLLNVAL");
        }
        if (revents & POLLERR) {
            _ssh_log(SSH_LOG_PROTOCOL, "=== my_fd_data_function", "poll revents & POLLERR");
        }
        return 0;
    }

    blocking = ssh_is_blocking(session);
    ssh_set_blocking(session, 0);

    _ssh_log(SSH_LOG_FUNCTIONS, "=== my_fd_data_function", "Trying to read from tcp socket fd = %d... (Channel %d:%d state=%d)",
                        *event_fd_data->p_fd, channel->local_channel, channel->remote_channel, channel->state);
#ifdef _WIN32
    struct sockaddr from;
    int fromlen = sizeof(from);
    len = recvfrom(*event_fd_data->p_fd, buf, sizeof(buf), 0, &from, &fromlen);
#else
    len = recv(*event_fd_data->p_fd, buf, sizeof(buf), 0);
#endif // _WIN32
    if (len < 0) {
        _ssh_log(SSH_LOG_WARNING, "=== my_fd_data_function", "Reading from tcp socket: %s", strerror(errno));

        ssh_channel_send_eof(channel);
    }
    else if (len > 0) {
        if (ssh_channel_is_open(channel)) {
            wr = 0;
            do {
                i = ssh_channel_write(channel, buf, len);
                if (i < 0) {
                    _ssh_log(SSH_LOG_WARNING, "=== my_fd_data_function", "Error writing on the direct-tcpip channel: %d", i);
                    len = wr;
                    break;
                }
                wr += i;
                _ssh_log(SSH_LOG_FUNCTIONS, "=== my_fd_data_function", "channel_write (%d from %d)", wr, len);
            } while (i > 0 && wr < len);
        }
        else {
            _ssh_log(SSH_LOG_WARNING, "=== my_fd_data_function", "Can't write on closed channel!");
        }
    }
    else {
        _ssh_log(SSH_LOG_PROTOCOL, "=== my_fd_data_function", "The destination host has disconnected!");

        ssh_channel_close(channel);
#ifdef _WIN32
        shutdown(*event_fd_data->p_fd, SD_RECEIVE);
#else
        shutdown(*event_fd_data->p_fd, SHUT_RD);
#endif // _WIN32
    }
    ssh_set_blocking(session, blocking);

    return len;
}