validate_token_exp, private

This commit is contained in:
Felicia Seo 2022-12-09 17:27:52 -05:00
parent af936cb46e
commit 4720b6f233
2 changed files with 50 additions and 42 deletions

View File

@ -115,13 +115,19 @@ http_process_headers(struct http_transaction *ta)
if (!strcasecmp(field_name, "Content-Length")) {
ta->req_content_len = atoi(field_value);
}
ta->valid_token = false; // special case?
/* Handle other headers here. Both field_value and field_name
* are zero-terminated strings.
*/
if (!strcasecmp(field_name, "Cookie")) {
if (!strcasecmp(field_name, "Cookie")) {
if (field_value == NULL)
return false;
ta->token = field_value + 11; // + 11 gets rid of "auth_token=" heading.
ta->valid_token = validate_token_exp(ta, ta->token);
ta->cookie = bufio_ptr2offset(ta->client->bufio, field_name);
ta->token = field_value; // fix this! needs to be just auth_token part
}
}
}
@ -294,22 +300,31 @@ guess_mime_type(char *filename)
}
/* Check a token is not expired. */
static bool validate_token_exp(struct http_transaction *ta, char* grants) {
char *gs = calloc(strlen(grants) + 1, sizeof(char));
memcpy(gs, grants, strlen(grants) + 1);
char *end;
char *expire = strtok_r(gs, "{\":, }", &end);
while (expire != NULL) {
if (!strcasecmp(expire, "exp")) {
int exp = atoi(strtok_r(NULL, "{\":, }", &end));
if (time(NULL) >= exp) {
return false;
}
break;
}
}
return true;
bool validate_token_exp(struct http_transaction *ta, char* token) {
jwt_t* cookie;
// Decode token.
int rc = jwt_decode(&cookie, ta->token, (unsigned char *)NEVER_EMBED_A_SECRET_IN_CODE, strlen(NEVER_EMBED_A_SECRET_IN_CODE));
if (rc)
return send_error(ta, HTTP_OK, "{}");
// Get claim (formatted grants).
char* grants = jwt_get_grants_json(cookie, NULL);
if (grants == NULL)
return send_error(ta, HTTP_OK, "{}");
// Get expiration time.
json_error_t error;
json_t *jgrants = json_loadb(grants, strlen(grants), 0, &error);
json_int_t exp, iat;
const char *sub;
json_unpack(jgrants, "{s:I, s:I, s:s}", "exp", &exp, "iat", &iat, "sub", &sub);
// Check expiration time.
if (time(NULL) >= exp)
return false;
return true;
}
/* Handle HTTP transaction for static files. */
@ -322,7 +337,7 @@ handle_static_asset(struct http_transaction *ta, char *basedir)
// The code below is vulnerable to an attack. Can you see
// which? Fix it to avoid indirect object reference (IDOR) attacks.
snprintf(fname, sizeof fname, "%s%s", basedir, req_path);
char *endptr;
char *p = calloc(strlen(fname) + 1, sizeof(char));
memcpy(p, fname, strlen(fname) + 1);
@ -340,6 +355,7 @@ handle_static_asset(struct http_transaction *ta, char *basedir)
snprintf(fname, sizeof fname, "%s%s", server_root, "/index.html");
}
if (access(fname, R_OK)) {
if (errno == EACCES)
return send_error(ta, HTTP_PERMISSION_DENIED, "Permission denied.");
@ -436,10 +452,12 @@ post_handle_login(struct http_transaction *ta)
// Add Set-Cookie header.
http_add_header(&ta->resp_headers, "Set-Cookie", "auth_token=%s; Path=%s; Max-Age=%d; HttpOnly", token, "/", max_age);
//
// Get claim (formatted grants).
char *grants = jwt_get_grants_json(cookie, NULL);
buffer_appends(&ta->resp_body, grants);
buffer_appends(&ta->resp_body, CRLF);
// Send claim.
ta->resp_status = HTTP_OK;
return send_response(ta);
}
@ -451,29 +469,14 @@ post_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");
if (ta->token == NULL) {
return send_error(ta, HTTP_OK, "{}");
}
jwt_t *cookie;
int rc = jwt_decode(&cookie, ta->token, (unsigned char *) "key", 3);
if (rc) {
return send_error(ta, HTTP_OK, "{}\n");
}
/* Send claims */
char *grants = jwt_get_grants_json(cookie, NULL);
if (grants == NULL) {
return send_error(ta, HTTP_OK, "{}\n");
}
if (!validate_token_exp(ta, grants)) {
if (!ta->valid_token) {
return send_error(ta, HTTP_PERMISSION_DENIED,"Forbidden.\n");
}
char *json = buffer_ensure_capacity(&ta->resp_body, MAX_HEADER_LEN);
int len = snprintf(json, strlen(grants) + 2, "%s\n", grants);
int length = len > MAX_HEADER_LEN ? MAX_HEADER_LEN - 1 : len;
ta->resp_body.len += length;
//~ char *json = buffer_ensure_capacity(&ta->resp_body, MAX_HEADER_LEN);
//~ int len = snprintf(json, strlen(grants) + 2, "%s\n", grants);
//~ int length = len > MAX_HEADER_LEN ? MAX_HEADER_LEN - 1 : len;
//~ ta->resp_body.len += length;
return send_response(ta);
}
@ -595,7 +598,10 @@ http_setup_client(struct http_client *self, struct bufio *bufio)
static bool
handle_private(struct http_transaction *ta)
{
return false;
if (ta->valid_token) {
return handle_static_asset(ta, server_root);
}
return send_error(ta, HTTP_PERMISSION_DENIED,"Forbidden.\n");
}
/* Handle a single HTTP transaction. Returns true on success. */

View File

@ -42,6 +42,7 @@ struct http_transaction {
size_t cookie; // offset to cookie header
char *token; // authentication token
bool valid_token;
/* response related fields */
enum http_response_status resp_status;
@ -58,5 +59,6 @@ struct http_client {
void http_setup_client(struct http_client *, struct bufio *bufio);
bool http_handle_transaction(struct http_client *);
void http_add_header(buffer_t * resp, char* key, char* fmt, ...);
bool validate_token_exp(struct http_transaction *ta, char* token);
#endif /* _HTTP_H */