Ejemplo n.º 1
0
static int ssh_stream_read(
	git_smart_subtransport_stream *stream,
	char *buffer,
	size_t buf_size,
	size_t *bytes_read)
{
	int rc;
	ssh_stream *s = (ssh_stream *)stream;

	*bytes_read = 0;

	if (!s->sent_command && send_command(s) < 0)
		return -1;

	if ((rc = libssh2_channel_read(s->channel, buffer, buf_size)) < LIBSSH2_ERROR_NONE) {
		ssh_error(s->session, "SSH could not read data");
		return -1;
	}

	/*
	 * If we can't get anything out of stdout, it's typically a
	 * not-found error, so read from stderr and signal EOF on
	 * stderr.
	 */
	if (rc == 0) {
		if ((rc = libssh2_channel_read_stderr(s->channel, buffer, buf_size)) > 0) {
			giterr_set(GITERR_SSH, "%*s", rc, buffer);
			return GIT_EEOF;
		} else if (rc < LIBSSH2_ERROR_NONE) {
			ssh_error(s->session, "SSH could not read stderr");
			return -1;
		}
	}


	*bytes_read = rc;

	return 0;
}
Ejemplo n.º 2
0
static int exec_channel_command_exec(SSH_SESSION* p_session, const char* command, int (*callback)(char*, const char*, void*), void* obj)
{
    char* buffer;
    int buffer_length = COMMAND_RESULT_BUFFER_LENGTH;
    int ec;
    int result_code;
    LIBSSH2_CHANNEL* channel;
    
    while((ec = libssh2_channel_exec(p_session->session_param->channel, command)) == LIBSSH2_ERROR_EAGAIN)
    {
        waitsocket(p_session->session_param->sock, p_session->session_param->session, TIMEOUT_SEC);
    }
    if(ec < 0)
    {
        debug_log(SSH_TERMINAL_COMMAND_EXEC_ERROR, "sync_command_exec : channel exec failed.");
        return SSH_TERMINAL_COMMAND_EXEC_ERROR;
    }
    
    buffer = (char*)malloc(sizeof(char) * (buffer_length + 1));
    
    while(1)
    {
        do{
            memset(buffer, 0, buffer_length + 1);
            ec = libssh2_channel_read(p_session->session_param->channel, buffer, buffer_length);
            if(ec == 0)
            {
                ec = libssh2_channel_read_stderr(p_session->session_param->channel, buffer, buffer_length);
            }
            if(ec > 0)
            {
                callback(buffer, command, obj);
            }
        }
        while(ec > 0);
        
        if(ec == LIBSSH2_ERROR_EAGAIN)
        {
            waitsocket(p_session->session_param->sock, p_session->session_param->session, TIMEOUT_SEC);
        }
        else
        {
            break;
        }
    }
    free(buffer);
    if(ec < 0)
    {
        debug_log(SSH_TERMINAL_CHANNEL_READ_ERROR, "sync_command_exec : channel read failed.");
        result_code = SSH_TERMINAL_CHANNEL_READ_ERROR;
    }
    else
    {
        result_code = 0;
    }
    
    while(libssh2_channel_close(p_session->session_param->channel) == LIBSSH2_ERROR_EAGAIN)
    {
        waitsocket(p_session->session_param->sock, p_session->session_param->session, TIMEOUT_SEC);
    }
    
    libssh2_channel_free(p_session->session_param->channel);
    
    while((channel = libssh2_channel_open_session(p_session->session_param->session)) == NULL &&
          libssh2_session_last_error(p_session->session_param->session, NULL, NULL, 0) == LIBSSH2_ERROR_EAGAIN)
    {
        waitsocket(p_session->session_param->sock, p_session->session_param->session, TIMEOUT_SEC);
    }
    if(channel == NULL)
    {
        result_code = SSH_TERMINAL_CHANNEL_OPEN_ERROR;
    }
    
    p_session->session_param->channel = channel;
    
    return result_code;
}
Ejemplo n.º 3
0
int Parser::runCommand(QString command)
{
    // command channel
    //------------setup channel ----------------------
    LIBSSH2_CHANNEL *channel = NULL;
    channel = libssh2_channel_open_session(session_);
    if ( channel == NULL )
    {
        qDebug()<<"Failed to open a new channel\n";
        socket_->disconnectFromHost();
        return -1;
    }

    /* Force Data to on STDOUT and STDERR to be on seperate channels
     * read individually with *_read and *_read_stderr functions */
    libssh2_channel_handle_extended_data(channel,LIBSSH2_CHANNEL_EXTENDED_DATA_NORMAL);

    libssh2_channel_set_blocking(channel, 1);

    {
    int rc;
    while ((rc=libssh2_channel_exec(channel, command.toLocal8Bit().constData()))==LIBSSH2_ERROR_EAGAIN );
    if (rc)
    {
        return -1;
    }


    //-------read channel-----------
    int read;

    QString stdout_str;
    QString stderr_str;
    while(true)
    {
        //qDebug("libssh2_channel_read() >>>");

        {
            QByteArray byte_array;
            byte_array.resize(4096);
            char* buffer=byte_array.data();
            int buffer_size=byte_array.size();
            read = libssh2_channel_read(channel, buffer, buffer_size-10);
            if(read>0)
            {
                QByteArray debug = QByteArray(buffer, read);
                stdout_str.append(debug);
            }
            if(LIBSSH2_ERROR_EAGAIN == read)
            {
                qDebug("LIBSSH2_ERROR_EAGAIN");
                break;
            }
            else if(read  < 0)
            {
                qDebug(" error reading from std channel");
                closeChannel(channel);
                goto next_channel;
            }
        }
        {
            QByteArray byte_array;
            byte_array.resize(4096);
            char* buffer=byte_array.data();
            int buffer_size=byte_array.size();

read = libssh2_channel_read_stderr(channel, buffer, buffer_size-10);
            if(read>0)
            {
                QByteArray debug = QByteArray(buffer, read);
                stderr_str.append(debug);
            }
            if(LIBSSH2_ERROR_EAGAIN == read)
            {
                qDebug("LIBSSH2_ERROR_EAGAIN");
                break;
            }
            else if(read  < 0)
            {
                qDebug(" error reading from stderr channel");
                closeChannel(channel);
                goto next_channel;
            }
        }


        int i = libssh2_channel_eof(channel);
        if(i)
        {
            //qDebug("libssh2_channel_eof %i", i);
            closeChannel(channel);
            goto next_channel;
        }
    }
    next_channel:
    if(!stdout_str.isEmpty())
    {
        qDebug()<<"STDOUT:\n"<<stdout_str;
    }
    if(!stderr_str.isEmpty())
    {
        qDebug()<<"STDERR:\n"<<stderr_str;
    }
    }
    return 1;
}
Ejemplo n.º 4
0
/**
 * usage: seashell-tunnel [username] [host] [target]
 *
 * First n bytes on standard input should be:
 *
 * ----------------------------------------------------------------------------------------------------------
 * | length / 4 byte unsigned integer | authentication method / 1 byte | authentication data : length bytes |
 * ----------------------------------------------------------------------------------------------------------
 *
 * Authentication methods:
 *  0 - password.
 *
 * Currently, only password authentication is supported.  Therefore,
 * the authentication method is ignored.  It might be worth looking
 * at supporting public key authentication in the future.  This'll
 * require extending the connection launcher.
 *
 * Bytes after n are simply forwarded onwards with no processing applied.
 *
 * For password authentication, the null terminating byte is expected to be in the authentication data.
 *
 * seashell-tunnel will write a single ASCII 'O' (79) denoting handshake success before starting
 * two-way forwarding.
 *
 * IP address are also written; IPv4 passed as X.X.X.X, IPv6 as [:X:X::X]
 */
