Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
libvmod-ece
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
uplex-varnish
libvmod-ece
Commits
a2871806
Commit
a2871806
authored
Sep 18, 2019
by
Geoff Simmons
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add custom decrypter VFPs.
parent
eb7e4b3f
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
565 additions
and
23 deletions
+565
-23
Makefile.am
src/Makefile.am
+1
-1
decrypter.vtc
src/tests/decrypter.vtc
+296
-0
vfp.h
src/vfp.h
+20
-0
vfp_common.h
src/vfp_common.h
+0
-5
vfp_decrypt.c
src/vfp_decrypt.c
+28
-16
vmod_ece.c
src/vmod_ece.c
+213
-1
vmod_ece.vcc
src/vmod_ece.vcc
+7
-0
No files found.
src/Makefile.am
View file @
a2871806
...
...
@@ -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@
...
...
src/tests/decrypter.vtc
0 → 100644
View file @
a2871806
# 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"
src/vfp.h
View file @
a2871806
...
...
@@ -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
;
src/vfp_common.h
View file @
a2871806
...
...
@@ -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
)
{
...
...
src/vfp_decrypt.c
View file @
a2871806
...
...
@@ -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
,
};
src/vmod_ece.c
View file @
a2871806
...
...
@@ -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
)
{
...
...
src/vmod_ece.vcc
View file @
a2871806
...
...
@@ -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
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment