6 * rune - Simple cookies you can extend (a-la Python runes class).
8 * This code is a form of cookies, but they are user-extensible, and
9 * contain a simple language to define what the cookie allows.
11 * A "rune" contains the hash of a secret (so the server can
12 * validate), such that you can add, but not subtract, conditions.
13 * This is a simplified form of Macaroons, See
14 * https://research.google/pubs/pub41892/ "Macaroons: Cookies with
15 * Contextual Caveats for Decentralized Authorization in the Cloud".
16 * It has one good idea, some extended ideas nobody implements, and
17 * lots and lots of words.
20 * Author: Rusty Russell <rusty@rustcorp.com.au>
22 * // Given "generate secret 1" outputs kr7AW-eJ2Munhv5ftu4rHqAnhxUpPQM8aOyWOmqiytk9MQ==
23 * // Given "add kr7AW-eJ2Munhv5ftu4rHqAnhxUpPQM8aOyWOmqiytk9MQ== uid=rusty" outputs Xyt5S6FKUnA2ppGB62c6HTPGojt2S7k2n7Cf7Tjj6zM9MSZ1aWQ9cnVzdHk=
24 * // Given "test secret Xyt5S6FKUnA2ppGB62c6HTPGojt2S7k2n7Cf7Tjj6zM9MSZ1aWQ9cnVzdHk= rusty" outputs PASSED
25 * // Given "test secret Xyt5S6FKUnA2ppGB62c6HTPGojt2S7k2n7Cf7Tjj6zM9MSZ1aWQ9cnVzdHk= notrusty" outputs FAILED: uid is not equal to rusty
26 * // Given "add Xyt5S6FKUnA2ppGB62c6HTPGojt2S7k2n7Cf7Tjj6zM9MSZ1aWQ9cnVzdHk= t\<1655958616" outputs _YBFmeAedqlLigWHAmvyyGGHRrnI40BRQGh2hWdSZ9E9MSZ1aWQ9cnVzdHkmdDwxNjU1OTU4NjE2
27 * // Given "test secret _YBFmeAedqlLigWHAmvyyGGHRrnI40BRQGh2hWdSZ9E9MSZ1aWQ9cnVzdHkmdDwxNjU1OTU4NjE2 rusty" outputs FAILED: t is greater or equal to 1655958616
28 * #include <ccan/err/err.h>
29 * #include <ccan/rune/rune.h>
30 * #include <ccan/str/str.h>
32 * #include <sys/time.h>
34 * // We support two values: current time (t), and user id (uid).
35 * static const char *check(const tal_t *ctx,
36 * const struct rune *rune,
37 * const struct rune_altern *alt,
40 * // t= means current time, in seconds, as integer
41 * if (streq(alt->fieldname, "t")) {
43 * gettimeofday(&now, NULL);
44 * return rune_alt_single_int(ctx, alt, now.tv_sec);
46 * if (streq(alt->fieldname, "uid")) {
47 * return rune_alt_single_str(ctx, alt, uid, strlen(uid));
49 * // Otherwise, field is missing
50 * return rune_alt_single_missing(ctx, alt);
53 * int main(int argc, char *argv[])
55 * struct rune *master, *rune;
60 * if (streq(argv[1], "generate")) {
61 * // Make master, derive a unique_id'd rune.
62 * if (argc != 3 && argc != 4)
64 * master = rune_new(NULL, (u8 *)argv[2], strlen(argv[2]), NULL);
65 * rune = rune_derive_start(NULL, master, argv[3]);
66 * } else if (streq(argv[1], "add")) {
67 * // Add a restriction
68 * struct rune_restr *restr;
71 * rune = rune_from_base64(NULL, argv[2]);
73 * errx(1, "Bad rune");
74 * restr = rune_restr_from_string(NULL, argv[3], strlen(argv[3]));
76 * errx(1, "Bad restriction string");
77 * rune_add_restr(rune, restr);
78 * } else if (streq(argv[1], "test")) {
82 * master = rune_new(NULL, (u8 *)argv[2], strlen(argv[2]), NULL);
84 * errx(1, "Bad master rune");
85 * rune = rune_from_base64(NULL, argv[3]);
87 * errx(1, "Bad rune");
88 * err = rune_test(NULL, master, rune, check, argv[4]);
90 * printf("FAILED: %s\n", err);
97 * printf("%s\n", rune_to_base64(NULL, rune));
101 * errx(1, "Usage: %s generate <secret> <uniqueid> OR\n"
102 * "%s add <rune> <restriction> OR\n"
103 * "%s test <secret> <rune> <uid>", argv[0], argv[0], argv[0]);
106 int main(int argc, char *argv[])
108 /* Expect exactly one argument */
112 if (strcmp(argv[1], "depends") == 0) {
113 printf("ccan/base64\n");
114 printf("ccan/crypto/sha256\n");
115 printf("ccan/endian\n");
116 printf("ccan/mem\n");
117 printf("ccan/short_types\n");
118 printf("ccan/str/hex\n");
119 printf("ccan/tal/str\n");
120 printf("ccan/tal\n");
121 printf("ccan/typesafe_cb\n");
124 if (strcmp(argv[1], "testdepends") == 0) {
125 printf("ccan/tal/grab_file\n");