void ssh_sandbox_child(struct ssh_sandbox *box) { struct rlimit rl_zero; cap_rights_t rights; caph_cache_tzdata(); rl_zero.rlim_cur = rl_zero.rlim_max = 0; if (setrlimit(RLIMIT_FSIZE, &rl_zero) == -1) fatal("%s: setrlimit(RLIMIT_FSIZE, { 0, 0 }): %s", __func__, strerror(errno)); #ifndef SANDBOX_SKIP_RLIMIT_NOFILE if (setrlimit(RLIMIT_NOFILE, &rl_zero) == -1) fatal("%s: setrlimit(RLIMIT_NOFILE, { 0, 0 }): %s", __func__, strerror(errno)); #endif if (setrlimit(RLIMIT_NPROC, &rl_zero) == -1) fatal("%s: setrlimit(RLIMIT_NPROC, { 0, 0 }): %s", __func__, strerror(errno)); cap_rights_init(&rights); if (cap_rights_limit(STDIN_FILENO, &rights) < 0 && errno != ENOSYS) fatal("can't limit stdin: %m"); if (cap_rights_limit(STDOUT_FILENO, &rights) < 0 && errno != ENOSYS) fatal("can't limit stdout: %m"); if (cap_rights_limit(STDERR_FILENO, &rights) < 0 && errno != ENOSYS) fatal("can't limit stderr: %m"); cap_rights_init(&rights, CAP_READ, CAP_WRITE); if (cap_rights_limit(box->monitor->m_recvfd, &rights) < 0 && errno != ENOSYS) fatal("%s: failed to limit the network socket", __func__); cap_rights_init(&rights, CAP_WRITE); if (cap_rights_limit(box->monitor->m_log_sendfd, &rights) < 0 && errno != ENOSYS) fatal("%s: failed to limit the logging socket", __func__); if (cap_enter() < 0 && errno != ENOSYS) fatal("%s: failed to enter capability mode", __func__); }
int main(int argc, char **argv) { #if USE_CAPSICUM cap_rights_t rights; #endif const char *user; struct passwd *pw; struct group *gr; uid_t user_uid; gid_t mail_gid; int f, maildirfd; /* * Open log fd now for capability sandbox. */ openlog("dma-mbox-create", LOG_NDELAY, LOG_MAIL); errno = 0; gr = getgrnam(DMA_GROUP); if (!gr) logfail(EX_CONFIG, "cannot find dma group `%s'", DMA_GROUP); mail_gid = gr->gr_gid; if (setgid(mail_gid) != 0) logfail(EX_NOPERM, "cannot set gid to %d (%s)", mail_gid, DMA_GROUP); if (getegid() != mail_gid) logfail(EX_NOPERM, "cannot set gid to %d (%s), still at %d", mail_gid, DMA_GROUP, getegid()); /* * We take exactly one argument: the username. */ if (argc != 2) { errno = 0; logfail(EX_USAGE, "no arguments"); } user = argv[1]; syslog(LOG_NOTICE, "creating mbox for `%s'", user); /* the username may not contain a pathname separator */ if (strchr(user, '/')) { errno = 0; logfail(EX_DATAERR, "path separator in username `%s'", user); exit(1); } /* verify the user exists */ errno = 0; pw = getpwnam(user); if (!pw) logfail(EX_NOUSER, "cannot find user `%s'", user); maildirfd = open(_PATH_MAILDIR, O_RDONLY); if (maildirfd < 0) logfail(EX_NOINPUT, "cannot open maildir %s", _PATH_MAILDIR); /* * Cache NLS data, for strerror, for err(3), before entering capability * mode. */ caph_cache_catpages(); /* * Cache local time before entering Capsicum capability sandbox. */ caph_cache_tzdata(); #if USE_CAPSICUM cap_rights_init(&rights, CAP_CREATE, CAP_FCHMOD, CAP_FCHOWN, CAP_LOOKUP, CAP_READ); if (cap_rights_limit(maildirfd, &rights) < 0 && errno != ENOSYS) err(EX_OSERR, "can't limit maildirfd rights"); /* Enter Capsicum capability sandbox */ if (caph_enter() < 0) err(EX_OSERR, "cap_enter"); #endif user_uid = pw->pw_uid; f = openat(maildirfd, user, O_RDONLY|O_CREAT|O_NOFOLLOW, 0600); if (f < 0) logfail(EX_NOINPUT, "cannot open mbox `%s'", user); if (fchown(f, user_uid, mail_gid)) logfail(EX_OSERR, "cannot change owner of mbox `%s'", user); if (fchmod(f, 0620)) logfail(EX_OSERR, "cannot change permissions of mbox `%s'", user); /* file should be present with the right owner and permissions */ syslog(LOG_NOTICE, "successfully created mbox for `%s'", user); return (0); }