/*1* Copyright (c) 2010-2014, Simon Schubert <[email protected]>.2* Copyright (c) 2008 The DragonFly Project. All rights reserved.3*4* This code is derived from software contributed to The DragonFly Project5* by Simon Schubert <[email protected]>.6*7* Redistribution and use in source and binary forms, with or without8* modification, are permitted provided that the following conditions9* are met:10*11* 1. Redistributions of source code must retain the above copyright12* notice, this list of conditions and the following disclaimer.13* 2. Redistributions in binary form must reproduce the above copyright14* notice, this list of conditions and the following disclaimer in15* the documentation and/or other materials provided with the16* distribution.17* 3. Neither the name of The DragonFly Project nor the names of its18* contributors may be used to endorse or promote products derived19* from this software without specific, prior written permission.20*21* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS22* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT23* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS24* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE25* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,26* INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,27* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;28* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED29* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,30* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT31* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF32* SUCH DAMAGE.33*/3435/*36* This binary is setuid root. Use extreme caution when touching37* user-supplied information. Keep the root window as small as possible.38*/3940#ifdef __FreeBSD__41#define USE_CAPSICUM 142#endif4344#include <sys/param.h>45#if USE_CAPSICUM46#include <sys/capsicum.h>47#endif48#include <sys/stat.h>4950#include <capsicum_helpers.h>51#include <err.h>52#include <errno.h>53#include <fcntl.h>54#include <grp.h>55#include <paths.h>56#include <pwd.h>57#include <stdio.h>58#include <string.h>59#include <syslog.h>60#include <unistd.h>6162#include "dma.h"636465static void66logfail(int exitcode, const char *fmt, ...)67{68int oerrno = errno;69va_list ap;70char outs[1024];7172outs[0] = 0;73if (fmt != NULL) {74va_start(ap, fmt);75vsnprintf(outs, sizeof(outs), fmt, ap);76va_end(ap);77}7879errno = oerrno;80if (*outs != 0)81syslog(LOG_ERR, errno ? "%s: %m" : "%s", outs);82else83syslog(LOG_ERR, errno ? "%m" : "unknown error");8485exit(exitcode);86}8788/*89* Create a mbox in /var/mail for a given user, or make sure90* the permissions are correct for dma.91*/9293int94main(int argc, char **argv)95{96#if USE_CAPSICUM97cap_rights_t rights;98#endif99const char *user;100struct passwd *pw;101struct group *gr;102uid_t user_uid;103gid_t mail_gid;104int f, maildirfd;105106/*107* Open log fd now for capability sandbox.108*/109openlog("dma-mbox-create", LOG_NDELAY, LOG_MAIL);110111errno = 0;112gr = getgrnam(DMA_GROUP);113if (!gr)114logfail(EX_CONFIG, "cannot find dma group `%s'", DMA_GROUP);115116mail_gid = gr->gr_gid;117118if (setgid(mail_gid) != 0)119logfail(EX_NOPERM, "cannot set gid to %d (%s)", mail_gid, DMA_GROUP);120if (getegid() != mail_gid)121logfail(EX_NOPERM, "cannot set gid to %d (%s), still at %d", mail_gid, DMA_GROUP, getegid());122123/*124* We take exactly one argument: the username.125*/126if (argc != 2) {127errno = 0;128logfail(EX_USAGE, "no arguments");129}130user = argv[1];131132syslog(LOG_NOTICE, "creating mbox for `%s'", user);133134/* the username may not contain a pathname separator */135if (strchr(user, '/')) {136errno = 0;137logfail(EX_DATAERR, "path separator in username `%s'", user);138exit(1);139}140141/* verify the user exists */142errno = 0;143pw = getpwnam(user);144if (!pw)145logfail(EX_NOUSER, "cannot find user `%s'", user);146147maildirfd = open(_PATH_MAILDIR, O_RDONLY);148if (maildirfd < 0)149logfail(EX_NOINPUT, "cannot open maildir %s", _PATH_MAILDIR);150151/*152* Cache NLS data, for strerror, for err(3), before entering capability153* mode.154*/155caph_cache_catpages();156157/*158* Cache local time before entering Capsicum capability sandbox.159*/160caph_cache_tzdata();161162#if USE_CAPSICUM163cap_rights_init(&rights, CAP_CREATE, CAP_FCHMOD, CAP_FCHOWN,164CAP_LOOKUP, CAP_READ);165if (cap_rights_limit(maildirfd, &rights) < 0 && errno != ENOSYS)166err(EX_OSERR, "can't limit maildirfd rights");167168/* Enter Capsicum capability sandbox */169if (caph_enter() < 0)170err(EX_OSERR, "cap_enter");171#endif172173user_uid = pw->pw_uid;174175f = openat(maildirfd, user, O_RDONLY|O_CREAT|O_NOFOLLOW, 0600);176if (f < 0)177logfail(EX_NOINPUT, "cannot open mbox `%s'", user);178179if (fchown(f, user_uid, mail_gid))180logfail(EX_OSERR, "cannot change owner of mbox `%s'", user);181182if (fchmod(f, 0620))183logfail(EX_OSERR, "cannot change permissions of mbox `%s'",184user);185186/* file should be present with the right owner and permissions */187188syslog(LOG_NOTICE, "successfully created mbox for `%s'", user);189190return (0);191}192193194