Friday, February 15, 2013

UPDATE: CONFIGURING RHEL 5 TO USE ACTIVE DIRECTORY SCRIPTED

I originally wrote about Configuring Red Hat Enterprise Linux (RHEL) 5 To Authenticate Against LDAP (Microsoft Windows Active Directory 2008 R2) Using Kerberos 5 and the general response I got was "too long" and "words ...".

So, I took that advice and I scripted the process.  It still a work in progress but it does work.

Check it out on my GitHub page.

Thanks.

Friday, September 14, 2012

LINUX MANAGING /etc/hosts WITH LDAP

Managing the /etc/hosts File Across Multiple Servers With LDAP (Microsoft Windows Active Directory 2008 R2)

 :: PURPOSE ::


Managing the /etc/hosts file across more than a handful of servers can quickly become more trouble than it’s worth.  There are many solutions that could be leveraged to manage this; like Puppet, Chef, or Cfengine.  A cron job tied to rsync could be made to work with little effort.  A SysAdmin with a lot of time on his hands who enjoys performing repetitive tasks better suited to shell scripts…

There are also many problem associated with trying to maintain identical yet separate copies of the /etc/hosts file across multiple servers.  All of the solutions listed above depend on the time between when the problem is first encountered and how soon the solution is scheduled to run.

But, if you’re like me, and you are already leveraging an LDAP (Microsoft Windows 2008 R2 Active Directory) environment for user and group information as well as Kerberos authentication, why not leverage it to provide /etc/hosts information as well?  For starters, changes to /etc/hosts entries in LDAP are available across all servers as soon as they are made (barring replication times between Domain Controllers).  A solid second reason is that LDAP-provided hosts data can serve as a fail-safe in the event that your DNS becomes unavailable.  Or, you may have a situation like mine where you want only a couple of entries in the local /etc/hosts file, then the majority of static host entries available from LDAP, and then, finally, some critical servers and services provided by DNS.  You might also be operating in an environment with less than stellar DNS management and you’d like to circumvent a problem you cannot resolve directly…not that I’ve ever heard of such a place.

A word of thanks to Kar Ellen and Karellen’s Unix Blog for providing the most clear information to this problem.  This post is almost wholly inspired by a similar one on Kar Ellen' blog; I've just adapted it to Microsoft Windows Active Directory 2008 R2.  Lots of really good information there.

I'd like to point out that sometimes we do things simply because we can.  This is one of those cases.  Do I have a driving need to provide /etc/hosts information from LDAP?  No.  But it's cool, so I did it.  Also, the Active Directory admins are fond of telling me what can and cannot be done with LDAP.  I am fond of proving them wrong.

The best thing about this is that only those individual servers that are configured to query LDAP for hosts information will be affected by this.  So you can have one or two servers running this just to try it out without impacted name resolution for the other servers in your domain. 

:: EXAMINE CURRENT /etc/hosts FILE ::


Let’s take a look at the current /etc/hosts file and see what we can work with.

As root first make a back-up of the existing /etc/hosts file:
# cp /etc/hosts /etc/hosts.backup
Now, cat the contents to see what we have:
# cat /etc/hosts
127.0.0.1       lux001.test.internal lux001 localhost.localdomain localhost
::1             localhost6.localdomain6 localhost6
10.0.0.50 dc01.test.internal dc01 # ACTIVE DIRECTORY DOMAIN CONTROLLER
10.0.0.51 dc02.test.internal dc02 # ACTIVE DIRECTORY DOMAIN CONTROLLER
10.0.0.60 lux001.test.internal lux001 # TEST.INTERNAL RHEL 5
10.0.0.61 lux002.test.internal lux002 # TEST.INTERNAL RHEL 5 HOME DIRECTORY SERVER

Comment out the entries for lux001.test.internal and lux002.test.internal and save /etc/hosts:
# vim /etc/hosts
127.0.0.1       lux001.test.internal lux001 localhost.localdomain localhost
::1             localhost6.localdomain6 localhost6
10.0.0.50 dc01.test.internal dc01 # ACTIVE DIRECTORY DOMAIN CONTROLLER
10.0.0.51 dc02.test.internal dc02 # ACTIVE DIRECTORY DOMAIN CONTROLLER
#10.0.0.60 lux001.test.internal lux001 # TEST.INTERNAL RHEL 5
#10.0.0.61 lux002.test.internal lux002 # TEST.INTERNAL RHEL 5 HOME DIRECTORY SERVER
 

