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. 23*f7dbdfc7SMarcel Telka# Copyright 2014 Nexenta Systems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate# 257c478bd9Sstevel@tonic-gate# This script is used to setup the Kerberos client by 267c478bd9Sstevel@tonic-gate# supplying information about the Kerberos realm and kdc. 277c478bd9Sstevel@tonic-gate# 287c478bd9Sstevel@tonic-gate# The kerberos configuration file (/etc/krb5/krb5.conf) would 297c478bd9Sstevel@tonic-gate# be generated and local host's keytab file setup. The script 307c478bd9Sstevel@tonic-gate# can also optionally setup the system to do kerberized nfs and 317c478bd9Sstevel@tonic-gate# bringover a master krb5.conf copy from a specified location. 3272f0806aSShawn Emery# 337c478bd9Sstevel@tonic-gate 34bd211b85Ssemeryfunction cleanup { 35bd211b85Ssemery 36c386eb9cSShawn Emery kdestroy -q > $TMP_FILE 2>&1 37bd211b85Ssemery rm -r $TMPDIR > /dev/null 2>&1 38bd211b85Ssemery 39c386eb9cSShawn Emery exit $1 40bd211b85Ssemery} 41bd211b85Ssemeryfunction exiting { 42bd211b85Ssemery 43bd211b85Ssemery printf "\n$(gettext "Exiting setup, nothing changed").\n\n" 44bd211b85Ssemery 45bd211b85Ssemery cleanup $1 467c478bd9Sstevel@tonic-gate} 477c478bd9Sstevel@tonic-gate 48bd211b85Ssemeryfunction error_message { 49bd211b85Ssemery 50c386eb9cSShawn Emery printf -- "---------------------------------------------------\n" >&2 51c386eb9cSShawn Emery printf "$(gettext "Setup FAILED").\n\n" >&2 52bd211b85Ssemery 53bd211b85Ssemery cleanup 1 54bd211b85Ssemery} 55bd211b85Ssemery 56bd211b85Ssemeryfunction check_bin { 57bd211b85Ssemery 58bd211b85Ssemery typeset bin=$1 59bd211b85Ssemery 60bd211b85Ssemery if [[ ! -x $bin ]]; then 61c386eb9cSShawn Emery printf "$(gettext "Could not access/execute %s").\n" $bin >&2 627c478bd9Sstevel@tonic-gate error_message 637c478bd9Sstevel@tonic-gate fi 647c478bd9Sstevel@tonic-gate} 657c478bd9Sstevel@tonic-gate 66bd211b85Ssemeryfunction cannot_create { 67bd211b85Ssemery typeset filename="$1" 68bd211b85Ssemery typeset stat="$2" 69bd211b85Ssemery 70bd211b85Ssemery if [[ $stat -ne 0 ]]; then 71bd211b85Ssemery printf "\n$(gettext "Can not create/edit %s, exiting").\n" $filename >&2 72bd211b85Ssemery error_message 73bd211b85Ssemery fi 74bd211b85Ssemery} 75bd211b85Ssemery 76bd211b85Ssemeryfunction update_pam_conf { 77bd211b85Ssemery typeset PAM TPAM service 78bd211b85Ssemery 79bd211b85Ssemery PAM=/etc/pam.conf 80bd211b85Ssemery 81bd211b85Ssemery TPAM=$(mktemp -q -t kclient-pamconf.XXXXXX) 82bd211b85Ssemery if [[ -z $TPAM ]]; then 83bd211b85Ssemery printf "\n$(gettext "Can not create temporary file, exiting").\n" >&2 84bd211b85Ssemery error_message 85bd211b85Ssemery fi 86bd211b85Ssemery 87bd211b85Ssemery cp $PAM $TPAM >/dev/null 2>&1 88bd211b85Ssemery 89bd211b85Ssemery printf "$(gettext "Configuring %s").\n\n" $PAM 90bd211b85Ssemery 91bd211b85Ssemery for service in $SVCs; do 92bd211b85Ssemery svc=${service%:*} 93bd211b85Ssemery auth_type=${service#*:} 94bd211b85Ssemery if egrep -s "^$svc[ ][ ]*auth.*pam_krb5*" $TPAM; then 95ae5b046dSsemery printf "$(gettext "The %s service is already configured for pam_krb5, please merge this service in %s").\n\n" $svc $PAM >&2 96bd211b85Ssemery continue 97bd211b85Ssemery else 98bd211b85Ssemery exec 3>>$TPAM 99ae5b046dSsemery printf "\n$svc\tauth include\t\tpam_krb5_$auth_type\n" 1>&3 100bd211b85Ssemery fi 101bd211b85Ssemery done 102bd211b85Ssemery 103bd211b85Ssemery cp $TPAM $PAM > /dev/null 2>&1 104bd211b85Ssemery 105bd211b85Ssemery rm $TPAM > /dev/null 2>&1 106bd211b85Ssemery} 107bd211b85Ssemery 108bd211b85Ssemeryfunction modify_nfssec_conf { 109bd211b85Ssemery typeset NFSSEC_FILE="/etc/nfssec.conf" 110bd211b85Ssemery 111bd211b85Ssemery if [[ -r $NFSSEC_FILE ]]; then 1127c478bd9Sstevel@tonic-gate cat $NFSSEC_FILE > $NFSSEC_FILE.sav 1137c478bd9Sstevel@tonic-gate cannot_create $NFSSEC_FILE.sav $? 1147c478bd9Sstevel@tonic-gate fi 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate cat $NFSSEC_FILE > $TMP_FILE 1177c478bd9Sstevel@tonic-gate cannot_create $TMP_FILE $? 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate if grep -s "#krb5" $NFSSEC_FILE > /dev/null 2>&1; then 1207c478bd9Sstevel@tonic-gate sed "s%^#krb5%krb5%" $TMP_FILE >$NFSSEC_FILE 1217c478bd9Sstevel@tonic-gate cannot_create $NFSSEC_FILE $? 1227c478bd9Sstevel@tonic-gate fi 1237c478bd9Sstevel@tonic-gate} 1247c478bd9Sstevel@tonic-gate 125bd211b85Ssemeryfunction call_kadmin { 1267c478bd9Sstevel@tonic-gate typeset svc="$1" 1277c478bd9Sstevel@tonic-gate typeset bool1 bool2 bool3 bool4 128bd211b85Ssemery typeset service_princ getprincsubcommand anksubcommand ktaddsubcommand 129bd211b85Ssemery typeset ktremsubcommand 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate for listentry in $fqdnlist; do 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate # Reset conditional vars to 1 1347c478bd9Sstevel@tonic-gate bool1=1; bool2=1; bool3=1; bool4=1 1357c478bd9Sstevel@tonic-gate 136bd211b85Ssemery service_princ=$(echo "${svc}/${listentry}") 1377c478bd9Sstevel@tonic-gate getprincsubcommand="getprinc $service_princ" 1387c478bd9Sstevel@tonic-gate anksubcommand="addprinc -randkey $service_princ" 1397c478bd9Sstevel@tonic-gate ktaddsubcommand="ktadd $service_princ" 140bd211b85Ssemery ktremsubcommand="ktrem $service_princ all" 1417c478bd9Sstevel@tonic-gate 142bd211b85Ssemery kadmin -c $KRB5CCNAME -q "$getprincsubcommand" 1>$TMP_FILE 2>&1 1437c478bd9Sstevel@tonic-gate 144ae5b046dSsemery egrep -s "$(gettext "get_principal: Principal does not exist")" $TMP_FILE 1457c478bd9Sstevel@tonic-gate bool1=$? 146ae5b046dSsemery egrep -s "$(gettext "get_principal: Operation requires ``get")" $TMP_FILE 1477c478bd9Sstevel@tonic-gate bool2=$? 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate if [[ $bool1 -eq 0 || $bool2 -eq 0 ]]; then 150bd211b85Ssemery kadmin -c $KRB5CCNAME -q "$anksubcommand" 1>$TMP_FILE 2>&1 1517c478bd9Sstevel@tonic-gate 152ae5b046dSsemery egrep -s "$(gettext "add_principal: Principal or policy already exists while creating \"$service_princ@$realm\".")" $TMP_FILE 1537c478bd9Sstevel@tonic-gate bool3=$? 1547c478bd9Sstevel@tonic-gate 155ae5b046dSsemery egrep -s "$(gettext "Principal \"$service_princ@$realm\" created.")" $TMP_FILE 1567c478bd9Sstevel@tonic-gate bool4=$? 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate if [[ $bool3 -eq 0 || $bool4 -eq 0 ]]; then 1597c478bd9Sstevel@tonic-gate printf "$(gettext "%s entry ADDED to KDC database").\n" $service_princ 1607c478bd9Sstevel@tonic-gate else 1617c478bd9Sstevel@tonic-gate cat $TMP_FILE; 162bd211b85Ssemery printf "\n$(gettext "kadmin: add_principal of %s failed, exiting").\n" $service_princ >&2 1637c478bd9Sstevel@tonic-gate error_message 1647c478bd9Sstevel@tonic-gate fi 1657c478bd9Sstevel@tonic-gate else 166bd211b85Ssemery printf "$(gettext "%s entry already exists in KDC database").\n" $service_princ >&2 1677c478bd9Sstevel@tonic-gate fi 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate klist -k 1>$TMP_FILE 2>&1 170bd211b85Ssemery egrep -s "$service_princ@$realm" $TMP_FILE 171bd211b85Ssemery if [[ $? -eq 0 ]]; then 172bd211b85Ssemery printf "$(gettext "%s entry already present in keytab").\n" $service_princ >&2 173bd211b85Ssemery # Don't care is this succeeds or not, just need to replace old 174bd211b85Ssemery # entries as it is assummed that the client is reinitialized 175bd211b85Ssemery kadmin -c $KRB5CCNAME -q "$ktremsubcommand" 1>$TMP_FILE 2>&1 176bd211b85Ssemery fi 177bd211b85Ssemery 178bd211b85Ssemery kadmin -c $KRB5CCNAME -q "$ktaddsubcommand" 1>$TMP_FILE 2>&1 179ae5b046dSsemery egrep -s "$(gettext "added to keytab WRFILE:$KRB5_KEYTAB_FILE.")" $TMP_FILE 180bd211b85Ssemery if [[ $? -ne 0 ]]; then 1817c478bd9Sstevel@tonic-gate cat $TMP_FILE; 182bd211b85Ssemery printf "\n$(gettext "kadmin: ktadd of %s failed, exiting").\n" $service_princ >&2 1837c478bd9Sstevel@tonic-gate error_message 1847c478bd9Sstevel@tonic-gate else 1857c478bd9Sstevel@tonic-gate printf "$(gettext "%s entry ADDED to keytab").\n" $service_princ 1867c478bd9Sstevel@tonic-gate fi 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate done 1897c478bd9Sstevel@tonic-gate} 1907c478bd9Sstevel@tonic-gate 191bd211b85Ssemeryfunction writeup_krb5_conf { 192bd211b85Ssemery typeset dh 1937c478bd9Sstevel@tonic-gate 194bd211b85Ssemery printf "\n$(gettext "Setting up %s").\n\n" $KRB5_CONFIG_FILE 1957c478bd9Sstevel@tonic-gate 196bd211b85Ssemery exec 3>$KRB5_CONFIG 197bd211b85Ssemery if [[ $? -ne 0 ]]; then 198c386eb9cSShawn Emery printf "\n$(gettext "Can not write to %s, exiting").\n" $KRB5_CONFIG >&2 1997c478bd9Sstevel@tonic-gate error_message 2007c478bd9Sstevel@tonic-gate fi 2017c478bd9Sstevel@tonic-gate 202bd211b85Ssemery printf "[libdefaults]\n" 1>&3 203bd211b85Ssemery if [[ $no_keytab == yes ]]; then 204bd211b85Ssemery printf "\tverify_ap_req_nofail = false\n" 1>&3 205bd211b85Ssemery fi 206bd211b85Ssemery if [[ $dns_lookup == yes ]]; then 207bd211b85Ssemery printf "\t$dnsarg = on\n" 1>&3 208bd211b85Ssemery if [[ $dnsarg == dns_lookup_kdc ]]; then 209bd211b85Ssemery printf "\tdefault_realm = $realm\n" 1>&3 210bd211b85Ssemery printf "\n[domain_realm]\n" 1>&3 211bd211b85Ssemery if [[ -n $fkdc_list ]]; then 212bd211b85Ssemery for kdc in $fkdc_list; do 213bd211b85Ssemery printf "\t$kdc = $realm\n" 1>&3 214bd211b85Ssemery done 215bd211b85Ssemery fi 216bd211b85Ssemery printf "\t$FKDC = $realm\n" 1>&3 217bd211b85Ssemery printf "\t$client_machine = $realm\n" 1>&3 218bd211b85Ssemery if [[ -z $short_fqdn ]]; then 219bd211b85Ssemery printf "\t.$domain = $realm\n\n" 1>&3 2207c478bd9Sstevel@tonic-gate else 221bd211b85Ssemery printf "\t.$short_fqdn = $realm\n\n" 1>&3 222bd211b85Ssemery fi 223bd211b85Ssemery if [[ -n $domain_list ]]; then 224bd211b85Ssemery for dh in $domain_list; do 225bd211b85Ssemery printf "\t$dh = $realm\n" 1>&3 226bd211b85Ssemery done 227bd211b85Ssemery fi 228bd211b85Ssemery else 229bd211b85Ssemery if [[ $dnsarg = dns_lookup_realm ]]; then 230ae5b046dSsemery printf "\tdefault_realm = $realm\n" 1>&3 231bd211b85Ssemery printf "\n[realms]\n" 1>&3 232bd211b85Ssemery printf "\t$realm = {\n" 1>&3 233bd211b85Ssemery if [[ -n $kdc_list ]]; then 234bd211b85Ssemery for kdc in $kdc_list; do 235bd211b85Ssemery printf "\t\tkdc = $kdc\n" 1>&3 236bd211b85Ssemery done 2377c478bd9Sstevel@tonic-gate else 238bd211b85Ssemery printf "\t\tkdc = $KDC\n" 1>&3 239bd211b85Ssemery fi 240bd211b85Ssemery printf "\t\tadmin_server = $KDC\n" 1>&3 241bd211b85Ssemery if [[ $non_solaris == yes ]]; then 242bd211b85Ssemery printf "\n\t\tkpasswd_protocol = SET_CHANGE\n" 1>&3 243bd211b85Ssemery fi 244bd211b85Ssemery printf "\t}\n\n" 1>&3 245bd211b85Ssemery else 246ae5b046dSsemery printf "\tdefault_realm = $realm\n\n" 1>&3 2477c478bd9Sstevel@tonic-gate fi 2487c478bd9Sstevel@tonic-gate fi 2497c478bd9Sstevel@tonic-gate else 250bd211b85Ssemery printf "\tdefault_realm = $realm\n\n" 1>&3 2517c478bd9Sstevel@tonic-gate 252bd211b85Ssemery printf "[realms]\n" 1>&3 253bd211b85Ssemery printf "\t$realm = {\n" 1>&3 254bd211b85Ssemery if [[ -n $kdc_list ]]; then 255bd211b85Ssemery for kdc in $kdc_list; do 256bd211b85Ssemery printf "\t\tkdc = $kdc\n" 1>&3 257bd211b85Ssemery done 258bd211b85Ssemery else 259bd211b85Ssemery printf "\t\tkdc = $KDC\n" 1>&3 260bd211b85Ssemery fi 261bd211b85Ssemery printf "\t\tadmin_server = $KDC\n" 1>&3 262bd211b85Ssemery if [[ $non_solaris == yes ]]; then 263bd211b85Ssemery printf "\n\t\tkpasswd_protocol = SET_CHANGE\n" 1>&3 264bd211b85Ssemery fi 265bd211b85Ssemery printf "\t}\n\n" 1>&3 2667c478bd9Sstevel@tonic-gate 267bd211b85Ssemery printf "[domain_realm]\n" 1>&3 268bd211b85Ssemery if [[ -n $fkdc_list ]]; then 269bd211b85Ssemery for kdc in $fkdc_list; do 270bd211b85Ssemery printf "\t$kdc = $realm\n" 1>&3 271bd211b85Ssemery done 272bd211b85Ssemery fi 273bd211b85Ssemery printf "\t$FKDC = $realm\n" 1>&3 274bd211b85Ssemery printf "\t$client_machine = $realm\n" 1>&3 275bd211b85Ssemery if [[ -z $short_fqdn ]]; then 276bd211b85Ssemery printf "\t.$domain = $realm\n\n" 1>&3 277bd211b85Ssemery else 278bd211b85Ssemery printf "\t.$short_fqdn = $realm\n\n" 1>&3 279bd211b85Ssemery fi 280bd211b85Ssemery if [[ -n $domain_list ]]; then 281bd211b85Ssemery for dh in $domain_list; do 282bd211b85Ssemery printf "\t$dh = $realm\n" 1>&3 283bd211b85Ssemery done 284bd211b85Ssemery fi 2857c478bd9Sstevel@tonic-gate fi 2867c478bd9Sstevel@tonic-gate 287bd211b85Ssemery printf "[logging]\n" 1>&3 288bd211b85Ssemery printf "\tdefault = FILE:/var/krb5/kdc.log\n" 1>&3 289bd211b85Ssemery printf "\tkdc = FILE:/var/krb5/kdc.log\n" 1>&3 290bd211b85Ssemery printf "\tkdc_rotate = {\n\t\tperiod = 1d\n\t\tversions = 10\n\t}\n\n" 1>&3 2917c478bd9Sstevel@tonic-gate 292bd211b85Ssemery printf "[appdefaults]\n" 1>&3 293bd211b85Ssemery printf "\tkinit = {\n\t\trenewable = true\n\t\tforwardable = true\n" 1>&3 294bd211b85Ssemery if [[ $no_keytab == yes ]]; then 295bd211b85Ssemery printf "\t\tno_addresses = true\n" 1>&3 296bd211b85Ssemery fi 297bd211b85Ssemery printf "\t}\n" 1>&3 2987c478bd9Sstevel@tonic-gate} 2997c478bd9Sstevel@tonic-gate 300bd211b85Ssemeryfunction ask { 301bd211b85Ssemery typeset question=$1 302bd211b85Ssemery typeset default_answer=$2 303bd211b85Ssemery 304bd211b85Ssemery if [[ -z $default_answer ]]; then 305bd211b85Ssemery printf "$question :" 3067c478bd9Sstevel@tonic-gate else 307bd211b85Ssemery printf "$question [$default_answer]: " 3087c478bd9Sstevel@tonic-gate fi 3097c478bd9Sstevel@tonic-gate read answer 3107c478bd9Sstevel@tonic-gate test -z "$answer" && answer="$default_answer" 3117c478bd9Sstevel@tonic-gate} 3127c478bd9Sstevel@tonic-gate 313bd211b85Ssemeryfunction yesno { 3147c478bd9Sstevel@tonic-gate typeset question="$1" 315bd211b85Ssemery 316bd211b85Ssemery answer= 317bd211b85Ssemery yn=`printf "$(gettext "y/n")"` 318bd211b85Ssemery y=`printf "$(gettext "y")"` 319bd211b85Ssemery n=`printf "$(gettext "n")"` 320bd211b85Ssemery yes=`printf "$(gettext "yes")"` 321bd211b85Ssemery no=`printf "$(gettext "no")"` 322bd211b85Ssemery 323bd211b85Ssemery while [[ -z $answer ]]; do 324bd211b85Ssemery ask "$question" $yn 325bd211b85Ssemery case $answer in 326bd211b85Ssemery $y|$yes) answer=yes;; 327bd211b85Ssemery $n|$no) answer=no;; 328bd211b85Ssemery *) answer=;; 3297c478bd9Sstevel@tonic-gate esac 3307c478bd9Sstevel@tonic-gate done 3317c478bd9Sstevel@tonic-gate} 3327c478bd9Sstevel@tonic-gate 333bd211b85Ssemeryfunction query { 3347c478bd9Sstevel@tonic-gate yesno "$*" 335bd211b85Ssemery 336bd211b85Ssemery if [[ $answer == no ]]; then 3377c478bd9Sstevel@tonic-gate printf "\t$(gettext "No action performed").\n" 3387c478bd9Sstevel@tonic-gate fi 3397c478bd9Sstevel@tonic-gate} 3407c478bd9Sstevel@tonic-gate 3417c478bd9Sstevel@tonic-gate 342bd211b85Ssemeryfunction read_profile { 3437c478bd9Sstevel@tonic-gate typeset param value 3447c478bd9Sstevel@tonic-gate typeset file="$1" 345bd211b85Ssemery 3467c478bd9Sstevel@tonic-gate if [[ ! -d $file && -r $file ]]; then 3477c478bd9Sstevel@tonic-gate while read param value 3487c478bd9Sstevel@tonic-gate do 349bd211b85Ssemery case $param in 350bd211b85Ssemery REALM) if [[ -z $realm ]]; then 351bd211b85Ssemery realm="$value" 352bd211b85Ssemery checkval="REALM"; check_value $realm 3537c478bd9Sstevel@tonic-gate fi 3547c478bd9Sstevel@tonic-gate ;; 355bd211b85Ssemery KDC) if [[ -z $KDC ]]; then 3567c478bd9Sstevel@tonic-gate KDC="$value" 3577c478bd9Sstevel@tonic-gate checkval="KDC"; check_value $KDC 3587c478bd9Sstevel@tonic-gate fi 3597c478bd9Sstevel@tonic-gate ;; 360bd211b85Ssemery ADMIN) if [[ -z $ADMIN_PRINC ]]; then 3617c478bd9Sstevel@tonic-gate ADMIN_PRINC="$value" 3627c478bd9Sstevel@tonic-gate checkval="ADMIN_PRINC" 3637c478bd9Sstevel@tonic-gate check_value $ADMIN_PRINC 3647c478bd9Sstevel@tonic-gate fi 3657c478bd9Sstevel@tonic-gate ;; 366bd211b85Ssemery FILEPATH) if [[ -z $filepath ]]; then 3677c478bd9Sstevel@tonic-gate filepath="$value" 3687c478bd9Sstevel@tonic-gate fi 3697c478bd9Sstevel@tonic-gate ;; 370bd211b85Ssemery NFS) if [[ -z $add_nfs ]]; then 371bd211b85Ssemery if [[ $value == 1 ]]; then 3727c478bd9Sstevel@tonic-gate add_nfs=yes 3737c478bd9Sstevel@tonic-gate else 3747c478bd9Sstevel@tonic-gate add_nfs=no 3757c478bd9Sstevel@tonic-gate fi 3767c478bd9Sstevel@tonic-gate fi 3777c478bd9Sstevel@tonic-gate ;; 378bd211b85Ssemery NOKEY) if [[ -z $no_keytab ]]; then 379bd211b85Ssemery if [[ $value == 1 ]]; then 380bd211b85Ssemery no_keytab=yes 381bd211b85Ssemery else 382bd211b85Ssemery no_keytab=no 383bd211b85Ssemery fi 384bd211b85Ssemery fi 385bd211b85Ssemery ;; 386bd211b85Ssemery NOSOL) if [[ -z $non_solaris ]]; then 387bd211b85Ssemery if [[ $value == 1 ]]; then 388bd211b85Ssemery non_solaris=yes 389bd211b85Ssemery no_keytab=yes 390bd211b85Ssemery else 391bd211b85Ssemery non_solaris=no 392bd211b85Ssemery fi 393bd211b85Ssemery fi 394bd211b85Ssemery ;; 395bd211b85Ssemery LHN) if [[ -z $logical_hn ]]; then 396bd211b85Ssemery logical_hn="$value" 397bd211b85Ssemery checkval="LOGICAL_HOSTNAME" 398bd211b85Ssemery check_value $logical_hn 399bd211b85Ssemery fi 400bd211b85Ssemery ;; 401bd211b85Ssemery DNSLOOKUP) if [[ -z $dnsarg ]]; then 4027c478bd9Sstevel@tonic-gate dnsarg="$value" 4037c478bd9Sstevel@tonic-gate checkval="DNS_OPTIONS" 4047c478bd9Sstevel@tonic-gate check_value $dnsarg 4057c478bd9Sstevel@tonic-gate fi 4067c478bd9Sstevel@tonic-gate ;; 407bd211b85Ssemery FQDN) if [[ -z $fqdnlist ]]; then 4087c478bd9Sstevel@tonic-gate fqdnlist="$value" 4097c478bd9Sstevel@tonic-gate checkval="FQDN" 4107c478bd9Sstevel@tonic-gate check_value $fqdnlist 4117c478bd9Sstevel@tonic-gate verify_fqdnlist "$fqdnlist" 4127c478bd9Sstevel@tonic-gate fi 4137c478bd9Sstevel@tonic-gate ;; 414bd211b85Ssemery MSAD) if [[ -z $msad ]]; then 415bd211b85Ssemery if [[ $value == 1 ]]; then 416bd211b85Ssemery msad=yes 417bd211b85Ssemery non_solaris=yes 418bd211b85Ssemery else 419bd211b85Ssemery msad=no 420bd211b85Ssemery fi 421bd211b85Ssemery fi 422bd211b85Ssemery ;; 4237c478bd9Sstevel@tonic-gate esac 4247c478bd9Sstevel@tonic-gate done <$file 4257c478bd9Sstevel@tonic-gate else 426bd211b85Ssemery printf "\n$(gettext "The kclient profile \`%s' is not valid, exiting").\n" $file >&2 4277c478bd9Sstevel@tonic-gate error_message 4287c478bd9Sstevel@tonic-gate fi 4297c478bd9Sstevel@tonic-gate} 4307c478bd9Sstevel@tonic-gate 431bd211b85Ssemeryfunction ping_check { 4327c478bd9Sstevel@tonic-gate typeset machine="$1" 4337c478bd9Sstevel@tonic-gate typeset string="$2" 434bd211b85Ssemery 435bd211b85Ssemery if ping $machine 2 > /dev/null 2>&1; then 4367c478bd9Sstevel@tonic-gate : 4377c478bd9Sstevel@tonic-gate else 438bd211b85Ssemery printf "\n$(gettext "%s %s is unreachable, exiting").\n" $string $machine >&2 4397c478bd9Sstevel@tonic-gate error_message 4407c478bd9Sstevel@tonic-gate fi 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate # Output timesync warning if not using a profile, i.e. in 4437c478bd9Sstevel@tonic-gate # interactive mode. 444bd211b85Ssemery if [[ -z $profile && $string == KDC ]]; then 4457c478bd9Sstevel@tonic-gate # It's difficult to sync up time with KDC esp. if in a 4467c478bd9Sstevel@tonic-gate # zone so just print a warning about KDC time sync. 447ae5b046dSsemery 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 448ae5b046dSsemery printf "$(gettext "Both systems should run some form of time synchronization system like Network Time Protocol (NTP)").\n" >&2 449bd211b85Ssemerybreak 4507c478bd9Sstevel@tonic-gate fi 4517c478bd9Sstevel@tonic-gate} 4527c478bd9Sstevel@tonic-gate 453bd211b85Ssemeryfunction check_value { 4547c478bd9Sstevel@tonic-gate typeset arg="$1" 455bd211b85Ssemery 456bd211b85Ssemery if [[ -z $arg ]]; then 457bd211b85Ssemery printf "\n$(gettext "No input obtained for %s, exiting").\n" $checkval >&2 4587c478bd9Sstevel@tonic-gate error_message 4597c478bd9Sstevel@tonic-gate else 4607c478bd9Sstevel@tonic-gate echo "$arg" > $TMP_FILE 4617c478bd9Sstevel@tonic-gate if egrep -s '[*$^#!]+' $TMP_FILE; then 462bd211b85Ssemery printf "\n$(gettext "Invalid input obtained for %s, exiting").\n" $checkval >&2 4637c478bd9Sstevel@tonic-gate error_message 4647c478bd9Sstevel@tonic-gate fi 4657c478bd9Sstevel@tonic-gate fi 4667c478bd9Sstevel@tonic-gate} 4677c478bd9Sstevel@tonic-gate 468bd211b85Ssemeryfunction set_dns_value { 469bd211b85Ssemery typeset -l arg="$1" 470bd211b85Ssemery 471bd211b85Ssemery if [[ $arg == dns_lookup_kdc || $arg == dns_lookup_realm || $arg == dns_fallback ]]; then 4727c478bd9Sstevel@tonic-gate dns_lookup=yes 4737c478bd9Sstevel@tonic-gate else 474bd211b85Ssemery if [[ $arg == none ]]; then 4757c478bd9Sstevel@tonic-gate dns_lookup=no 4767c478bd9Sstevel@tonic-gate else 477bd211b85Ssemery printf "\n$(gettext "Invalid DNS lookup option, exiting").\n" >&2 4787c478bd9Sstevel@tonic-gate error_message 4797c478bd9Sstevel@tonic-gate fi 4807c478bd9Sstevel@tonic-gate fi 4817c478bd9Sstevel@tonic-gate} 4827c478bd9Sstevel@tonic-gate 483bd211b85Ssemeryfunction verify_kdcs { 484bd211b85Ssemery typeset k_list="$1" 485bd211b85Ssemery typeset -l kdc 486bd211b85Ssemery typeset list fqhn f_list 4877c478bd9Sstevel@tonic-gate 488bd211b85Ssemery kdc_list=$(echo "$k_list" | sed 's/,/ /g') 489bd211b85Ssemery 490bd211b85Ssemery if [[ -z $k_list ]]; then 491bd211b85Ssemery printf "\n$(gettext "At least one KDC should be listed").\n\n" >&2 492bd211b85Ssemery usage 493bd211b85Ssemery fi 494bd211b85Ssemery 495bd211b85Ssemery for kdc in $k_list; do 496bd211b85Ssemery if [[ $kdc != $KDC ]]; then 497bd211b85Ssemery list="$list $kdc" 498bd211b85Ssemery fkdc=`$KLOOKUP $kdc` 499bd211b85Ssemery if ping $fkdc 2 > /dev/null; then 500bd211b85Ssemery : 501bd211b85Ssemery else 502bd211b85Ssemery printf "\n$(gettext "%s %s is unreachable, no action performed").\n" "KDC" $fkdc >&2 503bd211b85Ssemery fi 504bd211b85Ssemery f_list="$f_list $fkdc" 505bd211b85Ssemery fi 506bd211b85Ssemery done 507bd211b85Ssemery 508bd211b85Ssemery fkdc_list="$f_list" 509bd211b85Ssemery kdc_list="$list" 510bd211b85Ssemery} 511bd211b85Ssemery 512bd211b85Ssemeryfunction parse_service { 513bd211b85Ssemery typeset service_list=$1 514bd211b85Ssemery 515bd211b85Ssemery service_list=${service_list//,/ } 516bd211b85Ssemery for service in $service_list; do 517bd211b85Ssemery svc=${service%:} 518bd211b85Ssemery auth_type=${service#:} 519bd211b85Ssemery [[ -z $svc || -z $auth_type ]] && return 520bd211b85Ssemery print -- $svc $auth_type 521bd211b85Ssemery done 522bd211b85Ssemery} 523bd211b85Ssemery 524bd211b85Ssemeryfunction verify_fqdnlist { 525bd211b85Ssemery typeset list="$1" 526bd211b85Ssemery typeset -l hostname 527bd211b85Ssemery typeset -i count=1 528bd211b85Ssemery typeset fqdnlist eachfqdn tmpvar fullhost 529bd211b85Ssemery 530bd211b85Ssemery list=$(echo "$list" | tr -d " " | tr -d "\t") 531bd211b85Ssemery hostname=$(uname -n | cut -d"." -f1) 5327c478bd9Sstevel@tonic-gate fqdnlist=$client_machine 5337c478bd9Sstevel@tonic-gate 5347c478bd9Sstevel@tonic-gate eachfqdn=$(echo "$list" | cut -d"," -f$count) 535bd211b85Ssemery if [[ -z $eachfqdn ]]; then 536bd211b85Ssemery printf "\n$(gettext "If the -f option is used, at least one FQDN should be listed").\n\n" >&2 5377c478bd9Sstevel@tonic-gate usage 5387c478bd9Sstevel@tonic-gate else 539bd211b85Ssemery while [[ ! -z $eachfqdn ]]; do 5407c478bd9Sstevel@tonic-gate tmpvar=$(echo "$eachfqdn" | cut -d"." -f1) 541bd211b85Ssemery if [[ -z $tmpvar ]]; then 5427c478bd9Sstevel@tonic-gate fullhost="$hostname$eachfqdn" 5437c478bd9Sstevel@tonic-gate else 5447c478bd9Sstevel@tonic-gate fullhost="$hostname.$eachfqdn" 5457c478bd9Sstevel@tonic-gate fi 5467c478bd9Sstevel@tonic-gate 547bd211b85Ssemery ping_check $fullhost $(gettext "System") 548bd211b85Ssemery if [[ $fullhost == $client_machine ]]; then 5497c478bd9Sstevel@tonic-gate : 5507c478bd9Sstevel@tonic-gate else 5517c478bd9Sstevel@tonic-gate fqdnlist="$fqdnlist $fullhost" 5527c478bd9Sstevel@tonic-gate fi 5537c478bd9Sstevel@tonic-gate 554bd211b85Ssemery if [[ $list == *,* ]]; then 5557c478bd9Sstevel@tonic-gate ((count = count + 1)) 5567c478bd9Sstevel@tonic-gate eachfqdn=$(echo "$list" | cut -d"," -f$count) 5577c478bd9Sstevel@tonic-gate else 5587c478bd9Sstevel@tonic-gate break 5597c478bd9Sstevel@tonic-gate fi 5607c478bd9Sstevel@tonic-gate done 5617c478bd9Sstevel@tonic-gate fi 5627c478bd9Sstevel@tonic-gate} 5637c478bd9Sstevel@tonic-gate 564bd211b85Ssemeryfunction setup_keytab { 565bd211b85Ssemery typeset cname ask_fqdns current_release 566bd211b85Ssemery 567bd211b85Ssemery # 568bd211b85Ssemery # 1. kinit with ADMIN_PRINC 569bd211b85Ssemery # 570bd211b85Ssemery 571bd211b85Ssemery if [[ -z $ADMIN_PRINC ]]; then 572bd211b85Ssemery printf "\n$(gettext "Enter the krb5 administrative principal to be used"): " 573bd211b85Ssemery read ADMIN_PRINC 574bd211b85Ssemery checkval="ADMIN_PRINC"; check_value $ADMIN_PRINC 575bd211b85Ssemery fi 576bd211b85Ssemery 577bd211b85Ssemery echo "$ADMIN_PRINC">$TMP_FILE 578bd211b85Ssemery 579bd211b85Ssemery [[ -n $msad ]] && return 580bd211b85Ssemery if egrep -s '\/admin' $TMP_FILE; then 581bd211b85Ssemery # Already in "/admin" format, do nothing 582bd211b85Ssemery : 583bd211b85Ssemery else 584bd211b85Ssemery if egrep -s '\/' $TMP_FILE; then 585bd211b85Ssemery printf "\n$(gettext "Improper entry for krb5 admin principal, exiting").\n" >&2 5867c478bd9Sstevel@tonic-gate error_message 587bd211b85Ssemery else 588bd211b85Ssemery ADMIN_PRINC=$(echo "$ADMIN_PRINC/admin") 589bd211b85Ssemery fi 590bd211b85Ssemery fi 591bd211b85Ssemery 592bd211b85Ssemery printf "$(gettext "Obtaining TGT for %s") ...\n" $ADMIN_PRINC 593bd211b85Ssemery 594bd211b85Ssemery cname=$(canon_resolve $KDC) 595bd211b85Ssemery if [[ -n $cname ]]; then 596bd211b85Ssemery kinit -S kadmin/$cname $ADMIN_PRINC 597bd211b85Ssemery else 598bd211b85Ssemery kinit -S kadmin/$FKDC $ADMIN_PRINC 599bd211b85Ssemery fi 600bd211b85Ssemery klist 1>$TMP_FILE 2>&1 601ae5b046dSsemery if egrep -s "$(gettext "Valid starting")" $TMP_FILE && egrep -s "kadmin/$FKDC@$realm" $TMP_FILE; then 602bd211b85Ssemery : 603bd211b85Ssemery else 604bd211b85Ssemery printf "\n$(gettext "kinit of %s failed, exiting").\n" $ADMIN_PRINC >&2 605bd211b85Ssemery error_message 606bd211b85Ssemery fi 607bd211b85Ssemery 608bd211b85Ssemery # 609bd211b85Ssemery # 2. Do we want to create and/or add service principal(s) for fqdn's 610bd211b85Ssemery # other than the one listed in resolv.conf(4) ? 611bd211b85Ssemery # 612bd211b85Ssemery if [[ -z $options ]]; then 613bd211b85Ssemery query "$(gettext "Do you have multiple DNS domains spanning the Kerberos realm") $realm ?" 614bd211b85Ssemery ask_fqdns=$answer 615bd211b85Ssemery if [[ $ask_fqdns == yes ]]; then 616ae5b046dSsemery printf "$(gettext "Enter a comma-separated list of DNS domain names"): " 617bd211b85Ssemery read fqdnlist 618bd211b85Ssemery verify_fqdnlist "$fqdnlist" 619bd211b85Ssemery else 620bd211b85Ssemery fqdnlist=$client_machine 621bd211b85Ssemery fi 622bd211b85Ssemery else 623bd211b85Ssemery if [[ -z $fqdnlist ]]; then 624bd211b85Ssemery fqdnlist=$client_machine 625bd211b85Ssemery fi 626bd211b85Ssemery fi 627bd211b85Ssemery 628bd211b85Ssemery if [[ $add_nfs == yes ]]; then 629bd211b85Ssemery echo; call_kadmin nfs 630bd211b85Ssemery fi 631bd211b85Ssemery 632bd211b85Ssemery # Add the host entry to the keytab 633bd211b85Ssemery echo; call_kadmin host 634bd211b85Ssemery 635bd211b85Ssemery} 636bd211b85Ssemery 637bd211b85Ssemeryfunction setup_lhn { 638bd211b85Ssemery typeset -l logical_hn 639bd211b85Ssemery 640bd211b85Ssemery echo "$logical_hn" > $TMP_FILE 641bd211b85Ssemery if egrep -s '[^.]\.[^.]+$' $TMP_FILE; then 642bd211b85Ssemery # do nothing, logical_hn is in fqdn format 643bd211b85Ssemery : 644bd211b85Ssemery else 645bd211b85Ssemery if egrep -s '\.+' $TMP_FILE; then 646bd211b85Ssemery printf "\n$(gettext "Improper format of logical hostname, exiting").\n" >&2 647bd211b85Ssemery error_message 648bd211b85Ssemery else 649bd211b85Ssemery # Attach fqdn to logical_hn, to get the Fully Qualified 650bd211b85Ssemery # Host Name of the client requested 651bd211b85Ssemery logical_hn=$(echo "$logical_hn.$fqdn") 652bd211b85Ssemery fi 653bd211b85Ssemery fi 654bd211b85Ssemery 655bd211b85Ssemery client_machine=$logical_hn 656bd211b85Ssemery 657bd211b85Ssemery ping_check $client_machine $(gettext "System") 658bd211b85Ssemery} 659bd211b85Ssemery 660bd211b85Ssemeryfunction usage { 661bd211b85Ssemery printf "\n$(gettext "Usage: kclient [ options ]")\n" >&2 662bd211b85Ssemery printf "\t$(gettext "where options are any of the following")\n\n" >&2 663bd211b85Ssemery printf "\t$(gettext "[ -D domain_list ] configure a client that has mul 664bd211b85Ssemerytiple mappings of doamin and/or hosts to the default realm")\n" >&2 665bd211b85Ssemery printf "\t$(gettext "[ -K ] configure a client that does not have host/service keys")\n" >&2 666bd211b85Ssemery printf "\t$(gettext "[ -R realm ] specifies the realm to use")\n" >&2 667bd211b85Ssemery printf "\t$(gettext "[ -T kdc_vendor ] specifies which KDC vendor is the server")\n" >&2 668bd211b85Ssemery printf "\t$(gettext "[ -a adminuser ] specifies the Kerberos administrator")\n" >&2 669bd211b85Ssemery printf "\t$(gettext "[ -c filepath ] specifies the krb5.conf path used to configure this client")\n" >&2 670bd211b85Ssemery 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 671bd211b85Ssemery printf "\t$(gettext "[ -f fqdn_list ] specifies which domains to configure host keys for this client")\n" >&2 672bd211b85Ssemery printf "\t$(gettext "[ -h logicalhostname ] configure the logical host name for a client that is in a cluster")\n" >&2 673bd211b85Ssemery 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 674bd211b85Ssemery printf "\t$(gettext "[ -m master ] master KDC server host name")\n" >&2 675bd211b85Ssemery printf "\t$(gettext "[ -n ] configure client to be an NFS client")\n" >&2 676bd211b85Ssemery printf "\t$(gettext "[ -p profile ] specifies which profile file to use to configure this client")\n" >&2 677bd211b85Ssemery printf "\t$(gettext "[ -s pam_list ] update the service for Kerberos authentication")\n" >&2 678bd211b85Ssemery error_message 679bd211b85Ssemery} 680bd211b85Ssemery 681bd211b85Ssemeryfunction discover_domain { 682bd211b85Ssemery typeset dom DOMs 683bd211b85Ssemery 684bd211b85Ssemery if [[ -z $realm ]]; then 685bd211b85Ssemery set -A DOMs -- `$KLOOKUP _ldap._tcp.dc._msdcs S` 686bd211b85Ssemery else 687bd211b85Ssemery set -A DOMs -- `$KLOOKUP _ldap._tcp.dc._msdcs.$realm S` 688bd211b85Ssemery fi 689bd211b85Ssemery 690bd211b85Ssemery [[ -z ${DOMs[0]} ]] && return 1 691bd211b85Ssemery 692bd211b85Ssemery dom=${DOMs[0]} 693bd211b85Ssemery 694bd211b85Ssemery dom=${dom#*.} 695bd211b85Ssemery dom=${dom% *} 696bd211b85Ssemery 697bd211b85Ssemery domain=$dom 698bd211b85Ssemery 699bd211b85Ssemery return 0 700bd211b85Ssemery} 701bd211b85Ssemery 702bd211b85Ssemeryfunction check_nss_hosts_or_ipnodes_config { 703bd211b85Ssemery typeset backend 704bd211b85Ssemery 705bd211b85Ssemery for backend in $1 706bd211b85Ssemery do 707bd211b85Ssemery [[ $backend == dns ]] && return 0 708bd211b85Ssemery done 709bd211b85Ssemery return 1 710bd211b85Ssemery} 711bd211b85Ssemery 712bd211b85Ssemeryfunction check_nss_conf { 713bd211b85Ssemery typeset i j hosts_config 714bd211b85Ssemery 715bd211b85Ssemery for i in hosts ipnodes 716bd211b85Ssemery do 717bd211b85Ssemery grep "^${i}:" /etc/nsswitch.conf|read j hosts_config 718bd211b85Ssemery check_nss_hosts_or_ipnodes_config "$hosts_config" || return 1 719bd211b85Ssemery done 720bd211b85Ssemery 721bd211b85Ssemery return 0 722bd211b85Ssemery} 723bd211b85Ssemery 724bd211b85Ssemeryfunction canon_resolve { 725bd211b85Ssemery typeset name ip 726bd211b85Ssemery 727bd211b85Ssemery name=`$KLOOKUP $1 C` 728bd211b85Ssemery [[ -z $name ]] && name=`$KLOOKUP $1 A` 729bd211b85Ssemery [[ -z $name ]] && return 730bd211b85Ssemery 731bd211b85Ssemery ip=`$KLOOKUP $name I` 732bd211b85Ssemery [[ -z $ip ]] && return 733ae5b046dSsemery for i in $ip 734ae5b046dSsemery do 735ae5b046dSsemery if ping $i 2 > /dev/null 2>&1; then 736ae5b046dSsemery break 737ae5b046dSsemery else 738ae5b046dSsemery i= 739ae5b046dSsemery fi 740ae5b046dSsemery done 741bd211b85Ssemery 742bd211b85Ssemery cname=`$KLOOKUP $ip P` 743bd211b85Ssemery [[ -z $cname ]] && return 744bd211b85Ssemery 745bd211b85Ssemery print -- "$cname" 746bd211b85Ssemery} 747bd211b85Ssemery 748bd211b85Ssemeryfunction rev_resolve { 749bd211b85Ssemery typeset name ip 750bd211b85Ssemery 751bd211b85Ssemery ip=`$KLOOKUP $1 I` 752bd211b85Ssemery 753bd211b85Ssemery [[ -z $ip ]] && return 754bd211b85Ssemery name=`$KLOOKUP $ip P` 755bd211b85Ssemery [[ -z $name ]] && return 756bd211b85Ssemery 757bd211b85Ssemery print -- $name 758bd211b85Ssemery} 759bd211b85Ssemery 760bd211b85Ssemery# Convert an AD-style domain DN to a DNS domainname 761bd211b85Ssemeryfunction dn2dns { 762bd211b85Ssemery typeset OIFS dname dn comp components 763bd211b85Ssemery 764bd211b85Ssemery dn=$1 765bd211b85Ssemery dname= 766bd211b85Ssemery 767bd211b85Ssemery OIFS="$IFS" 768bd211b85Ssemery IFS=, 769bd211b85Ssemery set -A components -- $1 770bd211b85Ssemery IFS="$OIFS" 771bd211b85Ssemery 772bd211b85Ssemery for comp in "${components[@]}" 773bd211b85Ssemery do 774bd211b85Ssemery [[ "$comp" == [dD][cC]=* ]] || continue 775bd211b85Ssemery dname="$dname.${comp#??=}" 776bd211b85Ssemery done 777bd211b85Ssemery 778bd211b85Ssemery print ${dname#.} 779bd211b85Ssemery} 780bd211b85Ssemery 781bd211b85Ssemery# Form a base DN from a DNS domainname and container 782bd211b85Ssemeryfunction getBaseDN { 783bd211b85Ssemery if [[ -n "$2" ]] 784bd211b85Ssemery then 785bd211b85Ssemery baseDN="CN=$1,$(dns2dn $2)" 786bd211b85Ssemery else 787bd211b85Ssemery baseDN="$(dns2dn $2)" 788bd211b85Ssemery fi 789bd211b85Ssemery} 790bd211b85Ssemery 791bd211b85Ssemery# Convert a DNS domainname to an AD-style DN for that domain 792bd211b85Ssemeryfunction dns2dn { 793bd211b85Ssemery typeset OIFS dn labels 794bd211b85Ssemery 795bd211b85Ssemery OIFS="$IFS" 796bd211b85Ssemery IFS=. 797bd211b85Ssemery set -A labels -- $1 798bd211b85Ssemery IFS="$OIFS" 799bd211b85Ssemery 800bd211b85Ssemery dn= 801bd211b85Ssemery for label in "${labels[@]}" 802bd211b85Ssemery do 803bd211b85Ssemery dn="${dn},DC=$label" 804bd211b85Ssemery done 805bd211b85Ssemery 806bd211b85Ssemery print -- "${dn#,}" 807bd211b85Ssemery} 808bd211b85Ssemery 809bd211b85Ssemeryfunction getSRVs { 810bd211b85Ssemery typeset srv port 811bd211b85Ssemery 812bd211b85Ssemery $KLOOKUP $1 S | while read srv port 813bd211b85Ssemery do 814ae5b046dSsemery if ping $srv 2 > /dev/null 2>&1; then 815bd211b85Ssemery print -- $srv $port 816ae5b046dSsemery fi 817bd211b85Ssemery done 818bd211b85Ssemery} 819bd211b85Ssemery 820bd211b85Ssemeryfunction getKDC { 821bd211b85Ssemery typeset j 822bd211b85Ssemery 823bd211b85Ssemery set -A KPWs -- $(getSRVs _kpasswd._tcp.$dom.) 824bd211b85Ssemery kpasswd=${KPWs[0]} 825bd211b85Ssemery 826bd211b85Ssemery if [[ -n $siteName ]] 827bd211b85Ssemery then 828bd211b85Ssemery set -A KDCs -- $(getSRVs _kerberos._tcp.$siteName._sites.$dom.) 829bd211b85Ssemery kdc=${KDCs[0]} 830bd211b85Ssemery [[ -n $kdc ]] && return 831bd211b85Ssemery fi 832bd211b85Ssemery 833bd211b85Ssemery # No site name 834bd211b85Ssemery set -A KDCs -- $(getSRVs _kerberos._tcp.$dom.) 835bd211b85Ssemery kdc=${KDCs[0]} 836bd211b85Ssemery [[ -n $kdc ]] && return 837bd211b85Ssemery 838bd211b85Ssemery # Default 839bd211b85Ssemery set -A KDCs -- $DomainDnsZones 88 840bd211b85Ssemery kdc=$ForestDnsZones 841bd211b85Ssemery} 842bd211b85Ssemery 843bd211b85Ssemeryfunction getDC { 844bd211b85Ssemery typeset j 845bd211b85Ssemery 846bd211b85Ssemery if [[ -n $siteName ]] 847bd211b85Ssemery then 848bd211b85Ssemery set -A DCs -- $(getSRVs _ldap._tcp.$siteName._sites.dc._msdcs.$dom.) 849bd211b85Ssemery dc=${DCs[0]} 850bd211b85Ssemery [[ -n $dc ]] && return 851bd211b85Ssemery fi 852bd211b85Ssemery 853bd211b85Ssemery # No site name 854bd211b85Ssemery set -A DCs -- $(getSRVs _ldap._tcp.dc._msdcs.$dom.) 855bd211b85Ssemery dc=${DCs[0]} 856bd211b85Ssemery [[ -n $dc ]] && return 857bd211b85Ssemery 858bd211b85Ssemery # Default 859bd211b85Ssemery set -A DCs -- $DomainDnsZones 389 860bd211b85Ssemery dc=$DomainDnsZones 861bd211b85Ssemery} 862bd211b85Ssemery 863bd211b85Ssemeryfunction write_ads_krb5conf { 864c48f4690SShawn Emery typeset kdcs 865c48f4690SShawn Emery 866bd211b85Ssemery printf "\n$(gettext "Setting up %s").\n\n" $KRB5_CONFIG_FILE 867bd211b85Ssemery 868bd211b85Ssemery for i in ${KDCs[@]} 869bd211b85Ssemery do 870bd211b85Ssemery [[ $i == +([0-9]) ]] && continue 871c48f4690SShawn Emery if [[ -n $kdcs ]] 872c48f4690SShawn Emery then 873c48f4690SShawn Emery kdcs="$kdcs,$i" 874c48f4690SShawn Emery else 875c48f4690SShawn Emery kdcs=$i 876c48f4690SShawn Emery fi 877bd211b85Ssemery done 878c48f4690SShawn Emery 879c48f4690SShawn Emery $KCONF -f $KRB5_CONFIG -r $realm -k $kdcs -m $KDC -p SET_CHANGE -d .$dom 880c48f4690SShawn Emery 881c48f4690SShawn Emery if [[ $? -ne 0 ]]; then 882c48f4690SShawn Emery printf "\n$(gettext "Can not update %s, exiting").\n" $KRB5_CONFIG >&2 883c48f4690SShawn Emery error_message 884c48f4690SShawn Emery fi 885bd211b85Ssemery} 886bd211b85Ssemery 887bd211b85Ssemeryfunction getForestName { 888bd211b85Ssemery ldapsearch -R -T -h $dc $ldap_args \ 889bd211b85Ssemery -b "" -s base "" schemaNamingContext| \ 890bd211b85Ssemery grep ^schemaNamingContext|read j schemaNamingContext 891bd211b85Ssemery 892bd211b85Ssemery if [[ $? -ne 0 ]]; then 893c386eb9cSShawn Emery printf "$(gettext "Can't find forest").\n" >&2 894bd211b85Ssemery error_message 895bd211b85Ssemery fi 896bd211b85Ssemery schemaNamingContext=${schemaNamingContext#CN=Schema,CN=Configuration,} 897bd211b85Ssemery 898bd211b85Ssemery [[ -z $schemaNamingContext ]] && return 1 899bd211b85Ssemery 900bd211b85Ssemery forest= 901bd211b85Ssemery while [[ -n $schemaNamingContext ]] 902bd211b85Ssemery do 903bd211b85Ssemery schemaNamingContext=${schemaNamingContext#DC=} 904bd211b85Ssemery forest=${forest}.${schemaNamingContext%%,*} 905bd211b85Ssemery [[ "$schemaNamingContext" = *,* ]] || break 906bd211b85Ssemery schemaNamingContext=${schemaNamingContext#*,} 907bd211b85Ssemery done 908bd211b85Ssemery forest=${forest#.} 909bd211b85Ssemery} 910bd211b85Ssemery 911bd211b85Ssemeryfunction getGC { 912bd211b85Ssemery typeset j 913bd211b85Ssemery 914bd211b85Ssemery [[ -n $gc ]] && return 0 915bd211b85Ssemery 916bd211b85Ssemery if [[ -n $siteName ]] 917bd211b85Ssemery then 918bd211b85Ssemery set -A GCs -- $(getSRVs _ldap._tcp.$siteName._sites.gc._msdcs.$forest.) 919bd211b85Ssemery gc=${GCs[0]} 920bd211b85Ssemery [[ -n $gc ]] && return 921bd211b85Ssemery fi 922bd211b85Ssemery 923bd211b85Ssemery # No site name 924bd211b85Ssemery set -A GCs -- $(getSRVs _ldap._tcp.gc._msdcs.$forest.) 925bd211b85Ssemery gc=${GCs[0]} 926bd211b85Ssemery [[ -n $gc ]] && return 927bd211b85Ssemery 928bd211b85Ssemery # Default 929bd211b85Ssemery set -A GCs -- $ForestDnsZones 3268 930bd211b85Ssemery gc=$ForestDnsZones 931bd211b85Ssemery} 932bd211b85Ssemery 933c386eb9cSShawn Emery# 934c386eb9cSShawn Emery# The local variables used to calculate the IP address are of type unsigned 935c386eb9cSShawn Emery# integer (-ui), as this is required to restrict the integer to 32b. 936c386eb9cSShawn Emery# Starting in ksh88, Solaris has incorrectly assummed that -i represents 64b. 937c386eb9cSShawn Emery# 938bd211b85Ssemeryfunction ipAddr2num { 939bd211b85Ssemery typeset OIFS 940c386eb9cSShawn Emery typeset -ui16 num 941bd211b85Ssemery 942bd211b85Ssemery if [[ "$1" != +([0-9]).+([0-9]).+([0-9]).+([0-9]) ]] 943bd211b85Ssemery then 944bd211b85Ssemery print 0 945bd211b85Ssemery return 0 946bd211b85Ssemery fi 947bd211b85Ssemery 948bd211b85Ssemery OIFS="$IFS" 949bd211b85Ssemery IFS=. 950bd211b85Ssemery set -- $1 951bd211b85Ssemery IFS="$OIFS" 952bd211b85Ssemery 953bd211b85Ssemery num=$((${1}<<24 | ${2}<<16 | ${3}<<8 | ${4})) 954bd211b85Ssemery 955bd211b85Ssemery print -- $num 956bd211b85Ssemery} 957bd211b85Ssemery 958c386eb9cSShawn Emery# 959c386eb9cSShawn Emery# The local variables used to calculate the IP address are of type unsigned 960c386eb9cSShawn Emery# integer (-ui), as this is required to restrict the integer to 32b. 961c386eb9cSShawn Emery# Starting in ksh88, Solaris has incorrectly assummed that -i represents 64b. 962c386eb9cSShawn Emery# 963bd211b85Ssemeryfunction num2ipAddr { 964c386eb9cSShawn Emery typeset -ui16 num 965c386eb9cSShawn Emery typeset -ui10 a b c d 966bd211b85Ssemery 967bd211b85Ssemery num=$1 968bd211b85Ssemery a=$((num>>24 )) 969bd211b85Ssemery b=$((num>>16 & 16#ff)) 970bd211b85Ssemery c=$((num>>8 & 16#ff)) 971bd211b85Ssemery d=$((num & 16#ff)) 972bd211b85Ssemery print -- $a.$b.$c.$d 973bd211b85Ssemery} 974bd211b85Ssemery 975c386eb9cSShawn Emery# 976c386eb9cSShawn Emery# The local variables used to calculate the IP address are of type unsigned 977c386eb9cSShawn Emery# integer (-ui), as this is required to restrict the integer to 32b. 978c386eb9cSShawn Emery# Starting in ksh88, Solaris has incorrectly assummed that -i represents 64b. 979c386eb9cSShawn Emery# 980bd211b85Ssemeryfunction netmask2length { 981c386eb9cSShawn Emery typeset -ui16 netmask 982bd211b85Ssemery typeset -i len 983bd211b85Ssemery 984bd211b85Ssemery netmask=$1 985bd211b85Ssemery len=32 986bd211b85Ssemery while [[ $((netmask % 2)) -eq 0 ]] 987bd211b85Ssemery do 988bd211b85Ssemery netmask=$((netmask>>1)) 989bd211b85Ssemery len=$((len - 1)) 990bd211b85Ssemery done 991bd211b85Ssemery print $len 992bd211b85Ssemery} 993bd211b85Ssemery 994c386eb9cSShawn Emery# 995c386eb9cSShawn Emery# The local variables used to calculate the IP address are of type unsigned 996c386eb9cSShawn Emery# integer (-ui), as this is required to restrict the integer to 32b. 997c386eb9cSShawn Emery# Starting in ksh88, Solaris has incorrectly assummed that -i represents 64b. 998c386eb9cSShawn Emery# 999bd211b85Ssemeryfunction getSubnets { 1000c386eb9cSShawn Emery typeset -ui16 addr netmask 1001c386eb9cSShawn Emery typeset -ui16 classa=16\#ff000000 1002bd211b85Ssemery 1003bd211b85Ssemery ifconfig -a|while read line 1004bd211b85Ssemery do 1005bd211b85Ssemery addr=0 1006bd211b85Ssemery netmask=0 1007bd211b85Ssemery set -- $line 1008bd211b85Ssemery [[ $1 == inet ]] || continue 1009bd211b85Ssemery while [[ $# -gt 0 ]] 1010bd211b85Ssemery do 1011bd211b85Ssemery case "$1" in 1012bd211b85Ssemery inet) addr=$(ipAddr2num $2); shift;; 1013bd211b85Ssemery netmask) eval netmask=16\#$2; shift;; 1014bd211b85Ssemery *) :; 1015bd211b85Ssemery esac 1016bd211b85Ssemery shift 1017bd211b85Ssemery done 1018bd211b85Ssemery 1019bd211b85Ssemery [[ $addr -eq 0 || $netmask -eq 0 ]] && continue 1020bd211b85Ssemery [[ $((addr & classa)) -eq 16\#7f000000 ]] && continue 1021bd211b85Ssemery 1022bd211b85Ssemery print $(num2ipAddr $((addr & netmask)))/$(netmask2length $netmask) 1023bd211b85Ssemery done 1024bd211b85Ssemery} 1025bd211b85Ssemery 1026bd211b85Ssemeryfunction getSite { 1027bd211b85Ssemery typeset subnet siteDN j ldapsrv subnet_dom 1028bd211b85Ssemery 1029bd211b85Ssemery eval "[[ -n \"\$siteName\" ]]" && return 1030bd211b85Ssemery for subnet in $(getSubnets) 1031bd211b85Ssemery do 1032bd211b85Ssemery ldapsearch -R -T -h $dc $ldap_args \ 1033bd211b85Ssemery -p 3268 -b "" -s sub cn=$subnet dn |grep ^dn|read j subnetDN 1034bd211b85Ssemery 1035bd211b85Ssemery [[ -z $subnetDN ]] && continue 1036bd211b85Ssemery subnet_dom=$(dn2dns $subnetDN) 1037bd211b85Ssemery ldapsrv=$(canon_resolve DomainDnsZones.$subnet_dom) 1038ae5b046dSsemery [[ -z $ldapsrv ]] && continue 1039bd211b85Ssemery ldapsearch -R -T -h $ldapsrv $ldap_args \ 1040bd211b85Ssemery -b "$subnetDN" -s base "" siteObject \ 1041bd211b85Ssemery |grep ^siteObject|read j siteDN 1042bd211b85Ssemery 1043bd211b85Ssemery [[ -z $siteDN ]] && continue 1044bd211b85Ssemery 1045bd211b85Ssemery eval siteName=${siteDN%%,*} 1046bd211b85Ssemery eval siteName=\${siteName#CN=} 1047bd211b85Ssemery return 1048bd211b85Ssemery done 1049bd211b85Ssemery} 1050bd211b85Ssemery 1051bd211b85Ssemeryfunction doKRB5config { 1052bd211b85Ssemery [[ -f $KRB5_CONFIG_FILE ]] && \ 1053bd211b85Ssemery cp $KRB5_CONFIG_FILE ${KRB5_CONFIG_FILE}-pre-kclient 1054bd211b85Ssemery 1055bd211b85Ssemery [[ -f $KRB5_KEYTAB_FILE ]] && \ 1056bd211b85Ssemery cp $KRB5_KEYTAB_FILE ${KRB5_KEYTAB_FILE}-pre-kclient 1057bd211b85Ssemery 1058ae5b046dSsemery [[ -s $KRB5_CONFIG ]] && cp $KRB5_CONFIG $KRB5_CONFIG_FILE 1059ae5b046dSsemery [[ -s $KRB5_CONFIG_FILE ]] && chmod 0644 $KRB5_CONFIG_FILE 1060ae5b046dSsemery [[ -s $new_keytab ]] && cp $new_keytab $KRB5_KEYTAB_FILE 1061ae5b046dSsemery [[ -s $KRB5_KEYTAB_FILE ]] && chmod 0600 $KRB5_KEYTAB_FILE 1062bd211b85Ssemery} 1063bd211b85Ssemery 1064bd211b85Ssemeryfunction addDNSRR { 1065bd211b85Ssemery smbFMRI=svc:/network/smb/server:default 1066bd211b85Ssemery ddnsProp=smbd/ddns_enable 1067bd211b85Ssemery enProp=general/enabled 1068bd211b85Ssemery 1069bd211b85Ssemery enabled=`svcprop -p $enProp $smbFMRI` 1070bd211b85Ssemery ddns_enable=`svcprop -p $ddnsProp $smbFMRI` 1071bd211b85Ssemery 1072bd211b85Ssemery if [[ $enabled == true && $ddns_enable != true ]]; then 1073bd211b85Ssemery printf "$(gettext "Warning: won't create DNS records for client").\n" 1074bd211b85Ssemery printf "$(gettext "%s property not set to 'true' for the %s FMRI").\n" $ddnsProp $smbFMRI 1075bd211b85Ssemery return 1076bd211b85Ssemery fi 1077bd211b85Ssemery 1078bd211b85Ssemery # Destroy any existing ccache as GSS_C_NO_CREDENTIAL will pick up any 1079bd211b85Ssemery # residual default credential in the cache. 1080bd211b85Ssemery kdestroy > /dev/null 2>&1 1081bd211b85Ssemery 1082bd211b85Ssemery $KDYNDNS -d $1 > /dev/null 2>&1 1083bd211b85Ssemery if [[ $? -ne 0 ]]; then 1084bd211b85Ssemery # 1085bd211b85Ssemery # Non-fatal, we should carry-on as clients may resolve to 1086bd211b85Ssemery # different servers and the client could already exist there. 1087bd211b85Ssemery # 10888d7e4166Sjose borrego printf "$(gettext "Warning: unable to create DNS records for client").\n" 1089bd211b85Ssemery 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 1090bd211b85Ssemery fi 1091bd211b85Ssemery} 1092bd211b85Ssemery 1093bd211b85Ssemeryfunction setSMB { 1094bd211b85Ssemery typeset domain=$1 1095bd211b85Ssemery typeset server=$2 1096bd211b85Ssemery smbFMRI=svc:/network/smb/server 1097bd211b85Ssemery 1098986b458dSShawn Emery printf "%s" "$newpw" | $KSMB -d $domain -s $server 1099bd211b85Ssemery if [[ $? -ne 0 ]]; then 11008d7e4166Sjose borrego printf "$(gettext "Warning: unable to set %s domain, server and password information").\n" $smbFMRI 1101bd211b85Ssemery return 1102bd211b85Ssemery fi 1103bd211b85Ssemery 11048d7e4166Sjose borrego svcadm restart $smbFMRI > /dev/null 2>&1 1105bd211b85Ssemery if [[ $? -ne 0 ]]; then 11068d7e4166Sjose borrego printf "$(gettext "Warning: unable to restart %s").\n" $smbFMRI 1107bd211b85Ssemery fi 1108bd211b85Ssemery} 1109bd211b85Ssemery 1110bd211b85Ssemeryfunction compareDomains { 1111bd211b85Ssemery typeset oldDom hspn newDom=$1 1112bd211b85Ssemery 1113bd211b85Ssemery # If the client has been previously configured in a different 1114bd211b85Ssemery # realm/domain then we need to prompt the user to see if they wish to 1115bd211b85Ssemery # switch domains. 1116ae5b046dSsemery klist -k 2>&1 | grep @ | read j hspn 1117bd211b85Ssemery [[ -z $hspn ]] && return 1118bd211b85Ssemery 1119bd211b85Ssemery oldDom=${hspn#*@} 1120bd211b85Ssemery if [[ $oldDom != $newDom ]]; then 1121bd211b85Ssemery printf "$(gettext "The client is currently configured in a different domain").\n" 1122bd211b85Ssemery printf "$(gettext "Currently in the '%s' domain, trying to join the '%s' domain").\n" $oldDom $newDom 1123bd211b85Ssemery query "$(gettext "Do you want the client to join a new domain") ?" 1124bd211b85Ssemery printf "\n" 1125bd211b85Ssemery if [[ $answer != yes ]]; then 1126c386eb9cSShawn Emery printf "$(gettext "Client will not be joined to the new domain").\n" >&2 1127bd211b85Ssemery error_message 1128bd211b85Ssemery fi 1129bd211b85Ssemery fi 1130bd211b85Ssemery} 1131bd211b85Ssemery 1132bd211b85Ssemeryfunction getKDCDC { 1133bd211b85Ssemery 1134bd211b85Ssemery getKDC 1135bd211b85Ssemery if [[ -n $kdc ]]; then 1136bd211b85Ssemery KDC=$kdc 1137bd211b85Ssemery dc=$kdc 1138bd211b85Ssemery else 1139bd211b85Ssemery getDC 1140bd211b85Ssemery if [[ -n $dc ]]; then 1141bd211b85Ssemery KDC=$dc 1142bd211b85Ssemery else 1143c386eb9cSShawn Emery printf "$(gettext "Could not find domain controller server for '%s'. Exiting").\n" $realm >&2 1144bd211b85Ssemery error_message 1145bd211b85Ssemery fi 1146bd211b85Ssemery fi 1147bd211b85Ssemery} 1148bd211b85Ssemery 1149986b458dSShawn Emeryfunction gen_rand { 1150986b458dSShawn Emery typeset -u hex 1151986b458dSShawn Emery 1152986b458dSShawn Emery dd if=/dev/random bs=1 count=1 2>/dev/null | od -A n -tx1 | read hex 1153986b458dSShawn Emery 1154986b458dSShawn Emery printf %s $((16#$hex)) 1155986b458dSShawn Emery} 1156986b458dSShawn Emery 1157bd211b85Ssemeryfunction join_domain { 1158bd211b85Ssemery typeset -u upcase_nodename 115972f0806aSShawn Emery typeset -l locase_nodename 116072f0806aSShawn Emery typeset -L15 string15 1161bd211b85Ssemery typeset netbios_nodename fqdn 1162bd211b85Ssemery 1163bd211b85Ssemery container=Computers 1164bd211b85Ssemery ldap_args="-o authzid= -o mech=gssapi" 1165bd211b85Ssemery userAccountControlBASE=4096 1166bd211b85Ssemery 1167bd211b85Ssemery if [[ -z $ADMIN_PRINC ]]; then 1168bd211b85Ssemery cprinc=Administrator 1169bd211b85Ssemery else 1170bd211b85Ssemery cprinc=$ADMIN_PRINC 1171bd211b85Ssemery fi 1172bd211b85Ssemery 1173bd211b85Ssemery if ! discover_domain; then 1174c386eb9cSShawn Emery printf "$(gettext "Can not find realm") '%s'.\n" $realm >&2 1175bd211b85Ssemery error_message 1176bd211b85Ssemery fi 1177bd211b85Ssemery 1178bd211b85Ssemery dom=$domain 1179bd211b85Ssemery realm=$domain 118072f0806aSShawn Emery 118172f0806aSShawn Emery if [[ ${#hostname} -gt 15 ]]; then 118272f0806aSShawn Emery string15=$hostname 118372f0806aSShawn Emery upcase_nodename=$string15 118472f0806aSShawn Emery locase_nodename=$string15 118572f0806aSShawn Emery else 1186bd211b85Ssemery upcase_nodename=$hostname 118772f0806aSShawn Emery locase_nodename=$hostname 118872f0806aSShawn Emery fi 118972f0806aSShawn Emery 1190bd211b85Ssemery netbios_nodename="${upcase_nodename}\$" 1191bd211b85Ssemery fqdn=$hostname.$domain 1192037cac00Sjoyce mcintosh upn=host/${fqdn}@${realm} 1193bd211b85Ssemery 1194bd211b85Ssemery object=$(mktemp -q -t kclient-computer-object.XXXXXX) 1195bd211b85Ssemery if [[ -z $object ]]; then 1196bd211b85Ssemery printf "\n$(gettext "Can not create temporary file, exiting").\n 1197bd211b85Ssemery" >&2 1198bd211b85Ssemery error_message 1199bd211b85Ssemery fi 1200bd211b85Ssemery 1201bd211b85Ssemery modify_existing=false 1202bd211b85Ssemery recreate=false 1203bd211b85Ssemery 1204bd211b85Ssemery DomainDnsZones=$(rev_resolve DomainDnsZones.$dom.) 1205bd211b85Ssemery ForestDnsZones=$(rev_resolve ForestDnsZones.$dom.) 1206bd211b85Ssemery 1207bd211b85Ssemery getBaseDN "$container" "$dom" 1208bd211b85Ssemery 1209bd211b85Ssemery if [[ -n $KDC ]]; then 1210bd211b85Ssemery dc=$KDC 1211bd211b85Ssemery else 1212bd211b85Ssemery getKDCDC 1213bd211b85Ssemery fi 1214bd211b85Ssemery 1215bd211b85Ssemery write_ads_krb5conf 1216bd211b85Ssemery 1217ae5b046dSsemery printf "$(gettext "Attempting to join '%s' to the '%s' domain").\n\n" $upcase_nodename $realm 1218bd211b85Ssemery 1219bd211b85Ssemery kinit $cprinc@$realm 1220bd211b85Ssemery if [[ $? -ne 0 ]]; then 1221c386eb9cSShawn Emery printf "$(gettext "Could not authenticate %s. Exiting").\n" $cprinc@$realm >&2 1222bd211b85Ssemery error_message 1223bd211b85Ssemery fi 1224bd211b85Ssemery 1225bd211b85Ssemery if getForestName 1226bd211b85Ssemery then 1227bd211b85Ssemery printf "\n$(gettext "Forest name found: %s")\n\n" $forest 1228bd211b85Ssemery else 1229bd211b85Ssemery printf "\n$(gettext "Forest name not found, assuming forest is the domain name").\n" 1230bd211b85Ssemery fi 1231bd211b85Ssemery 1232bd211b85Ssemery getGC 1233bd211b85Ssemery getSite 1234bd211b85Ssemery 1235bd211b85Ssemery if [[ -z $siteName ]] 1236bd211b85Ssemery then 1237bd211b85Ssemery printf "$(gettext "Site name not found. Local DCs/GCs will not be discovered").\n\n" 1238bd211b85Ssemery else 1239bd211b85Ssemery printf "$(gettext "Looking for _local_ KDCs, DCs and global catalog servers (SRV RRs)").\n" 1240bd211b85Ssemery getKDCDC 1241bd211b85Ssemery getGC 1242bd211b85Ssemery 1243bd211b85Ssemery write_ads_krb5conf 1244bd211b85Ssemery fi 1245bd211b85Ssemery 1246bd211b85Ssemery if [[ ${#GCs} -eq 0 ]]; then 1247c386eb9cSShawn Emery printf "$(gettext "Could not find global catalogs. Exiting").\n" >&2 1248bd211b85Ssemery error_message 1249bd211b85Ssemery fi 1250bd211b85Ssemery 1251bd211b85Ssemery # Check to see if the client is transitioning between domains. 1252bd211b85Ssemery compareDomains $realm 1253bd211b85Ssemery 1254bd211b85Ssemery # Here we check domainFunctionality to see which release: 1255bd211b85Ssemery # 0, 1, 2: Windows 2000, 2003 Interim, 2003 respecitively 1256bd211b85Ssemery # 3: Windows 2008 1257bd211b85Ssemery level=0 1258bd211b85Ssemery ldapsearch -R -T -h "$dc" $ldap_args -b "" -s base "" \ 1259bd211b85Ssemery domainControllerFunctionality| grep ^domainControllerFunctionality| \ 1260bd211b85Ssemery read j level 1261bd211b85Ssemery if [[ $? -ne 0 ]]; then 1262c386eb9cSShawn Emery printf "$(gettext "Search for domain functionality failed, exiting").\n" >&2 1263bd211b85Ssemery error_message 1264bd211b85Ssemery fi 1265bd211b85Ssemery 1266bd211b85Ssemery if ldapsearch -R -T -h "$dc" $ldap_args -b "$baseDN" \ 1267bd211b85Ssemery -s sub sAMAccountName="$netbios_nodename" dn > /dev/null 2>&1 1268bd211b85Ssemery then 1269bd211b85Ssemery : 1270bd211b85Ssemery else 1271c386eb9cSShawn Emery printf "$(gettext "Search for node failed, exiting").\n" >&2 1272bd211b85Ssemery error_message 1273bd211b85Ssemery fi 1274bd211b85Ssemery ldapsearch -R -T -h "$dc" $ldap_args -b "$baseDN" -s sub \ 1275bd211b85Ssemery sAMAccountName="$netbios_nodename" dn|grep "^dn:"|read j dn 1276bd211b85Ssemery 1277bd211b85Ssemery if [[ -z $dn ]]; then 1278bd211b85Ssemery : # modify_existing is already false, which is what we want. 1279bd211b85Ssemery else 1280bd211b85Ssemery printf "$(gettext "Computer account '%s' already exists in the '%s' domain").\n" $upcase_nodename $realm 1281bd211b85Ssemery query "$(gettext "Do you wish to recreate this computer account") ?" 1282bd211b85Ssemery printf "\n" 1283bd211b85Ssemery if [[ $answer == yes ]]; then 1284bd211b85Ssemery recreate=true 1285bd211b85Ssemery else 1286bd211b85Ssemery modify_existing=true 1287bd211b85Ssemery fi 1288bd211b85Ssemery fi 1289bd211b85Ssemery 1290bd211b85Ssemery if [[ $modify_existing == false && -n $dn ]]; then 1291bd211b85Ssemery query "$(gettext "Would you like to delete any sub-object found for this computer account") ?" 1292bd211b85Ssemery if [[ $answer == yes ]]; then 1293bd211b85Ssemery printf "$(gettext "Looking to see if the machine account contains other objects")...\n" 1294bd211b85Ssemery ldapsearch -R -T -h "$dc" $ldap_args -b "$dn" -s sub "" dn | while read j sub_dn 1295bd211b85Ssemery do 1296bd211b85Ssemery [[ $j != dn: || -z $sub_dn || $dn == $sub_dn ]] && continue 1297bd211b85Ssemery if $recreate; then 1298bd211b85Ssemery printf "$(gettext "Deleting the following object: %s")\n" ${sub_dn#$dn} 1299bd211b85Ssemery ldapdelete -h "$dc" $ldap_args "$sub_dn" > /dev/null 2>&1 1300bd211b85Ssemery if [[ $? -ne 0 ]]; then 1301bd211b85Ssemery printf "$(gettext "Error in deleting object: %s").\n" ${sub_dn#$dn} 1302bd211b85Ssemery fi 1303bd211b85Ssemery else 1304bd211b85Ssemery printf "$(gettext "The following object will not be deleted"): %s\n" ${sub_dn#$dn} 1305bd211b85Ssemery fi 1306bd211b85Ssemery done 1307bd211b85Ssemery fi 1308bd211b85Ssemery 1309bd211b85Ssemery if $recreate; then 1310bd211b85Ssemery ldapdelete -h "$dc" $ldap_args "$dn" > /dev/null 2>&1 1311bd211b85Ssemery if [[ $? -ne 0 ]]; then 1312c386eb9cSShawn Emery printf "$(gettext "Error in deleting object: %s").\n" ${sub_dn#$dn} >&2 1313bd211b85Ssemery error_message 1314bd211b85Ssemery fi 1315bd211b85Ssemery elif $modify_existing; then 1316bd211b85Ssemery : # Nothing to delete 1317bd211b85Ssemery else 1318c386eb9cSShawn Emery printf "$(gettext "A machine account already exists").\n" >&2 1319bd211b85Ssemery error_message 1320bd211b85Ssemery fi 1321bd211b85Ssemery fi 1322bd211b85Ssemery 132372f0806aSShawn Emery [[ -z $dn ]] && dn="CN=${upcase_nodename},${baseDN}" 1324bd211b85Ssemery if $modify_existing; then 1325bd211b85Ssemery cat > "$object" <<EOF 132672f0806aSShawn Emerydn: $dn 1327bd211b85Ssemerychangetype: modify 1328bd211b85Ssemeryreplace: userPrincipalName 1329bd211b85SsemeryuserPrincipalName: $upn 1330bd211b85Ssemery- 1331bd211b85Ssemeryreplace: servicePrincipalName 1332bd211b85SsemeryservicePrincipalName: host/${fqdn} 1333bd211b85Ssemery- 1334bd211b85Ssemeryreplace: userAccountControl 1335bd211b85SsemeryuserAccountControl: $((userAccountControlBASE + 32 + 2)) 1336bd211b85Ssemery- 1337bd211b85Ssemeryreplace: dNSHostname 1338bd211b85SsemerydNSHostname: ${fqdn} 1339bd211b85SsemeryEOF 1340bd211b85Ssemery 1341bd211b85Ssemery printf "$(gettext "A machine account already exists; updating it").\n" 1342ae5b046dSsemery ldapadd -h "$dc" $ldap_args -f "$object" > /dev/null 2>&1 1343bd211b85Ssemery if [[ $? -ne 0 ]]; then 134472f0806aSShawn Emery printf "$(gettext "Failed to modify the AD object via LDAP").\n" >&2 1345bd211b85Ssemery error_message 1346bd211b85Ssemery fi 1347bd211b85Ssemery else 134872f0806aSShawn Emery dn="CN=${upcase_nodename},${baseDN}" 1349bd211b85Ssemery cat > "$object" <<EOF 135072f0806aSShawn Emerydn: $dn 1351bd211b85SsemeryobjectClass: computer 1352bd211b85Ssemerycn: $upcase_nodename 1353bd211b85SsemerysAMAccountName: ${netbios_nodename} 1354bd211b85SsemeryuserPrincipalName: $upn 1355bd211b85SsemeryservicePrincipalName: host/${fqdn} 1356bd211b85SsemeryuserAccountControl: $((userAccountControlBASE + 32 + 2)) 1357bd211b85SsemerydNSHostname: ${fqdn} 1358bd211b85SsemeryEOF 1359bd211b85Ssemery 1360bd211b85Ssemery printf "$(gettext "Creating the machine account in AD via LDAP").\n\n" 1361bd211b85Ssemery 1362bd211b85Ssemery ldapadd -h "$dc" $ldap_args -f "$object" > /dev/null 2>&1 1363bd211b85Ssemery if [[ $? -ne 0 ]]; then 1364c386eb9cSShawn Emery printf "$(gettext "Failed to create the AD object via LDAP").\n" >&2 1365bd211b85Ssemery error_message 1366bd211b85Ssemery fi 1367bd211b85Ssemery fi 1368bd211b85Ssemery 1369bd211b85Ssemery # Generate a new password for the new account 1370986b458dSShawn Emery MAX_PASS=120 1371bd211b85Ssemery i=0 1372bd211b85Ssemery 1373986b458dSShawn Emery # first check to see if /dev/random exists to generate a new password 1374986b458dSShawn Emery if [[ ! -h /dev/random ]]; then 1375986b458dSShawn Emery printf "$(gettext "/dev/random does not exist").\n" >&2 1376986b458dSShawn Emery error_message 1377986b458dSShawn Emery fi 1378986b458dSShawn Emery 1379bd211b85Ssemery while ((MAX_PASS > i)) 1380bd211b85Ssemery do 1381986b458dSShawn Emery # [MS-DISO] A machine password is an ASCII string of randomly 1382986b458dSShawn Emery # chosen characters. Each character's ASCII code is between 32 1383986b458dSShawn Emery # and 122 inclusive. 1384986b458dSShawn Emery c=$(printf "\\$(printf %o $(($(gen_rand) % 91 + 32)))\n") 1385986b458dSShawn Emery p="$p$c" 1386bd211b85Ssemery ((i+=1)) 1387bd211b85Ssemery done 1388bd211b85Ssemery 1389bd211b85Ssemery newpw=$p 1390986b458dSShawn Emery if [[ ${#newpw} -ne MAX_PASS ]]; then 1391986b458dSShawn Emery printf "$(gettext "Password created was of incorrect length").\n" >&2 1392986b458dSShawn Emery error_message 1393986b458dSShawn Emery fi 1394bd211b85Ssemery 1395bd211b85Ssemery # Set the new password 1396986b458dSShawn Emery printf "%s" "$newpw" | $KSETPW ${netbios_nodename}@${realm} > /dev/null 2>&1 1397bd211b85Ssemery if [[ $? -ne 0 ]] 1398bd211b85Ssemery then 1399c386eb9cSShawn Emery printf "$(gettext "Failed to set account password").\n" >&2 1400bd211b85Ssemery error_message 1401bd211b85Ssemery fi 1402bd211b85Ssemery 1403bd211b85Ssemery # Lookup the new principal's kvno: 1404bd211b85Ssemery ldapsearch -R -T -h "$dc" $ldap_args -b "$baseDN" \ 1405bd211b85Ssemery -s sub cn=$upcase_nodename msDS-KeyVersionNumber| \ 1406bd211b85Ssemery grep "^msDS-KeyVersionNumber"|read j kvno 1407bd211b85Ssemery [[ -z $kvno ]] && kvno=1 1408bd211b85Ssemery 1409bd211b85Ssemery # Set supported enctypes. This only works for Longhorn/Vista, so we 1410bd211b85Ssemery # ignore errors here. 1411bd211b85Ssemery userAccountControl=$((userAccountControlBASE + 524288 + 65536)) 1412bd211b85Ssemery set -A enctypes -- 1413bd211b85Ssemery 1414bd211b85Ssemery # Do we have local support for AES? 1415bd211b85Ssemery encrypt -l|grep ^aes|read j minkeysize maxkeysize 1416bd211b85Ssemery val= 1417bd211b85Ssemery if [[ $maxkeysize -eq 256 ]]; then 1418bd211b85Ssemery val=16 1419bd211b85Ssemery enctypes[${#enctypes[@]}]=aes256-cts-hmac-sha1-96 1420bd211b85Ssemery fi 1421bd211b85Ssemery if [[ $minkeysize -eq 128 ]]; then 1422bd211b85Ssemery ((val=val+8)) 1423bd211b85Ssemery enctypes[${#enctypes[@]}]=aes128-cts-hmac-sha1-96 1424bd211b85Ssemery fi 1425bd211b85Ssemery 1426bd211b85Ssemery # RC4 comes next (whether it's better than 1DES or not -- AD prefers it) 1427*f7dbdfc7SMarcel Telka if encrypt -l|grep -q ^arcfour 1428bd211b85Ssemery then 1429bd211b85Ssemery ((val=val+4)) 1430bd211b85Ssemery enctypes[${#enctypes[@]}]=arcfour-hmac-md5 1431bd211b85Ssemery else 1432bd211b85Ssemery # Use 1DES ONLY if we don't have arcfour 1433bd211b85Ssemery userAccountControl=$((userAccountControl + 2097152)) 1434bd211b85Ssemery fi 1435*f7dbdfc7SMarcel Telka if encrypt -l | grep -q ^des 1436bd211b85Ssemery then 1437c386eb9cSShawn Emery ((val=val+2)) 1438bd211b85Ssemery enctypes[${#enctypes[@]}]=des-cbc-md5 1439bd211b85Ssemery fi 1440bd211b85Ssemery 1441bd211b85Ssemery if [[ ${#enctypes[@]} -eq 0 ]] 1442bd211b85Ssemery then 1443bd211b85Ssemery printf "$(gettext "No enctypes are supported").\n" 1444c386eb9cSShawn Emery printf "$(gettext "Please enable arcfour or 1DES, then re-join; see cryptoadm(1M)").\n" >&2 1445bd211b85Ssemery error_message 1446bd211b85Ssemery fi 1447bd211b85Ssemery 1448bd211b85Ssemery # If domain crontroller is Longhorn or above then set new supported 1449bd211b85Ssemery # encryption type attributes. 1450bd211b85Ssemery if [[ $level -gt 2 ]]; then 1451bd211b85Ssemery cat > "$object" <<EOF 145272f0806aSShawn Emerydn: $dn 1453bd211b85Ssemerychangetype: modify 1454bd211b85Ssemeryreplace: msDS-SupportedEncryptionTypes 1455bd211b85SsemerymsDS-SupportedEncryptionTypes: $val 1456bd211b85SsemeryEOF 1457bd211b85Ssemery ldapmodify -h "$dc" $ldap_args -f "$object" >/dev/null 2>&1 1458bd211b85Ssemery if [[ $? -ne 0 ]]; then 1459bd211b85Ssemery printf "$(gettext "Warning: Could not set the supported encryption type for computer account").\n" 1460bd211b85Ssemery fi 1461bd211b85Ssemery fi 1462bd211b85Ssemery 1463bd211b85Ssemery # We should probably check whether arcfour is available, and if not, 1464bd211b85Ssemery # then set the 1DES only flag, but whatever, it's not likely NOT to be 1465bd211b85Ssemery # available on S10/Nevada! 1466bd211b85Ssemery 1467bd211b85Ssemery # Reset userAccountControl 1468bd211b85Ssemery # 1469bd211b85Ssemery # NORMAL_ACCOUNT (512) | DONT_EXPIRE_PASSWORD (65536) | 1470bd211b85Ssemery # TRUSTED_FOR_DELEGATION (524288) 1471bd211b85Ssemery # 1472bd211b85Ssemery # and possibly UseDesOnly (2097152) (see above) 1473bd211b85Ssemery # 1474bd211b85Ssemery cat > "$object" <<EOF 147572f0806aSShawn Emerydn: $dn 1476bd211b85Ssemerychangetype: modify 1477bd211b85Ssemeryreplace: userAccountControl 1478bd211b85SsemeryuserAccountControl: $userAccountControl 1479bd211b85SsemeryEOF 1480bd211b85Ssemery ldapmodify -h "$dc" $ldap_args -f "$object" >/dev/null 2>&1 1481bd211b85Ssemery if [[ $? -ne 0 ]]; then 1482c386eb9cSShawn Emery printf "$(gettext "ldapmodify failed to modify account attribute").\n" >&2 1483bd211b85Ssemery error_message 1484bd211b85Ssemery fi 1485bd211b85Ssemery 1486bd211b85Ssemery # Setup a keytab file 1487bd211b85Ssemery set -A args -- 1488bd211b85Ssemery for enctype in "${enctypes[@]}" 1489bd211b85Ssemery do 1490bd211b85Ssemery args[${#args[@]}]=-e 1491bd211b85Ssemery args[${#args[@]}]=$enctype 1492bd211b85Ssemery done 1493bd211b85Ssemery 1494bd211b85Ssemery rm $new_keytab > /dev/null 2>&1 1495bd211b85Ssemery 1496bd211b85Ssemery cat > "$object" <<EOF 149772f0806aSShawn Emerydn: $dn 1498bd211b85Ssemerychangetype: modify 1499bd211b85Ssemeryadd: servicePrincipalName 1500bd211b85SsemeryservicePrincipalName: nfs/${fqdn} 1501bd211b85SsemeryservicePrincipalName: HTTP/${fqdn} 1502bd211b85SsemeryservicePrincipalName: root/${fqdn} 1503c386eb9cSShawn EmeryservicePrincipalName: cifs/${fqdn} 150472f0806aSShawn EmeryservicePrincipalName: host/${upcase_nodename} 1505bd211b85SsemeryEOF 1506bd211b85Ssemery ldapmodify -h "$dc" $ldap_args -f "$object" >/dev/null 2>&1 1507bd211b85Ssemery if [[ $? -ne 0 ]]; then 1508c386eb9cSShawn Emery printf "$(gettext "ldapmodify failed to modify account attribute").\n" >&2 1509bd211b85Ssemery error_message 1510bd211b85Ssemery fi 1511bd211b85Ssemery 1512c386eb9cSShawn Emery # 1513c386eb9cSShawn Emery # In Windows, unlike MIT based implementations we salt the keys with 151472f0806aSShawn Emery # the UPN, which is based on the host/string15@realm elements, not 151572f0806aSShawn Emery # with the individual SPN strings. 1516c386eb9cSShawn Emery # 151772f0806aSShawn Emery salt=host/${locase_nodename}.${domain}@${realm} 1518c386eb9cSShawn Emery 1519e1831dbbSShawn Emery skeys=(host/${fqdn}@${realm} nfs/${fqdn}@${realm} HTTP/${fqdn}@${realm}) 1520e1831dbbSShawn Emery skeys+=(root/${fqdn}@${realm} cifs/${fqdn}@${realm}) 1521e1831dbbSShawn Emery skeys+=(${netbios_nodename}@${realm} host/${upcase_nodename}@${realm}) 1522e1831dbbSShawn Emery skeys+=(cifs/${upcase_nodename}@${realm}) 1523c386eb9cSShawn Emery 1524e1831dbbSShawn Emery ks_args="-n -s $salt -v $kvno -k $new_keytab ${args[@]}" 1525bd211b85Ssemery 1526e1831dbbSShawn Emery for skey in ${skeys[@]} 1527e1831dbbSShawn Emery do 1528e1831dbbSShawn Emery printf "%s" "$newpw" | $KSETPW $ks_args $skey > /dev/null 2>&1 1529bd211b85Ssemery if [[ $? -ne 0 ]] 1530bd211b85Ssemery then 1531e1831dbbSShawn Emery printf "$(gettext "Failed to set password").\n" >&2 1532bd211b85Ssemery error_message 1533bd211b85Ssemery fi 1534e1831dbbSShawn Emery done 153572f0806aSShawn Emery 1536bd211b85Ssemery doKRB5config 1537bd211b85Ssemery 1538bd211b85Ssemery addDNSRR $dom 1539bd211b85Ssemery 1540bd211b85Ssemery setSMB $dom $dc 1541bd211b85Ssemery 154272f0806aSShawn Emery printf -- "---------------------------------------------------\n" 1543bd211b85Ssemery printf "$(gettext "Setup COMPLETE").\n\n" 1544bd211b85Ssemery 1545bd211b85Ssemery kdestroy -q 1>$TMP_FILE 2>&1 1546bd211b85Ssemery rm -f $TMP_FILE 1547bd211b85Ssemery rm -rf $TMPDIR > /dev/null 2>&1 1548bd211b85Ssemery 1549bd211b85Ssemery exit 0 15507c478bd9Sstevel@tonic-gate} 15517c478bd9Sstevel@tonic-gate 15527c478bd9Sstevel@tonic-gate########################### 15537c478bd9Sstevel@tonic-gate# Main section # 15547c478bd9Sstevel@tonic-gate########################### 15557c478bd9Sstevel@tonic-gate# 15567c478bd9Sstevel@tonic-gate# Set the Kerberos config file and some default strings/files 15577c478bd9Sstevel@tonic-gate# 1558bd211b85SsemeryKRB5_CONFIG_FILE=/etc/krb5/krb5.conf 1559bd211b85SsemeryKRB5_KEYTAB_FILE=/etc/krb5/krb5.keytab 1560bd211b85SsemeryRESOLV_CONF_FILE=/etc/resolv.conf 1561bd211b85Ssemery 1562bd211b85SsemeryKLOOKUP=/usr/lib/krb5/klookup; check_bin $KLOOKUP 1563bd211b85SsemeryKSETPW=/usr/lib/krb5/ksetpw; check_bin $KSETPW 1564bd211b85SsemeryKSMB=/usr/lib/krb5/ksmb; check_bin $KSMB 1565bd211b85SsemeryKDYNDNS=/usr/lib/krb5/kdyndns; check_bin $KDYNDNS 1566c48f4690SShawn EmeryKCONF=/usr/lib/krb5/kconf; check_bin $KCONF 1567bd211b85Ssemery 1568bd211b85Ssemerydns_lookup=no 1569bd211b85Ssemeryask_fqdns=no 1570bd211b85Ssemeryadddns=no 1571ae5b046dSsemeryno_keytab=no 15727c478bd9Sstevel@tonic-gatecheckval="" 15737c478bd9Sstevel@tonic-gateprofile="" 1574bd211b85Ssemerytypeset -u realm 1575bd211b85Ssemerytypeset -l hostname KDC 15767c478bd9Sstevel@tonic-gate 1577bd211b85Ssemeryexport TMPDIR="/var/run/kclient" 15787c478bd9Sstevel@tonic-gate 1579bd211b85Ssemerymkdir $TMPDIR > /dev/null 2>&1 1580c386eb9cSShawn Emeryif [[ $? -ne 0 ]]; then 1581c386eb9cSShawn Emery printf "\n$(gettext "Can not create directory: %s")\n\n" $TMPDIR >&2 1582c386eb9cSShawn Emery exit 1 1583c386eb9cSShawn Emeryfi 15847c478bd9Sstevel@tonic-gate 1585bd211b85SsemeryTMP_FILE=$(mktemp -q -t kclient-tmpfile.XXXXXX) 1586bd211b85Ssemeryexport KRB5_CONFIG=$(mktemp -q -t kclient-krb5conf.XXXXXX) 1587ae5b046dSsemeryexport KRB5CCNAME=$(mktemp -q -t kclient-krb5ccache.XXXXXX) 1588bd211b85Ssemerynew_keytab=$(mktemp -q -t kclient-krb5keytab.XXXXXX) 1589bd211b85Ssemeryif [[ -z $TMP_FILE || -z $KRB5_CONFIG || -z $KRB5CCNAME || -z $new_keytab ]] 1590bd211b85Ssemerythen 1591c386eb9cSShawn Emery printf "\n$(gettext "Can not create temporary files, exiting").\n\n" >&2 1592c386eb9cSShawn Emery exit 1 15937c478bd9Sstevel@tonic-gatefi 15947c478bd9Sstevel@tonic-gate 15957c478bd9Sstevel@tonic-gate# 15967c478bd9Sstevel@tonic-gate# If we are interrupted, cleanup after ourselves 15977c478bd9Sstevel@tonic-gate# 1598bd211b85Ssemerytrap "exiting 1" HUP INT QUIT TERM 15997c478bd9Sstevel@tonic-gate 1600bd211b85Ssemeryif [[ -d /usr/bin ]]; then 1601bd211b85Ssemery if [[ -d /usr/sbin ]]; then 16027c478bd9Sstevel@tonic-gate PATH=/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:$PATH 16037c478bd9Sstevel@tonic-gate export PATH 16047c478bd9Sstevel@tonic-gate else 16057c478bd9Sstevel@tonic-gate printf "\n$(gettext "Directory /usr/sbin not found, exiting").\n" >&2 16067c478bd9Sstevel@tonic-gate exit 1 16077c478bd9Sstevel@tonic-gate fi 16087c478bd9Sstevel@tonic-gateelse 16097c478bd9Sstevel@tonic-gate printf "\n$(gettext "Directory /usr/bin not found, exiting").\n" >&2 16107c478bd9Sstevel@tonic-gate exit 1 16117c478bd9Sstevel@tonic-gatefi 16127c478bd9Sstevel@tonic-gate 16137c478bd9Sstevel@tonic-gateprintf "\n$(gettext "Starting client setup")\n\n" 1614bd211b85Ssemeryprintf -- "---------------------------------------------------\n" 16157c478bd9Sstevel@tonic-gate 16167c478bd9Sstevel@tonic-gate# 16177c478bd9Sstevel@tonic-gate# Check for uid 0, disallow otherwise 16187c478bd9Sstevel@tonic-gate# 16197c478bd9Sstevel@tonic-gateid 1>$TMP_FILE 2>&1 1620bd211b85Ssemeryif [[ $? -eq 0 ]]; then 16217c478bd9Sstevel@tonic-gate if egrep -s "uid=0\(root\)" $TMP_FILE; then 16227c478bd9Sstevel@tonic-gate # uid is 0, go ahead ... 16237c478bd9Sstevel@tonic-gate : 16247c478bd9Sstevel@tonic-gate else 1625bd211b85Ssemery printf "\n$(gettext "Administrative privileges are required to run this script, exiting").\n" >&2 16267c478bd9Sstevel@tonic-gate error_message 16277c478bd9Sstevel@tonic-gate fi 16287c478bd9Sstevel@tonic-gateelse 16297c478bd9Sstevel@tonic-gate cat $TMP_FILE; 1630bd211b85Ssemery printf "\n$(gettext "uid check failed, exiting").\n" >&2 16317c478bd9Sstevel@tonic-gate error_message 16327c478bd9Sstevel@tonic-gatefi 16337c478bd9Sstevel@tonic-gate 1634bd211b85Ssemeryuname=$(uname -n) 1635bd211b85Ssemeryhostname=${uname%%.*} 16367c478bd9Sstevel@tonic-gate 16377c478bd9Sstevel@tonic-gate# 16387c478bd9Sstevel@tonic-gate# Process the command-line arguments (if any) 16397c478bd9Sstevel@tonic-gate# 16407c478bd9Sstevel@tonic-gateOPTIND=1 1641bd211b85Ssemerywhile getopts nD:Kp:R:k:a:c:d:f:h:m:s:T: OPTIONS 16427c478bd9Sstevel@tonic-gatedo 16437c478bd9Sstevel@tonic-gate case $OPTIONS in 1644bd211b85Ssemery D) options="$options -D" 1645bd211b85Ssemery domain_list="$OPTARG" 1646bd211b85Ssemery ;; 1647bd211b85Ssemery K) options="$options -K" 1648bd211b85Ssemery no_keytab=yes 16497c478bd9Sstevel@tonic-gate ;; 16507c478bd9Sstevel@tonic-gate R) options="$options -R" 1651bd211b85Ssemery realm="$OPTARG" 1652bd211b85Ssemery checkval="REALM"; check_value $realm 16537c478bd9Sstevel@tonic-gate ;; 1654bd211b85Ssemery T) options="$options -T" 1655bd211b85Ssemery type="$OPTARG" 1656bd211b85Ssemery if [[ $type == ms_ad ]]; then 1657bd211b85Ssemery msad=yes 1658bd211b85Ssemery adddns=yes 1659bd211b85Ssemery else 1660bd211b85Ssemery non_solaris=yes 1661bd211b85Ssemery no_keytab=yes 1662bd211b85Ssemery fi 16637c478bd9Sstevel@tonic-gate ;; 16647c478bd9Sstevel@tonic-gate a) options="$options -a" 16657c478bd9Sstevel@tonic-gate ADMIN_PRINC="$OPTARG" 16667c478bd9Sstevel@tonic-gate checkval="ADMIN_PRINC"; check_value $ADMIN_PRINC 16677c478bd9Sstevel@tonic-gate ;; 16687c478bd9Sstevel@tonic-gate c) options="$options -c" 16697c478bd9Sstevel@tonic-gate filepath="$OPTARG" 16707c478bd9Sstevel@tonic-gate ;; 16717c478bd9Sstevel@tonic-gate d) options="$options -d" 16727c478bd9Sstevel@tonic-gate dnsarg="$OPTARG" 16737c478bd9Sstevel@tonic-gate checkval="DNS_OPTIONS"; check_value $dnsarg 16747c478bd9Sstevel@tonic-gate ;; 16757c478bd9Sstevel@tonic-gate f) options="$options -f" 16767c478bd9Sstevel@tonic-gate fqdnlist="$OPTARG" 1677bd211b85Ssemery ;; 1678bd211b85Ssemery h) options="$options -h" 1679bd211b85Ssemery logical_hn="$OPTARG" 1680bd211b85Ssemery checkval="LOGICAL_HOSTNAME"; check_value $logical_hn 1681bd211b85Ssemery ;; 1682bd211b85Ssemery k) options="$options -k" 1683bd211b85Ssemery kdc_list="$OPTARG" 1684bd211b85Ssemery ;; 1685bd211b85Ssemery m) options="$options -m" 1686bd211b85Ssemery KDC="$OPTARG" 1687bd211b85Ssemery checkval="KDC"; check_value $KDC 16887c478bd9Sstevel@tonic-gate ;; 16897c478bd9Sstevel@tonic-gate n) options="$options -n" 16907c478bd9Sstevel@tonic-gate add_nfs=yes 16917c478bd9Sstevel@tonic-gate ;; 1692bd211b85Ssemery p) options="$options -p" 1693bd211b85Ssemery profile="$OPTARG" 1694bd211b85Ssemery read_profile $profile 1695bd211b85Ssemery ;; 1696bd211b85Ssemery s) options="$options -s" 1697bd211b85Ssemery svc_list="$OPTARG" 1698bd211b85Ssemery SVCs=${svc_list//,/ } 1699bd211b85Ssemery ;; 17007c478bd9Sstevel@tonic-gate \?) usage 17017c478bd9Sstevel@tonic-gate ;; 17027c478bd9Sstevel@tonic-gate *) usage 17037c478bd9Sstevel@tonic-gate ;; 17047c478bd9Sstevel@tonic-gate esac 17057c478bd9Sstevel@tonic-gatedone 17067c478bd9Sstevel@tonic-gate 17077c478bd9Sstevel@tonic-gate#correct argument count after options 17087c478bd9Sstevel@tonic-gateshift `expr $OPTIND - 1` 17097c478bd9Sstevel@tonic-gate 1710bd211b85Ssemeryif [[ -z $options ]]; then 17117c478bd9Sstevel@tonic-gate : 17127c478bd9Sstevel@tonic-gateelse 1713bd211b85Ssemery if [[ $# -ne 0 ]]; then 17147c478bd9Sstevel@tonic-gate usage 17157c478bd9Sstevel@tonic-gate fi 17167c478bd9Sstevel@tonic-gatefi 17177c478bd9Sstevel@tonic-gate 1718bd211b85Ssemery# 1719ae5b046dSsemery# Check to see if we will be a client of a MIT, Heimdal, Shishi, etc. 1720ae5b046dSsemery# 1721ae5b046dSsemeryif [[ -z $options ]]; then 1722ae5b046dSsemery query "$(gettext "Is this a client of a non-Solaris KDC") ?" 1723ae5b046dSsemery non_solaris=$answer 1724ae5b046dSsemery if [[ $non_solaris == yes ]]; then 1725ae5b046dSsemery printf "$(gettext "Which type of KDC is the server"):\n" 1726ae5b046dSsemery printf "\t$(gettext "ms_ad: Microsoft Active Directory")\n" 1727ae5b046dSsemery printf "\t$(gettext "mit: MIT KDC server")\n" 1728ae5b046dSsemery printf "\t$(gettext "heimdal: Heimdal KDC server")\n" 1729ae5b046dSsemery printf "\t$(gettext "shishi: Shishi KDC server")\n" 1730ae5b046dSsemery printf "$(gettext "Enter required KDC type"): " 1731ae5b046dSsemery read kdctype 1732ae5b046dSsemery if [[ $kdctype == ms_ad ]]; then 1733ae5b046dSsemery msad=yes 1734ae5b046dSsemery elif [[ $kdctype == mit || $kdctype == heimdal || \ 1735ae5b046dSsemery $kdctype == shishi ]]; then 1736ae5b046dSsemery no_keytab=yes 1737ae5b046dSsemery else 1738ae5b046dSsemery printf "\n$(gettext "Invalid KDC type option, valid types are ms_ad, mit, heimdal, or shishi, exiting").\n" >&2 1739ae5b046dSsemery error_message 1740ae5b046dSsemery fi 1741ae5b046dSsemery fi 1742ae5b046dSsemeryfi 1743ae5b046dSsemery 1744ae5b046dSsemery[[ $msad == yes ]] && join_domain 1745ae5b046dSsemery 1746ae5b046dSsemery# 1747bd211b85Ssemery# Check for /etc/resolv.conf 1748bd211b85Ssemery# 1749bd211b85Ssemeryif [[ -r $RESOLV_CONF_FILE ]]; then 1750bd211b85Ssemery client_machine=`$KLOOKUP` 1751bd211b85Ssemery 1752bd211b85Ssemery if [[ $? -ne 0 ]]; then 1753bd211b85Ssemery if [[ $adddns == no ]]; then 1754bd211b85Ssemery printf "\n$(gettext "%s does not have a DNS record and is required for Kerberos setup")\n" $hostname >&2 1755bd211b85Ssemery error_message 1756bd211b85Ssemery fi 1757bd211b85Ssemery 1758bd211b85Ssemery else 1759bd211b85Ssemery # 1760bd211b85Ssemery # If client entry already exists then do not recreate it 1761bd211b85Ssemery # 1762bd211b85Ssemery adddns=no 1763bd211b85Ssemery 1764bd211b85Ssemery hostname=${client_machine%%.*} 1765bd211b85Ssemery domain=${client_machine#*.} 1766bd211b85Ssemery fi 1767bd211b85Ssemery 1768bd211b85Ssemery short_fqdn=${domain#*.*} 1769bd211b85Ssemery short_fqdn=$(echo $short_fqdn | grep "\.") 1770bd211b85Ssemeryelse 1771bd211b85Ssemery # 1772bd211b85Ssemery # /etc/resolv.conf not present, exit ... 1773bd211b85Ssemery # 1774bd211b85Ssemery printf "\n$(gettext "%s does not exist and is required for Kerberos setup")\n" $RESOLV_CONF_FILE >&2 1775bd211b85Ssemery printf "$(gettext "Refer to resolv.conf(4), exiting").\n" >&2 1776bd211b85Ssemery error_message 1777bd211b85Ssemeryfi 1778bd211b85Ssemery 1779ae5b046dSsemerycheck_nss_conf || printf "$(gettext "/etc/nsswitch.conf does not make use of DNS for hosts and/or ipnodes").\n" 1780bd211b85Ssemery 1781bd211b85Ssemery[[ -n $fqdnlist ]] && verify_fqdnlist "$fqdnlist" 1782bd211b85Ssemery 1783ae5b046dSsemeryif [[ -z $dnsarg && (-z $options || -z $filepath) ]]; then 17847c478bd9Sstevel@tonic-gate query "$(gettext "Do you want to use DNS for kerberos lookups") ?" 1785bd211b85Ssemery if [[ $answer == yes ]]; then 1786bd211b85Ssemery 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" 1787bd211b85Ssemery printf "\n$(gettext "Enter required DNS option"): " 17887c478bd9Sstevel@tonic-gate read dnsarg 17897c478bd9Sstevel@tonic-gate checkval="DNS_OPTIONS"; check_value $dnsarg 17907c478bd9Sstevel@tonic-gate set_dns_value $dnsarg 17917c478bd9Sstevel@tonic-gate fi 17927c478bd9Sstevel@tonic-gateelse 1793ae5b046dSsemery [[ -z $dnsarg ]] && dnsarg=none 17947c478bd9Sstevel@tonic-gate set_dns_value $dnsarg 17957c478bd9Sstevel@tonic-gatefi 17967c478bd9Sstevel@tonic-gate 1797bd211b85Ssemeryif [[ -n $kdc_list ]]; then 1798bd211b85Ssemery if [[ -z $KDC ]]; then 1799bd211b85Ssemery for kdc in $kdc_list; do 1800bd211b85Ssemery break 1801bd211b85Ssemery done 1802bd211b85Ssemery KDC="$kdc" 18037c478bd9Sstevel@tonic-gate fi 1804bd211b85Ssemeryfi 1805bd211b85Ssemery 1806ae5b046dSsemeryif [[ -z $realm ]]; then 1807bd211b85Ssemery printf "$(gettext "Enter the Kerberos realm"): " 1808bd211b85Ssemery read realm 1809bd211b85Ssemery checkval="REALM"; check_value $realm 1810bd211b85Ssemeryfi 1811ae5b046dSsemeryif [[ -z $KDC ]]; then 1812bd211b85Ssemery printf "$(gettext "Specify the master KDC hostname for the above realm"): " 18137c478bd9Sstevel@tonic-gate read KDC 18147c478bd9Sstevel@tonic-gate checkval="KDC"; check_value $KDC 18157c478bd9Sstevel@tonic-gatefi 18167c478bd9Sstevel@tonic-gate 1817bd211b85SsemeryFKDC=`$KLOOKUP $KDC` 18187c478bd9Sstevel@tonic-gate 18197c478bd9Sstevel@tonic-gate# 18207c478bd9Sstevel@tonic-gate# Ping to see if the kdc is alive ! 18217c478bd9Sstevel@tonic-gate# 1822bd211b85Ssemeryping_check $FKDC "KDC" 18237c478bd9Sstevel@tonic-gate 1824ae5b046dSsemeryif [[ -z $kdc_list && (-z $options || -z $filepath) ]]; then 1825ae5b046dSsemery query "$(gettext "Do you have any slave KDC(s)") ?" 1826ae5b046dSsemery if [[ $answer == yes ]]; then 1827ae5b046dSsemery printf "$(gettext "Enter a comma-separated list of slave KDC host names"): " 1828ae5b046dSsemery read kdc_list 1829ae5b046dSsemery fi 1830ae5b046dSsemeryfi 1831ae5b046dSsemery 1832ae5b046dSsemery[[ -n $kdc_list ]] && verify_kdcs "$kdc_list" 1833ae5b046dSsemery 1834bd211b85Ssemery# 1835bd211b85Ssemery# Check to see if we will have a dynamic presence in the realm 1836bd211b85Ssemery# 1837bd211b85Ssemeryif [[ -z $options ]]; then 1838bd211b85Ssemery query "$(gettext "Will this client need service keys") ?" 1839bd211b85Ssemery if [[ $answer == no ]]; then 1840bd211b85Ssemery no_keytab=yes 1841bd211b85Ssemery fi 1842bd211b85Ssemeryfi 1843bd211b85Ssemery 1844bd211b85Ssemery# 1845bd211b85Ssemery# Check to see if we are configuring the client to use a logical host name 1846bd211b85Ssemery# of a cluster environment 1847bd211b85Ssemery# 1848bd211b85Ssemeryif [[ -z $options ]]; then 1849bd211b85Ssemery query "$(gettext "Is this client a member of a cluster that uses a logical host name") ?" 1850bd211b85Ssemery if [[ $answer == yes ]]; then 1851bd211b85Ssemery printf "$(gettext "Specify the logical hostname of the cluster"): " 1852bd211b85Ssemery read logical_hn 1853bd211b85Ssemery checkval="LOGICAL_HOSTNAME"; check_value $logical_hn 1854bd211b85Ssemery setup_lhn 1855bd211b85Ssemery fi 1856bd211b85Ssemeryfi 1857bd211b85Ssemery 1858ae5b046dSsemeryif [[ -n $domain_list && (-z $options || -z $filepath) ]]; then 1859bd211b85Ssemery query "$(gettext "Do you have multiple domains/hosts to map to realm %s" 1860bd211b85Ssemery) ?" $realm 1861bd211b85Ssemery if [[ $answer == yes ]]; then 1862ae5b046dSsemery printf "$(gettext "Enter a comma-separated list of domain/hosts 1863bd211b85Ssemeryto map to the default realm"): " 1864bd211b85Ssemery read domain_list 1865bd211b85Ssemery fi 1866bd211b85Ssemeryfi 1867bd211b85Ssemery[[ -n domain_list ]] && domain_list=${domain_list//,/ } 18687c478bd9Sstevel@tonic-gate 18697c478bd9Sstevel@tonic-gate# 18707c478bd9Sstevel@tonic-gate# Start writing up the krb5.conf file, save the existing one 18717c478bd9Sstevel@tonic-gate# if already present 18727c478bd9Sstevel@tonic-gate# 18737c478bd9Sstevel@tonic-gatewriteup_krb5_conf 18747c478bd9Sstevel@tonic-gate 18757c478bd9Sstevel@tonic-gate# 1876bd211b85Ssemery# Is this client going to use krb-nfs? If so then we need to at least 1877bd211b85Ssemery# uncomment the krb5* sec flavors in nfssec.conf. 18787c478bd9Sstevel@tonic-gate# 1879bd211b85Ssemeryif [[ -z $options ]]; then 18807c478bd9Sstevel@tonic-gate query "$(gettext "Do you plan on doing Kerberized nfs") ?" 18817c478bd9Sstevel@tonic-gate add_nfs=$answer 18827c478bd9Sstevel@tonic-gatefi 18837c478bd9Sstevel@tonic-gate 1884bd211b85Ssemeryif [[ $add_nfs == yes ]]; then 18857c478bd9Sstevel@tonic-gate modify_nfssec_conf 18867c478bd9Sstevel@tonic-gate 18877c478bd9Sstevel@tonic-gate # 1888bd211b85Ssemery # We also want to enable gss as we now live in a SBD world 18897c478bd9Sstevel@tonic-gate # 1890bd211b85Ssemery svcadm enable svc:/network/rpc/gss:default 1891bd211b85Ssemery [[ $? -ne 0 ]] && printf "$(gettext "Warning: could not enable gss service").\n" 1892bd211b85Ssemeryfi 1893bd211b85Ssemery 1894bd211b85Ssemeryif [[ -z $options ]]; then 1895bd211b85Ssemery query "$(gettext "Do you want to update /etc/pam.conf") ?" 1896bd211b85Ssemery if [[ $answer == yes ]]; then 1897bd211b85Ssemery printf "$(gettext "Enter a list of PAM service names in the following format: service:{first|only|optional}[,..]"): " 1898bd211b85Ssemery read svc_list 1899bd211b85Ssemery SVCs=${svc_list//,/ } 1900bd211b85Ssemery fi 1901bd211b85Ssemeryfi 1902bd211b85Ssemery[[ -n $svc_list ]] && update_pam_conf 1903bd211b85Ssemery 1904bd211b85Ssemery# 1905bd211b85Ssemery# Copy over krb5.conf master copy from filepath 1906bd211b85Ssemery# 1907bd211b85Ssemeryif [[ -z $options || -z $filepath ]]; then 19087c478bd9Sstevel@tonic-gate query "$(gettext "Do you want to copy over the master krb5.conf file") ?" 1909bd211b85Ssemery if [[ $answer == yes ]]; then 1910bd211b85Ssemery printf "$(gettext "Enter the pathname of the file to be copied"): " 19117c478bd9Sstevel@tonic-gate read filepath 19127c478bd9Sstevel@tonic-gate fi 19137c478bd9Sstevel@tonic-gatefi 19147c478bd9Sstevel@tonic-gate 1915ae5b046dSsemeryif [[ -n $filepath && -r $filepath ]]; then 1916ae5b046dSsemery cp $filepath $KRB5_CONFIG 1917bd211b85Ssemery if [[ $? -eq 0 ]]; then 1918ae5b046dSsemery printf "$(gettext "Copied %s to %s").\n" $filepath $KRB5_CONFIG 19197c478bd9Sstevel@tonic-gate else 1920ae5b046dSsemery printf "$(gettext "Copy of %s failed, exiting").\n" $filepath >&2 19217c478bd9Sstevel@tonic-gate error_message 19227c478bd9Sstevel@tonic-gate fi 1923ae5b046dSsemeryelif [[ -n $filepath ]]; then 1924bd211b85Ssemery printf "\n$(gettext "%s not found, exiting").\n" $filepath >&2 19257c478bd9Sstevel@tonic-gate error_message 19267c478bd9Sstevel@tonic-gatefi 1927ae5b046dSsemery 1928ae5b046dSsemerydoKRB5config 19297c478bd9Sstevel@tonic-gate 1930bd211b85Ssemery# 1931bd211b85Ssemery# Populate any service keys needed for the client in the keytab file 1932bd211b85Ssemery# 1933ae5b046dSsemeryif [[ $no_keytab != yes ]]; then 1934ae5b046dSsemery setup_keytab 1935ae5b046dSsemeryelse 1936ae5b046dSsemery 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 1937ae5b046dSsemery printf "$(gettext "Client will also not be able to host services that use Kerberos").\n" 1938ae5b046dSsemeryfi 1939bd211b85Ssemery 1940bd211b85Ssemeryprintf -- "\n---------------------------------------------------\n" 1941bd211b85Ssemeryprintf "$(gettext "Setup COMPLETE").\n\n" 19427c478bd9Sstevel@tonic-gate 19437c478bd9Sstevel@tonic-gate# 1944bd211b85Ssemery# If we have configured the client in a cluster we need to remind the user 1945bd211b85Ssemery# to propagate the keytab and configuration files to the other members. 19467c478bd9Sstevel@tonic-gate# 1947bd211b85Ssemeryif [[ -n $logical_hn ]]; then 1948bd211b85Ssemery 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" 1949bd211b85Ssemeryfi 1950bd211b85Ssemery 1951bd211b85Ssemery# 1952bd211b85Ssemery# Cleanup. 1953bd211b85Ssemery# 1954bd211b85Ssemerykdestroy -q 1>$TMP_FILE 2>&1 19557c478bd9Sstevel@tonic-gaterm -f $TMP_FILE 1956bd211b85Ssemeryrm -rf $TMPDIR > /dev/null 2>&1 19577c478bd9Sstevel@tonic-gateexit 0 1958