]> git.ozlabs.org Git - ccan/blob - ccan/rune/coding.c
base64: fix for unsigned chars (e.g. ARM).
[ccan] / ccan / rune / coding.c
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>
9 #include <errno.h>
10
11 /* From Python base64.urlsafe_b64encode:
12  *
13  * The alphabet uses '-' instead of '+' and '_' instead of '/'.
14  */
15 static const base64_maps_t base64_maps_urlsafe = {
16   "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",
17
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 */
56 };
57
58 /* For encoding as a string */
59 struct wbuf {
60         size_t off, len;
61         char *buf;
62 };
63
64 static void to_wbuf(const char *s, size_t len, void *vwbuf)
65 {
66         struct wbuf *wbuf = vwbuf;
67
68         while (wbuf->off + len > wbuf->len)
69                 tal_resize(&wbuf->buf, wbuf->len *= 2);
70         memcpy(wbuf->buf + wbuf->off, s, len);
71         wbuf->off += len;
72 }
73
74 /* For adding to sha256 */
75 static void to_sha256(const char *s, size_t len, void *vshactx)
76 {
77         struct sha256_ctx *shactx = vshactx;
78         sha256_update(shactx, s, len);
79 }
80
81 static void rune_altern_encode(const struct rune_altern *altern,
82                                void (*cb)(const char *s, size_t len,
83                                           void *arg),
84                                void *arg)
85 {
86         char cond = altern->condition;
87         const char *p;
88
89         cb(altern->fieldname, strlen(altern->fieldname), arg);
90         cb(&cond, 1, arg);
91
92         p = altern->value;
93         for (;;) {
94                 char esc[2] = { '\\' };
95                 size_t len = strcspn(p, "\\|&");
96                 cb(p, len, arg);
97                 if (!p[len])
98                         break;
99                 esc[1] = p[len];
100                 cb(esc, 2, arg);
101                 p += len + 1;
102         }
103 }
104
105 static void rune_restr_encode(const struct rune_restr *restr,
106                               void (*cb)(const char *s, size_t len,
107                                          void *arg),
108                               void *arg)
109 {
110         for (size_t i = 0; i < tal_count(restr->alterns); i++) {
111                 if (i != 0)
112                         cb("|", 1, arg);
113                 rune_altern_encode(restr->alterns[i], cb, arg);
114         }
115 }
116
117 void rune_sha256_add_restr(struct sha256_ctx *shactx,
118                            struct rune_restr *restr)
119 {
120         rune_restr_encode(restr, to_sha256, shactx);
121         rune_sha256_endmarker(shactx);
122 }
123
124 const char *rune_is_derived(const struct rune *source, const struct rune *rune)
125 {
126         if (!runestr_eq(source->version, rune->version))
127                 return "Version mismatch";
128
129         return rune_is_derived_anyversion(source, rune);
130 }
131         
132 const char *rune_is_derived_anyversion(const struct rune *source,
133                                        const struct rune *rune)
134 {
135         struct sha256_ctx shactx;
136         size_t i;
137
138         if (tal_count(rune->restrs) < tal_count(source->restrs))
139                 return "Fewer restrictions than master";
140
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";
148                 } else
149                         rune_sha256_add_restr(&shactx, rune->restrs[i]);
150         }
151
152         if (memcmp(shactx.s, rune->shactx.s, sizeof(shactx.s)) != 0)
153                 return "Not derived from master";
154         return NULL;
155 }
156
157 static bool peek_char(const char *data, size_t len, char *c)
158 {
159         if (len == 0)
160                 return false;
161         *c = *data;
162         return true;
163 }
164
165 static void drop_char(const char **data, size_t *len)
166 {
167         (*data)++;
168         (*len)--;
169 }
170
171 static void pull_invalid(const char **data, size_t *len)
172 {
173         *data = NULL;
174         *len = 0;
175 }
176
177 static bool pull_char(const char **data, size_t *len, char *c)
178 {
179         if (!peek_char(*data, *len, c)) {
180                 pull_invalid(data, len);
181                 return false;
182         }
183         drop_char(data, len);
184         return true;
185 }
186
187 bool rune_condition_is_valid(enum rune_condition cond)
188 {
189         switch (cond) {
190         case RUNE_COND_IF_MISSING:
191         case RUNE_COND_EQUAL:
192         case RUNE_COND_NOT_EQUAL:
193         case RUNE_COND_BEGINS:
194         case RUNE_COND_ENDS:
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:
201                 return true;
202         }
203         return false;
204 }
205
206 size_t rune_altern_fieldname_len(const char *alternstr, size_t alternstrlen)
207 {
208         for (size_t i = 0; i < alternstrlen; i++) {
209                 if (cispunct(alternstr[i]))
210                         return i;
211         }
212         return alternstrlen;
213 }
214
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,
218                                               bool *more)
219 {
220         struct rune_altern *alt = tal(ctx, struct rune_altern);
221         char *value;
222         size_t strlen;
223         char c;
224
225         /* Swallow field up to possible conditional */
226         strlen = rune_altern_fieldname_len(*data, *len);
227         alt->fieldname = tal_strndup(alt, *data, strlen);
228         *data += strlen;
229         *len -= strlen;
230
231         /* Grab conditional */
232         if (!pull_char(data, len, &c) || !rune_condition_is_valid(c))
233                 return tal_free(alt);
234
235         alt->condition = c;
236
237         /* Assign worst case. */
238         value = tal_arr(alt, char, *len + 1);
239         strlen = 0;
240         *more = false;
241         while (*len && pull_char(data, len, &c)) {
242                 if (c == '|') {
243                         *more = true;
244                         break;
245                 }
246                 if (c == '&')
247                         break;
248
249                 if (c == '\\' && !pull_char(data, len, &c))
250                         return tal_free(alt);
251                 value[strlen++] = c;
252         }
253         value[strlen] = '\0';
254         tal_resize(&value, strlen + 1);
255         alt->value = value;
256         return alt;
257 }
258
259 static struct rune_restr *rune_restr_decode(const tal_t *ctx,
260                                             const char **data, size_t *len)
261 {
262         struct rune_restr *restr = tal(ctx, struct rune_restr);
263         size_t num_alts = 0;
264         bool more;
265
266         /* Must have at least one! */
267         restr->alterns = tal_arr(restr, struct rune_altern *, 0);
268         do {
269                 struct rune_altern *alt;
270
271                 alt = rune_altern_decode(restr, data, len, &more);
272                 if (!alt)
273                         return tal_free(restr);
274                 tal_resize(&restr->alterns, num_alts+1);
275                 restr->alterns[num_alts++] = alt;
276         } while (more);
277         return restr;
278 }
279
280 static struct rune *from_string(const tal_t *ctx,
281                                 const char *str,
282                                 const u8 *hash32)
283 {
284         size_t len = strlen(str);
285         struct rune *rune = tal(ctx, struct rune);
286
287         /* Now count up how many bytes we should have hashed: secret uses
288          * first block. */
289         rune->shactx.bytes = 64;
290
291         rune->restrs = tal_arr(rune, struct rune_restr *, 0);
292         rune->unique_id = NULL;
293         rune->version = NULL;
294
295         while (len) {
296                 struct rune_restr *restr;
297                 restr = rune_restr_decode(rune, &str, &len);
298                 if (!restr)
299                         return tal_free(rune);
300                 if (!rune_add_restr(rune, restr))
301                         return tal_free(rune);
302         }
303
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]);
308
309         return rune;
310 }
311
312 struct rune_restr *rune_restr_from_string(const tal_t *ctx,
313                                           const char *str,
314                                           size_t len)
315 {
316         struct rune_restr *restr;
317
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);
323 }
324
325 static void to_string(struct wbuf *wbuf, const struct rune *rune, u8 *hash32)
326 {
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));
331         }
332
333         for (size_t i = 0; i < tal_count(rune->restrs); i++) {
334                 if (i != 0)
335                         to_wbuf("&", 1, wbuf);
336                 rune_restr_encode(rune->restrs[i], to_wbuf, wbuf);
337         }
338         to_wbuf("", 1, wbuf);
339 }
340
341 struct rune *rune_from_base64n(const tal_t *ctx, const char *str, size_t len)
342 {
343         size_t blen;
344         u8 *data;
345         struct rune *rune;
346
347         data = tal_arr(NULL, u8, base64_decoded_length(len) + 1);
348
349         blen = base64_decode_using_maps(&base64_maps_urlsafe,
350                                        (char *)data, tal_bytelen(data),
351                                        str, len);
352         if (blen == -1)
353                 goto fail;
354
355         if (blen < 32)
356                 goto fail;
357
358         data[blen] = '\0';
359         /* Sanity check that it's a valid string! */
360         if (strlen((char *)data + 32) != blen - 32)
361                 goto fail;
362
363         rune = from_string(ctx, (const char *)data + 32, data);
364         tal_free(data);
365         return rune;
366
367 fail:
368         tal_free(data);
369         return NULL;
370 }
371
372 struct rune *rune_from_base64(const tal_t *ctx, const char *str)
373 {
374         return rune_from_base64n(ctx, str, strlen(str));
375 }
376
377 char *rune_to_base64(const tal_t *ctx, const struct rune *rune)
378 {
379         u8 hash32[32];
380         char *ret;
381         size_t ret_len;
382         struct wbuf wbuf;
383
384         /* We're going to prepend hash */
385         wbuf.off = sizeof(hash32);
386         wbuf.len = 64;
387         wbuf.buf = tal_arr(NULL, char, wbuf.len);
388
389         to_string(&wbuf, rune, hash32);
390         /* Prepend hash */
391         memcpy(wbuf.buf, hash32, sizeof(hash32));
392
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);
397         ret[ret_len] = '\0';
398         tal_free(wbuf.buf);
399         return ret;
400 }
401
402 struct rune *rune_from_string(const tal_t *ctx, const char *str)
403 {
404         u8 hash[32];
405         if (!hex_decode(str, 64, hash, sizeof(hash)))
406                 return NULL;
407         if (str[64] != ':')
408                 return NULL;
409         return from_string(ctx, str + 65, hash);
410 }
411
412 char *rune_to_string(const tal_t *ctx, const struct rune *rune)
413 {
414         u8 hash32[32];
415         struct wbuf wbuf;
416
417         /* We're going to prepend hash (in hex), plus colon */
418         wbuf.off = sizeof(hash32) * 2 + 1;
419         wbuf.len = 128;
420         wbuf.buf = tal_arr(ctx, char, wbuf.len);
421
422         to_string(&wbuf, rune, hash32);
423         hex_encode(hash32, sizeof(hash32), wbuf.buf, sizeof(hash32) * 2 + 1);
424         wbuf.buf[sizeof(hash32) * 2] = ':';
425         return wbuf.buf;
426 }