commit - d33ca522cdea5d420643c2c92a67db48764a0fc4
commit + 623876e175a9cf09a7b7ab0a3985568c9b2ccd4c
blob - 3a6e8b483b30f62b49005802d2f385998ec37933
blob + 6784fedcebbb5db7098941123eb6c458f50cb51d
--- Makefile
+++ Makefile
DPADD= ${LIBCRYPTO} ${LIBUTIL}
BINDIR= /usr/local/bin
-BINOWN= nobody
-BINGRP= nobody
-BINMODE=6555
.include <bsd.prog.mk>
blob - 2cf1a309829ca5ed8bb8eb9ac2f138fc5f878f97
blob + 3982f1c40bea3e8c22ae322eb71aee6849e3b6d7
--- ochat.c
+++ ochat.c
* Both sides run "ochat peer-address". Each tries to connect once:
* if the peer is not up yet, it listens instead and accepts only the
* peer. One process, one TCP connection, no files, no logs. Pledges
- * down to "stdio tty" before any byte from the peer is parsed.
- *
- * Always runs as nobody, whoever starts it: install it setuid and
- * setgid nobody (mode 6555), and the very first thing it does is
- * set real, effective and saved ids to nobody. Started as root, it
- * also chroots to /var/empty and drops supplementary groups.
+ * down to "stdio" before any byte from the peer is parsed.
*/
#include <sys/types.h>
#include <err.h>
#include <errno.h>
#include <poll.h>
-#include <pwd.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
static void cleanup(void);
static void sighandler(int);
-static void droppriv(void);
static int netconnect(const struct sockaddr_in *);
static int netaccept(const struct sockaddr_in *);
static size_t readpass(void);
int ch, init, on = 1, port = PORT, s;
size_t passlen;
- droppriv();
-
while ((ch = getopt(argc, argv, "lp:")) != -1) {
switch (ch) {
case 'p':
err(1, "setsockopt");
fprintf(stderr, "connected to %s\n", argv[0]);
- if (pledge("stdio tty", NULL) == -1)
+ if (pledge("stdio", NULL) == -1)
err(1, "pledge");
proto_handshake(s, init, pass, passlen, sas, sizeof(sas));
_exit(128 + sig);
}
-/*
- * Become nobody for good. From a setuid/setgid nobody binary the
- * effective and saved ids already are nobody, so an unprivileged
- * setresuid/setresgid may copy them into the real ids too. Root
- * can do it outright, plus chroot and setgroups.
- */
-static void
-droppriv(void)
-{
- struct passwd *pw;
- uid_t uid;
- gid_t gid;
-
- if ((pw = getpwnam("nobody")) == NULL)
- errx(1, "no such user: nobody");
- uid = pw->pw_uid;
- gid = pw->pw_gid;
-
- if (geteuid() == 0) {
- if (chroot("/var/empty") == -1 || chdir("/") == -1)
- err(1, "chroot");
- if (setgroups(1, &gid) == -1)
- err(1, "setgroups");
- } else if (geteuid() != uid) {
- errx(1, "Not running as nobody: the setuid bit was ignored. "
- "Install under /usr/local (doas make install) and run it "
- "from there; /home, /tmp, and /var are mounted nosuid.");
- }
-
- if (setresgid(gid, gid, gid) == -1 || setresuid(uid, uid, uid) == -1)
- errx(1, "cannot become nobody: install ochat setuid and "
- "setgid nobody (chown nobody:nobody, chmod 6555)");
-
- if (getuid() != uid || geteuid() != uid || getgid() != gid || getegid() != gid)
- errx(1, "failed to become nobody");
-
- /* We do pledge, which grants no file access at all, later, but still. */
- if (unveil("/", "") == -1 || unveil(NULL, NULL) == -1)
- err(1, "unveil");
-}
-
/* Try once. Refused means the peer is not up yet: return -1. */
static int
netconnect(const struct sockaddr_in *peer)