:: CREATING THE LDIF FILE ::


We’re going to create the entries for lux001, lux001.test.internal, lux002, and lux002.test.internal in LDAP.  We’re also going to create a new OU called HOSTS to store these objects. 

NOTE:  You can either create an LDIF file to perform these steps or you can manually create the OU, then use ADSIEdit to create the device object and, finally, add the objectClass “ipHost” and description through the Attribute Editor tab of the new device object.  I have found that trying to add the objectClass “ipHost” while creating the initial object manually seems to fail.  I do not know why.  It does not fail when being created by LDIF. 

NOTE:  Please remove the top-most section of this LDIF file if you have manually created the OU into which you will be storing these device entries.

On your Windows Domain Controller, create a file called “hosts.ldif” and save it.
Edit the “hosts.ldif” file with Notepad and add the following (remember to change this to suit your requirements…):

dn: ou=HOSTS,ou=servers,dc=test,dc=internal
objectClass: organizationalUnit
objectClass: top
ou: HOSTS

dn: cn=lux001,ou=hosts,ou=servers,dc=test,dc=internal
ipHostNumber: 10.0.0.60
objectClass: top
objectClass: ipHost
objectClass: device
description: /ETC/HOSTS SERVER IP: 10.0.0.60
cn: lux001

dn: cn=lux001.test.internal,ou=hosts,ou=servers,dc=test,dc=internal
ipHostNumber: 10.0.0.60
objectClass: top
objectClass: ipHost
objectClass: device
description: /ETC/HOSTS SERVER IP: 10.0.0.60
cn: lux001.test.internal

dn: cn=lux002,ou=hosts,ou=servers,dc=test,dc=internal
ipHostNumber: 10.0.0.61
objectClass: top
objectClass: ipHost
objectClass: device
description: /ETC/HOSTS SERVER IP: 10.0.0.61
cn: lux002

dn: cn=lux002.test.internal,ou=hosts,ou=servers,dc=test,dc=internal
ipHostNumber: 10.0.0.61
objectClass: top
objectClass: ipHost
objectClass: device
description: /ETC/HOSTS SERVER IP: 10.0.0.61
cn: lux002.test.internal

NOTE:  If you want your HOSTS OU to be lowercase or just not all uppercase than you must change it to the appearance you want on both the “cn:” and “dn:” lines.

Process the LDIF from the Domain Controller as a user with administrator rights for the domain as follows:
<PATH TO HOST.LDIF>:\> ldifde -i -f hosts.ldif

The ldifde command is pretty good about telling you what part of the command failed; most of the time it’s a syntax error in your file.  Double-check you work, remove any objects that ldifde may have created before failing and try running the command again.

Once it’s complete, you should see a new OU called “HOSTS” and the device objects you created in it.  If not, refresh Active Directory Users and Computers (ADUC) and they will appear.  It should look something like this:


The next steps will happen on the RHEL server.

:: CONFIGURING THE /etc/ldap.conf FILE ::


First thing we’re going to do is modify our existing /etc/ldap.conf file to look towards LDAP for hosts information.
As root, create a back-up of your existing /etc/ldap.conf file:
# cp /etc/ldap.conf /etc/ldap.conf.backup

Next, find, uncomment and update the following line to match your LDAP information:
# vim /etc/ldap.conf

nss_base_hosts          ou=servers,dc=test,dc=internal?sub?objectClass=device

Save and exit the /etc/ldap.conf file.

Check to see if the nscd daemon service is running…:

# service nscd status
[root@lux001 /]# service nscd status
nscd (pid 13587) is running...


…stop the nscd service and invalidate it’ host cache:

[root@lux001 skel]# service nscd stop
Stopping nscd:                                             [  OK  ]
[root@lux001 skel]# nscd -i hosts

So long as the nscd service is running and unless it is configure to not cache host information (which it is not by default) then you will not be able to properly test LDAP host resolution.

