Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
wsssh
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexlab
wsssh
Commits
153b6344
Commit
153b6344
authored
Jan 12, 2026
by
Stefy Lanza (nextime / spora )
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add proxy functionality
parent
f8266bf1
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
187 additions
and
79 deletions
+187
-79
config.c
wssshd2/config.c
+2
-1
main.c
wssshd2/main.c
+12
-8
web.c
wssshd2/web.c
+68
-24
web_proxy.c
wssshd2/web_proxy.c
+61
-35
websocket.c
wssshd2/websocket.c
+41
-11
websocket.h
wssshd2/websocket.h
+1
-0
websocket_protocol.h
wssshd2/websocket_protocol.h
+2
-0
No files found.
wssshd2/config.c
View file @
153b6344
...
@@ -116,7 +116,8 @@ static void load_config_file(wssshd_config_t *config, const char *config_file) {
...
@@ -116,7 +116,8 @@ static void load_config_file(wssshd_config_t *config, const char *config_file) {
}
else
if
(
strcmp
(
key
,
"web-https"
)
==
0
)
{
}
else
if
(
strcmp
(
key
,
"web-https"
)
==
0
)
{
config
->
web_https
=
(
strcmp
(
value
,
"true"
)
==
0
||
strcmp
(
value
,
"1"
)
==
0
);
config
->
web_https
=
(
strcmp
(
value
,
"true"
)
==
0
||
strcmp
(
value
,
"1"
)
==
0
);
}
else
if
(
strcmp
(
key
,
"web-proxy"
)
==
0
)
{
}
else
if
(
strcmp
(
key
,
"web-proxy"
)
==
0
)
{
config
->
web_proxy_enabled
=
(
strcmp
(
value
,
"true"
)
==
0
||
strcmp
(
value
,
"1"
)
==
0
);
config
->
web_proxy_enabled
=
true
;
config
->
web_proxy_port
=
atoi
(
value
);
}
else
if
(
strcmp
(
key
,
"web-proxy-port"
)
==
0
)
{
}
else
if
(
strcmp
(
key
,
"web-proxy-port"
)
==
0
)
{
config
->
web_proxy_port
=
atoi
(
value
);
config
->
web_proxy_port
=
atoi
(
value
);
}
else
if
(
strcmp
(
key
,
"websocket-tls-only"
)
==
0
)
{
}
else
if
(
strcmp
(
key
,
"websocket-tls-only"
)
==
0
)
{
...
...
wssshd2/main.c
View file @
153b6344
...
@@ -24,6 +24,7 @@
...
@@ -24,6 +24,7 @@
#include <fcntl.h>
#include <fcntl.h>
#include <pthread.h>
#include <pthread.h>
#include <time.h>
#include <time.h>
#include <arpa/inet.h>
#include "config.h"
#include "config.h"
#include "websocket.h"
#include "websocket.h"
#include "web.h"
#include "web.h"
...
@@ -169,22 +170,25 @@ int main(int argc, char *argv[]) {
...
@@ -169,22 +170,25 @@ int main(int argc, char *argv[]) {
fprintf
(
stderr
,
"Warning: Failed to start web interface
\n
"
);
fprintf
(
stderr
,
"Warning: Failed to start web interface
\n
"
);
}
}
// Start web proxy server if enabled
printf
(
"Checking web proxy: enabled=%d, port=%d
\n
"
,
config
->
web_proxy_enabled
,
config
->
web_proxy_port
);
if
(
config
->
web_proxy_enabled
)
{
printf
(
"Starting web proxy server
\n
"
);
if
(
web_proxy_start_server
(
config
,
state
)
!=
0
)
{
fprintf
(
stderr
,
"Warning: Failed to start web proxy server
\n
"
);
}
}
// Start WebSocket server
// Start WebSocket server
if
(
websocket_start_server
(
config
,
state
)
!=
0
)
{
if
(
websocket_start_server
(
config
,
state
)
!=
0
)
{
fprintf
(
stderr
,
"Failed to start WebSocket server
\n
"
);
fprintf
(
stderr
,
"Failed to start WebSocket server
\n
"
);
web_proxy_stop_server
();
web_stop_server
();
web_stop_server
();
websocket_free_state
(
state
);
websocket_free_state
(
state
);
free_config
(
config
);
free_config
(
config
);
return
1
;
return
1
;
}
}
// Start web proxy server if enabled
if
(
config
->
web_proxy_enabled
)
{
if
(
web_proxy_start_server
(
config
,
state
)
!=
0
)
{
fprintf
(
stderr
,
"Warning: Failed to start web proxy server
\n
"
);
}
}
printf
(
"WSSSH Daemon running on %s:%d
\n
"
,
config
->
host
,
config
->
port
);
printf
(
"WSSSH Daemon running on %s:%d
\n
"
,
config
->
host
,
config
->
port
);
if
(
config
->
web_proxy_enabled
)
{
if
(
config
->
web_proxy_enabled
)
{
printf
(
"Web proxy server running on 127.0.0.1:%d
\n
"
,
config
->
web_proxy_port
);
printf
(
"Web proxy server running on 127.0.0.1:%d
\n
"
,
config
->
web_proxy_port
);
...
@@ -208,9 +212,9 @@ int main(int argc, char *argv[]) {
...
@@ -208,9 +212,9 @@ int main(int argc, char *argv[]) {
printf
(
"
\n
Shutting down WSSSH Daemon...
\n
"
);
printf
(
"
\n
Shutting down WSSSH Daemon...
\n
"
);
// Stop servers
// Stop servers
websocket_stop_server
();
web_proxy_stop_server
();
web_proxy_stop_server
();
web_stop_server
();
web_stop_server
();
websocket_stop_server
();
// Clean up plugin system
// Clean up plugin system
plugin_system_cleanup
();
plugin_system_cleanup
();
...
...
wssshd2/web.c
View file @
153b6344
...
@@ -1227,14 +1227,32 @@ static const char *validate_session(const char *session_id) {
...
@@ -1227,14 +1227,32 @@ static const char *validate_session(const char *session_id) {
static
int
parse_http_request
(
int
client_fd
,
http_request_t
*
req
)
{
static
int
parse_http_request
(
int
client_fd
,
http_request_t
*
req
)
{
char
buffer
[
8192
];
char
buffer
[
8192
];
s
size_t
bytes_read
=
recv
(
client_fd
,
buffer
,
sizeof
(
buffer
)
-
1
,
0
)
;
s
ize_t
total_read
=
0
;
i
f
(
bytes_read
<=
0
)
return
-
1
;
i
nt
found_headers
=
0
;
buffer
[
bytes_read
]
=
'\0'
;
// Read data in chunks until we find \r\n\r\n or reach max size
while
(
total_read
<
sizeof
(
buffer
)
-
1
)
{
ssize_t
bytes_read
=
recv
(
client_fd
,
buffer
+
total_read
,
sizeof
(
buffer
)
-
1
-
total_read
,
0
);
if
(
bytes_read
<=
0
)
{
if
(
total_read
==
0
)
return
-
1
;
// No data read
break
;
// End of data
}
total_read
+=
bytes_read
;
buffer
[
total_read
]
=
'\0'
;
// Check if we have the complete headers
if
(
strstr
(
buffer
,
"
\r\n\r\n
"
))
{
found_headers
=
1
;
break
;
}
}
if
(
!
found_headers
&&
total_read
==
0
)
return
-
1
;
if
(
global_config
&&
global_config
->
debug_web
)
{
if
(
global_config
&&
global_config
->
debug_web
)
{
printf
(
"[WEB-DEBUG] Raw buffer (%z
d bytes): '"
,
bytes
_read
);
printf
(
"[WEB-DEBUG] Raw buffer (%z
u bytes): '"
,
total
_read
);
for
(
s
size_t
i
=
0
;
i
<
bytes
_read
;
i
++
)
{
for
(
s
ize_t
i
=
0
;
i
<
total
_read
;
i
++
)
{
if
(
buffer
[
i
]
==
'\r'
)
printf
(
"
\\
r"
);
if
(
buffer
[
i
]
==
'\r'
)
printf
(
"
\\
r"
);
else
if
(
buffer
[
i
]
==
'\n'
)
printf
(
"
\\
n"
);
else
if
(
buffer
[
i
]
==
'\n'
)
printf
(
"
\\
n"
);
else
if
(
buffer
[
i
]
>=
32
&&
buffer
[
i
]
<=
126
)
printf
(
"%c"
,
buffer
[
i
]);
else
if
(
buffer
[
i
]
>=
32
&&
buffer
[
i
]
<=
126
)
printf
(
"%c"
,
buffer
[
i
]);
...
@@ -1276,7 +1294,7 @@ static int parse_http_request(int client_fd, http_request_t *req) {
...
@@ -1276,7 +1294,7 @@ static int parse_http_request(int client_fd, http_request_t *req) {
printf
(
"[WEB-DEBUG] Content-Length from header: %d
\n
"
,
content_length
);
printf
(
"[WEB-DEBUG] Content-Length from header: %d
\n
"
,
content_length
);
}
}
// Find body start - look for \r\n\r\n
or calculate from Content-Length
// Find body start - look for \r\n\r\n
char
*
body_separator
=
strstr
(
buffer
,
"
\r\n\r\n
"
);
char
*
body_separator
=
strstr
(
buffer
,
"
\r\n\r\n
"
);
char
*
body_start
=
NULL
;
char
*
body_start
=
NULL
;
size_t
body_length
=
0
;
size_t
body_length
=
0
;
...
@@ -1287,14 +1305,14 @@ static int parse_http_request(int client_fd, http_request_t *req) {
...
@@ -1287,14 +1305,14 @@ static int parse_http_request(int client_fd, http_request_t *req) {
if
(
body_separator
)
{
if
(
body_separator
)
{
body_start
=
body_separator
+
4
;
body_start
=
body_separator
+
4
;
body_length
=
bytes
_read
-
(
body_start
-
buffer
);
body_length
=
total
_read
-
(
body_start
-
buffer
);
if
(
global_config
&&
global_config
->
debug_web
)
{
if
(
global_config
&&
global_config
->
debug_web
)
{
printf
(
"[WEB-DEBUG] Found
\\
r
\\
n
\\
r
\\
n separator at offset %ld, body_start at %ld, body_length: %zu
\n
"
,
printf
(
"[WEB-DEBUG] Found
\\
r
\\
n
\\
r
\\
n separator at offset %ld, body_start at %ld, body_length: %zu
\n
"
,
body_separator
-
buffer
,
body_start
-
buffer
,
body_length
);
body_separator
-
buffer
,
body_start
-
buffer
,
body_length
);
}
}
}
else
if
(
content_length
>
0
)
{
}
else
if
(
content_length
>
0
)
{
// Calculate body position: total bytes - content_length
// Calculate body position: total bytes - content_length
body_start
=
buffer
+
bytes
_read
-
content_length
;
body_start
=
buffer
+
total
_read
-
content_length
;
body_length
=
content_length
;
body_length
=
content_length
;
if
(
global_config
&&
global_config
->
debug_web
)
{
if
(
global_config
&&
global_config
->
debug_web
)
{
printf
(
"[WEB-DEBUG] Calculated body start from Content-Length, body_start at %ld, body_length: %zu
\n
"
,
printf
(
"[WEB-DEBUG] Calculated body start from Content-Length, body_start at %ld, body_length: %zu
\n
"
,
...
@@ -1463,6 +1481,8 @@ static const char *get_cookie(const char *headers, const char *name) {
...
@@ -1463,6 +1481,8 @@ static const char *get_cookie(const char *headers, const char *name) {
*
eq
=
'\0'
;
*
eq
=
'\0'
;
if
(
strcmp
(
token
,
name
)
==
0
)
{
if
(
strcmp
(
token
,
name
)
==
0
)
{
strcpy
(
value
,
eq
+
1
);
strcpy
(
value
,
eq
+
1
);
// URL decode the cookie value
url_decode
(
value
);
return
value
;
return
value
;
}
}
}
}
...
@@ -1486,6 +1506,8 @@ static void send_response(int client_fd, int status_code, const char *status_tex
...
@@ -1486,6 +1506,8 @@ static void send_response(int client_fd, int status_code, const char *status_tex
}
}
}
}
printf
(
"[DEBUG] Sending response: %d %s, body_len: %zu
\n
"
,
status_code
,
status_text
,
body_len
);
char
response
[
8192
];
char
response
[
8192
];
char
date
[
64
];
char
date
[
64
];
time_t
now
=
time
(
NULL
);
time_t
now
=
time
(
NULL
);
...
@@ -1656,18 +1678,18 @@ static int generate_users_html(const char *username, char *html, size_t max_len)
...
@@ -1656,18 +1678,18 @@ static int generate_users_html(const char *username, char *html, size_t max_len)
// Handle HTTP requests
// Handle HTTP requests
// Returns 1 if the connection should be kept open (WebSocket), 0 if it should be closed
// Returns 1 if the connection should be kept open (WebSocket), 0 if it should be closed
static
int
handle_request
(
int
client_fd
,
const
http_request_t
*
req
)
{
static
int
handle_request
(
int
client_fd
,
const
http_request_t
*
req
)
{
if
(
global_config
&&
global_config
->
debug_web
&&
!
strstr
(
req
->
path
,
"/xterm/data"
))
{
//
if (global_config && global_config->debug_web && !strstr(req->path, "/xterm/data")) {
printf
(
"[WEB-DEBUG] Received %s request for %s
\n
"
,
req
->
method
,
req
->
path
);
//
printf("[WEB-DEBUG] Received %s request for %s\n", req->method, req->path);
if
(
req
->
query
[
0
])
{
//
if (req->query[0]) {
printf
(
"[WEB-DEBUG] Query: %s
\n
"
,
req
->
query
);
//
printf("[WEB-DEBUG] Query: %s\n", req->query);
}
//
}
printf
(
"[WEB-DEBUG] Headers: %s
\n
"
,
req
->
headers
);
//
printf("[WEB-DEBUG] Headers: %s\n", req->headers);
if
(
req
->
content_length
>
0
)
{
//
if (req->content_length > 0) {
printf
(
"[WEB-DEBUG] Content-Length: %d
\n
"
,
req
->
content_length
);
//
printf("[WEB-DEBUG] Content-Length: %d\n", req->content_length);
}
//
}
}
//
}
const
char
*
session_id
=
get_cookie
(
req
->
headers
,
"
session_id
"
);
const
char
*
session_id
=
get_cookie
(
req
->
headers
,
"
wssshd_session
"
);
const
char
*
username
=
NULL
;
const
char
*
username
=
NULL
;
int
is_admin
=
0
;
int
is_admin
=
0
;
...
@@ -1690,10 +1712,12 @@ static int handle_request(int client_fd, const http_request_t *req) {
...
@@ -1690,10 +1712,12 @@ static int handle_request(int client_fd, const http_request_t *req) {
// Check if any plugin handles this request
// Check if any plugin handles this request
int
plugin_result
=
plugin_handle_web_request
(
client_fd
,
req
);
int
plugin_result
=
plugin_handle_web_request
(
client_fd
,
req
);
if
(
plugin_result
>
=
0
)
{
if
(
plugin_result
>
0
)
{
return
plugin_result
;
// Plugin handled the request
return
plugin_result
;
// Plugin handled the request
}
}
printf
(
"[DEBUG] Handling request: %s %s
\n
"
,
req
->
method
,
req
->
path
);
// Route handling
// Route handling
// Handle WebSocket terminal, VNC, and RDP connections first
// Handle WebSocket terminal, VNC, and RDP connections first
char
*
headers_copy
=
NULL
;
char
*
headers_copy
=
NULL
;
...
@@ -2535,9 +2559,15 @@ static int handle_request(int client_fd, const http_request_t *req) {
...
@@ -2535,9 +2559,15 @@ static int handle_request(int client_fd, const http_request_t *req) {
char
*
html
=
generate_index_html
(
username
,
is_admin
,
error
);
char
*
html
=
generate_index_html
(
username
,
is_admin
,
error
);
send_response
(
client_fd
,
200
,
"OK"
,
"text/html"
,
html
,
strlen
(
html
),
NULL
,
NULL
);
send_response
(
client_fd
,
200
,
"OK"
,
"text/html"
,
html
,
strlen
(
html
),
NULL
,
NULL
);
}
else
if
(
strcmp
(
req
->
path
,
"/login"
)
==
0
)
{
}
else
if
(
strcmp
(
req
->
path
,
"/login"
)
==
0
)
{
send_response
(
client_fd
,
200
,
"OK"
,
"text/html"
,
login_page_html
,
strlen
(
login_page_html
),
NULL
,
NULL
);
printf
(
"[DEBUG] Sending login page
\n
"
);
if
(
username
)
{
// If already logged in, redirect to home
send_response
(
client_fd
,
302
,
"Found"
,
"text/html"
,
NULL
,
0
,
NULL
,
"Location: /"
);
}
else
{
send_response
(
client_fd
,
200
,
"OK"
,
"text/html"
,
login_page_html
,
strlen
(
login_page_html
),
NULL
,
NULL
);
}
}
else
if
(
strcmp
(
req
->
path
,
"/logout"
)
==
0
)
{
}
else
if
(
strcmp
(
req
->
path
,
"/logout"
)
==
0
)
{
send_response
(
client_fd
,
302
,
"Found"
,
"text/html"
,
NULL
,
0
,
"
session_id
=; Max-Age=0; Path=/"
,
"Location: /"
);
send_response
(
client_fd
,
302
,
"Found"
,
"text/html"
,
NULL
,
0
,
"
wssshd_session
=; Max-Age=0; Path=/"
,
"Location: /"
);
return
0
;
return
0
;
}
else
if
(
strcmp
(
req
->
path
,
"/users"
)
==
0
)
{
}
else
if
(
strcmp
(
req
->
path
,
"/users"
)
==
0
)
{
if
(
!
username
||
!
is_admin
)
{
if
(
!
username
||
!
is_admin
)
{
...
@@ -2566,9 +2596,11 @@ static int handle_request(int client_fd, const http_request_t *req) {
...
@@ -2566,9 +2596,11 @@ static int handle_request(int client_fd, const http_request_t *req) {
send_response
(
client_fd
,
200
,
"OK"
,
"application/json"
,
json
,
len
,
NULL
,
NULL
);
send_response
(
client_fd
,
200
,
"OK"
,
"application/json"
,
json
,
len
,
NULL
,
NULL
);
}
else
{
}
else
{
// Try to serve embedded asset
// Try to serve embedded asset
printf
(
"[DEBUG] Trying to serve embedded asset: %s
\n
"
,
req
->
path
);
size_t
size
;
size_t
size
;
const
char
*
asset
=
get_embedded_asset
(
req
->
path
,
&
size
);
const
char
*
asset
=
get_embedded_asset
(
req
->
path
,
&
size
);
if
(
asset
)
{
if
(
asset
)
{
printf
(
"[DEBUG] Asset found, size: %zu
\n
"
,
size
);
const
char
*
content_type
=
"text/plain"
;
const
char
*
content_type
=
"text/plain"
;
if
(
strstr
(
req
->
path
,
".html"
))
content_type
=
"text/html"
;
if
(
strstr
(
req
->
path
,
".html"
))
content_type
=
"text/html"
;
else
if
(
strstr
(
req
->
path
,
".css"
))
content_type
=
"text/css"
;
else
if
(
strstr
(
req
->
path
,
".css"
))
content_type
=
"text/css"
;
...
@@ -2579,6 +2611,7 @@ static int handle_request(int client_fd, const http_request_t *req) {
...
@@ -2579,6 +2611,7 @@ static int handle_request(int client_fd, const http_request_t *req) {
else
if
(
strstr
(
req
->
path
,
".ico"
))
content_type
=
"image/x-icon"
;
else
if
(
strstr
(
req
->
path
,
".ico"
))
content_type
=
"image/x-icon"
;
send_response
(
client_fd
,
200
,
"OK"
,
content_type
,
asset
,
size
,
NULL
,
NULL
);
send_response
(
client_fd
,
200
,
"OK"
,
content_type
,
asset
,
size
,
NULL
,
NULL
);
}
else
{
}
else
{
printf
(
"[DEBUG] Asset not found for %s
\n
"
,
req
->
path
);
send_response
(
client_fd
,
404
,
"Not Found"
,
"text/html"
,
"Not found"
,
9
,
NULL
,
NULL
);
send_response
(
client_fd
,
404
,
"Not Found"
,
"text/html"
,
"Not found"
,
9
,
NULL
,
NULL
);
}
}
}
}
...
@@ -2609,7 +2642,7 @@ static int handle_request(int client_fd, const http_request_t *req) {
...
@@ -2609,7 +2642,7 @@ static int handle_request(int client_fd, const http_request_t *req) {
form_username
,
new_session
);
form_username
,
new_session
);
}
}
char
cookie
[
256
];
char
cookie
[
256
];
snprintf
(
cookie
,
sizeof
(
cookie
),
"
session_id
=%s; Path=/; HttpOnly"
,
new_session
);
snprintf
(
cookie
,
sizeof
(
cookie
),
"
wssshd_session
=%s; Path=/; HttpOnly"
,
new_session
);
send_response
(
client_fd
,
302
,
"Found"
,
"text/html"
,
NULL
,
0
,
cookie
,
"Location: /"
);
send_response
(
client_fd
,
302
,
"Found"
,
"text/html"
,
NULL
,
0
,
cookie
,
"Location: /"
);
return
0
;
return
0
;
}
else
{
}
else
{
...
@@ -2749,6 +2782,8 @@ static void *http_server_thread(void *arg __attribute__((unused))) {
...
@@ -2749,6 +2782,8 @@ static void *http_server_thread(void *arg __attribute__((unused))) {
struct
sockaddr_in
server_addr
,
client_addr
;
struct
sockaddr_in
server_addr
,
client_addr
;
socklen_t
client_len
=
sizeof
(
client_addr
);
socklen_t
client_len
=
sizeof
(
client_addr
);
printf
(
"HTTP server thread starting
\n
"
);
server_socket
=
socket
(
AF_INET
,
SOCK_STREAM
,
0
);
server_socket
=
socket
(
AF_INET
,
SOCK_STREAM
,
0
);
if
(
server_socket
<
0
)
{
if
(
server_socket
<
0
)
{
perror
(
"Failed to create server socket"
);
perror
(
"Failed to create server socket"
);
...
@@ -2766,10 +2801,13 @@ static void *http_server_thread(void *arg __attribute__((unused))) {
...
@@ -2766,10 +2801,13 @@ static void *http_server_thread(void *arg __attribute__((unused))) {
if
(
bind
(
server_socket
,
(
struct
sockaddr
*
)
&
server_addr
,
sizeof
(
server_addr
))
<
0
)
{
if
(
bind
(
server_socket
,
(
struct
sockaddr
*
)
&
server_addr
,
sizeof
(
server_addr
))
<
0
)
{
perror
(
"Failed to bind server socket"
);
perror
(
"Failed to bind server socket"
);
printf
(
"Failed to bind to %s:%d
\n
"
,
global_config
->
web_host
,
global_config
->
web_port
);
close
(
server_socket
);
close
(
server_socket
);
return
NULL
;
return
NULL
;
}
}
printf
(
"Web interface bound to %s:%d
\n
"
,
global_config
->
web_host
,
global_config
->
web_port
);
if
(
listen
(
server_socket
,
10
)
<
0
)
{
if
(
listen
(
server_socket
,
10
)
<
0
)
{
perror
(
"Failed to listen on server socket"
);
perror
(
"Failed to listen on server socket"
);
close
(
server_socket
);
close
(
server_socket
);
...
@@ -2787,12 +2825,16 @@ static void *http_server_thread(void *arg __attribute__((unused))) {
...
@@ -2787,12 +2825,16 @@ static void *http_server_thread(void *arg __attribute__((unused))) {
}
}
http_request_t
req
;
http_request_t
req
;
memset
(
&
req
,
0
,
sizeof
(
req
));
if
(
parse_http_request
(
client_fd
,
&
req
)
==
0
)
{
if
(
parse_http_request
(
client_fd
,
&
req
)
==
0
)
{
int
keep_open
=
handle_request
(
client_fd
,
&
req
);
int
keep_open
=
handle_request
(
client_fd
,
&
req
);
if
(
keep_open
)
{
if
(
keep_open
)
{
// WebSocket connection - don't close the socket
// WebSocket connection - don't close the socket
continue
;
continue
;
}
}
}
else
{
// Send error response if parsing failed
send_response
(
client_fd
,
400
,
"Bad Request"
,
"text/plain"
,
"Bad Request"
,
11
,
NULL
,
NULL
);
}
}
close
(
client_fd
);
close
(
client_fd
);
...
@@ -2813,6 +2855,8 @@ int web_start_server(const wssshd_config_t *config, wssshd_state_t *state) {
...
@@ -2813,6 +2855,8 @@ int web_start_server(const wssshd_config_t *config, wssshd_state_t *state) {
init_users
(
config
);
init_users
(
config
);
printf
(
"Web server initialization complete
\n
"
);
// Start HTTP server thread
// Start HTTP server thread
pthread_t
thread
;
pthread_t
thread
;
if
(
pthread_create
(
&
thread
,
NULL
,
http_server_thread
,
NULL
)
!=
0
)
{
if
(
pthread_create
(
&
thread
,
NULL
,
http_server_thread
,
NULL
)
!=
0
)
{
...
...
wssshd2/web_proxy.c
View file @
153b6344
...
@@ -34,9 +34,7 @@
...
@@ -34,9 +34,7 @@
#include "websocket.h"
#include "websocket.h"
#include "websocket_protocol.h"
#include "websocket_protocol.h"
// Global state
// Global state for shutdown
static
wssshd_state_t
*
global_state
=
NULL
;
static
const
wssshd_config_t
*
global_config
=
NULL
;
static
int
server_socket
=
-
1
;
static
int
server_socket
=
-
1
;
static
volatile
int
server_running
=
0
;
static
volatile
int
server_running
=
0
;
...
@@ -55,17 +53,30 @@ static proxy_connection_t proxy_connections[MAX_PROXY_CONNECTIONS];
...
@@ -55,17 +53,30 @@ static proxy_connection_t proxy_connections[MAX_PROXY_CONNECTIONS];
static
int
proxy_connections_count
=
0
;
static
int
proxy_connections_count
=
0
;
static
pthread_mutex_t
proxy_mutex
=
PTHREAD_MUTEX_INITIALIZER
;
static
pthread_mutex_t
proxy_mutex
=
PTHREAD_MUTEX_INITIALIZER
;
// Thread arguments structure
typedef
struct
{
const
wssshd_config_t
*
config
;
wssshd_state_t
*
state
;
}
proxy_thread_args_t
;
// Connection handler arguments
typedef
struct
{
int
client_fd
;
wssshd_state_t
*
state
;
const
wssshd_config_t
*
config
;
}
connection_handler_args_t
;
// Forward declaration for proxy connection handler
// Forward declaration for proxy connection handler
static
void
*
proxy_connection_handler
(
void
*
arg
);
static
void
*
proxy_connection_handler
(
void
*
arg
);
// Find client by hostname (matching subdomain or client_id)
// Find client by hostname (matching subdomain or client_id)
static
client_t
*
find_client_by_hostname
(
const
char
*
hostname
)
{
static
client_t
*
find_client_by_hostname
(
const
char
*
hostname
,
wssshd_state_t
*
state
,
const
wssshd_config_t
*
config
)
{
if
(
!
hostname
||
!
global_
state
)
return
NULL
;
if
(
!
hostname
||
!
state
)
return
NULL
;
pthread_mutex_lock
(
&
global_
state
->
client_mutex
);
pthread_mutex_lock
(
&
state
->
client_mutex
);
for
(
size_t
i
=
0
;
i
<
global_
state
->
clients_count
;
i
++
)
{
for
(
size_t
i
=
0
;
i
<
state
->
clients_count
;
i
++
)
{
client_t
*
client
=
&
global_
state
->
clients
[
i
];
client_t
*
client
=
&
state
->
clients
[
i
];
if
(
!
client
->
active
)
continue
;
if
(
!
client
->
active
)
continue
;
// Check if client has web service
// Check if client has web service
...
@@ -76,23 +87,23 @@ static client_t *find_client_by_hostname(const char *hostname) {
...
@@ -76,23 +87,23 @@ static client_t *find_client_by_hostname(const char *hostname) {
// Try exact match with client_id
// Try exact match with client_id
if
(
strcasecmp
(
hostname
,
client
->
client_id
)
==
0
)
{
if
(
strcasecmp
(
hostname
,
client
->
client_id
)
==
0
)
{
pthread_mutex_unlock
(
&
global_
state
->
client_mutex
);
pthread_mutex_unlock
(
&
state
->
client_mutex
);
return
client
;
return
client
;
}
}
// Try subdomain match: hostname.client_id.domain
// Try subdomain match: hostname.client_id.domain
if
(
global_config
&&
global_
config
->
domain
)
{
if
(
config
&&
config
->
domain
)
{
char
expected_hostname
[
512
];
char
expected_hostname
[
512
];
snprintf
(
expected_hostname
,
sizeof
(
expected_hostname
),
"%s.%s"
,
snprintf
(
expected_hostname
,
sizeof
(
expected_hostname
),
"%s.%s"
,
client
->
client_id
,
global_
config
->
domain
);
client
->
client_id
,
config
->
domain
);
if
(
strcasecmp
(
hostname
,
expected_hostname
)
==
0
)
{
if
(
strcasecmp
(
hostname
,
expected_hostname
)
==
0
)
{
pthread_mutex_unlock
(
&
global_
state
->
client_mutex
);
pthread_mutex_unlock
(
&
state
->
client_mutex
);
return
client
;
return
client
;
}
}
}
}
}
}
pthread_mutex_unlock
(
&
global_
state
->
client_mutex
);
pthread_mutex_unlock
(
&
state
->
client_mutex
);
return
NULL
;
return
NULL
;
}
}
...
@@ -196,7 +207,7 @@ static void *proxy_data_forward(void *arg) {
...
@@ -196,7 +207,7 @@ static void *proxy_data_forward(void *arg) {
}
}
// Handle incoming HTTP request and establish tunnel
// Handle incoming HTTP request and establish tunnel
static
int
handle_proxy_request
(
int
client_fd
)
{
static
int
handle_proxy_request
(
int
client_fd
,
wssshd_state_t
*
state
,
const
wssshd_config_t
*
config
)
{
char
request
[
8192
];
char
request
[
8192
];
ssize_t
bytes_read
=
recv
(
client_fd
,
request
,
sizeof
(
request
)
-
1
,
0
);
ssize_t
bytes_read
=
recv
(
client_fd
,
request
,
sizeof
(
request
)
-
1
,
0
);
if
(
bytes_read
<=
0
)
{
if
(
bytes_read
<=
0
)
{
...
@@ -214,7 +225,7 @@ static int handle_proxy_request(int client_fd) {
...
@@ -214,7 +225,7 @@ static int handle_proxy_request(int client_fd) {
printf
(
"[WEB-PROXY] Received request for hostname: %s
\n
"
,
hostname
);
printf
(
"[WEB-PROXY] Received request for hostname: %s
\n
"
,
hostname
);
// Find client by hostname
// Find client by hostname
client_t
*
client
=
find_client_by_hostname
(
hostname
);
client_t
*
client
=
find_client_by_hostname
(
hostname
,
state
,
config
);
if
(
!
client
)
{
if
(
!
client
)
{
printf
(
"[WEB-PROXY] No client found for hostname: %s
\n
"
,
hostname
);
printf
(
"[WEB-PROXY] No client found for hostname: %s
\n
"
,
hostname
);
send_http_error
(
client_fd
,
404
,
"Not Found"
);
send_http_error
(
client_fd
,
404
,
"Not Found"
);
...
@@ -244,12 +255,15 @@ static int handle_proxy_request(int client_fd) {
...
@@ -244,12 +255,15 @@ static int handle_proxy_request(int client_fd) {
// Proxy connection handler thread
// Proxy connection handler thread
static
void
*
proxy_connection_handler
(
void
*
arg
)
{
static
void
*
proxy_connection_handler
(
void
*
arg
)
{
int
client_fd
=
*
(
int
*
)
arg
;
connection_handler_args_t
*
args
=
(
connection_handler_args_t
*
)
arg
;
free
(
arg
);
int
client_fd
=
args
->
client_fd
;
wssshd_state_t
*
state
=
args
->
state
;
const
wssshd_config_t
*
config
=
args
->
config
;
free
(
args
);
printf
(
"[WEB-PROXY] New connection received
\n
"
);
printf
(
"[WEB-PROXY] New connection received
\n
"
);
handle_proxy_request
(
client_fd
);
handle_proxy_request
(
client_fd
,
state
,
config
);
close
(
client_fd
);
close
(
client_fd
);
printf
(
"[WEB-PROXY] Connection closed
\n
"
);
printf
(
"[WEB-PROXY] Connection closed
\n
"
);
...
@@ -257,16 +271,21 @@ static void *proxy_connection_handler(void *arg) {
...
@@ -257,16 +271,21 @@ static void *proxy_connection_handler(void *arg) {
return
NULL
;
return
NULL
;
}
}
// Main HTTP server thread
static
void
*
http_proxy_thread
(
void
*
arg
)
{
static
void
*
http_proxy_thread
(
void
*
arg
__attribute__
((
unused
)))
{
proxy_thread_args_t
*
args
=
(
proxy_thread_args_t
*
)
arg
;
const
wssshd_config_t
*
config
=
args
->
config
;
wssshd_state_t
*
state
=
args
->
state
;
free
(
args
);
struct
sockaddr_in
server_addr
,
client_addr
;
struct
sockaddr_in
server_addr
,
client_addr
;
socklen_t
client_len
=
sizeof
(
client_addr
);
socklen_t
client_len
=
sizeof
(
client_addr
);
printf
(
"[WEB-PROXY] Creating socket
\n
"
);
server_socket
=
socket
(
AF_INET
,
SOCK_STREAM
,
0
);
server_socket
=
socket
(
AF_INET
,
SOCK_STREAM
,
0
);
if
(
server_socket
<
0
)
{
if
(
server_socket
<
0
)
{
perror
(
"[WEB-PROXY] Failed to create server socket"
);
perror
(
"[WEB-PROXY] Failed to create server socket"
);
return
NULL
;
return
NULL
;
}
}
printf
(
"[WEB-PROXY] Socket created
\n
"
);
// Set socket options
// Set socket options
int
opt
=
1
;
int
opt
=
1
;
...
@@ -274,22 +293,25 @@ static void *http_proxy_thread(void *arg __attribute__((unused))) {
...
@@ -274,22 +293,25 @@ static void *http_proxy_thread(void *arg __attribute__((unused))) {
memset
(
&
server_addr
,
0
,
sizeof
(
server_addr
));
memset
(
&
server_addr
,
0
,
sizeof
(
server_addr
));
server_addr
.
sin_family
=
AF_INET
;
server_addr
.
sin_family
=
AF_INET
;
server_addr
.
sin_addr
.
s_addr
=
inet_addr
(
"127.0.0.1"
);
// Listen only on localhost
server_addr
.
sin_addr
.
s_addr
=
htonl
(
INADDR_LOOPBACK
);
// Listen on localhost only
server_addr
.
sin_port
=
htons
(
global_config
->
web_proxy_port
);
server_addr
.
sin_port
=
htons
(
config
->
web_proxy_port
);
printf
(
"[WEB-PROXY] Binding to 127.0.0.1:%d
\n
"
,
config
->
web_proxy_port
);
if
(
bind
(
server_socket
,
(
struct
sockaddr
*
)
&
server_addr
,
sizeof
(
server_addr
))
<
0
)
{
if
(
bind
(
server_socket
,
(
struct
sockaddr
*
)
&
server_addr
,
sizeof
(
server_addr
))
<
0
)
{
perror
(
"[WEB-PROXY] Failed to bind server socket"
);
perror
(
"[WEB-PROXY] Failed to bind server socket"
);
close
(
server_socket
);
close
(
server_socket
);
return
NULL
;
return
NULL
;
}
}
printf
(
"[WEB-PROXY] Bound successfully
\n
"
);
if
(
listen
(
server_socket
,
10
)
<
0
)
{
if
(
listen
(
server_socket
,
10
)
<
0
)
{
perror
(
"[WEB-PROXY] Failed to listen on server socket"
);
perror
(
"[WEB-PROXY] Failed to listen on server socket"
);
close
(
server_socket
);
close
(
server_socket
);
return
NULL
;
return
NULL
;
}
}
printf
(
"[WEB-PROXY] Listening successfully
\n
"
);
printf
(
"[WEB-PROXY] Web proxy server starting on 127.0.0.1:%d
\n
"
,
global_
config
->
web_proxy_port
);
printf
(
"[WEB-PROXY] Web proxy server starting on 127.0.0.1:%d
\n
"
,
config
->
web_proxy_port
);
server_running
=
1
;
server_running
=
1
;
// Ignore SIGPIPE to prevent crashes on broken connections
// Ignore SIGPIPE to prevent crashes on broken connections
...
@@ -303,17 +325,19 @@ static void *http_proxy_thread(void *arg __attribute__((unused))) {
...
@@ -303,17 +325,19 @@ static void *http_proxy_thread(void *arg __attribute__((unused))) {
}
}
// Create a new thread to handle the connection
// Create a new thread to handle the connection
int
*
client_fd_ptr
=
malloc
(
sizeof
(
in
t
));
connection_handler_args_t
*
handler_args
=
malloc
(
sizeof
(
connection_handler_args_
t
));
if
(
!
client_fd_ptr
)
{
if
(
!
handler_args
)
{
close
(
client_fd
);
close
(
client_fd
);
continue
;
continue
;
}
}
*
client_fd_ptr
=
client_fd
;
handler_args
->
client_fd
=
client_fd
;
handler_args
->
state
=
state
;
handler_args
->
config
=
config
;
pthread_t
thread
;
pthread_t
thread
;
if
(
pthread_create
(
&
thread
,
NULL
,
proxy_connection_handler
,
client_fd_ptr
)
!=
0
)
{
if
(
pthread_create
(
&
thread
,
NULL
,
proxy_connection_handler
,
handler_args
)
!=
0
)
{
perror
(
"[WEB-PROXY] Failed to create connection handler thread"
);
perror
(
"[WEB-PROXY] Failed to create connection handler thread"
);
free
(
client_fd_ptr
);
free
(
handler_args
);
close
(
client_fd
);
close
(
client_fd
);
continue
;
continue
;
}
}
...
@@ -332,18 +356,20 @@ int web_proxy_start_server(const wssshd_config_t *config, wssshd_state_t *state)
...
@@ -332,18 +356,20 @@ int web_proxy_start_server(const wssshd_config_t *config, wssshd_state_t *state)
return
0
;
// Web proxy not enabled
return
0
;
// Web proxy not enabled
}
}
global_config
=
config
;
// Allocate thread arguments
global_state
=
state
;
proxy_thread_args_t
*
args
=
malloc
(
sizeof
(
proxy_thread_args_t
));
if
(
!
args
)
{
// Set default port if not specified
perror
(
"[WEB-PROXY] Failed to allocate thread arguments"
);
if
(
config
->
web_proxy_port
==
0
)
{
return
-
1
;
// This won't work directly since config is const, but the CLI parsing sets it
}
}
args
->
config
=
config
;
args
->
state
=
state
;
// Start HTTP proxy server thread
// Start HTTP proxy server thread
pthread_t
thread
;
pthread_t
thread
;
if
(
pthread_create
(
&
thread
,
NULL
,
http_proxy_thread
,
NULL
)
!=
0
)
{
if
(
pthread_create
(
&
thread
,
NULL
,
http_proxy_thread
,
args
)
!=
0
)
{
perror
(
"[WEB-PROXY] Failed to create HTTP proxy server thread"
);
perror
(
"[WEB-PROXY] Failed to create HTTP proxy server thread"
);
free
(
args
);
return
-
1
;
return
-
1
;
}
}
...
...
wssshd2/websocket.c
View file @
153b6344
...
@@ -643,6 +643,8 @@ int websocket_handle_message(wssshd_state_t *state, ws_connection_t *conn __attr
...
@@ -643,6 +643,8 @@ int websocket_handle_message(wssshd_state_t *state, ws_connection_t *conn __attr
if
(
client_id
&&
password
&&
strcmp
(
password
,
state
->
server_password
)
==
0
)
{
if
(
client_id
&&
password
&&
strcmp
(
password
,
state
->
server_password
)
==
0
)
{
client_t
*
client
=
websocket_add_client
(
state
,
client_id
,
(
void
*
)
conn
,
services
);
client_t
*
client
=
websocket_add_client
(
state
,
client_id
,
(
void
*
)
conn
,
services
);
if
(
client
)
{
if
(
client
)
{
// Set client IP
strcpy
(
client
->
ip
,
inet_ntoa
(
conn
->
addr
.
sin_addr
));
// Send registration success
// Send registration success
char
response
[
512
];
char
response
[
512
];
snprintf
(
response
,
sizeof
(
response
),
REGISTERED_MSG
,
client_id
);
snprintf
(
response
,
sizeof
(
response
),
REGISTERED_MSG
,
client_id
);
...
@@ -1780,17 +1782,22 @@ int websocket_start_server(const wssshd_config_t *config, wssshd_state_t *state)
...
@@ -1780,17 +1782,22 @@ int websocket_start_server(const wssshd_config_t *config, wssshd_state_t *state)
// Load or generate certificates
// Load or generate certificates
char
cert_file
[
256
],
key_file
[
256
];
char
cert_file
[
256
],
key_file
[
256
];
// Try system location first, then fall back to local directory
bool
use_system_location
=
false
;
snprintf
(
cert_file
,
sizeof
(
cert_file
),
"/etc/wssshd/cert.pem"
);
snprintf
(
key_file
,
sizeof
(
key_file
),
"/etc/wssshd/key.pem"
);
// Check if /etc/wssshd directory exists
if
(
access
(
"/etc/wssshd"
,
F_OK
)
==
0
)
{
// If system location doesn't exist and we can't write there, use local directory
// Try to use system location
if
(
access
(
cert_file
,
F_OK
)
!=
0
)
{
snprintf
(
cert_file
,
sizeof
(
cert_file
),
"/etc/wssshd/cert.pem"
);
snprintf
(
key_file
,
sizeof
(
key_file
),
"/etc/wssshd/key.pem"
);
use_system_location
=
true
;
}
else
{
// Fall back to local directory
char
local_dir
[
256
];
char
local_dir
[
256
];
snprintf
(
local_dir
,
sizeof
(
local_dir
),
"./certs"
);
snprintf
(
local_dir
,
sizeof
(
local_dir
),
"./certs"
);
mkdir
(
local_dir
,
0755
);
// Create directory if it doesn't exist
mkdir
(
local_dir
,
0755
);
// Create directory if it doesn't exist
snprintf
(
cert_file
,
sizeof
(
cert_file
),
"./certs/cert.pem"
);
snprintf
(
cert_file
,
sizeof
(
cert_file
),
"./certs/cert.pem"
);
snprintf
(
key_file
,
sizeof
(
key_file
),
"./certs/key.pem"
);
snprintf
(
key_file
,
sizeof
(
key_file
),
"./certs/key.pem"
);
use_system_location
=
false
;
}
}
printf
(
"Using certificates: %s, %s
\n
"
,
cert_file
,
key_file
);
printf
(
"Using certificates: %s, %s
\n
"
,
cert_file
,
key_file
);
...
@@ -1798,12 +1805,32 @@ int websocket_start_server(const wssshd_config_t *config, wssshd_state_t *state)
...
@@ -1798,12 +1805,32 @@ int websocket_start_server(const wssshd_config_t *config, wssshd_state_t *state)
if
(
access
(
cert_file
,
F_OK
)
!=
0
||
access
(
key_file
,
F_OK
)
!=
0
)
{
if
(
access
(
cert_file
,
F_OK
)
!=
0
||
access
(
key_file
,
F_OK
)
!=
0
)
{
printf
(
"Generating self-signed certificate...
\n
"
);
printf
(
"Generating self-signed certificate...
\n
"
);
if
(
ssl_generate_self_signed_cert
(
cert_file
,
key_file
)
!=
0
)
{
if
(
ssl_generate_self_signed_cert
(
cert_file
,
key_file
)
!=
0
)
{
fprintf
(
stderr
,
"Failed to generate certificate
\n
"
);
if
(
use_system_location
)
{
SSL_CTX_free
(
ssl_ctx
);
// If system location failed, fall back to local directory
close
(
server_sock
);
printf
(
"Failed to generate certificate in system location, falling back to local directory...
\n
"
);
return
-
1
;
char
local_dir
[
256
];
snprintf
(
local_dir
,
sizeof
(
local_dir
),
"./certs"
);
mkdir
(
local_dir
,
0755
);
// Create directory if it doesn't exist
snprintf
(
cert_file
,
sizeof
(
cert_file
),
"./certs/cert.pem"
);
snprintf
(
key_file
,
sizeof
(
key_file
),
"./certs/key.pem"
);
printf
(
"Using certificates: %s, %s
\n
"
,
cert_file
,
key_file
);
if
(
ssl_generate_self_signed_cert
(
cert_file
,
key_file
)
!=
0
)
{
fprintf
(
stderr
,
"Failed to generate certificate in fallback location
\n
"
);
SSL_CTX_free
(
ssl_ctx
);
close
(
server_sock
);
return
-
1
;
}
printf
(
"Certificate generated successfully in fallback location
\n
"
);
}
else
{
fprintf
(
stderr
,
"Failed to generate certificate
\n
"
);
SSL_CTX_free
(
ssl_ctx
);
close
(
server_sock
);
return
-
1
;
}
}
else
{
printf
(
"Certificate generated successfully
\n
"
);
}
}
printf
(
"Certificate generated successfully
\n
"
);
}
}
printf
(
"Loading certificates...
\n
"
);
printf
(
"Loading certificates...
\n
"
);
...
@@ -1862,6 +1889,9 @@ int websocket_start_server(const wssshd_config_t *config, wssshd_state_t *state)
...
@@ -1862,6 +1889,9 @@ int websocket_start_server(const wssshd_config_t *config, wssshd_state_t *state)
continue
;
continue
;
}
}
// Set the client address
conn
->
addr
=
client_addr
;
// Start client handler thread
// Start client handler thread
client_thread_args_t
*
thread_args
=
malloc
(
sizeof
(
client_thread_args_t
));
client_thread_args_t
*
thread_args
=
malloc
(
sizeof
(
client_thread_args_t
));
...
...
wssshd2/websocket.h
View file @
153b6344
...
@@ -38,6 +38,7 @@ typedef struct {
...
@@ -38,6 +38,7 @@ typedef struct {
char
tunnel_control
[
16
];
char
tunnel_control
[
16
];
char
wssshd_private_ip
[
64
];
char
wssshd_private_ip
[
64
];
char
services
[
256
];
// Comma-separated list of services (e.g., "ssh,rdp,vnc")
char
services
[
256
];
// Comma-separated list of services (e.g., "ssh,rdp,vnc")
char
ip
[
INET_ADDRSTRLEN
];
}
client_t
;
}
client_t
;
// Terminal session (defined in terminal.h)
// Terminal session (defined in terminal.h)
...
...
wssshd2/websocket_protocol.h
View file @
153b6344
...
@@ -22,6 +22,7 @@
...
@@ -22,6 +22,7 @@
#include <stdint.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdbool.h>
#include <netinet/in.h>
#include <openssl/ssl.h>
#include <openssl/ssl.h>
// WebSocket frame opcodes
// WebSocket frame opcodes
...
@@ -60,6 +61,7 @@ typedef struct {
...
@@ -60,6 +61,7 @@ typedef struct {
char
*
recv_buffer
;
char
*
recv_buffer
;
size_t
recv_buffer_size
;
size_t
recv_buffer_size
;
size_t
recv_buffer_used
;
size_t
recv_buffer_used
;
struct
sockaddr_in
addr
;
}
ws_connection_t
;
}
ws_connection_t
;
// Function declarations
// Function declarations
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment