xref: /aosp_15_r20/external/mtools/privileges.c (revision d5c9a868b113e0ec0db2f27bc2ce8a253e77c4b0)
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