~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
|
||||
http_process_headers(struct http_transaction *ta)
|
||||
{
|
||||
ta->from = -1;
|
||||
ta->to = -1;
|
||||
for (;;) {
|
||||
size_t 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.
|
||||
*/
|
||||
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;
|
||||
printf("%s\n", field_value);
|
||||
}
|
||||
ta->token = field_value + 11; // + 11 gets rid of "auth_token=" heading.
|
||||
|
||||
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"))
|
||||
return "text/javascript";
|
||||
|
||||
if (!strcasecmp(suffix, ".mp4"))
|
||||
return "video/mp4";
|
||||
|
||||
return "text/plain";
|
||||
}
|
||||
@ -305,12 +339,12 @@ bool validate_token_exp(struct http_transaction *ta, char* 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));
|
||||
if (rc)
|
||||
return send_error(ta, HTTP_OK, "{}");
|
||||
return false;
|
||||
|
||||
// Get claim (formatted grants).
|
||||
char* grants = jwt_get_grants_json(cookie, NULL);
|
||||
if (grants == NULL)
|
||||
return send_error(ta, HTTP_OK, "{}");
|
||||
return false;
|
||||
ta->grants = grants;
|
||||
|
||||
// Get expiration time.
|
||||
@ -320,6 +354,8 @@ bool validate_token_exp(struct http_transaction *ta, char* token) {
|
||||
const char *sub;
|
||||
json_unpack(jgrants, "{s:I, s:I, s:s}", "exp", &exp, "iat", &iat, "sub", &sub);
|
||||
|
||||
ta->exp = exp;
|
||||
|
||||
// Check expiration time.
|
||||
if (time(NULL) >= exp)
|
||||
return false;
|
||||
@ -327,7 +363,7 @@ bool validate_token_exp(struct http_transaction *ta, char* token) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Handle HTTP transaction for static files. */
|
||||
/* Handle HTTP transaction for static files. */
|
||||
static bool
|
||||
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));
|
||||
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;
|
||||
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);
|
||||
if (!success)
|
||||
goto out;
|
||||
@ -399,22 +454,26 @@ handle_static_asset(struct http_transaction *ta, char *basedir)
|
||||
out:
|
||||
close(filefd);
|
||||
return success;
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
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* saveptr;
|
||||
req_body++;
|
||||
char* u_heading = strtok_r(req_body, ":", &saveptr);
|
||||
char* username = strtok_r(NULL, ",", &saveptr);
|
||||
char* p_heading = strtok_r(NULL, ":", &saveptr);
|
||||
char* password = strtok_r(NULL, "}", &saveptr);
|
||||
req_body[ta->req_content_len] = '\0';
|
||||
json_error_t error;
|
||||
json_t *jgrants = json_loadb(req_body, strlen(req_body), 0, &error);
|
||||
const char *username;
|
||||
const char *password;
|
||||
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)
|
||||
&& !strcmp(p_heading, "\"password\"") && (strlen(password)) > 2)
|
||||
if (!strcmp(username, "user0") && !strcmp(password, "thepassword"))
|
||||
{
|
||||
// Create cookie.
|
||||
jwt_t* cookie;
|
||||
@ -423,8 +482,6 @@ post_handle_login(struct http_transaction *ta)
|
||||
return send_error(ta, HTTP_INTERNAL_ERROR, "jwt_new");
|
||||
|
||||
// Add grants.
|
||||
username++;
|
||||
username = strtok_r(username, "\"", &saveptr);
|
||||
rc = jwt_add_grant(cookie, "sub", username);
|
||||
if (rc)
|
||||
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).
|
||||
char *grants = jwt_get_grants_json(cookie, NULL);
|
||||
buffer_appends(&ta->resp_body, grants);
|
||||
buffer_appends(&ta->resp_body, CRLF);
|
||||
|
||||
// Send claim.
|
||||
ta->resp_status = HTTP_OK;
|
||||
return send_response(ta);
|
||||
}
|
||||
|
||||
return false;
|
||||
return send_error(ta, HTTP_PERMISSION_DENIED, "???");
|
||||
}
|
||||
|
||||
|
||||
static bool get_handle_login(struct http_transaction *ta) {
|
||||
http_add_header(&ta->resp_headers, "Content-Type", "application/json");
|
||||
|
||||
|
||||
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, CRLF);
|
||||
|
||||
ta->resp_status = HTTP_OK;
|
||||
return send_response(ta);
|
||||
@ -581,14 +633,13 @@ handle_api(struct http_transaction *ta)
|
||||
|
||||
return send_response(ta);
|
||||
}
|
||||
if (ta->req_method == HTTP_POST) // handles logout
|
||||
if (val == 2) // handles logout
|
||||
{
|
||||
// Add Set-Cookie header.
|
||||
http_add_header(&ta->resp_headers, "Set-Cookie", "auth_token=; Path=/; Max-Age=0; HttpOnly");
|
||||
|
||||
// Send message.
|
||||
buffer_appends(&ta->resp_body, "{\"message\":\"logging out\"}");
|
||||
buffer_appends(&ta->resp_body, CRLF);
|
||||
ta->resp_status = HTTP_OK;
|
||||
return send_response(ta);
|
||||
}
|
||||
@ -608,9 +659,10 @@ static bool
|
||||
handle_private(struct http_transaction *ta)
|
||||
{
|
||||
if (ta->valid_token) {
|
||||
ta->resp_status = HTTP_OK;
|
||||
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. */
|
||||
@ -627,10 +679,10 @@ http_handle_transaction(struct http_client *self)
|
||||
bool is_http_1_1 = false; // false
|
||||
if (ta.req_version == HTTP_1_1)
|
||||
is_http_1_1 = true; // true
|
||||
|
||||
|
||||
if (!http_process_headers(&ta))
|
||||
return false;
|
||||
|
||||
|
||||
if (ta.req_content_len > 0) {
|
||||
int rc = bufio_read(self->bufio, ta.req_content_len, &ta.req_body);
|
||||
if (rc != ta.req_content_len)
|
||||
|
@ -42,6 +42,7 @@ struct http_transaction {
|
||||
|
||||
char *token; // authentication token
|
||||
bool valid_token;
|
||||
long exp;
|
||||
char* grants;
|
||||
|
||||
/* response related fields */
|
||||
@ -50,6 +51,10 @@ struct http_transaction {
|
||||
buffer_t resp_body;
|
||||
|
||||
struct http_client *client;
|
||||
|
||||
off_t from; // range from
|
||||
off_t to; // range to
|
||||
bool range_request;
|
||||
};
|
||||
|
||||
struct http_client {
|
||||
|
@ -73,8 +73,8 @@ socket_open_bind_listen(char * port_number_string, int backlog)
|
||||
/* Skip any non-IPv4 addresses.
|
||||
* Adding support for protocol independence/IPv6 is part of the project.
|
||||
*/
|
||||
if (pinfo->ai_family != AF_INET)
|
||||
continue;
|
||||
//if (pinfo->ai_family != AF_INET)
|
||||
//continue;
|
||||
|
||||
int s = socket(pinfo->ai_family, pinfo->ai_socktype, pinfo->ai_protocol);
|
||||
if (s == -1) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user