Blame src/clients/ksu/main.c

Packit fd8b60
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
Packit fd8b60
/*
Packit fd8b60
 * Copyright (c) 1994 by the University of Southern California
Packit fd8b60
 *
Packit fd8b60
 * EXPORT OF THIS SOFTWARE from the United States of America may
Packit fd8b60
 *     require a specific license from the United States Government.
Packit fd8b60
 *     It is the responsibility of any person or organization contemplating
Packit fd8b60
 *     export to obtain such a license before exporting.
Packit fd8b60
 *
Packit fd8b60
 * WITHIN THAT CONSTRAINT, permission to copy, modify, and distribute
Packit fd8b60
 *     this software and its documentation in source and binary forms is
Packit fd8b60
 *     hereby granted, provided that any documentation or other materials
Packit fd8b60
 *     related to such distribution or use acknowledge that the software
Packit fd8b60
 *     was developed by the University of Southern California.
Packit fd8b60
 *
Packit fd8b60
 * DISCLAIMER OF WARRANTY.  THIS SOFTWARE IS PROVIDED "AS IS".  The
Packit fd8b60
 *     University of Southern California MAKES NO REPRESENTATIONS OR
Packit fd8b60
 *     WARRANTIES, EXPRESS OR IMPLIED.  By way of example, but not
Packit fd8b60
 *     limitation, the University of Southern California MAKES NO
Packit fd8b60
 *     REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
Packit fd8b60
 *     PARTICULAR PURPOSE. The University of Southern
Packit fd8b60
 *     California shall not be held liable for any liability nor for any
Packit fd8b60
 *     direct, indirect, or consequential damages with respect to any
Packit fd8b60
 *     claim by the user or distributor of the ksu software.
Packit fd8b60
 *
Packit fd8b60
 * KSU was writen by:  Ari Medvinsky, ari@isi.edu
Packit fd8b60
 */
Packit fd8b60
Packit fd8b60
#include "ksu.h"
Packit fd8b60
#include "adm_proto.h"
Packit fd8b60
#include <sys/types.h>
Packit fd8b60
#include <sys/wait.h>
Packit fd8b60
#include <signal.h>
Packit fd8b60
#include <grp.h>
Packit fd8b60
Packit fd8b60
/* globals */
Packit fd8b60
char * prog_name;
Packit fd8b60
int auth_debug =0;
Packit fd8b60
char k5login_path[MAXPATHLEN];
Packit fd8b60
char k5users_path[MAXPATHLEN];
Packit fd8b60
char * gb_err = NULL;
Packit fd8b60
int quiet = 0;
Packit fd8b60
/***********/
Packit fd8b60
Packit fd8b60
#define KS_TEMPORARY_CACHE "MEMORY:_ksu"
Packit fd8b60
#define KS_TEMPORARY_PRINC "_ksu/_ksu@_ksu"
Packit fd8b60
#define _DEF_CSH "/bin/csh"
Packit fd8b60
static int set_env_var (char *, char *);
Packit fd8b60
static void sweep_up (krb5_context, krb5_ccache);
Packit fd8b60
static char * ontty (void);
Packit fd8b60
static krb5_error_code init_ksu_context(krb5_context *);
Packit fd8b60
static krb5_error_code set_ccname_env(krb5_context, krb5_ccache);
Packit fd8b60
static void print_status( const char *fmt, ...)
Packit fd8b60
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
Packit fd8b60
    __attribute__ ((__format__ (__printf__, 1, 2)))
Packit fd8b60
#endif
Packit fd8b60
    ;
Packit fd8b60
static krb5_error_code resolve_target_cache(krb5_context ksu_context,
Packit fd8b60
                                            krb5_principal princ,
Packit fd8b60
                                            krb5_ccache *ccache_out,
Packit fd8b60
                                            krb5_boolean *ccache_reused);
Packit fd8b60
Packit fd8b60
/* Note -e and -a options are mutually exclusive */
Packit fd8b60
/* insure the proper specification of target user as well as catching
Packit fd8b60
   ill specified arguments to commands */
