xref: /titanic_50/usr/src/cmd/krb5/kadmin/kclient/kclient.sh (revision 5e11cc3944e416541ce1ee9bae5126d0cce3f661)
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.
23f7dbdfc7SMarcel Telka# Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
24*5e11cc39SToomas Soome# Copyright 2016 Toomas Soome <tsoome@me.com>
257c478bd9Sstevel@tonic-gate#
267c478bd9Sstevel@tonic-gate# This script is used to setup the Kerberos client by
277c478bd9Sstevel@tonic-gate# supplying information about the Kerberos realm and kdc.
287c478bd9Sstevel@tonic-gate#
297c478bd9Sstevel@tonic-gate# The kerberos configuration file (/etc/krb5/krb5.conf) would
307c478bd9Sstevel@tonic-gate# be generated and local host's keytab file setup. The script
317c478bd9Sstevel@tonic-gate# can also optionally setup the system to do kerberized nfs and
327c478bd9Sstevel@tonic-gate# bringover a master krb5.conf copy from a specified location.
3372f0806aSShawn Emery#
347c478bd9Sstevel@tonic-gate
35bd211b85Ssemeryfunction cleanup {
36bd211b85Ssemery
37c386eb9cSShawn Emery	kdestroy -q > $TMP_FILE 2>&1
38bd211b85Ssemery	rm -r $TMPDIR > /dev/null 2>&1
39bd211b85Ssemery
40c386eb9cSShawn Emery	exit $1
41bd211b85Ssemery}
42bd211b85Ssemeryfunction exiting {
43bd211b85Ssemery
44bd211b85Ssemery        printf "\n$(gettext "Exiting setup, nothing changed").\n\n"
45bd211b85Ssemery
46bd211b85Ssemery	cleanup $1
477c478bd9Sstevel@tonic-gate}
487c478bd9Sstevel@tonic-gate
49bd211b85Ssemeryfunction error_message {
50bd211b85Ssemery
51c386eb9cSShawn Emery        printf -- "---------------------------------------------------\n" >&2
52c386eb9cSShawn Emery        printf "$(gettext "Setup FAILED").\n\n" >&2
53bd211b85Ssemery
54bd211b85Ssemery        cleanup 1
55bd211b85Ssemery}
56bd211b85Ssemery
57bd211b85Ssemeryfunction check_bin {
58bd211b85Ssemery
59bd211b85Ssemery	typeset bin=$1
60bd211b85Ssemery
61bd211b85Ssemery	if [[ ! -x $bin ]]; then
62c386eb9cSShawn Emery		printf "$(gettext "Could not access/execute %s").\n" $bin >&2
637c478bd9Sstevel@tonic-gate		error_message
647c478bd9Sstevel@tonic-gate	fi
657c478bd9Sstevel@tonic-gate}
667c478bd9Sstevel@tonic-gate
67bd211b85Ssemeryfunction cannot_create {
68bd211b85Ssemery	typeset filename="$1"
69bd211b85Ssemery	typeset stat="$2"
70bd211b85Ssemery
71bd211b85Ssemery	if [[ $stat -ne 0 ]]; then
72bd211b85Ssemery		printf "\n$(gettext "Can not create/edit %s, exiting").\n" $filename >&2
73bd211b85Ssemery		error_message
74bd211b85Ssemery	fi
75bd211b85Ssemery}
76bd211b85Ssemery
77bd211b85Ssemeryfunction update_pam_conf {
78bd211b85Ssemery	typeset PAM TPAM service
79bd211b85Ssemery
80bd211b85Ssemery	PAM=/etc/pam.conf
81bd211b85Ssemery
82bd211b85Ssemery	TPAM=$(mktemp -q -t kclient-pamconf.XXXXXX)
83bd211b85Ssemery	if [[ -z $TPAM ]]; then
84bd211b85Ssemery		printf "\n$(gettext "Can not create temporary file, exiting").\n" >&2
85bd211b85Ssemery		error_message
86bd211b85Ssemery	fi
87bd211b85Ssemery
88bd211b85Ssemery	cp $PAM $TPAM >/dev/null 2>&1
89bd211b85Ssemery
90bd211b85Ssemery	printf "$(gettext "Configuring %s").\n\n" $PAM
91bd211b85Ssemery
92bd211b85Ssemery	for service in $SVCs; do
93bd211b85Ssemery		svc=${service%:*}
94bd211b85Ssemery		auth_type=${service#*:}
95bd211b85Ssemery		if egrep -s "^$svc[ 	][ 	]*auth.*pam_krb5*" $TPAM; then
96ae5b046dSsemery			printf "$(gettext "The %s service is already configured for pam_krb5, please merge this service in %s").\n\n" $svc $PAM >&2
97bd211b85Ssemery			continue
98bd211b85Ssemery		else
99bd211b85Ssemery			exec 3>>$TPAM
100ae5b046dSsemery			printf "\n$svc\tauth include\t\tpam_krb5_$auth_type\n" 1>&3
101bd211b85Ssemery		fi
102bd211b85Ssemery	done
103bd211b85Ssemery
104bd211b85Ssemery	cp $TPAM $PAM > /dev/null 2>&1
105bd211b85Ssemery
106bd211b85Ssemery	rm $TPAM > /dev/null 2>&1
107bd211b85Ssemery}
108bd211b85Ssemery
109bd211b85Ssemeryfunction modify_nfssec_conf {
110bd211b85Ssemery	typeset NFSSEC_FILE="/etc/nfssec.conf"
111bd211b85Ssemery
112bd211b85Ssemery	if [[ -r $NFSSEC_FILE ]]; then
1137c478bd9Sstevel@tonic-gate		cat $NFSSEC_FILE > $NFSSEC_FILE.sav
1147c478bd9Sstevel@tonic-gate		cannot_create $NFSSEC_FILE.sav $?
1157c478bd9Sstevel@tonic-gate	fi
1167c478bd9Sstevel@tonic-gate
1177c478bd9Sstevel@tonic-gate	cat $NFSSEC_FILE > $TMP_FILE
1187c478bd9Sstevel@tonic-gate	cannot_create $TMP_FILE $?
1197c478bd9Sstevel@tonic-gate
1207c478bd9Sstevel@tonic-gate	if grep -s "#krb5" $NFSSEC_FILE > /dev/null 2>&1; then
1217c478bd9Sstevel@tonic-gate		sed "s%^#krb5%krb5%" $TMP_FILE >$NFSSEC_FILE
1227c478bd9Sstevel@tonic-gate		cannot_create $NFSSEC_FILE $?
1237c478bd9Sstevel@tonic-gate	fi
1247c478bd9Sstevel@tonic-gate}
1257c478bd9Sstevel@tonic-gate
126bd211b85Ssemeryfunction call_kadmin {
1277c478bd9Sstevel@tonic-gate	typeset svc="$1"
1287c478bd9Sstevel@tonic-gate	typeset bool1 bool2 bool3 bool4
129bd211b85Ssemery	typeset service_princ getprincsubcommand anksubcommand ktaddsubcommand
130bd211b85Ssemery	typeset ktremsubcommand
1317c478bd9Sstevel@tonic-gate
1327c478bd9Sstevel@tonic-gate	for listentry in $fqdnlist; do
1337c478bd9Sstevel@tonic-gate
1347c478bd9Sstevel@tonic-gate	# Reset conditional vars to 1
1357c478bd9Sstevel@tonic-gate	bool1=1; bool2=1; bool3=1; bool4=1
1367c478bd9Sstevel@tonic-gate
137bd211b85Ssemery	service_princ=$(echo "${svc}/${listentry}")
1387c478bd9Sstevel@tonic-gate	getprincsubcommand="getprinc $service_princ"
1397c478bd9Sstevel@tonic-gate	anksubcommand="addprinc -randkey $service_princ"
1407c478bd9Sstevel@tonic-gate	ktaddsubcommand="ktadd $service_princ"
141bd211b85Ssemery	ktremsubcommand="ktrem $service_princ all"
1427c478bd9Sstevel@tonic-gate
143bd211b85Ssemery	kadmin -c $KRB5CCNAME -q "$getprincsubcommand" 1>$TMP_FILE 2>&1
1447c478bd9Sstevel@tonic-gate
145ae5b046dSsemery	egrep -s "$(gettext "get_principal: Principal does not exist")" $TMP_FILE
1467c478bd9Sstevel@tonic-gate	bool1=$?
147ae5b046dSsemery	egrep -s "$(gettext "get_principal: Operation requires ``get")" $TMP_FILE
1487c478bd9Sstevel@tonic-gate	bool2=$?
1497c478bd9Sstevel@tonic-gate
1507c478bd9Sstevel@tonic-gate	if [[ $bool1 -eq 0 || $bool2 -eq 0 ]]; then
151bd211b85Ssemery		kadmin -c $KRB5CCNAME -q "$anksubcommand" 1>$TMP_FILE 2>&1
1527c478bd9Sstevel@tonic-gate
153ae5b046dSsemery		egrep -s "$(gettext "add_principal: Principal or policy already exists while creating \"$service_princ@$realm\".")" $TMP_FILE
1547c478bd9Sstevel@tonic-gate		bool3=$?
1557c478bd9Sstevel@tonic-gate
156ae5b046dSsemery		egrep -s "$(gettext "Principal \"$service_princ@$realm\" created.")" $TMP_FILE
1577c478bd9Sstevel@tonic-gate		bool4=$?
1587c478bd9Sstevel@tonic-gate
1597c478bd9Sstevel@tonic-gate		if [[ $bool3 -eq 0 || $bool4 -eq 0 ]]; then
1607c478bd9Sstevel@tonic-gate			printf "$(gettext "%s entry ADDED to KDC database").\n" $service_princ
1617c478bd9Sstevel@tonic-gate		else
1627c478bd9Sstevel@tonic-gate			cat $TMP_FILE;
163bd211b85Ssemery			printf "\n$(gettext "kadmin: add_principal of %s failed, exiting").\n" $service_princ >&2
1647c478bd9Sstevel@tonic-gate			error_message
1657c478bd9Sstevel@tonic-gate		fi
1667c478bd9Sstevel@tonic-gate	else
167bd211b85Ssemery		printf "$(gettext "%s entry already exists in KDC database").\n" $service_princ >&2
1687c478bd9Sstevel@tonic-gate	fi
1697c478bd9Sstevel@tonic-gate
1707c478bd9Sstevel@tonic-gate	klist -k 1>$TMP_FILE 2>&1
171bd211b85Ssemery	egrep -s "$service_princ@$realm" $TMP_FILE
172bd211b85Ssemery	if [[ $? -eq 0 ]]; then
173bd211b85Ssemery		printf "$(gettext "%s entry already present in keytab").\n" $service_princ >&2
174bd211b85Ssemery		# Don't care is this succeeds or not, just need to replace old
175bd211b85Ssemery		# entries as it is assummed that the client is reinitialized
176bd211b85Ssemery		kadmin -c $KRB5CCNAME -q "$ktremsubcommand" 1>$TMP_FILE 2>&1
177bd211b85Ssemery	fi
178bd211b85Ssemery
179bd211b85Ssemery	kadmin -c $KRB5CCNAME -q "$ktaddsubcommand" 1>$TMP_FILE 2>&1
180ae5b046dSsemery	egrep -s "$(gettext "added to keytab WRFILE:$KRB5_KEYTAB_FILE.")" $TMP_FILE
181bd211b85Ssemery	if [[ $? -ne 0 ]]; then
1827c478bd9Sstevel@tonic-gate		cat $TMP_FILE;
183bd211b85Ssemery		printf "\n$(gettext "kadmin: ktadd of %s failed, exiting").\n" $service_princ >&2
1847c478bd9Sstevel@tonic-gate		error_message
1857c478bd9Sstevel@tonic-gate	else
1867c478bd9Sstevel@tonic-gate		printf "$(gettext "%s entry ADDED to keytab").\n" $service_princ
1877c478bd9Sstevel@tonic-gate	fi
1887c478bd9Sstevel@tonic-gate
1897c478bd9Sstevel@tonic-gate	done
1907c478bd9Sstevel@tonic-gate}
1917c478bd9Sstevel@tonic-gate
192bd211b85Ssemeryfunction writeup_krb5_conf {
193bd211b85Ssemery	typeset dh
1947c478bd9Sstevel@tonic-gate
195bd211b85Ssemery	printf "\n$(gettext "Setting up %s").\n\n" $KRB5_CONFIG_FILE
1967c478bd9Sstevel@tonic-gate
197bd211b85Ssemery	exec 3>$KRB5_CONFIG
198bd211b85Ssemery	if [[ $? -ne 0 ]]; then
199c386eb9cSShawn Emery		printf "\n$(gettext "Can not write to %s, exiting").\n" $KRB5_CONFIG >&2
2007c478bd9Sstevel@tonic-gate		error_message
2017c478bd9Sstevel@tonic-gate	fi
2027c478bd9Sstevel@tonic-gate
203bd211b85Ssemery	printf "[libdefaults]\n" 1>&3
204bd211b85Ssemery	if [[ $no_keytab == yes ]]; then
205bd211b85Ssemery		printf "\tverify_ap_req_nofail = false\n" 1>&3
206bd211b85Ssemery	fi
207bd211b85Ssemery	if [[ $dns_lookup == yes ]]; then
208bd211b85Ssemery	    printf "\t$dnsarg = on\n" 1>&3
209bd211b85Ssemery	    if [[ $dnsarg == dns_lookup_kdc ]]; then
210bd211b85Ssemery		printf "\tdefault_realm = $realm\n" 1>&3
211bd211b85Ssemery		printf "\n[domain_realm]\n" 1>&3
212bd211b85Ssemery		if [[ -n $fkdc_list ]]; then
213bd211b85Ssemery			for kdc in $fkdc_list; do
214bd211b85Ssemery				printf "\t$kdc = $realm\n" 1>&3
215bd211b85Ssemery			done
216bd211b85Ssemery		fi
217bd211b85Ssemery		printf "\t$FKDC = $realm\n" 1>&3
218bd211b85Ssemery		printf "\t$client_machine = $realm\n" 1>&3
219bd211b85Ssemery		if [[ -z $short_fqdn ]]; then
220bd211b85Ssemery			printf "\t.$domain = $realm\n\n" 1>&3
2217c478bd9Sstevel@tonic-gate		else
222bd211b85Ssemery			printf "\t.$short_fqdn = $realm\n\n" 1>&3
223bd211b85Ssemery		fi
224bd211b85Ssemery		if [[ -n $domain_list ]]; then
225bd211b85Ssemery			for dh in $domain_list; do
226bd211b85Ssemery				printf "\t$dh = $realm\n" 1>&3
227bd211b85Ssemery			done
228bd211b85Ssemery		fi
229bd211b85Ssemery	    else
230bd211b85Ssemery		if [[ $dnsarg = dns_lookup_realm ]]; then
231ae5b046dSsemery		    printf "\tdefault_realm = $realm\n" 1>&3
232bd211b85Ssemery		    printf "\n[realms]\n" 1>&3
233bd211b85Ssemery		    printf "\t$realm = {\n" 1>&3
234bd211b85Ssemery		    if [[ -n $kdc_list ]]; then
235bd211b85Ssemery			for kdc in $kdc_list; do
236bd211b85Ssemery				printf "\t\tkdc = $kdc\n" 1>&3
237bd211b85Ssemery			done
2387c478bd9Sstevel@tonic-gate		    else
239bd211b85Ssemery		    	printf "\t\tkdc = $KDC\n" 1>&3
240bd211b85Ssemery		    fi
241bd211b85Ssemery		    printf "\t\tadmin_server = $KDC\n" 1>&3
242bd211b85Ssemery		    if [[ $non_solaris == yes ]]; then
243bd211b85Ssemery			printf "\n\t\tkpasswd_protocol = SET_CHANGE\n" 1>&3
244bd211b85Ssemery		    fi
245bd211b85Ssemery		    printf "\t}\n\n" 1>&3
246bd211b85Ssemery		else
247ae5b046dSsemery		    printf "\tdefault_realm = $realm\n\n" 1>&3
2487c478bd9Sstevel@tonic-gate		fi
2497c478bd9Sstevel@tonic-gate	    fi
2507c478bd9Sstevel@tonic-gate	else
251bd211b85Ssemery	    printf "\tdefault_realm = $realm\n\n" 1>&3
2527c478bd9Sstevel@tonic-gate
253bd211b85Ssemery	    printf "[realms]\n" 1>&3
254bd211b85Ssemery	    printf "\t$realm = {\n" 1>&3
255bd211b85Ssemery	    if [[ -n $kdc_list ]]; then
256bd211b85Ssemery		for kdc in $kdc_list; do
257bd211b85Ssemery			printf "\t\tkdc = $kdc\n" 1>&3
258bd211b85Ssemery		done
259bd211b85Ssemery	    else
260bd211b85Ssemery	    	printf "\t\tkdc = $KDC\n" 1>&3
261bd211b85Ssemery	    fi
262bd211b85Ssemery	    printf "\t\tadmin_server = $KDC\n" 1>&3
263bd211b85Ssemery	    if [[ $non_solaris == yes ]]; then
264bd211b85Ssemery	    	printf "\n\t\tkpasswd_protocol = SET_CHANGE\n" 1>&3
265bd211b85Ssemery	    fi
266bd211b85Ssemery	    printf "\t}\n\n" 1>&3
2677c478bd9Sstevel@tonic-gate
268bd211b85Ssemery	    printf "[domain_realm]\n" 1>&3
269bd211b85Ssemery	    if [[ -n $fkdc_list ]]; then
270bd211b85Ssemery		for kdc in $fkdc_list; do
271bd211b85Ssemery			printf "\t$kdc = $realm\n" 1>&3
272bd211b85Ssemery		done
273bd211b85Ssemery	    fi
274bd211b85Ssemery	    printf "\t$FKDC = $realm\n" 1>&3
275bd211b85Ssemery	    printf "\t$client_machine = $realm\n" 1>&3
276bd211b85Ssemery	    if [[ -z $short_fqdn ]]; then
277bd211b85Ssemery		printf "\t.$domain = $realm\n\n" 1>&3
278bd211b85Ssemery	    else
279bd211b85Ssemery		printf "\t.$short_fqdn = $realm\n\n" 1>&3
280bd211b85Ssemery	    fi
281bd211b85Ssemery	    if [[ -n $domain_list ]]; then
282bd211b85Ssemery		for dh in $domain_list; do
283bd211b85Ssemery			printf "\t$dh = $realm\n" 1>&3
284bd211b85Ssemery		done
285bd211b85Ssemery	    fi
2867c478bd9Sstevel@tonic-gate	fi
2877c478bd9Sstevel@tonic-gate
288bd211b85Ssemery	printf "[logging]\n" 1>&3
289bd211b85Ssemery	printf "\tdefault = FILE:/var/krb5/kdc.log\n" 1>&3
290bd211b85Ssemery	printf "\tkdc = FILE:/var/krb5/kdc.log\n" 1>&3
291bd211b85Ssemery	printf "\tkdc_rotate = {\n\t\tperiod = 1d\n\t\tversions = 10\n\t}\n\n" 1>&3
2927c478bd9Sstevel@tonic-gate
293bd211b85Ssemery	printf "[appdefaults]\n" 1>&3
294bd211b85Ssemery	printf "\tkinit = {\n\t\trenewable = true\n\t\tforwardable = true\n" 1>&3
295bd211b85Ssemery	if [[ $no_keytab == yes ]]; then
296bd211b85Ssemery		printf "\t\tno_addresses = true\n" 1>&3
297bd211b85Ssemery	fi
298bd211b85Ssemery	printf "\t}\n" 1>&3
2997c478bd9Sstevel@tonic-gate}
3007c478bd9Sstevel@tonic-gate
301bd211b85Ssemeryfunction ask {
302bd211b85Ssemery	typeset question=$1
303bd211b85Ssemery	typeset default_answer=$2
304bd211b85Ssemery
305bd211b85Ssemery	if [[ -z $default_answer ]]; then
306bd211b85Ssemery		printf "$question :"
3077c478bd9Sstevel@tonic-gate	else
308bd211b85Ssemery		printf "$question [$default_answer]: "
3097c478bd9Sstevel@tonic-gate	fi
3107c478bd9Sstevel@tonic-gate	read answer
3117c478bd9Sstevel@tonic-gate	test -z "$answer" && answer="$default_answer"
3127c478bd9Sstevel@tonic-gate}
3137c478bd9Sstevel@tonic-gate
314bd211b85Ssemeryfunction yesno {
3157c478bd9Sstevel@tonic-gate	typeset question="$1"
316bd211b85Ssemery
317bd211b85Ssemery	answer=
318bd211b85Ssemery	yn=`printf "$(gettext "y/n")"`
319bd211b85Ssemery	y=`printf "$(gettext "y")"`
320bd211b85Ssemery	n=`printf "$(gettext "n")"`
321bd211b85Ssemery	yes=`printf "$(gettext "yes")"`
322bd211b85Ssemery	no=`printf "$(gettext "no")"`
323bd211b85Ssemery
324bd211b85Ssemery	while [[ -z $answer ]]; do
325bd211b85Ssemery		ask "$question" $yn
326bd211b85Ssemery		case $answer in
327bd211b85Ssemery			$y|$yes)	answer=yes;;
328bd211b85Ssemery			$n|$no)		answer=no;;
329bd211b85Ssemery			*)		answer=;;
3307c478bd9Sstevel@tonic-gate		esac
3317c478bd9Sstevel@tonic-gate	done
3327c478bd9Sstevel@tonic-gate}
3337c478bd9Sstevel@tonic-gate
334bd211b85Ssemeryfunction query {
3357c478bd9Sstevel@tonic-gate	yesno "$*"
336bd211b85Ssemery
337bd211b85Ssemery	if [[ $answer == no ]]; then
3387c478bd9Sstevel@tonic-gate		printf "\t$(gettext "No action performed").\n"
3397c478bd9Sstevel@tonic-gate	fi
3407c478bd9Sstevel@tonic-gate}
3417c478bd9Sstevel@tonic-gate
3427c478bd9Sstevel@tonic-gate
343bd211b85Ssemeryfunction read_profile {
3447c478bd9Sstevel@tonic-gate	typeset param value
3457c478bd9Sstevel@tonic-gate	typeset file="$1"
346bd211b85Ssemery
3477c478bd9Sstevel@tonic-gate	if [[ ! -d $file && -r $file ]]; then
3487c478bd9Sstevel@tonic-gate		while read param value
3497c478bd9Sstevel@tonic-gate		do
350bd211b85Ssemery			case $param in
351bd211b85Ssemery			REALM)  if [[ -z $realm ]]; then
352bd211b85Ssemery					realm="$value"
353bd211b85Ssemery					checkval="REALM"; check_value $realm
3547c478bd9Sstevel@tonic-gate				fi
3557c478bd9Sstevel@tonic-gate				;;
356bd211b85Ssemery			KDC)    if [[ -z $KDC ]]; then
3577c478bd9Sstevel@tonic-gate					KDC="$value"
3587c478bd9Sstevel@tonic-gate					checkval="KDC"; check_value $KDC
3597c478bd9Sstevel@tonic-gate				fi
3607c478bd9Sstevel@tonic-gate				;;
361bd211b85Ssemery			ADMIN)  if [[ -z $ADMIN_PRINC ]]; then
3627c478bd9Sstevel@tonic-gate					ADMIN_PRINC="$value"
3637c478bd9Sstevel@tonic-gate					checkval="ADMIN_PRINC"
3647c478bd9Sstevel@tonic-gate    					check_value $ADMIN_PRINC
3657c478bd9Sstevel@tonic-gate				fi
3667c478bd9Sstevel@tonic-gate				;;
367bd211b85Ssemery			FILEPATH)  if [[ -z $filepath ]]; then
3687c478bd9Sstevel@tonic-gate					filepath="$value"
3697c478bd9Sstevel@tonic-gate				   fi
3707c478bd9Sstevel@tonic-gate				   ;;
371bd211b85Ssemery			NFS)    if [[ -z $add_nfs ]]; then
372bd211b85Ssemery				    if [[ $value == 1 ]]; then
3737c478bd9Sstevel@tonic-gate					    add_nfs=yes
3747c478bd9Sstevel@tonic-gate				    else
3757c478bd9Sstevel@tonic-gate					    add_nfs=no
3767c478bd9Sstevel@tonic-gate				    fi
3777c478bd9Sstevel@tonic-gate				fi
3787c478bd9Sstevel@tonic-gate				;;
379bd211b85Ssemery			NOKEY)    if [[ -z $no_keytab ]]; then
380bd211b85Ssemery				    if [[ $value == 1 ]]; then
381bd211b85Ssemery					    no_keytab=yes
382bd211b85Ssemery				    else
383bd211b85Ssemery					    no_keytab=no
384bd211b85Ssemery				    fi
385bd211b85Ssemery				fi
386bd211b85Ssemery				;;
387bd211b85Ssemery			NOSOL)  if [[ -z $non_solaris ]]; then
388bd211b85Ssemery				    if [[ $value == 1 ]]; then
389bd211b85Ssemery					    non_solaris=yes
390bd211b85Ssemery					    no_keytab=yes
391bd211b85Ssemery				    else
392bd211b85Ssemery					    non_solaris=no
393bd211b85Ssemery				    fi
394bd211b85Ssemery				fi
395bd211b85Ssemery				;;
396bd211b85Ssemery			LHN)    if [[ -z $logical_hn ]]; then
397bd211b85Ssemery					logical_hn="$value"
398bd211b85Ssemery					checkval="LOGICAL_HOSTNAME"
399bd211b85Ssemery    					check_value $logical_hn
400bd211b85Ssemery				fi
401bd211b85Ssemery				;;
402bd211b85Ssemery			DNSLOOKUP) if [[ -z $dnsarg ]]; then
4037c478bd9Sstevel@tonic-gate					dnsarg="$value"
4047c478bd9Sstevel@tonic-gate					checkval="DNS_OPTIONS"
4057c478bd9Sstevel@tonic-gate					check_value $dnsarg
4067c478bd9Sstevel@tonic-gate				   fi
4077c478bd9Sstevel@tonic-gate				   ;;
408bd211b85Ssemery			FQDN) if [[ -z $fqdnlist ]]; then
4097c478bd9Sstevel@tonic-gate					fqdnlist="$value"
4107c478bd9Sstevel@tonic-gate					checkval="FQDN"
4117c478bd9Sstevel@tonic-gate					check_value $fqdnlist
4127c478bd9Sstevel@tonic-gate					verify_fqdnlist "$fqdnlist"
4137c478bd9Sstevel@tonic-gate			      fi
4147c478bd9Sstevel@tonic-gate			      ;;
415bd211b85Ssemery			MSAD) if [[ -z $msad ]]; then
416bd211b85Ssemery				if [[ $value == 1 ]]; then
417bd211b85Ssemery					msad=yes
418bd211b85Ssemery					non_solaris=yes
419bd211b85Ssemery				else
420bd211b85Ssemery					msad=no
421bd211b85Ssemery				fi
422bd211b85Ssemery			      fi
423bd211b85Ssemery			      ;;
4247c478bd9Sstevel@tonic-gate			esac
4257c478bd9Sstevel@tonic-gate		done <$file
4267c478bd9Sstevel@tonic-gate	else
427bd211b85Ssemery		printf "\n$(gettext "The kclient profile \`%s' is not valid, exiting").\n" $file >&2
4287c478bd9Sstevel@tonic-gate		error_message
4297c478bd9Sstevel@tonic-gate	fi
4307c478bd9Sstevel@tonic-gate}
4317c478bd9Sstevel@tonic-gate
432bd211b85Ssemeryfunction ping_check {
4337c478bd9Sstevel@tonic-gate	typeset machine="$1"
4347c478bd9Sstevel@tonic-gate	typeset string="$2"
435bd211b85Ssemery
436bd211b85Ssemery	if ping $machine 2 > /dev/null 2>&1; then
4377c478bd9Sstevel@tonic-gate		:
4387c478bd9Sstevel@tonic-gate	else
439bd211b85Ssemery		printf "\n$(gettext "%s %s is unreachable, exiting").\n" $string $machine >&2
4407c478bd9Sstevel@tonic-gate		error_message
4417c478bd9Sstevel@tonic-gate	fi
4427c478bd9Sstevel@tonic-gate
4437c478bd9Sstevel@tonic-gate	# Output timesync warning if not using a profile, i.e. in
4447c478bd9Sstevel@tonic-gate	# interactive mode.
445bd211b85Ssemery	if [[ -z $profile && $string == KDC ]]; then
4467c478bd9Sstevel@tonic-gate		# It's difficult to sync up time with KDC esp. if in a
4477c478bd9Sstevel@tonic-gate		# zone so just print a warning about KDC time sync.
448ae5b046dSsemery		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
449ae5b046dSsemery		printf "$(gettext "Both systems should run some form of time synchronization system like Network Time Protocol (NTP)").\n" >&2
450bd211b85Ssemerybreak
4517c478bd9Sstevel@tonic-gate	fi
4527c478bd9Sstevel@tonic-gate}
4537c478bd9Sstevel@tonic-gate
454bd211b85Ssemeryfunction check_value {
4557c478bd9Sstevel@tonic-gate	typeset arg="$1"
456bd211b85Ssemery
457bd211b85Ssemery	if [[ -z $arg ]]; then
458bd211b85Ssemery		printf "\n$(gettext "No input obtained for %s, exiting").\n" $checkval >&2
4597c478bd9Sstevel@tonic-gate		error_message
4607c478bd9Sstevel@tonic-gate	else
4617c478bd9Sstevel@tonic-gate		echo "$arg" > $TMP_FILE
4627c478bd9Sstevel@tonic-gate		if egrep -s '[*$^#!]+' $TMP_FILE; then
463bd211b85Ssemery			printf "\n$(gettext "Invalid input obtained for %s, exiting").\n" $checkval >&2
4647c478bd9Sstevel@tonic-gate			error_message
4657c478bd9Sstevel@tonic-gate		fi
4667c478bd9Sstevel@tonic-gate	fi
4677c478bd9Sstevel@tonic-gate}
4687c478bd9Sstevel@tonic-gate
469bd211b85Ssemeryfunction set_dns_value {
470bd211b85Ssemery	typeset -l arg="$1"
471bd211b85Ssemery
472bd211b85Ssemery	if [[ $arg == dns_lookup_kdc  ||  $arg == dns_lookup_realm  || $arg == dns_fallback ]]; then
4737c478bd9Sstevel@tonic-gate		dns_lookup=yes
4747c478bd9Sstevel@tonic-gate	else
475bd211b85Ssemery		if [[ $arg == none ]]; then
4767c478bd9Sstevel@tonic-gate			dns_lookup=no
4777c478bd9Sstevel@tonic-gate		else
478bd211b85Ssemery			printf "\n$(gettext "Invalid DNS lookup option, exiting").\n" >&2
4797c478bd9Sstevel@tonic-gate			error_message
4807c478bd9Sstevel@tonic-gate		fi
4817c478bd9Sstevel@tonic-gate	fi
4827c478bd9Sstevel@tonic-gate}
4837c478bd9Sstevel@tonic-gate
484bd211b85Ssemeryfunction verify_kdcs {
485bd211b85Ssemery	typeset k_list="$1"
486bd211b85Ssemery	typeset -l kdc
487bd211b85Ssemery	typeset list fqhn f_list
4887c478bd9Sstevel@tonic-gate
489bd211b85Ssemery	kdc_list=$(echo "$k_list" | sed 's/,/ /g')
490bd211b85Ssemery
491bd211b85Ssemery	if [[ -z $k_list ]]; then
492bd211b85Ssemery		printf "\n$(gettext "At least one KDC should be listed").\n\n" >&2
493bd211b85Ssemery		usage
494bd211b85Ssemery	fi
495bd211b85Ssemery
496bd211b85Ssemery	for kdc in $k_list; do
497bd211b85Ssemery		if [[ $kdc != $KDC ]]; then
498bd211b85Ssemery			list="$list $kdc"
499bd211b85Ssemery			fkdc=`$KLOOKUP $kdc`
500bd211b85Ssemery			if ping $fkdc 2 > /dev/null; then
501bd211b85Ssemery				:
502bd211b85Ssemery			else
503bd211b85Ssemery				printf "\n$(gettext "%s %s is unreachable, no action performed").\n" "KDC" $fkdc >&2
504bd211b85Ssemery			fi
505bd211b85Ssemery			f_list="$f_list $fkdc"
506bd211b85Ssemery		fi
507bd211b85Ssemery	done
508bd211b85Ssemery
509bd211b85Ssemery	fkdc_list="$f_list"
510bd211b85Ssemery	kdc_list="$list"
511bd211b85Ssemery}
512bd211b85Ssemery
513bd211b85Ssemeryfunction parse_service {
514bd211b85Ssemery	typeset service_list=$1
515bd211b85Ssemery
516bd211b85Ssemery	service_list=${service_list//,/ }
517bd211b85Ssemery	for service in $service_list; do
518bd211b85Ssemery		svc=${service%:}
519bd211b85Ssemery		auth_type=${service#:}
520bd211b85Ssemery		[[ -z $svc || -z $auth_type ]] && return
521bd211b85Ssemery		print -- $svc $auth_type
522bd211b85Ssemery	done
523bd211b85Ssemery}
524bd211b85Ssemery
525bd211b85Ssemeryfunction verify_fqdnlist {
526bd211b85Ssemery	typeset list="$1"
527bd211b85Ssemery	typeset -l hostname
528bd211b85Ssemery	typeset -i count=1
529bd211b85Ssemery	typeset fqdnlist eachfqdn tmpvar fullhost
530bd211b85Ssemery
531bd211b85Ssemery	list=$(echo "$list" | tr -d " " | tr -d "\t")
532bd211b85Ssemery	hostname=$(uname -n | cut -d"." -f1)
5337c478bd9Sstevel@tonic-gate	fqdnlist=$client_machine
5347c478bd9Sstevel@tonic-gate
5357c478bd9Sstevel@tonic-gate	eachfqdn=$(echo "$list" | cut -d"," -f$count)
536bd211b85Ssemery	if [[ -z $eachfqdn ]]; then
537bd211b85Ssemery		printf "\n$(gettext "If the -f option is used, at least one FQDN should be listed").\n\n" >&2
5387c478bd9Sstevel@tonic-gate		usage
5397c478bd9Sstevel@tonic-gate	else
540bd211b85Ssemery		while [[ ! -z $eachfqdn ]]; do
5417c478bd9Sstevel@tonic-gate			tmpvar=$(echo "$eachfqdn" | cut -d"." -f1)
542bd211b85Ssemery			if [[ -z $tmpvar ]]; then
5437c478bd9Sstevel@tonic-gate				fullhost="$hostname$eachfqdn"
5447c478bd9Sstevel@tonic-gate			else
5457c478bd9Sstevel@tonic-gate				fullhost="$hostname.$eachfqdn"
5467c478bd9Sstevel@tonic-gate			fi
5477c478bd9Sstevel@tonic-gate
548bd211b85Ssemery			ping_check $fullhost $(gettext "System")
549bd211b85Ssemery			if [[ $fullhost == $client_machine ]]; then
5507c478bd9Sstevel@tonic-gate				:
5517c478bd9Sstevel@tonic-gate			else
5527c478bd9Sstevel@tonic-gate				fqdnlist="$fqdnlist $fullhost"
5537c478bd9Sstevel@tonic-gate			fi
5547c478bd9Sstevel@tonic-gate
555bd211b85Ssemery			if [[ $list == *,* ]]; then
5567c478bd9Sstevel@tonic-gate				((count = count + 1))
5577c478bd9Sstevel@tonic-gate				eachfqdn=$(echo "$list" | cut -d"," -f$count)
5587c478bd9Sstevel@tonic-gate			else
5597c478bd9Sstevel@tonic-gate				break
5607c478bd9Sstevel@tonic-gate			fi
5617c478bd9Sstevel@tonic-gate		done
5627c478bd9Sstevel@tonic-gate	fi
5637c478bd9Sstevel@tonic-gate}
5647c478bd9Sstevel@tonic-gate
565bd211b85Ssemeryfunction setup_keytab {
566bd211b85Ssemery	typeset cname ask_fqdns current_release
567bd211b85Ssemery
568bd211b85Ssemery	#
569bd211b85Ssemery	# 1. kinit with ADMIN_PRINC
570bd211b85Ssemery	#
571bd211b85Ssemery
572bd211b85Ssemery	if [[ -z $ADMIN_PRINC ]]; then
573bd211b85Ssemery		printf "\n$(gettext "Enter the krb5 administrative principal to be used"): "
574bd211b85Ssemery		read ADMIN_PRINC
575bd211b85Ssemery		checkval="ADMIN_PRINC"; check_value $ADMIN_PRINC
576bd211b85Ssemery	fi
577bd211b85Ssemery
578bd211b85Ssemery	echo "$ADMIN_PRINC">$TMP_FILE
579bd211b85Ssemery
580bd211b85Ssemery	[[ -n $msad ]] && return
581bd211b85Ssemery	if egrep -s '\/admin' $TMP_FILE; then
582bd211b85Ssemery		# Already in "/admin" format, do nothing
583bd211b85Ssemery		:
584bd211b85Ssemery	else
585bd211b85Ssemery		if egrep -s '\/' $TMP_FILE; then
586bd211b85Ssemery			printf "\n$(gettext "Improper entry for krb5 admin principal, exiting").\n" >&2
5877c478bd9Sstevel@tonic-gate			error_message
588bd211b85Ssemery		else
589bd211b85Ssemery			ADMIN_PRINC=$(echo "$ADMIN_PRINC/admin")
590bd211b85Ssemery		fi
591bd211b85Ssemery	fi
592bd211b85Ssemery
593bd211b85Ssemery	printf "$(gettext "Obtaining TGT for %s") ...\n" $ADMIN_PRINC
594bd211b85Ssemery
595bd211b85Ssemery	cname=$(canon_resolve $KDC)
596bd211b85Ssemery	if [[ -n $cname ]]; then
597bd211b85Ssemery		kinit -S kadmin/$cname $ADMIN_PRINC
598bd211b85Ssemery	else
599bd211b85Ssemery		kinit -S kadmin/$FKDC $ADMIN_PRINC
600bd211b85Ssemery	fi
601bd211b85Ssemery	klist 1>$TMP_FILE 2>&1
602ae5b046dSsemery	if egrep -s "$(gettext "Valid starting")" $TMP_FILE && egrep -s "kadmin/$FKDC@$realm" $TMP_FILE; then
603bd211b85Ssemery    		:
604bd211b85Ssemery	else
605bd211b85Ssemery		printf "\n$(gettext "kinit of %s failed, exiting").\n" $ADMIN_PRINC >&2
606bd211b85Ssemery		error_message
607bd211b85Ssemery	fi
608bd211b85Ssemery
609bd211b85Ssemery	#
610bd211b85Ssemery	# 2. Do we want to create and/or add service principal(s) for fqdn's
611bd211b85Ssemery	#    other than the one listed in resolv.conf(4) ?
612bd211b85Ssemery	#
613bd211b85Ssemery	if [[ -z $options ]]; then
614bd211b85Ssemery		query "$(gettext "Do you have multiple DNS domains spanning the Kerberos realm") $realm ?"
615bd211b85Ssemery		ask_fqdns=$answer
616bd211b85Ssemery		if [[ $ask_fqdns == yes ]]; then
617ae5b046dSsemery			printf "$(gettext "Enter a comma-separated list of DNS domain names"): "
618bd211b85Ssemery			read fqdnlist
619bd211b85Ssemery			verify_fqdnlist "$fqdnlist"
620bd211b85Ssemery		else
621bd211b85Ssemery			fqdnlist=$client_machine
622bd211b85Ssemery		fi
623bd211b85Ssemery	else
624bd211b85Ssemery		if [[ -z $fqdnlist ]]; then
625bd211b85Ssemery			fqdnlist=$client_machine
626bd211b85Ssemery		fi
627bd211b85Ssemery	fi
628bd211b85Ssemery
629bd211b85Ssemery	if [[ $add_nfs == yes ]]; then
630bd211b85Ssemery		echo; call_kadmin nfs
631bd211b85Ssemery	fi
632bd211b85Ssemery
633bd211b85Ssemery	# Add the host entry to the keytab
634bd211b85Ssemery	echo; call_kadmin host
635bd211b85Ssemery
636bd211b85Ssemery}
637bd211b85Ssemery
638bd211b85Ssemeryfunction setup_lhn {
639bd211b85Ssemery	typeset -l logical_hn
640bd211b85Ssemery
641bd211b85Ssemery	echo "$logical_hn" > $TMP_FILE
642bd211b85Ssemery	if egrep -s '[^.]\.[^.]+$' $TMP_FILE; then
643bd211b85Ssemery		# do nothing, logical_hn is in fqdn format
644bd211b85Ssemery		:
645bd211b85Ssemery	else
646bd211b85Ssemery		if egrep -s '\.+' $TMP_FILE; then
647bd211b85Ssemery			printf "\n$(gettext "Improper format of logical hostname, exiting").\n" >&2
648bd211b85Ssemery			error_message
649bd211b85Ssemery		else
650bd211b85Ssemery			# Attach fqdn to logical_hn, to get the Fully Qualified
651bd211b85Ssemery			# Host Name of the client requested
652bd211b85Ssemery			logical_hn=$(echo "$logical_hn.$fqdn")
653bd211b85Ssemery		fi
654bd211b85Ssemery	fi
655bd211b85Ssemery
656bd211b85Ssemery	client_machine=$logical_hn
657bd211b85Ssemery
658bd211b85Ssemery	ping_check $client_machine $(gettext "System")
659bd211b85Ssemery}
660bd211b85Ssemery
661bd211b85Ssemeryfunction usage {
662bd211b85Ssemery	printf "\n$(gettext "Usage: kclient [ options ]")\n" >&2
663bd211b85Ssemery	printf "\t$(gettext "where options are any of the following")\n\n" >&2
664bd211b85Ssemery	printf "\t$(gettext "[ -D domain_list ]  configure a client that has mul
665bd211b85Ssemerytiple mappings of doamin and/or hosts to the default realm")\n" >&2
666bd211b85Ssemery	printf "\t$(gettext "[ -K ]  configure a client that does not have host/service keys")\n" >&2
667bd211b85Ssemery	printf "\t$(gettext "[ -R realm ]  specifies the realm to use")\n" >&2
668bd211b85Ssemery	printf "\t$(gettext "[ -T kdc_vendor ]  specifies which KDC vendor is the server")\n" >&2
669bd211b85Ssemery	printf "\t$(gettext "[ -a adminuser ]  specifies the Kerberos administrator")\n" >&2
670bd211b85Ssemery	printf "\t$(gettext "[ -c filepath ]  specifies the krb5.conf path used to configure this client")\n" >&2
671bd211b85Ssemery	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
672bd211b85Ssemery	printf "\t$(gettext "[ -f fqdn_list ]  specifies which domains to configure host keys for this client")\n" >&2
673bd211b85Ssemery	printf "\t$(gettext "[ -h logicalhostname ]  configure the logical host name for a client that is in a cluster")\n" >&2
674bd211b85Ssemery	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
675bd211b85Ssemery	printf "\t$(gettext "[ -m master ]  master KDC server host name")\n" >&2
676bd211b85Ssemery	printf "\t$(gettext "[ -n ]  configure client to be an NFS client")\n" >&2
677bd211b85Ssemery	printf "\t$(gettext "[ -p profile ]  specifies which profile file to use to configure this client")\n" >&2
678bd211b85Ssemery	printf "\t$(gettext "[ -s pam_list ]  update the service for Kerberos authentication")\n" >&2
679bd211b85Ssemery	error_message
680bd211b85Ssemery}
681bd211b85Ssemery
682bd211b85Ssemeryfunction discover_domain {
683bd211b85Ssemery	typeset dom DOMs
684bd211b85Ssemery
685bd211b85Ssemery	if [[ -z $realm ]]; then
686bd211b85Ssemery		set -A DOMs -- `$KLOOKUP _ldap._tcp.dc._msdcs S`
687bd211b85Ssemery	else
688bd211b85Ssemery		set -A DOMs -- `$KLOOKUP _ldap._tcp.dc._msdcs.$realm S`
689bd211b85Ssemery	fi
690bd211b85Ssemery
691bd211b85Ssemery	[[ -z ${DOMs[0]} ]] && return 1
692bd211b85Ssemery
693bd211b85Ssemery	dom=${DOMs[0]}
694bd211b85Ssemery
695bd211b85Ssemery	dom=${dom#*.}
696bd211b85Ssemery	dom=${dom% *}
697bd211b85Ssemery
698bd211b85Ssemery	domain=$dom
699bd211b85Ssemery
700bd211b85Ssemery	return 0
701bd211b85Ssemery}
702bd211b85Ssemery
703bd211b85Ssemeryfunction check_nss_hosts_or_ipnodes_config {
704bd211b85Ssemery	typeset backend
705bd211b85Ssemery
706bd211b85Ssemery	for backend in $1
707bd211b85Ssemery	do
708bd211b85Ssemery		[[ $backend == dns ]] && return 0
709bd211b85Ssemery	done
710bd211b85Ssemery	return 1
711bd211b85Ssemery}
712bd211b85Ssemery
713bd211b85Ssemeryfunction check_nss_conf {
714bd211b85Ssemery	typeset i j hosts_config
715bd211b85Ssemery
716bd211b85Ssemery	for i in hosts ipnodes
717bd211b85Ssemery	do
718bd211b85Ssemery		grep "^${i}:" /etc/nsswitch.conf|read j hosts_config
719bd211b85Ssemery		check_nss_hosts_or_ipnodes_config "$hosts_config" || return 1
720bd211b85Ssemery	done
721bd211b85Ssemery
722bd211b85Ssemery	return 0
723bd211b85Ssemery}
724bd211b85Ssemery
725bd211b85Ssemeryfunction canon_resolve {
726bd211b85Ssemery	typeset name ip
727bd211b85Ssemery
728bd211b85Ssemery	name=`$KLOOKUP $1 C`
729bd211b85Ssemery	[[ -z $name ]] && name=`$KLOOKUP $1 A`
730bd211b85Ssemery	[[ -z $name ]] && return
731bd211b85Ssemery
732bd211b85Ssemery	ip=`$KLOOKUP $name I`
733bd211b85Ssemery	[[ -z $ip ]] && return
734ae5b046dSsemery	for i in $ip
735ae5b046dSsemery	do
736ae5b046dSsemery		if ping $i 2 > /dev/null 2>&1; then
737ae5b046dSsemery			break
738ae5b046dSsemery		else
739ae5b046dSsemery			i=
740ae5b046dSsemery		fi
741ae5b046dSsemery	done
742bd211b85Ssemery
743bd211b85Ssemery	cname=`$KLOOKUP $ip P`
744bd211b85Ssemery	[[ -z $cname ]] && return
745bd211b85Ssemery
746bd211b85Ssemery	print -- "$cname"
747bd211b85Ssemery}
748bd211b85Ssemery
749bd211b85Ssemeryfunction rev_resolve {
750bd211b85Ssemery	typeset name ip
751bd211b85Ssemery
752bd211b85Ssemery	ip=`$KLOOKUP $1 I`
753bd211b85Ssemery
754bd211b85Ssemery	[[ -z $ip ]] && return
755bd211b85Ssemery	name=`$KLOOKUP $ip P`
756bd211b85Ssemery	[[ -z $name ]] && return
757bd211b85Ssemery
758bd211b85Ssemery	print -- $name
759bd211b85Ssemery}
760bd211b85Ssemery
761bd211b85Ssemery# Convert an AD-style domain DN to a DNS domainname
762bd211b85Ssemeryfunction dn2dns {
763bd211b85Ssemery	typeset OIFS dname dn comp components
764bd211b85Ssemery
765bd211b85Ssemery	dn=$1
766bd211b85Ssemery	dname=
767bd211b85Ssemery
768bd211b85Ssemery	OIFS="$IFS"
769bd211b85Ssemery	IFS=,
770bd211b85Ssemery	set -A components -- $1
771bd211b85Ssemery	IFS="$OIFS"
772bd211b85Ssemery
773bd211b85Ssemery	for comp in "${components[@]}"
774bd211b85Ssemery	do
775bd211b85Ssemery		[[ "$comp" == [dD][cC]=* ]] || continue
776bd211b85Ssemery		dname="$dname.${comp#??=}"
777bd211b85Ssemery	done
778bd211b85Ssemery
779bd211b85Ssemery	print ${dname#.}
780bd211b85Ssemery}
781bd211b85Ssemery
782bd211b85Ssemery# Form a base DN from a DNS domainname and container
783bd211b85Ssemeryfunction getBaseDN {
784bd211b85Ssemery	if [[ -n "$2" ]]
785bd211b85Ssemery	then
786bd211b85Ssemery		baseDN="CN=$1,$(dns2dn $2)"
787bd211b85Ssemery	else
788bd211b85Ssemery		baseDN="$(dns2dn $2)"
789bd211b85Ssemery	fi
790bd211b85Ssemery}
791bd211b85Ssemery
792bd211b85Ssemery# Convert a DNS domainname to an AD-style DN for that domain
793bd211b85Ssemeryfunction dns2dn {
794bd211b85Ssemery	typeset OIFS dn labels
795bd211b85Ssemery
796bd211b85Ssemery	OIFS="$IFS"
797bd211b85Ssemery	IFS=.
798bd211b85Ssemery	set -A labels -- $1
799bd211b85Ssemery	IFS="$OIFS"
800bd211b85Ssemery
801bd211b85Ssemery	dn=
802bd211b85Ssemery	for label in "${labels[@]}"
803bd211b85Ssemery	do
804bd211b85Ssemery		dn="${dn},DC=$label"
805bd211b85Ssemery	done
806bd211b85Ssemery
807bd211b85Ssemery	print -- "${dn#,}"
808bd211b85Ssemery}
809bd211b85Ssemery
810bd211b85Ssemeryfunction getSRVs {
811bd211b85Ssemery	typeset srv port
812bd211b85Ssemery
813bd211b85Ssemery	$KLOOKUP $1 S | while read srv port
814bd211b85Ssemery	do
815ae5b046dSsemery		if ping $srv 2 > /dev/null 2>&1; then
816bd211b85Ssemery			print -- $srv $port
817ae5b046dSsemery		fi
818bd211b85Ssemery	done
819bd211b85Ssemery}
820bd211b85Ssemery
821bd211b85Ssemeryfunction getKDC {
822bd211b85Ssemery	typeset j
823bd211b85Ssemery
824bd211b85Ssemery	set -A KPWs -- $(getSRVs _kpasswd._tcp.$dom.)
825bd211b85Ssemery	kpasswd=${KPWs[0]}
826bd211b85Ssemery
827bd211b85Ssemery	if [[ -n $siteName ]]
828bd211b85Ssemery	then
829bd211b85Ssemery		set -A KDCs -- $(getSRVs _kerberos._tcp.$siteName._sites.$dom.)
830bd211b85Ssemery		kdc=${KDCs[0]}
831bd211b85Ssemery		[[ -n $kdc ]] && return
832bd211b85Ssemery	fi
833bd211b85Ssemery
834bd211b85Ssemery	# No site name
835bd211b85Ssemery	set -A KDCs -- $(getSRVs _kerberos._tcp.$dom.)
836bd211b85Ssemery	kdc=${KDCs[0]}
837bd211b85Ssemery	[[ -n $kdc ]] && return
838bd211b85Ssemery
839bd211b85Ssemery	# Default
840bd211b85Ssemery	set -A KDCs -- $DomainDnsZones 88
841bd211b85Ssemery	kdc=$ForestDnsZones
842bd211b85Ssemery}
843bd211b85Ssemery
844bd211b85Ssemeryfunction getDC {
845bd211b85Ssemery	typeset j
846bd211b85Ssemery
847bd211b85Ssemery	if [[ -n $siteName ]]
848bd211b85Ssemery	then
849bd211b85Ssemery		set -A DCs -- $(getSRVs _ldap._tcp.$siteName._sites.dc._msdcs.$dom.)
850bd211b85Ssemery		dc=${DCs[0]}
851bd211b85Ssemery		[[ -n $dc ]] && return
852bd211b85Ssemery	fi
853bd211b85Ssemery
854bd211b85Ssemery	# No site name
855bd211b85Ssemery	set -A DCs -- $(getSRVs _ldap._tcp.dc._msdcs.$dom.)
856bd211b85Ssemery	dc=${DCs[0]}
857bd211b85Ssemery	[[ -n $dc ]] && return
858bd211b85Ssemery
859bd211b85Ssemery	# Default
860bd211b85Ssemery	set -A DCs -- $DomainDnsZones 389
861bd211b85Ssemery	dc=$DomainDnsZones
862bd211b85Ssemery}
863bd211b85Ssemery
864bd211b85Ssemeryfunction write_ads_krb5conf {
865c48f4690SShawn Emery	typeset kdcs
866c48f4690SShawn Emery
867bd211b85Ssemery	printf "\n$(gettext "Setting up %s").\n\n" $KRB5_CONFIG_FILE
868bd211b85Ssemery
869bd211b85Ssemery	for i in ${KDCs[@]}
870bd211b85Ssemery	do
871bd211b85Ssemery		[[ $i == +([0-9]) ]] && continue
872c48f4690SShawn Emery		if [[ -n $kdcs ]]
873c48f4690SShawn Emery		then
874c48f4690SShawn Emery			kdcs="$kdcs,$i"
875c48f4690SShawn Emery		else
876c48f4690SShawn Emery			kdcs=$i
877c48f4690SShawn Emery		fi
878bd211b85Ssemery	done
879c48f4690SShawn Emery
880c48f4690SShawn Emery	$KCONF -f $KRB5_CONFIG -r $realm -k $kdcs -m $KDC -p SET_CHANGE -d .$dom
881c48f4690SShawn Emery
882c48f4690SShawn Emery	if [[ $? -ne 0 ]]; then
883c48f4690SShawn Emery		printf "\n$(gettext "Can not update %s, exiting").\n" $KRB5_CONFIG >&2
884c48f4690SShawn Emery		error_message
885c48f4690SShawn Emery	fi
886bd211b85Ssemery}
887bd211b85Ssemery
888bd211b85Ssemeryfunction getForestName {
889bd211b85Ssemery	ldapsearch -R -T -h $dc $ldap_args \
890bd211b85Ssemery	    -b "" -s base "" schemaNamingContext| \
891bd211b85Ssemery		grep ^schemaNamingContext|read j schemaNamingContext
892bd211b85Ssemery
893bd211b85Ssemery	if [[ $? -ne 0 ]]; then
894c386eb9cSShawn Emery		printf "$(gettext "Can't find forest").\n" >&2
895bd211b85Ssemery		error_message
896bd211b85Ssemery	fi
897bd211b85Ssemery	schemaNamingContext=${schemaNamingContext#CN=Schema,CN=Configuration,}
898bd211b85Ssemery
899bd211b85Ssemery	[[ -z $schemaNamingContext ]] && return 1
900bd211b85Ssemery
901bd211b85Ssemery	forest=
902bd211b85Ssemery	while [[ -n $schemaNamingContext ]]
903bd211b85Ssemery	do
904bd211b85Ssemery		schemaNamingContext=${schemaNamingContext#DC=}
905bd211b85Ssemery		forest=${forest}.${schemaNamingContext%%,*}
906bd211b85Ssemery		[[ "$schemaNamingContext" = *,* ]] || break
907bd211b85Ssemery		schemaNamingContext=${schemaNamingContext#*,}
908bd211b85Ssemery	done
909bd211b85Ssemery	forest=${forest#.}
910bd211b85Ssemery}
911bd211b85Ssemery
912bd211b85Ssemeryfunction getGC {
913bd211b85Ssemery	typeset j
914bd211b85Ssemery
915bd211b85Ssemery	[[ -n $gc ]] && return 0
916bd211b85Ssemery
917bd211b85Ssemery	if [[ -n $siteName ]]
918bd211b85Ssemery	then
919bd211b85Ssemery		set -A GCs -- $(getSRVs _ldap._tcp.$siteName._sites.gc._msdcs.$forest.)
920bd211b85Ssemery		gc=${GCs[0]}
921bd211b85Ssemery		[[ -n $gc ]] && return
922bd211b85Ssemery	fi
923bd211b85Ssemery
924bd211b85Ssemery	# No site name
925bd211b85Ssemery	set -A GCs -- $(getSRVs _ldap._tcp.gc._msdcs.$forest.)
926bd211b85Ssemery	gc=${GCs[0]}
927bd211b85Ssemery	[[ -n $gc ]] && return
928bd211b85Ssemery
929bd211b85Ssemery	# Default
930bd211b85Ssemery	set -A GCs -- $ForestDnsZones 3268
931bd211b85Ssemery	gc=$ForestDnsZones
932bd211b85Ssemery}
933bd211b85Ssemery
934c386eb9cSShawn Emery#
935c386eb9cSShawn Emery# The local variables used to calculate the IP address are of type unsigned
936c386eb9cSShawn Emery# integer (-ui), as this is required to restrict the integer to 32b.
937c386eb9cSShawn Emery# Starting in ksh88, Solaris has incorrectly assummed that -i represents 64b.
938c386eb9cSShawn Emery#
939bd211b85Ssemeryfunction ipAddr2num {
940bd211b85Ssemery	typeset OIFS
941c386eb9cSShawn Emery	typeset -ui16 num
942bd211b85Ssemery
943bd211b85Ssemery	if [[ "$1" != +([0-9]).+([0-9]).+([0-9]).+([0-9]) ]]
944bd211b85Ssemery	then
945bd211b85Ssemery		print 0
946bd211b85Ssemery		return 0
947bd211b85Ssemery	fi
948bd211b85Ssemery
949bd211b85Ssemery	OIFS="$IFS"
950bd211b85Ssemery	IFS=.
951bd211b85Ssemery	set -- $1
952bd211b85Ssemery	IFS="$OIFS"
953bd211b85Ssemery
954bd211b85Ssemery	num=$((${1}<<24 | ${2}<<16 | ${3}<<8 | ${4}))
955bd211b85Ssemery
956bd211b85Ssemery	print -- $num
957bd211b85Ssemery}
958bd211b85Ssemery
959c386eb9cSShawn Emery#
960c386eb9cSShawn Emery# The local variables used to calculate the IP address are of type unsigned
961c386eb9cSShawn Emery# integer (-ui), as this is required to restrict the integer to 32b.
962c386eb9cSShawn Emery# Starting in ksh88, Solaris has incorrectly assummed that -i represents 64b.
963c386eb9cSShawn Emery#
964bd211b85Ssemeryfunction num2ipAddr {
965c386eb9cSShawn Emery	typeset -ui16 num
966c386eb9cSShawn Emery	typeset -ui10 a b c d
967bd211b85Ssemery
968bd211b85Ssemery	num=$1
969bd211b85Ssemery	a=$((num>>24        ))
970bd211b85Ssemery	b=$((num>>16 & 16#ff))
971bd211b85Ssemery	c=$((num>>8  & 16#ff))
972bd211b85Ssemery	d=$((num     & 16#ff))
973bd211b85Ssemery	print -- $a.$b.$c.$d
974bd211b85Ssemery}
975bd211b85Ssemery
976c386eb9cSShawn Emery#
977c386eb9cSShawn Emery# The local variables used to calculate the IP address are of type unsigned
978c386eb9cSShawn Emery# integer (-ui), as this is required to restrict the integer to 32b.
979c386eb9cSShawn Emery# Starting in ksh88, Solaris has incorrectly assummed that -i represents 64b.
980c386eb9cSShawn Emery#
981bd211b85Ssemeryfunction netmask2length {
982c386eb9cSShawn Emery	typeset -ui16 netmask
983bd211b85Ssemery	typeset -i len
984bd211b85Ssemery
985bd211b85Ssemery	netmask=$1
986bd211b85Ssemery	len=32
987bd211b85Ssemery	while [[ $((netmask % 2)) -eq 0 ]]
988bd211b85Ssemery	do
989bd211b85Ssemery		netmask=$((netmask>>1))
990bd211b85Ssemery		len=$((len - 1))
991bd211b85Ssemery	done
992bd211b85Ssemery	print $len
993bd211b85Ssemery}
994bd211b85Ssemery
995c386eb9cSShawn Emery#
996c386eb9cSShawn Emery# The local variables used to calculate the IP address are of type unsigned
997c386eb9cSShawn Emery# integer (-ui), as this is required to restrict the integer to 32b.
998c386eb9cSShawn Emery# Starting in ksh88, Solaris has incorrectly assummed that -i represents 64b.
999c386eb9cSShawn Emery#
1000bd211b85Ssemeryfunction getSubnets {
1001c386eb9cSShawn Emery	typeset -ui16 addr netmask
1002c386eb9cSShawn Emery	typeset -ui16 classa=16\#ff000000
1003*5e11cc39SToomas Soome	typeset -ui16 classb=16\#ffff0000
1004*5e11cc39SToomas Soome	typeset -ui16 classc=16\#ffffff00
1005bd211b85Ssemery
1006bd211b85Ssemery	ifconfig -a|while read line
1007bd211b85Ssemery	do
1008bd211b85Ssemery		addr=0
1009bd211b85Ssemery		netmask=0
1010bd211b85Ssemery		set -- $line
1011bd211b85Ssemery		[[ $1 == inet ]] || continue
1012bd211b85Ssemery		while [[ $# -gt 0 ]]
1013bd211b85Ssemery		do
1014bd211b85Ssemery			case "$1" in
1015bd211b85Ssemery				inet) addr=$(ipAddr2num $2); shift;;
1016bd211b85Ssemery				netmask) eval netmask=16\#$2; shift;;
1017bd211b85Ssemery				*) :;
1018bd211b85Ssemery			esac
1019bd211b85Ssemery			shift
1020bd211b85Ssemery		done
1021bd211b85Ssemery
1022bd211b85Ssemery		[[ $addr -eq 0 || $netmask -eq 0 ]] && continue
1023bd211b85Ssemery		[[ $((addr & classa)) -eq 16\#7f000000 ]] && continue
1024bd211b85Ssemery
1025bd211b85Ssemery		print $(num2ipAddr $((addr & netmask)))/$(netmask2length $netmask)
1026*5e11cc39SToomas Soome		if [ $netmask -gt $classc ]
1027*5e11cc39SToomas Soome		then
1028*5e11cc39SToomas Soome			print $(num2ipAddr $((addr & classc)))/$(netmask2length $classc)
1029*5e11cc39SToomas Soome		fi
1030*5e11cc39SToomas Soome		if [ $netmask -gt $classb ]
1031*5e11cc39SToomas Soome		then
1032*5e11cc39SToomas Soome			print $(num2ipAddr $((addr & classb)))/$(netmask2length $classb)
1033*5e11cc39SToomas Soome		fi
1034*5e11cc39SToomas Soome		if [ $netmask -gt $classa ]
1035*5e11cc39SToomas Soome		then
1036*5e11cc39SToomas Soome			print $(num2ipAddr $((addr & classa)))/$(netmask2length $classa)
1037*5e11cc39SToomas Soome		fi
1038bd211b85Ssemery	done
1039bd211b85Ssemery}
1040bd211b85Ssemery
1041bd211b85Ssemeryfunction getSite {
1042bd211b85Ssemery	typeset subnet siteDN j ldapsrv subnet_dom
1043bd211b85Ssemery
1044bd211b85Ssemery	eval "[[ -n \"\$siteName\" ]]" && return
1045bd211b85Ssemery	for subnet in $(getSubnets)
1046bd211b85Ssemery	do
1047bd211b85Ssemery		ldapsearch -R -T -h $dc $ldap_args \
1048bd211b85Ssemery		    -p 3268 -b "" -s sub cn=$subnet dn |grep ^dn|read j subnetDN
1049bd211b85Ssemery
1050bd211b85Ssemery		[[ -z $subnetDN ]] && continue
1051bd211b85Ssemery		subnet_dom=$(dn2dns $subnetDN)
1052bd211b85Ssemery		ldapsrv=$(canon_resolve DomainDnsZones.$subnet_dom)
1053ae5b046dSsemery		[[ -z $ldapsrv ]] && continue
1054bd211b85Ssemery		ldapsearch -R -T -h $ldapsrv $ldap_args \
1055bd211b85Ssemery		    -b "$subnetDN" -s base "" siteObject \
1056bd211b85Ssemery		    |grep ^siteObject|read j siteDN
1057bd211b85Ssemery
1058bd211b85Ssemery		[[ -z $siteDN ]] && continue
1059bd211b85Ssemery
1060bd211b85Ssemery		eval siteName=${siteDN%%,*}
1061bd211b85Ssemery		eval siteName=\${siteName#CN=}
1062bd211b85Ssemery		return
1063bd211b85Ssemery	done
1064bd211b85Ssemery}
1065bd211b85Ssemery
1066bd211b85Ssemeryfunction doKRB5config {
1067bd211b85Ssemery	[[ -f $KRB5_CONFIG_FILE ]] && \
1068bd211b85Ssemery		cp $KRB5_CONFIG_FILE ${KRB5_CONFIG_FILE}-pre-kclient
1069bd211b85Ssemery
1070bd211b85Ssemery	[[ -f $KRB5_KEYTAB_FILE ]] && \
1071bd211b85Ssemery		cp $KRB5_KEYTAB_FILE ${KRB5_KEYTAB_FILE}-pre-kclient
1072bd211b85Ssemery
1073ae5b046dSsemery	[[ -s $KRB5_CONFIG ]] && cp $KRB5_CONFIG $KRB5_CONFIG_FILE
1074ae5b046dSsemery	[[ -s $KRB5_CONFIG_FILE ]] && chmod 0644 $KRB5_CONFIG_FILE
1075ae5b046dSsemery	[[ -s $new_keytab ]] && cp $new_keytab $KRB5_KEYTAB_FILE
1076ae5b046dSsemery	[[ -s $KRB5_KEYTAB_FILE ]] && chmod 0600 $KRB5_KEYTAB_FILE
1077bd211b85Ssemery}
1078bd211b85Ssemery
1079bd211b85Ssemeryfunction addDNSRR {
1080bd211b85Ssemery	smbFMRI=svc:/network/smb/server:default
1081bd211b85Ssemery	ddnsProp=smbd/ddns_enable
1082bd211b85Ssemery	enProp=general/enabled
1083bd211b85Ssemery
1084bd211b85Ssemery	enabled=`svcprop -p $enProp $smbFMRI`
1085bd211b85Ssemery	ddns_enable=`svcprop -p $ddnsProp $smbFMRI`
1086bd211b85Ssemery
1087bd211b85Ssemery	if [[ $enabled == true && $ddns_enable != true ]]; then
1088bd211b85Ssemery		printf "$(gettext "Warning: won't create DNS records for client").\n"
1089bd211b85Ssemery		printf "$(gettext "%s property not set to 'true' for the %s FMRI").\n" $ddnsProp $smbFMRI
1090bd211b85Ssemery		return
1091bd211b85Ssemery	fi
1092bd211b85Ssemery
1093bd211b85Ssemery	# Destroy any existing ccache as GSS_C_NO_CREDENTIAL will pick up any
1094bd211b85Ssemery	# residual default credential in the cache.
1095bd211b85Ssemery	kdestroy > /dev/null 2>&1
1096bd211b85Ssemery
1097bd211b85Ssemery	$KDYNDNS -d $1 > /dev/null 2>&1
1098bd211b85Ssemery	if [[ $? -ne 0 ]]; then
1099bd211b85Ssemery		#
1100bd211b85Ssemery		# Non-fatal, we should carry-on as clients may resolve to
1101bd211b85Ssemery		# different servers and the client could already exist there.
1102bd211b85Ssemery		#
11038d7e4166Sjose borrego		printf "$(gettext "Warning: unable to create DNS records for client").\n"
1104bd211b85Ssemery		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
1105bd211b85Ssemery	fi
1106bd211b85Ssemery}
1107bd211b85Ssemery
1108bd211b85Ssemeryfunction setSMB {
1109bd211b85Ssemery	typeset domain=$1
1110bd211b85Ssemery	typeset server=$2
1111bd211b85Ssemery	smbFMRI=svc:/network/smb/server
1112bd211b85Ssemery
1113986b458dSShawn Emery	printf "%s" "$newpw" | $KSMB -d $domain -s $server
1114bd211b85Ssemery	if [[ $? -ne 0 ]]; then
11158d7e4166Sjose borrego		printf "$(gettext "Warning: unable to set %s domain, server and password information").\n" $smbFMRI
1116bd211b85Ssemery		return
1117bd211b85Ssemery	fi
1118bd211b85Ssemery
11198d7e4166Sjose borrego	svcadm restart $smbFMRI > /dev/null 2>&1
1120bd211b85Ssemery	if [[ $? -ne 0 ]]; then
11218d7e4166Sjose borrego		printf "$(gettext "Warning: unable to restart %s").\n" $smbFMRI
1122bd211b85Ssemery	fi
1123bd211b85Ssemery}
1124bd211b85Ssemery
1125bd211b85Ssemeryfunction compareDomains {
1126bd211b85Ssemery	typeset oldDom hspn newDom=$1
1127bd211b85Ssemery
1128bd211b85Ssemery	# If the client has been previously configured in a different
1129bd211b85Ssemery	# realm/domain then we need to prompt the user to see if they wish to
1130bd211b85Ssemery	# switch domains.
1131ae5b046dSsemery	klist -k 2>&1 | grep @ | read j hspn
1132bd211b85Ssemery	[[ -z $hspn ]] && return
1133bd211b85Ssemery
1134bd211b85Ssemery	oldDom=${hspn#*@}
1135bd211b85Ssemery	if [[ $oldDom != $newDom ]]; then
1136bd211b85Ssemery		printf "$(gettext "The client is currently configured in a different domain").\n"
1137bd211b85Ssemery		printf "$(gettext "Currently in the '%s' domain, trying to join the '%s' domain").\n" $oldDom $newDom
1138bd211b85Ssemery		query "$(gettext "Do you want the client to join a new domain") ?"
1139bd211b85Ssemery		printf "\n"
1140bd211b85Ssemery		if [[ $answer != yes ]]; then
1141c386eb9cSShawn Emery			printf "$(gettext "Client will not be joined to the new domain").\n" >&2
1142bd211b85Ssemery			error_message
1143bd211b85Ssemery		fi
1144bd211b85Ssemery	fi
1145bd211b85Ssemery}
1146bd211b85Ssemery
1147bd211b85Ssemeryfunction getKDCDC {
1148bd211b85Ssemery
1149bd211b85Ssemery	getKDC
1150bd211b85Ssemery	if [[ -n $kdc ]]; then
1151bd211b85Ssemery		KDC=$kdc
1152bd211b85Ssemery		dc=$kdc
1153bd211b85Ssemery	else
1154bd211b85Ssemery		getDC
1155bd211b85Ssemery		if [[ -n $dc ]]; then
1156bd211b85Ssemery			KDC=$dc
1157bd211b85Ssemery		else
1158c386eb9cSShawn Emery			printf "$(gettext "Could not find domain controller server for '%s'.  Exiting").\n" $realm >&2
1159bd211b85Ssemery			error_message
1160bd211b85Ssemery		fi
1161bd211b85Ssemery	fi
1162bd211b85Ssemery}
1163bd211b85Ssemery
1164986b458dSShawn Emeryfunction gen_rand {
1165986b458dSShawn Emery	typeset -u hex
1166986b458dSShawn Emery
1167986b458dSShawn Emery	dd if=/dev/random bs=1 count=1 2>/dev/null | od -A n -tx1 | read hex
1168986b458dSShawn Emery
1169986b458dSShawn Emery	printf %s $((16#$hex))
1170986b458dSShawn Emery}
1171986b458dSShawn Emery
1172bd211b85Ssemeryfunction join_domain {
1173bd211b85Ssemery	typeset -u upcase_nodename
117472f0806aSShawn Emery	typeset -l locase_nodename
117572f0806aSShawn Emery	typeset -L15 string15
1176bd211b85Ssemery	typeset netbios_nodename fqdn
1177bd211b85Ssemery
1178bd211b85Ssemery	container=Computers
1179bd211b85Ssemery	ldap_args="-o authzid= -o mech=gssapi"
1180bd211b85Ssemery	userAccountControlBASE=4096
1181bd211b85Ssemery
1182bd211b85Ssemery	if [[ -z $ADMIN_PRINC ]]; then
1183bd211b85Ssemery		cprinc=Administrator
1184bd211b85Ssemery	else
1185bd211b85Ssemery		cprinc=$ADMIN_PRINC
1186bd211b85Ssemery	fi
1187bd211b85Ssemery
1188bd211b85Ssemery	if ! discover_domain; then
1189c386eb9cSShawn Emery		printf "$(gettext "Can not find realm") '%s'.\n" $realm >&2
1190bd211b85Ssemery		error_message
1191bd211b85Ssemery	fi
1192bd211b85Ssemery
1193bd211b85Ssemery	dom=$domain
1194bd211b85Ssemery	realm=$domain
119572f0806aSShawn Emery
119672f0806aSShawn Emery	if [[ ${#hostname} -gt 15 ]]; then
119772f0806aSShawn Emery		string15=$hostname
119872f0806aSShawn Emery		upcase_nodename=$string15
119972f0806aSShawn Emery		locase_nodename=$string15
120072f0806aSShawn Emery	else
1201bd211b85Ssemery		upcase_nodename=$hostname
120272f0806aSShawn Emery		locase_nodename=$hostname
120372f0806aSShawn Emery	fi
120472f0806aSShawn Emery
1205bd211b85Ssemery	netbios_nodename="${upcase_nodename}\$"
1206bd211b85Ssemery	fqdn=$hostname.$domain
1207037cac00Sjoyce mcintosh	upn=host/${fqdn}@${realm}
1208bd211b85Ssemery
1209bd211b85Ssemery	object=$(mktemp -q -t kclient-computer-object.XXXXXX)
1210bd211b85Ssemery	if [[ -z $object ]]; then
1211bd211b85Ssemery		printf "\n$(gettext "Can not create temporary file, exiting").\n
1212bd211b85Ssemery" >&2
1213bd211b85Ssemery		error_message
1214bd211b85Ssemery        fi
1215bd211b85Ssemery
1216bd211b85Ssemery	modify_existing=false
1217bd211b85Ssemery	recreate=false
1218bd211b85Ssemery
1219bd211b85Ssemery	DomainDnsZones=$(rev_resolve DomainDnsZones.$dom.)
1220bd211b85Ssemery	ForestDnsZones=$(rev_resolve ForestDnsZones.$dom.)
1221bd211b85Ssemery
1222bd211b85Ssemery	getBaseDN "$container" "$dom"
1223bd211b85Ssemery
1224bd211b85Ssemery	if [[ -n $KDC ]]; then
1225bd211b85Ssemery		dc=$KDC
1226bd211b85Ssemery	else
1227bd211b85Ssemery		getKDCDC
1228bd211b85Ssemery	fi
1229bd211b85Ssemery
1230bd211b85Ssemery	write_ads_krb5conf
1231bd211b85Ssemery
1232ae5b046dSsemery	printf "$(gettext "Attempting to join '%s' to the '%s' domain").\n\n" $upcase_nodename $realm
1233bd211b85Ssemery
1234bd211b85Ssemery	kinit $cprinc@$realm
1235bd211b85Ssemery	if [[ $? -ne 0 ]]; then
1236c386eb9cSShawn Emery		printf "$(gettext "Could not authenticate %s.  Exiting").\n" $cprinc@$realm >&2
1237bd211b85Ssemery		error_message
1238bd211b85Ssemery	fi
1239bd211b85Ssemery
1240bd211b85Ssemery	if getForestName
1241bd211b85Ssemery	then
1242bd211b85Ssemery		printf "\n$(gettext "Forest name found: %s")\n\n" $forest
1243bd211b85Ssemery	else
1244bd211b85Ssemery		printf "\n$(gettext "Forest name not found, assuming forest is the domain name").\n"
1245bd211b85Ssemery	fi
1246bd211b85Ssemery
1247bd211b85Ssemery	getGC
1248bd211b85Ssemery	getSite
1249bd211b85Ssemery
1250bd211b85Ssemery	if [[ -z $siteName ]]
1251bd211b85Ssemery	then
1252bd211b85Ssemery    		printf "$(gettext "Site name not found.  Local DCs/GCs will not be discovered").\n\n"
1253bd211b85Ssemery	else
1254bd211b85Ssemery    		printf "$(gettext "Looking for _local_ KDCs, DCs and global catalog servers (SRV RRs)").\n"
1255bd211b85Ssemery		getKDCDC
1256bd211b85Ssemery		getGC
1257bd211b85Ssemery
1258bd211b85Ssemery		write_ads_krb5conf
1259bd211b85Ssemery	fi
1260bd211b85Ssemery
1261bd211b85Ssemery	if [[ ${#GCs} -eq 0 ]]; then
1262c386eb9cSShawn Emery		printf "$(gettext "Could not find global catalogs.  Exiting").\n" >&2
1263bd211b85Ssemery		error_message
1264bd211b85Ssemery	fi
1265bd211b85Ssemery
1266bd211b85Ssemery	# Check to see if the client is transitioning between domains.
1267bd211b85Ssemery	compareDomains $realm
1268bd211b85Ssemery
1269bd211b85Ssemery	# Here we check domainFunctionality to see which release:
1270bd211b85Ssemery	# 0, 1, 2: Windows 2000, 2003 Interim, 2003 respecitively
1271bd211b85Ssemery	# 3: Windows 2008
1272bd211b85Ssemery	level=0
1273bd211b85Ssemery	ldapsearch -R -T -h "$dc" $ldap_args -b "" -s base "" \
1274bd211b85Ssemery	 domainControllerFunctionality| grep ^domainControllerFunctionality| \
1275bd211b85Ssemery	 read j level
1276bd211b85Ssemery	if [[ $? -ne 0 ]]; then
1277c386eb9cSShawn Emery		printf "$(gettext "Search for domain functionality failed, exiting").\n" >&2
1278bd211b85Ssemery		error_message
1279bd211b85Ssemery	fi
1280bd211b85Ssemery
1281bd211b85Ssemery	if ldapsearch -R -T -h "$dc" $ldap_args -b "$baseDN" \
1282bd211b85Ssemery	    -s sub sAMAccountName="$netbios_nodename" dn > /dev/null 2>&1
1283bd211b85Ssemery	then
1284bd211b85Ssemery		:
1285bd211b85Ssemery	else
1286c386eb9cSShawn Emery		printf "$(gettext "Search for node failed, exiting").\n" >&2
1287bd211b85Ssemery		error_message
1288bd211b85Ssemery	fi
1289bd211b85Ssemery	ldapsearch -R -T -h "$dc" $ldap_args -b "$baseDN" -s sub \
1290bd211b85Ssemery	    sAMAccountName="$netbios_nodename" dn|grep "^dn:"|read j dn
1291bd211b85Ssemery
1292bd211b85Ssemery	if [[ -z $dn ]]; then
1293bd211b85Ssemery		: # modify_existing is already false, which is what we want.
1294bd211b85Ssemery	else
1295bd211b85Ssemery		printf "$(gettext "Computer account '%s' already exists in the '%s' domain").\n" $upcase_nodename $realm
1296bd211b85Ssemery		query "$(gettext "Do you wish to recreate this computer account") ?"
1297bd211b85Ssemery		printf "\n"
1298bd211b85Ssemery		if [[ $answer == yes ]]; then
1299bd211b85Ssemery			recreate=true
1300bd211b85Ssemery		else
1301bd211b85Ssemery			modify_existing=true
1302bd211b85Ssemery		fi
1303bd211b85Ssemery	fi
1304bd211b85Ssemery
1305bd211b85Ssemery	if [[ $modify_existing == false && -n $dn ]]; then
1306bd211b85Ssemery		query "$(gettext "Would you like to delete any sub-object found for this computer account") ?"
1307bd211b85Ssemery		if [[ $answer == yes ]]; then
1308bd211b85Ssemery			printf "$(gettext "Looking to see if the machine account contains other objects")...\n"
1309bd211b85Ssemery			ldapsearch -R -T -h "$dc" $ldap_args -b "$dn" -s sub "" dn | while read j sub_dn
1310bd211b85Ssemery			do
1311bd211b85Ssemery				[[ $j != dn: || -z $sub_dn || $dn == $sub_dn ]] && continue
1312bd211b85Ssemery				if $recreate; then
1313bd211b85Ssemery					printf "$(gettext "Deleting the following object: %s")\n" ${sub_dn#$dn}
1314bd211b85Ssemery					ldapdelete -h "$dc" $ldap_args "$sub_dn" > /dev/null 2>&1
1315bd211b85Ssemery					if [[ $? -ne 0 ]]; then
1316bd211b85Ssemery						printf "$(gettext "Error in deleting object: %s").\n" ${sub_dn#$dn}
1317bd211b85Ssemery					fi
1318bd211b85Ssemery				else
1319bd211b85Ssemery					printf "$(gettext "The following object will not be deleted"): %s\n" ${sub_dn#$dn}
1320bd211b85Ssemery				fi
1321bd211b85Ssemery			done
1322bd211b85Ssemery		fi
1323bd211b85Ssemery
1324bd211b85Ssemery		if $recreate; then
1325bd211b85Ssemery			ldapdelete -h "$dc" $ldap_args "$dn" > /dev/null 2>&1
1326bd211b85Ssemery			if [[ $? -ne 0 ]]; then
1327c386eb9cSShawn Emery				printf "$(gettext "Error in deleting object: %s").\n" ${sub_dn#$dn} >&2
1328bd211b85Ssemery				error_message
1329bd211b85Ssemery			fi
1330bd211b85Ssemery		elif $modify_existing; then
1331bd211b85Ssemery			: # Nothing to delete
1332bd211b85Ssemery		else
1333c386eb9cSShawn Emery			printf "$(gettext "A machine account already exists").\n" >&2
1334bd211b85Ssemery			error_message
1335bd211b85Ssemery		fi
1336bd211b85Ssemery	fi
1337bd211b85Ssemery
133872f0806aSShawn Emery	[[ -z $dn ]] && dn="CN=${upcase_nodename},${baseDN}"
1339bd211b85Ssemery	if $modify_existing; then
1340bd211b85Ssemery		cat > "$object" <<EOF
134172f0806aSShawn Emerydn: $dn
1342bd211b85Ssemerychangetype: modify
1343bd211b85Ssemeryreplace: userPrincipalName
1344bd211b85SsemeryuserPrincipalName: $upn
1345bd211b85Ssemery-
1346bd211b85Ssemeryreplace: servicePrincipalName
1347bd211b85SsemeryservicePrincipalName: host/${fqdn}
1348bd211b85Ssemery-
1349bd211b85Ssemeryreplace: userAccountControl
1350bd211b85SsemeryuserAccountControl: $((userAccountControlBASE + 32 + 2))
1351bd211b85Ssemery-
1352bd211b85Ssemeryreplace: dNSHostname
1353bd211b85SsemerydNSHostname: ${fqdn}
1354bd211b85SsemeryEOF
1355bd211b85Ssemery
1356bd211b85Ssemery		printf "$(gettext "A machine account already exists; updating it").\n"
1357ae5b046dSsemery		ldapadd -h "$dc" $ldap_args -f "$object" > /dev/null 2>&1
1358bd211b85Ssemery		if [[ $? -ne 0 ]]; then
135972f0806aSShawn Emery			printf "$(gettext "Failed to modify the AD object via LDAP").\n" >&2
1360bd211b85Ssemery			error_message
1361bd211b85Ssemery		fi
1362bd211b85Ssemery	else
136372f0806aSShawn Emery		dn="CN=${upcase_nodename},${baseDN}"
1364bd211b85Ssemery		cat > "$object" <<EOF
136572f0806aSShawn Emerydn: $dn
1366bd211b85SsemeryobjectClass: computer
1367bd211b85Ssemerycn: $upcase_nodename
1368bd211b85SsemerysAMAccountName: ${netbios_nodename}
1369bd211b85SsemeryuserPrincipalName: $upn
1370bd211b85SsemeryservicePrincipalName: host/${fqdn}
1371bd211b85SsemeryuserAccountControl: $((userAccountControlBASE + 32 + 2))
1372bd211b85SsemerydNSHostname: ${fqdn}
1373bd211b85SsemeryEOF
1374bd211b85Ssemery
1375bd211b85Ssemery		printf "$(gettext "Creating the machine account in AD via LDAP").\n\n"
1376bd211b85Ssemery
1377bd211b85Ssemery		ldapadd -h "$dc" $ldap_args -f "$object" > /dev/null 2>&1
1378bd211b85Ssemery		if [[ $? -ne 0 ]]; then
1379c386eb9cSShawn Emery			printf "$(gettext "Failed to create the AD object via LDAP").\n" >&2
1380bd211b85Ssemery			error_message
1381bd211b85Ssemery		fi
1382bd211b85Ssemery	fi
1383bd211b85Ssemery
1384bd211b85Ssemery	# Generate a new password for the new account
1385986b458dSShawn Emery	MAX_PASS=120
1386bd211b85Ssemery        i=0
1387bd211b85Ssemery
1388986b458dSShawn Emery	# first check to see if /dev/random exists to generate a new password
1389986b458dSShawn Emery	if [[ ! -h /dev/random ]]; then
1390986b458dSShawn Emery		printf "$(gettext "/dev/random does not exist").\n" >&2
1391986b458dSShawn Emery		error_message
1392986b458dSShawn Emery	fi
1393986b458dSShawn Emery
1394bd211b85Ssemery	while ((MAX_PASS > i))
1395bd211b85Ssemery	do
1396986b458dSShawn Emery		# [MS-DISO] A machine password is an ASCII string of randomly
1397986b458dSShawn Emery		# chosen characters. Each character's ASCII code is between 32
1398986b458dSShawn Emery		# and 122 inclusive.
1399986b458dSShawn Emery		c=$(printf "\\$(printf %o $(($(gen_rand) % 91 + 32)))\n")
1400986b458dSShawn Emery		p="$p$c"
1401bd211b85Ssemery		((i+=1))
1402bd211b85Ssemery	done
1403bd211b85Ssemery
1404bd211b85Ssemery	newpw=$p
1405986b458dSShawn Emery	if [[ ${#newpw} -ne MAX_PASS ]]; then
1406986b458dSShawn Emery		printf "$(gettext "Password created was of incorrect length").\n" >&2
1407986b458dSShawn Emery		error_message
1408986b458dSShawn Emery	fi
1409bd211b85Ssemery
1410bd211b85Ssemery	# Set the new password
1411986b458dSShawn Emery	printf "%s" "$newpw" | $KSETPW ${netbios_nodename}@${realm} > /dev/null 2>&1
1412bd211b85Ssemery	if [[ $? -ne 0 ]]
1413bd211b85Ssemery	then
1414c386eb9cSShawn Emery		printf "$(gettext "Failed to set account password").\n" >&2
1415bd211b85Ssemery		error_message
1416bd211b85Ssemery	fi
1417bd211b85Ssemery
1418bd211b85Ssemery	# Lookup the new principal's kvno:
1419bd211b85Ssemery	ldapsearch -R -T -h "$dc" $ldap_args -b "$baseDN" \
1420bd211b85Ssemery		 -s sub cn=$upcase_nodename msDS-KeyVersionNumber| \
1421bd211b85Ssemery		grep "^msDS-KeyVersionNumber"|read j kvno
1422bd211b85Ssemery	[[ -z $kvno ]] && kvno=1
1423bd211b85Ssemery
1424bd211b85Ssemery	# Set supported enctypes.  This only works for Longhorn/Vista, so we
1425bd211b85Ssemery	# ignore errors here.
1426bd211b85Ssemery	userAccountControl=$((userAccountControlBASE + 524288 + 65536))
1427bd211b85Ssemery	set -A enctypes --
1428bd211b85Ssemery
1429bd211b85Ssemery	# Do we have local support for AES?
1430bd211b85Ssemery	encrypt -l|grep ^aes|read j minkeysize maxkeysize
1431bd211b85Ssemery	val=
1432bd211b85Ssemery	if [[ $maxkeysize -eq 256 ]]; then
1433bd211b85Ssemery		val=16
1434bd211b85Ssemery		enctypes[${#enctypes[@]}]=aes256-cts-hmac-sha1-96
1435bd211b85Ssemery	fi
1436bd211b85Ssemery	if [[ $minkeysize -eq 128 ]]; then
1437bd211b85Ssemery		((val=val+8))
1438bd211b85Ssemery		enctypes[${#enctypes[@]}]=aes128-cts-hmac-sha1-96
1439bd211b85Ssemery	fi
1440bd211b85Ssemery
1441bd211b85Ssemery	# RC4 comes next (whether it's better than 1DES or not -- AD prefers it)
1442f7dbdfc7SMarcel Telka	if encrypt -l|grep -q ^arcfour
1443bd211b85Ssemery	then
1444bd211b85Ssemery		((val=val+4))
1445bd211b85Ssemery		enctypes[${#enctypes[@]}]=arcfour-hmac-md5
1446bd211b85Ssemery	else
1447bd211b85Ssemery		# Use 1DES ONLY if we don't have arcfour
1448bd211b85Ssemery		userAccountControl=$((userAccountControl + 2097152))
1449bd211b85Ssemery	fi
1450f7dbdfc7SMarcel Telka	if encrypt -l | grep -q ^des
1451bd211b85Ssemery	then
1452c386eb9cSShawn Emery		((val=val+2))
1453bd211b85Ssemery		enctypes[${#enctypes[@]}]=des-cbc-md5
1454bd211b85Ssemery	fi
1455bd211b85Ssemery
1456bd211b85Ssemery	if [[ ${#enctypes[@]} -eq 0 ]]
1457bd211b85Ssemery	then
1458bd211b85Ssemery		printf "$(gettext "No enctypes are supported").\n"
1459c386eb9cSShawn Emery		printf "$(gettext "Please enable arcfour or 1DES, then re-join; see cryptoadm(1M)").\n" >&2
1460bd211b85Ssemery		error_message
1461bd211b85Ssemery	fi
1462bd211b85Ssemery
1463bd211b85Ssemery	# If domain crontroller is Longhorn or above then set new supported
1464bd211b85Ssemery	# encryption type attributes.
1465bd211b85Ssemery	if [[ $level -gt 2 ]]; then
1466bd211b85Ssemery		cat > "$object" <<EOF
146772f0806aSShawn Emerydn: $dn
1468bd211b85Ssemerychangetype: modify
1469bd211b85Ssemeryreplace: msDS-SupportedEncryptionTypes
1470bd211b85SsemerymsDS-SupportedEncryptionTypes: $val
1471bd211b85SsemeryEOF
1472bd211b85Ssemery		ldapmodify -h "$dc" $ldap_args -f "$object" >/dev/null 2>&1
1473bd211b85Ssemery		if [[ $? -ne 0 ]]; then
1474bd211b85Ssemery			printf "$(gettext "Warning: Could not set the supported encryption type for computer account").\n"
1475bd211b85Ssemery		fi
1476bd211b85Ssemery	fi
1477bd211b85Ssemery
1478bd211b85Ssemery	# We should probably check whether arcfour is available, and if not,
1479bd211b85Ssemery	# then set the 1DES only flag, but whatever, it's not likely NOT to be
1480bd211b85Ssemery	# available on S10/Nevada!
1481bd211b85Ssemery
1482bd211b85Ssemery	# Reset userAccountControl
1483bd211b85Ssemery	#
1484bd211b85Ssemery	#  NORMAL_ACCOUNT (512) | DONT_EXPIRE_PASSWORD (65536) |
1485bd211b85Ssemery	#  TRUSTED_FOR_DELEGATION (524288)
1486bd211b85Ssemery	#
1487bd211b85Ssemery	# and possibly UseDesOnly (2097152) (see above)
1488bd211b85Ssemery	#
1489bd211b85Ssemery	cat > "$object" <<EOF
149072f0806aSShawn Emerydn: $dn
1491bd211b85Ssemerychangetype: modify
1492bd211b85Ssemeryreplace: userAccountControl
1493bd211b85SsemeryuserAccountControl: $userAccountControl
1494bd211b85SsemeryEOF
1495bd211b85Ssemery	ldapmodify -h "$dc" $ldap_args -f "$object" >/dev/null 2>&1
1496bd211b85Ssemery	if [[ $? -ne 0 ]]; then
1497c386eb9cSShawn Emery		printf "$(gettext "ldapmodify failed to modify account attribute").\n" >&2
1498bd211b85Ssemery		error_message
1499bd211b85Ssemery	fi
1500bd211b85Ssemery
1501bd211b85Ssemery	# Setup a keytab file
1502bd211b85Ssemery	set -A args --
1503bd211b85Ssemery	for enctype in "${enctypes[@]}"
1504bd211b85Ssemery	do
1505bd211b85Ssemery		args[${#args[@]}]=-e
1506bd211b85Ssemery		args[${#args[@]}]=$enctype
1507bd211b85Ssemery	done
1508bd211b85Ssemery
1509bd211b85Ssemery	rm $new_keytab > /dev/null 2>&1
1510bd211b85Ssemery
1511bd211b85Ssemery	cat > "$object" <<EOF
151272f0806aSShawn Emerydn: $dn
1513bd211b85Ssemerychangetype: modify
1514bd211b85Ssemeryadd: servicePrincipalName
1515bd211b85SsemeryservicePrincipalName: nfs/${fqdn}
1516bd211b85SsemeryservicePrincipalName: HTTP/${fqdn}
1517bd211b85SsemeryservicePrincipalName: root/${fqdn}
1518c386eb9cSShawn EmeryservicePrincipalName: cifs/${fqdn}
151972f0806aSShawn EmeryservicePrincipalName: host/${upcase_nodename}
1520bd211b85SsemeryEOF
1521bd211b85Ssemery	ldapmodify -h "$dc" $ldap_args -f "$object" >/dev/null 2>&1
1522bd211b85Ssemery	if [[ $? -ne 0 ]]; then
1523c386eb9cSShawn Emery		printf "$(gettext "ldapmodify failed to modify account attribute").\n" >&2
1524bd211b85Ssemery		error_message
1525bd211b85Ssemery	fi
1526bd211b85Ssemery
1527c386eb9cSShawn Emery	#
1528c386eb9cSShawn Emery	# In Windows, unlike MIT based implementations we salt the keys with
152972f0806aSShawn Emery	# the UPN, which is based on the host/string15@realm elements, not
153072f0806aSShawn Emery	# with the individual SPN strings.
1531c386eb9cSShawn Emery	#
153272f0806aSShawn Emery	salt=host/${locase_nodename}.${domain}@${realm}
1533c386eb9cSShawn Emery
1534e1831dbbSShawn Emery	skeys=(host/${fqdn}@${realm} nfs/${fqdn}@${realm} HTTP/${fqdn}@${realm})
1535e1831dbbSShawn Emery	skeys+=(root/${fqdn}@${realm} cifs/${fqdn}@${realm})
1536e1831dbbSShawn Emery	skeys+=(${netbios_nodename}@${realm} host/${upcase_nodename}@${realm})
1537e1831dbbSShawn Emery	skeys+=(cifs/${upcase_nodename}@${realm})
1538c386eb9cSShawn Emery
1539e1831dbbSShawn Emery	ks_args="-n -s $salt -v $kvno -k $new_keytab ${args[@]}"
1540bd211b85Ssemery
1541e1831dbbSShawn Emery	for skey in ${skeys[@]}
1542e1831dbbSShawn Emery	do
1543e1831dbbSShawn Emery		printf "%s" "$newpw" | $KSETPW $ks_args $skey > /dev/null 2>&1
1544bd211b85Ssemery		if [[ $? -ne 0 ]]
1545bd211b85Ssemery		then
1546e1831dbbSShawn Emery			printf "$(gettext "Failed to set password").\n" >&2
1547bd211b85Ssemery			error_message
1548bd211b85Ssemery		fi
1549e1831dbbSShawn Emery	done
155072f0806aSShawn Emery
1551bd211b85Ssemery	doKRB5config
1552bd211b85Ssemery
1553bd211b85Ssemery	addDNSRR $dom
1554bd211b85Ssemery
1555bd211b85Ssemery	setSMB $dom $dc
1556bd211b85Ssemery
155772f0806aSShawn Emery	printf -- "---------------------------------------------------\n"
1558bd211b85Ssemery	printf "$(gettext "Setup COMPLETE").\n\n"
1559bd211b85Ssemery
1560bd211b85Ssemery	kdestroy -q 1>$TMP_FILE 2>&1
1561bd211b85Ssemery	rm -f $TMP_FILE
1562bd211b85Ssemery	rm -rf $TMPDIR > /dev/null 2>&1
1563bd211b85Ssemery
1564bd211b85Ssemery	exit 0
15657c478bd9Sstevel@tonic-gate}
15667c478bd9Sstevel@tonic-gate
15677c478bd9Sstevel@tonic-gate###########################
15687c478bd9Sstevel@tonic-gate#	Main section	  #
15697c478bd9Sstevel@tonic-gate###########################
15707c478bd9Sstevel@tonic-gate#
15717c478bd9Sstevel@tonic-gate# Set the Kerberos config file and some default strings/files
15727c478bd9Sstevel@tonic-gate#
1573bd211b85SsemeryKRB5_CONFIG_FILE=/etc/krb5/krb5.conf
1574bd211b85SsemeryKRB5_KEYTAB_FILE=/etc/krb5/krb5.keytab
1575bd211b85SsemeryRESOLV_CONF_FILE=/etc/resolv.conf
1576bd211b85Ssemery
1577bd211b85SsemeryKLOOKUP=/usr/lib/krb5/klookup;	check_bin $KLOOKUP
1578bd211b85SsemeryKSETPW=/usr/lib/krb5/ksetpw;	check_bin $KSETPW
1579bd211b85SsemeryKSMB=/usr/lib/krb5/ksmb;	check_bin $KSMB
1580bd211b85SsemeryKDYNDNS=/usr/lib/krb5/kdyndns;	check_bin $KDYNDNS
1581c48f4690SShawn EmeryKCONF=/usr/lib/krb5/kconf;	check_bin $KCONF
1582bd211b85Ssemery
1583bd211b85Ssemerydns_lookup=no
1584bd211b85Ssemeryask_fqdns=no
1585bd211b85Ssemeryadddns=no
1586ae5b046dSsemeryno_keytab=no
15877c478bd9Sstevel@tonic-gatecheckval=""
15887c478bd9Sstevel@tonic-gateprofile=""
1589bd211b85Ssemerytypeset -u realm
1590bd211b85Ssemerytypeset -l hostname KDC
15917c478bd9Sstevel@tonic-gate
1592bd211b85Ssemeryexport TMPDIR="/var/run/kclient"
15937c478bd9Sstevel@tonic-gate
1594bd211b85Ssemerymkdir $TMPDIR > /dev/null 2>&1
1595c386eb9cSShawn Emeryif [[ $? -ne 0 ]]; then
1596c386eb9cSShawn Emery	printf "\n$(gettext "Can not create directory: %s")\n\n" $TMPDIR >&2
1597c386eb9cSShawn Emery	exit 1
1598c386eb9cSShawn Emeryfi
15997c478bd9Sstevel@tonic-gate
1600bd211b85SsemeryTMP_FILE=$(mktemp -q -t kclient-tmpfile.XXXXXX)
1601bd211b85Ssemeryexport KRB5_CONFIG=$(mktemp -q -t kclient-krb5conf.XXXXXX)
1602ae5b046dSsemeryexport KRB5CCNAME=$(mktemp -q -t kclient-krb5ccache.XXXXXX)
1603bd211b85Ssemerynew_keytab=$(mktemp -q -t kclient-krb5keytab.XXXXXX)
1604bd211b85Ssemeryif [[ -z $TMP_FILE || -z $KRB5_CONFIG || -z $KRB5CCNAME || -z $new_keytab ]]
1605bd211b85Ssemerythen
1606c386eb9cSShawn Emery	printf "\n$(gettext "Can not create temporary files, exiting").\n\n" >&2
1607c386eb9cSShawn Emery	exit 1
16087c478bd9Sstevel@tonic-gatefi
16097c478bd9Sstevel@tonic-gate
16107c478bd9Sstevel@tonic-gate#
16117c478bd9Sstevel@tonic-gate# If we are interrupted, cleanup after ourselves
16127c478bd9Sstevel@tonic-gate#
1613bd211b85Ssemerytrap "exiting 1" HUP INT QUIT TERM
16147c478bd9Sstevel@tonic-gate
1615bd211b85Ssemeryif [[ -d /usr/bin ]]; then
1616bd211b85Ssemery	if [[ -d /usr/sbin ]]; then
16177c478bd9Sstevel@tonic-gate		PATH=/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:$PATH
16187c478bd9Sstevel@tonic-gate		export PATH
16197c478bd9Sstevel@tonic-gate	else
16207c478bd9Sstevel@tonic-gate		printf "\n$(gettext "Directory /usr/sbin not found, exiting").\n" >&2
16217c478bd9Sstevel@tonic-gate		exit 1
16227c478bd9Sstevel@tonic-gate	fi
16237c478bd9Sstevel@tonic-gateelse
16247c478bd9Sstevel@tonic-gate	printf "\n$(gettext "Directory /usr/bin not found, exiting").\n" >&2
16257c478bd9Sstevel@tonic-gate	exit 1
16267c478bd9Sstevel@tonic-gatefi
16277c478bd9Sstevel@tonic-gate
16287c478bd9Sstevel@tonic-gateprintf "\n$(gettext "Starting client setup")\n\n"
1629bd211b85Ssemeryprintf -- "---------------------------------------------------\n"
16307c478bd9Sstevel@tonic-gate
16317c478bd9Sstevel@tonic-gate#
16327c478bd9Sstevel@tonic-gate# Check for uid 0, disallow otherwise
16337c478bd9Sstevel@tonic-gate#
16347c478bd9Sstevel@tonic-gateid 1>$TMP_FILE 2>&1
1635bd211b85Ssemeryif [[ $? -eq 0 ]]; then
16367c478bd9Sstevel@tonic-gate	if egrep -s "uid=0\(root\)" $TMP_FILE; then
16377c478bd9Sstevel@tonic-gate		# uid is 0, go ahead ...
16387c478bd9Sstevel@tonic-gate		:
16397c478bd9Sstevel@tonic-gate	else
1640bd211b85Ssemery		printf "\n$(gettext "Administrative privileges are required to run this script, exiting").\n" >&2
16417c478bd9Sstevel@tonic-gate		error_message
16427c478bd9Sstevel@tonic-gate	fi
16437c478bd9Sstevel@tonic-gateelse
16447c478bd9Sstevel@tonic-gate	cat $TMP_FILE;
1645bd211b85Ssemery	printf "\n$(gettext "uid check failed, exiting").\n" >&2
16467c478bd9Sstevel@tonic-gate	error_message
16477c478bd9Sstevel@tonic-gatefi
16487c478bd9Sstevel@tonic-gate
1649bd211b85Ssemeryuname=$(uname -n)
1650bd211b85Ssemeryhostname=${uname%%.*}
16517c478bd9Sstevel@tonic-gate
16527c478bd9Sstevel@tonic-gate#
16537c478bd9Sstevel@tonic-gate# Process the command-line arguments (if any)
16547c478bd9Sstevel@tonic-gate#
16557c478bd9Sstevel@tonic-gateOPTIND=1
1656bd211b85Ssemerywhile getopts nD:Kp:R:k:a:c:d:f:h:m:s:T: OPTIONS
16577c478bd9Sstevel@tonic-gatedo
16587c478bd9Sstevel@tonic-gate	case $OPTIONS in
1659bd211b85Ssemery	    D) options="$options -D"
1660bd211b85Ssemery	       domain_list="$OPTARG"
1661bd211b85Ssemery	       ;;
1662bd211b85Ssemery	    K) options="$options -K"
1663bd211b85Ssemery	       no_keytab=yes
16647c478bd9Sstevel@tonic-gate	       ;;
16657c478bd9Sstevel@tonic-gate	    R) options="$options -R"
1666bd211b85Ssemery	       realm="$OPTARG"
1667bd211b85Ssemery	       checkval="REALM"; check_value $realm
16687c478bd9Sstevel@tonic-gate	       ;;
1669bd211b85Ssemery	    T) options="$options -T"
1670bd211b85Ssemery	       type="$OPTARG"
1671bd211b85Ssemery	       if [[ $type == ms_ad ]]; then
1672bd211b85Ssemery		msad=yes
1673bd211b85Ssemery		adddns=yes
1674bd211b85Ssemery	       else
1675bd211b85Ssemery		non_solaris=yes
1676bd211b85Ssemery		no_keytab=yes
1677bd211b85Ssemery	       fi
16787c478bd9Sstevel@tonic-gate	       ;;
16797c478bd9Sstevel@tonic-gate	    a) options="$options -a"
16807c478bd9Sstevel@tonic-gate	       ADMIN_PRINC="$OPTARG"
16817c478bd9Sstevel@tonic-gate	       checkval="ADMIN_PRINC"; check_value $ADMIN_PRINC
16827c478bd9Sstevel@tonic-gate	       ;;
16837c478bd9Sstevel@tonic-gate	    c) options="$options -c"
16847c478bd9Sstevel@tonic-gate	       filepath="$OPTARG"
16857c478bd9Sstevel@tonic-gate	       ;;
16867c478bd9Sstevel@tonic-gate	    d) options="$options -d"
16877c478bd9Sstevel@tonic-gate	       dnsarg="$OPTARG"
16887c478bd9Sstevel@tonic-gate	       checkval="DNS_OPTIONS"; check_value $dnsarg
16897c478bd9Sstevel@tonic-gate	       ;;
16907c478bd9Sstevel@tonic-gate	    f) options="$options -f"
16917c478bd9Sstevel@tonic-gate	       fqdnlist="$OPTARG"
1692bd211b85Ssemery 	       ;;
1693bd211b85Ssemery	    h) options="$options -h"
1694bd211b85Ssemery	       logical_hn="$OPTARG"
1695bd211b85Ssemery	       checkval="LOGICAL_HOSTNAME"; check_value $logical_hn
1696bd211b85Ssemery	       ;;
1697bd211b85Ssemery	    k) options="$options -k"
1698bd211b85Ssemery	       kdc_list="$OPTARG"
1699bd211b85Ssemery	       ;;
1700bd211b85Ssemery	    m) options="$options -m"
1701bd211b85Ssemery	       KDC="$OPTARG"
1702bd211b85Ssemery	       checkval="KDC"; check_value $KDC
17037c478bd9Sstevel@tonic-gate	       ;;
17047c478bd9Sstevel@tonic-gate	    n) options="$options -n"
17057c478bd9Sstevel@tonic-gate	       add_nfs=yes
17067c478bd9Sstevel@tonic-gate	       ;;
1707bd211b85Ssemery	    p) options="$options -p"
1708bd211b85Ssemery	       profile="$OPTARG"
1709bd211b85Ssemery	       read_profile $profile
1710bd211b85Ssemery	       ;;
1711bd211b85Ssemery	    s) options="$options -s"
1712bd211b85Ssemery	       svc_list="$OPTARG"
1713bd211b85Ssemery	       SVCs=${svc_list//,/ }
1714bd211b85Ssemery 	       ;;
17157c478bd9Sstevel@tonic-gate	    \?) usage
17167c478bd9Sstevel@tonic-gate	       ;;
17177c478bd9Sstevel@tonic-gate	    *) usage
17187c478bd9Sstevel@tonic-gate	       ;;
17197c478bd9Sstevel@tonic-gate	esac
17207c478bd9Sstevel@tonic-gatedone
17217c478bd9Sstevel@tonic-gate
17227c478bd9Sstevel@tonic-gate#correct argument count after options
17237c478bd9Sstevel@tonic-gateshift `expr $OPTIND - 1`
17247c478bd9Sstevel@tonic-gate
1725bd211b85Ssemeryif [[ -z $options ]]; then
17267c478bd9Sstevel@tonic-gate	:
17277c478bd9Sstevel@tonic-gateelse
1728bd211b85Ssemery	if [[ $# -ne 0 ]]; then
17297c478bd9Sstevel@tonic-gate		usage
17307c478bd9Sstevel@tonic-gate	fi
17317c478bd9Sstevel@tonic-gatefi
17327c478bd9Sstevel@tonic-gate
1733bd211b85Ssemery#
1734ae5b046dSsemery# Check to see if we will be a client of a MIT, Heimdal, Shishi, etc.
1735ae5b046dSsemery#
1736ae5b046dSsemeryif [[ -z $options ]]; then
1737ae5b046dSsemery	query "$(gettext "Is this a client of a non-Solaris KDC") ?"
1738ae5b046dSsemery	non_solaris=$answer
1739ae5b046dSsemery	if [[ $non_solaris == yes ]]; then
1740ae5b046dSsemery		printf "$(gettext "Which type of KDC is the server"):\n"
1741ae5b046dSsemery		printf "\t$(gettext "ms_ad: Microsoft Active Directory")\n"
1742ae5b046dSsemery		printf "\t$(gettext "mit: MIT KDC server")\n"
1743ae5b046dSsemery		printf "\t$(gettext "heimdal: Heimdal KDC server")\n"
1744ae5b046dSsemery		printf "\t$(gettext "shishi: Shishi KDC server")\n"
1745ae5b046dSsemery		printf "$(gettext "Enter required KDC type"): "
1746ae5b046dSsemery		read kdctype
1747ae5b046dSsemery		if [[ $kdctype == ms_ad ]]; then
1748ae5b046dSsemery			msad=yes
1749ae5b046dSsemery		elif [[ $kdctype == mit || $kdctype == heimdal || \
1750ae5b046dSsemery		    $kdctype == shishi ]]; then
1751ae5b046dSsemery			no_keytab=yes
1752ae5b046dSsemery		else
1753ae5b046dSsemery			printf "\n$(gettext "Invalid KDC type option, valid types are ms_ad, mit, heimdal, or shishi, exiting").\n" >&2
1754ae5b046dSsemery			error_message
1755ae5b046dSsemery		fi
1756ae5b046dSsemery	fi
1757ae5b046dSsemeryfi
1758ae5b046dSsemery
1759ae5b046dSsemery[[ $msad == yes ]] && join_domain
1760ae5b046dSsemery
1761ae5b046dSsemery#
1762bd211b85Ssemery# Check for /etc/resolv.conf
1763bd211b85Ssemery#
1764bd211b85Ssemeryif [[ -r $RESOLV_CONF_FILE ]]; then
1765bd211b85Ssemery	client_machine=`$KLOOKUP`
1766bd211b85Ssemery
1767bd211b85Ssemery	if [[ $? -ne 0 ]]; then
1768bd211b85Ssemery		if [[ $adddns == no ]]; then
1769bd211b85Ssemery			printf "\n$(gettext "%s does not have a DNS record and is required for Kerberos setup")\n" $hostname >&2
1770bd211b85Ssemery			error_message
1771bd211b85Ssemery		fi
1772bd211b85Ssemery
1773bd211b85Ssemery	else
1774bd211b85Ssemery		#
1775bd211b85Ssemery		# If client entry already exists then do not recreate it
1776bd211b85Ssemery		#
1777bd211b85Ssemery		adddns=no
1778bd211b85Ssemery
1779bd211b85Ssemery		hostname=${client_machine%%.*}
1780bd211b85Ssemery		domain=${client_machine#*.}
1781bd211b85Ssemery	fi
1782bd211b85Ssemery
1783bd211b85Ssemery	short_fqdn=${domain#*.*}
1784bd211b85Ssemery	short_fqdn=$(echo $short_fqdn | grep "\.")
1785bd211b85Ssemeryelse
1786bd211b85Ssemery	#
1787bd211b85Ssemery	# /etc/resolv.conf not present, exit ...
1788bd211b85Ssemery	#
1789bd211b85Ssemery	printf "\n$(gettext "%s does not exist and is required for Kerberos setup")\n" $RESOLV_CONF_FILE >&2
1790bd211b85Ssemery	printf "$(gettext "Refer to resolv.conf(4), exiting").\n" >&2
1791bd211b85Ssemery	error_message
1792bd211b85Ssemeryfi
1793bd211b85Ssemery
1794ae5b046dSsemerycheck_nss_conf || printf "$(gettext "/etc/nsswitch.conf does not make use of DNS for hosts and/or ipnodes").\n"
1795bd211b85Ssemery
1796bd211b85Ssemery[[ -n $fqdnlist ]] && verify_fqdnlist "$fqdnlist"
1797bd211b85Ssemery
1798ae5b046dSsemeryif [[ -z $dnsarg && (-z $options || -z $filepath) ]]; then
17997c478bd9Sstevel@tonic-gate	query "$(gettext "Do you want to use DNS for kerberos lookups") ?"
1800bd211b85Ssemery	if [[ $answer == yes ]]; then
1801bd211b85Ssemery		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"
1802bd211b85Ssemery		printf "\n$(gettext "Enter required DNS option"): "
18037c478bd9Sstevel@tonic-gate		read dnsarg
18047c478bd9Sstevel@tonic-gate		checkval="DNS_OPTIONS"; check_value $dnsarg
18057c478bd9Sstevel@tonic-gate		set_dns_value $dnsarg
18067c478bd9Sstevel@tonic-gate	fi
18077c478bd9Sstevel@tonic-gateelse
1808ae5b046dSsemery	[[ -z $dnsarg ]] && dnsarg=none
18097c478bd9Sstevel@tonic-gate	set_dns_value $dnsarg
18107c478bd9Sstevel@tonic-gatefi
18117c478bd9Sstevel@tonic-gate
1812bd211b85Ssemeryif [[ -n $kdc_list ]]; then
1813bd211b85Ssemery	if [[ -z $KDC ]]; then
1814bd211b85Ssemery		for kdc in $kdc_list; do
1815bd211b85Ssemery			break
1816bd211b85Ssemery		done
1817bd211b85Ssemery		KDC="$kdc"
18187c478bd9Sstevel@tonic-gate	fi
1819bd211b85Ssemeryfi
1820bd211b85Ssemery
1821ae5b046dSsemeryif [[ -z $realm ]]; then
1822bd211b85Ssemery	printf "$(gettext "Enter the Kerberos realm"): "
1823bd211b85Ssemery	read realm
1824bd211b85Ssemery	checkval="REALM"; check_value $realm
1825bd211b85Ssemeryfi
1826ae5b046dSsemeryif [[ -z $KDC ]]; then
1827bd211b85Ssemery	printf "$(gettext "Specify the master KDC hostname for the above realm"): "
18287c478bd9Sstevel@tonic-gate	read KDC
18297c478bd9Sstevel@tonic-gate	checkval="KDC"; check_value $KDC
18307c478bd9Sstevel@tonic-gatefi
18317c478bd9Sstevel@tonic-gate
1832bd211b85SsemeryFKDC=`$KLOOKUP $KDC`
18337c478bd9Sstevel@tonic-gate
18347c478bd9Sstevel@tonic-gate#
18357c478bd9Sstevel@tonic-gate# Ping to see if the kdc is alive !
18367c478bd9Sstevel@tonic-gate#
1837bd211b85Ssemeryping_check $FKDC "KDC"
18387c478bd9Sstevel@tonic-gate
1839ae5b046dSsemeryif [[ -z $kdc_list && (-z $options || -z $filepath) ]]; then
1840ae5b046dSsemery	query "$(gettext "Do you have any slave KDC(s)") ?"
1841ae5b046dSsemery	if [[ $answer == yes ]]; then
1842ae5b046dSsemery		printf "$(gettext "Enter a comma-separated list of slave KDC host names"): "
1843ae5b046dSsemery		read kdc_list
1844ae5b046dSsemery	fi
1845ae5b046dSsemeryfi
1846ae5b046dSsemery
1847ae5b046dSsemery[[ -n $kdc_list ]] && verify_kdcs "$kdc_list"
1848ae5b046dSsemery
1849bd211b85Ssemery#
1850bd211b85Ssemery# Check to see if we will have a dynamic presence in the realm
1851bd211b85Ssemery#
1852bd211b85Ssemeryif [[ -z $options ]]; then
1853bd211b85Ssemery	query "$(gettext "Will this client need service keys") ?"
1854bd211b85Ssemery	if [[ $answer == no ]]; then
1855bd211b85Ssemery		no_keytab=yes
1856bd211b85Ssemery	fi
1857bd211b85Ssemeryfi
1858bd211b85Ssemery
1859bd211b85Ssemery#
1860bd211b85Ssemery# Check to see if we are configuring the client to use a logical host name
1861bd211b85Ssemery# of a cluster environment
1862bd211b85Ssemery#
1863bd211b85Ssemeryif [[ -z $options ]]; then
1864bd211b85Ssemery	query "$(gettext "Is this client a member of a cluster that uses a logical host name") ?"
1865bd211b85Ssemery	if [[ $answer == yes ]]; then
1866bd211b85Ssemery		printf "$(gettext "Specify the logical hostname of the cluster"): "
1867bd211b85Ssemery		read logical_hn
1868bd211b85Ssemery		checkval="LOGICAL_HOSTNAME"; check_value $logical_hn
1869bd211b85Ssemery		setup_lhn
1870bd211b85Ssemery	fi
1871bd211b85Ssemeryfi
1872bd211b85Ssemery
1873ae5b046dSsemeryif [[ -n $domain_list && (-z $options || -z $filepath) ]]; then
1874bd211b85Ssemery	query "$(gettext "Do you have multiple domains/hosts to map to realm %s"
1875bd211b85Ssemery) ?" $realm
1876bd211b85Ssemery	if [[ $answer == yes ]]; then
1877ae5b046dSsemery		printf "$(gettext "Enter a comma-separated list of domain/hosts
1878bd211b85Ssemeryto map to the default realm"): "
1879bd211b85Ssemery		read domain_list
1880bd211b85Ssemery	fi
1881bd211b85Ssemeryfi
1882bd211b85Ssemery[[ -n domain_list ]] && domain_list=${domain_list//,/ }
18837c478bd9Sstevel@tonic-gate
18847c478bd9Sstevel@tonic-gate#
18857c478bd9Sstevel@tonic-gate# Start writing up the krb5.conf file, save the existing one
18867c478bd9Sstevel@tonic-gate# if already present
18877c478bd9Sstevel@tonic-gate#
18887c478bd9Sstevel@tonic-gatewriteup_krb5_conf
18897c478bd9Sstevel@tonic-gate
18907c478bd9Sstevel@tonic-gate#
1891bd211b85Ssemery# Is this client going to use krb-nfs?  If so then we need to at least
1892bd211b85Ssemery# uncomment the krb5* sec flavors in nfssec.conf.
18937c478bd9Sstevel@tonic-gate#
1894bd211b85Ssemeryif [[ -z $options ]]; then
18957c478bd9Sstevel@tonic-gate	query "$(gettext "Do you plan on doing Kerberized nfs") ?"
18967c478bd9Sstevel@tonic-gate	add_nfs=$answer
18977c478bd9Sstevel@tonic-gatefi
18987c478bd9Sstevel@tonic-gate
1899bd211b85Ssemeryif [[ $add_nfs == yes ]]; then
19007c478bd9Sstevel@tonic-gate	modify_nfssec_conf
19017c478bd9Sstevel@tonic-gate
19027c478bd9Sstevel@tonic-gate	#
1903bd211b85Ssemery	# We also want to enable gss as we now live in a SBD world
19047c478bd9Sstevel@tonic-gate	#
1905bd211b85Ssemery	svcadm enable svc:/network/rpc/gss:default
1906bd211b85Ssemery	[[ $? -ne 0 ]] && printf "$(gettext "Warning: could not enable gss service").\n"
1907bd211b85Ssemeryfi
1908bd211b85Ssemery
1909bd211b85Ssemeryif [[ -z $options ]]; then
1910bd211b85Ssemery	query "$(gettext "Do you want to update /etc/pam.conf") ?"
1911bd211b85Ssemery	if [[ $answer == yes ]]; then
1912bd211b85Ssemery		printf "$(gettext "Enter a list of PAM service names in the following format: service:{first|only|optional}[,..]"): "
1913bd211b85Ssemery		read svc_list
1914bd211b85Ssemery		SVCs=${svc_list//,/ }
1915bd211b85Ssemery	fi
1916bd211b85Ssemeryfi
1917bd211b85Ssemery[[ -n $svc_list ]] && update_pam_conf
1918bd211b85Ssemery
1919bd211b85Ssemery#
1920bd211b85Ssemery# Copy over krb5.conf master copy from filepath
1921bd211b85Ssemery#
1922bd211b85Ssemeryif [[ -z $options || -z $filepath ]]; then
19237c478bd9Sstevel@tonic-gate	query "$(gettext "Do you want to copy over the master krb5.conf file") ?"
1924bd211b85Ssemery	if [[ $answer == yes ]]; then
1925bd211b85Ssemery		printf "$(gettext "Enter the pathname of the file to be copied"): "
19267c478bd9Sstevel@tonic-gate		read filepath
19277c478bd9Sstevel@tonic-gate	fi
19287c478bd9Sstevel@tonic-gatefi
19297c478bd9Sstevel@tonic-gate
1930ae5b046dSsemeryif [[ -n $filepath && -r $filepath ]]; then
1931ae5b046dSsemery	cp $filepath $KRB5_CONFIG
1932bd211b85Ssemery	if [[ $? -eq 0 ]]; then
1933ae5b046dSsemery		printf "$(gettext "Copied %s to %s").\n" $filepath $KRB5_CONFIG
19347c478bd9Sstevel@tonic-gate	else
1935ae5b046dSsemery		printf "$(gettext "Copy of %s failed, exiting").\n" $filepath >&2
19367c478bd9Sstevel@tonic-gate		error_message
19377c478bd9Sstevel@tonic-gate	fi
1938ae5b046dSsemeryelif [[ -n $filepath ]]; then
1939bd211b85Ssemery	printf "\n$(gettext "%s not found, exiting").\n" $filepath >&2
19407c478bd9Sstevel@tonic-gate	error_message
19417c478bd9Sstevel@tonic-gatefi
1942ae5b046dSsemery
1943ae5b046dSsemerydoKRB5config
19447c478bd9Sstevel@tonic-gate
1945bd211b85Ssemery#
1946bd211b85Ssemery# Populate any service keys needed for the client in the keytab file
1947bd211b85Ssemery#
1948ae5b046dSsemeryif [[ $no_keytab != yes ]]; then
1949ae5b046dSsemery	setup_keytab
1950ae5b046dSsemeryelse
1951ae5b046dSsemery	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
1952ae5b046dSsemery	printf "$(gettext "Client will also not be able to host services that use Kerberos").\n"
1953ae5b046dSsemeryfi
1954bd211b85Ssemery
1955bd211b85Ssemeryprintf -- "\n---------------------------------------------------\n"
1956bd211b85Ssemeryprintf "$(gettext "Setup COMPLETE").\n\n"
19577c478bd9Sstevel@tonic-gate
19587c478bd9Sstevel@tonic-gate#
1959bd211b85Ssemery# If we have configured the client in a cluster we need to remind the user
1960bd211b85Ssemery# to propagate the keytab and configuration files to the other members.
19617c478bd9Sstevel@tonic-gate#
1962bd211b85Ssemeryif [[ -n $logical_hn ]]; then
1963bd211b85Ssemery	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"
1964bd211b85Ssemeryfi
1965bd211b85Ssemery
1966bd211b85Ssemery#
1967bd211b85Ssemery# Cleanup.
1968bd211b85Ssemery#
1969bd211b85Ssemerykdestroy -q 1>$TMP_FILE 2>&1
19707c478bd9Sstevel@tonic-gaterm -f $TMP_FILE
1971bd211b85Ssemeryrm -rf $TMPDIR > /dev/null 2>&1
19727c478bd9Sstevel@tonic-gateexit 0
1973