Next, update the /etc/nsswitch.conf file to tell it use LDAP as a source of hosts information.

As root, back-up the existing /etc/nsswitch.conf file:

# cp /etc/nsswitch.conf /etc/nsswitch.conf.backup

Next, update the following line:

# vim /etc/nsswitch.conf

hosts:      files ldap

Save and exit the /etc/nsswitch.conf file. 

NOTE:  You can remove the “dns” entry if you are 100% sure that the name resolution for these servers will work as normal just using local files name resolution with /etc/hosts and LDAP.  I keep the “dns” entry in place to act as a final fall-back and for servers and services that I consider critical and dynamic.  For testing, though, to ensure that LDAP host resolution is working, remove “dns” as shown above.  Once you know that it is working with no “dns” entry in /etc/nsswitch.conf and no nscd service running; you can put “dns” back in at the end as you see fit. 

NOTE:  If you previously had Microsoft Windows DNS entries for servers you no longer wish to be represented by DNS and only by LDAP hosts device entries, then make sure you remove them and their associated pointer (PTR) records as necessary.

:: TESTING LDAP HOST NAME RESOLUTION ::


Now that we have updated /etc/hosts, /etc/nsswitch.conf, stopped the nscd daemon service, invalidated the nscd daemon hosts cache, and ensured that no DNS entry for the servers lux001, lux001.test.internal, lux002, or lux002.test.internal exist; we can test LDAP host name resolution from the RHEL server:

[root@lux001 /]# getent hosts | grep ^10.0      
10.0.0.60       lux001
10.0.0.60       lux001.test.internal
10.0.0.61       lux002
10.0.0.61       lux002.test.internal

You will notice that, unlike a traditional /etc/hosts file entry, we aren’t getting back a FQDN and a hostname per IP address line.  I consider this a minor trade-off for not having to maintain this in a /etc/hosts file across hundreds of servers.

And now a ping test against both lux001 and lux001.test.internal:

[root@lux001 /]# ping lux001 -c4
PING lux001 (10.0.0.60) 56(84) bytes of data.
64 bytes from lux001 (10.0.0.60): icmp_seq=1 ttl=62 time=1.12 ms
64 bytes from lux001 (10.0.0.60): icmp_seq=2 ttl=62 time=1.47 ms
64 bytes from lux001 (10.0.0.60): icmp_seq=3 ttl=62 time=1.38 ms
64 bytes from lux001 (10.0.0.60): icmp_seq=4 ttl=62 time=1.20 ms
--- lux001 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3000ms
rtt min/avg/max/mdev = 1.122/1.298/1.475/0.139 ms

[root@lux001 /]# ping lux001 -c 4
PING lux001.test.internal (10.0.0.60) 56(84) bytes of data.
64 bytes from lux001.test.internal (10.0.0.60): icmp_seq=1 ttl=62 time=2.01 ms
64 bytes from lux001.test.internal (10.0.0.60): icmp_seq=2 ttl=62 time=1.54 ms
64 bytes from lux001.test.internal (10.0.0.60): icmp_seq=3 ttl=62 time=1.53 ms
64 bytes from lux001.test.internal (10.0.0.60): icmp_seq=4 ttl=62 time=1.58 ms
--- lux001.test.internal ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 1.534/1.668/2.013/0.203 ms

:: FINAL STEPS ::


Now that we are certain that LDAP name resolution works you can turn the nscd service back on.
[root@lux001 /]# service nscd start
Starting nscd:                                             [  OK  ]

You can also add the “dns” option back to /etc/nsswitch.conf if you so desire:
# vim /etc/nsswitch.conf

hosts:      files ldap dns

This completes the process for managing the /etc/hosts files with LDAP (Microsoft Windows 2008 R2 Active Directory).

Thursday, September 13, 2012

RHEL 5 K5START-TICKET-RENEW.SH

The k5start-ticket-renew.sh Script

The original source for this script can found at:  https://build.opensuse.org/package/files?package=msktutil&project=home%3Adipe

The original author can be contacted at:  dipeit@gmail.com

I have modified this script for my purposes but you can find more information and functionality at the link provided above.

