commit a0993bddf38dffabddd7d5b9a246f35cc00121ef from: Omar Polo date: Sun Jun 01 18:08:10 2025 UTC teach gotwebd how to decode the tokens commit - 9dc775ce5edf929701a9b3da70298d591862ba33 commit + a0993bddf38dffabddd7d5b9a246f35cc00121ef blob - 0505fbd1f8d0b37fded75218be702fa5b8fe4fab blob + a95ca469ac5b20574614e3fad8010383444bfd91 --- gotwebd/Makefile +++ gotwebd/Makefile @@ -37,9 +37,9 @@ MAN = ${PROG}.conf.5 ${PROG}.8 CPPFLAGS += -I${.CURDIR}/../include -I${.CURDIR}/../lib -I${.CURDIR} CPPFLAGS += -I${.CURDIR}/../template -LDADD += -lz -levent -lutil -lm +LDADD += -lz -levent -lutil -lm -lcrypto YFLAGS = -DPADD = ${LIBEVENT} ${LIBUTIL} ${LIBM} +DPADD = ${LIBEVENT} ${LIBUTIL} ${LIBM} ${LIBCRIPTO} #CFLAGS += -DGOT_NO_OBJ_CACHE .if ${GOT_RELEASE} != "Yes" blob - dee44e8340f2a08fb4909809fc41bf2ff6cd1e7d blob + d0f886fe876d26c60a5fe6f31cf305ca77299395 --- gotwebd/auth.c +++ gotwebd/auth.c @@ -64,7 +64,7 @@ auth_init(void) /* * The token format is: * - * "v1"[issued at/64bit][expire/64bit][username]"\0"[host]"\0" + * "v1\0"[issued at/64bit][expire/64bit][username]"\0"[host]"\0" * * followed by the HMAC-SHA256 of it, all encoded in base64. */ @@ -77,14 +77,62 @@ auth_init(void) int auth_is_allowed(const char *token) { - return !strcmp(token, "42"); + /* XXX should consult the ACLs */ + return auth_check_token(token); } /* checks whether the token's signature matches, i.e. if it looks good. */ int auth_check_token(const char *token) { - return !strcmp(token, "42"); + time_t now; + uint64_t issued, expire; + uint8_t *data; + size_t len; + char hmac[32], exp[32]; + + /* xxx check for overflow */ + len = (strlen(token) / 4) * 3; + if (len < 21 + 32) /* min length assuming empty username and host */ + return -1; + + data = malloc(len); + if (data == NULL) + return -1; + + if (EVP_DecodeBlock(data, token, strlen(token)) == -1) { + free(data); + return -1; + } + now = time(NULL); + + if (memcmp(data, "v1", 3) != 0) { + free(data); + return -1; + } + + if (HMAC(EVP_sha256(), token_secret, sizeof(token_secret), data, + len - 32, exp, NULL) == NULL) { + free(data); + return -1; + } + + memcpy(hmac, data + len - 32, 32); + if (memcmp(hmac, exp, 32) != 0) { + free(data); + return -1; + } + + memcpy(&issued, data + 3, sizeof(issued)); + memcpy(&expire, data + 3 + 8, sizeof(expire)); + + if (expire < now) { + free(data); + return -1; + } + + /* xxx: extract username and host */ + return 0; } /* */ blob - 98b573ad9c778c1a1e852430162d12d1be11dfc4 blob + db9f586dae8ab239b36bb87983f3f6345f44b4c0 --- gotwebd/gotweb.c +++ gotwebd/gotweb.c @@ -266,7 +266,7 @@ do_login(struct request *c) if (gotwebd_env->gotwebd_verbose > 0) log_info("processing login: code='%s'", qs->login); - if (!auth_check_token(qs->login)) { + if (auth_check_token(qs->login) == -1) { log_warnx("invalid code for login"); if (gotweb_reply(c, 401, "text/html", NULL) == -1) return (-1); @@ -326,7 +326,7 @@ gotweb_process_request(struct request *c) * TODO: pass the ACLs and the current repository. */ log_info("auth code is %s", c->auth_cookie); - if (!auth_is_allowed(c->auth_cookie)) { + if (auth_is_allowed(c->auth_cookie) == -1) { if (gotweb_reply(c, 401, "text/html", NULL) == -1) return -1; return gotweb_render_page(c->tp, gotweb_render_unauthorized);