Commit 4eeed3b6 authored by Geoff Simmons's avatar Geoff Simmons

allow the digest object methods to be called in vcl_init and _fini, and

allow the .final() method to be called more than once, caching the result
on the first call
parent bd7d2d01
Pipeline #45 skipped
......@@ -2,7 +2,7 @@
varnishtest "MD5 hash"
# VMOD blobcode must be installed
# VMODs blobcode and blob must be installed
varnish v1 -vcl {
import blobdigest from "${vmod_topbuild}/src/.libs/libvmod_blobdigest.so";
......@@ -423,3 +423,123 @@ client c1 {
expect resp.http.rfc2202t6 == "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd"
expect resp.http.rfc2202t7 == "6f630fad67cda0ee1fb1f562db3aa53e"
} -run
# Test use of digest object methods in vcl_init and _fini
varnish v1 -vcl {
import blobdigest from "${vmod_topbuild}/src/.libs/libvmod_blobdigest.so";
import blobcode;
import blob;
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new msg = blobcode.blob(IDENTITY, "message");
new space = blobcode.blob(IDENTITY, " ");
new digest = blobcode.blob(IDENTITY, "digest");
new msgdigest
= blobcode.blob(HEX, "F96B697D7CB7938D525A2F31AAF161D0");
new a = blobcode.blob(IDENTITY, "a");
new bc = blobcode.blob(IDENTITY, "bc");
new abc
= blobcode.blob(HEX, "900150983CD24FB0D6963F7D28E17F72");
new d1 = blobdigest.digest(MD5, msg.get());
if (!d1.update(space.get())) {
return(fail);
}
if (!d1.update(digest.get())) {
return(fail);
}
if (!blob.equal(d1.final(), msgdigest.get())) {
return(fail);
}
new d2 = blobdigest.digest(MD5, a.get());
}
sub vcl_recv {
return(synth(200));
}
sub vcl_fini {
# Don't know how to test the result, at least it
# shouldn't blow up
if (!d2.update(bc.get())) {}
if (!blob.equal(d2.final(), abc.get())) {}
}
}
client c1 {
txreq
rxresp
expect resp.status == 200
} -run
# Test repeated calls of the digest.final() method
server s1 -wait {
rxreq
txresp -hdr "Cache-Control: max-age=0"
} -start
varnish v1 -vcl+backend {
import blobdigest from "${vmod_topbuild}/src/.libs/libvmod_blobdigest.so";
import blobcode;
import blob;
sub vcl_init {
new a = blobcode.blob(IDENTITY, "a");
new bc = blobcode.blob(IDENTITY, "bc");
new abc
= blobcode.blob(HEX, "900150983CD24FB0D6963F7D28E17F72");
new d1 = blobdigest.digest(MD5, a.get());
if (!d1.update(bc.get())) {
return(fail);
}
if (!blob.equal(d1.final(), abc.get())) {
return(fail);
}
if (!blob.equal(d1.final(), abc.get())) {
return(fail);
}
new d2 = blobdigest.digest(MD5);
}
sub vcl_backend_response {
set beresp.http.d1_b1 = blobcode.encode(HEXUC, d1.final());
set beresp.http.d1_b2 = blobcode.encode(HEXUC, d1.final());
if (!d2.update(blobcode.decode(IDENTITY, "message digest"))) {
return(abandon);
}
set beresp.http.d2_b1 = blobcode.encode(HEXUC, d2.final());
set beresp.http.d2_b2 = blobcode.encode(HEXUC, d2.final());
}
sub vcl_deliver {
set resp.http.d1_c1 = blobcode.encode(HEXUC, d1.final());
set resp.http.d1_c2 = blobcode.encode(HEXUC, d1.final());
if (!d2.update(blobcode.decode(IDENTITY, "a"))) {
return(synth(500));
}
set resp.http.d2_c1 = blobcode.encode(HEXUC, d2.final());
set resp.http.d2_c2 = blobcode.encode(HEXUC, d2.final());
}
}
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.http.d1_b1 == "900150983CD24FB0D6963F7D28E17F72"
expect resp.http.d1_b2 == "900150983CD24FB0D6963F7D28E17F72"
expect resp.http.d1_c1 == "900150983CD24FB0D6963F7D28E17F72"
expect resp.http.d1_c2 == "900150983CD24FB0D6963F7D28E17F72"
expect resp.http.d2_b1 == "F96B697D7CB7938D525A2F31AAF161D0"
expect resp.http.d2_b2 == "F96B697D7CB7938D525A2F31AAF161D0"
expect resp.http.d2_c1 == "0CC175B9C0F1B6A831C399E269772661"
expect resp.http.d2_c2 == "0CC175B9C0F1B6A831C399E269772661"
} -run
......@@ -57,7 +57,7 @@ struct digest_task {
unsigned magic;
#define VMOD_BLOBDIGEST_DIGEST_TASK_MAGIC 0x646937a8
hash_ctx ctx;
int finalized;
struct vmod_priv *result;
};
struct vmod_blobdigest_digest {
......@@ -65,6 +65,7 @@ struct vmod_blobdigest_digest {
#define VMOD_BLOBDIGEST_DIGEST_MAGIC 0xaccb2e25
hash_ctx ctx;
char *vcl_name;
struct vmod_priv *result;
enum algorithm hash;
};
......@@ -209,13 +210,6 @@ digest(const enum algorithm hash, hash_ctx *restrict const hctx,
/* Objects */
static inline int
WS_Contains(struct ws * const restrict ws, const void * const restrict ptr,
const size_t len)
{
return ((char *)ptr >= ws->s && (char *)(ptr + len) <= ws->e);
}
static void
free_digest_task(void *p)
{
......@@ -239,7 +233,7 @@ get_task(const struct vrt_ctx * const restrict ctx,
ALLOC_OBJ(task, VMOD_BLOBDIGEST_DIGEST_TASK_MAGIC);
AN(task);
memcpy(&task->ctx, &h->ctx, sizeof(hash_ctx));
task->finalized = 0;
AZ(task->result);
priv->priv = task;
priv->free = free_digest_task;
}
......@@ -264,6 +258,7 @@ vmod_digest__init(VRT_CTX, struct vmod_blobdigest_digest **digestp,
digest->hash = hash;
digest->vcl_name = strdup(vcl_name);
AN(digest->vcl_name);
AZ(digest->result);
init(hash, &digest->ctx);
if (initb != NULL)
update(hash, &digest->ctx, initb->priv, initb->len);
......@@ -277,6 +272,11 @@ vmod_digest__fini(struct vmod_blobdigest_digest **digestp)
digest = *digestp;
*digestp = NULL;
CHECK_OBJ_NOTNULL(digest, VMOD_BLOBDIGEST_DIGEST_MAGIC);
if (digest->result != NULL) {
AN(digest->result->priv);
free(digest->result->priv);
free(digest->result);
}
if (digest->vcl_name != NULL)
free(digest->vcl_name);
FREE_OBJ(digest);
......@@ -290,15 +290,23 @@ vmod_digest_update(VRT_CTX, struct vmod_blobdigest_digest *h, VCL_BLOB b)
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(h, VMOD_BLOBDIGEST_DIGEST_MAGIC);
if (h->result != NULL) {
ERR(ctx, "already finalized in digest.update()");
return 0;
}
/* XXX: is b == NULL an error? */
if (b == NULL || b->len == 0 || b->priv == NULL)
return 1;
/* XXX: if in init or fini, just update the object context */
if (INIT_FINI(ctx)) {
update(h->hash, &h->ctx, b->priv, b->len);
return 1;
}
task = get_task(ctx, h);
CHECK_OBJ_NOTNULL(task, VMOD_BLOBDIGEST_DIGEST_TASK_MAGIC);
if (task->finalized) {
if (task->result != NULL) {
ERR(ctx, "already finalized in digest.update()");
return 0;
}
......@@ -318,18 +326,29 @@ vmod_digest_final(VRT_CTX, struct vmod_blobdigest_digest *h)
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(h, VMOD_BLOBDIGEST_DIGEST_MAGIC);
/* XXX: if in init or fini, just finalize the object context */
task = get_task(ctx, h);
CHECK_OBJ_NOTNULL(task, VMOD_BLOBDIGEST_DIGEST_TASK_MAGIC);
if (task->finalized) {
ERR(ctx, "already finalized in digest.final()");
return NULL;
}
if (h->result != NULL)
return h->result;
hash = h->hash;
digestsz = hashspec[hash].digestsz;
if (INIT_FINI(ctx)) {
b = malloc(sizeof(struct vmod_priv));
AN(b);
b->priv = malloc(digestsz);
AN(b->priv);
b->len = digestsz;
b->free = NULL;
final(hash, &h->ctx, b->priv);
h->result = b;
return b;
}
task = get_task(ctx, h);
CHECK_OBJ_NOTNULL(task, VMOD_BLOBDIGEST_DIGEST_TASK_MAGIC);
if (task->result != NULL)
return task->result;
CHECK_OBJ_NOTNULL(ctx->ws, WS_MAGIC);
snap = WS_Snapshot(ctx->ws);
/* XXX: use vcl_name in err messages */
......@@ -345,7 +364,7 @@ vmod_digest_final(VRT_CTX, struct vmod_blobdigest_digest *h)
b->len = digestsz;
b->free = NULL;
final(hash, &task->ctx, b->priv);
task->finalized = 1;
task->result = b;
return b;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment