summaryrefslogtreecommitdiff
path: root/privileges.c
blob: c2f5c74fe8935a8e8585aa91cc889eb196d54de6 (plain)
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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
/*  Copyright 1997,1999,2001,2002,2007,2009 Alain Knaff.
 *  This file is part of mtools.
 *
 *  Mtools is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  Mtools is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Mtools.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "sysincludes.h"
#include "msdos.h"
#include "mtools.h"

int noPrivileges=0;

#ifdef OS_mingw32msvc
void reclaim_privs(void)
{
}

void drop_privs(void)
{
}

void destroy_privs(void)
{
}

uid_t get_real_uid(void)
{
	return 0;
}

void init_privs(void)
{
}

void closeExec(int fd)
{
}

#else
/*#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 gid_t rgid, egid;
static uid_t 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(uid_t 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)
{
	if(noPrivileges)
		return;
	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  ");
}


uid_t get_real_uid(void)
{
	return ruid;
}

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

#ifndef F_SETFD
	if(euid != ruid) {
		fprintf(stderr,
			"Setuid installation not supported on this platform\n");
		fprintf(stderr,
			"Missing F_SETFD");
		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 F_SETFD
	fcntl(fd, F_SETFD, 1);
#endif
}
#endif