Commit a2871806 authored by Geoff Simmons's avatar Geoff Simmons

Add custom decrypter VFPs.

parent eb7e4b3f
......@@ -53,7 +53,7 @@ AM_TESTS_ENVIRONMENT = \
LD_LIBRARY_PATH="$(VARNISH_LIBRARY_PATH)" \
ENABLE_SET_SALT=@ENABLE_SET_SALT@
TEST_EXTENSIONS = .vtc
VTC_LOG_COMPILER = varnishtest -v
VTC_LOG_COMPILER = varnishtest -v -l
AM_VTC_LOG_FLAGS = -Dvmod_ece="$(VMOD_ECE)"
TESTS = @VMOD_TESTS@
......
# looks like -*- vcl -*-
varnishtest "decryption VFP with custom parameter settings"
# Test vectors from RFC 8188 ch 3.1 & 3.2
server s1 {
rxreq
txresp -nolen -hdr "Content-Encoding: aes128gcm" \
-hdr "Content-Length: 53"
sendhex "23 50 6c c6 d1 6d b6 5b f7 bb f3 a8 f7 8c 67 9b"
sendhex "00 00 10 00 00 f8 d0 15 b9 bd aa 16 00 44 b9 02"
sendhex "91 6a 9a 19 bb e2 31 90 8b da dc c1 01 d4 f0 fe"
sendhex "97 2f 13 86 38"
rxreq
txresp -nolen -hdr "Content-Encoding: aes128gcm" \
-hdr "Content-Length: 73"
sendhex "b8 d0 a4 5a 23 58 cc a4 e7 04 df 63 8b 7f aa 58"
sendhex "00 00 00 19 02 61 31 ce 1b c7 21 cf f8 27 be 03"
sendhex "aa 74 66 28 bf 1c a3 ba a4 72 24 58 c4 0f 2a 05"
sendhex "d4 5b e4 8f a8 50 3d d3 c7 23 9d 4e 11 42 84 a6"
sendhex "0c f7 4a c2 d6 22 a4 bf b8"
} -start
varnish v1 -arg "-p vsl_mask=+VfpAcct" -vcl+backend {
import ${vmod_ece};
import blob;
sub vcl_init {
# With all params set to defaults, the decrypter is
# just like the default ece_decrypt VFP.
new default_dup = ece.decrypter("default_dup");
ece.set_key("", blob.decode(BASE64URLNOPAD,
encoded="yqdlZ-tYemfogSmv7Ws5PQ"));
ece.set_key("a1", blob.decode(BASE64URLNOPAD,
encoded="BO3ZVPxUlnLORbVGMpbT1Q"));
}
sub vcl_backend_response {
set beresp.filters = "default_dup";
set beresp.uncacheable = true;
}
} -start
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.http.Content-Encoding == <undef>
expect resp.bodylen == 15
expect resp.body == "I am the walrus"
txreq
rxresp
expect resp.status == 200
expect resp.http.Content-Encoding == <undef>
expect resp.bodylen == 15
expect resp.body == "I am the walrus"
} -run
logexpect l1 -v v1 -d 1 -g vxid -q "VfpAcct" {
expect 0 * Begin bereq
expect * = Debug {^default_dup: id ""$}
expect 0 = Debug {^default_dup: record size 4096$}
expect 0 = Debug {^default_dup: chunk size 16384$}
expect * = VfpAcct {^default_dup \d+ 15$}
expect * = End
expect 0 * Begin bereq
expect * = Debug {^default_dup: id "a1"$}
expect 0 = Debug {^default_dup: record size 25$}
# chunksz rounded down to fit an even number of records
expect 0 = Debug {^default_dup: chunk size 16375$}
expect * = VfpAcct {^default_dup \d+ 15$}
expect * = End
} -run
server s1 -wait
server s1 -start
varnish v1 -vcl+backend {
import ${vmod_ece};
sub vcl_init {
# Use a chunk size that is smaller than the default.
new chunk4k = ece.decrypter("chunk4k", chunksz=4k);
}
sub vcl_backend_response {
set beresp.filters = "chunk4k";
set beresp.uncacheable = true;
}
}
logexpect l1 -v v1 -d 0 -g vxid -q "VfpAcct" {
expect 0 * Begin bereq
expect * = Debug {^chunk4k: id ""$}
expect 0 = Debug {^chunk4k: record size 4096$}
expect 0 = Debug {^chunk4k: chunk size 4096$}
expect * = VfpAcct {^chunk4k \d+ 15$}
expect * = End
expect 0 * Begin bereq
expect * = Debug {^chunk4k: id "a1"$}
expect 0 = Debug {^chunk4k: record size 25$}
# chunksz rounded down to fit an even number of records
expect 0 = Debug {^chunk4k: chunk size 4075$}
expect * = VfpAcct {^chunk4k \d+ 15$}
expect * = End
} -start
client c1 -run
logexpect l1 -wait
server s1 -wait
server s1 -start
varnish v1 -vcl+backend {
import ${vmod_ece};
sub vcl_init {
# max_rs=0 means that record sizes are only limited by INT_MAX.
new chunk4k = ece.decrypter("maxrs0", max_rs=0B);
}
sub vcl_backend_response {
set beresp.filters = "maxrs0";
set beresp.uncacheable = true;
}
}
logexpect l1 -v v1 -d 0 -g vxid -q "VfpAcct" {
expect 0 * Begin bereq
expect * = Debug {^maxrs0: id ""$}
expect 0 = Debug {^maxrs0: record size 4096$}
expect 0 = Debug {^maxrs0: chunk size 16384$}
expect * = VfpAcct {^maxrs0 \d+ 15$}
expect * = End
expect 0 * Begin bereq
expect * = Debug {^maxrs0: id "a1"$}
expect 0 = Debug {^maxrs0: record size 25$}
# chunksz rounded down as above.
expect 0 = Debug {^maxrs0: chunk size 16375$}
expect * = VfpAcct {^maxrs0 \d+ 15$}
expect * = End
} -start
client c1 -run
server s1 -wait
server s1 {
rxreq
txresp -nolen -hdr "Content-Encoding: aes128gcm" \
-hdr "Content-Length: 53"
sendhex "23 50 6c c6 d1 6d b6 5b f7 bb f3 a8 f7 8c 67 9b"
sendhex "00 00 10 00 00 f8 d0 15 b9 bd aa 16 00 44 b9 02"
sendhex "91 6a 9a 19 bb e2 31 90 8b da dc c1 01 d4 f0 fe"
sendhex "97 2f 13 86 38"
} -start
varnish v1 -vcl+backend {
import ${vmod_ece};
sub vcl_init {
# Set a max rs that is smaller than the record size
# specified by the response.
new rs1k = ece.decrypter("rs1k", max_rs=1k);
}
sub vcl_backend_response {
set beresp.filters = "rs1k";
set beresp.uncacheable = true;
set beresp.do_stream = false;
}
}
logexpect l1 -v v1 -d 0 -g vxid -q "FetchError" {
expect 0 * Begin bereq
expect * = FetchError {^ece decrypt: record size 4096 exceeds max 1024$}
expect * = End
} -start
client c1 {
txreq
rxresp
expect resp.status == 503
expect resp.reason == "Backend fetch failed"
} -run
varnish v1 -errvcl {vmod ece failure: new d: filter name must be non-empty} {
import ${vmod_ece};
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new d = ece.decrypter("");
}
}
varnish v1 -errvcl {vmod ece failure: new d: filter name ece_encrypt already in use by another VFP} {
import ${vmod_ece};
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new d = ece.decrypter("ece_encrypt");
}
}
varnish v1 -errvcl {vmod ece failure: new d: filter name ece_decrypt already in use by another VFP} {
import ${vmod_ece};
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new d = ece.decrypter("ece_decrypt");
}
}
varnish v1 -errvcl {vmod ece failure: new d: filter name esi already in use by another VFP} {
import ${vmod_ece};
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new d = ece.decrypter("esi");
}
}
varnish v1 -errvcl {vmod ece failure: new d: filter name esi_gzip already in use by another VFP} {
import ${vmod_ece};
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new d = ece.decrypter("esi_gzip");
}
}
varnish v1 -errvcl {vmod ece failure: new d: filter name gunzip already in use by another VFP} {
import ${vmod_ece};
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new d = ece.decrypter("gunzip");
}
}
varnish v1 -errvcl {vmod ece failure: new d: filter name gzip already in use by another VFP} {
import ${vmod_ece};
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new d = ece.decrypter("gzip");
}
}
varnish v1 -errvcl {vmod ece failure: new d: filter name testgunzip already in use by another VFP} {
import ${vmod_ece};
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new d = ece.decrypter("testgunzip");
}
}
varnish v1 -errvcl {vmod ece failure: new d: chunksz 4095 may not be < 4096} {
import ${vmod_ece};
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new d = ece.decrypter("small_chunks", chunksz=4095B);
}
}
varnish v1 -errvcl {vmod ece failure: new d: max_rs 17 too small (must be 0 or >= 18)} {
import ${vmod_ece};
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new d = ece.decrypter("small_rs", max_rs=17B);
}
}
varnish v1 -errvcl {vmod ece failure: new d: max_rs 4294967296 too large} {
import ${vmod_ece};
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new d = ece.decrypter("huge_rs", max_rs=4GB);
}
}
# Tests object finalization and DISCARD event.
varnish v1 -cli "vcl.discard vcl1"
varnish v1 -cli "vcl.discard vcl2"
varnish v1 -cli "vcl.discard vcl3"
varnish v1 -cli "vcl.list"
......@@ -28,4 +28,24 @@
#include "cache/cache_filter.h"
#define MIN_RS 18
struct vfp_settings {
unsigned magic;
#define VFP_SETTINGS_MAGIC 0x00b45435
size_t chunksz;
uint32_t rs;
};
/* VFP .fini method for both encrypt and decrypt */
void v_matchproto_(vfp_fini_f) vfp_common_fini(struct vfp_ctx *ctx,
struct vfp_entry *ent);
enum vfp_status v_matchproto_(vfp_init_f)
vfp_decrypt_init(struct vfp_ctx *ctx, struct vfp_entry *ent);
enum vfp_status v_matchproto_(vfp_pull_f)
vfp_decrypt_pull(struct vfp_ctx *ctx, struct vfp_entry *ent, void *ptr,
ssize_t *lenp);
extern const struct vfp vfp_decrypt, vfp_encrypt;
......@@ -37,7 +37,6 @@
#define HDR_PFX_LEN (SALT_LEN + 4 + 1)
#define MAX_ID_LEN UINT8_MAX
#define MIN_RS 18
#define ERR_VFP(ctx, type, msg) \
VFP_Error((ctx), "ece " type ": " msg)
......@@ -94,10 +93,6 @@ enum vfp_status crypto_init(struct vfp_ctx *ctx, struct ece_crypto *crypto,
enum vfp_status common_alloc(struct vfp_ctx *ctx, struct ece **ecep, int enc);
/* VFP .fini method for both encrypt and decrypt */
void v_matchproto_(vfp_fini_f) vfp_common_fini(struct vfp_ctx *ctx,
struct vfp_entry *ent);
static inline void
setInputBuf(struct ece_stream *stream, void *ptr, ssize_t len)
{
......
......@@ -37,7 +37,7 @@
VERR_VFP((ctx), "decrypt", fmt, __VA_ARGS__)
/* matches default fetch_chunksize */
#define DEFAULT_MAX_CHUNK (16 * 1024)
#define DEFAULT_CHUNKSZ (16 * 1024)
#define DEFAULT_MAX_RS (1024 * 1024)
......@@ -48,7 +48,8 @@
#define HDR_LEN(hdr) ((hdr)->next_in - (hdr)->hdr)
static enum vfp_status
decrypt_init(struct vfp_ctx *ctx, struct ece *ece)
decrypt_init(struct vfp_ctx *ctx, struct ece *ece,
const struct vfp_settings *settings, const char *vfp_name)
{
struct ece_hdrbuf *hdr;
enum vfp_status vp;
......@@ -62,6 +63,8 @@ decrypt_init(struct vfp_ctx *ctx, struct ece *ece)
CHECK_OBJ_NOTNULL(ece, ECE_MAGIC);
CHECK_OBJ_NOTNULL(ece->crypto, ECE_CRYPTO_MAGIC);
CHECK_OBJ_NOTNULL(ece->hdr, ECE_HDRBUF_MAGIC);
CHECK_OBJ_NOTNULL(settings, VFP_SETTINGS_MAGIC);
AN(vfp_name);
AZ(ece->rs);
AZ(ece->chunksz);
AZ(ece->buf);
......@@ -87,13 +90,10 @@ decrypt_init(struct vfp_ctx *ctx, struct ece *ece)
decode_header(hdr->hdr, &rs, &idlen);
if (rs < MIN_RS)
return (VERR(ctx, "invalid record size %u", rs));
/*
* XXX make max_rs configurable, 0 for unlimited
* A stat should show the rs high watermark.
*/
if (rs > DEFAULT_MAX_RS)
/* XXX a stat should show the rs high watermark. */
if (settings->rs != 0 && rs > settings->rs)
return (VERR(ctx, "record size %u exceeds max %u", rs,
DEFAULT_MAX_RS));
settings->rs));
if (rs > INT_MAX)
/*
* XXX This is because the input params to the libcrypto
......@@ -121,7 +121,7 @@ decrypt_init(struct vfp_ctx *ctx, struct ece *ece)
}
ece->rs = rs;
assert(ece->rs >= MIN_RS);
assert(ece->rs <= DEFAULT_MAX_RS);
assert(settings->rs == 0 || ece->rs <= settings->rs);
assert(ece->rs <= INT_MAX);
if (crypto_init(ctx, ece->crypto, hdr->hdr, hdr->hdr + HDR_PFX_LEN,
......@@ -129,7 +129,7 @@ decrypt_init(struct vfp_ctx *ctx, struct ece *ece)
return (VFP_ERROR);
/* set chunksz so that the fetches fit rs */
ece->chunksz = (DEFAULT_MAX_CHUNK / ece->rs) * ece->rs;
ece->chunksz = (settings->chunksz / ece->rs) * ece->rs;
if (ece->chunksz == 0)
ece->chunksz = ece->rs;
errno = 0;
......@@ -146,10 +146,10 @@ decrypt_init(struct vfp_ctx *ctx, struct ece *ece)
ece->stream->rec_next = ece->stream->rec_buf;
AZ(ece->stream->rec_avail);
VSLb(ctx->wrk->vsl, SLT_Debug, "ece_decrypt: id \"%.*s\"", idlen,
VSLb(ctx->wrk->vsl, SLT_Debug, "%s: id \"%.*s\"", vfp_name, idlen,
hdr->hdr + HDR_PFX_LEN);
VSLb(ctx->wrk->vsl, SLT_Debug, "ece_decrypt: record size %u", ece->rs);
VSLb(ctx->wrk->vsl, SLT_Debug, "ece_decrypt: chunk size %zu",
VSLb(ctx->wrk->vsl, SLT_Debug, "%s: record size %u", vfp_name, ece->rs);
VSLb(ctx->wrk->vsl, SLT_Debug, "%s: chunk size %zu", vfp_name,
ece->chunksz);
return (VFP_END);
......@@ -235,7 +235,7 @@ decrypt(struct vfp_ctx *ctx, struct ece *ece, enum vfp_status vp)
return (vp);
}
static enum vfp_status v_matchproto_(vfp_init_f)
enum vfp_status v_matchproto_(vfp_init_f)
vfp_decrypt_init(struct vfp_ctx *ctx, struct vfp_entry *ent)
{
struct ece *ece;
......@@ -267,12 +267,13 @@ vfp_decrypt_init(struct vfp_ctx *ctx, struct vfp_entry *ent)
* So we reject an empty body, but accept a header with no records. The
* latter results in a zero-length decryption.
*/
static enum vfp_status v_matchproto_(vfp_pull_f)
enum vfp_status v_matchproto_(vfp_pull_f)
vfp_decrypt_pull(struct vfp_ctx *ctx, struct vfp_entry *ent, void *ptr,
ssize_t *lenp)
{
struct ece *ece;
struct ece_stream *stream;
const struct vfp_settings *settings;
unsigned char *p = ptr;
enum vfp_status vp = VFP_OK;
......@@ -286,7 +287,11 @@ vfp_decrypt_pull(struct vfp_ctx *ctx, struct vfp_entry *ent, void *ptr,
stream = ece->stream;
if (ece->rs == 0) {
vp = decrypt_init(ctx, ece);
CHECK_OBJ_NOTNULL(ent, VFP_ENTRY_MAGIC);
AN(ent->vfp);
AN(ent->vfp->name);
CAST_OBJ_NOTNULL(settings, ent->vfp->priv1, VFP_SETTINGS_MAGIC);
vp = decrypt_init(ctx, ece, settings, ent->vfp->name);
if (vp == VFP_ERROR)
return (vp);
if (vp == VFP_NULL) {
......@@ -332,9 +337,16 @@ vfp_decrypt_pull(struct vfp_ctx *ctx, struct vfp_entry *ent, void *ptr,
return (vp);
}
static struct vfp_settings default_settings = {
.magic = VFP_SETTINGS_MAGIC,
.chunksz = DEFAULT_CHUNKSZ,
.rs = DEFAULT_MAX_RS,
};
const struct vfp vfp_decrypt = {
.name = "ece_decrypt",
.init = vfp_decrypt_init,
.pull = vfp_decrypt_pull,
.fini = vfp_common_fini,
.priv1 = &default_settings,
};
......@@ -26,6 +26,9 @@
* SUCH DAMAGE.
*/
/* for strdup() */
#define _POSIX_C_SOURCE 200809L
#include "config.h"
#include <string.h>
......@@ -40,20 +43,67 @@
#include "vfp.h"
#include "keys.h"
#define VFAIL(ctx, fmt, ...) \
VRT_fail((ctx), "vmod ece failure: " fmt, __VA_ARGS__)
/* minimum fetch_chunksize */
#define VARNISH_MIN_CHUNKSZ 4096
struct VPFX(ece_decrypter) {
unsigned magic;
#define ECE_DECRYPTER_MAGIC 0x2a28a833
char *vcl_name;
struct vfp *vfp;
};
struct custom_vfp_entry {
unsigned magic;
#define CUSTOM_VFP_MAGIC 0xfc88cb98
VSLIST_ENTRY(custom_vfp_entry) list;
struct vfp *vfp;
};
VSLIST_HEAD(custom_vfp_head, custom_vfp_entry);
/* Event function */
static struct custom_vfp_head *
init_priv_vcl(struct vmod_priv *priv)
{
struct custom_vfp_head *vfph;
AN(priv);
if (priv->priv == NULL) {
vfph = malloc(sizeof(*vfph));
AN(vfph);
priv->priv = vfph;
VSLIST_INIT(vfph);
}
else
vfph = priv->priv;
return (vfph);
}
int
VPFX(event)(VRT_CTX, struct vmod_priv *priv, enum vcl_event_e e)
{
struct custom_vfp_head *vfph;
struct custom_vfp_entry *vfpe;
struct vfp_settings *settings;
static int loaded = 0;
ASSERT_CLI();
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
AN(priv);
static int loaded = 0;
vfph = init_priv_vcl(priv);
AN(vfph);
switch(e) {
case VCL_EVENT_LOAD:
VRT_AddVFP(ctx, &vfp_encrypt);
VRT_AddVFP(ctx, &vfp_decrypt);
assert(loaded >= 0);
if (loaded++ == 0)
if (KEY_Init(ctx) != 0)
......@@ -62,6 +112,26 @@ VPFX(event)(VRT_CTX, struct vmod_priv *priv, enum vcl_event_e e)
case VCL_EVENT_DISCARD:
VRT_RemoveVFP(ctx, &vfp_encrypt);
VRT_RemoveVFP(ctx, &vfp_decrypt);
while (!VSLIST_EMPTY(vfph)) {
vfpe = VSLIST_FIRST(vfph);
CHECK_OBJ_NOTNULL(vfpe, CUSTOM_VFP_MAGIC);
if (vfpe->vfp != NULL) {
if (vfpe->vfp->priv1 != NULL) {
CAST_OBJ(settings,
TRUST_ME(vfpe->vfp->priv1),
VFP_SETTINGS_MAGIC);
if (settings != NULL)
FREE_OBJ(settings);
}
VRT_RemoveVFP(ctx, vfpe->vfp);
free(vfpe->vfp);
}
VSLIST_REMOVE_HEAD(vfph, list);
FREE_OBJ(vfpe);
}
free(vfph);
AN(loaded);
if (--loaded == 0)
KEY_Fini();
......@@ -75,6 +145,146 @@ VPFX(event)(VRT_CTX, struct vmod_priv *priv, enum vcl_event_e e)
NEEDLESS(return (0));
}
/* Object decrypter */
VCL_VOID
vmod_decrypter__init(VRT_CTX, struct VPFX(ece_decrypter) **decp,
const char *vcl_name, struct vmod_priv *priv,
VCL_STRING name, VCL_BYTES chunksz, VCL_BYTES max_rs)
{
struct VPFX(ece_decrypter) *dec;
struct vfp *vfp;
struct vfp_settings *settings;
struct custom_vfp_head *vfph;
struct custom_vfp_entry *vfpe;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
AN(decp);
AZ(*decp);
AN(vcl_name);
AN(priv);
AN(name);
if (*name == '\0') {
VFAIL(ctx, "new %s: filter name must be non-empty", vcl_name);
return;
}
if (strcmp(name, "ece_encrypt") == 0 || strcmp(name, "ece_decrypt") == 0
|| strcmp(name, "esi") == 0
|| strcmp(name, "esi_gzip") == 0
|| strcmp(name, "gunzip") == 0
|| strcmp(name, "gzip") == 0
|| strcmp(name, "testgunzip") == 0) {
VFAIL(ctx,
"new %s: filter name %s already in use by another VFP",
vcl_name, name);
return;
}
/* This catches chunksz < 0 (VCL_BYTES is int64_t, hence signed). */
if (chunksz < VARNISH_MIN_CHUNKSZ) {
VFAIL(ctx, "new %s: chunksz %jd may not be < %d", vcl_name,
(intmax_t)chunksz, VARNISH_MIN_CHUNKSZ);
return;
}
/* chunksz cannot be too large when cast to size_t */
assert(INT64_MAX <= SIZE_MAX);
if (max_rs != 0) {
/* Catches max_rs < 0. */
if (max_rs < MIN_RS) {
VFAIL(ctx, "new %s: max_rs %jd too small "
"(must be 0 or >= %d)", vcl_name,
(intmax_t)max_rs, MIN_RS);
return;
}
if (max_rs > INT_MAX) {
VFAIL(ctx, "new %s: max_rs %jd too large "
"(must be <= %d)", vcl_name, (intmax_t)max_rs,
INT_MAX);
return;
}
/* just in case INT_MAX >= UINT32_MAX */
if (max_rs > UINT32_MAX) {
VFAIL(ctx, "new %s: max_rs %jd too large "
"(must be <= %u)", vcl_name, (intmax_t)max_rs,
UINT32_MAX);
return;
}
}
errno = 0;
ALLOC_OBJ(dec, ECE_DECRYPTER_MAGIC);
if (dec == NULL) {
VFAIL(ctx, "new %s: cannot allocate space for object: %s",
vcl_name, strerror(errno));
return;
}
errno = 0;
vfp = malloc(sizeof(*vfp));
if (vfp == NULL) {
VFAIL(ctx, "new %s: cannot allocate space for VFP: %s",
vcl_name, vstrerror(errno));
return;
}
errno = 0;
ALLOC_OBJ(settings, VFP_SETTINGS_MAGIC);
if (settings == NULL) {
VFAIL(ctx, "new %s: cannot allocate space for settings: %s",
vcl_name, vstrerror(errno));
return;
}
errno = 0;
ALLOC_OBJ(vfpe, CUSTOM_VFP_MAGIC);
if (vfpe == NULL) {
VFAIL(ctx, "new %s: cannot allocate space for VFP list entry: %s",
vcl_name, vstrerror(errno));
return;
}
vfph = init_priv_vcl(priv);
AN(vfph);
settings->chunksz = (size_t)chunksz;
settings->rs = (uint32_t)max_rs;
vfp->name = strdup(name);
vfp->init = vfp_decrypt_init;
vfp->pull = vfp_decrypt_pull;
vfp->fini = vfp_common_fini;
vfp->priv1 = settings;
VRT_AddVFP(ctx, vfp);
vfpe->vfp = vfp;
VSLIST_INSERT_HEAD(vfph, vfpe, list);
dec->vfp = vfp;
dec->vcl_name = strdup(vcl_name);
*decp = dec;
}
/*
* The settings and custom VFP objects and PRIV_VCL list entry are freed
* on the DISCARD event, because we need a VRT_CTX to call
* VRT_RemoveVFP().
*/
VCL_VOID vmod_decrypter__fini(struct VPFX(ece_decrypter) **decp)
{
struct VPFX(ece_decrypter) *dec;
if (decp == NULL || *decp == NULL)
return;
TAKE_OBJ_NOTNULL(dec, decp, ECE_DECRYPTER_MAGIC);
if (dec->vcl_name != NULL)
free(dec->vcl_name);
FREE_OBJ(dec);
}
/* Key manipulation functions */
#define CHECK_ID(ctx, id, len, ret) \
do { \
if ((id) == NULL) { \
......@@ -205,6 +415,8 @@ vmod_dump_keys(VRT_CTX, VCL_ENUM zone)
KEY_Dump(ctx, tz);
}
/* Version functions */
VCL_STRING
vmod_libcrypto_version(VRT_CTX)
{
......
......@@ -56,6 +56,13 @@ Encryption and HTTP
XXX ...
$Object decrypter(PRIV_VCL, STRING name, BYTES chunksz=16384,
BYTES max_rs=1048576)
Create a decryption filter named ``name`` with custom parameters.
XXX ...
$Function VOID add_key(STRING id, BLOB key)
Add the keying material identified by ``id`` with the contents of the
......
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