Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 103947 | Differences between
and this patch

Collapse All | Expand All

(-)bfilter-0.9.4/main/main_unix.cpp (-2 / +52 lines)
Lines 26-38 Link Here
26
#include <popt.h>
26
#include <popt.h>
27
#include "network.h"
27
#include "network.h"
28
#include <ipcportal.h>
28
#include <ipcportal.h>
29
#include <sys/stat.h>
30
#include <pwd.h>
31
#include <grp.h>
29
32
30
// some older versions of popt don't define POPT_TABLEEND
33
// some older versions of popt don't define POPT_TABLEEND
31
#ifndef POPT_TABLEEND
34
#ifndef POPT_TABLEEND
32
#define POPT_TABLEEND { NULL, '\0', 0, 0, 0, NULL, NULL }
35
#define POPT_TABLEEND { NULL, '\0', 0, 0, 0, NULL, NULL }
33
#endif
36
#endif
34
37
35
int main_unix_standalone(const std::string& confdir, bool nodaemon);
38
int main_unix_standalone(const std::string& confdir, bool nodaemon, char *chroot, uid_t user, gid_t group);
36
int main_unix_backend(Network::Socket csock, IPCPortal* portal);
39
int main_unix_backend(Network::Socket csock, IPCPortal* portal);
37
40
38
int main(int argc, char *argv[])
41
int main(int argc, char *argv[])
Lines 40-55 Link Here
40
	enum {
43
	enum {
41
		ARG_VERSION = 1,
44
		ARG_VERSION = 1,
42
		ARG_CONFDIR,
45
		ARG_CONFDIR,
46
		ARG_CHROOT,
47
		ARG_USER,
48
		ARG_GROUP,
43
		ARG_NODAEMON,
49
		ARG_NODAEMON,
44
		ARG_BACKEND
50
		ARG_BACKEND
45
	};
51
	};
46
	bool backend = false;
52
	bool backend = false;
47
	bool nodaemon = false;
53
	bool nodaemon = false;
48
	char *cdir = 0;
54
	char *cdir = 0;
55
	char *chroot = 0;
56
	char *user = 0;
57
	char *group = 0;
58
	uid_t uid = 0;
59
	uid_t gid = 0;
49
	std::string confdir = CONFDIR;
60
	std::string confdir = CONFDIR;
50
	struct poptOption options[] = {
61
	struct poptOption options[] = {
51
		{ "version", 'v', POPT_ARG_NONE, NULL, ARG_VERSION, "Print version and exit" },
62
		{ "version", 'v', POPT_ARG_NONE, NULL, ARG_VERSION, "Print version and exit" },
52
		{ "confdir", 'c', POPT_ARG_STRING, &cdir, ARG_CONFDIR, "Set custom config directory", "dir" },
63
		{ "confdir", 'c', POPT_ARG_STRING, &cdir, ARG_CONFDIR, "Set custom config directory", "dir" },
64
		{ "chroot", 'r', POPT_ARG_STRING, &chroot, ARG_CHROOT, "Set chroot directory", "dir" },
65
		{ "user", 'u', POPT_ARG_STRING, &user, ARG_USER, "Set unprivileged user", "name" },
66
		{ "group", 'g', POPT_ARG_STRING, &group, ARG_GROUP, "Set unprivileged group", "name" },
53
		{ "nodaemon", 'n', POPT_ARG_NONE, NULL, ARG_NODAEMON, "Disable background daemon mode" },
67
		{ "nodaemon", 'n', POPT_ARG_NONE, NULL, ARG_NODAEMON, "Disable background daemon mode" },
54
		{ "backend", '\0', POPT_ARG_NONE|POPT_ARGFLAG_DOC_HIDDEN, NULL, ARG_BACKEND },
68
		{ "backend", '\0', POPT_ARG_NONE|POPT_ARGFLAG_DOC_HIDDEN, NULL, ARG_BACKEND },
55
		POPT_AUTOHELP
69
		POPT_AUTOHELP
Lines 78-90 Link Here
78
			<< ": " << poptStrerror(arg) << std::endl;
92
			<< ": " << poptStrerror(arg) << std::endl;
79
		return 1;
93
		return 1;
80
	}
94
	}
