| | varnish-cache/vmod/vmod_debug_filters.c |
0 |
|
/*- |
1 |
|
* Copyright (c) 2012-2019 Varnish Software AS |
2 |
|
* All rights reserved. |
3 |
|
* |
4 |
|
* Author: Poul-Henning Kamp <phk@FreeBSD.org> |
5 |
|
* |
6 |
|
* SPDX-License-Identifier: BSD-2-Clause |
7 |
|
* |
8 |
|
* Redistribution and use in source and binary forms, with or without |
9 |
|
* modification, are permitted provided that the following conditions |
10 |
|
* are met: |
11 |
|
* 1. Redistributions of source code must retain the above copyright |
12 |
|
* notice, this list of conditions and the following disclaimer. |
13 |
|
* 2. Redistributions in binary form must reproduce the above copyright |
14 |
|
* notice, this list of conditions and the following disclaimer in the |
15 |
|
* documentation and/or other materials provided with the distribution. |
16 |
|
* |
17 |
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
18 |
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
19 |
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
20 |
|
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE |
21 |
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
22 |
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
23 |
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
24 |
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
25 |
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
26 |
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
27 |
|
* SUCH DAMAGE. |
28 |
|
*/ |
29 |
|
|
30 |
|
#include "config.h" |
31 |
|
|
32 |
|
#include <stdlib.h> |
33 |
|
#include <stdio.h> |
34 |
|
#include <string.h> |
35 |
|
#include <sys/socket.h> |
36 |
|
#include <unistd.h> |
37 |
|
|
38 |
|
#include "cache/cache_varnishd.h" |
39 |
|
#include "cache/cache_filter.h" |
40 |
|
|
41 |
|
#include "vgz.h" |
42 |
|
#include "vsha256.h" |
43 |
|
#include "vtim.h" |
44 |
|
#include "vcc_debug_if.h" |
45 |
|
|
46 |
|
#include "vmod_debug.h" |
47 |
|
|
48 |
|
/**********************************************************************/ |
49 |
|
|
50 |
|
static enum vfp_status v_matchproto_(vfp_pull_f) |
51 |
198 |
xyzzy_vfp_rot13_pull(struct vfp_ctx *vc, struct vfp_entry *vfe, void *p, |
52 |
|
ssize_t *lp) |
53 |
|
{ |
54 |
|
enum vfp_status vp; |
55 |
|
char *q; |
56 |
|
ssize_t l; |
57 |
|
|
58 |
198 |
(void)vfe; |
59 |
198 |
vp = VFP_Suck(vc, p, lp); |
60 |
198 |
if (vp == VFP_ERROR) |
61 |
0 |
return (vp); |
62 |
198 |
q = p; |
63 |
5742 |
for (l = 0; l < *lp; l++, q++) { |
64 |
5544 |
if (*q >= 'A' && *q <= 'Z') |
65 |
792 |
*q = (((*q - 'A') + 13) % 26) + 'A'; |
66 |
5544 |
if (*q >= 'a' && *q <= 'z') |
67 |
3762 |
*q = (((*q - 'a') + 13) % 26) + 'a'; |
68 |
5544 |
} |
69 |
198 |
return (vp); |
70 |
198 |
} |
71 |
|
|
72 |
|
static const struct vfp xyzzy_vfp_rot13 = { |
73 |
|
.name = "rot13", |
74 |
|
.pull = xyzzy_vfp_rot13_pull, |
75 |
|
}; |
76 |
|
|
77 |
|
/**********************************************************************/ |
78 |
|
|
79 |
|
// deliberately fragmenting the stream to make testing more interesting |
80 |
|
#define ROT13_BUFSZ 8 |
81 |
|
|
82 |
|
static int v_matchproto_(vdp_init_f) |
83 |
308 |
xyzzy_vdp_rot13_init(VRT_CTX, struct vdp_ctx *vdc, void **priv) |
84 |
|
{ |
85 |
|
|
86 |
308 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
87 |
308 |
CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC); |
88 |
308 |
CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC); |
89 |
308 |
CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC); |
90 |
308 |
AN(vdc->clen); |
91 |
|
|
92 |
308 |
AN(priv); |
93 |
|
|
94 |
308 |
*priv = malloc(ROT13_BUFSZ); |
95 |
308 |
if (*priv == NULL) |
96 |
0 |
return (-1); |
97 |
|
|
98 |
308 |
return (0); |
99 |
308 |
} |
100 |
|
|
101 |
|
static int v_matchproto_(vdp_bytes_f) |
102 |
594 |
xyzzy_vdp_rot13_bytes(struct vdp_ctx *vdc, enum vdp_action act, void **priv, |
103 |
|
const void *ptr, ssize_t len) |
104 |
|
{ |
105 |
|
char *q; |
106 |
|
const char *pp; |
107 |
594 |
int i, j, retval = 0; |
108 |
|
|
109 |
594 |
CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC); |
110 |
594 |
AN(priv); |
111 |
594 |
AN(*priv); |
112 |
594 |
if (len <= 0) |
113 |
132 |
return (VDP_bytes(vdc, act, ptr, len)); |
114 |
462 |
AN(ptr); |
115 |
462 |
if (act != VDP_END) |
116 |
220 |
act = VDP_FLUSH; |
117 |
462 |
q = *priv; |
118 |
462 |
pp = ptr; |
119 |
|
|
120 |
12158 |
for (i = 0, j = 0; j < len; i++, j++) { |
121 |
11696 |
if (pp[j] >= 'A' && pp[j] <= 'Z') |
122 |
1012 |
q[i] = (((pp[j] - 'A') + 13) % 26) + 'A'; |
123 |
10684 |
else if (pp[j] >= 'a' && pp[j] <= 'z') |
124 |
7319 |
q[i] = (((pp[j] - 'a') + 13) % 26) + 'a'; |
125 |
|
else |
126 |
3365 |
q[i] = pp[j]; |
127 |
11696 |
if (i == ROT13_BUFSZ - 1 && j < len - 1) { |
128 |
1210 |
retval = VDP_bytes(vdc, VDP_FLUSH, q, ROT13_BUFSZ); |
129 |
1210 |
if (retval != 0) |
130 |
0 |
return (retval); |
131 |
1210 |
i = -1; |
132 |
1210 |
} |
133 |
11696 |
} |
134 |
462 |
if (i >= 0) |
135 |
462 |
retval = VDP_bytes(vdc, act, q, i); |
136 |
462 |
return (retval); |
137 |
594 |
} |
138 |
|
|
139 |
|
static int v_matchproto_(vdp_fini_f) |
140 |
286 |
xyzzy_vdp_rot13_fini(struct vdp_ctx *vdc, void **priv) |
141 |
|
{ |
142 |
286 |
(void)vdc; |
143 |
286 |
AN(priv); |
144 |
286 |
free(*priv); |
145 |
286 |
*priv = NULL; |
146 |
286 |
return (0); |
147 |
|
} |
148 |
|
|
149 |
|
static const struct vdp xyzzy_vdp_rot13 = { |
150 |
|
.name = "rot13", |
151 |
|
.init = xyzzy_vdp_rot13_init, |
152 |
|
.bytes = xyzzy_vdp_rot13_bytes, |
153 |
|
.fini = xyzzy_vdp_rot13_fini, |
154 |
|
}; |
155 |
|
|
156 |
|
VCL_VOID v_matchproto_(td_debug_rot104) |
157 |
22 |
xyzzy_rot104(VRT_CTX) |
158 |
|
{ |
159 |
|
|
160 |
22 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
161 |
|
// This should fail |
162 |
22 |
AN(VRT_AddFilter(ctx, &xyzzy_vfp_rot13, &xyzzy_vdp_rot13)); |
163 |
22 |
} |
164 |
|
|
165 |
|
/********************************************************************** |
166 |
|
* vdp debug_chunked: force http1 chunked encoding by removing the |
167 |
|
* Content-Length header |
168 |
|
* |
169 |
|
* this happens in a VDP because cnt_transmit() runs after VCL and |
170 |
|
* restores it |
171 |
|
*/ |
172 |
|
|
173 |
|
static int v_matchproto_(vdp_init_f) |
174 |
44 |
xyzzy_vdp_chunked_init(VRT_CTX, struct vdp_ctx *vdc, void **priv) |
175 |
|
{ |
176 |
|
|
177 |
44 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
178 |
44 |
CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC); |
179 |
44 |
CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC); |
180 |
44 |
CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC); |
181 |
44 |
AN(vdc->clen); |
182 |
44 |
AN(priv); |
183 |
|
|
184 |
44 |
http_Unset(vdc->hp, H_Content_Length); |
185 |
44 |
*vdc->clen = -1; |
186 |
|
|
187 |
44 |
return (1); |
188 |
|
} |
189 |
|
|
190 |
|
static const struct vdp xyzzy_vdp_chunked = { |
191 |
|
.name = "debug.chunked", |
192 |
|
.init = xyzzy_vdp_chunked_init, |
193 |
|
}; |
194 |
|
|
195 |
|
/********************************************************************** |
196 |
|
* pedantic tests of the VDP API: |
197 |
|
* - assert that we see a VDP_END |
198 |
|
* - assert that _fini gets called before the task ends |
199 |
|
* |
200 |
|
* note: |
201 |
|
* we could lookup our own vdpe in _fini and check for vdpe->end == VDP_END |
202 |
|
* yet that would cross the API |
203 |
|
*/ |
204 |
|
|
205 |
|
enum vdp_state_e { |
206 |
|
VDPS_NULL = 0, |
207 |
|
VDPS_INIT, // _init called |
208 |
|
VDPS_BYTES, // _bytes called act != VDP_END |
209 |
|
VDPS_END, // _bytes called act == VDP_END |
210 |
|
VDPS_FINI // _fini called |
211 |
|
}; |
212 |
|
|
213 |
|
struct vdp_state_s { |
214 |
|
unsigned magic; |
215 |
|
#define VDP_STATE_MAGIC 0x57c8d309 |
216 |
|
enum vdp_state_e state; |
217 |
|
}; |
218 |
|
|
219 |
|
static void v_matchproto_(vmod_priv_fini_f) |
220 |
4158 |
priv_pedantic_fini(VRT_CTX, void *priv) |
221 |
|
{ |
222 |
|
struct vdp_state_s *vdps; |
223 |
|
|
224 |
4158 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
225 |
4158 |
CAST_OBJ_NOTNULL(vdps, priv, VDP_STATE_MAGIC); |
226 |
|
|
227 |
4158 |
assert(vdps->state == VDPS_FINI); |
228 |
4158 |
} |
229 |
|
|
230 |
|
static const struct vmod_priv_methods priv_pedantic_methods[1] = {{ |
231 |
|
.magic = VMOD_PRIV_METHODS_MAGIC, |
232 |
|
.type = "debug_vdp_pedantic", |
233 |
|
.fini = priv_pedantic_fini |
234 |
|
}}; |
235 |
|
|
236 |
|
static int v_matchproto_(vdp_init_f) |
237 |
4334 |
xyzzy_pedantic_init(VRT_CTX, struct vdp_ctx *vdc, void **priv) |
238 |
|
{ |
239 |
|
struct vdp_state_s *vdps; |
240 |
|
struct vmod_priv *p; |
241 |
|
|
242 |
4334 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
243 |
4334 |
CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC); |
244 |
4334 |
CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC); |
245 |
4334 |
CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC); |
246 |
4334 |
AN(vdc->clen); |
247 |
4334 |
AN(priv); |
248 |
|
|
249 |
8492 |
WS_TASK_ALLOC_OBJ(ctx, vdps, VDP_STATE_MAGIC); |
250 |
4334 |
if (vdps == NULL) |
251 |
176 |
return (-1); |
252 |
4158 |
assert(vdps->state == VDPS_NULL); |
253 |
|
|
254 |
4158 |
p = VRT_priv_task(ctx, (void *)vdc); |
255 |
4158 |
if (p == NULL) |
256 |
0 |
return (-1); |
257 |
4158 |
p->priv = vdps; |
258 |
4158 |
p->methods = priv_pedantic_methods; |
259 |
|
|
260 |
4158 |
*priv = vdps; |
261 |
|
|
262 |
4158 |
vdps->state = VDPS_INIT; |
263 |
|
|
264 |
4158 |
return (0); |
265 |
4334 |
} |
266 |
|
|
267 |
|
static int v_matchproto_(vdp_bytes_f) |
268 |
5167 |
xyzzy_pedantic_bytes(struct vdp_ctx *vdc, enum vdp_action act, void **priv, |
269 |
|
const void *ptr, ssize_t len) |
270 |
|
{ |
271 |
|
struct vdp_state_s *vdps; |
272 |
|
|
273 |
5167 |
CAST_OBJ_NOTNULL(vdps, *priv, VDP_STATE_MAGIC); |
274 |
5167 |
assert(vdps->state >= VDPS_INIT); |
275 |
5167 |
assert(vdps->state < VDPS_END); |
276 |
|
|
277 |
5167 |
if (act == VDP_END) |
278 |
1342 |
vdps->state = VDPS_END; |
279 |
|
else |
280 |
3825 |
vdps->state = VDPS_BYTES; |
281 |
|
|
282 |
5167 |
return (VDP_bytes(vdc, act, ptr, len)); |
283 |
|
} |
284 |
|
|
285 |
|
static int v_matchproto_(vdp_fini_f) |
286 |
4334 |
xyzzy_pedantic_fini(struct vdp_ctx *vdc, void **priv) |
287 |
|
{ |
288 |
|
struct vdp_state_s *vdps; |
289 |
|
|
290 |
4334 |
(void) vdc; |
291 |
4334 |
AN(priv); |
292 |
4334 |
if (*priv == NULL) |
293 |
176 |
return (0); |
294 |
4158 |
CAST_OBJ_NOTNULL(vdps, *priv, VDP_STATE_MAGIC); |
295 |
4158 |
assert(vdps->state == VDPS_INIT || vdps->state == VDPS_END); |
296 |
4158 |
vdps->state = VDPS_FINI; |
297 |
|
|
298 |
4158 |
*priv = NULL; |
299 |
4158 |
return (0); |
300 |
4334 |
} |
301 |
|
|
302 |
|
static const struct vdp xyzzy_vdp_pedantic = { |
303 |
|
.name = "debug.pedantic", |
304 |
|
.init = xyzzy_pedantic_init, |
305 |
|
.bytes = xyzzy_pedantic_bytes, |
306 |
|
.fini = xyzzy_pedantic_fini, |
307 |
|
}; |
308 |
|
|
309 |
|
/********************************************************************** |
310 |
|
* |
311 |
|
* this trivial copy/paste/edit filter (of rot13) was specifically made for |
312 |
|
* someone who added a DBG_SLOW_BEREQ debug flag. It should actually be turned |
313 |
|
* in a proper "bandwidth control" filter, but that exceeds an evening's work, |
314 |
|
* so it's kept for later |
315 |
|
*/ |
316 |
|
|
317 |
|
static enum vfp_status v_matchproto_(vfp_pull_f) |
318 |
0 |
xyzzy_vfp_slow_pull(struct vfp_ctx *vc, struct vfp_entry *vfe, void *p, |
319 |
|
ssize_t *lp) |
320 |
|
{ |
321 |
|
|
322 |
0 |
(void)vfe; |
323 |
0 |
VTIM_sleep(1.0); |
324 |
0 |
return (VFP_Suck(vc, p, lp)); |
325 |
|
} |
326 |
|
|
327 |
|
static const struct vfp xyzzy_vfp_slow = { |
328 |
|
.name = "debug.slow", |
329 |
|
.pull = xyzzy_vfp_slow_pull, |
330 |
|
}; |
331 |
|
|
332 |
|
/**********************************************************************/ |
333 |
|
|
334 |
|
static int v_matchproto_(vdp_bytes_f) |
335 |
88 |
xyzzy_vdp_slow_bytes(struct vdp_ctx *vdc, enum vdp_action act, void **priv, |
336 |
|
const void *ptr, ssize_t len) |
337 |
|
{ |
338 |
|
|
339 |
88 |
(void)priv; |
340 |
88 |
VTIM_sleep(1.0); |
341 |
88 |
return (VDP_bytes(vdc, act, ptr, len)); |
342 |
|
} |
343 |
|
|
344 |
|
static const struct vdp xyzzy_vdp_slow = { |
345 |
|
.name = "debug.slow", |
346 |
|
.bytes = xyzzy_vdp_slow_bytes |
347 |
|
}; |
348 |
|
|
349 |
|
/* |
350 |
|
* checksum VDP: |
351 |
|
* test that the stream of bytes has a certain checksum and either log |
352 |
|
* or panic |
353 |
|
* |
354 |
|
* The sha256 and crc32 variants are basically identical, but the amount of |
355 |
|
* code does not justify generalizing. (slink) |
356 |
|
*/ |
357 |
|
|
358 |
|
enum vdp_chk_mode_e { |
359 |
|
//lint -esym(749, vdp_chk_mode_e::VDP_CHK_INVAL) deliberately not referenced |
360 |
|
VDP_CHK_INVAL = 0, |
361 |
|
VDP_CHK_LOG, |
362 |
|
VDP_CHK_PANIC, |
363 |
|
VDP_CHK_PANIC_UNLESS_ERROR |
364 |
|
}; |
365 |
|
|
366 |
|
struct vdp_chksha256_cfg_s { |
367 |
|
unsigned magic; |
368 |
|
#define VDP_CHKSHA256_CFG_MAGIC 0x624f5b32 |
369 |
|
enum vdp_chk_mode_e mode; |
370 |
|
unsigned char expected[VSHA256_DIGEST_LENGTH]; |
371 |
|
}; |
372 |
|
|
373 |
|
struct vdp_chkcrc32_cfg_s { |
374 |
|
unsigned magic; |
375 |
|
#define VDP_CHKCRC32_CFG_MAGIC 0x5a7a835c |
376 |
|
enum vdp_chk_mode_e mode; |
377 |
|
uint32_t expected; |
378 |
|
}; |
379 |
|
|
380 |
|
struct vdp_chksha256_s { |
381 |
|
unsigned magic; |
382 |
|
#define VDP_CHKSHA256_MAGIC 0x6856e913 |
383 |
|
unsigned called; |
384 |
|
size_t bytes; |
385 |
|
struct VSHA256Context cx[1]; |
386 |
|
struct vdp_chksha256_cfg_s *cfg; |
387 |
|
}; |
388 |
|
|
389 |
|
struct vdp_chkcrc32_s { |
390 |
|
unsigned magic; |
391 |
|
#define VDP_CHKCRC32_MAGIC 0x15c03d3c |
392 |
|
unsigned called; |
393 |
|
size_t bytes; |
394 |
|
uint32_t crc; |
395 |
|
struct vdp_chkcrc32_cfg_s *cfg; |
396 |
|
}; |
397 |
|
|
398 |
|
static const void * const chksha256_priv_id = &chksha256_priv_id; |
399 |
|
static const void * const chkcrc32_priv_id = &chkcrc32_priv_id; |
400 |
|
|
401 |
|
static int v_matchproto_(vdp_init_f) |
402 |
0 |
xyzzy_chksha256_init(VRT_CTX, struct vdp_ctx *vdc, void **priv) |
403 |
|
{ |
404 |
|
struct vdp_chksha256_s *vdps; |
405 |
|
struct vmod_priv *p; |
406 |
|
|
407 |
0 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
408 |
0 |
CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC); |
409 |
0 |
CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC); |
410 |
0 |
CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC); |
411 |
0 |
AN(vdc->clen); |
412 |
0 |
AN(priv); |
413 |
|
|
414 |
0 |
WS_TASK_ALLOC_OBJ(ctx, vdps, VDP_CHKSHA256_MAGIC); |
415 |
0 |
if (vdps == NULL) |
416 |
0 |
return (-1); |
417 |
0 |
VSHA256_Init(vdps->cx); |
418 |
|
|
419 |
0 |
p = VRT_priv_task_get(ctx, chksha256_priv_id); |
420 |
0 |
if (p == NULL) |
421 |
0 |
return (-1); |
422 |
|
|
423 |
0 |
assert(p->len == sizeof(struct vdp_chksha256_cfg_s)); |
424 |
0 |
CAST_OBJ_NOTNULL(vdps->cfg, p->priv, VDP_CHKSHA256_CFG_MAGIC); |
425 |
0 |
*priv = vdps; |
426 |
|
|
427 |
0 |
return (0); |
428 |
0 |
} |
429 |
|
|
430 |
|
static int v_matchproto_(vdp_init_f) |
431 |
0 |
xyzzy_chkcrc32_init(VRT_CTX, struct vdp_ctx *vdc, void **priv) |
432 |
|
{ |
433 |
|
struct vdp_chkcrc32_s *vdps; |
434 |
|
struct vmod_priv *p; |
435 |
|
|
436 |
0 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
437 |
0 |
CHECK_OBJ_NOTNULL(vdc, VDP_CTX_MAGIC); |
438 |
0 |
CHECK_OBJ_ORNULL(vdc->oc, OBJCORE_MAGIC); |
439 |
0 |
CHECK_OBJ_NOTNULL(vdc->hp, HTTP_MAGIC); |
440 |
0 |
AN(vdc->clen); |
441 |
0 |
AN(priv); |
442 |
|
|
443 |
0 |
WS_TASK_ALLOC_OBJ(ctx, vdps, VDP_CHKCRC32_MAGIC); |
444 |
0 |
if (vdps == NULL) |
445 |
0 |
return (-1); |
446 |
0 |
vdps->crc = crc32(0L, Z_NULL, 0); |
447 |
|
|
448 |
0 |
p = VRT_priv_task_get(ctx, chkcrc32_priv_id); |
449 |
0 |
if (p == NULL) |
450 |
0 |
return (-1); |
451 |
|
|
452 |
0 |
assert(p->len == sizeof(struct vdp_chkcrc32_cfg_s)); |
453 |
0 |
CAST_OBJ_NOTNULL(vdps->cfg, p->priv, VDP_CHKCRC32_CFG_MAGIC); |
454 |
0 |
*priv = vdps; |
455 |
|
|
456 |
0 |
return (0); |
457 |
0 |
} |
458 |
|
|
459 |
|
static int v_matchproto_(vdp_bytes_f) |
460 |
0 |
xyzzy_chksha256_bytes(struct vdp_ctx *vdc, enum vdp_action act, void **priv, |
461 |
|
const void *ptr, ssize_t len) |
462 |
|
{ |
463 |
|
struct vdp_chksha256_s *vdps; |
464 |
|
|
465 |
0 |
CAST_OBJ_NOTNULL(vdps, *priv, VDP_CHKSHA256_MAGIC); |
466 |
0 |
VSHA256_Update(vdps->cx, ptr, len); |
467 |
0 |
vdps->called++; |
468 |
0 |
vdps->bytes += len; |
469 |
0 |
return (VDP_bytes(vdc, act, ptr, len)); |
470 |
|
} |
471 |
|
|
472 |
|
static int v_matchproto_(vdp_bytes_f) |
473 |
0 |
xyzzy_chkcrc32_bytes(struct vdp_ctx *vdc, enum vdp_action act, void **priv, |
474 |
|
const void *ptr, ssize_t len) |
475 |
|
{ |
476 |
|
struct vdp_chkcrc32_s *vdps; |
477 |
|
|
478 |
0 |
CAST_OBJ_NOTNULL(vdps, *priv, VDP_CHKCRC32_MAGIC); |
479 |
0 |
if (len > 0) |
480 |
0 |
vdps->crc = crc32(vdps->crc, ptr, len); |
481 |
0 |
vdps->called++; |
482 |
0 |
vdps->bytes += len; |
483 |
0 |
return (VDP_bytes(vdc, act, ptr, len)); |
484 |
|
} |
485 |
|
|
486 |
|
static int v_matchproto_(vdp_fini_f) |
487 |
0 |
xyzzy_chksha256_fini(struct vdp_ctx *vdc, void **priv) |
488 |
|
{ |
489 |
|
unsigned char digest[VSHA256_DIGEST_LENGTH]; |
490 |
|
enum vdp_chk_mode_e mode; |
491 |
|
struct vdp_chksha256_s *vdps; |
492 |
|
struct vsb *vsb; |
493 |
|
int r; |
494 |
|
|
495 |
0 |
(void) vdc; |
496 |
0 |
AN(priv); |
497 |
0 |
if (*priv == NULL) |
498 |
0 |
return (0); |
499 |
0 |
CAST_OBJ_NOTNULL(vdps, *priv, VDP_CHKSHA256_MAGIC); |
500 |
0 |
*priv = NULL; |
501 |
|
|
502 |
0 |
VSHA256_Final(digest, vdps->cx); |
503 |
0 |
r = memcmp(digest, vdps->cfg->expected, sizeof digest); |
504 |
0 |
if (r == 0) |
505 |
0 |
return (0); |
506 |
|
|
507 |
0 |
mode = vdps->cfg->mode; |
508 |
0 |
if (mode == VDP_CHK_PANIC_UNLESS_ERROR) |
509 |
0 |
mode = (vdps->called == 0 || vdc->retval != 0) ? VDP_CHK_LOG : VDP_CHK_PANIC; |
510 |
|
|
511 |
0 |
if (mode == VDP_CHK_LOG) { |
512 |
0 |
VSLb(vdc->vsl, SLT_Debug, "sha256 checksum mismatch"); |
513 |
|
|
514 |
0 |
vsb = VSB_new_auto(); |
515 |
0 |
AN(vsb); |
516 |
0 |
VSB_quote(vsb, digest, sizeof digest, VSB_QUOTE_HEX); |
517 |
0 |
AZ(VSB_finish(vsb)); |
518 |
0 |
VSLb(vdc->vsl, SLT_Debug, "got: %s", VSB_data(vsb)); |
519 |
|
|
520 |
0 |
VSB_clear(vsb); |
521 |
0 |
VSB_quote(vsb, vdps->cfg->expected, sizeof digest, VSB_QUOTE_HEX); |
522 |
0 |
AZ(VSB_finish(vsb)); |
523 |
0 |
VSLb(vdc->vsl, SLT_Debug, "exp: %s", VSB_data(vsb)); |
524 |
0 |
VSB_destroy(&vsb); |
525 |
0 |
} |
526 |
0 |
else if (mode == VDP_CHK_PANIC) |
527 |
0 |
WRONG("body checksum"); |
528 |
|
else |
529 |
0 |
WRONG("mode"); |
530 |
|
|
531 |
0 |
return (0); |
532 |
0 |
} |
533 |
|
|
534 |
|
static int v_matchproto_(vdp_fini_f) |
535 |
0 |
xyzzy_chkcrc32_fini(struct vdp_ctx *vdc, void **priv) |
536 |
|
{ |
537 |
|
enum vdp_chk_mode_e mode; |
538 |
|
struct vdp_chkcrc32_s *vdps; |
539 |
|
|
540 |
0 |
(void) vdc; |
541 |
0 |
AN(priv); |
542 |
0 |
if (*priv == NULL) |
543 |
0 |
return (0); |
544 |
0 |
CAST_OBJ_NOTNULL(vdps, *priv, VDP_CHKCRC32_MAGIC); |
545 |
0 |
*priv = NULL; |
546 |
|
|
547 |
0 |
if (vdps->crc == vdps->cfg->expected) |
548 |
0 |
return (0); |
549 |
|
|
550 |
0 |
mode = vdps->cfg->mode; |
551 |
0 |
if (mode == VDP_CHK_PANIC_UNLESS_ERROR) |
552 |
0 |
mode = (vdps->called == 0 || vdc->retval != 0) ? VDP_CHK_LOG : VDP_CHK_PANIC; |
553 |
|
|
554 |
0 |
if (mode == VDP_CHK_LOG) { |
555 |
0 |
VSLb(vdc->vsl, SLT_Debug, "crc32 checksum mismatch"); |
556 |
0 |
VSLb(vdc->vsl, SLT_Debug, "got: %08x", vdps->crc); |
557 |
0 |
VSLb(vdc->vsl, SLT_Debug, "exp: %08x", vdps->cfg->expected); |
558 |
0 |
} |
559 |
0 |
else if (mode == VDP_CHK_PANIC) |
560 |
0 |
WRONG("body checksum"); |
561 |
|
else |
562 |
0 |
WRONG("mode"); |
563 |
|
|
564 |
0 |
return (0); |
565 |
0 |
} |
566 |
|
|
567 |
|
static const struct vdp xyzzy_vdp_chksha256 = { |
568 |
|
.name = "debug.chksha256", |
569 |
|
.init = xyzzy_chksha256_init, |
570 |
|
.bytes = xyzzy_chksha256_bytes, |
571 |
|
.fini = xyzzy_chksha256_fini, |
572 |
|
}; |
573 |
|
|
574 |
|
static const struct vdp xyzzy_vdp_chkcrc32 = { |
575 |
|
.name = "debug.chkcrc32", |
576 |
|
.init = xyzzy_chkcrc32_init, |
577 |
|
.bytes = xyzzy_chkcrc32_bytes, |
578 |
|
.fini = xyzzy_chkcrc32_fini, |
579 |
|
}; |
580 |
|
|
581 |
|
#define chkcfg(ws, cfg, magic, id, mode_e) do { \ |
582 |
|
struct vmod_priv *p = VRT_priv_task(ctx, id); \ |
583 |
|
\ |
584 |
|
XXXAN(p); \ |
585 |
|
if (p->priv == NULL) { \ |
586 |
|
p->priv = WS_Alloc(ws, sizeof *cfg); \ |
587 |
|
p->len = sizeof *cfg; \ |
588 |
|
} \ |
589 |
|
cfg = p->priv; \ |
590 |
|
INIT_OBJ(cfg, magic); \ |
591 |
|
if (mode_e == VENUM(log)) \ |
592 |
|
cfg->mode = VDP_CHK_LOG; \ |
593 |
|
else if (mode_e == VENUM(panic)) \ |
594 |
|
cfg->mode = VDP_CHK_PANIC; \ |
595 |
|
else if (mode_e == VENUM(panic_unless_error)) \ |
596 |
|
cfg->mode = VDP_CHK_PANIC_UNLESS_ERROR; \ |
597 |
|
else \ |
598 |
|
WRONG("mode"); \ |
599 |
|
} while(0) |
600 |
|
|
601 |
|
VCL_VOID v_matchproto_(td_xyzzy_debug_chksha256) |
602 |
0 |
xyzzy_chksha256(VRT_CTX, VCL_BLOB blob, VCL_ENUM mode_e) |
603 |
|
{ |
604 |
|
struct vdp_chksha256_cfg_s *cfg; |
605 |
|
size_t l; |
606 |
|
|
607 |
0 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
608 |
0 |
AN(blob); |
609 |
0 |
XXXAN(blob->blob); |
610 |
0 |
XXXAN(blob->len); |
611 |
|
|
612 |
0 |
chkcfg(ctx->ws, cfg, VDP_CHKSHA256_CFG_MAGIC, chksha256_priv_id, mode_e); |
613 |
|
|
614 |
0 |
l = blob->len; |
615 |
0 |
if (l > sizeof cfg->expected) |
616 |
0 |
l = sizeof cfg->expected; |
617 |
0 |
memcpy(cfg->expected, blob->blob, l); |
618 |
|
|
619 |
0 |
} |
620 |
|
|
621 |
|
VCL_VOID v_matchproto_(td_xyzzy_debug_chkcrc32) |
622 |
0 |
xyzzy_chkcrc32(VRT_CTX, VCL_INT expected, VCL_ENUM mode_e) |
623 |
|
{ |
624 |
|
struct vdp_chkcrc32_cfg_s *cfg; |
625 |
|
|
626 |
0 |
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); |
627 |
|
|
628 |
0 |
chkcfg(ctx->ws, cfg, VDP_CHKCRC32_CFG_MAGIC, chkcrc32_priv_id, mode_e); |
629 |
|
|
630 |
0 |
if (expected < 0) |
631 |
0 |
expected = 0; |
632 |
0 |
cfg->expected = (uintmax_t)expected % UINT32_MAX; |
633 |
0 |
} |
634 |
|
|
635 |
|
void |
636 |
2112 |
debug_add_filters(VRT_CTX) |
637 |
|
{ |
638 |
2112 |
AZ(VRT_AddFilter(ctx, &xyzzy_vfp_rot13, &xyzzy_vdp_rot13)); |
639 |
2112 |
AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_pedantic)); |
640 |
2112 |
AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_chunked)); |
641 |
2112 |
AZ(VRT_AddFilter(ctx, &xyzzy_vfp_slow, &xyzzy_vdp_slow)); |
642 |
2112 |
AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_chksha256)); |
643 |
2112 |
AZ(VRT_AddFilter(ctx, NULL, &xyzzy_vdp_chkcrc32)); |
644 |
2112 |
} |
645 |
|
|
646 |
|
void |
647 |
506 |
debug_remove_filters(VRT_CTX) |
648 |
|
{ |
649 |
506 |
VRT_RemoveFilter(ctx, &xyzzy_vfp_slow, &xyzzy_vdp_slow); |
650 |
506 |
VRT_RemoveFilter(ctx, &xyzzy_vfp_rot13, &xyzzy_vdp_rot13); |
651 |
506 |
VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_pedantic); |
652 |
506 |
VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_chunked); |
653 |
506 |
VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_chksha256); |
654 |
506 |
VRT_RemoveFilter(ctx, NULL, &xyzzy_vdp_chkcrc32); |
655 |
506 |
} |