Add --pipe mode for SSH ProxyCommand support

- Add MODE_PIPE constant to wsssht.h
- Implement run_pipe_mode() function with proper tunnel negotiation
- Add --pipe and --mode pipe command line options
- Pipe mode negotiates tunnel (tunnel_request -> tunnel_ack) like other modes
- Redirects raw tunnelled data to stdin/stdout instead of binding to TCP ports
- Silent operation with no terminal output
- Compatible with SSH ProxyCommand for transparent WebSocket SSH tunneling
- Update include paths in all affected files after moving headers to libwsssht/
- Update configure.sh to generate correct makefile with new file locations
parent de71d0fc
...@@ -56,7 +56,7 @@ CFLAGS = -Wall -Wextra -O2 -D_GNU_SOURCE $(shell pkg-config --cflags openssl) ...@@ -56,7 +56,7 @@ CFLAGS = -Wall -Wextra -O2 -D_GNU_SOURCE $(shell pkg-config --cflags openssl)
LDFLAGS = $(shell pkg-config --libs openssl) LDFLAGS = $(shell pkg-config --libs openssl)
# Source files # Source files
LIB_SRCS = wssshlib.c websocket.c wssh_ssl.c tunnel.c libwsssht/utils.c libwsssht/modes.c libwsssht/threads.c LIB_SRCS = libwsssht/wssshlib.c libwsssht/websocket.c libwsssht/wssh_ssl.c libwsssht/tunnel.c libwsssht/utils.c libwsssht/modes.c libwsssht/threads.c
LIB_OBJS = $(LIB_SRCS:.c=.o) LIB_OBJS = $(LIB_SRCS:.c=.o)
SRCS = wssshc.c wsssh.c wsscp.c wsssht.c SRCS = wssshc.c wsssh.c wsscp.c wsssht.c
OBJS = $(SRCS:.c=.o) OBJS = $(SRCS:.c=.o)
...@@ -69,13 +69,13 @@ MANPAGES = man/wssshc.1 man/wsssh.1 man/wsscp.1 man/wsssht.1 ...@@ -69,13 +69,13 @@ MANPAGES = man/wssshc.1 man/wsssh.1 man/wsscp.1 man/wsssht.1
all: $(TARGETS) all: $(TARGETS)
# Individual targets # Individual targets
wssshc: wssshc.o wssshlib.o websocket.o wssh_ssl.o tunnel.o wssshc: wssshc.o libwsssht/wssshlib.o libwsssht/websocket.o libwsssht/wssh_ssl.o libwsssht/tunnel.o
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
wsssh: wsssh.o wssshlib.o websocket.o wssh_ssl.o tunnel.o wsssh: wsssh.o libwsssht/wssshlib.o libwsssht/websocket.o libwsssht/wssh_ssl.o libwsssht/tunnel.o
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
wsscp: wsscp.o wssshlib.o websocket.o wssh_ssl.o tunnel.o wsscp: wsscp.o libwsssht/wssshlib.o libwsssht/websocket.o libwsssht/wssh_ssl.o libwsssht/tunnel.o
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
wsssht: wsssht.o $(LIB_OBJS) wsssht: wsssht.o $(LIB_OBJS)
...@@ -87,7 +87,7 @@ wsssht: wsssht.o $(LIB_OBJS) ...@@ -87,7 +87,7 @@ wsssht: wsssht.o $(LIB_OBJS)
# Clean # Clean
clean: clean:
rm -f $(OBJS) $(LIB_OBJS) $(TARGETS) libwsssht/*.o rm -f $(OBJS) $(LIB_OBJS) $(TARGETS)
# Install (optional) # Install (optional)
install: all install: all
......
...@@ -35,10 +35,10 @@ ...@@ -35,10 +35,10 @@
#include <time.h> #include <time.h>
#include <errno.h> #include <errno.h>
#include "../wssshlib.h" #include "wssshlib.h"
#include "../websocket.h" #include "websocket.h"
#include "../wssh_ssl.h" #include "wssh_ssl.h"
#include "../tunnel.h" #include "tunnel.h"
#include "modes.h" #include "modes.h"
int run_bridge_mode(wsssh_config_t *config, const char *client_id, const char *wssshd_host, int wssshd_port) { int run_bridge_mode(wsssh_config_t *config, const char *client_id, const char *wssshd_host, int wssshd_port) {
...@@ -607,6 +607,446 @@ int run_script_mode(wsssh_config_t *config, const char *client_id, const char *w ...@@ -607,6 +607,446 @@ int run_script_mode(wsssh_config_t *config, const char *client_id, const char *w
return 0; return 0;
} }
int run_pipe_mode(wsssh_config_t *config, const char *client_id, const char *wssshd_host, int wssshd_port) {
// Pipe mode: Negotiate tunnel and redirect raw tunnelled data to stdin/stdout
// Similar to other modes but doesn't bind to a port - handles data directly
if (config->debug) {
printf("[DEBUG] Starting pipe mode (tunnel negotiation + stdin/stdout proxy) with client_id=%s, host=%s, port=%d\n",
client_id, wssshd_host, wssshd_port);
fflush(stdout);
}
// Establish WebSocket connection and negotiate tunnel (similar to setup_tunnel but without port binding)
struct sockaddr_in server_addr;
struct hostent *he;
int ws_sock;
SSL_CTX *ssl_ctx;
SSL *ws_ssl;
char buffer[BUFFER_SIZE];
int bytes_read;
// Generate request ID
char request_id[37];
generate_request_id(request_id, sizeof(request_id));
// Resolve hostname
if ((he = gethostbyname(wssshd_host)) == NULL) {
herror("gethostbyname");
return 1;
}
// Create socket
if ((ws_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("WebSocket socket creation failed");
return 1;
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(wssshd_port);
server_addr.sin_addr = *((struct in_addr *)he->h_addr);
// Connect to server
if (connect(ws_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("WebSocket connection failed");
close(ws_sock);
return 1;
}
// Create SSL context and connection
ssl_ctx = create_ssl_context();
if (!ssl_ctx) {
close(ws_sock);
return 1;
}
ws_ssl = create_ssl_connection(ssl_ctx, ws_sock, config->debug);
if (!ws_ssl) {
SSL_CTX_free(ssl_ctx);
close(ws_sock);
return 1;
}
// Perform WebSocket handshake
if (!websocket_handshake(ws_ssl, wssshd_host, wssshd_port, "/", config->debug)) {
fprintf(stderr, "WebSocket handshake failed\n");
SSL_free(ws_ssl);
SSL_CTX_free(ssl_ctx);
close(ws_sock);
return 1;
}
if (config->debug) {
printf("[DEBUG] WebSocket handshake successful\n");
fflush(stdout);
}
// Send tunnel request (same as setup_tunnel)
char tunnel_request_msg[1024];
char *expanded_tunnel = expand_transport_list("any", 0); // Data channel transports
char *expanded_tunnel_control = expand_transport_list("any", 1); // Control channel transports
// Select best transport based on weight (lowest weight = highest priority)
char *best_tunnel = select_best_transport(expanded_tunnel);
char *best_tunnel_control = select_best_transport(expanded_tunnel_control);
snprintf(tunnel_request_msg, sizeof(tunnel_request_msg),
"{\"type\":\"tunnel_request\",\"client_id\":\"%s\",\"request_id\":\"%s\",\"tunnel\":\"%s\",\"tunnel_control\":\"%s\",\"service\":\"ssh\"}",
client_id, request_id, best_tunnel ? best_tunnel : expanded_tunnel, best_tunnel_control ? best_tunnel_control : expanded_tunnel_control);
if (!send_websocket_frame(ws_ssl, tunnel_request_msg)) {
free(expanded_tunnel);
free(expanded_tunnel_control);
if (best_tunnel) free(best_tunnel);
if (best_tunnel_control) free(best_tunnel_control);
SSL_free(ws_ssl);
SSL_CTX_free(ssl_ctx);
close(ws_sock);
return 1;
}
free(expanded_tunnel);
free(expanded_tunnel_control);
if (best_tunnel) free(best_tunnel);
if (best_tunnel_control) free(best_tunnel_control);
if (config->debug) {
printf("[DEBUG] Tunnel request sent for client: %s, request_id: %s\n", client_id, request_id);
fflush(stdout);
}
// Read acknowledgment (same as setup_tunnel)
bytes_read = SSL_read(ws_ssl, buffer, sizeof(buffer));
if (bytes_read <= 0) {
if (config->debug) {
printf("[DEBUG] No acknowledgment received\n");
}
SSL_free(ws_ssl);
SSL_CTX_free(ssl_ctx);
close(ws_sock);
return 1;
}
// Check if it's a close frame
if (bytes_read >= 2 && (buffer[0] & 0x8F) == 0x88) {
if (config->debug) {
printf("[DEBUG] Server sent close frame\n");
}
SSL_free(ws_ssl);
SSL_CTX_free(ssl_ctx);
close(ws_sock);
return 1;
}
// Parse WebSocket frame
char *payload;
int payload_len;
if (!parse_websocket_frame(buffer, bytes_read, &payload, &payload_len)) {
fprintf(stderr, "Failed to parse WebSocket frame\n");
SSL_free(ws_ssl);
SSL_CTX_free(ssl_ctx);
close(ws_sock);
return 1;
}
// Null terminate payload
payload[payload_len] = '\0';
// Check for tunnel acknowledgment
if (strstr(payload, "tunnel_ack") == NULL) {
fprintf(stderr, "Tunnel request denied: %s\n", payload);
SSL_free(ws_ssl);
SSL_CTX_free(ssl_ctx);
close(ws_sock);
return 1;
}
if (config->debug) {
printf("[DEBUG] Tunnel negotiated successfully, request_id: %s\n", request_id);
fflush(stdout);
}
// Create tunnel structure (but don't bind to port)
tunnel_t *pipe_tunnel = malloc(sizeof(tunnel_t));
if (!pipe_tunnel) {
perror("Memory allocation failed");
SSL_free(ws_ssl);
SSL_CTX_free(ssl_ctx);
close(ws_sock);
return 1;
}
// Initialize tunnel structure for pipe mode
strcpy(pipe_tunnel->request_id, request_id);
pipe_tunnel->sock = -1; // No remote server connection
pipe_tunnel->local_sock = -1; // No local socket binding
pipe_tunnel->active = 1;
pipe_tunnel->broken = 0;
pipe_tunnel->ssl = ws_ssl;
pipe_tunnel->outgoing_buffer = NULL; // No buffering needed
pipe_tunnel->incoming_buffer = NULL; // No buffering needed
pipe_tunnel->server_version_sent = 0;
// Add tunnel to global array
pthread_mutex_lock(&tunnel_mutex);
if (!add_tunnel(pipe_tunnel)) {
free(pipe_tunnel);
pthread_mutex_unlock(&tunnel_mutex);
SSL_free(ws_ssl);
SSL_CTX_free(ssl_ctx);
close(ws_sock);
return 1;
}
pthread_mutex_unlock(&tunnel_mutex);
// Clean up SSL context (no longer needed)
SSL_CTX_free(ssl_ctx);
if (config->debug) {
printf("[DEBUG] Pipe tunnel established, starting stdin/stdout data forwarding\n");
fflush(stdout);
}
// Main pipe loop - handle stdin/stdout and WebSocket tunnel data
fd_set readfds;
struct timeval tv;
// Frame accumulation buffer for handling partial WebSocket frames
static char frame_buffer[BUFFER_SIZE * 4];
static int frame_buffer_used = 0;
while (1) {
// Check tunnel status
pthread_mutex_lock(&tunnel_mutex);
int tunnel_active = pipe_tunnel && pipe_tunnel->active;
pthread_mutex_unlock(&tunnel_mutex);
if (!tunnel_active) {
if (config->debug) {
printf("[DEBUG] Tunnel is no longer active, exiting pipe mode\n");
fflush(stdout);
}
break;
}
// Check for stdin input and WebSocket data
FD_ZERO(&readfds);
FD_SET(STDIN_FILENO, &readfds);
FD_SET(ws_sock, &readfds);
tv.tv_sec = 0;
tv.tv_usec = 50000; // 50ms timeout
int max_fd = (ws_sock > STDIN_FILENO) ? ws_sock : STDIN_FILENO;
int retval = select(max_fd + 1, &readfds, NULL, NULL, &tv);
if (retval > 0) {
// Handle stdin input (data to send to tunnel)
if (FD_ISSET(STDIN_FILENO, &readfds)) {
ssize_t bytes_read = read(STDIN_FILENO, buffer, sizeof(buffer));
if (bytes_read <= 0) {
// EOF or error on stdin
if (config->debug) {
printf("[DEBUG] EOF on stdin, sending tunnel_close\n");
fflush(stdout);
}
// Send tunnel_close before exiting
send_tunnel_close(ws_ssl, request_id, config->debug);
break;
}
// Convert raw data to hex for WebSocket tunnel_data message
size_t hex_size = (size_t)bytes_read * 2 + 1;
char *hex_data = malloc(hex_size);
if (!hex_data) {
if (config->debug) {
fprintf(stderr, "[DEBUG] Failed to allocate memory for hex data\n");
}
continue;
}
// Convert binary data to hex string
for (ssize_t i = 0; i < bytes_read; i++) {
sprintf(hex_data + i * 2, "%02x", (unsigned char)buffer[i]);
}
hex_data[bytes_read * 2] = '\0';
// Create tunnel_data message
size_t msg_size = strlen("{\"type\":\"tunnel_data\",\"request_id\":\"\",\"data\":\"\"}") +
strlen(request_id) + strlen(hex_data) + 1;
char *message = malloc(msg_size);
if (!message) {
if (config->debug) {
fprintf(stderr, "[DEBUG] Failed to allocate memory for message\n");
}
free(hex_data);
continue;
}
snprintf(message, msg_size, "{\"type\":\"tunnel_data\",\"request_id\":\"%s\",\"data\":\"%s\"}",
request_id, hex_data);
// Send message via WebSocket
if (send_websocket_frame(ws_ssl, message)) {
if (config->debug) {
printf("[DEBUG] Sent %zd bytes from stdin to tunnel\n", bytes_read);
fflush(stdout);
}
} else {
if (config->debug) {
fprintf(stderr, "[DEBUG] Failed to send WebSocket frame\n");
}
}
free(hex_data);
free(message);
}
// Handle WebSocket data (tunnel data from server)
if (FD_ISSET(ws_sock, &readfds)) {
if ((size_t)frame_buffer_used < sizeof(frame_buffer)) {
// Read WebSocket data
int ws_bytes_read = SSL_read(ws_ssl, frame_buffer + frame_buffer_used,
sizeof(frame_buffer) - frame_buffer_used);
if (ws_bytes_read > 0) {
frame_buffer_used += ws_bytes_read;
if (config->debug) {
printf("[DEBUG] Accumulated %d bytes from WebSocket\n", frame_buffer_used);
fflush(stdout);
}
// Try to parse WebSocket frame
char *payload;
int payload_len;
if (parse_websocket_frame(frame_buffer, frame_buffer_used, &payload, &payload_len)) {
// Frame is complete, determine frame type
unsigned char frame_type = frame_buffer[0] & 0x8F;
if (frame_type == 0x81 || frame_type == 0x82) { // Text or binary frame
// Copy payload to buffer for processing
if ((size_t)payload_len < sizeof(buffer)) {
memcpy(buffer, payload, payload_len);
buffer[payload_len] = '\0';
// Handle tunnel messages
if (strstr(buffer, "tunnel_data") || strstr(buffer, "tunnel_response")) {
// Extract data from tunnel message and write to stdout
char *data_start = strstr(buffer, "\"data\"");
if (data_start) {
char *colon = strchr(data_start, ':');
if (colon) {
char *open_quote = strchr(colon, '"');
if (open_quote) {
data_start = open_quote + 1;
char *data_end = strchr(data_start, '"');
if (data_end) {
*data_end = '\0';
// Convert hex data back to binary
size_t hex_len = strlen(data_start);
if (hex_len % 2 == 0) {
size_t binary_len = hex_len / 2;
char *binary_data = malloc(binary_len);
if (binary_data) {
// Convert hex to binary
for (size_t i = 0; i < binary_len; i++) {
unsigned int byte_val;
if (sscanf(data_start + i * 2, "%2x", &byte_val) == 1) {
binary_data[i] = (char)byte_val;
} else {
binary_data[i] = 0;
}
}
// Write binary data to stdout
ssize_t written = write(STDOUT_FILENO, binary_data, binary_len);
if (written > 0 && config->debug) {
printf("[DEBUG] Wrote %zd bytes to stdout\n", written);
fflush(stdout);
}
free(binary_data);
}
}
}
}
}
}
} else if (strstr(buffer, "tunnel_close")) {
// Server closed tunnel
if (config->debug) {
printf("[DEBUG] Server closed tunnel\n");
fflush(stdout);
}
break;
}
// Ignore other message types in pipe mode (silent operation)
}
} else if (frame_type == 0x88) { // Close frame
if (config->debug) {
printf("[DEBUG] WebSocket close frame received\n");
fflush(stdout);
}
break;
} else if (frame_type == 0x89) { // Ping frame
// Send pong
if (!send_pong_frame(ws_ssl, payload, payload_len)) {
if (config->debug) {
fprintf(stderr, "[DEBUG] Failed to send pong frame\n");
}
}
}
// Ignore pong frames
// Remove processed frame from buffer
int frame_size = (payload - frame_buffer) + payload_len;
if (frame_size < frame_buffer_used) {
memmove(frame_buffer, frame_buffer + frame_size, frame_buffer_used - frame_size);
frame_buffer_used -= frame_size;
} else {
frame_buffer_used = 0;
}
}
} else if (ws_bytes_read == 0) {
// Connection closed
if (config->debug) {
printf("[DEBUG] WebSocket connection closed by server\n");
fflush(stdout);
}
break;
} else {
// Error
if (config->debug) {
fprintf(stderr, "[DEBUG] WebSocket read error\n");
}
break;
}
}
}
}
// Small delay to prevent busy looping
usleep(25000); // 25ms
}
// Cleanup
close(ws_sock);
// Remove tunnel from global array
pthread_mutex_lock(&tunnel_mutex);
remove_tunnel(request_id);
pthread_mutex_unlock(&tunnel_mutex);
if (config->debug) {
printf("[DEBUG] Pipe mode ended\n");
fflush(stdout);
}
return 0;
}
typedef struct { typedef struct {
wsssh_config_t *config; wsssh_config_t *config;
const char *client_id; const char *client_id;
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
#ifndef MODES_H #ifndef MODES_H
#define MODES_H #define MODES_H
#include "../wssshlib.h" #include "wssshlib.h"
// Function declarations for mode-specific functions // Function declarations for mode-specific functions
int run_bridge_mode(wsssh_config_t *config, const char *client_id, const char *wssshd_host, int wssshd_port); int run_bridge_mode(wsssh_config_t *config, const char *client_id, const char *wssshd_host, int wssshd_port);
......
...@@ -34,10 +34,10 @@ ...@@ -34,10 +34,10 @@
#include <time.h> #include <time.h>
#include <errno.h> #include <errno.h>
#include "../wssshlib.h" #include "wssshlib.h"
#include "../websocket.h" #include "websocket.h"
#include "../wssh_ssl.h" #include "wssh_ssl.h"
#include "../tunnel.h" #include "tunnel.h"
#include "wsssht.h" #include "wsssht.h"
#include "threads.h" #include "threads.h"
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
#include <string.h> #include <string.h>
#include <getopt.h> #include <getopt.h>
#include "../wssshlib.h" #include "wssshlib.h"
#include "utils.h" #include "utils.h"
void print_usage(const char *program_name) { void print_usage(const char *program_name) {
...@@ -42,10 +42,11 @@ void print_usage(const char *program_name) { ...@@ -42,10 +42,11 @@ void print_usage(const char *program_name) {
fprintf(stderr, " --tunnel TRANSPORT Transport for data channel (comma-separated or 'any', or 'websocket' default: any)\n"); fprintf(stderr, " --tunnel TRANSPORT Transport for data channel (comma-separated or 'any', or 'websocket' default: any)\n");
fprintf(stderr, " --tunnel-control TYPES Transport types for control channel (comma-separated or 'any', default: any)\n"); fprintf(stderr, " --tunnel-control TYPES Transport types for control channel (comma-separated or 'any', default: any)\n");
fprintf(stderr, " --service SERVICE Service type (default: ssh)\n"); fprintf(stderr, " --service SERVICE Service type (default: ssh)\n");
fprintf(stderr, " --mode MODE Operating mode: interactive, silent, bridge, script (default: interactive)\n"); fprintf(stderr, " --mode MODE Operating mode: interactive, silent, bridge, script, pipe (default: interactive)\n");
fprintf(stderr, " --silent Shortcut for --mode silent\n"); fprintf(stderr, " --silent Shortcut for --mode silent\n");
fprintf(stderr, " --bridge Shortcut for --mode bridge\n"); fprintf(stderr, " --bridge Shortcut for --mode bridge\n");
fprintf(stderr, " --script Shortcut for --mode script\n"); fprintf(stderr, " --script Shortcut for --mode script\n");
fprintf(stderr, " --pipe Shortcut for --mode pipe\n");
fprintf(stderr, " --daemon Enable daemon mode for lazy initialization\n"); fprintf(stderr, " --daemon Enable daemon mode for lazy initialization\n");
fprintf(stderr, " --help Show this help\n"); fprintf(stderr, " --help Show this help\n");
fprintf(stderr, "\nExamples:\n"); fprintf(stderr, "\nExamples:\n");
...@@ -158,6 +159,8 @@ int parse_args(int argc, char *argv[], wsssh_config_t *config, int *remaining_ar ...@@ -158,6 +159,8 @@ int parse_args(int argc, char *argv[], wsssh_config_t *config, int *remaining_ar
config->mode = MODE_BRIDGE; config->mode = MODE_BRIDGE;
} else if (strcmp(argv[i + 1], "script") == 0) { } else if (strcmp(argv[i + 1], "script") == 0) {
config->mode = MODE_SCRIPT; config->mode = MODE_SCRIPT;
} else if (strcmp(argv[i + 1], "pipe") == 0) {
config->mode = MODE_PIPE;
} else { } else {
fprintf(stderr, "Error: Invalid mode: %s\n", argv[i + 1]); fprintf(stderr, "Error: Invalid mode: %s\n", argv[i + 1]);
print_usage(argv[0]); print_usage(argv[0]);
...@@ -172,6 +175,8 @@ int parse_args(int argc, char *argv[], wsssh_config_t *config, int *remaining_ar ...@@ -172,6 +175,8 @@ int parse_args(int argc, char *argv[], wsssh_config_t *config, int *remaining_ar
config->mode = MODE_BRIDGE; config->mode = MODE_BRIDGE;
} else if (strcmp(argv[i], "--script") == 0) { } else if (strcmp(argv[i], "--script") == 0) {
config->mode = MODE_SCRIPT; config->mode = MODE_SCRIPT;
} else if (strcmp(argv[i], "--pipe") == 0) {
config->mode = MODE_PIPE;
} else if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) { } else if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) {
print_usage(argv[0]); print_usage(argv[0]);
return 0; return 0;
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
#ifndef UTILS_H #ifndef UTILS_H
#define UTILS_H #define UTILS_H
#include "../wssshlib.h" #include "wssshlib.h"
// Function declarations for utility functions // Function declarations for utility functions
void print_usage(const char *program_name); void print_usage(const char *program_name);
......
...@@ -57,7 +57,8 @@ typedef enum { ...@@ -57,7 +57,8 @@ typedef enum {
MODE_INTERACTIVE = 0, // Default: current functionality MODE_INTERACTIVE = 0, // Default: current functionality
MODE_SILENT, // Same as interactive but no output MODE_SILENT, // Same as interactive but no output
MODE_BRIDGE, // JSON stdin/stdout bridge MODE_BRIDGE, // JSON stdin/stdout bridge
MODE_SCRIPT // JSON protocol for scripting MODE_SCRIPT, // JSON protocol for scripting
MODE_PIPE // ProxyCommand mode: stdin/stdout proxy
} wsssh_mode_t; } wsssh_mode_t;
// Config structures // Config structures
......
...@@ -35,10 +35,10 @@ ...@@ -35,10 +35,10 @@
#include <pthread.h> #include <pthread.h>
#include <sys/select.h> #include <sys/select.h>
#include "../wssshlib.h" #include "wssshlib.h"
#include "../websocket.h" #include "websocket.h"
#include "../wssh_ssl.h" #include "wssh_ssl.h"
#include "../tunnel.h" #include "tunnel.h"
// Thread arguments structure for concurrent tunnel handling // Thread arguments structure for concurrent tunnel handling
typedef struct { typedef struct {
...@@ -57,6 +57,7 @@ int parse_args(int argc, char *argv[], wsssh_config_t *config, int *remaining_ar ...@@ -57,6 +57,7 @@ int parse_args(int argc, char *argv[], wsssh_config_t *config, int *remaining_ar
int run_bridge_mode(wsssh_config_t *config, const char *client_id, const char *wssshd_host, int wssshd_port); int run_bridge_mode(wsssh_config_t *config, const char *client_id, const char *wssshd_host, int wssshd_port);
int run_script_mode(wsssh_config_t *config, const char *client_id, const char *wssshd_host, int wssshd_port); int run_script_mode(wsssh_config_t *config, const char *client_id, const char *wssshd_host, int wssshd_port);
int run_daemon_mode(wsssh_config_t *config, const char *client_id, const char *wssshd_host, int wssshd_port); int run_daemon_mode(wsssh_config_t *config, const char *client_id, const char *wssshd_host, int wssshd_port);
int run_pipe_mode(wsssh_config_t *config, const char *client_id, const char *wssshd_host, int wssshd_port);
void *run_tunnel_thread(void *arg); void *run_tunnel_thread(void *arg);
#endif // WSSSHT_H #endif // WSSSHT_H
\ No newline at end of file
...@@ -33,10 +33,10 @@ ...@@ -33,10 +33,10 @@
#include <errno.h> #include <errno.h>
#include <sys/select.h> #include <sys/select.h>
#include "wssshlib.h" #include "libwsssht/wssshlib.h"
#include "websocket.h" #include "libwsssht/websocket.h"
#include "wssh_ssl.h" #include "libwsssht/wssh_ssl.h"
#include "tunnel.h" #include "libwsssht/tunnel.h"
......
...@@ -32,10 +32,10 @@ ...@@ -32,10 +32,10 @@
#include <pthread.h> #include <pthread.h>
#include <sys/select.h> #include <sys/select.h>
#include "wssshlib.h" #include "libwsssht/wssshlib.h"
#include "websocket.h" #include "libwsssht/websocket.h"
#include "wssh_ssl.h" #include "libwsssht/wssh_ssl.h"
#include "tunnel.h" #include "libwsssht/tunnel.h"
......
...@@ -32,10 +32,10 @@ ...@@ -32,10 +32,10 @@
#include <signal.h> #include <signal.h>
#include <time.h> #include <time.h>
#include "wssshlib.h" #include "libwsssht/wssshlib.h"
#include "websocket.h" #include "libwsssht/websocket.h"
#include "wssh_ssl.h" #include "libwsssht/wssh_ssl.h"
#include "tunnel.h" #include "libwsssht/tunnel.h"
......
...@@ -32,10 +32,10 @@ ...@@ -32,10 +32,10 @@
#include <pthread.h> #include <pthread.h>
#include <sys/select.h> #include <sys/select.h>
#include "wssshlib.h" #include "libwsssht/wssshlib.h"
#include "websocket.h" #include "libwsssht/websocket.h"
#include "wssh_ssl.h" #include "libwsssht/wssh_ssl.h"
#include "tunnel.h" #include "libwsssht/tunnel.h"
#include "libwsssht/wsssht.h" #include "libwsssht/wsssht.h"
#include "libwsssht/utils.h" #include "libwsssht/utils.h"
...@@ -64,6 +64,8 @@ int main(int argc, char *argv[]) { ...@@ -64,6 +64,8 @@ int main(int argc, char *argv[]) {
initial_mode = MODE_BRIDGE; initial_mode = MODE_BRIDGE;
} else if (strcmp(config_mode, "script") == 0) { } else if (strcmp(config_mode, "script") == 0) {
initial_mode = MODE_SCRIPT; initial_mode = MODE_SCRIPT;
} else if (strcmp(config_mode, "pipe") == 0) {
initial_mode = MODE_PIPE;
} }
free(config_mode); free(config_mode);
} }
...@@ -203,6 +205,8 @@ int main(int argc, char *argv[]) { ...@@ -203,6 +205,8 @@ int main(int argc, char *argv[]) {
return run_bridge_mode(&config, client_id, wssshd_host, wssshd_port); return run_bridge_mode(&config, client_id, wssshd_host, wssshd_port);
} else if (config.mode == MODE_SCRIPT) { } else if (config.mode == MODE_SCRIPT) {
return run_script_mode(&config, client_id, wssshd_host, wssshd_port); return run_script_mode(&config, client_id, wssshd_host, wssshd_port);
} else if (config.mode == MODE_PIPE) {
return run_pipe_mode(&config, client_id, wssshd_host, wssshd_port);
} }
// MODE_INTERACTIVE and MODE_SILENT continue with normal flow // MODE_INTERACTIVE and MODE_SILENT continue with normal flow
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment