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