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