Imported Upstream version 1.1.11
[platform/upstream/cdrkit.git] / icedax / setuid.c
1 /*
2  * This file has been modified for the cdrkit suite.
3  *
4  * The behaviour and appearence of the program code below can differ to a major
5  * extent from the version distributed by the original author(s).
6  *
7  * For details, see Changelog file distributed with the cdrkit package. If you
8  * received this file from another source then ask the distributing person for
9  * a log of modifications.
10  *
11  */
12
13 /* @(#)setuid.c 1.11 06/02/19 Copyright 1998,1999,2004 Heiko Eissfeldt, Copyright 2004-2006 J. Schilling */
14 /* Security functions by zblaxell
15
16    If these functions fail, it is because there was an installation error
17    or a programming error, and we can't be sure about what privileges
18    we do or do not have.  This means we might not be able to recover
19    the privileges we need to fix anything that may be broken (e.g. the
20    CDDA state of some interface types), and we may in fact do something
21    quite dangerous (like write to the WAV file as root).
22
23    In any case, it is unsafe to do anything but exit *now*.  Ideally we'd
24    kill -9 our process group too, just to be sure.  Root privileges are not
25    something you want floating around at random in user-level applications.
26
27    If any signal handlers or child processes are introduced into this
28    program, it will be necessary to call dontneedroot() or neverneedroot()
29    on entry, respectively; otherwise, it will be possible to trick
30    the program into executing the signal handler or child process with
31    root privileges by sending signals at the right time.
32  */
33
34 #include "config.h"
35 #include <unixstd.h>
36 #include <stdio.h>
37 #include <stdxlib.h>
38
39 #include "exitcodes.h"
40 #include "setuid.h"
41
42 /*#undef DEBUG*/
43 /*#define DEBUG*/
44
45 /* True at return from initsecurity */
46 static uid_t real_uid = (uid_t) (-1);
47 static uid_t effective_uid = (uid_t) (-1);
48 static gid_t real_gid = (gid_t) (-1);
49 static gid_t effective_gid = (gid_t) (-1);
50
51 /* Run this at the beginning of the program to initialize this code and
52    to drop privileges before someone uses them to shoot us in the foot.
53    Do not pass(go), do not dollars += 200. */
54
55 void initsecurity()
56 {
57     int leffective_uid;
58
59     alarm(0);                   /* can be inherited from parent process */
60     real_uid = getuid();
61     leffective_uid = geteuid();
62     if ((int) real_uid != leffective_uid && leffective_uid != 0) { /* sanity check */
63         fprintf(stderr, "Warning: setuid but not to root (uid=%ld, euid=%d)\n", (long) real_uid, leffective_uid);
64         fprintf(stderr, "Dropping setuid privileges now.\n");
65         neverneedroot();
66     } else {
67         effective_uid = leffective_uid;
68     }
69     real_gid = getgid();
70     effective_gid = getegid();
71     dontneedroot();
72     dontneedgroup();
73 }
74
75 /* Temporarily gain root privileges. */
76
77 #if defined _POSIX_SAVED_IDS && defined (HAVE_SETEUID) && defined SCO
78 /* SCO seems to lack the prototypes... */
79 int     seteuid(uid_t euid);
80 int     setegid(gid_t guid);
81 #endif
82
83 void needroot(int necessary)
84 {
85 #ifdef DEBUG
86     fprintf(stderr, "call to     needroot (_euid_=%d, uid=%d), current=%d/%d, pid=%d\n",
87                         effective_uid, real_uid, geteuid(), getuid(), getpid());
88 #endif
89     if (effective_uid) {
90         if (necessary) {
91           fprintf(stderr, "Fatal error:  require root privilege but not setuid root.\n");
92           exit(PERM_ERROR);
93         } else
94           return;
95     }
96     if (real_uid == (uid_t) (-1)) {
97         fprintf(stderr, "Fatal error:  initsecurity() not called.\n");
98         exit(INTERNAL_ERROR);
99     }
100
101     if (geteuid() == 0) return; /* nothing to do */
102
103 #if defined _POSIX_SAVED_IDS && defined (HAVE_SETEUID)
104     if (seteuid(effective_uid)) {
105         perror("seteuid in needroot()");
106         exit(PERM_ERROR);
107     }
108 #else
109 #if defined (HAVE_SETREUID)
110     if (setreuid(real_uid, effective_uid)) {
111         perror("setreuid in needroot()");
112         exit(PERM_ERROR);
113     }
114 #endif
115 #endif
116     if (geteuid() != 0 && necessary) {
117         fprintf(stderr, "Fatal error:  did not get root privilege.\n");
118         exit(PERM_ERROR);
119     }
120 #ifdef DEBUG
121     fprintf(stderr, "exit of     needroot (_euid_=%d, uid=%d), current=%d/%d, pid=%d\n",
122                         effective_uid, real_uid, geteuid(), getuid(), getpid());
123 #endif
124 }
125
126 /* Temporarily drop root privileges.  */
127
128 void dontneedroot()
129 {
130 #ifdef DEBUG
131     fprintf(stderr, "call to dontneedroot (_euid_=%d, uid=%d), current=%d/%d, pid=%d\n",
132                         effective_uid, real_uid, geteuid(), getuid(), getpid());
133 #endif
134     if (real_uid == (uid_t) (-1)) {
135         fprintf(stderr, "Fatal error:  initsecurity() not called.\n");
136         exit(INTERNAL_ERROR);
137     }
138     if (effective_uid)
139         return;
140     if (geteuid() != 0) return; /* nothing to do */
141
142 #if defined _POSIX_SAVED_IDS && defined (HAVE_SETEUID)
143     if (seteuid(real_uid)) {
144         perror("seteuid in dontneedroot()");
145         exit(PERM_ERROR);
146     }
147 #else
148 #if defined (HAVE_SETREUID)
149     if (setreuid(effective_uid, real_uid)) {
150         perror("setreuid in dontneedroot()");
151         exit(PERM_ERROR);
152     }
153 #endif
154 #endif
155     if (geteuid() != real_uid) {
156         fprintf(stderr, "Fatal error:  did not drop root privilege.\n");
157 #ifdef DEBUG
158     fprintf(stderr, "in   to dontneedroot (_euid_=%d, uid=%d), current=%d/%d, pid=%d\n",
159                         effective_uid, real_uid, geteuid(), getuid(), getpid());
160 #endif
161         exit(PERM_ERROR);
162     }
163 }
164
165 /* Permanently drop root privileges.  */
166
167 void neverneedroot()
168 {
169 #ifdef DEBUG
170     fprintf(stderr, "call to neverneedroot (_euid_=%d, uid=%d), current=%d/%d, pid=%d\n",
171                         effective_uid, real_uid, geteuid(), getuid(), getpid());
172 #endif
173     if (real_uid == (uid_t) (-1)) {
174         fprintf(stderr, "Fatal error:  initsecurity() not called.\n");
175         exit(INTERNAL_ERROR);
176     }
177     if (geteuid() == effective_uid) {
178 #if defined (HAVE_SETUID)
179       if (setuid(real_uid)) {
180         perror("setuid in neverneedroot()");
181         exit(PERM_ERROR);
182       }
183 #endif
184     }
185 #if     defined(__FreeBSD__) || defined(__DragonFly__)  /* XXX this is a big hack and and not a permanent solution */
186     else {
187 #if defined (HAVE_SETUID)
188         if (setuid(real_uid)) {
189                 perror("setuid in neverneedroot()");
190                 exit(PERM_ERROR);
191         }
192 #endif
193     }
194 #endif
195     if (geteuid() != real_uid || getuid() != real_uid) {
196         fprintf(stderr, "Fatal error:  did not drop root privilege.\n");
197 #ifdef DEBUG
198     fprintf(stderr, "in  to neverneedroot (_euid_=%d, uid=%d), current=%d/%d, pid=%d\n",
199                         effective_uid, real_uid, geteuid(), getuid(), getpid());
200 #endif
201         exit(PERM_ERROR);
202     }
203     effective_uid = real_uid;
204 #ifdef DEBUG
205     fprintf(stderr, "exit of neverneedroot (_euid_=%d, uid=%d), current=%d/%d, pid=%d\n",
206                         effective_uid, real_uid, geteuid(), getuid(), getpid());
207 #endif
208 }
209
210 /* Temporarily gain group privileges. */
211
212 void needgroup(int necessary)
213 {
214 #ifdef DEBUG
215     fprintf(stderr, "call to     needgroup (egid=%d, gid=%d), current=%d/%d, pid=%d\n",
216                         effective_gid, real_gid, getegid(), getgid(), getpid());
217 #endif
218     if (real_gid == (gid_t) (-1)) {
219         fprintf(stderr, "Fatal error:  initsecurity() not called.\n");
220         exit(INTERNAL_ERROR);
221     }
222
223     if (getegid() == effective_gid) return; /* nothing to do */
224
225 #if defined _POSIX_SAVED_IDS && defined (HAVE_SETEGID)
226     if (setegid(effective_gid)) {
227         perror("setegid in needgroup()");
228         exit(PERM_ERROR);
229     }
230 #else
231 #if defined (HAVE_SETREGID)
232     if (setregid(real_gid, effective_gid)) {
233         perror("setregid in needgroup()");
234         exit(PERM_ERROR);
235     }
236 #endif
237 #endif
238     if (necessary && getegid() != effective_gid) {
239         fprintf(stderr, "Fatal error:  did not get group privilege.\n");
240         exit(PERM_ERROR);
241     }
242 }
243
244 /* Temporarily drop group privileges.  */
245
246 void dontneedgroup()
247 {
248 #ifdef DEBUG
249     fprintf(stderr, "call to dontneedgroup (egid=%d, gid=%d), current=%d/%d, pid=%d\n",
250                         effective_gid, real_gid, getegid(), getgid(), getpid());
251 #endif
252     if (real_gid == (gid_t) (-1)) {
253         fprintf(stderr, "Fatal error:  initsecurity() not called.\n");
254         exit(INTERNAL_ERROR);
255     }
256     if (getegid() != effective_gid) return; /* nothing to do */
257 #if defined _POSIX_SAVED_IDS && defined (HAVE_SETEGID)
258     if (setegid(real_gid)) {
259         perror("setegid in dontneedgroup()");
260         exit(PERM_ERROR);
261     }
262 #else
263 #if defined (HAVE_SETREGID)
264     if (setregid(effective_gid, real_gid)) {
265         perror("setregid in dontneedgroup()");
266         exit(PERM_ERROR);
267     }
268 #endif
269 #endif
270     if (getegid() != real_gid) {
271         fprintf(stderr, "Fatal error:  did not drop group privilege.\n");
272         exit(PERM_ERROR);
273     }
274 #ifdef DEBUG
275     fprintf(stderr, "exit if dontneedgroup (egid=%d, gid=%d), current=%d/%d, pid=%d\n",
276                         effective_gid, real_gid, getegid(), getgid(), getpid());
277 #endif
278 }
279
280 /* Permanently drop group privileges.  */
281
282 void neverneedgroup()
283 {
284 #ifdef DEBUG
285     fprintf(stderr, "call to neverneedgroup (egid=%d, gid=%d), current=%d/%d, pid=%d\n",
286                         effective_gid, real_gid, getegid(), getgid(), getpid());
287 #endif
288     if (real_gid == (gid_t) (-1)) {
289         fprintf(stderr, "Fatal error:  initsecurity() not called.\n");
290         exit(INTERNAL_ERROR);
291     }
292     if (getegid() == effective_gid) {
293 #if defined (HAVE_SETGID)
294       if (setgid(real_gid)) {
295           perror("setgid in neverneedgroup()");
296           exit(PERM_ERROR);
297       }
298 #endif
299     }
300 #if     defined(__FreeBSD__) || defined(__DragonFly__)  /* XXX this is a big hack and and not a permanent solution */
301     else {
302 #if defined (HAVE_SETGID)
303         if (setgid(real_gid)) {
304                 perror("setgid in neverneedgroup()");
305                 exit(PERM_ERROR);
306         }
307 #endif
308     }
309 #endif
310     if (getegid() != real_gid || getgid() != real_gid) {
311         fprintf(stderr, "Fatal error:  did not drop group privilege.\n");
312         exit(PERM_ERROR);
313     }
314     effective_gid = real_gid;
315 }
316
317 #if defined (HPUX)
318 int seteuid(uid_t uid)
319 {
320   return setresuid(-1, uid, -1);
321 }
322
323 int setreuid(uid_t uid1, uid_t uid2)
324 {
325   return setresuid(uid2, uid2, uid1 == uid2 ? uid2 : 0);
326 }
327
328 int setregid(gid_t gid1, gid_t gid2)
329 {
330   return setresgid(gid2, gid2, gid1 == gid2 ? gid2 : 0);
331 }
332 #endif