Packit fd8b60
Packit fd8b60
void usage (){
Packit fd8b60
    fprintf(stderr,
Packit fd8b60
            _("Usage: %s [target user] [-n principal] [-c source cachename] "
Packit fd8b60
              "[-k] [-r time] [-p|-P] [-f|-F] [-l lifetime] [-zZ] [-q] "
Packit fd8b60
              "[-e command [args... ] ] [-a [args... ] ]\n"), prog_name);
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
/* for Ultrix and friends ... */
Packit fd8b60
#ifndef MAXHOSTNAMELEN
Packit fd8b60
#define MAXHOSTNAMELEN 64
Packit fd8b60
#endif
Packit fd8b60
Packit fd8b60
/* These are file static so sweep_up can get to them*/
Packit fd8b60
static uid_t source_uid, target_uid;
Packit fd8b60
Packit fd8b60
int
Packit fd8b60
main (argc, argv)
Packit fd8b60
    int argc;
Packit fd8b60
    char ** argv;
Packit fd8b60
{
Packit fd8b60
    int hp =0;
Packit fd8b60
    int some_rest_copy = 0;
Packit fd8b60
    int all_rest_copy = 0;
Packit fd8b60
    char *localhostname = NULL;
Packit fd8b60
    krb5_get_init_creds_opt *options = NULL;
Packit fd8b60
    int option=0;
Packit fd8b60
    int statusp=0;
Packit fd8b60
    krb5_error_code retval = 0;
Packit fd8b60
    krb5_principal client = NULL, tmp_princ = NULL;
Packit fd8b60
    krb5_ccache cc_tmp = NULL, cc_target = NULL;
Packit fd8b60
    krb5_context ksu_context;
Packit fd8b60
    char * cc_target_tag = NULL;
Packit fd8b60
    char * target_user = NULL;
Packit fd8b60
    char * source_user;
Packit fd8b60
Packit fd8b60
    krb5_ccache cc_source = NULL;
Packit fd8b60
    const char * cc_source_tag = NULL;
Packit fd8b60
    const char * cc_source_tag_tmp = NULL;
Packit fd8b60
    char * cmd = NULL, * exec_cmd = NULL;
Packit fd8b60
    int errflg = 0;
Packit fd8b60
    krb5_boolean auth_val;
Packit fd8b60
    krb5_boolean authorization_val = FALSE;
Packit fd8b60
    int path_passwd = 0;
Packit fd8b60
    int done =0,i,j;
Packit fd8b60
    uid_t ruid = getuid ();
Packit fd8b60
    struct passwd *pwd=NULL,  *target_pwd ;
Packit fd8b60
    char * shell;
Packit fd8b60
    char ** params;
Packit fd8b60
    int keep_target_cache = 0;
Packit fd8b60
    int child_pid, child_pgrp, ret_pid;
Packit fd8b60
    extern char * getpass(), *crypt();
Packit fd8b60
    int pargc;
Packit fd8b60
    char ** pargv;
Packit fd8b60
    krb5_boolean stored = FALSE, cc_reused = FALSE, given_princ = FALSE;
Packit fd8b60
    krb5_boolean zero_password;
Packit fd8b60
    krb5_boolean restrict_creds;
Packit fd8b60
    krb5_deltat lifetime, rlife;
Packit fd8b60
Packit fd8b60
    if (argc == 0)
Packit fd8b60
        exit(1);
Packit fd8b60
Packit fd8b60
    params = (char **) xcalloc (2, sizeof (char *));
Packit fd8b60
    params[1] = NULL;
Packit fd8b60
Packit fd8b60
    unsetenv ("KRB5_CONFIG");
Packit fd8b60
Packit fd8b60
    retval = init_ksu_context(&ksu_context);
Packit fd8b60
    if (retval) {
Packit fd8b60
        com_err(argv[0], retval, _("while initializing krb5"));
Packit fd8b60
        exit(1);
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    retval = krb5_get_init_creds_opt_alloc(ksu_context, &options);
Packit fd8b60
    if (retval) {
Packit fd8b60
        com_err(argv[0], retval, _("while initializing krb5"));
Packit fd8b60
        exit(1);
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    if (strrchr(argv[0], '/'))
Packit fd8b60
        argv[0] = strrchr(argv[0], '/')+1;
Packit fd8b60
    prog_name = argv[0];
Packit fd8b60
    if (strlen (prog_name) > 50) {
Packit fd8b60
        /* this many chars *after* last / ?? */
Packit fd8b60
        com_err(prog_name, 0,
Packit fd8b60
                _("program name too long - quitting to avoid triggering "
Packit fd8b60
                  "system logging bugs"));
Packit fd8b60
        exit (1);
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
Packit fd8b60
#ifndef LOG_NDELAY
Packit fd8b60
#define LOG_NDELAY 0
Packit fd8b60
#endif
Packit fd8b60
Packit fd8b60
#ifndef LOG_AUTH /* 4.2 syslog */
Packit fd8b60
    openlog(prog_name, LOG_PID|LOG_NDELAY);
Packit fd8b60
#else
Packit fd8b60
    openlog(prog_name, LOG_PID | LOG_NDELAY, LOG_AUTH);
Packit fd8b60
#endif /* 4.2 syslog */
Packit fd8b60
Packit fd8b60
Packit fd8b60
    if (( argc == 1) || (argv[1][0] == '-')){
Packit fd8b60
        target_user = xstrdup("root");
Packit fd8b60
        pargc = argc;
Packit fd8b60
        pargv = argv;
Packit fd8b60
    } else {
Packit fd8b60
        target_user = xstrdup(argv[1]);
Packit fd8b60
        pargc = argc -1;
Packit fd8b60
Packit fd8b60
        if ((pargv =(char **) calloc(pargc +1,sizeof(char *)))==NULL){
Packit fd8b60
            com_err(prog_name, errno, _("while allocating memory"));
Packit fd8b60
            exit(1);
Packit fd8b60
        }
Packit fd8b60
Packit fd8b60
        pargv[pargc] = NULL;
Packit fd8b60
        pargv[0] = argv[0];
Packit fd8b60
Packit fd8b60
        for(i =1; i< pargc; i ++){
Packit fd8b60
            pargv[i] = argv[i + 1];
Packit fd8b60
        }
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    if (krb5_seteuid (ruid)) {
Packit fd8b60
        com_err (prog_name, errno, _("while setting euid to source user"));
Packit fd8b60
        exit (1);
Packit fd8b60
    }
Packit fd8b60
    while (!done &&
Packit fd8b60
           (option = getopt(pargc, pargv,"n:c:r:a:zZDfFpPkql:e:")) != -1) {
Packit fd8b60
        switch (option) {
Packit fd8b60
        case 'r':
Packit fd8b60
            if (strlen (optarg) >= 14)
Packit fd8b60
                optarg = "bad-time";
Packit fd8b60
            retval = krb5_string_to_deltat(optarg, &rlife);
Packit fd8b60
            if (retval != 0 || rlife == 0) {
Packit fd8b60
                fprintf(stderr, _("Bad lifetime value (%s hours?)\n"), optarg);
Packit fd8b60
                errflg++;
Packit fd8b60
            }
Packit fd8b60
            krb5_get_init_creds_opt_set_renew_life(options, rlife);
Packit fd8b60
            break;
Packit fd8b60
        case 'a':
Packit fd8b60
            /* when integrating this remember to pass in pargc, pargv and
Packit fd8b60
               take care of params argument */
Packit fd8b60
            optind --;
Packit fd8b60
            if (auth_debug){printf("Before get_params optind=%d\n", optind);}
Packit fd8b60
Packit fd8b60
            if ((retval = get_params( & optind, pargc, pargv, &params))){
Packit fd8b60
                com_err(prog_name, retval, _("when gathering parameters"));
Packit fd8b60
                errflg++;
Packit fd8b60
            }
Packit fd8b60
            if(auth_debug){ printf("After get_params optind=%d\n", optind);}
Packit fd8b60
            done = 1;
Packit fd8b60
            break;
Packit fd8b60
        case 'p':
Packit fd8b60
            krb5_get_init_creds_opt_set_proxiable(options, 1);
Packit fd8b60
            break;
Packit fd8b60
        case 'P':
Packit fd8b60
            krb5_get_init_creds_opt_set_proxiable(options, 0);
Packit fd8b60
            break;
Packit fd8b60
        case 'f':
Packit fd8b60
            krb5_get_init_creds_opt_set_forwardable(options, 1);
Packit fd8b60
            break;
Packit fd8b60
        case 'F':
Packit fd8b60
            krb5_get_init_creds_opt_set_forwardable(options, 0);
Packit fd8b60
            break;
Packit fd8b60
        case 'k':
Packit fd8b60
            keep_target_cache =1;
Packit fd8b60
            break;
Packit fd8b60
        case 'q':
Packit fd8b60
            quiet =1;
Packit fd8b60
            break;
Packit fd8b60
        case 'l':
Packit fd8b60
            if (strlen (optarg) >= 14)
Packit fd8b60
                optarg = "bad-time";
Packit fd8b60
            retval = krb5_string_to_deltat(optarg, &lifetime);
Packit fd8b60
            if (retval != 0 || lifetime == 0) {
Packit fd8b60
                fprintf(stderr, _("Bad lifetime value (%s hours?)\n"), optarg);
Packit fd8b60
                errflg++;
Packit fd8b60
            }
Packit fd8b60
            krb5_get_init_creds_opt_set_tkt_life(options, lifetime);
Packit fd8b60
            break;
Packit fd8b60
        case 'n':
Packit fd8b60
            if ((retval = krb5_parse_name(ksu_context, optarg, &client))){
Packit fd8b60
                com_err(prog_name, retval, _("when parsing name %s"), optarg);
Packit fd8b60
                errflg++;
Packit fd8b60
            }
Packit fd8b60
            given_princ = TRUE;
Packit fd8b60
            break;
Packit fd8b60
#ifdef DEBUG
Packit fd8b60
        case 'D':
Packit fd8b60
            auth_debug = 1;
Packit fd8b60
            break;
Packit fd8b60
#endif
Packit fd8b60
        case 'z':
Packit fd8b60
            some_rest_copy = 1;
Packit fd8b60
            if(all_rest_copy) {
Packit fd8b60
                fprintf(stderr,
Packit fd8b60
                        _("-z option is mutually exclusive with -Z.\n"));
Packit fd8b60
                errflg++;
Packit fd8b60
            }
Packit fd8b60
            break;
Packit fd8b60
        case 'Z':
Packit fd8b60
            all_rest_copy = 1;
Packit fd8b60
            if(some_rest_copy) {
Packit fd8b60
                fprintf(stderr,
Packit fd8b60
                        _("-Z option is mutually exclusive with -z.\n"));
Packit fd8b60
                errflg++;
Packit fd8b60
            }
Packit fd8b60
            break;
Packit fd8b60
        case 'c':
Packit fd8b60
            if (cc_source_tag == NULL) {
Packit fd8b60
                cc_source_tag = xstrdup(optarg);
Packit fd8b60
                if ( strchr(cc_source_tag, ':')){
Packit fd8b60
                    cc_source_tag_tmp = strchr(cc_source_tag, ':') + 1;
Packit fd8b60
Packit fd8b60
                    if (!ks_ccache_name_is_initialized(ksu_context,
Packit fd8b60
                                                       cc_source_tag)) {
Packit fd8b60
                        com_err(prog_name, errno,
Packit fd8b60
                                _("while looking for credentials cache %s"),
Packit fd8b60
                                cc_source_tag_tmp);
Packit fd8b60
                        exit (1);
Packit fd8b60
                    }
Packit fd8b60
                }
Packit fd8b60
                else {
Packit fd8b60
                    fprintf(stderr, _("malformed credential cache name %s\n"),
Packit fd8b60
                            cc_source_tag);
Packit fd8b60
                    errflg++;
Packit fd8b60
                }
Packit fd8b60
Packit fd8b60
            } else {
Packit fd8b60
                fprintf(stderr, _("Only one -c option allowed\n"));
Packit fd8b60
                errflg++;
Packit fd8b60
            }
Packit fd8b60
            break;
Packit fd8b60
        case 'e':
Packit fd8b60
            cmd = xstrdup(optarg);
Packit fd8b60
            if(auth_debug){printf("Before get_params optind=%d\n", optind);}
Packit fd8b60
            if ((retval = get_params( & optind, pargc, pargv, &params))){
Packit fd8b60
                com_err(prog_name, retval, _("when gathering parameters"));
Packit fd8b60
                errflg++;
Packit fd8b60
            }
Packit fd8b60
            if(auth_debug){printf("After get_params optind=%d\n", optind);}
Packit fd8b60
            done = 1;
Packit fd8b60
Packit fd8b60
            if (auth_debug){
Packit fd8b60
                fprintf(stderr,"Command to be executed: %s\n", cmd);
Packit fd8b60
            }
Packit fd8b60
            break;
Packit fd8b60
        case '?':
Packit fd8b60
        default:
Packit fd8b60
            errflg++;
Packit fd8b60
            break;
Packit fd8b60
        }
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    if (errflg) {
Packit fd8b60
        usage();
Packit fd8b60
        exit(2);
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    if (optind != pargc ){
Packit fd8b60
        usage();
Packit fd8b60
        exit(2);
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    if (auth_debug){
Packit fd8b60
        for(j=1; params[j] != NULL; j++){
Packit fd8b60
            fprintf (stderr,"params[%d]= %s\n", j,params[j]);
Packit fd8b60
        }
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    /***********************************/
Packit fd8b60
    source_user = getlogin(); /*checks for the the login name in /etc/utmp*/
Packit fd8b60
Packit fd8b60
    /* verify that that the user exists and get his passwd structure */
Packit fd8b60
Packit fd8b60
    if (source_user == NULL ||(pwd = getpwnam(source_user)) == NULL ||
Packit fd8b60
        pwd->pw_uid != ruid){
Packit fd8b60
        pwd = getpwuid(ruid);
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    if (pwd == NULL) {
Packit fd8b60
        fprintf(stderr, _("ksu: who are you?\n"));
Packit fd8b60
        exit(1);
Packit fd8b60
    }
Packit fd8b60
    if (pwd->pw_uid != ruid) {
Packit fd8b60
        fprintf (stderr, _("Your uid doesn't match your passwd entry?!\n"));
Packit fd8b60
        exit (1);
Packit fd8b60
    }
Packit fd8b60
    /* Okay, now we have *some* passwd entry that matches the
Packit fd8b60
       current real uid.  */
Packit fd8b60
Packit fd8b60
    /* allocate space and copy the usernamane there */
Packit fd8b60
    source_user = xstrdup(pwd->pw_name);
Packit fd8b60
    source_uid = pwd->pw_uid;
Packit fd8b60
Packit fd8b60
    if (!strcmp(SOURCE_USER_LOGIN, target_user)){
Packit fd8b60
        target_user = xstrdup (source_user);
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    if ((target_pwd = getpwnam(target_user)) == NULL){
Packit fd8b60
        fprintf(stderr, _("ksu: unknown login %s\n"), target_user);
Packit fd8b60
        exit(1);
Packit fd8b60
    }
Packit fd8b60
    target_uid = target_pwd->pw_uid;
Packit fd8b60
Packit fd8b60
    init_auth_names(target_pwd->pw_dir);
Packit fd8b60
Packit fd8b60
    /***********************************/
Packit fd8b60
Packit fd8b60
    if (cc_source_tag == NULL){
Packit fd8b60
        cc_source_tag = krb5_cc_default_name(ksu_context);
Packit fd8b60
        cc_source_tag_tmp = strchr(cc_source_tag, ':');
Packit fd8b60
        if (cc_source_tag_tmp == 0)
Packit fd8b60
            cc_source_tag_tmp = cc_source_tag;
Packit fd8b60
        else
Packit fd8b60
            cc_source_tag_tmp++;
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    /* get a handle for the cache */
Packit fd8b60
    if ((retval = krb5_cc_resolve(ksu_context, cc_source_tag, &cc_source))){
Packit fd8b60
        com_err(prog_name, retval, _("while getting source cache"));
Packit fd8b60
        exit(1);
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    if ((retval = get_best_princ_for_target(ksu_context, source_uid,
Packit fd8b60
                                            target_uid, source_user,
Packit fd8b60
                                            target_user, cc_source,
Packit fd8b60
                                            options, cmd, localhostname,
Packit fd8b60
                                            &client, &hp))){
Packit fd8b60
        com_err(prog_name,retval, _("while selecting the best principal"));
Packit fd8b60
        exit(1);
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    /* We may be running as either source or target, depending on
Packit fd8b60
       what happened; become source.*/
Packit fd8b60
    if ( geteuid() != source_uid) {
Packit fd8b60
        if (krb5_seteuid(0) || krb5_seteuid(source_uid) ) {
Packit fd8b60
            com_err(prog_name, errno, _("while returning to source uid after "
Packit fd8b60
                                        "finding best principal"));
Packit fd8b60
            exit(1);
Packit fd8b60
        }
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    if (auth_debug){
Packit fd8b60
        if (hp){
Packit fd8b60
            fprintf(stderr,
Packit fd8b60
                    "GET_best_princ_for_target result: NOT AUTHORIZED\n");
Packit fd8b60
        }else{
Packit fd8b60
            fprintf(stderr,
Packit fd8b60
                    "GET_best_princ_for_target result-best principal ");
Packit fd8b60
            plain_dump_principal (ksu_context, client);
Packit fd8b60
            fprintf(stderr,"\n");
Packit fd8b60
        }
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    if (hp){
Packit fd8b60
        if (gb_err) fprintf(stderr, "%s", gb_err);
Packit fd8b60
        fprintf(stderr, _("account %s: authorization failed\n"), target_user);
Packit fd8b60
Packit fd8b60
        if (cmd != NULL) {
Packit fd8b60
            syslog(LOG_WARNING,
Packit fd8b60
                   "Account %s: authorization for %s for execution of %s failed",
Packit fd8b60
                   target_user, source_user, cmd);
Packit fd8b60
        } else {
Packit fd8b60
            syslog(LOG_WARNING, "Account %s: authorization of %s failed",
Packit fd8b60
                   target_user, source_user);
Packit fd8b60
        }
Packit fd8b60
Packit fd8b60
        exit(1);
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    if (auth_debug)
Packit fd8b60
        fprintf(stderr, " source cache =  %s\n", cc_source_tag);
Packit fd8b60
Packit fd8b60
    /*
Packit fd8b60
     * After proper authentication and authorization, populate a cache for the
Packit fd8b60
     * target user.
Packit fd8b60
     */
Packit fd8b60
Packit fd8b60
    /*
Packit fd8b60
     * We read the set of creds we want to copy from the source ccache as the
Packit fd8b60
     * source uid, become root for authentication, and then become the target
Packit fd8b60
     * user to handle authorization and creating the target user's cache.
Packit fd8b60
     */
Packit fd8b60
Packit fd8b60
    /* if root ksu's to a regular user, then
Packit fd8b60
       then only the credentials for that particular user
Packit fd8b60
       should be copied */
Packit fd8b60
Packit fd8b60
    restrict_creds = (source_uid == 0) && (target_uid != 0);
Packit fd8b60
    retval = krb5_parse_name(ksu_context, KS_TEMPORARY_PRINC, &tmp_princ);
Packit fd8b60
    if (retval) {
Packit fd8b60
        com_err(prog_name, retval, _("while parsing temporary name"));
Packit fd8b60
        exit(1);
Packit fd8b60
    }
Packit fd8b60
    retval = krb5_cc_resolve(ksu_context, KS_TEMPORARY_CACHE, &cc_tmp);
Packit fd8b60
    if (retval) {
Packit fd8b60
        com_err(prog_name, retval, _("while creating temporary cache"));
Packit fd8b60
        exit(1);
Packit fd8b60
    }
Packit fd8b60
    retval = krb5_ccache_copy(ksu_context, cc_source, tmp_princ, cc_tmp,
Packit fd8b60
                              restrict_creds, client, &stored);
Packit fd8b60
    if (retval) {
Packit fd8b60
        com_err(prog_name, retval, _("while copying cache %s to %s"),
Packit fd8b60
                krb5_cc_get_name(ksu_context, cc_source), KS_TEMPORARY_CACHE);
Packit fd8b60
        exit(1);
Packit fd8b60
    }
Packit fd8b60
    krb5_cc_close(ksu_context, cc_source);
Packit fd8b60
Packit fd8b60
    krb5_get_init_creds_opt_set_out_ccache(ksu_context, options, cc_tmp);
Packit fd8b60
Packit fd8b60
    /* Become root for authentication*/
Packit fd8b60
Packit fd8b60
    if (krb5_seteuid(0)) {
Packit fd8b60
        com_err(prog_name, errno, _("while reclaiming root uid"));
Packit fd8b60
        exit(1);
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    if ((source_uid == 0) || (target_uid == source_uid)){
Packit fd8b60
#ifdef GET_TGT_VIA_PASSWD
Packit fd8b60
        if (!all_rest_copy && given_princ && client != NULL && !stored) {
Packit fd8b60
            fprintf(stderr, _("WARNING: Your password may be exposed if you "
Packit fd8b60
                              "enter it here and are logged\n"));
Packit fd8b60
            fprintf(stderr, _("         in remotely using an unsecure "
Packit fd8b60
                              "(non-encrypted) channel.\n"));
Packit fd8b60
            if (ksu_get_tgt_via_passwd(ksu_context, client, options,
Packit fd8b60
                                       &zero_password, NULL) == FALSE) {
Packit fd8b60
Packit fd8b60
                if (zero_password == FALSE){
Packit fd8b60
                    fprintf(stderr, _("Goodbye\n"));
Packit fd8b60
                    exit(1);
Packit fd8b60
                }
Packit fd8b60
Packit fd8b60
                fprintf(stderr, _("Could not get a tgt for "));
Packit fd8b60
                plain_dump_principal (ksu_context, client);
Packit fd8b60
                fprintf(stderr, "\n");
Packit fd8b60
Packit fd8b60
            }
Packit fd8b60
            stored = TRUE;
Packit fd8b60
        }
Packit fd8b60
#endif /* GET_TGT_VIA_PASSWD */
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    /* if the user is root or same uid then authentication is not neccesary,
Packit fd8b60
       root gets in automatically */
Packit fd8b60
Packit fd8b60
    if (source_uid && (source_uid != target_uid)) {
Packit fd8b60
        char * client_name;
Packit fd8b60
Packit fd8b60
        auth_val = krb5_auth_check(ksu_context, client, localhostname,
Packit fd8b60
                                   options, target_user, cc_tmp,
Packit fd8b60
                                   &path_passwd, target_uid);
Packit fd8b60
Packit fd8b60
        /* if Kerberos authentication failed then exit */
Packit fd8b60
        if (auth_val ==FALSE){
Packit fd8b60
            fprintf(stderr, _("Authentication failed.\n"));
Packit fd8b60
            syslog(LOG_WARNING, "'%s %s' authentication failed for %s%s",
Packit fd8b60
                   prog_name,target_user,source_user,ontty());
Packit fd8b60
            exit(1);
Packit fd8b60
        }
Packit fd8b60
        stored = TRUE;
Packit fd8b60
Packit fd8b60
        if ((retval = krb5_unparse_name(ksu_context, client, &client_name))) {
Packit fd8b60
            com_err(prog_name, retval, _("When unparsing name"));
Packit fd8b60
            exit(1);
Packit fd8b60
        }
Packit fd8b60
Packit fd8b60
        print_status(_("Authenticated %s\n"), client_name);
Packit fd8b60
        syslog(LOG_NOTICE,"'%s %s' authenticated %s for %s%s",
Packit fd8b60
               prog_name,target_user,client_name,
Packit fd8b60
               source_user,ontty());
Packit fd8b60
Packit fd8b60
        /* Run authorization as target.*/
Packit fd8b60
        if (krb5_seteuid(target_uid)) {
Packit fd8b60
            com_err(prog_name, errno, _("while switching to target for "
Packit fd8b60
                                        "authorization check"));
Packit fd8b60
            exit(1);
Packit fd8b60
        }
Packit fd8b60
Packit fd8b60
        if ((retval = krb5_authorization(ksu_context, client,target_user,
Packit fd8b60
                                         cmd, &authorization_val, &exec_cmd))){
Packit fd8b60
            com_err(prog_name,retval, _("while checking authorization"));
Packit fd8b60
            krb5_seteuid(0); /*So we have some chance of sweeping up*/
Packit fd8b60
            exit(1);
Packit fd8b60
        }
Packit fd8b60
Packit fd8b60
        if (krb5_seteuid(0)) {
Packit fd8b60
            com_err(prog_name, errno, _("while switching back from target "
Packit fd8b60
                                        "after authorization check"));
Packit fd8b60
            exit(1);
Packit fd8b60
        }
Packit fd8b60
        if (authorization_val == TRUE){
Packit fd8b60
Packit fd8b60
            if (cmd) {
Packit fd8b60
                print_status(_("Account %s: authorization for %s for "
Packit fd8b60
                               "execution of\n"), target_user, client_name);
Packit fd8b60
                print_status(_("               %s successful\n"), exec_cmd);
Packit fd8b60
                syslog(LOG_NOTICE,
Packit fd8b60
                       "Account %s: authorization for %s for execution of %s successful",
Packit fd8b60
                       target_user, client_name, exec_cmd);
Packit fd8b60
Packit fd8b60
            }else{
Packit fd8b60
                print_status(_("Account %s: authorization for %s "
Packit fd8b60
                               "successful\n"), target_user, client_name);
Packit fd8b60
                syslog(LOG_NOTICE,
Packit fd8b60
                       "Account %s: authorization for %s successful",
Packit fd8b60
                       target_user, client_name);
Packit fd8b60
            }
Packit fd8b60
        }else {
Packit fd8b60
            if (cmd){
Packit fd8b60
                if (exec_cmd){ /* was used to pass back the error msg */
Packit fd8b60
                    fprintf(stderr, "%s", exec_cmd );
Packit fd8b60
                    syslog(LOG_WARNING, "%s",exec_cmd);
Packit fd8b60
                }
Packit fd8b60
                fprintf(stderr, _("Account %s: authorization for %s for "
Packit fd8b60
                                  "execution of %s failed\n"),
Packit fd8b60
                        target_user, client_name, cmd );
Packit fd8b60
                syslog(LOG_WARNING,
Packit fd8b60
                       "Account %s: authorization for %s for execution of %s failed",
Packit fd8b60
                       target_user, client_name, cmd );
Packit fd8b60
Packit fd8b60
            }else{
Packit fd8b60
                fprintf(stderr, _("Account %s: authorization of %s failed\n"),
Packit fd8b60
                        target_user, client_name);
Packit fd8b60
                syslog(LOG_WARNING,
Packit fd8b60
                       "Account %s: authorization of %s failed",
Packit fd8b60
                       target_user, client_name);
Packit fd8b60
Packit fd8b60
            }
Packit fd8b60
Packit fd8b60
            exit(1);
Packit fd8b60
        }
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    if( some_rest_copy){
Packit fd8b60
        retval = krb5_ccache_filter(ksu_context, cc_tmp, client);
Packit fd8b60
        if (retval) {
Packit fd8b60
            com_err(prog_name,retval, _("while calling cc_filter"));
Packit fd8b60
            exit(1);
Packit fd8b60
        }
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    if (all_rest_copy){
Packit fd8b60
        retval = krb5_cc_initialize(ksu_context, cc_tmp, tmp_princ);
Packit fd8b60
        if (retval) {
Packit fd8b60
            com_err(prog_name, retval, _("while erasing target cache"));
Packit fd8b60
            exit(1);
Packit fd8b60
        }
Packit fd8b60
        stored = FALSE;
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    /* get the shell of the user, this will be the shell used by su */
Packit fd8b60
    target_pwd = getpwnam(target_user);
Packit fd8b60
Packit fd8b60
    if (target_pwd->pw_shell)
Packit fd8b60
        shell = xstrdup(target_pwd->pw_shell);
Packit fd8b60
    else {
Packit fd8b60
        shell = _DEF_CSH;  /* default is cshell */
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
#ifdef HAVE_GETUSERSHELL
Packit fd8b60
Packit fd8b60
    /* insist that the target login uses a standard shell (root is omited) */
Packit fd8b60
Packit fd8b60
    if (!standard_shell(target_pwd->pw_shell) && source_uid) {
Packit fd8b60
        fprintf(stderr, _("ksu: permission denied (shell).\n"));
Packit fd8b60
        exit(1);
Packit fd8b60
    }
Packit fd8b60
#endif /* HAVE_GETUSERSHELL */
Packit fd8b60
Packit fd8b60
    if (target_pwd->pw_uid){
Packit fd8b60
Packit fd8b60
        if(set_env_var("USER", target_pwd->pw_name)){
Packit fd8b60
            fprintf(stderr,
Packit fd8b60
                    _("ksu: couldn't set environment variable USER\n"));
Packit fd8b60
            exit(1);
Packit fd8b60
        }
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    if(set_env_var( "HOME", target_pwd->pw_dir)){
Packit fd8b60
        fprintf(stderr, _("ksu: couldn't set environment variable HOME\n"));
Packit fd8b60
        exit(1);
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    if(set_env_var( "SHELL", shell)){
Packit fd8b60
        fprintf(stderr, _("ksu: couldn't set environment variable SHELL\n"));
Packit fd8b60
        exit(1);
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    /* set permissions */
Packit fd8b60
    if (setgid(target_pwd->pw_gid) < 0) {
Packit fd8b60
        perror("ksu: setgid");
Packit fd8b60
        exit(1);
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    if (initgroups(target_user, target_pwd->pw_gid)) {
Packit fd8b60
        fprintf(stderr, _("ksu: initgroups failed.\n"));
Packit fd8b60
        exit(1);
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    if ( ! strcmp(target_user, source_user)){
Packit fd8b60
        print_status(_("Leaving uid as %s (%ld)\n"),
Packit fd8b60
                     target_user, (long) target_pwd->pw_uid);
Packit fd8b60
    }else{
Packit fd8b60
        print_status(_("Changing uid to %s (%ld)\n"),
Packit fd8b60
                     target_user, (long) target_pwd->pw_uid);
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
#ifdef  HAVE_SETLUID
Packit fd8b60
    /*
Packit fd8b60
     * If we're on a system which keeps track of login uids, then
Packit fd8b60
     * set the login uid. If this fails this opens up a problem on DEC OSF
Packit fd8b60
     * with C2 enabled.
Packit fd8b60
     */
Packit fd8b60
    if (setluid((uid_t) pwd->pw_uid) < 0) {
Packit fd8b60
        perror("setluid");
Packit fd8b60
        exit(1);
Packit fd8b60
    }
Packit fd8b60
#endif  /* HAVE_SETLUID */
Packit fd8b60
Packit fd8b60
    if (setuid(target_pwd->pw_uid) < 0) {
Packit fd8b60
        perror("ksu: setuid");
Packit fd8b60
        exit(1);
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    retval = resolve_target_cache(ksu_context, client, &cc_target, &cc_reused);
Packit fd8b60
    if (retval)
Packit fd8b60
        exit(1);
Packit fd8b60
    retval = krb5_cc_get_full_name(ksu_context, cc_target, &cc_target_tag);
Packit fd8b60
    if (retval) {
Packit fd8b60
        com_err(prog_name, retval, _("while getting name of target ccache"));
Packit fd8b60
        sweep_up(ksu_context, cc_target);
Packit fd8b60
        exit(1);
Packit fd8b60
    }
Packit fd8b60
    if (auth_debug)
Packit fd8b60
        fprintf(stderr, " target cache =  %s\n", cc_target_tag);
Packit fd8b60
    if (cc_reused)
Packit fd8b60
        keep_target_cache = TRUE;
Packit fd8b60
Packit fd8b60
    if (stored) {
Packit fd8b60
        retval = krb5_ccache_copy(ksu_context, cc_tmp, client, cc_target,
Packit fd8b60
                                  FALSE, client, &stored);
Packit fd8b60
        if (retval) {
Packit fd8b60
            com_err(prog_name, retval, _("while copying cache %s to %s"),
Packit fd8b60
                    KS_TEMPORARY_CACHE, cc_target_tag);
Packit fd8b60
            exit(1);
Packit fd8b60
        }
Packit fd8b60
Packit fd8b60
        if (!ks_ccache_is_initialized(ksu_context, cc_target)) {
Packit fd8b60
            com_err(prog_name, errno,
Packit fd8b60
                    _("%s does not have correct permissions for %s, "
Packit fd8b60
                      "%s aborted"), target_user, cc_target_tag, prog_name);
Packit fd8b60
            exit(1);
Packit fd8b60
        }
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    krb5_free_string(ksu_context, cc_target_tag);
Packit fd8b60
Packit fd8b60
    /* Set the cc env name to target. */
Packit fd8b60
    retval = set_ccname_env(ksu_context, cc_target);
Packit fd8b60
    if (retval != 0) {
Packit fd8b60
        sweep_up(ksu_context, cc_target);
Packit fd8b60
        exit(1);
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    if (cmd){
Packit fd8b60
        if ((source_uid == 0) || (source_uid == target_uid )){
Packit fd8b60
            exec_cmd = cmd;
Packit fd8b60
        }
Packit fd8b60
Packit fd8b60
        if( !exec_cmd){
Packit fd8b60
            fprintf(stderr, _("Internal error: command %s did not get "
Packit fd8b60
                              "resolved\n"), cmd);
Packit fd8b60
            exit(1);
Packit fd8b60
        }
Packit fd8b60
Packit fd8b60
        params[0] = exec_cmd;
Packit fd8b60
    }
Packit fd8b60
    else{
Packit fd8b60
        params[0] = shell;
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    if (auth_debug){
Packit fd8b60
        fprintf(stderr, "program to be execed %s\n",params[0]);
Packit fd8b60
    }
Packit fd8b60
Packit Service a81408
    if( keep_target_cache ) {
Packit fd8b60
        execv(params[0], params);
Packit fd8b60
        com_err(prog_name, errno, _("while trying to execv %s"), params[0]);
Packit fd8b60
        sweep_up(ksu_context, cc_target);
Packit fd8b60
        exit(1);
Packit fd8b60
    }else{
Packit fd8b60
        statusp = 1;
Packit fd8b60
        switch ((child_pid = fork())) {
Packit fd8b60
        default:
Packit fd8b60
            if (auth_debug){
Packit fd8b60
                printf(" The child pid is %ld\n", (long) child_pid);
Packit fd8b60
                printf(" The parent pid is %ld\n", (long) getpid());
Packit fd8b60
            }
Packit fd8b60
            while ((ret_pid = waitpid(child_pid, &statusp, WUNTRACED)) != -1) {
Packit fd8b60
                if (WIFSTOPPED(statusp)) {
Packit fd8b60
                    child_pgrp = tcgetpgrp(1);
Packit fd8b60
                    kill(getpid(), SIGSTOP);
Packit fd8b60
                    tcsetpgrp(1, child_pgrp);
Packit fd8b60
                    kill(child_pid, SIGCONT);
Packit fd8b60
                    statusp = 1;
Packit fd8b60
                    continue;
Packit fd8b60
                }
Packit fd8b60
                break;
Packit fd8b60
            }
Packit fd8b60
            if (auth_debug){
Packit fd8b60
                printf("The exit status of the child is %d\n", statusp);
Packit fd8b60
            }
Packit fd8b60
            if (ret_pid == -1) {
Packit fd8b60
                com_err(prog_name, errno, _("while calling waitpid"));
Packit fd8b60
            }
Packit Service a81408
            sweep_up(ksu_context, cc_target);
Packit fd8b60
            exit (statusp);
Packit fd8b60
        case -1:
Packit fd8b60
            com_err(prog_name, errno, _("while trying to fork."));
Packit fd8b60
            sweep_up(ksu_context, cc_target);
Packit fd8b60
            exit (1);
Packit fd8b60
        case 0:
Packit fd8b60
            execv(params[0], params);
Packit fd8b60
            com_err(prog_name, errno, _("while trying to execv %s"),
Packit fd8b60
                    params[0]);
Packit fd8b60
            exit (1);
Packit fd8b60
        }
Packit fd8b60
    }
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
static krb5_error_code
Packit fd8b60
init_ksu_context(krb5_context *context_out)
Packit fd8b60
{
Packit fd8b60
    krb5_error_code retval;
Packit fd8b60
    const char *env_ccname;
Packit fd8b60
    krb5_context context;
Packit fd8b60
Packit fd8b60
    *context_out = NULL;
Packit fd8b60
Packit fd8b60
    retval = krb5_init_secure_context(&context);
Packit fd8b60
    if (retval)
Packit fd8b60
        return retval;
Packit fd8b60
Packit fd8b60
    /* We want to obey KRB5CCNAME in this context even though this is a setuid
Packit fd8b60
     * program.  (It will only be used when operating as the real uid.) */
Packit fd8b60
    env_ccname = getenv(KRB5_ENV_CCNAME);
Packit fd8b60
    if (env_ccname != NULL) {
Packit fd8b60
        retval = krb5_cc_set_default_name(context, env_ccname);
Packit fd8b60
        if (retval) {
Packit fd8b60
            krb5_free_context(context);
Packit fd8b60
            return retval;
Packit fd8b60
        }
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    *context_out = context;
Packit fd8b60
    return 0;
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
/* Set KRB5CCNAME in the environment to point to ccache.  Print an error
Packit fd8b60
 * message on failure. */
Packit fd8b60
static krb5_error_code
Packit fd8b60
set_ccname_env(krb5_context ksu_context, krb5_ccache ccache)
Packit fd8b60
{
Packit fd8b60
    krb5_error_code retval;
Packit fd8b60
    char *ccname;
Packit fd8b60
Packit fd8b60
    retval = krb5_cc_get_full_name(ksu_context, ccache, &ccname);
Packit fd8b60
    if (retval) {
Packit fd8b60
        com_err(prog_name, retval, _("while reading cache name from ccache"));
Packit fd8b60
        return retval;
Packit fd8b60
    }
Packit fd8b60
    if (set_env_var(KRB5_ENV_CCNAME, ccname)) {
Packit fd8b60
        retval = errno;
Packit fd8b60
        fprintf(stderr,
Packit fd8b60
                _("ksu: couldn't set environment variable %s\n"),
Packit fd8b60
                KRB5_ENV_CCNAME);
Packit fd8b60
    }
Packit fd8b60
    krb5_free_string(ksu_context, ccname);
Packit fd8b60
    return retval;
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
/*
Packit fd8b60
 * Get the configured default ccache name.  Unset KRB5CCNAME and force a
Packit fd8b60
 * recomputation so we don't use values for the source user.  Print an error
Packit fd8b60
 * message on failure.
Packit fd8b60
 */
Packit fd8b60
static krb5_error_code
Packit fd8b60
get_configured_defccname(krb5_context context, char **target_out)
Packit fd8b60
{
Packit fd8b60
    krb5_error_code retval;
Packit fd8b60
    const char *defname;
Packit fd8b60
    char *target = NULL;
Packit fd8b60
Packit fd8b60
    *target_out = NULL;
Packit fd8b60
Packit fd8b60
    unsetenv(KRB5_ENV_CCNAME);
Packit fd8b60
Packit fd8b60
    /* Make sure we don't have a cached value for a different uid. */
Packit fd8b60
    retval = krb5_cc_set_default_name(context, NULL);
Packit fd8b60
    if (retval != 0) {
Packit fd8b60
        com_err(prog_name, retval, _("while resetting target ccache name"));
Packit fd8b60
        return retval;
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    defname = krb5_cc_default_name(context);
Packit fd8b60
    if (defname != NULL) {
Packit fd8b60
        if (strchr(defname, ':') != NULL) {
Packit fd8b60
            target = strdup(defname);
Packit fd8b60
        } else {
Packit fd8b60
            if (asprintf(&target, "FILE:%s", defname) < 0)
Packit fd8b60
                target = NULL;
Packit fd8b60
        }
Packit fd8b60
    }
Packit fd8b60
    if (target == NULL) {
Packit fd8b60
        com_err(prog_name, ENOMEM, _("while determining target ccache name"));
Packit fd8b60
        return ENOMEM;
Packit fd8b60
    }
Packit fd8b60
    *target_out = target;
Packit fd8b60
    return 0;
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
/* Determine where the target user's creds should be stored.  Print an error
Packit fd8b60
 * message on failure. */
Packit fd8b60
static krb5_error_code
Packit fd8b60
resolve_target_cache(krb5_context context, krb5_principal princ,
Packit fd8b60
                     krb5_ccache *ccache_out, krb5_boolean *ccache_reused)
Packit fd8b60
{
Packit fd8b60
    krb5_error_code retval;
Packit fd8b60
    krb5_boolean switchable, reused = FALSE;
Packit fd8b60
    krb5_ccache ccache = NULL;
Packit fd8b60
    char *sep, *ccname = NULL, *sym = NULL, *target;
Packit fd8b60
Packit fd8b60
    *ccache_out = NULL;
Packit fd8b60
    *ccache_reused = FALSE;
Packit fd8b60
Packit fd8b60
    retval = get_configured_defccname(context, &target);
Packit fd8b60
    if (retval != 0)
Packit fd8b60
        return retval;
Packit fd8b60
Packit fd8b60
    /* Check if the configured default name uses a switchable type. */
Packit fd8b60
    sep = strchr(target, ':');
Packit fd8b60
    *sep = '\0';
Packit fd8b60
    switchable = krb5_cc_support_switch(context, target);
Packit fd8b60
    *sep = ':';
Packit fd8b60
Packit fd8b60
    if (!switchable) {
Packit fd8b60
        /* Try to avoid destroying an in-use target ccache by coming up with
Packit fd8b60
         * the name of a cache that doesn't exist yet. */
Packit fd8b60
        do {
Packit fd8b60
            free(ccname);
Packit fd8b60
            retval = gen_sym(context, &sym);
Packit fd8b60
            if (retval) {
Packit fd8b60
                com_err(prog_name, retval,
Packit fd8b60
                        _("while generating part of the target ccache name"));
Packit fd8b60
                return retval;
Packit fd8b60
            }
Packit fd8b60
            if (asprintf(&ccname, "%s.%s", target, sym) < 0) {
Packit fd8b60
                retval = ENOMEM;
Packit fd8b60
                free(sym);
Packit fd8b60
                com_err(prog_name, retval, _("while allocating memory for the "
Packit fd8b60
                                             "target ccache name"));
Packit fd8b60
                goto cleanup;
Packit fd8b60
            }
Packit fd8b60
            free(sym);
Packit fd8b60
        } while (ks_ccache_name_is_initialized(context, ccname));
Packit fd8b60
        retval = krb5_cc_resolve(context, ccname, &ccache);
Packit fd8b60
    } else {
Packit fd8b60
        /* Look for a cache in the collection that we can reuse. */
Packit fd8b60
        retval = krb5_cc_cache_match(context, princ, &ccache);
Packit fd8b60
        if (retval == 0) {
Packit fd8b60
            reused = TRUE;
Packit fd8b60
        } else {
Packit fd8b60
            /* There isn't one, so create a new one. */
Packit fd8b60
            *sep = '\0';
Packit fd8b60
            retval = krb5_cc_new_unique(context, target, NULL, &ccache);
Packit fd8b60
            *sep = ':';
Packit fd8b60
            if (retval) {
Packit fd8b60
                com_err(prog_name, retval,
Packit fd8b60
                        _("while creating new target ccache"));
Packit fd8b60
                goto cleanup;
Packit fd8b60
            }
Packit fd8b60
            retval = krb5_cc_initialize(context, ccache, princ);
Packit fd8b60
            if (retval) {
Packit fd8b60
                com_err(prog_name, retval,
Packit fd8b60
                        _("while initializing target cache"));
Packit fd8b60
                goto cleanup;
Packit fd8b60
            }
Packit fd8b60
        }
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    *ccache_out = ccache;
Packit fd8b60
    *ccache_reused = reused;
Packit fd8b60
Packit fd8b60
cleanup:
Packit fd8b60
    free(target);
Packit fd8b60
    return retval;
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
#ifdef HAVE_GETUSERSHELL
Packit fd8b60
Packit fd8b60
int standard_shell(sh)
Packit fd8b60
    char *sh;
Packit fd8b60
{
Packit fd8b60
    char *cp;
Packit fd8b60
    char *getusershell();
Packit fd8b60
Packit fd8b60
    while ((cp = getusershell()) != NULL)
Packit fd8b60
        if (!strcmp(cp, sh))
Packit fd8b60
            return (1);
Packit fd8b60
    return (0);
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
#endif /* HAVE_GETUSERSHELL */
Packit fd8b60
Packit fd8b60
static char * ontty()
Packit fd8b60
{
Packit fd8b60
    char *p;
Packit fd8b60
    static char buf[MAXPATHLEN + 5];
Packit fd8b60
    int result;
Packit fd8b60
Packit fd8b60
    buf[0] = 0;
Packit fd8b60
    if ((p = ttyname(STDERR_FILENO))) {
Packit fd8b60
        result = snprintf(buf, sizeof(buf), " on %s", p);
Packit fd8b60
        if (SNPRINTF_OVERFLOW(result, sizeof(buf))) {
Packit fd8b60
            fprintf(stderr, _("terminal name %s too long\n"), p);
Packit fd8b60
            exit (1);
Packit fd8b60
        }
Packit fd8b60
    }
Packit fd8b60
    return (buf);
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
Packit fd8b60
static int set_env_var(name, value)
Packit fd8b60
    char *name;
Packit fd8b60
    char *value;
Packit fd8b60
{
Packit fd8b60
    char * env_var_buf;
Packit fd8b60
Packit fd8b60
    asprintf(&env_var_buf,"%s=%s",name, value);
Packit fd8b60
    return putenv(env_var_buf);
Packit fd8b60
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
static void sweep_up(context, cc)
Packit fd8b60
    krb5_context context;
Packit fd8b60
    krb5_ccache cc;
Packit fd8b60
{
Packit fd8b60
    krb5_error_code retval;
Packit fd8b60
Packit fd8b60
    krb5_seteuid(0);
Packit fd8b60
    if (krb5_seteuid(target_uid) < 0) {
Packit fd8b60
        com_err(prog_name, errno,
Packit fd8b60
                _("while changing to target uid for destroying ccache"));
Packit fd8b60
        exit(1);
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    if (ks_ccache_is_initialized(context, cc)) {
Packit fd8b60
        if ((retval = krb5_cc_destroy(context, cc)))
Packit fd8b60
            com_err(prog_name, retval, _("while destroying cache"));
Packit fd8b60
    }
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
/*****************************************************************
Packit fd8b60
get_params is to be called for the -a option or -e option to
Packit fd8b60
           collect all params passed in for the shell or for
Packit fd8b60
           cmd.  An aray is returned containing all params.
Packit fd8b60
           optindex is incremented accordingly and the first
Packit fd8b60
           element in the returned array is reserved for the
Packit fd8b60
           name of the command to be executed or the name of the
Packit fd8b60
           shell.
Packit fd8b60
*****************************************************************/
Packit fd8b60
Packit fd8b60
krb5_error_code
Packit fd8b60
get_params(optindex, pargc, pargv, params)
Packit fd8b60
    int *optindex;
Packit fd8b60
    int pargc;
Packit fd8b60
    char **pargv;
Packit fd8b60
    char ***params;
Packit fd8b60
{
Packit fd8b60
Packit fd8b60
    int i,j;
Packit fd8b60
    char ** ret_params;
Packit fd8b60
    int size = pargc - *optindex + 2;
Packit fd8b60
Packit fd8b60
    if ((ret_params = (char **) calloc(size, sizeof (char *)))== NULL ){
Packit fd8b60
        return ENOMEM;
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    for (i = *optindex, j=1; i < pargc; i++,j++){
Packit fd8b60
        ret_params[j] = pargv[i];
Packit fd8b60
        *optindex = *optindex + 1;
Packit fd8b60
    }
Packit fd8b60
Packit fd8b60
    ret_params[size-1] = NULL;
Packit fd8b60
    *params = ret_params;
Packit fd8b60
    return 0;
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
static
Packit fd8b60
void print_status(const char *fmt, ...)
Packit fd8b60
{
Packit fd8b60
    va_list ap;
Packit fd8b60
    if (! quiet){
Packit fd8b60
        va_start(ap, fmt);
Packit fd8b60
        vfprintf(stderr, fmt, ap);
Packit fd8b60
        va_end(ap);
Packit fd8b60
    }
Packit fd8b60
}
Packit fd8b60
Packit fd8b60
krb5_error_code
Packit fd8b60
ksu_tgtname(context, server, client, tgtprinc)
Packit fd8b60
    krb5_context context;
Packit fd8b60
    const krb5_data *server, *client;
Packit fd8b60
    krb5_principal *tgtprinc;
Packit fd8b60
{
Packit fd8b60
    return krb5_build_principal_ext(context, tgtprinc, client->length, client->data,
Packit fd8b60
                                    KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME,
Packit fd8b60
                                    server->length, server->data,
Packit fd8b60
                                    0);
Packit fd8b60
}