int main (int argc, char *argv[]) {
  uint32_t length = 0;
  uint8_t method = 0;
  int8_t* data = NULL;
  int i = 0;
  char stderr_buffer[4096];
  ssize_t stderr_read = 0;

  if (argc < 4) {
    fprintf(stderr, "usage: %s [username] [host] [target]\n", argv[0]);
    return IO_ERROR;
  }

  FPRINTF_IF_DEBUG(stderr, "%s: Launching tunnel!\n", argv[1]);

  for (i = 0; i < 4; i++) {
    uint8_t buf;
    if (1 != read(0, &buf, 1)) {
      fprintf(stderr, "%s: I/O error on reading authentication packet length.\n", argv[1]);
      return IO_ERROR;
    }
    length |= buf << (8 * i);
  }
  FPRINTF_IF_DEBUG(stderr, "%s: Read authentication packet length.\n", argv[1]);

  if (1 != read(0, &method, 1)) {
    fprintf(stderr, "%s: I/O error on reading authentication method.\n", argv[1]);
    return IO_ERROR;
  }
  FPRINTF_IF_DEBUG(stderr, "%s: Read authentication method.\n", argv[1]);

  data = malloc(length);
  if (!data) {
    fprintf(stderr, "%s: Ran out of memory!\n", argv[1]);
    return OTHER_ERROR;
  }
  if (length != read(0, data, length)) {
    fprintf(stderr, "%s: Couldn't read authentication data!\n", argv[1]);
    return IO_ERROR;
  }
  FPRINTF_IF_DEBUG(stderr, "%s: Read authentication data.\n", argv[1]);

  /** This is where we need to handle extra authentication methods. */
  int error; char* exitsignal;

  error = seashell_tunnel_startup();
  if (error) {
    fprintf(stderr, "%s: Error launching libssh2!\n", argv[1]);
    goto end;
  }

  char remote_addr[128];
  memset(remote_addr, 0, 128);
  int family;

  struct seashell_connection* conn = seashell_tunnel_connect_password(
      argv[2], argv[1], data, &error, remote_addr, &family, argv[3]);

  if (!conn) {
    fprintf(stderr, "%s: Error on opening tunnel to %s: %d\n", argv[1], argv[2], error);
    goto end;
  }

  /** Signal success */
  {
    const int8_t success = 'O';
    write(1, &success, 1);
    uint8_t addrlen = strlen(remote_addr);

    /** Write the address, formatted for URI safety. */

    /** IPv6 addresses need to be formatted for safety. */
    if (family == AF_INET6) {
      char buffer[130] = {0};
      int bufferlen = snprintf(buffer, 130, "[%s]", remote_addr);
          
      write(1, &bufferlen, 1);
      write(1, buffer, bufferlen);
    }
    /** IPv4 addresses do not need to be formatted. */
    else if (family == AF_INET) {
      write(1, &addrlen, 1);
      write(1, remote_addr, addrlen);
    } else {
      fprintf(stderr, "%s: Unknown address family %d!\n", argv[1], family);
      goto end;
    }

    FPRINTF_IF_DEBUG(stderr, "%s: Remote address is '%s' (%d) (%d)\n", argv[1], remote_addr, (int)addrlen, family);
  }
  FPRINTF_IF_DEBUG(stderr, "%s: Tunnel launched!\n", argv[1]);

  /** Now we select from fd 0, write to socket,
   *  select from socket, write to fd 1 */
  error = loop_and_copy(0, 1, conn);

  if (error) {
    fprintf(stderr, "%s: I/O error on copy: %d\n", argv[1], error);
    goto report_errors;
  }

  /** Make sure the remote end hung up cleanly. */
  error = libssh2_channel_get_exit_status(conn->channel);
  libssh2_channel_get_exit_signal(conn->channel, &exitsignal,
      NULL, NULL, NULL, NULL, NULL);

  FPRINTF_IF_DEBUG(stderr, "%s: Remote end hung up with %d (%s)\n", argv[1], error, exitsignal);

  if (exitsignal) {
    error = OTHER_ERROR;
  }
report_errors:
  /** Drain stderr on the SSH connection. */
  while ((stderr_read = libssh2_channel_read_stderr(conn->channel, stderr_buffer, sizeof(char)*4096)) > 0) {
    fwrite(stderr_buffer, sizeof(char), stderr_read, stderr);
  }
end:
  seashell_tunnel_free(conn);
  seashell_tunnel_teardown();
  return error;
}
Ejemplo n.º 5
0
/**
 * loop_and_copy (int infd, int outfd, struct seashell_connection* conn)
 * Copies data to/from the file descriptors and socket.
 *
 *
 * Arguments:
 *  infd, outfd - input/output file descriptors.
 *  conn - Seashell connection object.
 *
 * Returns:
 *  0 on clean disconnect, nonzero value otherwise.
 */
