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")) {
44 * gettimeofday(&now, NULL);
46 * return rune_alt_single(ctx, alt, NULL, &t);
48 * if (streq(alt->fieldname, "uid")) {
49 * return rune_alt_single(ctx, alt, uid, NULL);
51 * // Otherwise, field is missing
52 * return rune_alt_single(ctx, alt, NULL, NULL);
55 * int main(int argc, char *argv[])
57 * struct rune *master, *rune;
62 * if (streq(argv[1], "generate")) {
63 * // Make master, derive a unique_id'd rune.
64 * if (argc != 3 && argc != 4)
66 * master = rune_new(NULL, (u8 *)argv[2], strlen(argv[2]), NULL);
67 * rune = rune_derive_start(NULL, master, argv[3]);
68 * } else if (streq(argv[1], "add")) {
69 * // Add a restriction
70 * struct rune_restr *restr;
73 * rune = rune_from_base64(NULL, argv[2]);
75 * errx(1, "Bad rune");
76 * restr = rune_restr_from_string(NULL, argv[3], strlen(argv[3]));
78 * errx(1, "Bad restriction string");
79 * rune_add_restr(rune, restr);
80 * } else if (streq(argv[1], "test")) {
84 * master = rune_new(NULL, (u8 *)argv[2], strlen(argv[2]), NULL);
86 * errx(1, "Bad master rune");
87 * rune = rune_from_base64(NULL, argv[3]);
89 * errx(1, "Bad rune");
90 * err = rune_test(NULL, master, rune, check, argv[4]);
92 * printf("FAILED: %s\n", err);
99 * printf("%s\n", rune_to_base64(NULL, rune));
103 * errx(1, "Usage: %s generate <secret> <uniqueid> OR\n"
104 * "%s add <rune> <restriction> OR\n"
105 * "%s test <secret> <rune> <uid>", argv[0], argv[0], argv[0]);
108 int main(int argc, char *argv[])
110 /* Expect exactly one argument */
114 if (strcmp(argv[1], "depends") == 0) {
115 printf("ccan/base64\n");
116 printf("ccan/crypto/sha256\n");
117 printf("ccan/endian\n");
118 printf("ccan/short_types\n");
119 printf("ccan/str/hex\n");
120 printf("ccan/tal/str\n");
121 printf("ccan/tal\n");
122 printf("ccan/typesafe_cb\n");
125 if (strcmp(argv[1], "testdepends") == 0) {
126 printf("ccan/tal/grab_file\n");