BUG/MEDIUM: cli: Properly set stream analyzers to process one command at a time

The proxy used by the master CLI is an internal proxy and no filter are
registered on it. Thus, there is no reason to take care to set or unset
filter analyzers in the master CLI analyzers. AN_REQ_FLT_END was set on the
request channel to prevent the infinite forward and be sure to be able to
process one commande at a time. However, the only work because
CF_FLT_ANALYZE flag was used by error as a channel analyzer instead of a
channel flag. This erroneously set AN_RES_FLT_END on the request channel,
that really prevent the infinite forward, be side effet.

In fact, We must avoid this kind of trick because this only work by chance
and may be source of bugs in future. Instead, we must always keep the CLI
request analyzer and add an early return if the response is not fully
processed. It happens when the CLI response analyzer is set.

This patch must be backported as far as 2.0.
This commit is contained in:
Christopher Faulet 2021-10-18 14:52:49 +02:00 committed by William Lallemand
parent 4673c5e2c8
commit d98da3bc90
1 changed files with 9 additions and 9 deletions

View File

@ -2392,6 +2392,13 @@ int pcli_wait_for_request(struct stream *s, struct channel *req, int an_bit)
int to_forward; int to_forward;
char *errmsg = NULL; char *errmsg = NULL;
/* Don't read the next command if still processing the reponse of the
* current one. Just wait. At this stage, errors should be handled by
* the response analyzer.
*/
if (s->res.analysers & AN_RES_WAIT_CLI)
return 0;
if ((s->pcli_flags & ACCESS_LVL_MASK) == ACCESS_LVL_NONE) if ((s->pcli_flags & ACCESS_LVL_MASK) == ACCESS_LVL_NONE)
s->pcli_flags |= strm_li(s)->bind_conf->level & ACCESS_LVL_MASK; s->pcli_flags |= strm_li(s)->bind_conf->level & ACCESS_LVL_MASK;
@ -2439,13 +2446,6 @@ int pcli_wait_for_request(struct stream *s, struct channel *req, int an_bit)
} }
s->res.flags |= CF_WAKE_ONCE; /* need to be called again */ s->res.flags |= CF_WAKE_ONCE; /* need to be called again */
/* remove the XFER_DATA analysers, which forwards all
* the data, we don't want to forward the next requests
* We need to add CF_FLT_ANALYZE to abort the forward too.
*/
req->analysers &= ~(AN_REQ_FLT_XFER_DATA|AN_REQ_WAIT_CLI);
req->analysers |= AN_REQ_FLT_END|CF_FLT_ANALYZE;
s->res.analysers |= AN_RES_WAIT_CLI; s->res.analysers |= AN_RES_WAIT_CLI;
if (!(s->flags & SF_ASSIGNED)) { if (!(s->flags & SF_ASSIGNED)) {
@ -2467,6 +2467,7 @@ int pcli_wait_for_request(struct stream *s, struct channel *req, int an_bit)
} else if (to_forward == -1 && errmsg) { } else if (to_forward == -1 && errmsg) {
/* there was an error during the parsing */ /* there was an error during the parsing */
pcli_reply_and_close(s, errmsg); pcli_reply_and_close(s, errmsg);
s->req.analysers &= ~AN_REQ_WAIT_CLI;
return 0; return 0;
} else if (to_forward == -1 && channel_full(req, global.tune.maxrewrite)) { } else if (to_forward == -1 && channel_full(req, global.tune.maxrewrite)) {
/* buffer is full and we didn't catch the end of a command */ /* buffer is full and we didn't catch the end of a command */
@ -2488,6 +2489,7 @@ int pcli_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
if (rep->flags & CF_READ_ERROR) { if (rep->flags & CF_READ_ERROR) {
pcli_reply_and_close(s, "Can't connect to the target CLI!\n"); pcli_reply_and_close(s, "Can't connect to the target CLI!\n");
s->req.analysers &= ~AN_REQ_WAIT_CLI;
s->res.analysers &= ~AN_RES_WAIT_CLI; s->res.analysers &= ~AN_RES_WAIT_CLI;
return 0; return 0;
} }
@ -2499,7 +2501,6 @@ int pcli_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
channel_dont_close(&s->req); channel_dont_close(&s->req);
if (s->pcli_flags & PCLI_F_PAYLOAD) { if (s->pcli_flags & PCLI_F_PAYLOAD) {
s->req.analysers |= AN_REQ_WAIT_CLI;
s->res.analysers &= ~AN_RES_WAIT_CLI; s->res.analysers &= ~AN_RES_WAIT_CLI;
s->req.flags |= CF_WAKE_ONCE; /* need to be called again if there is some command left in the request */ s->req.flags |= CF_WAKE_ONCE; /* need to be called again if there is some command left in the request */
return 0; return 0;
@ -2620,7 +2621,6 @@ int pcli_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
s->req.flags |= CF_WAKE_ONCE; /* need to be called again if there is some command left in the request */ s->req.flags |= CF_WAKE_ONCE; /* need to be called again if there is some command left in the request */
s->req.analysers |= AN_REQ_WAIT_CLI;
s->res.analysers &= ~AN_RES_WAIT_CLI; s->res.analysers &= ~AN_RES_WAIT_CLI;
/* We must trim any excess data from the response buffer, because we /* We must trim any excess data from the response buffer, because we