Skip to content

Commit

Permalink
http: add basic auth support back
Browse files Browse the repository at this point in the history
  • Loading branch information
tsl0922 committed Jun 22, 2019
1 parent c1c82b1 commit ae83791
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 54 deletions.
11 changes: 9 additions & 2 deletions html/src/components/terminal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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();
}

Expand Down
118 changes: 67 additions & 51 deletions src/http.c
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand All @@ -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;

pss->buffer = pss->ptr = body;
pss->len = n;
lws_callback_on_writable(wsi);

return -1;
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;
}
Expand All @@ -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,
Expand All @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/index.html

Large diffs are not rendered by default.

0 comments on commit ae83791

Please sign in to comment.