diff --git a/attachments/kong/plugins/open-appsec-waf-kong-plugin/handler.lua b/attachments/kong/plugins/open-appsec-waf-kong-plugin/handler.lua index 7ebe9d7..ea7342d 100755 --- a/attachments/kong/plugins/open-appsec-waf-kong-plugin/handler.lua +++ b/attachments/kong/plugins/open-appsec-waf-kong-plugin/handler.lua @@ -157,13 +157,10 @@ function NanoHandler.header_filter(conf) local status_code = kong.response.get_status() local content_length = tonumber(headers["content-length"]) or 0 - -- For responses that will be streamed in chunks via body_filter, pass 0 content_length - -- to prevent nano service from trying to read the entire body at once - local nano_content_length = 0 + kong.log.debug("[header_filter] Session: ", session_id, " | Status: ", status_code, " | Content-Length: ", content_length) - kong.log.debug("[header_filter] Session: ", session_id, " | Status: ", status_code, " | Content-Length: ", content_length, " | Nano Content-Length: ", nano_content_length) - - local verdict, response = nano.send_response_headers(session_id, session_data, header_data, status_code, nano_content_length) + -- Send response headers WITHOUT content_length (like nginx does) + local verdict, response = nano.send_response_headers(session_id, session_data, header_data, status_code, 0) if verdict == nano.AttachmentVerdict.DROP then kong.log.warn("[header_filter] Response headers verdict DROP for session: ", session_id) kong.ctx.plugin.blocked = true @@ -172,6 +169,16 @@ function NanoHandler.header_filter(conf) return nano.handle_custom_response(session_data, response) end + -- Send content_length separately (like nginx does) + verdict, response = nano.send_content_length(session_id, session_data, content_length) + if verdict == nano.AttachmentVerdict.DROP then + kong.log.warn("[header_filter] Content length verdict DROP for session: ", session_id) + kong.ctx.plugin.blocked = true + nano.fini_session(session_data) + nano.cleanup_all() + return nano.handle_custom_response(session_data, response) + end + ctx.expect_body = not (status_code == 204 or status_code == 304 or (100 <= status_code and status_code < 200) or content_length == 0) kong.log.debug("[header_filter] Session: ", session_id, " | Expect body: ", ctx.expect_body) 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 83c1b1d..3c9e673 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 @@ -498,6 +498,30 @@ static int lua_send_response_headers(lua_State *L) { return 2; } +static int lua_send_content_length(lua_State *L) { + NanoAttachment* attachment = (NanoAttachment*) lua_touserdata(L, 1); + SessionID session_id = luaL_checkinteger(L, 2); + HttpSessionData *session_data = (HttpSessionData*) lua_touserdata(L, 3); + uint64_t content_length = luaL_checkinteger(L, 4); + + if (!attachment || !session_data) { + lua_pushstring(L, "Error: Invalid attachment or session_data"); + return lua_error(L); + } + + AttachmentData attachment_data; + attachment_data.session_id = session_id; + attachment_data.session_data = session_data; + attachment_data.chunk_type = CONTENT_LENGTH; + attachment_data.data = &content_length; + + AttachmentVerdictResponse* res_ptr = malloc(sizeof(AttachmentVerdictResponse)); + *res_ptr = SendDataNanoAttachment(attachment, &attachment_data); + lua_pushinteger(L, res_ptr->verdict); + lua_pushlightuserdata(L, res_ptr); + return 2; +} + static int lua_free_verdict_response(lua_State *L) { AttachmentVerdictResponse *response = (AttachmentVerdictResponse *)lua_touserdata(L, 1); if (!response) return 0; @@ -518,6 +542,7 @@ static const struct luaL_Reg nano_attachment_lib[] = { {"setHeaderElement", lua_setHeaderElement}, {"send_data", lua_send_data}, {"send_response_headers", lua_send_response_headers}, + {"send_content_length", lua_send_content_length}, {"fini_session", lua_fini_session}, {"is_session_finalized", lua_is_session_finalized}, {"init_session", lua_init_session}, 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 e897d93..e4de0d2 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 @@ -412,6 +412,29 @@ function nano.send_response_headers(session_id, session_data, headers, status_co return verdict, response end +function nano.send_content_length(session_id, session_data, content_length) + local worker_id = ngx.worker.id() + local attachment = nano.attachments[worker_id] + + if not attachment then + kong.log.warn("Attachment not available for worker ", worker_id, " - failing open") + return nano.AttachmentVerdict.INSPECT + end + + local verdict, response = nano_attachment.send_content_length( + attachment, + session_id, + session_data, + content_length + ) + + if response then + table.insert(nano.allocated_responses, response) + end + + return verdict, response +end + function nano.handle_header_modifications(headers, modifications) if not modifications then return headers