~73/95
This commit is contained in:
parent
a874b62771
commit
aeb235246d
114
src/http.c
114
src/http.c
@ -84,6 +84,8 @@ http_parse_request(struct http_transaction *ta)
|
|||||||
static bool
|
static bool
|
||||||
http_process_headers(struct http_transaction *ta)
|
http_process_headers(struct http_transaction *ta)
|
||||||
{
|
{
|
||||||
|
ta->from = -1;
|
||||||
|
ta->to = -1;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
size_t header_offset;
|
size_t header_offset;
|
||||||
ssize_t len = bufio_readline(ta->client->bufio, &header_offset);
|
ssize_t len = bufio_readline(ta->client->bufio, &header_offset);
|
||||||
@ -121,13 +123,42 @@ http_process_headers(struct http_transaction *ta)
|
|||||||
* are zero-terminated strings.
|
* are zero-terminated strings.
|
||||||
*/
|
*/
|
||||||
if (!strcasecmp(field_name, "Cookie")) {
|
if (!strcasecmp(field_name, "Cookie")) {
|
||||||
if ((field_value == NULL) || (strlen(field_value) <= 11)
|
if ((field_value == NULL) || (strlen(field_value) <= 11))
|
||||||
|
{
|
||||||
|
ta->resp_status = HTTP_PERMISSION_DENIED;
|
||||||
return false;
|
return false;
|
||||||
printf("%s\n", field_value);
|
}
|
||||||
ta->token = field_value + 11; // + 11 gets rid of "auth_token=" heading.
|
ta->token = field_value + 11; // + 11 gets rid of "auth_token=" heading.
|
||||||
|
|
||||||
ta->valid_token = validate_token_exp(ta, ta->token);
|
ta->valid_token = validate_token_exp(ta, ta->token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!strcasecmp(field_name, "Range")){
|
||||||
|
char *endp;
|
||||||
|
char *token = strtok_r(field_value, "= ", &endp);
|
||||||
|
while (token != NULL && strcasecmp(token, "bytes")) {
|
||||||
|
token = strtok_r(NULL, "= ", &endp);
|
||||||
|
}
|
||||||
|
token = strtok_r(NULL, "= ", &endp);
|
||||||
|
if (token != NULL) {
|
||||||
|
if (token[0] == '-') {
|
||||||
|
ta->to = atol(token + 1);
|
||||||
|
}
|
||||||
|
else if (token[strlen(token) - 1] == '-') {
|
||||||
|
token[strlen(token) - 1] = '\0';
|
||||||
|
ta->from = atol(token);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
char *to;
|
||||||
|
char *from = strtok_r(token, "- ", &to);
|
||||||
|
ta->from = atol(from);
|
||||||
|
ta->to = atol(to);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ta->range_request = true;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,6 +325,9 @@ guess_mime_type(char *filename)
|
|||||||
|
|
||||||
if (!strcasecmp(suffix, ".js"))
|
if (!strcasecmp(suffix, ".js"))
|
||||||
return "text/javascript";
|
return "text/javascript";
|
||||||
|
|
||||||
|
if (!strcasecmp(suffix, ".mp4"))
|
||||||
|
return "video/mp4";
|
||||||
|
|
||||||
return "text/plain";
|
return "text/plain";
|
||||||
}
|
}
|
||||||
@ -305,12 +339,12 @@ bool validate_token_exp(struct http_transaction *ta, char* token) {
|
|||||||
// Decode token.
|
// Decode token.
|
||||||
int rc = jwt_decode(&cookie, ta->token, (unsigned char *)NEVER_EMBED_A_SECRET_IN_CODE, strlen(NEVER_EMBED_A_SECRET_IN_CODE));
|
int rc = jwt_decode(&cookie, ta->token, (unsigned char *)NEVER_EMBED_A_SECRET_IN_CODE, strlen(NEVER_EMBED_A_SECRET_IN_CODE));
|
||||||
if (rc)
|
if (rc)
|
||||||
return send_error(ta, HTTP_OK, "{}");
|
return false;
|
||||||
|
|
||||||
// Get claim (formatted grants).
|
// Get claim (formatted grants).
|
||||||
char* grants = jwt_get_grants_json(cookie, NULL);
|
char* grants = jwt_get_grants_json(cookie, NULL);
|
||||||
if (grants == NULL)
|
if (grants == NULL)
|
||||||
return send_error(ta, HTTP_OK, "{}");
|
return false;
|
||||||
ta->grants = grants;
|
ta->grants = grants;
|
||||||
|
|
||||||
// Get expiration time.
|
// Get expiration time.
|
||||||
@ -320,6 +354,8 @@ bool validate_token_exp(struct http_transaction *ta, char* token) {
|
|||||||
const char *sub;
|
const char *sub;
|
||||||
json_unpack(jgrants, "{s:I, s:I, s:s}", "exp", &exp, "iat", &iat, "sub", &sub);
|
json_unpack(jgrants, "{s:I, s:I, s:s}", "exp", &exp, "iat", &iat, "sub", &sub);
|
||||||
|
|
||||||
|
ta->exp = exp;
|
||||||
|
|
||||||
// Check expiration time.
|
// Check expiration time.
|
||||||
if (time(NULL) >= exp)
|
if (time(NULL) >= exp)
|
||||||
return false;
|
return false;
|
||||||
@ -327,7 +363,7 @@ bool validate_token_exp(struct http_transaction *ta, char* token) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle HTTP transaction for static files. */
|
/* Handle HTTP transaction for static files. */
|
||||||
static bool
|
static bool
|
||||||
handle_static_asset(struct http_transaction *ta, char *basedir)
|
handle_static_asset(struct http_transaction *ta, char *basedir)
|
||||||
{
|
{
|
||||||
@ -385,9 +421,28 @@ handle_static_asset(struct http_transaction *ta, char *basedir)
|
|||||||
http_add_header(&ta->resp_headers, "Content-Type", "%s", guess_mime_type(fname));
|
http_add_header(&ta->resp_headers, "Content-Type", "%s", guess_mime_type(fname));
|
||||||
off_t from = 0, to = st.st_size - 1;
|
off_t from = 0, to = st.st_size - 1;
|
||||||
|
|
||||||
|
if (ta->range_request) {
|
||||||
|
if (ta->from >= 0) {
|
||||||
|
from = ta->from;
|
||||||
|
}
|
||||||
|
if (ta->to >= 0) {
|
||||||
|
to = ta->to;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
off_t content_length = to + 1 - from;
|
off_t content_length = to + 1 - from;
|
||||||
add_content_length(&ta->resp_headers, content_length);
|
add_content_length(&ta->resp_headers, content_length);
|
||||||
|
|
||||||
|
http_add_header(&ta->resp_headers, "Accept-Ranges", "bytes");
|
||||||
|
|
||||||
|
if (ta->range_request) {
|
||||||
|
ta->resp_status = HTTP_PARTIAL_CONTENT;
|
||||||
|
http_add_header(&ta->resp_headers, "Content-Range",
|
||||||
|
"bytes %ld-%ld/%ld", from, to, st.st_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool success = send_response_header(ta);
|
bool success = send_response_header(ta);
|
||||||
if (!success)
|
if (!success)
|
||||||
goto out;
|
goto out;
|
||||||
@ -399,22 +454,26 @@ handle_static_asset(struct http_transaction *ta, char *basedir)
|
|||||||
out:
|
out:
|
||||||
close(filefd);
|
close(filefd);
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
post_handle_login(struct http_transaction *ta)
|
post_handle_login(struct http_transaction *ta)
|
||||||
{
|
{
|
||||||
|
http_add_header(&ta->resp_headers, "Content-Type", "application/json");
|
||||||
char* req_body = bufio_offset2ptr(ta->client->bufio, ta->req_body);
|
char* req_body = bufio_offset2ptr(ta->client->bufio, ta->req_body);
|
||||||
|
|
||||||
char* saveptr;
|
req_body[ta->req_content_len] = '\0';
|
||||||
req_body++;
|
json_error_t error;
|
||||||
char* u_heading = strtok_r(req_body, ":", &saveptr);
|
json_t *jgrants = json_loadb(req_body, strlen(req_body), 0, &error);
|
||||||
char* username = strtok_r(NULL, ",", &saveptr);
|
const char *username;
|
||||||
char* p_heading = strtok_r(NULL, ":", &saveptr);
|
const char *password;
|
||||||
char* password = strtok_r(NULL, "}", &saveptr);
|
int rc = json_unpack(jgrants, "{s:s, s:s}", "username", &username, "password", &password);
|
||||||
|
if (rc == -1)
|
||||||
|
{
|
||||||
|
return send_error(ta, HTTP_PERMISSION_DENIED, "???");
|
||||||
|
}
|
||||||
|
|
||||||
if (!strcmp(u_heading, "\"username\"") && (strlen(username) > 2)
|
if (!strcmp(username, "user0") && !strcmp(password, "thepassword"))
|
||||||
&& !strcmp(p_heading, "\"password\"") && (strlen(password)) > 2)
|
|
||||||
{
|
{
|
||||||
// Create cookie.
|
// Create cookie.
|
||||||
jwt_t* cookie;
|
jwt_t* cookie;
|
||||||
@ -423,8 +482,6 @@ post_handle_login(struct http_transaction *ta)
|
|||||||
return send_error(ta, HTTP_INTERNAL_ERROR, "jwt_new");
|
return send_error(ta, HTTP_INTERNAL_ERROR, "jwt_new");
|
||||||
|
|
||||||
// Add grants.
|
// Add grants.
|
||||||
username++;
|
|
||||||
username = strtok_r(username, "\"", &saveptr);
|
|
||||||
rc = jwt_add_grant(cookie, "sub", username);
|
rc = jwt_add_grant(cookie, "sub", username);
|
||||||
if (rc)
|
if (rc)
|
||||||
return send_error(ta, HTTP_INTERNAL_ERROR, "jwt_add_grant");
|
return send_error(ta, HTTP_INTERNAL_ERROR, "jwt_add_grant");
|
||||||
@ -455,31 +512,26 @@ post_handle_login(struct http_transaction *ta)
|
|||||||
// Get claim (formatted grants).
|
// Get claim (formatted grants).
|
||||||
char *grants = jwt_get_grants_json(cookie, NULL);
|
char *grants = jwt_get_grants_json(cookie, NULL);
|
||||||
buffer_appends(&ta->resp_body, grants);
|
buffer_appends(&ta->resp_body, grants);
|
||||||
buffer_appends(&ta->resp_body, CRLF);
|
|
||||||
|
|
||||||
// Send claim.
|
// Send claim.
|
||||||
ta->resp_status = HTTP_OK;
|
ta->resp_status = HTTP_OK;
|
||||||
return send_response(ta);
|
return send_response(ta);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return send_error(ta, HTTP_PERMISSION_DENIED, "???");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool get_handle_login(struct http_transaction *ta) {
|
static bool get_handle_login(struct http_transaction *ta) {
|
||||||
http_add_header(&ta->resp_headers, "Content-Type", "application/json");
|
http_add_header(&ta->resp_headers, "Content-Type", "application/json");
|
||||||
|
|
||||||
if (!ta->valid_token) {
|
if (!ta->valid_token) {
|
||||||
return send_error(ta, HTTP_PERMISSION_DENIED,"Permission denied.\n");
|
buffer_appends(&ta->resp_body, "{}");
|
||||||
|
ta->resp_status = HTTP_OK;
|
||||||
|
return send_response(ta);
|
||||||
}
|
}
|
||||||
|
|
||||||
//~ char *json = buffer_ensure_capacity(&ta->resp_body, MAX_HEADER_LEN);
|
|
||||||
//~ int len = snprintf(json, strlen(ta->grants) + 2, "%s\n", ta->grants);
|
|
||||||
//~ int length = len > MAX_HEADER_LEN ? MAX_HEADER_LEN - 1 : len;
|
|
||||||
//~ ta->resp_body.len += length;
|
|
||||||
|
|
||||||
buffer_appends(&ta->resp_body, ta->grants);
|
buffer_appends(&ta->resp_body, ta->grants);
|
||||||
buffer_appends(&ta->resp_body, CRLF);
|
|
||||||
|
|
||||||
ta->resp_status = HTTP_OK;
|
ta->resp_status = HTTP_OK;
|
||||||
return send_response(ta);
|
return send_response(ta);
|
||||||
@ -581,14 +633,13 @@ handle_api(struct http_transaction *ta)
|
|||||||
|
|
||||||
return send_response(ta);
|
return send_response(ta);
|
||||||
}
|
}
|
||||||
if (ta->req_method == HTTP_POST) // handles logout
|
if (val == 2) // handles logout
|
||||||
{
|
{
|
||||||
// Add Set-Cookie header.
|
// Add Set-Cookie header.
|
||||||
http_add_header(&ta->resp_headers, "Set-Cookie", "auth_token=; Path=/; Max-Age=0; HttpOnly");
|
http_add_header(&ta->resp_headers, "Set-Cookie", "auth_token=; Path=/; Max-Age=0; HttpOnly");
|
||||||
|
|
||||||
// Send message.
|
// Send message.
|
||||||
buffer_appends(&ta->resp_body, "{\"message\":\"logging out\"}");
|
buffer_appends(&ta->resp_body, "{\"message\":\"logging out\"}");
|
||||||
buffer_appends(&ta->resp_body, CRLF);
|
|
||||||
ta->resp_status = HTTP_OK;
|
ta->resp_status = HTTP_OK;
|
||||||
return send_response(ta);
|
return send_response(ta);
|
||||||
}
|
}
|
||||||
@ -608,9 +659,10 @@ static bool
|
|||||||
handle_private(struct http_transaction *ta)
|
handle_private(struct http_transaction *ta)
|
||||||
{
|
{
|
||||||
if (ta->valid_token) {
|
if (ta->valid_token) {
|
||||||
|
ta->resp_status = HTTP_OK;
|
||||||
return handle_static_asset(ta, server_root);
|
return handle_static_asset(ta, server_root);
|
||||||
}
|
}
|
||||||
return send_error(ta, HTTP_PERMISSION_DENIED,"Forbidden.\n");
|
return send_error(ta, HTTP_PERMISSION_DENIED, "invalid token");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle a single HTTP transaction. Returns true on success. */
|
/* Handle a single HTTP transaction. Returns true on success. */
|
||||||
@ -627,10 +679,10 @@ http_handle_transaction(struct http_client *self)
|
|||||||
bool is_http_1_1 = false; // false
|
bool is_http_1_1 = false; // false
|
||||||
if (ta.req_version == HTTP_1_1)
|
if (ta.req_version == HTTP_1_1)
|
||||||
is_http_1_1 = true; // true
|
is_http_1_1 = true; // true
|
||||||
|
|
||||||
if (!http_process_headers(&ta))
|
if (!http_process_headers(&ta))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (ta.req_content_len > 0) {
|
if (ta.req_content_len > 0) {
|
||||||
int rc = bufio_read(self->bufio, ta.req_content_len, &ta.req_body);
|
int rc = bufio_read(self->bufio, ta.req_content_len, &ta.req_body);
|
||||||
if (rc != ta.req_content_len)
|
if (rc != ta.req_content_len)
|
||||||
|
@ -42,6 +42,7 @@ struct http_transaction {
|
|||||||
|
|
||||||
char *token; // authentication token
|
char *token; // authentication token
|
||||||
bool valid_token;
|
bool valid_token;
|
||||||
|
long exp;
|
||||||
char* grants;
|
char* grants;
|
||||||
|
|
||||||
/* response related fields */
|
/* response related fields */
|
||||||
@ -50,6 +51,10 @@ struct http_transaction {
|
|||||||
buffer_t resp_body;
|
buffer_t resp_body;
|
||||||
|
|
||||||
struct http_client *client;
|
struct http_client *client;
|
||||||
|
|
||||||
|
off_t from; // range from
|
||||||
|
off_t to; // range to
|
||||||
|
bool range_request;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct http_client {
|
struct http_client {
|
||||||
|
@ -73,8 +73,8 @@ socket_open_bind_listen(char * port_number_string, int backlog)
|
|||||||
/* Skip any non-IPv4 addresses.
|
/* Skip any non-IPv4 addresses.
|
||||||
* Adding support for protocol independence/IPv6 is part of the project.
|
* Adding support for protocol independence/IPv6 is part of the project.
|
||||||
*/
|
*/
|
||||||
if (pinfo->ai_family != AF_INET)
|
//if (pinfo->ai_family != AF_INET)
|
||||||
continue;
|
//continue;
|
||||||
|
|
||||||
int s = socket(pinfo->ai_family, pinfo->ai_socktype, pinfo->ai_protocol);
|
int s = socket(pinfo->ai_family, pinfo->ai_socktype, pinfo->ai_protocol);
|
||||||
if (s == -1) {
|
if (s == -1) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user