mirror of
https://github.com/tsl0922/ttyd.git
synced 2025-12-23 04:14:18 +01:00
Implemented authentication for websocket connection
This commit is contained in:
57
src/http.c
57
src/http.c
@@ -18,11 +18,11 @@ check_auth(struct lws *wsi) {
|
|||||||
if (strlen(token) == 0)
|
if (strlen(token) == 0)
|
||||||
continue;
|
continue;
|
||||||
if (i++ == 2) {
|
if (i++ == 2) {
|
||||||
b64_text = strdup(token);
|
b64_text = token;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (b64_text != NULL && strcmp(b64_text, server->credential) == 0)
|
if (b64_text != NULL && !strcmp(b64_text, server->credential))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,18 +51,13 @@ int
|
|||||||
callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) {
|
callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) {
|
||||||
unsigned char buffer[4096 + LWS_PRE], *p, *end;
|
unsigned char buffer[4096 + LWS_PRE], *p, *end;
|
||||||
char buf[256];
|
char buf[256];
|
||||||
int n;
|
|
||||||
|
|
||||||
switch (reason) {
|
switch (reason) {
|
||||||
case LWS_CALLBACK_HTTP:
|
case LWS_CALLBACK_HTTP:
|
||||||
lwsl_notice("lws_http_serve: %s\n", in);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
char name[100], rip[50];
|
char name[100], rip[50];
|
||||||
lws_get_peer_addresses(wsi, lws_get_socket_fd(wsi), name,
|
lws_get_peer_addresses(wsi, lws_get_socket_fd(wsi), name, sizeof(name), rip, sizeof(rip));
|
||||||
sizeof(name), rip, sizeof(rip));
|
lwsl_notice("HTTP connect from %s (%s), path: %s\n", name, rip, in);
|
||||||
sprintf(buf, "%s (%s)", name, rip);
|
|
||||||
lwsl_notice("HTTP connect from %s\n", buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len < 1) {
|
if (len < 1) {
|
||||||
@@ -70,7 +65,6 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, voi
|
|||||||
goto try_to_reuse;
|
goto try_to_reuse;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: this doesn't work for websocket
|
|
||||||
switch (check_auth(wsi)) {
|
switch (check_auth(wsi)) {
|
||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
@@ -85,37 +79,54 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, voi
|
|||||||
if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI))
|
if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (strcmp((const char *) in, "/")) {
|
p = buffer + LWS_PRE;
|
||||||
|
end = p + sizeof(buffer) - LWS_PRE;
|
||||||
|
|
||||||
|
if (!strncmp((const char *)in, "/auth_token.js", 14)) {
|
||||||
|
size_t n = server->credential != NULL ? sprintf(buf, "var tty_auth_token = '%s';", server->credential) : 0;
|
||||||
|
|
||||||
|
if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end))
|
||||||
|
return 1;
|
||||||
|
if (lws_add_http_header_by_token(wsi,
|
||||||
|
WSI_TOKEN_HTTP_CONTENT_TYPE,
|
||||||
|
(unsigned char *) "application/javascript",
|
||||||
|
22, &p, end))
|
||||||
|
return 1;
|
||||||
|
if (lws_add_http_header_content_length(wsi, (unsigned long) n, &p, end))
|
||||||
|
return 1;
|
||||||
|
if (lws_finalize_http_header(wsi, &p, end))
|
||||||
|
return 1;
|
||||||
|
if (lws_write(wsi, buffer + LWS_PRE, p - (buffer + LWS_PRE), LWS_WRITE_HTTP_HEADERS) < 0)
|
||||||
|
return 1;
|
||||||
|
if (n > 0 && lws_write_http(wsi, buf, n) < 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
goto try_to_reuse;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strncmp((const char *) in, "/", 1)) {
|
||||||
lws_return_http_status(wsi, HTTP_STATUS_NOT_FOUND, NULL);
|
lws_return_http_status(wsi, HTTP_STATUS_NOT_FOUND, NULL);
|
||||||
goto try_to_reuse;
|
goto try_to_reuse;
|
||||||
}
|
}
|
||||||
|
|
||||||
p = buffer + LWS_PRE;
|
if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end))
|
||||||
end = p + sizeof(buffer) - LWS_PRE;
|
|
||||||
|
|
||||||
if (lws_add_http_header_status(wsi, 200, &p, end))
|
|
||||||
return 1;
|
return 1;
|
||||||
if (lws_add_http_header_by_token(wsi,
|
if (lws_add_http_header_by_token(wsi,
|
||||||
WSI_TOKEN_HTTP_CONTENT_TYPE,
|
WSI_TOKEN_HTTP_CONTENT_TYPE,
|
||||||
(unsigned char *) "text/html",
|
(unsigned char *) "text/html",
|
||||||
9, &p, end))
|
9, &p, end))
|
||||||
return 1;
|
return 1;
|
||||||
if (lws_add_http_header_content_length(wsi, index_html_len, &p, end))
|
if (lws_add_http_header_content_length(wsi, (unsigned long) index_html_len, &p, end))
|
||||||
return 1;
|
return 1;
|
||||||
if (lws_finalize_http_header(wsi, &p, end))
|
if (lws_finalize_http_header(wsi, &p, end))
|
||||||
return 1;
|
return 1;
|
||||||
n = lws_write(wsi, buffer + LWS_PRE, p - (buffer + LWS_PRE), LWS_WRITE_HTTP_HEADERS);
|
if (lws_write(wsi, buffer + LWS_PRE, p - (buffer + LWS_PRE), LWS_WRITE_HTTP_HEADERS) < 0) {
|
||||||
if (n < 0) {
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
n = lws_write_http(wsi, index_html, index_html_len);
|
if (lws_write_http(wsi, index_html, index_html_len) < 0)
|
||||||
if (n < 0)
|
|
||||||
return 1;
|
return 1;
|
||||||
goto try_to_reuse;
|
goto try_to_reuse;
|
||||||
case LWS_CALLBACK_HTTP_WRITEABLE:
|
|
||||||
lwsl_info("LWS_CALLBACK_HTTP_WRITEABLE\n");
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
9
src/index.html
vendored
9
src/index.html
vendored
@@ -571,6 +571,7 @@
|
|||||||
"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"+
|
||||||
"m2L/kruPM6Q7oz4tvDQy+bZ3HzOi+gNHA4DZEgA="+"");lib.resource.add("hterm/concat/date","text/plain","Sat, 10 Sep 2016 08:51:57 +0000"+"");lib.resource.add("hterm/changelog/version","text/plain","1.58"+"");lib.resource.add("hterm/changelog/date","text/plain","2016-07-12"+"");lib.resource.add("hterm/git/HEAD","text/plain","49f8641dd055afaad9eadcd8553804eff0dd2637"+"");</script>
|
"m2L/kruPM6Q7oz4tvDQy+bZ3HzOi+gNHA4DZEgA="+"");lib.resource.add("hterm/concat/date","text/plain","Sat, 10 Sep 2016 08:51:57 +0000"+"");lib.resource.add("hterm/changelog/version","text/plain","1.58"+"");lib.resource.add("hterm/changelog/date","text/plain","2016-07-12"+"");lib.resource.add("hterm/git/HEAD","text/plain","49f8641dd055afaad9eadcd8553804eff0dd2637"+"");</script>
|
||||||
|
<script src="auth_token.js"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
(function() {
|
(function() {
|
||||||
var httpsEnabled = window.location.protocol == "https:";
|
var httpsEnabled = window.location.protocol == "https:";
|
||||||
@@ -580,12 +581,12 @@
|
|||||||
|
|
||||||
var openWs = function() {
|
var openWs = function() {
|
||||||
var ws = new WebSocket(url, protocols);
|
var ws = new WebSocket(url, protocols);
|
||||||
|
var term, pingTimer;
|
||||||
var term;
|
|
||||||
|
|
||||||
var pingTimer;
|
|
||||||
|
|
||||||
ws.onopen = function(event) {
|
ws.onopen = function(event) {
|
||||||
|
if (typeof tty_auth_token !== 'undefined') {
|
||||||
|
ws.send(JSON.stringify({AuthToken: tty_auth_token}));
|
||||||
|
}
|
||||||
pingTimer = setInterval(sendPing, 30 * 1000, ws);
|
pingTimer = setInterval(sendPing, 30 * 1000, ws);
|
||||||
|
|
||||||
hterm.defaultStorage = new lib.Storage.Local();
|
hterm.defaultStorage = new lib.Storage.Local();
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#define INPUT '0'
|
#define INPUT '0'
|
||||||
#define PING '1'
|
#define PING '1'
|
||||||
#define RESIZE_TERMINAL '2'
|
#define RESIZE_TERMINAL '2'
|
||||||
|
#define JSON_DATA '{'
|
||||||
|
|
||||||
// server message
|
// server message
|
||||||
#define OUTPUT '0'
|
#define OUTPUT '0'
|
||||||
@@ -158,6 +159,7 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
|
|||||||
case LWS_CALLBACK_ESTABLISHED:
|
case LWS_CALLBACK_ESTABLISHED:
|
||||||
client->exit = false;
|
client->exit = false;
|
||||||
client->initialized = false;
|
client->initialized = false;
|
||||||
|
client->authenticated = false;
|
||||||
client->wsi = wsi;
|
client->wsi = wsi;
|
||||||
lws_get_peer_addresses(wsi, lws_get_socket_fd(wsi),
|
lws_get_peer_addresses(wsi, lws_get_socket_fd(wsi),
|
||||||
client->hostname, sizeof(client->hostname),
|
client->hostname, sizeof(client->hostname),
|
||||||
@@ -165,7 +167,7 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
|
|||||||
STAILQ_INIT(&client->queue);
|
STAILQ_INIT(&client->queue);
|
||||||
if (pthread_create(&client->thread, NULL, thread_run_command, client) != 0) {
|
if (pthread_create(&client->thread, NULL, thread_run_command, client) != 0) {
|
||||||
lwsl_err("pthread_create\n");
|
lwsl_err("pthread_create\n");
|
||||||
return 1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_lock(&server->lock);
|
pthread_mutex_lock(&server->lock);
|
||||||
@@ -222,6 +224,13 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
|
|||||||
case LWS_CALLBACK_RECEIVE:
|
case LWS_CALLBACK_RECEIVE:
|
||||||
data = (char *) in;
|
data = (char *) in;
|
||||||
char command = data[0];
|
char command = data[0];
|
||||||
|
|
||||||
|
// check auth
|
||||||
|
if (server->credential != NULL && !client->authenticated && command != JSON_DATA) {
|
||||||
|
lwsl_notice("websocket authentication failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
switch (command) {
|
switch (command) {
|
||||||
case INPUT:
|
case INPUT:
|
||||||
if (write(client->pty, data + 1, len - 1) < len - 1) {
|
if (write(client->pty, data + 1, len - 1) < len - 1) {
|
||||||
@@ -247,6 +256,22 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
|
|||||||
t_free(size);
|
t_free(size);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case JSON_DATA:
|
||||||
|
if (server->credential == NULL)
|
||||||
|
break;
|
||||||
|
{
|
||||||
|
json_object *obj = json_tokener_parse(data);
|
||||||
|
struct json_object *o = NULL;
|
||||||
|
if (json_object_object_get_ex(obj, "AuthToken", &o)) {
|
||||||
|
const char *token = json_object_get_string(o);
|
||||||
|
if (strcmp(token, server->credential)) {
|
||||||
|
lwsl_notice("websocket authentication failed with token: %s\n", token);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
client->authenticated = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
lwsl_notice("unknown message type: %c\n", command);
|
lwsl_notice("unknown message type: %c\n", command);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -18,9 +18,7 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
|
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#include <pty.h>
|
#include <pty.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -43,6 +41,7 @@ struct pty_data {
|
|||||||
struct tty_client {
|
struct tty_client {
|
||||||
bool exit;
|
bool exit;
|
||||||
bool initialized;
|
bool initialized;
|
||||||
|
bool authenticated;
|
||||||
char hostname[100];
|
char hostname[100];
|
||||||
char address[50];
|
char address[50];
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ t_malloc(size_t size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void t_free(void *p) {
|
void t_free(void *p) {
|
||||||
if (p)
|
|
||||||
free(p);
|
free(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user