~bug-zappers/ubuntu/lucid/samba/bugzapping

« back to all changes in this revision

Viewing changes to source/lib/util_sec.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2004-10-15 12:31:58 UTC
  • Revision ID: james.westby@ubuntu.com-20041015123158-aokykzdqkdgy6dfx
Tags: upstream-3.0.7
ImportĀ upstreamĀ versionĀ 3.0.7

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
   Unix SMB/CIFS implementation.
 
3
   Copyright (C) Jeremy Allison 1998.
 
4
   rewritten for version 2.0.6 by Tridge
 
5
 
 
6
   This program is free software; you can redistribute it and/or modify
 
7
   it under the terms of the GNU General Public License as published by
 
8
   the Free Software Foundation; either version 2 of the License, or
 
9
   (at your option) any later version.
 
10
 
 
11
   This program is distributed in the hope that it will be useful,
 
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
   GNU General Public License for more details.
 
15
 
 
16
   You should have received a copy of the GNU General Public License
 
17
   along with this program; if not, write to the Free Software
 
18
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
19
*/
 
20
 
 
21
#ifndef AUTOCONF_TEST
 
22
#include "includes.h"
 
23
#else
 
24
/* we are running this code in autoconf test mode to see which type of setuid
 
25
   function works */
 
26
#if defined(HAVE_UNISTD_H)
 
27
#include <unistd.h>
 
28
#endif
 
29
#include <stdlib.h>
 
30
#include <stdio.h>
 
31
#include <sys/types.h>
 
32
#include <errno.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
#define BOOL int
 
44
#endif
 
45
 
 
46
/* are we running as non-root? This is used by the regresison test code,
 
47
   and potentially also for sites that want non-root smbd */
 
48
static uid_t initial_uid;
 
49
static gid_t initial_gid;
 
50
 
 
51
/****************************************************************************
 
52
remember what uid we got started as - this allows us to run correctly
 
53
as non-root while catching trapdoor systems
 
54
****************************************************************************/
 
55
void sec_init(void)
 
56
{
 
57
        initial_uid = geteuid();
 
58
        initial_gid = getegid();
 
59
}
 
60
 
 
61
/****************************************************************************
 
62
some code (eg. winbindd) needs to know what uid we started as
 
63
****************************************************************************/
 
64
uid_t sec_initial_uid(void)
 
65
{
 
66
        return initial_uid;
 
67
}
 
68
 
 
69
/****************************************************************************
 
70
some code (eg. winbindd, profiling shm) needs to know what gid we started as
 
71
****************************************************************************/
 
72
gid_t sec_initial_gid(void)
 
73
{
 
74
        return initial_gid;
 
75
}
 
76
 
 
77
/****************************************************************************
 
78
are we running in non-root mode?
 
79
****************************************************************************/
 
80
BOOL non_root_mode(void)
 
81
{
 
82
        return (initial_uid != (uid_t)0);
 
83
}
 
84
 
 
85
/****************************************************************************
 
86
abort if we haven't set the uid correctly
 
87
****************************************************************************/
 
88
static void assert_uid(uid_t ruid, uid_t euid)
 
89
{
 
90
        if ((euid != (uid_t)-1 && geteuid() != euid) ||
 
91
            (ruid != (uid_t)-1 && getuid() != ruid)) {
 
92
                if (!non_root_mode()) {
 
93
                        DEBUG(0,("Failed to set uid privileges to (%d,%d) now set to (%d,%d)\n",
 
94
                                 (int)ruid, (int)euid,
 
95
                                 (int)getuid(), (int)geteuid()));
 
96
                        smb_panic("failed to set uid\n");
 
97
                        exit(1);
 
98
                }
 
99
        }
 
100
}
 
101
 
 
102
/****************************************************************************
 
103
abort if we haven't set the gid correctly
 
104
****************************************************************************/
 
105
static void assert_gid(gid_t rgid, gid_t egid)
 
