post login, post logout, multiclient
This commit is contained in:
parent
5516fe8910
commit
724afe49c1
102
src/http.c
102
src/http.c
@ -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)
|
||||||
{
|
{
|
||||||
|
switch (ta->req_version) {
|
||||||
|
case HTTP_1_0:
|
||||||
buffer_appends(res, "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;
|
||||||
}
|
}
|
||||||
|
@ -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 */
|
||||||
|
16
src/main.c
16
src/main.c
@ -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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user