File: privileges.c

package info (click to toggle)
mtools 3.8-1
  • links: PTS
  • area: main
  • in suites: hamm
  • size: 1,116 kB
  • ctags: 1,306
  • sloc: ansic: 11,489; sh: 2,052; makefile: 223; sed: 8
file content (156 lines) | stat: -rw-r--r-- 3,685 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#include "sysincludes.h"
#include "msdos.h"
#include "mtools.h"
#include "patchlevel.h"

/*#define PRIV_DEBUG*/

#if 0
#undef HAVE_SETEUID
#define HAVE_SETRESUID
#include <asm/unistd.h>
int setresuid(int a, int b, int c)
{
	syscall(164, a, b, c);

}
#endif

static inline void print_privs(const char *message)
{
#ifdef PRIV_DEBUG
	/* for debugging purposes only */
	fprintf(stderr,"%s egid=%d rgid=%d\n", message, getegid(), getgid());
	fprintf(stderr,"%s euid=%d ruid=%d\n", message, geteuid(), getuid());
#endif
}

static int rgid, egid, ruid, euid;

/* privilege management routines for SunOS and Solaris.  These are
 * needed in order to issue raw SCSI read/write ioctls.  Mtools drops
 * its privileges at the beginning, and reclaims them just for the
 * above-mentioned ioctl's.  Before popen(), exec() or system, it
 * drops its privileges completely, and issues a warning.
 */


/* group id handling is lots easyer, as long as we don't use group 0.
 * If you want to use group id's, create a *new* group mtools or
 * floppy.  Chgrp any devices that you only want to be accessible to
 * mtools to this group, and give them the appropriate privs.  Make
 * sure this group doesn't own any other files: be aware that any user
 * with access to mtools may mformat these files!
 */


static inline void Setuid(int uid)
{
#if defined HAVE_SETEUID || defined HAVE_SETRESUID
	if(euid == 0) {
#ifdef HAVE_SETEUID
		seteuid(uid);
#else
		setresuid(ruid, uid, euid);
#endif
	} else
#endif
		setuid(uid);
}

/* In reclaim_privs and drop privs, we have to manipulate group privileges
 * when having no root privileges, else we might lose them */

void reclaim_privs(void)
{
	setgid(egid);
	Setuid(euid);
	print_privs("after reclaim privs, both uids should be 0 ");
}

void drop_privs(void)
{
	Setuid(ruid);
	setgid(rgid);
	print_privs("after drop_privs, real should be 0, effective should not ");
}

void destroy_privs(void)
{

#if defined HAVE_SETEUID || defined HAVE_SETRESUID
	if(euid == 0) {
#ifdef HAVE_SETEUID
		setuid(0); /* get the necessary privs to drop real root id */
		setuid(ruid); /* this should be enough to get rid of the three
			       * ids */
		seteuid(ruid); /* for good measure... just in case we came
				* accross a system which implemented sane
				* semantics instead of POSIXly broken
				* semantics for setuid */
#else
		setresuid(ruid, ruid, ruid);
#endif
	}
#endif

	/* we also destroy group privileges */
	drop_privs();

	/* saved set [ug]id will go away by itself on exec */

	print_privs("destroy_privs, no uid should be zero  ");
}


void init_privs(void)
{
	euid = geteuid();
	ruid = getuid();
	egid = getegid();
	rgid = getgid();

#ifndef FD_CLOEXEC
	if(euid != ruid) {
		fprintf(stderr,
			"Setuid installation not supported on this platform\n");
		fprintf(stderr,
			"Missing FD_CLOEXEC");
		exit(1);
	}
#endif
	
	if(euid == 0 && ruid != 0) {
#ifdef HAVE_SETEUID
		setuid(0); /* set real uid to 0 */
#else
#ifndef HAVE_SETRESUID
		/* on this machine, it is not possible to reversibly drop
		 * root privileges.  We print an error and quit */

		/* BEOS is no longer a special case, as both euid and ruid
		 * return 0, and thus we do not get any longer into this
		 * branch */
		fprintf(stderr,
			"Seteuid call not supported on this architecture.\n");
		fprintf(stderr,
			"Mtools cannot be installed setuid root.\n");
		fprintf(stderr,
			"However, it can be installed setuid to a non root");
		fprintf(stderr,
			"user or setgid to any id.\n");
		exit(1);
#endif
#endif
	}
	
	drop_privs();
	print_privs("after init, real should be 0, effective should not ");
}

void closeExec(int fd)
{
#ifdef FD_CLOEXEC
	fcntl(fd, F_SETFL, FD_CLOEXEC);
#endif
}