106
{
 
107
        if ((egid != (gid_t)-1 && getegid() != egid) ||
 
108
            (rgid != (gid_t)-1 && getgid() != rgid)) {
 
109
                if (!non_root_mode()) {
 
110
                        DEBUG(0,("Failed to set gid privileges to (%d,%d) now set to (%d,%d) uid=(%d,%d)\n",
 
111
                                 (int)rgid, (int)egid,
 
112
                                 (int)getgid(), (int)getegid(),
 
113
                                 (int)getuid(), (int)geteuid()));
 
114
                        smb_panic("failed to set gid\n");
 
115
                        exit(1);
 
116
                }
 
117
        }
 
118
}
 
119
 
 
120
/****************************************************************************
 
121
 Gain root privilege before doing something. 
 
122
 We want to end up with ruid==euid==0
 
123
****************************************************************************/
 
124
void gain_root_privilege(void)
 
125
{       
 
126
#if USE_SETRESUID
 
127
        setresuid(0,0,0);
 
128
#endif
 
129
    
 
130
#if USE_SETEUID
 
131
        seteuid(0);
 
132
#endif
 
133
 
 
134
#if USE_SETREUID
 
135
        setreuid(0, 0);
 
136
#endif
 
137
 
 
138
#if USE_SETUIDX
 
139
        setuidx(ID_EFFECTIVE, 0);
 
140
        setuidx(ID_REAL, 0);
 
141
#endif
 
142
 
 
143
        /* this is needed on some systems */
 
144
        setuid(0);
 
145
 
 
146
        assert_uid(0, 0);
 
147
}
 
148
 
 
149
 
 
150
/****************************************************************************
 
151
 Ensure our real and effective groups are zero.
 
152
 we want to end up with rgid==egid==0
 
153
****************************************************************************/
 
154
void gain_root_group_privilege(void)
 
155
{
 
156
#if USE_SETRESUID
 
157
        setresgid(0,0,0);
 
158
#endif
 
159
 
 
160
#if USE_SETREUID
 
161
        setregid(0,0);
 
162
#endif
 
163
 
 
164
#if USE_SETEUID
 
165
        setegid(0);
 
166
#endif
 
167
 
 
168
#if USE_SETUIDX
 
169
        setgidx(ID_EFFECTIVE, 0);
 
170
        setgidx(ID_REAL, 0);
 
171
#endif
 
172
 
 
173
        setgid(0);
 
174
 
 
175
        assert_gid(0, 0);
 
176
}
 
177
 
 
178
 
 
179
/****************************************************************************
 
180
 Set effective uid, and possibly the real uid too.
 
181
 We want to end up with either:
 
182
  
 
183
   ruid==uid and euid==uid
 
184
 
 
185
 or
 
186
 
 
187
   ruid==0 and euid==uid
 
188
 
 
189
 depending on what the local OS will allow us to regain root from.
 
190
****************************************************************************/
 
191
void set_effective_uid(uid_t uid)
 
192
{
 
193
#if USE_SETRESUID
 
194
        /* Set the effective as well as the real uid. */
 
195
        setresuid(uid,uid,-1);
 
196
#endif
 
197
 
 
198
#if USE_SETREUID
 
199
        setreuid(-1,uid);
 
200
#endif
 
201
 
 
202
#if USE_SETEUID
 
203
        seteuid(uid);
 
204
#endif
 
205
 
 
206
#if USE_SETUIDX
 
207
        setuidx(ID_EFFECTIVE, uid);
 
208
#endif
 
209
 
 
210
        assert_uid(-1, uid);
 
211
}
 
212
 
 
213
/****************************************************************************
 
214
 Set *only* the effective gid.
 
215
 we want to end up with rgid==0 and egid==gid
 
216
****************************************************************************/
 
217
void set_effective_gid(gid_t gid)
 
218
{
 
219
#if USE_SETRESUID
 
220
        setresgid(-1,gid,-1);
 
221
#endif
 
222
 
 
223
#if USE_SETREUID
 
224
        setregid(-1,gid);
 
225
#endif
 
226
 
 
227
#if USE_SETEUID
 
228
        setegid(gid);
 
229
#endif
 
230
 
 
231
#if USE_SETUIDX
 
232
        setgidx(ID_EFFECTIVE, gid);
 
233
#endif
 
234
 
 
235
        assert_gid(-1, gid);
 
236
}
 
