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