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
22 int noPrivileges=0;
23
24 #ifdef OS_mingw32msvc
reclaim_privs(void)25 void reclaim_privs(void)
26 {
27 }
28
drop_privs(void)29 void drop_privs(void)
30 {
31 }
32
destroy_privs(void)33 void destroy_privs(void)
34 {
35 }
36
get_real_uid(void)37 uid_t get_real_uid(void)
38 {
39 return 0;
40 }
41
init_privs(void)42 void init_privs(void)
43 {
44 }
45
closeExec(int fd)46 void 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>
57 int setresuid(int a, int b, int c)
58 {
59 syscall(164, a, b, c);
60
61 }
62 #endif
63
print_privs(const char * message UNUSEDP)64 static __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
74 static gid_t rgid, egid;
75 static 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
Setuid(uid_t uid)94 static __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
reclaim_privs(void)111 void 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
drop_privs(void)120 void 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
destroy_privs(void)127 void 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
get_real_uid(void)155 uid_t get_real_uid(void)
156 {
157 return ruid;
158 }
159
init_privs(void)160 void 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 }
203
204 drop_privs();
205 print_privs("after init, real should be 0, effective should not ");
206 }
207
closeExec(int fd)208 void closeExec(int fd)
209 {
210 #ifdef F_SETFD
211 fcntl(fd, F_SETFD, 1);
212 #endif
213 }
214 #endif
215