16815Ssemery#!/bin/ksh93 -p 20Sstevel@tonic-gate# 36656Ssemery# CDDL HEADER START 46656Ssemery# 56656Ssemery# The contents of this file are subject to the terms of the 66656Ssemery# Common Development and Distribution License (the "License"). 76656Ssemery# You may not use this file except in compliance with the License. 86656Ssemery# 96656Ssemery# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 106656Ssemery# or http://www.opensolaris.org/os/licensing. 116656Ssemery# See the License for the specific language governing permissions 126656Ssemery# and limitations under the License. 136656Ssemery# 146656Ssemery# When distributing Covered Code, include this CDDL HEADER in each 156656Ssemery# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 166656Ssemery# If applicable, add the following below this CDDL HEADER, with the 176656Ssemery# fields enclosed by brackets "[]" replaced with your own identifying 186656Ssemery# information: Portions Copyright [yyyy] [name of copyright owner] 196656Ssemery# 206656Ssemery# CDDL HEADER END 216656Ssemery# 2211570SShawn.Emery@Sun.COM# Copyright 2010 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate# Use is subject to license terms. 240Sstevel@tonic-gate# 250Sstevel@tonic-gate# This script is used to setup the Kerberos client by 260Sstevel@tonic-gate# supplying information about the Kerberos realm and kdc. 270Sstevel@tonic-gate# 280Sstevel@tonic-gate# The kerberos configuration file (/etc/krb5/krb5.conf) would 290Sstevel@tonic-gate# be generated and local host's keytab file setup. The script 300Sstevel@tonic-gate# can also optionally setup the system to do kerberized nfs and 310Sstevel@tonic-gate# bringover a master krb5.conf copy from a specified location. 3211061SShawn.Emery@Sun.COM# 330Sstevel@tonic-gate 346656Ssemeryfunction cleanup { 356656Ssemery 369833SShawn.Emery@Sun.COM kdestroy -q > $TMP_FILE 2>&1 376656Ssemery rm -r $TMPDIR > /dev/null 2>&1 386656Ssemery 399833SShawn.Emery@Sun.COM exit $1 406656Ssemery} 416656Ssemeryfunction exiting { 426656Ssemery 436656Ssemery printf "\n$(gettext "Exiting setup, nothing changed").\n\n" 446656Ssemery 456656Ssemery cleanup $1 460Sstevel@tonic-gate} 470Sstevel@tonic-gate 486656Ssemeryfunction error_message { 496656Ssemery 509833SShawn.Emery@Sun.COM printf -- "---------------------------------------------------\n" >&2 519833SShawn.Emery@Sun.COM printf "$(gettext "Setup FAILED").\n\n" >&2 526656Ssemery 536656Ssemery cleanup 1 546656Ssemery} 556656Ssemery 566656Ssemeryfunction check_bin { 576656Ssemery 586656Ssemery typeset bin=$1 596656Ssemery 606656Ssemery if [[ ! -x $bin ]]; then 619833SShawn.Emery@Sun.COM printf "$(gettext "Could not access/execute %s").\n" $bin >&2 620Sstevel@tonic-gate error_message 630Sstevel@tonic-gate fi 640Sstevel@tonic-gate} 650Sstevel@tonic-gate 666656Ssemeryfunction cannot_create { 676656Ssemery typeset filename="$1" 686656Ssemery typeset stat="$2" 696656Ssemery 706656Ssemery if [[ $stat -ne 0 ]]; then 716656Ssemery printf "\n$(gettext "Can not create/edit %s, exiting").\n" $filename >&2 726656Ssemery error_message 736656Ssemery fi 746656Ssemery} 756656Ssemery 766656Ssemeryfunction update_pam_conf { 776656Ssemery typeset PAM TPAM service 786656Ssemery 796656Ssemery PAM=/etc/pam.conf 806656Ssemery 816656Ssemery TPAM=$(mktemp -q -t kclient-pamconf.XXXXXX) 826656Ssemery if [[ -z $TPAM ]]; then 836656Ssemery printf "\n$(gettext "Can not create temporary file, exiting").\n" >&2 846656Ssemery error_message 856656Ssemery fi 866656Ssemery 876656Ssemery cp $PAM $TPAM >/dev/null 2>&1 886656Ssemery 896656Ssemery printf "$(gettext "Configuring %s").\n\n" $PAM 906656Ssemery 916656Ssemery for service in $SVCs; do 926656Ssemery svc=${service%:*} 936656Ssemery auth_type=${service#*:} 946656Ssemery if egrep -s "^$svc[ ][ ]*auth.*pam_krb5*" $TPAM; then 956815Ssemery printf "$(gettext "The %s service is already configured for pam_krb5, please merge this service in %s").\n\n" $svc $PAM >&2 966656Ssemery continue 976656Ssemery else 986656Ssemery exec 3>>$TPAM 996815Ssemery printf "\n$svc\tauth include\t\tpam_krb5_$auth_type\n" 1>&3 1006656Ssemery fi 1016656Ssemery done 1026656Ssemery 1036656Ssemery cp $TPAM $PAM > /dev/null 2>&1 1046656Ssemery 1056656Ssemery rm $TPAM > /dev/null 2>&1 1066656Ssemery} 1076656Ssemery 1086656Ssemeryfunction modify_nfssec_conf { 1096656Ssemery typeset NFSSEC_FILE="/etc/nfssec.conf" 1106656Ssemery 1116656Ssemery if [[ -r $NFSSEC_FILE ]]; then 1120Sstevel@tonic-gate cat $NFSSEC_FILE > $NFSSEC_FILE.sav 1130Sstevel@tonic-gate cannot_create $NFSSEC_FILE.sav $? 1140Sstevel@tonic-gate fi 1150Sstevel@tonic-gate 1160Sstevel@tonic-gate cat $NFSSEC_FILE > $TMP_FILE 1170Sstevel@tonic-gate cannot_create $TMP_FILE $? 1180Sstevel@tonic-gate 1190Sstevel@tonic-gate if grep -s "#krb5" $NFSSEC_FILE > /dev/null 2>&1; then 1200Sstevel@tonic-gate sed "s%^#krb5%krb5%" $TMP_FILE >$NFSSEC_FILE 1210Sstevel@tonic-gate cannot_create $NFSSEC_FILE $? 1220Sstevel@tonic-gate fi 1230Sstevel@tonic-gate} 1240Sstevel@tonic-gate 1256656Ssemeryfunction call_kadmin { 1260Sstevel@tonic-gate typeset svc="$1" 1270Sstevel@tonic-gate typeset bool1 bool2 bool3 bool4 1286656Ssemery typeset service_princ getprincsubcommand anksubcommand ktaddsubcommand 1296656Ssemery typeset ktremsubcommand 1300Sstevel@tonic-gate 1310Sstevel@tonic-gate for listentry in $fqdnlist; do 1320Sstevel@tonic-gate 1330Sstevel@tonic-gate # Reset conditional vars to 1 1340Sstevel@tonic-gate bool1=1; bool2=1; bool3=1; bool4=1 1350Sstevel@tonic-gate 1366656Ssemery service_princ=$(echo "${svc}/${listentry}") 1370Sstevel@tonic-gate getprincsubcommand="getprinc $service_princ" 1380Sstevel@tonic-gate anksubcommand="addprinc -randkey $service_princ" 1390Sstevel@tonic-gate ktaddsubcommand="ktadd $service_princ" 1406656Ssemery ktremsubcommand="ktrem $service_princ all" 1410Sstevel@tonic-gate 1426656Ssemery kadmin -c $KRB5CCNAME -q "$getprincsubcommand" 1>$TMP_FILE 2>&1 1430Sstevel@tonic-gate 1446815Ssemery egrep -s "$(gettext "get_principal: Principal does not exist")" $TMP_FILE 1450Sstevel@tonic-gate bool1=$? 1466815Ssemery egrep -s "$(gettext "get_principal: Operation requires ``get")" $TMP_FILE 1470Sstevel@tonic-gate bool2=$? 1480Sstevel@tonic-gate 1490Sstevel@tonic-gate if [[ $bool1 -eq 0 || $bool2 -eq 0 ]]; then 1506656Ssemery kadmin -c $KRB5CCNAME -q "$anksubcommand" 1>$TMP_FILE 2>&1 1510Sstevel@tonic-gate 1526815Ssemery egrep -s "$(gettext "add_principal: Principal or policy already exists while creating \"$service_princ@$realm\".")" $TMP_FILE 1530Sstevel@tonic-gate bool3=$? 1540Sstevel@tonic-gate 1556815Ssemery egrep -s "$(gettext "Principal \"$service_princ@$realm\" created.")" $TMP_FILE 1560Sstevel@tonic-gate bool4=$? 1570Sstevel@tonic-gate 1580Sstevel@tonic-gate if [[ $bool3 -eq 0 || $bool4 -eq 0 ]]; then 1590Sstevel@tonic-gate printf "$(gettext "%s entry ADDED to KDC database").\n" $service_princ 1600Sstevel@tonic-gate else 1610Sstevel@tonic-gate cat $TMP_FILE; 1626656Ssemery printf "\n$(gettext "kadmin: add_principal of %s failed, exiting").\n" $service_princ >&2 1630Sstevel@tonic-gate error_message 1640Sstevel@tonic-gate fi 1650Sstevel@tonic-gate else 1666656Ssemery printf "$(gettext "%s entry already exists in KDC database").\n" $service_princ >&2 1670Sstevel@tonic-gate fi 1680Sstevel@tonic-gate 1690Sstevel@tonic-gate klist -k 1>$TMP_FILE 2>&1 1706656Ssemery egrep -s "$service_princ@$realm" $TMP_FILE 1716656Ssemery if [[ $? -eq 0 ]]; then 1726656Ssemery printf "$(gettext "%s entry already present in keytab").\n" $service_princ >&2 1736656Ssemery # Don't care is this succeeds or not, just need to replace old 1746656Ssemery # entries as it is assummed that the client is reinitialized 1756656Ssemery kadmin -c $KRB5CCNAME -q "$ktremsubcommand" 1>$TMP_FILE 2>&1 1766656Ssemery fi 1776656Ssemery 1786656Ssemery kadmin -c $KRB5CCNAME -q "$ktaddsubcommand" 1>$TMP_FILE 2>&1 1796815Ssemery egrep -s "$(gettext "added to keytab WRFILE:$KRB5_KEYTAB_FILE.")" $TMP_FILE 1806656Ssemery if [[ $? -ne 0 ]]; then 1816656Ssemery cat $TMP_FILE; 1826656Ssemery printf "\n$(gettext "kadmin: ktadd of %s failed, exiting").\n" $service_princ >&2 1836656Ssemery error_message 1840Sstevel@tonic-gate else 1856656Ssemery printf "$(gettext "%s entry ADDED to keytab").\n" $service_princ 1860Sstevel@tonic-gate fi 1870Sstevel@tonic-gate 1880Sstevel@tonic-gate done 1890Sstevel@tonic-gate} 1900Sstevel@tonic-gate 1916656Ssemeryfunction writeup_krb5_conf { 1926656Ssemery typeset dh 1930Sstevel@tonic-gate 1946656Ssemery printf "\n$(gettext "Setting up %s").\n\n" $KRB5_CONFIG_FILE 1950Sstevel@tonic-gate 1966656Ssemery exec 3>$KRB5_CONFIG 1976656Ssemery if [[ $? -ne 0 ]]; then 1989833SShawn.Emery@Sun.COM printf "\n$(gettext "Can not write to %s, exiting").\n" $KRB5_CONFIG >&2 1990Sstevel@tonic-gate error_message 2000Sstevel@tonic-gate fi 2010Sstevel@tonic-gate 2026656Ssemery printf "[libdefaults]\n" 1>&3 2036656Ssemery if [[ $no_keytab == yes ]]; then 2046656Ssemery printf "\tverify_ap_req_nofail = false\n" 1>&3 2056656Ssemery fi 2066656Ssemery if [[ $dns_lookup == yes ]]; then 2076656Ssemery printf "\t$dnsarg = on\n" 1>&3 2086656Ssemery if [[ $dnsarg == dns_lookup_kdc ]]; then 2096656Ssemery printf "\tdefault_realm = $realm\n" 1>&3 2106656Ssemery printf "\n[domain_realm]\n" 1>&3 2116656Ssemery if [[ -n $fkdc_list ]]; then 2126656Ssemery for kdc in $fkdc_list; do 2136656Ssemery printf "\t$kdc = $realm\n" 1>&3 2146656Ssemery done 2156656Ssemery fi 2166656Ssemery printf "\t$FKDC = $realm\n" 1>&3 2176656Ssemery printf "\t$client_machine = $realm\n" 1>&3 2186656Ssemery if [[ -z $short_fqdn ]]; then 2196656Ssemery printf "\t.$domain = $realm\n\n" 1>&3 2206656Ssemery else 2216656Ssemery printf "\t.$short_fqdn = $realm\n\n" 1>&3 2226656Ssemery fi 2236656Ssemery if [[ -n $domain_list ]]; then 2246656Ssemery for dh in $domain_list; do 2256656Ssemery printf "\t$dh = $realm\n" 1>&3 2266656Ssemery done 2276656Ssemery fi 2280Sstevel@tonic-gate else 2296656Ssemery if [[ $dnsarg = dns_lookup_realm ]]; then 2306815Ssemery printf "\tdefault_realm = $realm\n" 1>&3 2316656Ssemery printf "\n[realms]\n" 1>&3 2326656Ssemery printf "\t$realm = {\n" 1>&3 2336656Ssemery if [[ -n $kdc_list ]]; then 2346656Ssemery for kdc in $kdc_list; do 2356656Ssemery printf "\t\tkdc = $kdc\n" 1>&3 2366656Ssemery done 2376656Ssemery else 2386656Ssemery printf "\t\tkdc = $KDC\n" 1>&3 2396656Ssemery fi 2406656Ssemery printf "\t\tadmin_server = $KDC\n" 1>&3 2416656Ssemery if [[ $non_solaris == yes ]]; then 2426656Ssemery printf "\n\t\tkpasswd_protocol = SET_CHANGE\n" 1>&3 2436656Ssemery fi 2446656Ssemery printf "\t}\n\n" 1>&3 2450Sstevel@tonic-gate else 2466815Ssemery printf "\tdefault_realm = $realm\n\n" 1>&3 2470Sstevel@tonic-gate fi 2480Sstevel@tonic-gate fi 2490Sstevel@tonic-gate else 2506656Ssemery printf "\tdefault_realm = $realm\n\n" 1>&3 2516656Ssemery 2526656Ssemery printf "[realms]\n" 1>&3 2536656Ssemery printf "\t$realm = {\n" 1>&3 2546656Ssemery if [[ -n $kdc_list ]]; then 2556656Ssemery for kdc in $kdc_list; do 2566656Ssemery printf "\t\tkdc = $kdc\n" 1>&3 2576656Ssemery done 2586656Ssemery else 2596656Ssemery printf "\t\tkdc = $KDC\n" 1>&3 2606656Ssemery fi 2616656Ssemery printf "\t\tadmin_server = $KDC\n" 1>&3 2626656Ssemery if [[ $non_solaris == yes ]]; then 2636656Ssemery printf "\n\t\tkpasswd_protocol = SET_CHANGE\n" 1>&3 2646656Ssemery fi 2656656Ssemery printf "\t}\n\n" 1>&3 2660Sstevel@tonic-gate 2676656Ssemery printf "[domain_realm]\n" 1>&3 2686656Ssemery if [[ -n $fkdc_list ]]; then 2696656Ssemery for kdc in $fkdc_list; do 2706656Ssemery printf "\t$kdc = $realm\n" 1>&3 2716656Ssemery done 2726656Ssemery fi 2736656Ssemery printf "\t$FKDC = $realm\n" 1>&3 2746656Ssemery printf "\t$client_machine = $realm\n" 1>&3 2756656Ssemery if [[ -z $short_fqdn ]]; then 2766656Ssemery printf "\t.$domain = $realm\n\n" 1>&3 2776656Ssemery else 2786656Ssemery printf "\t.$short_fqdn = $realm\n\n" 1>&3 2796656Ssemery fi 2806656Ssemery if [[ -n $domain_list ]]; then 2816656Ssemery for dh in $domain_list; do 2826656Ssemery printf "\t$dh = $realm\n" 1>&3 2836656Ssemery done 2846656Ssemery fi 2850Sstevel@tonic-gate fi 2860Sstevel@tonic-gate 2876656Ssemery printf "[logging]\n" 1>&3 2886656Ssemery printf "\tdefault = FILE:/var/krb5/kdc.log\n" 1>&3 2896656Ssemery printf "\tkdc = FILE:/var/krb5/kdc.log\n" 1>&3 2906656Ssemery printf "\tkdc_rotate = {\n\t\tperiod = 1d\n\t\tversions = 10\n\t}\n\n" 1>&3 2910Sstevel@tonic-gate 2926656Ssemery printf "[appdefaults]\n" 1>&3 2936656Ssemery printf "\tkinit = {\n\t\trenewable = true\n\t\tforwardable = true\n" 1>&3 2946656Ssemery if [[ $no_keytab == yes ]]; then 2956656Ssemery printf "\t\tno_addresses = true\n" 1>&3 2966656Ssemery fi 2976656Ssemery printf "\t}\n" 1>&3 2980Sstevel@tonic-gate} 2990Sstevel@tonic-gate 3006656Ssemeryfunction ask { 3016656Ssemery typeset question=$1 3026656Ssemery typeset default_answer=$2 3036656Ssemery 3046656Ssemery if [[ -z $default_answer ]]; then 3056656Ssemery printf "$question :" 3060Sstevel@tonic-gate else 3076656Ssemery printf "$question [$default_answer]: " 3080Sstevel@tonic-gate fi 3090Sstevel@tonic-gate read answer 3100Sstevel@tonic-gate test -z "$answer" && answer="$default_answer" 3110Sstevel@tonic-gate} 3120Sstevel@tonic-gate 3136656Ssemeryfunction yesno { 3140Sstevel@tonic-gate typeset question="$1" 3156656Ssemery 3166656Ssemery answer= 3176656Ssemery yn=`printf "$(gettext "y/n")"` 3186656Ssemery y=`printf "$(gettext "y")"` 3196656Ssemery n=`printf "$(gettext "n")"` 3206656Ssemery yes=`printf "$(gettext "yes")"` 3216656Ssemery no=`printf "$(gettext "no")"` 3226656Ssemery 3236656Ssemery while [[ -z $answer ]]; do 3246656Ssemery ask "$question" $yn 3256656Ssemery case $answer in 3266656Ssemery $y|$yes) answer=yes;; 3276656Ssemery $n|$no) answer=no;; 3286656Ssemery *) answer=;; 3290Sstevel@tonic-gate esac 3300Sstevel@tonic-gate done 3310Sstevel@tonic-gate} 3320Sstevel@tonic-gate 3336656Ssemeryfunction query { 3340Sstevel@tonic-gate yesno "$*" 3356656Ssemery 3366656Ssemery if [[ $answer == no ]]; then 3370Sstevel@tonic-gate printf "\t$(gettext "No action performed").\n" 3380Sstevel@tonic-gate fi 3390Sstevel@tonic-gate} 3400Sstevel@tonic-gate 3410Sstevel@tonic-gate 3426656Ssemeryfunction read_profile { 3430Sstevel@tonic-gate typeset param value 3440Sstevel@tonic-gate typeset file="$1" 3456656Ssemery 3460Sstevel@tonic-gate if [[ ! -d $file && -r $file ]]; then 3470Sstevel@tonic-gate while read param value 3480Sstevel@tonic-gate do 3496656Ssemery case $param in 3506656Ssemery REALM) if [[ -z $realm ]]; then 3516656Ssemery realm="$value" 3526656Ssemery checkval="REALM"; check_value $realm 3530Sstevel@tonic-gate fi 3540Sstevel@tonic-gate ;; 3556656Ssemery KDC) if [[ -z $KDC ]]; then 3560Sstevel@tonic-gate KDC="$value" 3570Sstevel@tonic-gate checkval="KDC"; check_value $KDC 3580Sstevel@tonic-gate fi 3590Sstevel@tonic-gate ;; 3606656Ssemery ADMIN) if [[ -z $ADMIN_PRINC ]]; then 3610Sstevel@tonic-gate ADMIN_PRINC="$value" 3620Sstevel@tonic-gate checkval="ADMIN_PRINC" 3630Sstevel@tonic-gate check_value $ADMIN_PRINC 3640Sstevel@tonic-gate fi 3650Sstevel@tonic-gate ;; 3666656Ssemery FILEPATH) if [[ -z $filepath ]]; then 3670Sstevel@tonic-gate filepath="$value" 3680Sstevel@tonic-gate fi 3690Sstevel@tonic-gate ;; 3706656Ssemery NFS) if [[ -z $add_nfs ]]; then 3716656Ssemery if [[ $value == 1 ]]; then 3720Sstevel@tonic-gate add_nfs=yes 3730Sstevel@tonic-gate else 3740Sstevel@tonic-gate add_nfs=no 3750Sstevel@tonic-gate fi 3760Sstevel@tonic-gate fi 3770Sstevel@tonic-gate ;; 3786656Ssemery NOKEY) if [[ -z $no_keytab ]]; then 3796656Ssemery if [[ $value == 1 ]]; then 3806656Ssemery no_keytab=yes 3816656Ssemery else 3826656Ssemery no_keytab=no 3836656Ssemery fi 3846656Ssemery fi 3856656Ssemery ;; 3866656Ssemery NOSOL) if [[ -z $non_solaris ]]; then 3876656Ssemery if [[ $value == 1 ]]; then 3886656Ssemery non_solaris=yes 3896656Ssemery no_keytab=yes 3906656Ssemery else 3916656Ssemery non_solaris=no 3926656Ssemery fi 3936656Ssemery fi 3946656Ssemery ;; 3956656Ssemery LHN) if [[ -z $logical_hn ]]; then 3966656Ssemery logical_hn="$value" 3976656Ssemery checkval="LOGICAL_HOSTNAME" 3986656Ssemery check_value $logical_hn 3996656Ssemery fi 4006656Ssemery ;; 4016656Ssemery DNSLOOKUP) if [[ -z $dnsarg ]]; then 4020Sstevel@tonic-gate dnsarg="$value" 4030Sstevel@tonic-gate checkval="DNS_OPTIONS" 4040Sstevel@tonic-gate check_value $dnsarg 4050Sstevel@tonic-gate fi 4060Sstevel@tonic-gate ;; 4076656Ssemery FQDN) if [[ -z $fqdnlist ]]; then 4080Sstevel@tonic-gate fqdnlist="$value" 4090Sstevel@tonic-gate checkval="FQDN" 4100Sstevel@tonic-gate check_value $fqdnlist 4110Sstevel@tonic-gate verify_fqdnlist "$fqdnlist" 4120Sstevel@tonic-gate fi 4130Sstevel@tonic-gate ;; 4146656Ssemery MSAD) if [[ -z $msad ]]; then 4156656Ssemery if [[ $value == 1 ]]; then 4166656Ssemery msad=yes 4176656Ssemery non_solaris=yes 4186656Ssemery else 4196656Ssemery msad=no 4206656Ssemery fi 4216656Ssemery fi 4226656Ssemery ;; 4230Sstevel@tonic-gate esac 4240Sstevel@tonic-gate done <$file 4250Sstevel@tonic-gate else 4266656Ssemery printf "\n$(gettext "The kclient profile \`%s' is not valid, exiting").\n" $file >&2 4270Sstevel@tonic-gate error_message 4280Sstevel@tonic-gate fi 4290Sstevel@tonic-gate} 4300Sstevel@tonic-gate 4316656Ssemeryfunction ping_check { 4320Sstevel@tonic-gate typeset machine="$1" 4330Sstevel@tonic-gate typeset string="$2" 4346656Ssemery 4356656Ssemery if ping $machine 2 > /dev/null 2>&1; then 4360Sstevel@tonic-gate : 4370Sstevel@tonic-gate else 4386656Ssemery printf "\n$(gettext "%s %s is unreachable, exiting").\n" $string $machine >&2 4390Sstevel@tonic-gate error_message 4400Sstevel@tonic-gate fi 4410Sstevel@tonic-gate 4420Sstevel@tonic-gate # Output timesync warning if not using a profile, i.e. in 4430Sstevel@tonic-gate # interactive mode. 4446656Ssemery if [[ -z $profile && $string == KDC ]]; then 4450Sstevel@tonic-gate # It's difficult to sync up time with KDC esp. if in a 4460Sstevel@tonic-gate # zone so just print a warning about KDC time sync. 4476815Ssemery 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 4486815Ssemery printf "$(gettext "Both systems should run some form of time synchronization system like Network Time Protocol (NTP)").\n" >&2 4496656Ssemerybreak 4500Sstevel@tonic-gate fi 4510Sstevel@tonic-gate} 4520Sstevel@tonic-gate 4536656Ssemeryfunction check_value { 4540Sstevel@tonic-gate typeset arg="$1" 4556656Ssemery 4566656Ssemery if [[ -z $arg ]]; then 4576656Ssemery printf "\n$(gettext "No input obtained for %s, exiting").\n" $checkval >&2 4580Sstevel@tonic-gate error_message 4590Sstevel@tonic-gate else 4606656Ssemery echo "$arg" > $TMP_FILE 4610Sstevel@tonic-gate if egrep -s '[*$^#!]+' $TMP_FILE; then 4626656Ssemery printf "\n$(gettext "Invalid input obtained for %s, exiting").\n" $checkval >&2 4636656Ssemery error_message 4646656Ssemery fi 4656656Ssemery fi 4666656Ssemery} 4676656Ssemery 4686656Ssemeryfunction set_dns_value { 4696656Ssemery typeset -l arg="$1" 4706656Ssemery 4716656Ssemery if [[ $arg == dns_lookup_kdc || $arg == dns_lookup_realm || $arg == dns_fallback ]]; then 4726656Ssemery dns_lookup=yes 4736656Ssemery else 4746656Ssemery if [[ $arg == none ]]; then 4756656Ssemery dns_lookup=no 4766656Ssemery else 4776656Ssemery printf "\n$(gettext "Invalid DNS lookup option, exiting").\n" >&2 4780Sstevel@tonic-gate error_message 4790Sstevel@tonic-gate fi 4800Sstevel@tonic-gate fi 4810Sstevel@tonic-gate} 4820Sstevel@tonic-gate 4836656Ssemeryfunction verify_kdcs { 4846656Ssemery typeset k_list="$1" 4856656Ssemery typeset -l kdc 4866656Ssemery typeset list fqhn f_list 4876656Ssemery 4886656Ssemery kdc_list=$(echo "$k_list" | sed 's/,/ /g') 4896656Ssemery 4906656Ssemery if [[ -z $k_list ]]; then 4916656Ssemery printf "\n$(gettext "At least one KDC should be listed").\n\n" >&2 4926656Ssemery usage 4936656Ssemery fi 4946656Ssemery 4956656Ssemery for kdc in $k_list; do 4966656Ssemery if [[ $kdc != $KDC ]]; then 4976656Ssemery list="$list $kdc" 4986656Ssemery fkdc=`$KLOOKUP $kdc` 4996656Ssemery if ping $fkdc 2 > /dev/null; then 5006656Ssemery : 5016656Ssemery else 5026656Ssemery printf "\n$(gettext "%s %s is unreachable, no action performed").\n" "KDC" $fkdc >&2 5036656Ssemery fi 5046656Ssemery f_list="$f_list $fkdc" 5050Sstevel@tonic-gate fi 5066656Ssemery done 5076656Ssemery 5086656Ssemery fkdc_list="$f_list" 5096656Ssemery kdc_list="$list" 5100Sstevel@tonic-gate} 5110Sstevel@tonic-gate 5126656Ssemeryfunction parse_service { 5136656Ssemery typeset service_list=$1 5140Sstevel@tonic-gate 5156656Ssemery service_list=${service_list//,/ } 5166656Ssemery for service in $service_list; do 5176656Ssemery svc=${service%:} 5186656Ssemery auth_type=${service#:} 5196656Ssemery [[ -z $svc || -z $auth_type ]] && return 5206656Ssemery print -- $svc $auth_type 5216656Ssemery done 5226656Ssemery} 5236656Ssemery 5246656Ssemeryfunction verify_fqdnlist { 5256656Ssemery typeset list="$1" 5266656Ssemery typeset -l hostname 5276656Ssemery typeset -i count=1 5286656Ssemery typeset fqdnlist eachfqdn tmpvar fullhost 5296656Ssemery 5306656Ssemery list=$(echo "$list" | tr -d " " | tr -d "\t") 5316656Ssemery hostname=$(uname -n | cut -d"." -f1) 5320Sstevel@tonic-gate fqdnlist=$client_machine 5330Sstevel@tonic-gate 5340Sstevel@tonic-gate eachfqdn=$(echo "$list" | cut -d"," -f$count) 5356656Ssemery if [[ -z $eachfqdn ]]; then 5366656Ssemery printf "\n$(gettext "If the -f option is used, at least one FQDN should be listed").\n\n" >&2 5370Sstevel@tonic-gate usage 5380Sstevel@tonic-gate else 5396656Ssemery while [[ ! -z $eachfqdn ]]; do 5400Sstevel@tonic-gate tmpvar=$(echo "$eachfqdn" | cut -d"." -f1) 5416656Ssemery if [[ -z $tmpvar ]]; then 5420Sstevel@tonic-gate fullhost="$hostname$eachfqdn" 5430Sstevel@tonic-gate else 5440Sstevel@tonic-gate fullhost="$hostname.$eachfqdn" 5450Sstevel@tonic-gate fi 5460Sstevel@tonic-gate 5476656Ssemery ping_check $fullhost $(gettext "System") 5486656Ssemery if [[ $fullhost == $client_machine ]]; then 5490Sstevel@tonic-gate : 5500Sstevel@tonic-gate else 5510Sstevel@tonic-gate fqdnlist="$fqdnlist $fullhost" 5520Sstevel@tonic-gate fi 5530Sstevel@tonic-gate 5546656Ssemery if [[ $list == *,* ]]; then 5550Sstevel@tonic-gate ((count = count + 1)) 5560Sstevel@tonic-gate eachfqdn=$(echo "$list" | cut -d"," -f$count) 5570Sstevel@tonic-gate else 5580Sstevel@tonic-gate break 5590Sstevel@tonic-gate fi 5600Sstevel@tonic-gate done 5610Sstevel@tonic-gate fi 5620Sstevel@tonic-gate} 5630Sstevel@tonic-gate 5646656Ssemeryfunction setup_keytab { 5656656Ssemery typeset cname ask_fqdns current_release 5666656Ssemery 5676656Ssemery # 5686656Ssemery # 1. kinit with ADMIN_PRINC 5696656Ssemery # 5706656Ssemery 5716656Ssemery if [[ -z $ADMIN_PRINC ]]; then 5726656Ssemery printf "\n$(gettext "Enter the krb5 administrative principal to be used"): " 5736656Ssemery read ADMIN_PRINC 5746656Ssemery checkval="ADMIN_PRINC"; check_value $ADMIN_PRINC 5756656Ssemery fi 5766656Ssemery 5776656Ssemery echo "$ADMIN_PRINC">$TMP_FILE 5786656Ssemery 5796656Ssemery [[ -n $msad ]] && return 5806656Ssemery if egrep -s '\/admin' $TMP_FILE; then 5816656Ssemery # Already in "/admin" format, do nothing 5826656Ssemery : 5836656Ssemery else 5846656Ssemery if egrep -s '\/' $TMP_FILE; then 5856656Ssemery printf "\n$(gettext "Improper entry for krb5 admin principal, exiting").\n" >&2 5866656Ssemery error_message 5876656Ssemery else 5886656Ssemery ADMIN_PRINC=$(echo "$ADMIN_PRINC/admin") 5896656Ssemery fi 5906656Ssemery fi 5916656Ssemery 5926656Ssemery printf "$(gettext "Obtaining TGT for %s") ...\n" $ADMIN_PRINC 5936656Ssemery 5946656Ssemery cname=$(canon_resolve $KDC) 5956656Ssemery if [[ -n $cname ]]; then 5966656Ssemery kinit -S kadmin/$cname $ADMIN_PRINC 5976656Ssemery else 5986656Ssemery kinit -S kadmin/$FKDC $ADMIN_PRINC 5996656Ssemery fi 6006656Ssemery klist 1>$TMP_FILE 2>&1 6016815Ssemery if egrep -s "$(gettext "Valid starting")" $TMP_FILE && egrep -s "kadmin/$FKDC@$realm" $TMP_FILE; then 6026656Ssemery : 6036656Ssemery else 6046656Ssemery printf "\n$(gettext "kinit of %s failed, exiting").\n" $ADMIN_PRINC >&2 6056656Ssemery error_message 6066656Ssemery fi 6076656Ssemery 6086656Ssemery # 6096656Ssemery # 2. Do we want to create and/or add service principal(s) for fqdn's 6106656Ssemery # other than the one listed in resolv.conf(4) ? 6116656Ssemery # 6126656Ssemery if [[ -z $options ]]; then 6136656Ssemery query "$(gettext "Do you have multiple DNS domains spanning the Kerberos realm") $realm ?" 6146656Ssemery ask_fqdns=$answer 6156656Ssemery if [[ $ask_fqdns == yes ]]; then 6166815Ssemery printf "$(gettext "Enter a comma-separated list of DNS domain names"): " 6176656Ssemery read fqdnlist 6186656Ssemery verify_fqdnlist "$fqdnlist" 6196656Ssemery else 6206656Ssemery fqdnlist=$client_machine 6216656Ssemery fi 6226656Ssemery else 6236656Ssemery if [[ -z $fqdnlist ]]; then 6246656Ssemery fqdnlist=$client_machine 6256656Ssemery fi 6266656Ssemery fi 6276656Ssemery 6286656Ssemery if [[ $add_nfs == yes ]]; then 6296656Ssemery echo; call_kadmin nfs 6306656Ssemery fi 6316656Ssemery 6326656Ssemery # Add the host entry to the keytab 6336656Ssemery echo; call_kadmin host 6346656Ssemery 6356656Ssemery} 6366656Ssemery 6376656Ssemeryfunction setup_lhn { 6386656Ssemery typeset -l logical_hn 6396656Ssemery 6406656Ssemery echo "$logical_hn" > $TMP_FILE 6416656Ssemery if egrep -s '[^.]\.[^.]+$' $TMP_FILE; then 6426656Ssemery # do nothing, logical_hn is in fqdn format 6436656Ssemery : 6446656Ssemery else 6456656Ssemery if egrep -s '\.+' $TMP_FILE; then 6466656Ssemery printf "\n$(gettext "Improper format of logical hostname, exiting").\n" >&2 6476656Ssemery error_message 6486656Ssemery else 6496656Ssemery # Attach fqdn to logical_hn, to get the Fully Qualified 6506656Ssemery # Host Name of the client requested 6516656Ssemery logical_hn=$(echo "$logical_hn.$fqdn") 6526656Ssemery fi 6536656Ssemery fi 6546656Ssemery 6556656Ssemery client_machine=$logical_hn 6566656Ssemery 6576656Ssemery ping_check $client_machine $(gettext "System") 6586656Ssemery} 6596656Ssemery 6606656Ssemeryfunction usage { 6616656Ssemery printf "\n$(gettext "Usage: kclient [ options ]")\n" >&2 6626656Ssemery printf "\t$(gettext "where options are any of the following")\n\n" >&2 6636656Ssemery printf "\t$(gettext "[ -D domain_list ] configure a client that has mul 6646656Ssemerytiple mappings of doamin and/or hosts to the default realm")\n" >&2 6656656Ssemery printf "\t$(gettext "[ -K ] configure a client that does not have host/service keys")\n" >&2 6666656Ssemery printf "\t$(gettext "[ -R realm ] specifies the realm to use")\n" >&2 6676656Ssemery printf "\t$(gettext "[ -T kdc_vendor ] specifies which KDC vendor is the server")\n" >&2 6686656Ssemery printf "\t$(gettext "[ -a adminuser ] specifies the Kerberos administrator")\n" >&2 6696656Ssemery printf "\t$(gettext "[ -c filepath ] specifies the krb5.conf path used to configure this client")\n" >&2 6706656Ssemery 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 6716656Ssemery printf "\t$(gettext "[ -f fqdn_list ] specifies which domains to configure host keys for this client")\n" >&2 6726656Ssemery printf "\t$(gettext "[ -h logicalhostname ] configure the logical host name for a client that is in a cluster")\n" >&2 6736656Ssemery 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 6746656Ssemery printf "\t$(gettext "[ -m master ] master KDC server host name")\n" >&2 6756656Ssemery printf "\t$(gettext "[ -n ] configure client to be an NFS client")\n" >&2 6766656Ssemery printf "\t$(gettext "[ -p profile ] specifies which profile file to use to configure this client")\n" >&2 6776656Ssemery printf "\t$(gettext "[ -s pam_list ] update the service for Kerberos authentication")\n" >&2 6780Sstevel@tonic-gate error_message 6790Sstevel@tonic-gate} 6800Sstevel@tonic-gate 6816656Ssemeryfunction discover_domain { 6826656Ssemery typeset dom DOMs 6836656Ssemery 6846656Ssemery if [[ -z $realm ]]; then 6856656Ssemery set -A DOMs -- `$KLOOKUP _ldap._tcp.dc._msdcs S` 6866656Ssemery else 6876656Ssemery set -A DOMs -- `$KLOOKUP _ldap._tcp.dc._msdcs.$realm S` 6886656Ssemery fi 6896656Ssemery 6906656Ssemery [[ -z ${DOMs[0]} ]] && return 1 6916656Ssemery 6926656Ssemery dom=${DOMs[0]} 6936656Ssemery 6946656Ssemery dom=${dom#*.} 6956656Ssemery dom=${dom% *} 6966656Ssemery 6976656Ssemery domain=$dom 6986656Ssemery 6996656Ssemery return 0 7006656Ssemery} 7016656Ssemery 7026656Ssemeryfunction check_nss_hosts_or_ipnodes_config { 7036656Ssemery typeset backend 7046656Ssemery 7056656Ssemery for backend in $1 7066656Ssemery do 7076656Ssemery [[ $backend == dns ]] && return 0 7086656Ssemery done 7096656Ssemery return 1 7106656Ssemery} 7116656Ssemery 7126656Ssemeryfunction check_nss_conf { 7136656Ssemery typeset i j hosts_config 7146656Ssemery 7156656Ssemery for i in hosts ipnodes 7166656Ssemery do 7176656Ssemery grep "^${i}:" /etc/nsswitch.conf|read j hosts_config 7186656Ssemery check_nss_hosts_or_ipnodes_config "$hosts_config" || return 1 7196656Ssemery done 7206656Ssemery 7216656Ssemery return 0 7226656Ssemery} 7236656Ssemery 7246656Ssemeryfunction canon_resolve { 7256656Ssemery typeset name ip 7266656Ssemery 7276656Ssemery name=`$KLOOKUP $1 C` 7286656Ssemery [[ -z $name ]] && name=`$KLOOKUP $1 A` 7296656Ssemery [[ -z $name ]] && return 7306656Ssemery 7316656Ssemery ip=`$KLOOKUP $name I` 7326656Ssemery [[ -z $ip ]] && return 7336815Ssemery for i in $ip 7346815Ssemery do 7356815Ssemery if ping $i 2 > /dev/null 2>&1; then 7366815Ssemery break 7376815Ssemery else 7386815Ssemery i= 7396815Ssemery fi 7406815Ssemery done 7416656Ssemery 7426656Ssemery cname=`$KLOOKUP $ip P` 7436656Ssemery [[ -z $cname ]] && return 7446656Ssemery 7456656Ssemery print -- "$cname" 7466656Ssemery} 7476656Ssemery 7486656Ssemeryfunction rev_resolve { 7496656Ssemery typeset name ip 7506656Ssemery 7516656Ssemery ip=`$KLOOKUP $1 I` 7526656Ssemery 7536656Ssemery [[ -z $ip ]] && return 7546656Ssemery name=`$KLOOKUP $ip P` 7556656Ssemery [[ -z $name ]] && return 7566656Ssemery 7576656Ssemery print -- $name 7586656Ssemery} 7596656Ssemery 7606656Ssemery# Convert an AD-style domain DN to a DNS domainname 7616656Ssemeryfunction dn2dns { 7626656Ssemery typeset OIFS dname dn comp components 7636656Ssemery 7646656Ssemery dn=$1 7656656Ssemery dname= 7666656Ssemery 7676656Ssemery OIFS="$IFS" 7686656Ssemery IFS=, 7696656Ssemery set -A components -- $1 7706656Ssemery IFS="$OIFS" 7716656Ssemery 7726656Ssemery for comp in "${components[@]}" 7736656Ssemery do 7746656Ssemery [[ "$comp" == [dD][cC]=* ]] || continue 7756656Ssemery dname="$dname.${comp#??=}" 7766656Ssemery done 7776656Ssemery 7786656Ssemery print ${dname#.} 7796656Ssemery} 7806656Ssemery 7816656Ssemery# Form a base DN from a DNS domainname and container 7826656Ssemeryfunction getBaseDN { 7836656Ssemery if [[ -n "$2" ]] 7846656Ssemery then 7856656Ssemery baseDN="CN=$1,$(dns2dn $2)" 7866656Ssemery else 7876656Ssemery baseDN="$(dns2dn $2)" 7886656Ssemery fi 7896656Ssemery} 7906656Ssemery 7916656Ssemery# Convert a DNS domainname to an AD-style DN for that domain 7926656Ssemeryfunction dns2dn { 7936656Ssemery typeset OIFS dn labels 7946656Ssemery 7956656Ssemery OIFS="$IFS" 7966656Ssemery IFS=. 7976656Ssemery set -A labels -- $1 7986656Ssemery IFS="$OIFS" 7996656Ssemery 8006656Ssemery dn= 8016656Ssemery for label in "${labels[@]}" 8026656Ssemery do 8036656Ssemery dn="${dn},DC=$label" 8046656Ssemery done 8056656Ssemery 8066656Ssemery print -- "${dn#,}" 8076656Ssemery} 8086656Ssemery 8096656Ssemeryfunction getSRVs { 8106656Ssemery typeset srv port 8116656Ssemery 8126656Ssemery $KLOOKUP $1 S | while read srv port 8136656Ssemery do 8146815Ssemery if ping $srv 2 > /dev/null 2>&1; then 8156815Ssemery print -- $srv $port 8166815Ssemery fi 8176656Ssemery done 8186656Ssemery} 8196656Ssemery 8206656Ssemeryfunction getKDC { 8216656Ssemery typeset j 8226656Ssemery 8236656Ssemery set -A KPWs -- $(getSRVs _kpasswd._tcp.$dom.) 8246656Ssemery kpasswd=${KPWs[0]} 8256656Ssemery 8266656Ssemery if [[ -n $siteName ]] 8276656Ssemery then 8286656Ssemery set -A KDCs -- $(getSRVs _kerberos._tcp.$siteName._sites.$dom.) 8296656Ssemery kdc=${KDCs[0]} 8306656Ssemery [[ -n $kdc ]] && return 8316656Ssemery fi 8326656Ssemery 8336656Ssemery # No site name 8346656Ssemery set -A KDCs -- $(getSRVs _kerberos._tcp.$dom.) 8356656Ssemery kdc=${KDCs[0]} 8366656Ssemery [[ -n $kdc ]] && return 8376656Ssemery 8386656Ssemery # Default 8396656Ssemery set -A KDCs -- $DomainDnsZones 88 8406656Ssemery kdc=$ForestDnsZones 8416656Ssemery} 8426656Ssemery 8436656Ssemeryfunction getDC { 8446656Ssemery typeset j 8456656Ssemery 8466656Ssemery if [[ -n $siteName ]] 8476656Ssemery then 8486656Ssemery set -A DCs -- $(getSRVs _ldap._tcp.$siteName._sites.dc._msdcs.$dom.) 8496656Ssemery dc=${DCs[0]} 8506656Ssemery [[ -n $dc ]] && return 8516656Ssemery fi 8526656Ssemery 8536656Ssemery # No site name 8546656Ssemery set -A DCs -- $(getSRVs _ldap._tcp.dc._msdcs.$dom.) 8556656Ssemery dc=${DCs[0]} 8566656Ssemery [[ -n $dc ]] && return 8576656Ssemery 8586656Ssemery # Default 8596656Ssemery set -A DCs -- $DomainDnsZones 389 8606656Ssemery dc=$DomainDnsZones 8616656Ssemery} 8626656Ssemery 8636656Ssemeryfunction write_ads_krb5conf { 8646656Ssemery printf "\n$(gettext "Setting up %s").\n\n" $KRB5_CONFIG_FILE 8656656Ssemery 8666656Ssemery exec 3>$KRB5_CONFIG 8676656Ssemery if [[ $? -ne 0 ]]; then 8689833SShawn.Emery@Sun.COM printf "\n$(gettext "Can not write to %s, exiting").\n" $KRB5_CONFIG >&2 8696656Ssemery error_message 8706656Ssemery fi 8716656Ssemery 8726656Ssemery printf "[libdefaults]\n" 1>&3 8736656Ssemery printf "\tdefault_realm = $realm\n" 1>&3 8746656Ssemery printf "\n[realms]\n" 1>&3 8756656Ssemery printf "\t$realm = {\n" 1>&3 8766656Ssemery for i in ${KDCs[@]} 8776656Ssemery do 8786656Ssemery [[ $i == +([0-9]) ]] && continue 8796656Ssemery printf "\t\tkdc = $i\n" 1>&3 8806656Ssemery done 8816656Ssemery # Defining the same as admin_server. This would cause auth failures 8826656Ssemery # if this was different. 8836656Ssemery printf "\n\t\tkpasswd_server = $KDC\n" 1>&3 8846656Ssemery printf "\n\t\tadmin_server = $KDC\n" 1>&3 8856656Ssemery printf "\t\tkpasswd_protocol = SET_CHANGE\n\t}\n" 1>&3 8866656Ssemery printf "\n[domain_realm]\n" 1>&3 8876656Ssemery printf "\t.$dom = $realm\n\n" 1>&3 8886656Ssemery printf "[logging]\n" 1>&3 8896656Ssemery printf "\tdefault = FILE:/var/krb5/kdc.log\n" 1>&3 8906656Ssemery printf "\tkdc = FILE:/var/krb5/kdc.log\n" 1>&3 8916656Ssemery printf "\tkdc_rotate = {\n\t\tperiod = 1d\n\t\tversions = 10\n\t}\n\n" 1>&3 8926656Ssemery printf "[appdefaults]\n" 1>&3 8936656Ssemery printf "\tkinit = {\n\t\trenewable = true\n\t\tforwardable = true\n\t}\n" 1>&3 8946656Ssemery} 8956656Ssemery 8966656Ssemeryfunction getForestName { 8976656Ssemery ldapsearch -R -T -h $dc $ldap_args \ 8986656Ssemery -b "" -s base "" schemaNamingContext| \ 8996656Ssemery grep ^schemaNamingContext|read j schemaNamingContext 9006656Ssemery 9016656Ssemery if [[ $? -ne 0 ]]; then 9029833SShawn.Emery@Sun.COM printf "$(gettext "Can't find forest").\n" >&2 9036656Ssemery error_message 9046656Ssemery fi 9056656Ssemery schemaNamingContext=${schemaNamingContext#CN=Schema,CN=Configuration,} 9066656Ssemery 9076656Ssemery [[ -z $schemaNamingContext ]] && return 1 9086656Ssemery 9096656Ssemery forest= 9106656Ssemery while [[ -n $schemaNamingContext ]] 9116656Ssemery do 9126656Ssemery schemaNamingContext=${schemaNamingContext#DC=} 9136656Ssemery forest=${forest}.${schemaNamingContext%%,*} 9146656Ssemery [[ "$schemaNamingContext" = *,* ]] || break 9156656Ssemery schemaNamingContext=${schemaNamingContext#*,} 9166656Ssemery done 9176656Ssemery forest=${forest#.} 9186656Ssemery} 9196656Ssemery 9206656Ssemeryfunction getGC { 9216656Ssemery typeset j 9226656Ssemery 9236656Ssemery [[ -n $gc ]] && return 0 9246656Ssemery 9256656Ssemery if [[ -n $siteName ]] 9266656Ssemery then 9276656Ssemery set -A GCs -- $(getSRVs _ldap._tcp.$siteName._sites.gc._msdcs.$forest.) 9286656Ssemery gc=${GCs[0]} 9296656Ssemery [[ -n $gc ]] && return 9306656Ssemery fi 9316656Ssemery 9326656Ssemery # No site name 9336656Ssemery set -A GCs -- $(getSRVs _ldap._tcp.gc._msdcs.$forest.) 9346656Ssemery gc=${GCs[0]} 9356656Ssemery [[ -n $gc ]] && return 9366656Ssemery 9376656Ssemery # Default 9386656Ssemery set -A GCs -- $ForestDnsZones 3268 9396656Ssemery gc=$ForestDnsZones 9406656Ssemery} 9416656Ssemery 9429833SShawn.Emery@Sun.COM# 9439833SShawn.Emery@Sun.COM# The local variables used to calculate the IP address are of type unsigned 9449833SShawn.Emery@Sun.COM# integer (-ui), as this is required to restrict the integer to 32b. 9459833SShawn.Emery@Sun.COM# Starting in ksh88, Solaris has incorrectly assummed that -i represents 64b. 9469833SShawn.Emery@Sun.COM# 9476656Ssemeryfunction ipAddr2num { 9486656Ssemery typeset OIFS 9499833SShawn.Emery@Sun.COM typeset -ui16 num 9506656Ssemery 9516656Ssemery if [[ "$1" != +([0-9]).+([0-9]).+([0-9]).+([0-9]) ]] 9526656Ssemery then 9536656Ssemery print 0 9546656Ssemery return 0 9556656Ssemery fi 9566656Ssemery 9576656Ssemery OIFS="$IFS" 9586656Ssemery IFS=. 9596656Ssemery set -- $1 9606656Ssemery IFS="$OIFS" 9616656Ssemery 9626656Ssemery num=$((${1}<<24 | ${2}<<16 | ${3}<<8 | ${4})) 9636656Ssemery 9646656Ssemery print -- $num 9656656Ssemery} 9666656Ssemery 9679833SShawn.Emery@Sun.COM# 9689833SShawn.Emery@Sun.COM# The local variables used to calculate the IP address are of type unsigned 9699833SShawn.Emery@Sun.COM# integer (-ui), as this is required to restrict the integer to 32b. 9709833SShawn.Emery@Sun.COM# Starting in ksh88, Solaris has incorrectly assummed that -i represents 64b. 9719833SShawn.Emery@Sun.COM# 9726656Ssemeryfunction num2ipAddr { 9739833SShawn.Emery@Sun.COM typeset -ui16 num 9749833SShawn.Emery@Sun.COM typeset -ui10 a b c d 9756656Ssemery 9766656Ssemery num=$1 9776656Ssemery a=$((num>>24 )) 9786656Ssemery b=$((num>>16 & 16#ff)) 9796656Ssemery c=$((num>>8 & 16#ff)) 9806656Ssemery d=$((num & 16#ff)) 9816656Ssemery print -- $a.$b.$c.$d 9826656Ssemery} 9836656Ssemery 9849833SShawn.Emery@Sun.COM# 9859833SShawn.Emery@Sun.COM# The local variables used to calculate the IP address are of type unsigned 9869833SShawn.Emery@Sun.COM# integer (-ui), as this is required to restrict the integer to 32b. 9879833SShawn.Emery@Sun.COM# Starting in ksh88, Solaris has incorrectly assummed that -i represents 64b. 9889833SShawn.Emery@Sun.COM# 9896656Ssemeryfunction netmask2length { 9909833SShawn.Emery@Sun.COM typeset -ui16 netmask 9916656Ssemery typeset -i len 9926656Ssemery 9936656Ssemery netmask=$1 9946656Ssemery len=32 9956656Ssemery while [[ $((netmask % 2)) -eq 0 ]] 9966656Ssemery do 9976656Ssemery netmask=$((netmask>>1)) 9986656Ssemery len=$((len - 1)) 9996656Ssemery done 10006656Ssemery print $len 10016656Ssemery} 10026656Ssemery 10039833SShawn.Emery@Sun.COM# 10049833SShawn.Emery@Sun.COM# The local variables used to calculate the IP address are of type unsigned 10059833SShawn.Emery@Sun.COM# integer (-ui), as this is required to restrict the integer to 32b. 10069833SShawn.Emery@Sun.COM# Starting in ksh88, Solaris has incorrectly assummed that -i represents 64b. 10079833SShawn.Emery@Sun.COM# 10086656Ssemeryfunction getSubnets { 10099833SShawn.Emery@Sun.COM typeset -ui16 addr netmask 10109833SShawn.Emery@Sun.COM typeset -ui16 classa=16\#ff000000 10116656Ssemery 10126656Ssemery ifconfig -a|while read line 10136656Ssemery do 10146656Ssemery addr=0 10156656Ssemery netmask=0 10166656Ssemery set -- $line 10176656Ssemery [[ $1 == inet ]] || continue 10186656Ssemery while [[ $# -gt 0 ]] 10196656Ssemery do 10206656Ssemery case "$1" in 10216656Ssemery inet) addr=$(ipAddr2num $2); shift;; 10226656Ssemery netmask) eval netmask=16\#$2; shift;; 10236656Ssemery *) :; 10246656Ssemery esac 10256656Ssemery shift 10266656Ssemery done 10276656Ssemery 10286656Ssemery [[ $addr -eq 0 || $netmask -eq 0 ]] && continue 10296656Ssemery [[ $((addr & classa)) -eq 16\#7f000000 ]] && continue 10306656Ssemery 10316656Ssemery print $(num2ipAddr $((addr & netmask)))/$(netmask2length $netmask) 10326656Ssemery done 10336656Ssemery} 10346656Ssemery 10356656Ssemeryfunction getSite { 10366656Ssemery typeset subnet siteDN j ldapsrv subnet_dom 10376656Ssemery 10386656Ssemery eval "[[ -n \"\$siteName\" ]]" && return 10396656Ssemery for subnet in $(getSubnets) 10406656Ssemery do 10416656Ssemery ldapsearch -R -T -h $dc $ldap_args \ 10426656Ssemery -p 3268 -b "" -s sub cn=$subnet dn |grep ^dn|read j subnetDN 10436656Ssemery 10446656Ssemery [[ -z $subnetDN ]] && continue 10456656Ssemery subnet_dom=$(dn2dns $subnetDN) 10466656Ssemery ldapsrv=$(canon_resolve DomainDnsZones.$subnet_dom) 10476815Ssemery [[ -z $ldapsrv ]] && continue 10486656Ssemery ldapsearch -R -T -h $ldapsrv $ldap_args \ 10496656Ssemery -b "$subnetDN" -s base "" siteObject \ 10506656Ssemery |grep ^siteObject|read j siteDN 10516656Ssemery 10526656Ssemery [[ -z $siteDN ]] && continue 10536656Ssemery 10546656Ssemery eval siteName=${siteDN%%,*} 10556656Ssemery eval siteName=\${siteName#CN=} 10566656Ssemery return 10576656Ssemery done 10586656Ssemery} 10596656Ssemery 10606656Ssemeryfunction doKRB5config { 10616656Ssemery [[ -f $KRB5_CONFIG_FILE ]] && \ 10626656Ssemery cp $KRB5_CONFIG_FILE ${KRB5_CONFIG_FILE}-pre-kclient 10636656Ssemery 10646656Ssemery [[ -f $KRB5_KEYTAB_FILE ]] && \ 10656656Ssemery cp $KRB5_KEYTAB_FILE ${KRB5_KEYTAB_FILE}-pre-kclient 10666656Ssemery 10676815Ssemery [[ -s $KRB5_CONFIG ]] && cp $KRB5_CONFIG $KRB5_CONFIG_FILE 10686815Ssemery [[ -s $KRB5_CONFIG_FILE ]] && chmod 0644 $KRB5_CONFIG_FILE 10696815Ssemery [[ -s $new_keytab ]] && cp $new_keytab $KRB5_KEYTAB_FILE 10706815Ssemery [[ -s $KRB5_KEYTAB_FILE ]] && chmod 0600 $KRB5_KEYTAB_FILE 10716656Ssemery} 10726656Ssemery 10736656Ssemeryfunction addDNSRR { 10746656Ssemery smbFMRI=svc:/network/smb/server:default 10756656Ssemery ddnsProp=smbd/ddns_enable 10766656Ssemery enProp=general/enabled 10776656Ssemery 10786656Ssemery enabled=`svcprop -p $enProp $smbFMRI` 10796656Ssemery ddns_enable=`svcprop -p $ddnsProp $smbFMRI` 10806656Ssemery 10816656Ssemery if [[ $enabled == true && $ddns_enable != true ]]; then 10826656Ssemery printf "$(gettext "Warning: won't create DNS records for client").\n" 10836656Ssemery printf "$(gettext "%s property not set to 'true' for the %s FMRI").\n" $ddnsProp $smbFMRI 10846656Ssemery return 10856656Ssemery fi 10866656Ssemery 10876656Ssemery # Destroy any existing ccache as GSS_C_NO_CREDENTIAL will pick up any 10886656Ssemery # residual default credential in the cache. 10896656Ssemery kdestroy > /dev/null 2>&1 10906656Ssemery 10916656Ssemery $KDYNDNS -d $1 > /dev/null 2>&1 10926656Ssemery if [[ $? -ne 0 ]]; then 10936656Ssemery # 10946656Ssemery # Non-fatal, we should carry-on as clients may resolve to 10956656Ssemery # different servers and the client could already exist there. 10966656Ssemery # 10978334SJose.Borrego@Sun.COM printf "$(gettext "Warning: unable to create DNS records for client").\n" 10986656Ssemery 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 10996656Ssemery fi 11006656Ssemery} 11016656Ssemery 11026656Ssemeryfunction setSMB { 11036656Ssemery typeset domain=$1 11046656Ssemery typeset server=$2 11056656Ssemery smbFMRI=svc:/network/smb/server 11066656Ssemery 110711570SShawn.Emery@Sun.COM printf "%s" "$newpw" | $KSMB -d $domain -s $server 11086656Ssemery if [[ $? -ne 0 ]]; then 11098334SJose.Borrego@Sun.COM printf "$(gettext "Warning: unable to set %s domain, server and password information").\n" $smbFMRI 11106656Ssemery return 11116656Ssemery fi 11126656Ssemery 11138334SJose.Borrego@Sun.COM svcadm restart $smbFMRI > /dev/null 2>&1 11146656Ssemery if [[ $? -ne 0 ]]; then 11158334SJose.Borrego@Sun.COM printf "$(gettext "Warning: unable to restart %s").\n" $smbFMRI 11166656Ssemery fi 11176656Ssemery} 11186656Ssemery 11196656Ssemeryfunction compareDomains { 11206656Ssemery typeset oldDom hspn newDom=$1 11216656Ssemery 11226656Ssemery # If the client has been previously configured in a different 11236656Ssemery # realm/domain then we need to prompt the user to see if they wish to 11246656Ssemery # switch domains. 11256815Ssemery klist -k 2>&1 | grep @ | read j hspn 11266656Ssemery [[ -z $hspn ]] && return 11276656Ssemery 11286656Ssemery oldDom=${hspn#*@} 11296656Ssemery if [[ $oldDom != $newDom ]]; then 11306656Ssemery printf "$(gettext "The client is currently configured in a different domain").\n" 11316656Ssemery printf "$(gettext "Currently in the '%s' domain, trying to join the '%s' domain").\n" $oldDom $newDom 11326656Ssemery query "$(gettext "Do you want the client to join a new domain") ?" 11336656Ssemery printf "\n" 11346656Ssemery if [[ $answer != yes ]]; then 11359833SShawn.Emery@Sun.COM printf "$(gettext "Client will not be joined to the new domain").\n" >&2 11366656Ssemery error_message 11376656Ssemery fi 11386656Ssemery fi 11396656Ssemery} 11406656Ssemery 11416656Ssemeryfunction getKDCDC { 11426656Ssemery 11436656Ssemery getKDC 11446656Ssemery if [[ -n $kdc ]]; then 11456656Ssemery KDC=$kdc 11466656Ssemery dc=$kdc 11476656Ssemery else 11486656Ssemery getDC 11496656Ssemery if [[ -n $dc ]]; then 11506656Ssemery KDC=$dc 11516656Ssemery else 11529833SShawn.Emery@Sun.COM printf "$(gettext "Could not find domain controller server for '%s'. Exiting").\n" $realm >&2 11536656Ssemery error_message 11546656Ssemery fi 11556656Ssemery fi 11566656Ssemery} 11576656Ssemery 115811570SShawn.Emery@Sun.COMfunction gen_rand { 115911570SShawn.Emery@Sun.COM typeset -u hex 116011570SShawn.Emery@Sun.COM 116111570SShawn.Emery@Sun.COM dd if=/dev/random bs=1 count=1 2>/dev/null | od -A n -tx1 | read hex 116211570SShawn.Emery@Sun.COM 116311570SShawn.Emery@Sun.COM printf %s $((16#$hex)) 116411570SShawn.Emery@Sun.COM} 116511570SShawn.Emery@Sun.COM 11666656Ssemeryfunction join_domain { 11676656Ssemery typeset -u upcase_nodename 116811061SShawn.Emery@Sun.COM typeset -l locase_nodename 116911061SShawn.Emery@Sun.COM typeset -L15 string15 11706656Ssemery typeset netbios_nodename fqdn 11716656Ssemery 11726656Ssemery container=Computers 11736656Ssemery ldap_args="-o authzid= -o mech=gssapi" 11746656Ssemery userAccountControlBASE=4096 11756656Ssemery 11766656Ssemery if [[ -z $ADMIN_PRINC ]]; then 11776656Ssemery cprinc=Administrator 11786656Ssemery else 11796656Ssemery cprinc=$ADMIN_PRINC 11806656Ssemery fi 11816656Ssemery 11826656Ssemery if ! discover_domain; then 11839833SShawn.Emery@Sun.COM printf "$(gettext "Can not find realm") '%s'.\n" $realm >&2 11846656Ssemery error_message 11856656Ssemery fi 11866656Ssemery 11876656Ssemery dom=$domain 11886656Ssemery realm=$domain 118911061SShawn.Emery@Sun.COM 119011061SShawn.Emery@Sun.COM if [[ ${#hostname} -gt 15 ]]; then 119111061SShawn.Emery@Sun.COM string15=$hostname 119211061SShawn.Emery@Sun.COM upcase_nodename=$string15 119311061SShawn.Emery@Sun.COM locase_nodename=$string15 119411061SShawn.Emery@Sun.COM else 119511061SShawn.Emery@Sun.COM upcase_nodename=$hostname 119611061SShawn.Emery@Sun.COM locase_nodename=$hostname 119711061SShawn.Emery@Sun.COM fi 119811061SShawn.Emery@Sun.COM 11996656Ssemery netbios_nodename="${upcase_nodename}\$" 12006656Ssemery fqdn=$hostname.$domain 120110001SJoyce.McIntosh@Sun.COM upn=host/${fqdn}@${realm} 12026656Ssemery 12036656Ssemery grep=/usr/xpg4/bin/grep 12046656Ssemery 12056656Ssemery object=$(mktemp -q -t kclient-computer-object.XXXXXX) 12066656Ssemery if [[ -z $object ]]; then 12076656Ssemery printf "\n$(gettext "Can not create temporary file, exiting").\n 12086656Ssemery" >&2 12096656Ssemery error_message 12106656Ssemery fi 12116656Ssemery 12126656Ssemery grep=/usr/xpg4/bin/grep 12136656Ssemery 12146656Ssemery modify_existing=false 12156656Ssemery recreate=false 12166656Ssemery 12176656Ssemery DomainDnsZones=$(rev_resolve DomainDnsZones.$dom.) 12186656Ssemery ForestDnsZones=$(rev_resolve ForestDnsZones.$dom.) 12196656Ssemery 12206656Ssemery getBaseDN "$container" "$dom" 12216656Ssemery 12226656Ssemery if [[ -n $KDC ]]; then 12236656Ssemery dc=$KDC 12246656Ssemery else 12256656Ssemery getKDCDC 12266656Ssemery fi 12276656Ssemery 12286656Ssemery write_ads_krb5conf 12296656Ssemery 12306815Ssemery printf "$(gettext "Attempting to join '%s' to the '%s' domain").\n\n" $upcase_nodename $realm 12316656Ssemery 12326656Ssemery kinit $cprinc@$realm 12336656Ssemery if [[ $? -ne 0 ]]; then 12349833SShawn.Emery@Sun.COM printf "$(gettext "Could not authenticate %s. Exiting").\n" $cprinc@$realm >&2 12356656Ssemery error_message 12366656Ssemery fi 12376656Ssemery 12386656Ssemery if getForestName 12396656Ssemery then 12406656Ssemery printf "\n$(gettext "Forest name found: %s")\n\n" $forest 12416656Ssemery else 12426656Ssemery printf "\n$(gettext "Forest name not found, assuming forest is the domain name").\n" 12436656Ssemery fi 12446656Ssemery 12456656Ssemery getGC 12466656Ssemery getSite 12476656Ssemery 12486656Ssemery if [[ -z $siteName ]] 12496656Ssemery then 12506656Ssemery printf "$(gettext "Site name not found. Local DCs/GCs will not be discovered").\n\n" 12516656Ssemery else 12526656Ssemery printf "$(gettext "Looking for _local_ KDCs, DCs and global catalog servers (SRV RRs)").\n" 12536656Ssemery getKDCDC 12546656Ssemery getGC 12556656Ssemery 12566656Ssemery write_ads_krb5conf 12576656Ssemery fi 12586656Ssemery 12596656Ssemery if [[ ${#GCs} -eq 0 ]]; then 12609833SShawn.Emery@Sun.COM printf "$(gettext "Could not find global catalogs. Exiting").\n" >&2 12616656Ssemery error_message 12626656Ssemery fi 12636656Ssemery 12646656Ssemery # Check to see if the client is transitioning between domains. 12656656Ssemery compareDomains $realm 12666656Ssemery 12676656Ssemery # Here we check domainFunctionality to see which release: 12686656Ssemery # 0, 1, 2: Windows 2000, 2003 Interim, 2003 respecitively 12696656Ssemery # 3: Windows 2008 12706656Ssemery level=0 12716656Ssemery ldapsearch -R -T -h "$dc" $ldap_args -b "" -s base "" \ 12726656Ssemery domainControllerFunctionality| grep ^domainControllerFunctionality| \ 12736656Ssemery read j level 12746656Ssemery if [[ $? -ne 0 ]]; then 12759833SShawn.Emery@Sun.COM printf "$(gettext "Search for domain functionality failed, exiting").\n" >&2 12766656Ssemery error_message 12776656Ssemery fi 12786656Ssemery 12796656Ssemery if ldapsearch -R -T -h "$dc" $ldap_args -b "$baseDN" \ 12806656Ssemery -s sub sAMAccountName="$netbios_nodename" dn > /dev/null 2>&1 12816656Ssemery then 12826656Ssemery : 12836656Ssemery else 12849833SShawn.Emery@Sun.COM printf "$(gettext "Search for node failed, exiting").\n" >&2 12856656Ssemery error_message 12866656Ssemery fi 12876656Ssemery ldapsearch -R -T -h "$dc" $ldap_args -b "$baseDN" -s sub \ 12886656Ssemery sAMAccountName="$netbios_nodename" dn|grep "^dn:"|read j dn 12896656Ssemery 12906656Ssemery if [[ -z $dn ]]; then 12916656Ssemery : # modify_existing is already false, which is what we want. 12926656Ssemery else 12936656Ssemery printf "$(gettext "Computer account '%s' already exists in the '%s' domain").\n" $upcase_nodename $realm 12946656Ssemery query "$(gettext "Do you wish to recreate this computer account") ?" 12956656Ssemery printf "\n" 12966656Ssemery if [[ $answer == yes ]]; then 12976656Ssemery recreate=true 12986656Ssemery else 12996656Ssemery modify_existing=true 13006656Ssemery fi 13016656Ssemery fi 13026656Ssemery 13036656Ssemery if [[ $modify_existing == false && -n $dn ]]; then 13046656Ssemery query "$(gettext "Would you like to delete any sub-object found for this computer account") ?" 13056656Ssemery if [[ $answer == yes ]]; then 13066656Ssemery printf "$(gettext "Looking to see if the machine account contains other objects")...\n" 13076656Ssemery ldapsearch -R -T -h "$dc" $ldap_args -b "$dn" -s sub "" dn | while read j sub_dn 13086656Ssemery do 13096656Ssemery [[ $j != dn: || -z $sub_dn || $dn == $sub_dn ]] && continue 13106656Ssemery if $recreate; then 13116656Ssemery printf "$(gettext "Deleting the following object: %s")\n" ${sub_dn#$dn} 13126656Ssemery ldapdelete -h "$dc" $ldap_args "$sub_dn" > /dev/null 2>&1 13136656Ssemery if [[ $? -ne 0 ]]; then 13146656Ssemery printf "$(gettext "Error in deleting object: %s").\n" ${sub_dn#$dn} 13156656Ssemery fi 13166656Ssemery else 13176656Ssemery printf "$(gettext "The following object will not be deleted"): %s\n" ${sub_dn#$dn} 13186656Ssemery fi 13196656Ssemery done 13206656Ssemery fi 13216656Ssemery 13226656Ssemery if $recreate; then 13236656Ssemery ldapdelete -h "$dc" $ldap_args "$dn" > /dev/null 2>&1 13246656Ssemery if [[ $? -ne 0 ]]; then 13259833SShawn.Emery@Sun.COM printf "$(gettext "Error in deleting object: %s").\n" ${sub_dn#$dn} >&2 13266656Ssemery error_message 13276656Ssemery fi 13286656Ssemery elif $modify_existing; then 13296656Ssemery : # Nothing to delete 13306656Ssemery else 13319833SShawn.Emery@Sun.COM printf "$(gettext "A machine account already exists").\n" >&2 13326656Ssemery error_message 13336656Ssemery fi 13346656Ssemery fi 13356656Ssemery 133611061SShawn.Emery@Sun.COM [[ -z $dn ]] && dn="CN=${upcase_nodename},${baseDN}" 13376656Ssemery if $modify_existing; then 13386656Ssemery cat > "$object" <<EOF 133911061SShawn.Emery@Sun.COMdn: $dn 13406656Ssemerychangetype: modify 13416656Ssemeryreplace: userPrincipalName 13426656SsemeryuserPrincipalName: $upn 13436656Ssemery- 13446656Ssemeryreplace: servicePrincipalName 13456656SsemeryservicePrincipalName: host/${fqdn} 13466656Ssemery- 13476656Ssemeryreplace: userAccountControl 13486656SsemeryuserAccountControl: $((userAccountControlBASE + 32 + 2)) 13496656Ssemery- 13506656Ssemeryreplace: dNSHostname 13516656SsemerydNSHostname: ${fqdn} 13526656SsemeryEOF 13536656Ssemery 13546656Ssemery printf "$(gettext "A machine account already exists; updating it").\n" 13556815Ssemery ldapadd -h "$dc" $ldap_args -f "$object" > /dev/null 2>&1 13566656Ssemery if [[ $? -ne 0 ]]; then 135711061SShawn.Emery@Sun.COM printf "$(gettext "Failed to modify the AD object via LDAP").\n" >&2 13586656Ssemery error_message 13596656Ssemery fi 13606656Ssemery else 136111061SShawn.Emery@Sun.COM dn="CN=${upcase_nodename},${baseDN}" 13626656Ssemery cat > "$object" <<EOF 136311061SShawn.Emery@Sun.COMdn: $dn 13646656SsemeryobjectClass: computer 13656656Ssemerycn: $upcase_nodename 13666656SsemerysAMAccountName: ${netbios_nodename} 13676656SsemeryuserPrincipalName: $upn 13686656SsemeryservicePrincipalName: host/${fqdn} 13696656SsemeryuserAccountControl: $((userAccountControlBASE + 32 + 2)) 13706656SsemerydNSHostname: ${fqdn} 13716656SsemeryEOF 13726656Ssemery 13736656Ssemery printf "$(gettext "Creating the machine account in AD via LDAP").\n\n" 13746656Ssemery 13756656Ssemery ldapadd -h "$dc" $ldap_args -f "$object" > /dev/null 2>&1 13766656Ssemery if [[ $? -ne 0 ]]; then 13779833SShawn.Emery@Sun.COM printf "$(gettext "Failed to create the AD object via LDAP").\n" >&2 13786656Ssemery error_message 13796656Ssemery fi 13806656Ssemery fi 13816656Ssemery 13826656Ssemery # Generate a new password for the new account 138311570SShawn.Emery@Sun.COM MAX_PASS=120 13846656Ssemery i=0 13856656Ssemery 138611570SShawn.Emery@Sun.COM # first check to see if /dev/random exists to generate a new password 138711570SShawn.Emery@Sun.COM if [[ ! -h /dev/random ]]; then 138811570SShawn.Emery@Sun.COM printf "$(gettext "/dev/random does not exist").\n" >&2 138911570SShawn.Emery@Sun.COM error_message 139011570SShawn.Emery@Sun.COM fi 13916656Ssemery 139211570SShawn.Emery@Sun.COM while ((MAX_PASS > i)) 139311570SShawn.Emery@Sun.COM do 139411570SShawn.Emery@Sun.COM # [MS-DISO] A machine password is an ASCII string of randomly 139511570SShawn.Emery@Sun.COM # chosen characters. Each character's ASCII code is between 32 139611570SShawn.Emery@Sun.COM # and 122 inclusive. 139711570SShawn.Emery@Sun.COM c=$(printf "\\$(printf %o $(($(gen_rand) % 91 + 32)))\n") 139811570SShawn.Emery@Sun.COM p="$p$c" 139911570SShawn.Emery@Sun.COM ((i+=1)) 140011570SShawn.Emery@Sun.COM done 14016656Ssemery 14026656Ssemery newpw=$p 140311570SShawn.Emery@Sun.COM if [[ ${#newpw} -ne MAX_PASS ]]; then 140411570SShawn.Emery@Sun.COM printf "$(gettext "Password created was of incorrect length").\n" >&2 140511570SShawn.Emery@Sun.COM error_message 140611570SShawn.Emery@Sun.COM fi 14076656Ssemery 14086656Ssemery # Set the new password 140911570SShawn.Emery@Sun.COM printf "%s" "$newpw" | $KSETPW ${netbios_nodename}@${realm} > /dev/null 2>&1 14106656Ssemery if [[ $? -ne 0 ]] 14116656Ssemery then 14129833SShawn.Emery@Sun.COM printf "$(gettext "Failed to set account password").\n" >&2 14136656Ssemery error_message 14146656Ssemery fi 14156656Ssemery 14166656Ssemery # Lookup the new principal's kvno: 14176656Ssemery ldapsearch -R -T -h "$dc" $ldap_args -b "$baseDN" \ 14186656Ssemery -s sub cn=$upcase_nodename msDS-KeyVersionNumber| \ 14196656Ssemery grep "^msDS-KeyVersionNumber"|read j kvno 14206656Ssemery [[ -z $kvno ]] && kvno=1 14216656Ssemery 14226656Ssemery # Set supported enctypes. This only works for Longhorn/Vista, so we 14236656Ssemery # ignore errors here. 14246656Ssemery userAccountControl=$((userAccountControlBASE + 524288 + 65536)) 14256656Ssemery set -A enctypes -- 14266656Ssemery 14276656Ssemery # Do we have local support for AES? 14286656Ssemery encrypt -l|grep ^aes|read j minkeysize maxkeysize 14296656Ssemery val= 14306656Ssemery if [[ $maxkeysize -eq 256 ]]; then 14316656Ssemery val=16 14326656Ssemery enctypes[${#enctypes[@]}]=aes256-cts-hmac-sha1-96 14336656Ssemery fi 14346656Ssemery if [[ $minkeysize -eq 128 ]]; then 14356656Ssemery ((val=val+8)) 14366656Ssemery enctypes[${#enctypes[@]}]=aes128-cts-hmac-sha1-96 14376656Ssemery fi 14386656Ssemery 14396656Ssemery # RC4 comes next (whether it's better than 1DES or not -- AD prefers it) 14406656Ssemery if encrypt -l|$grep -q ^arcfour 14416656Ssemery then 14426656Ssemery ((val=val+4)) 14436656Ssemery enctypes[${#enctypes[@]}]=arcfour-hmac-md5 14446656Ssemery else 14456656Ssemery # Use 1DES ONLY if we don't have arcfour 14466656Ssemery userAccountControl=$((userAccountControl + 2097152)) 14476656Ssemery fi 14486656Ssemery if encrypt -l | $grep -q ^des 14496656Ssemery then 14509833SShawn.Emery@Sun.COM ((val=val+2)) 14516656Ssemery enctypes[${#enctypes[@]}]=des-cbc-md5 14526656Ssemery fi 14536656Ssemery 14546656Ssemery if [[ ${#enctypes[@]} -eq 0 ]] 14556656Ssemery then 14566656Ssemery printf "$(gettext "No enctypes are supported").\n" 14579833SShawn.Emery@Sun.COM printf "$(gettext "Please enable arcfour or 1DES, then re-join; see cryptoadm(1M)").\n" >&2 14586656Ssemery error_message 14596656Ssemery fi 14606656Ssemery 14616656Ssemery # If domain crontroller is Longhorn or above then set new supported 14626656Ssemery # encryption type attributes. 14636656Ssemery if [[ $level -gt 2 ]]; then 14646656Ssemery cat > "$object" <<EOF 146511061SShawn.Emery@Sun.COMdn: $dn 14666656Ssemerychangetype: modify 14676656Ssemeryreplace: msDS-SupportedEncryptionTypes 14686656SsemerymsDS-SupportedEncryptionTypes: $val 14696656SsemeryEOF 14706656Ssemery ldapmodify -h "$dc" $ldap_args -f "$object" >/dev/null 2>&1 14716656Ssemery if [[ $? -ne 0 ]]; then 14726656Ssemery printf "$(gettext "Warning: Could not set the supported encryption type for computer account").\n" 14736656Ssemery fi 14746656Ssemery fi 14756656Ssemery 14766656Ssemery # We should probably check whether arcfour is available, and if not, 14776656Ssemery # then set the 1DES only flag, but whatever, it's not likely NOT to be 14786656Ssemery # available on S10/Nevada! 14796656Ssemery 14806656Ssemery # Reset userAccountControl 14816656Ssemery # 14826656Ssemery # NORMAL_ACCOUNT (512) | DONT_EXPIRE_PASSWORD (65536) | 14836656Ssemery # TRUSTED_FOR_DELEGATION (524288) 14846656Ssemery # 14856656Ssemery # and possibly UseDesOnly (2097152) (see above) 14866656Ssemery # 14876656Ssemery cat > "$object" <<EOF 148811061SShawn.Emery@Sun.COMdn: $dn 14896656Ssemerychangetype: modify 14906656Ssemeryreplace: userAccountControl 14916656SsemeryuserAccountControl: $userAccountControl 14926656SsemeryEOF 14936656Ssemery ldapmodify -h "$dc" $ldap_args -f "$object" >/dev/null 2>&1 14946656Ssemery if [[ $? -ne 0 ]]; then 14959833SShawn.Emery@Sun.COM printf "$(gettext "ldapmodify failed to modify account attribute").\n" >&2 14966656Ssemery error_message 14976656Ssemery fi 14986656Ssemery 14996656Ssemery # Setup a keytab file 15006656Ssemery set -A args -- 15016656Ssemery for enctype in "${enctypes[@]}" 15026656Ssemery do 15036656Ssemery args[${#args[@]}]=-e 15046656Ssemery args[${#args[@]}]=$enctype 15056656Ssemery done 15066656Ssemery 15076656Ssemery rm $new_keytab > /dev/null 2>&1 15086656Ssemery 15096656Ssemery cat > "$object" <<EOF 151011061SShawn.Emery@Sun.COMdn: $dn 15116656Ssemerychangetype: modify 15126656Ssemeryadd: servicePrincipalName 15136656SsemeryservicePrincipalName: nfs/${fqdn} 15146656SsemeryservicePrincipalName: HTTP/${fqdn} 15156656SsemeryservicePrincipalName: root/${fqdn} 15169833SShawn.Emery@Sun.COMservicePrincipalName: cifs/${fqdn} 151711061SShawn.Emery@Sun.COMservicePrincipalName: host/${upcase_nodename} 15186656SsemeryEOF 15196656Ssemery ldapmodify -h "$dc" $ldap_args -f "$object" >/dev/null 2>&1 15206656Ssemery if [[ $? -ne 0 ]]; then 15219833SShawn.Emery@Sun.COM printf "$(gettext "ldapmodify failed to modify account attribute").\n" >&2 15226656Ssemery error_message 15236656Ssemery fi 15246656Ssemery 15259833SShawn.Emery@Sun.COM # 15269833SShawn.Emery@Sun.COM # In Windows, unlike MIT based implementations we salt the keys with 152711061SShawn.Emery@Sun.COM # the UPN, which is based on the host/string15@realm elements, not 152811061SShawn.Emery@Sun.COM # with the individual SPN strings. 15299833SShawn.Emery@Sun.COM # 153011061SShawn.Emery@Sun.COM salt=host/${locase_nodename}.${domain}@${realm} 15319833SShawn.Emery@Sun.COM 1532*12566SShawn.Emery@Sun.COM skeys=(host/${fqdn}@${realm} nfs/${fqdn}@${realm} HTTP/${fqdn}@${realm}) 1533*12566SShawn.Emery@Sun.COM skeys+=(root/${fqdn}@${realm} cifs/${fqdn}@${realm}) 1534*12566SShawn.Emery@Sun.COM skeys+=(${netbios_nodename}@${realm} host/${upcase_nodename}@${realm}) 1535*12566SShawn.Emery@Sun.COM skeys+=(cifs/${upcase_nodename}@${realm}) 15369833SShawn.Emery@Sun.COM 1537*12566SShawn.Emery@Sun.COM ks_args="-n -s $salt -v $kvno -k $new_keytab ${args[@]}" 15386656Ssemery 1539*12566SShawn.Emery@Sun.COM for skey in ${skeys[@]} 1540*12566SShawn.Emery@Sun.COM do 1541*12566SShawn.Emery@Sun.COM printf "%s" "$newpw" | $KSETPW $ks_args $skey > /dev/null 2>&1 1542*12566SShawn.Emery@Sun.COM if [[ $? -ne 0 ]] 1543*12566SShawn.Emery@Sun.COM then 1544*12566SShawn.Emery@Sun.COM printf "$(gettext "Failed to set password").\n" >&2 1545*12566SShawn.Emery@Sun.COM error_message 1546*12566SShawn.Emery@Sun.COM fi 1547*12566SShawn.Emery@Sun.COM done 154811061SShawn.Emery@Sun.COM 15496656Ssemery doKRB5config 15506656Ssemery 15516656Ssemery addDNSRR $dom 15526656Ssemery 15536656Ssemery setSMB $dom $dc 15546656Ssemery 155511061SShawn.Emery@Sun.COM printf -- "---------------------------------------------------\n" 15566656Ssemery printf "$(gettext "Setup COMPLETE").\n\n" 15576656Ssemery 15586656Ssemery kdestroy -q 1>$TMP_FILE 2>&1 15596656Ssemery rm -f $TMP_FILE 15606656Ssemery rm -rf $TMPDIR > /dev/null 2>&1 15616656Ssemery 15626656Ssemery exit 0 15636656Ssemery} 15646656Ssemery 15650Sstevel@tonic-gate########################### 15660Sstevel@tonic-gate# Main section # 15670Sstevel@tonic-gate########################### 15680Sstevel@tonic-gate# 15690Sstevel@tonic-gate# Set the Kerberos config file and some default strings/files 15700Sstevel@tonic-gate# 15716656SsemeryKRB5_CONFIG_FILE=/etc/krb5/krb5.conf 15726656SsemeryKRB5_KEYTAB_FILE=/etc/krb5/krb5.keytab 15736656SsemeryRESOLV_CONF_FILE=/etc/resolv.conf 15746656Ssemery 15756656SsemeryKLOOKUP=/usr/lib/krb5/klookup; check_bin $KLOOKUP 15766656SsemeryKSETPW=/usr/lib/krb5/ksetpw; check_bin $KSETPW 15776656SsemeryKSMB=/usr/lib/krb5/ksmb; check_bin $KSMB 15786656SsemeryKDYNDNS=/usr/lib/krb5/kdyndns; check_bin $KDYNDNS 15796656Ssemery 15806656Ssemerydns_lookup=no 15816656Ssemeryask_fqdns=no 15826656Ssemeryadddns=no 15836815Ssemeryno_keytab=no 15840Sstevel@tonic-gatecheckval="" 15850Sstevel@tonic-gateprofile="" 15866656Ssemerytypeset -u realm 15876656Ssemerytypeset -l hostname KDC 15880Sstevel@tonic-gate 15896656Ssemeryexport TMPDIR="/var/run/kclient" 15906656Ssemery 15916656Ssemerymkdir $TMPDIR > /dev/null 2>&1 15929833SShawn.Emery@Sun.COMif [[ $? -ne 0 ]]; then 15939833SShawn.Emery@Sun.COM printf "\n$(gettext "Can not create directory: %s")\n\n" $TMPDIR >&2 15949833SShawn.Emery@Sun.COM exit 1 15959833SShawn.Emery@Sun.COMfi 15960Sstevel@tonic-gate 15976656SsemeryTMP_FILE=$(mktemp -q -t kclient-tmpfile.XXXXXX) 15986656Ssemeryexport KRB5_CONFIG=$(mktemp -q -t kclient-krb5conf.XXXXXX) 15996815Ssemeryexport KRB5CCNAME=$(mktemp -q -t kclient-krb5ccache.XXXXXX) 16006656Ssemerynew_keytab=$(mktemp -q -t kclient-krb5keytab.XXXXXX) 16016656Ssemeryif [[ -z $TMP_FILE || -z $KRB5_CONFIG || -z $KRB5CCNAME || -z $new_keytab ]] 16026656Ssemerythen 16039833SShawn.Emery@Sun.COM printf "\n$(gettext "Can not create temporary files, exiting").\n\n" >&2 16049833SShawn.Emery@Sun.COM exit 1 16050Sstevel@tonic-gatefi 16060Sstevel@tonic-gate 16070Sstevel@tonic-gate# 16080Sstevel@tonic-gate# If we are interrupted, cleanup after ourselves 16090Sstevel@tonic-gate# 16106656Ssemerytrap "exiting 1" HUP INT QUIT TERM 16110Sstevel@tonic-gate 16126656Ssemeryif [[ -d /usr/bin ]]; then 16136656Ssemery if [[ -d /usr/sbin ]]; then 16140Sstevel@tonic-gate PATH=/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:$PATH 16150Sstevel@tonic-gate export PATH 16160Sstevel@tonic-gate else 16170Sstevel@tonic-gate printf "\n$(gettext "Directory /usr/sbin not found, exiting").\n" >&2 16180Sstevel@tonic-gate exit 1 16190Sstevel@tonic-gate fi 16200Sstevel@tonic-gateelse 16210Sstevel@tonic-gate printf "\n$(gettext "Directory /usr/bin not found, exiting").\n" >&2 16220Sstevel@tonic-gate exit 1 16230Sstevel@tonic-gatefi 16240Sstevel@tonic-gate 16250Sstevel@tonic-gateprintf "\n$(gettext "Starting client setup")\n\n" 16266656Ssemeryprintf -- "---------------------------------------------------\n" 16270Sstevel@tonic-gate 16280Sstevel@tonic-gate# 16290Sstevel@tonic-gate# Check for uid 0, disallow otherwise 16300Sstevel@tonic-gate# 16310Sstevel@tonic-gateid 1>$TMP_FILE 2>&1 16326656Ssemeryif [[ $? -eq 0 ]]; then 16330Sstevel@tonic-gate if egrep -s "uid=0\(root\)" $TMP_FILE; then 16340Sstevel@tonic-gate # uid is 0, go ahead ... 16350Sstevel@tonic-gate : 16360Sstevel@tonic-gate else 16376656Ssemery printf "\n$(gettext "Administrative privileges are required to run this script, exiting").\n" >&2 16380Sstevel@tonic-gate error_message 16390Sstevel@tonic-gate fi 16400Sstevel@tonic-gateelse 16410Sstevel@tonic-gate cat $TMP_FILE; 16426656Ssemery printf "\n$(gettext "uid check failed, exiting").\n" >&2 16430Sstevel@tonic-gate error_message 16440Sstevel@tonic-gatefi 16450Sstevel@tonic-gate 16466656Ssemeryuname=$(uname -n) 16476656Ssemeryhostname=${uname%%.*} 16480Sstevel@tonic-gate 16490Sstevel@tonic-gate# 16500Sstevel@tonic-gate# Process the command-line arguments (if any) 16510Sstevel@tonic-gate# 16520Sstevel@tonic-gateOPTIND=1 16536656Ssemerywhile getopts nD:Kp:R:k:a:c:d:f:h:m:s:T: OPTIONS 16540Sstevel@tonic-gatedo 16550Sstevel@tonic-gate case $OPTIONS in 16566656Ssemery D) options="$options -D" 16576656Ssemery domain_list="$OPTARG" 16586656Ssemery ;; 16596656Ssemery K) options="$options -K" 16606656Ssemery no_keytab=yes 16610Sstevel@tonic-gate ;; 16620Sstevel@tonic-gate R) options="$options -R" 16636656Ssemery realm="$OPTARG" 16646656Ssemery checkval="REALM"; check_value $realm 16650Sstevel@tonic-gate ;; 16666656Ssemery T) options="$options -T" 16676656Ssemery type="$OPTARG" 16686656Ssemery if [[ $type == ms_ad ]]; then 16696656Ssemery msad=yes 16706656Ssemery adddns=yes 16716656Ssemery else 16726656Ssemery non_solaris=yes 16736656Ssemery no_keytab=yes 16746656Ssemery fi 16750Sstevel@tonic-gate ;; 16760Sstevel@tonic-gate a) options="$options -a" 16770Sstevel@tonic-gate ADMIN_PRINC="$OPTARG" 16780Sstevel@tonic-gate checkval="ADMIN_PRINC"; check_value $ADMIN_PRINC 16790Sstevel@tonic-gate ;; 16800Sstevel@tonic-gate c) options="$options -c" 16810Sstevel@tonic-gate filepath="$OPTARG" 16820Sstevel@tonic-gate ;; 16830Sstevel@tonic-gate d) options="$options -d" 16840Sstevel@tonic-gate dnsarg="$OPTARG" 16850Sstevel@tonic-gate checkval="DNS_OPTIONS"; check_value $dnsarg 16860Sstevel@tonic-gate ;; 16870Sstevel@tonic-gate f) options="$options -f" 16880Sstevel@tonic-gate fqdnlist="$OPTARG" 16890Sstevel@tonic-gate ;; 16906656Ssemery h) options="$options -h" 16916656Ssemery logical_hn="$OPTARG" 16926656Ssemery checkval="LOGICAL_HOSTNAME"; check_value $logical_hn 16936656Ssemery ;; 16946656Ssemery k) options="$options -k" 16956656Ssemery kdc_list="$OPTARG" 16966656Ssemery ;; 16976656Ssemery m) options="$options -m" 16986656Ssemery KDC="$OPTARG" 16996656Ssemery checkval="KDC"; check_value $KDC 17006656Ssemery ;; 17010Sstevel@tonic-gate n) options="$options -n" 17020Sstevel@tonic-gate add_nfs=yes 17030Sstevel@tonic-gate ;; 17046656Ssemery p) options="$options -p" 17056656Ssemery profile="$OPTARG" 17066656Ssemery read_profile $profile 17076656Ssemery ;; 17086656Ssemery s) options="$options -s" 17096656Ssemery svc_list="$OPTARG" 17106656Ssemery SVCs=${svc_list//,/ } 17116656Ssemery ;; 17120Sstevel@tonic-gate \?) usage 17136656Ssemery ;; 17140Sstevel@tonic-gate *) usage 17150Sstevel@tonic-gate ;; 17160Sstevel@tonic-gate esac 17170Sstevel@tonic-gatedone 17180Sstevel@tonic-gate 17190Sstevel@tonic-gate#correct argument count after options 17200Sstevel@tonic-gateshift `expr $OPTIND - 1` 17210Sstevel@tonic-gate 17226656Ssemeryif [[ -z $options ]]; then 17230Sstevel@tonic-gate : 17240Sstevel@tonic-gateelse 17256656Ssemery if [[ $# -ne 0 ]]; then 17260Sstevel@tonic-gate usage 17270Sstevel@tonic-gate fi 17280Sstevel@tonic-gatefi 17290Sstevel@tonic-gate 17306656Ssemery# 17316815Ssemery# Check to see if we will be a client of a MIT, Heimdal, Shishi, etc. 17326815Ssemery# 17336815Ssemeryif [[ -z $options ]]; then 17346815Ssemery query "$(gettext "Is this a client of a non-Solaris KDC") ?" 17356815Ssemery non_solaris=$answer 17366815Ssemery if [[ $non_solaris == yes ]]; then 17376815Ssemery printf "$(gettext "Which type of KDC is the server"):\n" 17386815Ssemery printf "\t$(gettext "ms_ad: Microsoft Active Directory")\n" 17396815Ssemery printf "\t$(gettext "mit: MIT KDC server")\n" 17406815Ssemery printf "\t$(gettext "heimdal: Heimdal KDC server")\n" 17416815Ssemery printf "\t$(gettext "shishi: Shishi KDC server")\n" 17426815Ssemery printf "$(gettext "Enter required KDC type"): " 17436815Ssemery read kdctype 17446815Ssemery if [[ $kdctype == ms_ad ]]; then 17456815Ssemery msad=yes 17466815Ssemery elif [[ $kdctype == mit || $kdctype == heimdal || \ 17476815Ssemery $kdctype == shishi ]]; then 17486815Ssemery no_keytab=yes 17496815Ssemery else 17506815Ssemery printf "\n$(gettext "Invalid KDC type option, valid types are ms_ad, mit, heimdal, or shishi, exiting").\n" >&2 17516815Ssemery error_message 17526815Ssemery fi 17536815Ssemery fi 17546815Ssemeryfi 17556815Ssemery 17566815Ssemery[[ $msad == yes ]] && join_domain 17576815Ssemery 17586815Ssemery# 17596656Ssemery# Check for /etc/resolv.conf 17606656Ssemery# 17616656Ssemeryif [[ -r $RESOLV_CONF_FILE ]]; then 17626656Ssemery client_machine=`$KLOOKUP` 17636656Ssemery 17646656Ssemery if [[ $? -ne 0 ]]; then 17656656Ssemery if [[ $adddns == no ]]; then 17666656Ssemery printf "\n$(gettext "%s does not have a DNS record and is required for Kerberos setup")\n" $hostname >&2 17676656Ssemery error_message 17686656Ssemery fi 17696656Ssemery 17706656Ssemery else 17716656Ssemery # 17726656Ssemery # If client entry already exists then do not recreate it 17736656Ssemery # 17746656Ssemery adddns=no 17756656Ssemery 17766656Ssemery hostname=${client_machine%%.*} 17776656Ssemery domain=${client_machine#*.} 17786656Ssemery fi 17796656Ssemery 17806656Ssemery short_fqdn=${domain#*.*} 17816656Ssemery short_fqdn=$(echo $short_fqdn | grep "\.") 17826656Ssemeryelse 17836656Ssemery # 17846656Ssemery # /etc/resolv.conf not present, exit ... 17856656Ssemery # 17866656Ssemery printf "\n$(gettext "%s does not exist and is required for Kerberos setup")\n" $RESOLV_CONF_FILE >&2 17876656Ssemery printf "$(gettext "Refer to resolv.conf(4), exiting").\n" >&2 17886656Ssemery error_message 17896656Ssemeryfi 17906656Ssemery 17916815Ssemerycheck_nss_conf || printf "$(gettext "/etc/nsswitch.conf does not make use of DNS for hosts and/or ipnodes").\n" 17926656Ssemery 17936656Ssemery[[ -n $fqdnlist ]] && verify_fqdnlist "$fqdnlist" 17946656Ssemery 17956815Ssemeryif [[ -z $dnsarg && (-z $options || -z $filepath) ]]; then 17960Sstevel@tonic-gate query "$(gettext "Do you want to use DNS for kerberos lookups") ?" 17976656Ssemery if [[ $answer == yes ]]; then 17986656Ssemery 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" 17996656Ssemery printf "\n$(gettext "Enter required DNS option"): " 18000Sstevel@tonic-gate read dnsarg 18010Sstevel@tonic-gate checkval="DNS_OPTIONS"; check_value $dnsarg 18020Sstevel@tonic-gate set_dns_value $dnsarg 18030Sstevel@tonic-gate fi 18040Sstevel@tonic-gateelse 18056815Ssemery [[ -z $dnsarg ]] && dnsarg=none 18060Sstevel@tonic-gate set_dns_value $dnsarg 18070Sstevel@tonic-gatefi 18080Sstevel@tonic-gate 18096656Ssemeryif [[ -n $kdc_list ]]; then 18106656Ssemery if [[ -z $KDC ]]; then 18116656Ssemery for kdc in $kdc_list; do 18126656Ssemery break 18136656Ssemery done 18146656Ssemery KDC="$kdc" 18156656Ssemery fi 18160Sstevel@tonic-gatefi 18176656Ssemery 18186815Ssemeryif [[ -z $realm ]]; then 18196656Ssemery printf "$(gettext "Enter the Kerberos realm"): " 18206656Ssemery read realm 18216656Ssemery checkval="REALM"; check_value $realm 18226656Ssemeryfi 18236815Ssemeryif [[ -z $KDC ]]; then 18246656Ssemery printf "$(gettext "Specify the master KDC hostname for the above realm"): " 18250Sstevel@tonic-gate read KDC 18260Sstevel@tonic-gate checkval="KDC"; check_value $KDC 18270Sstevel@tonic-gatefi 18280Sstevel@tonic-gate 18296656SsemeryFKDC=`$KLOOKUP $KDC` 18300Sstevel@tonic-gate 18310Sstevel@tonic-gate# 18320Sstevel@tonic-gate# Ping to see if the kdc is alive ! 18330Sstevel@tonic-gate# 18346656Ssemeryping_check $FKDC "KDC" 18356656Ssemery 18366815Ssemeryif [[ -z $kdc_list && (-z $options || -z $filepath) ]]; then 18376815Ssemery query "$(gettext "Do you have any slave KDC(s)") ?" 18386815Ssemery if [[ $answer == yes ]]; then 18396815Ssemery printf "$(gettext "Enter a comma-separated list of slave KDC host names"): " 18406815Ssemery read kdc_list 18416815Ssemery fi 18426815Ssemeryfi 18436815Ssemery 18446815Ssemery[[ -n $kdc_list ]] && verify_kdcs "$kdc_list" 18456815Ssemery 18466656Ssemery# 18476656Ssemery# Check to see if we will have a dynamic presence in the realm 18486656Ssemery# 18496656Ssemeryif [[ -z $options ]]; then 18506656Ssemery query "$(gettext "Will this client need service keys") ?" 18516656Ssemery if [[ $answer == no ]]; then 18526656Ssemery no_keytab=yes 18536656Ssemery fi 18546656Ssemeryfi 18550Sstevel@tonic-gate 18566656Ssemery# 18576656Ssemery# Check to see if we are configuring the client to use a logical host name 18586656Ssemery# of a cluster environment 18596656Ssemery# 18606656Ssemeryif [[ -z $options ]]; then 18616656Ssemery query "$(gettext "Is this client a member of a cluster that uses a logical host name") ?" 18626656Ssemery if [[ $answer == yes ]]; then 18636656Ssemery printf "$(gettext "Specify the logical hostname of the cluster"): " 18646656Ssemery read logical_hn 18656656Ssemery checkval="LOGICAL_HOSTNAME"; check_value $logical_hn 18666656Ssemery setup_lhn 18676656Ssemery fi 18686656Ssemeryfi 18696656Ssemery 18706815Ssemeryif [[ -n $domain_list && (-z $options || -z $filepath) ]]; then 18716656Ssemery query "$(gettext "Do you have multiple domains/hosts to map to realm %s" 18726656Ssemery) ?" $realm 18736656Ssemery if [[ $answer == yes ]]; then 18746815Ssemery printf "$(gettext "Enter a comma-separated list of domain/hosts 18756656Ssemeryto map to the default realm"): " 18766656Ssemery read domain_list 18776656Ssemery fi 18786656Ssemeryfi 18796656Ssemery[[ -n domain_list ]] && domain_list=${domain_list//,/ } 18800Sstevel@tonic-gate 18810Sstevel@tonic-gate# 18820Sstevel@tonic-gate# Start writing up the krb5.conf file, save the existing one 18830Sstevel@tonic-gate# if already present 18840Sstevel@tonic-gate# 18850Sstevel@tonic-gatewriteup_krb5_conf 18860Sstevel@tonic-gate 18876656Ssemery# 18886656Ssemery# Is this client going to use krb-nfs? If so then we need to at least 18896656Ssemery# uncomment the krb5* sec flavors in nfssec.conf. 18906656Ssemery# 18916656Ssemeryif [[ -z $options ]]; then 18926656Ssemery query "$(gettext "Do you plan on doing Kerberized nfs") ?" 18936656Ssemery add_nfs=$answer 18946656Ssemeryfi 18956656Ssemery 18966656Ssemeryif [[ $add_nfs == yes ]]; then 18976656Ssemery modify_nfssec_conf 18986656Ssemery 18996656Ssemery # 19006656Ssemery # We also want to enable gss as we now live in a SBD world 19016656Ssemery # 19026656Ssemery svcadm enable svc:/network/rpc/gss:default 19036656Ssemery [[ $? -ne 0 ]] && printf "$(gettext "Warning: could not enable gss service").\n" 19046656Ssemeryfi 19056656Ssemery 19066656Ssemeryif [[ -z $options ]]; then 19076656Ssemery query "$(gettext "Do you want to update /etc/pam.conf") ?" 19086656Ssemery if [[ $answer == yes ]]; then 19096656Ssemery printf "$(gettext "Enter a list of PAM service names in the following format: service:{first|only|optional}[,..]"): " 19106656Ssemery read svc_list 19116656Ssemery SVCs=${svc_list//,/ } 19126656Ssemery fi 19136656Ssemeryfi 19146656Ssemery[[ -n $svc_list ]] && update_pam_conf 19150Sstevel@tonic-gate 19160Sstevel@tonic-gate# 19176656Ssemery# Copy over krb5.conf master copy from filepath 19180Sstevel@tonic-gate# 19196656Ssemeryif [[ -z $options || -z $filepath ]]; then 19206656Ssemery query "$(gettext "Do you want to copy over the master krb5.conf file") ?" 19216656Ssemery if [[ $answer == yes ]]; then 19226656Ssemery printf "$(gettext "Enter the pathname of the file to be copied"): " 19236656Ssemery read filepath 19240Sstevel@tonic-gate fi 19250Sstevel@tonic-gatefi 19260Sstevel@tonic-gate 19276815Ssemeryif [[ -n $filepath && -r $filepath ]]; then 19286815Ssemery cp $filepath $KRB5_CONFIG 19296815Ssemery if [[ $? -eq 0 ]]; then 19306815Ssemery printf "$(gettext "Copied %s to %s").\n" $filepath $KRB5_CONFIG 19310Sstevel@tonic-gate else 19326815Ssemery printf "$(gettext "Copy of %s failed, exiting").\n" $filepath >&2 19336656Ssemery error_message 19340Sstevel@tonic-gate fi 19356815Ssemeryelif [[ -n $filepath ]]; then 19366815Ssemery printf "\n$(gettext "%s not found, exiting").\n" $filepath >&2 19376815Ssemery error_message 19380Sstevel@tonic-gatefi 19390Sstevel@tonic-gate 19406815SsemerydoKRB5config 19416815Ssemery 19420Sstevel@tonic-gate# 19436656Ssemery# Populate any service keys needed for the client in the keytab file 19440Sstevel@tonic-gate# 19456815Ssemeryif [[ $no_keytab != yes ]]; then 19466815Ssemery setup_keytab 19476815Ssemeryelse 19486815Ssemery 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 19496815Ssemery printf "$(gettext "Client will also not be able to host services that use Kerberos").\n" 19506815Ssemeryfi 19510Sstevel@tonic-gate 19526656Ssemeryprintf -- "\n---------------------------------------------------\n" 19536656Ssemeryprintf "$(gettext "Setup COMPLETE").\n\n" 19540Sstevel@tonic-gate 19550Sstevel@tonic-gate# 19566656Ssemery# If we have configured the client in a cluster we need to remind the user 19576656Ssemery# to propagate the keytab and configuration files to the other members. 19580Sstevel@tonic-gate# 19596656Ssemeryif [[ -n $logical_hn ]]; then 19606656Ssemery 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" 19610Sstevel@tonic-gatefi 19620Sstevel@tonic-gate 19636656Ssemery# 19646656Ssemery# Cleanup. 19650Sstevel@tonic-gate# 19666656Ssemerykdestroy -q 1>$TMP_FILE 2>&1 19670Sstevel@tonic-gaterm -f $TMP_FILE 19686656Ssemeryrm -rf $TMPDIR > /dev/null 2>&1 19690Sstevel@tonic-gateexit 0 1970