3

Below is a section of code I wrote with the help of this post here: C: can I forward port for external application with libssh?.

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; /* initialize the mutex  */

struct arg_struct 
{
  int sockfd;           /* client socket */
  ssh_session session;  /* ssh session */
  char *rhost;          /* remote where we perform forwarding */
  int rport;            /* ssh port */
  int lport;            /* local port to listen on */
};

/* forward_handler: handle the port forwarding for every thread */
void *forward_handler(void *arg)
{
  char data[4060];
  int rc, recvl, nwritten, nread;
  ssh_channel forwarding_channel;
  struct arg_struct *args = (struct arg_struct*)arg;

  pthread_mutex_lock(&lock); /* lock mutex until task complete */

  /* requests on the fd can return immediately with a failure status if no input, vs blocking */
  if ((fcntl(args->sockfd, F_SETFL, O_NONBLOCK)) != 0)
    goto exit;

  /* get pointer to a newly allocated channel, NULL on error */
  if ((forwarding_channel = ssh_channel_new(args->session)) == NULL) {
    perror("Error");
    goto exit;
  }

  /* open a TCP/IP forwarding channel, SSH_OK if successfull */
  rc = ssh_channel_open_forward(forwarding_channel,
                                args->rhost, args->rport,
                                "127.0.0.1", args->lport);
  if (rc != SSH_OK) {
    perror("Error");
    goto exit;
  }

  printf("Connected! Tunnel open (127.0.0.1:%d) -> (ssh://%s) -> (\"%s:%d\")\n",
    args->lport, args->rhost, args->rhost, args->rport
  );

  /* while we have an open channel and channel has NOT sent an EOF response */
  while(ssh_channel_is_open(forwarding_channel) && !ssh_channel_is_eof(forwarding_channel))
  {
    if ((recvl = recv(args->sockfd, data, sizeof(data), MSG_DONTWAIT)) < 0)                       /* recieve data & enable nonblocking */
      if ((nread = ssh_channel_read_nonblocking(forwarding_channel, data, sizeof(data), 0)) > 0)  /* do a nonblocking read on the channel */
        if ((write(args->sockfd, data, nread)) < 0)                                               /* write to socket */
        {
          perror("Error");
          goto exit;
        }
    else if (!recvl) {
      printf("Local client disconnected, exiting\n");
      goto exit;
    }
    nwritten = ssh_channel_write(forwarding_channel, data, recvl); /* send to the remote host */
    if (recvl != nwritten) {
      perror("Error");
      goto exit;
    }
  }
exit:
  ssh_channel_free(forwarding_channel); /* free the forwarding channel */
  pthread_mutex_unlock(&lock);          /* unlock mutex */
  close(args->sockfd);                  /* close socket file descriptor */
  pthread_exit(NULL);                   /* exit thread */
}

This code has not been optimized and heavily tested and tbh wrote it fairly quickly and need to review it, but it works on Linux as my POC for now. When I try to do the same on Windows I mainly run into an issue on the following lines:

  if ((fcntl(args->sockfd, F_SETFL, O_NONBLOCK)) != 0)
    goto exit;
---snip---
    if ((recvl = recv(args->sockfd, data, sizeof(data), MSG_DONTWAIT)) < 0)                       /* recieve data & enable nonblocking */
      if ((nread = ssh_channel_read_nonblocking(forwarding_channel, data, sizeof(data), 0)) > 0)  /* do a nonblocking read on the channel */
        if ((write(args->sockfd, data, nread)) < 0)                                               

Below are my attempts to fix this:

/* forward_handler: handle the port forwarding for every thread */
void *forward_handler(void *arg)
{
  char data[4096];
  unsigned long int iMode = 1;
  int rc, recvl, nwritten, nread;
  ssh_channel forwarding_channel;
  struct arg_struct *args = (struct arg_struct*)arg;

  pthread_mutex_lock(&lock); /* lock mutex until task complete */

  /* requests on the fd can return immediately with a failure status if no input, vs blocking */
  if ((ioctlsocket(args->sockfd, FIONBIO, &iMode)) != NO_ERROR)
    goto exit;

  /* get pointer to a newly allocated channel, NULL on error */
  if ((forwarding_channel = ssh_channel_new(args->session)) == NULL) {
    fprintf(stderr, "forward_handler: Failed to create new channel with error: %d\n", forwarding_channel);
    exit(0);
  }

  /* open a TCP/IP forwarding channel, SSH_OK if successfull */
  rc = ssh_channel_open_forward(forwarding_channel,
                                args->rhost, args->rport,
                                "127.0.0.1", args->lport);
  if (rc != SSH_OK) {
    fprintf(stderr, "forward_handler: Failed to open forwarding channel with error: %d\n", rc);
    goto exit_and_free;
  }

  printf("Connected! Tunnel open (127.0.0.1:%d) -> (ssh://%s) -> (\"%s:%d\")\n",
    args->lport, args->rhost, args->rhost, args->rport
  );

  /* while we have an open channel and channel has NOT sent an EOF response */
  while(ssh_channel_is_open(forwarding_channel) && !ssh_channel_is_eof(forwarding_channel))
  {
    if ((recvl = recv(args->sockfd, data, sizeof(data), 0)) < 0) {
      if ((nread = ssh_channel_read_nonblocking(forwarding_channel, data, sizeof(data), 0)) > 0)  /* do a nonblocking read on the channel */
        if ((WriteFile((HANDLE)args->sockfd, data, nread, NULL, NULL)) < 0)                       /* write to socket */
        {
          fprintf(stderr, "forward_handler: Error writing to file descriptor");
          goto exit_and_free;
        }
    }
    else if (!recvl) {
      printf("Local client disconnected, exiting\n");
      goto exit_and_free;
    }
    nwritten = ssh_channel_write(forwarding_channel, data, recvl); /* send to the remote host */
    if (recvl != nwritten) {
      fprintf(stderr, "forward_handler: Error writing to SSH channel\n");
      goto exit_and_free;
    }
  }
exit_and_free:
  ssh_channel_free(forwarding_channel); /* free the forwarding channel */
exit:
  pthread_mutex_unlock(&lock);          /* unlock mutex */
  close(args->sockfd);                  /* close socket file descriptor */
  pthread_exit(NULL);                   /* exit thread */
}

Aight hit me with the roasts on bad code :) because I'm stuck.

ChrisMM
  • 8,448
  • 13
  • 29
  • 48
heh
  • 48
  • 8
  • You ran into an issue? *What* is the issue? – Shawn Dec 12 '19 at 18:02
  • I'm not receiving any data on the local port, am I redirecting it properly in Windows? I included both snippets for each OS. The Linux one works perfectly.I have also listed the lines I believe to be causing the issue. – heh Dec 12 '19 at 19:17

0 Answers0