MINOR: rules: record the last http/tcp rule that gave a final verdict

When a tcp-{request,response} content or http-request/http-response
rule delivers a final verdict (deny, accept, redirect etc), the last
evaluated one will now be recorded in the stream. The purpose is to
permit to log the last one that performed a final action. For now
the log is not produced.
This commit is contained in:
Willy Tarreau 2022-03-09 17:23:10 +01:00
parent 3ec1461b03
commit c6dae869ca
4 changed files with 72 additions and 0 deletions

View File

@ -182,6 +182,8 @@ struct stream {
struct list *current_rule_list; /* this is used to store the current executed rule list. */
void *current_rule; /* this is used to store the current rule to be resumed. */
int rules_exp; /* expiration date for current rules execution */
const char *last_rule_file; /* last evaluated final rule's file (def: NULL) */
int last_rule_line; /* last evaluated final rule's line (def: 0) */
unsigned int stream_epoch; /* copy of stream_epoch when the stream was created */
struct hlua *hlua; /* lua runtime context */

View File

@ -2744,6 +2744,8 @@ static enum rule_result http_req_get_intercept_rule(struct proxy *px, struct lis
break;
case ACT_RET_STOP:
rule_ret = HTTP_RULE_RES_STOP;
s->last_rule_file = rule->conf.file;
s->last_rule_line = rule->conf.line;
goto end;
case ACT_RET_YIELD:
s->current_rule = rule;
@ -2751,20 +2753,30 @@ static enum rule_result http_req_get_intercept_rule(struct proxy *px, struct lis
goto end;
case ACT_RET_ERR:
rule_ret = HTTP_RULE_RES_ERROR;
s->last_rule_file = rule->conf.file;
s->last_rule_line = rule->conf.line;
goto end;
case ACT_RET_DONE:
rule_ret = HTTP_RULE_RES_DONE;
s->last_rule_file = rule->conf.file;
s->last_rule_line = rule->conf.line;
goto end;
case ACT_RET_DENY:
if (txn->status == -1)
txn->status = 403;
rule_ret = HTTP_RULE_RES_DENY;
s->last_rule_file = rule->conf.file;
s->last_rule_line = rule->conf.line;
goto end;
case ACT_RET_ABRT:
rule_ret = HTTP_RULE_RES_ABRT;
s->last_rule_file = rule->conf.file;
s->last_rule_line = rule->conf.line;
goto end;
case ACT_RET_INV:
rule_ret = HTTP_RULE_RES_BADREQ;
s->last_rule_file = rule->conf.file;
s->last_rule_line = rule->conf.line;
goto end;
}
continue; /* eval the next rule */
@ -2774,12 +2786,16 @@ static enum rule_result http_req_get_intercept_rule(struct proxy *px, struct lis
switch (rule->action) {
case ACT_ACTION_ALLOW:
rule_ret = HTTP_RULE_RES_STOP;
s->last_rule_file = rule->conf.file;
s->last_rule_line = rule->conf.line;
goto end;
case ACT_ACTION_DENY:
txn->status = rule->arg.http_reply->status;
txn->http_reply = rule->arg.http_reply;
rule_ret = HTTP_RULE_RES_DENY;
s->last_rule_file = rule->conf.file;
s->last_rule_line = rule->conf.line;
goto end;
case ACT_HTTP_REQ_TARPIT:
@ -2787,6 +2803,8 @@ static enum rule_result http_req_get_intercept_rule(struct proxy *px, struct lis
txn->status = rule->arg.http_reply->status;
txn->http_reply = rule->arg.http_reply;
rule_ret = HTTP_RULE_RES_DENY;
s->last_rule_file = rule->conf.file;
s->last_rule_line = rule->conf.line;
goto end;
case ACT_HTTP_REDIR: {
@ -2796,6 +2814,8 @@ static enum rule_result http_req_get_intercept_rule(struct proxy *px, struct lis
break;
rule_ret = ret ? HTTP_RULE_RES_ABRT : HTTP_RULE_RES_ERROR;
s->last_rule_file = rule->conf.file;
s->last_rule_line = rule->conf.line;
goto end;
}
@ -2887,6 +2907,8 @@ resume_execution:
break;
case ACT_RET_STOP:
rule_ret = HTTP_RULE_RES_STOP;
s->last_rule_file = rule->conf.file;
s->last_rule_line = rule->conf.line;
goto end;
case ACT_RET_YIELD:
s->current_rule = rule;
@ -2894,20 +2916,30 @@ resume_execution:
goto end;
case ACT_RET_ERR:
rule_ret = HTTP_RULE_RES_ERROR;
s->last_rule_file = rule->conf.file;
s->last_rule_line = rule->conf.line;
goto end;
case ACT_RET_DONE:
rule_ret = HTTP_RULE_RES_DONE;
s->last_rule_file = rule->conf.file;
s->last_rule_line = rule->conf.line;
goto end;
case ACT_RET_DENY:
if (txn->status == -1)
txn->status = 502;
rule_ret = HTTP_RULE_RES_DENY;
s->last_rule_file = rule->conf.file;
s->last_rule_line = rule->conf.line;
goto end;
case ACT_RET_ABRT:
rule_ret = HTTP_RULE_RES_ABRT;
s->last_rule_file = rule->conf.file;
s->last_rule_line = rule->conf.line;
goto end;
case ACT_RET_INV:
rule_ret = HTTP_RULE_RES_BADREQ;
s->last_rule_file = rule->conf.file;
s->last_rule_line = rule->conf.line;
goto end;
}
continue; /* eval the next rule */
@ -2917,12 +2949,16 @@ resume_execution:
switch (rule->action) {
case ACT_ACTION_ALLOW:
rule_ret = HTTP_RULE_RES_STOP; /* "allow" rules are OK */
s->last_rule_file = rule->conf.file;
s->last_rule_line = rule->conf.line;
goto end;
case ACT_ACTION_DENY:
txn->status = rule->arg.http_reply->status;
txn->http_reply = rule->arg.http_reply;
rule_ret = HTTP_RULE_RES_DENY;
s->last_rule_file = rule->conf.file;
s->last_rule_line = rule->conf.line;
goto end;
case ACT_HTTP_REDIR: {
@ -2932,6 +2968,8 @@ resume_execution:
break;
rule_ret = ret ? HTTP_RULE_RES_ABRT : HTTP_RULE_RES_ERROR;
s->last_rule_file = rule->conf.file;
s->last_rule_line = rule->conf.line;
goto end;
}
/* other flags exists, but normally, they never be matched. */

View File

@ -385,6 +385,8 @@ struct stream *stream_new(struct session *sess, struct conn_stream *cs, struct b
s->current_rule_list = NULL;
s->current_rule = NULL;
s->rules_exp = TICK_ETERNITY;
s->last_rule_file = NULL;
s->last_rule_line = 0;
/* Copy SC counters for the stream. We don't touch refcounts because
* any reference we have is inherited from the session. Since the stream

View File

@ -163,6 +163,8 @@ resume_execution:
break;
case ACT_RET_STOP:
case ACT_RET_DONE:
s->last_rule_file = rule->conf.file;
s->last_rule_line = rule->conf.line;
goto end;
case ACT_RET_YIELD:
s->current_rule = rule;
@ -174,12 +176,20 @@ resume_execution:
}
goto missing_data;
case ACT_RET_DENY:
s->last_rule_file = rule->conf.file;
s->last_rule_line = rule->conf.line;
goto deny;
case ACT_RET_ABRT:
s->last_rule_file = rule->conf.file;
s->last_rule_line = rule->conf.line;
goto abort;
case ACT_RET_ERR:
s->last_rule_file = rule->conf.file;
s->last_rule_line = rule->conf.line;
goto internal;
case ACT_RET_INV:
s->last_rule_file = rule->conf.file;
s->last_rule_line = rule->conf.line;
goto invalid;
}
continue; /* eval the next rule */
@ -187,9 +197,13 @@ resume_execution:
/* If not action function defined, check for known actions */
if (rule->action == ACT_ACTION_ALLOW) {
s->last_rule_file = rule->conf.file;
s->last_rule_line = rule->conf.line;
goto end;
}
else if (rule->action == ACT_ACTION_DENY) {
s->last_rule_file = rule->conf.file;
s->last_rule_line = rule->conf.line;
goto deny;
}
}
@ -331,6 +345,8 @@ resume_execution:
break;
case ACT_RET_STOP:
case ACT_RET_DONE:
s->last_rule_file = rule->conf.file;
s->last_rule_line = rule->conf.line;
goto end;
case ACT_RET_YIELD:
s->current_rule = rule;
@ -343,12 +359,20 @@ resume_execution:
channel_dont_close(rep);
goto missing_data;
case ACT_RET_DENY:
s->last_rule_file = rule->conf.file;
s->last_rule_line = rule->conf.line;
goto deny;
case ACT_RET_ABRT:
s->last_rule_file = rule->conf.file;
s->last_rule_line = rule->conf.line;
goto abort;
case ACT_RET_ERR:
s->last_rule_file = rule->conf.file;
s->last_rule_line = rule->conf.line;
goto internal;
case ACT_RET_INV:
s->last_rule_file = rule->conf.file;
s->last_rule_line = rule->conf.line;
goto invalid;
}
continue; /* eval the next rule */
@ -356,9 +380,13 @@ resume_execution:
/* If not action function defined, check for known actions */
if (rule->action == ACT_ACTION_ALLOW) {
s->last_rule_file = rule->conf.file;
s->last_rule_line = rule->conf.line;
goto end;
}
else if (rule->action == ACT_ACTION_DENY) {
s->last_rule_file = rule->conf.file;
s->last_rule_line = rule->conf.line;
goto deny;
}
else if (rule->action == ACT_TCP_CLOSE) {
@ -366,6 +394,8 @@ resume_execution:
si_must_kill_conn(chn_prod(rep));
si_shutr(chn_prod(rep));
si_shutw(chn_prod(rep));
s->last_rule_file = rule->conf.file;
s->last_rule_line = rule->conf.line;
goto end;
}
}