Files
ttyd/http.c
2016-09-17 11:58:40 +08:00

132 lines
4.2 KiB
C

#include "server.h"
#include "html.h"
int
check_auth(struct lws *wsi) {
if (server->credential == NULL)
return 0;
int hdr_length = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_AUTHORIZATION);
char buf[hdr_length + 1];
int len = lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_HTTP_AUTHORIZATION);
if (len > 0) {
// extract base64 text from authorization header
char *ptr = &buf[0];
char *token, *b64_text = NULL;
int i = 1;
while ((token = strsep(&ptr, " ")) != NULL) {
if (strlen(token) == 0)
continue;
if (i++ == 2) {
b64_text = strdup(token);
break;
}
}
if (b64_text != NULL && strcmp(b64_text, server->credential) == 0)
return 0;
}
unsigned char buffer[1024 + LWS_PRE], *p, *end;
p = buffer + LWS_PRE;
end = p + sizeof(buffer) - LWS_PRE;
if (lws_add_http_header_status(wsi, HTTP_STATUS_UNAUTHORIZED, &p, end))
return 1;
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;
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;
return -1;
}
int
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;
char buf[256];
int n;
switch (reason) {
case LWS_CALLBACK_HTTP:
lwsl_notice("lws_http_serve: %s\n", in);
{
char name[100], rip[50];
lws_get_peer_addresses(wsi, lws_get_socket_fd(wsi), name,
sizeof(name), rip, sizeof(rip));
sprintf(buf, "%s (%s)", name, rip);
lwsl_notice("HTTP connect from %s\n", buf);
}
if (len < 1) {
lws_return_http_status(wsi, HTTP_STATUS_BAD_REQUEST, NULL);
goto try_to_reuse;
}
// TODO: this doesn't work for websocket
switch (check_auth(wsi)) {
case 1:
return 1;
case -1:
goto try_to_reuse;
case 0:
default:
break;
}
// if a legal POST URL, let it continue and accept data
if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI))
return 0;
if (strcmp((const char *) in, "/")) {
lws_return_http_status(wsi, HTTP_STATUS_NOT_FOUND, NULL);
goto try_to_reuse;
}
p = buffer + LWS_PRE;
end = p + sizeof(buffer) - LWS_PRE;
if (lws_add_http_header_status(wsi, 200, &p, end))
return 1;
if (lws_add_http_header_by_token(wsi,
WSI_TOKEN_HTTP_CONTENT_TYPE,
(unsigned char *) "text/html",
9, &p, end))
return 1;
if (lws_add_http_header_content_length(wsi, index_html_len, &p, end))
return 1;
if (lws_finalize_http_header(wsi, &p, end))
return 1;
n = lws_write(wsi, buffer + LWS_PRE, p - (buffer + LWS_PRE), LWS_WRITE_HTTP_HEADERS);
if (n < 0) {
return 1;
}
n = lws_write_http(wsi, index_html, index_html_len);
if (n < 0)
return 1;
goto try_to_reuse;
case LWS_CALLBACK_HTTP_WRITEABLE:
lwsl_info("LWS_CALLBACK_HTTP_WRITEABLE\n");
break;
default:
break;
}
return 0;
/* if we're on HTTP1.1 or 2.0, will keep the idle connection alive */
try_to_reuse:
if (lws_http_transaction_completed(wsi))
return -1;
return 0;
}