comments
This commit is contained in:
parent
f93671ac58
commit
269ac0c501
52
src/http.c
52
src/http.c
@ -118,35 +118,45 @@ http_process_headers(struct http_transaction *ta)
|
|||||||
ta->req_content_len = atoi(field_value);
|
ta->req_content_len = atoi(field_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
ta->valid_token = false; // special case?
|
ta->valid_token = false;
|
||||||
/* Handle other headers here. Both field_value and field_name
|
/* Handle other headers here. Both field_value and field_name
|
||||||
* are zero-terminated strings.
|
* are zero-terminated strings.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Cookie header
|
||||||
if (!strcasecmp(field_name, "Cookie")) {
|
if (!strcasecmp(field_name, "Cookie")) {
|
||||||
|
|
||||||
|
// Gets the cookies.
|
||||||
char* cookie2;
|
char* cookie2;
|
||||||
char* cookie1 = strtok_r(field_value, ";", &cookie2);
|
char* cookie1 = strtok_r(field_value, ";", &cookie2);
|
||||||
cookie2++;
|
cookie2++;
|
||||||
|
|
||||||
|
// Stores the 2nd cookie.
|
||||||
ta->extra_cookie = cookie2;
|
ta->extra_cookie = cookie2;
|
||||||
|
|
||||||
|
// Determines if the 1st cookie is invalid.
|
||||||
if ((cookie1 == NULL) || (strlen(cookie1) <= 11))
|
if ((cookie1 == NULL) || (strlen(cookie1) <= 11))
|
||||||
{
|
{
|
||||||
ta->resp_status = HTTP_PERMISSION_DENIED;
|
ta->resp_status = HTTP_PERMISSION_DENIED;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ta->token = cookie1 + 11; // + 11 gets rid of "auth_token=" heading.
|
|
||||||
|
|
||||||
|
// If not, find token.
|
||||||
|
ta->token = cookie1 + 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Range header
|
||||||
if (!strcasecmp(field_name, "Range")){
|
if (!strcasecmp(field_name, "Range")){
|
||||||
|
// Gets token.
|
||||||
char *endp;
|
char *endp;
|
||||||
char *token = strtok_r(field_value, "= ", &endp);
|
char *token = strtok_r(field_value, "= ", &endp);
|
||||||
while (token != NULL && strcasecmp(token, "bytes")) {
|
while (token != NULL && strcasecmp(token, "bytes")) {
|
||||||
token = strtok_r(NULL, "= ", &endp);
|
token = strtok_r(NULL, "= ", &endp);
|
||||||
}
|
}
|
||||||
token = strtok_r(NULL, "= ", &endp);
|
token = strtok_r(NULL, "= ", &endp);
|
||||||
|
|
||||||
|
// Determines if the token exist.
|
||||||
if (token != NULL) {
|
if (token != NULL) {
|
||||||
if (token[0] == '-') {
|
if (token[0] == '-') {
|
||||||
ta->to = atol(token + 1);
|
ta->to = atol(token + 1);
|
||||||
@ -361,8 +371,6 @@ 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;
|
||||||
@ -463,12 +471,14 @@ out:
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Handles api/login POST */
|
||||||
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");
|
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);
|
||||||
|
|
||||||
|
// Gets the username and password.
|
||||||
req_body[ta->req_content_len] = '\0';
|
req_body[ta->req_content_len] = '\0';
|
||||||
json_error_t error;
|
json_error_t error;
|
||||||
json_t *jgrants = json_loadb(req_body, strlen(req_body), 0, &error);
|
json_t *jgrants = json_loadb(req_body, strlen(req_body), 0, &error);
|
||||||
@ -480,6 +490,7 @@ post_handle_login(struct http_transaction *ta)
|
|||||||
return send_error(ta, HTTP_PERMISSION_DENIED, "???");
|
return send_error(ta, HTTP_PERMISSION_DENIED, "???");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Authenticates the username and password.
|
||||||
if (!strcmp(username, "user0") && !strcmp(password, "thepassword"))
|
if (!strcmp(username, "user0") && !strcmp(password, "thepassword"))
|
||||||
{
|
{
|
||||||
int iat = time(NULL);
|
int iat = time(NULL);
|
||||||
@ -527,21 +538,22 @@ post_handle_login(struct http_transaction *ta)
|
|||||||
return send_response(ta);
|
return send_response(ta);
|
||||||
}
|
}
|
||||||
|
|
||||||
return send_error(ta, HTTP_PERMISSION_DENIED, "???");
|
return send_error(ta, HTTP_PERMISSION_DENIED, "Permission denied");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Handles api/login GET */
|
||||||
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");
|
||||||
|
|
||||||
|
// Determines if the token is invalid.
|
||||||
if (!ta->valid_token) {
|
if (!ta->valid_token) {
|
||||||
buffer_appends(&ta->resp_body, "{}");
|
buffer_appends(&ta->resp_body, "{}");
|
||||||
ta->resp_status = HTTP_OK;
|
ta->resp_status = HTTP_OK;
|
||||||
return send_response(ta);
|
return send_response(ta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If not, send response.
|
||||||
buffer_appends(&ta->resp_body, ta->grants);
|
buffer_appends(&ta->resp_body, ta->grants);
|
||||||
|
|
||||||
ta->resp_status = HTTP_OK;
|
ta->resp_status = HTTP_OK;
|
||||||
return send_response(ta);
|
return send_response(ta);
|
||||||
}
|
}
|
||||||
@ -585,7 +597,7 @@ static char *list_videos(DIR* dir) {
|
|||||||
return json_dumps(list, 0);
|
return json_dumps(list, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Determines what the API request is. */
|
||||||
static int val_api_url(struct http_transaction *ta) {
|
static int val_api_url(struct http_transaction *ta) {
|
||||||
char *req_path = bufio_offset2ptr(ta->client->bufio, ta->req_path);
|
char *req_path = bufio_offset2ptr(ta->client->bufio, ta->req_path);
|
||||||
if (!strcmp(req_path, "/api/login")) {
|
if (!strcmp(req_path, "/api/login")) {
|
||||||
@ -600,6 +612,8 @@ static int val_api_url(struct http_transaction *ta) {
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Handles API requests like login/logout/video. */
|
||||||
static bool
|
static bool
|
||||||
handle_api(struct http_transaction *ta)
|
handle_api(struct http_transaction *ta)
|
||||||
{
|
{
|
||||||
@ -609,6 +623,7 @@ handle_api(struct http_transaction *ta)
|
|||||||
return send_not_found(ta);
|
return send_not_found(ta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// API login
|
||||||
if (val == 0) {
|
if (val == 0) {
|
||||||
if (ta->req_method == HTTP_POST) {
|
if (ta->req_method == HTTP_POST) {
|
||||||
// Handle login post
|
// Handle login post
|
||||||
@ -625,24 +640,26 @@ handle_api(struct http_transaction *ta)
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
// API video
|
||||||
if (val == 1) {
|
if (val == 1) {
|
||||||
http_add_header(&ta->resp_headers, "Accept-Ranges", "bytes");
|
http_add_header(&ta->resp_headers, "Accept-Ranges", "bytes");
|
||||||
|
|
||||||
DIR* dir = opendir(server_root);
|
DIR* dir = opendir(server_root);
|
||||||
char *json = list_videos(dir);
|
char *json = list_videos(dir); // handling
|
||||||
fprintf(stderr, "json: %s\n", json);
|
fprintf(stderr, "json: %s\n", json);
|
||||||
|
|
||||||
http_add_header(&ta->resp_headers, "Content-Type", "application/json");
|
http_add_header(&ta->resp_headers, "Content-Type", "application/json");
|
||||||
|
|
||||||
|
// Ensures response can be sent and sends it.
|
||||||
char *body = buffer_ensure_capacity(&ta->resp_body, MAX_HEADER_LEN);
|
char *body = buffer_ensure_capacity(&ta->resp_body, MAX_HEADER_LEN);
|
||||||
int len = snprintf(body, strlen(json) + 2, "%s\n", json);
|
int len = snprintf(body, strlen(json) + 2, "%s\n", json);
|
||||||
int length = len > MAX_HEADER_LEN ? MAX_HEADER_LEN - 1 : len;
|
int length = len > MAX_HEADER_LEN ? MAX_HEADER_LEN - 1 : len;
|
||||||
ta->resp_body.len += length;
|
ta->resp_body.len += length;
|
||||||
ta->resp_status = HTTP_OK;
|
ta->resp_status = HTTP_OK;
|
||||||
|
|
||||||
return send_response(ta);
|
return send_response(ta);
|
||||||
}
|
}
|
||||||
if (val == 2) // handles logout
|
// API logout
|
||||||
|
if (val == 2)
|
||||||
{
|
{
|
||||||
// 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");
|
||||||
@ -664,28 +681,33 @@ http_setup_client(struct http_client *self, struct bufio *bufio)
|
|||||||
self->bufio = bufio;
|
self->bufio = bufio;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Handles attempts to access private files. */
|
||||||
static bool
|
static bool
|
||||||
handle_private(struct http_transaction *ta)
|
handle_private(struct http_transaction *ta)
|
||||||
{
|
{
|
||||||
|
// Determines if the token from the 1st cookie is valid.
|
||||||
if (ta->valid_token) {
|
if (ta->valid_token) {
|
||||||
ta->resp_status = HTTP_OK;
|
ta->resp_status = HTTP_OK;
|
||||||
return handle_static_asset(ta, server_root);
|
return handle_static_asset(ta, server_root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Determines if there's a 2nd cookie.
|
||||||
if ((ta->extra_cookie == NULL) || (strlen(ta->extra_cookie) <= 11)) {
|
if ((ta->extra_cookie == NULL) || (strlen(ta->extra_cookie) <= 11)) {
|
||||||
return send_error(ta, HTTP_PERMISSION_DENIED, "???");
|
return send_error(ta, HTTP_PERMISSION_DENIED, "Permission denied.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If so, find its token.
|
||||||
ta->token = ta->extra_cookie + 11; // + 11 gets rid of "auth_token=" heading.
|
ta->token = ta->extra_cookie + 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);
|
||||||
|
|
||||||
|
// valid
|
||||||
if (ta->valid_token) {
|
if (ta->valid_token) {
|
||||||
ta->resp_status = HTTP_OK;
|
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, "???");
|
// invalid
|
||||||
|
return send_error(ta, HTTP_PERMISSION_DENIED, "Permission denied.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle a single HTTP transaction. Returns true on success. */
|
/* Handle a single HTTP transaction. Returns true on success. */
|
||||||
|
@ -40,12 +40,11 @@ struct http_transaction {
|
|||||||
size_t req_body; // ditto
|
size_t req_body; // ditto
|
||||||
int req_content_len; // content length of request body
|
int req_content_len; // content length of request body
|
||||||
|
|
||||||
char* extra_cookie;
|
char* extra_cookie; // the 2nd cookie if it exists.
|
||||||
|
|
||||||
char *token; // authentication token
|
char *token; // authentication token
|
||||||
bool valid_token;
|
bool valid_token; // true if valid, false if not.
|
||||||
long exp;
|
char* grants; // exp, iat, sub
|
||||||
char* grants;
|
|
||||||
|
|
||||||
/* response related fields */
|
/* response related fields */
|
||||||
enum http_response_status resp_status;
|
enum http_response_status resp_status;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user