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