diff --git a/attachments/kong/plugins/open-appsec-waf-kong-plugin/lua_attachment_wrapper.c b/attachments/kong/plugins/open-appsec-waf-kong-plugin/lua_attachment_wrapper.c index eb49244..fe21236 100755 --- a/attachments/kong/plugins/open-appsec-waf-kong-plugin/lua_attachment_wrapper.c +++ b/attachments/kong/plugins/open-appsec-waf-kong-plugin/lua_attachment_wrapper.c @@ -104,6 +104,49 @@ static int lua_get_redirect_page(lua_State *L) { return 1; } +static int lua_get_custom_response_with_headers(lua_State *L) { + NanoAttachment* attachment = (NanoAttachment*)lua_touserdata(L, 1); + HttpSessionData* session_data = (HttpSessionData*)lua_touserdata(L, 2); + AttachmentVerdictResponse* response = (AttachmentVerdictResponse*)lua_touserdata(L, 3); + + if (!attachment || !session_data || !response) { + return luaL_error(L, "invalid args to get_custom_response_with_headers"); + } + + CustomResponseWithHeaders* custom_response = GetCustomResponseWithHeaders(attachment, session_data, response); + if (!custom_response) { + lua_pushnil(L); + lua_pushstring(L, "Failed to get custom response with headers"); + return 2; + } + + // Create a table to return the data + lua_newtable(L); + + // Add response code + lua_pushinteger(L, custom_response->response_code); + lua_setfield(L, -2, "response_code"); + + // Add headers as a nested table + lua_newtable(L); + for (uint8_t i = 0; i < custom_response->headers_count; i++) { + lua_pushlstring(L, custom_response->headers[i].key, custom_response->headers[i].key_size); + lua_pushlstring(L, custom_response->headers[i].value, custom_response->headers[i].value_size); + lua_settable(L, -3); + } + lua_setfield(L, -2, "headers"); + + // Add body + if (custom_response->body_size > 0 && custom_response->body) { + lua_pushlstring(L, custom_response->body, custom_response->body_size); + } else { + lua_pushstring(L, ""); + } + lua_setfield(L, -2, "body"); + + return 1; +} + static int lua_free_http_metadata(lua_State *L) { HttpMetaData *metadata = (HttpMetaData *)lua_touserdata(L, 1); if (!metadata) return 0; @@ -537,6 +580,7 @@ static const struct luaL_Reg nano_attachment_lib[] = { {"get_response_code", lua_get_response_code}, {"get_block_page", lua_get_block_page}, {"get_redirect_page", lua_get_redirect_page}, + {"get_custom_response_with_headers", lua_get_custom_response_with_headers}, {"createNanoStrAlloc", lua_createNanoStrAlloc}, {"freeNanoStr", lua_freeNanoStr}, {"setHeaderElement", lua_setHeaderElement}, diff --git a/attachments/kong/plugins/open-appsec-waf-kong-plugin/nano_ffi.lua b/attachments/kong/plugins/open-appsec-waf-kong-plugin/nano_ffi.lua index b88c73d..1c2f671 100755 --- a/attachments/kong/plugins/open-appsec-waf-kong-plugin/nano_ffi.lua +++ b/attachments/kong/plugins/open-appsec-waf-kong-plugin/nano_ffi.lua @@ -29,9 +29,11 @@ nano.HttpChunkType = { nano.WebResponseType = { CUSTOM_WEB_RESPONSE = 0, - RESPONSE_CODE_ONLY = 1, - REDIRECT_WEB_RESPONSE = 2, - NO_WEB_RESPONSE = 3, + CUSTOM_WEB_BLOCK_PAGE_RESPONSE = 1, + RESPONSE_CODE_ONLY = 2, + REDIRECT_WEB_RESPONSE = 3, + CUSTOM_RESPONSE_WITH_HEADERS = 4, + NO_WEB_RESPONSE = 5, } local ffi = require "ffi" @@ -47,8 +49,10 @@ typedef enum HttpModificationType typedef enum NanoWebResponseType { CUSTOM_WEB_RESPONSE, + CUSTOM_WEB_BLOCK_PAGE_RESPONSE, RESPONSE_CODE_ONLY, REDIRECT_WEB_RESPONSE, + CUSTOM_RESPONSE_WITH_HEADERS, NO_WEB_RESPONSE } NanoWebResponseType; @@ -109,6 +113,26 @@ function nano.get_custom_response_data(session_data, response) return code, "", { ["Location"] = location } end + if response_type == nano.WebResponseType.CUSTOM_RESPONSE_WITH_HEADERS then + local custom_response, err = nano_attachment.get_custom_response_with_headers(attachment, session_data, response) + if not custom_response then + kong.log.err("Failed to get custom response with headers: ", err) + return 500, "Internal Server Error" + end + + local code = custom_response.response_code + if not code or code < 100 or code > 599 then + kong.log.warn("Invalid response code in custom response: ", code, " - using 403 instead") + code = 403 + end + + local headers = custom_response.headers or {} + local body = custom_response.body or "" + + kong.log.debug("Custom response with headers: code=", code, ", headers_count=", #headers, ", body_size=", #body) + return code, body, headers + end + local block_page = nano_attachment.get_block_page(attachment, session_data, response) if not block_page then kong.log.debug("Failed to retrieve custom block page for session ", session_data) diff --git a/attachments/kong/plugins/open-appsec-waf-kong-plugin/open-appsec-waf-kong-plugin-1.0.0-1.rockspec b/attachments/kong/plugins/open-appsec-waf-kong-plugin/open-appsec-waf-kong-plugin-1.0.0-1.rockspec index 3b44c02..ae30849 100755 --- a/attachments/kong/plugins/open-appsec-waf-kong-plugin/open-appsec-waf-kong-plugin-1.0.0-1.rockspec +++ b/attachments/kong/plugins/open-appsec-waf-kong-plugin/open-appsec-waf-kong-plugin-1.0.0-1.rockspec @@ -3,7 +3,7 @@ version = "1.0.0-1" source = { url = "git://github.com/openappsec/attachment.git", - tag = "main" + tag = "custom-block-page" } description = {