Download raw body.
gotwebd login status and logout link
Make gotwebd display the name of the logged in user, and add a link which
can be clicked to log out (asking the browser to delete the auth cookie).
ok?
M gotwebd/auth.c | 65+ 0-
M gotwebd/fcgi.c | 6+ 0-
M gotwebd/files/htdocs/gotwebd/gotweb.css | 9+ 0-
M gotwebd/gotweb.c | 6+ 0-
M gotwebd/gotwebd.h | 3+ 0-
M gotwebd/pages.tmpl | 12+ 1-
M gotwebd/sockets.c | 3+ 0-
M include/got_error.h | 1+ 0-
M lib/error.c | 1+ 0-
M regress/gotsysd/test_gotwebd.sh | 6+ 0-
M regress/gotsysd/test_gotwebd_repos_www.sh | 1+ 0-
11 files changed, 113 insertions(+), 1 deletion(-)
commit - cc8eaf00fec74bd43bc96a5daedef4c8540964bf
commit + 0b654469a1c4fc80c19dd929a6ff463be03c24ea
blob - 3e9cee3c275c4af7cd66b09401c857dac8177c95
blob + e2dbe8fa26b762709ae7cfc950d4c8fe3dab6c38
--- gotwebd/auth.c
+++ gotwebd/auth.c
@@ -420,6 +420,69 @@ err:
}
}
+static void
+do_logout(struct request *c)
+{
+ const struct got_error *error = NULL;
+ struct gotwebd *env = gotwebd_env;
+ uid_t uid;
+ char *hostname = NULL;
+ const char *identifier = NULL;
+ struct gotweb_url url;
+
+ int r;
+
+ if (login_check_token(&uid, &hostname, c->fcgi_params.auth_cookie,
+ auth_token_secret, sizeof(auth_token_secret),
+ "authentication") == -1) {
+ error = got_error(GOT_ERR_LOGOUT_FAILED);
+ goto err;
+ }
+
+ /*
+ * The www user ID represents the case where no authentication
+ * occurred. This user must not be allowed to log in.
+ */
+ if (uid == env->www_uid) {
+ error = got_error(GOT_ERR_LOGOUT_FAILED);
+ goto err;
+ }
+
+ c->client_uid = uid;
+ if (strcmp(hostname, c->fcgi_params.server_name) != 0) {
+ error = got_error_msg(GOT_ERR_LOGOUT_FAILED,
+ "wrong server name in authentication cookie");
+ goto err;
+ }
+
+ if (gotwebd_env->gotwebd_verbose > 0) {
+ log_info("logging out uid %u as %s for server \"%s\"",
+ uid, identifier, hostname);
+ }
+
+ /* Ask the browser to delete the authentication cookie. */
+ r = tp_writef(c->tp, "Clear-Site-Data: \"cookies\"\r\n");
+ if (r == -1) {
+ error = got_error_from_errno("tp_writef");
+ goto err;
+ }
+
+ memset(&url, 0, sizeof(url));
+ url.action = INDEX;
+ gotweb_reply(c, 307, "text/html", &url);
+ return;
+
+err:
+ free(hostname);
+ hostname = NULL;
+
+ log_warnx("%s: %s", __func__, error->msg);
+ c->t->error = error;
+ if (gotweb_reply(c, 400, "text/html", NULL) == -1)
+ return;
+ gotweb_render_page(c->tp, gotweb_render_error);
+}
+
static const struct got_error *
login_error_hint(struct request *c)
{
@@ -760,6 +823,8 @@ auth_dispatch_sockets(int fd, short event, void *arg)
if (c->fcgi_params.qs.login[0] != '\0')
do_login(c);
+ else if (c->fcgi_params.qs.logout)
+ do_logout(c);
else
process_request(c);
blob - 2a81e7f5e7e6523aa37d8d9e15a0ab325483eb37
blob + 3aa0806a14d767bd4f2ead5eea1fec881a7c5e9c
--- gotwebd/fcgi.c
+++ gotwebd/fcgi.c
@@ -192,6 +192,7 @@ static const struct querystring_keys querystring_keys[
{ "index_page", GOTWEBD_QS_INDEX_PAGE },
{ "path", GOTWEBD_QS_PATH },
{ "login", GOTWEBD_QS_LOGIN },
+ { "logout", GOTWEBD_QS_LOGOUT },
};
static const struct action_keys action_keys[] = {
@@ -380,6 +381,11 @@ assign_querystring(struct querystring *qs, char *key,
goto done;
}
break;
+ case GOTWEBD_QS_LOGOUT:
+ if (strcmp(value, "1") != 0)
+ break;
+ qs->logout = 1;
+ break;
}
/* entry found */
blob - ea4cdedb51cb3f930bbc483b0f82bc9590a180b6
blob + 15e6ffef2c615352d5e23d6ef94fe1e37fb9dff1
--- gotwebd/files/htdocs/gotwebd/gotweb.css
+++ gotwebd/files/htdocs/gotwebd/gotweb.css
@@ -101,6 +101,15 @@ hr {
padding-bottom: 10px;
padding-top: 10px;
}
+#login_status {
+ color: lightgrey;
+ text-align: right;
+ padding-right: 10px;
+ padding-left: 10px;
+ padding-top: 5px;
+ padding-bottom: 5px;
+ font-weight: monospace;
+}
#np_wrapper {
width: 100%;
border-bottom: 1px dotted #444444;
blob - 2dcdf486c002a5a2a948db88611b6912fc1de984
blob + 21603a5b4142f0537aca3e2741d0930cb22ef6b8
--- gotwebd/gotweb.c
+++ gotwebd/gotweb.c
@@ -1469,6 +1469,12 @@ gotweb_render_url(struct request *c, struct gotweb_url
sep = "&";
}
+ if (url->logout == 1) {
+ if (tp_writef(c->tp, "%slogout=1", sep) == -1)
+ return -1;
+ sep = "&";
+ }
+
return 0;
}
blob - 69c2896f72735357062dc4f09af598567a4aa339
blob + e308c7906f34668208667e5f2742f917d90a6df7
--- gotwebd/gotwebd.h
+++ gotwebd/gotwebd.h
@@ -311,6 +311,7 @@ struct querystring {
int index_page;
char path[PATH_MAX];
char login[MAX_AUTH_COOKIE];
+ int logout;
};
struct gotwebd_fcgi_params {
@@ -556,6 +557,7 @@ struct gotweb_url {
const char *folder;
const char *headref;
const char *path;
+ int logout;
};
struct querystring_keys {
@@ -577,6 +579,7 @@ enum querystring_elements {
GOTWEBD_QS_INDEX_PAGE,
GOTWEBD_QS_PATH,
GOTWEBD_QS_LOGIN,
+ GOTWEBD_QS_LOGOUT,
};
extern struct gotwebd *gotwebd_env;
blob - 4fb768f84e038e9bdfc9ee78a9e9c615084cb757
blob + 620eae4ecfde34d2e50eb56fa4eb94374d73fe0d
--- gotwebd/pages.tmpl
+++ gotwebd/pages.tmpl
@@ -169,7 +169,7 @@ nextsep(char *s, char **t)
struct request *c = tp->tp_arg;
struct server *srv = c->srv;
const struct querystring *qs = c->t->qs;
- struct gotweb_url u_path;
+ struct gotweb_url u_path, u_logout;
char prefix[MAX_DOCUMENT_URI * 2];
const char *css = srv->custom_css;
const char *url_root, *url_path;
@@ -198,6 +198,11 @@ nextsep(char *s, char **t)
memset(&u_path, 0, sizeof(u_path));
u_path.index_page = -1;
u_path.action = SUMMARY;
+
+ memset(&u_logout, 0, sizeof(u_logout));
+ u_logout.index_page = -1;
+ u_logout.action = INDEX;
+ u_logout.logout = 1;
!}
<!doctype html>
<html>
@@ -221,6 +226,12 @@ nextsep(char *s, char **t)
<img src="{{ prefix }}/{{ srv->logo }}" />
</a>
</div>
+ {{ if (c->access_identifier[0]) }}
+ <div id="login_status">
+ Logged in as: <b>{{ c->access_identifier }}</b>
+ (<a href="{{ render gotweb_render_url(c, &u_logout) }}">Logout</a>)
+ </div>
+ {{ end }}
</header>
<nav id="site_path">
<div id="site_link">
blob - 387e6c57b105661f9840264b1240b2880aba9517
blob + 6d106f0a375678d96ece6c28b54c08e49d0cdecd
--- gotwebd/sockets.c
+++ gotwebd/sockets.c
@@ -640,6 +640,9 @@ recv_parsed_params(struct imsg *imsg)
goto fail;
}
+ if (params.qs.logout)
+ p->qs.logout = 1;
+
if (params.document_uri[0] != '\0' &&
strlcpy(p->document_uri, params.document_uri,
sizeof(p->document_uri)) >= sizeof(p->document_uri)) {
blob - 1868cf47328cce63d6b5b9fec9cd8152af55ed29
blob + 301dcaa124592fd188562af5f52a713b9138d4b9
--- include/got_error.h
+++ include/got_error.h
@@ -201,6 +201,7 @@
#define GOT_ERR_UNKNOWN_COMMAND 193
#define GOT_ERR_NOT_FOUND 194
#define GOT_ERR_MEDIA_TYPE 195
+#define GOT_ERR_LOGOUT_FAILED 196
struct got_error {
int code;
blob - 6d25b5840fd9283ff9543c6405e6dca52a0825f8
blob + dcca96bf17d67b78004204c30d6fdf6ecd2153f5
--- lib/error.c
+++ lib/error.c
@@ -252,6 +252,7 @@ static const struct got_error got_errors[] = {
{ GOT_ERR_UNKNOWN_COMMAND, "command not found" },
{ GOT_ERR_NOT_FOUND, "not found" },
{ GOT_ERR_MEDIA_TYPE, "malformed media type" },
+ { GOT_ERR_LOGOUT_FAILED, "logout failed" },
};
static struct got_custom_error {
blob - b8c0500e50a21e234c5a8ec5f7dd2688296be03e
blob + eb1b65c4fa32ec243b7e7e8e4f29b25d9e336c16
--- regress/gotsysd/test_gotwebd.sh
+++ regress/gotsysd/test_gotwebd.sh
@@ -173,6 +173,7 @@ EOF
w3m -cookie-jar "$testroot/cookies" "$url" -dump > $testroot/stdout
cat > $testroot/stdout.expected <<EOF
[got]
+Logged in as: ${GOTSYSD_TEST_USER} (Logout)
Repositories
Repository
testrepo.git
@@ -202,6 +203,7 @@ EOF
cat > $testroot/stdout.expected <<EOF
[got]
+Logged in as: ${GOTSYSD_TEST_USER} (Logout)
Repositories / testrepo.git / tree /
Tree
@@ -401,6 +403,7 @@ EOF
w3m -cookie-jar "$testroot/cookies" "$url" -dump > $testroot/stdout
cat > $testroot/stdout.expected <<EOF
[got]
+Logged in as: ${GOTSYSD_TEST_USER} (Logout)
Repositories
Repository
gottest.git
@@ -435,6 +438,7 @@ EOF
w3m -cookie-jar "$testroot/cookies" "$url" -dump > $testroot/stdout
cat > $testroot/stdout.expected <<EOF
[got]
+Logged in as: ${GOTSYSD_DEV_USER} (Logout)
Repositories
Repository
gottestdev.git
@@ -601,6 +605,7 @@ EOF
w3m -cookie-jar "$testroot/cookies" "$url" -dump > $testroot/stdout
cat > $testroot/stdout.expected <<EOF
[got]
+Logged in as: ${GOTSYSD_TEST_USER} (Logout)
Repositories
Repository
gottest.git
@@ -626,6 +631,7 @@ EOF
cat > $testroot/stdout.expected <<EOF
[got]
+Logged in as: ${GOTSYSD_TEST_USER} (Logout)
Repositories / gottest.git / tree /
reference refs/heads/main not found
blob - f649b0aa2de90feea176fb354a2986697d9e5826
blob + 56fb4c9aa170331283950ac27c8fdeb2db863c0b
--- regress/gotsysd/test_gotwebd_repos_www.sh
+++ regress/gotsysd/test_gotwebd_repos_www.sh
@@ -193,6 +193,7 @@ EOF
w3m -cookie-jar "$testroot/cookies" "$url" -dump > $testroot/stdout
cat > $testroot/stdout.expected <<EOF
[got]
+Logged in as: ${GOTSYSD_TEST_USER} (Logout)
Repositories
Repository
www.git
gotwebd login status and logout link