1 /* MIT (BSD) license - see LICENSE file for details */
7 #include <ccan/endian/endian.h>
8 #include <ccan/tal/str/str.h>
9 #include <ccan/rune/rune.h>
10 #include <ccan/rune/internal.h>
12 /* Helper to produce an id field */
13 static struct rune_restr *unique_id_restr(const tal_t *ctx,
14 const char *unique_id,
18 struct rune_restr *restr;
20 assert(!strchr(unique_id, '-'));
22 id = tal_fmt(NULL, "%s-%s", unique_id, version);
24 id = tal_strdup(NULL, unique_id);
26 restr = rune_restr_new(ctx);
27 /* We use the empty field for this, since it's always present. */
28 rune_restr_add_altern(restr,
29 take(rune_altern_new(NULL, "", '=', take(id))));
33 /* We pad between fields with something identical to the SHA end marker */
34 void rune_sha256_endmarker(struct sha256_ctx *shactx)
36 static const unsigned char pad[64] = {0x80};
39 sizedesc = cpu_to_be64((uint64_t)shactx->bytes << 3);
40 /* Add '1' bit to terminate, then all 0 bits, up to next block - 8. */
41 sha256_update(shactx, pad, 1 + ((128 - 8 - (shactx->bytes % 64) - 1) % 64));
42 /* Add number of bits of data (big endian) */
43 sha256_update(shactx, &sizedesc, 8);
46 struct rune *rune_new(const tal_t *ctx, const u8 *secret, size_t secret_len,
49 struct rune *rune = tal(ctx, struct rune);
50 assert(secret_len + 1 + 8 <= 64);
53 rune->version = tal_strdup(rune, version);
56 rune->unique_id = NULL;
57 sha256_init(&rune->shactx);
58 sha256_update(&rune->shactx, secret, secret_len);
59 rune_sha256_endmarker(&rune->shactx);
60 rune->restrs = tal_arr(rune, struct rune_restr *, 0);
64 struct rune *rune_dup(const tal_t *ctx, const struct rune *rune TAKES)
69 return (struct rune *)rune;
71 dup = tal_dup(ctx, struct rune, rune);
72 dup->restrs = tal_arr(dup, struct rune_restr *, tal_count(rune->restrs));
73 for (size_t i = 0; i < tal_count(rune->restrs); i++) {
74 dup->restrs[i] = rune_restr_dup(dup->restrs,
80 struct rune *rune_derive_start(const tal_t *ctx,
81 const struct rune *master,
82 const char *unique_id TAKES)
84 struct rune *rune = rune_dup(ctx, master);
86 /* If they provide a unique_id, it goes first. */
89 rune->unique_id = unique_id;
91 rune->unique_id = tal_strdup(rune, unique_id);
93 rune_add_restr(rune, take(unique_id_restr(NULL,
97 assert(!rune->version);
102 struct rune_altern *rune_altern_new(const tal_t *ctx,
103 const char *fieldname TAKES,
104 enum rune_condition condition,
105 const char *value TAKES)
107 struct rune_altern *altern = tal(ctx, struct rune_altern);
108 altern->condition = condition;
109 altern->fieldname = tal_strdup(altern, fieldname);
110 altern->value = tal_strdup(altern, value);
114 struct rune_altern *rune_altern_dup(const tal_t *ctx,
115 const struct rune_altern *altern TAKES)
117 struct rune_altern *dup;
120 return (struct rune_altern *)altern;;
121 dup = tal(ctx, struct rune_altern);
122 dup->condition = altern->condition;
123 dup->fieldname = tal_strdup(dup, altern->fieldname);
124 dup->value = tal_strdup(dup, altern->value);
128 struct rune_restr *rune_restr_dup(const tal_t *ctx,
129 const struct rune_restr *restr TAKES)
131 struct rune_restr *dup;
135 return (struct rune_restr *)restr;
137 num_altern = tal_count(restr->alterns);
138 dup = tal(ctx, struct rune_restr);
139 dup->alterns = tal_arr(dup, struct rune_altern *, num_altern);
140 for (size_t i = 0; i < num_altern; i++) {
141 dup->alterns[i] = rune_altern_dup(dup->alterns,
147 struct rune_restr *rune_restr_new(const tal_t *ctx)
149 struct rune_restr *restr = tal(ctx, struct rune_restr);
150 restr->alterns = tal_arr(restr, struct rune_altern *, 0);
154 void rune_restr_add_altern(struct rune_restr *restr,
155 const struct rune_altern *alt TAKES)
157 size_t num = tal_count(restr->alterns);
159 tal_resize(&restr->alterns, num+1);
160 restr->alterns[num] = rune_altern_dup(restr->alterns, alt);
163 static bool is_unique_id(const struct rune_altern *alt)
165 return streq(alt->fieldname, "");
168 /* Return unique_id if valid, and sets *version */
169 static const char *extract_unique_id(const tal_t *ctx,
170 const struct rune_altern *alt,
171 const char **version)
174 /* Condition must be '='! */
175 if (alt->condition != '=')
178 len = strcspn(alt->value, "-");
180 *version = tal_strdup(ctx, alt->value + len + 1);
183 return tal_strndup(ctx, alt->value, len);
186 bool rune_add_restr(struct rune *rune,
187 const struct rune_restr *restr TAKES)
189 size_t num = tal_count(rune->restrs);
191 /* An empty fieldname is additional correctness checks */
192 for (size_t i = 0; i < tal_count(restr->alterns); i++) {
193 if (!is_unique_id(restr->alterns[i]))
196 /* Must be the only alternative */
197 if (tal_count(restr->alterns) != 1)
199 /* Must be the first restriction */
203 rune->unique_id = extract_unique_id(rune,
206 if (!rune->unique_id)
210 tal_resize(&rune->restrs, num+1);
211 rune->restrs[num] = rune_restr_dup(rune->restrs, restr);
213 rune_sha256_add_restr(&rune->shactx, rune->restrs[num]);
222 static const char *rune_restr_test(const tal_t *ctx,
223 const struct rune *rune,
224 const struct rune_restr *restr,
225 const char *(*check)(const tal_t *ctx,
226 const struct rune *rune,
227 const struct rune_altern *alt,
231 size_t num = tal_count(restr->alterns);
232 const char **errs = tal_arr(NULL, const char *, num);
235 /* Only one alternative has to pass! */
236 for (size_t i = 0; i < num; i++) {
237 errs[i] = check(errs, rune, restr->alterns[i], arg);
244 err = tal_fmt(ctx, "%s", errs[0]);
245 for (size_t i = 1; i < num; i++)
246 tal_append_fmt(&err, " AND %s", errs[i]);
251 static const char *cond_test(const tal_t *ctx,
252 const struct rune_altern *alt,
253 const char *complaint,
259 return tal_fmt(ctx, "%s %s %s", alt->fieldname, complaint, alt->value);
262 static const char *integer_compare_valid(const tal_t *ctx,
263 const s64 *fieldval_int,
264 const struct rune_altern *alt,
271 return tal_fmt(ctx, "%s is not an integer field",
275 l = strtol(alt->value, &p, 10);
278 || ((l == LONG_MIN || l == LONG_MAX) && errno == ERANGE))
279 return tal_fmt(ctx, "%s is not a valid integer", alt->value);
285 const char *rune_alt_single(const tal_t *ctx,
286 const struct rune_altern *alt,
287 const char *fieldval_str,
288 const s64 *fieldval_int)
290 char strfield[STR_MAX_CHARS(s64) + 1];
294 /* Caller can't set both! */
296 assert(!fieldval_str);
297 sprintf(strfield, "%"PRIi64, *fieldval_int);
298 fieldval_str = strfield;
301 switch (alt->condition) {
302 case RUNE_COND_IF_MISSING:
305 return tal_fmt(ctx, "%s is present", alt->fieldname);
306 case RUNE_COND_EQUAL:
308 return tal_fmt(ctx, "%s not present", alt->fieldname);
309 return cond_test(ctx, alt, "is not equal to",
310 streq(fieldval_str, alt->value));
311 case RUNE_COND_NOT_EQUAL:
313 return tal_fmt(ctx, "%s not present", alt->fieldname);
314 return cond_test(ctx, alt, "is equal to",
315 !streq(fieldval_str, alt->value));
316 case RUNE_COND_BEGINS:
318 return tal_fmt(ctx, "%s not present", alt->fieldname);
319 return cond_test(ctx, alt, "does not start with",
320 strstarts(fieldval_str, alt->value));
323 return tal_fmt(ctx, "%s not present", alt->fieldname);
324 return cond_test(ctx, alt, "does not end with",
325 strends(fieldval_str, alt->value));
326 case RUNE_COND_CONTAINS:
328 return tal_fmt(ctx, "%s not present", alt->fieldname);
329 return cond_test(ctx, alt, "does not contain",
330 strstr(fieldval_str, alt->value));
331 case RUNE_COND_INT_LESS:
332 err = integer_compare_valid(ctx, fieldval_int,
336 return cond_test(ctx, alt, "is greater or equal to",
337 *fieldval_int < runeval_int);
338 case RUNE_COND_INT_GREATER:
339 err = integer_compare_valid(ctx, fieldval_int,
343 return cond_test(ctx, alt, "is less or equal to",
344 *fieldval_int > runeval_int);
345 case RUNE_COND_LEXO_BEFORE:
347 return tal_fmt(ctx, "%s not present", alt->fieldname);
348 return cond_test(ctx, alt, "is equal to or ordered after",
349 strcmp(fieldval_str, alt->value) < 0);
350 case RUNE_COND_LEXO_AFTER:
352 return tal_fmt(ctx, "%s not present", alt->fieldname);
353 return cond_test(ctx, alt, "is equal to or ordered before",
354 strcmp(fieldval_str, alt->value) > 0);
355 case RUNE_COND_COMMENT:
358 /* We should never create any other values! */
362 const char *rune_meets_criteria_(const tal_t *ctx,
363 const struct rune *rune,
364 const char *(*check)(const tal_t *ctx,
365 const struct rune *rune,
366 const struct rune_altern *alt,
370 for (size_t i = 0; i < tal_count(rune->restrs); i++) {
373 /* Don't "check" unique id */
374 if (i == 0 && is_unique_id(rune->restrs[i]->alterns[0]))
377 err = rune_restr_test(ctx, rune, rune->restrs[i], check, arg);
384 const char *rune_test_(const tal_t *ctx,
385 const struct rune *master,
386 const struct rune *rune,
387 const char *(*check)(const tal_t *ctx,
388 const struct rune *rune,
389 const struct rune_altern *alt,
395 err = rune_is_derived(master, rune);
398 return rune_meets_criteria_(ctx, rune, check, arg);
401 bool rune_altern_eq(const struct rune_altern *alt1,
402 const struct rune_altern *alt2)
404 return alt1->condition == alt2->condition
405 && streq(alt1->fieldname, alt2->fieldname)
406 && streq(alt1->value, alt2->value);
409 bool rune_restr_eq(const struct rune_restr *rest1,
410 const struct rune_restr *rest2)
412 if (tal_count(rest1->alterns) != tal_count(rest2->alterns))
415 for (size_t i = 0; i < tal_count(rest1->alterns); i++)
416 if (!rune_altern_eq(rest1->alterns[i], rest2->alterns[i]))
421 /* Equal, as in both NULL, or both non-NULL and matching */
422 bool runestr_eq(const char *a, const char *b)
432 bool rune_eq(const struct rune *rune1, const struct rune *rune2)
434 if (!runestr_eq(rune1->unique_id, rune2->unique_id))
436 if (!runestr_eq(rune1->version, rune2->version))
439 if (memcmp(rune1->shactx.s, rune2->shactx.s, sizeof(rune1->shactx.s)))
441 if (rune1->shactx.bytes != rune2->shactx.bytes)
443 if (memcmp(rune1->shactx.buf.u8, rune2->shactx.buf.u8,
444 rune1->shactx.bytes % 64))
447 if (tal_count(rune1->restrs) != tal_count(rune2->restrs))
450 for (size_t i = 0; i < tal_count(rune1->restrs); i++)
451 if (!rune_restr_eq(rune1->restrs[i], rune2->restrs[i]))