I've never spoken with the original author so I hope he doesn't mind my usage of his scripts.

This script should live in /etc/cron.hourly.

I've made a one change from the original; the full PATH to the Kerberos 5 binaries in RHEL was added as /usr/kerberos/bin.  I'm pretty sure that was the extent of it.

Pay attention to the authors note about adding the following to individual users' ~/.bash_profile:

export PROMPT_COMMAND="k5start -H 360"

Save this script as k5start-ticket-renew.sh (or whatever you'd like), chown it root.root, and chmod it it 755.

#! /bin/sh

# dipeit@gmail.com / 2010-09-01
# This script renews kerberos tickets for all logged on users
# that have not yet expired and removes tickets that have expired.
# It also allows a user to refresh her ticket in time by not
# auto renewing tickets that have between 8 and 1 hour to live
# durning the last 4 days of the renew_lifetime. Thus, the user
# is not prompted for a password for 3 days after logon if the
# ticket renew lifetime is 7 days (MS AD default policy)
# The user should set this env variable (6 hours):
# export PROMPT_COMMAND="k5start -H 360"
#
# Finally the scripts logs out users for who renew_lifetime is
# less than 1 hour. (FORCELOGOUT is set to "no" by default) and
# sends a warning email to all users for who renew_lifetime is less than
# 2 hours (SENDWARNING is set to "no" by default)
#
# Test cases, there are more test cases in the code below.
# kinit -l 10m -r 3d
# (ticket_lifetime = 10 minutes,  renew_lifetime = 3 days)
#
# Please put this script in /etc/cron.hourly and edit /etc/krb5.conf :
##[libdefaults]
##    ticket_lifetime = 10h
##    renew_lifetime = 7d

# Set path to Kerberos binaries for RHEL
PATH=$PATH:/usr/kerberos/bin

if [ -f /etc/krb5-ticket-renew.conf ]; then
  . /etc/krb5-ticket-renew.conf
else
  SENDWARNING="no"
  FORCELOGOUT="no"
  MAILHOST="mx"
  HOURSTOEXPIRE=48
fi
DOMAIN=`hostname -d`
CURRUSERS=`users | sed 's/ /\n/g' | sort -u`
for TCACHE in $( ls -1 /tmp/krb5cc* 2> /dev/null ); do
    OWNER=$( ls -l $TCACHE | awk '{print $3}' )
    GROUP=$( ls -l $TCACHE | awk '{print $4}' )
    NOW=$( date +%s )
    EXPIRE_TIME=$( date -d "$( klist -c $TCACHE | grep -m1 krbtgt | awk '{print $3, $4}' )" +%s )
    RENEW_TIME=$( date -d "$( klist -c $TCACHE | grep -m1 "renew until" | awk '{print $3, $4}' )" +%s )

    #logger -i -t krb5-renew owner:$OWNER tcache:$TCACHE expire:$EXPIRE_TIME renew:$RENEW_TIME current:$NOW

    # If the ticket has already expired, might as well delete it
    # testcase: kinit -l 10s
    if [ $NOW -ge $EXPIRE_TIME ]; then
        kdestroy -c $TCACHE &> /dev/null:
        logger -i -t krb5-renew "Removed expired ticket cache for $OWNER: $TCACHE"

    # log user out if we are within one hour or less of max renew_lifetime, prevent lockup
    # testcase: kinit -l 1h -r 1h
    elif [ $( expr $RENEW_TIME - $NOW ) -le 3600 ]; then
        logger -i -t krb5-renew "time to log user $OWNER out!"
        if [[ $FORCELOGOUT == "yes" ]]; then
            kill -15 $(ps -U $OWNER -o "pid=")
            logger -i -t krb5-renew "send notice to user $OWNER !"
            emailbody=`mktemp`
            mail -s "You have been logged out from '`hostname`' and all your jobs have been ended." -r root@`hostname -f` \
                     -S "smtp=$MAILHOST.$DOMAIN" $OWNER@$DOMAIN < $emailbody
            rm $emailbody
        fi

    # notify user if we are between 3 and 4 hours of max renew_lifetime to prevent forced logout
    # testcase: kinit -l 1h -r 4h
    elif [ $( expr $RENEW_TIME - $NOW ) -le 14400 ]; then
        if [ $( expr $RENEW_TIME - $NOW ) -gt 10800 ]; then
            logger -i -t krb5-renew "send warning to user $OWNER that they are pending automated logout!"
            if [[ $SENDWARNING == "yes" ]]; then
                emailbody=`mktemp`
                echo "$OWNER, please make sure to login to '`hostname`' to update your credentials."  >> $emailbody
                echo "If you can't login within 3 hours you will be logged out and your running jobs will be ended." >> $emailbody
                mail -s "Please login to '`hostname`' within the next 3 hours." -r root@`hostname -f` \
                         -S "smtp=$MAILHOST.$DOMAIN" $OWNER@$DOMAIN < $emailbody
                rm $emailbody
            fi
        fi

    else

        # standard refresh loop, tickets are not in immediate danger to expire
        for user in $CURRUSERS; do
            if [[ $user == $OWNER ]]; then
                logger -i -t krb5-renew "user $OWNER is logged on, check renewal!"
                # renew ticket if it will expire in one hour or less
                # testcase: kinit -l 1h -r 1d
                if [ $( expr $EXPIRE_TIME - $NOW ) -le 3600 ]; then
                    kinit -R -c $TCACHE
                    chown $OWNER:$GROUP $TCACHE
                    logger -i -t krb5-renew "auto renewed - 1h left - $OWNER - $TCACHE"

                # renew ticket if it will expire in 8 hours or less
                # testcase: kinit -l 8h -r 97h
                elif [ $( expr $EXPIRE_TIME - $NOW ) -le 28800 ]; then
                    # ....and if there is at least 96 hours left for renewal
                    let "SECTOEXPIRE = $HOURSTOEXPIRE * 3600"
                    if [ $( expr $RENEW_TIME - $NOW ) -ge $SECTOEXPIRE ]; then
                        kinit -R -c $TCACHE
                        chown $OWNER:$GROUP $TCACHE
                        logger -i -t krb5-renew "auto renewed < $HOURSTOEXPIRE h left: $OWNER - $TCACHE"
                    else
                        #testcase: kinit -l 8h -r 96h
                        logger -i -t krb5-renew "time for ticket refresh for $OWNER via k5start or systray app"
                    fi
                fi
            fi
        done

    fi

done


RHEL 5 MSKTUTIL_NFSV4.SH

The msktutil_nfsv4.sh Script

The original source for this script can found at:  https://build.opensuse.org/package/files?package=msktutil&project=home%3Adipe

The original author can be contacted at:  dipeit@gmail.com

I have modified this script for my purposes but you can find more information and functionality at the link provided above.

I've never spoken with the original author so I hope he doesn't mind my usage of his scripts.

Save this script as msktutil_nfsv4.sh (or whatever you'd like), chown it root.root, and chmod it it 755.

#! /bin/sh

# Creates Active Directory computer objects for kerberized NFSv4
# Modified 09.12.2012 By Aaron Wyllie
# Original source can be found at https://build.opensuse.org/package/files?package=msktutil&project=home%3Adipe
# Original author contact: dipeit@gmail.com

OU='ou=services,ou=servers'

if [ $# -ne 1 ]; then
  hostfqdn=`hostname -f`
else
  hostfqdn=$1
fi
computername=${hostfqdn%%.*}
if [ $hostfqdn == $computername ]; then
  hostfqdn=$computername.`hostname -d`
fi

if [ -e /etc/krb5.keytab ]; then
  rm /etc/krb5.keytab
fi 

# add --verbose for debugging

# CREATE ROOT servicePrincipleName (SPN) AND userPrincipleName (UPN) COMPUTER OBJECT - NOT REQUIRED FOR THIS IMPLEMENTATION - SEE ORIGINAL SOURCES ABOVE IF YOU'RE INTERESTED IN HOW IT COULD BE USED
#msktutil --dont-expire-password --no-pac --computer-name $computername-root --enctypes 0x1F -b "$OU" -k /etc/krb5.keytab -h $hostfqdn -s root/$hostfqdn --upn root/$hostfqdn  --verbose --description "TEST.INTERNAL ROOT SERVICE PRINCIPLE OBJECT - DO NOT DELETE, DISABLE, MODIFY, OR MOVE"

# CREATE NFSv4 servicePrincipleName (SPN) AND userPrincipleName (UPN) COMPUTER OBJECT
msktutil --delegation --dont-expire-password --no-pac --computer-name $computername-nfs --enctypes 0x1F -b "$OU" -k /etc/krb5.keytab -h $hostfqdn -s nfs/$hostfqdn --upn nfs/$hostfqdn  --verbose --description "TEST.INTERNAL NFSv4 SERVICE PRINCIPLE OBJECT - DO NOT DELETE, DISABLE, MODIFY, OR MOVE"

# I'm not using this
#echo -e "\nKerberized NFSv4 is activated\nDo you also want to create a ServicePricipleName HOST (aka "join the windows domain") to enable SSO, etc? Please select 'No' if you are already using another tool (like likewise or winbind) to bind this computer to Active Directory!"
#select yn in "Yes" "No"; do
#    case $yn in
#        Yes ) msktjoin; break;;
#        No ) klist -k -t -e; break;;
#    esac
#done

#echo -e "\nIf you experience problems, please delete the computer accounts in Active Directory that belong to $computername and run this tool again!\n"

echo -e "\nKerberized NFSv4 has been enabled.\n"

klist -ket

RHEL 5 MSKTUTIL_JOIN.SH

The msktutil_join.sh Script

The original source for this script can found at:  https://build.opensuse.org/package/files?package=msktutil&project=home%3Adipe

The original author can be contacted at:  dipeit@gmail.com

I have modified this script for my purposes but you can find more information and functionality at the link provided above.

I've never spoken with the original author so I hope he doesn't mind my usage of his scripts.

Save this script as msktutil_join.sh (or whatever you'd like), chown it root.root, and chmod it it 755.

#! /bin/sh

# Creates Active Directory computer object with host service principle, aka "joins AD Domain".
# Modified 09.12.2012 By Aaron Wyllie
# Original source can be found at https://build.opensuse.org/package/files?package=msktutil&project=home%3Adipe
# Original author contact: dipeit@gmail.com

OU='ou=servers'

if [ $# -ne 1 ]; then
  hostfqdn=`hostname -f`
else
  hostfqdn=$1
fi
computername=${hostfqdn%%.*}
if [ $hostfqdn == $computername ]; then
  hostfqdn=$computername.`hostname -d`
fi

# add --verbose for debugging
# host principal is needed for sso via sshd but can also be provided via samba/winbind

# CREATE HOST servicePrincipleName (SPN) AND userPrincipleName (UPN)
msktutil --delegation --dont-expire-password --no-pac --computer-name $computername --enctypes 0x1F -b "$OU" -k /etc/krb5.keytab -h $hostfqdn -s host/$hostfqdn -s host/$computername --upn host/$hostfqdn --verbose --description "TEST.INTERNAL KERBEROS RHEL 5 SERVER OBJECT - DO NOT DELETE, DISABLE, MODIFY, OR MOVE"

klist -ket

RHEL 5 KRB5-TICKET-RENEW.CONF

The krb5-ticket-renew.conf File

The original source for this script can found at:  https://build.opensuse.org/package/files?package=msktutil&project=home%3Adipe

The original author can be contacted at:  dipeit@gmail.com

This script has not been modified from it's original source.

I've never spoken with the original author so I hope he doesn't mind my usage of his scripts.

Save this script in /etc, chown it root.root, and chmod it 600.

# Config for /etc/cron.hourly/krb5-ticket-renew
# The script logs out users for who renew_lifetime is
# less than 1 hour. (FORCELOGOUT is set to "no" by default) and
# sends a warning email to all users for who renew_lifetime is less than
# 2 hours (SENDWARNING is set to "no" by default)
#
SENDWARNING="no"
FORCELOGOUT="no"
MAILHOST="mx"
HOURSTOEXPIRE=48

Wednesday, September 12, 2012

RHEL 5 K5START_LDAP

The k5start_ldap Initialization Script


For starters, the original source for this script can be found at the yp2ldap project page:  http://yp2ldap.sourceforge.net/

Beyond that, thanks go to Mark R. Bannister and his blog, Technical Prose located at:  http://technicalprose.blogspot.com/

This init script should live in /etc/rc.d/init/k5start_ldap.

The only change I've made was to set the K5START_OPTIONS to properly grab the server' proper principle from /etc/krb5.keytab.  I ran into a problem after trying to setup NFSv4 where the NFS principle was at the top of the keytab and that is what was being grabbed by this script.  Workable but it could cause problems down the road if I want to break the NFSv4 Kerberos ticket cache out and maybe add an HTTP ticket cache as well, etc., etc..  It works fine now.

#!/bin/bash
##############################################################################
# k5start_ldap:    Keeps Kerberos 5 /etc/.ldapcache ticket active
# Author:    Mark R. Bannister <cambridge@users.sourceforge.net>
#
# chkconfig: 345 20 75
# description:  Keeps Kerberos 5 /etc/.ldapcache ticket active
#
# processname: /usr/bin/k5start_ldap
# config: /etc/krb5.conf
# pidfile: /var/run/k5start_ldap.pid
##############################################################################
# k5start_ldap init script
# Copyright (c) 2011 Mark R. Bannister <cambridge@users.sourceforge.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
##############################################################################

# Sanity checks.
[ -f /etc/krb5.conf ] || exit 0
[ -x /usr/bin/k5start ] || exit 0

# Source function library.
. /etc/init.d/functions

K5START_KEYTAB=/etc/krb5.keytab
K5START_MINUTES=30
K5START_OPTIONS="-u `echo ${HOSTNAME%%.*}`\$"

# Source an auxiliary options file if we have one
# This can override K5START_KEYTAB, K5START_MINUTES and K5START_OPTIONS
# It can also set DAEMON_COREFILE_LIMIT and NICELEVEL
[ -r /etc/sysconfig/k5start_ldap ] && . /etc/sysconfig/k5start_ldap

RETVAL=0

start() {
    echo -n $"Starting k5start_ldap: "

    #
    # Use KINIT_PROG and the -t option to keep /etc/.ldapcache file always
    # readable by everyone (otherwise nss_ldap will hang if it is configured
    # to use this Kerberos ticket cache)
    #
    # Also running 'getent passwd' will serve two purposes:
    #    1. Pre-populate ticket cache with a ticket
    #        (user processes can't write to this file, so without this
    #        there will be a Kerberos ticket request every time nss_ldap
    #        needs some information from the directory)
    #    2. As a useful side-effect, nscd will be pre-populated
    #
    export KINIT_PROG="chmod 644 /etc/.ldapcache && getent passwd > /dev/null"
    daemon --pidfile /var/run/k5start_ldap.pid \
        /usr/bin/k5start -f $K5START_KEYTAB -bLtK$K5START_MINUTES \
            -p /var/run/k5start_ldap.pid -k /etc/.ldapcache \
            $K5START_OPTIONS
    RETVAL=$?
    echo
    [ $RETVAL -eq 0 ] && touch /var/lock/subsys/k5start_ldap
    return $RETVAL
}

stop() {
    echo -n $"Stopping k5start_ldap: "
    killproc -p /var/run/k5start_ldap.pid k5start
    RETVAL=$?
    [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/k5start_ldap
    echo
    return $RETVAL
}

restart() {
    stop
    start
}

# See how we were called.
case "$1" in
    start)
    start
    RETVAL=$?
    ;;
    stop)
    stop
    RETVAL=$?
    ;;
    status)
    status -p /var/run/k5start_ldap.pid k5start
    RETVAL=$?
    ;;
    restart)
    restart
    RETVAL=$?
    ;;
    try-restart | condrestart)
    [ -e /var/lock/subsys/k5start_ldap ] && restart
    RETVAL=$?
    ;;
    force-reload | reload)
        echo -n $"Refreshing k5start_ldap ticket cache: "
    killproc -p /var/run/k5start_ldap.pid k5start -ALRM
    RETVAL=$?
    echo
    ;;
    *)
    echo $"Usage: $0 {start|stop|status|restart|reload|condrestart}"
    RETVAL=1
    ;;
esac
exit $RETVAL