mirror of
https://github.com/tsl0922/ttyd.git
synced 2026-02-19 16:34:22 +01:00
http: add basic auth support back
This commit is contained in:
@@ -7,6 +7,12 @@ import { OverlayAddon } from './overlay';
|
||||
|
||||
import 'xterm/dist/xterm.css';
|
||||
|
||||
export interface IWindowWithTerminal extends Window {
|
||||
term: Terminal;
|
||||
tty_auth_token?: string;
|
||||
}
|
||||
declare let window: IWindowWithTerminal;
|
||||
|
||||
const enum Command {
|
||||
// server side
|
||||
OUTPUT = '0',
|
||||
@@ -86,7 +92,7 @@ export default class Xterm extends Component<Props> {
|
||||
this.socket = new WebSocket(this.props.url, ['tty']);
|
||||
this.terminal = new Terminal(this.props.options);
|
||||
const { socket, terminal, container, fitAddon, overlayAddon } = this;
|
||||
(window as any).term = terminal;
|
||||
window.term = terminal;
|
||||
|
||||
socket.binaryType = 'arraybuffer';
|
||||
socket.onopen = this.onSocketOpen;
|
||||
@@ -121,8 +127,9 @@ export default class Xterm extends Component<Props> {
|
||||
private onSocketOpen() {
|
||||
console.log('[ttyd] Websocket connection opened');
|
||||
const { socket, textEncoder, fitAddon } = this;
|
||||
const authToken = window.tty_auth_token;
|
||||
|
||||
socket.send(textEncoder.encode(JSON.stringify({AuthToken: ''})));
|
||||
socket.send(textEncoder.encode(JSON.stringify({AuthToken: authToken})));
|
||||
fitAddon.fit();
|
||||
}
|
||||
|
||||
|
||||
118
src/http.c
118
src/http.c
@@ -4,10 +4,14 @@
|
||||
#include "server.h"
|
||||
#include "html.h"
|
||||
|
||||
enum {
|
||||
AUTH_OK, AUTH_FAIL, AUTH_ERROR
|
||||
};
|
||||
|
||||
int
|
||||
check_auth(struct lws *wsi) {
|
||||
check_auth(struct lws *wsi, struct pss_http *pss) {
|
||||
if (server->credential == NULL)
|
||||
return 0;
|
||||
return AUTH_OK;
|
||||
|
||||
int hdr_length = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_AUTHORIZATION);
|
||||
char buf[hdr_length + 1];
|
||||
@@ -26,54 +30,64 @@ check_auth(struct lws *wsi) {
|
||||
}
|
||||
}
|
||||
if (b64_text != NULL && !strcmp(b64_text, server->credential))
|
||||
return 0;
|
||||
return AUTH_OK;
|
||||
}
|
||||
|
||||
unsigned char buffer[1024 + LWS_PRE], *p, *end;
|
||||
p = buffer + LWS_PRE;
|
||||
end = p + sizeof(buffer) - LWS_PRE;
|
||||
|
||||
char *body = strdup("401 Unauthorized\n");
|
||||
size_t n = strlen(body);
|
||||
|
||||
if (lws_add_http_header_status(wsi, HTTP_STATUS_UNAUTHORIZED, &p, end))
|
||||
return 1;
|
||||
return AUTH_ERROR;
|
||||
if (lws_add_http_header_by_token(wsi,
|
||||
WSI_TOKEN_HTTP_WWW_AUTHENTICATE,
|
||||
(unsigned char *) "Basic realm=\"ttyd\"",
|
||||
18, &p, end))
|
||||
return 1;
|
||||
if (lws_add_http_header_content_length(wsi, 0, &p, end))
|
||||
return 1;
|
||||
return AUTH_ERROR;
|
||||
if (lws_add_http_header_content_length(wsi, n, &p, end))
|
||||
return AUTH_ERROR;
|
||||
if (lws_finalize_http_header(wsi, &p, end))
|
||||
return 1;
|
||||
return AUTH_ERROR;
|
||||
if (lws_write(wsi, buffer + LWS_PRE, p - (buffer + LWS_PRE), LWS_WRITE_HTTP_HEADERS) < 0)
|
||||
return 1;
|
||||
return AUTH_ERROR;
|
||||
|
||||
return -1;
|
||||
pss->buffer = pss->ptr = body;
|
||||
pss->len = n;
|
||||
lws_callback_on_writable(wsi);
|
||||
|
||||
return AUTH_FAIL;
|
||||
}
|
||||
|
||||
void access_log(struct lws *wsi, const char *path) {
|
||||
char name[100], rip[50];
|
||||
#if LWS_LIBRARY_VERSION_MAJOR >=2 && LWS_LIBRARY_VERSION_MINOR >=4
|
||||
struct lws *n_wsi = lws_get_network_wsi(wsi);
|
||||
#else
|
||||
struct lws *n_wsi = wsi;
|
||||
#endif
|
||||
lws_get_peer_addresses(wsi, lws_get_socket_fd(n_wsi), name, sizeof(name), rip, sizeof(rip));
|
||||
lwsl_notice("HTTP %s - %s (%s)\n", path, rip, name);
|
||||
}
|
||||
|
||||
int
|
||||
callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) {
|
||||
struct pss_http *pss = (struct pss_http *) user;
|
||||
unsigned char buffer[4096 + LWS_PRE], *p, *end;
|
||||
char buf[256], name[100], rip[50];
|
||||
char buf[256];
|
||||
|
||||
switch (reason) {
|
||||
case LWS_CALLBACK_HTTP:
|
||||
// only GET method is allowed
|
||||
if (!lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI) || len < 1) {
|
||||
lws_return_http_status(wsi, HTTP_STATUS_BAD_REQUEST, NULL);
|
||||
goto try_to_reuse;
|
||||
}
|
||||
|
||||
snprintf(pss->path, sizeof(pss->path), "%s", (const char *)in);
|
||||
lws_get_peer_addresses(wsi, lws_get_socket_fd(wsi), name, sizeof(name), rip, sizeof(rip));
|
||||
lwsl_notice("HTTP %s - %s (%s)\n", (char *) in, rip, name);
|
||||
|
||||
switch (check_auth(wsi)) {
|
||||
case 0:
|
||||
access_log(wsi, (const char *) in);
|
||||
snprintf(pss->path, sizeof(pss->path), "%s", (const char *) in);
|
||||
switch (check_auth(wsi, pss)) {
|
||||
case AUTH_OK:
|
||||
break;
|
||||
case -1:
|
||||
goto try_to_reuse;
|
||||
case 1:
|
||||
case AUTH_FAIL:
|
||||
return 0;
|
||||
case AUTH_ERROR:
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
@@ -82,8 +96,8 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, voi
|
||||
end = p + sizeof(buffer) - LWS_PRE;
|
||||
|
||||
if (strncmp(pss->path, "/auth_token.js", 14) == 0) {
|
||||
size_t n = server->credential != NULL ? sprintf(buf, "var tty_auth_token = '%s';", server->credential) : 0;
|
||||
|
||||
const char *credential = server->credential != NULL ? server->credential : "";
|
||||
size_t n = sprintf(buf, "var tty_auth_token = '%s';\n", credential);
|
||||
if (lws_add_http_header_status(wsi, HTTP_STATUS_OK, &p, end))
|
||||
return 1;
|
||||
if (lws_add_http_header_by_token(wsi,
|
||||
@@ -97,13 +111,10 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, voi
|
||||
return 1;
|
||||
if (lws_write(wsi, buffer + LWS_PRE, p - (buffer + LWS_PRE), LWS_WRITE_HTTP_HEADERS) < 0)
|
||||
return 1;
|
||||
if (n > 0) {
|
||||
pss->buffer = pss->ptr = strdup(buf);
|
||||
pss->len = n;
|
||||
lws_callback_on_writable(wsi);
|
||||
break;
|
||||
}
|
||||
goto try_to_reuse;
|
||||
pss->buffer = pss->ptr = strdup(buf);
|
||||
pss->len = n;
|
||||
lws_callback_on_writable(wsi);
|
||||
break;
|
||||
}
|
||||
|
||||
if (strcmp(pss->path, "/") != 0) {
|
||||
@@ -134,26 +145,31 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, voi
|
||||
break;
|
||||
|
||||
case LWS_CALLBACK_HTTP_WRITEABLE:
|
||||
if (pss->len <= 0)
|
||||
goto try_to_reuse;
|
||||
|
||||
if (pss ->ptr - pss->buffer == pss->len) {
|
||||
if (pss->buffer != (char *) index_html) free(pss->buffer);
|
||||
if (!pss->buffer || pss->len <= 0) {
|
||||
goto try_to_reuse;
|
||||
}
|
||||
|
||||
int n = sizeof(buffer) - LWS_PRE;
|
||||
if (pss->ptr - pss->buffer + n > pss->len)
|
||||
n = (int) (pss->len - (pss->ptr - pss->buffer));
|
||||
memcpy(buffer + LWS_PRE, pss->ptr, n);
|
||||
pss->ptr += n;
|
||||
if (lws_write_http(wsi, buffer + LWS_PRE, (size_t) n) < n) {
|
||||
if (pss->buffer != (char *) index_html) free(pss->buffer);
|
||||
return -1;
|
||||
}
|
||||
do {
|
||||
int n = sizeof(buffer) - LWS_PRE;
|
||||
int m = lws_get_peer_write_allowance(wsi);
|
||||
if (m == 0) {
|
||||
lws_callback_on_writable(wsi);
|
||||
return 0;
|
||||
} else if (m != -1 && m < n) {
|
||||
n = m;
|
||||
}
|
||||
if (pss->ptr + n > pss->buffer + pss->len)
|
||||
n = (int) (pss->len - (pss->ptr - pss->buffer));
|
||||
memcpy(buffer + LWS_PRE, pss->ptr, n);
|
||||
pss->ptr += n;
|
||||
if (lws_write_http(wsi, buffer + LWS_PRE, (size_t) n) < n) {
|
||||
if (pss->buffer != (char *) index_html) free(pss->buffer);
|
||||
return -1;
|
||||
}
|
||||
} while (!lws_send_pipe_choked(wsi) && pss->ptr != pss->buffer + pss->len);
|
||||
|
||||
lws_callback_on_writable(wsi);
|
||||
break;
|
||||
if (pss->buffer != (char *) index_html) free(pss->buffer);
|
||||
goto try_to_reuse;
|
||||
|
||||
case LWS_CALLBACK_HTTP_FILE_COMPLETION:
|
||||
goto try_to_reuse;
|
||||
|
||||
2
src/index.html
vendored
2
src/index.html
vendored
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user