Kerberos

Last modified by Sebastian Marsching on 2022/03/27 14:03

Request a Kerberos ticket on login and renew it automatically

I wrote a script for retrieving a Kerberos ticket automatically on login and renewing it periodically. This script is intended for Ubuntu 12.04 LTS, but it probably will work in other environments if the necessary tools are present. It uses kinit and kdestroy from the krb5-user package, krenew from the kstart package, xprop from the x11-utils package and zenity from the zenity package.

I run the script by registering it as a startup application in Unity, but probably it can also be started from .xinitrc or some other place, that is run after the X server has been started. If starting it from a script, you want to run it in the background, because otherwise it will block further execution.

Obviously, you have to replace the username and realm in the script with the data that applies to your environment. When the script is started, a dialog that asks you for your password (the one needed to obtain the Kerberos TGT). After obtaining the initial ticket, it will automatically renew it from time to time, so that you will not have to enter your password again.

Their is a section in the script where you can add your own commands, e.g. for mounting a Samba share, that needs a Kerberos TGT to be available.

If you are using KDE instead of an GTK-based environment (like Unity or GNOME), you might want to use kdedialog instead of zenity.

#!/bin/bash

user="myusername"
realm="MY.KERBEROS.REALM.EXAMPLE.COM"

ask_for_password() {
 # When using KDE, you might want to use kdedialog instead of zenity
 password="`zenity --password --title "Kerberos Authentication"`"
}

request_ticket() {
 # Request a renewable ticket that is valid for one day
 kinit -r 1d "$user@$realm" <<EOF
$password
EOF

}

rc=1
while [ $rc -ne 0 ] && ask_for_password; do
  request_ticket
 rc=$?
done

if [ $rc -ne 0 ]; then
 # The user cancelled the operation before a Kerberos ticket could be
 # successfully received.
 exit 1
fi

# Optional: Perform actions that depend on a Kerberos ticket being available
# (e.g. gvfs-mount)
#gvfs-mount smb://myserver.example.com/myshare
# We use this process in order to detect when the X session ends.
xprop -root -spy >/dev/null &
xprop_pid=$!

# Function for killing processes and cleaning up the Kerberos tickets
clean_up() {
 kill $xprop_pid
  kdestroy
 exit 0
}

# If this script receives a HUP, INT or TERM signal, we want to kill the
# child processes immediately.
trap clean_up HUP INT TERM

# Wait for X session to end and occasionally (every minute) try to renew
# ticket, if it is going to expire within the next 15 minutes.

run_with_default_locale() {
 LANG=C LC_ALL=C LC_CTYPE=C LC_MESSAGES=C "$@"
}

get_expiration_time_string() {
run_with_default_locale klist | \
 grep -E "^[0-9]+/[0-9]+/[0-9]+[[:space:]]+[0-9]+:[0-9]+:[0-9]+[[:space:]]+[0-9]+/[0-9]+/[0-9]+[[:space:]]+[0-9]+:[0-9]+:[0-9]+[[:space:]]+krbtgt/" | \
 grep -o -E "[0-9]+/[0-9]+/[0-9]+[[:space:]]+[0-9]+:[0-9]+:[0-9]+" | \
 tail -n 1
}

get_expiration_time() {
 local expiration_time
 expiration_time="`get_expiration_time_string`"
 if [ -n "${expiration_time}" ]; then
    run_with_default_locale date --date="${expiration_time}" +%s
 else
   echo 0
 fi
}

get_remaining_time() {
 local expiration_time now remaining_time
 expiration_time="`get_expiration_time`"
 now="`run_with_default_locale date +%s`"
 echo "$(( ${expiration_time} - ${now} ))"
}

last_renew="`date "+%s"`"
while kill -0 $xprop_pid; do
 now="`date "+%s"`"
 if [ $(( $now - $last_renew)) -ge 60 ]; then
   if [ "`get_remaining_time`" -lt 900 ]; then
      request_ticket
   fi
 fi
  sleep 1
done

# Clean up after X session has ended
clean_up