This commit is contained in:
Felicia Seo 2022-12-11 19:10:09 -05:00
parent f93671ac58
commit 269ac0c501
2 changed files with 41 additions and 20 deletions

View File

@ -118,35 +118,45 @@ http_process_headers(struct http_transaction *ta)
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
* are zero-terminated strings.
*/
// Cookie header
if (!strcasecmp(field_name, "Cookie")) {
// Gets the cookies.
char* cookie2;
char* cookie1 = strtok_r(field_value, ";", &cookie2);
cookie2++;
// Stores the 2nd cookie.
ta->extra_cookie = cookie2;
// Determines if the 1st cookie is invalid.
if ((cookie1 == NULL) || (strlen(cookie1) <= 11))
{
ta->resp_status = HTTP_PERMISSION_DENIED;
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);
}
// Range header
if (!strcasecmp(field_name, "Range")){
// Gets token.
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);
// Determines if the token exist.
if (token != NULL) {
if (token[0] == '-') {
ta->to = atol(token + 1);
@ -361,8 +371,6 @@ 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;
@ -463,12 +471,14 @@ out:
return success;
}
/* Handles api/login POST */
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);
// Gets the username and password.
req_body[ta->req_content_len] = '\0';
json_error_t 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, "???");
}
// Authenticates the username and password.
if (!strcmp(username, "user0") && !strcmp(password, "thepassword"))
{
int iat = time(NULL);
@ -527,21 +538,22 @@ post_handle_login(struct http_transaction *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) {
http_add_header(&ta->resp_headers, "Content-Type", "application/json");
// Determines if the token is invalid.
if (!ta->valid_token) {
buffer_appends(&ta->resp_body, "{}");
ta->resp_status = HTTP_OK;
return send_response(ta);
}
// If not, send response.
buffer_appends(&ta->resp_body, ta->grants);
ta->resp_status = HTTP_OK;
return send_response(ta);
}
@ -585,7 +597,7 @@ static char *list_videos(DIR* dir) {
return json_dumps(list, 0);
}
/* Determines what the API request is. */
static int val_api_url(struct http_transaction *ta) {
char *req_path = bufio_offset2ptr(ta->client->bufio, ta->req_path);
if (!strcmp(req_path, "/api/login")) {
@ -600,6 +612,8 @@ static int val_api_url(struct http_transaction *ta) {
return -1;
}
/* Handles API requests like login/logout/video. */
static bool
handle_api(struct http_transaction *ta)
{
@ -609,6 +623,7 @@ handle_api(struct http_transaction *ta)
return send_not_found(ta);
}
// API login
if (val == 0) {
if (ta->req_method == HTTP_POST) {
// Handle login post
@ -625,24 +640,26 @@ handle_api(struct http_transaction *ta)
}
}
// API video
if (val == 1) {
http_add_header(&ta->resp_headers, "Accept-Ranges", "bytes");
DIR* dir = opendir(server_root);
char *json = list_videos(dir);
char *json = list_videos(dir); // handling
fprintf(stderr, "json: %s\n", 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);
int len = snprintf(body, strlen(json) + 2, "%s\n", json);
int length = len > MAX_HEADER_LEN ? MAX_HEADER_LEN - 1 : len;
ta->resp_body.len += length;
ta->resp_status = HTTP_OK;
return send_response(ta);
}
if (val == 2) // handles logout
// API logout
if (val == 2)
{
// Add Set-Cookie header.
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;
}
/* Handles attempts to access private files. */
static bool
handle_private(struct http_transaction *ta)
{
// Determines if the token from the 1st cookie is valid.
if (ta->valid_token) {
ta->resp_status = HTTP_OK;
return handle_static_asset(ta, server_root);
}
// Determines if there's a 2nd cookie.
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->valid_token = validate_token_exp(ta, ta->token);
// valid
if (ta->valid_token) {
ta->resp_status = HTTP_OK;
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. */

View File

@ -40,12 +40,11 @@ struct http_transaction {
size_t req_body; // ditto
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
bool valid_token;
long exp;
char* grants;
char *token; // authentication token
bool valid_token; // true if valid, false if not.
char* grants; // exp, iat, sub
/* response related fields */
enum http_response_status resp_status;