xref: /titanic_44/usr/src/cmd/krb5/kadmin/kclient/kclient.sh (revision f7dbdfc7b241e42b135dc9118e41b127cb935483)
1ae5b046dSsemery#!/bin/ksh93 -p
27c478bd9Sstevel@tonic-gate#
3bd211b85Ssemery# CDDL HEADER START
4bd211b85Ssemery#
5bd211b85Ssemery# The contents of this file are subject to the terms of the
6bd211b85Ssemery# Common Development and Distribution License (the "License").
7bd211b85Ssemery# You may not use this file except in compliance with the License.
8bd211b85Ssemery#
9bd211b85Ssemery# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10bd211b85Ssemery# or http://www.opensolaris.org/os/licensing.
11bd211b85Ssemery# See the License for the specific language governing permissions
12bd211b85Ssemery# and limitations under the License.
13bd211b85Ssemery#
14bd211b85Ssemery# When distributing Covered Code, include this CDDL HEADER in each
15bd211b85Ssemery# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16bd211b85Ssemery# If applicable, add the following below this CDDL HEADER, with the
17bd211b85Ssemery# fields enclosed by brackets "[]" replaced with your own identifying
18bd211b85Ssemery# information: Portions Copyright [yyyy] [name of copyright owner]
19bd211b85Ssemery#
20bd211b85Ssemery# CDDL HEADER END
21bd211b85Ssemery#
22c48f4690SShawn Emery# Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
23*f7dbdfc7SMarcel Telka# Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate#
257c478bd9Sstevel@tonic-gate# This script is used to setup the Kerberos client by
267c478bd9Sstevel@tonic-gate# supplying information about the Kerberos realm and kdc.
277c478bd9Sstevel@tonic-gate#
287c478bd9Sstevel@tonic-gate# The kerberos configuration file (/etc/krb5/krb5.conf) would
297c478bd9Sstevel@tonic-gate# be generated and local host's keytab file setup. The script
307c478bd9Sstevel@tonic-gate# can also optionally setup the system to do kerberized nfs and
317c478bd9Sstevel@tonic-gate# bringover a master krb5.conf copy from a specified location.
3272f0806aSShawn Emery#
337c478bd9Sstevel@tonic-gate
34bd211b85Ssemeryfunction cleanup {
35bd211b85Ssemery
36c386eb9cSShawn Emery	kdestroy -q > $TMP_FILE 2>&1
37bd211b85Ssemery	rm -r $TMPDIR > /dev/null 2>&1
38bd211b85Ssemery
39c386eb9cSShawn Emery	exit $1
40bd211b85Ssemery}
41bd211b85Ssemeryfunction exiting {
42bd211b85Ssemery
43bd211b85Ssemery        printf "\n$(gettext "Exiting setup, nothing changed").\n\n"
44bd211b85Ssemery
45bd211b85Ssemery	cleanup $1
467c478bd9Sstevel@tonic-gate}
477c478bd9Sstevel@tonic-gate
48bd211b85Ssemeryfunction error_message {
49bd211b85Ssemery
50c386eb9cSShawn Emery        printf -- "---------------------------------------------------\n" >&2
51c386eb9cSShawn Emery        printf "$(gettext "Setup FAILED").\n\n" >&2
52bd211b85Ssemery
53bd211b85Ssemery        cleanup 1
54bd211b85Ssemery}
55bd211b85Ssemery
56bd211b85Ssemeryfunction check_bin {
57bd211b85Ssemery
58bd211b85Ssemery	typeset bin=$1
59bd211b85Ssemery
60bd211b85Ssemery	if [[ ! -x $bin ]]; then
61c386eb9cSShawn Emery		printf "$(gettext "Could not access/execute %s").\n" $bin >&2
627c478bd9Sstevel@tonic-gate		error_message
637c478bd9Sstevel@tonic-gate	fi
647c478bd9Sstevel@tonic-gate}
657c478bd9Sstevel@tonic-gate
66bd211b85Ssemeryfunction cannot_create {
67bd211b85Ssemery	typeset filename="$1"
68bd211b85Ssemery	typeset stat="$2"
69bd211b85Ssemery
70bd211b85Ssemery	if [[ $stat -ne 0 ]]; then
71bd211b85Ssemery		printf "\n$(gettext "Can not create/edit %s, exiting").\n" $filename >&2
72bd211b85Ssemery		error_message
73bd211b85Ssemery	fi
74bd211b85Ssemery}
75bd211b85Ssemery
76bd211b85Ssemeryfunction update_pam_conf {
77bd211b85Ssemery	typeset PAM TPAM service
78bd211b85Ssemery
79bd211b85Ssemery	PAM=/etc/pam.conf
80bd211b85Ssemery
81bd211b85Ssemery	TPAM=$(mktemp -q -t kclient-pamconf.XXXXXX)
82bd211b85Ssemery	if [[ -z $TPAM ]]; then
83bd211b85Ssemery		printf "\n$(gettext "Can not create temporary file, exiting").\n" >&2
84bd211b85Ssemery		error_message
85bd211b85Ssemery	fi
86bd211b85Ssemery
87bd211b85Ssemery	cp $PAM $TPAM >/dev/null 2>&1
88bd211b85Ssemery
89bd211b85Ssemery	printf "$(gettext "Configuring %s").\n\n" $PAM
90bd211b85Ssemery
91bd211b85Ssemery	for service in $SVCs; do
92bd211b85Ssemery		svc=${service%:*}
93bd211b85Ssemery		auth_type=${service#*:}
94bd211b85Ssemery		if egrep -s "^$svc[ 	][ 	]*auth.*pam_krb5*" $TPAM; then
95ae5b046dSsemery			printf "$(gettext "The %s service is already configured for pam_krb5, please merge this service in %s").\n\n" $svc $PAM >&2
96bd211b85Ssemery			continue
97bd211b85Ssemery		else
98bd211b85Ssemery			exec 3>>$TPAM
99ae5b046dSsemery			printf "\n$svc\tauth include\t\tpam_krb5_$auth_type\n" 1>&3
100bd211b85Ssemery		fi
101bd211b85Ssemery	done
102bd211b85Ssemery
103bd211b85Ssemery	cp $TPAM $PAM > /dev/null 2>&1
104bd211b85Ssemery
105bd211b85Ssemery	rm $TPAM > /dev/null 2>&1
106bd211b85Ssemery}
107bd211b85Ssemery
108bd211b85Ssemeryfunction modify_nfssec_conf {
109bd211b85Ssemery	typeset NFSSEC_FILE="/etc/nfssec.conf"
110bd211b85Ssemery
111bd211b85Ssemery	if [[ -r $NFSSEC_FILE ]]; then
1127c478bd9Sstevel@tonic-gate		cat $NFSSEC_FILE > $NFSSEC_FILE.sav
1137c478bd9Sstevel@tonic-gate		cannot_create $NFSSEC_FILE.sav $?
1147c478bd9Sstevel@tonic-gate	fi
1157c478bd9Sstevel@tonic-gate
1167c478bd9Sstevel@tonic-gate	cat $NFSSEC_FILE > $TMP_FILE
1177c478bd9Sstevel@tonic-gate	cannot_create $TMP_FILE $?
1187c478bd9Sstevel@tonic-gate
1197c478bd9Sstevel@tonic-gate	if grep -s "#krb5" $NFSSEC_FILE > /dev/null 2>&1; then
1207c478bd9Sstevel@tonic-gate		sed "s%^#krb5%krb5%" $TMP_FILE >$NFSSEC_FILE
1217c478bd9Sstevel@tonic-gate		cannot_create $NFSSEC_FILE $?
1227c478bd9Sstevel@tonic-gate	fi
1237c478bd9Sstevel@tonic-gate}
1247c478bd9Sstevel@tonic-gate
125bd211b85Ssemeryfunction call_kadmin {
1267c478bd9Sstevel@tonic-gate	typeset svc="$1"
1277c478bd9Sstevel@tonic-gate	typeset bool1 bool2 bool3 bool4
128bd211b85Ssemery	typeset service_princ getprincsubcommand anksubcommand ktaddsubcommand
129bd211b85Ssemery	typeset ktremsubcommand
1307c478bd9Sstevel@tonic-gate
1317c478bd9Sstevel@tonic-gate	for listentry in $fqdnlist; do
1327c478bd9Sstevel@tonic-gate
1337c478bd9Sstevel@tonic-gate	# Reset conditional vars to 1
1347c478bd9Sstevel@tonic-gate	bool1=1; bool2=1; bool3=1; bool4=1
1357c478bd9Sstevel@tonic-gate
136bd211b85Ssemery	service_princ=$(echo "${svc}/${listentry}")
1377c478bd9Sstevel@tonic-gate	getprincsubcommand="getprinc $service_princ"
1387c478bd9Sstevel@tonic-gate	anksubcommand="addprinc -randkey $service_princ"
1397c478bd9Sstevel@tonic-gate	ktaddsubcommand="ktadd $service_princ"
140bd211b85Ssemery	ktremsubcommand="ktrem $service_princ all"
1417c478bd9Sstevel@tonic-gate
142bd211b85Ssemery	kadmin -c $KRB5CCNAME -q "$getprincsubcommand" 1>$TMP_FILE 2>&1
1437c478bd9Sstevel@tonic-gate
144ae5b046dSsemery	egrep -s "$(gettext "get_principal: Principal does not exist")" $TMP_FILE
1457c478bd9Sstevel@tonic-gate	bool1=$?
146ae5b046dSsemery	egrep -s "$(gettext "get_principal: Operation requires ``get")" $TMP_FILE
1477c478bd9Sstevel@tonic-gate	bool2=$?
1487c478bd9Sstevel@tonic-gate
1497c478bd9Sstevel@tonic-gate	if [[ $bool1 -eq 0 || $bool2 -eq 0 ]]; then
150bd211b85Ssemery		kadmin -c $KRB5CCNAME -q "$anksubcommand" 1>$TMP_FILE 2>&1
1517c478bd9Sstevel@tonic-gate
152ae5b046dSsemery		egrep -s "$(gettext "add_principal: Principal or policy already exists while creating \"$service_princ@$realm\".")" $TMP_FILE
1537c478bd9Sstevel@tonic-gate		bool3=$?
1547c478bd9Sstevel@tonic-gate
155ae5b046dSsemery		egrep -s "$(gettext "Principal \"$service_princ@$realm\" created.")" $TMP_FILE
1567c478bd9Sstevel@tonic-gate		bool4=$?
1577c478bd9Sstevel@tonic-gate
1587c478bd9Sstevel@tonic-gate		if [[ $bool3 -eq 0 || $bool4 -eq 0 ]]; then
1597c478bd9Sstevel@tonic-gate			printf "$(gettext "%s entry ADDED to KDC database").\n" $service_princ
1607c478bd9Sstevel@tonic-gate		else
1617c478bd9Sstevel@tonic-gate			cat $TMP_FILE;
162bd211b85Ssemery			printf "\n$(gettext "kadmin: add_principal of %s failed, exiting").\n" $service_princ >&2
1637c478bd9Sstevel@tonic-gate			error_message
1647c478bd9Sstevel@tonic-gate		fi
1657c478bd9Sstevel@tonic-gate	else
166bd211b85Ssemery		printf "$(gettext "%s entry already exists in KDC database").\n" $service_princ >&2
1677c478bd9Sstevel@tonic-gate	fi
1687c478bd9Sstevel@tonic-gate
1697c478bd9Sstevel@tonic-gate	klist -k 1>$TMP_FILE 2>&1
170bd211b85Ssemery	egrep -s "$service_princ@$realm" $TMP_FILE
171bd211b85Ssemery	if [[ $? -eq 0 ]]; then
172bd211b85Ssemery		printf "$(gettext "%s entry already present in keytab").\n" $service_princ >&2
173bd211b85Ssemery		# Don't care is this succeeds or not, just need to replace old
174bd211b85Ssemery		# entries as it is assummed that the client is reinitialized
175bd211b85Ssemery		kadmin -c $KRB5CCNAME -q "$ktremsubcommand" 1>$TMP_FILE 2>&1
176bd211b85Ssemery	fi
177bd211b85Ssemery
178bd211b85Ssemery	kadmin -c $KRB5CCNAME -q "$ktaddsubcommand" 1>$TMP_FILE 2>&1
179ae5b046dSsemery	egrep -s "$(gettext "added to keytab WRFILE:$KRB5_KEYTAB_FILE.")" $TMP_FILE
180bd211b85Ssemery	if [[ $? -ne 0 ]]; then
1817c478bd9Sstevel@tonic-gate		cat $TMP_FILE;
182bd211b85Ssemery		printf "\n$(gettext "kadmin: ktadd of %s failed, exiting").\n" $service_princ >&2
1837c478bd9Sstevel@tonic-gate		error_message
1847c478bd9Sstevel@tonic-gate	else
1857c478bd9Sstevel@tonic-gate		printf "$(gettext "%s entry ADDED to keytab").\n" $service_princ
1867c478bd9Sstevel@tonic-gate	fi
1877c478bd9Sstevel@tonic-gate
1887c478bd9Sstevel@tonic-gate	done
1897c478bd9Sstevel@tonic-gate}
1907c478bd9Sstevel@tonic-gate
191bd211b85Ssemeryfunction writeup_krb5_conf {
192bd211b85Ssemery	typeset dh
1937c478bd9Sstevel@tonic-gate
194bd211b85Ssemery	printf "\n$(gettext "Setting up %s").\n\n" $KRB5_CONFIG_FILE
1957c478bd9Sstevel@tonic-gate
196bd211b85Ssemery	exec 3>$KRB5_CONFIG
197bd211b85Ssemery	if [[ $? -ne 0 ]]; then
198c386eb9cSShawn Emery		printf "\n$(gettext "Can not write to %s, exiting").\n" $KRB5_CONFIG >&2
1997c478bd9Sstevel@tonic-gate		error_message
2007c478bd9Sstevel@tonic-gate	fi
2017c478bd9Sstevel@tonic-gate
202bd211b85Ssemery	printf "[libdefaults]\n" 1>&3
203bd211b85Ssemery	if [[ $no_keytab == yes ]]; then
204bd211b85Ssemery		printf "\tverify_ap_req_nofail = false\n" 1>&3
205bd211b85Ssemery	fi
206bd211b85Ssemery	if [[ $dns_lookup == yes ]]; then
207bd211b85Ssemery	    printf "\t$dnsarg = on\n" 1>&3
208bd211b85Ssemery	    if [[ $dnsarg == dns_lookup_kdc ]]; then
209bd211b85Ssemery		printf "\tdefault_realm = $realm\n" 1>&3
210bd211b85Ssemery		printf "\n[domain_realm]\n" 1>&3
211bd211b85Ssemery		if [[ -n $fkdc_list ]]; then
212bd211b85Ssemery			for kdc in $fkdc_list; do
213bd211b85Ssemery				printf "\t$kdc = $realm\n" 1>&3
214bd211b85Ssemery			done
215bd211b85Ssemery		fi
216bd211b85Ssemery		printf "\t$FKDC = $realm\n" 1>&3
217bd211b85Ssemery		printf "\t$client_machine = $realm\n" 1>&3
218bd211b85Ssemery		if [[ -z $short_fqdn ]]; then
219bd211b85Ssemery			printf "\t.$domain = $realm\n\n" 1>&3
2207c478bd9Sstevel@tonic-gate		else
221bd211b85Ssemery			printf "\t.$short_fqdn = $realm\n\n" 1>&3
222bd211b85Ssemery		fi
223bd211b85Ssemery		if [[ -n $domain_list ]]; then
224bd211b85Ssemery			for dh in $domain_list; do
225bd211b85Ssemery				printf "\t$dh = $realm\n" 1>&3
226bd211b85Ssemery			done
227bd211b85Ssemery		fi
228bd211b85Ssemery	    else
229bd211b85Ssemery		if [[ $dnsarg = dns_lookup_realm ]]; then
230ae5b046dSsemery		    printf "\tdefault_realm = $realm\n" 1>&3
231bd211b85Ssemery		    printf "\n[realms]\n" 1>&3
232bd211b85Ssemery		    printf "\t$realm = {\n" 1>&3
233bd211b85Ssemery		    if [[ -n $kdc_list ]]; then
234bd211b85Ssemery			for kdc in $kdc_list; do
235bd211b85Ssemery				printf "\t\tkdc = $kdc\n" 1>&3
236bd211b85Ssemery			done
2377c478bd9Sstevel@tonic-gate		    else
238bd211b85Ssemery		    	printf "\t\tkdc = $KDC\n" 1>&3
239bd211b85Ssemery		    fi
240bd211b85Ssemery		    printf "\t\tadmin_server = $KDC\n" 1>&3
241bd211b85Ssemery		    if [[ $non_solaris == yes ]]; then
242bd211b85Ssemery			printf "\n\t\tkpasswd_protocol = SET_CHANGE\n" 1>&3
243bd211b85Ssemery		    fi
244bd211b85Ssemery		    printf "\t}\n\n" 1>&3
245bd211b85Ssemery		else
246ae5b046dSsemery		    printf "\tdefault_realm = $realm\n\n" 1>&3
2477c478bd9Sstevel@tonic-gate		fi
2487c478bd9Sstevel@tonic-gate	    fi
2497c478bd9Sstevel@tonic-gate	else
250bd211b85Ssemery	    printf "\tdefault_realm = $realm\n\n" 1>&3
2517c478bd9Sstevel@tonic-gate
252bd211b85Ssemery	    printf "[realms]\n" 1>&3
253bd211b85Ssemery	    printf "\t$realm = {\n" 1>&3
254bd211b85Ssemery	    if [[ -n $kdc_list ]]; then
255bd211b85Ssemery		for kdc in $kdc_list; do
256bd211b85Ssemery			printf "\t\tkdc = $kdc\n" 1>&3
257bd211b85Ssemery		done
258bd211b85Ssemery	    else
259bd211b85Ssemery	    	printf "\t\tkdc = $KDC\n" 1>&3
260bd211b85Ssemery	    fi
261bd211b85Ssemery	    printf "\t\tadmin_server = $KDC\n" 1>&3
262bd211b85Ssemery	    if [[ $non_solaris == yes ]]; then
263bd211b85Ssemery	    	printf "\n\t\tkpasswd_protocol = SET_CHANGE\n" 1>&3
264bd211b85Ssemery	    fi
265bd211b85Ssemery	    printf "\t}\n\n" 1>&3
2667c478bd9Sstevel@tonic-gate
267bd211b85Ssemery	    printf "[domain_realm]\n" 1>&3
268bd211b85Ssemery	    if [[ -n $fkdc_list ]]; then
269bd211b85Ssemery		for kdc in $fkdc_list; do
270bd211b85Ssemery			printf "\t$kdc = $realm\n" 1>&3
271bd211b85Ssemery		done
272bd211b85Ssemery	    fi
273bd211b85Ssemery	    printf "\t$FKDC = $realm\n" 1>&3
274bd211b85Ssemery	    printf "\t$client_machine = $realm\n" 1>&3
275bd211b85Ssemery	    if [[ -z $short_fqdn ]]; then
276bd211b85Ssemery		printf "\t.$domain = $realm\n\n" 1>&3
277bd211b85Ssemery	    else
278bd211b85Ssemery		printf "\t.$short_fqdn = $realm\n\n" 1>&3
279bd211b85Ssemery	    fi
280bd211b85Ssemery	    if [[ -n $domain_list ]]; then
281bd211b85Ssemery		for dh in $domain_list; do
282bd211b85Ssemery			printf "\t$dh = $realm\n" 1>&3
283bd211b85Ssemery		done
284bd211b85Ssemery	    fi
2857c478bd9Sstevel@tonic-gate	fi
2867c478bd9Sstevel@tonic-gate
287bd211b85Ssemery	printf "[logging]\n" 1>&3
288bd211b85Ssemery	printf "\tdefault = FILE:/var/krb5/kdc.log\n" 1>&3
289bd211b85Ssemery	printf "\tkdc = FILE:/var/krb5/kdc.log\n" 1>&3
290bd211b85Ssemery	printf "\tkdc_rotate = {\n\t\tperiod = 1d\n\t\tversions = 10\n\t}\n\n" 1>&3
2917c478bd9Sstevel@tonic-gate
292bd211b85Ssemery	printf "[appdefaults]\n" 1>&3
293bd211b85Ssemery	printf "\tkinit = {\n\t\trenewable = true\n\t\tforwardable = true\n" 1>&3
294bd211b85Ssemery	if [[ $no_keytab == yes ]]; then
295bd211b85Ssemery		printf "\t\tno_addresses = true\n" 1>&3
296bd211b85Ssemery	fi
297bd211b85Ssemery	printf "\t}\n" 1>&3
2987c478bd9Sstevel@tonic-gate}
2997c478bd9Sstevel@tonic-gate
300bd211b85Ssemeryfunction ask {
301bd211b85Ssemery	typeset question=$1
302bd211b85Ssemery	typeset default_answer=$2
303bd211b85Ssemery
304bd211b85Ssemery	if [[ -z $default_answer ]]; then
305bd211b85Ssemery		printf "$question :"
3067c478bd9Sstevel@tonic-gate	else
307bd211b85Ssemery		printf "$question [$default_answer]: "
3087c478bd9Sstevel@tonic-gate	fi
3097c478bd9Sstevel@tonic-gate	read answer
3107c478bd9Sstevel@tonic-gate	test -z "$answer" && answer="$default_answer"
3117c478bd9Sstevel@tonic-gate}
3127c478bd9Sstevel@tonic-gate
313bd211b85Ssemeryfunction yesno {
3147c478bd9Sstevel@tonic-gate	typeset question="$1"
315bd211b85Ssemery
316bd211b85Ssemery	answer=
317bd211b85Ssemery	yn=`printf "$(gettext "y/n")"`
318bd211b85Ssemery	y=`printf "$(gettext "y")"`
319bd211b85Ssemery	n=`printf "$(gettext "n")"`
320bd211b85Ssemery	yes=`printf "$(gettext "yes")"`
321bd211b85Ssemery	no=`printf "$(gettext "no")"`
322bd211b85Ssemery
323bd211b85Ssemery	while [[ -z $answer ]]; do
324bd211b85Ssemery		ask "$question" $yn
325bd211b85Ssemery		case $answer in
326bd211b85Ssemery			$y|$yes)	answer=yes;;
327bd211b85Ssemery			$n|$no)		answer=no;;
328bd211b85Ssemery			*)		answer=;;
3297c478bd9Sstevel@tonic-gate		esac
3307c478bd9Sstevel@tonic-gate	done
3317c478bd9Sstevel@tonic-gate}
3327c478bd9Sstevel@tonic-gate
333bd211b85Ssemeryfunction query {
3347c478bd9Sstevel@tonic-gate	yesno "$*"
335bd211b85Ssemery
336bd211b85Ssemery	if [[ $answer == no ]]; then
3377c478bd9Sstevel@tonic-gate		printf "\t$(gettext "No action performed").\n"
3387c478bd9Sstevel@tonic-gate	fi
3397c478bd9Sstevel@tonic-gate}
3407c478bd9Sstevel@tonic-gate
3417c478bd9Sstevel@tonic-gate
342bd211b85Ssemeryfunction read_profile {
3437c478bd9Sstevel@tonic-gate	typeset param value
3447c478bd9Sstevel@tonic-gate	typeset file="$1"
345bd211b85Ssemery
3467c478bd9Sstevel@tonic-gate	if [[ ! -d $file && -r $file ]]; then
3477c478bd9Sstevel@tonic-gate		while read param value
3487c478bd9Sstevel@tonic-gate		do
349bd211b85Ssemery			case $param in
350bd211b85Ssemery			REALM)  if [[ -z $realm ]]; then
351bd211b85Ssemery					realm="$value"
352bd211b85Ssemery					checkval="REALM"; check_value $realm
3537c478bd9Sstevel@tonic-gate				fi
3547c478bd9Sstevel@tonic-gate				;;
355bd211b85Ssemery			KDC)    if [[ -z $KDC ]]; then
3567c478bd9Sstevel@tonic-gate					KDC="$value"
3577c478bd9Sstevel@tonic-gate					checkval="KDC"; check_value $KDC
3587c478bd9Sstevel@tonic-gate				fi
3597c478bd9Sstevel@tonic-gate				;;
360bd211b85Ssemery			ADMIN)  if [[ -z $ADMIN_PRINC ]]; then
3617c478bd9Sstevel@tonic-gate					ADMIN_PRINC="$value"
3627c478bd9Sstevel@tonic-gate					checkval="ADMIN_PRINC"
3637c478bd9Sstevel@tonic-gate    					check_value $ADMIN_PRINC
3647c478bd9Sstevel@tonic-gate				fi
3657c478bd9Sstevel@tonic-gate				;;
366bd211b85Ssemery			FILEPATH)  if [[ -z $filepath ]]; then
3677c478bd9Sstevel@tonic-gate					filepath="$value"
3687c478bd9Sstevel@tonic-gate				   fi
3697c478bd9Sstevel@tonic-gate				   ;;
370bd211b85Ssemery			NFS)    if [[ -z $add_nfs ]]; then
371bd211b85Ssemery				    if [[ $value == 1 ]]; then
3727c478bd9Sstevel@tonic-gate					    add_nfs=yes
3737c478bd9Sstevel@tonic-gate				    else
3747c478bd9Sstevel@tonic-gate					    add_nfs=no
3757c478bd9Sstevel@tonic-gate				    fi
3767c478bd9Sstevel@tonic-gate				fi
3777c478bd9Sstevel@tonic-gate				;;
378bd211b85Ssemery			NOKEY)    if [[ -z $no_keytab ]]; then
379bd211b85Ssemery				    if [[ $value == 1 ]]; then
380bd211b85Ssemery					    no_keytab=yes
381bd211b85Ssemery				    else
382bd211b85Ssemery					    no_keytab=no
383bd211b85Ssemery				    fi
384bd211b85Ssemery				fi
385bd211b85Ssemery				;;
386bd211b85Ssemery			NOSOL)  if [[ -z $non_solaris ]]; then
387bd211b85Ssemery				    if [[ $value == 1 ]]; then
388bd211b85Ssemery					    non_solaris=yes
389bd211b85Ssemery					    no_keytab=yes
390bd211b85Ssemery				    else
391bd211b85Ssemery					    non_solaris=no
392bd211b85Ssemery				    fi
393bd211b85Ssemery				fi
394bd211b85Ssemery				;;
395bd211b85Ssemery			LHN)    if [[ -z $logical_hn ]]; then
396bd211b85Ssemery					logical_hn="$value"
397bd211b85Ssemery					checkval="LOGICAL_HOSTNAME"
398bd211b85Ssemery    					check_value $logical_hn
399bd211b85Ssemery				fi
400bd211b85Ssemery				;;
401bd211b85Ssemery			DNSLOOKUP) if [[ -z $dnsarg ]]; then
4027c478bd9Sstevel@tonic-gate					dnsarg="$value"
4037c478bd9Sstevel@tonic-gate					checkval="DNS_OPTIONS"
4047c478bd9Sstevel@tonic-gate					check_value $dnsarg
4057c478bd9Sstevel@tonic-gate				   fi
4067c478bd9Sstevel@tonic-gate				   ;;
407bd211b85Ssemery			FQDN) if [[ -z $fqdnlist ]]; then
4087c478bd9Sstevel@tonic-gate					fqdnlist="$value"
4097c478bd9Sstevel@tonic-gate					checkval="FQDN"
4107c478bd9Sstevel@tonic-gate					check_value $fqdnlist
4117c478bd9Sstevel@tonic-gate					verify_fqdnlist "$fqdnlist"
4127c478bd9Sstevel@tonic-gate			      fi
4137c478bd9Sstevel@tonic-gate			      ;;
414bd211b85Ssemery			MSAD) if [[ -z $msad ]]; then
415bd211b85Ssemery				if [[ $value == 1 ]]; then
416bd211b85Ssemery					msad=yes
417bd211b85Ssemery					non_solaris=yes
418bd211b85Ssemery				else
419bd211b85Ssemery					msad=no
420bd211b85Ssemery				fi
421bd211b85Ssemery			      fi
422bd211b85Ssemery			      ;;
4237c478bd9Sstevel@tonic-gate			esac
4247c478bd9Sstevel@tonic-gate		done <$file
4257c478bd9Sstevel@tonic-gate	else
426bd211b85Ssemery		printf "\n$(gettext "The kclient profile \`%s' is not valid, exiting").\n" $file >&2
4277c478bd9Sstevel@tonic-gate		error_message
4287c478bd9Sstevel@tonic-gate	fi
4297c478bd9Sstevel@tonic-gate}
4307c478bd9Sstevel@tonic-gate
431bd211b85Ssemeryfunction ping_check {
4327c478bd9Sstevel@tonic-gate	typeset machine="$1"
4337c478bd9Sstevel@tonic-gate	typeset string="$2"
434bd211b85Ssemery
435bd211b85Ssemery	if ping $machine 2 > /dev/null 2>&1; then
4367c478bd9Sstevel@tonic-gate		:
4377c478bd9Sstevel@tonic-gate	else
438bd211b85Ssemery		printf "\n$(gettext "%s %s is unreachable, exiting").\n" $string $machine >&2
4397c478bd9Sstevel@tonic-gate		error_message
4407c478bd9Sstevel@tonic-gate	fi
4417c478bd9Sstevel@tonic-gate
4427c478bd9Sstevel@tonic-gate	# Output timesync warning if not using a profile, i.e. in
4437c478bd9Sstevel@tonic-gate	# interactive mode.
444bd211b85Ssemery	if [[ -z $profile && $string == KDC ]]; then
4457c478bd9Sstevel@tonic-gate		# It's difficult to sync up time with KDC esp. if in a
4467c478bd9Sstevel@tonic-gate		# zone so just print a warning about KDC time sync.
447ae5b046dSsemery		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
448ae5b046dSsemery		printf "$(gettext "Both systems should run some form of time synchronization system like Network Time Protocol (NTP)").\n" >&2
449bd211b85Ssemerybreak
4507c478bd9Sstevel@tonic-gate	fi
4517c478bd9Sstevel@tonic-gate}
4527c478bd9Sstevel@tonic-gate
453bd211b85Ssemeryfunction check_value {
4547c478bd9Sstevel@tonic-gate	typeset arg="$1"
455bd211b85Ssemery
456bd211b85Ssemery	if [[ -z $arg ]]; then
457bd211b85Ssemery		printf "\n$(gettext "No input obtained for %s, exiting").\n" $checkval >&2
4587c478bd9Sstevel@tonic-gate		error_message
4597c478bd9Sstevel@tonic-gate	else
4607c478bd9Sstevel@tonic-gate		echo "$arg" > $TMP_FILE
4617c478bd9Sstevel@tonic-gate		if egrep -s '[*$^#!]+' $TMP_FILE; then
462bd211b85Ssemery			printf "\n$(gettext "Invalid input obtained for %s, exiting").\n" $checkval >&2
4637c478bd9Sstevel@tonic-gate			error_message
4647c478bd9Sstevel@tonic-gate		fi
4657c478bd9Sstevel@tonic-gate	fi
4667c478bd9Sstevel@tonic-gate}
4677c478bd9Sstevel@tonic-gate
468bd211b85Ssemeryfunction set_dns_value {
469bd211b85Ssemery	typeset -l arg="$1"
470bd211b85Ssemery
471bd211b85Ssemery	if [[ $arg == dns_lookup_kdc  ||  $arg == dns_lookup_realm  || $arg == dns_fallback ]]; then
4727c478bd9Sstevel@tonic-gate		dns_lookup=yes
4737c478bd9Sstevel@tonic-gate	else
474bd211b85Ssemery		if [[ $arg == none ]]; then
4757c478bd9Sstevel@tonic-gate			dns_lookup=no
4767c478bd9Sstevel@tonic-gate		else
477bd211b85Ssemery			printf "\n$(gettext "Invalid DNS lookup option, exiting").\n" >&2
4787c478bd9Sstevel@tonic-gate			error_message
4797c478bd9Sstevel@tonic-gate		fi
4807c478bd9Sstevel@tonic-gate	fi
4817c478bd9Sstevel@tonic-gate}
4827c478bd9Sstevel@tonic-gate
483bd211b85Ssemeryfunction verify_kdcs {
484bd211b85Ssemery	typeset k_list="$1"
485bd211b85Ssemery	typeset -l kdc
486bd211b85Ssemery	typeset list fqhn f_list
4877c478bd9Sstevel@tonic-gate
488bd211b85Ssemery	kdc_list=$(echo "$k_list" | sed 's/,/ /g')
489bd211b85Ssemery
490bd211b85Ssemery	if [[ -z $k_list ]]; then
491bd211b85Ssemery		printf "\n$(gettext "At least one KDC should be listed").\n\n" >&2
492bd211b85Ssemery		usage
493bd211b85Ssemery	fi
494bd211b85Ssemery
495bd211b85Ssemery	for kdc in $k_list; do
496bd211b85Ssemery		if [[ $kdc != $KDC ]]; then
497bd211b85Ssemery			list="$list $kdc"
498bd211b85Ssemery			fkdc=`$KLOOKUP $kdc`
499bd211b85Ssemery			if ping $fkdc 2 > /dev/null; then
500bd211b85Ssemery				:
501bd211b85Ssemery			else
502bd211b85Ssemery				printf "\n$(gettext "%s %s is unreachable, no action performed").\n" "KDC" $fkdc >&2
503bd211b85Ssemery			fi
504bd211b85Ssemery			f_list="$f_list $fkdc"
505bd211b85Ssemery		fi
506bd211b85Ssemery	done
507bd211b85Ssemery
508bd211b85Ssemery	fkdc_list="$f_list"
509bd211b85Ssemery	kdc_list="$list"
510bd211b85Ssemery}
511bd211b85Ssemery
512bd211b85Ssemeryfunction parse_service {
513bd211b85Ssemery	typeset service_list=$1
514bd211b85Ssemery
515bd211b85Ssemery	service_list=${service_list//,/ }
516bd211b85Ssemery	for service in $service_list; do
517bd211b85Ssemery		svc=${service%:}
518bd211b85Ssemery		auth_type=${service#:}
519bd211b85Ssemery		[[ -z $svc || -z $auth_type ]] && return
520bd211b85Ssemery		print -- $svc $auth_type
521bd211b85Ssemery	done
522bd211b85Ssemery}
523bd211b85Ssemery
524bd211b85Ssemeryfunction verify_fqdnlist {
525bd211b85Ssemery	typeset list="$1"
526bd211b85Ssemery	typeset -l hostname
527bd211b85Ssemery	typeset -i count=1
528bd211b85Ssemery	typeset fqdnlist eachfqdn tmpvar fullhost
529bd211b85Ssemery
530bd211b85Ssemery	list=$(echo "$list" | tr -d " " | tr -d "\t")
531bd211b85Ssemery	hostname=$(uname -n | cut -d"." -f1)
5327c478bd9Sstevel@tonic-gate	fqdnlist=$client_machine
5337c478bd9Sstevel@tonic-gate
5347c478bd9Sstevel@tonic-gate	eachfqdn=$(echo "$list" | cut -d"," -f$count)
535bd211b85Ssemery	if [[ -z $eachfqdn ]]; then
536bd211b85Ssemery		printf "\n$(gettext "If the -f option is used, at least one FQDN should be listed").\n\n" >&2
5377c478bd9Sstevel@tonic-gate		usage
5387c478bd9Sstevel@tonic-gate	else
539bd211b85Ssemery		while [[ ! -z $eachfqdn ]]; do
5407c478bd9Sstevel@tonic-gate			tmpvar=$(echo "$eachfqdn" | cut -d"." -f1)
541bd211b85Ssemery			if [[ -z $tmpvar ]]; then
5427c478bd9Sstevel@tonic-gate				fullhost="$hostname$eachfqdn"
5437c478bd9Sstevel@tonic-gate			else
5447c478bd9Sstevel@tonic-gate				fullhost="$hostname.$eachfqdn"
5457c478bd9Sstevel@tonic-gate			fi
5467c478bd9Sstevel@tonic-gate
547bd211b85Ssemery			ping_check $fullhost $(gettext "System")
548bd211b85Ssemery			if [[ $fullhost == $client_machine ]]; then
5497c478bd9Sstevel@tonic-gate				:
5507c478bd9Sstevel@tonic-gate			else
5517c478bd9Sstevel@tonic-gate				fqdnlist="$fqdnlist $fullhost"
5527c478bd9Sstevel@tonic-gate			fi
5537c478bd9Sstevel@tonic-gate
554bd211b85Ssemery			if [[ $list == *,* ]]; then
5557c478bd9Sstevel@tonic-gate				((count = count + 1))
5567c478bd9Sstevel@tonic-gate				eachfqdn=$(echo "$list" | cut -d"," -f$count)
5577c478bd9Sstevel@tonic-gate			else
5587c478bd9Sstevel@tonic-gate				break
5597c478bd9Sstevel@tonic-gate			fi
5607c478bd9Sstevel@tonic-gate		done
5617c478bd9Sstevel@tonic-gate	fi
5627c478bd9Sstevel@tonic-gate}
5637c478bd9Sstevel@tonic-gate
564bd211b85Ssemeryfunction setup_keytab {
565bd211b85Ssemery	typeset cname ask_fqdns current_release
566bd211b85Ssemery
567bd211b85Ssemery	#
568bd211b85Ssemery	# 1. kinit with ADMIN_PRINC
569bd211b85Ssemery	#
570bd211b85Ssemery
571bd211b85Ssemery	if [[ -z $ADMIN_PRINC ]]; then
572bd211b85Ssemery		printf "\n$(gettext "Enter the krb5 administrative principal to be used"): "
573bd211b85Ssemery		read ADMIN_PRINC
574bd211b85Ssemery		checkval="ADMIN_PRINC"; check_value $ADMIN_PRINC
575bd211b85Ssemery	fi
576bd211b85Ssemery
577bd211b85Ssemery	echo "$ADMIN_PRINC">$TMP_FILE
578bd211b85Ssemery
579bd211b85Ssemery	[[ -n $msad ]] && return
580bd211b85Ssemery	if egrep -s '\/admin' $TMP_FILE; then
581bd211b85Ssemery		# Already in "/admin" format, do nothing
582bd211b85Ssemery		:
583bd211b85Ssemery	else
584bd211b85Ssemery		if egrep -s '\/' $TMP_FILE; then
585bd211b85Ssemery			printf "\n$(gettext "Improper entry for krb5 admin principal, exiting").\n" >&2
5867c478bd9Sstevel@tonic-gate			error_message
587bd211b85Ssemery		else
588bd211b85Ssemery			ADMIN_PRINC=$(echo "$ADMIN_PRINC/admin")
589bd211b85Ssemery		fi
590bd211b85Ssemery	fi
591bd211b85Ssemery
592bd211b85Ssemery	printf "$(gettext "Obtaining TGT for %s") ...\n" $ADMIN_PRINC
593bd211b85Ssemery
594bd211b85Ssemery	cname=$(canon_resolve $KDC)
595bd211b85Ssemery	if [[ -n $cname ]]; then
596bd211b85Ssemery		kinit -S kadmin/$cname $ADMIN_PRINC
597bd211b85Ssemery	else
598bd211b85Ssemery		kinit -S kadmin/$FKDC $ADMIN_PRINC
599bd211b85Ssemery	fi
600bd211b85Ssemery	klist 1>$TMP_FILE 2>&1
601ae5b046dSsemery	if egrep -s "$(gettext "Valid starting")" $TMP_FILE && egrep -s "kadmin/$FKDC@$realm" $TMP_FILE; then
602bd211b85Ssemery    		:
603bd211b85Ssemery	else
604bd211b85Ssemery		printf "\n$(gettext "kinit of %s failed, exiting").\n" $ADMIN_PRINC >&2
605bd211b85Ssemery		error_message
606bd211b85Ssemery	fi
607bd211b85Ssemery
608bd211b85Ssemery	#
609bd211b85Ssemery	# 2. Do we want to create and/or add service principal(s) for fqdn's
610bd211b85Ssemery	#    other than the one listed in resolv.conf(4) ?
611bd211b85Ssemery	#
612bd211b85Ssemery	if [[ -z $options ]]; then
613bd211b85Ssemery		query "$(gettext "Do you have multiple DNS domains spanning the Kerberos realm") $realm ?"
614bd211b85Ssemery		ask_fqdns=$answer
615bd211b85Ssemery		if [[ $ask_fqdns == yes ]]; then
616ae5b046dSsemery			printf "$(gettext "Enter a comma-separated list of DNS domain names"): "
617bd211b85Ssemery			read fqdnlist
618bd211b85Ssemery			verify_fqdnlist "$fqdnlist"
619bd211b85Ssemery		else
620bd211b85Ssemery			fqdnlist=$client_machine
621bd211b85Ssemery		fi
622bd211b85Ssemery	else
623bd211b85Ssemery		if [[ -z $fqdnlist ]]; then
624bd211b85Ssemery			fqdnlist=$client_machine
625bd211b85Ssemery		fi
626bd211b85Ssemery	fi
627bd211b85Ssemery
628bd211b85Ssemery	if [[ $add_nfs == yes ]]; then
629bd211b85Ssemery		echo; call_kadmin nfs
630bd211b85Ssemery	fi
631bd211b85Ssemery
632bd211b85Ssemery	# Add the host entry to the keytab
633bd211b85Ssemery	echo; call_kadmin host
634bd211b85Ssemery
635bd211b85Ssemery}
636bd211b85Ssemery
637bd211b85Ssemeryfunction setup_lhn {
638bd211b85Ssemery	typeset -l logical_hn
639bd211b85Ssemery
640bd211b85Ssemery	echo "$logical_hn" > $TMP_FILE
641bd211b85Ssemery	if egrep -s '[^.]\.[^.]+$' $TMP_FILE; then
642bd211b85Ssemery		# do nothing, logical_hn is in fqdn format
643bd211b85Ssemery		:
644bd211b85Ssemery	else
645bd211b85Ssemery		if egrep -s '\.+' $TMP_FILE; then
646bd211b85Ssemery			printf "\n$(gettext "Improper format of logical hostname, exiting").\n" >&2
647bd211b85Ssemery			error_message
648bd211b85Ssemery		else
649bd211b85Ssemery			# Attach fqdn to logical_hn, to get the Fully Qualified
650bd211b85Ssemery			# Host Name of the client requested
651bd211b85Ssemery			logical_hn=$(echo "$logical_hn.$fqdn")
652bd211b85Ssemery		fi
653bd211b85Ssemery	fi
654bd211b85Ssemery
655bd211b85Ssemery	client_machine=$logical_hn
656bd211b85Ssemery
657bd211b85Ssemery	ping_check $client_machine $(gettext "System")
658bd211b85Ssemery}
659bd211b85Ssemery
660bd211b85Ssemeryfunction usage {
661bd211b85Ssemery	printf "\n$(gettext "Usage: kclient [ options ]")\n" >&2
662bd211b85Ssemery	printf "\t$(gettext "where options are any of the following")\n\n" >&2
663bd211b85Ssemery	printf "\t$(gettext "[ -D domain_list ]  configure a client that has mul
664bd211b85Ssemerytiple mappings of doamin and/or hosts to the default realm")\n" >&2
665bd211b85Ssemery	printf "\t$(gettext "[ -K ]  configure a client that does not have host/service keys")\n" >&2
666bd211b85Ssemery	printf "\t$(gettext "[ -R realm ]  specifies the realm to use")\n" >&2
667bd211b85Ssemery	printf "\t$(gettext "[ -T kdc_vendor ]  specifies which KDC vendor is the server")\n" >&2
668bd211b85Ssemery	printf "\t$(gettext "[ -a adminuser ]  specifies the Kerberos administrator")\n" >&2
669bd211b85Ssemery	printf "\t$(gettext "[ -c filepath ]  specifies the krb5.conf path used to configure this client")\n" >&2
670bd211b85Ssemery	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
671bd211b85Ssemery	printf "\t$(gettext "[ -f fqdn_list ]  specifies which domains to configure host keys for this client")\n" >&2
672bd211b85Ssemery	printf "\t$(gettext "[ -h logicalhostname ]  configure the logical host name for a client that is in a cluster")\n" >&2
673bd211b85Ssemery	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
674bd211b85Ssemery	printf "\t$(gettext "[ -m master ]  master KDC server host name")\n" >&2
675bd211b85Ssemery	printf "\t$(gettext "[ -n ]  configure client to be an NFS client")\n" >&2
676bd211b85Ssemery	printf "\t$(gettext "[ -p profile ]  specifies which profile file to use to configure this client")\n" >&2
677bd211b85Ssemery	printf "\t$(gettext "[ -s pam_list ]  update the service for Kerberos authentication")\n" >&2
678bd211b85Ssemery	error_message
679bd211b85Ssemery}
680bd211b85Ssemery
681bd211b85Ssemeryfunction discover_domain {
682bd211b85Ssemery	typeset dom DOMs
683bd211b85Ssemery
684bd211b85Ssemery	if [[ -z $realm ]]; then
685bd211b85Ssemery		set -A DOMs -- `$KLOOKUP _ldap._tcp.dc._msdcs S`
686bd211b85Ssemery	else
687bd211b85Ssemery		set -A DOMs -- `$KLOOKUP _ldap._tcp.dc._msdcs.$realm S`
688bd211b85Ssemery	fi
689bd211b85Ssemery
690bd211b85Ssemery	[[ -z ${DOMs[0]} ]] && return 1
691bd211b85Ssemery
692bd211b85Ssemery	dom=${DOMs[0]}
693bd211b85Ssemery
694bd211b85Ssemery	dom=${dom#*.}
695bd211b85Ssemery	dom=${dom% *}
696bd211b85Ssemery
697bd211b85Ssemery	domain=$dom
698bd211b85Ssemery
699bd211b85Ssemery	return 0
700bd211b85Ssemery}
701bd211b85Ssemery
702bd211b85Ssemeryfunction check_nss_hosts_or_ipnodes_config {
703bd211b85Ssemery	typeset backend
704bd211b85Ssemery
705bd211b85Ssemery	for backend in $1
706bd211b85Ssemery	do
707bd211b85Ssemery		[[ $backend == dns ]] && return 0
708bd211b85Ssemery	done
709bd211b85Ssemery	return 1
710bd211b85Ssemery}
711bd211b85Ssemery
712bd211b85Ssemeryfunction check_nss_conf {
713bd211b85Ssemery	typeset i j hosts_config
714bd211b85Ssemery
715bd211b85Ssemery	for i in hosts ipnodes
716bd211b85Ssemery	do
717bd211b85Ssemery		grep "^${i}:" /etc/nsswitch.conf|read j hosts_config
718bd211b85Ssemery		check_nss_hosts_or_ipnodes_config "$hosts_config" || return 1
719bd211b85Ssemery	done
720bd211b85Ssemery
721bd211b85Ssemery	return 0
722bd211b85Ssemery}
723bd211b85Ssemery
724bd211b85Ssemeryfunction canon_resolve {
725bd211b85Ssemery	typeset name ip
726bd211b85Ssemery
727bd211b85Ssemery	name=`$KLOOKUP $1 C`
728bd211b85Ssemery	[[ -z $name ]] && name=`$KLOOKUP $1 A`
729bd211b85Ssemery	[[ -z $name ]] && return
730bd211b85Ssemery
731bd211b85Ssemery	ip=`$KLOOKUP $name I`
732bd211b85Ssemery	[[ -z $ip ]] && return
733ae5b046dSsemery	for i in $ip
734ae5b046dSsemery	do
735ae5b046dSsemery		if ping $i 2 > /dev/null 2>&1; then
736ae5b046dSsemery			break
737ae5b046dSsemery		else
738ae5b046dSsemery			i=
739ae5b046dSsemery		fi
740ae5b046dSsemery	done
741bd211b85Ssemery
742bd211b85Ssemery	cname=`$KLOOKUP $ip P`
743bd211b85Ssemery	[[ -z $cname ]] && return
744bd211b85Ssemery
745bd211b85Ssemery	print -- "$cname"
746bd211b85Ssemery}
747bd211b85Ssemery
748bd211b85Ssemeryfunction rev_resolve {
749bd211b85Ssemery	typeset name ip
750bd211b85Ssemery
751bd211b85Ssemery	ip=`$KLOOKUP $1 I`
752bd211b85Ssemery
753bd211b85Ssemery	[[ -z $ip ]] && return
754bd211b85Ssemery	name=`$KLOOKUP $ip P`
755bd211b85Ssemery	[[ -z $name ]] && return
756bd211b85Ssemery
757bd211b85Ssemery	print -- $name
758bd211b85Ssemery}
759bd211b85Ssemery
760bd211b85Ssemery# Convert an AD-style domain DN to a DNS domainname
761bd211b85Ssemeryfunction dn2dns {
762bd211b85Ssemery	typeset OIFS dname dn comp components
763bd211b85Ssemery
764bd211b85Ssemery	dn=$1
765bd211b85Ssemery	dname=
766bd211b85Ssemery
767bd211b85Ssemery	OIFS="$IFS"
768bd211b85Ssemery	IFS=,
769bd211b85Ssemery	set -A components -- $1
770bd211b85Ssemery	IFS="$OIFS"
771bd211b85Ssemery
772bd211b85Ssemery	for comp in "${components[@]}"
773bd211b85Ssemery	do
774bd211b85Ssemery		[[ "$comp" == [dD][cC]=* ]] || continue
775bd211b85Ssemery		dname="$dname.${comp#??=}"
776bd211b85Ssemery	done
777bd211b85Ssemery
778bd211b85Ssemery	print ${dname#.}
779bd211b85Ssemery}
780bd211b85Ssemery
781bd211b85Ssemery# Form a base DN from a DNS domainname and container
782bd211b85Ssemeryfunction getBaseDN {
783bd211b85Ssemery	if [[ -n "$2" ]]
784bd211b85Ssemery	then
785bd211b85Ssemery		baseDN="CN=$1,$(dns2dn $2)"
786bd211b85Ssemery	else
787bd211b85Ssemery		baseDN="$(dns2dn $2)"
788bd211b85Ssemery	fi
789bd211b85Ssemery}
790bd211b85Ssemery
791bd211b85Ssemery# Convert a DNS domainname to an AD-style DN for that domain
792bd211b85Ssemeryfunction dns2dn {
793bd211b85Ssemery	typeset OIFS dn labels
794bd211b85Ssemery
795bd211b85Ssemery	OIFS="$IFS"
796bd211b85Ssemery	IFS=.
797bd211b85Ssemery	set -A labels -- $1
798bd211b85Ssemery	IFS="$OIFS"
799bd211b85Ssemery
800bd211b85Ssemery	dn=
801bd211b85Ssemery	for label in "${labels[@]}"
802bd211b85Ssemery	do
803bd211b85Ssemery		dn="${dn},DC=$label"
804bd211b85Ssemery	done
805bd211b85Ssemery
806bd211b85Ssemery	print -- "${dn#,}"
807bd211b85Ssemery}
808bd211b85Ssemery
809bd211b85Ssemeryfunction getSRVs {
810bd211b85Ssemery	typeset srv port
811bd211b85Ssemery
812bd211b85Ssemery	$KLOOKUP $1 S | while read srv port
813bd211b85Ssemery	do
814ae5b046dSsemery		if ping $srv 2 > /dev/null 2>&1; then
815bd211b85Ssemery			print -- $srv $port
816ae5b046dSsemery		fi
817bd211b85Ssemery	done
818bd211b85Ssemery}
819bd211b85Ssemery
820bd211b85Ssemeryfunction getKDC {
821bd211b85Ssemery	typeset j
822bd211b85Ssemery
823bd211b85Ssemery	set -A KPWs -- $(getSRVs _kpasswd._tcp.$dom.)
824bd211b85Ssemery	kpasswd=${KPWs[0]}
825bd211b85Ssemery
826bd211b85Ssemery	if [[ -n $siteName ]]
827bd211b85Ssemery	then
828bd211b85Ssemery		set -A KDCs -- $(getSRVs _kerberos._tcp.$siteName._sites.$dom.)
829bd211b85Ssemery		kdc=${KDCs[0]}
830bd211b85Ssemery		[[ -n $kdc ]] && return
831bd211b85Ssemery	fi
832bd211b85Ssemery
833bd211b85Ssemery	# No site name
834bd211b85Ssemery	set -A KDCs -- $(getSRVs _kerberos._tcp.$dom.)
835bd211b85Ssemery	kdc=${KDCs[0]}
836bd211b85Ssemery	[[ -n $kdc ]] && return
837bd211b85Ssemery
838bd211b85Ssemery	# Default
839bd211b85Ssemery	set -A KDCs -- $DomainDnsZones 88
840bd211b85Ssemery	kdc=$ForestDnsZones
841bd211b85Ssemery}
842bd211b85Ssemery
843bd211b85Ssemeryfunction getDC {
844bd211b85Ssemery	typeset j
845bd211b85Ssemery
846bd211b85Ssemery	if [[ -n $siteName ]]
847bd211b85Ssemery	then
848bd211b85Ssemery		set -A DCs -- $(getSRVs _ldap._tcp.$siteName._sites.dc._msdcs.$dom.)
849bd211b85Ssemery		dc=${DCs[0]}
850bd211b85Ssemery		[[ -n $dc ]] && return
851bd211b85Ssemery	fi
852bd211b85Ssemery
853bd211b85Ssemery	# No site name
854bd211b85Ssemery	set -A DCs -- $(getSRVs _ldap._tcp.dc._msdcs.$dom.)
855bd211b85Ssemery	dc=${DCs[0]}
856bd211b85Ssemery	[[ -n $dc ]] && return
857bd211b85Ssemery
858bd211b85Ssemery	# Default
859bd211b85Ssemery	set -A DCs -- $DomainDnsZones 389
860bd211b85Ssemery	dc=$DomainDnsZones
861bd211b85Ssemery}
862bd211b85Ssemery
863bd211b85Ssemeryfunction write_ads_krb5conf {
864c48f4690SShawn Emery	typeset kdcs
865c48f4690SShawn Emery
866bd211b85Ssemery	printf "\n$(gettext "Setting up %s").\n\n" $KRB5_CONFIG_FILE
867bd211b85Ssemery
868bd211b85Ssemery	for i in ${KDCs[@]}
869bd211b85Ssemery	do
870bd211b85Ssemery		[[ $i == +([0-9]) ]] && continue
871c48f4690SShawn Emery		if [[ -n $kdcs ]]
872c48f4690SShawn Emery		then
873c48f4690SShawn Emery			kdcs="$kdcs,$i"
874c48f4690SShawn Emery		else
875c48f4690SShawn Emery			kdcs=$i
876c48f4690SShawn Emery		fi
877bd211b85Ssemery	done
878c48f4690SShawn Emery
879c48f4690SShawn Emery	$KCONF -f $KRB5_CONFIG -r $realm -k $kdcs -m $KDC -p SET_CHANGE -d .$dom
880c48f4690SShawn Emery
881c48f4690SShawn Emery	if [[ $? -ne 0 ]]; then
882c48f4690SShawn Emery		printf "\n$(gettext "Can not update %s, exiting").\n" $KRB5_CONFIG >&2
883c48f4690SShawn Emery		error_message
884c48f4690SShawn Emery	fi
885bd211b85Ssemery}
886bd211b85Ssemery
887bd211b85Ssemeryfunction getForestName {
888bd211b85Ssemery	ldapsearch -R -T -h $dc $ldap_args \
889bd211b85Ssemery	    -b "" -s base "" schemaNamingContext| \
890bd211b85Ssemery		grep ^schemaNamingContext|read j schemaNamingContext
891bd211b85Ssemery
892bd211b85Ssemery	if [[ $? -ne 0 ]]; then
893c386eb9cSShawn Emery		printf "$(gettext "Can't find forest").\n" >&2
894bd211b85Ssemery		error_message
895bd211b85Ssemery	fi
896bd211b85Ssemery	schemaNamingContext=${schemaNamingContext#CN=Schema,CN=Configuration,}
897bd211b85Ssemery
898bd211b85Ssemery	[[ -z $schemaNamingContext ]] && return 1
899bd211b85Ssemery
900bd211b85Ssemery	forest=
901bd211b85Ssemery	while [[ -n $schemaNamingContext ]]
902bd211b85Ssemery	do
903bd211b85Ssemery		schemaNamingContext=${schemaNamingContext#DC=}
904bd211b85Ssemery		forest=${forest}.${schemaNamingContext%%,*}
905bd211b85Ssemery		[[ "$schemaNamingContext" = *,* ]] || break
906bd211b85Ssemery		schemaNamingContext=${schemaNamingContext#*,}
907bd211b85Ssemery	done
908bd211b85Ssemery	forest=${forest#.}
909bd211b85Ssemery}
910bd211b85Ssemery
911bd211b85Ssemeryfunction getGC {
912bd211b85Ssemery	typeset j
913bd211b85Ssemery
914bd211b85Ssemery	[[ -n $gc ]] && return 0
915bd211b85Ssemery
916bd211b85Ssemery	if [[ -n $siteName ]]
917bd211b85Ssemery	then
918bd211b85Ssemery		set -A GCs -- $(getSRVs _ldap._tcp.$siteName._sites.gc._msdcs.$forest.)
919bd211b85Ssemery		gc=${GCs[0]}
920bd211b85Ssemery		[[ -n $gc ]] && return
921bd211b85Ssemery	fi
922bd211b85Ssemery
923bd211b85Ssemery	# No site name
924bd211b85Ssemery	set -A GCs -- $(getSRVs _ldap._tcp.gc._msdcs.$forest.)
925bd211b85Ssemery	gc=${GCs[0]}
926bd211b85Ssemery	[[ -n $gc ]] && return
927bd211b85Ssemery
928bd211b85Ssemery	# Default
929bd211b85Ssemery	set -A GCs -- $ForestDnsZones 3268
930bd211b85Ssemery	gc=$ForestDnsZones
931bd211b85Ssemery}
932bd211b85Ssemery
933c386eb9cSShawn Emery#
934c386eb9cSShawn Emery# The local variables used to calculate the IP address are of type unsigned
935c386eb9cSShawn Emery# integer (-ui), as this is required to restrict the integer to 32b.
936c386eb9cSShawn Emery# Starting in ksh88, Solaris has incorrectly assummed that -i represents 64b.
937c386eb9cSShawn Emery#
938bd211b85Ssemeryfunction ipAddr2num {
939bd211b85Ssemery	typeset OIFS
940c386eb9cSShawn Emery	typeset -ui16 num
941bd211b85Ssemery
942bd211b85Ssemery	if [[ "$1" != +([0-9]).+([0-9]).+([0-9]).+([0-9]) ]]
943bd211b85Ssemery	then
944bd211b85Ssemery		print 0
945bd211b85Ssemery		return 0
946bd211b85Ssemery	fi
947bd211b85Ssemery
948bd211b85Ssemery	OIFS="$IFS"
949bd211b85Ssemery	IFS=.
950bd211b85Ssemery	set -- $1
951bd211b85Ssemery	IFS="$OIFS"
952bd211b85Ssemery
953bd211b85Ssemery	num=$((${1}<<24 | ${2}<<16 | ${3}<<8 | ${4}))
954bd211b85Ssemery
955bd211b85Ssemery	print -- $num
956bd211b85Ssemery}
957bd211b85Ssemery
958c386eb9cSShawn Emery#
959c386eb9cSShawn Emery# The local variables used to calculate the IP address are of type unsigned
960c386eb9cSShawn Emery# integer (-ui), as this is required to restrict the integer to 32b.
961c386eb9cSShawn Emery# Starting in ksh88, Solaris has incorrectly assummed that -i represents 64b.
962c386eb9cSShawn Emery#
963bd211b85Ssemeryfunction num2ipAddr {
964c386eb9cSShawn Emery	typeset -ui16 num
965c386eb9cSShawn Emery	typeset -ui10 a b c d
966bd211b85Ssemery
967bd211b85Ssemery	num=$1
968bd211b85Ssemery	a=$((num>>24        ))
969bd211b85Ssemery	b=$((num>>16 & 16#ff))
970bd211b85Ssemery	c=$((num>>8  & 16#ff))
971bd211b85Ssemery	d=$((num     & 16#ff))
972bd211b85Ssemery	print -- $a.$b.$c.$d
973bd211b85Ssemery}
974bd211b85Ssemery
975c386eb9cSShawn Emery#
976c386eb9cSShawn Emery# The local variables used to calculate the IP address are of type unsigned
977c386eb9cSShawn Emery# integer (-ui), as this is required to restrict the integer to 32b.
978c386eb9cSShawn Emery# Starting in ksh88, Solaris has incorrectly assummed that -i represents 64b.
979c386eb9cSShawn Emery#
980bd211b85Ssemeryfunction netmask2length {
981c386eb9cSShawn Emery	typeset -ui16 netmask
982bd211b85Ssemery	typeset -i len
983bd211b85Ssemery
984bd211b85Ssemery	netmask=$1
985bd211b85Ssemery	len=32
986bd211b85Ssemery	while [[ $((netmask % 2)) -eq 0 ]]
987bd211b85Ssemery	do
988bd211b85Ssemery		netmask=$((netmask>>1))
989bd211b85Ssemery		len=$((len - 1))
990bd211b85Ssemery	done
991bd211b85Ssemery	print $len
992bd211b85Ssemery}
993bd211b85Ssemery
994c386eb9cSShawn Emery#
995c386eb9cSShawn Emery# The local variables used to calculate the IP address are of type unsigned
996c386eb9cSShawn Emery# integer (-ui), as this is required to restrict the integer to 32b.
997c386eb9cSShawn Emery# Starting in ksh88, Solaris has incorrectly assummed that -i represents 64b.
998c386eb9cSShawn Emery#
999bd211b85Ssemeryfunction getSubnets {
1000c386eb9cSShawn Emery	typeset -ui16 addr netmask
1001c386eb9cSShawn Emery	typeset -ui16 classa=16\#ff000000
1002bd211b85Ssemery
1003bd211b85Ssemery	ifconfig -a|while read line
1004bd211b85Ssemery	do
1005bd211b85Ssemery		addr=0
1006bd211b85Ssemery		netmask=0
1007bd211b85Ssemery		set -- $line
1008bd211b85Ssemery		[[ $1 == inet ]] || continue
1009bd211b85Ssemery		while [[ $# -gt 0 ]]
1010bd211b85Ssemery		do
1011bd211b85Ssemery			case "$1" in
1012bd211b85Ssemery				inet) addr=$(ipAddr2num $2); shift;;
1013bd211b85Ssemery				netmask) eval netmask=16\#$2; shift;;
1014bd211b85Ssemery				*) :;
1015bd211b85Ssemery			esac
1016bd211b85Ssemery			shift
1017bd211b85Ssemery		done
1018bd211b85Ssemery
1019bd211b85Ssemery		[[ $addr -eq 0 || $netmask -eq 0 ]] && continue
1020bd211b85Ssemery		[[ $((addr & classa)) -eq 16\#7f000000 ]] && continue
1021bd211b85Ssemery
1022bd211b85Ssemery		print $(num2ipAddr $((addr & netmask)))/$(netmask2length $netmask)
1023bd211b85Ssemery	done
1024bd211b85Ssemery}
1025bd211b85Ssemery
1026bd211b85Ssemeryfunction getSite {
1027bd211b85Ssemery	typeset subnet siteDN j ldapsrv subnet_dom
1028bd211b85Ssemery
1029bd211b85Ssemery	eval "[[ -n \"\$siteName\" ]]" && return
1030bd211b85Ssemery	for subnet in $(getSubnets)
1031bd211b85Ssemery	do
1032bd211b85Ssemery		ldapsearch -R -T -h $dc $ldap_args \
1033bd211b85Ssemery		    -p 3268 -b "" -s sub cn=$subnet dn |grep ^dn|read j subnetDN
1034bd211b85Ssemery
1035bd211b85Ssemery		[[ -z $subnetDN ]] && continue
1036bd211b85Ssemery		subnet_dom=$(dn2dns $subnetDN)
1037bd211b85Ssemery		ldapsrv=$(canon_resolve DomainDnsZones.$subnet_dom)
1038ae5b046dSsemery		[[ -z $ldapsrv ]] && continue
1039bd211b85Ssemery		ldapsearch -R -T -h $ldapsrv $ldap_args \
1040bd211b85Ssemery		    -b "$subnetDN" -s base "" siteObject \
1041bd211b85Ssemery		    |grep ^siteObject|read j siteDN
1042bd211b85Ssemery
1043bd211b85Ssemery		[[ -z $siteDN ]] && continue
1044bd211b85Ssemery
1045bd211b85Ssemery		eval siteName=${siteDN%%,*}
1046bd211b85Ssemery		eval siteName=\${siteName#CN=}
1047bd211b85Ssemery		return
1048bd211b85Ssemery	done
1049bd211b85Ssemery}
1050bd211b85Ssemery
1051bd211b85Ssemeryfunction doKRB5config {
1052bd211b85Ssemery	[[ -f $KRB5_CONFIG_FILE ]] && \
1053bd211b85Ssemery		cp $KRB5_CONFIG_FILE ${KRB5_CONFIG_FILE}-pre-kclient
1054bd211b85Ssemery
1055bd211b85Ssemery	[[ -f $KRB5_KEYTAB_FILE ]] && \
1056bd211b85Ssemery		cp $KRB5_KEYTAB_FILE ${KRB5_KEYTAB_FILE}-pre-kclient
1057bd211b85Ssemery
1058ae5b046dSsemery	[[ -s $KRB5_CONFIG ]] && cp $KRB5_CONFIG $KRB5_CONFIG_FILE
1059ae5b046dSsemery	[[ -s $KRB5_CONFIG_FILE ]] && chmod 0644 $KRB5_CONFIG_FILE
1060ae5b046dSsemery	[[ -s $new_keytab ]] && cp $new_keytab $KRB5_KEYTAB_FILE
1061ae5b046dSsemery	[[ -s $KRB5_KEYTAB_FILE ]] && chmod 0600 $KRB5_KEYTAB_FILE
1062bd211b85Ssemery}
1063bd211b85Ssemery
1064bd211b85Ssemeryfunction addDNSRR {
1065bd211b85Ssemery	smbFMRI=svc:/network/smb/server:default
1066bd211b85Ssemery	ddnsProp=smbd/ddns_enable
1067bd211b85Ssemery	enProp=general/enabled
1068bd211b85Ssemery
1069bd211b85Ssemery	enabled=`svcprop -p $enProp $smbFMRI`
1070bd211b85Ssemery	ddns_enable=`svcprop -p $ddnsProp $smbFMRI`
1071bd211b85Ssemery
1072bd211b85Ssemery	if [[ $enabled == true && $ddns_enable != true ]]; then
1073bd211b85Ssemery		printf "$(gettext "Warning: won't create DNS records for client").\n"
1074bd211b85Ssemery		printf "$(gettext "%s property not set to 'true' for the %s FMRI").\n" $ddnsProp $smbFMRI
1075bd211b85Ssemery		return
1076bd211b85Ssemery	fi
1077bd211b85Ssemery
1078bd211b85Ssemery	# Destroy any existing ccache as GSS_C_NO_CREDENTIAL will pick up any
1079bd211b85Ssemery	# residual default credential in the cache.
1080bd211b85Ssemery	kdestroy > /dev/null 2>&1
1081bd211b85Ssemery
1082bd211b85Ssemery	$KDYNDNS -d $1 > /dev/null 2>&1
1083bd211b85Ssemery	if [[ $? -ne 0 ]]; then
1084bd211b85Ssemery		#
1085bd211b85Ssemery		# Non-fatal, we should carry-on as clients may resolve to
1086bd211b85Ssemery		# different servers and the client could already exist there.
1087bd211b85Ssemery		#
10888d7e4166Sjose borrego		printf "$(gettext "Warning: unable to create DNS records for client").\n"
1089bd211b85Ssemery		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
1090bd211b85Ssemery	fi
1091bd211b85Ssemery}
1092bd211b85Ssemery
1093bd211b85Ssemeryfunction setSMB {
1094bd211b85Ssemery	typeset domain=$1
1095bd211b85Ssemery	typeset server=$2
1096bd211b85Ssemery	smbFMRI=svc:/network/smb/server
1097bd211b85Ssemery
1098986b458dSShawn Emery	printf "%s" "$newpw" | $KSMB -d $domain -s $server
1099bd211b85Ssemery	if [[ $? -ne 0 ]]; then
11008d7e4166Sjose borrego		printf "$(gettext "Warning: unable to set %s domain, server and password information").\n" $smbFMRI
1101bd211b85Ssemery		return
1102bd211b85Ssemery	fi
1103bd211b85Ssemery
11048d7e4166Sjose borrego	svcadm restart $smbFMRI > /dev/null 2>&1
1105bd211b85Ssemery	if [[ $? -ne 0 ]]; then
11068d7e4166Sjose borrego		printf "$(gettext "Warning: unable to restart %s").\n" $smbFMRI
1107bd211b85Ssemery	fi
1108bd211b85Ssemery}
1109bd211b85Ssemery
1110bd211b85Ssemeryfunction compareDomains {
1111bd211b85Ssemery	typeset oldDom hspn newDom=$1
1112bd211b85Ssemery
1113bd211b85Ssemery	# If the client has been previously configured in a different
1114bd211b85Ssemery	# realm/domain then we need to prompt the user to see if they wish to
1115bd211b85Ssemery	# switch domains.
1116ae5b046dSsemery	klist -k 2>&1 | grep @ | read j hspn
1117bd211b85Ssemery	[[ -z $hspn ]] && return
1118bd211b85Ssemery
1119bd211b85Ssemery	oldDom=${hspn#*@}
1120bd211b85Ssemery	if [[ $oldDom != $newDom ]]; then
1121bd211b85Ssemery		printf "$(gettext "The client is currently configured in a different domain").\n"
1122bd211b85Ssemery		printf "$(gettext "Currently in the '%s' domain, trying to join the '%s' domain").\n" $oldDom $newDom
1123bd211b85Ssemery		query "$(gettext "Do you want the client to join a new domain") ?"
1124bd211b85Ssemery		printf "\n"
1125bd211b85Ssemery		if [[ $answer != yes ]]; then
1126c386eb9cSShawn Emery			printf "$(gettext "Client will not be joined to the new domain").\n" >&2
1127bd211b85Ssemery			error_message
1128bd211b85Ssemery		fi
1129bd211b85Ssemery	fi
1130bd211b85Ssemery}
1131bd211b85Ssemery
1132bd211b85Ssemeryfunction getKDCDC {
1133bd211b85Ssemery
1134bd211b85Ssemery	getKDC
1135bd211b85Ssemery	if [[ -n $kdc ]]; then
1136bd211b85Ssemery		KDC=$kdc
1137bd211b85Ssemery		dc=$kdc
1138bd211b85Ssemery	else
1139bd211b85Ssemery		getDC
1140bd211b85Ssemery		if [[ -n $dc ]]; then
1141bd211b85Ssemery			KDC=$dc
1142bd211b85Ssemery		else
1143c386eb9cSShawn Emery			printf "$(gettext "Could not find domain controller server for '%s'.  Exiting").\n" $realm >&2
1144bd211b85Ssemery			error_message
1145bd211b85Ssemery		fi
1146bd211b85Ssemery	fi
1147bd211b85Ssemery}
1148bd211b85Ssemery
1149986b458dSShawn Emeryfunction gen_rand {
1150986b458dSShawn Emery	typeset -u hex
1151986b458dSShawn Emery
1152986b458dSShawn Emery	dd if=/dev/random bs=1 count=1 2>/dev/null | od -A n -tx1 | read hex
1153986b458dSShawn Emery
1154986b458dSShawn Emery	printf %s $((16#$hex))
1155986b458dSShawn Emery}
1156986b458dSShawn Emery
1157bd211b85Ssemeryfunction join_domain {
1158bd211b85Ssemery	typeset -u upcase_nodename
115972f0806aSShawn Emery	typeset -l locase_nodename
116072f0806aSShawn Emery	typeset -L15 string15
1161bd211b85Ssemery	typeset netbios_nodename fqdn
1162bd211b85Ssemery
1163bd211b85Ssemery	container=Computers
1164bd211b85Ssemery	ldap_args="-o authzid= -o mech=gssapi"
1165bd211b85Ssemery	userAccountControlBASE=4096
1166bd211b85Ssemery
1167bd211b85Ssemery	if [[ -z $ADMIN_PRINC ]]; then
1168bd211b85Ssemery		cprinc=Administrator
1169bd211b85Ssemery	else
1170bd211b85Ssemery		cprinc=$ADMIN_PRINC
1171bd211b85Ssemery	fi
1172bd211b85Ssemery
1173bd211b85Ssemery	if ! discover_domain; then
1174c386eb9cSShawn Emery		printf "$(gettext "Can not find realm") '%s'.\n" $realm >&2
1175bd211b85Ssemery		error_message
1176bd211b85Ssemery	fi
1177bd211b85Ssemery
1178bd211b85Ssemery	dom=$domain
1179bd211b85Ssemery	realm=$domain
118072f0806aSShawn Emery
118172f0806aSShawn Emery	if [[ ${#hostname} -gt 15 ]]; then
118272f0806aSShawn Emery		string15=$hostname
118372f0806aSShawn Emery		upcase_nodename=$string15
118472f0806aSShawn Emery		locase_nodename=$string15
118572f0806aSShawn Emery	else
1186bd211b85Ssemery		upcase_nodename=$hostname
118772f0806aSShawn Emery		locase_nodename=$hostname
118872f0806aSShawn Emery	fi
118972f0806aSShawn Emery
1190bd211b85Ssemery	netbios_nodename="${upcase_nodename}\$"
1191bd211b85Ssemery	fqdn=$hostname.$domain
1192037cac00Sjoyce mcintosh	upn=host/${fqdn}@${realm}
1193bd211b85Ssemery
1194bd211b85Ssemery	object=$(mktemp -q -t kclient-computer-object.XXXXXX)
1195bd211b85Ssemery	if [[ -z $object ]]; then
1196bd211b85Ssemery		printf "\n$(gettext "Can not create temporary file, exiting").\n
1197bd211b85Ssemery" >&2
1198bd211b85Ssemery		error_message
1199bd211b85Ssemery        fi
1200bd211b85Ssemery
1201bd211b85Ssemery	modify_existing=false
1202bd211b85Ssemery	recreate=false
1203bd211b85Ssemery
1204bd211b85Ssemery	DomainDnsZones=$(rev_resolve DomainDnsZones.$dom.)
1205bd211b85Ssemery	ForestDnsZones=$(rev_resolve ForestDnsZones.$dom.)
1206bd211b85Ssemery
1207bd211b85Ssemery	getBaseDN "$container" "$dom"
1208bd211b85Ssemery
1209bd211b85Ssemery	if [[ -n $KDC ]]; then
1210bd211b85Ssemery		dc=$KDC
1211bd211b85Ssemery	else
1212bd211b85Ssemery		getKDCDC
1213bd211b85Ssemery	fi
1214bd211b85Ssemery
1215bd211b85Ssemery	write_ads_krb5conf
1216bd211b85Ssemery
1217ae5b046dSsemery	printf "$(gettext "Attempting to join '%s' to the '%s' domain").\n\n" $upcase_nodename $realm
1218bd211b85Ssemery
1219bd211b85Ssemery	kinit $cprinc@$realm
1220bd211b85Ssemery	if [[ $? -ne 0 ]]; then
1221c386eb9cSShawn Emery		printf "$(gettext "Could not authenticate %s.  Exiting").\n" $cprinc@$realm >&2
1222bd211b85Ssemery		error_message
1223bd211b85Ssemery	fi
1224bd211b85Ssemery
1225bd211b85Ssemery	if getForestName
1226bd211b85Ssemery	then
1227bd211b85Ssemery		printf "\n$(gettext "Forest name found: %s")\n\n" $forest
1228bd211b85Ssemery	else
1229bd211b85Ssemery		printf "\n$(gettext "Forest name not found, assuming forest is the domain name").\n"
1230bd211b85Ssemery	fi
1231bd211b85Ssemery
1232bd211b85Ssemery	getGC
1233bd211b85Ssemery	getSite
1234bd211b85Ssemery
1235bd211b85Ssemery	if [[ -z $siteName ]]
1236bd211b85Ssemery	then
1237bd211b85Ssemery    		printf "$(gettext "Site name not found.  Local DCs/GCs will not be discovered").\n\n"
1238bd211b85Ssemery	else
1239bd211b85Ssemery    		printf "$(gettext "Looking for _local_ KDCs, DCs and global catalog servers (SRV RRs)").\n"
1240bd211b85Ssemery		getKDCDC
1241bd211b85Ssemery		getGC
1242bd211b85Ssemery
1243bd211b85Ssemery		write_ads_krb5conf
1244bd211b85Ssemery	fi
1245bd211b85Ssemery
1246bd211b85Ssemery	if [[ ${#GCs} -eq 0 ]]; then
1247c386eb9cSShawn Emery		printf "$(gettext "Could not find global catalogs.  Exiting").\n" >&2
1248bd211b85Ssemery		error_message
1249bd211b85Ssemery	fi
1250bd211b85Ssemery
1251bd211b85Ssemery	# Check to see if the client is transitioning between domains.
1252bd211b85Ssemery	compareDomains $realm
1253bd211b85Ssemery
1254bd211b85Ssemery	# Here we check domainFunctionality to see which release:
1255bd211b85Ssemery	# 0, 1, 2: Windows 2000, 2003 Interim, 2003 respecitively
1256bd211b85Ssemery	# 3: Windows 2008
1257bd211b85Ssemery	level=0
1258bd211b85Ssemery	ldapsearch -R -T -h "$dc" $ldap_args -b "" -s base "" \
1259bd211b85Ssemery	 domainControllerFunctionality| grep ^domainControllerFunctionality| \
1260bd211b85Ssemery	 read j level
1261bd211b85Ssemery	if [[ $? -ne 0 ]]; then
1262c386eb9cSShawn Emery		printf "$(gettext "Search for domain functionality failed, exiting").\n" >&2
1263bd211b85Ssemery		error_message
1264bd211b85Ssemery	fi
1265bd211b85Ssemery
1266bd211b85Ssemery	if ldapsearch -R -T -h "$dc" $ldap_args -b "$baseDN" \
1267bd211b85Ssemery	    -s sub sAMAccountName="$netbios_nodename" dn > /dev/null 2>&1
1268bd211b85Ssemery	then
1269bd211b85Ssemery		:
1270bd211b85Ssemery	else
1271c386eb9cSShawn Emery		printf "$(gettext "Search for node failed, exiting").\n" >&2
1272bd211b85Ssemery		error_message
1273bd211b85Ssemery	fi
1274bd211b85Ssemery	ldapsearch -R -T -h "$dc" $ldap_args -b "$baseDN" -s sub \
1275bd211b85Ssemery	    sAMAccountName="$netbios_nodename" dn|grep "^dn:"|read j dn
1276bd211b85Ssemery
1277bd211b85Ssemery	if [[ -z $dn ]]; then
1278bd211b85Ssemery		: # modify_existing is already false, which is what we want.
1279bd211b85Ssemery	else
1280bd211b85Ssemery		printf "$(gettext "Computer account '%s' already exists in the '%s' domain").\n" $upcase_nodename $realm
1281bd211b85Ssemery		query "$(gettext "Do you wish to recreate this computer account") ?"
1282bd211b85Ssemery		printf "\n"
1283bd211b85Ssemery		if [[ $answer == yes ]]; then
1284bd211b85Ssemery			recreate=true
1285bd211b85Ssemery		else
1286bd211b85Ssemery			modify_existing=true
1287bd211b85Ssemery		fi
1288bd211b85Ssemery	fi
1289bd211b85Ssemery
1290bd211b85Ssemery	if [[ $modify_existing == false && -n $dn ]]; then
1291bd211b85Ssemery		query "$(gettext "Would you like to delete any sub-object found for this computer account") ?"
1292bd211b85Ssemery		if [[ $answer == yes ]]; then
1293bd211b85Ssemery			printf "$(gettext "Looking to see if the machine account contains other objects")...\n"
1294bd211b85Ssemery			ldapsearch -R -T -h "$dc" $ldap_args -b "$dn" -s sub "" dn | while read j sub_dn
1295bd211b85Ssemery			do
1296bd211b85Ssemery				[[ $j != dn: || -z $sub_dn || $dn == $sub_dn ]] && continue
1297bd211b85Ssemery				if $recreate; then
1298bd211b85Ssemery					printf "$(gettext "Deleting the following object: %s")\n" ${sub_dn#$dn}
1299bd211b85Ssemery					ldapdelete -h "$dc" $ldap_args "$sub_dn" > /dev/null 2>&1
1300bd211b85Ssemery					if [[ $? -ne 0 ]]; then
1301bd211b85Ssemery						printf "$(gettext "Error in deleting object: %s").\n" ${sub_dn#$dn}
1302bd211b85Ssemery					fi
1303bd211b85Ssemery				else
1304bd211b85Ssemery					printf "$(gettext "The following object will not be deleted"): %s\n" ${sub_dn#$dn}
1305bd211b85Ssemery				fi
1306bd211b85Ssemery			done
1307bd211b85Ssemery		fi
1308bd211b85Ssemery
1309bd211b85Ssemery		if $recreate; then
1310bd211b85Ssemery			ldapdelete -h "$dc" $ldap_args "$dn" > /dev/null 2>&1
1311bd211b85Ssemery			if [[ $? -ne 0 ]]; then
1312c386eb9cSShawn Emery				printf "$(gettext "Error in deleting object: %s").\n" ${sub_dn#$dn} >&2
1313bd211b85Ssemery				error_message
1314bd211b85Ssemery			fi
1315bd211b85Ssemery		elif $modify_existing; then
1316bd211b85Ssemery			: # Nothing to delete
1317bd211b85Ssemery		else
1318c386eb9cSShawn Emery			printf "$(gettext "A machine account already exists").\n" >&2
1319bd211b85Ssemery			error_message
1320bd211b85Ssemery		fi
1321bd211b85Ssemery	fi
1322bd211b85Ssemery
132372f0806aSShawn Emery	[[ -z $dn ]] && dn="CN=${upcase_nodename},${baseDN}"
1324bd211b85Ssemery	if $modify_existing; then
1325bd211b85Ssemery		cat > "$object" <<EOF
132672f0806aSShawn Emerydn: $dn
1327bd211b85Ssemerychangetype: modify
1328bd211b85Ssemeryreplace: userPrincipalName
1329bd211b85SsemeryuserPrincipalName: $upn
1330bd211b85Ssemery-
1331bd211b85Ssemeryreplace: servicePrincipalName
1332bd211b85SsemeryservicePrincipalName: host/${fqdn}
1333bd211b85Ssemery-
1334bd211b85Ssemeryreplace: userAccountControl
1335bd211b85SsemeryuserAccountControl: $((userAccountControlBASE + 32 + 2))
1336bd211b85Ssemery-
1337bd211b85Ssemeryreplace: dNSHostname
1338bd211b85SsemerydNSHostname: ${fqdn}
1339bd211b85SsemeryEOF
1340bd211b85Ssemery
1341bd211b85Ssemery		printf "$(gettext "A machine account already exists; updating it").\n"
1342ae5b046dSsemery		ldapadd -h "$dc" $ldap_args -f "$object" > /dev/null 2>&1
1343bd211b85Ssemery		if [[ $? -ne 0 ]]; then
134472f0806aSShawn Emery			printf "$(gettext "Failed to modify the AD object via LDAP").\n" >&2
1345bd211b85Ssemery			error_message
1346bd211b85Ssemery		fi
1347bd211b85Ssemery	else
134872f0806aSShawn Emery		dn="CN=${upcase_nodename},${baseDN}"
1349bd211b85Ssemery		cat > "$object" <<EOF
135072f0806aSShawn Emerydn: $dn
1351bd211b85SsemeryobjectClass: computer
1352bd211b85Ssemerycn: $upcase_nodename
1353bd211b85SsemerysAMAccountName: ${netbios_nodename}
1354bd211b85SsemeryuserPrincipalName: $upn
1355bd211b85SsemeryservicePrincipalName: host/${fqdn}
1356bd211b85SsemeryuserAccountControl: $((userAccountControlBASE + 32 + 2))
1357bd211b85SsemerydNSHostname: ${fqdn}
1358bd211b85SsemeryEOF
1359bd211b85Ssemery
1360bd211b85Ssemery		printf "$(gettext "Creating the machine account in AD via LDAP").\n\n"
1361bd211b85Ssemery
1362bd211b85Ssemery		ldapadd -h "$dc" $ldap_args -f "$object" > /dev/null 2>&1
1363bd211b85Ssemery		if [[ $? -ne 0 ]]; then
1364c386eb9cSShawn Emery			printf "$(gettext "Failed to create the AD object via LDAP").\n" >&2
1365bd211b85Ssemery			error_message
1366bd211b85Ssemery		fi
1367bd211b85Ssemery	fi
1368bd211b85Ssemery
1369bd211b85Ssemery	# Generate a new password for the new account
1370986b458dSShawn Emery	MAX_PASS=120
1371bd211b85Ssemery        i=0
1372bd211b85Ssemery
1373986b458dSShawn Emery	# first check to see if /dev/random exists to generate a new password
1374986b458dSShawn Emery	if [[ ! -h /dev/random ]]; then
1375986b458dSShawn Emery		printf "$(gettext "/dev/random does not exist").\n" >&2
1376986b458dSShawn Emery		error_message
1377986b458dSShawn Emery	fi
1378986b458dSShawn Emery
1379bd211b85Ssemery	while ((MAX_PASS > i))
1380bd211b85Ssemery	do
1381986b458dSShawn Emery		# [MS-DISO] A machine password is an ASCII string of randomly
1382986b458dSShawn Emery		# chosen characters. Each character's ASCII code is between 32
1383986b458dSShawn Emery		# and 122 inclusive.
1384986b458dSShawn Emery		c=$(printf "\\$(printf %o $(($(gen_rand) % 91 + 32)))\n")
1385986b458dSShawn Emery		p="$p$c"
1386bd211b85Ssemery		((i+=1))
1387bd211b85Ssemery	done
1388bd211b85Ssemery
1389bd211b85Ssemery	newpw=$p
1390986b458dSShawn Emery	if [[ ${#newpw} -ne MAX_PASS ]]; then
1391986b458dSShawn Emery		printf "$(gettext "Password created was of incorrect length").\n" >&2
1392986b458dSShawn Emery		error_message
1393986b458dSShawn Emery	fi
1394bd211b85Ssemery
1395bd211b85Ssemery	# Set the new password
1396986b458dSShawn Emery	printf "%s" "$newpw" | $KSETPW ${netbios_nodename}@${realm} > /dev/null 2>&1
1397bd211b85Ssemery	if [[ $? -ne 0 ]]
1398bd211b85Ssemery	then
1399c386eb9cSShawn Emery		printf "$(gettext "Failed to set account password").\n" >&2
1400bd211b85Ssemery		error_message
1401bd211b85Ssemery	fi
1402bd211b85Ssemery
1403bd211b85Ssemery	# Lookup the new principal's kvno:
1404bd211b85Ssemery	ldapsearch -R -T -h "$dc" $ldap_args -b "$baseDN" \
1405bd211b85Ssemery		 -s sub cn=$upcase_nodename msDS-KeyVersionNumber| \
1406bd211b85Ssemery		grep "^msDS-KeyVersionNumber"|read j kvno
1407bd211b85Ssemery	[[ -z $kvno ]] && kvno=1
1408bd211b85Ssemery
1409bd211b85Ssemery	# Set supported enctypes.  This only works for Longhorn/Vista, so we
1410bd211b85Ssemery	# ignore errors here.
1411bd211b85Ssemery	userAccountControl=$((userAccountControlBASE + 524288 + 65536))
1412bd211b85Ssemery	set -A enctypes --
1413bd211b85Ssemery
1414bd211b85Ssemery	# Do we have local support for AES?
1415bd211b85Ssemery	encrypt -l|grep ^aes|read j minkeysize maxkeysize
1416bd211b85Ssemery	val=
1417bd211b85Ssemery	if [[ $maxkeysize -eq 256 ]]; then
1418bd211b85Ssemery		val=16
1419bd211b85Ssemery		enctypes[${#enctypes[@]}]=aes256-cts-hmac-sha1-96
1420bd211b85Ssemery	fi
1421bd211b85Ssemery	if [[ $minkeysize -eq 128 ]]; then
1422bd211b85Ssemery		((val=val+8))
1423bd211b85Ssemery		enctypes[${#enctypes[@]}]=aes128-cts-hmac-sha1-96
1424bd211b85Ssemery	fi
1425bd211b85Ssemery
1426bd211b85Ssemery	# RC4 comes next (whether it's better than 1DES or not -- AD prefers it)
1427*f7dbdfc7SMarcel Telka	if encrypt -l|grep -q ^arcfour
1428bd211b85Ssemery	then
1429bd211b85Ssemery		((val=val+4))
1430bd211b85Ssemery		enctypes[${#enctypes[@]}]=arcfour-hmac-md5
1431bd211b85Ssemery	else
1432bd211b85Ssemery		# Use 1DES ONLY if we don't have arcfour
1433bd211b85Ssemery		userAccountControl=$((userAccountControl + 2097152))
1434bd211b85Ssemery	fi
1435*f7dbdfc7SMarcel Telka	if encrypt -l | grep -q ^des
1436bd211b85Ssemery	then
1437c386eb9cSShawn Emery		((val=val+2))
1438bd211b85Ssemery		enctypes[${#enctypes[@]}]=des-cbc-md5
1439bd211b85Ssemery	fi
1440bd211b85Ssemery
1441bd211b85Ssemery	if [[ ${#enctypes[@]} -eq 0 ]]
1442bd211b85Ssemery	then
1443bd211b85Ssemery		printf "$(gettext "No enctypes are supported").\n"
1444c386eb9cSShawn Emery		printf "$(gettext "Please enable arcfour or 1DES, then re-join; see cryptoadm(1M)").\n" >&2
1445bd211b85Ssemery		error_message
1446bd211b85Ssemery	fi
1447bd211b85Ssemery
1448bd211b85Ssemery	# If domain crontroller is Longhorn or above then set new supported
1449bd211b85Ssemery	# encryption type attributes.
1450bd211b85Ssemery	if [[ $level -gt 2 ]]; then
1451bd211b85Ssemery		cat > "$object" <<EOF
145272f0806aSShawn Emerydn: $dn
1453bd211b85Ssemerychangetype: modify
1454bd211b85Ssemeryreplace: msDS-SupportedEncryptionTypes
1455bd211b85SsemerymsDS-SupportedEncryptionTypes: $val
1456bd211b85SsemeryEOF
1457bd211b85Ssemery		ldapmodify -h "$dc" $ldap_args -f "$object" >/dev/null 2>&1
1458bd211b85Ssemery		if [[ $? -ne 0 ]]; then
1459bd211b85Ssemery			printf "$(gettext "Warning: Could not set the supported encryption type for computer account").\n"
1460bd211b85Ssemery		fi
1461bd211b85Ssemery	fi
1462bd211b85Ssemery
1463bd211b85Ssemery	# We should probably check whether arcfour is available, and if not,
1464bd211b85Ssemery	# then set the 1DES only flag, but whatever, it's not likely NOT to be
1465bd211b85Ssemery	# available on S10/Nevada!
1466bd211b85Ssemery
1467bd211b85Ssemery	# Reset userAccountControl
1468bd211b85Ssemery	#
1469bd211b85Ssemery	#  NORMAL_ACCOUNT (512) | DONT_EXPIRE_PASSWORD (65536) |
1470bd211b85Ssemery	#  TRUSTED_FOR_DELEGATION (524288)
1471bd211b85Ssemery	#
1472bd211b85Ssemery	# and possibly UseDesOnly (2097152) (see above)
1473bd211b85Ssemery	#
1474bd211b85Ssemery	cat > "$object" <<EOF
147572f0806aSShawn Emerydn: $dn
1476bd211b85Ssemerychangetype: modify
1477bd211b85Ssemeryreplace: userAccountControl
1478bd211b85SsemeryuserAccountControl: $userAccountControl
1479bd211b85SsemeryEOF
1480bd211b85Ssemery	ldapmodify -h "$dc" $ldap_args -f "$object" >/dev/null 2>&1
1481bd211b85Ssemery	if [[ $? -ne 0 ]]; then
1482c386eb9cSShawn Emery		printf "$(gettext "ldapmodify failed to modify account attribute").\n" >&2
1483bd211b85Ssemery		error_message
1484bd211b85Ssemery	fi
1485bd211b85Ssemery
1486bd211b85Ssemery	# Setup a keytab file
1487bd211b85Ssemery	set -A args --
1488bd211b85Ssemery	for enctype in "${enctypes[@]}"
1489bd211b85Ssemery	do
1490bd211b85Ssemery		args[${#args[@]}]=-e
1491bd211b85Ssemery		args[${#args[@]}]=$enctype
1492bd211b85Ssemery	done
1493bd211b85Ssemery
1494bd211b85Ssemery	rm $new_keytab > /dev/null 2>&1
1495bd211b85Ssemery
1496bd211b85Ssemery	cat > "$object" <<EOF
149772f0806aSShawn Emerydn: $dn
1498bd211b85Ssemerychangetype: modify
1499bd211b85Ssemeryadd: servicePrincipalName
1500bd211b85SsemeryservicePrincipalName: nfs/${fqdn}
1501bd211b85SsemeryservicePrincipalName: HTTP/${fqdn}
1502bd211b85SsemeryservicePrincipalName: root/${fqdn}
1503c386eb9cSShawn EmeryservicePrincipalName: cifs/${fqdn}
150472f0806aSShawn EmeryservicePrincipalName: host/${upcase_nodename}
1505bd211b85SsemeryEOF
1506bd211b85Ssemery	ldapmodify -h "$dc" $ldap_args -f "$object" >/dev/null 2>&1
1507bd211b85Ssemery	if [[ $? -ne 0 ]]; then
1508c386eb9cSShawn Emery		printf "$(gettext "ldapmodify failed to modify account attribute").\n" >&2
1509bd211b85Ssemery		error_message
1510bd211b85Ssemery	fi
1511bd211b85Ssemery
1512c386eb9cSShawn Emery	#
1513c386eb9cSShawn Emery	# In Windows, unlike MIT based implementations we salt the keys with
151472f0806aSShawn Emery	# the UPN, which is based on the host/string15@realm elements, not
151572f0806aSShawn Emery	# with the individual SPN strings.
1516c386eb9cSShawn Emery	#
151772f0806aSShawn Emery	salt=host/${locase_nodename}.${domain}@${realm}
1518c386eb9cSShawn Emery
1519e1831dbbSShawn Emery	skeys=(host/${fqdn}@${realm} nfs/${fqdn}@${realm} HTTP/${fqdn}@${realm})
1520e1831dbbSShawn Emery	skeys+=(root/${fqdn}@${realm} cifs/${fqdn}@${realm})
1521e1831dbbSShawn Emery	skeys+=(${netbios_nodename}@${realm} host/${upcase_nodename}@${realm})
1522e1831dbbSShawn Emery	skeys+=(cifs/${upcase_nodename}@${realm})
1523c386eb9cSShawn Emery
1524e1831dbbSShawn Emery	ks_args="-n -s $salt -v $kvno -k $new_keytab ${args[@]}"
1525bd211b85Ssemery
1526e1831dbbSShawn Emery	for skey in ${skeys[@]}
1527e1831dbbSShawn Emery	do
1528e1831dbbSShawn Emery		printf "%s" "$newpw" | $KSETPW $ks_args $skey > /dev/null 2>&1
1529bd211b85Ssemery		if [[ $? -ne 0 ]]
1530bd211b85Ssemery		then
1531e1831dbbSShawn Emery			printf "$(gettext "Failed to set password").\n" >&2
1532bd211b85Ssemery			error_message
1533bd211b85Ssemery		fi
1534e1831dbbSShawn Emery	done
153572f0806aSShawn Emery
1536bd211b85Ssemery	doKRB5config
1537bd211b85Ssemery
1538bd211b85Ssemery	addDNSRR $dom
1539bd211b85Ssemery
1540bd211b85Ssemery	setSMB $dom $dc
1541bd211b85Ssemery
154272f0806aSShawn Emery	printf -- "---------------------------------------------------\n"
1543bd211b85Ssemery	printf "$(gettext "Setup COMPLETE").\n\n"
1544bd211b85Ssemery
1545bd211b85Ssemery	kdestroy -q 1>$TMP_FILE 2>&1
1546bd211b85Ssemery	rm -f $TMP_FILE
1547bd211b85Ssemery	rm -rf $TMPDIR > /dev/null 2>&1
1548bd211b85Ssemery
1549bd211b85Ssemery	exit 0
15507c478bd9Sstevel@tonic-gate}
15517c478bd9Sstevel@tonic-gate
15527c478bd9Sstevel@tonic-gate###########################
15537c478bd9Sstevel@tonic-gate#	Main section	  #
15547c478bd9Sstevel@tonic-gate###########################
15557c478bd9Sstevel@tonic-gate#
15567c478bd9Sstevel@tonic-gate# Set the Kerberos config file and some default strings/files
15577c478bd9Sstevel@tonic-gate#
1558bd211b85SsemeryKRB5_CONFIG_FILE=/etc/krb5/krb5.conf
1559bd211b85SsemeryKRB5_KEYTAB_FILE=/etc/krb5/krb5.keytab
1560bd211b85SsemeryRESOLV_CONF_FILE=/etc/resolv.conf
1561bd211b85Ssemery
1562bd211b85SsemeryKLOOKUP=/usr/lib/krb5/klookup;	check_bin $KLOOKUP
1563bd211b85SsemeryKSETPW=/usr/lib/krb5/ksetpw;	check_bin $KSETPW
1564bd211b85SsemeryKSMB=/usr/lib/krb5/ksmb;	check_bin $KSMB
1565bd211b85SsemeryKDYNDNS=/usr/lib/krb5/kdyndns;	check_bin $KDYNDNS
1566c48f4690SShawn EmeryKCONF=/usr/lib/krb5/kconf;	check_bin $KCONF
1567bd211b85Ssemery
1568bd211b85Ssemerydns_lookup=no
1569bd211b85Ssemeryask_fqdns=no
1570bd211b85Ssemeryadddns=no
1571ae5b046dSsemeryno_keytab=no
15727c478bd9Sstevel@tonic-gatecheckval=""
15737c478bd9Sstevel@tonic-gateprofile=""
1574bd211b85Ssemerytypeset -u realm
1575bd211b85Ssemerytypeset -l hostname KDC
15767c478bd9Sstevel@tonic-gate
1577bd211b85Ssemeryexport TMPDIR="/var/run/kclient"
15787c478bd9Sstevel@tonic-gate
1579bd211b85Ssemerymkdir $TMPDIR > /dev/null 2>&1
1580c386eb9cSShawn Emeryif [[ $? -ne 0 ]]; then
1581c386eb9cSShawn Emery	printf "\n$(gettext "Can not create directory: %s")\n\n" $TMPDIR >&2
1582c386eb9cSShawn Emery	exit 1
1583c386eb9cSShawn Emeryfi
15847c478bd9Sstevel@tonic-gate
1585bd211b85SsemeryTMP_FILE=$(mktemp -q -t kclient-tmpfile.XXXXXX)
1586bd211b85Ssemeryexport KRB5_CONFIG=$(mktemp -q -t kclient-krb5conf.XXXXXX)
1587ae5b046dSsemeryexport KRB5CCNAME=$(mktemp -q -t kclient-krb5ccache.XXXXXX)
1588bd211b85Ssemerynew_keytab=$(mktemp -q -t kclient-krb5keytab.XXXXXX)
1589bd211b85Ssemeryif [[ -z $TMP_FILE || -z $KRB5_CONFIG || -z $KRB5CCNAME || -z $new_keytab ]]
1590bd211b85Ssemerythen
1591c386eb9cSShawn Emery	printf "\n$(gettext "Can not create temporary files, exiting").\n\n" >&2
1592c386eb9cSShawn Emery	exit 1
15937c478bd9Sstevel@tonic-gatefi
15947c478bd9Sstevel@tonic-gate
15957c478bd9Sstevel@tonic-gate#
15967c478bd9Sstevel@tonic-gate# If we are interrupted, cleanup after ourselves
15977c478bd9Sstevel@tonic-gate#
1598bd211b85Ssemerytrap "exiting 1" HUP INT QUIT TERM
15997c478bd9Sstevel@tonic-gate
1600bd211b85Ssemeryif [[ -d /usr/bin ]]; then
1601bd211b85Ssemery	if [[ -d /usr/sbin ]]; then
16027c478bd9Sstevel@tonic-gate		PATH=/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:$PATH
16037c478bd9Sstevel@tonic-gate		export PATH
16047c478bd9Sstevel@tonic-gate	else
16057c478bd9Sstevel@tonic-gate		printf "\n$(gettext "Directory /usr/sbin not found, exiting").\n" >&2
16067c478bd9Sstevel@tonic-gate		exit 1
16077c478bd9Sstevel@tonic-gate	fi
16087c478bd9Sstevel@tonic-gateelse
16097c478bd9Sstevel@tonic-gate	printf "\n$(gettext "Directory /usr/bin not found, exiting").\n" >&2
16107c478bd9Sstevel@tonic-gate	exit 1
16117c478bd9Sstevel@tonic-gatefi
16127c478bd9Sstevel@tonic-gate
16137c478bd9Sstevel@tonic-gateprintf "\n$(gettext "Starting client setup")\n\n"
1614bd211b85Ssemeryprintf -- "---------------------------------------------------\n"
16157c478bd9Sstevel@tonic-gate
16167c478bd9Sstevel@tonic-gate#
16177c478bd9Sstevel@tonic-gate# Check for uid 0, disallow otherwise
16187c478bd9Sstevel@tonic-gate#
16197c478bd9Sstevel@tonic-gateid 1>$TMP_FILE 2>&1
1620bd211b85Ssemeryif [[ $? -eq 0 ]]; then
16217c478bd9Sstevel@tonic-gate	if egrep -s "uid=0\(root\)" $TMP_FILE; then
16227c478bd9Sstevel@tonic-gate		# uid is 0, go ahead ...
16237c478bd9Sstevel@tonic-gate		:
16247c478bd9Sstevel@tonic-gate	else
1625bd211b85Ssemery		printf "\n$(gettext "Administrative privileges are required to run this script, exiting").\n" >&2
16267c478bd9Sstevel@tonic-gate		error_message
16277c478bd9Sstevel@tonic-gate	fi
16287c478bd9Sstevel@tonic-gateelse
16297c478bd9Sstevel@tonic-gate	cat $TMP_FILE;
1630bd211b85Ssemery	printf "\n$(gettext "uid check failed, exiting").\n" >&2
16317c478bd9Sstevel@tonic-gate	error_message
16327c478bd9Sstevel@tonic-gatefi
16337c478bd9Sstevel@tonic-gate
1634bd211b85Ssemeryuname=$(uname -n)
1635bd211b85Ssemeryhostname=${uname%%.*}
16367c478bd9Sstevel@tonic-gate
16377c478bd9Sstevel@tonic-gate#
16387c478bd9Sstevel@tonic-gate# Process the command-line arguments (if any)
16397c478bd9Sstevel@tonic-gate#
16407c478bd9Sstevel@tonic-gateOPTIND=1
1641bd211b85Ssemerywhile getopts nD:Kp:R:k:a:c:d:f:h:m:s:T: OPTIONS
16427c478bd9Sstevel@tonic-gatedo
16437c478bd9Sstevel@tonic-gate	case $OPTIONS in
1644bd211b85Ssemery	    D) options="$options -D"
1645bd211b85Ssemery	       domain_list="$OPTARG"
1646bd211b85Ssemery	       ;;
1647bd211b85Ssemery	    K) options="$options -K"
1648bd211b85Ssemery	       no_keytab=yes
16497c478bd9Sstevel@tonic-gate	       ;;
16507c478bd9Sstevel@tonic-gate	    R) options="$options -R"
1651bd211b85Ssemery	       realm="$OPTARG"
1652bd211b85Ssemery	       checkval="REALM"; check_value $realm
16537c478bd9Sstevel@tonic-gate	       ;;
1654bd211b85Ssemery	    T) options="$options -T"
1655bd211b85Ssemery	       type="$OPTARG"
1656bd211b85Ssemery	       if [[ $type == ms_ad ]]; then
1657bd211b85Ssemery		msad=yes
1658bd211b85Ssemery		adddns=yes
1659bd211b85Ssemery	       else
1660bd211b85Ssemery		non_solaris=yes
1661bd211b85Ssemery		no_keytab=yes
1662bd211b85Ssemery	       fi
16637c478bd9Sstevel@tonic-gate	       ;;
16647c478bd9Sstevel@tonic-gate	    a) options="$options -a"
16657c478bd9Sstevel@tonic-gate	       ADMIN_PRINC="$OPTARG"
16667c478bd9Sstevel@tonic-gate	       checkval="ADMIN_PRINC"; check_value $ADMIN_PRINC
16677c478bd9Sstevel@tonic-gate	       ;;
16687c478bd9Sstevel@tonic-gate	    c) options="$options -c"
16697c478bd9Sstevel@tonic-gate	       filepath="$OPTARG"
16707c478bd9Sstevel@tonic-gate	       ;;
16717c478bd9Sstevel@tonic-gate	    d) options="$options -d"
16727c478bd9Sstevel@tonic-gate	       dnsarg="$OPTARG"
16737c478bd9Sstevel@tonic-gate	       checkval="DNS_OPTIONS"; check_value $dnsarg
16747c478bd9Sstevel@tonic-gate	       ;;
16757c478bd9Sstevel@tonic-gate	    f) options="$options -f"
16767c478bd9Sstevel@tonic-gate	       fqdnlist="$OPTARG"
1677bd211b85Ssemery 	       ;;
1678bd211b85Ssemery	    h) options="$options -h"
1679bd211b85Ssemery	       logical_hn="$OPTARG"
1680bd211b85Ssemery	       checkval="LOGICAL_HOSTNAME"; check_value $logical_hn
1681bd211b85Ssemery	       ;;
1682bd211b85Ssemery	    k) options="$options -k"
1683bd211b85Ssemery	       kdc_list="$OPTARG"
1684bd211b85Ssemery	       ;;
1685bd211b85Ssemery	    m) options="$options -m"
1686bd211b85Ssemery	       KDC="$OPTARG"
1687bd211b85Ssemery	       checkval="KDC"; check_value $KDC
16887c478bd9Sstevel@tonic-gate	       ;;
16897c478bd9Sstevel@tonic-gate	    n) options="$options -n"
16907c478bd9Sstevel@tonic-gate	       add_nfs=yes
16917c478bd9Sstevel@tonic-gate	       ;;
1692bd211b85Ssemery	    p) options="$options -p"
1693bd211b85Ssemery	       profile="$OPTARG"
1694bd211b85Ssemery	       read_profile $profile
1695bd211b85Ssemery	       ;;
1696bd211b85Ssemery	    s) options="$options -s"
1697bd211b85Ssemery	       svc_list="$OPTARG"
1698bd211b85Ssemery	       SVCs=${svc_list//,/ }
1699bd211b85Ssemery 	       ;;
17007c478bd9Sstevel@tonic-gate	    \?) usage
17017c478bd9Sstevel@tonic-gate	       ;;
17027c478bd9Sstevel@tonic-gate	    *) usage
17037c478bd9Sstevel@tonic-gate	       ;;
17047c478bd9Sstevel@tonic-gate	esac
17057c478bd9Sstevel@tonic-gatedone
17067c478bd9Sstevel@tonic-gate
17077c478bd9Sstevel@tonic-gate#correct argument count after options
17087c478bd9Sstevel@tonic-gateshift `expr $OPTIND - 1`
17097c478bd9Sstevel@tonic-gate
1710bd211b85Ssemeryif [[ -z $options ]]; then
17117c478bd9Sstevel@tonic-gate	:
17127c478bd9Sstevel@tonic-gateelse
1713bd211b85Ssemery	if [[ $# -ne 0 ]]; then
17147c478bd9Sstevel@tonic-gate		usage
17157c478bd9Sstevel@tonic-gate	fi
17167c478bd9Sstevel@tonic-gatefi
17177c478bd9Sstevel@tonic-gate
1718bd211b85Ssemery#
1719ae5b046dSsemery# Check to see if we will be a client of a MIT, Heimdal, Shishi, etc.
1720ae5b046dSsemery#
1721ae5b046dSsemeryif [[ -z $options ]]; then
1722ae5b046dSsemery	query "$(gettext "Is this a client of a non-Solaris KDC") ?"
1723ae5b046dSsemery	non_solaris=$answer
1724ae5b046dSsemery	if [[ $non_solaris == yes ]]; then
1725ae5b046dSsemery		printf "$(gettext "Which type of KDC is the server"):\n"
1726ae5b046dSsemery		printf "\t$(gettext "ms_ad: Microsoft Active Directory")\n"
1727ae5b046dSsemery		printf "\t$(gettext "mit: MIT KDC server")\n"
1728ae5b046dSsemery		printf "\t$(gettext "heimdal: Heimdal KDC server")\n"
1729ae5b046dSsemery		printf "\t$(gettext "shishi: Shishi KDC server")\n"
1730ae5b046dSsemery		printf "$(gettext "Enter required KDC type"): "
1731ae5b046dSsemery		read kdctype
1732ae5b046dSsemery		if [[ $kdctype == ms_ad ]]; then
1733ae5b046dSsemery			msad=yes
1734ae5b046dSsemery		elif [[ $kdctype == mit || $kdctype == heimdal || \
1735ae5b046dSsemery		    $kdctype == shishi ]]; then
1736ae5b046dSsemery			no_keytab=yes
1737ae5b046dSsemery		else
1738ae5b046dSsemery			printf "\n$(gettext "Invalid KDC type option, valid types are ms_ad, mit, heimdal, or shishi, exiting").\n" >&2
1739ae5b046dSsemery			error_message
1740ae5b046dSsemery		fi
1741ae5b046dSsemery	fi
1742ae5b046dSsemeryfi
1743ae5b046dSsemery
1744ae5b046dSsemery[[ $msad == yes ]] && join_domain
1745ae5b046dSsemery
1746ae5b046dSsemery#
1747bd211b85Ssemery# Check for /etc/resolv.conf
1748bd211b85Ssemery#
1749bd211b85Ssemeryif [[ -r $RESOLV_CONF_FILE ]]; then
1750bd211b85Ssemery	client_machine=`$KLOOKUP`
1751bd211b85Ssemery
1752bd211b85Ssemery	if [[ $? -ne 0 ]]; then
1753bd211b85Ssemery		if [[ $adddns == no ]]; then
1754bd211b85Ssemery			printf "\n$(gettext "%s does not have a DNS record and is required for Kerberos setup")\n" $hostname >&2
1755bd211b85Ssemery			error_message
1756bd211b85Ssemery		fi
1757bd211b85Ssemery
1758bd211b85Ssemery	else
1759bd211b85Ssemery		#
1760bd211b85Ssemery		# If client entry already exists then do not recreate it
1761bd211b85Ssemery		#
1762bd211b85Ssemery		adddns=no
1763bd211b85Ssemery
1764bd211b85Ssemery		hostname=${client_machine%%.*}
1765bd211b85Ssemery		domain=${client_machine#*.}
1766bd211b85Ssemery	fi
1767bd211b85Ssemery
1768bd211b85Ssemery	short_fqdn=${domain#*.*}
1769bd211b85Ssemery	short_fqdn=$(echo $short_fqdn | grep "\.")
1770bd211b85Ssemeryelse
1771bd211b85Ssemery	#
1772bd211b85Ssemery	# /etc/resolv.conf not present, exit ...
1773bd211b85Ssemery	#
1774bd211b85Ssemery	printf "\n$(gettext "%s does not exist and is required for Kerberos setup")\n" $RESOLV_CONF_FILE >&2
1775bd211b85Ssemery	printf "$(gettext "Refer to resolv.conf(4), exiting").\n" >&2
1776bd211b85Ssemery	error_message
1777bd211b85Ssemeryfi
1778bd211b85Ssemery
1779ae5b046dSsemerycheck_nss_conf || printf "$(gettext "/etc/nsswitch.conf does not make use of DNS for hosts and/or ipnodes").\n"
1780bd211b85Ssemery
1781bd211b85Ssemery[[ -n $fqdnlist ]] && verify_fqdnlist "$fqdnlist"
1782bd211b85Ssemery
1783ae5b046dSsemeryif [[ -z $dnsarg && (-z $options || -z $filepath) ]]; then
17847c478bd9Sstevel@tonic-gate	query "$(gettext "Do you want to use DNS for kerberos lookups") ?"
1785bd211b85Ssemery	if [[ $answer == yes ]]; then
1786bd211b85Ssemery		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"
1787bd211b85Ssemery		printf "\n$(gettext "Enter required DNS option"): "
17887c478bd9Sstevel@tonic-gate		read dnsarg
17897c478bd9Sstevel@tonic-gate		checkval="DNS_OPTIONS"; check_value $dnsarg
17907c478bd9Sstevel@tonic-gate		set_dns_value $dnsarg
17917c478bd9Sstevel@tonic-gate	fi
17927c478bd9Sstevel@tonic-gateelse
1793ae5b046dSsemery	[[ -z $dnsarg ]] && dnsarg=none
17947c478bd9Sstevel@tonic-gate	set_dns_value $dnsarg
17957c478bd9Sstevel@tonic-gatefi
17967c478bd9Sstevel@tonic-gate
1797bd211b85Ssemeryif [[ -n $kdc_list ]]; then
1798bd211b85Ssemery	if [[ -z $KDC ]]; then
1799bd211b85Ssemery		for kdc in $kdc_list; do
1800bd211b85Ssemery			break
1801bd211b85Ssemery		done
1802bd211b85Ssemery		KDC="$kdc"
18037c478bd9Sstevel@tonic-gate	fi
1804bd211b85Ssemeryfi
1805bd211b85Ssemery
1806ae5b046dSsemeryif [[ -z $realm ]]; then
1807bd211b85Ssemery	printf "$(gettext "Enter the Kerberos realm"): "
1808bd211b85Ssemery	read realm
1809bd211b85Ssemery	checkval="REALM"; check_value $realm
1810bd211b85Ssemeryfi
1811ae5b046dSsemeryif [[ -z $KDC ]]; then
1812bd211b85Ssemery	printf "$(gettext "Specify the master KDC hostname for the above realm"): "
18137c478bd9Sstevel@tonic-gate	read KDC
18147c478bd9Sstevel@tonic-gate	checkval="KDC"; check_value $KDC
18157c478bd9Sstevel@tonic-gatefi
18167c478bd9Sstevel@tonic-gate
1817bd211b85SsemeryFKDC=`$KLOOKUP $KDC`
18187c478bd9Sstevel@tonic-gate
18197c478bd9Sstevel@tonic-gate#
18207c478bd9Sstevel@tonic-gate# Ping to see if the kdc is alive !
18217c478bd9Sstevel@tonic-gate#
1822bd211b85Ssemeryping_check $FKDC "KDC"
18237c478bd9Sstevel@tonic-gate
1824ae5b046dSsemeryif [[ -z $kdc_list && (-z $options || -z $filepath) ]]; then
1825ae5b046dSsemery	query "$(gettext "Do you have any slave KDC(s)") ?"
1826ae5b046dSsemery	if [[ $answer == yes ]]; then
1827ae5b046dSsemery		printf "$(gettext "Enter a comma-separated list of slave KDC host names"): "
1828ae5b046dSsemery		read kdc_list
1829ae5b046dSsemery	fi
1830ae5b046dSsemeryfi
1831ae5b046dSsemery
1832ae5b046dSsemery[[ -n $kdc_list ]] && verify_kdcs "$kdc_list"
1833ae5b046dSsemery
1834bd211b85Ssemery#
1835bd211b85Ssemery# Check to see if we will have a dynamic presence in the realm
1836bd211b85Ssemery#
1837bd211b85Ssemeryif [[ -z $options ]]; then
1838bd211b85Ssemery	query "$(gettext "Will this client need service keys") ?"
1839bd211b85Ssemery	if [[ $answer == no ]]; then
1840bd211b85Ssemery		no_keytab=yes
1841bd211b85Ssemery	fi
1842bd211b85Ssemeryfi
1843bd211b85Ssemery
1844bd211b85Ssemery#
1845bd211b85Ssemery# Check to see if we are configuring the client to use a logical host name
1846bd211b85Ssemery# of a cluster environment
1847bd211b85Ssemery#
1848bd211b85Ssemeryif [[ -z $options ]]; then
1849bd211b85Ssemery	query "$(gettext "Is this client a member of a cluster that uses a logical host name") ?"
1850bd211b85Ssemery	if [[ $answer == yes ]]; then
1851bd211b85Ssemery		printf "$(gettext "Specify the logical hostname of the cluster"): "
1852bd211b85Ssemery		read logical_hn
1853bd211b85Ssemery		checkval="LOGICAL_HOSTNAME"; check_value $logical_hn
1854bd211b85Ssemery		setup_lhn
1855bd211b85Ssemery	fi
1856bd211b85Ssemeryfi
1857bd211b85Ssemery
1858ae5b046dSsemeryif [[ -n $domain_list && (-z $options || -z $filepath) ]]; then
1859bd211b85Ssemery	query "$(gettext "Do you have multiple domains/hosts to map to realm %s"
1860bd211b85Ssemery) ?" $realm
1861bd211b85Ssemery	if [[ $answer == yes ]]; then
1862ae5b046dSsemery		printf "$(gettext "Enter a comma-separated list of domain/hosts
1863bd211b85Ssemeryto map to the default realm"): "
1864bd211b85Ssemery		read domain_list
1865bd211b85Ssemery	fi
1866bd211b85Ssemeryfi
1867bd211b85Ssemery[[ -n domain_list ]] && domain_list=${domain_list//,/ }
18687c478bd9Sstevel@tonic-gate
18697c478bd9Sstevel@tonic-gate#
18707c478bd9Sstevel@tonic-gate# Start writing up the krb5.conf file, save the existing one
18717c478bd9Sstevel@tonic-gate# if already present
18727c478bd9Sstevel@tonic-gate#
18737c478bd9Sstevel@tonic-gatewriteup_krb5_conf
18747c478bd9Sstevel@tonic-gate
18757c478bd9Sstevel@tonic-gate#
1876bd211b85Ssemery# Is this client going to use krb-nfs?  If so then we need to at least
1877bd211b85Ssemery# uncomment the krb5* sec flavors in nfssec.conf.
18787c478bd9Sstevel@tonic-gate#
1879bd211b85Ssemeryif [[ -z $options ]]; then
18807c478bd9Sstevel@tonic-gate	query "$(gettext "Do you plan on doing Kerberized nfs") ?"
18817c478bd9Sstevel@tonic-gate	add_nfs=$answer
18827c478bd9Sstevel@tonic-gatefi
18837c478bd9Sstevel@tonic-gate
1884bd211b85Ssemeryif [[ $add_nfs == yes ]]; then
18857c478bd9Sstevel@tonic-gate	modify_nfssec_conf
18867c478bd9Sstevel@tonic-gate
18877c478bd9Sstevel@tonic-gate	#
1888bd211b85Ssemery	# We also want to enable gss as we now live in a SBD world
18897c478bd9Sstevel@tonic-gate	#
1890bd211b85Ssemery	svcadm enable svc:/network/rpc/gss:default
1891bd211b85Ssemery	[[ $? -ne 0 ]] && printf "$(gettext "Warning: could not enable gss service").\n"
1892bd211b85Ssemeryfi
1893bd211b85Ssemery
1894bd211b85Ssemeryif [[ -z $options ]]; then
1895bd211b85Ssemery	query "$(gettext "Do you want to update /etc/pam.conf") ?"
1896bd211b85Ssemery	if [[ $answer == yes ]]; then
1897bd211b85Ssemery		printf "$(gettext "Enter a list of PAM service names in the following format: service:{first|only|optional}[,..]"): "
1898bd211b85Ssemery		read svc_list
1899bd211b85Ssemery		SVCs=${svc_list//,/ }
1900bd211b85Ssemery	fi
1901bd211b85Ssemeryfi
1902bd211b85Ssemery[[ -n $svc_list ]] && update_pam_conf
1903bd211b85Ssemery
1904bd211b85Ssemery#
1905bd211b85Ssemery# Copy over krb5.conf master copy from filepath
1906bd211b85Ssemery#
1907bd211b85Ssemeryif [[ -z $options || -z $filepath ]]; then
19087c478bd9Sstevel@tonic-gate	query "$(gettext "Do you want to copy over the master krb5.conf file") ?"
1909bd211b85Ssemery	if [[ $answer == yes ]]; then
1910bd211b85Ssemery		printf "$(gettext "Enter the pathname of the file to be copied"): "
19117c478bd9Sstevel@tonic-gate		read filepath
19127c478bd9Sstevel@tonic-gate	fi
19137c478bd9Sstevel@tonic-gatefi
19147c478bd9Sstevel@tonic-gate
1915ae5b046dSsemeryif [[ -n $filepath && -r $filepath ]]; then
1916ae5b046dSsemery	cp $filepath $KRB5_CONFIG
1917bd211b85Ssemery	if [[ $? -eq 0 ]]; then
1918ae5b046dSsemery		printf "$(gettext "Copied %s to %s").\n" $filepath $KRB5_CONFIG
19197c478bd9Sstevel@tonic-gate	else
1920ae5b046dSsemery		printf "$(gettext "Copy of %s failed, exiting").\n" $filepath >&2
19217c478bd9Sstevel@tonic-gate		error_message
19227c478bd9Sstevel@tonic-gate	fi
1923ae5b046dSsemeryelif [[ -n $filepath ]]; then
1924bd211b85Ssemery	printf "\n$(gettext "%s not found, exiting").\n" $filepath >&2
19257c478bd9Sstevel@tonic-gate	error_message
19267c478bd9Sstevel@tonic-gatefi
1927ae5b046dSsemery
1928ae5b046dSsemerydoKRB5config
19297c478bd9Sstevel@tonic-gate
1930bd211b85Ssemery#
1931bd211b85Ssemery# Populate any service keys needed for the client in the keytab file
1932bd211b85Ssemery#
1933ae5b046dSsemeryif [[ $no_keytab != yes ]]; then
1934ae5b046dSsemery	setup_keytab
1935ae5b046dSsemeryelse
1936ae5b046dSsemery	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
1937ae5b046dSsemery	printf "$(gettext "Client will also not be able to host services that use Kerberos").\n"
1938ae5b046dSsemeryfi
1939bd211b85Ssemery
1940bd211b85Ssemeryprintf -- "\n---------------------------------------------------\n"
1941bd211b85Ssemeryprintf "$(gettext "Setup COMPLETE").\n\n"
19427c478bd9Sstevel@tonic-gate
19437c478bd9Sstevel@tonic-gate#
1944bd211b85Ssemery# If we have configured the client in a cluster we need to remind the user
1945bd211b85Ssemery# to propagate the keytab and configuration files to the other members.
19467c478bd9Sstevel@tonic-gate#
1947bd211b85Ssemeryif [[ -n $logical_hn ]]; then
1948bd211b85Ssemery	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"
1949bd211b85Ssemeryfi
1950bd211b85Ssemery
1951bd211b85Ssemery#
1952bd211b85Ssemery# Cleanup.
1953bd211b85Ssemery#
1954bd211b85Ssemerykdestroy -q 1>$TMP_FILE 2>&1
19557c478bd9Sstevel@tonic-gaterm -f $TMP_FILE
1956bd211b85Ssemeryrm -rf $TMPDIR > /dev/null 2>&1
19577c478bd9Sstevel@tonic-gateexit 0
1958