Commit 3c9ab553 authored by nextime's avatar nextime

Add configuration file support for wsssh and wsscp

- Added INI-formatted config file ~/.config/wsssh/wsssh.conf
- Default port and domain settings for both Python and C implementations
- Command line arguments take precedence over config file
- Enhanced hostname parsing with config-based defaults
- Updated documentation and version to 1.3.0
- Updated Debian package version to 1.3.0-1
parent e91872f7
...@@ -5,6 +5,29 @@ All notable changes to this project will be documented in this file. ...@@ -5,6 +5,29 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.3.0] - 2025-09-13
### Added
- **Configuration File Support**: Added INI-formatted config file `~/.config/wsssh/wsssh.conf`
- Default port and domain settings for wsssh and wsscp
- Command line arguments take precedence over config file
- Domain fallback to config when not specified in command line
- Port fallback to config when not specified via -p/-P options
- **Enhanced CLI Flexibility**: Improved hostname parsing with config-based defaults
- Support for `user@client` format using config domain
- Support for `user@client.domain` format overriding config domain
- Automatic port resolution: command line > config file > error
### Changed
- **Port Precedence**: Command line `-p`/`-P` options override config file port
- **Domain Precedence**: Command line domain specification overrides config domain
- **Error Handling**: Better error messages when port/domain cannot be determined
### Technical Details
- **Config File Format**: Simple INI format with `[default]` section
- **Cross-Implementation**: Consistent behavior between Python and C versions
- **Backward Compatibility**: All existing functionality preserved
## [1.2.0] - 2025-09-13 ## [1.2.0] - 2025-09-13
### Changed ### Changed
......
...@@ -295,6 +295,29 @@ wsscp [SCP_OPTIONS...] SOURCE... DESTINATION ...@@ -295,6 +295,29 @@ wsscp [SCP_OPTIONS...] SOURCE... DESTINATION
## Configuration ## Configuration
### Config File Configuration
WebSocket SSH supports an optional INI-formatted configuration file at `~/.config/wsssh/wsssh.conf`:
```ini
[default]
port=8080
domain=example.com
```
**Configuration Options:**
- `port`: Default WebSocket server port (used when not specified via `-p`/`-P` options)
- `domain`: Default domain suffix (used when hostname doesn't include domain)
**Precedence Rules:**
- **Port**: Command line `-p`/`-P` options override config file, config file overrides default (22)
- **Domain**: Command line domain (e.g., `user@client.domain`) overrides config domain, config domain overrides localhost
**File Location:**
- **Path**: `~/.config/wsssh/wsssh.conf`
- **Format**: Standard INI format with `[default]` section
- **Permissions**: Readable by the user running wsssh/wsscp
### SSL Certificate Configuration ### SSL Certificate Configuration
The system uses SSL/TLS certificates for WebSocket encryption: The system uses SSL/TLS certificates for WebSocket encryption:
......
...@@ -160,24 +160,29 @@ This automatically: ...@@ -160,24 +160,29 @@ This automatically:
## Hostname Format ## Hostname Format
The system uses intelligent hostname parsing: The system uses intelligent hostname parsing with config file support:
``` ```
<CLIENT_ID>.<WSSSHD_HOST> <CLIENT_ID>.<WSSSHD_HOST>
``` ```
Port is specified using `-p` (SSH) or `-P` (SCP) options. **Supported Formats:**
- `user@client.domain` - Full specification with domain
- `user@client` - Uses domain from config file or defaults to localhost
Port is specified using `-p` (SSH) or `-P` (SCP) options, or from config file.
### Examples: ### Examples:
- `remote.example.com -p 9898` → Client: `remote`, Server: `example.com:9898` - `remote.example.com -p 9898` → Client: `remote`, Server: `example.com:9898`
- `server.datacenter.com -P 2222` → Client: `server`, Server: `datacenter.com:2222` - `server.datacenter.com -P 2222` → Client: `server`, Server: `datacenter.com:2222`
- `test.localhost -p 8080` → Client: `test`, Server: `localhost:8080` - `test.localhost -p 8080` → Client: `test`, Server: `localhost:8080`
- `myclient` (with config domain `example.com`) → Client: `myclient`, Server: `example.com:<config_port>`
## Port Detection Priority ## Port Detection Priority
1. **Hostname suffix**: `host:port` in the target hostname 1. **Command line option**: `-p <port>` (SSH) or `-P <port>` (SCP)
2. **SSH/SCP port option**: `-p <port>` (SSH) or `-P <port>` (SCP) 2. **Config file**: `port` setting in `~/.config/wsssh/wsssh.conf`
3. **Default**: `22` (standard SSH port) 3. **Default**: `22` (standard SSH port)
## Detailed Usage ## Detailed Usage
...@@ -230,12 +235,15 @@ When `--web-host` and `--web-port` are specified, a web management interface is ...@@ -230,12 +235,15 @@ When `--web-host` and `--web-port` are specified, a web management interface is
**Examples:** **Examples:**
```bash ```bash
# Basic SSH connection # Basic SSH connection with explicit port and domain
./wsssh -p 9898 user@myclient.example.com ./wsssh -p 9898 user@myclient.example.com
# SSH with custom port # SSH with custom port
./wsssh -p 2222 user@myclient.example.com ./wsssh -p 2222 user@myclient.example.com
# SSH using config file defaults
./wsssh user@myclient
# SSH with options # SSH with options
./wsssh -p 9898 -i ~/.ssh/key user@myclient.example.com ls -la ./wsssh -p 9898 -i ~/.ssh/key user@myclient.example.com ls -la
``` ```
...@@ -252,18 +260,51 @@ When `--web-host` and `--web-port` are specified, a web management interface is ...@@ -252,18 +260,51 @@ When `--web-host` and `--web-port` are specified, a web management interface is
**Examples:** **Examples:**
```bash ```bash
# Copy file to remote # Copy file to remote with explicit port and domain
./wsscp -P 9898 localfile user@myclient.example.com:/remote/path/ ./wsscp -P 9898 localfile user@myclient.example.com:/remote/path/
# Copy file from remote # Copy file from remote
./wsscp -P 9898 user@myclient.example.com:/remote/file ./localfile ./wsscp -P 9898 user@myclient.example.com:/remote/file ./localfile
# Copy using config file defaults
./wsscp localfile user@myclient:/remote/path/
# Copy with custom port # Copy with custom port
./wsscp -P 2222 localfile user@myclient.example.com:/remote/path/ ./wsscp -P 2222 localfile user@myclient.example.com:/remote/path/
``` ```
## Configuration ## Configuration
### Config File
WebSocket SSH supports an optional INI-formatted configuration file at `~/.config/wsssh/wsssh.conf`:
```ini
[default]
port=8080
domain=example.com
```
**Configuration Options:**
- `port`: Default WebSocket server port (used when not specified via `-p`/`-P` options)
- `domain`: Default domain suffix (used when hostname doesn't include domain)
**Precedence Rules:**
- **Port**: Command line `-p`/`-P` options override config file, config file overrides default (22)
- **Domain**: Command line domain (e.g., `user@client.domain`) overrides config domain, config domain overrides localhost
**Examples:**
```bash
# Uses config port 8080 and domain example.com
./wsssh user@myclient
# Uses command line port 2222, config domain example.com
./wsssh -p 2222 user@myclient
# Uses command line port 2222 and domain mydomain.com
./wsssh -p 2222 user@myclient.mydomain.com
```
### SSL Certificates ### SSL Certificates
The system uses self-signed SSL certificates for WebSocket encryption. Certificates are automatically generated during the build process if they don't exist. The system uses self-signed SSL certificates for WebSocket encryption. Certificates are automatically generated during the build process if they don't exist.
......
...@@ -28,6 +28,8 @@ import socket ...@@ -28,6 +28,8 @@ import socket
import subprocess import subprocess
import sys import sys
import uuid import uuid
import configparser
import os
debug = False debug = False
...@@ -164,7 +166,7 @@ async def run_scp(server_ip, server_port, client_id, local_port, scp_args): ...@@ -164,7 +166,7 @@ async def run_scp(server_ip, server_port, client_id, local_port, scp_args):
return 0 return 0
def parse_hostname(hostname): def parse_hostname(hostname, config_domain=None):
"""Parse hostname to extract CLIENT_ID and WSSSHD_HOST""" """Parse hostname to extract CLIENT_ID and WSSSHD_HOST"""
# Split by dots to get client_id and wssshd_host # Split by dots to get client_id and wssshd_host
parts = hostname.split('.') parts = hostname.split('.')
...@@ -174,11 +176,27 @@ def parse_hostname(hostname): ...@@ -174,11 +176,27 @@ def parse_hostname(hostname):
else: else:
# No domain, assume whole hostname is client_id # No domain, assume whole hostname is client_id
client_id = hostname client_id = hostname
wssshd_host = 'localhost' # Default fallback wssshd_host = config_domain if config_domain else 'localhost' # Default fallback
return client_id, wssshd_host return client_id, wssshd_host
def main(): def main():
# Read config file
config = configparser.ConfigParser()
config_file = os.path.expanduser("~/.config/wsssh/wsssh.conf")
config_port = None
config_domain = None
if os.path.exists(config_file):
config.read(config_file)
if 'default' in config:
if 'port' in config['default']:
try:
config_port = int(config['default']['port'])
except ValueError:
pass
if 'domain' in config['default']:
config_domain = config['default']['domain']
parser = argparse.ArgumentParser(description='WebSocket SCP (wsscp)', add_help=False) parser = argparse.ArgumentParser(description='WebSocket SCP (wsscp)', add_help=False)
parser.add_argument('--local-port', type=int, default=0, help='Local port for tunnel (0 = auto)') parser.add_argument('--local-port', type=int, default=0, help='Local port for tunnel (0 = auto)')
parser.add_argument('--debug', action='store_true', help='Enable debug output') parser.add_argument('--debug', action='store_true', help='Enable debug output')
...@@ -215,14 +233,17 @@ def main(): ...@@ -215,14 +233,17 @@ def main():
sys.exit(1) sys.exit(1)
if not scp_port: if not scp_port:
print("Error: Could not determine wssshd port from -P option") if config_port:
scp_port = config_port
else:
print("Error: Could not determine wssshd port from -P option or config file")
sys.exit(1) sys.exit(1)
# Use the first host for parsing # Use the first host for parsing
host = hosts[0] host = hosts[0]
# Parse hostname to extract client_id and wssshd_host # Parse hostname to extract client_id and wssshd_host
client_id, wssshd_host = parse_hostname(host) client_id, wssshd_host = parse_hostname(host, config_domain)
if debug: if debug:
print(f"[DEBUG] Hosts: {hosts}") print(f"[DEBUG] Hosts: {hosts}")
......
...@@ -28,6 +28,8 @@ import socket ...@@ -28,6 +28,8 @@ import socket
import subprocess import subprocess
import sys import sys
import uuid import uuid
import configparser
import os
debug = False debug = False
...@@ -164,7 +166,7 @@ async def run_ssh(server_ip, server_port, client_id, local_port, ssh_args): ...@@ -164,7 +166,7 @@ async def run_ssh(server_ip, server_port, client_id, local_port, ssh_args):
return 0 return 0
def parse_hostname(hostname): def parse_hostname(hostname, config_domain=None):
"""Parse hostname to extract CLIENT_ID and WSSSHD_HOST""" """Parse hostname to extract CLIENT_ID and WSSSHD_HOST"""
# Split by dots to get client_id and wssshd_host # Split by dots to get client_id and wssshd_host
parts = hostname.split('.') parts = hostname.split('.')
...@@ -174,11 +176,27 @@ def parse_hostname(hostname): ...@@ -174,11 +176,27 @@ def parse_hostname(hostname):
else: else:
# No domain, assume whole hostname is client_id # No domain, assume whole hostname is client_id
client_id = hostname client_id = hostname
wssshd_host = 'localhost' # Default fallback wssshd_host = config_domain if config_domain else 'localhost' # Default fallback
return client_id, wssshd_host return client_id, wssshd_host
def main(): def main():
# Read config file
config = configparser.ConfigParser()
config_file = os.path.expanduser("~/.config/wsssh/wsssh.conf")
config_port = None
config_domain = None
if os.path.exists(config_file):
config.read(config_file)
if 'default' in config:
if 'port' in config['default']:
try:
config_port = int(config['default']['port'])
except ValueError:
pass
if 'domain' in config['default']:
config_domain = config['default']['domain']
parser = argparse.ArgumentParser(description='WebSocket SSH (wsssh)', add_help=False) parser = argparse.ArgumentParser(description='WebSocket SSH (wsssh)', add_help=False)
parser.add_argument('--local-port', type=int, default=0, help='Local port for tunnel (0 = auto)') parser.add_argument('--local-port', type=int, default=0, help='Local port for tunnel (0 = auto)')
parser.add_argument('--debug', action='store_true', help='Enable debug output') parser.add_argument('--debug', action='store_true', help='Enable debug output')
...@@ -218,11 +236,14 @@ def main(): ...@@ -218,11 +236,14 @@ def main():
sys.exit(1) sys.exit(1)
if not ssh_port: if not ssh_port:
print("Error: Could not determine wssshd port from -p option") if config_port:
ssh_port = config_port
else:
print("Error: Could not determine wssshd port from -p option or config file")
sys.exit(1) sys.exit(1)
# Parse hostname to extract client_id and wssshd_host # Parse hostname to extract client_id and wssshd_host
client_id, wssshd_host = parse_hostname(host) client_id, wssshd_host = parse_hostname(host, config_domain)
if debug: if debug:
print(f"[DEBUG] Host: {host}") print(f"[DEBUG] Host: {host}")
......
wsssh-tools (1.3.0-1) unstable; urgency=medium
* Version 1.3.0: Added configuration file support
* Added INI-formatted config file ~/.config/wsssh/wsssh.conf
* Default port and domain settings for wsssh and wsscp
* Command line arguments take precedence over config file
* Enhanced hostname parsing with config-based defaults
-- Stefy Lanza <stefy@nexlab.net> Fri, 13 Sep 2025 15:41:00 +0200
wsssh-tools (1.0.0-1) unstable; urgency=medium wsssh-tools (1.0.0-1) unstable; urgency=medium
* Initial release of WebSocket SSH Tools C implementation * Initial release of WebSocket SSH Tools C implementation
......
...@@ -39,6 +39,27 @@ ...@@ -39,6 +39,27 @@
#define DEFAULT_PORT 22 #define DEFAULT_PORT 22
#define INITIAL_FRAME_BUFFER_SIZE 8192 #define INITIAL_FRAME_BUFFER_SIZE 8192
char *read_config_value(const char *key) {
char *home = getenv("HOME");
if (!home) return NULL;
char path[PATH_MAX];
snprintf(path, sizeof(path), "%s/.config/wsssh/wsssh.conf", home);
FILE *f = fopen(path, "r");
if (!f) return NULL;
char line[256];
while (fgets(line, sizeof(line), f)) {
if (strncmp(line, key, strlen(key)) == 0 && line[strlen(key)] == '=') {
char *value = strdup(line + strlen(key) + 1);
// remove newline
value[strcspn(value, "\n")] = 0;
fclose(f);
return value;
}
}
fclose(f);
return NULL;
}
typedef struct { typedef struct {
char *local_port; char *local_port;
int debug; int debug;
...@@ -134,7 +155,7 @@ int parse_args(int argc, char *argv[], wsscp_config_t *config, int *remaining_ar ...@@ -134,7 +155,7 @@ int parse_args(int argc, char *argv[], wsscp_config_t *config, int *remaining_ar
return 1; return 1;
} }
int parse_hostname(const char *hostname, char **client_id, char **wssshd_host) { int parse_hostname(const char *hostname, char **client_id, char **wssshd_host, const char *config_domain) {
char *colon_pos = strchr(hostname, ':'); char *colon_pos = strchr(hostname, ':');
if (!colon_pos) { if (!colon_pos) {
fprintf(stderr, "Error: Invalid hostname format. Expected user@host: or host:\n"); fprintf(stderr, "Error: Invalid hostname format. Expected user@host: or host:\n");
...@@ -157,20 +178,25 @@ int parse_hostname(const char *hostname, char **client_id, char **wssshd_host) { ...@@ -157,20 +178,25 @@ int parse_hostname(const char *hostname, char **client_id, char **wssshd_host) {
char *dot_pos = strchr(actual_host, '.'); char *dot_pos = strchr(actual_host, '.');
if (!dot_pos) { if (!dot_pos) {
fprintf(stderr, "Error: Invalid hostname format. Expected client.domain format\n"); // No domain, use config
if (!config_domain) {
fprintf(stderr, "Error: Invalid hostname format. Expected client.domain format or domain in config\n");
free(host_part); free(host_part);
return 0; return 0;
} }
*client_id = strdup(actual_host);
*wssshd_host = strdup(config_domain);
} else {
*dot_pos = '\0'; *dot_pos = '\0';
*client_id = strdup(actual_host); *client_id = strdup(actual_host);
*wssshd_host = strdup(dot_pos + 1); *wssshd_host = strdup(dot_pos + 1);
}
free(host_part); free(host_part);
return 1; return 1;
} }
int parse_scp_args(int argc, char *argv[], char **destination, int *scp_port, int debug) { int parse_scp_args(int argc, char *argv[], char **destination, int *scp_port, int config_port, int debug) {
*destination = NULL; *destination = NULL;
*scp_port = DEFAULT_PORT; *scp_port = DEFAULT_PORT;
...@@ -203,6 +229,11 @@ int parse_scp_args(int argc, char *argv[], char **destination, int *scp_port, in ...@@ -203,6 +229,11 @@ int parse_scp_args(int argc, char *argv[], char **destination, int *scp_port, in
return 0; return 0;
} }
// If no port found in args, use config
if (*scp_port == DEFAULT_PORT && config_port != 0) {
*scp_port = config_port;
}
return 1; return 1;
} }
...@@ -1023,6 +1054,12 @@ int setup_tunnel(const char *wssshd_host, int wssshd_port, const char *client_id ...@@ -1023,6 +1054,12 @@ int setup_tunnel(const char *wssshd_host, int wssshd_port, const char *client_id
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
// Read config
char *config_port_str = read_config_value("port");
int config_port = config_port_str ? atoi(config_port_str) : 0;
free(config_port_str);
char *config_domain = read_config_value("domain");
wsscp_config_t config = { wsscp_config_t config = {
.local_port = NULL, .local_port = NULL,
.debug = 0 .debug = 0
...@@ -1031,6 +1068,7 @@ int main(int argc, char *argv[]) { ...@@ -1031,6 +1068,7 @@ int main(int argc, char *argv[]) {
// Easter egg: --support option (only when it's the only argument) // Easter egg: --support option (only when it's the only argument)
if (argc == 2 && strcmp(argv[1], "--support") == 0) { if (argc == 2 && strcmp(argv[1], "--support") == 0) {
print_trans_flag(); print_trans_flag();
free(config_domain);
return 0; return 0;
} }
...@@ -1038,6 +1076,7 @@ int main(int argc, char *argv[]) { ...@@ -1038,6 +1076,7 @@ int main(int argc, char *argv[]) {
for (int i = 1; i < argc; i++) { for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) { if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) {
print_usage(argv[0]); print_usage(argv[0]);
free(config_domain);
return 0; return 0;
} }
} }
...@@ -1049,6 +1088,7 @@ int main(int argc, char *argv[]) { ...@@ -1049,6 +1088,7 @@ int main(int argc, char *argv[]) {
char **remaining_argv; char **remaining_argv;
if (!parse_args(argc, argv, &config, &remaining_argc, &remaining_argv)) { if (!parse_args(argc, argv, &config, &remaining_argc, &remaining_argv)) {
pthread_mutex_destroy(&tunnel_mutex); pthread_mutex_destroy(&tunnel_mutex);
free(config_domain);
return 1; return 1;
} }
...@@ -1063,8 +1103,9 @@ int main(int argc, char *argv[]) { ...@@ -1063,8 +1103,9 @@ int main(int argc, char *argv[]) {
// Parse SCP arguments to extract destination and port // Parse SCP arguments to extract destination and port
char *scp_destination = NULL; char *scp_destination = NULL;
int scp_port = DEFAULT_PORT; int scp_port = DEFAULT_PORT;
if (!parse_scp_args(remaining_argc, remaining_argv, &scp_destination, &scp_port, config.debug)) { if (!parse_scp_args(remaining_argc, remaining_argv, &scp_destination, &scp_port, config_port, config.debug)) {
pthread_mutex_destroy(&tunnel_mutex); pthread_mutex_destroy(&tunnel_mutex);
free(config_domain);
return 1; return 1;
} }
...@@ -1073,8 +1114,9 @@ int main(int argc, char *argv[]) { ...@@ -1073,8 +1114,9 @@ int main(int argc, char *argv[]) {
char *wssshd_host = NULL; char *wssshd_host = NULL;
int wssshd_port = scp_port; // The -P port becomes the WebSocket server port int wssshd_port = scp_port; // The -P port becomes the WebSocket server port
if (!parse_hostname(scp_destination, &client_id, &wssshd_host)) { if (!parse_hostname(scp_destination, &client_id, &wssshd_host, config_domain)) {
pthread_mutex_destroy(&tunnel_mutex); pthread_mutex_destroy(&tunnel_mutex);
free(config_domain);
return 1; return 1;
} }
...@@ -1581,6 +1623,7 @@ cleanup: ...@@ -1581,6 +1623,7 @@ cleanup:
} }
} }
free(new_scp_args); free(new_scp_args);
free(config_domain);
pthread_mutex_destroy(&tunnel_mutex); pthread_mutex_destroy(&tunnel_mutex);
return 0; return 0;
......
...@@ -37,6 +37,27 @@ ...@@ -37,6 +37,27 @@
#define BUFFER_SIZE 1048576 #define BUFFER_SIZE 1048576
#define DEFAULT_PORT 22 #define DEFAULT_PORT 22
char *read_config_value(const char *key) {
char *home = getenv("HOME");
if (!home) return NULL;
char path[PATH_MAX];
snprintf(path, sizeof(path), "%s/.config/wsssh/wsssh.conf", home);
FILE *f = fopen(path, "r");
if (!f) return NULL;
char line[256];
while (fgets(line, sizeof(line), f)) {
if (strncmp(line, key, strlen(key)) == 0 && line[strlen(key)] == '=') {
char *value = strdup(line + strlen(key) + 1);
// remove newline
value[strcspn(value, "\n")] = 0;
fclose(f);
return value;
}
}
fclose(f);
return NULL;
}
typedef struct { typedef struct {
char *local_port; char *local_port;
int debug; int debug;
...@@ -168,7 +189,7 @@ int parse_args(int argc, char *argv[], wsssh_config_t *config, int *remaining_ar ...@@ -168,7 +189,7 @@ int parse_args(int argc, char *argv[], wsssh_config_t *config, int *remaining_ar
return 1; return 1;
} }
int parse_hostname(const char *hostname, char **client_id, char **wssshd_host) { int parse_hostname(const char *hostname, char **client_id, char **wssshd_host, const char *config_domain) {
char *at_pos = strchr(hostname, '@'); char *at_pos = strchr(hostname, '@');
if (!at_pos) { if (!at_pos) {
fprintf(stderr, "Error: Invalid hostname format. Expected user@host\n"); fprintf(stderr, "Error: Invalid hostname format. Expected user@host\n");
...@@ -190,20 +211,25 @@ int parse_hostname(const char *hostname, char **client_id, char **wssshd_host) { ...@@ -190,20 +211,25 @@ int parse_hostname(const char *hostname, char **client_id, char **wssshd_host) {
// Split host by dots to extract client_id // Split host by dots to extract client_id
char *dot_pos = strchr(host_copy, '.'); char *dot_pos = strchr(host_copy, '.');
if (!dot_pos) { if (!dot_pos) {
fprintf(stderr, "Error: Invalid hostname format. Expected client.domain format\n"); // No domain, use config
if (!config_domain) {
fprintf(stderr, "Error: Invalid hostname format. Expected client.domain format or domain in config\n");
free(host_copy); free(host_copy);
return 0; return 0;
} }
*client_id = strdup(host_copy);
*wssshd_host = strdup(config_domain);
} else {
*dot_pos = '\0'; *dot_pos = '\0';
*client_id = strdup(host_copy); *client_id = strdup(host_copy);
*wssshd_host = strdup(dot_pos + 1); *wssshd_host = strdup(dot_pos + 1);
}
free(host_copy); free(host_copy);
return 1; return 1;
} }
int parse_ssh_args(int argc, char *argv[], char **host, int *ssh_port, int debug) { int parse_ssh_args(int argc, char *argv[], char **host, int *ssh_port, int config_port, int debug) {
*host = NULL; *host = NULL;
*ssh_port = DEFAULT_PORT; *ssh_port = DEFAULT_PORT;
...@@ -234,6 +260,11 @@ int parse_ssh_args(int argc, char *argv[], char **host, int *ssh_port, int debug ...@@ -234,6 +260,11 @@ int parse_ssh_args(int argc, char *argv[], char **host, int *ssh_port, int debug
return 0; return 0;
} }
// If no port found in args, use config
if (*ssh_port == DEFAULT_PORT && config_port != 0) {
*ssh_port = config_port;
}
return 1; return 1;
} }
...@@ -905,6 +936,12 @@ int setup_tunnel(const char *wssshd_host, int wssshd_port, const char *client_id ...@@ -905,6 +936,12 @@ int setup_tunnel(const char *wssshd_host, int wssshd_port, const char *client_id
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
// Read config
char *config_port_str = read_config_value("port");
int config_port = config_port_str ? atoi(config_port_str) : 0;
free(config_port_str);
char *config_domain = read_config_value("domain");
wsssh_config_t config = { wsssh_config_t config = {
.local_port = NULL, .local_port = NULL,
.debug = 0 .debug = 0
...@@ -913,6 +950,7 @@ int main(int argc, char *argv[]) { ...@@ -913,6 +950,7 @@ int main(int argc, char *argv[]) {
// Easter egg: --support option (only when it's the only argument) // Easter egg: --support option (only when it's the only argument)
if (argc == 2 && strcmp(argv[1], "--support") == 0) { if (argc == 2 && strcmp(argv[1], "--support") == 0) {
print_trans_flag(); print_trans_flag();
free(config_domain);
return 0; return 0;
} }
...@@ -920,6 +958,7 @@ int main(int argc, char *argv[]) { ...@@ -920,6 +958,7 @@ int main(int argc, char *argv[]) {
for (int i = 1; i < argc; i++) { for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) { if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) {
print_usage(argv[0]); print_usage(argv[0]);
free(config_domain);
return 0; return 0;
} }
} }
...@@ -931,6 +970,7 @@ int main(int argc, char *argv[]) { ...@@ -931,6 +970,7 @@ int main(int argc, char *argv[]) {
char **remaining_argv; char **remaining_argv;
if (!parse_args(argc, argv, &config, &remaining_argc, &remaining_argv)) { if (!parse_args(argc, argv, &config, &remaining_argc, &remaining_argv)) {
pthread_mutex_destroy(&tunnel_mutex); pthread_mutex_destroy(&tunnel_mutex);
free(config_domain);
return 1; return 1;
} }
...@@ -945,8 +985,9 @@ int main(int argc, char *argv[]) { ...@@ -945,8 +985,9 @@ int main(int argc, char *argv[]) {
// Parse SSH arguments to extract host and port // Parse SSH arguments to extract host and port
char *ssh_host = NULL; char *ssh_host = NULL;
int ssh_port = DEFAULT_PORT; int ssh_port = DEFAULT_PORT;
if (!parse_ssh_args(remaining_argc, remaining_argv, &ssh_host, &ssh_port, config.debug)) { if (!parse_ssh_args(remaining_argc, remaining_argv, &ssh_host, &ssh_port, config_port, config.debug)) {
pthread_mutex_destroy(&tunnel_mutex); pthread_mutex_destroy(&tunnel_mutex);
free(config_domain);
return 1; return 1;
} }
...@@ -955,8 +996,9 @@ int main(int argc, char *argv[]) { ...@@ -955,8 +996,9 @@ int main(int argc, char *argv[]) {
char *wssshd_host = NULL; char *wssshd_host = NULL;
int wssshd_port = ssh_port; // The -p port becomes the WebSocket server port int wssshd_port = ssh_port; // The -p port becomes the WebSocket server port
if (!parse_hostname(ssh_host, &client_id, &wssshd_host)) { if (!parse_hostname(ssh_host, &client_id, &wssshd_host, config_domain)) {
pthread_mutex_destroy(&tunnel_mutex); pthread_mutex_destroy(&tunnel_mutex);
free(config_domain);
return 1; return 1;
} }
...@@ -1341,6 +1383,7 @@ int main(int argc, char *argv[]) { ...@@ -1341,6 +1383,7 @@ int main(int argc, char *argv[]) {
} }
} }
free(new_ssh_args); free(new_ssh_args);
free(config_domain);
pthread_mutex_destroy(&tunnel_mutex); pthread_mutex_destroy(&tunnel_mutex);
return 0; return 0;
......
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