]> git.ozlabs.org Git - ccan/blob - ccan/rune/rune.c
0ff7968b4aa9b093f42bb5febdd6fb4b455b8e25
[ccan] / ccan / rune / rune.c
1 /* MIT (BSD) license - see LICENSE file for details */
2 #include "config.h"
3 #include <assert.h>
4 #include <errno.h>
5 #include <inttypes.h>
6 #include <stdio.h>
7 #include <ccan/endian/endian.h>
8 #include <ccan/mem/mem.h>
9 #include <ccan/tal/str/str.h>
10 #include <ccan/rune/rune.h>
11 #include <ccan/rune/internal.h>
12
13 /* Helper to produce an id field */
14 static struct rune_restr *unique_id_restr(const tal_t *ctx,
15                                           const char *unique_id,
16                                           const char *version)
17 {
18         const char *id;
19         struct rune_restr *restr;
20
21         assert(!strchr(unique_id, '-'));
22         if (version)
23                 id = tal_fmt(NULL, "%s-%s", unique_id, version);
24         else
25                 id = tal_strdup(NULL, unique_id);
26
27         restr = rune_restr_new(ctx);
28         /* We use the empty field for this, since it's always present. */
29         rune_restr_add_altern(restr,
30                               take(rune_altern_new(NULL, "", '=', take(id))));
31         return restr;
32 }
33
34 /* We pad between fields with something identical to the SHA end marker */
35 void rune_sha256_endmarker(struct sha256_ctx *shactx)
36 {
37         static const unsigned char pad[64] = {0x80};
38         be64 sizedesc;
39
40         sizedesc = cpu_to_be64((uint64_t)shactx->bytes << 3);
41         /* Add '1' bit to terminate, then all 0 bits, up to next block - 8. */
42         sha256_update(shactx, pad, 1 + ((128 - 8 - (shactx->bytes % 64) - 1) % 64));
43         /* Add number of bits of data (big endian) */
44         sha256_update(shactx, &sizedesc, 8);
45 }
46
47 struct rune *rune_new(const tal_t *ctx, const u8 *secret, size_t secret_len,
48                       const char *version)
49 {
50         struct rune *rune = tal(ctx, struct rune);
51         assert(secret_len + 1 + 8 <= 64);
52
53         if (version)
54                 rune->version = tal_strdup(rune, version);
55         else
56                 rune->version = NULL;
57         rune->unique_id = NULL;
58         sha256_init(&rune->shactx);
59         sha256_update(&rune->shactx, secret, secret_len);
60         rune_sha256_endmarker(&rune->shactx);
61         rune->restrs = tal_arr(rune, struct rune_restr *, 0);
62         return rune;
63 }
64
65 struct rune *rune_dup(const tal_t *ctx, const struct rune *rune TAKES)
66 {
67         struct rune *dup;
68
69         if (taken(rune))
70                 return tal_steal(ctx, (struct rune *)rune);
71
72         dup = tal_dup(ctx, struct rune, rune);
73         dup->restrs = tal_arr(dup, struct rune_restr *, tal_count(rune->restrs));
74         for (size_t i = 0; i < tal_count(rune->restrs); i++) {
75                 dup->restrs[i] = rune_restr_dup(dup->restrs,
76                                                 rune->restrs[i]);
77         }
78         return dup;
79 }
80
81 struct rune *rune_derive_start(const tal_t *ctx,
82                                const struct rune *master,
83                                const char *unique_id TAKES)
84 {
85         struct rune *rune = rune_dup(ctx, master);
86
87         /* If they provide a unique_id, it goes first. */
88         if (unique_id) {
89                 if (taken(unique_id))
90                         rune->unique_id = tal_steal(rune, unique_id);
91                 else
92                         rune->unique_id = tal_strdup(rune, unique_id);
93                 
94                 rune_add_restr(rune, take(unique_id_restr(NULL,
95                                                           rune->unique_id,
96                                                           rune->version)));
97         } else {
98                 assert(!rune->version);
99         }
100         return rune;
101 }
102
103 struct rune_altern *rune_altern_new(const tal_t *ctx,
104                                     const char *fieldname TAKES,
105                                     enum rune_condition condition,
106                                     const char *value TAKES)
107 {
108         struct rune_altern *altern = tal(ctx, struct rune_altern);
109         altern->condition = condition;
110         altern->fieldname = tal_strdup(altern, fieldname);
111         altern->value = tal_strdup(altern, value);
112         return altern;
113 }
114
115 struct rune_altern *rune_altern_dup(const tal_t *ctx,
116                                     const struct rune_altern *altern TAKES)
117 {
118         struct rune_altern *dup;
119
120         if (taken(altern))
121                 return tal_steal(ctx, (struct rune_altern *)altern);
122         dup = tal(ctx, struct rune_altern);
123         dup->condition = altern->condition;
124         dup->fieldname = tal_strdup(dup, altern->fieldname);
125         dup->value = tal_strdup(dup, altern->value);
126         return dup;
127 }
128
129 struct rune_restr *rune_restr_dup(const tal_t *ctx,
130                                   const struct rune_restr *restr TAKES)
131 {
132         struct rune_restr *dup;
133         size_t num_altern;
134
135         if (taken(restr))
136                 return tal_steal(ctx, (struct rune_restr *)restr);
137
138         num_altern = tal_count(restr->alterns);
139         dup = tal(ctx, struct rune_restr);
140         dup->alterns = tal_arr(dup, struct rune_altern *, num_altern);
141         for (size_t i = 0; i < num_altern; i++) {
142                 dup->alterns[i] = rune_altern_dup(dup->alterns,
143                                                   restr->alterns[i]);
144         }
145         return dup;
146 }
147
148 struct rune_restr *rune_restr_new(const tal_t *ctx)
149 {
150         struct rune_restr *restr = tal(ctx, struct rune_restr);
151         restr->alterns = tal_arr(restr, struct rune_altern *, 0);
152         return restr;
153 }
154
155 void rune_restr_add_altern(struct rune_restr *restr,
156                            const struct rune_altern *alt TAKES)
157 {
158         size_t num = tal_count(restr->alterns);
159
160         tal_resize(&restr->alterns, num+1);
161         restr->alterns[num] = rune_altern_dup(restr->alterns, alt);
162 }
163
164 static bool is_unique_id(const struct rune_altern *alt)
165 {
166         return streq(alt->fieldname, "");
167 }
168         
169 /* Return unique_id if valid, and sets *version */
170 static const char *extract_unique_id(const tal_t *ctx,
171                                      const struct rune_altern *alt,
172                                      const char **version)
173 {
174         size_t len;
175         /* Condition must be '='! */
176         if (alt->condition != '=')
177                 return NULL;
178
179         len = strcspn(alt->value, "-");
180         if (alt->value[len])
181                 *version = tal_strdup(ctx, alt->value + len + 1);
182         else
183                 *version = NULL;
184         return tal_strndup(ctx, alt->value, len);
185 }
186
187 bool rune_add_restr(struct rune *rune,
188                     const struct rune_restr *restr TAKES)
189 {
190         size_t num = tal_count(rune->restrs);
191
192         /* An empty fieldname is additional correctness checks */
193         for (size_t i = 0; i < tal_count(restr->alterns); i++) {
194                 if (!is_unique_id(restr->alterns[i]))
195                         continue;
196
197                 /* Must be the only alternative */
198                 if (tal_count(restr->alterns) != 1)
199                         goto fail;
200                 /* Must be the first restriction */
201                 if (num != 0)
202                         goto fail;
203
204                 rune->unique_id = extract_unique_id(rune,
205                                                     restr->alterns[i],
206                                                     &rune->version);
207                 if (!rune->unique_id)
208                         goto fail;
209         }
210
211         tal_resize(&rune->restrs, num+1);
212         rune->restrs[num] = rune_restr_dup(rune->restrs, restr);
213
214         rune_sha256_add_restr(&rune->shactx, rune->restrs[num]);
215         return true;
216
217 fail:
218         if (taken(restr))
219                 tal_free(restr);
220         return false;
221 }
222
223 static const char *rune_restr_test(const tal_t *ctx,
224                                    const struct rune *rune,
225                                    const struct rune_restr *restr,
226                                    const char *(*check)(const tal_t *ctx,
227                                                         const struct rune *rune,
228                                                         const struct rune_altern *alt,
229                                                         void *arg),
230                                    void *arg)
231 {
232         size_t num = tal_count(restr->alterns);
233         const char **errs = tal_arr(NULL, const char *, num);
234         char *err;
235
236         /* Only one alternative has to pass! */
237         for (size_t i = 0; i < num; i++) {
238                 errs[i] = check(errs, rune, restr->alterns[i], arg);
239                 if (!errs[i]) {
240                         tal_free(errs);
241                         return NULL;
242                 }
243         }
244
245         err = tal_fmt(ctx, "%s", errs[0]);
246         for (size_t i = 1; i < num; i++)
247                 tal_append_fmt(&err, " AND %s", errs[i]);
248         tal_free(errs);
249         return err;
250 }
251
252 static const char *cond_test(const tal_t *ctx,
253                              const struct rune_altern *alt,
254                              const char *complaint,
255                              bool cond)
256 {
257         if (cond)
258                 return NULL;
259
260         return tal_fmt(ctx, "%s %s %s", alt->fieldname, complaint, alt->value);
261 }
262
263 static const char *integer_compare_valid(const tal_t *ctx,
264                                          const s64 *fieldval_int,
265                                          const struct rune_altern *alt,
266                                          s64 *runeval_int)
267 {
268         long l;
269         char *p;
270
271         if (!fieldval_int)
272                 return tal_fmt(ctx, "%s is not an integer field",
273                                alt->fieldname);
274
275         errno = 0;
276         l = strtol(alt->value, &p, 10);
277         if (p == alt->value
278             || *p
279             || ((l == LONG_MIN || l == LONG_MAX) && errno == ERANGE))
280                 return tal_fmt(ctx, "%s is not a valid integer", alt->value);
281
282         *runeval_int = l;
283         return NULL;
284 }
285
286 static int lexo_order(const char *fieldval_str,
287                       size_t fieldval_strlen,
288                       const char *alt)
289 {
290         int ret = strncmp(fieldval_str, alt, fieldval_strlen);
291
292         /* If alt is same but longer, fieldval is < */
293         if (ret == 0 && strlen(alt) > fieldval_strlen)
294                 ret = -1;
295         return ret;
296 }
297
298 static const char *rune_alt_single(const tal_t *ctx,
299                                    const struct rune_altern *alt,
300                                    const char *fieldval_str,
301                                    size_t fieldval_strlen,
302                                    const s64 *fieldval_int)
303 {
304         char strfield[STR_MAX_CHARS(s64) + 1];
305         s64 runeval_int;
306         const char *err;
307
308         /* Caller can't set both! */
309         if (fieldval_int) {
310                 assert(!fieldval_str);
311                 sprintf(strfield, "%"PRIi64, *fieldval_int);
312                 fieldval_str = strfield;
313                 fieldval_strlen = strlen(strfield);
314         }
315
316         switch (alt->condition) {
317         case RUNE_COND_IF_MISSING:
318                 if (!fieldval_str)
319                         return NULL;
320                 return tal_fmt(ctx, "%s is present", alt->fieldname);
321         case RUNE_COND_EQUAL:
322                 if (!fieldval_str)
323                         return tal_fmt(ctx, "%s not present", alt->fieldname);
324                 return cond_test(ctx, alt, "is not equal to",
325                                  memeqstr(fieldval_str, fieldval_strlen, alt->value));
326         case RUNE_COND_NOT_EQUAL:
327                 if (!fieldval_str)
328                         return tal_fmt(ctx, "%s not present", alt->fieldname);
329                 return cond_test(ctx, alt, "is equal to",
330                                  !memeqstr(fieldval_str, fieldval_strlen, alt->value));
331         case RUNE_COND_BEGINS:
332                 if (!fieldval_str)
333                         return tal_fmt(ctx, "%s not present", alt->fieldname);
334                 return cond_test(ctx, alt, "does not start with",
335                                  memstarts_str(fieldval_str, fieldval_strlen, alt->value));
336         case RUNE_COND_ENDS:
337                 if (!fieldval_str)
338                         return tal_fmt(ctx, "%s not present", alt->fieldname);
339                 return cond_test(ctx, alt, "does not end with",
340                                  memends_str(fieldval_str, fieldval_strlen, alt->value));
341         case RUNE_COND_CONTAINS:
342                 if (!fieldval_str)
343                         return tal_fmt(ctx, "%s not present", alt->fieldname);
344                 return cond_test(ctx, alt, "does not contain",
345                                  memmem(fieldval_str, fieldval_strlen,
346                                         alt->value, strlen(alt->value)));
347         case RUNE_COND_INT_LESS:
348                 err = integer_compare_valid(ctx, fieldval_int,
349                                             alt, &runeval_int);
350                 if (err)
351                         return err;
352                 return cond_test(ctx, alt, "is greater or equal to",
353                                  *fieldval_int < runeval_int);
354         case RUNE_COND_INT_GREATER:
355                 err = integer_compare_valid(ctx, fieldval_int,
356                                             alt, &runeval_int);
357                 if (err)
358                         return err;
359                 return cond_test(ctx, alt, "is less or equal to",
360                                  *fieldval_int > runeval_int);
361         case RUNE_COND_LEXO_BEFORE:
362                 if (!fieldval_str)
363                         return tal_fmt(ctx, "%s not present", alt->fieldname);
364                 return cond_test(ctx, alt, "is equal to or ordered after",
365                                  lexo_order(fieldval_str, fieldval_strlen, alt->value) < 0);
366         case RUNE_COND_LEXO_AFTER:
367                 if (!fieldval_str)
368                         return tal_fmt(ctx, "%s not present", alt->fieldname);
369                 return cond_test(ctx, alt, "is equal to or ordered before",
370                                  lexo_order(fieldval_str, fieldval_strlen, alt->value) > 0);
371         case RUNE_COND_COMMENT:
372                 return NULL;
373         }
374         /* We should never create any other values! */
375         abort();
376 }
377
378 const char *rune_alt_single_str(const tal_t *ctx,
379                                 const struct rune_altern *alt,
380                                 const char *fieldval_str,
381                                 size_t fieldval_strlen)
382 {
383         return rune_alt_single(ctx, alt, fieldval_str, fieldval_strlen, NULL);
384 }
385
386 const char *rune_alt_single_int(const tal_t *ctx,
387                                 const struct rune_altern *alt,
388                                 s64 fieldval_int)
389 {
390         return rune_alt_single(ctx, alt, NULL, 0, &fieldval_int);
391 }
392
393 const char *rune_alt_single_missing(const tal_t *ctx,
394                                     const struct rune_altern *alt)
395 {
396         return rune_alt_single(ctx, alt, NULL, 0, NULL);
397 }
398
399 const char *rune_meets_criteria_(const tal_t *ctx,
400                                  const struct rune *rune,
401                                  const char *(*check)(const tal_t *ctx,
402                                                       const struct rune *rune,
403                                                       const struct rune_altern *alt,
404                                                       void *arg),
405                                  void *arg)
406 {
407         for (size_t i = 0; i < tal_count(rune->restrs); i++) {
408                 const char *err;
409
410                 /* Don't "check" unique id */
411                 if (i == 0 && is_unique_id(rune->restrs[i]->alterns[0]))
412                         continue;
413                 
414                 err = rune_restr_test(ctx, rune, rune->restrs[i], check, arg);
415                 if (err)
416                         return err;
417         }
418         return NULL;
419 }
420
421 const char *rune_test_(const tal_t *ctx,
422                        const struct rune *master,
423                        const struct rune *rune,
424                        const char *(*check)(const tal_t *ctx,
425                                             const struct rune *rune,
426                                             const struct rune_altern *alt,
427                                             void *arg),
428                        void *arg)
429 {
430         const char *err;
431
432         err = rune_is_derived(master, rune);
433         if (err)
434                 return err;
435         return rune_meets_criteria_(ctx, rune, check, arg);
436 }
437
438 bool rune_altern_eq(const struct rune_altern *alt1,
439                     const struct rune_altern *alt2)
440 {
441         return alt1->condition == alt2->condition
442                 && streq(alt1->fieldname, alt2->fieldname)
443                 && streq(alt1->value, alt2->value);
444 }
445
446 bool rune_restr_eq(const struct rune_restr *rest1,
447                    const struct rune_restr *rest2)
448 {
449         if (tal_count(rest1->alterns) != tal_count(rest2->alterns))
450                 return false;
451
452         for (size_t i = 0; i < tal_count(rest1->alterns); i++)
453                 if (!rune_altern_eq(rest1->alterns[i], rest2->alterns[i]))
454                         return false;
455         return true;
456 }
457
458 /* Equal, as in both NULL, or both non-NULL and matching */
459 bool runestr_eq(const char *a, const char *b)
460 {
461         if (a) {
462                 if (!b)
463                         return false;
464                 return streq(a, b);
465         } else
466                 return b == NULL;
467 }
468
469 bool rune_eq(const struct rune *rune1, const struct rune *rune2)
470 {
471         if (!runestr_eq(rune1->unique_id, rune2->unique_id))
472                 return false;
473         if (!runestr_eq(rune1->version, rune2->version))
474                 return false;
475
476         if (memcmp(rune1->shactx.s, rune2->shactx.s, sizeof(rune1->shactx.s)))
477                 return false;
478         if (rune1->shactx.bytes != rune2->shactx.bytes)
479                 return false;
480         if (memcmp(rune1->shactx.buf.u8, rune2->shactx.buf.u8,
481                    rune1->shactx.bytes % 64))
482                 return false;
483
484         if (tal_count(rune1->restrs) != tal_count(rune2->restrs))
485                 return false;
486
487         for (size_t i = 0; i < tal_count(rune1->restrs); i++)
488                 if (!rune_restr_eq(rune1->restrs[i], rune2->restrs[i]))
489                         return false;
490         return true;
491 }