xref: /titanic_51/usr/src/cmd/krb5/kadmin/kdcmgr/kdcmgr.sh (revision b453864f3587ccc3324d7a3b0438a1e542dcfde7)
1#!/usr/bin/ksh
2#
3# CDDL HEADER START
4#
5# The contents of this file are subject to the terms of the
6# Common Development and Distribution License (the "License").
7# You may not use this file except in compliance with the License.
8#
9# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10# or http://www.opensolaris.org/os/licensing.
11# See the License for the specific language governing permissions
12# and limitations under the License.
13#
14# When distributing Covered Code, include this CDDL HEADER in each
15# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16# If applicable, add the following below this CDDL HEADER, with the
17# fields enclosed by brackets "[]" replaced with your own identifying
18# information: Portions Copyright [yyyy] [name of copyright owner]
19#
20# CDDL HEADER END
21#
22# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23# Use is subject to license terms.
24#
25
26#
27# This command provides an simple interface to configure, destroy, and to obtain
28# the status of a master or slave Kerberos KDC server.
29#
30
31function usage {
32
33	app=`basename $0`
34
35	printf "\n$(gettext "Usage: %s [ -a admprincipal ] [ -e enctype ] [ -h ]")\n" $app
36	printf "\t$(gettext "[ -p pwfile ] [ -r realm ] subcommand")\n\n"
37
38	printf "\t$(gettext "-a: Create non-default admin principal.")\n"
39	printf "\t$(gettext "-e: Encryption type used to encrypt the master key")\n"
40	printf "\t$(gettext "-h: This help message.")\n"
41	printf "\t$(gettext "-p: File that contains the admin principal and master key password.")\n"
42	printf "\t$(gettext "-r: Set the default realm for this server.")\n\n"
43
44	printf "\t$(gettext "where 'subcommand' is one of the following:")\n\n"
45
46	printf "\t$(gettext "create [ master ]")\n"
47	printf "\t$(gettext "create [ -m masterkdc ] slave")\n"
48	printf "\t$(gettext "destroy")\n"
49	printf "\t$(gettext "status")\n\n"
50
51	cleanup 1
52}
53
54function ask {
55
56	# ask question, set global answer
57	typeset question=$1 default_answer=$2
58	if [[ -z $default_answer ]]; then
59		print "$question \c"
60	else
61		print "$question [$default_answer]: \c"
62	fi
63	read answer
64	[ -z "$answer" ] && answer="$default_answer"
65}
66
67function yesno {
68
69	typeset question="$1"
70	# answer is a global set by ask
71	answer=
72	yn=`printf "$(gettext "y/n")"`
73	y=`printf "$(gettext "y")"`
74	n=`printf "$(gettext "n")"`
75	yes=`printf "$(gettext "yes")"`
76	no=`printf "$(gettext "no")"`
77
78	while [[ -z $answer ]]; do
79		ask "$question" $yn
80		case $answer in
81			$y|$yes)	answer=yes;;
82			$n|$no)		answer=no;;
83			*)		answer=;;
84		esac
85	done
86}
87
88function query {
89
90	yesno "$*"
91	if [[ $answer = no ]]; then
92		printf "\t$(gettext "No action performed").\n"
93	fi
94}
95
96function cleanup {
97
98	integer ret=$1
99
100	kdestroy -q -c $TMP_CCACHE 1>$TMP_FILE 2>&1
101        rm -f $TMP_FILE
102
103        exit $ret
104}
105
106function error_message {
107
108        printf "---------------------------------------------------\n"
109        printf "$(gettext "Setup FAILED").\n\n"
110
111	cleanup 1
112}
113
114function check_bin {
115
116	bin=$1
117
118	if [[ ! -x $bin ]]; then
119		printf "$(gettext "Could not access/execute %s").\n" $bin
120		error_message
121	fi
122}
123
124function check_ret {
125
126	integer ret=$1
127	prog=$2
128
129	if [[ $ret -ne 0 ]]; then
130		printf "\n$(gettext "%s failed with return value %d, exiting").\n\n" $prog $ret
131		error_message
132	fi
133}
134
135
136function ok_to_proceed {
137
138	yesno "$@"
139
140	if [[ $answer = no ]]; then
141		printf "\n$(gettext "Exiting, no action performed")\n\n"
142		cleanup 0
143	fi
144}
145
146function check_value {
147
148	typeset arg="$1"
149
150	if [[ -z $arg ]]; then
151		printf "\n$(gettext "No input obtained for %s, exiting").\n" $checkval
152		error_message
153	else
154		echo "$arg">$TMP_FILE
155		if egrep -s '[*$^#!]+' $TMP_FILE; then
156			printf "\n$(gettext "Invalid input obtained for %s, exiting").\n" $checkval
157			error_message
158		fi
159	fi
160}
161
162function setup_kdc_conf {
163
164	printf "\n$(gettext "Setting up %s").\n" $KRB5_KDC_CONF
165
166	if [[ -r $KRB5_KDC_CONF ]]; then
167		cat $KRB5_KDC_CONF > $KRB5_KDC_CONF.sav
168		cannot_create $KRB5_KDC_CONF.sav $?
169	fi
170
171	exec 3>$KRB5_KDC_CONF
172	if [[ $? -ne 0 ]]; then
173		printf "\n$(gettext "Cannot write to %s, exiting").\n" $KRB5_KDC_CONF
174		error_message
175	fi
176
177	printf "\n[kdcdefaults]\n\tkdc_ports = 88,750\n\n" 1>&3
178	printf "[realms]\n\t$REALM = {\n" 1>&3
179	printf "\t\tprofile = $KRB5_KRB_CONF\n" 1>&3
180	printf "\t\tdatabase_name = $PRINCDB\n" 1>&3
181	printf "\t\tmaster_key_type = $ENCTYPE\n" 1>&3
182	printf "\t\tacl_file = $KADM5ACL\n" 1>&3
183	printf "\t\tkadmind_port = 749\n" 1>&3
184	printf "\t\tmax_life = 8h 0m 0s\n" 1>&3
185	printf "\t\tmax_renewable_life = 7d 0h 0m 0s\n" 1>&3
186	printf "\t\tdefault_principal_flags = +preauth\n" 1>&3
187
188	printf "\t\tsunw_dbprop_enable = true\n" 1>&3
189	if [[ $master = yes ]]; then
190		printf "\t\tsunw_dbprop_master_ulogsize = 1000\n" 1>&3
191	fi
192	if [[ $slave = yes ]]; then
193		printf "\t\tsunw_dbprop_slave_poll = 2m\n" 1>&3
194	fi
195
196	printf "\t}\n" 1>&3
197}
198
199function setup_krb_conf {
200
201	printf "\n$(gettext "Setting up %s").\n" $KRB5_KRB_CONF
202
203	if [[ -r $KRB5_KRB_CONF ]]; then
204		cat $KRB5_KRB_CONF > $KRB5_KRB_CONF.sav
205		cannot_create $KRB5_KRB_CONF.sav $?
206	fi
207
208	exec 3>$KRB5_KRB_CONF
209	if [[ $? -ne 0 ]]; then
210		printf "\n$(gettext "Cannot write to %s, exiting").\n" $KRB5_KRB_CONF
211		error_message
212	fi
213
214	printf "[libdefaults]\n" 1>&3
215	printf "\tdefault_realm = $REALM\n\n" 1>&3
216
217	printf "[realms]\n" 1>&3
218	printf "\t$REALM = {\n" 1>&3
219	if [[ $slave = yes ]]; then
220		printf "\t\tkdc = $master_hn\n" 1>&3
221	fi
222	printf "\t\tkdc = $fqhn\n" 1>&3
223	if [[ $master = yes ]]; then
224		printf "\t\tadmin_server = $fqhn\n" 1>&3
225	else
226		printf "\t\tadmin_server = $master_hn\n" 1>&3
227	fi
228	printf "\t}\n\n" 1>&3
229
230	printf "[domain_realm]\n" 1>&3
231	printf "\t.$domain = $REALM\n\n" 1>&3
232
233	printf "[logging]\n" 1>&3
234	printf "\tdefault = FILE:/var/krb5/kdc.log\n" 1>&3
235	printf "\tkdc = FILE:/var/krb5/kdc.log\n" 1>&3
236	printf "\tkdc_rotate = {\n\t\tperiod = 1d\n\t\tversions = 10\n\t}\n\n" 1>&3
237
238	printf "[appdefaults]\n" 1>&3
239	printf "\tkinit = {\n\t\trenewable = true\n\t\tforwardable = true\n" 1>&3
240	printf "\t}\n" 1>&3
241}
242
243function cannot_create {
244
245	typeset filename="$1"
246	typeset stat="$2"
247	if [[ $stat -ne 0 ]]; then
248		printf "\n$(gettext "Cannot create/edit %s, exiting").\n" $filename
249		error_message
250	fi
251}
252
253function check_admin {
254
255	message=$1
256
257	if [[ -z $ADMIN_PRINC ]]; then
258		printf "$message"
259		read ADMIN_PRINC
260		checkval="ADMIN_PRINC"; check_value $ADMIN_PRINC
261	fi
262
263	echo "$ADMIN_PRINC">$TMP_FILE
264
265	if egrep -s '\/admin' $TMP_FILE; then
266		# Already in "/admin" format, do nothing
267		:
268	else
269		if egrep -s '\/' $TMP_FILE; then
270			printf "\n$(gettext "Improper entry for krb5 admin principal, exiting").\n"
271			error_message
272		else
273			ADMIN_PRINC=$(echo "$ADMIN_PRINC/admin")
274		fi
275	fi
276
277}
278
279function ping_check {
280
281	typeset machine="$1"
282
283	if $PING $machine > /dev/null 2>&1; then
284		:
285	else
286		printf "\n$(gettext "%s %s is unreachable, exiting").\n" $string $machine
287		error_message
288	fi
289}
290
291function check_host {
292
293	host=$(echo "$host"|tr '[A-Z]' '[a-z]')
294
295	echo "$host">$TMP_FILE
296	if egrep -s '[^.]\.[^.]+$' $TMP_FILE; then
297		# do nothing, host is in fqhn format
298		:
299	else
300		if egrep -s '\.+' $TMP_FILE; then
301			printf "\n$(gettext "Improper format of host name: '%s'").\n"
302			printf "$(gettext "Expecting the following format: 'somehost.example.com' or 'somehost', exiting").\n"
303			error_message
304		else
305			# Attach fqdn to host, to get the Fully Qualified Domain
306			# Name of the host requested
307			host=$(echo "$host.$domain")
308		fi
309	fi
310
311	#
312	# Ping to see if the host is alive!
313	#
314	ping_check $host
315}
316
317function kill_daemons {
318
319	# Kill daemons so they won't go into maintenance mode
320	$SVCADM disable -s krb5kdc
321	if [[ $? -ne 0 ]]; then
322		printf "\n$(gettext "Error in disabling krb5kdc, exiting").\n"
323		error_message
324	fi
325	$SVCADM disable -s kadmin
326	if [[ $? -ne 0 ]]; then
327		printf "\n$(gettext "Error in disabling kadmind, exiting").\n"
328		error_message
329	fi
330	$SVCADM disable -s krb5_prop
331	if [[ $? -ne 0 ]]; then
332		printf "\n$(gettext "Error in disabling kpropd, exiting").\n"
333		error_message
334	fi
335
336	# Make sure that none of the daemons outside of SMF are running either
337	pkill kadmind
338	if [[ $? -gt 1 ]]; then
339		printf "\n$(gettext "Error in killing kadmind, exiting").\n"
340		error_message
341	fi
342	pkill krb5kdc
343	if [[ $? -gt 1 ]]; then
344		printf "\n$(gettext "Error in killing krb5kdc, exiting").\n"
345		error_message
346	fi
347	pkill kpropd
348	if [[ $? -gt 1 ]]; then
349		printf "\n$(gettext "Error in killing kpropd, exiting").\n"
350		error_message
351	fi
352}
353
354function setup_mkeytab {
355
356	check_admin "\n$(gettext "Enter the krb5 administrative principal to be created"): \c"
357
358	if [[ -z $PWFILE ]]; then
359		echo
360		$KADMINL -q "ank $ADMIN_PRINC"
361		check_ret $? $KADMINL
362	else
363		cat $PWFILE $PWFILE | $KADMINL -q "ank $ADMIN_PRINC" > /dev/null 2>&1
364		check_ret $? $KADMINL
365	fi
366
367	$KADMINL -q "ank -randkey host/$fqhn" 1>$TMP_FILE 2>&1
368	check_ret $? $KADMINL
369	$KADMINL -q "ktadd host/$fqhn" 1>$TMP_FILE 2>&1
370	check_ret $? $KADMINL
371}
372
373function setup_skeytab {
374
375	check_admin "\n$(gettext "Enter the krb5 administrative principal to be used"): \c"
376
377	printf "$(gettext "Obtaining TGT for %s") ...\n" $ADMIN_PRINC
378
379	if [[ -z $PWFILE ]]; then
380		kinit -c $TMP_CCACHE -S kadmin/$master_hn $ADMIN_PRINC
381		check_ret $? kinit
382	else
383		cat $PWFILE | kinit -c $TMP_CCACHE -S kadmin/$master_hn \
384			$ADMIN_PRINC > /dev/null 2>&1
385	fi
386	klist -c $TMP_CCACHE 1>$TMP_FILE 2>&1
387	if egrep -s "$(gettext "Valid starting")" $TMP_FILE && \
388	   egrep -s "kadmin/$master_hn@$REALM" $TMP_FILE; then
389		:
390	else
391		printf "\n$(gettext "kinit of %s failed, exiting").\n" $ADMIN_PRINC
392		error_message
393	fi
394
395	$KADMIN -c $TMP_CCACHE -q "ank -randkey kiprop/$fqhn" 1>$TMP_FILE 2>&1
396	check_ret $? $KADMIN
397	$KADMIN -c $TMP_CCACHE -q "ktadd kiprop/$fqhn" 1>$TMP_FILE 2>&1
398	check_ret $? $KADMIN
399
400	$KADMIN -c $TMP_CCACHE -q "ank -randkey host/$fqhn" 1>$TMP_FILE 2>&1
401	check_ret $? $KADMIN
402	$KADMIN -c $TMP_CCACHE -q "ktadd host/$fqhn" 1>$TMP_FILE 2>&1
403	check_ret $? $KADMIN
404
405	kdestroy -q -c $TMP_CCACHE 1>$TMP_FILE 2>&1
406	check_ret $? $kdestroy
407}
408
409function setup_kadm5acl {
410
411	printf "\n$(gettext "Setting up %s").\n" $KADM5ACL
412
413	if [[ -r $KADM5ACL ]]; then
414		cat $KADM5ACL > $KADM5ACL.sav
415		cannot_create $KADM5ACL.sav $?
416	fi
417
418	exec 3>$KADM5ACL
419	if [[ $? -ne 0 ]]; then
420		printf "\n$(gettext "Cannot write to %s, exiting").\n" $KADM5ACL
421		error_message
422	fi
423
424	if [[ $master = yes ]]; then
425		printf "\n$ADMIN_PRINC@$REALM\t\tacmil\n" 1>&3
426		printf "\nkiprop/*@$REALM\t\tp\n" 1>&3
427	else
428		printf "\n*/admin@___default_realm___\t\t*\n" 1>&3
429	fi
430}
431
432function setup_kpropdacl {
433
434	printf "\n$(gettext "Setting up %s").\n\n" $KPROPACL
435
436	if [[ -r $KPROPACL ]]; then
437		cat $KPROPACL > $KPROPACL.sav
438		cannot_create $KPROPACL.sav $?
439	fi
440
441	exec 3>$KPROPACL
442	if [[ $? -ne 0 ]]; then
443		printf "\n$(gettext "Cannot write to %s, exiting").\n" $KPROPACL
444		error_message
445	fi
446	printf "\nhost/$master_hn@$REALM\n" 1>&3
447}
448
449function setup_master {
450
451	# create principal DB (KDB)
452	if [[ -z $PWFILE ]]; then
453		echo
454		kdb5_util create
455		check_ret $? kdb5_util
456	else
457		cat $PWFILE $PWFILE | kdb5_util create > /dev/null
458		check_ret $? kdb5_util
459	fi
460
461	setup_mkeytab
462	setup_kadm5acl
463
464	$SVCADM enable -r -s krb5kdc
465	$SVCADM enable -r -s kadmin
466}
467
468function setup_slave {
469
470	integer count=1
471
472	setup_skeytab
473
474	# Clear the kadm5acl, since the start methods look at this file
475	# to see if the server has been configured as a master server
476	setup_kadm5acl
477
478	setup_kpropdacl
479
480	$SVCADM enable -r -s krb5_prop
481
482	# Wait for full propagation of the database, in some environments
483	# this could take a few seconds
484	while [[ ! -f /var/krb5/principal ]]; do
485		if [[ count -gt $LOOPCNT ]]; then
486			printf "\n$(gettext "Could not receive updates from the master").\n"
487                        error_message
488			((count = count + 1))
489		fi
490		printf "$(gettext "Waiting for database from master")...\n"
491		sleep $SLEEPTIME
492	done
493
494	# The database is propagated now we need to create the stash file
495	if [[ -z $PWFILE ]]; then
496		kdb5_util stash
497		check_ret $? kdb5_util
498	else
499		cat $PWFILE | kdb5_util stash > /dev/null 2>&1
500		check_ret $? kdb5_util
501	fi
502
503	$SVCADM enable -r -s krb5kdc
504}
505
506function destroy_kdc {
507
508	# Check first to see if this is an existing KDC or server
509	if [[ -f $KRB5KT || -f $PRINCDB || -f $OLDPRINCDB ]]
510	then
511		if [[ -z $PWFILE ]]; then
512			printf "\n$(gettext "Some of the following files are present on this system"):\n"
513			echo "\t$KRB5KT\n\t$PRINCDB\n\t$OLDPRINCDB\n\t$STASH\n"
514			if [[ -z $d_option ]]; then
515				printf "$(gettext "You must first run 'kdcmgr destroy' to remove all of these files before creating a KDC server").\n\n"
516				cleanup 1
517			else
518				ok_to_proceed "$(gettext "All of these files will be removed, okay to proceed?")"
519			fi
520		fi
521	else
522		if [[ -n $d_option ]]; then
523			printf "\n$(gettext "No KDC related files exist, exiting").\n\n"
524			cleanup 0
525		fi
526		return
527	fi
528
529	printf "$(gettext "yes")\n" | kdb5_util destroy > /dev/null 2>&1
530	rm -f $KRB5KT
531}
532
533function kadm5_acl_configed {
534
535	if [[ -s $KADM5ACL ]]; then
536		grep -v '^[    ]*#' $KADM5ACL | \
537			egrep '_default_realm_' > /dev/null 2>&1
538		if [[ $? -gt 0 ]]; then
539			return 0
540		fi
541	fi
542
543	return 1
544}
545
546function status_kdc {
547
548	integer is_master=0
549
550	printf "\n$(gettext "KDC Status Information")\n"
551	echo "--------------------------------------------"
552	svcs -xv svc:/network/security/krb5kdc:default
553
554	if kadm5_acl_configed; then
555		is_master=1
556		printf "\n$(gettext "KDC Master Status Information")\n"
557		echo "--------------------------------------------"
558		svcs -xv svc:/network/security/kadmin:default
559	else
560		printf "\n$(gettext "KDC Slave Status Information")\n"
561		echo "--------------------------------------------"
562		svcs -xv svc:/network/security/krb5_prop:default
563	fi
564
565	printf "\n$(gettext "Transaction Log Information")\n"
566	echo "--------------------------------------------"
567	/usr/sbin/kproplog -h
568
569	printf "$(gettext "Kerberos Related File Information")\n"
570	echo "--------------------------------------------"
571	printf "$(gettext "(will display any missing files below)")\n"
572	FILELIST="$KRB5_KDC_CONF $KRB5_KRB_CONF $KADM5ACL $KRB5KT $PRINCDB "
573	for file in $FILELIST; do
574		if [[ ! -s $file ]]; then
575			printf "$(gettext "%s not found").\n" $file
576		fi
577	done
578	if [[ $is_master -eq 0 && ! -s $KPROPACL ]]; then
579		printf "$(gettext "%s not found").\n" $KPROPACL
580	fi
581
582	test ! -s $STASH &&
583	    printf "$(gettext "Stash file not found") (/var/krb5/.k5.*).\n"
584	echo
585
586	cleanup 0
587}
588
589# Start of Main script
590
591# Defaults
592KRB5_KDC_CONF=/etc/krb5/kdc.conf
593KRB5_KRB_CONF=/etc/krb5/krb5.conf
594KADM5ACL=/etc/krb5/kadm5.acl
595KPROPACL=/etc/krb5/kpropd.acl
596
597KRB5KT=/etc/krb5/krb5.keytab
598PRINCDB=/var/krb5/principal
599OLDPRINCDB=/var/krb5/principal.old
600STASH=/var/krb5/.k5.*
601
602KADMINL=/usr/sbin/kadmin.local;	check_bin $KADMINL
603KADMIN=/usr/sbin/kadmin;	check_bin $KADMIN
604KDCRES=/usr/lib/krb5/klookup;	check_bin $KDCRES
605SVCADM=/usr/sbin/svcadm;	check_bin $SVCADM
606PING=/usr/sbin/ping;		check_bin $PING
607
608ENCTYPE=aes128-cts-hmac-sha1-96
609LOOPCNT=10
610SLEEPTIME=5
611
612if [[ -x /usr/bin/mktemp ]]; then
613	TMP_FILE=$(/usr/bin/mktemp /etc/krb5/krb5tmpfile.XXXXXX)
614	TMP_CCACHE=$(/usr/bin/mktemp /etc/krb5/krb5tmpccache.XXXXXX)
615else
616	TMP_FILE="/etc/krb5/krb5tmpfile.$$"
617	TMP_CCACHE="/etc/krb5/krb5tmpccache.$$"
618fi
619
620if [[ ! -f /etc/resolv.conf ]]; then
621	printf "$(gettext "Error: need to configure /etc/resolv.conf").\n"
622
623	cleanup 1
624fi
625
626fqhn=`$KDCRES`
627if [[ -n "$fqhn" ]]; then
628	:
629elif [[ -n $(hostname) && -n $(domainname) ]]; then
630	fqhn=$(hostname|cut -f1 -d'.').$(domainname|cut -f2- -d'.'|/usr/ucb/tr 'A-Z' 'a-z')
631else
632	printf "$(gettext "Error: can not determine full hostname (FQHN).  Aborting")\n"
633	printf "$(gettext "Note, trying to use hostname and domainname to get FQHN").\n"
634
635	cleanup 1
636fi
637
638ping_check $fqhn
639
640domain=${fqhn#*.} # remove host part
641
642exitmsg=`printf "$(gettext "Exiting...")"`
643
644trap "echo $exitmsg; rm -f $TMP_FILE $TMP_CCACHE; exit 1" HUP INT QUIT TERM
645
646while getopts :a:e:hp:r:s flag
647do
648	case "$flag" in
649		a)	ADMIN_PRINC=$OPTARG;;
650		e)	ENCTYPE=$OPTARG;;
651		h)	usage;;
652		p)	PWFILE=$OPTARG
653			if [[ ! -r $PWFILE ]]; then
654				printf "\n$(gettext "Password file %s does not exist, exiting").\n\n" $PWFILE
655				cleanup 1
656			fi
657			;;
658		r)	REALM=$OPTARG;;
659		*)	usage;;
660	esac
661done
662shift $(($OPTIND - 1))
663
664case "$*" in
665	create)			master=yes;;
666	"create master")	master=yes;;
667	"create -m "*)		host=$3
668				checkval="MASTER"; check_value $host
669				check_host
670				master_hn=$host
671				if [[ $4 != slave ]]; then
672					usage
673				fi;&
674	"create slave")		slave=yes;;
675	destroy)		d_option=yes
676				kill_daemons
677				destroy_kdc
678				cleanup 0;;
679	status)			status_kdc;;
680	*)			usage;;
681esac
682
683kill_daemons
684
685printf "\n$(gettext "Starting server setup")\n"
686printf "---------------------------------------------------\n"
687
688# Checks for existing kdb and destroys if desired
689destroy_kdc
690
691if [[ -z $REALM ]]; then
692	printf "$(gettext "Enter the Kerberos realm"): \c"
693	read REALM
694	checkval="REALM"; check_value $REALM
695fi
696REALM=$(echo "$REALM"|tr '[a-z]' '[A-Z]')
697
698if [[ -z $master && -z $slave ]]; then
699	query "$(gettext "Is this machine to be configured as a master?"): \c"
700	master=$answer
701
702	if [[ $answer = no ]]; then
703		query "$(gettext "Is this machine to be configured as a slave?"): \c"
704		slave=$answer
705		if [[ $answer = no ]]; then
706			printf "\n$(gettext "Machine must either be a master or a slave KDC server").\n"
707			error_message
708		fi
709	fi
710fi
711
712if [[ $slave = yes && -z $master_hn ]]; then
713	printf "$(gettext "What is the master KDC's host name?"): \c"
714	read host
715	checkval="MASTER"; check_value $host
716	check_host
717	master_hn=$host
718fi
719
720setup_kdc_conf
721
722setup_krb_conf
723
724if [[ $master = yes ]]; then
725	setup_master
726else
727	setup_slave
728fi
729
730printf "\n---------------------------------------------------\n"
731printf "$(gettext "Setup COMPLETE").\n\n"
732
733cleanup 0
734