util_sec.c from 2.0.6
[kamenim/samba-autobuild/.git] / source3 / lib / util_sec.c
1 /*
2    Unix SMB/Netbios implementation.
3    Version 2.0
4    Copyright (C) Jeremy Allison 1998.
5    rewritten for version 2.0.6 by Tridge
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #ifndef AUTOCONF_TEST
23 #include "includes.h"
24 extern int DEBUGLEVEL;
25 #else
26 /* we are running this code in autoconf test mode to see which type of setuid
27    function works */
28 #if defined(HAVE_UNISTD_H)
29 #include <unistd.h>
30 #endif
31 #include <stdlib.h>
32 #include <stdio.h>
33
34 #ifdef HAVE_SYS_PRIV_H
35 #include <sys/priv.h>
36 #endif
37 #ifdef HAVE_SYS_ID_H
38 #include <sys/id.h>
39 #endif
40
41 #define DEBUG(x, y) printf y
42 #define smb_panic(x) exit(1)
43 #endif
44
45 /****************************************************************************
46 abort if we haven't set the uid correctly
47 ****************************************************************************/
48 static void assert_uid(uid_t ruid, uid_t euid)
49 {
50         if ((euid != (uid_t)-1 && geteuid() != euid) ||
51             (ruid != (uid_t)-1 && getuid() != ruid)) {
52                 DEBUG(0,("Failed to set uid privileges to (%d,%d) now set to (%d,%d)\n",
53                          (int)ruid, (int)euid,
54                          (int)getuid(), (int)geteuid()));
55                 smb_panic("failed to set uid\n");
56                 exit(1);
57         }
58 }
59
60 /****************************************************************************
61 abort if we haven't set the gid correctly
62 ****************************************************************************/
63 static void assert_gid(gid_t rgid, gid_t egid)
64 {
65         if ((egid != (gid_t)-1 && getegid() != egid) ||
66             (rgid != (gid_t)-1 && getgid() != rgid)) {
67                 DEBUG(0,("Failed to set gid privileges to (%d,%d) now set to (%d,%d) uid=(%d,%d)\n",
68                          (int)rgid, (int)egid,
69                          (int)getgid(), (int)getegid(),
70                          (int)getuid(), (int)geteuid()));
71                 smb_panic("failed to set gid\n");
72                 exit(1);
73         }
74 }
75
76 /****************************************************************************
77  Gain root privilege before doing something. 
78  We want to end up with ruid==euid==0
79 ****************************************************************************/
80 void gain_root_privilege(void)
81 {       
82 #if USE_SETRESUID
83         setresuid(0,0,0);
84 #endif
85     
86 #if USE_SETEUID
87         seteuid(0);
88 #endif
89
90 #if USE_SETREUID
91         setreuid(0, 0);
92 #endif
93
94 #if USE_SETUIDX
95         setuidx(ID_EFFECTIVE, 0);
96         setuidx(ID_REAL, 0);
97 #endif
98
99         /* this is needed on some systems */
100         setuid(0);
101
102         assert_uid(0, 0);
103 }
104
105
106 /****************************************************************************
107  Ensure our real and effective groups are zero.
108  we want to end up with rgid==egid==0
109 ****************************************************************************/
110 void gain_root_group_privilege(void)
111 {
112 #if USE_SETRESUID
113         setresgid(0,0,0);
114 #endif
115
116 #if USE_SETREUID
117         setregid(0,0);
118 #endif
119
120 #if USE_SETEUID
121         setegid(0);
122 #endif
123
124 #if USE_SETUIDX
125         setgidx(ID_EFFECTIVE, 0);
126         setgidx(ID_REAL, 0);
127 #endif
128
129         setgid(0);
130
131         assert_gid(0, 0);
132 }
133
134
135 /****************************************************************************
136  Set *only* the effective uid.
137  we want to end up with ruid==0 and euid==uid
138 ****************************************************************************/
139 void set_effective_uid(uid_t uid)
140 {
141 #if USE_SETRESUID
142         setresuid(-1,uid,-1);
143 #endif
144
145 #if USE_SETREUID
146         setreuid(-1,uid);
147 #endif
148
149 #if USE_SETEUID
150         seteuid(uid);
151 #endif
152
153 #if USE_SETUIDX
154         setuidx(ID_EFFECTIVE, uid);
155 #endif
156
157         assert_uid(-1, uid);
158 }
159
160 /****************************************************************************
161  Set *only* the effective gid.
162  we want to end up with rgid==0 and egid==gid
163 ****************************************************************************/
164 void set_effective_gid(gid_t gid)
165 {
166 #if USE_SETRESUID
167         setresgid(-1,gid,-1);
168 #endif
169
170 #if USE_SETREUID
171         setregid(-1,gid);
172 #endif
173
174 #if USE_SETEUID
175         setegid(gid);
176 #endif
177
178 #if USE_SETUIDX
179         setgidx(ID_EFFECTIVE, gid);
180 #endif
181
182         assert_gid(-1, gid);
183 }
184
185 static uid_t saved_euid, saved_ruid;
186
187 /****************************************************************************
188  save the real and effective uid for later restoration. Used by the quotas
189  code
190 ****************************************************************************/
191 void save_re_uid(void)
192 {
193         saved_ruid = getuid();
194         saved_euid = geteuid();
195 }
196
197
198 /****************************************************************************
199  and restore them!
200 ****************************************************************************/
201 void restore_re_uid(void)
202 {
203         set_effective_uid(0);
204         set_effective_uid(saved_euid);
205         if (getuid() != saved_ruid) setuid(saved_ruid);
206         set_effective_uid(saved_euid);
207
208         assert_uid(saved_ruid, saved_euid);
209 }
210
211 /****************************************************************************
212  set the real AND effective uid to the current effective uid in a way that
213  allows root to be regained.
214  This is only possible on some platforms.
215 ****************************************************************************/
216 int set_re_uid(void)
217 {
218         uid_t uid = geteuid();
219
220 #if USE_SETRESUID
221         setresuid(geteuid(), -1, -1);
222 #endif
223
224 #if USE_SETREUID
225         setreuid(0, 0);
226         setreuid(uid, -1);
227         setreuid(-1, uid);
228 #endif
229
230 #if USE_SETEUID
231         /* can't be done */
232         return -1;
233 #endif
234
235 #if USE_SETUIDX
236         /* can't be done */
237         return -1;
238 #endif
239
240         assert_uid(uid, uid);
241         return 0;
242 }
243
244
245 /****************************************************************************
246  Become the specified uid and gid - permanently !
247  there should be no way back if possible
248 ****************************************************************************/
249 void become_user_permanently(uid_t uid, gid_t gid)
250 {
251         /*
252          * First - gain root privilege. We do this to ensure
253          * we can lose it again.
254          */
255
256         gain_root_privilege();
257         gain_root_group_privilege();
258
259 #if USE_SETRESUID
260         setresgid(gid,gid,gid);
261         setgid(gid);
262         setresuid(uid,uid,uid);
263         setuid(uid);
264 #endif
265
266 #if USE_SETREUID
267         setregid(gid,gid);
268         setgid(gid);
269         setreuid(uid,uid);
270         setuid(uid);
271 #endif
272
273 #if USE_SETEUID
274         setegid(gid);
275         setgid(gid);
276         setuid(uid);
277         seteuid(uid);
278         setuid(uid);
279 #endif
280
281 #if USE_SETUIDX
282         setgidx(ID_REAL, gid);
283         setgidx(ID_EFFECTIVE, gid);
284         setgid(gid);
285         setuidx(ID_REAL, uid);
286         setuidx(ID_EFFECTIVE, uid);
287         setuid(uid);
288 #endif
289         
290         assert_uid(uid, uid);
291         assert_gid(gid, gid);
292 }
293
294 #ifdef AUTOCONF_TEST
295 main()
296 {
297         if (getuid() != 0) {
298 #if (defined(AIX) && defined(USE_SETREUID))
299                 /* setreuid is badly broken on AIX 4.1, we avoid it completely */
300                 fprintf(stderr,"avoiding possibly broken setreuid\n");
301                 exit(1);
302 #endif
303
304                 /* assume that if we have the functions then they work */
305                 fprintf(stderr,"not running as root: assuming OK\n");
306                 exit(0);
307         }
308
309         gain_root_privilege();
310         gain_root_group_privilege();
311         set_effective_gid(1);
312         set_effective_uid(1);
313         gain_root_privilege();
314         gain_root_group_privilege();
315         become_user_permanently(1, 1);
316         setuid(0);
317         if (getuid() == 0) {
318                 fprintf(stderr,"uid not set permanently\n");
319                 exit(1);
320         }
321
322         printf("OK\n");
323
324         exit(0);
325 }
326 #endif