237
 
 
238
static uid_t saved_euid, saved_ruid;
 
239
static gid_t saved_egid, saved_rgid;
 
240
 
 
241
/****************************************************************************
 
242
 save the real and effective uid for later restoration. Used by the quotas
 
243
 code
 
244
****************************************************************************/
 
245
void save_re_uid(void)
 
246
{
 
247
        saved_ruid = getuid();
 
248
        saved_euid = geteuid();
 
249
}
 
250
 
 
251
 
 
252
/****************************************************************************
 
253
 and restore them!
 
254
****************************************************************************/
 
255
void restore_re_uid(void)
 
256
{
 
257
        set_effective_uid(0);
 
258
 
 
259
#if USE_SETRESUID
 
260
        setresuid(saved_ruid, saved_euid, -1);
 
261
#elif USE_SETREUID
 
262
        setreuid(saved_ruid, -1);
 
263
        setreuid(-1,saved_euid);
 
264
#elif USE_SETUIDX
 
265
        setuidx(ID_REAL, saved_ruid);
 
266
        setuidx(ID_EFFECTIVE, saved_euid);
 
267
#else
 
268
        set_effective_uid(saved_euid);
 
269
        if (getuid() != saved_ruid)
 
270
                setuid(saved_ruid);
 
271
        set_effective_uid(saved_euid);
 
272
#endif
 
273
 
 
274
        assert_uid(saved_ruid, saved_euid);
 
275
}
 
276
 
 
277
 
 
278
/****************************************************************************
 
279
 save the real and effective gid for later restoration. Used by the 
 
280
 getgroups code
 
281
****************************************************************************/
 
282
void save_re_gid(void)
 
283
{
 
284
        saved_rgid = getgid();
 
285
        saved_egid = getegid();
 
286
}
 
287
 
 
288
/****************************************************************************
 
289
 and restore them!
 
290
****************************************************************************/
 
291
void restore_re_gid(void)
 
292
{
 
293
#if USE_SETRESUID
 
294
        setresgid(saved_rgid, saved_egid, -1);
 
295
#elif USE_SETREUID
 
296
        setregid(saved_rgid, -1);
 
297
        setregid(-1,saved_egid);
 
298
#elif USE_SETUIDX
 
299
        setgidx(ID_REAL, saved_rgid);
 
300
        setgidx(ID_EFFECTIVE, saved_egid);
 
301
#else
 
302
        set_effective_gid(saved_egid);
 
303
        if (getgid() != saved_rgid)
 
304
                setgid(saved_rgid);
 
305
        set_effective_gid(saved_egid);
 
306
#endif
 
307
 
 
308
        assert_gid(saved_rgid, saved_egid);
 
309
}
 
310
 
 
311
 
 
312
/****************************************************************************
 
313
 set the real AND effective uid to the current effective uid in a way that
 
314
 allows root to be regained.
 
315
 This is only possible on some platforms.
 
316
****************************************************************************/
 
317
int set_re_uid(void)
 
318
{
 
319
        uid_t uid = geteuid();
 
320
 
 
321
#if USE_SETRESUID
 
322
        setresuid(geteuid(), -1, -1);
 
323
#endif
 
324
 
 
325
#if USE_SETREUID
 
326
        setreuid(0, 0);
 
327
        setreuid(uid, -1);
 
328
        setreuid(-1, uid);
 
329
#endif
 
330
 
 
331
#if USE_SETEUID
 
332
        /* can't be done */
 
333
        return -1;
 
334
#endif
 
335
 
 
336
#if USE_SETUIDX
 
337
        /* can't be done */
 
338
        return -1;
 
339
#endif
 
340
 
 
341
        assert_uid(uid, uid);
 
342
        return 0;
 
343
}
 
344
 
 
345
 
 
346
/****************************************************************************
 
347
 Become the specified uid and gid - permanently !
 
348
 there should be no way back if possible
 
349
****************************************************************************/
 
350
void become_user_permanently(uid_t uid, gid_t gid)
 
