1/* Copyright 1997,1999,2001,2002,2007,2009 Alain Knaff. 2 * This file is part of mtools. 3 * 4 * Mtools is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * Mtools is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with Mtools. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18#include "sysincludes.h" 19#include "msdos.h" 20#include "mtools.h" 21 22int noPrivileges=0; 23 24#ifdef OS_mingw32msvc 25void reclaim_privs(void) 26{ 27} 28 29void drop_privs(void) 30{ 31} 32 33void destroy_privs(void) 34{ 35} 36 37uid_t get_real_uid(void) 38{ 39 return 0; 40} 41 42void init_privs(void) 43{ 44} 45 46void closeExec(int fd) 47{ 48} 49 50#else 51/*#define PRIV_DEBUG*/ 52 53#if 0 54#undef HAVE_SETEUID 55#define HAVE_SETRESUID 56#include <asm/unistd.h> 57int setresuid(int a, int b, int c) 58{ 59 syscall(164, a, b, c); 60 61} 62#endif 63 64static __inline__ void print_privs(const char *message) 65{ 66#ifdef PRIV_DEBUG 67 /* for debugging purposes only */ 68 fprintf(stderr,"%s egid=%d rgid=%d\n", message, getegid(), getgid()); 69 fprintf(stderr,"%s euid=%d ruid=%d\n", message, geteuid(), getuid()); 70#endif 71} 72 73 74static gid_t rgid, egid; 75static uid_t ruid, euid; 76 77/* privilege management routines for SunOS and Solaris. These are 78 * needed in order to issue raw SCSI read/write ioctls. Mtools drops 79 * its privileges at the beginning, and reclaims them just for the 80 * above-mentioned ioctl's. Before popen(), exec() or system, it 81 * drops its privileges completely, and issues a warning. 82 */ 83 84 85/* group id handling is lots easyer, as long as we don't use group 0. 86 * If you want to use group id's, create a *new* group mtools or 87 * floppy. Chgrp any devices that you only want to be accessible to 88 * mtools to this group, and give them the appropriate privs. Make 89 * sure this group doesn't own any other files: be aware that any user 90 * with access to mtools may mformat these files! 91 */ 92 93 94static __inline__ void Setuid(uid_t uid) 95{ 96#if defined HAVE_SETEUID || defined HAVE_SETRESUID 97 if(euid == 0) { 98#ifdef HAVE_SETEUID 99 seteuid(uid); 100#else 101 setresuid(ruid, uid, euid); 102#endif 103 } else 104#endif 105 setuid(uid); 106} 107 108/* In reclaim_privs and drop privs, we have to manipulate group privileges 109 * when having no root privileges, else we might lose them */ 110 111void reclaim_privs(void) 112{ 113 if(noPrivileges) 114 return; 115 setgid(egid); 116 Setuid(euid); 117 print_privs("after reclaim privs, both uids should be 0 "); 118} 119 120void drop_privs(void) 121{ 122 Setuid(ruid); 123 setgid(rgid); 124 print_privs("after drop_privs, real should be 0, effective should not "); 125} 126 127void destroy_privs(void) 128{ 129 130#if defined HAVE_SETEUID || defined HAVE_SETRESUID 131 if(euid == 0) { 132#ifdef HAVE_SETEUID 133 setuid(0); /* get the necessary privs to drop real root id */ 134 setuid(ruid); /* this should be enough to get rid of the three 135 * ids */ 136 seteuid(ruid); /* for good measure... just in case we came 137 * accross a system which implemented sane 138 * semantics instead of POSIXly broken 139 * semantics for setuid */ 140#else 141 setresuid(ruid, ruid, ruid); 142#endif 143 } 144#endif 145 146 /* we also destroy group privileges */ 147 drop_privs(); 148 149 /* saved set [ug]id will go away by itself on exec */ 150 151 print_privs("destroy_privs, no uid should be zero "); 152} 153 154 155uid_t get_real_uid(void) 156{ 157 return ruid; 158} 159 160void init_privs(void) 161{ 162 euid = geteuid(); 163 ruid = getuid(); 164 egid = getegid(); 165 rgid = getgid(); 166 167#ifndef F_SETFD 168 if(euid != ruid) { 169 fprintf(stderr, 170 "Setuid installation not supported on this platform\n"); 171 fprintf(stderr, 172 "Missing F_SETFD"); 173 exit(1); 174 } 175#endif 176 177 if(euid == 0 && ruid != 0) { 178#ifdef HAVE_SETEUID 179 setuid(0); /* set real uid to 0 */ 180#else 181#ifndef HAVE_SETRESUID 182 /* on this machine, it is not possible to reversibly drop 183 * root privileges. We print an error and quit */ 184 185 /* BEOS is no longer a special case, as both euid and ruid 186 * return 0, and thus we do not get any longer into this 187 * branch */ 188 fprintf(stderr, 189 "Seteuid call not supported on this architecture.\n"); 190 fprintf(stderr, 191 "Mtools cannot be installed setuid root.\n"); 192 fprintf(stderr, 193 "However, it can be installed setuid to a non root"); 194 fprintf(stderr, 195 "user or setgid to any id.\n"); 196 exit(1); 197#endif 198#endif 199 } 200 201 drop_privs(); 202 print_privs("after init, real should be 0, effective should not "); 203} 204 205void closeExec(int fd) 206{ 207#ifdef F_SETFD 208 fcntl(fd, F_SETFD, 1); 209#endif 210} 211#endif 212