summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/tmux/Makefile4
-rw-r--r--usr.bin/tmux/client.c3
-rw-r--r--usr.bin/tmux/cmd-attach-session.c5
-rw-r--r--usr.bin/tmux/cmd-queue.c28
-rw-r--r--usr.bin/tmux/cmd-server-access.c147
-rw-r--r--usr.bin/tmux/cmd.c4
-rw-r--r--usr.bin/tmux/proc.c8
-rw-r--r--usr.bin/tmux/server-acl.c186
-rw-r--r--usr.bin/tmux/server-client.c24
-rw-r--r--usr.bin/tmux/server.c18
-rw-r--r--usr.bin/tmux/tmux.144
-rw-r--r--usr.bin/tmux/tmux.h14
12 files changed, 460 insertions, 25 deletions
diff --git a/usr.bin/tmux/Makefile b/usr.bin/tmux/Makefile
index e141324851c..e73ff615cf1 100644
--- a/usr.bin/tmux/Makefile
+++ b/usr.bin/tmux/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.108 2021/06/10 07:50:03 nicm Exp $
+# $OpenBSD: Makefile,v 1.109 2022/05/30 12:48:57 nicm Exp $
PROG= tmux
SRCS= alerts.c \
@@ -55,6 +55,7 @@ SRCS= alerts.c \
cmd-select-pane.c \
cmd-select-window.c \
cmd-send-keys.c \
+ cmd-server-access.c \
cmd-set-buffer.c \
cmd-set-environment.c \
cmd-set-option.c \
@@ -104,6 +105,7 @@ SRCS= alerts.c \
screen-redraw.c \
screen-write.c \
screen.c \
+ server-acl.c \
server-client.c \
server-fn.c \
server.c \
diff --git a/usr.bin/tmux/client.c b/usr.bin/tmux/client.c
index 31218d6a825..509476b6378 100644
--- a/usr.bin/tmux/client.c
+++ b/usr.bin/tmux/client.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: client.c,v 1.157 2022/02/28 09:34:57 nicm Exp $ */
+/* $OpenBSD: client.c,v 1.158 2022/05/30 12:48:57 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -360,6 +360,7 @@ client_main(struct event_base *base, int argc, char **argv, uint64_t flags,
/* Send identify messages. */
client_send_identify(ttynam, termname, caps, ncaps, cwd, feat);
tty_term_free_list(caps, ncaps);
+ proc_flush_peer(client_peer);
/* Send first command. */
if (msg == MSG_COMMAND) {
diff --git a/usr.bin/tmux/cmd-attach-session.c b/usr.bin/tmux/cmd-attach-session.c
index a2541b8d433..855c27c0804 100644
--- a/usr.bin/tmux/cmd-attach-session.c
+++ b/usr.bin/tmux/cmd-attach-session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-attach-session.c,v 1.87 2021/08/21 10:22:38 nicm Exp $ */
+/* $OpenBSD: cmd-attach-session.c,v 1.88 2022/05/30 12:48:57 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -43,7 +43,7 @@ const struct cmd_entry cmd_attach_session_entry = {
/* -t is special */
- .flags = CMD_STARTSERVER,
+ .flags = CMD_STARTSERVER|CMD_READONLY,
.exec = cmd_attach_session_exec
};
@@ -69,6 +69,7 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag,
if (c == NULL)
return (CMD_RETURN_NORMAL);
+
if (server_client_check_nested(c)) {
cmdq_error(item, "sessions should be nested with care, "
"unset $TMUX to force");
diff --git a/usr.bin/tmux/cmd-queue.c b/usr.bin/tmux/cmd-queue.c
index 7d36f3cb8be..dfed88a5cf4 100644
--- a/usr.bin/tmux/cmd-queue.c
+++ b/usr.bin/tmux/cmd-queue.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-queue.c,v 1.107 2021/08/21 17:25:32 nicm Exp $ */
+/* $OpenBSD: cmd-queue.c,v 1.108 2022/05/30 12:48:57 nicm Exp $ */
/*
* Copyright (c) 2013 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -19,9 +19,11 @@
#include <sys/types.h>
#include <ctype.h>
+#include <pwd.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
+#include <unistd.h>
#include "tmux.h"
@@ -558,17 +560,31 @@ cmdq_add_message(struct cmdq_item *item)
{
struct client *c = item->client;
struct cmdq_state *state = item->state;
- const char *name, *key;
+ const char *key;
char *tmp;
+ uid_t uid;
+ struct passwd *pw;
+ char *user = NULL;
tmp = cmd_print(item->cmd);
if (c != NULL) {
- name = c->name;
+ uid = proc_get_peer_uid(c->peer);
+ if (uid != (uid_t)-1 && uid != getuid()) {
+ if ((pw = getpwuid(uid)) != NULL)
+ xasprintf(&user, "[%s]", pw->pw_name);
+ else
+ user = xstrdup("[unknown]");
+ } else
+ user = xstrdup("");
if (c->session != NULL && state->event.key != KEYC_NONE) {
key = key_string_lookup_key(state->event.key, 0);
- server_add_message("%s key %s: %s", name, key, tmp);
- } else
- server_add_message("%s command: %s", name, tmp);
+ server_add_message("%s%s key %s: %s", c->name, user,
+ key, tmp);
+ } else {
+ server_add_message("%s%s command: %s", c->name, user,
+ tmp);
+ }
+ free(user);
} else
server_add_message("command: %s", tmp);
free(tmp);
diff --git a/usr.bin/tmux/cmd-server-access.c b/usr.bin/tmux/cmd-server-access.c
new file mode 100644
index 00000000000..d7f3826275c
--- /dev/null
+++ b/usr.bin/tmux/cmd-server-access.c
@@ -0,0 +1,147 @@
+/* $OpenBSD: cmd-server-access.c,v 1.1 2022/05/30 12:48:57 nicm Exp $ */
+
+/*
+ * Copyright (c) 2021 Dallas Lyons <dallasdlyons@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <pwd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "tmux.h"
+
+/*
+ * Controls access to session.
+ */
+
+static enum cmd_retval cmd_server_access_exec(struct cmd *, struct cmdq_item *);
+
+const struct cmd_entry cmd_server_access_entry = {
+ .name = "server-access",
+ .alias = NULL,
+
+ .args = { "adlrw", 0, 1, NULL },
+ .usage = "[-adlrw]" CMD_TARGET_PANE_USAGE " [user]",
+
+ .flags = CMD_CLIENT_CANFAIL,
+ .exec = cmd_server_access_exec
+};
+
+static enum cmd_retval
+cmd_server_access_deny(struct cmdq_item *item, struct passwd *pw)
+{
+ struct client *loop;
+ struct server_acl_user *user;
+ uid_t uid;
+
+ if ((user = server_acl_user_find(pw->pw_uid)) == NULL) {
+ cmdq_error(item, "user %s not found", pw->pw_name);
+ return (CMD_RETURN_ERROR);
+ }
+ TAILQ_FOREACH(loop, &clients, entry) {
+ uid = proc_get_peer_uid(loop->peer);
+ if (uid == server_acl_get_uid(user)) {
+ loop->exit_message = xstrdup("access not allowed");
+ loop->flags |= CLIENT_EXIT;
+ }
+ }
+ server_acl_user_deny(pw->pw_uid);
+
+ return (CMD_RETURN_NORMAL);
+}
+
+static enum cmd_retval
+cmd_server_access_exec(struct cmd *self, struct cmdq_item *item)
+{
+
+ struct args *args = cmd_get_args(self);
+ struct client *c = cmdq_get_target_client(item);
+ char *name;
+ struct passwd *pw = NULL;
+
+ if (args_has(args, 'l')) {
+ server_acl_display(item);
+ return (CMD_RETURN_NORMAL);
+ }
+ if (args_count(args) == 0) {
+ cmdq_error(item, "missing user arguement");
+ return (CMD_RETURN_ERROR);
+ }
+
+ name = format_single(item, args_string(args, 0), c, NULL, NULL, NULL);
+ if (*name != '\0')
+ pw = getpwnam(name);
+ if (pw == NULL) {
+ cmdq_error(item, "unknown user: %s", name);
+ return (CMD_RETURN_ERROR);
+ }
+ free(name);
+
+ if (pw->pw_uid == 0 || pw->pw_uid == getuid()) {
+ cmdq_error(item, "%s owns the server, can't change access",
+ pw->pw_name);
+ return (CMD_RETURN_ERROR);
+ }
+
+ if (args_has(args, 'a') && args_has(args, 'd')) {
+ cmdq_error(item, "-a and -d cannot be used together");
+ return (CMD_RETURN_ERROR);
+ }
+ if (args_has(args, 'w') && args_has(args, 'r')) {
+ cmdq_error(item, "-r and -w cannot be used together");
+ return (CMD_RETURN_ERROR);
+ }
+
+ if (args_has(args, 'd'))
+ return (cmd_server_access_deny(item, pw));
+ if (args_has(args, 'a')) {
+ if (server_acl_user_find(pw->pw_uid) != NULL) {
+ cmdq_error(item, "user %s is already added",
+ pw->pw_name);
+ return (CMD_RETURN_ERROR);
+ }
+ server_acl_user_allow(pw->pw_uid);
+ /* Do not return - allow -r or -w with -a. */
+ } else if (args_has(args, 'r') || args_has(args, 'w')) {
+ /* -r or -w implies -a if user does not exist. */
+ if (server_acl_user_find(pw->pw_uid) == NULL)
+ server_acl_user_allow(pw->pw_uid);
+ }
+
+ if (args_has(args, 'w')) {
+ if (server_acl_user_find(pw->pw_uid) == NULL) {
+ cmdq_error(item, "user %s not found", pw->pw_name);
+ return (CMD_RETURN_ERROR);
+ }
+ server_acl_user_allow_write(pw->pw_uid);
+ return (CMD_RETURN_NORMAL);
+ }
+
+ if (args_has(args, 'r')) {
+ if (server_acl_user_find(pw->pw_uid) == NULL) {
+ cmdq_error(item, "user %s not found", pw->pw_name);
+ return (CMD_RETURN_ERROR);
+ }
+ server_acl_user_deny_write(pw->pw_uid);
+ return (CMD_RETURN_NORMAL);
+ }
+
+ return (CMD_RETURN_NORMAL);
+}
diff --git a/usr.bin/tmux/cmd.c b/usr.bin/tmux/cmd.c
index 5245871fe53..bd6a0907575 100644
--- a/usr.bin/tmux/cmd.c
+++ b/usr.bin/tmux/cmd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd.c,v 1.173 2021/09/09 21:55:03 nicm Exp $ */
+/* $OpenBSD: cmd.c,v 1.174 2022/05/30 12:48:57 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -96,6 +96,7 @@ extern const struct cmd_entry cmd_select_pane_entry;
extern const struct cmd_entry cmd_select_window_entry;
extern const struct cmd_entry cmd_send_keys_entry;
extern const struct cmd_entry cmd_send_prefix_entry;
+extern const struct cmd_entry cmd_server_access_entry;
extern const struct cmd_entry cmd_set_buffer_entry;
extern const struct cmd_entry cmd_set_environment_entry;
extern const struct cmd_entry cmd_set_hook_entry;
@@ -188,6 +189,7 @@ const struct cmd_entry *cmd_table[] = {
&cmd_select_window_entry,
&cmd_send_keys_entry,
&cmd_send_prefix_entry,
+ &cmd_server_access_entry,
&cmd_set_buffer_entry,
&cmd_set_environment_entry,
&cmd_set_hook_entry,
diff --git a/usr.bin/tmux/proc.c b/usr.bin/tmux/proc.c
index e58a15316dc..b82a6058ec7 100644
--- a/usr.bin/tmux/proc.c
+++ b/usr.bin/tmux/proc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: proc.c,v 1.21 2022/03/08 11:28:40 nicm Exp $ */
+/* $OpenBSD: proc.c,v 1.22 2022/05/30 12:48:57 nicm Exp $ */
/*
* Copyright (c) 2015 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -338,6 +338,12 @@ proc_kill_peer(struct tmuxpeer *peer)
}
void
+proc_flush_peer(struct tmuxpeer *peer)
+{
+ imsg_flush(&peer->ibuf);
+}
+
+void
proc_toggle_log(struct tmuxproc *tp)
{
log_toggle(tp->name);
diff --git a/usr.bin/tmux/server-acl.c b/usr.bin/tmux/server-acl.c
new file mode 100644
index 00000000000..bb9658e4e20
--- /dev/null
+++ b/usr.bin/tmux/server-acl.c
@@ -0,0 +1,186 @@
+/* $OpenBSD: server-acl.c,v 1.1 2022/05/30 12:48:57 nicm Exp $ */
+
+/*
+ * Copyright (c) 2021 Holland Schutte, Jayson Morberg
+ * Copyright (c) 2021 Dallas Lyons <dallasdlyons@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+
+#include <ctype.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "tmux.h"
+
+struct server_acl_user {
+ uid_t uid;
+
+ int flags;
+#define SERVER_ACL_READONLY 0x1
+
+ RB_ENTRY(server_acl_user) entry;
+};
+
+static int
+server_acl_cmp(struct server_acl_user *user1, struct server_acl_user *user2)
+{
+ if (user1->uid < user2->uid)
+ return -1;
+ return user1->uid > user2->uid;
+}
+
+RB_HEAD(server_acl_entries, server_acl_user) server_acl_entries;
+RB_GENERATE_STATIC(server_acl_entries, server_acl_user, entry, server_acl_cmp);
+
+/* Initialize server_acl tree. */
+void
+server_acl_init(void)
+{
+ RB_INIT(&server_acl_entries);
+
+ if (getuid() != 0)
+ server_acl_user_allow(0);
+ server_acl_user_allow(getuid());
+}
+
+/* Find user entry. */
+struct server_acl_user*
+server_acl_user_find(uid_t uid)
+{
+ struct server_acl_user find = { .uid = uid };
+
+ return RB_FIND(server_acl_entries, &server_acl_entries, &find);
+}
+
+/* Display the tree. */
+void
+server_acl_display(struct cmdq_item *item)
+{
+ struct server_acl_user *loop;
+ struct passwd *pw;
+ const char *name;
+
+ RB_FOREACH(loop, server_acl_entries, &server_acl_entries) {
+ if (loop->uid == 0)
+ continue;
+ if ((pw = getpwuid(loop->uid)) != NULL)
+ name = pw->pw_name;
+ else
+ name = "unknown";
+ if (loop->flags == SERVER_ACL_READONLY)
+ cmdq_print(item, "%s (R)", name);
+ else
+ cmdq_print(item, "%s (W)", name);
+ }
+}
+
+/* Allow a user. */
+void
+server_acl_user_allow(uid_t uid)
+{
+ struct server_acl_user *user;
+
+ user = server_acl_user_find(uid);
+ if (user == NULL) {
+ user = xcalloc(1, sizeof *user);
+ user->uid = uid;
+ RB_INSERT(server_acl_entries, &server_acl_entries, user);
+ }
+}
+
+/* Deny a user (remove from the tree). */
+void
+server_acl_user_deny(uid_t uid)
+{
+ struct server_acl_user *user;
+
+ user = server_acl_user_find(uid);
+ if (user != NULL) {
+ RB_REMOVE(server_acl_entries, &server_acl_entries, user);
+ free(user);
+ }
+}
+
+/* Allow this user write access. */
+void
+server_acl_user_allow_write(uid_t uid)
+{
+ struct server_acl_user *user;
+ struct client *c;
+
+ user = server_acl_user_find(uid);
+ if (user == NULL)
+ return;
+ user->flags &= ~SERVER_ACL_READONLY;
+
+ TAILQ_FOREACH(c, &clients, entry) {
+ uid = proc_get_peer_uid(c->peer);
+ if (uid != (uid_t)-1 && uid == user->uid)
+ c->flags &= ~CLIENT_READONLY;
+ }
+}
+
+/* Deny this user write access. */
+void
+server_acl_user_deny_write(uid_t uid)
+{
+ struct server_acl_user *user;
+ struct client *c;
+
+ user = server_acl_user_find(uid);
+ if (user == NULL)
+ return;
+ user->flags |= SERVER_ACL_READONLY;
+
+ TAILQ_FOREACH(c, &clients, entry) {
+ uid = proc_get_peer_uid(c->peer);
+ if (uid != (uid_t)-1 && uid == user->uid)
+ c->flags |= CLIENT_READONLY;
+ }
+}
+
+/*
+ * Check if the client's UID exists in the ACL list and if so, set as read only
+ * if needed. Return false if the user does not exist.
+ */
+int
+server_acl_join(struct client *c)
+{
+ struct server_acl_user *user;
+ uid_t uid;
+
+ uid = proc_get_peer_uid(c->peer);
+ if (uid == (uid_t)-1)
+ return (0);
+
+ user = server_acl_user_find(uid);
+ if (user == NULL)
+ return (0);
+ if (user->flags & SERVER_ACL_READONLY)
+ c->flags |= CLIENT_READONLY;
+ return (1);
+}
+
+/* Get UID for user entry. */
+uid_t
+server_acl_get_uid(struct server_acl_user *user)
+{
+ return (user->uid);
+}
diff --git a/usr.bin/tmux/server-client.c b/usr.bin/tmux/server-client.c
index 44a957c5cd7..6e64188e16a 100644
--- a/usr.bin/tmux/server-client.c
+++ b/usr.bin/tmux/server-client.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server-client.c,v 1.393 2022/03/24 09:05:57 nicm Exp $ */
+/* $OpenBSD: server-client.c,v 1.394 2022/05/30 12:48:57 nicm Exp $ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -2775,6 +2775,14 @@ server_client_dispatch(struct imsg *imsg, void *arg)
}
}
+/* Callback when command is not allowed. */
+static enum cmd_retval
+server_client_read_only(struct cmdq_item *item, __unused void *data)
+{
+ cmdq_error(item, "client is read-only");
+ return (CMD_RETURN_ERROR);
+}
+
/* Callback when command is done. */
static enum cmd_retval
server_client_command_done(struct cmdq_item *item, __unused void *data)
@@ -2799,6 +2807,7 @@ server_client_dispatch_command(struct client *c, struct imsg *imsg)
char **argv, *cause;
struct cmd_parse_result *pr;
struct args_value *values;
+ struct cmdq_item *new_item;
if (c->flags & CLIENT_EXIT)
return;
@@ -2837,7 +2846,12 @@ server_client_dispatch_command(struct client *c, struct imsg *imsg)
free(values);
cmd_free_argv(argc, argv);
- cmdq_append(c, cmdq_get_command(pr->cmdlist, NULL));
+ if ((c->flags & CLIENT_READONLY) &&
+ !cmd_list_all_have(pr->cmdlist, CMD_READONLY))
+ new_item = cmdq_get_callback(server_client_read_only, NULL);
+ else
+ new_item = cmdq_get_command(pr->cmdlist, NULL);
+ cmdq_append(c, new_item);
cmdq_append(c, cmdq_get_callback(server_client_command_done, NULL));
cmd_list_free(pr->cmdlist);
@@ -3071,9 +3085,11 @@ server_client_set_flags(struct client *c, const char *flags)
continue;
log_debug("client %s set flag %s", c->name, next);
- if (not)
+ if (not) {
+ if (c->flags & CLIENT_READONLY)
+ flag &= ~CLIENT_READONLY;
c->flags &= ~flag;
- else
+ } else
c->flags |= flag;
if (flag == CLIENT_CONTROL_NOOUTPUT)
control_reset_offsets(c);
diff --git a/usr.bin/tmux/server.c b/usr.bin/tmux/server.c
index a1293c749c4..ef1183146a5 100644
--- a/usr.bin/tmux/server.c
+++ b/usr.bin/tmux/server.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: server.c,v 1.200 2022/03/28 07:40:57 nicm Exp $ */
+/* $OpenBSD: server.c,v 1.201 2022/05/30 12:48:57 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -239,6 +239,8 @@ server_start(struct tmuxproc *client, int flags, struct event_base *base,
evtimer_set(&server_ev_tidy, server_tidy_event, NULL);
evtimer_add(&server_ev_tidy, &tv);
+ server_acl_init();
+
server_add_accept(0);
proc_loop(server_proc, server_loop);
@@ -355,9 +357,10 @@ server_update_socket(void)
static void
server_accept(int fd, short events, __unused void *data)
{
- struct sockaddr_storage sa;
- socklen_t slen = sizeof sa;
- int newfd;
+ struct sockaddr_storage sa;
+ socklen_t slen = sizeof sa;
+ int newfd;
+ struct client *c;
server_add_accept(0);
if (!(events & EV_READ))
@@ -374,11 +377,16 @@ server_accept(int fd, short events, __unused void *data)
}
fatal("accept failed");
}
+
if (server_exit) {
close(newfd);
return;
}
- server_client_create(newfd);
+ c = server_client_create(newfd);
+ if (!server_acl_join(c)) {
+ c->exit_message = xstrdup("access not allowed");
+ c->flags |= CLIENT_EXIT;
+ }
}
/*
diff --git a/usr.bin/tmux/tmux.1 b/usr.bin/tmux/tmux.1
index 17784899eaa..15efa888f72 100644
--- a/usr.bin/tmux/tmux.1
+++ b/usr.bin/tmux/tmux.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: tmux.1,v 1.887 2022/04/14 06:59:29 nicm Exp $
+.\" $OpenBSD: tmux.1,v 1.888 2022/05/30 12:48:57 nicm Exp $
.\"
.\" Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
.\"
@@ -14,7 +14,7 @@
.\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
.\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: April 14 2022 $
+.Dd $Mdocdate: May 30 2022 $
.Dt TMUX 1
.Os
.Sh NAME
@@ -1485,6 +1485,44 @@ option.
.D1 Pq alias: Ic rename
Rename the session to
.Ar new-name .
+.It Xo Ic server-access
+.Op Fl adlrw
+.Op Ar user
+.Xc
+Change the access or read/write permission of
+.Ar user .
+The user running the
+.Nm
+server (its owner) and the root user cannot be changed and are always
+permitted access.
+.Pp
+.Fl a
+and
+.Fl d
+are used to give or revoke access for the specified user.
+If the user is already attached, the
+.Fl d
+flag causes their clients to be detached.
+.Pp
+.Fl r
+and
+.Fl w
+change the permissions for
+.Ar user :
+.Fl r
+makes their clients read-only and
+.Fl w
+writable.
+.Fl l
+lists current access permissions.
+.Pp
+By default, the access list is empty and
+.Nm
+creates sockets with file system permissions preventing access by any user
+other than the owner (and root).
+These permissions must be changed manually.
+Great care should be taken not to allow access to untrusted users even
+read-only.
.Tg showmsgs
.It Xo Ic show-messages
.Op Fl JT
@@ -5069,7 +5107,7 @@ The following variables are available, where appropriate:
.It Li "client_name" Ta "" Ta "Name of client"
.It Li "client_pid" Ta "" Ta "PID of client process"
.It Li "client_prefix" Ta "" Ta "1 if prefix key has been pressed"
-.It Li "client_readonly" Ta "" Ta "1 if client is readonly"
+.It Li "client_readonly" Ta "" Ta "1 if client is read-only"
.It Li "client_session" Ta "" Ta "Name of the client's session"
.It Li "client_termfeatures" Ta "" Ta "Terminal features of client, if any"
.It Li "client_termname" Ta "" Ta "Terminal name of client"
diff --git a/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h
index 8095c3aa0d0..9cf1a6160b3 100644
--- a/usr.bin/tmux/tmux.h
+++ b/usr.bin/tmux/tmux.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tmux.h,v 1.1166 2022/03/24 09:05:57 nicm Exp $ */
+/* $OpenBSD: tmux.h,v 1.1167 2022/05/30 12:48:57 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -2024,6 +2024,7 @@ struct tmuxpeer *proc_add_peer(struct tmuxproc *, int,
void (*)(struct imsg *, void *), void *);
void proc_remove_peer(struct tmuxpeer *);
void proc_kill_peer(struct tmuxpeer *);
+void proc_flush_peer(struct tmuxpeer *);
void proc_toggle_log(struct tmuxproc *);
pid_t proc_fork_and_daemon(int *);
uid_t proc_get_peer_uid(struct tmuxpeer *);
@@ -3266,4 +3267,15 @@ struct window_pane *spawn_pane(struct spawn_context *, char **);
/* regsub.c */
char *regsub(const char *, const char *, const char *, int);
+/* server-acl.c */
+void server_acl_init(void);
+struct server_acl_user *server_acl_user_find(uid_t);
+void server_acl_display(struct cmdq_item *);
+void server_acl_user_allow(uid_t);
+void server_acl_user_deny(uid_t);
+void server_acl_user_allow_write(uid_t);
+void server_acl_user_deny_write(uid_t);
+int server_acl_join(struct client *);
+uid_t server_acl_get_uid(struct server_acl_user *);
+
#endif /* TMUX_H */