351
{
 
352
        /*
 
353
         * First - gain root privilege. We do this to ensure
 
354
         * we can lose it again.
 
355
         */
 
356
 
 
357
        gain_root_privilege();
 
358
        gain_root_group_privilege();
 
359
 
 
360
#if USE_SETRESUID
 
361
        setresgid(gid,gid,gid);
 
362
        setgid(gid);
 
363
        setresuid(uid,uid,uid);
 
364
        setuid(uid);
 
365
#endif
 
366
 
 
367
#if USE_SETREUID
 
368
        setregid(gid,gid);
 
369
        setgid(gid);
 
370
        setreuid(uid,uid);
 
371
        setuid(uid);
 
372
#endif
 
373
 
 
374
#if USE_SETEUID
 
375
        setegid(gid);
 
376
        setgid(gid);
 
377
        setuid(uid);
 
378
        seteuid(uid);
 
379
        setuid(uid);
 
380
#endif
 
381
 
 
382
#if USE_SETUIDX
 
383
        setgidx(ID_REAL, gid);
 
384
        setgidx(ID_EFFECTIVE, gid);
 
385
        setgid(gid);
 
386
        setuidx(ID_REAL, uid);
 
387
        setuidx(ID_EFFECTIVE, uid);
 
388
        setuid(uid);
 
389
#endif
 
390
        
 
391
        assert_uid(uid, uid);
 
392
        assert_gid(gid, gid);
 
393
}
 
394
 
 
395
#ifdef AUTOCONF_TEST
 
396
 
 
397
/****************************************************************************
 
398
this function just checks that we don't get ENOSYS back
 
399
****************************************************************************/
 
400
static int have_syscall(void)
 
401
{
 
402
        errno = 0;
 
403
 
 
404
#if USE_SETRESUID
 
405
        setresuid(-1,-1,-1);
 
406
#endif
 
407
 
 
408
#if USE_SETREUID
 
409
        setreuid(-1,-1);
 
410
#endif
 
411
 
 
412
#if USE_SETEUID
 
413
        seteuid(-1);
 
414
#endif
 
415
 
 
416
#if USE_SETUIDX
 
417
        setuidx(ID_EFFECTIVE, -1);
 
418
#endif
 
419
 
 
420
        if (errno == ENOSYS) return -1;
 
421
        
 
422
        return 0;
 
423
}
 
424
 
 
425
main()
 
426
{
 
427
        if (getuid() != 0) {
 
428
#if (defined(AIX) && defined(USE_SETREUID))
 
429
                /* setreuid is badly broken on AIX 4.1, we avoid it completely */
 
430
                fprintf(stderr,"avoiding possibly broken setreuid\n");
 
431
                exit(1);
 
432
#endif
 
433
 
 
434
                /* if not running as root then at least check to see if we get ENOSYS - this 
 
435
                   handles Linux 2.0.x with glibc 2.1 */
 
436
                fprintf(stderr,"not running as root: checking for ENOSYS\n");
 
437
                exit(have_syscall());
 
438
        }
 
439
 
 
440
        gain_root_privilege();
 
441
        gain_root_group_privilege();
 
442
        set_effective_gid(1);
 
443
        set_effective_uid(1);
 
444
        save_re_uid();
 
445
        restore_re_uid();
 
446
        gain_root_privilege();
 
447
        gain_root_group_privilege();
 
448
        become_user_permanently(1, 1);
 
449
        setuid(0);
 
450
        if (getuid() == 0) {
 
451
                fprintf(stderr,"uid not set permanently\n");
 
452
                exit(1);
 
453
        }
 
454
 
 
455
        printf("OK\n");
 
456
 
 
457
        exit(0);
 
458
}
 
459
#endif
 
460
 
 
461
/****************************************************************************
 
462
Check if we are setuid root.  Used in libsmb and smbpasswd paranoia checks.
 
463
****************************************************************************/
 
464
BOOL is_setuid_root(void) 
 
465
{
 
466
        return (geteuid() == (uid_t)0) && (getuid() != (uid_t)0);
 
467
}