aboutsummaryrefslogtreecommitdiff
path: root/src/regex/plugin_block_regex.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/regex/plugin_block_regex.c')
-rw-r--r--src/regex/plugin_block_regex.c287
1 files changed, 20 insertions, 267 deletions
diff --git a/src/regex/plugin_block_regex.c b/src/regex/plugin_block_regex.c
index 0953830ab..61442ac10 100644
--- a/src/regex/plugin_block_regex.c
+++ b/src/regex/plugin_block_regex.c
@@ -93,242 +93,6 @@ block_plugin_regex_create_group (void *cls,
93 93
94 94
95/** 95/**
96 * Function called to validate a reply or a request of type
97 * #GNUNET_BLOCK_TYPE_REGEX.
98 * For request evaluation, pass "NULL" for the reply_block.
99 * Note that it is assumed that the reply has already been
100 * matched to the key (and signatures checked) as it would
101 * be done with the #GNUNET_BLOCK_get_key() function.
102 *
103 * @param cls closure
104 * @param type block type
105 * @param bg block group to evaluate against
106 * @param eo control flags
107 * @param query original query (hash)
108 * @param xquery extrended query data (can be NULL, depending on type)
109 * @param xquery_size number of bytes in @a xquery
110 * @param reply_block response to validate
111 * @param reply_block_size number of bytes in @a reply_block
112 * @return characterization of result
113 */
114static enum GNUNET_BLOCK_EvaluationResult
115evaluate_block_regex (void *cls,
116 enum GNUNET_BLOCK_Type type,
117 struct GNUNET_BLOCK_Group *bg,
118 enum GNUNET_BLOCK_EvaluationOptions eo,
119 const struct GNUNET_HashCode *query,
120 const void *xquery,
121 size_t xquery_size,
122 const void *reply_block,
123 size_t reply_block_size)
124{
125 struct GNUNET_HashCode chash;
126
127 if (NULL == reply_block)
128 {
129 if (0 != xquery_size)
130 {
131 const char *s;
132
133 s = (const char *) xquery;
134 if ('\0' != s[xquery_size - 1]) /* must be valid 0-terminated string */
135 {
136 GNUNET_break_op (0);
137 return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID;
138 }
139 }
140 return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
141 }
142 if (0 != xquery_size)
143 {
144 const char *s;
145
146 s = (const char *) xquery;
147 if ('\0' != s[xquery_size - 1]) /* must be valid 0-terminated string */
148 {
149 GNUNET_break_op (0);
150 return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID;
151 }
152 }
153 else if (NULL != query)
154 {
155 /* xquery is required for regex GETs, at least an empty string */
156 GNUNET_break_op (0);
157 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "type %d, query %p, xquery %p\n",
158 type, query, xquery);
159 return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID;
160 }
161 switch (REGEX_BLOCK_check (reply_block,
162 reply_block_size,
163 query,
164 xquery))
165 {
166 case GNUNET_SYSERR:
167 GNUNET_break_op (0);
168 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
169
170 case GNUNET_NO:
171 /* xquery mismatch, can happen */
172 return GNUNET_BLOCK_EVALUATION_RESULT_IRRELEVANT;
173
174 default:
175 break;
176 }
177 GNUNET_CRYPTO_hash (reply_block,
178 reply_block_size,
179 &chash);
180 if (GNUNET_YES ==
181 GNUNET_BLOCK_GROUP_bf_test_and_set (bg,
182 &chash))
183 return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE;
184 return GNUNET_BLOCK_EVALUATION_OK_MORE;
185}
186
187
188/**
189 * Function called to validate a reply or a request of type
190 * #GNUNET_BLOCK_TYPE_REGEX_ACCEPT.
191 * For request evaluation, pass "NULL" for the reply_block.
192 * Note that it is assumed that the reply has already been
193 * matched to the key (and signatures checked) as it would
194 * be done with the #GNUNET_BLOCK_get_key() function.
195 *
196 * @param cls closure
197 * @param type block type
198 * @param bg block group to evaluate against
199 * @param eo control flags
200 * @param query original query (hash)
201 * @param xquery extrended query data (can be NULL, depending on type)
202 * @param xquery_size number of bytes in @a xquery
203 * @param reply_block response to validate
204 * @param reply_block_size number of bytes in @a reply_block
205 * @return characterization of result
206 */
207static enum GNUNET_BLOCK_EvaluationResult
208evaluate_block_regex_accept (void *cls,
209 enum GNUNET_BLOCK_Type type,
210 struct GNUNET_BLOCK_Group *bg,
211 enum GNUNET_BLOCK_EvaluationOptions eo,
212 const struct GNUNET_HashCode *query,
213 const void *xquery,
214 size_t xquery_size, const void *reply_block,
215 size_t reply_block_size)
216{
217 const struct RegexAcceptBlock *rba;
218 struct GNUNET_HashCode chash;
219
220 if (0 != xquery_size)
221 {
222 GNUNET_break_op (0);
223 return GNUNET_BLOCK_EVALUATION_REQUEST_INVALID;
224 }
225 if (NULL == reply_block)
226 return GNUNET_BLOCK_EVALUATION_REQUEST_VALID;
227 if (sizeof(struct RegexAcceptBlock) != reply_block_size)
228 {
229 GNUNET_break_op (0);
230 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
231 }
232 rba = reply_block;
233 if (ntohl (rba->purpose.size) !=
234 sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
235 + sizeof(struct GNUNET_TIME_AbsoluteNBO)
236 + sizeof(struct GNUNET_HashCode))
237 {
238 GNUNET_break_op (0);
239 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
240 }
241 if (0 == GNUNET_TIME_absolute_get_remaining (GNUNET_TIME_absolute_ntoh (
242 rba->expiration_time)).
243 rel_value_us)
244 {
245 /* technically invalid, but can happen without an error, so
246 we're nice by reporting it as a 'duplicate' */
247 return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE;
248 }
249 if (GNUNET_OK !=
250 GNUNET_CRYPTO_eddsa_verify_ (GNUNET_SIGNATURE_PURPOSE_REGEX_ACCEPT,
251 &rba->purpose,
252 &rba->signature,
253 &rba->peer.public_key))
254 {
255 GNUNET_break_op (0);
256 return GNUNET_BLOCK_EVALUATION_RESULT_INVALID;
257 }
258 GNUNET_CRYPTO_hash (reply_block,
259 reply_block_size,
260 &chash);
261 if (GNUNET_YES ==
262 GNUNET_BLOCK_GROUP_bf_test_and_set (bg,
263 &chash))
264 return GNUNET_BLOCK_EVALUATION_OK_DUPLICATE;
265 return GNUNET_BLOCK_EVALUATION_OK_MORE;
266}
267
268
269/**
270 * Function called to validate a reply or a request. For
271 * request evaluation, simply pass "NULL" for the reply_block.
272 * Note that it is assumed that the reply has already been
273 * matched to the key (and signatures checked) as it would
274 * be done with the #GNUNET_BLOCK_get_key() function.
275 *
276 * @param cls closure
277 * @param ctx block context
278 * @param type block type
279 * @param bg group to evaluate against
280 * @param eo control flags
281 * @param query original query (hash)
282 * @param xquery extrended query data (can be NULL, depending on type)
283 * @param xquery_size number of bytes in xquery
284 * @param reply_block response to validate
285 * @param reply_block_size number of bytes in reply block
286 * @return characterization of result
287 */
288static enum GNUNET_BLOCK_EvaluationResult
289block_plugin_regex_evaluate (void *cls,
290 struct GNUNET_BLOCK_Context *ctx,
291 enum GNUNET_BLOCK_Type type,
292 struct GNUNET_BLOCK_Group *bg,
293 enum GNUNET_BLOCK_EvaluationOptions eo,
294 const struct GNUNET_HashCode *query,
295 const void *xquery,
296 size_t xquery_size,
297 const void *reply_block,
298 size_t reply_block_size)
299{
300 enum GNUNET_BLOCK_EvaluationResult result;
301
302 switch (type)
303 {
304 case GNUNET_BLOCK_TYPE_REGEX:
305 result = evaluate_block_regex (cls,
306 type,
307 bg,
308 eo,
309 query,
310 xquery, xquery_size,
311 reply_block, reply_block_size);
312 break;
313
314 case GNUNET_BLOCK_TYPE_REGEX_ACCEPT:
315 result = evaluate_block_regex_accept (cls,
316 type,
317 bg,
318 eo,
319 query,
320 xquery, xquery_size,
321 reply_block, reply_block_size);
322 break;
323
324 default:
325 result = GNUNET_BLOCK_EVALUATION_TYPE_NOT_SUPPORTED;
326 }
327 return result;
328}
329
330
331/**
332 * Function called to validate a query. 96 * Function called to validate a query.
333 * 97 *
334 * @param cls closure 98 * @param cls closure
@@ -341,10 +105,10 @@ block_plugin_regex_evaluate (void *cls,
341 */ 105 */
342static enum GNUNET_GenericReturnValue 106static enum GNUNET_GenericReturnValue
343block_plugin_regex_check_query (void *cls, 107block_plugin_regex_check_query (void *cls,
344 enum GNUNET_BLOCK_Type type, 108 enum GNUNET_BLOCK_Type type,
345 const struct GNUNET_HashCode *query, 109 const struct GNUNET_HashCode *query,
346 const void *xquery, 110 const void *xquery,
347 size_t xquery_size) 111 size_t xquery_size)
348{ 112{
349 switch (type) 113 switch (type)
350 { 114 {
@@ -380,7 +144,6 @@ block_plugin_regex_check_query (void *cls,
380 * 144 *
381 * @param cls closure 145 * @param cls closure
382 * @param type block type 146 * @param type block type
383 * @param query key for the block (hash), must match exactly
384 * @param block block data to validate 147 * @param block block data to validate
385 * @param block_size number of bytes in @a block 148 * @param block_size number of bytes in @a block
386 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not 149 * @return #GNUNET_OK if the block is fine, #GNUNET_NO if not
@@ -388,7 +151,6 @@ block_plugin_regex_check_query (void *cls,
388static enum GNUNET_GenericReturnValue 151static enum GNUNET_GenericReturnValue
389block_plugin_regex_check_block (void *cls, 152block_plugin_regex_check_block (void *cls,
390 enum GNUNET_BLOCK_Type type, 153 enum GNUNET_BLOCK_Type type,
391 const struct GNUNET_HashCode *query,
392 const void *block, 154 const void *block,
393 size_t block_size) 155 size_t block_size)
394{ 156{
@@ -398,7 +160,7 @@ block_plugin_regex_check_block (void *cls,
398 if (GNUNET_SYSERR == 160 if (GNUNET_SYSERR ==
399 REGEX_BLOCK_check (block, 161 REGEX_BLOCK_check (block,
400 block_size, 162 block_size,
401 query, 163 NULL,
402 NULL)) 164 NULL))
403 return GNUNET_NO; 165 return GNUNET_NO;
404 return GNUNET_OK; 166 return GNUNET_OK;
@@ -480,12 +242,7 @@ block_plugin_regex_check_reply (
480 const char *s; 242 const char *s;
481 243
482 s = (const char *) xquery; 244 s = (const char *) xquery;
483 if ('\0' != s[xquery_size - 1]) /* must be valid 0-terminated string */ 245 GNUNET_assert ('\0' == s[xquery_size - 1]);
484 {
485 /* Technically, the query is invalid ... */
486 GNUNET_break (0);
487 return GNUNET_BLOCK_REPLY_INVALID;
488 }
489 } 246 }
490 switch (REGEX_BLOCK_check (reply_block, 247 switch (REGEX_BLOCK_check (reply_block,
491 reply_block_size, 248 reply_block_size,
@@ -493,8 +250,7 @@ block_plugin_regex_check_reply (
493 xquery)) 250 xquery))
494 { 251 {
495 case GNUNET_SYSERR: 252 case GNUNET_SYSERR:
496 GNUNET_break_op (0); 253 GNUNET_assert (0);
497 return GNUNET_BLOCK_REPLY_INVALID;
498 case GNUNET_NO: 254 case GNUNET_NO:
499 /* xquery mismatch, can happen */ 255 /* xquery mismatch, can happen */
500 return GNUNET_BLOCK_REPLY_IRRELEVANT; 256 return GNUNET_BLOCK_REPLY_IRRELEVANT;
@@ -513,20 +269,12 @@ block_plugin_regex_check_reply (
513 { 269 {
514 const struct RegexAcceptBlock *rba; 270 const struct RegexAcceptBlock *rba;
515 271
516 if (sizeof(struct RegexAcceptBlock) != reply_block_size) 272 GNUNET_assert (sizeof(struct RegexAcceptBlock) == reply_block_size);
517 {
518 GNUNET_break_op (0);
519 return GNUNET_BLOCK_REPLY_INVALID;
520 }
521 rba = reply_block; 273 rba = reply_block;
522 if (ntohl (rba->purpose.size) != 274 GNUNET_assert (ntohl (rba->purpose.size) ==
523 sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose) 275 sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
524 + sizeof(struct GNUNET_TIME_AbsoluteNBO) 276 + sizeof(struct GNUNET_TIME_AbsoluteNBO)
525 + sizeof(struct GNUNET_HashCode)) 277 + sizeof(struct GNUNET_HashCode));
526 {
527 GNUNET_break_op (0);
528 return GNUNET_BLOCK_REPLY_INVALID;
529 }
530 GNUNET_CRYPTO_hash (reply_block, 278 GNUNET_CRYPTO_hash (reply_block,
531 reply_block_size, 279 reply_block_size,
532 &chash); 280 &chash);
@@ -552,8 +300,8 @@ block_plugin_regex_check_reply (
552 * @param block block to get the key for 300 * @param block block to get the key for
553 * @param block_size number of bytes in @a block 301 * @param block_size number of bytes in @a block
554 * @param key set to the key (query) for the given block 302 * @param key set to the key (query) for the given block
555 * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported 303 * @return #GNUNET_OK on success, #GNUNET_SYSERR if type not supported,
556 * (or if extracting a key from a block of this type does not work) 304 * #GNUNET_NO if extracting a key from a block of this type does not work
557 */ 305 */
558static enum GNUNET_GenericReturnValue 306static enum GNUNET_GenericReturnValue
559block_plugin_regex_get_key (void *cls, 307block_plugin_regex_get_key (void *cls,
@@ -571,14 +319,20 @@ block_plugin_regex_get_key (void *cls,
571 key)) 319 key))
572 { 320 {
573 GNUNET_break_op (0); 321 GNUNET_break_op (0);
574 return GNUNET_NO; 322 memset (key,
323 0,
324 sizeof (*key));
325 return GNUNET_OK;
575 } 326 }
576 return GNUNET_OK; 327 return GNUNET_OK;
577 case GNUNET_BLOCK_TYPE_REGEX_ACCEPT: 328 case GNUNET_BLOCK_TYPE_REGEX_ACCEPT:
578 if (sizeof(struct RegexAcceptBlock) != block_size) 329 if (sizeof(struct RegexAcceptBlock) != block_size)
579 { 330 {
580 GNUNET_break_op (0); 331 GNUNET_break_op (0);
581 return GNUNET_NO; 332 memset (key,
333 0,
334 sizeof (*key));
335 return GNUNET_OK;
582 } 336 }
583 *key = ((struct RegexAcceptBlock *) block)->key; 337 *key = ((struct RegexAcceptBlock *) block)->key;
584 return GNUNET_OK; 338 return GNUNET_OK;
@@ -603,7 +357,6 @@ libgnunet_plugin_block_regex_init (void *cls)
603 struct GNUNET_BLOCK_PluginFunctions *api; 357 struct GNUNET_BLOCK_PluginFunctions *api;
604 358
605 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions); 359 api = GNUNET_new (struct GNUNET_BLOCK_PluginFunctions);
606 api->evaluate = &block_plugin_regex_evaluate;
607 api->get_key = &block_plugin_regex_get_key; 360 api->get_key = &block_plugin_regex_get_key;
608 api->check_query = &block_plugin_regex_check_query; 361 api->check_query = &block_plugin_regex_check_query;
609 api->check_block = &block_plugin_regex_check_block; 362 api->check_block = &block_plugin_regex_check_block;