post login, post logout, multiclient

This commit is contained in:
Felicia Seo 2022-12-08 08:48:09 -05:00
parent 5516fe8910
commit 724afe49c1
3 changed files with 111 additions and 12 deletions

View File

@ -28,6 +28,8 @@
#include "bufio.h" #include "bufio.h"
#include "main.h" #include "main.h"
static const char * NEVER_EMBED_A_SECRET_IN_CODE = "supa secret";
// Need macros here because of the sizeof // Need macros here because of the sizeof
#define CRLF "\r\n" #define CRLF "\r\n"
#define CR "\r" #define CR "\r"
@ -117,6 +119,10 @@ http_process_headers(struct http_transaction *ta)
/* 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.
*/ */
if (!strcasecmp(field_name, "Cookie")) {
ta->cookie = bufio_ptr2offset(ta->client->bufio, field_name);
ta->token = field_value; // fix this! needs to be just auth_token part
}
} }
} }
@ -152,7 +158,15 @@ add_content_length(buffer_t *res, size_t len)
static void static void
start_response(struct http_transaction * ta, buffer_t *res) start_response(struct http_transaction * ta, buffer_t *res)
{ {
buffer_appends(res, "HTTP/1.0 "); switch (ta->req_version) {
case HTTP_1_0:
buffer_appends(res, "HTTP/1.0 ");
break;
case HTTP_1_1:
default:
buffer_appends(res, "HTTP/1.1 ");
break;
}
switch (ta->resp_status) { switch (ta->resp_status) {
case HTTP_OK: case HTTP_OK:
@ -354,6 +368,68 @@ out:
return success; return success;
} }
static bool
post_handle_login(struct http_transaction *ta)
{
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);
if (!strcmp(u_heading, "\"username\"") && (strlen(username) > 2)
&& !strcmp(p_heading, "\"password\"") && (strlen(password)) > 2)
{
// Create cookie.
jwt_t* cookie;
int rc = jwt_new(&cookie);
if (rc)
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");
time_t age = time(NULL);
rc = jwt_add_grant_int(cookie, "iat", age);
if (rc)
return send_error(ta, HTTP_INTERNAL_ERROR, "jwt_add_grant");
time_t max_age = age + 3600 * 24;
rc = jwt_add_grant_int(cookie, "exp", max_age);
if (rc)
return send_error(ta, HTTP_INTERNAL_ERROR, "jwt_add_grant");
// Set algorithm.
rc = jwt_set_alg(cookie, JWT_ALG_HS256, (unsigned char *)NEVER_EMBED_A_SECRET_IN_CODE, strlen(NEVER_EMBED_A_SECRET_IN_CODE));
if (rc)
return send_error(ta, HTTP_INTERNAL_ERROR, "jwt_set_alg");
// Create token.
char* token = jwt_encode_str(cookie);
if (token == NULL)
return send_error(ta, HTTP_INTERNAL_ERROR, "jwt_encode_str");
// Add Set-Cookie header.
http_add_header(&ta->resp_headers, "Set-Cookie", "auth_token=%s; Path=%s; Max-Age=%d; HttpOnly", token, "/", max_age);
//
char *grants = jwt_get_grants_json(cookie, NULL);
buffer_appends(&ta->resp_body, grants);
buffer_appends(&ta->resp_body, CRLF);
ta->resp_status = HTTP_OK;
return send_response(ta);
}
return false;
}
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");
@ -433,6 +509,9 @@ static int val_api_url(struct http_transaction *ta) {
if (!strcmp(req_path, "/api/video")) { if (!strcmp(req_path, "/api/video")) {
return 1; return 1;
} }
if (!strcmp(req_path, "/api/logout")) {
return 2;
}
return -1; return -1;
} }
@ -449,6 +528,7 @@ handle_api(struct http_transaction *ta)
if (val == 0) { if (val == 0) {
if (ta->req_method == HTTP_POST) { if (ta->req_method == HTTP_POST) {
// Handle login post // Handle login post
return post_handle_login(ta);
} }
else if (ta->req_method == HTTP_GET){ else if (ta->req_method == HTTP_GET){
@ -461,7 +541,7 @@ handle_api(struct http_transaction *ta)
} }
} }
else { if (val == 1) {
DIR* dir = opendir(server_root); DIR* dir = opendir(server_root);
char *json = list_videos(dir); char *json = list_videos(dir);
fprintf(stderr, "json: %s\n", json); fprintf(stderr, "json: %s\n", json);
@ -477,6 +557,12 @@ handle_api(struct http_transaction *ta)
return send_response(ta); return send_response(ta);
} }
if (ta->req_method == HTTP_POST) // handles logout
{
char* cookie = "auth_token=; Path=/; Max-Age=0; HttpOnly";
ta->cookie = bufio_ptr2offset(ta->client->bufio, cookie);
return true;
}
return false; return false;
@ -489,6 +575,12 @@ http_setup_client(struct http_client *self, struct bufio *bufio)
self->bufio = bufio; self->bufio = bufio;
} }
static bool
handle_private(struct http_transaction *ta)
{
return false;
}
/* Handle a single HTTP transaction. Returns true on success. */ /* Handle a single HTTP transaction. Returns true on success. */
bool bool
http_handle_transaction(struct http_client *self) http_handle_transaction(struct http_client *self)
@ -500,6 +592,10 @@ http_handle_transaction(struct http_client *self)
if (!http_parse_request(&ta)) if (!http_parse_request(&ta))
return false; return false;
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)) if (!http_process_headers(&ta))
return false; return false;
@ -523,7 +619,7 @@ http_handle_transaction(struct http_client *self)
rc = handle_api(&ta); rc = handle_api(&ta);
} else } else
if (STARTS_WITH(req_path, "/private")) { if (STARTS_WITH(req_path, "/private")) {
/* not implemented */ rc = handle_private(&ta);
} else { } else {
rc = handle_static_asset(&ta, server_root); rc = handle_static_asset(&ta, server_root);
} }
@ -531,5 +627,5 @@ http_handle_transaction(struct http_client *self)
buffer_delete(&ta.resp_headers); buffer_delete(&ta.resp_headers);
buffer_delete(&ta.resp_body); buffer_delete(&ta.resp_body);
return rc; return is_http_1_1 && rc;
} }

View File

@ -40,6 +40,7 @@ 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
size_t cookie; // offset to cookie header
char *token; // authentication token char *token; // authentication token
/* response related fields */ /* response related fields */

View File

@ -35,11 +35,13 @@ int token_expiration_time = 24 * 60 * 60;
// root from which static files are served // root from which static files are served
char * server_root; char * server_root;
static void *thr_func(void *c) { static void *thr_func(void *cs) {
struct http_client *client = c; int client_socket = *(int*) cs;
while (http_handle_transaction(client)); struct http_client client;
bufio_close(client->bufio); http_setup_client(&client, bufio_create(client_socket));
while (http_handle_transaction(&client)){};
bufio_close(client.bufio);
return NULL; return NULL;
} }
@ -65,10 +67,10 @@ server_loop(char *port_string)
if (client_socket == -1){ if (client_socket == -1){
return; return;
} }
struct http_client *client = malloc(sizeof(struct http_client)); //~ struct http_client *client = malloc(sizeof(struct http_client));
http_setup_client(client, bufio_create(client_socket)); //~ http_setup_client(client, bufio_create(client_socket));
int rc = pthread_create(&threads[num_clients++], NULL, thr_func, client); int rc = pthread_create(&threads[num_clients++], NULL, thr_func, &client_socket);
if (rc) { if (rc) {
perror(NULL); perror(NULL);