1262266Sbapt/* 2289123Sbapt * Copyright (c) 2010-2014, Simon Schubert <2@0x2c.org>. 3262266Sbapt * Copyright (c) 2008 The DragonFly Project. All rights reserved. 4262266Sbapt * 5262266Sbapt * This code is derived from software contributed to The DragonFly Project 6289123Sbapt * by Simon Schubert <2@0x2c.org>. 7262266Sbapt * 8262266Sbapt * Redistribution and use in source and binary forms, with or without 9262266Sbapt * modification, are permitted provided that the following conditions 10262266Sbapt * are met: 11262266Sbapt * 12262266Sbapt * 1. Redistributions of source code must retain the above copyright 13262266Sbapt * notice, this list of conditions and the following disclaimer. 14262266Sbapt * 2. Redistributions in binary form must reproduce the above copyright 15262266Sbapt * notice, this list of conditions and the following disclaimer in 16262266Sbapt * the documentation and/or other materials provided with the 17262266Sbapt * distribution. 18262266Sbapt * 3. Neither the name of The DragonFly Project nor the names of its 19262266Sbapt * contributors may be used to endorse or promote products derived 20262266Sbapt * from this software without specific, prior written permission. 21262266Sbapt * 22262266Sbapt * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23262266Sbapt * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24262266Sbapt * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 25262266Sbapt * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 26262266Sbapt * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27262266Sbapt * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 28262266Sbapt * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29262266Sbapt * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 30262266Sbapt * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 31262266Sbapt * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 32262266Sbapt * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33262266Sbapt * SUCH DAMAGE. 34262266Sbapt */ 35262266Sbapt 36262266Sbapt/* 37262266Sbapt * This binary is setuid root. Use extreme caution when touching 38262266Sbapt * user-supplied information. Keep the root window as small as possible. 39262266Sbapt */ 40262266Sbapt 41262266Sbapt#include <sys/param.h> 42262266Sbapt#include <sys/stat.h> 43262266Sbapt 44262266Sbapt#include <errno.h> 45262266Sbapt#include <fcntl.h> 46262266Sbapt#include <grp.h> 47262266Sbapt#include <paths.h> 48262266Sbapt#include <pwd.h> 49262266Sbapt#include <stdio.h> 50262266Sbapt#include <syslog.h> 51262266Sbapt#include <unistd.h> 52262266Sbapt 53262266Sbapt#include "dma.h" 54262266Sbapt 55262266Sbapt 56262266Sbaptstatic void 57289123Sbaptlogfail(int exitcode, const char *fmt, ...) 58262266Sbapt{ 59262266Sbapt int oerrno = errno; 60262266Sbapt va_list ap; 61262266Sbapt char outs[1024]; 62262266Sbapt 63262266Sbapt outs[0] = 0; 64262266Sbapt if (fmt != NULL) { 65262266Sbapt va_start(ap, fmt); 66262266Sbapt vsnprintf(outs, sizeof(outs), fmt, ap); 67262266Sbapt va_end(ap); 68262266Sbapt } 69262266Sbapt 70262266Sbapt errno = oerrno; 71262266Sbapt if (*outs != 0) 72262266Sbapt syslog(LOG_ERR, errno ? "%s: %m" : "%s", outs); 73262266Sbapt else 74262266Sbapt syslog(LOG_ERR, errno ? "%m" : "unknown error"); 75262266Sbapt 76289123Sbapt exit(exitcode); 77262266Sbapt} 78262266Sbapt 79262266Sbapt/* 80262266Sbapt * Create a mbox in /var/mail for a given user, or make sure 81262266Sbapt * the permissions are correct for dma. 82262266Sbapt */ 83262266Sbapt 84262266Sbaptint 85262266Sbaptmain(int argc, char **argv) 86262266Sbapt{ 87262266Sbapt const char *user; 88262266Sbapt struct passwd *pw; 89262266Sbapt struct group *gr; 90262266Sbapt uid_t user_uid; 91262266Sbapt gid_t mail_gid; 92306800Sbapt int f, maildirfd; 93262266Sbapt 94262266Sbapt openlog("dma-mbox-create", 0, LOG_MAIL); 95262266Sbapt 96262266Sbapt errno = 0; 97262266Sbapt gr = getgrnam(DMA_GROUP); 98262266Sbapt if (!gr) 99289123Sbapt logfail(EX_CONFIG, "cannot find dma group `%s'", DMA_GROUP); 100262266Sbapt 101262266Sbapt mail_gid = gr->gr_gid; 102262266Sbapt 103262266Sbapt if (setgid(mail_gid) != 0) 104289123Sbapt logfail(EX_NOPERM, "cannot set gid to %d (%s)", mail_gid, DMA_GROUP); 105262266Sbapt if (getegid() != mail_gid) 106289123Sbapt logfail(EX_NOPERM, "cannot set gid to %d (%s), still at %d", mail_gid, DMA_GROUP, getegid()); 107262266Sbapt 108262266Sbapt /* 109262266Sbapt * We take exactly one argument: the username. 110262266Sbapt */ 111262266Sbapt if (argc != 2) { 112262266Sbapt errno = 0; 113289123Sbapt logfail(EX_USAGE, "no arguments"); 114262266Sbapt } 115262266Sbapt user = argv[1]; 116262266Sbapt 117262266Sbapt syslog(LOG_NOTICE, "creating mbox for `%s'", user); 118262266Sbapt 119262266Sbapt /* the username may not contain a pathname separator */ 120262266Sbapt if (strchr(user, '/')) { 121262266Sbapt errno = 0; 122289123Sbapt logfail(EX_DATAERR, "path separator in username `%s'", user); 123262266Sbapt exit(1); 124262266Sbapt } 125262266Sbapt 126262266Sbapt /* verify the user exists */ 127262266Sbapt errno = 0; 128262266Sbapt pw = getpwnam(user); 129262266Sbapt if (!pw) 130289123Sbapt logfail(EX_NOUSER, "cannot find user `%s'", user); 131262266Sbapt 132306800Sbapt maildirfd = open(_PATH_MAILDIR, O_RDONLY); 133306800Sbapt if (maildirfd < 0) 134306800Sbapt logfail(EX_NOINPUT, "cannot open maildir %s", _PATH_MAILDIR); 135306800Sbapt 136262266Sbapt user_uid = pw->pw_uid; 137262266Sbapt 138306800Sbapt f = openat(maildirfd, user, O_RDONLY|O_CREAT|O_NOFOLLOW, 0600); 139262266Sbapt if (f < 0) 140306800Sbapt logfail(EX_NOINPUT, "cannot open mbox `%s'", user); 141262266Sbapt 142262266Sbapt if (fchown(f, user_uid, mail_gid)) 143306800Sbapt logfail(EX_OSERR, "cannot change owner of mbox `%s'", user); 144262266Sbapt 145262266Sbapt if (fchmod(f, 0620)) 146306800Sbapt logfail(EX_OSERR, "cannot change permissions of mbox `%s'", 147306800Sbapt user); 148262266Sbapt 149262266Sbapt /* file should be present with the right owner and permissions */ 150262266Sbapt 151262266Sbapt syslog(LOG_NOTICE, "successfully created mbox for `%s'", user); 152262266Sbapt 153262266Sbapt return (0); 154262266Sbapt} 155