Commit Diff


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);