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_nsock.h"
|
||||||
#include "nse_utility.h"
|
#include "nse_utility.h"
|
||||||
|
#include "nbase.h"
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
@@ -702,10 +703,10 @@ static int channel_read (lua_State *L, int status, lua_KContext ctx) {
|
|||||||
int rc;
|
int rc;
|
||||||
char buf[2048];
|
char buf[2048];
|
||||||
size_t buflen = 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);
|
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);
|
1, channel_read, ctx);
|
||||||
|
|
||||||
if (rc > 0) {
|
if (rc > 0) {
|
||||||
@@ -734,14 +735,14 @@ static int channel_write (lua_State *L, int status, lua_KContext ctx) {
|
|||||||
int rc;
|
int rc;
|
||||||
const char *buf;
|
const char *buf;
|
||||||
size_t buflen = 0;
|
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))
|
if (lua_isstring(L, 3))
|
||||||
buf = lua_tolstring(L, 3, &buflen);
|
buf = lua_tolstring(L, 3, &buflen);
|
||||||
else
|
else
|
||||||
return luaL_error(L, "Invalid buffer");
|
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);
|
1, channel_write, ctx);
|
||||||
|
|
||||||
if (rc < 0)
|
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) {
|
static int channel_exec (lua_State *L, int status, lua_KContext ctx) {
|
||||||
int rc;
|
int rc;
|
||||||
// ssh_userdata *state = (ssh_userdata *)lua_touserdata(L, 1);
|
// 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);
|
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);
|
1, channel_exec, ctx);
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
return luaL_error(L, "Error executing command");
|
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) {
|
static int l_channel_eof(lua_State *L) {
|
||||||
int result;
|
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)
|
if (result >= 0)
|
||||||
lua_pushboolean(L, result);
|
lua_pushboolean(L, result);
|
||||||
else
|
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) {
|
static int channel_send_eof(lua_State *L, int status, lua_KContext ctx) {
|
||||||
int rc;
|
int rc;
|
||||||
// ssh_userdata *state = (ssh_userdata *)lua_touserdata(L, 1);
|
// 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);
|
1, channel_send_eof, ctx);
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
return luaL_error(L, "Error sending EOF");
|
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);
|
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) {
|
static int setup_channel(lua_State *L, int status, lua_KContext ctx) {
|
||||||
int rc;
|
int rc;
|
||||||
// ssh_userdata *state = (ssh_userdata *)lua_touserdata(L, 1);
|
channel_context *channel_ctx = (channel_context *) ctx;
|
||||||
LIBSSH2_CHANNEL **channel = (LIBSSH2_CHANNEL **) lua_touserdata(L, 2);
|
ssh_userdata *state = (ssh_userdata *)lua_touserdata(L, 1);
|
||||||
|
|
||||||
DO_OR_YIELD((rc = libssh2_channel_request_pty(*channel, "vanilla")),
|
if (channel_ctx->channel == NULL) {
|
||||||
1, setup_channel, ctx);
|
DO_OR_YIELD(((channel_ctx->channel = libssh2_channel_open_session(state->session)) == NULL ?
|
||||||
if (rc != 0)
|
libssh2_session_last_errno(state->session) : LIBSSH2_ERROR_NONE),
|
||||||
|
1, setup_channel, ctx);
|
||||||
|
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");
|
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;
|
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) {
|
static int l_open_channel (lua_State *L) {
|
||||||
ssh_userdata *state = (ssh_userdata *)lua_touserdata(L, 1);
|
//ssh_userdata *state = (ssh_userdata *)lua_touserdata(L, 1);
|
||||||
LIBSSH2_CHANNEL **channel = (LIBSSH2_CHANNEL **)lua_newuserdatauv(L, sizeof(LIBSSH2_CHANNEL *), 0);
|
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 ?
|
channel_context *ctx = (channel_context *)safe_zalloc(sizeof(channel_context));
|
||||||
libssh2_session_last_errno(state->session) : LIBSSH2_ERROR_NONE),
|
ctx->request_pty = !no_pty;
|
||||||
1, finish_open_channel, 0);
|
|
||||||
|
|
||||||
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) {
|
static int channel_close (lua_State *L, int status, lua_KContext ctx) {
|
||||||
int rc;
|
int rc;
|
||||||
// ssh_userdata *state = (ssh_userdata *)lua_touserdata(L, 1);
|
// 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);
|
1, channel_close, ctx);
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
return luaL_error(L, "Error closing channel");;
|
return luaL_error(L, "Error closing channel");;
|
||||||
|
|||||||
@@ -57,12 +57,13 @@ end
|
|||||||
-- Runs a shell command on the remote host.
|
-- Runs a shell command on the remote host.
|
||||||
--
|
--
|
||||||
-- @param cmd A command to run.
|
-- @param cmd A command to run.
|
||||||
|
-- @param no_pty If true, skip requesting a PTY.
|
||||||
-- @return The command output.
|
-- @return The command output.
|
||||||
function SSHConnection:run_remote (cmd)
|
function SSHConnection:run_remote (cmd, no_pty)
|
||||||
if not (self.session and self.authenticated) then
|
if not (self.session and self.authenticated) then
|
||||||
return false
|
return false
|
||||||
end
|
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_exec(self.session, channel, cmd)
|
||||||
libssh2.channel_send_eof(self.session, channel)
|
libssh2.channel_send_eof(self.session, channel)
|
||||||
local buff = {}
|
local buff = {}
|
||||||
@@ -71,6 +72,9 @@ function SSHConnection:run_remote (cmd)
|
|||||||
data = libssh2.channel_read(self.session, channel)
|
data = libssh2.channel_read(self.session, channel)
|
||||||
if data then
|
if data then
|
||||||
table.insert(buff, data)
|
table.insert(buff, data)
|
||||||
|
elseif no_pty then
|
||||||
|
-- PTY is responsible for sending EOF
|
||||||
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return table.concat(buff)
|
return table.concat(buff)
|
||||||
|
|||||||
@@ -67,11 +67,12 @@ function read_publickey(publickeyfile)
|
|||||||
-- @return true/false, depending on whether user can authenticate with given key
|
-- @return true/false, depending on whether user can authenticate with given key
|
||||||
function publickey_canauth(session, username, publickeydata)
|
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.
|
-- terminal mode.
|
||||||
-- @param session Authenticated libssh2 session
|
-- @param session Authenticated libssh2 session
|
||||||
|
-- @param no_pty If true, skip requesting a PTY.
|
||||||
-- @return libssh2 channel
|
-- @return libssh2 channel
|
||||||
function open_channel(session)
|
function open_channel(session, pty)
|
||||||
|
|
||||||
--- Reads data from stdin on libssh2 channel.
|
--- Reads data from stdin on libssh2 channel.
|
||||||
-- @param session Authenticated libssh2 session
|
-- @param session Authenticated libssh2 session
|
||||||
|
|||||||
Reference in New Issue
Block a user