95
	if (!backend && (chroot || user || group)) {
96
		struct stat stat_r;
97
		struct passwd *user_r;
98
		struct group *group_r;
99
100
		if (getuid()) {
101
			std::cerr << "Cannot lower privileges, not running as root" << std::endl;
102
			return 1;
103
		}
104
105
		if (chroot && stat(chroot, &stat_r)) {
106
			if (!S_ISDIR(stat_r.st_mode)){
107
				std::cerr << "Cannot lower privileges, chroot directory does not exist" << std::endl;
108
				return 1;
109
			}
110
		}
111
		if (user) {
112
			user_r = getpwnam(user);
113
			if (user_r)
114
				uid = user_r->pw_uid;
115
			else {
116
				std::cerr << "Cannot lower privileges, unknown user" << std::endl;
117
				return 1;
118
			}
119
		}
120
121
		if (group) {
122
			group_r = getgrnam(group);
123
			if (group_r)
124
				gid = group_r->gr_gid;
125
			else {
126
				std::cerr << "Cannot lower privileges, unknown group" << std::endl;
127
				return 1;
128
			}
129
		}
130
	}
81
	poptFreeContext(context);
131
	poptFreeContext(context);
82
	
132
	
83
	if (backend) {
133
	if (backend) {
84
		IPCPortal portal(0, 1);
134
		IPCPortal portal(0, 1);
85
		return main_unix_backend(3, &portal);
135
		return main_unix_backend(3, &portal);
86
	} else {
136
	} else {
87
		return main_unix_standalone(confdir, nodaemon);
137
		return main_unix_standalone(confdir, nodaemon, chroot, uid, gid);
88
	}
138
	}
89
}
139
}
90
140
(-)bfilter-0.9.4/main/main_unix_standalone.cpp (-1 / +38 lines)
Lines 26-31 Link Here
26
#include "state.h"
26
#include "state.h"
27
#include <ipcportal.h>
27
#include <ipcportal.h>
28
#include "syscall.h"
28
#include "syscall.h"
29
#include <pwd.h>
30
#include <grp.h>
31
#include <resolv.h>
29
32
30
class StandaloneState : public State
33
class StandaloneState : public State
31
{
34
{
Lines 175-181 Link Here
175
	return strm.str();
178
	return strm.str();
176
}
179
}
177
180
178
int main_unix_standalone(const std::string& confdir, bool nodaemon)
181
static int drop_privileges(char *dir, uid_t uid, gid_t gid)
182
{
183
	if (dir) {
184
		// Using gethostbyname before chrooting means that the chroot
185
		// directory can be empty (no etc/resolv.conf or dynamically
186
		// loaded lib/libnss* libraries). Unfortunately simply using
187
		// gethostbyname once in the parent process does not apply to
188
		// forked children. Using localhost here to prevent remote
189
		// name resolution also does not work.
190
		gethostbyname("slashdot.org");
191
		if (chroot(dir)) {
192
			std::cerr << "Cannot lower privileges, chroot directory no longer exists" << std::endl;
193
			return 1;
194
		}
195
		chdir("/");
196
	}
197
	if (gid) {
198
		setgroups(0, NULL);
199
		setgid(gid);
200
	}
201
	if (uid) {
202
		setuid(uid);
203
	}
204
205
	return 0;
206
}
207
208
int main_unix_standalone(const std::string& confdir, bool nodaemon, char *chroot, uid_t uid, gid_t gid)
179
{
209
{
180
	Network::Socket serv_sock = Network::INVALID_SOCK;
210
	Network::Socket serv_sock = Network::INVALID_SOCK;
181
	Network::Socket clnt_sock = Network::INVALID_SOCK;
211
	Network::Socket clnt_sock = Network::INVALID_SOCK;
Lines 249-254 Link Here
249
		daemon(1, 0);
279
		daemon(1, 0);
250
	}
280
	}
251
	setup_parent_signals();
281
	setup_parent_signals();
282
	if (!chroot) {
283
		drop_privileges(NULL, uid, gid);
284
	}
252
	
285
	
253
	while (true) {
286
	while (true) {
254
		clnt_sock = Network::tcpServerWaitConn(serv_sock, &client);
287
		clnt_sock = Network::tcpServerWaitConn(serv_sock, &client);
Lines 261-266 Link Here
261
			setup_child_signals();
294
			setup_child_signals();
262
			Network::closeSocket(serv_sock);
295
			Network::closeSocket(serv_sock);
263
			Network::sockSetNodelay(clnt_sock, true);
296
			Network::sockSetNodelay(clnt_sock, true);
297
			if (drop_privileges(chroot, uid, gid)) {
298
				Network::disconnectAndCloseSocket(clnt_sock, 10);
299
				return 1;
300
			}
264
			BFilter filter(clnt_sock, &state);
301
			BFilter filter(clnt_sock, &state);
265
			filter.run();
302
			filter.run();
266
			Network::disconnectAndCloseSocket(clnt_sock, 10);
303
			Network::disconnectAndCloseSocket(clnt_sock, 10);

Return to bug 103947