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->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. */

View File

@ -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;