xref: /illumos-gate/usr/src/cmd/tsol/misc/txzonemgr.sh (revision d362b749)
1#!/bin/pfksh
2#
3# CDDL HEADER START
4#
5# The contents of this file are subject to the terms of the
6# Common Development and Distribution License (the "License").
7# You may not use this file except in compliance with the License.
8#
9# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10# or http://www.opensolaris.org/os/licensing.
11# See the License for the specific language governing permissions
12# and limitations under the License.
13#
14# When distributing Covered Code, include this CDDL HEADER in each
15# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16# If applicable, add the following below this CDDL HEADER, with the
17# fields enclosed by brackets "[]" replaced with your own identifying
18# information: Portions Copyright [yyyy] [name of copyright owner]
19#
20# CDDL HEADER END
21#
22# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23# Use is subject to license terms.
24#
25#ident	"%Z%%M%	%I%	%E% SMI"
26#
27
28# This script provides a simple GUI for managing labeled zones.
29# It takes no arguments, but provides contextual menus which
30# provide appropriate choices. It must be run in the global
31# zone as root.
32
33PATH=/usr/bin:/usr/sbin:/usr/lib export PATH
34title="Labeled Zone Manager"
35maxlabel=`chk_encodings -X 2>/dev/null`
36if [[ ! -n $maxlabel ]]; then
37	maxlabel=0x000a-08-f8
38fi
39config=/tmp/zfg.$$ ;
40
41consoleCheck() {
42	zconsole=`pgrep -f "zlogin -C $zonename"`
43	if [ $? != 0 ]; then
44		console="Zone Console...\n"
45	fi
46}
47
48labelCheck() {
49	hexlabel=`/bin/grep "^$zonename:" \
50	    /etc/security/tsol/tnzonecfg|cut -d ":" -f2`;
51	if [ $hexlabel ] ; then
52		label=
53		curlabel=`hextoalabel $hexlabel`
54	else
55		label="Select Label...\n"
56		curlabel=...
57	fi
58}
59
60snapshotCheck() {
61	filesystem=`zfs list |grep zone/$zonename |cut -d " " -f1`
62	if [[ -n $filesystem ]]; then
63		snapshot="Create Snapshot\n"
64	fi
65}
66
67copyCheck() {
68	zonelist=""
69	for p in `zoneadm list -ip`; do
70		q=`echo $p|cut -d ":" -f2`
71		if [ $q != $zonename ]; then
72			zonelist="$zonelist $q"
73		fi
74	done
75	if [[ -n $zonelist ]]; then
76		copy="Copy...\n"; \
77		clone="Clone\n"; \
78	fi
79}
80
81relabelCheck() {
82	macstate=`zonecfg -z $zonename info|grep win_mac_write`
83	if [[ -n $macstate ]]; then
84		permitrelabel="Deny Relabeling\n"
85	else
86		permitrelabel="Permit Relabeling\n"
87	fi
88}
89
90selectLabel() {
91	labelList=""
92	for p in `lslabels -h $maxlabel`; do
93		hexlabel=`/bin/grep :$p: /etc/security/tsol/tnzonecfg`
94		if [ $? != 0 ]; then
95			newlabel=`hextoalabel $p`
96			labelList="$labelList $newlabel\n"
97		fi
98	done
99	alabel=$(echo $labelList|zenity --list \
100	    --title="$title" \
101	    --height=300 \
102	    --width=400 \
103	    --column="Available Sensitivity Labels")
104
105	if [[ -n $alabel ]]; then
106		newlabel=`atohexlabel "$alabel" 2>null`
107		if [[ -n $newlabel ]]; then
108			echo $zonename:$newlabel:0:: >> /etc/security/tsol/tnzonecfg
109		else
110			x=$(zenity --error \
111			    --title="$title" \
112			    --text="$alabel is not valid")
113		fi
114	fi
115}
116
117clone() {
118	image=`zfs list |grep snapshot|cut -d " " -f1| \
119	    zenity --list \
120		--title="$title" \
121	        --height=300 \
122		--column="ZFS Zone Snapshots"`
123	if [[ -n $image ]]; then
124		dataset=`zfs list |grep zone/$zonename |cut -d " " -f1`
125		if [[ -n $dataset ]]; then
126			/usr/sbin/zfs destroy zone/$zonename
127		fi
128		/usr/sbin/zfs clone $image zone/$zonename
129		/usr/sbin/zoneadm -z $zonename attach -F
130		if [ ! -f /var/ldap/ldap_client_file ]; then
131			sharePasswd
132		fi
133	fi
134}
135
136copy() {
137
138	image=`zenity --list \
139	    --title="$title: Copy From" \
140	    --height=300 \
141	    --column="Installed Zones" $zonelist`
142
143	/usr/bin/gnome-terminal \
144	    --title="$title: Copying $image to $zonename zone" \
145	    --command "zoneadm -z $zonename clone -m copy $image"
146	    --hide-menubar
147
148	if [ ! -f /var/ldap/ldap_client_file ]; then
149		sharePasswd
150	fi
151}
152
153initialize() {
154	hostname=`hostname`
155	hostname=$(zenity --entry \
156	    --title="$title" \
157	    --text="Enter Host Name: " \
158	    --entry-text $hostname)
159	if [ $? != 0 ]; then
160		exit 1
161	fi
162
163	ZONE_PATH=`zoneadm list -cp|grep ":${zonename}:"|cut -d ":" -f4`
164	ZONE_ETC_DIR=$ZONE_PATH/root/etc
165	ipaddress=`getent hosts $hostname|cut -f1`
166	SYSIDCFG=${ZONE_ETC_DIR}/sysidcfg
167
168	if [ -f /var/ldap/ldap_client_file ]; then
169		ldapaddress=`ldapclient list | \
170		    /bin/grep "^NS_LDAP_SERVERS" | cut -d " " -f2`
171		echo "name_service=LDAP {" > ${SYSIDCFG}
172		domain=`domainname`
173		echo "domain_name=$domain" >> ${SYSIDCFG}
174		profName=`ldapclient list | \
175		    /bin/grep "^NS_LDAP_PROFILE" | cut -d " " -f2`
176		proxyPwd=`ldapclient list | \
177		    /bin/grep "^NS_LDAP_BINDPASSWD" | cut -d " " -f2`
178		proxyDN=`ldapclient list | \
179		    /bin/grep "^NS_LDAP_BINDDN" | cut -d " " -f 2`
180		if [ "$proxyDN" ]; then
181			echo "proxy_dn=\"$proxyDN\"" >> ${SYSIDCFG}
182			echo "proxy_password=\"$proxyPwd\"" >> ${SYSIDCFG}
183		fi
184		echo "profile=$profName" >> ${SYSIDCFG}
185		echo "profile_server=$ldapaddress }" >> ${SYSIDCFG}
186		cp /etc/nsswitch.conf $ZONE_ETC_DIR/nsswitch.ldap
187	else
188		echo "name_service=NONE" > ${SYSIDCFG}
189		sharePasswd
190	fi
191
192	echo "security_policy=NONE" >> ${SYSIDCFG}
193	locale=`locale|grep LANG | cut -d "=" -f2`
194	if [[ -z $locale ]]; then
195		locale="C"
196	fi
197	echo "system_locale=$locale" >> ${SYSIDCFG}
198	timezone=`/bin/grep "^TZ" /etc/TIMEZONE|cut -d "=" -f2`
199	echo "timezone=$timezone" >> ${SYSIDCFG}
200	echo "terminal=vt100" >> ${SYSIDCFG}
201	rootpwd=`/bin/grep "^root:" /etc/shadow|cut -d ":" -f2`
202	echo "root_password=$rootpwd" >> ${SYSIDCFG}
203	echo "network_interface=PRIMARY {" >> ${SYSIDCFG}
204	echo "protocol_ipv6=no" >> ${SYSIDCFG}
205	echo "hostname=$hostname" >> ${SYSIDCFG}
206	echo "ip_address=$ipaddress }" >> ${SYSIDCFG}
207	cp /etc/default/nfs ${ZONE_ETC_DIR}/default/nfs
208	touch ${ZONE_ETC_DIR}/.NFS4inst_state.domain
209}
210
211install() {
212	# if there is a zfs pool for zone
213	# create a new dataset for the zone
214	# This step is done automatically by zonecfg
215	# in Solaris Express 8/06 or newer
216
217	zp=`zpool list -H zone 2>/dev/null`
218	if [ $? = 0 ]; then
219		zfs create zone/$zonename
220		chmod 700 /zone/$zonename
221	fi
222
223	/usr/bin/gnome-terminal \
224	    --title="$title: Installing $zonename zone" \
225	    --command "zoneadm -z $zonename install" \
226	    --hide-menubar
227
228	initialize
229}
230
231delete() {
232	# if there is an entry for this zone in tnzonecfg, remove it
233	# before deleting the zone.
234
235	tnzone=`egrep "^$zonename:" /etc/security/tsol/tnzonecfg 2>/dev/null`
236	if [ -n "${tnzone}" ]; then
237		sed -e "/^$tnzone:*/d" /etc/security/tsol/tnzonecfg > \
238		    /tmp/tnzonefg.$$ 2>/dev/null
239		mv /tmp/tnzonefg.$$ /etc/security/tsol/tnzonecfg
240	fi
241	zonecfg -z $zonename delete -F
242	zonename=
243}
244
245getNIC(){
246
247	nics=
248	for i in `ifconfig -a4|grep  "^[a-z].*:" |grep -v LOOPBACK`
249	do
250		echo $i |grep "^[a-z].*:" >/dev/null 2>&1
251		if [ $? -eq 1 ]; then
252			continue
253		fi
254		i=${i%:} # Remove colon after interface name
255		echo $i |grep ":" >/dev/null 2>&1
256		if [ $? -eq 0 ]; then
257			continue
258		fi
259		nics="$nics $i"
260	done
261
262	nic=$(zenity --list \
263	    --title="$title" \
264	    --column="Interface" \
265	    $nics)
266}
267
268getNetmask() {
269
270	cidr=
271	nm=$(zenity --entry \
272	    --title="$title" \
273	    --text="$ipaddr: Enter netmask: " \
274	    --entry-text 255.255.255.0)
275	if [ $? != 0 ]; then
276	       return;
277	fi
278
279	cidr=`perl -e 'use Socket; print unpack("%32b*",inet_aton($ARGV[0])), "\n";' $nm`
280}
281
282addNet() {
283	getNIC
284	if [[ -z $nic ]]; then
285		return;
286	fi
287	getIPaddr
288	if [[ -z $ipaddr ]]; then
289		return;
290	fi
291	getNetmask
292	if [[ -z $cidr ]]; then
293		return;
294	fi
295	zcfg="
296add net
297set address=${ipaddr}/${cidr}
298set physical=$nic
299end
300commit
301"
302	echo "$zcfg" > $config ;
303	zonecfg -z $zonename -f $config ;
304	rm $config
305}
306
307getAttrs() {
308	zone=global
309	type=ignore
310	for j in `ifconfig $nic`
311	do
312		case $j in
313			inet) type=$j;;
314			zone) type=$j;;
315			all-zones) zone=all-zones;;
316			flags*) flags=$j;;
317			*) case $type in
318				inet) ipaddr=$j ;;
319				zone) zone=$j ;;
320				*) continue ;;
321			   esac;\
322			   type=ignore;;
323		esac
324	done
325	if [ $ipaddr != 0.0.0.0 ]; then
326		template=`tninfo -h $ipaddr|grep Template| cut -d" " -f3`
327	else
328		template="..."
329		ipaddr="..."
330	fi
331}
332
333updateTnrhdb() {
334	tnctl -h ${ipaddr}:$template
335	x=`grep "^${ipaddr}[^0-9]" /etc/security/tsol/tnrhdb`
336	if [ $? = 0 ]; then
337		sed s/$x/${ipaddr}:$template/g /etc/security/tsol/tnrhdb \
338		    > /tmp/txnetmgr.$$
339		mv /tmp/txnetmgr.$$ /etc/security/tsol/tnrhdb
340	else
341		echo ${ipaddr}:$template >> /etc/security/tsol/tnrhdb
342	fi
343}
344
345getIPaddr() {
346        hostname=$(zenity --entry \
347            --title="$title" \
348            --text="$nic: Enter hostname: ")
349
350        if [ $? != 0 ]; then
351               return;
352	fi
353
354	ipaddr=`getent hosts $hostname|cut -f1`
355        if [[ -z $ipaddr ]]; then
356
357		ipaddr=$(zenity --entry \
358		    --title="$title" \
359		    --text="$nic: Enter IP address: " \
360		    --entry-text a.b.c.d)
361		if [ $? != 0 ]; then
362		       return;
363		fi
364	fi
365
366}
367
368addHost() {
369	# Update hosts and ipnodes
370        if [[ -z $ipaddr ]]; then
371               return;
372	fi
373	grep "^${ipaddr}[^0-9]" /etc/inet/hosts >/dev/null
374	if [ $? -eq 1 ]; then
375		echo "$ipaddr\t$hostname" >> /etc/inet/hosts
376	fi
377
378	grep "^${ipaddr}[^0-9]" /etc/inet/ipnodes >/dev/null
379	if [ $? -eq 1 ]; then
380		echo "$ipaddr\t$hostname" >> /etc/inet/ipnodes
381	fi
382
383	template=cipso
384	updateTnrhdb
385
386	ifconfig $nic $ipaddr netmask + broadcast +
387	echo $hostname > /etc/hostname.$nic
388}
389
390getTemplate() {
391	templates=$(cat /etc/security/tsol/tnrhtp|\
392	    grep "^[A-z]"|grep "type=cipso"|cut -f1 -d":")
393
394	while [ 1 -gt 0 ]; do
395		t_cmd=$(zenity --list \
396		    --title="$title" \
397		    --height=300 \
398		    --column="Network Templates" \
399		    $templates)
400
401		if [ $? != 0 ]; then
402		       break;
403		fi
404
405		t_label=$(tninfo -t $t_cmd | grep sl|zenity --list \
406		    --title="$title" \
407		    --height=300 \
408		    --width=450 \
409		    --column="Click OK to associate $t_cmd template with $ipaddr" )
410
411		if [ $? != 0 ]; then
412			continue
413		fi
414		template=$t_cmd
415		updateTnrhdb
416		break
417	done
418}
419
420createInterface() {
421	msg=`ifconfig $nic addif 0.0.0.0`
422	$(zenity --info \
423	    --title="$title" \
424	    --text="$msg" )
425}
426
427shareInterface() {
428	ifconfig $nic all-zones;\
429	if_file=/etc/hostname.$nic
430	sed q | sed -e "s/$/ all-zones/" < $if_file >/tmp/txnetmgr.$$
431	mv /tmp/txnetmgr.$$ $if_file
432}
433
434setMacPrivs() {
435	zcfg="
436set limitpriv=default,win_mac_read,win_mac_write,win_selection,win_dac_read,win_dac_write,file_downgrade_sl,file_upgrade_sl,sys_trans_label
437commit
438"
439	echo "$zcfg" > $config ;
440	zonecfg -z $zonename -f $config ;
441	rm $config
442}
443
444resetMacPrivs() {
445	zcfg="
446set limitpriv=default
447commit
448"
449	echo "$zcfg" > $config ;
450	zonecfg -z $zonename -f $config ;
451	rm $config
452}
453
454sharePasswd() {
455	passwd=`zonecfg -z $zonename info|grep /etc/passwd`
456	if [[ $? -eq 1 ]]; then
457		zcfg="
458add fs
459set special=/etc/passwd
460set dir=/etc/passwd
461set type=lofs
462end
463add fs
464set special=/etc/shadow
465set dir=/etc/shadow
466set type=lofs
467end
468commit
469"
470		echo "$zcfg" > $config ;
471		zonecfg -z $zonename -f $config ;
472		rm $config
473	fi
474}
475
476manageNets() {
477	while [ 1 -gt 0 ]; do
478		attrs=
479		for i in `ifconfig -au4|grep  "^[a-z].*:" |grep -v LOOPBACK`
480		do
481			echo $i |grep "^[a-z].*:" >/dev/null 2>&1
482			if [ $? -eq 1 ]; then
483				continue
484			fi
485			nic=${i%:} # Remove colon after interface name
486			getAttrs
487			attrs="$nic $zone $ipaddr $template Up $attrs"
488		done
489
490		for i in `ifconfig -ad4 |grep  "^[a-z].*:" |grep -v LOOPBACK`
491		do
492			echo $i |grep "^[a-z].*:" >/dev/null 2>&1
493			if [ $? -eq 1 ]; then
494				continue
495			fi
496			nic=${i%:} # Remove colon after interface name
497			getAttrs
498			attrs="$nic $zone $ipaddr $template Down $attrs"
499		done
500
501		nic=$(zenity --list \
502		    --title="$title" \
503		    --height=300 \
504		    --width=450 \
505		    --column="Interface" \
506		    --column="Zone Name" \
507		    --column="IP Address" \
508		    --column="Template" \
509		    --column="State" \
510		    $attrs)
511
512		if [[ -z $nic ]]; then
513			return
514		fi
515
516		getAttrs
517
518		# Clear list of commands
519
520		share=
521		setipaddr=
522		settemplate=
523		newlogical=
524		unplumb=
525		bringup=
526		bringdown=
527
528		# Check for physical interface
529
530		hascolon=`echo $nic |grep :`
531		if [ $? != 0 ]; then
532			newlogical="Create Logical Interface\n";
533		else
534			up=`echo $flags|grep "UP,"`
535			if [ $? != 0 ]; then
536				unplumb="Remove Logical Interface\n"
537				if [ $ipaddr != "..." ]; then
538					bringup="Bring Up\n"
539				fi
540			else
541				bringdown="Bring Down\n"
542			fi
543		fi
544
545		if [ $ipaddr = "..." ]; then
546			setipaddr="Set IP address...\n";
547		else
548			settemplate="View Templates...\n"
549			if [ $zone = global ]; then
550				share="Share\n"
551			fi
552		fi
553
554		command=$(echo ""\
555		    $share \
556		    $setipaddr \
557		    $settemplate \
558		    $newlogical \
559		    $unplumb \
560		    $bringup \
561		    $bringdown \
562		    | zenity --list \
563		    --title="$title" \
564		    --height=300 \
565		    --column "Interface: $nic" )
566
567		case $command in
568		    " Create Logical Interface")\
569			createInterface;;
570		    " Set IP address...")\
571			getIPaddr
572			addHost;;
573		    " Share")\
574			shareInterface;;
575		    " View Templates...")\
576			getTemplate;;
577		    " Remove Logical Interface")\
578			ifconfig $nic unplumb;\
579			rm -f /etc/hostname.$nic;;
580		    " Bring Up")\
581			ifconfig $nic up;;
582		    " Bring Down")\
583			ifconfig $nic down;;
584		    *) continue;;
585		esac
586	done
587}
588
589# Main loop for top-level window
590#
591# Always display vni0 since it is useful for cross-zone networking
592#
593ifconfig vni0 > /dev/null 2>&1
594if [ $? != 0 ]; then
595	ifconfig vni0 plumb >/dev/null 2>&1
596fi
597while [ "${command}" != Exit ]; do
598	if [[ ! -n $zonename ]]; then
599		zonelist=""
600		for p in `zoneadm list -cp|grep -v global:`; do
601			zonename=`echo $p|cut -d : -f2`
602			state=`echo $p|cut -d : -f3`
603			labelCheck
604			zonelist="$zonelist$zonename\n$state\n$curlabel\n"
605		done
606
607		zonelist="${zonelist}Create a new zone...\n\n\nManage Network Interfaces...\n\n"
608		zonename=$(echo $zonelist|zenity --list \
609		    --title="$title" \
610		    --height=300 \
611		    --width=500 \
612		    --column="Zone Name" \
613		    --column="Status" \
614		    --column="Sensitivity Label" \
615		    )
616
617		if [[ ! -n $zonename ]]; then
618			exit
619		fi
620
621		if [ "$zonename" = "Manage Network Interfaces..." ]; then
622			zonename=
623			manageNets
624			continue
625		elif [ "$zonename" = "Create a new zone..." ]; then
626			zonename=$(zenity --entry \
627			    --title="$title" \
628			    --entry-text="" \
629			    --text="Enter Zone Name: ")
630
631			if [[ ! -n $zonename ]]; then
632				continue
633			fi
634
635			zcfg="
636create -t SUNWtsoldef
637set zonepath=/zone/$zonename
638commit
639"
640			echo "$zcfg" > $config ;
641			zonecfg -z $zonename -f $config ;
642			rm $config
643		fi
644	fi
645
646	# Clear list of commands
647
648	console=
649	label=
650	start=
651	reboot=
652	stop=
653	clone=
654	copy=
655	install=
656	ready=
657	uninstall=
658	delete=
659	snapshot=
660	addnet=
661	deletenet=
662	permitrelabel=
663
664	zonestate=`zoneadm -z $zonename list -p | cut -d ":" -f 3`
665
666	consoleCheck;
667	labelCheck;
668	delay=0
669
670	case $zonestate in
671		running) ready="Ready\n"; \
672		       reboot="Reboot\n"; \
673		       stop="Halt\n"; \
674		;;
675		ready) start="Boot\n"; \
676		       stop="Halt\n" \
677		;;
678		installed)
679			if [[ -z $label ]]; then \
680				ready="Ready\n"; \
681				start="Boot\n"; \
682			fi; \
683			uninstall="Uninstall\n"; \
684			snapshotCheck; \
685			relabelCheck;
686			addnet="Add Network...\n"
687		;;
688		configured) install="Install...\n"; \
689			copyCheck; \
690			delete="Delete\n"; \
691			console=; \
692		;;
693		incomplete) delete="Delete\n"; \
694		;;
695		*)
696		;;
697	esac
698
699	command=$(echo ""\
700	    $console \
701	    $label \
702	    $start \
703	    $reboot \
704	    $stop \
705	    $clone \
706	    $copy \
707	    $install \
708	    $ready \
709	    $uninstall \
710	    $delete \
711	    $snapshot \
712	    $addnet \
713	    $deletenet \
714	    $permitrelabel \
715	    "Select another zone...\n" \
716	    "Exit" \
717	    | zenity --list \
718	    --title="$title" \
719	    --height=300 \
720	    --column "$zonename: $zonestate" )
721
722	case $command in
723	    " Zone Console...")
724		delay=2; \
725		/usr/bin/gnome-terminal \
726		    --title="Zone Terminal Console: $zonename" \
727		    --command "/usr/sbin/zlogin -C $zonename" &;;
728
729	    " Select Label...")
730		selectLabel;;
731
732	    " Ready")
733		zoneadm -z $zonename ready ;;
734
735	    " Boot")
736		zoneadm -z $zonename boot ;;
737
738	    " Halt")
739		zoneadm -z $zonename halt ;;
740
741	    " Reboot")
742		zoneadm -z $zonename reboot ;;
743
744	    " Install...")
745		install;;
746
747	    " Clone")
748		clone ;;
749
750	    " Copy...")
751		copy ;;
752
753	    " Uninstall")
754		zoneadm -z $zonename uninstall -F;;
755
756	    " Delete")
757		delete ;;
758
759	    " Create Snapshot")
760		zfs snapshot zone/${zonename}@snapshot;;
761
762	    " Add Network...")
763		addNet ;;
764
765	    " Permit Relabeling")
766		setMacPrivs ;;
767
768	    " Deny Relabeling")
769		resetMacPrivs ;;
770
771	    " Select another zone...")
772		zonename= ;;
773
774	    *)
775		exit ;;
776	esac
777	sleep $delay;
778done
779