Mailing List Archive

Extra bucket brigade with just an EOS on an input filter at the end.
In some code (https://source.redwax.eu/svn/redwax/rs/mod_cms_verify/trunk/mod_cms_verify.c) I have in input filter (that checks a PKCS#7 signature before passing the payload on to a proxy/cgi-script, etc).

I am testing this with:

echo "field1=foo&field2=bar” |\
openssl cms -sign -signer /tmp/sign.cert -outform DER -stream |\
curl --data-binary @- -vvvv http://127.0.0.1:8080/show.cgi

Works well.

But I am seeing after all this going well an extra bucket brigade being passed; with 0 bytes. And I’d like to understand why.

Code is roughly ((https://source.redwax.eu/svn/redwax/rs/mod_cms_verify/trunk/mod_cms_verify.c for the real McCoy):

static apr_status_t _input_filter(ap_filter_t * f, apr_bucket_brigade * bbout, ….
{
verify_config_rec *conf = ap_get_module_config(r->per_dir_config, &cms_verify_module);
request_rec *r = f->r;

bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);

if (state == NULL) {
setup some state..
state->pbb_tmp = apr_brigade_create(r->pool, c->bucket_alloc);
….
}

if (APR_BRIGADE_EMPTY(state->pbb_tmp)) {
rv = ap_get_brigade(f->next, state->pbb_tmp, eMode, eBlock, nBytes);
if (eMode == AP_MODE_EATCRLF || rv != APR_SUCCESS)
return rv;
}

while (!APR_BRIGADE_EMPTY(state->pbb_tmp)) {
apr_bucket *pbkt_in = APR_BRIGADE_FIRST(state->pbb_tmp);
const char *data;
apr_size_t len;

if (APR_BUCKET_IS_EOS(pbkt_in)) {
apr_bucket *pbkt_out = validate()..

if (pbkt_out is valid)
APR_BRIGADE_INSERT_TAIL(bbout, pbkt_out);

APR_BRIGADE_INSERT_TAIL(bbout, apr_bucket_eos_create(r->connection->bucket_alloc));
APR_BUCKET_REMOVE(pbkt_in);
break;
}

rv = apr_bucket_read(pbkt_in, &data, &len, eBlock);
if (rv != APR_SUCCESS)
return rv;

… add len bytes to a buffer

apr_bucket_delete(pbkt_in);
};
return APR_SUCCESS;
}

And mostly taken from mod_example.

What I am seeing is a first brigade with the POST content; with a terminating EOF. The bbout data makes it to the CGI script or (reverse) proxy.

But I am then getting a second _input_filter call with a second brigade of just an EOS packet.

What causes that ? Or am I not running through the brigade properly ?

Dw
Re: Extra bucket brigade with just an EOS on an input filter at the end. [ In reply to ]
On Sat, Aug 07, 2021 at 06:33:49PM +0200, Dirk-Willem van Gulik wrote:
...
> What I am seeing is a first brigade with the POST content; with a
> terminating EOF. The bbout data makes it to the CGI script or
> (reverse) proxy.
>
> But I am then getting a second _input_filter call with a second
> brigade of just an EOS packet.
>
> What causes that ? Or am I not running through the brigade properly ?

You're not doing anything wrong, it seems to be a "feature" of the way
input filtering is implemented and should probably be better documented.
I wrote this in mod_ssl:

/* Surprisingly (and perhaps, wrongly), the request body can be
* pulled from the input filter stack more than once; a
* handler may read it, and ap_discard_request_body() will
* attempt to do so again after *every* request. So input
* filters must be prepared to give up an EOS if invoked after
* initially reading the request. The HTTP_IN filter does this
* with its ->eos_sent flag. */

https://svn.apache.org/viewvc/httpd/httpd/trunk/modules/ssl/ssl_engine_io.c?view=markup#l2205

Regards, Joe