1235679Sadrian/* 2235679Sadrian * Copyright (c) 2010-2014, Simon Schubert <2@0x2c.org>. 3235679Sadrian * Copyright (c) 2008 The DragonFly Project. All rights reserved. 4235679Sadrian * 5235679Sadrian * This code is derived from software contributed to The DragonFly Project 6235679Sadrian * by Simon Schubert <2@0x2c.org>. 7235679Sadrian * 8235679Sadrian * Redistribution and use in source and binary forms, with or without 9235679Sadrian * modification, are permitted provided that the following conditions 10235679Sadrian * are met: 11235679Sadrian * 12235679Sadrian * 1. Redistributions of source code must retain the above copyright 13235679Sadrian * notice, this list of conditions and the following disclaimer. 14235679Sadrian * 2. Redistributions in binary form must reproduce the above copyright 15235679Sadrian * notice, this list of conditions and the following disclaimer in 16235679Sadrian * the documentation and/or other materials provided with the 17235679Sadrian * distribution. 18235679Sadrian * 3. Neither the name of The DragonFly Project nor the names of its 19235679Sadrian * contributors may be used to endorse or promote products derived 20235679Sadrian * from this software without specific, prior written permission. 21235679Sadrian * 22235679Sadrian * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23235679Sadrian * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24235679Sadrian * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 25235679Sadrian * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 26235679Sadrian * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27235679Sadrian * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 28235679Sadrian * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29235679Sadrian * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 30235679Sadrian * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 31235679Sadrian * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 32235679Sadrian * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33235679Sadrian * SUCH DAMAGE. 34235679Sadrian */ 35235679Sadrian 36235679Sadrian/* 37235679Sadrian * This binary is setuid root. Use extreme caution when touching 38235679Sadrian * user-supplied information. Keep the root window as small as possible. 39235679Sadrian */ 40235679Sadrian 41235679Sadrian#include <sys/param.h> 42235679Sadrian#include <sys/stat.h> 43235679Sadrian 44235679Sadrian#include <errno.h> 45235679Sadrian#include <fcntl.h> 46235679Sadrian#include <grp.h> 47235679Sadrian#include <paths.h> 48235679Sadrian#include <pwd.h> 49235679Sadrian#include <stdio.h> 50235679Sadrian#include <syslog.h> 51235679Sadrian#include <unistd.h> 52235679Sadrian 53235679Sadrian#include "dma.h" 54235679Sadrian 55235679Sadrian 56static void 57logfail(int exitcode, const char *fmt, ...) 58{ 59 int oerrno = errno; 60 va_list ap; 61 char outs[1024]; 62 63 outs[0] = 0; 64 if (fmt != NULL) { 65 va_start(ap, fmt); 66 vsnprintf(outs, sizeof(outs), fmt, ap); 67 va_end(ap); 68 } 69 70 errno = oerrno; 71 if (*outs != 0) 72 syslog(LOG_ERR, errno ? "%s: %m" : "%s", outs); 73 else 74 syslog(LOG_ERR, errno ? "%m" : "unknown error"); 75 76 exit(exitcode); 77} 78 79/* 80 * Create a mbox in /var/mail for a given user, or make sure 81 * the permissions are correct for dma. 82 */ 83 84int 85main(int argc, char **argv) 86{ 87 const char *user; 88 struct passwd *pw; 89 struct group *gr; 90 uid_t user_uid; 91 gid_t mail_gid; 92 int error; 93 char fn[PATH_MAX+1]; 94 int f; 95 96 openlog("dma-mbox-create", 0, LOG_MAIL); 97 98 errno = 0; 99 gr = getgrnam(DMA_GROUP); 100 if (!gr) 101 logfail(EX_CONFIG, "cannot find dma group `%s'", DMA_GROUP); 102 103 mail_gid = gr->gr_gid; 104 105 if (setgid(mail_gid) != 0) 106 logfail(EX_NOPERM, "cannot set gid to %d (%s)", mail_gid, DMA_GROUP); 107 if (getegid() != mail_gid) 108 logfail(EX_NOPERM, "cannot set gid to %d (%s), still at %d", mail_gid, DMA_GROUP, getegid()); 109 110 /* 111 * We take exactly one argument: the username. 112 */ 113 if (argc != 2) { 114 errno = 0; 115 logfail(EX_USAGE, "no arguments"); 116 } 117 user = argv[1]; 118 119 syslog(LOG_NOTICE, "creating mbox for `%s'", user); 120 121 /* the username may not contain a pathname separator */ 122 if (strchr(user, '/')) { 123 errno = 0; 124 logfail(EX_DATAERR, "path separator in username `%s'", user); 125 exit(1); 126 } 127 128 /* verify the user exists */ 129 errno = 0; 130 pw = getpwnam(user); 131 if (!pw) 132 logfail(EX_NOUSER, "cannot find user `%s'", user); 133 134 user_uid = pw->pw_uid; 135 136 error = snprintf(fn, sizeof(fn), "%s/%s", _PATH_MAILDIR, user); 137 if (error < 0 || (size_t)error >= sizeof(fn)) { 138 if (error >= 0) { 139 errno = 0; 140 logfail(EX_USAGE, "mbox path too long"); 141 } 142 logfail(EX_CANTCREAT, "cannot build mbox path for `%s/%s'", _PATH_MAILDIR, user); 143 } 144 145 f = open(fn, O_RDONLY|O_CREAT|O_NOFOLLOW, 0600); 146 if (f < 0) 147 logfail(EX_NOINPUT, "cannt open mbox `%s'", fn); 148 149 if (fchown(f, user_uid, mail_gid)) 150 logfail(EX_OSERR, "cannot change owner of mbox `%s'", fn); 151 152 if (fchmod(f, 0620)) 153 logfail(EX_OSERR, "cannot change permissions of mbox `%s'", fn); 154 155 /* file should be present with the right owner and permissions */ 156 157 syslog(LOG_NOTICE, "successfully created mbox for `%s'", user); 158 159 return (0); 160} 161