1 /* MIT (BSD) license - see LICENSE file for details */
2 /* Routines to encode / decode a rune */
3 #include <ccan/rune/rune.h>
4 #include <ccan/rune/internal.h>
5 #include <ccan/str/hex/hex.h>
6 #include <ccan/tal/str/str.h>
7 #include <ccan/base64/base64.h>
8 #include <ccan/endian/endian.h>
11 /* From Python base64.urlsafe_b64encode:
13 * The alphabet uses '-' instead of '+' and '_' instead of '/'.
15 static const base64_maps_t base64_maps_urlsafe = {
16 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",
18 "\xff\xff\xff\xff\xff" /* 0 */
19 "\xff\xff\xff\xff\xff" /* 5 */
20 "\xff\xff\xff\xff\xff" /* 10 */
21 "\xff\xff\xff\xff\xff" /* 15 */
22 "\xff\xff\xff\xff\xff" /* 20 */
23 "\xff\xff\xff\xff\xff" /* 25 */
24 "\xff\xff\xff\xff\xff" /* 30 */
25 "\xff\xff\xff\xff\xff" /* 35 */
26 "\xff\xff\xff\xff\xff" /* 40 */
27 "\x3e\xff\xff\x34\x35" /* 45 */
28 "\x36\x37\x38\x39\x3a" /* 50 */
29 "\x3b\x3c\x3d\xff\xff" /* 55 */
30 "\xff\xff\xff\xff\xff" /* 60 */
31 "\x00\x01\x02\x03\x04" /* 65 A */
32 "\x05\x06\x07\x08\x09" /* 70 */
33 "\x0a\x0b\x0c\x0d\x0e" /* 75 */
34 "\x0f\x10\x11\x12\x13" /* 80 */
35 "\x14\x15\x16\x17\x18" /* 85 */
36 "\x19\xff\xff\xff\xff" /* 90 */
37 "\x3f\xff\x1a\x1b\x1c" /* 95 */
38 "\x1d\x1e\x1f\x20\x21" /* 100 */
39 "\x22\x23\x24\x25\x26" /* 105 */
40 "\x27\x28\x29\x2a\x2b" /* 110 */
41 "\x2c\x2d\x2e\x2f\x30" /* 115 */
42 "\x31\x32\x33\xff\xff" /* 120 */
43 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" /* 125 */
44 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" /* 135 */
45 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" /* 145 */
46 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" /* 155 */
47 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" /* 165 */
48 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" /* 175 */
49 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" /* 185 */
50 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" /* 195 */
51 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" /* 205 */
52 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" /* 215 */
53 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" /* 225 */
54 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" /* 235 */
55 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" /* 245 */
58 /* For encoding as a string */
64 static void to_wbuf(const char *s, size_t len, void *vwbuf)
66 struct wbuf *wbuf = vwbuf;
68 while (wbuf->off + len > wbuf->len)
69 tal_resize(&wbuf->buf, wbuf->len *= 2);
70 memcpy(wbuf->buf + wbuf->off, s, len);
74 /* For adding to sha256 */
75 static void to_sha256(const char *s, size_t len, void *vshactx)
77 struct sha256_ctx *shactx = vshactx;
78 sha256_update(shactx, s, len);
81 static void rune_altern_encode(const struct rune_altern *altern,
82 void (*cb)(const char *s, size_t len,
86 char cond = altern->condition;
89 cb(altern->fieldname, strlen(altern->fieldname), arg);
94 char esc[2] = { '\\' };
95 size_t len = strcspn(p, "\\|&");
105 static void rune_restr_encode(const struct rune_restr *restr,
106 void (*cb)(const char *s, size_t len,
110 for (size_t i = 0; i < tal_count(restr->alterns); i++) {
113 rune_altern_encode(restr->alterns[i], cb, arg);
117 void rune_sha256_add_restr(struct sha256_ctx *shactx,
118 struct rune_restr *restr)
120 rune_restr_encode(restr, to_sha256, shactx);
121 rune_sha256_endmarker(shactx);
124 const char *rune_is_derived(const struct rune *source, const struct rune *rune)
126 if (!runestr_eq(source->version, rune->version))
127 return "Version mismatch";
129 return rune_is_derived_anyversion(source, rune);
132 const char *rune_is_derived_anyversion(const struct rune *source,
133 const struct rune *rune)
135 struct sha256_ctx shactx;
138 if (tal_count(rune->restrs) < tal_count(source->restrs))
139 return "Fewer restrictions than master";
141 /* If we add the same restrictions to source rune, do we match? */
142 shactx = source->shactx;
143 for (i = 0; i < tal_count(rune->restrs); i++) {
144 /* First restrictions must be identical */
145 if (i < tal_count(source->restrs)) {
146 if (!rune_restr_eq(source->restrs[i], rune->restrs[i]))
147 return "Does not match master restrictions";
149 rune_sha256_add_restr(&shactx, rune->restrs[i]);
152 if (memcmp(shactx.s, rune->shactx.s, sizeof(shactx.s)) != 0)
153 return "Not derived from master";
157 static bool peek_char(const char *data, size_t len, char *c)
165 static void drop_char(const char **data, size_t *len)
171 static void pull_invalid(const char **data, size_t *len)
177 static bool pull_char(const char **data, size_t *len, char *c)
179 if (!peek_char(*data, *len, c)) {
180 pull_invalid(data, len);
183 drop_char(data, len);
187 bool rune_condition_is_valid(enum rune_condition cond)
190 case RUNE_COND_IF_MISSING:
191 case RUNE_COND_EQUAL:
192 case RUNE_COND_NOT_EQUAL:
193 case RUNE_COND_BEGINS:
195 case RUNE_COND_CONTAINS:
196 case RUNE_COND_INT_LESS:
197 case RUNE_COND_INT_GREATER:
198 case RUNE_COND_LEXO_BEFORE:
199 case RUNE_COND_LEXO_AFTER:
200 case RUNE_COND_COMMENT:
206 size_t rune_altern_fieldname_len(const char *alternstr, size_t alternstrlen)
208 for (size_t i = 0; i < alternstrlen; i++) {
209 if (cispunct(alternstr[i]) && alternstr[i] != '_')
215 /* Sets *more on success: true if another altern follows */
216 static struct rune_altern *rune_altern_decode(const tal_t *ctx,
217 const char **data, size_t *len,
220 struct rune_altern *alt = tal(ctx, struct rune_altern);
225 /* Swallow field up to possible conditional */
226 strlen = rune_altern_fieldname_len(*data, *len);
227 alt->fieldname = tal_strndup(alt, *data, strlen);
231 /* Grab conditional */
232 if (!pull_char(data, len, &c) || !rune_condition_is_valid(c))
233 return tal_free(alt);
237 /* Assign worst case. */
238 value = tal_arr(alt, char, *len + 1);
241 while (*len && pull_char(data, len, &c)) {
249 if (c == '\\' && !pull_char(data, len, &c))
250 return tal_free(alt);
253 value[strlen] = '\0';
254 tal_resize(&value, strlen + 1);
259 static struct rune_restr *rune_restr_decode(const tal_t *ctx,
260 const char **data, size_t *len)
262 struct rune_restr *restr = tal(ctx, struct rune_restr);
266 /* Must have at least one! */
267 restr->alterns = tal_arr(restr, struct rune_altern *, 0);
269 struct rune_altern *alt;
271 alt = rune_altern_decode(restr, data, len, &more);
273 return tal_free(restr);
274 tal_resize(&restr->alterns, num_alts+1);
275 restr->alterns[num_alts++] = alt;
280 static struct rune *from_string(const tal_t *ctx,
284 size_t len = strlen(str);
285 struct rune *rune = tal(ctx, struct rune);
287 /* Now count up how many bytes we should have hashed: secret uses
289 rune->shactx.bytes = 64;
291 rune->restrs = tal_arr(rune, struct rune_restr *, 0);
292 rune->unique_id = NULL;
293 rune->version = NULL;
296 struct rune_restr *restr;
297 restr = rune_restr_decode(rune, &str, &len);
299 return tal_free(rune);
300 if (!rune_add_restr(rune, restr))
301 return tal_free(rune);
304 /* Now we replace with canned hash state */
305 memcpy(rune->shactx.s, hash32, 32);
306 for (size_t i = 0; i < 8; i++)
307 rune->shactx.s[i] = be32_to_cpu(rune->shactx.s[i]);
312 struct rune_restr *rune_restr_from_string(const tal_t *ctx,
316 struct rune_restr *restr;
318 restr = rune_restr_decode(NULL, &str, &len);
319 /* Don't allow trailing chars */
320 if (restr && len != 0)
321 restr = tal_free(restr);
322 return tal_steal(ctx, restr);
325 static void to_string(struct wbuf *wbuf, const struct rune *rune, u8 *hash32)
327 /* Copy hash in big-endian */
328 for (size_t i = 0; i < 8; i++) {
329 be32 v = cpu_to_be32(rune->shactx.s[i]);
330 memcpy(hash32 + i*4, &v, sizeof(v));
333 for (size_t i = 0; i < tal_count(rune->restrs); i++) {
335 to_wbuf("&", 1, wbuf);
336 rune_restr_encode(rune->restrs[i], to_wbuf, wbuf);
338 to_wbuf("", 1, wbuf);
341 struct rune *rune_from_base64n(const tal_t *ctx, const char *str, size_t len)
347 data = tal_arr(NULL, u8, base64_decoded_length(len) + 1);
349 blen = base64_decode_using_maps(&base64_maps_urlsafe,
350 (char *)data, tal_bytelen(data),
359 /* Sanity check that it's a valid string! */
360 if (strlen((char *)data + 32) != blen - 32)
363 rune = from_string(ctx, (const char *)data + 32, data);
372 struct rune *rune_from_base64(const tal_t *ctx, const char *str)
374 return rune_from_base64n(ctx, str, strlen(str));
377 char *rune_to_base64(const tal_t *ctx, const struct rune *rune)
384 /* We're going to prepend hash */
385 wbuf.off = sizeof(hash32);
387 wbuf.buf = tal_arr(NULL, char, wbuf.len);
389 to_string(&wbuf, rune, hash32);
391 memcpy(wbuf.buf, hash32, sizeof(hash32));
393 ret = tal_arr(ctx, char, base64_encoded_length(wbuf.off) + 1);
394 ret_len = base64_encode_using_maps(&base64_maps_urlsafe,
395 ret, tal_bytelen(ret),
396 wbuf.buf, wbuf.off - 1);
402 struct rune *rune_from_string(const tal_t *ctx, const char *str)
405 if (!hex_decode(str, 64, hash, sizeof(hash)))
409 return from_string(ctx, str + 65, hash);
412 char *rune_to_string(const tal_t *ctx, const struct rune *rune)
417 /* We're going to prepend hash (in hex), plus colon */
418 wbuf.off = sizeof(hash32) * 2 + 1;
420 wbuf.buf = tal_arr(ctx, char, wbuf.len);
422 to_string(&wbuf, rune, hash32);
423 hex_encode(hash32, sizeof(hash32), wbuf.buf, sizeof(hash32) * 2 + 1);
424 wbuf.buf[sizeof(hash32) * 2] = ':';