xref: /openbsd-src/usr.bin/tmux/cmd-server-access.c (revision afa45568d407f29115da6bbe6c32128e13247d14)
1*afa45568Snicm /* $OpenBSD: cmd-server-access.c,v 1.3 2022/05/31 16:13:43 nicm Exp $ */
28ab000fcSnicm 
38ab000fcSnicm /*
48ab000fcSnicm  * Copyright (c) 2021 Dallas Lyons <dallasdlyons@gmail.com>
58ab000fcSnicm  *
68ab000fcSnicm  * Permission to use, copy, modify, and distribute this software for any
78ab000fcSnicm  * purpose with or without fee is hereby granted, provided that the above
88ab000fcSnicm  * copyright notice and this permission notice appear in all copies.
98ab000fcSnicm  *
108ab000fcSnicm  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
118ab000fcSnicm  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
128ab000fcSnicm  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
138ab000fcSnicm  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
148ab000fcSnicm  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
158ab000fcSnicm  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
168ab000fcSnicm  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
178ab000fcSnicm  */
188ab000fcSnicm 
198ab000fcSnicm #include <sys/stat.h>
208ab000fcSnicm #include <sys/types.h>
218ab000fcSnicm 
228ab000fcSnicm #include <pwd.h>
238ab000fcSnicm #include <stdio.h>
248ab000fcSnicm #include <string.h>
258ab000fcSnicm #include <stdlib.h>
268ab000fcSnicm #include <unistd.h>
278ab000fcSnicm 
288ab000fcSnicm #include "tmux.h"
298ab000fcSnicm 
308ab000fcSnicm /*
318ab000fcSnicm  * Controls access to session.
328ab000fcSnicm  */
338ab000fcSnicm 
348ab000fcSnicm static enum cmd_retval cmd_server_access_exec(struct cmd *, struct cmdq_item *);
358ab000fcSnicm 
368ab000fcSnicm const struct cmd_entry cmd_server_access_entry = {
378ab000fcSnicm 	.name = "server-access",
388ab000fcSnicm 	.alias = NULL,
398ab000fcSnicm 
408ab000fcSnicm 	.args = { "adlrw", 0, 1, NULL },
418ab000fcSnicm 	.usage = "[-adlrw] " CMD_TARGET_PANE_USAGE " [user]",
428ab000fcSnicm 
438ab000fcSnicm 	.flags = CMD_CLIENT_CANFAIL,
448ab000fcSnicm 	.exec = cmd_server_access_exec
458ab000fcSnicm };
468ab000fcSnicm 
478ab000fcSnicm static enum cmd_retval
cmd_server_access_deny(struct cmdq_item * item,struct passwd * pw)488ab000fcSnicm cmd_server_access_deny(struct cmdq_item *item, struct passwd *pw)
498ab000fcSnicm {
508ab000fcSnicm 	struct client		*loop;
518ab000fcSnicm 	struct server_acl_user	*user;
528ab000fcSnicm 	uid_t			 uid;
538ab000fcSnicm 
548ab000fcSnicm 	if ((user = server_acl_user_find(pw->pw_uid)) == NULL) {
558ab000fcSnicm 		cmdq_error(item, "user %s not found", pw->pw_name);
568ab000fcSnicm 		return (CMD_RETURN_ERROR);
578ab000fcSnicm 	}
588ab000fcSnicm 	TAILQ_FOREACH(loop, &clients, entry) {
598ab000fcSnicm 		uid = proc_get_peer_uid(loop->peer);
608ab000fcSnicm 		if (uid == server_acl_get_uid(user)) {
618ab000fcSnicm 			loop->exit_message = xstrdup("access not allowed");
628ab000fcSnicm 			loop->flags |= CLIENT_EXIT;
638ab000fcSnicm 		}
648ab000fcSnicm 	}
658ab000fcSnicm 	server_acl_user_deny(pw->pw_uid);
668ab000fcSnicm 
678ab000fcSnicm 	return (CMD_RETURN_NORMAL);
688ab000fcSnicm }
698ab000fcSnicm 
708ab000fcSnicm static enum cmd_retval
cmd_server_access_exec(struct cmd * self,struct cmdq_item * item)718ab000fcSnicm cmd_server_access_exec(struct cmd *self, struct cmdq_item *item)
728ab000fcSnicm {
738ab000fcSnicm 
748ab000fcSnicm 	struct args	*args = cmd_get_args(self);
758ab000fcSnicm 	struct client	*c = cmdq_get_target_client(item);
768ab000fcSnicm 	char		*name;
778ab000fcSnicm 	struct passwd	*pw = NULL;
788ab000fcSnicm 
798ab000fcSnicm 	if (args_has(args, 'l')) {
808ab000fcSnicm 		server_acl_display(item);
818ab000fcSnicm 		return (CMD_RETURN_NORMAL);
828ab000fcSnicm 	}
838ab000fcSnicm 	if (args_count(args) == 0) {
846df9671cSnicm 		cmdq_error(item, "missing user argument");
858ab000fcSnicm 		return (CMD_RETURN_ERROR);
868ab000fcSnicm 	}
878ab000fcSnicm 
888ab000fcSnicm 	name = format_single(item, args_string(args, 0), c, NULL, NULL, NULL);
898ab000fcSnicm 	if (*name != '\0')
908ab000fcSnicm 		pw = getpwnam(name);
918ab000fcSnicm 	if (pw == NULL) {
928ab000fcSnicm 		cmdq_error(item, "unknown user: %s", name);
938ab000fcSnicm 		return (CMD_RETURN_ERROR);
948ab000fcSnicm 	}
958ab000fcSnicm 	free(name);
968ab000fcSnicm 
978ab000fcSnicm 	if (pw->pw_uid == 0 || pw->pw_uid == getuid()) {
988ab000fcSnicm 		cmdq_error(item, "%s owns the server, can't change access",
998ab000fcSnicm 		    pw->pw_name);
1008ab000fcSnicm 		return (CMD_RETURN_ERROR);
1018ab000fcSnicm 	}
1028ab000fcSnicm 
1038ab000fcSnicm 	if (args_has(args, 'a') && args_has(args, 'd')) {
1048ab000fcSnicm 		cmdq_error(item, "-a and -d cannot be used together");
1058ab000fcSnicm 		return (CMD_RETURN_ERROR);
1068ab000fcSnicm 	}
1078ab000fcSnicm 	if (args_has(args, 'w') && args_has(args, 'r')) {
1088ab000fcSnicm 		cmdq_error(item, "-r and -w cannot be used together");
1098ab000fcSnicm 		return (CMD_RETURN_ERROR);
1108ab000fcSnicm 	}
1118ab000fcSnicm 
1128ab000fcSnicm 	if (args_has(args, 'd'))
1138ab000fcSnicm 		return (cmd_server_access_deny(item, pw));
1148ab000fcSnicm 	if (args_has(args, 'a')) {
1158ab000fcSnicm 		if (server_acl_user_find(pw->pw_uid) != NULL) {
1168ab000fcSnicm 			cmdq_error(item, "user %s is already added",
1178ab000fcSnicm 			    pw->pw_name);
1188ab000fcSnicm 			return (CMD_RETURN_ERROR);
1198ab000fcSnicm 		}
1208ab000fcSnicm 		server_acl_user_allow(pw->pw_uid);
1218ab000fcSnicm 		/* Do not return - allow -r or -w with -a. */
1228ab000fcSnicm 	} else if (args_has(args, 'r') || args_has(args, 'w')) {
1238ab000fcSnicm 		/* -r or -w implies -a if user does not exist. */
1248ab000fcSnicm 		if (server_acl_user_find(pw->pw_uid) == NULL)
1258ab000fcSnicm 			server_acl_user_allow(pw->pw_uid);
1268ab000fcSnicm 	}
1278ab000fcSnicm 
1288ab000fcSnicm 	if (args_has(args, 'w')) {
1298ab000fcSnicm 		if (server_acl_user_find(pw->pw_uid) == NULL) {
1308ab000fcSnicm 			cmdq_error(item, "user %s not found", pw->pw_name);
1318ab000fcSnicm 			return (CMD_RETURN_ERROR);
1328ab000fcSnicm 		}
1338ab000fcSnicm 		server_acl_user_allow_write(pw->pw_uid);
1348ab000fcSnicm 		return (CMD_RETURN_NORMAL);
1358ab000fcSnicm 	}
1368ab000fcSnicm 
1378ab000fcSnicm 	if (args_has(args, 'r')) {
1388ab000fcSnicm 		if (server_acl_user_find(pw->pw_uid) == NULL) {
1398ab000fcSnicm 			cmdq_error(item, "user %s not found", pw->pw_name);
1408ab000fcSnicm 			return (CMD_RETURN_ERROR);
1418ab000fcSnicm 		}
1428ab000fcSnicm 		server_acl_user_deny_write(pw->pw_uid);
1438ab000fcSnicm 		return (CMD_RETURN_NORMAL);
1448ab000fcSnicm 	}
1458ab000fcSnicm 
1468ab000fcSnicm 	return (CMD_RETURN_NORMAL);
1478ab000fcSnicm }
148