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.
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.
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]
22 # Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 # Use is subject to license terms.
27 # This command provides an simple interface to configure, destroy, and to obtain
28 # the status of a master or slave Kerberos KDC server.
35 printf "\n$(gettext "Usage
: %s
[ -a admprincipal
] [ -e enctype
] [ -h ]")\n" $app
36 printf "\t$(gettext "[ -p pwfile
] [ -r realm
] subcommand
")\n\n"
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"
44 printf "\t$(gettext "where
'subcommand' is one of the following
:")\n\n"
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"
56 # ask question, set global answer
57 typeset question
=$1 default_answer
=$2
58 if [[ -z $default_answer ]]; then
61 print
"$question [$default_answer]: \c"
64 [ -z "$answer" ] && answer
="$default_answer"
70 # answer is a global set by ask
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")"`
78 while [[ -z $answer ]]; do
91 if [[ $answer = no
]]; then
92 printf "\t$(gettext "No action performed
").\n"
100 kdestroy
-q -c $TMP_CCACHE 1>$TMP_FILE 2>&1
106 function error_message
{
108 printf "---------------------------------------------------\n"
109 printf "$(gettext "Setup FAILED
").\n\n"
118 if [[ ! -x $bin ]]; then
119 printf "$(gettext "Could not access
/execute
%s
").\n" $bin
129 if [[ $ret -ne 0 ]]; then
130 printf "\n$(gettext "%s failed with
return value
%d
, exiting
").\n\n" $prog $ret
136 function ok_to_proceed
{
140 if [[ $answer = no
]]; then
141 printf "\n$(gettext "Exiting
, no action performed
")\n\n"
146 function check_value
{
150 if [[ -z $arg ]]; then
151 printf "\n$(gettext "No input obtained
for %s
, exiting
").\n" $checkval
154 echo "$arg">$TMP_FILE
155 if egrep -s '[*$^#!]+' $TMP_FILE; then
156 printf "\n$(gettext "Invalid input obtained
for %s
, exiting
").\n" $checkval
162 function setup_kdc_conf
{
164 printf "\n$(gettext "Setting up
%s
").\n" $KRB5_KDC_CONF
166 if [[ -r $KRB5_KDC_CONF ]]; then
167 cat $KRB5_KDC_CONF > $KRB5_KDC_CONF.sav
168 cannot_create
$KRB5_KDC_CONF.sav $?
171 exec 3>$KRB5_KDC_CONF
172 if [[ $?
-ne 0 ]]; then
173 printf "\n$(gettext "Cannot
write to
%s
, exiting
").\n" $KRB5_KDC_CONF
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
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
192 if [[ $slave = yes ]]; then
193 printf "\t\tsunw_dbprop_slave_poll = 2m\n" 1>&3
199 function setup_krb_conf
{
201 printf "\n$(gettext "Setting up
%s
").\n" $KRB5_KRB_CONF
203 if [[ -r $KRB5_KRB_CONF ]]; then
204 cat $KRB5_KRB_CONF > $KRB5_KRB_CONF.sav
205 cannot_create
$KRB5_KRB_CONF.sav $?
208 exec 3>$KRB5_KRB_CONF
209 if [[ $?
-ne 0 ]]; then
210 printf "\n$(gettext "Cannot
write to
%s
, exiting
").\n" $KRB5_KRB_CONF
214 printf "[libdefaults]\n" 1>&3
215 printf "\tdefault_realm = $REALM\n\n" 1>&3
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
222 printf "\t\tkdc = $fqhn\n" 1>&3
223 if [[ $master = yes ]]; then
224 printf "\t\tadmin_server = $fqhn\n" 1>&3
226 printf "\t\tadmin_server = $master_hn\n" 1>&3
228 printf "\t}\n\n" 1>&3
230 printf "[domain_realm]\n" 1>&3
231 printf "\t.$domain = $REALM\n\n" 1>&3
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
238 printf "[appdefaults]\n" 1>&3
239 printf "\tkinit = {\n\t\trenewable = true\n\t\tforwardable = true\n" 1>&3
243 function cannot_create
{
245 typeset filename
="$1"
247 if [[ $stat -ne 0 ]]; then
248 printf "\n$(gettext "Cannot create
/edit
%s
, exiting
").\n" $filename
253 function check_admin
{
257 if [[ -z $ADMIN_PRINC ]]; then
260 checkval
="ADMIN_PRINC"; check_value
$ADMIN_PRINC
263 echo "$ADMIN_PRINC">$TMP_FILE
265 if egrep -s '\/admin' $TMP_FILE; then
266 # Already in "/admin" format, do nothing
269 if egrep -s '\/' $TMP_FILE; then
270 printf "\n$(gettext "Improper entry
for krb5 admin principal
, exiting
").\n"
273 ADMIN_PRINC
=$
(echo "$ADMIN_PRINC/admin")
279 function ping_check
{
283 if $PING $machine > /dev
/null
2>&1; then
286 printf "\n$(gettext "%s
%s is unreachable
, exiting
").\n" $string $machine
291 function check_host
{
293 echo "$host">$TMP_FILE
294 if egrep -s '[^.]\.[^.]+$' $TMP_FILE; then
295 # do nothing, host is in fqhn format
298 if egrep -s '\.+' $TMP_FILE; then
299 printf "\n$(gettext "Improper format of
host name
: '%s'").\n"
300 printf "$(gettext "Expecting the following format
: 'somehost.example.com' or
'somehost', exiting
").\n"
303 # Attach fqdn to host, to get the Fully Qualified Domain
304 # Name of the host requested
305 host=$
(echo "$host.$domain")
310 # Ping to see if the host is alive!
315 function kill_daemons
{
317 # Kill daemons so they won't go into maintenance mode
318 $SVCADM disable
-s krb5kdc
319 if [[ $?
-ne 0 ]]; then
320 printf "\n$(gettext "Error
in disabling krb5kdc
, exiting
").\n"
323 $SVCADM disable
-s kadmin
324 if [[ $?
-ne 0 ]]; then
325 printf "\n$(gettext "Error
in disabling kadmind
, exiting
").\n"
328 $SVCADM disable
-s krb5_prop
329 if [[ $?
-ne 0 ]]; then
330 printf "\n$(gettext "Error
in disabling kpropd
, exiting
").\n"
334 # Make sure that none of the daemons outside of SMF are running either
336 if [[ $?
-gt 1 ]]; then
337 printf "\n$(gettext "Error
in killing kadmind
, exiting
").\n"
341 if [[ $?
-gt 1 ]]; then
342 printf "\n$(gettext "Error
in killing krb5kdc
, exiting
").\n"
346 if [[ $?
-gt 1 ]]; then
347 printf "\n$(gettext "Error
in killing kpropd
, exiting
").\n"
352 function setup_mkeytab
{
354 check_admin
"\n$(gettext "Enter the krb5 administrative principal to be created
"): \c"
356 if [[ -z $PWFILE ]]; then
358 $KADMINL -q "ank $ADMIN_PRINC"
359 check_ret $?
$KADMINL
361 cat $PWFILE $PWFILE |
$KADMINL -q "ank $ADMIN_PRINC" > /dev
/null
2>&1
362 check_ret $?
$KADMINL
365 $KADMINL -q "ank -randkey host/$fqhn" 1>$TMP_FILE 2>&1
366 check_ret $?
$KADMINL
367 $KADMINL -q "ktadd host/$fqhn" 1>$TMP_FILE 2>&1
368 check_ret $?
$KADMINL
371 function setup_skeytab
{
373 check_admin
"\n$(gettext "Enter the krb5 administrative principal to be used
"): \c"
375 printf "$(gettext "Obtaining TGT
for %s
") ...\n" $ADMIN_PRINC
377 if [[ -z $PWFILE ]]; then
378 kinit
-c $TMP_CCACHE -S kadmin
/$master_hn $ADMIN_PRINC
381 cat $PWFILE | kinit
-c $TMP_CCACHE -S kadmin
/$master_hn \
382 $ADMIN_PRINC > /dev
/null
2>&1
384 klist
-c $TMP_CCACHE 1>$TMP_FILE 2>&1
385 if egrep -s "$(gettext "Valid starting
")" $TMP_FILE && \
386 egrep -s "kadmin/$master_hn@$REALM" $TMP_FILE; then
389 printf "\n$(gettext "kinit of
%s failed
, exiting
").\n" $ADMIN_PRINC
393 $KADMIN -c $TMP_CCACHE -q "ank -randkey kiprop/$fqhn" 1>$TMP_FILE 2>&1
395 $KADMIN -c $TMP_CCACHE -q "ktadd kiprop/$fqhn" 1>$TMP_FILE 2>&1
398 $KADMIN -c $TMP_CCACHE -q "ank -randkey host/$fqhn" 1>$TMP_FILE 2>&1
400 $KADMIN -c $TMP_CCACHE -q "ktadd host/$fqhn" 1>$TMP_FILE 2>&1
403 kdestroy
-q -c $TMP_CCACHE 1>$TMP_FILE 2>&1
404 check_ret $?
$kdestroy
407 function setup_kadm5acl
{
409 printf "\n$(gettext "Setting up
%s
").\n" $KADM5ACL
411 if [[ -r $KADM5ACL ]]; then
412 cat $KADM5ACL > $KADM5ACL.sav
413 cannot_create
$KADM5ACL.sav $?
417 if [[ $?
-ne 0 ]]; then
418 printf "\n$(gettext "Cannot
write to
%s
, exiting
").\n" $KADM5ACL
422 if [[ $master = yes ]]; then
423 printf "\n$ADMIN_PRINC@$REALM\t\tacmil\n" 1>&3
424 printf "\nkiprop/*@$REALM\t\tp\n" 1>&3
426 printf "\n*/admin@___default_realm___\t\t*\n" 1>&3
430 function setup_kpropdacl
{
432 printf "\n$(gettext "Setting up
%s
").\n\n" $KPROPACL
434 if [[ -r $KPROPACL ]]; then
435 cat $KPROPACL > $KPROPACL.sav
436 cannot_create
$KPROPACL.sav $?
440 if [[ $?
-ne 0 ]]; then
441 printf "\n$(gettext "Cannot
write to
%s
, exiting
").\n" $KPROPACL
444 printf "\nhost/$master_hn@$REALM\n" 1>&3
447 function setup_master
{
449 # create principal DB (KDB)
450 if [[ -z $PWFILE ]]; then
453 check_ret $? kdb5_util
455 cat $PWFILE $PWFILE | kdb5_util create
> /dev
/null
456 check_ret $? kdb5_util
462 $SVCADM enable -r -s krb5kdc
463 $SVCADM enable -r -s kadmin
466 function setup_slave
{
472 # Clear the kadm5acl, since the start methods look at this file
473 # to see if the server has been configured as a master server
478 $SVCADM enable -r -s krb5_prop
480 # Wait for full propagation of the database, in some environments
481 # this could take a few seconds
482 while [[ ! -f /var
/krb
5/principal
]]; do
483 if [[ count
-gt $LOOPCNT ]]; then
484 printf "\n$(gettext "Could not receive updates from the master
").\n"
486 ((count
= count
+ 1))
488 printf "$(gettext "Waiting
for database from master
")...\n"
492 # The database is propagated now we need to create the stash file
493 if [[ -z $PWFILE ]]; then
495 check_ret $? kdb5_util
497 cat $PWFILE | kdb5_util stash
> /dev
/null
2>&1
498 check_ret $? kdb5_util
501 $SVCADM enable -r -s krb5kdc
504 function kdb5_destroy
{
508 [[ -n $REALM ]] && arg
="-r $REALM"
509 printf "$(gettext "yes")\n" | kdb5_util
$arg destroy
> /dev
/null
2>&1
512 [[ $status -eq 0 ]] && return $status
514 # Could mean that the admin could have already removed part of the
515 # configuration. Better to check to see if anything else should be
516 # destroyed. We check by looking at any other stash files in /var/krb5
517 stashfiles
=`ls $STASH`
518 for stash
in $stashfiles
521 [[ -z $realm ]] && continue
523 printf "$(gettext "Found non-default realm
: %s
")\n" $realm
524 query
"$(gettext "Do you wish to destroy realm
"): $realm ?"
525 if [[ $answer == yes ]]; then
526 printf "$(gettext "yes")\n" | kdb5_util
-r $realm destroy
> /dev
/null
2>&1
528 if [[ $status -ne 0 ]]; then
529 printf "$(gettext "Could not destroy realm
: %s
")\n" $realm
533 printf "$(gettext "%s will not be destroyed
").\n" $realm
541 function destroy_kdc
{
544 # Check first to see if this is an existing KDC or server
545 if [[ -f $KRB5KT ||
-f $PRINCDB ||
-f $OLDPRINCDB ]]
547 if [[ -z $PWFILE ]]; then
548 printf "\n$(gettext "Some of the following files are present on this system
"):\n"
549 echo "\t$KRB5KT\n\t$PRINCDB\n\t$OLDPRINCDB\n\t$STASH\n"
550 if [[ -z $d_option ]]; then
551 printf "$(gettext "You must first run
'kdcmgr destroy' to remove all of these files before creating a KDC server
").\n\n"
554 ok_to_proceed
"$(gettext "All of these files will be removed
, okay to proceed?
")"
558 if [[ -n $d_option ]]; then
559 printf "\n$(gettext "No KDC related files exist
, exiting
").\n\n"
570 [[ $status -ne 0 ]] && cleanup
1
573 function kadm5_acl_configed
{
575 if [[ -s $KADM5ACL ]]; then
576 grep -v '^[ ]*#' $KADM5ACL | \
577 egrep '_default_realm_' > /dev
/null
2>&1
578 if [[ $?
-gt 0 ]]; then
586 function status_kdc
{
590 printf "\n$(gettext "KDC Status Information
")\n"
591 echo "--------------------------------------------"
592 svcs
-xv svc
:/network
/security
/krb5kdc
:default
594 if kadm5_acl_configed
; then
596 printf "\n$(gettext "KDC Master Status Information
")\n"
597 echo "--------------------------------------------"
598 svcs
-xv svc
:/network
/security
/kadmin
:default
600 printf "\n$(gettext "KDC Slave Status Information
")\n"
601 echo "--------------------------------------------"
602 svcs
-xv svc
:/network
/security
/krb5_prop
:default
605 printf "\n$(gettext "Transaction Log Information
")\n"
606 echo "--------------------------------------------"
607 /usr
/sbin
/kproplog
-h
609 printf "$(gettext "Kerberos Related File Information
")\n"
610 echo "--------------------------------------------"
611 printf "$(gettext "(will display any missing files below
)")\n"
612 FILELIST
="$KRB5_KDC_CONF $KRB5_KRB_CONF $KADM5ACL $KRB5KT $PRINCDB "
613 for file in $FILELIST; do
614 if [[ ! -s $file ]]; then
615 printf "$(gettext "%s not found
").\n" $file
618 if [[ $is_master -eq 0 && ! -s $KPROPACL ]]; then
619 printf "$(gettext "%s not found
").\n" $KPROPACL
623 printf "$(gettext "Stash
file not found
") (/var/krb5/.k5.*).\n"
629 # Start of Main script
636 KRB5_KDC_CONF
=/etc
/krb
5/kdc.conf
637 KRB5_KRB_CONF
=/etc
/krb
5/krb5.conf
638 KADM5ACL
=/etc
/krb
5/kadm5.acl
639 KPROPACL
=/etc
/krb
5/kpropd.acl
641 KRB5KT
=/etc
/krb
5/krb5.keytab
642 PRINCDB
=/var
/krb
5/principal
643 OLDPRINCDB
=/var
/krb
5/principal.old
644 STASH
=/var
/krb
5/.k5.
*
646 KADMINL
=/usr
/sbin
/kadmin.
local; check_bin
$KADMINL
647 KADMIN
=/usr
/sbin
/kadmin
; check_bin
$KADMIN
648 KDCRES
=/usr
/lib
/krb
5/klookup
; check_bin
$KDCRES
649 SVCADM
=/usr
/sbin
/svcadm
; check_bin
$SVCADM
650 PING
=/usr
/sbin
/ping; check_bin
$PING
652 ENCTYPE
=aes128-cts-hmac-sha1-96
656 if [[ -x /usr
/bin
/mktemp
]]; then
657 TMP_FILE
=$
(/usr
/bin
/mktemp
/etc
/krb
5/krb5tmpfile.XXXXXX
)
658 TMP_CCACHE
=$
(/usr
/bin
/mktemp
/etc
/krb
5/krb5tmpccache.XXXXXX
)
660 TMP_FILE
="/etc/krb5/krb5tmpfile.$$"
661 TMP_CCACHE
="/etc/krb5/krb5tmpccache.$$"
664 if [[ ! -f /etc
/resolv.conf
]]; then
665 printf "$(gettext "Error
: need to configure
/etc
/resolv.conf
").\n"
671 if [[ -n "$fqhn" ]]; then
673 elif [[ -n $
(hostname
) && -n $
(domainname
) ]]; then
674 fqhn
=$
(hostname|cut
-f1 -d'.').$
(domainname|cut
-f2- -d'.')
676 printf "$(gettext "Error
: can not determine full hostname
(FQHN
). Aborting
")\n"
677 printf "$(gettext "Note
, trying to use hostname and domainname to get FQHN
").\n"
684 domain
=${fqhn#*.} # remove host part
686 exitmsg
=`printf "$(gettext "Exiting...")"`
688 trap "echo $exitmsg; rm -f $TMP_FILE $TMP_CCACHE; exit 1" HUP INT QUIT TERM
690 while getopts :a
:e
:hp
:r
:s flag
693 a
) ADMIN_PRINC
=$OPTARG;;
697 if [[ ! -r $PWFILE ]]; then
698 printf "\n$(gettext "Password
file %s does not exist
, exiting
").\n\n" $PWFILE
706 shift $
(($OPTIND - 1))
710 "create master") master
=yes;;
711 "create -m "*) host=$3
712 checkval
="MASTER"; check_value
$host
715 if [[ $4 != slave
]]; then
718 "create slave") slave
=yes;;
719 destroy
) d_option
=yes
729 printf "\n$(gettext "Starting server setup
")\n"
730 printf "---------------------------------------------------\n"
732 # Checks for existing kdb and destroys if desired
735 if [[ -z $REALM ]]; then
736 printf "$(gettext "Enter the Kerberos realm
"): \c"
738 checkval
="REALM"; check_value
$REALM
741 if [[ -z $master && -z $slave ]]; then
742 query
"$(gettext "Is this machine to be configured as a master?
"): \c"
745 if [[ $answer = no
]]; then
746 query
"$(gettext "Is this machine to be configured as a slave?
"): \c"
748 if [[ $answer = no
]]; then
749 printf "\n$(gettext "Machine must either be a master or a slave KDC server
").\n"
755 if [[ $slave = yes && -z $master_hn ]]; then
756 printf "$(gettext "What is the master KDC
's host name?"): \c"
758 checkval="MASTER"; check_value $host
767 if [[ $master = yes ]]; then
773 printf "\n---------------------------------------------------\n"
774 printf "$(gettext "Setup COMPLETE").\n\n"