#!/bin/ksh
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
# Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
#
NSCD_INDICATOR=/var/tsol/doors/nscd_per_label
export LANG=C
# The labeled_parseNet function is used by functions in this file
# and by txzonemgr. So changes must be verified in both places.
# The function takes either a zonecfg net or anet resource, passed in
# via $net. It parses the keywords, and sets the following variables:
#
# ipaddr - the IP address, including the cidr suffix if present
# defaultrouter -if present
# physical - the corresponding global zone interface
function labeled_parseNet {
typeset alpha
ipaddr="..."
linkname="..."
vlan_id="..."
shift 1
while (( $# > 1)) do
case $1 in
"lower-link:")
physical=$2
;;
"physical:")
physical=$2
;;
"address:")
if [ $2 != "..." ]; then
ipaddr="$2"
fi
;;
"allowed-address:")
if [ $2 != "..." ]; then
ipaddr="$2"
fi
;;
"defrouter:")
defrouter="$2"
;;
"linkname:")
linkname=$2
;;
"vlan-id:")
vlan_id=$2
;;
esac
shift 1
done
#
# If address is a hostname, return IP address
#
alpha=$(echo $ipaddr|grep ^[A-z]|grep -v :)
if [[ ! -z $alpha ]]; then
ipaddr=$(getent hosts $ipaddr|nawk '{print $1}')
if [[ -z $ipaddr ]] ; then
ipaddr="..."
fi
fi
}
# The _getIPconfig function is only used in this file.
# It is used to determine the hostname and IP address
# of the labeled zone. In addition to the variables set
# by labeled_parseNet, it also sets the variable $hostname.
function _getIPconfig {
typeset hostattr
typeset cidr
ipType=$(zonecfg -z $ZONENAME info ip-type|cut -d" " -f2)
if [ $ipType = exclusive ] ; then
net=$(zonecfg -z $ZONENAME info anet 2>/dev/null)
else
net=$(zonecfg -z $ZONENAME info net 2>/dev/null)
fi
if [[ ! -n $net ]]; then
hostname=$(hostname)
ipaddr=127.0.0.1
return 1
fi
net=$(echo $net|sed 's/ not specified/: .../g')
labeled_parseNet $net
if [ $ipaddr = ... ]; then
ipaddr=127.0.0.1
return 1
fi
hostattr=$(zonecfg -z $ZONENAME info attr name=hostname 2>/dev/null)
if [[ -n $hostattr ]]; then
hostname=$(echo $hostattr|cut -d" " -f7)
return 0
else
cidr=$(echo $ipaddr|grep /|cut -f2 -d/)
if [[ -n $cidr ]]; then
# remove the optional cidr suffix
# which is input to getNetmask()
ipaddr=$(echo $ipaddr|cut -f1 -d/)
fi
getent=$(getent hosts $ipaddr)
if [ $? = 0 ]; then
hostname=$(echo $getent|nawk '{print $2}')
else
hostname=$ZONENAME
fi
return 0
fi
}
# The labeled_unsharePasswed function removes the passwd and shadow
# lofs mounts that are part of the shared name service configuration.
# This function is also called by txzonemgr so changes must be
# verified in both files.
function labeled_unsharePasswd {
zonecfg -z $1 remove fs dir=/etc/passwd >/dev/null 2>&1
zonecfg -z $1 remove fs dir=/etc/shadow >/dev/null 2>&1
}
# The labeled_sharePasswed function sets the passwd and shadow
# lofs mounts that are part of the shared name service configuration.
# This function is also called by txzonemgr so changes must be
# verified in both files.
function labeled_sharePasswd {
passwd=$(zonecfg -z $1 info|grep /etc/passwd)
if [ $? -eq 1 ] ; then
zonecfg -z $1 "add fs; \
set special=/etc/passwd; \
set dir=/etc/passwd; \
set type=lofs; \
add options ro; \
end" 2>/dev/null
fi
shadow=$(zonecfg -z $1 info|grep /etc/shadow)
if [ $? -eq 1 ] ; then
zonecfg -z $1 "add fs; \
set special=/etc/shadow; \
set dir=/etc/shadow; \
set type=lofs; \
add options ro; \
end" 2>/dev/null
fi
}
#
# The _auto_home function automates NFS sharing of the minimum labeled
# home directory with higher lableled zones. Reading the lowest
# labeled home directory is required by updatehome(1).
#
# An auto_home_<zonename> automap entry is created and stored in
# /var/tsol/doors/automount, which is then readable to all zones.
#
# Although zone administrators can configure their own automount
# entries, it is done automatically here to make things easier.
#
function _auto_home {
typeset ZONE_ETC_DIR=$l_zonepath/root/etc
typeset ZONE_AUTO_HOME=$ZONE_ETC_DIR/auto_home_$ZONENAME
typeset TNZONECFG=/etc/security/tsol/tnzonecfg
typeset AUTOMOUNTDIR=/var/tsol/doors/automount
if [ -f $NSCD_INDICATOR -a $1 = clone ] ; then
if [ ! -f $ZONE_AUTO_HOME -a $LOGNAME != "root" ]; then
echo "$LOGNAME\tlocalhost:/export/home/$LOGNAME" >> \
$ZONE_AUTO_HOME
fi
fi
# Find the labeled zone corresponding to the minimum label
typeset deflabel=$(chk_encodings -a|grep "Default User Sensitivity"|\
sed 's/= /=/'|sed 's/"/'''/g|cut -d"=" -f2)
typeset DEFAULTLABEL=$(atohexlabel "${deflabel}")
typeset minzone_entry=$(grep ${DEFAULTLABEL} $TNZONECFG)
if [[ ! -n $minzone_entry ]]; then
return
fi
typeset minzone=$(echo $minzone_entry|cut -d: -f1)
typeset am=auto_home_$minzone
if [ $minzone = $ZONENAME ]; then
# If the current zone has the minimum label,
# check if its home directories can be shared.
# An explicit IP address assignment is required
# for a zone to be a multilevel NFS server.
_getIPconfig || return
# Save the automount entry for other zones to import
if [ ! -d $AUTOMOUNTDIR ] ; then
mkdir $AUTOMOUNTDIR
fi
echo "+$am" > $AUTOMOUNTDIR/$am
echo "* ${ipaddr}:/export/home/&" \
>> $AUTOMOUNTDIR/$am
# Configure multilevel NFS ports if
# this hasn't been done already.
tncfg -z $ZONENAME "add mlp_private=111/tcp;\
add mlp_private=111/udp;\
add mlp_private=2049/tcp" >/dev/null 2>&1
else
# If an automount map exists, then copy it into the higher
# labeled zone.
if [ -f $AUTOMOUNTDIR/$am ]; then
cp $AUTOMOUNTDIR/$am $ZONE_ETC_DIR/$am
mountpoint="/zone/${minzone}/home"
# Add map to auto_master if necessary
entry=$(grep ^$mountpoint $ZONE_ETC_DIR/auto_master)
if [ $? != 0 ] ;then
entry="$mountpoint $am -nobrowse"
echo $entry >> $ZONE_ETC_DIR/auto_master
fi
else
rm $ZONE_ETC_DIR/$am 2>/dev/null
fi
fi
}
# The labeled_printsysconfig function generates a custom
# SC profile for a labeled zone using properies from the
# zone's configuration file and global zone settings.
function labeled_printsysconfig {
typeset fmtsvc='<service name="%s" version="1" type="service">\n<instance name="%s" enabled="true">\n'
typeset fmtgrp='<property_group name="%s" type="%s">\n'
typeset fmtval='<propval name="%s" type="%s" value="%s"/>\n'
typeset fmtendsvc='</property_group>\n</instance>\n</service>\n'
print '<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">'
print '<service_bundle type="profile" name="system configuration">'
printf "$fmtsvc" milestone/config default
printf "$fmtgrp" configuration application
printf "$fmtval" configure boolean true
printf "$fmtval" interactive_config boolean false
printf "$fmtval" config_groups astring $1
printf "$fmtendsvc"
typeset ldap=$(svcprop -p general/enabled ldap/client)
if [ $ldap = true ] ; then
printf "$fmtsvc" network/ldap/client default
printf "$fmtgrp" config application
searchbase=$(svcprop -p config/search_base network/ldap/client)
printf "$fmtval" search_base astring "$searchbase"
serverlist=$(svcprop -p config/server_list network/ldap/client)
printf "$fmtval" server_list astring "$serverlist"
profName=$(svcprop -p config/profile network/ldap/client)
printf "$fmtval" profile astring $profName
print '</property_group>'
printf "$fmtgrp" cred application
profDN=$(svcprop -p cred/bind_dn network/ldap/client)
printf "$fmtval" bind_dn astring $profDN
profPwd=$(ldapclient list | \
grep "^NS_LDAP_BINDPASSWD" | cut -d " " -f2)
printf "$fmtval" bind_passwd astring $profPwd
printf "$fmtendsvc"
printf "$fmtsvc" system/name-service/switch default
printf "$fmtgrp" config application
printf "$fmtval" default astring "files ldap"
printf "$fmtval" netgroup astring "ldap"
printf "$fmtendsvc"
fi
_getIPconfig
printf "$fmtsvc" system/identity node
printf "$fmtgrp" config application
printf "$fmtval" nodename astring $hostname
printf "$fmtendsvc"
typeset locale=$(svcprop -p environment/LANG system/environment:init 2>/dev/null)
if [ $? = 0 -a $locale != '""' ]; then
printf "$fmtsvc" system/environment init
printf "$fmtgrp" environment application
printf "$fmtval" LANG astring $locale
printf "$fmtendsvc"
fi
typeset timezone=$(svcprop -p timezone/localtime system/timezone:default)
printf "$fmtsvc" system/timezone default
printf "$fmtgrp" timezone application
printf "$fmtval" localtime astring $timezone
printf "$fmtendsvc"
printf "$fmtsvc" system/console-login default
printf "$fmtgrp" ttymon application
printf "$fmtval" terminal_type astring vt100
printf "$fmtendsvc"
if [ -f $NSCD_INDICATOR -a $LOGNAME != "root" ]; then
printf "$fmtsvc" system/config-user default
printf "$fmtgrp" root_account application
rootpwd=$(grep "^root:" /etc/shadow|cut -d : -f2)
printf "$fmtval" password astring $rootpwd
printf "$fmtval" type astring role
print '</property_group>'
printf "$fmtgrp" user_account application
printf "$fmtval" login astring gfaden
userpwd=$(grep "^${LOGNAME}:" /etc/shadow|cut -d : -f2)
printf "$fmtval" password astring $userpwd
printf "$fmtval" roles astring root
getent passwd $LOGNAME|while IFS=: \
read name pw uid gid descr home shell; do
printf "$fmtval" uid astring $uid
printf "$fmtval" gid astring $gid
printf "$fmtval" description astring "$descr"
printf "$fmtval" shell astring $shell
done
printf "$fmtendsvc"
fi
print '</service_bundle>'
}
# The labeled_reconfigure function is used to generate a
# a customized SC profile for a cloned zone, and to setup
# some nameservice-specific properties for the user account.
# It is called by the common clone code when the user runs zoneadm
# without specifying a SC profile for a labeled zone.
# $1 specifies how much to configure.
# possible values are "system,identity,network,location,users"
#
# $2 specifies if the unconfiguration should be destructive
# possible values are --destructive and null
# Returns 0 if successful, and 1 if mount failure
function labeled_reconfigure {
if [ -f $NSCD_INDICATOR ] ; then
labeled_unsharePasswd $ZONENAME
else
labeled_sharePasswd $ZONENAME
fi
# change "system" to "users" when partial
# reconfiguration is supported
l_zonepath=$(zoneadm -z $ZONENAME list -p|cut -d : -f4)
zoneadm -z $ZONENAME mount -f
typeset zonestate=$(zoneadm -z $ZONENAME list -p | cut -d : -f 3)
if [ $zonestate != mounted ] ; then
gettext "error getting zone $ZONENAME mounted.\n"
return 1
fi
_auto_home clone
typeset configured SCPROFILE ZONE_PROFILE_DIR
configured=$l_zonepath/root/var/svc/log/milestone-config:default.log
# A zone can't be unconfigured until it is configured
# so if the config service has no log file yet we assume
# if has never been configured, and we can just place
# the profile in the site directory.
if [ ! -f $configured ]; then
ZONE_PROFILE_DIR=$l_zonepath/root/etc/svc/profile/site
SCPROFILE=${ZONE_PROFILE_DIR}/sc_profile.xml
touch $SCPROFILE
chmod 400 $SCPROFILE
labeled_printsysconfig system >$SCPROFILE
elif ([ -f $NSCD_INDICATOR ] || _getIPconfig); then
ZONE_PROFILE_DIR=$l_zonepath/lu/system/volatile
SCPROFILE_TMP=$(mktemp ${ZONE_PROFILE_DIR}/sc_profile-XXXX)
SCPROFILE=${SCPROFILE_TMP}.xml
mv $SCPROFILE_TMP $SCPROFILE
labeled_printsysconfig $1 >$SCPROFILE
typeset SC_CONFIG_BASE=$(basename $SCPROFILE)
zlogin -S $ZONENAME "export _UNCONFIG_ALT_ROOT=/a; \
/usr/sbin/sysconfig configure -g $1 \
-c /system/volatile/$SC_CONFIG_BASE $2"
fi
zoneadm -z $ZONENAME unmount
return $?
}
# The labeled_configure function is used to setup the
# some nameservice-specific properties for the user account.
# It is called by common pkgcreatezone code after a labeled zone
# has been installed, to set up user account properties
function labeled_configure {
typeset l_zonepath=$(zoneadm -z $ZONENAME list -p|cut -d : -f4)
_auto_home install
if [ -f $NSCD_INDICATOR ] ; then
labeled_unsharePasswd $ZONENAME
else
labeled_sharePasswd $ZONENAME
fi
}
# The labeled_makeSCprofile() function is used to create
# a customized SC profile for a new labeled zone.
# It is called by the common pkgcreatezone code when user runs
# zoneadm without specifying a SC profile for a labeled zone.
# The pathname of the new SC profile is set in
# the variable $temp_scprofile which is then passed to
# auto-install in the common pkgcreatezone code.
function labeled_makeSCprofile {
temp_scprofile=$(mktemp -t sc_profile.XXXX)
if [[ -z $temp_scprofile ]]; then
print "$f_mktemp"
exit $ZONE_SUBPROC_NOTCOMPLETE
fi
mv $temp_scprofile ${temp_scprofile}.xml
temp_scprofile=${temp_scprofile}.xml
labeled_printsysconfig system >$temp_scprofile
}