From 95bb627ffbb5fcbf9462b5957d0cb25072d8c64e Mon Sep 17 00:00:00 2001 From: "C. McEnroe" Date: Sat, 23 Jan 2021 00:03:58 -0500 Subject: Separate kiosk mode from restrict mode Restrict mode will focus on sandboxing, while kiosk will continue to restrict IRC access through a public kiosk. Kiosk mode without restrict mode allows execution of man 1 catgirl with /help, assuming external sandboxing. The /list and /part commands are also added to the list of disabled commands in kiosk mode, since they are pointless without access to /join. --- catgirl.1 | 39 +++++++++++++++++++++++++++++---------- chat.c | 8 +++++--- chat.h | 1 + command.c | 38 +++++++++++++++++++++++--------------- 4 files changed, 58 insertions(+), 28 deletions(-) diff --git a/catgirl.1 b/catgirl.1 index b632317..f0dddfe 100644 --- a/catgirl.1 +++ b/catgirl.1 @@ -1,4 +1,4 @@ -.Dd January 16, 2021 +.Dd January 22, 2021 .Dt CATGIRL 1 .Os . @@ -8,7 +8,7 @@ . .Sh SYNOPSIS .Nm -.Op Fl Relv +.Op Fl KRelv .Op Fl C Ar copy .Op Fl H Ar hash .Op Fl I Ar highlight @@ -123,6 +123,20 @@ The commands which can be filtered are: .Sy QUIT , .Sy SETNAME . . +.It Fl K , Cm kiosk +Disable the +.Ic /copy , +.Ic /debug , +.Ic /exec , +.Ic /join , +.Ic /list , +.Ic /msg , +.Ic /open , +.Ic /part , +.Ic /query , +.Ic /quote +commands. +. .It Fl N Ar util , Cm notify = Ar util Send notifications using a utility. Use more than once to add arguments to @@ -145,14 +159,19 @@ The default is the first available of .It Fl R , Cm restrict Disable the .Ic /copy , -.Ic /debug , -.Ic /exec , -.Ic /join , -.Ic /msg , -.Ic /open , -.Ic /query , -.Ic /quote -commands. +.Ic /exec +and +.Ic /open +commands, +as well as viewing this manual with +.Ic /help . +On +.Ox , +restrict system operations +and filesystem access with +.Xr pledge 2 +and +.Xr unveil 2 . . .It Fl S Ar host , Cm bind = Ar host Bind to source address diff --git a/chat.c b/chat.c index ebffe46..f455b35 100644 --- a/chat.c +++ b/chat.c @@ -159,7 +159,6 @@ static void sandbox(const char *trust, const char *cert, const char *priv) { const char *path; const char *perm; } paths[] = { - { "/usr/bin/man", "x" }, { "/usr/share/terminfo", "r" }, { tls_default_ca_cert_file(), "r" }, { NULL, NULL }, @@ -200,6 +199,7 @@ int main(int argc, char *argv[]) { { .val = 'C', .name = "copy", required_argument }, { .val = 'H', .name = "hash", required_argument }, { .val = 'I', .name = "highlight", required_argument }, + { .val = 'K', .name = "kiosk", no_argument }, { .val = 'N', .name = "notify", required_argument }, { .val = 'O', .name = "open", required_argument }, { .val = 'R', .name = "restrict", no_argument }, @@ -236,6 +236,7 @@ int main(int argc, char *argv[]) { break; case 'C': utilPush(&urlCopyUtil, optarg); break; case 'H': parseHash(optarg); break; case 'I': filterAdd(Hot, optarg); + break; case 'K': self.kiosk = true; break; case 'N': utilPush(&uiNotifyUtil, optarg); break; case 'O': utilPush(&urlOpenUtil, optarg); break; case 'R': self.restricted = true; @@ -325,7 +326,8 @@ int main(int argc, char *argv[]) { sig_t cursesWinch = signal(SIGWINCH, signalHandler); fcntl(irc, F_SETFD, FD_CLOEXEC); - if (!self.restricted) { + bool pipes = !self.kiosk && !self.restricted; + if (pipes) { int error = pipe(utilPipe); if (error) err(EX_OSERR, "pipe"); @@ -345,7 +347,7 @@ int main(int argc, char *argv[]) { { .events = POLLIN, .fd = execPipe[0] }, }; while (!self.quit) { - int nfds = poll(fds, (self.restricted ? 2 : ARRAY_LEN(fds)), -1); + int nfds = poll(fds, (pipes ? ARRAY_LEN(fds) : 2), -1); if (nfds < 0 && errno != EINTR) err(EX_IOERR, "poll"); if (nfds > 0) { if (fds[0].revents) uiRead(); diff --git a/chat.h b/chat.h index 1b1c338..4c9b32b 100644 --- a/chat.h +++ b/chat.h @@ -183,6 +183,7 @@ enum Cap { extern struct Self { bool debug; + bool kiosk; bool restricted; size_t pos; enum Cap caps; diff --git a/command.c b/command.c index 998d9a2..655b32d 100644 --- a/command.c +++ b/command.c @@ -457,6 +457,10 @@ static void commandHelp(uint id, char *params) { replies[ReplyHelp]++; return; } + if (self.restricted) { + uiFormat(id, Warm, NULL, "See catgirl(1) or /help index"); + return; + } uiHide(); pid_t pid = fork(); @@ -474,7 +478,8 @@ static void commandHelp(uint id, char *params) { enum Flag { BIT(Multiline), - BIT(Restricted), + BIT(Restrict), + BIT(Kiosk), }; static const struct Handler { @@ -485,37 +490,37 @@ static const struct Handler { { "/away", commandAway, 0 }, { "/ban", commandBan, 0 }, { "/close", commandClose, 0 }, - { "/copy", commandCopy, Restricted }, + { "/copy", commandCopy, Restrict | Kiosk }, { "/cs", commandCS, 0 }, - { "/debug", commandDebug, Restricted }, + { "/debug", commandDebug, Kiosk }, { "/deop", commandDeop, 0 }, { "/devoice", commandDevoice, 0 }, { "/except", commandExcept, 0 }, - { "/exec", commandExec, Multiline | Restricted }, - { "/help", commandHelp, 0 }, + { "/exec", commandExec, Multiline | Restrict }, + { "/help", commandHelp, 0 }, // Restrict special case. { "/highlight", commandHighlight, 0 }, { "/ignore", commandIgnore, 0 }, { "/invex", commandInvex, 0 }, { "/invite", commandInvite, 0 }, - { "/join", commandJoin, Restricted }, + { "/join", commandJoin, Kiosk }, { "/kick", commandKick, 0 }, - { "/list", commandList, 0 }, + { "/list", commandList, Kiosk }, { "/me", commandMe, 0 }, { "/mode", commandMode, 0 }, { "/move", commandMove, 0 }, - { "/msg", commandMsg, Multiline | Restricted }, + { "/msg", commandMsg, Multiline | Kiosk }, { "/names", commandNames, 0 }, { "/nick", commandNick, 0 }, { "/notice", commandNotice, Multiline }, { "/ns", commandNS, 0 }, - { "/o", commandOpen, Restricted }, + { "/o", commandOpen, Restrict | Kiosk }, { "/op", commandOp, 0 }, - { "/open", commandOpen, Restricted }, + { "/open", commandOpen, Restrict | Kiosk }, { "/ops", commandOps, 0 }, - { "/part", commandPart, 0 }, - { "/query", commandQuery, Restricted }, + { "/part", commandPart, Kiosk }, + { "/query", commandQuery, Kiosk }, { "/quit", commandQuit, 0 }, - { "/quote", commandQuote, Multiline | Restricted }, + { "/quote", commandQuote, Multiline | Kiosk }, { "/say", commandPrivmsg, Multiline }, { "/setname", commandSetname, 0 }, { "/topic", commandTopic, 0 }, @@ -584,8 +589,11 @@ void command(uint id, char *input) { uiFormat(id, Warm, NULL, "No such command %s", cmd); return; } - if (self.restricted && handler->flags & Restricted) { - uiFormat(id, Warm, NULL, "Command %s is restricted", cmd); + if ( + (self.restricted && handler->flags & Restrict) || + (self.kiosk && handler->flags & Kiosk) + ) { + uiFormat(id, Warm, NULL, "Command %s is unavailable", cmd); return; } -- cgit 1.4.1