#!/usr/afsws/bin/pagsh.krb # $Id: runauth,v 1.15 2009-05-18 01:58:14 eagle Exp $ # # runauth -- Runs a program with a ticket and optionally a token. # # Written by Russ Allbery # With some code by Carol Oliver # # Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2005 # Board of Trustees, Leland Stanford Jr. University # # This is a wrapper around ksrvtgt or kstart that obtains a ticket from a # local srvtab file, optionally also obtains a token, and then runs a command # as a specified user (or as root if no user is given), cleaning up the # authentication credentials afterwards. By default this script uses ksrvtgt, # so the obtained credentials are only good for five minutes. # # If -a is specified, kstart is used instead of ksrvtgt to obtain a ticket # with a longer than five minute lifetime. By default -a will get a 60 minute # ticket, but -l can be specified to get a different lifetime. # # Usage: runauth [-a] [-t] [-f ] [-p ] [-u ] # [-l ] [-r ] # Paths to programs used. At Stanford, this depends on AFS and pubsw. afslog_path=/usr/pubsw/bin/aklog kdestroy_path=/usr/pubsw/bin/kdestroy kstart_path=/usr/pubsw/bin/kstart ksrvtgt_path=/usr/pubsw/bin/ksrvtgt ps_path=/usr/bin/ps setuidgid_path=/usr/pubsw/bin/setuidgid # Read in the options, if any. srvtab='' principal='' realm='' user='' kstart=false lifetime='60' token=false options=true while $options ; do case X"$1" in X-a) kstart=true ;; X-f) shift srvtab="$1" ;; X-l) shift lifetime="$1" ;; X-p) shift name=`echo "$1" | sed 's/\..*//'` if echo "$1" | grep '\.' >/dev/null 2>&1 ; then instance=`echo "$1" | sed 's/^[^.]*\.//'` else instance='' fi ;; X-r) shift realm="$1" ;; X-t) token=true ;; X-u) shift user="$1" ;; X-*) echo "$0: Illegal option -- $1" 1>&2 exit 1 ;; *) options=false ;; esac $options && shift done # If no principal was specified, use the default one of rcmd.`hostname`. if [ -z "$name" ] ; then name='rcmd' instance=`hostname | sed 's/\..*//'` fi # Grab the rest. command="$@" if [ -z "$command" ] ; then exec 1>&2 echo 'Usage: runauth [-a] [-t] [-f ] [-p ] [-u ]' echo ' [-l ] [-r ] ' exit 1 fi # Now, do the real work. First, obtain the ticket. If we're using kstart and # the lifetime is longer than 25 hours, we need to background kstart and will # need to kill it again when the job finishes. child=false if [ x"$kstart" = xtrue ] ; then if [ -z "$srvtab" ] ; then srvtab='/etc/leland/srvtab' fi auth="$kstart_path -q -f '$srvtab' -u '$name' -i '$instance'" if [ -n "$realm" ] ; then auth="$auth -r '$realm'" else if [ x"$token" = xtrue ] ; then auth="$auth -t" fi fi if [ "$lifetime" -gt 1500 ] ; then child=true auth="$auth -K 60 &" else auth="$auth -l '$lifetime'" fi else if [ -n "$realm" -a -z "$srvtab" ] ; then srvtab='/etc/leland/srvtab' fi auth="$ksrvtgt_path '$name' '$instance'" if [ -n "$srvtab" ] ; then if [ -n "$realm" ] ; then auth="$auth '$realm' '$srvtab'" else auth="$auth '$srvtab'" fi fi fi eval $auth status=$? if [ $status != 0 ] ; then echo "$0: Error obtaining Kerberos ticket" 1>&2 exit $status fi if [ x"$child" = xtrue ] ; then sleep 1 fi # Okay, we now have a ticket. Obtain a token if we were told to. if [ x"$token" = xtrue ] ; then if [ x"$kstart" != xtrue -o -n "$realm" ] ; then if [ -z "$realm" ] ; then "$afslog_path" else # Realm needs to be lowercased. realm=`echo $realm | tr A-Z a-z` "$afslog_path" -c "$realm" fi status=$? if [ $status != 0 ] ; then echo "$0: Error obtaining AFS token" 1>&2 exit $status fi fi fi # We're authenticated; run the command. Always start from / if we're not # root, since otherwise we may be in a protected directory. if [ -z "$user" ] ; then $command else cd / "$setuidgid_path" "$user" $command fi status=$? # Succeed or fail, we now destroy our credentials. if [ x"$child" = xtrue ] ; then me="$$" process=`"$ps_path" -eo pid,ppid,comm | grep " $me " | grep kstart` if [ -n "$process" ] ; then kill -HUP `echo "$process" | sed -e 's/^ *//' -e 's/ .*//'` fi fi "$kdestroy_path" -4 > /dev/null 2>&1 # Exit with the same exit status as su or the command. exit $status # Documentation. Use a hack to hide this from the shell. Because of the # above exit line, this should never be executed. DOCS=<<__END_OF_DOCS__ =head1 NAME runauth - Runs a program with a ticket and optionally a token. =head1 SYNOPSIS B [B<-a>] [B<-t>] [B<-f> I] [B<-p> I] S<[B<-u> I]> S<[B<-l> I]> S<[B<-r> I]> I =head1 REQUIREMENTS B uses either B or B to obtain Kerberos tickets. It is designed to work with Kerberos v4, but can be easily changed to use Kerberos v5 by pointing it at B instead. For the B<-t> option, some program to obtain AFS tokens from a ticket is needed (normally B or B). For the B<-u> option, B from daemontools is used. To support long ticket lifetimes with B, a version of B that supports the standard System V B<-o> option is required. The paths to all supporting programs used are set at the beginning of this script. =head1 DESCRIPTION This is a wrapper around B or B that obtains a ticket from a local srvtab file, optionally also obtains a token, and then runs I as a specified user (or as root if no user is given with B<-u>), cleaning up the authentication credentials afterwards. By default this script uses B, so the obtained credentials are only good for five minutes. This script depends on AFS and pubsw, and uses hard-coded paths to pubsw programs so that it has no dependencies on a properly set PATH or any local software installation. The command is run inside a PAG shell to isolate its credentials from other programs running on the same system. It is suitable for use in cron jobs or programs run infrequently from .forward or the equivalent. =head1 OPTIONS =over 4 =item B<-a> Use B instead of B to obtain the ticket. By default, B uses B and therefore obtains a ticket with only a five minute lifetime. This flag causes it to use B instead and get a ticket with an hour lifetime (this can be increased with the B<-l> flag). =item B<-f> I Use I as the srvtab to authenticate to Kerberos rather than the default of F. =item B<-l> I Obtain a ticket of lifetime I (in minutes) rather than the default (with B<-a>) of one hour. This option only makes sense in combination with B<-a>. If I is longer than 25 hours, B will be run in daemon mode and killed when the command exits. =item B<-p> I Authenticate as I rather than the default of rcmd.I where I is the current host name (stripped of anything following the first period). Note that I must use Kerberos v4 syntax, namely I.I, and not Kerberos v5 syntax. =item B<-r> I Obtain tickets and tokens in the realm I rather than the default realm. =item B<-t> Obtain an AFS token as well as a ticket (by running aklog(1) after obtaining a ticket). =item B<-u> I Run the actual command as the user I rather than as root. Use of this option is recommended for any command that doesn't have to actually run as root on the local machine for additional security. If this option is given, I will be run using setuidgid(8). =back =head1 EXAMPLES This command: runauth -t -u news /news/local/archivegroups -v runs C as the user news, after obtaining tickets and tokens using the rcmd srvtab for the current machine. This command: runauth -a -l 180 -f /etc/leland/srvtab.imap -p service.imap \ /usr/local/bin/check-imap obtains a ticket for service.imap using F as the srvtab, using kstart and obtaining a ticket with a three-hour lifetime, and then runs C. =head1 FILES =over 4 =item F The default srvtab used to obtain a ticket. =back =head1 BUGS When run with a lifetime of longer than 25 hours, at least Solaris sh prints out an extraneous message when B is killed after the job completes, looking like: 193 Hangup There seems to be no way to silence this message without rewriting this script in a saner programming language. Getting tokens in an external realm with a lifetime of longer than 25 hours doesn't work, since B doesn't know how to run B with the right arguments currently. The boundary at which B is run in daemon mode is chosen for the 25 hour default ticket lifetime at Stanford and may not be appropriate for other sites. =head1 SEE ALSO aklog(1), ksrvtgt(1), k5start(1), kstart(1), setuidgid(8) B was tested with the B implementation from KTH Kerberos. B is part of daemontools, available from L. B and B are available from L. L will have the current version of this program. =head1 AUTHOR Russ Allbery , with contributions from Carol Oliver. =head1 COPYRIGHT AND LICENSE Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2005 Board of Trustees, Leland Stanford Jr. University. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. =cut __END_OF_DOCS__