int loop_and_copy(int infd, int outfd, struct seashell_connection* conn) {
  struct timeval timeout;
  fd_set readfds;

  char buffer[4096];
  ssize_t start = 0, len = 0, rc = 0;
  int nfds = 1 + MAX(infd, conn->sockfd);

  while (1) {
    FD_ZERO(&readfds);
    FD_SET(conn->sockfd, &readfds);
    FD_SET(infd, &readfds);

    timeout.tv_sec = 10;
    timeout.tv_usec = 0;

    if (select(nfds, &readfds, NULL, NULL, &timeout) > 0) {
      /** We're OK only when we have something to read from and something to write to. */

      /**
       *  Something to read from remote - might block on write, this is OK.
       *  Time permitting, it might be nice to have a write queue and
       *  go through the select loop again for fairness,
       *  but it really doesn't matter.
       */
      if (FD_ISSET(conn->sockfd, &readfds)) {
        /** Do our reads in nonblocking mode as we may get payload data for
         *  some other stream. */
        seashell_set_nonblocking(conn);
        len = libssh2_channel_read(conn->channel, buffer, sizeof(buffer));
        seashell_set_blocking(conn);

        if (len == LIBSSH2_ERROR_EAGAIN) {
        }
        else if (len < 0) {
          return len;
        } else if (len > 0) {

          start = 0;

          while (len) {
            rc = write(outfd, buffer + start, len);
            if (rc < 0) {
              return rc;
            }
            len -= rc;
            start += rc;
          }
        }

        /** Drain stderr. */
        seashell_set_nonblocking(conn);
        len = libssh2_channel_read_stderr(conn->channel, buffer, sizeof(buffer));
        seashell_set_blocking(conn);
        if (len == LIBSSH2_ERROR_EAGAIN) {
        }
        else if (len < 0) {
          return len;
        } else if (len > 0) {
          start = 0;

          while (len) {
            rc = write(2, buffer + start, len);
            if (rc < 0) {
              return rc;
            }
            len -= rc;
            start += rc;
          }
        }
      }

      /**
       * Something to read from local - might block on write, this is OK.
       * See above for rationale, and libssh2_channel_write doesn't seem
       * to block nicely.  Oh well.
       */
      if (FD_ISSET(infd, &readfds)) {
        len = read(infd, buffer, sizeof(buffer));

        if (len < 0) {
          return len;
        } else if (len == 0) {
          return 0;
        } else {
          start = 0;

          while (len) {
            rc = libssh2_channel_write(conn->channel, buffer + start, len);
            if (rc < 0) {
              return rc;
            }
            len -= rc;
            start += rc;
          }
        }
      }
    }
    /**
     * And if we died...
     */
    if (libssh2_channel_eof(conn->channel) == 1) {
      return 0;
    }
  }
}
Ejemplo n.º 6
0
int ssh::exec_cmd(const string &command)
{
	int rc;

	/* Exec non-blocking on the remove host */
	while( (channel = libssh2_channel_open_session(session)) == NULL &&
				libssh2_session_last_error(session,NULL,NULL,0) ==
				LIBSSH2_ERROR_EAGAIN )
	{
		waitsocket(_sock_fd, session);
	}

	if( channel == NULL )
	{
		cout << "Error" << std::endl;
		exit( 1 );
	}

	while( (rc = libssh2_channel_exec(channel, command.c_str())) ==
			LIBSSH2_ERROR_EAGAIN )
	{
		waitsocket(_sock_fd, session);
	}

	if( rc != 0 )
	{
		cout << "Error" << std::endl;
		exit( 1 );
	}

	for( ;; )
	{
		/* loop until we block */
		int rc;
		do
		{
			char buffer[0x4000];
			rc = libssh2_channel_read( channel, buffer, sizeof(buffer) );
			if( rc > 0 )
			{
			/*	int i;
				bytecount += rc;*/
			/*	cout <<  "We read: " << std::endl;*/
				cout << "[" << _ip_addr << "]====start====== " << std::endl;
				/*for( i=0; i < rc; ++i )
					fputc( buffer[i], stderr);*/
				cout << buffer;
				cout << "[" << _ip_addr << "]====end======== " << std::endl;
			}
			/*else {
				if( rc != LIBSSH2_ERROR_EAGAIN )
			no need to output this for the EAGAIN case 
					cout << "libssh2_channel_read returned " << rc << std::endl;
			}*/
			
		}
		while( rc > 0 );

		do
		{
			char buffer2[0x4000];
			rc = libssh2_channel_read_stderr( channel, buffer2, sizeof(buffer2) );
			if( rc > 0 )
			{
			/*	int i;
				bytecount += rc;*/
				/*cout <<  "We read: " << std::endl;*/
				cout << "[" << _ip_addr << "]====start====== " << std::endl;
				/*for( i=0; i < rc; ++i )
					fputc( buffer[i], stderr);*/
				cout << buffer2;
				cout << "[" << _ip_addr << "]====end======== " << std::endl;
			}
			/*else {
				if( rc != LIBSSH2_ERROR_EAGAIN )
				no need to output this for the EAGAIN case 
					cout << "libssh2_channel_read_stderr returned " << rc << std::endl;
			}*/
			
		}
		while( rc > 0 );

		/* this is due to blocking that would occur otherwise so we loop on
		this condition */
		if( rc == LIBSSH2_ERROR_EAGAIN )
		{
			waitsocket(_sock_fd, session);
		}
		else
			break;
	}

	quit_channel();
	
	return 0;
}
Ejemplo n.º 7
-1
QString Parser::sshRequest(QString commandline)
{
    QString host_ip(this->sharedHost);
    QString user_name=this->sharedUser;
    QString pass_word=this->sharedPass;

    //---------- connection --------------
    int libssh2_error = libssh2_init(0);
    if(libssh2_error)
    {
        qDebug("libssh2_init() error: %d", libssh2_error);
        //return -2;
    }

    QTcpSocket socket;
    socket.connectToHost(host_ip, 22);
    if(!socket.waitForConnected())
    {
        qDebug("Error connecting to host %s", host_ip.toLocal8Bit().constData());
        //return -1;
    }

    LIBSSH2_SESSION *session = libssh2_session_init();
    if(!session)
    {
        qDebug("libssh2_session_init() failed");
        //return -2;
    }

    libssh2_error = libssh2_session_startup(session, socket.socketDescriptor());
    if(libssh2_error)
    {
        qDebug("libssh2_session_startup() error: %d", libssh2_error);
        //return -3;
    }

    {
    /* At this point we havn't yet authenticated.  The first thing to do
     * is check the hostkey's fingerprint against our known hosts Your app
     * may have it hard coded, may go to a file, may present it to the
     * user, that's your call
     */
    const char *fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
    }

    libssh2_userauth_list(session, user_name.toLocal8Bit().constData(), user_name.toLocal8Bit().length());
    if(libssh2_userauth_password(
        session,
        user_name.toLocal8Bit().constData(),
        pass_word.toLocal8Bit().constData()
    ))
    {
        qDebug("Password authentication failed");

        socket.disconnectFromHost();
        libssh2_session_disconnect(session, "Client disconnecting for error");
        libssh2_session_free(session);
        libssh2_exit();

        //return -4;
    }

    // command channel
    //------------setup channel ----------------------
    LIBSSH2_CHANNEL *channel = NULL;
    channel = libssh2_channel_open_session(session);
    int rc;
    if ( channel == NULL )
    {
        qDebug()<<"Failed to open a new channel\n";
        socket.disconnectFromHost();
        //return -1;
    }
    libssh2_channel_set_blocking(channel, 1);
    while ((rc=libssh2_channel_exec(channel, commandline.toLocal8Bit().constData()))==LIBSSH2_ERROR_EAGAIN );
    if (rc)
    {
        //return -1;
    }

    //-------read channel-----------
    int read;
    QByteArray byte_array;
    byte_array.resize(4096);
    char* buffer=byte_array.data();
    int buffer_size=byte_array.size();

    QString myOutPut;

    while(true)
    {
        {
            read = libssh2_channel_read(channel, buffer, buffer_size);
            QByteArray debug = QByteArray(buffer, read);

            //qDebug()<<"STDOUT: "<<debug.constData();
            myOutPut = debug.constData();
            qDebug() << myOutPut;
            if(LIBSSH2_ERROR_EAGAIN == read)
            {
                qDebug("LIBSSH2_ERROR_EAGAIN");
                break;
            }
            else if(read  < 0)
            {
                qDebug(" error reading from channel");
                closeChannel(channel);
                goto next_channel;
            }

        }
        {
            read = libssh2_channel_read_stderr(channel, buffer, buffer_size);
            QByteArray debug = QByteArray(buffer, read);
            qDebug()<<"STDERR: "<<debug.constData();
            if(LIBSSH2_ERROR_EAGAIN == read)
            {
                qDebug("LIBSSH2_ERROR_EAGAIN");
                break;
            }
            else if(read  < 0)
            {
                qDebug(" error reading from channel");
                closeChannel(channel);
                goto next_channel;
            }

        }

        int i=0;

        i = libssh2_channel_eof(channel);
        if(i)
        {
            qDebug("libssh2_channel_eof %i", i);
            closeChannel(channel);
            goto next_channel;
        }
    }
next_channel:

    //------------ clean session
    socket.disconnectFromHost();

    libssh2_session_disconnect(session, "Client disconnecting normally");
    libssh2_session_free(session);
    libssh2_exit();

    return myOutPut;
}