Skip to content

Commit

Permalink
gzip: Heal-the-BREACH mitigation for gzip VFP
Browse files Browse the repository at this point in the history
  • Loading branch information
dridi committed Jul 10, 2024
1 parent 13d3023 commit b0bff2a
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 1 deletion.
20 changes: 19 additions & 1 deletion bin/varnishd/cache/cache_gzip.c
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,10 @@ static const unsigned char breach_hdr[] = {
0xff, /* unknown OS */
};

static const gz_header breach_gz_header = {
.os = 0xff, /* unknown OS */
};

static const char *
breach_comment(struct ws *ws, size_t *plen)
{
Expand Down Expand Up @@ -637,13 +641,15 @@ static enum vfp_status v_matchproto_(vfp_init_f)
vfp_gzip_init(VRT_CTX, struct vfp_ctx *vc, struct vfp_entry *vfe)
{
struct vgz *vg;
gz_header *hdr;
const char *comm;

CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(vc, VFP_CTX_MAGIC);
CHECK_OBJ_NOTNULL(vfe, VFP_ENTRY_MAGIC);

/*
* G(un)zip makes no sence on partial responses, but since
* G(un)zip makes no sense on partial responses, but since
* it is an pure 1:1 transform, we can just ignore it.
*/
if (http_GetStatus(vc->resp) == 206)
Expand All @@ -654,6 +660,18 @@ vfp_gzip_init(VRT_CTX, struct vfp_ctx *vc, struct vfp_entry *vfe)
return (VFP_NULL);
vg = VGZ_NewGzip(vc->wrk->vsl, vfe->vfp->priv1);
vc->obj_flags |= OF_GZIPED | OF_CHGCE;
if (FEATURE(FEATURE_GZIP_BREACH)) {
comm = breach_comment(ctx->ws, NULL);
hdr = WS_Copy(ctx->ws, &breach_gz_header,
sizeof breach_gz_header);
if (comm == NULL || hdr == NULL) {
VSLb(vc->wrk->vsl, SLT_FetchError,
"gzip_breach: Out of workspace");
return (VFP_ERROR);
}
hdr->comment = TRUST_ME(comm);
assert(deflateSetHeader(&vg->vz, hdr) == Z_OK);
}
} else {
if (!http_HdrIs(vc->resp, H_Content_Encoding, "gzip"))
return (VFP_NULL);
Expand Down
50 changes: 50 additions & 0 deletions bin/varnishtest/tests/b00086.vtc
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
varnishtest "Heal-the-BREACH mitigation during fetch"

server s0 {
rxreq
txresp -bodylen 4001
} -dispatch

varnish v1 -cliok "param.set feature +gzip_breach"
varnish v1 -vcl+backend {
sub vcl_recv {
return (pass);
}
sub vcl_backend_response {
set beresp.do_gzip = true;
}
} -start

varnish v1 -cliok "debug.srandom"

client c1 {
txreq -hdr "accept-encoding: gzip"
rxresp
expect resp.bodylen == 381
gunzip
expect resp.bodylen == 4001

txreq -hdr "accept-encoding: gzip"
rxresp
expect resp.bodylen == 485
gunzip
expect resp.bodylen == 4001

txreq -hdr "accept-encoding: gzip"
rxresp
expect resp.bodylen == 430
gunzip
expect resp.bodylen == 4001

txreq -hdr "accept-encoding: gzip"
rxresp
expect resp.bodylen == 277
gunzip
expect resp.bodylen == 4001

txreq -hdr "accept-encoding: gzip"
rxresp
expect resp.bodylen == 414
gunzip
expect resp.bodylen == 4001
} -run

0 comments on commit b0bff2a

Please sign in to comment.