xref: /onnv-gate/usr/src/cmd/krb5/kadmin/kclient/kclient.sh (revision 12567:f6b7e92780d6)
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#
22*12567SShawn.Emery@Sun.COM# Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate#
240Sstevel@tonic-gate# This script is used to setup the Kerberos client by
250Sstevel@tonic-gate# supplying information about the Kerberos realm and kdc.
260Sstevel@tonic-gate#
270Sstevel@tonic-gate# The kerberos configuration file (/etc/krb5/krb5.conf) would
280Sstevel@tonic-gate# be generated and local host's keytab file setup. The script
290Sstevel@tonic-gate# can also optionally setup the system to do kerberized nfs and
300Sstevel@tonic-gate# bringover a master krb5.conf copy from a specified location.
3111061SShawn.Emery@Sun.COM#
320Sstevel@tonic-gate
336656Ssemeryfunction cleanup {
346656Ssemery
359833SShawn.Emery@Sun.COM	kdestroy -q > $TMP_FILE 2>&1
366656Ssemery	rm -r $TMPDIR > /dev/null 2>&1
376656Ssemery
389833SShawn.Emery@Sun.COM	exit $1
396656Ssemery}
406656Ssemeryfunction exiting {
416656Ssemery
426656Ssemery        printf "\n$(gettext "Exiting setup, nothing changed").\n\n"
436656Ssemery
446656Ssemery	cleanup $1
450Sstevel@tonic-gate}
460Sstevel@tonic-gate
476656Ssemeryfunction error_message {
486656Ssemery
499833SShawn.Emery@Sun.COM        printf -- "---------------------------------------------------\n" >&2
509833SShawn.Emery@Sun.COM        printf "$(gettext "Setup FAILED").\n\n" >&2
516656Ssemery
526656Ssemery        cleanup 1
536656Ssemery}
546656Ssemery
556656Ssemeryfunction check_bin {
566656Ssemery
576656Ssemery	typeset bin=$1
586656Ssemery
596656Ssemery	if [[ ! -x $bin ]]; then
609833SShawn.Emery@Sun.COM		printf "$(gettext "Could not access/execute %s").\n" $bin >&2
610Sstevel@tonic-gate		error_message
620Sstevel@tonic-gate	fi
630Sstevel@tonic-gate}
640Sstevel@tonic-gate
656656Ssemeryfunction cannot_create {
666656Ssemery	typeset filename="$1"
676656Ssemery	typeset stat="$2"
686656Ssemery
696656Ssemery	if [[ $stat -ne 0 ]]; then
706656Ssemery		printf "\n$(gettext "Can not create/edit %s, exiting").\n" $filename >&2
716656Ssemery		error_message
726656Ssemery	fi
736656Ssemery}
746656Ssemery
756656Ssemeryfunction update_pam_conf {
766656Ssemery	typeset PAM TPAM service
776656Ssemery
786656Ssemery	PAM=/etc/pam.conf
796656Ssemery
806656Ssemery	TPAM=$(mktemp -q -t kclient-pamconf.XXXXXX)
816656Ssemery	if [[ -z $TPAM ]]; then
826656Ssemery		printf "\n$(gettext "Can not create temporary file, exiting").\n" >&2
836656Ssemery		error_message
846656Ssemery	fi
856656Ssemery
866656Ssemery	cp $PAM $TPAM >/dev/null 2>&1
876656Ssemery
886656Ssemery	printf "$(gettext "Configuring %s").\n\n" $PAM
896656Ssemery
906656Ssemery	for service in $SVCs; do
916656Ssemery		svc=${service%:*}
926656Ssemery		auth_type=${service#*:}
936656Ssemery		if egrep -s "^$svc[ 	][ 	]*auth.*pam_krb5*" $TPAM; then
946815Ssemery			printf "$(gettext "The %s service is already configured for pam_krb5, please merge this service in %s").\n\n" $svc $PAM >&2
956656Ssemery			continue
966656Ssemery		else
976656Ssemery			exec 3>>$TPAM
986815Ssemery			printf "\n$svc\tauth include\t\tpam_krb5_$auth_type\n" 1>&3
996656Ssemery		fi
1006656Ssemery	done
1016656Ssemery
1026656Ssemery	cp $TPAM $PAM > /dev/null 2>&1
1036656Ssemery
1046656Ssemery	rm $TPAM > /dev/null 2>&1
1056656Ssemery}
1066656Ssemery
1076656Ssemeryfunction modify_nfssec_conf {
1086656Ssemery	typeset NFSSEC_FILE="/etc/nfssec.conf"
1096656Ssemery
1106656Ssemery	if [[ -r $NFSSEC_FILE ]]; then
1110Sstevel@tonic-gate		cat $NFSSEC_FILE > $NFSSEC_FILE.sav
1120Sstevel@tonic-gate		cannot_create $NFSSEC_FILE.sav $?
1130Sstevel@tonic-gate	fi
1140Sstevel@tonic-gate
1150Sstevel@tonic-gate	cat $NFSSEC_FILE > $TMP_FILE
1160Sstevel@tonic-gate	cannot_create $TMP_FILE $?
1170Sstevel@tonic-gate
1180Sstevel@tonic-gate	if grep -s "#krb5" $NFSSEC_FILE > /dev/null 2>&1; then
1190Sstevel@tonic-gate		sed "s%^#krb5%krb5%" $TMP_FILE >$NFSSEC_FILE
1200Sstevel@tonic-gate		cannot_create $NFSSEC_FILE $?
1210Sstevel@tonic-gate	fi
1220Sstevel@tonic-gate}
1230Sstevel@tonic-gate
1246656Ssemeryfunction call_kadmin {
1250Sstevel@tonic-gate	typeset svc="$1"
1260Sstevel@tonic-gate	typeset bool1 bool2 bool3 bool4
1276656Ssemery	typeset service_princ getprincsubcommand anksubcommand ktaddsubcommand
1286656Ssemery	typeset ktremsubcommand
1290Sstevel@tonic-gate
1300Sstevel@tonic-gate	for listentry in $fqdnlist; do
1310Sstevel@tonic-gate
1320Sstevel@tonic-gate	# Reset conditional vars to 1
1330Sstevel@tonic-gate	bool1=1; bool2=1; bool3=1; bool4=1
1340Sstevel@tonic-gate
1356656Ssemery	service_princ=$(echo "${svc}/${listentry}")
1360Sstevel@tonic-gate	getprincsubcommand="getprinc $service_princ"
1370Sstevel@tonic-gate	anksubcommand="addprinc -randkey $service_princ"
1380Sstevel@tonic-gate	ktaddsubcommand="ktadd $service_princ"
1396656Ssemery	ktremsubcommand="ktrem $service_princ all"
1400Sstevel@tonic-gate
1416656Ssemery	kadmin -c $KRB5CCNAME -q "$getprincsubcommand" 1>$TMP_FILE 2>&1
1420Sstevel@tonic-gate
1436815Ssemery	egrep -s "$(gettext "get_principal: Principal does not exist")" $TMP_FILE
1440Sstevel@tonic-gate	bool1=$?
1456815Ssemery	egrep -s "$(gettext "get_principal: Operation requires ``get")" $TMP_FILE
1460Sstevel@tonic-gate	bool2=$?
1470Sstevel@tonic-gate
1480Sstevel@tonic-gate	if [[ $bool1 -eq 0 || $bool2 -eq 0 ]]; then
1496656Ssemery		kadmin -c $KRB5CCNAME -q "$anksubcommand" 1>$TMP_FILE 2>&1
1500Sstevel@tonic-gate
1516815Ssemery		egrep -s "$(gettext "add_principal: Principal or policy already exists while creating \"$service_princ@$realm\".")" $TMP_FILE
1520Sstevel@tonic-gate		bool3=$?
1530Sstevel@tonic-gate
1546815Ssemery		egrep -s "$(gettext "Principal \"$service_princ@$realm\" created.")" $TMP_FILE
1550Sstevel@tonic-gate		bool4=$?
1560Sstevel@tonic-gate
1570Sstevel@tonic-gate		if [[ $bool3 -eq 0 || $bool4 -eq 0 ]]; then
1580Sstevel@tonic-gate			printf "$(gettext "%s entry ADDED to KDC database").\n" $service_princ
1590Sstevel@tonic-gate		else
1600Sstevel@tonic-gate			cat $TMP_FILE;
1616656Ssemery			printf "\n$(gettext "kadmin: add_principal of %s failed, exiting").\n" $service_princ >&2
1620Sstevel@tonic-gate			error_message
1630Sstevel@tonic-gate		fi
1640Sstevel@tonic-gate	else
1656656Ssemery		printf "$(gettext "%s entry already exists in KDC database").\n" $service_princ >&2
1660Sstevel@tonic-gate	fi
1670Sstevel@tonic-gate
1680Sstevel@tonic-gate	klist -k 1>$TMP_FILE 2>&1
1696656Ssemery	egrep -s "$service_princ@$realm" $TMP_FILE
1706656Ssemery	if [[ $? -eq 0 ]]; then
1716656Ssemery		printf "$(gettext "%s entry already present in keytab").\n" $service_princ >&2
1726656Ssemery		# Don't care is this succeeds or not, just need to replace old
1736656Ssemery		# entries as it is assummed that the client is reinitialized
1746656Ssemery		kadmin -c $KRB5CCNAME -q "$ktremsubcommand" 1>$TMP_FILE 2>&1
1756656Ssemery	fi
1766656Ssemery
1776656Ssemery	kadmin -c $KRB5CCNAME -q "$ktaddsubcommand" 1>$TMP_FILE 2>&1
1786815Ssemery	egrep -s "$(gettext "added to keytab WRFILE:$KRB5_KEYTAB_FILE.")" $TMP_FILE
1796656Ssemery	if [[ $? -ne 0 ]]; then
1806656Ssemery		cat $TMP_FILE;
1816656Ssemery		printf "\n$(gettext "kadmin: ktadd of %s failed, exiting").\n" $service_princ >&2
1826656Ssemery		error_message
1830Sstevel@tonic-gate	else
1846656Ssemery		printf "$(gettext "%s entry ADDED to keytab").\n" $service_princ
1850Sstevel@tonic-gate	fi
1860Sstevel@tonic-gate
1870Sstevel@tonic-gate	done
1880Sstevel@tonic-gate}
1890Sstevel@tonic-gate
1906656Ssemeryfunction writeup_krb5_conf {
1916656Ssemery	typeset dh
1920Sstevel@tonic-gate
1936656Ssemery	printf "\n$(gettext "Setting up %s").\n\n" $KRB5_CONFIG_FILE
1940Sstevel@tonic-gate
1956656Ssemery	exec 3>$KRB5_CONFIG
1966656Ssemery	if [[ $? -ne 0 ]]; then
1979833SShawn.Emery@Sun.COM		printf "\n$(gettext "Can not write to %s, exiting").\n" $KRB5_CONFIG >&2
1980Sstevel@tonic-gate		error_message
1990Sstevel@tonic-gate	fi
2000Sstevel@tonic-gate
2016656Ssemery	printf "[libdefaults]\n" 1>&3
2026656Ssemery	if [[ $no_keytab == yes ]]; then
2036656Ssemery		printf "\tverify_ap_req_nofail = false\n" 1>&3
2046656Ssemery	fi
2056656Ssemery	if [[ $dns_lookup == yes ]]; then
2066656Ssemery	    printf "\t$dnsarg = on\n" 1>&3
2076656Ssemery	    if [[ $dnsarg == dns_lookup_kdc ]]; then
2086656Ssemery		printf "\tdefault_realm = $realm\n" 1>&3
2096656Ssemery		printf "\n[domain_realm]\n" 1>&3
2106656Ssemery		if [[ -n $fkdc_list ]]; then
2116656Ssemery			for kdc in $fkdc_list; do
2126656Ssemery				printf "\t$kdc = $realm\n" 1>&3
2136656Ssemery			done
2146656Ssemery		fi
2156656Ssemery		printf "\t$FKDC = $realm\n" 1>&3
2166656Ssemery		printf "\t$client_machine = $realm\n" 1>&3
2176656Ssemery		if [[ -z $short_fqdn ]]; then
2186656Ssemery			printf "\t.$domain = $realm\n\n" 1>&3
2196656Ssemery		else
2206656Ssemery			printf "\t.$short_fqdn = $realm\n\n" 1>&3
2216656Ssemery		fi
2226656Ssemery		if [[ -n $domain_list ]]; then
2236656Ssemery			for dh in $domain_list; do
2246656Ssemery				printf "\t$dh = $realm\n" 1>&3
2256656Ssemery			done
2266656Ssemery		fi
2270Sstevel@tonic-gate	    else
2286656Ssemery		if [[ $dnsarg = dns_lookup_realm ]]; then
2296815Ssemery		    printf "\tdefault_realm = $realm\n" 1>&3
2306656Ssemery		    printf "\n[realms]\n" 1>&3
2316656Ssemery		    printf "\t$realm = {\n" 1>&3
2326656Ssemery		    if [[ -n $kdc_list ]]; then
2336656Ssemery			for kdc in $kdc_list; do
2346656Ssemery				printf "\t\tkdc = $kdc\n" 1>&3
2356656Ssemery			done
2366656Ssemery		    else
2376656Ssemery		    	printf "\t\tkdc = $KDC\n" 1>&3
2386656Ssemery		    fi
2396656Ssemery		    printf "\t\tadmin_server = $KDC\n" 1>&3
2406656Ssemery		    if [[ $non_solaris == yes ]]; then
2416656Ssemery			printf "\n\t\tkpasswd_protocol = SET_CHANGE\n" 1>&3
2426656Ssemery		    fi
2436656Ssemery		    printf "\t}\n\n" 1>&3
2440Sstevel@tonic-gate		else
2456815Ssemery		    printf "\tdefault_realm = $realm\n\n" 1>&3
2460Sstevel@tonic-gate		fi
2470Sstevel@tonic-gate	    fi
2480Sstevel@tonic-gate	else
2496656Ssemery	    printf "\tdefault_realm = $realm\n\n" 1>&3
2506656Ssemery
2516656Ssemery	    printf "[realms]\n" 1>&3
2526656Ssemery	    printf "\t$realm = {\n" 1>&3
2536656Ssemery	    if [[ -n $kdc_list ]]; then
2546656Ssemery		for kdc in $kdc_list; do
2556656Ssemery			printf "\t\tkdc = $kdc\n" 1>&3
2566656Ssemery		done
2576656Ssemery	    else
2586656Ssemery	    	printf "\t\tkdc = $KDC\n" 1>&3
2596656Ssemery	    fi
2606656Ssemery	    printf "\t\tadmin_server = $KDC\n" 1>&3
2616656Ssemery	    if [[ $non_solaris == yes ]]; then
2626656Ssemery	    	printf "\n\t\tkpasswd_protocol = SET_CHANGE\n" 1>&3
2636656Ssemery	    fi
2646656Ssemery	    printf "\t}\n\n" 1>&3
2650Sstevel@tonic-gate
2666656Ssemery	    printf "[domain_realm]\n" 1>&3
2676656Ssemery	    if [[ -n $fkdc_list ]]; then
2686656Ssemery		for kdc in $fkdc_list; do
2696656Ssemery			printf "\t$kdc = $realm\n" 1>&3
2706656Ssemery		done
2716656Ssemery	    fi
2726656Ssemery	    printf "\t$FKDC = $realm\n" 1>&3
2736656Ssemery	    printf "\t$client_machine = $realm\n" 1>&3
2746656Ssemery	    if [[ -z $short_fqdn ]]; then
2756656Ssemery		printf "\t.$domain = $realm\n\n" 1>&3
2766656Ssemery	    else
2776656Ssemery		printf "\t.$short_fqdn = $realm\n\n" 1>&3
2786656Ssemery	    fi
2796656Ssemery	    if [[ -n $domain_list ]]; then
2806656Ssemery		for dh in $domain_list; do
2816656Ssemery			printf "\t$dh = $realm\n" 1>&3
2826656Ssemery		done
2836656Ssemery	    fi
2840Sstevel@tonic-gate	fi
2850Sstevel@tonic-gate
2866656Ssemery	printf "[logging]\n" 1>&3
2876656Ssemery	printf "\tdefault = FILE:/var/krb5/kdc.log\n" 1>&3
2886656Ssemery	printf "\tkdc = FILE:/var/krb5/kdc.log\n" 1>&3
2896656Ssemery	printf "\tkdc_rotate = {\n\t\tperiod = 1d\n\t\tversions = 10\n\t}\n\n" 1>&3
2900Sstevel@tonic-gate
2916656Ssemery	printf "[appdefaults]\n" 1>&3
2926656Ssemery	printf "\tkinit = {\n\t\trenewable = true\n\t\tforwardable = true\n" 1>&3
2936656Ssemery	if [[ $no_keytab == yes ]]; then
2946656Ssemery		printf "\t\tno_addresses = true\n" 1>&3
2956656Ssemery	fi
2966656Ssemery	printf "\t}\n" 1>&3
2970Sstevel@tonic-gate}
2980Sstevel@tonic-gate
2996656Ssemeryfunction ask {
3006656Ssemery	typeset question=$1
3016656Ssemery	typeset default_answer=$2
3026656Ssemery
3036656Ssemery	if [[ -z $default_answer ]]; then
3046656Ssemery		printf "$question :"
3050Sstevel@tonic-gate	else
3066656Ssemery		printf "$question [$default_answer]: "
3070Sstevel@tonic-gate	fi
3080Sstevel@tonic-gate	read answer
3090Sstevel@tonic-gate	test -z "$answer" && answer="$default_answer"
3100Sstevel@tonic-gate}
3110Sstevel@tonic-gate
3126656Ssemeryfunction yesno {
3130Sstevel@tonic-gate	typeset question="$1"
3146656Ssemery
3156656Ssemery	answer=
3166656Ssemery	yn=`printf "$(gettext "y/n")"`
3176656Ssemery	y=`printf "$(gettext "y")"`
3186656Ssemery	n=`printf "$(gettext "n")"`
3196656Ssemery	yes=`printf "$(gettext "yes")"`
3206656Ssemery	no=`printf "$(gettext "no")"`
3216656Ssemery
3226656Ssemery	while [[ -z $answer ]]; do
3236656Ssemery		ask "$question" $yn
3246656Ssemery		case $answer in
3256656Ssemery			$y|$yes)	answer=yes;;
3266656Ssemery			$n|$no)		answer=no;;
3276656Ssemery			*)		answer=;;
3280Sstevel@tonic-gate		esac
3290Sstevel@tonic-gate	done
3300Sstevel@tonic-gate}
3310Sstevel@tonic-gate
3326656Ssemeryfunction query {
3330Sstevel@tonic-gate	yesno "$*"
3346656Ssemery
3356656Ssemery	if [[ $answer == no ]]; then
3360Sstevel@tonic-gate		printf "\t$(gettext "No action performed").\n"
3370Sstevel@tonic-gate	fi
3380Sstevel@tonic-gate}
3390Sstevel@tonic-gate
3400Sstevel@tonic-gate
3416656Ssemeryfunction read_profile {
3420Sstevel@tonic-gate	typeset param value
3430Sstevel@tonic-gate	typeset file="$1"
3446656Ssemery
3450Sstevel@tonic-gate	if [[ ! -d $file && -r $file ]]; then
3460Sstevel@tonic-gate		while read param value
3470Sstevel@tonic-gate		do
3486656Ssemery			case $param in
3496656Ssemery			REALM)  if [[ -z $realm ]]; then
3506656Ssemery					realm="$value"
3516656Ssemery					checkval="REALM"; check_value $realm
3520Sstevel@tonic-gate				fi
3530Sstevel@tonic-gate				;;
3546656Ssemery			KDC)    if [[ -z $KDC ]]; then
3550Sstevel@tonic-gate					KDC="$value"
3560Sstevel@tonic-gate					checkval="KDC"; check_value $KDC
3570Sstevel@tonic-gate				fi
3580Sstevel@tonic-gate				;;
3596656Ssemery			ADMIN)  if [[ -z $ADMIN_PRINC ]]; then
3600Sstevel@tonic-gate					ADMIN_PRINC="$value"
3610Sstevel@tonic-gate					checkval="ADMIN_PRINC"
3620Sstevel@tonic-gate    					check_value $ADMIN_PRINC
3630Sstevel@tonic-gate				fi
3640Sstevel@tonic-gate				;;
3656656Ssemery			FILEPATH)  if [[ -z $filepath ]]; then
3660Sstevel@tonic-gate					filepath="$value"
3670Sstevel@tonic-gate				   fi
3680Sstevel@tonic-gate				   ;;
3696656Ssemery			NFS)    if [[ -z $add_nfs ]]; then
3706656Ssemery				    if [[ $value == 1 ]]; then
3710Sstevel@tonic-gate					    add_nfs=yes
3720Sstevel@tonic-gate				    else
3730Sstevel@tonic-gate					    add_nfs=no
3740Sstevel@tonic-gate				    fi
3750Sstevel@tonic-gate				fi
3760Sstevel@tonic-gate				;;
3776656Ssemery			NOKEY)    if [[ -z $no_keytab ]]; then
3786656Ssemery				    if [[ $value == 1 ]]; then
3796656Ssemery					    no_keytab=yes
3806656Ssemery				    else
3816656Ssemery					    no_keytab=no
3826656Ssemery				    fi
3836656Ssemery				fi
3846656Ssemery				;;
3856656Ssemery			NOSOL)  if [[ -z $non_solaris ]]; then
3866656Ssemery				    if [[ $value == 1 ]]; then
3876656Ssemery					    non_solaris=yes
3886656Ssemery					    no_keytab=yes
3896656Ssemery				    else
3906656Ssemery					    non_solaris=no
3916656Ssemery				    fi
3926656Ssemery				fi
3936656Ssemery				;;
3946656Ssemery			LHN)    if [[ -z $logical_hn ]]; then
3956656Ssemery					logical_hn="$value"
3966656Ssemery					checkval="LOGICAL_HOSTNAME"
3976656Ssemery    					check_value $logical_hn
3986656Ssemery				fi
3996656Ssemery				;;
4006656Ssemery			DNSLOOKUP) if [[ -z $dnsarg ]]; then
4010Sstevel@tonic-gate					dnsarg="$value"
4020Sstevel@tonic-gate					checkval="DNS_OPTIONS"
4030Sstevel@tonic-gate					check_value $dnsarg
4040Sstevel@tonic-gate				   fi
4050Sstevel@tonic-gate				   ;;
4066656Ssemery			FQDN) if [[ -z $fqdnlist ]]; then
4070Sstevel@tonic-gate					fqdnlist="$value"
4080Sstevel@tonic-gate					checkval="FQDN"
4090Sstevel@tonic-gate					check_value $fqdnlist
4100Sstevel@tonic-gate					verify_fqdnlist "$fqdnlist"
4110Sstevel@tonic-gate			      fi
4120Sstevel@tonic-gate			      ;;
4136656Ssemery			MSAD) if [[ -z $msad ]]; then
4146656Ssemery				if [[ $value == 1 ]]; then
4156656Ssemery					msad=yes
4166656Ssemery					non_solaris=yes
4176656Ssemery				else
4186656Ssemery					msad=no
4196656Ssemery				fi
4206656Ssemery			      fi
4216656Ssemery			      ;;
4220Sstevel@tonic-gate			esac
4230Sstevel@tonic-gate		done <$file
4240Sstevel@tonic-gate	else
4256656Ssemery		printf "\n$(gettext "The kclient profile \`%s' is not valid, exiting").\n" $file >&2
4260Sstevel@tonic-gate		error_message
4270Sstevel@tonic-gate	fi
4280Sstevel@tonic-gate}
4290Sstevel@tonic-gate
4306656Ssemeryfunction ping_check {
4310Sstevel@tonic-gate	typeset machine="$1"
4320Sstevel@tonic-gate	typeset string="$2"
4336656Ssemery
4346656Ssemery	if ping $machine 2 > /dev/null 2>&1; then
4350Sstevel@tonic-gate		:
4360Sstevel@tonic-gate	else
4376656Ssemery		printf "\n$(gettext "%s %s is unreachable, exiting").\n" $string $machine >&2
4380Sstevel@tonic-gate		error_message
4390Sstevel@tonic-gate	fi
4400Sstevel@tonic-gate
4410Sstevel@tonic-gate	# Output timesync warning if not using a profile, i.e. in
4420Sstevel@tonic-gate	# interactive mode.
4436656Ssemery	if [[ -z $profile && $string == KDC ]]; then
4440Sstevel@tonic-gate		# It's difficult to sync up time with KDC esp. if in a
4450Sstevel@tonic-gate		# zone so just print a warning about KDC time sync.
4466815Ssemery		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
4476815Ssemery		printf "$(gettext "Both systems should run some form of time synchronization system like Network Time Protocol (NTP)").\n" >&2
4486656Ssemerybreak
4490Sstevel@tonic-gate	fi
4500Sstevel@tonic-gate}
4510Sstevel@tonic-gate
4526656Ssemeryfunction check_value {
4530Sstevel@tonic-gate	typeset arg="$1"
4546656Ssemery
4556656Ssemery	if [[ -z $arg ]]; then
4566656Ssemery		printf "\n$(gettext "No input obtained for %s, exiting").\n" $checkval >&2
4570Sstevel@tonic-gate		error_message
4580Sstevel@tonic-gate	else
4596656Ssemery		echo "$arg" > $TMP_FILE
4600Sstevel@tonic-gate		if egrep -s '[*$^#!]+' $TMP_FILE; then
4616656Ssemery			printf "\n$(gettext "Invalid input obtained for %s, exiting").\n" $checkval >&2
4626656Ssemery			error_message
4636656Ssemery		fi
4646656Ssemery	fi
4656656Ssemery}
4666656Ssemery
4676656Ssemeryfunction set_dns_value {
4686656Ssemery	typeset -l arg="$1"
4696656Ssemery
4706656Ssemery	if [[ $arg == dns_lookup_kdc  ||  $arg == dns_lookup_realm  || $arg == dns_fallback ]]; then
4716656Ssemery		dns_lookup=yes
4726656Ssemery	else
4736656Ssemery		if [[ $arg == none ]]; then
4746656Ssemery			dns_lookup=no
4756656Ssemery		else
4766656Ssemery			printf "\n$(gettext "Invalid DNS lookup option, exiting").\n" >&2
4770Sstevel@tonic-gate			error_message
4780Sstevel@tonic-gate		fi
4790Sstevel@tonic-gate	fi
4800Sstevel@tonic-gate}
4810Sstevel@tonic-gate
4826656Ssemeryfunction verify_kdcs {
4836656Ssemery	typeset k_list="$1"
4846656Ssemery	typeset -l kdc
4856656Ssemery	typeset list fqhn f_list
4866656Ssemery
4876656Ssemery	kdc_list=$(echo "$k_list" | sed 's/,/ /g')
4886656Ssemery
4896656Ssemery	if [[ -z $k_list ]]; then
4906656Ssemery		printf "\n$(gettext "At least one KDC should be listed").\n\n" >&2
4916656Ssemery		usage
4926656Ssemery	fi
4936656Ssemery
4946656Ssemery	for kdc in $k_list; do
4956656Ssemery		if [[ $kdc != $KDC ]]; then
4966656Ssemery			list="$list $kdc"
4976656Ssemery			fkdc=`$KLOOKUP $kdc`
4986656Ssemery			if ping $fkdc 2 > /dev/null; then
4996656Ssemery				:
5006656Ssemery			else
5016656Ssemery				printf "\n$(gettext "%s %s is unreachable, no action performed").\n" "KDC" $fkdc >&2
5026656Ssemery			fi
5036656Ssemery			f_list="$f_list $fkdc"
5040Sstevel@tonic-gate		fi
5056656Ssemery	done
5066656Ssemery
5076656Ssemery	fkdc_list="$f_list"
5086656Ssemery	kdc_list="$list"
5090Sstevel@tonic-gate}
5100Sstevel@tonic-gate
5116656Ssemeryfunction parse_service {
5126656Ssemery	typeset service_list=$1
5130Sstevel@tonic-gate
5146656Ssemery	service_list=${service_list//,/ }
5156656Ssemery	for service in $service_list; do
5166656Ssemery		svc=${service%:}
5176656Ssemery		auth_type=${service#:}
5186656Ssemery		[[ -z $svc || -z $auth_type ]] && return
5196656Ssemery		print -- $svc $auth_type
5206656Ssemery	done
5216656Ssemery}
5226656Ssemery
5236656Ssemeryfunction verify_fqdnlist {
5246656Ssemery	typeset list="$1"
5256656Ssemery	typeset -l hostname
5266656Ssemery	typeset -i count=1
5276656Ssemery	typeset fqdnlist eachfqdn tmpvar fullhost
5286656Ssemery
5296656Ssemery	list=$(echo "$list" | tr -d " " | tr -d "\t")
5306656Ssemery	hostname=$(uname -n | cut -d"." -f1)
5310Sstevel@tonic-gate	fqdnlist=$client_machine
5320Sstevel@tonic-gate
5330Sstevel@tonic-gate	eachfqdn=$(echo "$list" | cut -d"," -f$count)
5346656Ssemery	if [[ -z $eachfqdn ]]; then
5356656Ssemery		printf "\n$(gettext "If the -f option is used, at least one FQDN should be listed").\n\n" >&2
5360Sstevel@tonic-gate		usage
5370Sstevel@tonic-gate	else
5386656Ssemery		while [[ ! -z $eachfqdn ]]; do
5390Sstevel@tonic-gate			tmpvar=$(echo "$eachfqdn" | cut -d"." -f1)
5406656Ssemery			if [[ -z $tmpvar ]]; then
5410Sstevel@tonic-gate				fullhost="$hostname$eachfqdn"
5420Sstevel@tonic-gate			else
5430Sstevel@tonic-gate				fullhost="$hostname.$eachfqdn"
5440Sstevel@tonic-gate			fi
5450Sstevel@tonic-gate
5466656Ssemery			ping_check $fullhost $(gettext "System")
5476656Ssemery			if [[ $fullhost == $client_machine ]]; then
5480Sstevel@tonic-gate				:
5490Sstevel@tonic-gate			else
5500Sstevel@tonic-gate				fqdnlist="$fqdnlist $fullhost"
5510Sstevel@tonic-gate			fi
5520Sstevel@tonic-gate
5536656Ssemery			if [[ $list == *,* ]]; then
5540Sstevel@tonic-gate				((count = count + 1))
5550Sstevel@tonic-gate				eachfqdn=$(echo "$list" | cut -d"," -f$count)
5560Sstevel@tonic-gate			else
5570Sstevel@tonic-gate				break
5580Sstevel@tonic-gate			fi
5590Sstevel@tonic-gate		done
5600Sstevel@tonic-gate	fi
5610Sstevel@tonic-gate}
5620Sstevel@tonic-gate
5636656Ssemeryfunction setup_keytab {
5646656Ssemery	typeset cname ask_fqdns current_release
5656656Ssemery
5666656Ssemery	#
5676656Ssemery	# 1. kinit with ADMIN_PRINC
5686656Ssemery	#
5696656Ssemery
5706656Ssemery	if [[ -z $ADMIN_PRINC ]]; then
5716656Ssemery		printf "\n$(gettext "Enter the krb5 administrative principal to be used"): "
5726656Ssemery		read ADMIN_PRINC
5736656Ssemery		checkval="ADMIN_PRINC"; check_value $ADMIN_PRINC
5746656Ssemery	fi
5756656Ssemery
5766656Ssemery	echo "$ADMIN_PRINC">$TMP_FILE
5776656Ssemery
5786656Ssemery	[[ -n $msad ]] && return
5796656Ssemery	if egrep -s '\/admin' $TMP_FILE; then
5806656Ssemery		# Already in "/admin" format, do nothing
5816656Ssemery		:
5826656Ssemery	else
5836656Ssemery		if egrep -s '\/' $TMP_FILE; then
5846656Ssemery			printf "\n$(gettext "Improper entry for krb5 admin principal, exiting").\n" >&2
5856656Ssemery			error_message
5866656Ssemery		else
5876656Ssemery			ADMIN_PRINC=$(echo "$ADMIN_PRINC/admin")
5886656Ssemery		fi
5896656Ssemery	fi
5906656Ssemery
5916656Ssemery	printf "$(gettext "Obtaining TGT for %s") ...\n" $ADMIN_PRINC
5926656Ssemery
5936656Ssemery	cname=$(canon_resolve $KDC)
5946656Ssemery	if [[ -n $cname ]]; then
5956656Ssemery		kinit -S kadmin/$cname $ADMIN_PRINC
5966656Ssemery	else
5976656Ssemery		kinit -S kadmin/$FKDC $ADMIN_PRINC
5986656Ssemery	fi
5996656Ssemery	klist 1>$TMP_FILE 2>&1
6006815Ssemery	if egrep -s "$(gettext "Valid starting")" $TMP_FILE && egrep -s "kadmin/$FKDC@$realm" $TMP_FILE; then
6016656Ssemery    		:
6026656Ssemery	else
6036656Ssemery		printf "\n$(gettext "kinit of %s failed, exiting").\n" $ADMIN_PRINC >&2
6046656Ssemery		error_message
6056656Ssemery	fi
6066656Ssemery
6076656Ssemery	#
6086656Ssemery	# 2. Do we want to create and/or add service principal(s) for fqdn's
6096656Ssemery	#    other than the one listed in resolv.conf(4) ?
6106656Ssemery	#
6116656Ssemery	if [[ -z $options ]]; then
6126656Ssemery		query "$(gettext "Do you have multiple DNS domains spanning the Kerberos realm") $realm ?"
6136656Ssemery		ask_fqdns=$answer
6146656Ssemery		if [[ $ask_fqdns == yes ]]; then
6156815Ssemery			printf "$(gettext "Enter a comma-separated list of DNS domain names"): "
6166656Ssemery			read fqdnlist
6176656Ssemery			verify_fqdnlist "$fqdnlist"
6186656Ssemery		else
6196656Ssemery			fqdnlist=$client_machine
6206656Ssemery		fi
6216656Ssemery	else
6226656Ssemery		if [[ -z $fqdnlist ]]; then
6236656Ssemery			fqdnlist=$client_machine
6246656Ssemery		fi
6256656Ssemery	fi
6266656Ssemery
6276656Ssemery	if [[ $add_nfs == yes ]]; then
6286656Ssemery		echo; call_kadmin nfs
6296656Ssemery	fi
6306656Ssemery
6316656Ssemery	# Add the host entry to the keytab
6326656Ssemery	echo; call_kadmin host
6336656Ssemery
6346656Ssemery}
6356656Ssemery
6366656Ssemeryfunction setup_lhn {
6376656Ssemery	typeset -l logical_hn
6386656Ssemery
6396656Ssemery	echo "$logical_hn" > $TMP_FILE
6406656Ssemery	if egrep -s '[^.]\.[^.]+$' $TMP_FILE; then
6416656Ssemery		# do nothing, logical_hn is in fqdn format
6426656Ssemery		:
6436656Ssemery	else
6446656Ssemery		if egrep -s '\.+' $TMP_FILE; then
6456656Ssemery			printf "\n$(gettext "Improper format of logical hostname, exiting").\n" >&2
6466656Ssemery			error_message
6476656Ssemery		else
6486656Ssemery			# Attach fqdn to logical_hn, to get the Fully Qualified
6496656Ssemery			# Host Name of the client requested
6506656Ssemery			logical_hn=$(echo "$logical_hn.$fqdn")
6516656Ssemery		fi
6526656Ssemery	fi
6536656Ssemery
6546656Ssemery	client_machine=$logical_hn
6556656Ssemery
6566656Ssemery	ping_check $client_machine $(gettext "System")
6576656Ssemery}
6586656Ssemery
6596656Ssemeryfunction usage {
6606656Ssemery	printf "\n$(gettext "Usage: kclient [ options ]")\n" >&2
6616656Ssemery	printf "\t$(gettext "where options are any of the following")\n\n" >&2
6626656Ssemery	printf "\t$(gettext "[ -D domain_list ]  configure a client that has mul
6636656Ssemerytiple mappings of doamin and/or hosts to the default realm")\n" >&2
6646656Ssemery	printf "\t$(gettext "[ -K ]  configure a client that does not have host/service keys")\n" >&2
6656656Ssemery	printf "\t$(gettext "[ -R realm ]  specifies the realm to use")\n" >&2
6666656Ssemery	printf "\t$(gettext "[ -T kdc_vendor ]  specifies which KDC vendor is the server")\n" >&2
6676656Ssemery	printf "\t$(gettext "[ -a adminuser ]  specifies the Kerberos administrator")\n" >&2
6686656Ssemery	printf "\t$(gettext "[ -c filepath ]  specifies the krb5.conf path used to configure this client")\n" >&2
6696656Ssemery	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
6706656Ssemery	printf "\t$(gettext "[ -f fqdn_list ]  specifies which domains to configure host keys for this client")\n" >&2
6716656Ssemery	printf "\t$(gettext "[ -h logicalhostname ]  configure the logical host name for a client that is in a cluster")\n" >&2
6726656Ssemery	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
6736656Ssemery	printf "\t$(gettext "[ -m master ]  master KDC server host name")\n" >&2
6746656Ssemery	printf "\t$(gettext "[ -n ]  configure client to be an NFS client")\n" >&2
6756656Ssemery	printf "\t$(gettext "[ -p profile ]  specifies which profile file to use to configure this client")\n" >&2
6766656Ssemery	printf "\t$(gettext "[ -s pam_list ]  update the service for Kerberos authentication")\n" >&2
6770Sstevel@tonic-gate	error_message
6780Sstevel@tonic-gate}
6790Sstevel@tonic-gate
6806656Ssemeryfunction discover_domain {
6816656Ssemery	typeset dom DOMs
6826656Ssemery
6836656Ssemery	if [[ -z $realm ]]; then
6846656Ssemery		set -A DOMs -- `$KLOOKUP _ldap._tcp.dc._msdcs S`
6856656Ssemery	else
6866656Ssemery		set -A DOMs -- `$KLOOKUP _ldap._tcp.dc._msdcs.$realm S`
6876656Ssemery	fi
6886656Ssemery
6896656Ssemery	[[ -z ${DOMs[0]} ]] && return 1
6906656Ssemery
6916656Ssemery	dom=${DOMs[0]}
6926656Ssemery
6936656Ssemery	dom=${dom#*.}
6946656Ssemery	dom=${dom% *}
6956656Ssemery
6966656Ssemery	domain=$dom
6976656Ssemery
6986656Ssemery	return 0
6996656Ssemery}
7006656Ssemery
7016656Ssemeryfunction check_nss_hosts_or_ipnodes_config {
7026656Ssemery	typeset backend
7036656Ssemery
7046656Ssemery	for backend in $1
7056656Ssemery	do
7066656Ssemery		[[ $backend == dns ]] && return 0
7076656Ssemery	done
7086656Ssemery	return 1
7096656Ssemery}
7106656Ssemery
7116656Ssemeryfunction check_nss_conf {
7126656Ssemery	typeset i j hosts_config
7136656Ssemery
7146656Ssemery	for i in hosts ipnodes
7156656Ssemery	do
7166656Ssemery		grep "^${i}:" /etc/nsswitch.conf|read j hosts_config
7176656Ssemery		check_nss_hosts_or_ipnodes_config "$hosts_config" || return 1
7186656Ssemery	done
7196656Ssemery
7206656Ssemery	return 0
7216656Ssemery}
7226656Ssemery
7236656Ssemeryfunction canon_resolve {
7246656Ssemery	typeset name ip
7256656Ssemery
7266656Ssemery	name=`$KLOOKUP $1 C`
7276656Ssemery	[[ -z $name ]] && name=`$KLOOKUP $1 A`
7286656Ssemery	[[ -z $name ]] && return
7296656Ssemery
7306656Ssemery	ip=`$KLOOKUP $name I`
7316656Ssemery	[[ -z $ip ]] && return
7326815Ssemery	for i in $ip
7336815Ssemery	do
7346815Ssemery		if ping $i 2 > /dev/null 2>&1; then
7356815Ssemery			break
7366815Ssemery		else
7376815Ssemery			i=
7386815Ssemery		fi
7396815Ssemery	done
7406656Ssemery
7416656Ssemery	cname=`$KLOOKUP $ip P`
7426656Ssemery	[[ -z $cname ]] && return
7436656Ssemery
7446656Ssemery	print -- "$cname"
7456656Ssemery}
7466656Ssemery
7476656Ssemeryfunction rev_resolve {
7486656Ssemery	typeset name ip
7496656Ssemery
7506656Ssemery	ip=`$KLOOKUP $1 I`
7516656Ssemery
7526656Ssemery	[[ -z $ip ]] && return
7536656Ssemery	name=`$KLOOKUP $ip P`
7546656Ssemery	[[ -z $name ]] && return
7556656Ssemery
7566656Ssemery	print -- $name
7576656Ssemery}
7586656Ssemery
7596656Ssemery# Convert an AD-style domain DN to a DNS domainname
7606656Ssemeryfunction dn2dns {
7616656Ssemery	typeset OIFS dname dn comp components
7626656Ssemery
7636656Ssemery	dn=$1
7646656Ssemery	dname=
7656656Ssemery
7666656Ssemery	OIFS="$IFS"
7676656Ssemery	IFS=,
7686656Ssemery	set -A components -- $1
7696656Ssemery	IFS="$OIFS"
7706656Ssemery
7716656Ssemery	for comp in "${components[@]}"
7726656Ssemery	do
7736656Ssemery		[[ "$comp" == [dD][cC]=* ]] || continue
7746656Ssemery		dname="$dname.${comp#??=}"
7756656Ssemery	done
7766656Ssemery
7776656Ssemery	print ${dname#.}
7786656Ssemery}
7796656Ssemery
7806656Ssemery# Form a base DN from a DNS domainname and container
7816656Ssemeryfunction getBaseDN {
7826656Ssemery	if [[ -n "$2" ]]
7836656Ssemery	then
7846656Ssemery		baseDN="CN=$1,$(dns2dn $2)"
7856656Ssemery	else
7866656Ssemery		baseDN="$(dns2dn $2)"
7876656Ssemery	fi
7886656Ssemery}
7896656Ssemery
7906656Ssemery# Convert a DNS domainname to an AD-style DN for that domain
7916656Ssemeryfunction dns2dn {
7926656Ssemery	typeset OIFS dn labels
7936656Ssemery
7946656Ssemery	OIFS="$IFS"
7956656Ssemery	IFS=.
7966656Ssemery	set -A labels -- $1
7976656Ssemery	IFS="$OIFS"
7986656Ssemery
7996656Ssemery	dn=
8006656Ssemery	for label in "${labels[@]}"
8016656Ssemery	do
8026656Ssemery		dn="${dn},DC=$label"
8036656Ssemery	done
8046656Ssemery
8056656Ssemery	print -- "${dn#,}"
8066656Ssemery}
8076656Ssemery
8086656Ssemeryfunction getSRVs {
8096656Ssemery	typeset srv port
8106656Ssemery
8116656Ssemery	$KLOOKUP $1 S | while read srv port
8126656Ssemery	do
8136815Ssemery		if ping $srv 2 > /dev/null 2>&1; then
8146815Ssemery			print -- $srv $port
8156815Ssemery		fi
8166656Ssemery	done
8176656Ssemery}
8186656Ssemery
8196656Ssemeryfunction getKDC {
8206656Ssemery	typeset j
8216656Ssemery
8226656Ssemery	set -A KPWs -- $(getSRVs _kpasswd._tcp.$dom.)
8236656Ssemery	kpasswd=${KPWs[0]}
8246656Ssemery
8256656Ssemery	if [[ -n $siteName ]]
8266656Ssemery	then
8276656Ssemery		set -A KDCs -- $(getSRVs _kerberos._tcp.$siteName._sites.$dom.)
8286656Ssemery		kdc=${KDCs[0]}
8296656Ssemery		[[ -n $kdc ]] && return
8306656Ssemery	fi
8316656Ssemery
8326656Ssemery	# No site name
8336656Ssemery	set -A KDCs -- $(getSRVs _kerberos._tcp.$dom.)
8346656Ssemery	kdc=${KDCs[0]}
8356656Ssemery	[[ -n $kdc ]] && return
8366656Ssemery
8376656Ssemery	# Default
8386656Ssemery	set -A KDCs -- $DomainDnsZones 88
8396656Ssemery	kdc=$ForestDnsZones
8406656Ssemery}
8416656Ssemery
8426656Ssemeryfunction getDC {
8436656Ssemery	typeset j
8446656Ssemery
8456656Ssemery	if [[ -n $siteName ]]
8466656Ssemery	then
8476656Ssemery		set -A DCs -- $(getSRVs _ldap._tcp.$siteName._sites.dc._msdcs.$dom.)
8486656Ssemery		dc=${DCs[0]}
8496656Ssemery		[[ -n $dc ]] && return
8506656Ssemery	fi
8516656Ssemery
8526656Ssemery	# No site name
8536656Ssemery	set -A DCs -- $(getSRVs _ldap._tcp.dc._msdcs.$dom.)
8546656Ssemery	dc=${DCs[0]}
8556656Ssemery	[[ -n $dc ]] && return
8566656Ssemery
8576656Ssemery	# Default
8586656Ssemery	set -A DCs -- $DomainDnsZones 389
8596656Ssemery	dc=$DomainDnsZones
8606656Ssemery}
8616656Ssemery
8626656Ssemeryfunction write_ads_krb5conf {
863*12567SShawn.Emery@Sun.COM	typeset kdcs
864*12567SShawn.Emery@Sun.COM
8656656Ssemery	printf "\n$(gettext "Setting up %s").\n\n" $KRB5_CONFIG_FILE
8666656Ssemery
8676656Ssemery	for i in ${KDCs[@]}
8686656Ssemery	do
8696656Ssemery		[[ $i == +([0-9]) ]] && continue
870*12567SShawn.Emery@Sun.COM		if [[ -n $kdcs ]]
871*12567SShawn.Emery@Sun.COM		then
872*12567SShawn.Emery@Sun.COM			kdcs="$kdcs,$i"
873*12567SShawn.Emery@Sun.COM		else
874*12567SShawn.Emery@Sun.COM			kdcs=$i
875*12567SShawn.Emery@Sun.COM		fi
8766656Ssemery	done
877*12567SShawn.Emery@Sun.COM
878*12567SShawn.Emery@Sun.COM	$KCONF -f $KRB5_CONFIG -r $realm -k $kdcs -m $KDC -p SET_CHANGE -d .$dom
879*12567SShawn.Emery@Sun.COM
880*12567SShawn.Emery@Sun.COM	if [[ $? -ne 0 ]]; then
881*12567SShawn.Emery@Sun.COM		printf "\n$(gettext "Can not update %s, exiting").\n" $KRB5_CONFIG >&2
882*12567SShawn.Emery@Sun.COM		error_message
883*12567SShawn.Emery@Sun.COM	fi
8846656Ssemery}
8856656Ssemery
8866656Ssemeryfunction getForestName {
8876656Ssemery	ldapsearch -R -T -h $dc $ldap_args \
8886656Ssemery	    -b "" -s base "" schemaNamingContext| \
8896656Ssemery		grep ^schemaNamingContext|read j schemaNamingContext
8906656Ssemery
8916656Ssemery	if [[ $? -ne 0 ]]; then
8929833SShawn.Emery@Sun.COM		printf "$(gettext "Can't find forest").\n" >&2
8936656Ssemery		error_message
8946656Ssemery	fi
8956656Ssemery	schemaNamingContext=${schemaNamingContext#CN=Schema,CN=Configuration,}
8966656Ssemery
8976656Ssemery	[[ -z $schemaNamingContext ]] && return 1
8986656Ssemery
8996656Ssemery	forest=
9006656Ssemery	while [[ -n $schemaNamingContext ]]
9016656Ssemery	do
9026656Ssemery		schemaNamingContext=${schemaNamingContext#DC=}
9036656Ssemery		forest=${forest}.${schemaNamingContext%%,*}
9046656Ssemery		[[ "$schemaNamingContext" = *,* ]] || break
9056656Ssemery		schemaNamingContext=${schemaNamingContext#*,}
9066656Ssemery	done
9076656Ssemery	forest=${forest#.}
9086656Ssemery}
9096656Ssemery
9106656Ssemeryfunction getGC {
9116656Ssemery	typeset j
9126656Ssemery
9136656Ssemery	[[ -n $gc ]] && return 0
9146656Ssemery
9156656Ssemery	if [[ -n $siteName ]]
9166656Ssemery	then
9176656Ssemery		set -A GCs -- $(getSRVs _ldap._tcp.$siteName._sites.gc._msdcs.$forest.)
9186656Ssemery		gc=${GCs[0]}
9196656Ssemery		[[ -n $gc ]] && return
9206656Ssemery	fi
9216656Ssemery
9226656Ssemery	# No site name
9236656Ssemery	set -A GCs -- $(getSRVs _ldap._tcp.gc._msdcs.$forest.)
9246656Ssemery	gc=${GCs[0]}
9256656Ssemery	[[ -n $gc ]] && return
9266656Ssemery
9276656Ssemery	# Default
9286656Ssemery	set -A GCs -- $ForestDnsZones 3268
9296656Ssemery	gc=$ForestDnsZones
9306656Ssemery}
9316656Ssemery
9329833SShawn.Emery@Sun.COM#
9339833SShawn.Emery@Sun.COM# The local variables used to calculate the IP address are of type unsigned
9349833SShawn.Emery@Sun.COM# integer (-ui), as this is required to restrict the integer to 32b.
9359833SShawn.Emery@Sun.COM# Starting in ksh88, Solaris has incorrectly assummed that -i represents 64b.
9369833SShawn.Emery@Sun.COM#
9376656Ssemeryfunction ipAddr2num {
9386656Ssemery	typeset OIFS
9399833SShawn.Emery@Sun.COM	typeset -ui16 num
9406656Ssemery
9416656Ssemery	if [[ "$1" != +([0-9]).+([0-9]).+([0-9]).+([0-9]) ]]
9426656Ssemery	then
9436656Ssemery		print 0
9446656Ssemery		return 0
9456656Ssemery	fi
9466656Ssemery
9476656Ssemery	OIFS="$IFS"
9486656Ssemery	IFS=.
9496656Ssemery	set -- $1
9506656Ssemery	IFS="$OIFS"
9516656Ssemery
9526656Ssemery	num=$((${1}<<24 | ${2}<<16 | ${3}<<8 | ${4}))
9536656Ssemery
9546656Ssemery	print -- $num
9556656Ssemery}
9566656Ssemery
9579833SShawn.Emery@Sun.COM#
9589833SShawn.Emery@Sun.COM# The local variables used to calculate the IP address are of type unsigned
9599833SShawn.Emery@Sun.COM# integer (-ui), as this is required to restrict the integer to 32b.
9609833SShawn.Emery@Sun.COM# Starting in ksh88, Solaris has incorrectly assummed that -i represents 64b.
9619833SShawn.Emery@Sun.COM#
9626656Ssemeryfunction num2ipAddr {
9639833SShawn.Emery@Sun.COM	typeset -ui16 num
9649833SShawn.Emery@Sun.COM	typeset -ui10 a b c d
9656656Ssemery
9666656Ssemery	num=$1
9676656Ssemery	a=$((num>>24        ))
9686656Ssemery	b=$((num>>16 & 16#ff))
9696656Ssemery	c=$((num>>8  & 16#ff))
9706656Ssemery	d=$((num     & 16#ff))
9716656Ssemery	print -- $a.$b.$c.$d
9726656Ssemery}
9736656Ssemery
9749833SShawn.Emery@Sun.COM#
9759833SShawn.Emery@Sun.COM# The local variables used to calculate the IP address are of type unsigned
9769833SShawn.Emery@Sun.COM# integer (-ui), as this is required to restrict the integer to 32b.
9779833SShawn.Emery@Sun.COM# Starting in ksh88, Solaris has incorrectly assummed that -i represents 64b.
9789833SShawn.Emery@Sun.COM#
9796656Ssemeryfunction netmask2length {
9809833SShawn.Emery@Sun.COM	typeset -ui16 netmask
9816656Ssemery	typeset -i len
9826656Ssemery
9836656Ssemery	netmask=$1
9846656Ssemery	len=32
9856656Ssemery	while [[ $((netmask % 2)) -eq 0 ]]
9866656Ssemery	do
9876656Ssemery		netmask=$((netmask>>1))
9886656Ssemery		len=$((len - 1))
9896656Ssemery	done
9906656Ssemery	print $len
9916656Ssemery}
9926656Ssemery
9939833SShawn.Emery@Sun.COM#
9949833SShawn.Emery@Sun.COM# The local variables used to calculate the IP address are of type unsigned
9959833SShawn.Emery@Sun.COM# integer (-ui), as this is required to restrict the integer to 32b.
9969833SShawn.Emery@Sun.COM# Starting in ksh88, Solaris has incorrectly assummed that -i represents 64b.
9979833SShawn.Emery@Sun.COM#
9986656Ssemeryfunction getSubnets {
9999833SShawn.Emery@Sun.COM	typeset -ui16 addr netmask
10009833SShawn.Emery@Sun.COM	typeset -ui16 classa=16\#ff000000
10016656Ssemery
10026656Ssemery	ifconfig -a|while read line
10036656Ssemery	do
10046656Ssemery		addr=0
10056656Ssemery		netmask=0
10066656Ssemery		set -- $line
10076656Ssemery		[[ $1 == inet ]] || continue
10086656Ssemery		while [[ $# -gt 0 ]]
10096656Ssemery		do
10106656Ssemery			case "$1" in
10116656Ssemery				inet) addr=$(ipAddr2num $2); shift;;
10126656Ssemery				netmask) eval netmask=16\#$2; shift;;
10136656Ssemery				*) :;
10146656Ssemery			esac
10156656Ssemery			shift
10166656Ssemery		done
10176656Ssemery
10186656Ssemery		[[ $addr -eq 0 || $netmask -eq 0 ]] && continue
10196656Ssemery		[[ $((addr & classa)) -eq 16\#7f000000 ]] && continue
10206656Ssemery
10216656Ssemery		print $(num2ipAddr $((addr & netmask)))/$(netmask2length $netmask)
10226656Ssemery	done
10236656Ssemery}
10246656Ssemery
10256656Ssemeryfunction getSite {
10266656Ssemery	typeset subnet siteDN j ldapsrv subnet_dom
10276656Ssemery
10286656Ssemery	eval "[[ -n \"\$siteName\" ]]" && return
10296656Ssemery	for subnet in $(getSubnets)
10306656Ssemery	do
10316656Ssemery		ldapsearch -R -T -h $dc $ldap_args \
10326656Ssemery		    -p 3268 -b "" -s sub cn=$subnet dn |grep ^dn|read j subnetDN
10336656Ssemery
10346656Ssemery		[[ -z $subnetDN ]] && continue
10356656Ssemery		subnet_dom=$(dn2dns $subnetDN)
10366656Ssemery		ldapsrv=$(canon_resolve DomainDnsZones.$subnet_dom)
10376815Ssemery		[[ -z $ldapsrv ]] && continue
10386656Ssemery		ldapsearch -R -T -h $ldapsrv $ldap_args \
10396656Ssemery		    -b "$subnetDN" -s base "" siteObject \
10406656Ssemery		    |grep ^siteObject|read j siteDN
10416656Ssemery
10426656Ssemery		[[ -z $siteDN ]] && continue
10436656Ssemery
10446656Ssemery		eval siteName=${siteDN%%,*}
10456656Ssemery		eval siteName=\${siteName#CN=}
10466656Ssemery		return
10476656Ssemery	done
10486656Ssemery}
10496656Ssemery
10506656Ssemeryfunction doKRB5config {
10516656Ssemery	[[ -f $KRB5_CONFIG_FILE ]] && \
10526656Ssemery		cp $KRB5_CONFIG_FILE ${KRB5_CONFIG_FILE}-pre-kclient
10536656Ssemery
10546656Ssemery	[[ -f $KRB5_KEYTAB_FILE ]] && \
10556656Ssemery		cp $KRB5_KEYTAB_FILE ${KRB5_KEYTAB_FILE}-pre-kclient
10566656Ssemery
10576815Ssemery	[[ -s $KRB5_CONFIG ]] && cp $KRB5_CONFIG $KRB5_CONFIG_FILE
10586815Ssemery	[[ -s $KRB5_CONFIG_FILE ]] && chmod 0644 $KRB5_CONFIG_FILE
10596815Ssemery	[[ -s $new_keytab ]] && cp $new_keytab $KRB5_KEYTAB_FILE
10606815Ssemery	[[ -s $KRB5_KEYTAB_FILE ]] && chmod 0600 $KRB5_KEYTAB_FILE
10616656Ssemery}
10626656Ssemery
10636656Ssemeryfunction addDNSRR {
10646656Ssemery	smbFMRI=svc:/network/smb/server:default
10656656Ssemery	ddnsProp=smbd/ddns_enable
10666656Ssemery	enProp=general/enabled
10676656Ssemery
10686656Ssemery	enabled=`svcprop -p $enProp $smbFMRI`
10696656Ssemery	ddns_enable=`svcprop -p $ddnsProp $smbFMRI`
10706656Ssemery
10716656Ssemery	if [[ $enabled == true && $ddns_enable != true ]]; then
10726656Ssemery		printf "$(gettext "Warning: won't create DNS records for client").\n"
10736656Ssemery		printf "$(gettext "%s property not set to 'true' for the %s FMRI").\n" $ddnsProp $smbFMRI
10746656Ssemery		return
10756656Ssemery	fi
10766656Ssemery
10776656Ssemery	# Destroy any existing ccache as GSS_C_NO_CREDENTIAL will pick up any
10786656Ssemery	# residual default credential in the cache.
10796656Ssemery	kdestroy > /dev/null 2>&1
10806656Ssemery
10816656Ssemery	$KDYNDNS -d $1 > /dev/null 2>&1
10826656Ssemery	if [[ $? -ne 0 ]]; then
10836656Ssemery		#
10846656Ssemery		# Non-fatal, we should carry-on as clients may resolve to
10856656Ssemery		# different servers and the client could already exist there.
10866656Ssemery		#
10878334SJose.Borrego@Sun.COM		printf "$(gettext "Warning: unable to create DNS records for client").\n"
10886656Ssemery		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
10896656Ssemery	fi
10906656Ssemery}
10916656Ssemery
10926656Ssemeryfunction setSMB {
10936656Ssemery	typeset domain=$1
10946656Ssemery	typeset server=$2
10956656Ssemery	smbFMRI=svc:/network/smb/server
10966656Ssemery
109711570SShawn.Emery@Sun.COM	printf "%s" "$newpw" | $KSMB -d $domain -s $server
10986656Ssemery	if [[ $? -ne 0 ]]; then
10998334SJose.Borrego@Sun.COM		printf "$(gettext "Warning: unable to set %s domain, server and password information").\n" $smbFMRI
11006656Ssemery		return
11016656Ssemery	fi
11026656Ssemery
11038334SJose.Borrego@Sun.COM	svcadm restart $smbFMRI > /dev/null 2>&1
11046656Ssemery	if [[ $? -ne 0 ]]; then
11058334SJose.Borrego@Sun.COM		printf "$(gettext "Warning: unable to restart %s").\n" $smbFMRI
11066656Ssemery	fi
11076656Ssemery}
11086656Ssemery
11096656Ssemeryfunction compareDomains {
11106656Ssemery	typeset oldDom hspn newDom=$1
11116656Ssemery
11126656Ssemery	# If the client has been previously configured in a different
11136656Ssemery	# realm/domain then we need to prompt the user to see if they wish to
11146656Ssemery	# switch domains.
11156815Ssemery	klist -k 2>&1 | grep @ | read j hspn
11166656Ssemery	[[ -z $hspn ]] && return
11176656Ssemery
11186656Ssemery	oldDom=${hspn#*@}
11196656Ssemery	if [[ $oldDom != $newDom ]]; then
11206656Ssemery		printf "$(gettext "The client is currently configured in a different domain").\n"
11216656Ssemery		printf "$(gettext "Currently in the '%s' domain, trying to join the '%s' domain").\n" $oldDom $newDom
11226656Ssemery		query "$(gettext "Do you want the client to join a new domain") ?"
11236656Ssemery		printf "\n"
11246656Ssemery		if [[ $answer != yes ]]; then
11259833SShawn.Emery@Sun.COM			printf "$(gettext "Client will not be joined to the new domain").\n" >&2
11266656Ssemery			error_message
11276656Ssemery		fi
11286656Ssemery	fi
11296656Ssemery}
11306656Ssemery
11316656Ssemeryfunction getKDCDC {
11326656Ssemery
11336656Ssemery	getKDC
11346656Ssemery	if [[ -n $kdc ]]; then
11356656Ssemery		KDC=$kdc
11366656Ssemery		dc=$kdc
11376656Ssemery	else
11386656Ssemery		getDC
11396656Ssemery		if [[ -n $dc ]]; then
11406656Ssemery			KDC=$dc
11416656Ssemery		else
11429833SShawn.Emery@Sun.COM			printf "$(gettext "Could not find domain controller server for '%s'.  Exiting").\n" $realm >&2
11436656Ssemery			error_message
11446656Ssemery		fi
11456656Ssemery	fi
11466656Ssemery}
11476656Ssemery
114811570SShawn.Emery@Sun.COMfunction gen_rand {
114911570SShawn.Emery@Sun.COM	typeset -u hex
115011570SShawn.Emery@Sun.COM
115111570SShawn.Emery@Sun.COM	dd if=/dev/random bs=1 count=1 2>/dev/null | od -A n -tx1 | read hex
115211570SShawn.Emery@Sun.COM
115311570SShawn.Emery@Sun.COM	printf %s $((16#$hex))
115411570SShawn.Emery@Sun.COM}
115511570SShawn.Emery@Sun.COM
11566656Ssemeryfunction join_domain {
11576656Ssemery	typeset -u upcase_nodename
115811061SShawn.Emery@Sun.COM	typeset -l locase_nodename
115911061SShawn.Emery@Sun.COM	typeset -L15 string15
11606656Ssemery	typeset netbios_nodename fqdn
11616656Ssemery
11626656Ssemery	container=Computers
11636656Ssemery	ldap_args="-o authzid= -o mech=gssapi"
11646656Ssemery	userAccountControlBASE=4096
11656656Ssemery
11666656Ssemery	if [[ -z $ADMIN_PRINC ]]; then
11676656Ssemery		cprinc=Administrator
11686656Ssemery	else
11696656Ssemery		cprinc=$ADMIN_PRINC
11706656Ssemery	fi
11716656Ssemery
11726656Ssemery	if ! discover_domain; then
11739833SShawn.Emery@Sun.COM		printf "$(gettext "Can not find realm") '%s'.\n" $realm >&2
11746656Ssemery		error_message
11756656Ssemery	fi
11766656Ssemery
11776656Ssemery	dom=$domain
11786656Ssemery	realm=$domain
117911061SShawn.Emery@Sun.COM
118011061SShawn.Emery@Sun.COM	if [[ ${#hostname} -gt 15 ]]; then
118111061SShawn.Emery@Sun.COM		string15=$hostname
118211061SShawn.Emery@Sun.COM		upcase_nodename=$string15
118311061SShawn.Emery@Sun.COM		locase_nodename=$string15
118411061SShawn.Emery@Sun.COM	else
118511061SShawn.Emery@Sun.COM		upcase_nodename=$hostname
118611061SShawn.Emery@Sun.COM		locase_nodename=$hostname
118711061SShawn.Emery@Sun.COM	fi
118811061SShawn.Emery@Sun.COM
11896656Ssemery	netbios_nodename="${upcase_nodename}\$"
11906656Ssemery	fqdn=$hostname.$domain
119110001SJoyce.McIntosh@Sun.COM	upn=host/${fqdn}@${realm}
11926656Ssemery
11936656Ssemery	grep=/usr/xpg4/bin/grep
11946656Ssemery
11956656Ssemery	object=$(mktemp -q -t kclient-computer-object.XXXXXX)
11966656Ssemery	if [[ -z $object ]]; then
11976656Ssemery		printf "\n$(gettext "Can not create temporary file, exiting").\n
11986656Ssemery" >&2
11996656Ssemery		error_message
12006656Ssemery        fi
12016656Ssemery
12026656Ssemery	grep=/usr/xpg4/bin/grep
12036656Ssemery
12046656Ssemery	modify_existing=false
12056656Ssemery	recreate=false
12066656Ssemery
12076656Ssemery	DomainDnsZones=$(rev_resolve DomainDnsZones.$dom.)
12086656Ssemery	ForestDnsZones=$(rev_resolve ForestDnsZones.$dom.)
12096656Ssemery
12106656Ssemery	getBaseDN "$container" "$dom"
12116656Ssemery
12126656Ssemery	if [[ -n $KDC ]]; then
12136656Ssemery		dc=$KDC
12146656Ssemery	else
12156656Ssemery		getKDCDC
12166656Ssemery	fi
12176656Ssemery
12186656Ssemery	write_ads_krb5conf
12196656Ssemery
12206815Ssemery	printf "$(gettext "Attempting to join '%s' to the '%s' domain").\n\n" $upcase_nodename $realm
12216656Ssemery
12226656Ssemery	kinit $cprinc@$realm
12236656Ssemery	if [[ $? -ne 0 ]]; then
12249833SShawn.Emery@Sun.COM		printf "$(gettext "Could not authenticate %s.  Exiting").\n" $cprinc@$realm >&2
12256656Ssemery		error_message
12266656Ssemery	fi
12276656Ssemery
12286656Ssemery	if getForestName
12296656Ssemery	then
12306656Ssemery		printf "\n$(gettext "Forest name found: %s")\n\n" $forest
12316656Ssemery	else
12326656Ssemery		printf "\n$(gettext "Forest name not found, assuming forest is the domain name").\n"
12336656Ssemery	fi
12346656Ssemery
12356656Ssemery	getGC
12366656Ssemery	getSite
12376656Ssemery
12386656Ssemery	if [[ -z $siteName ]]
12396656Ssemery	then
12406656Ssemery    		printf "$(gettext "Site name not found.  Local DCs/GCs will not be discovered").\n\n"
12416656Ssemery	else
12426656Ssemery    		printf "$(gettext "Looking for _local_ KDCs, DCs and global catalog servers (SRV RRs)").\n"
12436656Ssemery		getKDCDC
12446656Ssemery		getGC
12456656Ssemery
12466656Ssemery		write_ads_krb5conf
12476656Ssemery	fi
12486656Ssemery
12496656Ssemery	if [[ ${#GCs} -eq 0 ]]; then
12509833SShawn.Emery@Sun.COM		printf "$(gettext "Could not find global catalogs.  Exiting").\n" >&2
12516656Ssemery		error_message
12526656Ssemery	fi
12536656Ssemery
12546656Ssemery	# Check to see if the client is transitioning between domains.
12556656Ssemery	compareDomains $realm
12566656Ssemery
12576656Ssemery	# Here we check domainFunctionality to see which release:
12586656Ssemery	# 0, 1, 2: Windows 2000, 2003 Interim, 2003 respecitively
12596656Ssemery	# 3: Windows 2008
12606656Ssemery	level=0
12616656Ssemery	ldapsearch -R -T -h "$dc" $ldap_args -b "" -s base "" \
12626656Ssemery	 domainControllerFunctionality| grep ^domainControllerFunctionality| \
12636656Ssemery	 read j level
12646656Ssemery	if [[ $? -ne 0 ]]; then
12659833SShawn.Emery@Sun.COM		printf "$(gettext "Search for domain functionality failed, exiting").\n" >&2
12666656Ssemery		error_message
12676656Ssemery	fi
12686656Ssemery
12696656Ssemery	if ldapsearch -R -T -h "$dc" $ldap_args -b "$baseDN" \
12706656Ssemery	    -s sub sAMAccountName="$netbios_nodename" dn > /dev/null 2>&1
12716656Ssemery	then
12726656Ssemery		:
12736656Ssemery	else
12749833SShawn.Emery@Sun.COM		printf "$(gettext "Search for node failed, exiting").\n" >&2
12756656Ssemery		error_message
12766656Ssemery	fi
12776656Ssemery	ldapsearch -R -T -h "$dc" $ldap_args -b "$baseDN" -s sub \
12786656Ssemery	    sAMAccountName="$netbios_nodename" dn|grep "^dn:"|read j dn
12796656Ssemery
12806656Ssemery	if [[ -z $dn ]]; then
12816656Ssemery		: # modify_existing is already false, which is what we want.
12826656Ssemery	else
12836656Ssemery		printf "$(gettext "Computer account '%s' already exists in the '%s' domain").\n" $upcase_nodename $realm
12846656Ssemery		query "$(gettext "Do you wish to recreate this computer account") ?"
12856656Ssemery		printf "\n"
12866656Ssemery		if [[ $answer == yes ]]; then
12876656Ssemery			recreate=true
12886656Ssemery		else
12896656Ssemery			modify_existing=true
12906656Ssemery		fi
12916656Ssemery	fi
12926656Ssemery
12936656Ssemery	if [[ $modify_existing == false && -n $dn ]]; then
12946656Ssemery		query "$(gettext "Would you like to delete any sub-object found for this computer account") ?"
12956656Ssemery		if [[ $answer == yes ]]; then
12966656Ssemery			printf "$(gettext "Looking to see if the machine account contains other objects")...\n"
12976656Ssemery			ldapsearch -R -T -h "$dc" $ldap_args -b "$dn" -s sub "" dn | while read j sub_dn
12986656Ssemery			do
12996656Ssemery				[[ $j != dn: || -z $sub_dn || $dn == $sub_dn ]] && continue
13006656Ssemery				if $recreate; then
13016656Ssemery					printf "$(gettext "Deleting the following object: %s")\n" ${sub_dn#$dn}
13026656Ssemery					ldapdelete -h "$dc" $ldap_args "$sub_dn" > /dev/null 2>&1
13036656Ssemery					if [[ $? -ne 0 ]]; then
13046656Ssemery						printf "$(gettext "Error in deleting object: %s").\n" ${sub_dn#$dn}
13056656Ssemery					fi
13066656Ssemery				else
13076656Ssemery					printf "$(gettext "The following object will not be deleted"): %s\n" ${sub_dn#$dn}
13086656Ssemery				fi
13096656Ssemery			done
13106656Ssemery		fi
13116656Ssemery
13126656Ssemery		if $recreate; then
13136656Ssemery			ldapdelete -h "$dc" $ldap_args "$dn" > /dev/null 2>&1
13146656Ssemery			if [[ $? -ne 0 ]]; then
13159833SShawn.Emery@Sun.COM				printf "$(gettext "Error in deleting object: %s").\n" ${sub_dn#$dn} >&2
13166656Ssemery				error_message
13176656Ssemery			fi
13186656Ssemery		elif $modify_existing; then
13196656Ssemery			: # Nothing to delete
13206656Ssemery		else
13219833SShawn.Emery@Sun.COM			printf "$(gettext "A machine account already exists").\n" >&2
13226656Ssemery			error_message
13236656Ssemery		fi
13246656Ssemery	fi
13256656Ssemery
132611061SShawn.Emery@Sun.COM	[[ -z $dn ]] && dn="CN=${upcase_nodename},${baseDN}"
13276656Ssemery	if $modify_existing; then
13286656Ssemery		cat > "$object" <<EOF
132911061SShawn.Emery@Sun.COMdn: $dn
13306656Ssemerychangetype: modify
13316656Ssemeryreplace: userPrincipalName
13326656SsemeryuserPrincipalName: $upn
13336656Ssemery-
13346656Ssemeryreplace: servicePrincipalName
13356656SsemeryservicePrincipalName: host/${fqdn}
13366656Ssemery-
13376656Ssemeryreplace: userAccountControl
13386656SsemeryuserAccountControl: $((userAccountControlBASE + 32 + 2))
13396656Ssemery-
13406656Ssemeryreplace: dNSHostname
13416656SsemerydNSHostname: ${fqdn}
13426656SsemeryEOF
13436656Ssemery
13446656Ssemery		printf "$(gettext "A machine account already exists; updating it").\n"
13456815Ssemery		ldapadd -h "$dc" $ldap_args -f "$object" > /dev/null 2>&1
13466656Ssemery		if [[ $? -ne 0 ]]; then
134711061SShawn.Emery@Sun.COM			printf "$(gettext "Failed to modify the AD object via LDAP").\n" >&2
13486656Ssemery			error_message
13496656Ssemery		fi
13506656Ssemery	else
135111061SShawn.Emery@Sun.COM		dn="CN=${upcase_nodename},${baseDN}"
13526656Ssemery		cat > "$object" <<EOF
135311061SShawn.Emery@Sun.COMdn: $dn
13546656SsemeryobjectClass: computer
13556656Ssemerycn: $upcase_nodename
13566656SsemerysAMAccountName: ${netbios_nodename}
13576656SsemeryuserPrincipalName: $upn
13586656SsemeryservicePrincipalName: host/${fqdn}
13596656SsemeryuserAccountControl: $((userAccountControlBASE + 32 + 2))
13606656SsemerydNSHostname: ${fqdn}
13616656SsemeryEOF
13626656Ssemery
13636656Ssemery		printf "$(gettext "Creating the machine account in AD via LDAP").\n\n"
13646656Ssemery
13656656Ssemery		ldapadd -h "$dc" $ldap_args -f "$object" > /dev/null 2>&1
13666656Ssemery		if [[ $? -ne 0 ]]; then
13679833SShawn.Emery@Sun.COM			printf "$(gettext "Failed to create the AD object via LDAP").\n" >&2
13686656Ssemery			error_message
13696656Ssemery		fi
13706656Ssemery	fi
13716656Ssemery
13726656Ssemery	# Generate a new password for the new account
137311570SShawn.Emery@Sun.COM	MAX_PASS=120
13746656Ssemery        i=0
13756656Ssemery
137611570SShawn.Emery@Sun.COM	# first check to see if /dev/random exists to generate a new password
137711570SShawn.Emery@Sun.COM	if [[ ! -h /dev/random ]]; then
137811570SShawn.Emery@Sun.COM		printf "$(gettext "/dev/random does not exist").\n" >&2
137911570SShawn.Emery@Sun.COM		error_message
138011570SShawn.Emery@Sun.COM	fi
13816656Ssemery
138211570SShawn.Emery@Sun.COM	while ((MAX_PASS > i))
138311570SShawn.Emery@Sun.COM	do
138411570SShawn.Emery@Sun.COM		# [MS-DISO] A machine password is an ASCII string of randomly
138511570SShawn.Emery@Sun.COM		# chosen characters. Each character's ASCII code is between 32
138611570SShawn.Emery@Sun.COM		# and 122 inclusive.
138711570SShawn.Emery@Sun.COM		c=$(printf "\\$(printf %o $(($(gen_rand) % 91 + 32)))\n")
138811570SShawn.Emery@Sun.COM		p="$p$c"
138911570SShawn.Emery@Sun.COM		((i+=1))
139011570SShawn.Emery@Sun.COM	done
13916656Ssemery
13926656Ssemery	newpw=$p
139311570SShawn.Emery@Sun.COM	if [[ ${#newpw} -ne MAX_PASS ]]; then
139411570SShawn.Emery@Sun.COM		printf "$(gettext "Password created was of incorrect length").\n" >&2
139511570SShawn.Emery@Sun.COM		error_message
139611570SShawn.Emery@Sun.COM	fi
13976656Ssemery
13986656Ssemery	# Set the new password
139911570SShawn.Emery@Sun.COM	printf "%s" "$newpw" | $KSETPW ${netbios_nodename}@${realm} > /dev/null 2>&1
14006656Ssemery	if [[ $? -ne 0 ]]
14016656Ssemery	then
14029833SShawn.Emery@Sun.COM		printf "$(gettext "Failed to set account password").\n" >&2
14036656Ssemery		error_message
14046656Ssemery	fi
14056656Ssemery
14066656Ssemery	# Lookup the new principal's kvno:
14076656Ssemery	ldapsearch -R -T -h "$dc" $ldap_args -b "$baseDN" \
14086656Ssemery		 -s sub cn=$upcase_nodename msDS-KeyVersionNumber| \
14096656Ssemery		grep "^msDS-KeyVersionNumber"|read j kvno
14106656Ssemery	[[ -z $kvno ]] && kvno=1
14116656Ssemery
14126656Ssemery	# Set supported enctypes.  This only works for Longhorn/Vista, so we
14136656Ssemery	# ignore errors here.
14146656Ssemery	userAccountControl=$((userAccountControlBASE + 524288 + 65536))
14156656Ssemery	set -A enctypes --
14166656Ssemery
14176656Ssemery	# Do we have local support for AES?
14186656Ssemery	encrypt -l|grep ^aes|read j minkeysize maxkeysize
14196656Ssemery	val=
14206656Ssemery	if [[ $maxkeysize -eq 256 ]]; then
14216656Ssemery		val=16
14226656Ssemery		enctypes[${#enctypes[@]}]=aes256-cts-hmac-sha1-96
14236656Ssemery	fi
14246656Ssemery	if [[ $minkeysize -eq 128 ]]; then
14256656Ssemery		((val=val+8))
14266656Ssemery		enctypes[${#enctypes[@]}]=aes128-cts-hmac-sha1-96
14276656Ssemery	fi
14286656Ssemery
14296656Ssemery	# RC4 comes next (whether it's better than 1DES or not -- AD prefers it)
14306656Ssemery	if encrypt -l|$grep -q ^arcfour
14316656Ssemery	then
14326656Ssemery		((val=val+4))
14336656Ssemery		enctypes[${#enctypes[@]}]=arcfour-hmac-md5
14346656Ssemery	else
14356656Ssemery		# Use 1DES ONLY if we don't have arcfour
14366656Ssemery		userAccountControl=$((userAccountControl + 2097152))
14376656Ssemery	fi
14386656Ssemery	if encrypt -l | $grep -q ^des
14396656Ssemery	then
14409833SShawn.Emery@Sun.COM		((val=val+2))
14416656Ssemery		enctypes[${#enctypes[@]}]=des-cbc-md5
14426656Ssemery	fi
14436656Ssemery
14446656Ssemery	if [[ ${#enctypes[@]} -eq 0 ]]
14456656Ssemery	then
14466656Ssemery		printf "$(gettext "No enctypes are supported").\n"
14479833SShawn.Emery@Sun.COM		printf "$(gettext "Please enable arcfour or 1DES, then re-join; see cryptoadm(1M)").\n" >&2
14486656Ssemery		error_message
14496656Ssemery	fi
14506656Ssemery
14516656Ssemery	# If domain crontroller is Longhorn or above then set new supported
14526656Ssemery	# encryption type attributes.
14536656Ssemery	if [[ $level -gt 2 ]]; then
14546656Ssemery		cat > "$object" <<EOF
145511061SShawn.Emery@Sun.COMdn: $dn
14566656Ssemerychangetype: modify
14576656Ssemeryreplace: msDS-SupportedEncryptionTypes
14586656SsemerymsDS-SupportedEncryptionTypes: $val
14596656SsemeryEOF
14606656Ssemery		ldapmodify -h "$dc" $ldap_args -f "$object" >/dev/null 2>&1
14616656Ssemery		if [[ $? -ne 0 ]]; then
14626656Ssemery			printf "$(gettext "Warning: Could not set the supported encryption type for computer account").\n"
14636656Ssemery		fi
14646656Ssemery	fi
14656656Ssemery
14666656Ssemery	# We should probably check whether arcfour is available, and if not,
14676656Ssemery	# then set the 1DES only flag, but whatever, it's not likely NOT to be
14686656Ssemery	# available on S10/Nevada!
14696656Ssemery
14706656Ssemery	# Reset userAccountControl
14716656Ssemery	#
14726656Ssemery	#  NORMAL_ACCOUNT (512) | DONT_EXPIRE_PASSWORD (65536) |
14736656Ssemery	#  TRUSTED_FOR_DELEGATION (524288)
14746656Ssemery	#
14756656Ssemery	# and possibly UseDesOnly (2097152) (see above)
14766656Ssemery	#
14776656Ssemery	cat > "$object" <<EOF
147811061SShawn.Emery@Sun.COMdn: $dn
14796656Ssemerychangetype: modify
14806656Ssemeryreplace: userAccountControl
14816656SsemeryuserAccountControl: $userAccountControl
14826656SsemeryEOF
14836656Ssemery	ldapmodify -h "$dc" $ldap_args -f "$object" >/dev/null 2>&1
14846656Ssemery	if [[ $? -ne 0 ]]; then
14859833SShawn.Emery@Sun.COM		printf "$(gettext "ldapmodify failed to modify account attribute").\n" >&2
14866656Ssemery		error_message
14876656Ssemery	fi
14886656Ssemery
14896656Ssemery	# Setup a keytab file
14906656Ssemery	set -A args --
14916656Ssemery	for enctype in "${enctypes[@]}"
14926656Ssemery	do
14936656Ssemery		args[${#args[@]}]=-e
14946656Ssemery		args[${#args[@]}]=$enctype
14956656Ssemery	done
14966656Ssemery
14976656Ssemery	rm $new_keytab > /dev/null 2>&1
14986656Ssemery
14996656Ssemery	cat > "$object" <<EOF
150011061SShawn.Emery@Sun.COMdn: $dn
15016656Ssemerychangetype: modify
15026656Ssemeryadd: servicePrincipalName
15036656SsemeryservicePrincipalName: nfs/${fqdn}
15046656SsemeryservicePrincipalName: HTTP/${fqdn}
15056656SsemeryservicePrincipalName: root/${fqdn}
15069833SShawn.Emery@Sun.COMservicePrincipalName: cifs/${fqdn}
150711061SShawn.Emery@Sun.COMservicePrincipalName: host/${upcase_nodename}
15086656SsemeryEOF
15096656Ssemery	ldapmodify -h "$dc" $ldap_args -f "$object" >/dev/null 2>&1
15106656Ssemery	if [[ $? -ne 0 ]]; then
15119833SShawn.Emery@Sun.COM		printf "$(gettext "ldapmodify failed to modify account attribute").\n" >&2
15126656Ssemery		error_message
15136656Ssemery	fi
15146656Ssemery
15159833SShawn.Emery@Sun.COM	#
15169833SShawn.Emery@Sun.COM	# In Windows, unlike MIT based implementations we salt the keys with
151711061SShawn.Emery@Sun.COM	# the UPN, which is based on the host/string15@realm elements, not
151811061SShawn.Emery@Sun.COM	# with the individual SPN strings.
15199833SShawn.Emery@Sun.COM	#
152011061SShawn.Emery@Sun.COM	salt=host/${locase_nodename}.${domain}@${realm}
15219833SShawn.Emery@Sun.COM
152212566SShawn.Emery@Sun.COM	skeys=(host/${fqdn}@${realm} nfs/${fqdn}@${realm} HTTP/${fqdn}@${realm})
152312566SShawn.Emery@Sun.COM	skeys+=(root/${fqdn}@${realm} cifs/${fqdn}@${realm})
152412566SShawn.Emery@Sun.COM	skeys+=(${netbios_nodename}@${realm} host/${upcase_nodename}@${realm})
152512566SShawn.Emery@Sun.COM	skeys+=(cifs/${upcase_nodename}@${realm})
15269833SShawn.Emery@Sun.COM
152712566SShawn.Emery@Sun.COM	ks_args="-n -s $salt -v $kvno -k $new_keytab ${args[@]}"
15286656Ssemery
152912566SShawn.Emery@Sun.COM	for skey in ${skeys[@]}
153012566SShawn.Emery@Sun.COM	do
153112566SShawn.Emery@Sun.COM		printf "%s" "$newpw" | $KSETPW $ks_args $skey > /dev/null 2>&1
153212566SShawn.Emery@Sun.COM		if [[ $? -ne 0 ]]
153312566SShawn.Emery@Sun.COM		then
153412566SShawn.Emery@Sun.COM			printf "$(gettext "Failed to set password").\n" >&2
153512566SShawn.Emery@Sun.COM			error_message
153612566SShawn.Emery@Sun.COM		fi
153712566SShawn.Emery@Sun.COM	done
153811061SShawn.Emery@Sun.COM
15396656Ssemery	doKRB5config
15406656Ssemery
15416656Ssemery	addDNSRR $dom
15426656Ssemery
15436656Ssemery	setSMB $dom $dc
15446656Ssemery
154511061SShawn.Emery@Sun.COM	printf -- "---------------------------------------------------\n"
15466656Ssemery	printf "$(gettext "Setup COMPLETE").\n\n"
15476656Ssemery
15486656Ssemery	kdestroy -q 1>$TMP_FILE 2>&1
15496656Ssemery	rm -f $TMP_FILE
15506656Ssemery	rm -rf $TMPDIR > /dev/null 2>&1
15516656Ssemery
15526656Ssemery	exit 0
15536656Ssemery}
15546656Ssemery
15550Sstevel@tonic-gate###########################
15560Sstevel@tonic-gate#	Main section	  #
15570Sstevel@tonic-gate###########################
15580Sstevel@tonic-gate#
15590Sstevel@tonic-gate# Set the Kerberos config file and some default strings/files
15600Sstevel@tonic-gate#
15616656SsemeryKRB5_CONFIG_FILE=/etc/krb5/krb5.conf
15626656SsemeryKRB5_KEYTAB_FILE=/etc/krb5/krb5.keytab
15636656SsemeryRESOLV_CONF_FILE=/etc/resolv.conf
15646656Ssemery
15656656SsemeryKLOOKUP=/usr/lib/krb5/klookup;	check_bin $KLOOKUP
15666656SsemeryKSETPW=/usr/lib/krb5/ksetpw;	check_bin $KSETPW
15676656SsemeryKSMB=/usr/lib/krb5/ksmb;	check_bin $KSMB
15686656SsemeryKDYNDNS=/usr/lib/krb5/kdyndns;	check_bin $KDYNDNS
1569*12567SShawn.Emery@Sun.COMKCONF=/usr/lib/krb5/kconf;	check_bin $KCONF
15706656Ssemery
15716656Ssemerydns_lookup=no
15726656Ssemeryask_fqdns=no
15736656Ssemeryadddns=no
15746815Ssemeryno_keytab=no
15750Sstevel@tonic-gatecheckval=""
15760Sstevel@tonic-gateprofile=""
15776656Ssemerytypeset -u realm
15786656Ssemerytypeset -l hostname KDC
15790Sstevel@tonic-gate
15806656Ssemeryexport TMPDIR="/var/run/kclient"
15816656Ssemery
15826656Ssemerymkdir $TMPDIR > /dev/null 2>&1
15839833SShawn.Emery@Sun.COMif [[ $? -ne 0 ]]; then
15849833SShawn.Emery@Sun.COM	printf "\n$(gettext "Can not create directory: %s")\n\n" $TMPDIR >&2
15859833SShawn.Emery@Sun.COM	exit 1
15869833SShawn.Emery@Sun.COMfi
15870Sstevel@tonic-gate
15886656SsemeryTMP_FILE=$(mktemp -q -t kclient-tmpfile.XXXXXX)
15896656Ssemeryexport KRB5_CONFIG=$(mktemp -q -t kclient-krb5conf.XXXXXX)
15906815Ssemeryexport KRB5CCNAME=$(mktemp -q -t kclient-krb5ccache.XXXXXX)
15916656Ssemerynew_keytab=$(mktemp -q -t kclient-krb5keytab.XXXXXX)
15926656Ssemeryif [[ -z $TMP_FILE || -z $KRB5_CONFIG || -z $KRB5CCNAME || -z $new_keytab ]]
15936656Ssemerythen
15949833SShawn.Emery@Sun.COM	printf "\n$(gettext "Can not create temporary files, exiting").\n\n" >&2
15959833SShawn.Emery@Sun.COM	exit 1
15960Sstevel@tonic-gatefi
15970Sstevel@tonic-gate
15980Sstevel@tonic-gate#
15990Sstevel@tonic-gate# If we are interrupted, cleanup after ourselves
16000Sstevel@tonic-gate#
16016656Ssemerytrap "exiting 1" HUP INT QUIT TERM
16020Sstevel@tonic-gate
16036656Ssemeryif [[ -d /usr/bin ]]; then
16046656Ssemery	if [[ -d /usr/sbin ]]; then
16050Sstevel@tonic-gate		PATH=/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:$PATH
16060Sstevel@tonic-gate		export PATH
16070Sstevel@tonic-gate	else
16080Sstevel@tonic-gate		printf "\n$(gettext "Directory /usr/sbin not found, exiting").\n" >&2
16090Sstevel@tonic-gate		exit 1
16100Sstevel@tonic-gate	fi
16110Sstevel@tonic-gateelse
16120Sstevel@tonic-gate	printf "\n$(gettext "Directory /usr/bin not found, exiting").\n" >&2
16130Sstevel@tonic-gate	exit 1
16140Sstevel@tonic-gatefi
16150Sstevel@tonic-gate
16160Sstevel@tonic-gateprintf "\n$(gettext "Starting client setup")\n\n"
16176656Ssemeryprintf -- "---------------------------------------------------\n"
16180Sstevel@tonic-gate
16190Sstevel@tonic-gate#
16200Sstevel@tonic-gate# Check for uid 0, disallow otherwise
16210Sstevel@tonic-gate#
16220Sstevel@tonic-gateid 1>$TMP_FILE 2>&1
16236656Ssemeryif [[ $? -eq 0 ]]; then
16240Sstevel@tonic-gate	if egrep -s "uid=0\(root\)" $TMP_FILE; then
16250Sstevel@tonic-gate		# uid is 0, go ahead ...
16260Sstevel@tonic-gate		:
16270Sstevel@tonic-gate	else
16286656Ssemery		printf "\n$(gettext "Administrative privileges are required to run this script, exiting").\n" >&2
16290Sstevel@tonic-gate		error_message
16300Sstevel@tonic-gate	fi
16310Sstevel@tonic-gateelse
16320Sstevel@tonic-gate	cat $TMP_FILE;
16336656Ssemery	printf "\n$(gettext "uid check failed, exiting").\n" >&2
16340Sstevel@tonic-gate	error_message
16350Sstevel@tonic-gatefi
16360Sstevel@tonic-gate
16376656Ssemeryuname=$(uname -n)
16386656Ssemeryhostname=${uname%%.*}
16390Sstevel@tonic-gate
16400Sstevel@tonic-gate#
16410Sstevel@tonic-gate# Process the command-line arguments (if any)
16420Sstevel@tonic-gate#
16430Sstevel@tonic-gateOPTIND=1
16446656Ssemerywhile getopts nD:Kp:R:k:a:c:d:f:h:m:s:T: OPTIONS
16450Sstevel@tonic-gatedo
16460Sstevel@tonic-gate	case $OPTIONS in
16476656Ssemery	    D) options="$options -D"
16486656Ssemery	       domain_list="$OPTARG"
16496656Ssemery	       ;;
16506656Ssemery	    K) options="$options -K"
16516656Ssemery	       no_keytab=yes
16520Sstevel@tonic-gate	       ;;
16530Sstevel@tonic-gate	    R) options="$options -R"
16546656Ssemery	       realm="$OPTARG"
16556656Ssemery	       checkval="REALM"; check_value $realm
16560Sstevel@tonic-gate	       ;;
16576656Ssemery	    T) options="$options -T"
16586656Ssemery	       type="$OPTARG"
16596656Ssemery	       if [[ $type == ms_ad ]]; then
16606656Ssemery		msad=yes
16616656Ssemery		adddns=yes
16626656Ssemery	       else
16636656Ssemery		non_solaris=yes
16646656Ssemery		no_keytab=yes
16656656Ssemery	       fi
16660Sstevel@tonic-gate	       ;;
16670Sstevel@tonic-gate	    a) options="$options -a"
16680Sstevel@tonic-gate	       ADMIN_PRINC="$OPTARG"
16690Sstevel@tonic-gate	       checkval="ADMIN_PRINC"; check_value $ADMIN_PRINC
16700Sstevel@tonic-gate	       ;;
16710Sstevel@tonic-gate	    c) options="$options -c"
16720Sstevel@tonic-gate	       filepath="$OPTARG"
16730Sstevel@tonic-gate	       ;;
16740Sstevel@tonic-gate	    d) options="$options -d"
16750Sstevel@tonic-gate	       dnsarg="$OPTARG"
16760Sstevel@tonic-gate	       checkval="DNS_OPTIONS"; check_value $dnsarg
16770Sstevel@tonic-gate	       ;;
16780Sstevel@tonic-gate	    f) options="$options -f"
16790Sstevel@tonic-gate	       fqdnlist="$OPTARG"
16800Sstevel@tonic-gate 	       ;;
16816656Ssemery	    h) options="$options -h"
16826656Ssemery	       logical_hn="$OPTARG"
16836656Ssemery	       checkval="LOGICAL_HOSTNAME"; check_value $logical_hn
16846656Ssemery	       ;;
16856656Ssemery	    k) options="$options -k"
16866656Ssemery	       kdc_list="$OPTARG"
16876656Ssemery	       ;;
16886656Ssemery	    m) options="$options -m"
16896656Ssemery	       KDC="$OPTARG"
16906656Ssemery	       checkval="KDC"; check_value $KDC
16916656Ssemery	       ;;
16920Sstevel@tonic-gate	    n) options="$options -n"
16930Sstevel@tonic-gate	       add_nfs=yes
16940Sstevel@tonic-gate	       ;;
16956656Ssemery	    p) options="$options -p"
16966656Ssemery	       profile="$OPTARG"
16976656Ssemery	       read_profile $profile
16986656Ssemery	       ;;
16996656Ssemery	    s) options="$options -s"
17006656Ssemery	       svc_list="$OPTARG"
17016656Ssemery	       SVCs=${svc_list//,/ }
17026656Ssemery 	       ;;
17030Sstevel@tonic-gate	    \?) usage
17046656Ssemery	       ;;
17050Sstevel@tonic-gate	    *) usage
17060Sstevel@tonic-gate	       ;;
17070Sstevel@tonic-gate	esac
17080Sstevel@tonic-gatedone
17090Sstevel@tonic-gate
17100Sstevel@tonic-gate#correct argument count after options
17110Sstevel@tonic-gateshift `expr $OPTIND - 1`
17120Sstevel@tonic-gate
17136656Ssemeryif [[ -z $options ]]; then
17140Sstevel@tonic-gate	:
17150Sstevel@tonic-gateelse
17166656Ssemery	if [[ $# -ne 0 ]]; then
17170Sstevel@tonic-gate		usage
17180Sstevel@tonic-gate	fi
17190Sstevel@tonic-gatefi
17200Sstevel@tonic-gate
17216656Ssemery#
17226815Ssemery# Check to see if we will be a client of a MIT, Heimdal, Shishi, etc.
17236815Ssemery#
17246815Ssemeryif [[ -z $options ]]; then
17256815Ssemery	query "$(gettext "Is this a client of a non-Solaris KDC") ?"
17266815Ssemery	non_solaris=$answer
17276815Ssemery	if [[ $non_solaris == yes ]]; then
17286815Ssemery		printf "$(gettext "Which type of KDC is the server"):\n"
17296815Ssemery		printf "\t$(gettext "ms_ad: Microsoft Active Directory")\n"
17306815Ssemery		printf "\t$(gettext "mit: MIT KDC server")\n"
17316815Ssemery		printf "\t$(gettext "heimdal: Heimdal KDC server")\n"
17326815Ssemery		printf "\t$(gettext "shishi: Shishi KDC server")\n"
17336815Ssemery		printf "$(gettext "Enter required KDC type"): "
17346815Ssemery		read kdctype
17356815Ssemery		if [[ $kdctype == ms_ad ]]; then
17366815Ssemery			msad=yes
17376815Ssemery		elif [[ $kdctype == mit || $kdctype == heimdal || \
17386815Ssemery		    $kdctype == shishi ]]; then
17396815Ssemery			no_keytab=yes
17406815Ssemery		else
17416815Ssemery			printf "\n$(gettext "Invalid KDC type option, valid types are ms_ad, mit, heimdal, or shishi, exiting").\n" >&2
17426815Ssemery			error_message
17436815Ssemery		fi
17446815Ssemery	fi
17456815Ssemeryfi
17466815Ssemery
17476815Ssemery[[ $msad == yes ]] && join_domain
17486815Ssemery
17496815Ssemery#
17506656Ssemery# Check for /etc/resolv.conf
17516656Ssemery#
17526656Ssemeryif [[ -r $RESOLV_CONF_FILE ]]; then
17536656Ssemery	client_machine=`$KLOOKUP`
17546656Ssemery
17556656Ssemery	if [[ $? -ne 0 ]]; then
17566656Ssemery		if [[ $adddns == no ]]; then
17576656Ssemery			printf "\n$(gettext "%s does not have a DNS record and is required for Kerberos setup")\n" $hostname >&2
17586656Ssemery			error_message
17596656Ssemery		fi
17606656Ssemery
17616656Ssemery	else
17626656Ssemery		#
17636656Ssemery		# If client entry already exists then do not recreate it
17646656Ssemery		#
17656656Ssemery		adddns=no
17666656Ssemery
17676656Ssemery		hostname=${client_machine%%.*}
17686656Ssemery		domain=${client_machine#*.}
17696656Ssemery	fi
17706656Ssemery
17716656Ssemery	short_fqdn=${domain#*.*}
17726656Ssemery	short_fqdn=$(echo $short_fqdn | grep "\.")
17736656Ssemeryelse
17746656Ssemery	#
17756656Ssemery	# /etc/resolv.conf not present, exit ...
17766656Ssemery	#
17776656Ssemery	printf "\n$(gettext "%s does not exist and is required for Kerberos setup")\n" $RESOLV_CONF_FILE >&2
17786656Ssemery	printf "$(gettext "Refer to resolv.conf(4), exiting").\n" >&2
17796656Ssemery	error_message
17806656Ssemeryfi
17816656Ssemery
17826815Ssemerycheck_nss_conf || printf "$(gettext "/etc/nsswitch.conf does not make use of DNS for hosts and/or ipnodes").\n"
17836656Ssemery
17846656Ssemery[[ -n $fqdnlist ]] && verify_fqdnlist "$fqdnlist"
17856656Ssemery
17866815Ssemeryif [[ -z $dnsarg && (-z $options || -z $filepath) ]]; then
17870Sstevel@tonic-gate	query "$(gettext "Do you want to use DNS for kerberos lookups") ?"
17886656Ssemery	if [[ $answer == yes ]]; then
17896656Ssemery		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"
17906656Ssemery		printf "\n$(gettext "Enter required DNS option"): "
17910Sstevel@tonic-gate		read dnsarg
17920Sstevel@tonic-gate		checkval="DNS_OPTIONS"; check_value $dnsarg
17930Sstevel@tonic-gate		set_dns_value $dnsarg
17940Sstevel@tonic-gate	fi
17950Sstevel@tonic-gateelse
17966815Ssemery	[[ -z $dnsarg ]] && dnsarg=none
17970Sstevel@tonic-gate	set_dns_value $dnsarg
17980Sstevel@tonic-gatefi
17990Sstevel@tonic-gate
18006656Ssemeryif [[ -n $kdc_list ]]; then
18016656Ssemery	if [[ -z $KDC ]]; then
18026656Ssemery		for kdc in $kdc_list; do
18036656Ssemery			break
18046656Ssemery		done
18056656Ssemery		KDC="$kdc"
18066656Ssemery	fi
18070Sstevel@tonic-gatefi
18086656Ssemery
18096815Ssemeryif [[ -z $realm ]]; then
18106656Ssemery	printf "$(gettext "Enter the Kerberos realm"): "
18116656Ssemery	read realm
18126656Ssemery	checkval="REALM"; check_value $realm
18136656Ssemeryfi
18146815Ssemeryif [[ -z $KDC ]]; then
18156656Ssemery	printf "$(gettext "Specify the master KDC hostname for the above realm"): "
18160Sstevel@tonic-gate	read KDC
18170Sstevel@tonic-gate	checkval="KDC"; check_value $KDC
18180Sstevel@tonic-gatefi
18190Sstevel@tonic-gate
18206656SsemeryFKDC=`$KLOOKUP $KDC`
18210Sstevel@tonic-gate
18220Sstevel@tonic-gate#
18230Sstevel@tonic-gate# Ping to see if the kdc is alive !
18240Sstevel@tonic-gate#
18256656Ssemeryping_check $FKDC "KDC"
18266656Ssemery
18276815Ssemeryif [[ -z $kdc_list && (-z $options || -z $filepath) ]]; then
18286815Ssemery	query "$(gettext "Do you have any slave KDC(s)") ?"
18296815Ssemery	if [[ $answer == yes ]]; then
18306815Ssemery		printf "$(gettext "Enter a comma-separated list of slave KDC host names"): "
18316815Ssemery		read kdc_list
18326815Ssemery	fi
18336815Ssemeryfi
18346815Ssemery
18356815Ssemery[[ -n $kdc_list ]] && verify_kdcs "$kdc_list"
18366815Ssemery
18376656Ssemery#
18386656Ssemery# Check to see if we will have a dynamic presence in the realm
18396656Ssemery#
18406656Ssemeryif [[ -z $options ]]; then
18416656Ssemery	query "$(gettext "Will this client need service keys") ?"
18426656Ssemery	if [[ $answer == no ]]; then
18436656Ssemery		no_keytab=yes
18446656Ssemery	fi
18456656Ssemeryfi
18460Sstevel@tonic-gate
18476656Ssemery#
18486656Ssemery# Check to see if we are configuring the client to use a logical host name
18496656Ssemery# of a cluster environment
18506656Ssemery#
18516656Ssemeryif [[ -z $options ]]; then
18526656Ssemery	query "$(gettext "Is this client a member of a cluster that uses a logical host name") ?"
18536656Ssemery	if [[ $answer == yes ]]; then
18546656Ssemery		printf "$(gettext "Specify the logical hostname of the cluster"): "
18556656Ssemery		read logical_hn
18566656Ssemery		checkval="LOGICAL_HOSTNAME"; check_value $logical_hn
18576656Ssemery		setup_lhn
18586656Ssemery	fi
18596656Ssemeryfi
18606656Ssemery
18616815Ssemeryif [[ -n $domain_list && (-z $options || -z $filepath) ]]; then
18626656Ssemery	query "$(gettext "Do you have multiple domains/hosts to map to realm %s"
18636656Ssemery) ?" $realm
18646656Ssemery	if [[ $answer == yes ]]; then
18656815Ssemery		printf "$(gettext "Enter a comma-separated list of domain/hosts
18666656Ssemeryto map to the default realm"): "
18676656Ssemery		read domain_list
18686656Ssemery	fi
18696656Ssemeryfi
18706656Ssemery[[ -n domain_list ]] && domain_list=${domain_list//,/ }
18710Sstevel@tonic-gate
18720Sstevel@tonic-gate#
18730Sstevel@tonic-gate# Start writing up the krb5.conf file, save the existing one
18740Sstevel@tonic-gate# if already present
18750Sstevel@tonic-gate#
18760Sstevel@tonic-gatewriteup_krb5_conf
18770Sstevel@tonic-gate
18786656Ssemery#
18796656Ssemery# Is this client going to use krb-nfs?  If so then we need to at least
18806656Ssemery# uncomment the krb5* sec flavors in nfssec.conf.
18816656Ssemery#
18826656Ssemeryif [[ -z $options ]]; then
18836656Ssemery	query "$(gettext "Do you plan on doing Kerberized nfs") ?"
18846656Ssemery	add_nfs=$answer
18856656Ssemeryfi
18866656Ssemery
18876656Ssemeryif [[ $add_nfs == yes ]]; then
18886656Ssemery	modify_nfssec_conf
18896656Ssemery
18906656Ssemery	#
18916656Ssemery	# We also want to enable gss as we now live in a SBD world
18926656Ssemery	#
18936656Ssemery	svcadm enable svc:/network/rpc/gss:default
18946656Ssemery	[[ $? -ne 0 ]] && printf "$(gettext "Warning: could not enable gss service").\n"
18956656Ssemeryfi
18966656Ssemery
18976656Ssemeryif [[ -z $options ]]; then
18986656Ssemery	query "$(gettext "Do you want to update /etc/pam.conf") ?"
18996656Ssemery	if [[ $answer == yes ]]; then
19006656Ssemery		printf "$(gettext "Enter a list of PAM service names in the following format: service:{first|only|optional}[,..]"): "
19016656Ssemery		read svc_list
19026656Ssemery		SVCs=${svc_list//,/ }
19036656Ssemery	fi
19046656Ssemeryfi
19056656Ssemery[[ -n $svc_list ]] && update_pam_conf
19060Sstevel@tonic-gate
19070Sstevel@tonic-gate#
19086656Ssemery# Copy over krb5.conf master copy from filepath
19090Sstevel@tonic-gate#
19106656Ssemeryif [[ -z $options || -z $filepath ]]; then
19116656Ssemery	query "$(gettext "Do you want to copy over the master krb5.conf file") ?"
19126656Ssemery	if [[ $answer == yes ]]; then
19136656Ssemery		printf "$(gettext "Enter the pathname of the file to be copied"): "
19146656Ssemery		read filepath
19150Sstevel@tonic-gate	fi
19160Sstevel@tonic-gatefi
19170Sstevel@tonic-gate
19186815Ssemeryif [[ -n $filepath && -r $filepath ]]; then
19196815Ssemery	cp $filepath $KRB5_CONFIG
19206815Ssemery	if [[ $? -eq 0 ]]; then
19216815Ssemery		printf "$(gettext "Copied %s to %s").\n" $filepath $KRB5_CONFIG
19220Sstevel@tonic-gate	else
19236815Ssemery		printf "$(gettext "Copy of %s failed, exiting").\n" $filepath >&2
19246656Ssemery		error_message
19250Sstevel@tonic-gate	fi
19266815Ssemeryelif [[ -n $filepath ]]; then
19276815Ssemery	printf "\n$(gettext "%s not found, exiting").\n" $filepath >&2
19286815Ssemery	error_message
19290Sstevel@tonic-gatefi
19300Sstevel@tonic-gate
19316815SsemerydoKRB5config
19326815Ssemery
19330Sstevel@tonic-gate#
19346656Ssemery# Populate any service keys needed for the client in the keytab file
19350Sstevel@tonic-gate#
19366815Ssemeryif [[ $no_keytab != yes ]]; then
19376815Ssemery	setup_keytab
19386815Ssemeryelse
19396815Ssemery	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
19406815Ssemery	printf "$(gettext "Client will also not be able to host services that use Kerberos").\n"
19416815Ssemeryfi
19420Sstevel@tonic-gate
19436656Ssemeryprintf -- "\n---------------------------------------------------\n"
19446656Ssemeryprintf "$(gettext "Setup COMPLETE").\n\n"
19450Sstevel@tonic-gate
19460Sstevel@tonic-gate#
19476656Ssemery# If we have configured the client in a cluster we need to remind the user
19486656Ssemery# to propagate the keytab and configuration files to the other members.
19490Sstevel@tonic-gate#
19506656Ssemeryif [[ -n $logical_hn ]]; then
19516656Ssemery	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"
19520Sstevel@tonic-gatefi
19530Sstevel@tonic-gate
19546656Ssemery#
19556656Ssemery# Cleanup.
19560Sstevel@tonic-gate#
19576656Ssemerykdestroy -q 1>$TMP_FILE 2>&1
19580Sstevel@tonic-gaterm -f $TMP_FILE
19596656Ssemeryrm -rf $TMPDIR > /dev/null 2>&1
19600Sstevel@tonic-gateexit 0
1961