From 4720b6f233d99c4e7b89bd29767c54fd2fd1d5d1 Mon Sep 17 00:00:00 2001 From: Felicia Seo Date: Fri, 9 Dec 2022 17:27:52 -0500 Subject: [PATCH] validate_token_exp, private --- src/http.c | 90 +++++++++++++++++++++++++++++------------------------- src/http.h | 2 ++ 2 files changed, 50 insertions(+), 42 deletions(-) diff --git a/src/http.c b/src/http.c index efd6199..320fd27 100644 --- a/src/http.c +++ b/src/http.c @@ -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. */ diff --git a/src/http.h b/src/http.h index 05ee571..e626154 100644 --- a/src/http.h +++ b/src/http.h @@ -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 */