diff options
Diffstat (limited to 'privileges.c')
-rw-r--r-- | privileges.c | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/privileges.c b/privileges.c new file mode 100644 index 0000000..c2f5c74 --- /dev/null +++ b/privileges.c @@ -0,0 +1,211 @@ +/* Copyright 1997,1999,2001,2002,2007,2009 Alain Knaff. + * This file is part of mtools. + * + * Mtools is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Mtools is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Mtools. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "sysincludes.h" +#include "msdos.h" +#include "mtools.h" + +int noPrivileges=0; + +#ifdef OS_mingw32msvc +void reclaim_privs(void) +{ +} + +void drop_privs(void) +{ +} + +void destroy_privs(void) +{ +} + +uid_t get_real_uid(void) +{ + return 0; +} + +void init_privs(void) +{ +} + +void closeExec(int fd) +{ +} + +#else +/*#define PRIV_DEBUG*/ + +#if 0 +#undef HAVE_SETEUID +#define HAVE_SETRESUID +#include <asm/unistd.h> +int setresuid(int a, int b, int c) +{ + syscall(164, a, b, c); + +} +#endif + +static __inline__ void print_privs(const char *message) +{ +#ifdef PRIV_DEBUG + /* for debugging purposes only */ + fprintf(stderr,"%s egid=%d rgid=%d\n", message, getegid(), getgid()); + fprintf(stderr,"%s euid=%d ruid=%d\n", message, geteuid(), getuid()); +#endif +} + + +static gid_t rgid, egid; +static uid_t ruid, euid; + +/* privilege management routines for SunOS and Solaris. These are + * needed in order to issue raw SCSI read/write ioctls. Mtools drops + * its privileges at the beginning, and reclaims them just for the + * above-mentioned ioctl's. Before popen(), exec() or system, it + * drops its privileges completely, and issues a warning. + */ + + +/* group id handling is lots easyer, as long as we don't use group 0. + * If you want to use group id's, create a *new* group mtools or + * floppy. Chgrp any devices that you only want to be accessible to + * mtools to this group, and give them the appropriate privs. Make + * sure this group doesn't own any other files: be aware that any user + * with access to mtools may mformat these files! + */ + + +static __inline__ void Setuid(uid_t uid) +{ +#if defined HAVE_SETEUID || defined HAVE_SETRESUID + if(euid == 0) { +#ifdef HAVE_SETEUID + seteuid(uid); +#else + setresuid(ruid, uid, euid); +#endif + } else +#endif + setuid(uid); +} + +/* In reclaim_privs and drop privs, we have to manipulate group privileges + * when having no root privileges, else we might lose them */ + +void reclaim_privs(void) +{ + if(noPrivileges) + return; + setgid(egid); + Setuid(euid); + print_privs("after reclaim privs, both uids should be 0 "); +} + +void drop_privs(void) +{ + Setuid(ruid); + setgid(rgid); + print_privs("after drop_privs, real should be 0, effective should not "); +} + +void destroy_privs(void) +{ + +#if defined HAVE_SETEUID || defined HAVE_SETRESUID + if(euid == 0) { +#ifdef HAVE_SETEUID + setuid(0); /* get the necessary privs to drop real root id */ + setuid(ruid); /* this should be enough to get rid of the three + * ids */ + seteuid(ruid); /* for good measure... just in case we came + * accross a system which implemented sane + * semantics instead of POSIXly broken + * semantics for setuid */ +#else + setresuid(ruid, ruid, ruid); +#endif + } +#endif + + /* we also destroy group privileges */ + drop_privs(); + + /* saved set [ug]id will go away by itself on exec */ + + print_privs("destroy_privs, no uid should be zero "); +} + + +uid_t get_real_uid(void) +{ + return ruid; +} + +void init_privs(void) +{ + euid = geteuid(); + ruid = getuid(); + egid = getegid(); + rgid = getgid(); + +#ifndef F_SETFD + if(euid != ruid) { + fprintf(stderr, + "Setuid installation not supported on this platform\n"); + fprintf(stderr, + "Missing F_SETFD"); + exit(1); + } +#endif + + if(euid == 0 && ruid != 0) { +#ifdef HAVE_SETEUID + setuid(0); /* set real uid to 0 */ +#else +#ifndef HAVE_SETRESUID + /* on this machine, it is not possible to reversibly drop + * root privileges. We print an error and quit */ + + /* BEOS is no longer a special case, as both euid and ruid + * return 0, and thus we do not get any longer into this + * branch */ + fprintf(stderr, + "Seteuid call not supported on this architecture.\n"); + fprintf(stderr, + "Mtools cannot be installed setuid root.\n"); + fprintf(stderr, + "However, it can be installed setuid to a non root"); + fprintf(stderr, + "user or setgid to any id.\n"); + exit(1); +#endif +#endif + } + + drop_privs(); + print_privs("after init, real should be 0, effective should not "); +} + +void closeExec(int fd) +{ +#ifdef F_SETFD + fcntl(fd, F_SETFD, 1); +#endif +} +#endif |