diff --git a/README.md b/README.md index 0ecf560..0388fdd 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ The `noxssh` executable is produced in `bin/` (or `build/bin/` depending on your ### Usage ```text -Usage: noxssh [-h] [-d|-dd|-ddd] [-p port] [-w password] [user@]host [command] +Usage: noxssh [-h] [-d|-dd|-ddd] [-T] [-p port] [-w password] [user@]host [command] ``` | Example | Description | @@ -59,8 +59,9 @@ Usage: noxssh [-h] [-d|-dd|-ddd] [-p port] [-w password] [user@]host [command] | `noxssh user@example.com "uname -a"` | Run a single command and exit | | `noxssh -d user@example.com` | Basic debug logging | | `noxssh -ddd user@example.com` | Packet-level debug logging | +| `noxssh -T user@example.com` | Request shell without PTY allocation | -If `user@` is omitted, the default username is `user`. You are prompted for the password when using password authentication unless `-w` is provided. +If `user@` is omitted, the default username is `user`. You are prompted for the password when using password authentication unless `-w` is provided. Use `-T` to disable PTY allocation (like OpenSSH), which is useful for non-interactive/automation scenarios. --- diff --git a/client/main.c b/client/main.c index bdc173d..b56a6cc 100644 --- a/client/main.c +++ b/client/main.c @@ -53,6 +53,7 @@ typedef int app_socket_t; #endif #include "version.h" +#include "../noxtls/noxtls_version.h" #include "noxssh_common.h" /** @brief Default username when user@host is not provided. */ @@ -80,12 +81,14 @@ typedef struct static void noxssh_print_usage(const char * prog) { printf("%s " NOXSSH_VERSION_STRING "\n", (prog != NULL ? prog : "noxssh")); - printf("Usage: %s [-h] [-d|-dd|-ddd] [-p port] [-w password] [user@]host [command]\n", (prog != NULL ? prog : "noxssh")); + printf("Using NoxTLS Library %s\n", NOXTLS_VERSION_STRING); + printf("Usage: %s [-h] [-d|-dd|-ddd] [-T] [-p port] [-w password] [user@]host [command]\n", (prog != NULL ? prog : "noxssh")); printf("Options:\n"); printf(" -h, --help Show this help and exit.\n"); printf(" -d Enable basic SSH debug output.\n"); printf(" -dd Enable verbose SSH debug output.\n"); printf(" -ddd Enable packet-level SSH debug output.\n"); + printf(" -T Disable PTY allocation for shell sessions.\n"); printf(" -p port SSH server port (default: 22).\n"); printf(" -w password Password (avoid on command line in production).\n"); printf("Examples:\n"); @@ -514,6 +517,7 @@ int main(int argc, char ** argv) char password[NOXSSH_MAX_PASSWORD_LEN + 1u]; int password_set = 0; int command_set = 0; + int request_pty = 1; int debug_level = 0; int i = 0; noxssh_conn_t conn; @@ -589,6 +593,11 @@ int main(int argc, char ** argv) continue; } + if(strcmp(argv[i], "-T") == 0) { + request_pty = 0; + continue; + } + if(strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) { noxssh_print_usage(argv[0]); #ifdef _WIN32 @@ -778,7 +787,7 @@ int main(int argc, char ** argv) } noxssh_print_channel_output(&client); } else { - rc = netnox_ssh_client_request_shell(&client); + rc = netnox_ssh_client_request_shell_ex(&client, (uint8_t)request_pty); if(rc != NETNOX_RETURN_SUCCESS) { printf("ERROR: Failed to request remote shell.\n"); (void)netnox_ssh_client_close(&client); diff --git a/client/version.h b/client/version.h index d081863..e83f60c 100644 --- a/client/version.h +++ b/client/version.h @@ -14,9 +14,9 @@ /** @brief Minor version number. */ #define NOXSSH_VERSION_MINOR 1 /** @brief Patch version number. */ -#define NOXSSH_VERSION_PATCH 2 +#define NOXSSH_VERSION_PATCH 10 /** @brief Version string for display (e.g. "0.1.0"). */ -#define NOXSSH_VERSION_STRING "0.1.2" +#define NOXSSH_VERSION_STRING "0.1.10" #endif /* NOXSSH_VERSION_H */ diff --git a/common/noxssh_common.c b/common/noxssh_common.c index f6076eb..34d74ac 100644 --- a/common/noxssh_common.c +++ b/common/noxssh_common.c @@ -2153,7 +2153,8 @@ netnox_return_t netnox_ssh_client_exec(netnox_ssh_client_t * client, const char return NETNOX_RETURN_SUCCESS; } -netnox_return_t netnox_ssh_client_request_shell(netnox_ssh_client_t * client) +netnox_return_t netnox_ssh_client_request_shell_ex(netnox_ssh_client_t * client, + uint8_t request_pty) { uint8_t payload[512]; uint32_t payload_len = 0u; @@ -2171,62 +2172,66 @@ netnox_return_t netnox_ssh_client_request_shell(netnox_ssh_client_t * client) return NETNOX_RETURN_BAD_PARAM; } - /* Ask server for a PTY so shell behaves interactively (prompts/line editing). */ - payload_len = 0u; - if(netnox_ssh_payload_append_u8(payload, &payload_len, (uint32_t)sizeof(payload), NETNOX_SSH_MSG_CHANNEL_REQUEST) != NETNOX_RETURN_SUCCESS) { - return NETNOX_RETURN_FAILED; - } - if(netnox_ssh_payload_append_u32(payload, &payload_len, (uint32_t)sizeof(payload), client->remote_channel_id) != NETNOX_RETURN_SUCCESS) { - return NETNOX_RETURN_FAILED; - } - if(netnox_ssh_payload_append_string(payload, &payload_len, (uint32_t)sizeof(payload), - (const uint8_t *)"pty-req", - (uint32_t)strlen("pty-req")) != NETNOX_RETURN_SUCCESS) { - return NETNOX_RETURN_FAILED; - } - if(netnox_ssh_payload_append_u8(payload, &payload_len, (uint32_t)sizeof(payload), 1u) != NETNOX_RETURN_SUCCESS) { - return NETNOX_RETURN_FAILED; - } - if(netnox_ssh_payload_append_string(payload, &payload_len, (uint32_t)sizeof(payload), - (const uint8_t *)"xterm-256color", - (uint32_t)strlen("xterm-256color")) != NETNOX_RETURN_SUCCESS) { - return NETNOX_RETURN_FAILED; - } - if(netnox_ssh_payload_append_u32(payload, &payload_len, (uint32_t)sizeof(payload), 80u) != NETNOX_RETURN_SUCCESS) { - return NETNOX_RETURN_FAILED; - } - if(netnox_ssh_payload_append_u32(payload, &payload_len, (uint32_t)sizeof(payload), 24u) != NETNOX_RETURN_SUCCESS) { - return NETNOX_RETURN_FAILED; - } - if(netnox_ssh_payload_append_u32(payload, &payload_len, (uint32_t)sizeof(payload), 0u) != NETNOX_RETURN_SUCCESS) { - return NETNOX_RETURN_FAILED; - } - if(netnox_ssh_payload_append_u32(payload, &payload_len, (uint32_t)sizeof(payload), 0u) != NETNOX_RETURN_SUCCESS) { - return NETNOX_RETURN_FAILED; - } - if(netnox_ssh_payload_append_string(payload, &payload_len, (uint32_t)sizeof(payload), NULL, 0u) != NETNOX_RETURN_SUCCESS) { - return NETNOX_RETURN_FAILED; - } - if(netnox_ssh_send_packet(client, payload, payload_len) != NETNOX_RETURN_SUCCESS) { - SSH_DEBUG("request_shell: send CHANNEL_REQUEST(pty-req) failed"); - return NETNOX_RETURN_FAILED; - } - if(netnox_ssh_wait_for_message(client, - NETNOX_SSH_MSG_CHANNEL_SUCCESS, - NETNOX_SSH_MSG_CHANNEL_FAILURE, - rsp, - (uint32_t)sizeof(rsp), - &rsp_len) != NETNOX_RETURN_SUCCESS) { - SSH_DEBUG("request_shell: wait_for_message pty-req success/failure failed"); - return NETNOX_RETURN_FAILED; - } - if(rsp_len == 0u || rsp[0] != NETNOX_SSH_MSG_CHANNEL_SUCCESS) { - SSH_DEBUG("request_shell: pty-req rejected (rsp_len=%u type=%u)", - (unsigned)rsp_len, - (unsigned)(rsp_len > 0u ? rsp[0] : 0xFFu)); - return NETNOX_RETURN_FAILED; + if(request_pty != 0u) { + /* Ask server for a PTY so shell behaves interactively (prompts/line editing). */ + payload_len = 0u; + if(netnox_ssh_payload_append_u8(payload, &payload_len, (uint32_t)sizeof(payload), NETNOX_SSH_MSG_CHANNEL_REQUEST) != NETNOX_RETURN_SUCCESS) { + return NETNOX_RETURN_FAILED; + } + if(netnox_ssh_payload_append_u32(payload, &payload_len, (uint32_t)sizeof(payload), client->remote_channel_id) != NETNOX_RETURN_SUCCESS) { + return NETNOX_RETURN_FAILED; + } + if(netnox_ssh_payload_append_string(payload, &payload_len, (uint32_t)sizeof(payload), + (const uint8_t *)"pty-req", + (uint32_t)strlen("pty-req")) != NETNOX_RETURN_SUCCESS) { + return NETNOX_RETURN_FAILED; + } + if(netnox_ssh_payload_append_u8(payload, &payload_len, (uint32_t)sizeof(payload), 1u) != NETNOX_RETURN_SUCCESS) { + return NETNOX_RETURN_FAILED; + } + if(netnox_ssh_payload_append_string(payload, &payload_len, (uint32_t)sizeof(payload), + (const uint8_t *)"xterm-256color", + (uint32_t)strlen("xterm-256color")) != NETNOX_RETURN_SUCCESS) { + return NETNOX_RETURN_FAILED; + } + if(netnox_ssh_payload_append_u32(payload, &payload_len, (uint32_t)sizeof(payload), 80u) != NETNOX_RETURN_SUCCESS) { + return NETNOX_RETURN_FAILED; + } + if(netnox_ssh_payload_append_u32(payload, &payload_len, (uint32_t)sizeof(payload), 24u) != NETNOX_RETURN_SUCCESS) { + return NETNOX_RETURN_FAILED; + } + if(netnox_ssh_payload_append_u32(payload, &payload_len, (uint32_t)sizeof(payload), 0u) != NETNOX_RETURN_SUCCESS) { + return NETNOX_RETURN_FAILED; + } + if(netnox_ssh_payload_append_u32(payload, &payload_len, (uint32_t)sizeof(payload), 0u) != NETNOX_RETURN_SUCCESS) { + return NETNOX_RETURN_FAILED; + } + if(netnox_ssh_payload_append_string(payload, &payload_len, (uint32_t)sizeof(payload), NULL, 0u) != NETNOX_RETURN_SUCCESS) { + return NETNOX_RETURN_FAILED; + } + if(netnox_ssh_send_packet(client, payload, payload_len) != NETNOX_RETURN_SUCCESS) { + SSH_DEBUG("request_shell: send CHANNEL_REQUEST(pty-req) failed"); + return NETNOX_RETURN_FAILED; + } + if(netnox_ssh_wait_for_message(client, + NETNOX_SSH_MSG_CHANNEL_SUCCESS, + NETNOX_SSH_MSG_CHANNEL_FAILURE, + rsp, + (uint32_t)sizeof(rsp), + &rsp_len) != NETNOX_RETURN_SUCCESS) { + SSH_DEBUG("request_shell: wait_for_message pty-req success/failure failed"); + return NETNOX_RETURN_FAILED; + } + if(rsp_len == 0u || rsp[0] != NETNOX_SSH_MSG_CHANNEL_SUCCESS) { + SSH_DEBUG("request_shell: pty-req rejected (rsp_len=%u type=%u)", + (unsigned)rsp_len, + (unsigned)(rsp_len > 0u ? rsp[0] : 0xFFu)); + return NETNOX_RETURN_FAILED; + } + SSH_DEBUG("request_shell: CHANNEL_REQUEST(pty-req) accepted"); + } else { + SSH_DEBUG("request_shell: PTY request disabled by caller"); } - SSH_DEBUG("request_shell: CHANNEL_REQUEST(pty-req) accepted"); payload_len = 0u; if(netnox_ssh_payload_append_u8(payload, &payload_len, (uint32_t)sizeof(payload), NETNOX_SSH_MSG_CHANNEL_REQUEST) != NETNOX_RETURN_SUCCESS) { @@ -2268,6 +2273,11 @@ netnox_return_t netnox_ssh_client_request_shell(netnox_ssh_client_t * client) return NETNOX_RETURN_SUCCESS; } +netnox_return_t netnox_ssh_client_request_shell(netnox_ssh_client_t * client) +{ + return netnox_ssh_client_request_shell_ex(client, 1u); +} + netnox_return_t netnox_ssh_client_send_data(netnox_ssh_client_t * client, const uint8_t * data, uint32_t len) diff --git a/common/noxssh_common.h b/common/noxssh_common.h index ca61898..8fbcd3e 100644 --- a/common/noxssh_common.h +++ b/common/noxssh_common.h @@ -183,6 +183,8 @@ extern netnox_return_t netnox_ssh_client_authenticate(netnox_ssh_client_t * clie extern netnox_return_t netnox_ssh_client_open_session(netnox_ssh_client_t * client); extern netnox_return_t netnox_ssh_client_exec(netnox_ssh_client_t * client, const char * command); +extern netnox_return_t netnox_ssh_client_request_shell_ex(netnox_ssh_client_t * client, + uint8_t request_pty); extern netnox_return_t netnox_ssh_client_request_shell(netnox_ssh_client_t * client); extern netnox_return_t netnox_ssh_client_send_data(netnox_ssh_client_t * client, const uint8_t * data, diff --git a/noxtls b/noxtls index d564b2f..bf6872b 160000 --- a/noxtls +++ b/noxtls @@ -1 +1 @@ -Subproject commit d564b2f6ddc921ca35b41812e3734fcd0eb94090 +Subproject commit bf6872b563ff31cecc0c1a3d35b6e31713bfb4cb