1#!/bin/sh
2# vim: tabstop=4
3#
4# author:    chris friedhoff - chris@friedhoff.org
5# version:   pcaps4server  5  Tue Mar 11 2008
6#
7#
8# changelog:
9# 1 - initial release pcaps4convenience
10# 1 - 2007.02.15 - initial release
11# 2 - 2007.11.02 - changed to new setfcaps api; each app is now callable; supressed error of id
12# 3 - 2007.12.28 - changed to libcap2 package setcap/getcap
13# 4 - renamed to pcaps4server
14#      removed suid0 and convenience files,
15#      they are now in pcaps4suid0 resp. pcaps4convenience
16# 5 - changed 'attr -S -r' to 'setcap -r' and removed attr code
17#
18#
19###########################################################################
20# change the installation of different server to be able not to run as root
21# and have their own unpriviledged user. The binary has the needed POSIX
22# Capabilities.
23# to ensure that the server is really started as his respective user, we set
24# the suid bit (BUT NOT 0)!
25# paths are hard coded and derive from a slackware system
26# change it to your needs !!
27###########################################################################
28
29
30
31VERBOSE="-v"
32#VERBOSE=""
33APPS=""
34
35message(){
36	printRedMessage "$1"
37}
38
39printRedMessage(){
40	# print message red and turn back to white
41	echo -e "\n\033[00;31m $1 ...\033[00;00m\n"
42}
43
44printGreenMessage(){
45	# print message red and turn back to white
46	echo -e "\033[00;32m $1 ...\033[00;00m\n"
47	sleep 0.5
48}
49
50checkReturnCode(){
51    if [ "$?" != "0" ]; then
52        printRedMessage "!! I'M HAVING A PROBLEM !! THE RETURNCODE IS NOT 0 !! I STOP HERE !!"
53        exit 1
54    else
55        printGreenMessage ":-)"
56		sleep 0.5
57    fi
58}
59
60
61
62p4r_test(){
63	#for now, we work with root
64	if [ "$( id -u )" != "0" ]; then
65		echo "Sorry, you must be root !"
66		exit
67	fi
68}
69
70
71
72
73# apache 1.3
74########
75#APPS="$APPS apache1"
76apache1_convert(){
77	message "converting apache1"
78	if [ "$( id -g apache 2>/dev/null )" == "" ]; then
79		groupadd -g 60 apache
80	fi
81	if [ "$( id -u apache 2>/dev/null )" == "" ]; then
82		useradd -g apache -d / -u 600 apache
83	fi
84	sed -i -e "{s|^\(User\).*|\1 apache|; s|^\(Group\) .*|\1 apache|}" /etc/apache/httpd.conf
85	chown $VERBOSE -R apache:apache /var/run/apache/
86	chown $VERBOSE -R apache:apache /etc/apache/
87	chown $VERBOSE -R apache:apache /var/log/apache/
88	chown $VERBOSE apache:apache /usr/sbin/httpd
89	chmod $VERBOSE u+s /usr/sbin/httpd
90	setcap cap_net_bind_service=ep /usr/sbin/httpd
91	checkReturnCode
92}
93apache1_revert(){
94	message "reverting apache1"
95	chown $VERBOSE -R root:root /var/run/apache/
96	chown $VERBOSE -R root:root /etc/apache/
97	chown $VERBOSE -R root:root /var/log/apache/
98	chown $VERBOSE root:root /usr/sbin/httpd
99	chmod $VERBOSE u-s /usr/sbin/httpd
100	setcap -r /usr/sbin/httpd
101	checkReturnCode
102	sed -i -e "{s|^\(User\).*|\1 nobody|; s|^\(Group\).*|\1 nogroup|}" /etc/apache/httpd.conf
103	userdel apache
104	groupdel apache
105}
106
107
108# apache 2.x
109########
110APPS="$APPS apache2"
111apache2_convert(){
112	message "converting apache2"
113	if [ "$( id -g apache 2>/dev/null )" == "" ]; then
114		groupadd -g 60 apache
115	fi
116	if [ "$( id -u apache 2>/dev/null )" == "" ]; then
117		useradd -g apache -d / -u 600 apache
118	fi
119	sed -i -e "{s|^\(User\).*|\1 apache|; s|^\(Group\) .*|\1 apache|}" /etc/httpd/httpd.conf
120	chown $VERBOSE -R apache:apache /var/run/httpd/
121	chown $VERBOSE -R apache:apache /etc/httpd/
122	chown $VERBOSE -R apache:apache /var/log/httpd/
123	chown $VERBOSE apache:apache /usr/sbin/httpd
124	chmod $VERBOSE u+s /usr/sbin/httpd
125	#setfcaps -c cap_net_bind_service=p -e /usr/sbin/httpd
126	setcap cap_net_bind_service=ep /usr/sbin/httpd
127	checkReturnCode
128}
129apache2_revert(){
130	message "reverting apache2"
131	chown $VERBOSE -R root:root /var/run/httpd/
132	chown $VERBOSE -R root:root /etc/httpd/
133	chown $VERBOSE -R root:root /var/log/httpd/
134	chown $VERBOSE root:root /usr/sbin/httpd
135	chmod $VERBOSE u-s /usr/sbin/httpd
136	setcap -r /usr/sbin/httpd
137	checkReturnCode
138	sed -i -e "{s|^\(User\).*|\1 nobody|; s|^\(Group\).*|\1 nogroup|}" /etc/httpd/httpd.conf
139	userdel apache
140	groupdel apache
141}
142
143
144# samba
145#######
146APPS="$APPS samba"
147samba_convert(){
148	message "converting samba"
149	if [ "$( id -g samba 2>/dev/null )" == "" ]; then
150		groupadd -g 61 samba
151	fi
152	if [ "$( id -u samba 2>/dev/null )" == "" ]; then
153		useradd -g samba -d / -u 610 samba
154	fi
155	chown $VERBOSE -R samba:samba /var/log/samba
156	chown $VERBOSE -R samba:samba /etc/samba
157	chown $VERBOSE -R samba:samba /var/run/samba
158	chown $VERBOSE -R samba:samba /var/cache/samba
159	chown $VERBOSE samba:samba /usr/sbin/smbd /usr/sbin/nmbd
160	chmod $VERBOSE u+s /usr/sbin/smbd /usr/sbin/nmbd
161	setcap cap_net_bind_service,cap_sys_resource,cap_dac_override=ep /usr/sbin/smbd
162	checkReturnCode
163	setcap cap_net_bind_service=ep /usr/sbin/nmbd
164	checkReturnCode
165}
166
167samba_revert(){
168	message "reverting samba"
169	chown $VERBOSE -R root:root /var/log/samba
170	chown $VERBOSE -R root:root /etc/samba
171	chown $VERBOSE -R root:root /var/run/samba
172	chown $VERBOSE -R root:root /var/cache/samba
173	chown $VERBOSE root:root /usr/sbin/smbd /usr/sbin/nmbd
174	chmod $VERBOSE u-s /usr/sbin/smbd /usr/sbin/nmbd
175	setcap -r /usr/sbin/smbd
176	checkReturnCode
177	setcap -r /usr/sbin/nmbd
178	checkReturnCode
179	userdel samba
180	groupdel samba
181}
182
183
184# bind
185######
186APPS="$APPS bind"
187bind_convert(){
188	message "converting bind"
189	if [ "$( id -g bind 2>/dev/null )" == "" ]; then
190		groupadd -g 62 bind
191	fi
192	if [ "$( id -u bind 2>/dev/null )" == "" ]; then
193		useradd -g bind -d / -u 620 bind
194	fi
195	chown $VERBOSE -R bind:bind /var/run/named
196	chown $VERBOSE -R bind:bind /var/named
197	chown $VERBOSE bind:bind /etc/rndc.key
198	chown $VERBOSE bind:bind /usr/sbin/named
199	chmod $VERBOSE u+s /usr/sbin/named
200	setcap cap_net_bind_service=ep /usr/sbin/named
201	checkReturnCode
202}
203bind_revert(){
204	message "reverting bind"
205	chown $VERBOSE -R root:root /var/run/named
206	chown $VERBOSE -R root:root /var/named
207	chown $VERBOSE root:root /etc/rndc.key
208	chown $VERBOSE root:root /usr/sbin/named
209	chmod $VERBOSE u-s /usr/sbin/named
210	setcap -r /usr/sbin/named
211	checkReturnCode
212	userdel bind
213	groupdel bind
214}
215
216
217# dhcpd
218#######
219APPS="$APPS dhcpd"
220dhcpd_convert(){
221	message "converting dhcpd"
222	if [ "$( id -g dhcpd 2>/dev/null )" == "" ]; then
223		groupadd -g 63 dhcpd
224	fi
225	if [ "$( id -u dhcpd 2>/dev/null )" == "" ]; then
226		useradd -g dhcpd -d / -u 630 dhcpd
227	fi
228	chown $VERBOSE dhcpd:dhcpd /var/run/dhcpd
229	chown $VERBOSE dhcpd:dhcpd /etc/dhcpd.conf
230	chown $VERBOSE -R dhcpd:dhcpd /var/state/dhcp/
231	chown $VERBOSE dhcpd:dhcpd /usr/sbin/dhcpd
232	chmod $VERBOSE u+s /usr/sbin/dhcpd
233	setcap cap_net_bind_service,cap_net_raw=ep /usr/sbin/dhcpd
234	checkReturnCode
235}
236dhcpd_revert(){
237	message "reverting dhcpd"
238	chown $VERBOSE root:root /var/run/dhcpd
239	chown $VERBOSE root:root /etc/dhcpd.conf
240	chown $VERBOSE -R root:root /var/state/dhcp/
241	chown $VERBOSE root:root /usr/sbin/dhcpd
242	chmod $VERBOSE u-s /usr/sbin/dhcpd
243	setcap -r /usr/sbin/dhcpd
244	checkReturnCode
245	userdel dhcpd
246	groupdel dhcpd
247}
248
249
250# cupsd
251#######
252APPS="$APPS cupsd"
253cupsd_convert(){
254	message "converting cupsd"
255	if [ "$( id -g cupsd 2>/dev/null )" == "" ]; then
256		groupadd -g 64 cupsd
257	fi
258	if [ "$( id -u cupsd 2>/dev/null )" == "" ]; then
259		useradd -g cupsd -d / -u 640 cupsd
260	fi
261	sed -i -e "{s|^\(User\).*|\1 cupsd|; s|^\(Group\) .*|\1 cupsd|}" /etc/cups/cupsd.conf
262	chown $VERBOSE -R cupsd:cupsd /etc/cups
263	chown $VERBOSE -R cupsd:cupsd /var/cache/cups
264	chown $VERBOSE -R cupsd:cupsd /var/log/cups
265	chown $VERBOSE -R cupsd:cupsd /var/spool/cups
266	chown $VERBOSE -R cupsd:cupsd /var/run/cups
267	chown $VERBOSE cupsd:cupsd /usr/sbin/cupsd
268	chmod $VERBOSE u+s /usr/sbin/cupsd
269	setcap cap_net_bind_service,cap_dac_read_search=ep /usr/sbin/cupsd
270	checkReturnCode
271}
272cupsd_revert(){
273	message "reverting cupsd"
274	chown $VERBOSE -R root:root /etc/cups
275	chown $VERBOSE -R root:lp /var/cache/cups
276	chown $VERBOSE -R root:root /var/log/cups
277	chown $VERBOSE -R root:root /var/spool/cups
278	chown $VERBOSE root:lp /var/run/cups
279	chown $VERBOSE lp:sys /var/run/cups/certs
280	chmod $VERBOSE 750 /var/run/cups/certs
281	chown $VERBOSE root:root /usr/sbin/cupsd
282	chmod $VERBOSE u-s /usr/sbin/cupsd
283	setcap -r /usr/sbin/cupsd
284	checkReturnCode
285	sed -i -e "{s|^\(User\).*|\1 lp|; s|^\(Group\) .*|\1 sys|}" /etc/cups/cupsd.conf
286	userdel cupsd
287	groupdel cupsd
288}
289
290
291usage_message(){
292	echo "Try 'pcaps4server help' for more information"
293}
294
295
296p4r_usage(){
297    echo
298    echo "pcaps4server"
299    echo
300    echo "pcaps4server stores the needed POSIX Capabilities for server binaries to"
301    echo "run successful into their Permitted and Effective Set."
302    echo "The server are now able to run as an unpriviledged user."
303	echo "For each server software an unpriviledged user is added the system."
304    echo "The ownership of all the respective paths are	changed to this user."
305	echo "To ensure that the server is starting as this unpriviledgesd user, the"
306    echo "suid bit (NOT 0) is set."
307	echo "Effectively this means every user can start this server daemons (for now)."
308	echo "All paths are hard coded!"
309	echo "You have been warned. Enjoy!"
310    echo
311    echo "Your Filesystem has to support extended attributes and your kernel must have"
312    echo "support for POSIX File Capabilities (CONFIG_SECURITY_FILE_CAPABILITIES)."
313    echo
314    echo "Usage:  pcaps4server [PROG] [con(vert)|rev(ert)|help]"
315    echo
316    echo "         con|convert - from setuid0 to POSIX Capabilities"
317    echo "         rev|revert  - from POSIX Capabilities back to setui0"
318    echo "         help        - this help message"
319	echo
320	echo "  PROG: $APPS"
321    echo
322}
323
324
325
326
327case "$1" in
328	con|convert)
329		p4r_test
330		for j in $APPS; do
331			${j}_convert
332		done
333		exit
334		;;
335	rev|renvert)
336		p4r_test
337		for j in $APPS; do
338			${j}_revert
339		done
340		exit
341		;;
342	help)
343		p4r_usage
344		exit
345		;;
346esac
347
348for i in ${APPS}; do
349	if [ "$1" == "$i" ]; then
350		case "$2" in
351			con|convert)
352				p4r_test
353				${i}_convert
354				exit
355				;;
356			rev|revert)
357				p4r_test
358				${i}_revert
359				exit
360				;;
361			*)
362				usage_message
363				exit 1
364				;;
365			esac
366	fi
367done
368
369usage_message
370