blob: b055003aa26501224eec340faf1951caf15c5f37 [file] [log] [blame]
Alistair Delvabeaee832021-02-24 11:27:23 -08001/* 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 UNUSEDP)
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 easier, 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 * across 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 != ruid) {
178 unsetenv("SOURCE_DATE_EPOCH");
179 }
180 if(euid == 0 && ruid != 0) {
181#ifdef HAVE_SETEUID
182 setuid(0); /* set real uid to 0 */
183#else
184#ifndef HAVE_SETRESUID
185 /* on this machine, it is not possible to reversibly drop
186 * root privileges. We print an error and quit */
187
188 /* BEOS is no longer a special case, as both euid and ruid
189 * return 0, and thus we do not get any longer into this
190 * branch */
191 fprintf(stderr,
192 "Seteuid call not supported on this architecture.\n");
193 fprintf(stderr,
194 "Mtools cannot be installed setuid root.\n");
195 fprintf(stderr,
196 "However, it can be installed setuid to a non root");
197 fprintf(stderr,
198 "user or setgid to any id.\n");
199 exit(1);
200#endif
201#endif
202 }
Yi Kong39bbd962022-01-09 19:41:38 +0800203
Alistair Delvabeaee832021-02-24 11:27:23 -0800204 drop_privs();
205 print_privs("after init, real should be 0, effective should not ");
206}
207
208void closeExec(int fd)
209{
210#ifdef F_SETFD
211 fcntl(fd, F_SETFD, 1);
212#endif
213}
214#endif