xref: /onnv-gate/usr/src/cmd/krb5/kadmin/kclient/kclient.sh (revision 12566:8c45f76d0972)
16815Ssemery#!/bin/ksh93 -p
20Sstevel@tonic-gate#
36656Ssemery# CDDL HEADER START
46656Ssemery#
56656Ssemery# The contents of this file are subject to the terms of the
66656Ssemery# Common Development and Distribution License (the "License").
76656Ssemery# You may not use this file except in compliance with the License.
86656Ssemery#
96656Ssemery# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
106656Ssemery# or http://www.opensolaris.org/os/licensing.
116656Ssemery# See the License for the specific language governing permissions
126656Ssemery# and limitations under the License.
136656Ssemery#
146656Ssemery# When distributing Covered Code, include this CDDL HEADER in each
156656Ssemery# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
166656Ssemery# If applicable, add the following below this CDDL HEADER, with the
176656Ssemery# fields enclosed by brackets "[]" replaced with your own identifying
186656Ssemery# information: Portions Copyright [yyyy] [name of copyright owner]
196656Ssemery#
206656Ssemery# CDDL HEADER END
216656Ssemery#
2211570SShawn.Emery@Sun.COM# Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate# Use is subject to license terms.
240Sstevel@tonic-gate#
250Sstevel@tonic-gate# This script is used to setup the Kerberos client by
260Sstevel@tonic-gate# supplying information about the Kerberos realm and kdc.
270Sstevel@tonic-gate#
280Sstevel@tonic-gate# The kerberos configuration file (/etc/krb5/krb5.conf) would
290Sstevel@tonic-gate# be generated and local host's keytab file setup. The script
300Sstevel@tonic-gate# can also optionally setup the system to do kerberized nfs and
310Sstevel@tonic-gate# bringover a master krb5.conf copy from a specified location.
3211061SShawn.Emery@Sun.COM#
330Sstevel@tonic-gate
346656Ssemeryfunction cleanup {
356656Ssemery
369833SShawn.Emery@Sun.COM	kdestroy -q > $TMP_FILE 2>&1
376656Ssemery	rm -r $TMPDIR > /dev/null 2>&1
386656Ssemery
399833SShawn.Emery@Sun.COM	exit $1
406656Ssemery}
416656Ssemeryfunction exiting {
426656Ssemery
436656Ssemery        printf "\n$(gettext "Exiting setup, nothing changed").\n\n"
446656Ssemery
456656Ssemery	cleanup $1
460Sstevel@tonic-gate}
470Sstevel@tonic-gate
486656Ssemeryfunction error_message {
496656Ssemery
509833SShawn.Emery@Sun.COM        printf -- "---------------------------------------------------\n" >&2
519833SShawn.Emery@Sun.COM        printf "$(gettext "Setup FAILED").\n\n" >&2
526656Ssemery
536656Ssemery        cleanup 1
546656Ssemery}
556656Ssemery
566656Ssemeryfunction check_bin {
576656Ssemery
586656Ssemery	typeset bin=$1
596656Ssemery
606656Ssemery	if [[ ! -x $bin ]]; then
619833SShawn.Emery@Sun.COM		printf "$(gettext "Could not access/execute %s").\n" $bin >&2
620Sstevel@tonic-gate		error_message
630Sstevel@tonic-gate	fi
640Sstevel@tonic-gate}
650Sstevel@tonic-gate
666656Ssemeryfunction cannot_create {
676656Ssemery	typeset filename="$1"
686656Ssemery	typeset stat="$2"
696656Ssemery
706656Ssemery	if [[ $stat -ne 0 ]]; then
716656Ssemery		printf "\n$(gettext "Can not create/edit %s, exiting").\n" $filename >&2
726656Ssemery		error_message
736656Ssemery	fi
746656Ssemery}
756656Ssemery
766656Ssemeryfunction update_pam_conf {
776656Ssemery	typeset PAM TPAM service
786656Ssemery
796656Ssemery	PAM=/etc/pam.conf
806656Ssemery
816656Ssemery	TPAM=$(mktemp -q -t kclient-pamconf.XXXXXX)
826656Ssemery	if [[ -z $TPAM ]]; then
836656Ssemery		printf "\n$(gettext "Can not create temporary file, exiting").\n" >&2
846656Ssemery		error_message
856656Ssemery	fi
866656Ssemery
876656Ssemery	cp $PAM $TPAM >/dev/null 2>&1
886656Ssemery
896656Ssemery	printf "$(gettext "Configuring %s").\n\n" $PAM
906656Ssemery
916656Ssemery	for service in $SVCs; do
926656Ssemery		svc=${service%:*}
936656Ssemery		auth_type=${service#*:}
946656Ssemery		if egrep -s "^$svc[ 	][ 	]*auth.*pam_krb5*" $TPAM; then
956815Ssemery			printf "$(gettext "The %s service is already configured for pam_krb5, please merge this service in %s").\n\n" $svc $PAM >&2
966656Ssemery			continue
976656Ssemery		else
986656Ssemery			exec 3>>$TPAM
996815Ssemery			printf "\n$svc\tauth include\t\tpam_krb5_$auth_type\n" 1>&3
1006656Ssemery		fi
1016656Ssemery	done
1026656Ssemery
1036656Ssemery	cp $TPAM $PAM > /dev/null 2>&1
1046656Ssemery
1056656Ssemery	rm $TPAM > /dev/null 2>&1
1066656Ssemery}
1076656Ssemery
1086656Ssemeryfunction modify_nfssec_conf {
1096656Ssemery	typeset NFSSEC_FILE="/etc/nfssec.conf"
1106656Ssemery
1116656Ssemery	if [[ -r $NFSSEC_FILE ]]; then
1120Sstevel@tonic-gate		cat $NFSSEC_FILE > $NFSSEC_FILE.sav
1130Sstevel@tonic-gate		cannot_create $NFSSEC_FILE.sav $?
1140Sstevel@tonic-gate	fi
1150Sstevel@tonic-gate
1160Sstevel@tonic-gate	cat $NFSSEC_FILE > $TMP_FILE
1170Sstevel@tonic-gate	cannot_create $TMP_FILE $?
1180Sstevel@tonic-gate
1190Sstevel@tonic-gate	if grep -s "#krb5" $NFSSEC_FILE > /dev/null 2>&1; then
1200Sstevel@tonic-gate		sed "s%^#krb5%krb5%" $TMP_FILE >$NFSSEC_FILE
1210Sstevel@tonic-gate		cannot_create $NFSSEC_FILE $?
1220Sstevel@tonic-gate	fi
1230Sstevel@tonic-gate}
1240Sstevel@tonic-gate
1256656Ssemeryfunction call_kadmin {
1260Sstevel@tonic-gate	typeset svc="$1"
1270Sstevel@tonic-gate	typeset bool1 bool2 bool3 bool4
1286656Ssemery	typeset service_princ getprincsubcommand anksubcommand ktaddsubcommand
1296656Ssemery	typeset ktremsubcommand
1300Sstevel@tonic-gate
1310Sstevel@tonic-gate	for listentry in $fqdnlist; do
1320Sstevel@tonic-gate
1330Sstevel@tonic-gate	# Reset conditional vars to 1
1340Sstevel@tonic-gate	bool1=1; bool2=1; bool3=1; bool4=1
1350Sstevel@tonic-gate
1366656Ssemery	service_princ=$(echo "${svc}/${listentry}")
1370Sstevel@tonic-gate	getprincsubcommand="getprinc $service_princ"
1380Sstevel@tonic-gate	anksubcommand="addprinc -randkey $service_princ"
1390Sstevel@tonic-gate	ktaddsubcommand="ktadd $service_princ"
1406656Ssemery	ktremsubcommand="ktrem $service_princ all"
1410Sstevel@tonic-gate
1426656Ssemery	kadmin -c $KRB5CCNAME -q "$getprincsubcommand" 1>$TMP_FILE 2>&1
1430Sstevel@tonic-gate
1446815Ssemery	egrep -s "$(gettext "get_principal: Principal does not exist")" $TMP_FILE
1450Sstevel@tonic-gate	bool1=$?
1466815Ssemery	egrep -s "$(gettext "get_principal: Operation requires ``get")" $TMP_FILE
1470Sstevel@tonic-gate	bool2=$?
1480Sstevel@tonic-gate
1490Sstevel@tonic-gate	if [[ $bool1 -eq 0 || $bool2 -eq 0 ]]; then
1506656Ssemery		kadmin -c $KRB5CCNAME -q "$anksubcommand" 1>$TMP_FILE 2>&1
1510Sstevel@tonic-gate
1526815Ssemery		egrep -s "$(gettext "add_principal: Principal or policy already exists while creating \"$service_princ@$realm\".")" $TMP_FILE
1530Sstevel@tonic-gate		bool3=$?
1540Sstevel@tonic-gate
1556815Ssemery		egrep -s "$(gettext "Principal \"$service_princ@$realm\" created.")" $TMP_FILE
1560Sstevel@tonic-gate		bool4=$?
1570Sstevel@tonic-gate
1580Sstevel@tonic-gate		if [[ $bool3 -eq 0 || $bool4 -eq 0 ]]; then
1590Sstevel@tonic-gate			printf "$(gettext "%s entry ADDED to KDC database").\n" $service_princ
1600Sstevel@tonic-gate		else
1610Sstevel@tonic-gate			cat $TMP_FILE;
1626656Ssemery			printf "\n$(gettext "kadmin: add_principal of %s failed, exiting").\n" $service_princ >&2
1630Sstevel@tonic-gate			error_message
1640Sstevel@tonic-gate		fi
1650Sstevel@tonic-gate	else
1666656Ssemery		printf "$(gettext "%s entry already exists in KDC database").\n" $service_princ >&2
1670Sstevel@tonic-gate	fi
1680Sstevel@tonic-gate
1690Sstevel@tonic-gate	klist -k 1>$TMP_FILE 2>&1
1706656Ssemery	egrep -s "$service_princ@$realm" $TMP_FILE
1716656Ssemery	if [[ $? -eq 0 ]]; then
1726656Ssemery		printf "$(gettext "%s entry already present in keytab").\n" $service_princ >&2
1736656Ssemery		# Don't care is this succeeds or not, just need to replace old
1746656Ssemery		# entries as it is assummed that the client is reinitialized
1756656Ssemery		kadmin -c $KRB5CCNAME -q "$ktremsubcommand" 1>$TMP_FILE 2>&1
1766656Ssemery	fi
1776656Ssemery
1786656Ssemery	kadmin -c $KRB5CCNAME -q "$ktaddsubcommand" 1>$TMP_FILE 2>&1
1796815Ssemery	egrep -s "$(gettext "added to keytab WRFILE:$KRB5_KEYTAB_FILE.")" $TMP_FILE
1806656Ssemery	if [[ $? -ne 0 ]]; then
1816656Ssemery		cat $TMP_FILE;
1826656Ssemery		printf "\n$(gettext "kadmin: ktadd of %s failed, exiting").\n" $service_princ >&2
1836656Ssemery		error_message
1840Sstevel@tonic-gate	else
1856656Ssemery		printf "$(gettext "%s entry ADDED to keytab").\n" $service_princ
1860Sstevel@tonic-gate	fi
1870Sstevel@tonic-gate
1880Sstevel@tonic-gate	done
1890Sstevel@tonic-gate}
1900Sstevel@tonic-gate
1916656Ssemeryfunction writeup_krb5_conf {
1926656Ssemery	typeset dh
1930Sstevel@tonic-gate
1946656Ssemery	printf "\n$(gettext "Setting up %s").\n\n" $KRB5_CONFIG_FILE
1950Sstevel@tonic-gate
1966656Ssemery	exec 3>$KRB5_CONFIG
1976656Ssemery	if [[ $? -ne 0 ]]; then
1989833SShawn.Emery@Sun.COM		printf "\n$(gettext "Can not write to %s, exiting").\n" $KRB5_CONFIG >&2
1990Sstevel@tonic-gate		error_message
2000Sstevel@tonic-gate	fi
2010Sstevel@tonic-gate
2026656Ssemery	printf "[libdefaults]\n" 1>&3
2036656Ssemery	if [[ $no_keytab == yes ]]; then
2046656Ssemery		printf "\tverify_ap_req_nofail = false\n" 1>&3
2056656Ssemery	fi
2066656Ssemery	if [[ $dns_lookup == yes ]]; then
2076656Ssemery	    printf "\t$dnsarg = on\n" 1>&3
2086656Ssemery	    if [[ $dnsarg == dns_lookup_kdc ]]; then
2096656Ssemery		printf "\tdefault_realm = $realm\n" 1>&3
2106656Ssemery		printf "\n[domain_realm]\n" 1>&3
2116656Ssemery		if [[ -n $fkdc_list ]]; then
2126656Ssemery			for kdc in $fkdc_list; do
2136656Ssemery				printf "\t$kdc = $realm\n" 1>&3
2146656Ssemery			done
2156656Ssemery		fi
2166656Ssemery		printf "\t$FKDC = $realm\n" 1>&3
2176656Ssemery		printf "\t$client_machine = $realm\n" 1>&3
2186656Ssemery		if [[ -z $short_fqdn ]]; then
2196656Ssemery			printf "\t.$domain = $realm\n\n" 1>&3
2206656Ssemery		else
2216656Ssemery			printf "\t.$short_fqdn = $realm\n\n" 1>&3
2226656Ssemery		fi
2236656Ssemery		if [[ -n $domain_list ]]; then
2246656Ssemery			for dh in $domain_list; do
2256656Ssemery				printf "\t$dh = $realm\n" 1>&3
2266656Ssemery			done
2276656Ssemery		fi
2280Sstevel@tonic-gate	    else
2296656Ssemery		if [[ $dnsarg = dns_lookup_realm ]]; then
2306815Ssemery		    printf "\tdefault_realm = $realm\n" 1>&3
2316656Ssemery		    printf "\n[realms]\n" 1>&3
2326656Ssemery		    printf "\t$realm = {\n" 1>&3
2336656Ssemery		    if [[ -n $kdc_list ]]; then
2346656Ssemery			for kdc in $kdc_list; do
2356656Ssemery				printf "\t\tkdc = $kdc\n" 1>&3
2366656Ssemery			done
2376656Ssemery		    else
2386656Ssemery		    	printf "\t\tkdc = $KDC\n" 1>&3
2396656Ssemery		    fi
2406656Ssemery		    printf "\t\tadmin_server = $KDC\n" 1>&3
2416656Ssemery		    if [[ $non_solaris == yes ]]; then
2426656Ssemery			printf "\n\t\tkpasswd_protocol = SET_CHANGE\n" 1>&3
2436656Ssemery		    fi
2446656Ssemery		    printf "\t}\n\n" 1>&3
2450Sstevel@tonic-gate		else
2466815Ssemery		    printf "\tdefault_realm = $realm\n\n" 1>&3
2470Sstevel@tonic-gate		fi
2480Sstevel@tonic-gate	    fi
2490Sstevel@tonic-gate	else
2506656Ssemery	    printf "\tdefault_realm = $realm\n\n" 1>&3
2516656Ssemery
2526656Ssemery	    printf "[realms]\n" 1>&3
2536656Ssemery	    printf "\t$realm = {\n" 1>&3
2546656Ssemery	    if [[ -n $kdc_list ]]; then
2556656Ssemery		for kdc in $kdc_list; do
2566656Ssemery			printf "\t\tkdc = $kdc\n" 1>&3
2576656Ssemery		done
2586656Ssemery	    else
2596656Ssemery	    	printf "\t\tkdc = $KDC\n" 1>&3
2606656Ssemery	    fi
2616656Ssemery	    printf "\t\tadmin_server = $KDC\n" 1>&3
2626656Ssemery	    if [[ $non_solaris == yes ]]; then
2636656Ssemery	    	printf "\n\t\tkpasswd_protocol = SET_CHANGE\n" 1>&3
2646656Ssemery	    fi
2656656Ssemery	    printf "\t}\n\n" 1>&3
2660Sstevel@tonic-gate
2676656Ssemery	    printf "[domain_realm]\n" 1>&3
2686656Ssemery	    if [[ -n $fkdc_list ]]; then
2696656Ssemery		for kdc in $fkdc_list; do
2706656Ssemery			printf "\t$kdc = $realm\n" 1>&3
2716656Ssemery		done
2726656Ssemery	    fi
2736656Ssemery	    printf "\t$FKDC = $realm\n" 1>&3
2746656Ssemery	    printf "\t$client_machine = $realm\n" 1>&3
2756656Ssemery	    if [[ -z $short_fqdn ]]; then
2766656Ssemery		printf "\t.$domain = $realm\n\n" 1>&3
2776656Ssemery	    else
2786656Ssemery		printf "\t.$short_fqdn = $realm\n\n" 1>&3
2796656Ssemery	    fi
2806656Ssemery	    if [[ -n $domain_list ]]; then
2816656Ssemery		for dh in $domain_list; do
2826656Ssemery			printf "\t$dh = $realm\n" 1>&3
2836656Ssemery		done
2846656Ssemery	    fi
2850Sstevel@tonic-gate	fi
2860Sstevel@tonic-gate
2876656Ssemery	printf "[logging]\n" 1>&3
2886656Ssemery	printf "\tdefault = FILE:/var/krb5/kdc.log\n" 1>&3
2896656Ssemery	printf "\tkdc = FILE:/var/krb5/kdc.log\n" 1>&3
2906656Ssemery	printf "\tkdc_rotate = {\n\t\tperiod = 1d\n\t\tversions = 10\n\t}\n\n" 1>&3
2910Sstevel@tonic-gate
2926656Ssemery	printf "[appdefaults]\n" 1>&3
2936656Ssemery	printf "\tkinit = {\n\t\trenewable = true\n\t\tforwardable = true\n" 1>&3
2946656Ssemery	if [[ $no_keytab == yes ]]; then
2956656Ssemery		printf "\t\tno_addresses = true\n" 1>&3
2966656Ssemery	fi
2976656Ssemery	printf "\t}\n" 1>&3
2980Sstevel@tonic-gate}
2990Sstevel@tonic-gate
3006656Ssemeryfunction ask {
3016656Ssemery	typeset question=$1
3026656Ssemery	typeset default_answer=$2
3036656Ssemery
3046656Ssemery	if [[ -z $default_answer ]]; then
3056656Ssemery		printf "$question :"
3060Sstevel@tonic-gate	else
3076656Ssemery		printf "$question [$default_answer]: "
3080Sstevel@tonic-gate	fi
3090Sstevel@tonic-gate	read answer
3100Sstevel@tonic-gate	test -z "$answer" && answer="$default_answer"
3110Sstevel@tonic-gate}
3120Sstevel@tonic-gate
3136656Ssemeryfunction yesno {
3140Sstevel@tonic-gate	typeset question="$1"
3156656Ssemery
3166656Ssemery	answer=
3176656Ssemery	yn=`printf "$(gettext "y/n")"`
3186656Ssemery	y=`printf "$(gettext "y")"`
3196656Ssemery	n=`printf "$(gettext "n")"`
3206656Ssemery	yes=`printf "$(gettext "yes")"`
3216656Ssemery	no=`printf "$(gettext "no")"`
3226656Ssemery
3236656Ssemery	while [[ -z $answer ]]; do
3246656Ssemery		ask "$question" $yn
3256656Ssemery		case $answer in
3266656Ssemery			$y|$yes)	answer=yes;;
3276656Ssemery			$n|$no)		answer=no;;
3286656Ssemery			*)		answer=;;
3290Sstevel@tonic-gate		esac
3300Sstevel@tonic-gate	done
3310Sstevel@tonic-gate}
3320Sstevel@tonic-gate
3336656Ssemeryfunction query {
3340Sstevel@tonic-gate	yesno "$*"
3356656Ssemery
3366656Ssemery	if [[ $answer == no ]]; then
3370Sstevel@tonic-gate		printf "\t$(gettext "No action performed").\n"
3380Sstevel@tonic-gate	fi
3390Sstevel@tonic-gate}
3400Sstevel@tonic-gate
3410Sstevel@tonic-gate
3426656Ssemeryfunction read_profile {
3430Sstevel@tonic-gate	typeset param value
3440Sstevel@tonic-gate	typeset file="$1"
3456656Ssemery
3460Sstevel@tonic-gate	if [[ ! -d $file && -r $file ]]; then
3470Sstevel@tonic-gate		while read param value
3480Sstevel@tonic-gate		do
3496656Ssemery			case $param in
3506656Ssemery			REALM)  if [[ -z $realm ]]; then
3516656Ssemery					realm="$value"
3526656Ssemery					checkval="REALM"; check_value $realm
3530Sstevel@tonic-gate				fi
3540Sstevel@tonic-gate				;;
3556656Ssemery			KDC)    if [[ -z $KDC ]]; then
3560Sstevel@tonic-gate					KDC="$value"
3570Sstevel@tonic-gate					checkval="KDC"; check_value $KDC
3580Sstevel@tonic-gate				fi
3590Sstevel@tonic-gate				;;
3606656Ssemery			ADMIN)  if [[ -z $ADMIN_PRINC ]]; then
3610Sstevel@tonic-gate					ADMIN_PRINC="$value"
3620Sstevel@tonic-gate					checkval="ADMIN_PRINC"
3630Sstevel@tonic-gate    					check_value $ADMIN_PRINC
3640Sstevel@tonic-gate				fi
3650Sstevel@tonic-gate				;;
3666656Ssemery			FILEPATH)  if [[ -z $filepath ]]; then
3670Sstevel@tonic-gate					filepath="$value"
3680Sstevel@tonic-gate				   fi
3690Sstevel@tonic-gate				   ;;
3706656Ssemery			NFS)    if [[ -z $add_nfs ]]; then
3716656Ssemery				    if [[ $value == 1 ]]; then
3720Sstevel@tonic-gate					    add_nfs=yes
3730Sstevel@tonic-gate				    else
3740Sstevel@tonic-gate					    add_nfs=no
3750Sstevel@tonic-gate				    fi
3760Sstevel@tonic-gate				fi
3770Sstevel@tonic-gate				;;
3786656Ssemery			NOKEY)    if [[ -z $no_keytab ]]; then
3796656Ssemery				    if [[ $value == 1 ]]; then
3806656Ssemery					    no_keytab=yes
3816656Ssemery				    else
3826656Ssemery					    no_keytab=no
3836656Ssemery				    fi
3846656Ssemery				fi
3856656Ssemery				;;
3866656Ssemery			NOSOL)  if [[ -z $non_solaris ]]; then
3876656Ssemery				    if [[ $value == 1 ]]; then
3886656Ssemery					    non_solaris=yes
3896656Ssemery					    no_keytab=yes
3906656Ssemery				    else
3916656Ssemery					    non_solaris=no
3926656Ssemery				    fi
3936656Ssemery				fi
3946656Ssemery				;;
3956656Ssemery			LHN)    if [[ -z $logical_hn ]]; then
3966656Ssemery					logical_hn="$value"
3976656Ssemery					checkval="LOGICAL_HOSTNAME"
3986656Ssemery    					check_value $logical_hn
3996656Ssemery				fi
4006656Ssemery				;;
4016656Ssemery			DNSLOOKUP) if [[ -z $dnsarg ]]; then
4020Sstevel@tonic-gate					dnsarg="$value"
4030Sstevel@tonic-gate					checkval="DNS_OPTIONS"
4040Sstevel@tonic-gate					check_value $dnsarg
4050Sstevel@tonic-gate				   fi
4060Sstevel@tonic-gate				   ;;
4076656Ssemery			FQDN) if [[ -z $fqdnlist ]]; then
4080Sstevel@tonic-gate					fqdnlist="$value"
4090Sstevel@tonic-gate					checkval="FQDN"
4100Sstevel@tonic-gate					check_value $fqdnlist
4110Sstevel@tonic-gate					verify_fqdnlist "$fqdnlist"
4120Sstevel@tonic-gate			      fi
4130Sstevel@tonic-gate			      ;;
4146656Ssemery			MSAD) if [[ -z $msad ]]; then
4156656Ssemery				if [[ $value == 1 ]]; then
4166656Ssemery					msad=yes
4176656Ssemery					non_solaris=yes
4186656Ssemery				else
4196656Ssemery					msad=no
4206656Ssemery				fi
4216656Ssemery			      fi
4226656Ssemery			      ;;
4230Sstevel@tonic-gate			esac
4240Sstevel@tonic-gate		done <$file
4250Sstevel@tonic-gate	else
4266656Ssemery		printf "\n$(gettext "The kclient profile \`%s' is not valid, exiting").\n" $file >&2
4270Sstevel@tonic-gate		error_message
4280Sstevel@tonic-gate	fi
4290Sstevel@tonic-gate}
4300Sstevel@tonic-gate
4316656Ssemeryfunction ping_check {
4320Sstevel@tonic-gate	typeset machine="$1"
4330Sstevel@tonic-gate	typeset string="$2"
4346656Ssemery
4356656Ssemery	if ping $machine 2 > /dev/null 2>&1; then
4360Sstevel@tonic-gate		:
4370Sstevel@tonic-gate	else
4386656Ssemery		printf "\n$(gettext "%s %s is unreachable, exiting").\n" $string $machine >&2
4390Sstevel@tonic-gate		error_message
4400Sstevel@tonic-gate	fi
4410Sstevel@tonic-gate
4420Sstevel@tonic-gate	# Output timesync warning if not using a profile, i.e. in
4430Sstevel@tonic-gate	# interactive mode.
4446656Ssemery	if [[ -z $profile && $string == KDC ]]; then
4450Sstevel@tonic-gate		# It's difficult to sync up time with KDC esp. if in a
4460Sstevel@tonic-gate		# zone so just print a warning about KDC time sync.
4476815Ssemery		printf "\n$(gettext "Note, this system and the KDC's time must be within 5 minutes of each other for Kerberos to function").\n" >&2
4486815Ssemery		printf "$(gettext "Both systems should run some form of time synchronization system like Network Time Protocol (NTP)").\n" >&2
4496656Ssemerybreak
4500Sstevel@tonic-gate	fi
4510Sstevel@tonic-gate}
4520Sstevel@tonic-gate
4536656Ssemeryfunction check_value {
4540Sstevel@tonic-gate	typeset arg="$1"
4556656Ssemery
4566656Ssemery	if [[ -z $arg ]]; then
4576656Ssemery		printf "\n$(gettext "No input obtained for %s, exiting").\n" $checkval >&2
4580Sstevel@tonic-gate		error_message
4590Sstevel@tonic-gate	else
4606656Ssemery		echo "$arg" > $TMP_FILE
4610Sstevel@tonic-gate		if egrep -s '[*$^#!]+' $TMP_FILE; then
4626656Ssemery			printf "\n$(gettext "Invalid input obtained for %s, exiting").\n" $checkval >&2
4636656Ssemery			error_message
4646656Ssemery		fi
4656656Ssemery	fi
4666656Ssemery}
4676656Ssemery
4686656Ssemeryfunction set_dns_value {
4696656Ssemery	typeset -l arg="$1"
4706656Ssemery
4716656Ssemery	if [[ $arg == dns_lookup_kdc  ||  $arg == dns_lookup_realm  || $arg == dns_fallback ]]; then
4726656Ssemery		dns_lookup=yes
4736656Ssemery	else
4746656Ssemery		if [[ $arg == none ]]; then
4756656Ssemery			dns_lookup=no
4766656Ssemery		else
4776656Ssemery			printf "\n$(gettext "Invalid DNS lookup option, exiting").\n" >&2
4780Sstevel@tonic-gate			error_message
4790Sstevel@tonic-gate		fi
4800Sstevel@tonic-gate	fi
4810Sstevel@tonic-gate}
4820Sstevel@tonic-gate
4836656Ssemeryfunction verify_kdcs {
4846656Ssemery	typeset k_list="$1"
4856656Ssemery	typeset -l kdc
4866656Ssemery	typeset list fqhn f_list
4876656Ssemery
4886656Ssemery	kdc_list=$(echo "$k_list" | sed 's/,/ /g')
4896656Ssemery
4906656Ssemery	if [[ -z $k_list ]]; then
4916656Ssemery		printf "\n$(gettext "At least one KDC should be listed").\n\n" >&2
4926656Ssemery		usage
4936656Ssemery	fi
4946656Ssemery
4956656Ssemery	for kdc in $k_list; do
4966656Ssemery		if [[ $kdc != $KDC ]]; then
4976656Ssemery			list="$list $kdc"
4986656Ssemery			fkdc=`$KLOOKUP $kdc`
4996656Ssemery			if ping $fkdc 2 > /dev/null; then
5006656Ssemery				:
5016656Ssemery			else
5026656Ssemery				printf "\n$(gettext "%s %s is unreachable, no action performed").\n" "KDC" $fkdc >&2
5036656Ssemery			fi
5046656Ssemery			f_list="$f_list $fkdc"
5050Sstevel@tonic-gate		fi
5066656Ssemery	done
5076656Ssemery
5086656Ssemery	fkdc_list="$f_list"
5096656Ssemery	kdc_list="$list"
5100Sstevel@tonic-gate}
5110Sstevel@tonic-gate
5126656Ssemeryfunction parse_service {
5136656Ssemery	typeset service_list=$1
5140Sstevel@tonic-gate
5156656Ssemery	service_list=${service_list//,/ }
5166656Ssemery	for service in $service_list; do
5176656Ssemery		svc=${service%:}
5186656Ssemery		auth_type=${service#:}
5196656Ssemery		[[ -z $svc || -z $auth_type ]] && return
5206656Ssemery		print -- $svc $auth_type
5216656Ssemery	done
5226656Ssemery}
5236656Ssemery
5246656Ssemeryfunction verify_fqdnlist {
5256656Ssemery	typeset list="$1"
5266656Ssemery	typeset -l hostname
5276656Ssemery	typeset -i count=1
5286656Ssemery	typeset fqdnlist eachfqdn tmpvar fullhost
5296656Ssemery
5306656Ssemery	list=$(echo "$list" | tr -d " " | tr -d "\t")
5316656Ssemery	hostname=$(uname -n | cut -d"." -f1)
5320Sstevel@tonic-gate	fqdnlist=$client_machine
5330Sstevel@tonic-gate
5340Sstevel@tonic-gate	eachfqdn=$(echo "$list" | cut -d"," -f$count)
5356656Ssemery	if [[ -z $eachfqdn ]]; then
5366656Ssemery		printf "\n$(gettext "If the -f option is used, at least one FQDN should be listed").\n\n" >&2
5370Sstevel@tonic-gate		usage
5380Sstevel@tonic-gate	else
5396656Ssemery		while [[ ! -z $eachfqdn ]]; do
5400Sstevel@tonic-gate			tmpvar=$(echo "$eachfqdn" | cut -d"." -f1)
5416656Ssemery			if [[ -z $tmpvar ]]; then
5420Sstevel@tonic-gate				fullhost="$hostname$eachfqdn"
5430Sstevel@tonic-gate			else
5440Sstevel@tonic-gate				fullhost="$hostname.$eachfqdn"
5450Sstevel@tonic-gate			fi
5460Sstevel@tonic-gate
5476656Ssemery			ping_check $fullhost $(gettext "System")
5486656Ssemery			if [[ $fullhost == $client_machine ]]; then
5490Sstevel@tonic-gate				:
5500Sstevel@tonic-gate			else
5510Sstevel@tonic-gate				fqdnlist="$fqdnlist $fullhost"
5520Sstevel@tonic-gate			fi
5530Sstevel@tonic-gate
5546656Ssemery			if [[ $list == *,* ]]; then
5550Sstevel@tonic-gate				((count = count + 1))
5560Sstevel@tonic-gate				eachfqdn=$(echo "$list" | cut -d"," -f$count)
5570Sstevel@tonic-gate			else
5580Sstevel@tonic-gate				break
5590Sstevel@tonic-gate			fi
5600Sstevel@tonic-gate		done
5610Sstevel@tonic-gate	fi
5620Sstevel@tonic-gate}
5630Sstevel@tonic-gate
5646656Ssemeryfunction setup_keytab {
5656656Ssemery	typeset cname ask_fqdns current_release
5666656Ssemery
5676656Ssemery	#
5686656Ssemery	# 1. kinit with ADMIN_PRINC
5696656Ssemery	#
5706656Ssemery
5716656Ssemery	if [[ -z $ADMIN_PRINC ]]; then
5726656Ssemery		printf "\n$(gettext "Enter the krb5 administrative principal to be used"): "
5736656Ssemery		read ADMIN_PRINC
5746656Ssemery		checkval="ADMIN_PRINC"; check_value $ADMIN_PRINC
5756656Ssemery	fi
5766656Ssemery
5776656Ssemery	echo "$ADMIN_PRINC">$TMP_FILE
5786656Ssemery
5796656Ssemery	[[ -n $msad ]] && return
5806656Ssemery	if egrep -s '\/admin' $TMP_FILE; then
5816656Ssemery		# Already in "/admin" format, do nothing
5826656Ssemery		:
5836656Ssemery	else
5846656Ssemery		if egrep -s '\/' $TMP_FILE; then
5856656Ssemery			printf "\n$(gettext "Improper entry for krb5 admin principal, exiting").\n" >&2
5866656Ssemery			error_message
5876656Ssemery		else
5886656Ssemery			ADMIN_PRINC=$(echo "$ADMIN_PRINC/admin")
5896656Ssemery		fi
5906656Ssemery	fi
5916656Ssemery
5926656Ssemery	printf "$(gettext "Obtaining TGT for %s") ...\n" $ADMIN_PRINC
5936656Ssemery
5946656Ssemery	cname=$(canon_resolve $KDC)
5956656Ssemery	if [[ -n $cname ]]; then
5966656Ssemery		kinit -S kadmin/$cname $ADMIN_PRINC
5976656Ssemery	else
5986656Ssemery		kinit -S kadmin/$FKDC $ADMIN_PRINC
5996656Ssemery	fi
6006656Ssemery	klist 1>$TMP_FILE 2>&1
6016815Ssemery	if egrep -s "$(gettext "Valid starting")" $TMP_FILE && egrep -s "kadmin/$FKDC@$realm" $TMP_FILE; then
6026656Ssemery    		:
6036656Ssemery	else
6046656Ssemery		printf "\n$(gettext "kinit of %s failed, exiting").\n" $ADMIN_PRINC >&2
6056656Ssemery		error_message
6066656Ssemery	fi
6076656Ssemery
6086656Ssemery	#
6096656Ssemery	# 2. Do we want to create and/or add service principal(s) for fqdn's
6106656Ssemery	#    other than the one listed in resolv.conf(4) ?
6116656Ssemery	#
6126656Ssemery	if [[ -z $options ]]; then
6136656Ssemery		query "$(gettext "Do you have multiple DNS domains spanning the Kerberos realm") $realm ?"
6146656Ssemery		ask_fqdns=$answer
6156656Ssemery		if [[ $ask_fqdns == yes ]]; then
6166815Ssemery			printf "$(gettext "Enter a comma-separated list of DNS domain names"): "
6176656Ssemery			read fqdnlist
6186656Ssemery			verify_fqdnlist "$fqdnlist"
6196656Ssemery		else
6206656Ssemery			fqdnlist=$client_machine
6216656Ssemery		fi
6226656Ssemery	else
6236656Ssemery		if [[ -z $fqdnlist ]]; then
6246656Ssemery			fqdnlist=$client_machine
6256656Ssemery		fi
6266656Ssemery	fi
6276656Ssemery
6286656Ssemery	if [[ $add_nfs == yes ]]; then
6296656Ssemery		echo; call_kadmin nfs
6306656Ssemery	fi
6316656Ssemery
6326656Ssemery	# Add the host entry to the keytab
6336656Ssemery	echo; call_kadmin host
6346656Ssemery
6356656Ssemery}
6366656Ssemery
6376656Ssemeryfunction setup_lhn {
6386656Ssemery	typeset -l logical_hn
6396656Ssemery
6406656Ssemery	echo "$logical_hn" > $TMP_FILE
6416656Ssemery	if egrep -s '[^.]\.[^.]+$' $TMP_FILE; then
6426656Ssemery		# do nothing, logical_hn is in fqdn format
6436656Ssemery		:
6446656Ssemery	else
6456656Ssemery		if egrep -s '\.+' $TMP_FILE; then
6466656Ssemery			printf "\n$(gettext "Improper format of logical hostname, exiting").\n" >&2
6476656Ssemery			error_message
6486656Ssemery		else
6496656Ssemery			# Attach fqdn to logical_hn, to get the Fully Qualified
6506656Ssemery			# Host Name of the client requested
6516656Ssemery			logical_hn=$(echo "$logical_hn.$fqdn")
6526656Ssemery		fi
6536656Ssemery	fi
6546656Ssemery
6556656Ssemery	client_machine=$logical_hn
6566656Ssemery
6576656Ssemery	ping_check $client_machine $(gettext "System")
6586656Ssemery}
6596656Ssemery
6606656Ssemeryfunction usage {
6616656Ssemery	printf "\n$(gettext "Usage: kclient [ options ]")\n" >&2
6626656Ssemery	printf "\t$(gettext "where options are any of the following")\n\n" >&2
6636656Ssemery	printf "\t$(gettext "[ -D domain_list ]  configure a client that has mul
6646656Ssemerytiple mappings of doamin and/or hosts to the default realm")\n" >&2
6656656Ssemery	printf "\t$(gettext "[ -K ]  configure a client that does not have host/service keys")\n" >&2
6666656Ssemery	printf "\t$(gettext "[ -R realm ]  specifies the realm to use")\n" >&2
6676656Ssemery	printf "\t$(gettext "[ -T kdc_vendor ]  specifies which KDC vendor is the server")\n" >&2
6686656Ssemery	printf "\t$(gettext "[ -a adminuser ]  specifies the Kerberos administrator")\n" >&2
6696656Ssemery	printf "\t$(gettext "[ -c filepath ]  specifies the krb5.conf path used to configure this client")\n" >&2
6706656Ssemery	printf "\t$(gettext "[ -d dnsarg ]  specifies which information should be looked up in DNS (dns_lookup_kdc, dns_lookup_realm, and dns_fallback)")\n" >&2
6716656Ssemery	printf "\t$(gettext "[ -f fqdn_list ]  specifies which domains to configure host keys for this client")\n" >&2
6726656Ssemery	printf "\t$(gettext "[ -h logicalhostname ]  configure the logical host name for a client that is in a cluster")\n" >&2
6736656Ssemery	printf "\t$(gettext "[ -k kdc_list ]  specify multiple KDCs, if -m is not used the first KDC in the list is assumed to be the master.  KDC host names are used verbatim.")\n" >&2
6746656Ssemery	printf "\t$(gettext "[ -m master ]  master KDC server host name")\n" >&2
6756656Ssemery	printf "\t$(gettext "[ -n ]  configure client to be an NFS client")\n" >&2
6766656Ssemery	printf "\t$(gettext "[ -p profile ]  specifies which profile file to use to configure this client")\n" >&2
6776656Ssemery	printf "\t$(gettext "[ -s pam_list ]  update the service for Kerberos authentication")\n" >&2
6780Sstevel@tonic-gate	error_message
6790Sstevel@tonic-gate}
6800Sstevel@tonic-gate
6816656Ssemeryfunction discover_domain {
6826656Ssemery	typeset dom DOMs
6836656Ssemery
6846656Ssemery	if [[ -z $realm ]]; then
6856656Ssemery		set -A DOMs -- `$KLOOKUP _ldap._tcp.dc._msdcs S`
6866656Ssemery	else
6876656Ssemery		set -A DOMs -- `$KLOOKUP _ldap._tcp.dc._msdcs.$realm S`
6886656Ssemery	fi
6896656Ssemery
6906656Ssemery	[[ -z ${DOMs[0]} ]] && return 1
6916656Ssemery
6926656Ssemery	dom=${DOMs[0]}
6936656Ssemery
6946656Ssemery	dom=${dom#*.}
6956656Ssemery	dom=${dom% *}
6966656Ssemery
6976656Ssemery	domain=$dom
6986656Ssemery
6996656Ssemery	return 0
7006656Ssemery}
7016656Ssemery
7026656Ssemeryfunction check_nss_hosts_or_ipnodes_config {
7036656Ssemery	typeset backend
7046656Ssemery
7056656Ssemery	for backend in $1
7066656Ssemery	do
7076656Ssemery		[[ $backend == dns ]] && return 0
7086656Ssemery	done
7096656Ssemery	return 1
7106656Ssemery}
7116656Ssemery
7126656Ssemeryfunction check_nss_conf {
7136656Ssemery	typeset i j hosts_config
7146656Ssemery
7156656Ssemery	for i in hosts ipnodes
7166656Ssemery	do
7176656Ssemery		grep "^${i}:" /etc/nsswitch.conf|read j hosts_config
7186656Ssemery		check_nss_hosts_or_ipnodes_config "$hosts_config" || return 1
7196656Ssemery	done
7206656Ssemery
7216656Ssemery	return 0
7226656Ssemery}
7236656Ssemery
7246656Ssemeryfunction canon_resolve {
7256656Ssemery	typeset name ip
7266656Ssemery
7276656Ssemery	name=`$KLOOKUP $1 C`
7286656Ssemery	[[ -z $name ]] && name=`$KLOOKUP $1 A`
7296656Ssemery	[[ -z $name ]] && return
7306656Ssemery
7316656Ssemery	ip=`$KLOOKUP $name I`
7326656Ssemery	[[ -z $ip ]] && return
7336815Ssemery	for i in $ip
7346815Ssemery	do
7356815Ssemery		if ping $i 2 > /dev/null 2>&1; then
7366815Ssemery			break
7376815Ssemery		else
7386815Ssemery			i=
7396815Ssemery		fi
7406815Ssemery	done
7416656Ssemery
7426656Ssemery	cname=`$KLOOKUP $ip P`
7436656Ssemery	[[ -z $cname ]] && return
7446656Ssemery
7456656Ssemery	print -- "$cname"
7466656Ssemery}
7476656Ssemery
7486656Ssemeryfunction rev_resolve {
7496656Ssemery	typeset name ip
7506656Ssemery
7516656Ssemery	ip=`$KLOOKUP $1 I`
7526656Ssemery
7536656Ssemery	[[ -z $ip ]] && return
7546656Ssemery	name=`$KLOOKUP $ip P`
7556656Ssemery	[[ -z $name ]] && return
7566656Ssemery
7576656Ssemery	print -- $name
7586656Ssemery}
7596656Ssemery
7606656Ssemery# Convert an AD-style domain DN to a DNS domainname
7616656Ssemeryfunction dn2dns {
7626656Ssemery	typeset OIFS dname dn comp components
7636656Ssemery
7646656Ssemery	dn=$1
7656656Ssemery	dname=
7666656Ssemery
7676656Ssemery	OIFS="$IFS"
7686656Ssemery	IFS=,
7696656Ssemery	set -A components -- $1
7706656Ssemery	IFS="$OIFS"
7716656Ssemery
7726656Ssemery	for comp in "${components[@]}"
7736656Ssemery	do
7746656Ssemery		[[ "$comp" == [dD][cC]=* ]] || continue
7756656Ssemery		dname="$dname.${comp#??=}"
7766656Ssemery	done
7776656Ssemery
7786656Ssemery	print ${dname#.}
7796656Ssemery}
7806656Ssemery
7816656Ssemery# Form a base DN from a DNS domainname and container
7826656Ssemeryfunction getBaseDN {
7836656Ssemery	if [[ -n "$2" ]]
7846656Ssemery	then
7856656Ssemery		baseDN="CN=$1,$(dns2dn $2)"
7866656Ssemery	else
7876656Ssemery		baseDN="$(dns2dn $2)"
7886656Ssemery	fi
7896656Ssemery}
7906656Ssemery
7916656Ssemery# Convert a DNS domainname to an AD-style DN for that domain
7926656Ssemeryfunction dns2dn {
7936656Ssemery	typeset OIFS dn labels
7946656Ssemery
7956656Ssemery	OIFS="$IFS"
7966656Ssemery	IFS=.
7976656Ssemery	set -A labels -- $1
7986656Ssemery	IFS="$OIFS"
7996656Ssemery
8006656Ssemery	dn=
8016656Ssemery	for label in "${labels[@]}"
8026656Ssemery	do
8036656Ssemery		dn="${dn},DC=$label"
8046656Ssemery	done
8056656Ssemery
8066656Ssemery	print -- "${dn#,}"
8076656Ssemery}
8086656Ssemery
8096656Ssemeryfunction getSRVs {
8106656Ssemery	typeset srv port
8116656Ssemery
8126656Ssemery	$KLOOKUP $1 S | while read srv port
8136656Ssemery	do
8146815Ssemery		if ping $srv 2 > /dev/null 2>&1; then
8156815Ssemery			print -- $srv $port
8166815Ssemery		fi
8176656Ssemery	done
8186656Ssemery}
8196656Ssemery
8206656Ssemeryfunction getKDC {
8216656Ssemery	typeset j
8226656Ssemery
8236656Ssemery	set -A KPWs -- $(getSRVs _kpasswd._tcp.$dom.)
8246656Ssemery	kpasswd=${KPWs[0]}
8256656Ssemery
8266656Ssemery	if [[ -n $siteName ]]
8276656Ssemery	then
8286656Ssemery		set -A KDCs -- $(getSRVs _kerberos._tcp.$siteName._sites.$dom.)
8296656Ssemery		kdc=${KDCs[0]}
8306656Ssemery		[[ -n $kdc ]] && return
8316656Ssemery	fi
8326656Ssemery
8336656Ssemery	# No site name
8346656Ssemery	set -A KDCs -- $(getSRVs _kerberos._tcp.$dom.)
8356656Ssemery	kdc=${KDCs[0]}
8366656Ssemery	[[ -n $kdc ]] && return
8376656Ssemery
8386656Ssemery	# Default
8396656Ssemery	set -A KDCs -- $DomainDnsZones 88
8406656Ssemery	kdc=$ForestDnsZones
8416656Ssemery}
8426656Ssemery
8436656Ssemeryfunction getDC {
8446656Ssemery	typeset j
8456656Ssemery
8466656Ssemery	if [[ -n $siteName ]]
8476656Ssemery	then
8486656Ssemery		set -A DCs -- $(getSRVs _ldap._tcp.$siteName._sites.dc._msdcs.$dom.)
8496656Ssemery		dc=${DCs[0]}
8506656Ssemery		[[ -n $dc ]] && return
8516656Ssemery	fi
8526656Ssemery
8536656Ssemery	# No site name
8546656Ssemery	set -A DCs -- $(getSRVs _ldap._tcp.dc._msdcs.$dom.)
8556656Ssemery	dc=${DCs[0]}
8566656Ssemery	[[ -n $dc ]] && return
8576656Ssemery
8586656Ssemery	# Default
8596656Ssemery	set -A DCs -- $DomainDnsZones 389
8606656Ssemery	dc=$DomainDnsZones
8616656Ssemery}
8626656Ssemery
8636656Ssemeryfunction write_ads_krb5conf {
8646656Ssemery	printf "\n$(gettext "Setting up %s").\n\n" $KRB5_CONFIG_FILE
8656656Ssemery
8666656Ssemery	exec 3>$KRB5_CONFIG
8676656Ssemery	if [[ $? -ne 0 ]]; then
8689833SShawn.Emery@Sun.COM		printf "\n$(gettext "Can not write to %s, exiting").\n" $KRB5_CONFIG >&2
8696656Ssemery		error_message
8706656Ssemery	fi
8716656Ssemery
8726656Ssemery	printf "[libdefaults]\n" 1>&3
8736656Ssemery	printf "\tdefault_realm = $realm\n" 1>&3
8746656Ssemery	printf "\n[realms]\n" 1>&3
8756656Ssemery	printf "\t$realm = {\n" 1>&3
8766656Ssemery	for i in ${KDCs[@]}
8776656Ssemery	do
8786656Ssemery		[[ $i == +([0-9]) ]] && continue
8796656Ssemery		printf "\t\tkdc = $i\n" 1>&3
8806656Ssemery	done
8816656Ssemery	# Defining the same as admin_server.  This would cause auth failures
8826656Ssemery	# if this was different.
8836656Ssemery	printf "\n\t\tkpasswd_server = $KDC\n" 1>&3
8846656Ssemery	printf "\n\t\tadmin_server = $KDC\n" 1>&3
8856656Ssemery	printf "\t\tkpasswd_protocol = SET_CHANGE\n\t}\n" 1>&3
8866656Ssemery	printf "\n[domain_realm]\n" 1>&3
8876656Ssemery	printf "\t.$dom = $realm\n\n" 1>&3
8886656Ssemery	printf "[logging]\n" 1>&3
8896656Ssemery	printf "\tdefault = FILE:/var/krb5/kdc.log\n" 1>&3
8906656Ssemery	printf "\tkdc = FILE:/var/krb5/kdc.log\n" 1>&3
8916656Ssemery	printf "\tkdc_rotate = {\n\t\tperiod = 1d\n\t\tversions = 10\n\t}\n\n" 1>&3
8926656Ssemery	printf "[appdefaults]\n" 1>&3
8936656Ssemery	printf "\tkinit = {\n\t\trenewable = true\n\t\tforwardable = true\n\t}\n" 1>&3
8946656Ssemery}
8956656Ssemery
8966656Ssemeryfunction getForestName {
8976656Ssemery	ldapsearch -R -T -h $dc $ldap_args \
8986656Ssemery	    -b "" -s base "" schemaNamingContext| \
8996656Ssemery		grep ^schemaNamingContext|read j schemaNamingContext
9006656Ssemery
9016656Ssemery	if [[ $? -ne 0 ]]; then
9029833SShawn.Emery@Sun.COM		printf "$(gettext "Can't find forest").\n" >&2
9036656Ssemery		error_message
9046656Ssemery	fi
9056656Ssemery	schemaNamingContext=${schemaNamingContext#CN=Schema,CN=Configuration,}
9066656Ssemery
9076656Ssemery	[[ -z $schemaNamingContext ]] && return 1
9086656Ssemery
9096656Ssemery	forest=
9106656Ssemery	while [[ -n $schemaNamingContext ]]
9116656Ssemery	do
9126656Ssemery		schemaNamingContext=${schemaNamingContext#DC=}
9136656Ssemery		forest=${forest}.${schemaNamingContext%%,*}
9146656Ssemery		[[ "$schemaNamingContext" = *,* ]] || break
9156656Ssemery		schemaNamingContext=${schemaNamingContext#*,}
9166656Ssemery	done
9176656Ssemery	forest=${forest#.}
9186656Ssemery}
9196656Ssemery
9206656Ssemeryfunction getGC {
9216656Ssemery	typeset j
9226656Ssemery
9236656Ssemery	[[ -n $gc ]] && return 0
9246656Ssemery
9256656Ssemery	if [[ -n $siteName ]]
9266656Ssemery	then
9276656Ssemery		set -A GCs -- $(getSRVs _ldap._tcp.$siteName._sites.gc._msdcs.$forest.)
9286656Ssemery		gc=${GCs[0]}
9296656Ssemery		[[ -n $gc ]] && return
9306656Ssemery	fi
9316656Ssemery
9326656Ssemery	# No site name
9336656Ssemery	set -A GCs -- $(getSRVs _ldap._tcp.gc._msdcs.$forest.)
9346656Ssemery	gc=${GCs[0]}
9356656Ssemery	[[ -n $gc ]] && return
9366656Ssemery
9376656Ssemery	# Default
9386656Ssemery	set -A GCs -- $ForestDnsZones 3268
9396656Ssemery	gc=$ForestDnsZones
9406656Ssemery}
9416656Ssemery
9429833SShawn.Emery@Sun.COM#
9439833SShawn.Emery@Sun.COM# The local variables used to calculate the IP address are of type unsigned
9449833SShawn.Emery@Sun.COM# integer (-ui), as this is required to restrict the integer to 32b.
9459833SShawn.Emery@Sun.COM# Starting in ksh88, Solaris has incorrectly assummed that -i represents 64b.
9469833SShawn.Emery@Sun.COM#
9476656Ssemeryfunction ipAddr2num {
9486656Ssemery	typeset OIFS
9499833SShawn.Emery@Sun.COM	typeset -ui16 num
9506656Ssemery
9516656Ssemery	if [[ "$1" != +([0-9]).+([0-9]).+([0-9]).+([0-9]) ]]
9526656Ssemery	then
9536656Ssemery		print 0
9546656Ssemery		return 0
9556656Ssemery	fi
9566656Ssemery
9576656Ssemery	OIFS="$IFS"
9586656Ssemery	IFS=.
9596656Ssemery	set -- $1
9606656Ssemery	IFS="$OIFS"
9616656Ssemery
9626656Ssemery	num=$((${1}<<24 | ${2}<<16 | ${3}<<8 | ${4}))
9636656Ssemery
9646656Ssemery	print -- $num
9656656Ssemery}
9666656Ssemery
9679833SShawn.Emery@Sun.COM#
9689833SShawn.Emery@Sun.COM# The local variables used to calculate the IP address are of type unsigned
9699833SShawn.Emery@Sun.COM# integer (-ui), as this is required to restrict the integer to 32b.
9709833SShawn.Emery@Sun.COM# Starting in ksh88, Solaris has incorrectly assummed that -i represents 64b.
9719833SShawn.Emery@Sun.COM#
9726656Ssemeryfunction num2ipAddr {
9739833SShawn.Emery@Sun.COM	typeset -ui16 num
9749833SShawn.Emery@Sun.COM	typeset -ui10 a b c d
9756656Ssemery
9766656Ssemery	num=$1
9776656Ssemery	a=$((num>>24        ))
9786656Ssemery	b=$((num>>16 & 16#ff))
9796656Ssemery	c=$((num>>8  & 16#ff))
9806656Ssemery	d=$((num     & 16#ff))
9816656Ssemery	print -- $a.$b.$c.$d
9826656Ssemery}
9836656Ssemery
9849833SShawn.Emery@Sun.COM#
9859833SShawn.Emery@Sun.COM# The local variables used to calculate the IP address are of type unsigned
9869833SShawn.Emery@Sun.COM# integer (-ui), as this is required to restrict the integer to 32b.
9879833SShawn.Emery@Sun.COM# Starting in ksh88, Solaris has incorrectly assummed that -i represents 64b.
9889833SShawn.Emery@Sun.COM#
9896656Ssemeryfunction netmask2length {
9909833SShawn.Emery@Sun.COM	typeset -ui16 netmask
9916656Ssemery	typeset -i len
9926656Ssemery
9936656Ssemery	netmask=$1
9946656Ssemery	len=32
9956656Ssemery	while [[ $((netmask % 2)) -eq 0 ]]
9966656Ssemery	do
9976656Ssemery		netmask=$((netmask>>1))
9986656Ssemery		len=$((len - 1))
9996656Ssemery	done
10006656Ssemery	print $len
10016656Ssemery}
10026656Ssemery
10039833SShawn.Emery@Sun.COM#
10049833SShawn.Emery@Sun.COM# The local variables used to calculate the IP address are of type unsigned
10059833SShawn.Emery@Sun.COM# integer (-ui), as this is required to restrict the integer to 32b.
10069833SShawn.Emery@Sun.COM# Starting in ksh88, Solaris has incorrectly assummed that -i represents 64b.
10079833SShawn.Emery@Sun.COM#
10086656Ssemeryfunction getSubnets {
10099833SShawn.Emery@Sun.COM	typeset -ui16 addr netmask
10109833SShawn.Emery@Sun.COM	typeset -ui16 classa=16\#ff000000
10116656Ssemery
10126656Ssemery	ifconfig -a|while read line
10136656Ssemery	do
10146656Ssemery		addr=0
10156656Ssemery		netmask=0
10166656Ssemery		set -- $line
10176656Ssemery		[[ $1 == inet ]] || continue
10186656Ssemery		while [[ $# -gt 0 ]]
10196656Ssemery		do
10206656Ssemery			case "$1" in
10216656Ssemery				inet) addr=$(ipAddr2num $2); shift;;
10226656Ssemery				netmask) eval netmask=16\#$2; shift;;
10236656Ssemery				*) :;
10246656Ssemery			esac
10256656Ssemery			shift
10266656Ssemery		done
10276656Ssemery
10286656Ssemery		[[ $addr -eq 0 || $netmask -eq 0 ]] && continue
10296656Ssemery		[[ $((addr & classa)) -eq 16\#7f000000 ]] && continue
10306656Ssemery
10316656Ssemery		print $(num2ipAddr $((addr & netmask)))/$(netmask2length $netmask)
10326656Ssemery	done
10336656Ssemery}
10346656Ssemery
10356656Ssemeryfunction getSite {
10366656Ssemery	typeset subnet siteDN j ldapsrv subnet_dom
10376656Ssemery
10386656Ssemery	eval "[[ -n \"\$siteName\" ]]" && return
10396656Ssemery	for subnet in $(getSubnets)
10406656Ssemery	do
10416656Ssemery		ldapsearch -R -T -h $dc $ldap_args \
10426656Ssemery		    -p 3268 -b "" -s sub cn=$subnet dn |grep ^dn|read j subnetDN
10436656Ssemery
10446656Ssemery		[[ -z $subnetDN ]] && continue
10456656Ssemery		subnet_dom=$(dn2dns $subnetDN)
10466656Ssemery		ldapsrv=$(canon_resolve DomainDnsZones.$subnet_dom)
10476815Ssemery		[[ -z $ldapsrv ]] && continue
10486656Ssemery		ldapsearch -R -T -h $ldapsrv $ldap_args \
10496656Ssemery		    -b "$subnetDN" -s base "" siteObject \
10506656Ssemery		    |grep ^siteObject|read j siteDN
10516656Ssemery
10526656Ssemery		[[ -z $siteDN ]] && continue
10536656Ssemery
10546656Ssemery		eval siteName=${siteDN%%,*}
10556656Ssemery		eval siteName=\${siteName#CN=}
10566656Ssemery		return
10576656Ssemery	done
10586656Ssemery}
10596656Ssemery
10606656Ssemeryfunction doKRB5config {
10616656Ssemery	[[ -f $KRB5_CONFIG_FILE ]] && \
10626656Ssemery		cp $KRB5_CONFIG_FILE ${KRB5_CONFIG_FILE}-pre-kclient
10636656Ssemery
10646656Ssemery	[[ -f $KRB5_KEYTAB_FILE ]] && \
10656656Ssemery		cp $KRB5_KEYTAB_FILE ${KRB5_KEYTAB_FILE}-pre-kclient
10666656Ssemery
10676815Ssemery	[[ -s $KRB5_CONFIG ]] && cp $KRB5_CONFIG $KRB5_CONFIG_FILE
10686815Ssemery	[[ -s $KRB5_CONFIG_FILE ]] && chmod 0644 $KRB5_CONFIG_FILE
10696815Ssemery	[[ -s $new_keytab ]] && cp $new_keytab $KRB5_KEYTAB_FILE
10706815Ssemery	[[ -s $KRB5_KEYTAB_FILE ]] && chmod 0600 $KRB5_KEYTAB_FILE
10716656Ssemery}
10726656Ssemery
10736656Ssemeryfunction addDNSRR {
10746656Ssemery	smbFMRI=svc:/network/smb/server:default
10756656Ssemery	ddnsProp=smbd/ddns_enable
10766656Ssemery	enProp=general/enabled
10776656Ssemery
10786656Ssemery	enabled=`svcprop -p $enProp $smbFMRI`
10796656Ssemery	ddns_enable=`svcprop -p $ddnsProp $smbFMRI`
10806656Ssemery
10816656Ssemery	if [[ $enabled == true && $ddns_enable != true ]]; then
10826656Ssemery		printf "$(gettext "Warning: won't create DNS records for client").\n"
10836656Ssemery		printf "$(gettext "%s property not set to 'true' for the %s FMRI").\n" $ddnsProp $smbFMRI
10846656Ssemery		return
10856656Ssemery	fi
10866656Ssemery
10876656Ssemery	# Destroy any existing ccache as GSS_C_NO_CREDENTIAL will pick up any
10886656Ssemery	# residual default credential in the cache.
10896656Ssemery	kdestroy > /dev/null 2>&1
10906656Ssemery
10916656Ssemery	$KDYNDNS -d $1 > /dev/null 2>&1
10926656Ssemery	if [[ $? -ne 0 ]]; then
10936656Ssemery		#
10946656Ssemery		# Non-fatal, we should carry-on as clients may resolve to
10956656Ssemery		# different servers and the client could already exist there.
10966656Ssemery		#
10978334SJose.Borrego@Sun.COM		printf "$(gettext "Warning: unable to create DNS records for client").\n"
10986656Ssemery		printf "$(gettext "This could mean that '%s' is not included as a 'nameserver' in the /etc/resolv.conf file or some other type of error").\n" $dc
10996656Ssemery	fi
11006656Ssemery}
11016656Ssemery
11026656Ssemeryfunction setSMB {
11036656Ssemery	typeset domain=$1
11046656Ssemery	typeset server=$2
11056656Ssemery	smbFMRI=svc:/network/smb/server
11066656Ssemery
110711570SShawn.Emery@Sun.COM	printf "%s" "$newpw" | $KSMB -d $domain -s $server
11086656Ssemery	if [[ $? -ne 0 ]]; then
11098334SJose.Borrego@Sun.COM		printf "$(gettext "Warning: unable to set %s domain, server and password information").\n" $smbFMRI
11106656Ssemery		return
11116656Ssemery	fi
11126656Ssemery
11138334SJose.Borrego@Sun.COM	svcadm restart $smbFMRI > /dev/null 2>&1
11146656Ssemery	if [[ $? -ne 0 ]]; then
11158334SJose.Borrego@Sun.COM		printf "$(gettext "Warning: unable to restart %s").\n" $smbFMRI
11166656Ssemery	fi
11176656Ssemery}
11186656Ssemery
11196656Ssemeryfunction compareDomains {
11206656Ssemery	typeset oldDom hspn newDom=$1
11216656Ssemery
11226656Ssemery	# If the client has been previously configured in a different
11236656Ssemery	# realm/domain then we need to prompt the user to see if they wish to
11246656Ssemery	# switch domains.
11256815Ssemery	klist -k 2>&1 | grep @ | read j hspn
11266656Ssemery	[[ -z $hspn ]] && return
11276656Ssemery
11286656Ssemery	oldDom=${hspn#*@}
11296656Ssemery	if [[ $oldDom != $newDom ]]; then
11306656Ssemery		printf "$(gettext "The client is currently configured in a different domain").\n"
11316656Ssemery		printf "$(gettext "Currently in the '%s' domain, trying to join the '%s' domain").\n" $oldDom $newDom
11326656Ssemery		query "$(gettext "Do you want the client to join a new domain") ?"
11336656Ssemery		printf "\n"
11346656Ssemery		if [[ $answer != yes ]]; then
11359833SShawn.Emery@Sun.COM			printf "$(gettext "Client will not be joined to the new domain").\n" >&2
11366656Ssemery			error_message
11376656Ssemery		fi
11386656Ssemery	fi
11396656Ssemery}
11406656Ssemery
11416656Ssemeryfunction getKDCDC {
11426656Ssemery
11436656Ssemery	getKDC
11446656Ssemery	if [[ -n $kdc ]]; then
11456656Ssemery		KDC=$kdc
11466656Ssemery		dc=$kdc
11476656Ssemery	else
11486656Ssemery		getDC
11496656Ssemery		if [[ -n $dc ]]; then
11506656Ssemery			KDC=$dc
11516656Ssemery		else
11529833SShawn.Emery@Sun.COM			printf "$(gettext "Could not find domain controller server for '%s'.  Exiting").\n" $realm >&2
11536656Ssemery			error_message
11546656Ssemery		fi
11556656Ssemery	fi
11566656Ssemery}
11576656Ssemery
115811570SShawn.Emery@Sun.COMfunction gen_rand {
115911570SShawn.Emery@Sun.COM	typeset -u hex
116011570SShawn.Emery@Sun.COM
116111570SShawn.Emery@Sun.COM	dd if=/dev/random bs=1 count=1 2>/dev/null | od -A n -tx1 | read hex
116211570SShawn.Emery@Sun.COM
116311570SShawn.Emery@Sun.COM	printf %s $((16#$hex))
116411570SShawn.Emery@Sun.COM}
116511570SShawn.Emery@Sun.COM
11666656Ssemeryfunction join_domain {
11676656Ssemery	typeset -u upcase_nodename
116811061SShawn.Emery@Sun.COM	typeset -l locase_nodename
116911061SShawn.Emery@Sun.COM	typeset -L15 string15
11706656Ssemery	typeset netbios_nodename fqdn
11716656Ssemery
11726656Ssemery	container=Computers
11736656Ssemery	ldap_args="-o authzid= -o mech=gssapi"
11746656Ssemery	userAccountControlBASE=4096
11756656Ssemery
11766656Ssemery	if [[ -z $ADMIN_PRINC ]]; then
11776656Ssemery		cprinc=Administrator
11786656Ssemery	else
11796656Ssemery		cprinc=$ADMIN_PRINC
11806656Ssemery	fi
11816656Ssemery
11826656Ssemery	if ! discover_domain; then
11839833SShawn.Emery@Sun.COM		printf "$(gettext "Can not find realm") '%s'.\n" $realm >&2
11846656Ssemery		error_message
11856656Ssemery	fi
11866656Ssemery
11876656Ssemery	dom=$domain
11886656Ssemery	realm=$domain
118911061SShawn.Emery@Sun.COM
119011061SShawn.Emery@Sun.COM	if [[ ${#hostname} -gt 15 ]]; then
119111061SShawn.Emery@Sun.COM		string15=$hostname
119211061SShawn.Emery@Sun.COM		upcase_nodename=$string15
119311061SShawn.Emery@Sun.COM		locase_nodename=$string15
119411061SShawn.Emery@Sun.COM	else
119511061SShawn.Emery@Sun.COM		upcase_nodename=$hostname
119611061SShawn.Emery@Sun.COM		locase_nodename=$hostname
119711061SShawn.Emery@Sun.COM	fi
119811061SShawn.Emery@Sun.COM
11996656Ssemery	netbios_nodename="${upcase_nodename}\$"
12006656Ssemery	fqdn=$hostname.$domain
120110001SJoyce.McIntosh@Sun.COM	upn=host/${fqdn}@${realm}
12026656Ssemery
12036656Ssemery	grep=/usr/xpg4/bin/grep
12046656Ssemery
12056656Ssemery	object=$(mktemp -q -t kclient-computer-object.XXXXXX)
12066656Ssemery	if [[ -z $object ]]; then
12076656Ssemery		printf "\n$(gettext "Can not create temporary file, exiting").\n
12086656Ssemery" >&2
12096656Ssemery		error_message
12106656Ssemery        fi
12116656Ssemery
12126656Ssemery	grep=/usr/xpg4/bin/grep
12136656Ssemery
12146656Ssemery	modify_existing=false
12156656Ssemery	recreate=false
12166656Ssemery
12176656Ssemery	DomainDnsZones=$(rev_resolve DomainDnsZones.$dom.)
12186656Ssemery	ForestDnsZones=$(rev_resolve ForestDnsZones.$dom.)
12196656Ssemery
12206656Ssemery	getBaseDN "$container" "$dom"
12216656Ssemery
12226656Ssemery	if [[ -n $KDC ]]; then
12236656Ssemery		dc=$KDC
12246656Ssemery	else
12256656Ssemery		getKDCDC
12266656Ssemery	fi
12276656Ssemery
12286656Ssemery	write_ads_krb5conf
12296656Ssemery
12306815Ssemery	printf "$(gettext "Attempting to join '%s' to the '%s' domain").\n\n" $upcase_nodename $realm
12316656Ssemery
12326656Ssemery	kinit $cprinc@$realm
12336656Ssemery	if [[ $? -ne 0 ]]; then
12349833SShawn.Emery@Sun.COM		printf "$(gettext "Could not authenticate %s.  Exiting").\n" $cprinc@$realm >&2
12356656Ssemery		error_message
12366656Ssemery	fi
12376656Ssemery
12386656Ssemery	if getForestName
12396656Ssemery	then
12406656Ssemery		printf "\n$(gettext "Forest name found: %s")\n\n" $forest
12416656Ssemery	else
12426656Ssemery		printf "\n$(gettext "Forest name not found, assuming forest is the domain name").\n"
12436656Ssemery	fi
12446656Ssemery
12456656Ssemery	getGC
12466656Ssemery	getSite
12476656Ssemery
12486656Ssemery	if [[ -z $siteName ]]
12496656Ssemery	then
12506656Ssemery    		printf "$(gettext "Site name not found.  Local DCs/GCs will not be discovered").\n\n"
12516656Ssemery	else
12526656Ssemery    		printf "$(gettext "Looking for _local_ KDCs, DCs and global catalog servers (SRV RRs)").\n"
12536656Ssemery		getKDCDC
12546656Ssemery		getGC
12556656Ssemery
12566656Ssemery		write_ads_krb5conf
12576656Ssemery	fi
12586656Ssemery
12596656Ssemery	if [[ ${#GCs} -eq 0 ]]; then
12609833SShawn.Emery@Sun.COM		printf "$(gettext "Could not find global catalogs.  Exiting").\n" >&2
12616656Ssemery		error_message
12626656Ssemery	fi
12636656Ssemery
12646656Ssemery	# Check to see if the client is transitioning between domains.
12656656Ssemery	compareDomains $realm
12666656Ssemery
12676656Ssemery	# Here we check domainFunctionality to see which release:
12686656Ssemery	# 0, 1, 2: Windows 2000, 2003 Interim, 2003 respecitively
12696656Ssemery	# 3: Windows 2008
12706656Ssemery	level=0
12716656Ssemery	ldapsearch -R -T -h "$dc" $ldap_args -b "" -s base "" \
12726656Ssemery	 domainControllerFunctionality| grep ^domainControllerFunctionality| \
12736656Ssemery	 read j level
12746656Ssemery	if [[ $? -ne 0 ]]; then
12759833SShawn.Emery@Sun.COM		printf "$(gettext "Search for domain functionality failed, exiting").\n" >&2
12766656Ssemery		error_message
12776656Ssemery	fi
12786656Ssemery
12796656Ssemery	if ldapsearch -R -T -h "$dc" $ldap_args -b "$baseDN" \
12806656Ssemery	    -s sub sAMAccountName="$netbios_nodename" dn > /dev/null 2>&1
12816656Ssemery	then
12826656Ssemery		:
12836656Ssemery	else
12849833SShawn.Emery@Sun.COM		printf "$(gettext "Search for node failed, exiting").\n" >&2
12856656Ssemery		error_message
12866656Ssemery	fi
12876656Ssemery	ldapsearch -R -T -h "$dc" $ldap_args -b "$baseDN" -s sub \
12886656Ssemery	    sAMAccountName="$netbios_nodename" dn|grep "^dn:"|read j dn
12896656Ssemery
12906656Ssemery	if [[ -z $dn ]]; then
12916656Ssemery		: # modify_existing is already false, which is what we want.
12926656Ssemery	else
12936656Ssemery		printf "$(gettext "Computer account '%s' already exists in the '%s' domain").\n" $upcase_nodename $realm
12946656Ssemery		query "$(gettext "Do you wish to recreate this computer account") ?"
12956656Ssemery		printf "\n"
12966656Ssemery		if [[ $answer == yes ]]; then
12976656Ssemery			recreate=true
12986656Ssemery		else
12996656Ssemery			modify_existing=true
13006656Ssemery		fi
13016656Ssemery	fi
13026656Ssemery
13036656Ssemery	if [[ $modify_existing == false && -n $dn ]]; then
13046656Ssemery		query "$(gettext "Would you like to delete any sub-object found for this computer account") ?"
13056656Ssemery		if [[ $answer == yes ]]; then
13066656Ssemery			printf "$(gettext "Looking to see if the machine account contains other objects")...\n"
13076656Ssemery			ldapsearch -R -T -h "$dc" $ldap_args -b "$dn" -s sub "" dn | while read j sub_dn
13086656Ssemery			do
13096656Ssemery				[[ $j != dn: || -z $sub_dn || $dn == $sub_dn ]] && continue
13106656Ssemery				if $recreate; then
13116656Ssemery					printf "$(gettext "Deleting the following object: %s")\n" ${sub_dn#$dn}
13126656Ssemery					ldapdelete -h "$dc" $ldap_args "$sub_dn" > /dev/null 2>&1
13136656Ssemery					if [[ $? -ne 0 ]]; then
13146656Ssemery						printf "$(gettext "Error in deleting object: %s").\n" ${sub_dn#$dn}
13156656Ssemery					fi
13166656Ssemery				else
13176656Ssemery					printf "$(gettext "The following object will not be deleted"): %s\n" ${sub_dn#$dn}
13186656Ssemery				fi
13196656Ssemery			done
13206656Ssemery		fi
13216656Ssemery
13226656Ssemery		if $recreate; then
13236656Ssemery			ldapdelete -h "$dc" $ldap_args "$dn" > /dev/null 2>&1
13246656Ssemery			if [[ $? -ne 0 ]]; then
13259833SShawn.Emery@Sun.COM				printf "$(gettext "Error in deleting object: %s").\n" ${sub_dn#$dn} >&2
13266656Ssemery				error_message
13276656Ssemery			fi
13286656Ssemery		elif $modify_existing; then
13296656Ssemery			: # Nothing to delete
13306656Ssemery		else
13319833SShawn.Emery@Sun.COM			printf "$(gettext "A machine account already exists").\n" >&2
13326656Ssemery			error_message
13336656Ssemery		fi
13346656Ssemery	fi
13356656Ssemery
133611061SShawn.Emery@Sun.COM	[[ -z $dn ]] && dn="CN=${upcase_nodename},${baseDN}"
13376656Ssemery	if $modify_existing; then
13386656Ssemery		cat > "$object" <<EOF
133911061SShawn.Emery@Sun.COMdn: $dn
13406656Ssemerychangetype: modify
13416656Ssemeryreplace: userPrincipalName
13426656SsemeryuserPrincipalName: $upn
13436656Ssemery-
13446656Ssemeryreplace: servicePrincipalName
13456656SsemeryservicePrincipalName: host/${fqdn}
13466656Ssemery-
13476656Ssemeryreplace: userAccountControl
13486656SsemeryuserAccountControl: $((userAccountControlBASE + 32 + 2))
13496656Ssemery-
13506656Ssemeryreplace: dNSHostname
13516656SsemerydNSHostname: ${fqdn}
13526656SsemeryEOF
13536656Ssemery
13546656Ssemery		printf "$(gettext "A machine account already exists; updating it").\n"
13556815Ssemery		ldapadd -h "$dc" $ldap_args -f "$object" > /dev/null 2>&1
13566656Ssemery		if [[ $? -ne 0 ]]; then
135711061SShawn.Emery@Sun.COM			printf "$(gettext "Failed to modify the AD object via LDAP").\n" >&2
13586656Ssemery			error_message
13596656Ssemery		fi
13606656Ssemery	else
136111061SShawn.Emery@Sun.COM		dn="CN=${upcase_nodename},${baseDN}"
13626656Ssemery		cat > "$object" <<EOF
136311061SShawn.Emery@Sun.COMdn: $dn
13646656SsemeryobjectClass: computer
13656656Ssemerycn: $upcase_nodename
13666656SsemerysAMAccountName: ${netbios_nodename}
13676656SsemeryuserPrincipalName: $upn
13686656SsemeryservicePrincipalName: host/${fqdn}
13696656SsemeryuserAccountControl: $((userAccountControlBASE + 32 + 2))
13706656SsemerydNSHostname: ${fqdn}
13716656SsemeryEOF
13726656Ssemery
13736656Ssemery		printf "$(gettext "Creating the machine account in AD via LDAP").\n\n"
13746656Ssemery
13756656Ssemery		ldapadd -h "$dc" $ldap_args -f "$object" > /dev/null 2>&1
13766656Ssemery		if [[ $? -ne 0 ]]; then
13779833SShawn.Emery@Sun.COM			printf "$(gettext "Failed to create the AD object via LDAP").\n" >&2
13786656Ssemery			error_message
13796656Ssemery		fi
13806656Ssemery	fi
13816656Ssemery
13826656Ssemery	# Generate a new password for the new account
138311570SShawn.Emery@Sun.COM	MAX_PASS=120
13846656Ssemery        i=0
13856656Ssemery
138611570SShawn.Emery@Sun.COM	# first check to see if /dev/random exists to generate a new password
138711570SShawn.Emery@Sun.COM	if [[ ! -h /dev/random ]]; then
138811570SShawn.Emery@Sun.COM		printf "$(gettext "/dev/random does not exist").\n" >&2
138911570SShawn.Emery@Sun.COM		error_message
139011570SShawn.Emery@Sun.COM	fi
13916656Ssemery
139211570SShawn.Emery@Sun.COM	while ((MAX_PASS > i))
139311570SShawn.Emery@Sun.COM	do
139411570SShawn.Emery@Sun.COM		# [MS-DISO] A machine password is an ASCII string of randomly
139511570SShawn.Emery@Sun.COM		# chosen characters. Each character's ASCII code is between 32
139611570SShawn.Emery@Sun.COM		# and 122 inclusive.
139711570SShawn.Emery@Sun.COM		c=$(printf "\\$(printf %o $(($(gen_rand) % 91 + 32)))\n")
139811570SShawn.Emery@Sun.COM		p="$p$c"
139911570SShawn.Emery@Sun.COM		((i+=1))
140011570SShawn.Emery@Sun.COM	done
14016656Ssemery
14026656Ssemery	newpw=$p
140311570SShawn.Emery@Sun.COM	if [[ ${#newpw} -ne MAX_PASS ]]; then
140411570SShawn.Emery@Sun.COM		printf "$(gettext "Password created was of incorrect length").\n" >&2
140511570SShawn.Emery@Sun.COM		error_message
140611570SShawn.Emery@Sun.COM	fi
14076656Ssemery
14086656Ssemery	# Set the new password
140911570SShawn.Emery@Sun.COM	printf "%s" "$newpw" | $KSETPW ${netbios_nodename}@${realm} > /dev/null 2>&1
14106656Ssemery	if [[ $? -ne 0 ]]
14116656Ssemery	then
14129833SShawn.Emery@Sun.COM		printf "$(gettext "Failed to set account password").\n" >&2
14136656Ssemery		error_message
14146656Ssemery	fi
14156656Ssemery
14166656Ssemery	# Lookup the new principal's kvno:
14176656Ssemery	ldapsearch -R -T -h "$dc" $ldap_args -b "$baseDN" \
14186656Ssemery		 -s sub cn=$upcase_nodename msDS-KeyVersionNumber| \
14196656Ssemery		grep "^msDS-KeyVersionNumber"|read j kvno
14206656Ssemery	[[ -z $kvno ]] && kvno=1
14216656Ssemery
14226656Ssemery	# Set supported enctypes.  This only works for Longhorn/Vista, so we
14236656Ssemery	# ignore errors here.
14246656Ssemery	userAccountControl=$((userAccountControlBASE + 524288 + 65536))
14256656Ssemery	set -A enctypes --
14266656Ssemery
14276656Ssemery	# Do we have local support for AES?
14286656Ssemery	encrypt -l|grep ^aes|read j minkeysize maxkeysize
14296656Ssemery	val=
14306656Ssemery	if [[ $maxkeysize -eq 256 ]]; then
14316656Ssemery		val=16
14326656Ssemery		enctypes[${#enctypes[@]}]=aes256-cts-hmac-sha1-96
14336656Ssemery	fi
14346656Ssemery	if [[ $minkeysize -eq 128 ]]; then
14356656Ssemery		((val=val+8))
14366656Ssemery		enctypes[${#enctypes[@]}]=aes128-cts-hmac-sha1-96
14376656Ssemery	fi
14386656Ssemery
14396656Ssemery	# RC4 comes next (whether it's better than 1DES or not -- AD prefers it)
14406656Ssemery	if encrypt -l|$grep -q ^arcfour
14416656Ssemery	then
14426656Ssemery		((val=val+4))
14436656Ssemery		enctypes[${#enctypes[@]}]=arcfour-hmac-md5
14446656Ssemery	else
14456656Ssemery		# Use 1DES ONLY if we don't have arcfour
14466656Ssemery		userAccountControl=$((userAccountControl + 2097152))
14476656Ssemery	fi
14486656Ssemery	if encrypt -l | $grep -q ^des
14496656Ssemery	then
14509833SShawn.Emery@Sun.COM		((val=val+2))
14516656Ssemery		enctypes[${#enctypes[@]}]=des-cbc-md5
14526656Ssemery	fi
14536656Ssemery
14546656Ssemery	if [[ ${#enctypes[@]} -eq 0 ]]
14556656Ssemery	then
14566656Ssemery		printf "$(gettext "No enctypes are supported").\n"
14579833SShawn.Emery@Sun.COM		printf "$(gettext "Please enable arcfour or 1DES, then re-join; see cryptoadm(1M)").\n" >&2
14586656Ssemery		error_message
14596656Ssemery	fi
14606656Ssemery
14616656Ssemery	# If domain crontroller is Longhorn or above then set new supported
14626656Ssemery	# encryption type attributes.
14636656Ssemery	if [[ $level -gt 2 ]]; then
14646656Ssemery		cat > "$object" <<EOF
146511061SShawn.Emery@Sun.COMdn: $dn
14666656Ssemerychangetype: modify
14676656Ssemeryreplace: msDS-SupportedEncryptionTypes
14686656SsemerymsDS-SupportedEncryptionTypes: $val
14696656SsemeryEOF
14706656Ssemery		ldapmodify -h "$dc" $ldap_args -f "$object" >/dev/null 2>&1
14716656Ssemery		if [[ $? -ne 0 ]]; then
14726656Ssemery			printf "$(gettext "Warning: Could not set the supported encryption type for computer account").\n"
14736656Ssemery		fi
14746656Ssemery	fi
14756656Ssemery
14766656Ssemery	# We should probably check whether arcfour is available, and if not,
14776656Ssemery	# then set the 1DES only flag, but whatever, it's not likely NOT to be
14786656Ssemery	# available on S10/Nevada!
14796656Ssemery
14806656Ssemery	# Reset userAccountControl
14816656Ssemery	#
14826656Ssemery	#  NORMAL_ACCOUNT (512) | DONT_EXPIRE_PASSWORD (65536) |
14836656Ssemery	#  TRUSTED_FOR_DELEGATION (524288)
14846656Ssemery	#
14856656Ssemery	# and possibly UseDesOnly (2097152) (see above)
14866656Ssemery	#
14876656Ssemery	cat > "$object" <<EOF
148811061SShawn.Emery@Sun.COMdn: $dn
14896656Ssemerychangetype: modify
14906656Ssemeryreplace: userAccountControl
14916656SsemeryuserAccountControl: $userAccountControl
14926656SsemeryEOF
14936656Ssemery	ldapmodify -h "$dc" $ldap_args -f "$object" >/dev/null 2>&1
14946656Ssemery	if [[ $? -ne 0 ]]; then
14959833SShawn.Emery@Sun.COM		printf "$(gettext "ldapmodify failed to modify account attribute").\n" >&2
14966656Ssemery		error_message
14976656Ssemery	fi
14986656Ssemery
14996656Ssemery	# Setup a keytab file
15006656Ssemery	set -A args --
15016656Ssemery	for enctype in "${enctypes[@]}"
15026656Ssemery	do
15036656Ssemery		args[${#args[@]}]=-e
15046656Ssemery		args[${#args[@]}]=$enctype
15056656Ssemery	done
15066656Ssemery
15076656Ssemery	rm $new_keytab > /dev/null 2>&1
15086656Ssemery
15096656Ssemery	cat > "$object" <<EOF
151011061SShawn.Emery@Sun.COMdn: $dn
15116656Ssemerychangetype: modify
15126656Ssemeryadd: servicePrincipalName
15136656SsemeryservicePrincipalName: nfs/${fqdn}
15146656SsemeryservicePrincipalName: HTTP/${fqdn}
15156656SsemeryservicePrincipalName: root/${fqdn}
15169833SShawn.Emery@Sun.COMservicePrincipalName: cifs/${fqdn}
151711061SShawn.Emery@Sun.COMservicePrincipalName: host/${upcase_nodename}
15186656SsemeryEOF
15196656Ssemery	ldapmodify -h "$dc" $ldap_args -f "$object" >/dev/null 2>&1
15206656Ssemery	if [[ $? -ne 0 ]]; then
15219833SShawn.Emery@Sun.COM		printf "$(gettext "ldapmodify failed to modify account attribute").\n" >&2
15226656Ssemery		error_message
15236656Ssemery	fi
15246656Ssemery
15259833SShawn.Emery@Sun.COM	#
15269833SShawn.Emery@Sun.COM	# In Windows, unlike MIT based implementations we salt the keys with
152711061SShawn.Emery@Sun.COM	# the UPN, which is based on the host/string15@realm elements, not
152811061SShawn.Emery@Sun.COM	# with the individual SPN strings.
15299833SShawn.Emery@Sun.COM	#
153011061SShawn.Emery@Sun.COM	salt=host/${locase_nodename}.${domain}@${realm}
15319833SShawn.Emery@Sun.COM
1532*12566SShawn.Emery@Sun.COM	skeys=(host/${fqdn}@${realm} nfs/${fqdn}@${realm} HTTP/${fqdn}@${realm})
1533*12566SShawn.Emery@Sun.COM	skeys+=(root/${fqdn}@${realm} cifs/${fqdn}@${realm})
1534*12566SShawn.Emery@Sun.COM	skeys+=(${netbios_nodename}@${realm} host/${upcase_nodename}@${realm})
1535*12566SShawn.Emery@Sun.COM	skeys+=(cifs/${upcase_nodename}@${realm})
15369833SShawn.Emery@Sun.COM
1537*12566SShawn.Emery@Sun.COM	ks_args="-n -s $salt -v $kvno -k $new_keytab ${args[@]}"
15386656Ssemery
1539*12566SShawn.Emery@Sun.COM	for skey in ${skeys[@]}
1540*12566SShawn.Emery@Sun.COM	do
1541*12566SShawn.Emery@Sun.COM		printf "%s" "$newpw" | $KSETPW $ks_args $skey > /dev/null 2>&1
1542*12566SShawn.Emery@Sun.COM		if [[ $? -ne 0 ]]
1543*12566SShawn.Emery@Sun.COM		then
1544*12566SShawn.Emery@Sun.COM			printf "$(gettext "Failed to set password").\n" >&2
1545*12566SShawn.Emery@Sun.COM			error_message
1546*12566SShawn.Emery@Sun.COM		fi
1547*12566SShawn.Emery@Sun.COM	done
154811061SShawn.Emery@Sun.COM
15496656Ssemery	doKRB5config
15506656Ssemery
15516656Ssemery	addDNSRR $dom
15526656Ssemery
15536656Ssemery	setSMB $dom $dc
15546656Ssemery
155511061SShawn.Emery@Sun.COM	printf -- "---------------------------------------------------\n"
15566656Ssemery	printf "$(gettext "Setup COMPLETE").\n\n"
15576656Ssemery
15586656Ssemery	kdestroy -q 1>$TMP_FILE 2>&1
15596656Ssemery	rm -f $TMP_FILE
15606656Ssemery	rm -rf $TMPDIR > /dev/null 2>&1
15616656Ssemery
15626656Ssemery	exit 0
15636656Ssemery}
15646656Ssemery
15650Sstevel@tonic-gate###########################
15660Sstevel@tonic-gate#	Main section	  #
15670Sstevel@tonic-gate###########################
15680Sstevel@tonic-gate#
15690Sstevel@tonic-gate# Set the Kerberos config file and some default strings/files
15700Sstevel@tonic-gate#
15716656SsemeryKRB5_CONFIG_FILE=/etc/krb5/krb5.conf
15726656SsemeryKRB5_KEYTAB_FILE=/etc/krb5/krb5.keytab
15736656SsemeryRESOLV_CONF_FILE=/etc/resolv.conf
15746656Ssemery
15756656SsemeryKLOOKUP=/usr/lib/krb5/klookup;	check_bin $KLOOKUP
15766656SsemeryKSETPW=/usr/lib/krb5/ksetpw;	check_bin $KSETPW
15776656SsemeryKSMB=/usr/lib/krb5/ksmb;	check_bin $KSMB
15786656SsemeryKDYNDNS=/usr/lib/krb5/kdyndns;	check_bin $KDYNDNS
15796656Ssemery
15806656Ssemerydns_lookup=no
15816656Ssemeryask_fqdns=no
15826656Ssemeryadddns=no
15836815Ssemeryno_keytab=no
15840Sstevel@tonic-gatecheckval=""
15850Sstevel@tonic-gateprofile=""
15866656Ssemerytypeset -u realm
15876656Ssemerytypeset -l hostname KDC
15880Sstevel@tonic-gate
15896656Ssemeryexport TMPDIR="/var/run/kclient"
15906656Ssemery
15916656Ssemerymkdir $TMPDIR > /dev/null 2>&1
15929833SShawn.Emery@Sun.COMif [[ $? -ne 0 ]]; then
15939833SShawn.Emery@Sun.COM	printf "\n$(gettext "Can not create directory: %s")\n\n" $TMPDIR >&2
15949833SShawn.Emery@Sun.COM	exit 1
15959833SShawn.Emery@Sun.COMfi
15960Sstevel@tonic-gate
15976656SsemeryTMP_FILE=$(mktemp -q -t kclient-tmpfile.XXXXXX)
15986656Ssemeryexport KRB5_CONFIG=$(mktemp -q -t kclient-krb5conf.XXXXXX)
15996815Ssemeryexport KRB5CCNAME=$(mktemp -q -t kclient-krb5ccache.XXXXXX)
16006656Ssemerynew_keytab=$(mktemp -q -t kclient-krb5keytab.XXXXXX)
16016656Ssemeryif [[ -z $TMP_FILE || -z $KRB5_CONFIG || -z $KRB5CCNAME || -z $new_keytab ]]
16026656Ssemerythen
16039833SShawn.Emery@Sun.COM	printf "\n$(gettext "Can not create temporary files, exiting").\n\n" >&2
16049833SShawn.Emery@Sun.COM	exit 1
16050Sstevel@tonic-gatefi
16060Sstevel@tonic-gate
16070Sstevel@tonic-gate#
16080Sstevel@tonic-gate# If we are interrupted, cleanup after ourselves
16090Sstevel@tonic-gate#
16106656Ssemerytrap "exiting 1" HUP INT QUIT TERM
16110Sstevel@tonic-gate
16126656Ssemeryif [[ -d /usr/bin ]]; then
16136656Ssemery	if [[ -d /usr/sbin ]]; then
16140Sstevel@tonic-gate		PATH=/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:$PATH
16150Sstevel@tonic-gate		export PATH
16160Sstevel@tonic-gate	else
16170Sstevel@tonic-gate		printf "\n$(gettext "Directory /usr/sbin not found, exiting").\n" >&2
16180Sstevel@tonic-gate		exit 1
16190Sstevel@tonic-gate	fi
16200Sstevel@tonic-gateelse
16210Sstevel@tonic-gate	printf "\n$(gettext "Directory /usr/bin not found, exiting").\n" >&2
16220Sstevel@tonic-gate	exit 1
16230Sstevel@tonic-gatefi
16240Sstevel@tonic-gate
16250Sstevel@tonic-gateprintf "\n$(gettext "Starting client setup")\n\n"
16266656Ssemeryprintf -- "---------------------------------------------------\n"
16270Sstevel@tonic-gate
16280Sstevel@tonic-gate#
16290Sstevel@tonic-gate# Check for uid 0, disallow otherwise
16300Sstevel@tonic-gate#
16310Sstevel@tonic-gateid 1>$TMP_FILE 2>&1
16326656Ssemeryif [[ $? -eq 0 ]]; then
16330Sstevel@tonic-gate	if egrep -s "uid=0\(root\)" $TMP_FILE; then
16340Sstevel@tonic-gate		# uid is 0, go ahead ...
16350Sstevel@tonic-gate		:
16360Sstevel@tonic-gate	else
16376656Ssemery		printf "\n$(gettext "Administrative privileges are required to run this script, exiting").\n" >&2
16380Sstevel@tonic-gate		error_message
16390Sstevel@tonic-gate	fi
16400Sstevel@tonic-gateelse
16410Sstevel@tonic-gate	cat $TMP_FILE;
16426656Ssemery	printf "\n$(gettext "uid check failed, exiting").\n" >&2
16430Sstevel@tonic-gate	error_message
16440Sstevel@tonic-gatefi
16450Sstevel@tonic-gate
16466656Ssemeryuname=$(uname -n)
16476656Ssemeryhostname=${uname%%.*}
16480Sstevel@tonic-gate
16490Sstevel@tonic-gate#
16500Sstevel@tonic-gate# Process the command-line arguments (if any)
16510Sstevel@tonic-gate#
16520Sstevel@tonic-gateOPTIND=1
16536656Ssemerywhile getopts nD:Kp:R:k:a:c:d:f:h:m:s:T: OPTIONS
16540Sstevel@tonic-gatedo
16550Sstevel@tonic-gate	case $OPTIONS in
16566656Ssemery	    D) options="$options -D"
16576656Ssemery	       domain_list="$OPTARG"
16586656Ssemery	       ;;
16596656Ssemery	    K) options="$options -K"
16606656Ssemery	       no_keytab=yes
16610Sstevel@tonic-gate	       ;;
16620Sstevel@tonic-gate	    R) options="$options -R"
16636656Ssemery	       realm="$OPTARG"
16646656Ssemery	       checkval="REALM"; check_value $realm
16650Sstevel@tonic-gate	       ;;
16666656Ssemery	    T) options="$options -T"
16676656Ssemery	       type="$OPTARG"
16686656Ssemery	       if [[ $type == ms_ad ]]; then
16696656Ssemery		msad=yes
16706656Ssemery		adddns=yes
16716656Ssemery	       else
16726656Ssemery		non_solaris=yes
16736656Ssemery		no_keytab=yes
16746656Ssemery	       fi
16750Sstevel@tonic-gate	       ;;
16760Sstevel@tonic-gate	    a) options="$options -a"
16770Sstevel@tonic-gate	       ADMIN_PRINC="$OPTARG"
16780Sstevel@tonic-gate	       checkval="ADMIN_PRINC"; check_value $ADMIN_PRINC
16790Sstevel@tonic-gate	       ;;
16800Sstevel@tonic-gate	    c) options="$options -c"
16810Sstevel@tonic-gate	       filepath="$OPTARG"
16820Sstevel@tonic-gate	       ;;
16830Sstevel@tonic-gate	    d) options="$options -d"
16840Sstevel@tonic-gate	       dnsarg="$OPTARG"
16850Sstevel@tonic-gate	       checkval="DNS_OPTIONS"; check_value $dnsarg
16860Sstevel@tonic-gate	       ;;
16870Sstevel@tonic-gate	    f) options="$options -f"
16880Sstevel@tonic-gate	       fqdnlist="$OPTARG"
16890Sstevel@tonic-gate 	       ;;
16906656Ssemery	    h) options="$options -h"
16916656Ssemery	       logical_hn="$OPTARG"
16926656Ssemery	       checkval="LOGICAL_HOSTNAME"; check_value $logical_hn
16936656Ssemery	       ;;
16946656Ssemery	    k) options="$options -k"
16956656Ssemery	       kdc_list="$OPTARG"
16966656Ssemery	       ;;
16976656Ssemery	    m) options="$options -m"
16986656Ssemery	       KDC="$OPTARG"
16996656Ssemery	       checkval="KDC"; check_value $KDC
17006656Ssemery	       ;;
17010Sstevel@tonic-gate	    n) options="$options -n"
17020Sstevel@tonic-gate	       add_nfs=yes
17030Sstevel@tonic-gate	       ;;
17046656Ssemery	    p) options="$options -p"
17056656Ssemery	       profile="$OPTARG"
17066656Ssemery	       read_profile $profile
17076656Ssemery	       ;;
17086656Ssemery	    s) options="$options -s"
17096656Ssemery	       svc_list="$OPTARG"
17106656Ssemery	       SVCs=${svc_list//,/ }
17116656Ssemery 	       ;;
17120Sstevel@tonic-gate	    \?) usage
17136656Ssemery	       ;;
17140Sstevel@tonic-gate	    *) usage
17150Sstevel@tonic-gate	       ;;
17160Sstevel@tonic-gate	esac
17170Sstevel@tonic-gatedone
17180Sstevel@tonic-gate
17190Sstevel@tonic-gate#correct argument count after options
17200Sstevel@tonic-gateshift `expr $OPTIND - 1`
17210Sstevel@tonic-gate
17226656Ssemeryif [[ -z $options ]]; then
17230Sstevel@tonic-gate	:
17240Sstevel@tonic-gateelse
17256656Ssemery	if [[ $# -ne 0 ]]; then
17260Sstevel@tonic-gate		usage
17270Sstevel@tonic-gate	fi
17280Sstevel@tonic-gatefi
17290Sstevel@tonic-gate
17306656Ssemery#
17316815Ssemery# Check to see if we will be a client of a MIT, Heimdal, Shishi, etc.
17326815Ssemery#
17336815Ssemeryif [[ -z $options ]]; then
17346815Ssemery	query "$(gettext "Is this a client of a non-Solaris KDC") ?"
17356815Ssemery	non_solaris=$answer
17366815Ssemery	if [[ $non_solaris == yes ]]; then
17376815Ssemery		printf "$(gettext "Which type of KDC is the server"):\n"
17386815Ssemery		printf "\t$(gettext "ms_ad: Microsoft Active Directory")\n"
17396815Ssemery		printf "\t$(gettext "mit: MIT KDC server")\n"
17406815Ssemery		printf "\t$(gettext "heimdal: Heimdal KDC server")\n"
17416815Ssemery		printf "\t$(gettext "shishi: Shishi KDC server")\n"
17426815Ssemery		printf "$(gettext "Enter required KDC type"): "
17436815Ssemery		read kdctype
17446815Ssemery		if [[ $kdctype == ms_ad ]]; then
17456815Ssemery			msad=yes
17466815Ssemery		elif [[ $kdctype == mit || $kdctype == heimdal || \
17476815Ssemery		    $kdctype == shishi ]]; then
17486815Ssemery			no_keytab=yes
17496815Ssemery		else
17506815Ssemery			printf "\n$(gettext "Invalid KDC type option, valid types are ms_ad, mit, heimdal, or shishi, exiting").\n" >&2
17516815Ssemery			error_message
17526815Ssemery		fi
17536815Ssemery	fi
17546815Ssemeryfi
17556815Ssemery
17566815Ssemery[[ $msad == yes ]] && join_domain
17576815Ssemery
17586815Ssemery#
17596656Ssemery# Check for /etc/resolv.conf
17606656Ssemery#
17616656Ssemeryif [[ -r $RESOLV_CONF_FILE ]]; then
17626656Ssemery	client_machine=`$KLOOKUP`
17636656Ssemery
17646656Ssemery	if [[ $? -ne 0 ]]; then
17656656Ssemery		if [[ $adddns == no ]]; then
17666656Ssemery			printf "\n$(gettext "%s does not have a DNS record and is required for Kerberos setup")\n" $hostname >&2
17676656Ssemery			error_message
17686656Ssemery		fi
17696656Ssemery
17706656Ssemery	else
17716656Ssemery		#
17726656Ssemery		# If client entry already exists then do not recreate it
17736656Ssemery		#
17746656Ssemery		adddns=no
17756656Ssemery
17766656Ssemery		hostname=${client_machine%%.*}
17776656Ssemery		domain=${client_machine#*.}
17786656Ssemery	fi
17796656Ssemery
17806656Ssemery	short_fqdn=${domain#*.*}
17816656Ssemery	short_fqdn=$(echo $short_fqdn | grep "\.")
17826656Ssemeryelse
17836656Ssemery	#
17846656Ssemery	# /etc/resolv.conf not present, exit ...
17856656Ssemery	#
17866656Ssemery	printf "\n$(gettext "%s does not exist and is required for Kerberos setup")\n" $RESOLV_CONF_FILE >&2
17876656Ssemery	printf "$(gettext "Refer to resolv.conf(4), exiting").\n" >&2
17886656Ssemery	error_message
17896656Ssemeryfi
17906656Ssemery
17916815Ssemerycheck_nss_conf || printf "$(gettext "/etc/nsswitch.conf does not make use of DNS for hosts and/or ipnodes").\n"
17926656Ssemery
17936656Ssemery[[ -n $fqdnlist ]] && verify_fqdnlist "$fqdnlist"
17946656Ssemery
17956815Ssemeryif [[ -z $dnsarg && (-z $options || -z $filepath) ]]; then
17960Sstevel@tonic-gate	query "$(gettext "Do you want to use DNS for kerberos lookups") ?"
17976656Ssemery	if [[ $answer == yes ]]; then
17986656Ssemery		printf "\n$(gettext "Valid DNS lookup options are dns_lookup_kdc, dns_lookup_realm,\nand dns_fallback. Refer krb5.conf(4) for further details").\n"
17996656Ssemery		printf "\n$(gettext "Enter required DNS option"): "
18000Sstevel@tonic-gate		read dnsarg
18010Sstevel@tonic-gate		checkval="DNS_OPTIONS"; check_value $dnsarg
18020Sstevel@tonic-gate		set_dns_value $dnsarg
18030Sstevel@tonic-gate	fi
18040Sstevel@tonic-gateelse
18056815Ssemery	[[ -z $dnsarg ]] && dnsarg=none
18060Sstevel@tonic-gate	set_dns_value $dnsarg
18070Sstevel@tonic-gatefi
18080Sstevel@tonic-gate
18096656Ssemeryif [[ -n $kdc_list ]]; then
18106656Ssemery	if [[ -z $KDC ]]; then
18116656Ssemery		for kdc in $kdc_list; do
18126656Ssemery			break
18136656Ssemery		done
18146656Ssemery		KDC="$kdc"
18156656Ssemery	fi
18160Sstevel@tonic-gatefi
18176656Ssemery
18186815Ssemeryif [[ -z $realm ]]; then
18196656Ssemery	printf "$(gettext "Enter the Kerberos realm"): "
18206656Ssemery	read realm
18216656Ssemery	checkval="REALM"; check_value $realm
18226656Ssemeryfi
18236815Ssemeryif [[ -z $KDC ]]; then
18246656Ssemery	printf "$(gettext "Specify the master KDC hostname for the above realm"): "
18250Sstevel@tonic-gate	read KDC
18260Sstevel@tonic-gate	checkval="KDC"; check_value $KDC
18270Sstevel@tonic-gatefi
18280Sstevel@tonic-gate
18296656SsemeryFKDC=`$KLOOKUP $KDC`
18300Sstevel@tonic-gate
18310Sstevel@tonic-gate#
18320Sstevel@tonic-gate# Ping to see if the kdc is alive !
18330Sstevel@tonic-gate#
18346656Ssemeryping_check $FKDC "KDC"
18356656Ssemery
18366815Ssemeryif [[ -z $kdc_list && (-z $options || -z $filepath) ]]; then
18376815Ssemery	query "$(gettext "Do you have any slave KDC(s)") ?"
18386815Ssemery	if [[ $answer == yes ]]; then
18396815Ssemery		printf "$(gettext "Enter a comma-separated list of slave KDC host names"): "
18406815Ssemery		read kdc_list
18416815Ssemery	fi
18426815Ssemeryfi
18436815Ssemery
18446815Ssemery[[ -n $kdc_list ]] && verify_kdcs "$kdc_list"
18456815Ssemery
18466656Ssemery#
18476656Ssemery# Check to see if we will have a dynamic presence in the realm
18486656Ssemery#
18496656Ssemeryif [[ -z $options ]]; then
18506656Ssemery	query "$(gettext "Will this client need service keys") ?"
18516656Ssemery	if [[ $answer == no ]]; then
18526656Ssemery		no_keytab=yes
18536656Ssemery	fi
18546656Ssemeryfi
18550Sstevel@tonic-gate
18566656Ssemery#
18576656Ssemery# Check to see if we are configuring the client to use a logical host name
18586656Ssemery# of a cluster environment
18596656Ssemery#
18606656Ssemeryif [[ -z $options ]]; then
18616656Ssemery	query "$(gettext "Is this client a member of a cluster that uses a logical host name") ?"
18626656Ssemery	if [[ $answer == yes ]]; then
18636656Ssemery		printf "$(gettext "Specify the logical hostname of the cluster"): "
18646656Ssemery		read logical_hn
18656656Ssemery		checkval="LOGICAL_HOSTNAME"; check_value $logical_hn
18666656Ssemery		setup_lhn
18676656Ssemery	fi
18686656Ssemeryfi
18696656Ssemery
18706815Ssemeryif [[ -n $domain_list && (-z $options || -z $filepath) ]]; then
18716656Ssemery	query "$(gettext "Do you have multiple domains/hosts to map to realm %s"
18726656Ssemery) ?" $realm
18736656Ssemery	if [[ $answer == yes ]]; then
18746815Ssemery		printf "$(gettext "Enter a comma-separated list of domain/hosts
18756656Ssemeryto map to the default realm"): "
18766656Ssemery		read domain_list
18776656Ssemery	fi
18786656Ssemeryfi
18796656Ssemery[[ -n domain_list ]] && domain_list=${domain_list//,/ }
18800Sstevel@tonic-gate
18810Sstevel@tonic-gate#
18820Sstevel@tonic-gate# Start writing up the krb5.conf file, save the existing one
18830Sstevel@tonic-gate# if already present
18840Sstevel@tonic-gate#
18850Sstevel@tonic-gatewriteup_krb5_conf
18860Sstevel@tonic-gate
18876656Ssemery#
18886656Ssemery# Is this client going to use krb-nfs?  If so then we need to at least
18896656Ssemery# uncomment the krb5* sec flavors in nfssec.conf.
18906656Ssemery#
18916656Ssemeryif [[ -z $options ]]; then
18926656Ssemery	query "$(gettext "Do you plan on doing Kerberized nfs") ?"
18936656Ssemery	add_nfs=$answer
18946656Ssemeryfi
18956656Ssemery
18966656Ssemeryif [[ $add_nfs == yes ]]; then
18976656Ssemery	modify_nfssec_conf
18986656Ssemery
18996656Ssemery	#
19006656Ssemery	# We also want to enable gss as we now live in a SBD world
19016656Ssemery	#
19026656Ssemery	svcadm enable svc:/network/rpc/gss:default
19036656Ssemery	[[ $? -ne 0 ]] && printf "$(gettext "Warning: could not enable gss service").\n"
19046656Ssemeryfi
19056656Ssemery
19066656Ssemeryif [[ -z $options ]]; then
19076656Ssemery	query "$(gettext "Do you want to update /etc/pam.conf") ?"
19086656Ssemery	if [[ $answer == yes ]]; then
19096656Ssemery		printf "$(gettext "Enter a list of PAM service names in the following format: service:{first|only|optional}[,..]"): "
19106656Ssemery		read svc_list
19116656Ssemery		SVCs=${svc_list//,/ }
19126656Ssemery	fi
19136656Ssemeryfi
19146656Ssemery[[ -n $svc_list ]] && update_pam_conf
19150Sstevel@tonic-gate
19160Sstevel@tonic-gate#
19176656Ssemery# Copy over krb5.conf master copy from filepath
19180Sstevel@tonic-gate#
19196656Ssemeryif [[ -z $options || -z $filepath ]]; then
19206656Ssemery	query "$(gettext "Do you want to copy over the master krb5.conf file") ?"
19216656Ssemery	if [[ $answer == yes ]]; then
19226656Ssemery		printf "$(gettext "Enter the pathname of the file to be copied"): "
19236656Ssemery		read filepath
19240Sstevel@tonic-gate	fi
19250Sstevel@tonic-gatefi
19260Sstevel@tonic-gate
19276815Ssemeryif [[ -n $filepath && -r $filepath ]]; then
19286815Ssemery	cp $filepath $KRB5_CONFIG
19296815Ssemery	if [[ $? -eq 0 ]]; then
19306815Ssemery		printf "$(gettext "Copied %s to %s").\n" $filepath $KRB5_CONFIG
19310Sstevel@tonic-gate	else
19326815Ssemery		printf "$(gettext "Copy of %s failed, exiting").\n" $filepath >&2
19336656Ssemery		error_message
19340Sstevel@tonic-gate	fi
19356815Ssemeryelif [[ -n $filepath ]]; then
19366815Ssemery	printf "\n$(gettext "%s not found, exiting").\n" $filepath >&2
19376815Ssemery	error_message
19380Sstevel@tonic-gatefi
19390Sstevel@tonic-gate
19406815SsemerydoKRB5config
19416815Ssemery
19420Sstevel@tonic-gate#
19436656Ssemery# Populate any service keys needed for the client in the keytab file
19440Sstevel@tonic-gate#
19456815Ssemeryif [[ $no_keytab != yes ]]; then
19466815Ssemery	setup_keytab
19476815Ssemeryelse
19486815Ssemery	printf "\n$(gettext "Note: %s file not created, please refer to verify_ap_req_nofail in krb5.conf(4) for the implications").\n" $KRB5_KEYTAB_FILE
19496815Ssemery	printf "$(gettext "Client will also not be able to host services that use Kerberos").\n"
19506815Ssemeryfi
19510Sstevel@tonic-gate
19526656Ssemeryprintf -- "\n---------------------------------------------------\n"
19536656Ssemeryprintf "$(gettext "Setup COMPLETE").\n\n"
19540Sstevel@tonic-gate
19550Sstevel@tonic-gate#
19566656Ssemery# If we have configured the client in a cluster we need to remind the user
19576656Ssemery# to propagate the keytab and configuration files to the other members.
19580Sstevel@tonic-gate#
19596656Ssemeryif [[ -n $logical_hn ]]; then
19606656Ssemery	printf "\n$(gettext "Note, you will need to securely transfer the /etc/krb5/krb5.keytab and /etc/krb5/krb5.conf files to all the other members of your cluster").\n"
19610Sstevel@tonic-gatefi
19620Sstevel@tonic-gate
19636656Ssemery#
19646656Ssemery# Cleanup.
19650Sstevel@tonic-gate#
19666656Ssemerykdestroy -q 1>$TMP_FILE 2>&1
19670Sstevel@tonic-gaterm -f $TMP_FILE
19686656Ssemeryrm -rf $TMPDIR > /dev/null 2>&1
19690Sstevel@tonic-gateexit 0
1970