mirror of
https://github.com/nmap/nmap.git
synced 2025-12-06 04:31:29 +00:00
NSE libssh2 bindings: allow exec without pty
This commit is contained in:
@@ -14,6 +14,7 @@ extern "C" {
|
||||
|
||||
#include "nse_nsock.h"
|
||||
#include "nse_utility.h"
|
||||
#include "nbase.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
@@ -702,10 +703,10 @@ static int channel_read (lua_State *L, int status, lua_KContext ctx) {
|
||||
int rc;
|
||||
char buf[2048];
|
||||
size_t buflen = 2048;
|
||||
LIBSSH2_CHANNEL **channel = (LIBSSH2_CHANNEL **) lua_touserdata(L, 2);
|
||||
LIBSSH2_CHANNEL *channel = (LIBSSH2_CHANNEL *) lua_touserdata(L, 2);
|
||||
int stream_id = luaL_checkinteger(L, 3);
|
||||
|
||||
DO_OR_YIELD((rc = libssh2_channel_read_ex(*channel, stream_id, buf, buflen)),
|
||||
DO_OR_YIELD((rc = libssh2_channel_read_ex(channel, stream_id, buf, buflen)),
|
||||
1, channel_read, ctx);
|
||||
|
||||
if (rc > 0) {
|
||||
@@ -734,14 +735,14 @@ static int channel_write (lua_State *L, int status, lua_KContext ctx) {
|
||||
int rc;
|
||||
const char *buf;
|
||||
size_t buflen = 0;
|
||||
LIBSSH2_CHANNEL **channel = (LIBSSH2_CHANNEL **) lua_touserdata(L, 2);
|
||||
LIBSSH2_CHANNEL *channel = (LIBSSH2_CHANNEL *) lua_touserdata(L, 2);
|
||||
|
||||
if (lua_isstring(L, 3))
|
||||
buf = lua_tolstring(L, 3, &buflen);
|
||||
else
|
||||
return luaL_error(L, "Invalid buffer");
|
||||
|
||||
DO_OR_YIELD((rc = libssh2_channel_write(*channel, buf, buflen)),
|
||||
DO_OR_YIELD((rc = libssh2_channel_write(channel, buf, buflen)),
|
||||
1, channel_write, ctx);
|
||||
|
||||
if (rc < 0)
|
||||
@@ -758,10 +759,10 @@ static int l_channel_write (lua_State *L) {
|
||||
static int channel_exec (lua_State *L, int status, lua_KContext ctx) {
|
||||
int rc;
|
||||
// ssh_userdata *state = (ssh_userdata *)lua_touserdata(L, 1);
|
||||
LIBSSH2_CHANNEL **channel = (LIBSSH2_CHANNEL **) lua_touserdata(L, 2);
|
||||
LIBSSH2_CHANNEL *channel = (LIBSSH2_CHANNEL *) lua_touserdata(L, 2);
|
||||
const char *cmd = luaL_checkstring(L, 3);
|
||||
|
||||
DO_OR_YIELD((rc = libssh2_channel_exec(*channel, cmd)),
|
||||
DO_OR_YIELD((rc = libssh2_channel_exec(channel, cmd)),
|
||||
1, channel_exec, ctx);
|
||||
if (rc != 0)
|
||||
return luaL_error(L, "Error executing command");
|
||||
@@ -775,9 +776,9 @@ static int l_channel_exec (lua_State *L) {
|
||||
|
||||
static int l_channel_eof(lua_State *L) {
|
||||
int result;
|
||||
LIBSSH2_CHANNEL **channel = (LIBSSH2_CHANNEL **) lua_touserdata(L, 1);
|
||||
LIBSSH2_CHANNEL *channel = (LIBSSH2_CHANNEL *) lua_touserdata(L, 1);
|
||||
|
||||
result = libssh2_channel_eof(*channel);
|
||||
result = libssh2_channel_eof(channel);
|
||||
if (result >= 0)
|
||||
lua_pushboolean(L, result);
|
||||
else
|
||||
@@ -789,9 +790,9 @@ static int l_channel_eof(lua_State *L) {
|
||||
static int channel_send_eof(lua_State *L, int status, lua_KContext ctx) {
|
||||
int rc;
|
||||
// ssh_userdata *state = (ssh_userdata *)lua_touserdata(L, 1);
|
||||
LIBSSH2_CHANNEL **channel = (LIBSSH2_CHANNEL **) lua_touserdata(L, 2);
|
||||
LIBSSH2_CHANNEL *channel = (LIBSSH2_CHANNEL *) lua_touserdata(L, 2);
|
||||
|
||||
DO_OR_YIELD((rc = libssh2_channel_send_eof(*channel)),
|
||||
DO_OR_YIELD((rc = libssh2_channel_send_eof(channel)),
|
||||
1, channel_send_eof, ctx);
|
||||
if (rc != 0)
|
||||
return luaL_error(L, "Error sending EOF");
|
||||
@@ -803,53 +804,62 @@ static int l_channel_send_eof(lua_State *L) {
|
||||
return channel_send_eof(L, 0, 0);
|
||||
}
|
||||
|
||||
struct channel_context {
|
||||
bool request_pty;
|
||||
LIBSSH2_CHANNEL *channel;
|
||||
};
|
||||
|
||||
static int setup_channel(lua_State *L, int status, lua_KContext ctx) {
|
||||
int rc;
|
||||
// ssh_userdata *state = (ssh_userdata *)lua_touserdata(L, 1);
|
||||
LIBSSH2_CHANNEL **channel = (LIBSSH2_CHANNEL **) lua_touserdata(L, 2);
|
||||
channel_context *channel_ctx = (channel_context *) ctx;
|
||||
ssh_userdata *state = (ssh_userdata *)lua_touserdata(L, 1);
|
||||
|
||||
DO_OR_YIELD((rc = libssh2_channel_request_pty(*channel, "vanilla")),
|
||||
if (channel_ctx->channel == NULL) {
|
||||
DO_OR_YIELD(((channel_ctx->channel = libssh2_channel_open_session(state->session)) == NULL ?
|
||||
libssh2_session_last_errno(state->session) : LIBSSH2_ERROR_NONE),
|
||||
1, setup_channel, ctx);
|
||||
if (rc != 0)
|
||||
if (channel_ctx->channel == NULL) {
|
||||
free(channel_ctx);
|
||||
return luaL_error(L, "Opening channel");
|
||||
}
|
||||
}
|
||||
|
||||
if (channel_ctx->request_pty) {
|
||||
DO_OR_YIELD((rc = libssh2_channel_request_pty(channel_ctx->channel, "vanilla")),
|
||||
1, setup_channel, ctx);
|
||||
if (rc != 0) {
|
||||
free(channel_ctx);
|
||||
return luaL_error(L, "Requesting pty");
|
||||
}
|
||||
channel_ctx->request_pty = false; // make sure we don't enter this block again
|
||||
}
|
||||
|
||||
lua_pushlightuserdata(L, channel_ctx->channel);
|
||||
free(channel_ctx);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_setup_channel (lua_State *L) {
|
||||
return setup_channel(L, 0, 0);
|
||||
}
|
||||
|
||||
static int finish_open_channel (lua_State *L, int status, lua_KContext ctx) {
|
||||
ssh_userdata *state = (ssh_userdata *)lua_touserdata(L, 1);
|
||||
LIBSSH2_CHANNEL **channel = (LIBSSH2_CHANNEL **) lua_touserdata(L, 2);
|
||||
|
||||
DO_OR_YIELD(((*channel = libssh2_channel_open_session(state->session)) == NULL ?
|
||||
libssh2_session_last_errno(state->session) : LIBSSH2_ERROR_NONE),
|
||||
1, finish_open_channel, ctx);
|
||||
if (*channel == NULL)
|
||||
return luaL_error(L, "Opening channel");
|
||||
|
||||
return setup_channel(L, 0, 0);
|
||||
}
|
||||
|
||||
static int l_open_channel (lua_State *L) {
|
||||
ssh_userdata *state = (ssh_userdata *)lua_touserdata(L, 1);
|
||||
LIBSSH2_CHANNEL **channel = (LIBSSH2_CHANNEL **)lua_newuserdatauv(L, sizeof(LIBSSH2_CHANNEL *), 0);
|
||||
//ssh_userdata *state = (ssh_userdata *)lua_touserdata(L, 1);
|
||||
bool no_pty = false;
|
||||
if (lua_gettop(L) > 1) {
|
||||
no_pty = lua_toboolean(L, 2);
|
||||
}
|
||||
lua_settop(L, 1);
|
||||
|
||||
DO_OR_YIELD(((*channel = libssh2_channel_open_session(state->session)) == NULL ?
|
||||
libssh2_session_last_errno(state->session) : LIBSSH2_ERROR_NONE),
|
||||
1, finish_open_channel, 0);
|
||||
channel_context *ctx = (channel_context *)safe_zalloc(sizeof(channel_context));
|
||||
ctx->request_pty = !no_pty;
|
||||
|
||||
return l_setup_channel(L);
|
||||
return setup_channel(L, 0, (lua_KContext) ctx);
|
||||
}
|
||||
|
||||
static int channel_close (lua_State *L, int status, lua_KContext ctx) {
|
||||
int rc;
|
||||
// ssh_userdata *state = (ssh_userdata *)lua_touserdata(L, 1);
|
||||
LIBSSH2_CHANNEL **channel = (LIBSSH2_CHANNEL **) lua_touserdata(L, 2);
|
||||
LIBSSH2_CHANNEL *channel = (LIBSSH2_CHANNEL *) lua_touserdata(L, 2);
|
||||
|
||||
DO_OR_YIELD((rc = libssh2_channel_close(*channel)),
|
||||
DO_OR_YIELD((rc = libssh2_channel_close(channel)),
|
||||
1, channel_close, ctx);
|
||||
if (rc != 0)
|
||||
return luaL_error(L, "Error closing channel");;
|
||||
|
||||
@@ -57,12 +57,13 @@ end
|
||||
-- Runs a shell command on the remote host.
|
||||
--
|
||||
-- @param cmd A command to run.
|
||||
-- @param no_pty If true, skip requesting a PTY.
|
||||
-- @return The command output.
|
||||
function SSHConnection:run_remote (cmd)
|
||||
function SSHConnection:run_remote (cmd, no_pty)
|
||||
if not (self.session and self.authenticated) then
|
||||
return false
|
||||
end
|
||||
local channel = libssh2.open_channel(self.session)
|
||||
local channel = libssh2.open_channel(self.session, no_pty)
|
||||
libssh2.channel_exec(self.session, channel, cmd)
|
||||
libssh2.channel_send_eof(self.session, channel)
|
||||
local buff = {}
|
||||
@@ -71,6 +72,9 @@ function SSHConnection:run_remote (cmd)
|
||||
data = libssh2.channel_read(self.session, channel)
|
||||
if data then
|
||||
table.insert(buff, data)
|
||||
elseif no_pty then
|
||||
-- PTY is responsible for sending EOF
|
||||
break
|
||||
end
|
||||
end
|
||||
return table.concat(buff)
|
||||
|
||||
@@ -67,11 +67,12 @@ function read_publickey(publickeyfile)
|
||||
-- @return true/false, depending on whether user can authenticate with given key
|
||||
function publickey_canauth(session, username, publickeydata)
|
||||
|
||||
--- Opens channel on authenticated ssh2 session and sets it to pseudo
|
||||
--- Opens channel on authenticated ssh2 session and optionally sets it to pseudo
|
||||
-- terminal mode.
|
||||
-- @param session Authenticated libssh2 session
|
||||
-- @param no_pty If true, skip requesting a PTY.
|
||||
-- @return libssh2 channel
|
||||
function open_channel(session)
|
||||
function open_channel(session, pty)
|
||||
|
||||
--- Reads data from stdin on libssh2 channel.
|
||||
-- @param session Authenticated libssh2 session
|
||||
|
||||
Reference in New Issue
Block a user