xref: /freebsd/crypto/krb5/src/clients/ksu/main.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1*7f2fe78bSCy Schubert /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2*7f2fe78bSCy Schubert /*
3*7f2fe78bSCy Schubert  * Copyright (c) 1994 by the University of Southern California
4*7f2fe78bSCy Schubert  *
5*7f2fe78bSCy Schubert  * EXPORT OF THIS SOFTWARE from the United States of America may
6*7f2fe78bSCy Schubert  *     require a specific license from the United States Government.
7*7f2fe78bSCy Schubert  *     It is the responsibility of any person or organization contemplating
8*7f2fe78bSCy Schubert  *     export to obtain such a license before exporting.
9*7f2fe78bSCy Schubert  *
10*7f2fe78bSCy Schubert  * WITHIN THAT CONSTRAINT, permission to copy, modify, and distribute
11*7f2fe78bSCy Schubert  *     this software and its documentation in source and binary forms is
12*7f2fe78bSCy Schubert  *     hereby granted, provided that any documentation or other materials
13*7f2fe78bSCy Schubert  *     related to such distribution or use acknowledge that the software
14*7f2fe78bSCy Schubert  *     was developed by the University of Southern California.
15*7f2fe78bSCy Schubert  *
16*7f2fe78bSCy Schubert  * DISCLAIMER OF WARRANTY.  THIS SOFTWARE IS PROVIDED "AS IS".  The
17*7f2fe78bSCy Schubert  *     University of Southern California MAKES NO REPRESENTATIONS OR
18*7f2fe78bSCy Schubert  *     WARRANTIES, EXPRESS OR IMPLIED.  By way of example, but not
19*7f2fe78bSCy Schubert  *     limitation, the University of Southern California MAKES NO
20*7f2fe78bSCy Schubert  *     REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY
21*7f2fe78bSCy Schubert  *     PARTICULAR PURPOSE. The University of Southern
22*7f2fe78bSCy Schubert  *     California shall not be held liable for any liability nor for any
23*7f2fe78bSCy Schubert  *     direct, indirect, or consequential damages with respect to any
24*7f2fe78bSCy Schubert  *     claim by the user or distributor of the ksu software.
25*7f2fe78bSCy Schubert  *
26*7f2fe78bSCy Schubert  * KSU was written by:  Ari Medvinsky, ari@isi.edu
27*7f2fe78bSCy Schubert  */
28*7f2fe78bSCy Schubert 
29*7f2fe78bSCy Schubert #include "ksu.h"
30*7f2fe78bSCy Schubert #include "adm_proto.h"
31*7f2fe78bSCy Schubert #include <sys/types.h>
32*7f2fe78bSCy Schubert #include <sys/wait.h>
33*7f2fe78bSCy Schubert #include <signal.h>
34*7f2fe78bSCy Schubert #include <grp.h>
35*7f2fe78bSCy Schubert 
36*7f2fe78bSCy Schubert /* globals */
37*7f2fe78bSCy Schubert char * prog_name;
38*7f2fe78bSCy Schubert int auth_debug =0;
39*7f2fe78bSCy Schubert char k5login_path[MAXPATHLEN];
40*7f2fe78bSCy Schubert char k5users_path[MAXPATHLEN];
41*7f2fe78bSCy Schubert char * gb_err = NULL;
42*7f2fe78bSCy Schubert int quiet = 0;
43*7f2fe78bSCy Schubert /***********/
44*7f2fe78bSCy Schubert 
45*7f2fe78bSCy Schubert #define KS_TEMPORARY_CACHE "MEMORY:_ksu"
46*7f2fe78bSCy Schubert #define KS_TEMPORARY_PRINC "_ksu/_ksu@_ksu"
47*7f2fe78bSCy Schubert #define _DEF_CSH "/bin/csh"
48*7f2fe78bSCy Schubert static int set_env_var (char *, char *);
49*7f2fe78bSCy Schubert static void sweep_up (krb5_context, krb5_ccache);
50*7f2fe78bSCy Schubert static char * ontty (void);
51*7f2fe78bSCy Schubert static krb5_error_code init_ksu_context(krb5_context *);
52*7f2fe78bSCy Schubert static krb5_error_code set_ccname_env(krb5_context, krb5_ccache);
53*7f2fe78bSCy Schubert static void print_status( const char *fmt, ...)
54*7f2fe78bSCy Schubert #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
55*7f2fe78bSCy Schubert     __attribute__ ((__format__ (__printf__, 1, 2)))
56*7f2fe78bSCy Schubert #endif
57*7f2fe78bSCy Schubert     ;
58*7f2fe78bSCy Schubert static krb5_error_code resolve_target_cache(krb5_context ksu_context,
59*7f2fe78bSCy Schubert                                             krb5_principal princ,
60*7f2fe78bSCy Schubert                                             krb5_ccache *ccache_out,
61*7f2fe78bSCy Schubert                                             krb5_boolean *ccache_reused);
62*7f2fe78bSCy Schubert 
63*7f2fe78bSCy Schubert /* Note -e and -a options are mutually exclusive */
64*7f2fe78bSCy Schubert /* insure the proper specification of target user as well as catching
65*7f2fe78bSCy Schubert    ill specified arguments to commands */
66*7f2fe78bSCy Schubert 
usage()67*7f2fe78bSCy Schubert void usage (){
68*7f2fe78bSCy Schubert     fprintf(stderr,
69*7f2fe78bSCy Schubert             _("Usage: %s [target user] [-n principal] [-c source cachename] "
70*7f2fe78bSCy Schubert               "[-k] [-r time] [-p|-P] [-f|-F] [-l lifetime] [-zZ] [-q] "
71*7f2fe78bSCy Schubert               "[-e command [args... ] ] [-a [args... ] ]\n"), prog_name);
72*7f2fe78bSCy Schubert }
73*7f2fe78bSCy Schubert 
74*7f2fe78bSCy Schubert /* for Ultrix and friends ... */
75*7f2fe78bSCy Schubert #ifndef MAXHOSTNAMELEN
76*7f2fe78bSCy Schubert #define MAXHOSTNAMELEN 64
77*7f2fe78bSCy Schubert #endif
78*7f2fe78bSCy Schubert 
79*7f2fe78bSCy Schubert /* These are file static so sweep_up can get to them*/
80*7f2fe78bSCy Schubert static uid_t source_uid, target_uid;
81*7f2fe78bSCy Schubert 
82*7f2fe78bSCy Schubert int
main(argc,argv)83*7f2fe78bSCy Schubert main (argc, argv)
84*7f2fe78bSCy Schubert     int argc;
85*7f2fe78bSCy Schubert     char ** argv;
86*7f2fe78bSCy Schubert {
87*7f2fe78bSCy Schubert     int hp =0;
88*7f2fe78bSCy Schubert     int some_rest_copy = 0;
89*7f2fe78bSCy Schubert     int all_rest_copy = 0;
90*7f2fe78bSCy Schubert     char *localhostname = NULL;
91*7f2fe78bSCy Schubert     krb5_get_init_creds_opt *options = NULL;
92*7f2fe78bSCy Schubert     int option=0;
93*7f2fe78bSCy Schubert     int statusp=0;
94*7f2fe78bSCy Schubert     krb5_error_code retval = 0;
95*7f2fe78bSCy Schubert     krb5_principal client = NULL, tmp_princ = NULL;
96*7f2fe78bSCy Schubert     krb5_ccache cc_tmp = NULL, cc_target = NULL;
97*7f2fe78bSCy Schubert     krb5_context ksu_context;
98*7f2fe78bSCy Schubert     char * cc_target_tag = NULL;
99*7f2fe78bSCy Schubert     char * target_user = NULL;
100*7f2fe78bSCy Schubert     char * source_user;
101*7f2fe78bSCy Schubert 
102*7f2fe78bSCy Schubert     krb5_ccache cc_source = NULL;
103*7f2fe78bSCy Schubert     const char * cc_source_tag = NULL;
104*7f2fe78bSCy Schubert     const char * cc_source_tag_tmp = NULL;
105*7f2fe78bSCy Schubert     char * cmd = NULL, * exec_cmd = NULL;
106*7f2fe78bSCy Schubert     int errflg = 0;
107*7f2fe78bSCy Schubert     krb5_boolean auth_val;
108*7f2fe78bSCy Schubert     krb5_boolean authorization_val = FALSE;
109*7f2fe78bSCy Schubert     int path_passwd = 0;
110*7f2fe78bSCy Schubert     int done =0,i,j;
111*7f2fe78bSCy Schubert     uid_t ruid = getuid ();
112*7f2fe78bSCy Schubert     struct passwd *pwd=NULL,  *target_pwd ;
113*7f2fe78bSCy Schubert     char * shell;
114*7f2fe78bSCy Schubert     char ** params;
115*7f2fe78bSCy Schubert     int keep_target_cache = 0;
116*7f2fe78bSCy Schubert     int child_pid, child_pgrp, ret_pid;
117*7f2fe78bSCy Schubert     extern char * getpass(), *crypt();
118*7f2fe78bSCy Schubert     int pargc;
119*7f2fe78bSCy Schubert     char ** pargv;
120*7f2fe78bSCy Schubert     krb5_boolean stored = FALSE, cc_reused = FALSE, given_princ = FALSE;
121*7f2fe78bSCy Schubert     krb5_boolean zero_password;
122*7f2fe78bSCy Schubert     krb5_boolean restrict_creds;
123*7f2fe78bSCy Schubert     krb5_deltat lifetime, rlife;
124*7f2fe78bSCy Schubert 
125*7f2fe78bSCy Schubert     if (argc == 0)
126*7f2fe78bSCy Schubert         exit(1);
127*7f2fe78bSCy Schubert 
128*7f2fe78bSCy Schubert     params = (char **) xcalloc (2, sizeof (char *));
129*7f2fe78bSCy Schubert     params[1] = NULL;
130*7f2fe78bSCy Schubert 
131*7f2fe78bSCy Schubert     unsetenv ("KRB5_CONFIG");
132*7f2fe78bSCy Schubert 
133*7f2fe78bSCy Schubert     retval = init_ksu_context(&ksu_context);
134*7f2fe78bSCy Schubert     if (retval) {
135*7f2fe78bSCy Schubert         com_err(argv[0], retval, _("while initializing krb5"));
136*7f2fe78bSCy Schubert         exit(1);
137*7f2fe78bSCy Schubert     }
138*7f2fe78bSCy Schubert 
139*7f2fe78bSCy Schubert     retval = krb5_get_init_creds_opt_alloc(ksu_context, &options);
140*7f2fe78bSCy Schubert     if (retval) {
141*7f2fe78bSCy Schubert         com_err(argv[0], retval, _("while initializing krb5"));
142*7f2fe78bSCy Schubert         exit(1);
143*7f2fe78bSCy Schubert     }
144*7f2fe78bSCy Schubert 
145*7f2fe78bSCy Schubert     if (strrchr(argv[0], '/'))
146*7f2fe78bSCy Schubert         argv[0] = strrchr(argv[0], '/')+1;
147*7f2fe78bSCy Schubert     prog_name = argv[0];
148*7f2fe78bSCy Schubert     if (strlen (prog_name) > 50) {
149*7f2fe78bSCy Schubert         /* this many chars *after* last / ?? */
150*7f2fe78bSCy Schubert         com_err(prog_name, 0,
151*7f2fe78bSCy Schubert                 _("program name too long - quitting to avoid triggering "
152*7f2fe78bSCy Schubert                   "system logging bugs"));
153*7f2fe78bSCy Schubert         exit (1);
154*7f2fe78bSCy Schubert     }
155*7f2fe78bSCy Schubert 
156*7f2fe78bSCy Schubert 
157*7f2fe78bSCy Schubert #ifndef LOG_NDELAY
158*7f2fe78bSCy Schubert #define LOG_NDELAY 0
159*7f2fe78bSCy Schubert #endif
160*7f2fe78bSCy Schubert 
161*7f2fe78bSCy Schubert #ifndef LOG_AUTH /* 4.2 syslog */
162*7f2fe78bSCy Schubert     openlog(prog_name, LOG_PID|LOG_NDELAY);
163*7f2fe78bSCy Schubert #else
164*7f2fe78bSCy Schubert     openlog(prog_name, LOG_PID | LOG_NDELAY, LOG_AUTH);
165*7f2fe78bSCy Schubert #endif /* 4.2 syslog */
166*7f2fe78bSCy Schubert 
167*7f2fe78bSCy Schubert 
168*7f2fe78bSCy Schubert     if (( argc == 1) || (argv[1][0] == '-')){
169*7f2fe78bSCy Schubert         target_user = xstrdup("root");
170*7f2fe78bSCy Schubert         pargc = argc;
171*7f2fe78bSCy Schubert         pargv = argv;
172*7f2fe78bSCy Schubert     } else {
173*7f2fe78bSCy Schubert         target_user = xstrdup(argv[1]);
174*7f2fe78bSCy Schubert         pargc = argc -1;
175*7f2fe78bSCy Schubert 
176*7f2fe78bSCy Schubert         if ((pargv =(char **) calloc(pargc +1,sizeof(char *)))==NULL){
177*7f2fe78bSCy Schubert             com_err(prog_name, errno, _("while allocating memory"));
178*7f2fe78bSCy Schubert             exit(1);
179*7f2fe78bSCy Schubert         }
180*7f2fe78bSCy Schubert 
181*7f2fe78bSCy Schubert         pargv[pargc] = NULL;
182*7f2fe78bSCy Schubert         pargv[0] = argv[0];
183*7f2fe78bSCy Schubert 
184*7f2fe78bSCy Schubert         for(i =1; i< pargc; i ++){
185*7f2fe78bSCy Schubert             pargv[i] = argv[i + 1];
186*7f2fe78bSCy Schubert         }
187*7f2fe78bSCy Schubert     }
188*7f2fe78bSCy Schubert 
189*7f2fe78bSCy Schubert     if (krb5_seteuid (ruid)) {
190*7f2fe78bSCy Schubert         com_err (prog_name, errno, _("while setting euid to source user"));
191*7f2fe78bSCy Schubert         exit (1);
192*7f2fe78bSCy Schubert     }
193*7f2fe78bSCy Schubert     while (!done &&
194*7f2fe78bSCy Schubert            (option = getopt(pargc, pargv,"n:c:r:a:zZDfFpPkql:e:")) != -1) {
195*7f2fe78bSCy Schubert         switch (option) {
196*7f2fe78bSCy Schubert         case 'r':
197*7f2fe78bSCy Schubert             if (strlen (optarg) >= 14)
198*7f2fe78bSCy Schubert                 optarg = "bad-time";
199*7f2fe78bSCy Schubert             retval = krb5_string_to_deltat(optarg, &rlife);
200*7f2fe78bSCy Schubert             if (retval != 0 || rlife == 0) {
201*7f2fe78bSCy Schubert                 fprintf(stderr, _("Bad lifetime value (%s hours?)\n"), optarg);
202*7f2fe78bSCy Schubert                 errflg++;
203*7f2fe78bSCy Schubert             }
204*7f2fe78bSCy Schubert             krb5_get_init_creds_opt_set_renew_life(options, rlife);
205*7f2fe78bSCy Schubert             break;
206*7f2fe78bSCy Schubert         case 'a':
207*7f2fe78bSCy Schubert             /* when integrating this remember to pass in pargc, pargv and
208*7f2fe78bSCy Schubert                take care of params argument */
209*7f2fe78bSCy Schubert             optind --;
210*7f2fe78bSCy Schubert             if (auth_debug){printf("Before get_params optind=%d\n", optind);}
211*7f2fe78bSCy Schubert 
212*7f2fe78bSCy Schubert             if ((retval = get_params( & optind, pargc, pargv, &params))){
213*7f2fe78bSCy Schubert                 com_err(prog_name, retval, _("when gathering parameters"));
214*7f2fe78bSCy Schubert                 errflg++;
215*7f2fe78bSCy Schubert             }
216*7f2fe78bSCy Schubert             if(auth_debug){ printf("After get_params optind=%d\n", optind);}
217*7f2fe78bSCy Schubert             done = 1;
218*7f2fe78bSCy Schubert             break;
219*7f2fe78bSCy Schubert         case 'p':
220*7f2fe78bSCy Schubert             krb5_get_init_creds_opt_set_proxiable(options, 1);
221*7f2fe78bSCy Schubert             break;
222*7f2fe78bSCy Schubert         case 'P':
223*7f2fe78bSCy Schubert             krb5_get_init_creds_opt_set_proxiable(options, 0);
224*7f2fe78bSCy Schubert             break;
225*7f2fe78bSCy Schubert         case 'f':
226*7f2fe78bSCy Schubert             krb5_get_init_creds_opt_set_forwardable(options, 1);
227*7f2fe78bSCy Schubert             break;
228*7f2fe78bSCy Schubert         case 'F':
229*7f2fe78bSCy Schubert             krb5_get_init_creds_opt_set_forwardable(options, 0);
230*7f2fe78bSCy Schubert             break;
231*7f2fe78bSCy Schubert         case 'k':
232*7f2fe78bSCy Schubert             keep_target_cache =1;
233*7f2fe78bSCy Schubert             break;
234*7f2fe78bSCy Schubert         case 'q':
235*7f2fe78bSCy Schubert             quiet =1;
236*7f2fe78bSCy Schubert             break;
237*7f2fe78bSCy Schubert         case 'l':
238*7f2fe78bSCy Schubert             if (strlen (optarg) >= 14)
239*7f2fe78bSCy Schubert                 optarg = "bad-time";
240*7f2fe78bSCy Schubert             retval = krb5_string_to_deltat(optarg, &lifetime);
241*7f2fe78bSCy Schubert             if (retval != 0 || lifetime == 0) {
242*7f2fe78bSCy Schubert                 fprintf(stderr, _("Bad lifetime value (%s hours?)\n"), optarg);
243*7f2fe78bSCy Schubert                 errflg++;
244*7f2fe78bSCy Schubert             }
245*7f2fe78bSCy Schubert             krb5_get_init_creds_opt_set_tkt_life(options, lifetime);
246*7f2fe78bSCy Schubert             break;
247*7f2fe78bSCy Schubert         case 'n':
248*7f2fe78bSCy Schubert             if ((retval = krb5_parse_name(ksu_context, optarg, &client))){
249*7f2fe78bSCy Schubert                 com_err(prog_name, retval, _("when parsing name %s"), optarg);
250*7f2fe78bSCy Schubert                 errflg++;
251*7f2fe78bSCy Schubert             }
252*7f2fe78bSCy Schubert             given_princ = TRUE;
253*7f2fe78bSCy Schubert             break;
254*7f2fe78bSCy Schubert #ifdef DEBUG
255*7f2fe78bSCy Schubert         case 'D':
256*7f2fe78bSCy Schubert             auth_debug = 1;
257*7f2fe78bSCy Schubert             break;
258*7f2fe78bSCy Schubert #endif
259*7f2fe78bSCy Schubert         case 'z':
260*7f2fe78bSCy Schubert             some_rest_copy = 1;
261*7f2fe78bSCy Schubert             if(all_rest_copy) {
262*7f2fe78bSCy Schubert                 fprintf(stderr,
263*7f2fe78bSCy Schubert                         _("-z option is mutually exclusive with -Z.\n"));
264*7f2fe78bSCy Schubert                 errflg++;
265*7f2fe78bSCy Schubert             }
266*7f2fe78bSCy Schubert             break;
267*7f2fe78bSCy Schubert         case 'Z':
268*7f2fe78bSCy Schubert             all_rest_copy = 1;
269*7f2fe78bSCy Schubert             if(some_rest_copy) {
270*7f2fe78bSCy Schubert                 fprintf(stderr,
271*7f2fe78bSCy Schubert                         _("-Z option is mutually exclusive with -z.\n"));
272*7f2fe78bSCy Schubert                 errflg++;
273*7f2fe78bSCy Schubert             }
274*7f2fe78bSCy Schubert             break;
275*7f2fe78bSCy Schubert         case 'c':
276*7f2fe78bSCy Schubert             if (cc_source_tag == NULL) {
277*7f2fe78bSCy Schubert                 cc_source_tag = xstrdup(optarg);
278*7f2fe78bSCy Schubert                 if ( strchr(cc_source_tag, ':')){
279*7f2fe78bSCy Schubert                     cc_source_tag_tmp = strchr(cc_source_tag, ':') + 1;
280*7f2fe78bSCy Schubert 
281*7f2fe78bSCy Schubert                     if (!ks_ccache_name_is_initialized(ksu_context,
282*7f2fe78bSCy Schubert                                                        cc_source_tag)) {
283*7f2fe78bSCy Schubert                         com_err(prog_name, errno,
284*7f2fe78bSCy Schubert                                 _("while looking for credentials cache %s"),
285*7f2fe78bSCy Schubert                                 cc_source_tag_tmp);
286*7f2fe78bSCy Schubert                         exit (1);
287*7f2fe78bSCy Schubert                     }
288*7f2fe78bSCy Schubert                 }
289*7f2fe78bSCy Schubert                 else {
290*7f2fe78bSCy Schubert                     fprintf(stderr, _("malformed credential cache name %s\n"),
291*7f2fe78bSCy Schubert                             cc_source_tag);
292*7f2fe78bSCy Schubert                     errflg++;
293*7f2fe78bSCy Schubert                 }
294*7f2fe78bSCy Schubert 
295*7f2fe78bSCy Schubert             } else {
296*7f2fe78bSCy Schubert                 fprintf(stderr, _("Only one -c option allowed\n"));
297*7f2fe78bSCy Schubert                 errflg++;
298*7f2fe78bSCy Schubert             }
299*7f2fe78bSCy Schubert             break;
300*7f2fe78bSCy Schubert         case 'e':
301*7f2fe78bSCy Schubert             cmd = xstrdup(optarg);
302*7f2fe78bSCy Schubert             if(auth_debug){printf("Before get_params optind=%d\n", optind);}
303*7f2fe78bSCy Schubert             if ((retval = get_params( & optind, pargc, pargv, &params))){
304*7f2fe78bSCy Schubert                 com_err(prog_name, retval, _("when gathering parameters"));
305*7f2fe78bSCy Schubert                 errflg++;
306*7f2fe78bSCy Schubert             }
307*7f2fe78bSCy Schubert             if(auth_debug){printf("After get_params optind=%d\n", optind);}
308*7f2fe78bSCy Schubert             done = 1;
309*7f2fe78bSCy Schubert 
310*7f2fe78bSCy Schubert             if (auth_debug){
311*7f2fe78bSCy Schubert                 fprintf(stderr,"Command to be executed: %s\n", cmd);
312*7f2fe78bSCy Schubert             }
313*7f2fe78bSCy Schubert             break;
314*7f2fe78bSCy Schubert         case '?':
315*7f2fe78bSCy Schubert         default:
316*7f2fe78bSCy Schubert             errflg++;
317*7f2fe78bSCy Schubert             break;
318*7f2fe78bSCy Schubert         }
319*7f2fe78bSCy Schubert     }
320*7f2fe78bSCy Schubert 
321*7f2fe78bSCy Schubert     if (errflg) {
322*7f2fe78bSCy Schubert         usage();
323*7f2fe78bSCy Schubert         exit(2);
324*7f2fe78bSCy Schubert     }
325*7f2fe78bSCy Schubert 
326*7f2fe78bSCy Schubert     if (optind != pargc ){
327*7f2fe78bSCy Schubert         usage();
328*7f2fe78bSCy Schubert         exit(2);
329*7f2fe78bSCy Schubert     }
330*7f2fe78bSCy Schubert 
331*7f2fe78bSCy Schubert     if (auth_debug){
332*7f2fe78bSCy Schubert         for(j=1; params[j] != NULL; j++){
333*7f2fe78bSCy Schubert             fprintf (stderr,"params[%d]= %s\n", j,params[j]);
334*7f2fe78bSCy Schubert         }
335*7f2fe78bSCy Schubert     }
336*7f2fe78bSCy Schubert 
337*7f2fe78bSCy Schubert     /***********************************/
338*7f2fe78bSCy Schubert     source_user = getlogin(); /*checks for the the login name in /etc/utmp*/
339*7f2fe78bSCy Schubert 
340*7f2fe78bSCy Schubert     /* verify that that the user exists and get his passwd structure */
341*7f2fe78bSCy Schubert 
342*7f2fe78bSCy Schubert     if (source_user == NULL ||(pwd = getpwnam(source_user)) == NULL ||
343*7f2fe78bSCy Schubert         pwd->pw_uid != ruid){
344*7f2fe78bSCy Schubert         pwd = getpwuid(ruid);
345*7f2fe78bSCy Schubert     }
346*7f2fe78bSCy Schubert 
347*7f2fe78bSCy Schubert     if (pwd == NULL) {
348*7f2fe78bSCy Schubert         fprintf(stderr, _("ksu: who are you?\n"));
349*7f2fe78bSCy Schubert         exit(1);
350*7f2fe78bSCy Schubert     }
351*7f2fe78bSCy Schubert     if (pwd->pw_uid != ruid) {
352*7f2fe78bSCy Schubert         fprintf (stderr, _("Your uid doesn't match your passwd entry?!\n"));
353*7f2fe78bSCy Schubert         exit (1);
354*7f2fe78bSCy Schubert     }
355*7f2fe78bSCy Schubert     /* Okay, now we have *some* passwd entry that matches the
356*7f2fe78bSCy Schubert        current real uid.  */
357*7f2fe78bSCy Schubert 
358*7f2fe78bSCy Schubert     /* allocate space and copy the usernamane there */
359*7f2fe78bSCy Schubert     source_user = xstrdup(pwd->pw_name);
360*7f2fe78bSCy Schubert     source_uid = pwd->pw_uid;
361*7f2fe78bSCy Schubert 
362*7f2fe78bSCy Schubert     if (!strcmp(SOURCE_USER_LOGIN, target_user)){
363*7f2fe78bSCy Schubert         target_user = xstrdup (source_user);
364*7f2fe78bSCy Schubert     }
365*7f2fe78bSCy Schubert 
366*7f2fe78bSCy Schubert     if ((target_pwd = getpwnam(target_user)) == NULL){
367*7f2fe78bSCy Schubert         fprintf(stderr, _("ksu: unknown login %s\n"), target_user);
368*7f2fe78bSCy Schubert         exit(1);
369*7f2fe78bSCy Schubert     }
370*7f2fe78bSCy Schubert     target_uid = target_pwd->pw_uid;
371*7f2fe78bSCy Schubert 
372*7f2fe78bSCy Schubert     init_auth_names(target_pwd->pw_dir);
373*7f2fe78bSCy Schubert 
374*7f2fe78bSCy Schubert     /***********************************/
375*7f2fe78bSCy Schubert 
376*7f2fe78bSCy Schubert     if (cc_source_tag == NULL){
377*7f2fe78bSCy Schubert         cc_source_tag = krb5_cc_default_name(ksu_context);
378*7f2fe78bSCy Schubert         cc_source_tag_tmp = strchr(cc_source_tag, ':');
379*7f2fe78bSCy Schubert         if (cc_source_tag_tmp == 0)
380*7f2fe78bSCy Schubert             cc_source_tag_tmp = cc_source_tag;
381*7f2fe78bSCy Schubert         else
382*7f2fe78bSCy Schubert             cc_source_tag_tmp++;
383*7f2fe78bSCy Schubert     }
384*7f2fe78bSCy Schubert 
385*7f2fe78bSCy Schubert     /* get a handle for the cache */
386*7f2fe78bSCy Schubert     if ((retval = krb5_cc_resolve(ksu_context, cc_source_tag, &cc_source))){
387*7f2fe78bSCy Schubert         com_err(prog_name, retval, _("while getting source cache"));
388*7f2fe78bSCy Schubert         exit(1);
389*7f2fe78bSCy Schubert     }
390*7f2fe78bSCy Schubert 
391*7f2fe78bSCy Schubert     if ((retval = get_best_princ_for_target(ksu_context, source_uid,
392*7f2fe78bSCy Schubert                                             target_uid, source_user,
393*7f2fe78bSCy Schubert                                             target_user, cc_source,
394*7f2fe78bSCy Schubert                                             options, cmd, localhostname,
395*7f2fe78bSCy Schubert                                             &client, &hp))){
396*7f2fe78bSCy Schubert         com_err(prog_name,retval, _("while selecting the best principal"));
397*7f2fe78bSCy Schubert         exit(1);
398*7f2fe78bSCy Schubert     }
399*7f2fe78bSCy Schubert 
400*7f2fe78bSCy Schubert     /* We may be running as either source or target, depending on
401*7f2fe78bSCy Schubert        what happened; become source.*/
402*7f2fe78bSCy Schubert     if ( geteuid() != source_uid) {
403*7f2fe78bSCy Schubert         if (krb5_seteuid(0) || krb5_seteuid(source_uid) ) {
404*7f2fe78bSCy Schubert             com_err(prog_name, errno, _("while returning to source uid after "
405*7f2fe78bSCy Schubert                                         "finding best principal"));
406*7f2fe78bSCy Schubert             exit(1);
407*7f2fe78bSCy Schubert         }
408*7f2fe78bSCy Schubert     }
409*7f2fe78bSCy Schubert 
410*7f2fe78bSCy Schubert     if (auth_debug){
411*7f2fe78bSCy Schubert         if (hp){
412*7f2fe78bSCy Schubert             fprintf(stderr,
413*7f2fe78bSCy Schubert                     "GET_best_princ_for_target result: NOT AUTHORIZED\n");
414*7f2fe78bSCy Schubert         }else{
415*7f2fe78bSCy Schubert             fprintf(stderr,
416*7f2fe78bSCy Schubert                     "GET_best_princ_for_target result-best principal ");
417*7f2fe78bSCy Schubert             plain_dump_principal (ksu_context, client);
418*7f2fe78bSCy Schubert             fprintf(stderr,"\n");
419*7f2fe78bSCy Schubert         }
420*7f2fe78bSCy Schubert     }
421*7f2fe78bSCy Schubert 
422*7f2fe78bSCy Schubert     if (hp){
423*7f2fe78bSCy Schubert         if (gb_err) fprintf(stderr, "%s", gb_err);
424*7f2fe78bSCy Schubert         fprintf(stderr, _("account %s: authorization failed\n"), target_user);
425*7f2fe78bSCy Schubert 
426*7f2fe78bSCy Schubert         if (cmd != NULL) {
427*7f2fe78bSCy Schubert             syslog(LOG_WARNING,
428*7f2fe78bSCy Schubert                    "Account %s: authorization for %s for execution of %s failed",
429*7f2fe78bSCy Schubert                    target_user, source_user, cmd);
430*7f2fe78bSCy Schubert         } else {
431*7f2fe78bSCy Schubert             syslog(LOG_WARNING, "Account %s: authorization of %s failed",
432*7f2fe78bSCy Schubert                    target_user, source_user);
433*7f2fe78bSCy Schubert         }
434*7f2fe78bSCy Schubert 
435*7f2fe78bSCy Schubert         exit(1);
436*7f2fe78bSCy Schubert     }
437*7f2fe78bSCy Schubert 
438*7f2fe78bSCy Schubert     if (auth_debug)
439*7f2fe78bSCy Schubert         fprintf(stderr, " source cache =  %s\n", cc_source_tag);
440*7f2fe78bSCy Schubert 
441*7f2fe78bSCy Schubert     /*
442*7f2fe78bSCy Schubert      * After proper authentication and authorization, populate a cache for the
443*7f2fe78bSCy Schubert      * target user.
444*7f2fe78bSCy Schubert      */
445*7f2fe78bSCy Schubert 
446*7f2fe78bSCy Schubert     /*
447*7f2fe78bSCy Schubert      * We read the set of creds we want to copy from the source ccache as the
448*7f2fe78bSCy Schubert      * source uid, become root for authentication, and then become the target
449*7f2fe78bSCy Schubert      * user to handle authorization and creating the target user's cache.
450*7f2fe78bSCy Schubert      */
451*7f2fe78bSCy Schubert 
452*7f2fe78bSCy Schubert     /* if root ksu's to a regular user, then
453*7f2fe78bSCy Schubert        then only the credentials for that particular user
454*7f2fe78bSCy Schubert        should be copied */
455*7f2fe78bSCy Schubert 
456*7f2fe78bSCy Schubert     restrict_creds = (source_uid == 0) && (target_uid != 0);
457*7f2fe78bSCy Schubert     retval = krb5_parse_name(ksu_context, KS_TEMPORARY_PRINC, &tmp_princ);
458*7f2fe78bSCy Schubert     if (retval) {
459*7f2fe78bSCy Schubert         com_err(prog_name, retval, _("while parsing temporary name"));
460*7f2fe78bSCy Schubert         exit(1);
461*7f2fe78bSCy Schubert     }
462*7f2fe78bSCy Schubert     retval = krb5_cc_resolve(ksu_context, KS_TEMPORARY_CACHE, &cc_tmp);
463*7f2fe78bSCy Schubert     if (retval) {
464*7f2fe78bSCy Schubert         com_err(prog_name, retval, _("while creating temporary cache"));
465*7f2fe78bSCy Schubert         exit(1);
466*7f2fe78bSCy Schubert     }
467*7f2fe78bSCy Schubert     retval = krb5_ccache_copy(ksu_context, cc_source, tmp_princ, cc_tmp,
468*7f2fe78bSCy Schubert                               restrict_creds, client, &stored);
469*7f2fe78bSCy Schubert     if (retval) {
470*7f2fe78bSCy Schubert         com_err(prog_name, retval, _("while copying cache %s to %s"),
471*7f2fe78bSCy Schubert                 krb5_cc_get_name(ksu_context, cc_source), KS_TEMPORARY_CACHE);
472*7f2fe78bSCy Schubert         exit(1);
473*7f2fe78bSCy Schubert     }
474*7f2fe78bSCy Schubert     krb5_cc_close(ksu_context, cc_source);
475*7f2fe78bSCy Schubert 
476*7f2fe78bSCy Schubert     krb5_get_init_creds_opt_set_out_ccache(ksu_context, options, cc_tmp);
477*7f2fe78bSCy Schubert 
478*7f2fe78bSCy Schubert     /* Become root for authentication*/
479*7f2fe78bSCy Schubert 
480*7f2fe78bSCy Schubert     if (krb5_seteuid(0)) {
481*7f2fe78bSCy Schubert         com_err(prog_name, errno, _("while reclaiming root uid"));
482*7f2fe78bSCy Schubert         exit(1);
483*7f2fe78bSCy Schubert     }
484*7f2fe78bSCy Schubert 
485*7f2fe78bSCy Schubert     if ((source_uid == 0) || (target_uid == source_uid)){
486*7f2fe78bSCy Schubert #ifdef GET_TGT_VIA_PASSWD
487*7f2fe78bSCy Schubert         if (!all_rest_copy && given_princ && client != NULL && !stored) {
488*7f2fe78bSCy Schubert             fprintf(stderr, _("WARNING: Your password may be exposed if you "
489*7f2fe78bSCy Schubert                               "enter it here and are logged\n"));
490*7f2fe78bSCy Schubert             fprintf(stderr, _("         in remotely using an unsecure "
491*7f2fe78bSCy Schubert                               "(non-encrypted) channel.\n"));
492*7f2fe78bSCy Schubert             if (ksu_get_tgt_via_passwd(ksu_context, client, options,
493*7f2fe78bSCy Schubert                                        &zero_password, NULL) == FALSE) {
494*7f2fe78bSCy Schubert 
495*7f2fe78bSCy Schubert                 if (zero_password == FALSE){
496*7f2fe78bSCy Schubert                     fprintf(stderr, _("Goodbye\n"));
497*7f2fe78bSCy Schubert                     exit(1);
498*7f2fe78bSCy Schubert                 }
499*7f2fe78bSCy Schubert 
500*7f2fe78bSCy Schubert                 fprintf(stderr, _("Could not get a tgt for "));
501*7f2fe78bSCy Schubert                 plain_dump_principal (ksu_context, client);
502*7f2fe78bSCy Schubert                 fprintf(stderr, "\n");
503*7f2fe78bSCy Schubert 
504*7f2fe78bSCy Schubert             }
505*7f2fe78bSCy Schubert             stored = TRUE;
506*7f2fe78bSCy Schubert         }
507*7f2fe78bSCy Schubert #endif /* GET_TGT_VIA_PASSWD */
508*7f2fe78bSCy Schubert     }
509*7f2fe78bSCy Schubert 
510*7f2fe78bSCy Schubert     /* if the user is root or same uid then authentication is not necessary,
511*7f2fe78bSCy Schubert        root gets in automatically */
512*7f2fe78bSCy Schubert 
513*7f2fe78bSCy Schubert     if (source_uid && (source_uid != target_uid)) {
514*7f2fe78bSCy Schubert         char * client_name;
515*7f2fe78bSCy Schubert 
516*7f2fe78bSCy Schubert         auth_val = krb5_auth_check(ksu_context, client, localhostname,
517*7f2fe78bSCy Schubert                                    options, target_user, cc_tmp,
518*7f2fe78bSCy Schubert                                    &path_passwd, target_uid);
519*7f2fe78bSCy Schubert 
520*7f2fe78bSCy Schubert         /* if Kerberos authentication failed then exit */
521*7f2fe78bSCy Schubert         if (auth_val ==FALSE){
522*7f2fe78bSCy Schubert             fprintf(stderr, _("Authentication failed.\n"));
523*7f2fe78bSCy Schubert             syslog(LOG_WARNING, "'%s %s' authentication failed for %s%s",
524*7f2fe78bSCy Schubert                    prog_name,target_user,source_user,ontty());
525*7f2fe78bSCy Schubert             exit(1);
526*7f2fe78bSCy Schubert         }
527*7f2fe78bSCy Schubert         stored = TRUE;
528*7f2fe78bSCy Schubert 
529*7f2fe78bSCy Schubert         if ((retval = krb5_unparse_name(ksu_context, client, &client_name))) {
530*7f2fe78bSCy Schubert             com_err(prog_name, retval, _("When unparsing name"));
531*7f2fe78bSCy Schubert             exit(1);
532*7f2fe78bSCy Schubert         }
533*7f2fe78bSCy Schubert 
534*7f2fe78bSCy Schubert         print_status(_("Authenticated %s\n"), client_name);
535*7f2fe78bSCy Schubert         syslog(LOG_NOTICE,"'%s %s' authenticated %s for %s%s",
536*7f2fe78bSCy Schubert                prog_name,target_user,client_name,
537*7f2fe78bSCy Schubert                source_user,ontty());
538*7f2fe78bSCy Schubert 
539*7f2fe78bSCy Schubert         /* Run authorization as target.*/
540*7f2fe78bSCy Schubert         if (krb5_seteuid(target_uid)) {
541*7f2fe78bSCy Schubert             com_err(prog_name, errno, _("while switching to target for "
542*7f2fe78bSCy Schubert                                         "authorization check"));
543*7f2fe78bSCy Schubert             exit(1);
544*7f2fe78bSCy Schubert         }
545*7f2fe78bSCy Schubert 
546*7f2fe78bSCy Schubert         if ((retval = krb5_authorization(ksu_context, client,target_user,
547*7f2fe78bSCy Schubert                                          cmd, &authorization_val, &exec_cmd))){
548*7f2fe78bSCy Schubert             com_err(prog_name,retval, _("while checking authorization"));
549*7f2fe78bSCy Schubert             krb5_seteuid(0); /*So we have some chance of sweeping up*/
550*7f2fe78bSCy Schubert             exit(1);
551*7f2fe78bSCy Schubert         }
552*7f2fe78bSCy Schubert 
553*7f2fe78bSCy Schubert         if (krb5_seteuid(0)) {
554*7f2fe78bSCy Schubert             com_err(prog_name, errno, _("while switching back from target "
555*7f2fe78bSCy Schubert                                         "after authorization check"));
556*7f2fe78bSCy Schubert             exit(1);
557*7f2fe78bSCy Schubert         }
558*7f2fe78bSCy Schubert         if (authorization_val == TRUE){
559*7f2fe78bSCy Schubert 
560*7f2fe78bSCy Schubert             if (cmd) {
561*7f2fe78bSCy Schubert                 print_status(_("Account %s: authorization for %s for "
562*7f2fe78bSCy Schubert                                "execution of\n"), target_user, client_name);
563*7f2fe78bSCy Schubert                 print_status(_("               %s successful\n"), exec_cmd);
564*7f2fe78bSCy Schubert                 syslog(LOG_NOTICE,
565*7f2fe78bSCy Schubert                        "Account %s: authorization for %s for execution of %s successful",
566*7f2fe78bSCy Schubert                        target_user, client_name, exec_cmd);
567*7f2fe78bSCy Schubert 
568*7f2fe78bSCy Schubert             }else{
569*7f2fe78bSCy Schubert                 print_status(_("Account %s: authorization for %s "
570*7f2fe78bSCy Schubert                                "successful\n"), target_user, client_name);
571*7f2fe78bSCy Schubert                 syslog(LOG_NOTICE,
572*7f2fe78bSCy Schubert                        "Account %s: authorization for %s successful",
573*7f2fe78bSCy Schubert                        target_user, client_name);
574*7f2fe78bSCy Schubert             }
575*7f2fe78bSCy Schubert         }else {
576*7f2fe78bSCy Schubert             if (cmd){
577*7f2fe78bSCy Schubert                 if (exec_cmd){ /* was used to pass back the error msg */
578*7f2fe78bSCy Schubert                     fprintf(stderr, "%s", exec_cmd );
579*7f2fe78bSCy Schubert                     syslog(LOG_WARNING, "%s",exec_cmd);
580*7f2fe78bSCy Schubert                 }
581*7f2fe78bSCy Schubert                 fprintf(stderr, _("Account %s: authorization for %s for "
582*7f2fe78bSCy Schubert                                   "execution of %s failed\n"),
583*7f2fe78bSCy Schubert                         target_user, client_name, cmd );
584*7f2fe78bSCy Schubert                 syslog(LOG_WARNING,
585*7f2fe78bSCy Schubert                        "Account %s: authorization for %s for execution of %s failed",
586*7f2fe78bSCy Schubert                        target_user, client_name, cmd );
587*7f2fe78bSCy Schubert 
588*7f2fe78bSCy Schubert             }else{
589*7f2fe78bSCy Schubert                 fprintf(stderr, _("Account %s: authorization of %s failed\n"),
590*7f2fe78bSCy Schubert                         target_user, client_name);
591*7f2fe78bSCy Schubert                 syslog(LOG_WARNING,
592*7f2fe78bSCy Schubert                        "Account %s: authorization of %s failed",
593*7f2fe78bSCy Schubert                        target_user, client_name);
594*7f2fe78bSCy Schubert 
595*7f2fe78bSCy Schubert             }
596*7f2fe78bSCy Schubert 
597*7f2fe78bSCy Schubert             exit(1);
598*7f2fe78bSCy Schubert         }
599*7f2fe78bSCy Schubert     }
600*7f2fe78bSCy Schubert 
601*7f2fe78bSCy Schubert     if( some_rest_copy){
602*7f2fe78bSCy Schubert         retval = krb5_ccache_filter(ksu_context, cc_tmp, client);
603*7f2fe78bSCy Schubert         if (retval) {
604*7f2fe78bSCy Schubert             com_err(prog_name,retval, _("while calling cc_filter"));
605*7f2fe78bSCy Schubert             exit(1);
606*7f2fe78bSCy Schubert         }
607*7f2fe78bSCy Schubert     }
608*7f2fe78bSCy Schubert 
609*7f2fe78bSCy Schubert     if (all_rest_copy){
610*7f2fe78bSCy Schubert         retval = krb5_cc_initialize(ksu_context, cc_tmp, tmp_princ);
611*7f2fe78bSCy Schubert         if (retval) {
612*7f2fe78bSCy Schubert             com_err(prog_name, retval, _("while erasing target cache"));
613*7f2fe78bSCy Schubert             exit(1);
614*7f2fe78bSCy Schubert         }
615*7f2fe78bSCy Schubert         stored = FALSE;
616*7f2fe78bSCy Schubert     }
617*7f2fe78bSCy Schubert 
618*7f2fe78bSCy Schubert     /* get the shell of the user, this will be the shell used by su */
619*7f2fe78bSCy Schubert     target_pwd = getpwnam(target_user);
620*7f2fe78bSCy Schubert 
621*7f2fe78bSCy Schubert     if (target_pwd->pw_shell)
622*7f2fe78bSCy Schubert         shell = xstrdup(target_pwd->pw_shell);
623*7f2fe78bSCy Schubert     else {
624*7f2fe78bSCy Schubert         shell = _DEF_CSH;  /* default is cshell */
625*7f2fe78bSCy Schubert     }
626*7f2fe78bSCy Schubert 
627*7f2fe78bSCy Schubert #ifdef HAVE_GETUSERSHELL
628*7f2fe78bSCy Schubert 
629*7f2fe78bSCy Schubert     /* insist that the target login uses a standard shell (root is omitted) */
630*7f2fe78bSCy Schubert 
631*7f2fe78bSCy Schubert     if (!standard_shell(target_pwd->pw_shell) && source_uid) {
632*7f2fe78bSCy Schubert         fprintf(stderr, _("ksu: permission denied (shell).\n"));
633*7f2fe78bSCy Schubert         exit(1);
634*7f2fe78bSCy Schubert     }
635*7f2fe78bSCy Schubert #endif /* HAVE_GETUSERSHELL */
636*7f2fe78bSCy Schubert 
637*7f2fe78bSCy Schubert     if (target_pwd->pw_uid){
638*7f2fe78bSCy Schubert 
639*7f2fe78bSCy Schubert         if(set_env_var("USER", target_pwd->pw_name)){
640*7f2fe78bSCy Schubert             fprintf(stderr,
641*7f2fe78bSCy Schubert                     _("ksu: couldn't set environment variable USER\n"));
642*7f2fe78bSCy Schubert             exit(1);
643*7f2fe78bSCy Schubert         }
644*7f2fe78bSCy Schubert     }
645*7f2fe78bSCy Schubert 
646*7f2fe78bSCy Schubert     if(set_env_var( "HOME", target_pwd->pw_dir)){
647*7f2fe78bSCy Schubert         fprintf(stderr, _("ksu: couldn't set environment variable HOME\n"));
648*7f2fe78bSCy Schubert         exit(1);
649*7f2fe78bSCy Schubert     }
650*7f2fe78bSCy Schubert 
651*7f2fe78bSCy Schubert     if(set_env_var( "SHELL", shell)){
652*7f2fe78bSCy Schubert         fprintf(stderr, _("ksu: couldn't set environment variable SHELL\n"));
653*7f2fe78bSCy Schubert         exit(1);
654*7f2fe78bSCy Schubert     }
655*7f2fe78bSCy Schubert 
656*7f2fe78bSCy Schubert     /* set permissions */
657*7f2fe78bSCy Schubert     if (setgid(target_pwd->pw_gid) < 0) {
658*7f2fe78bSCy Schubert         perror("ksu: setgid");
659*7f2fe78bSCy Schubert         exit(1);
660*7f2fe78bSCy Schubert     }
661*7f2fe78bSCy Schubert 
662*7f2fe78bSCy Schubert     if (initgroups(target_user, target_pwd->pw_gid)) {
663*7f2fe78bSCy Schubert         fprintf(stderr, _("ksu: initgroups failed.\n"));
664*7f2fe78bSCy Schubert         exit(1);
665*7f2fe78bSCy Schubert     }
666*7f2fe78bSCy Schubert 
667*7f2fe78bSCy Schubert     if ( ! strcmp(target_user, source_user)){
668*7f2fe78bSCy Schubert         print_status(_("Leaving uid as %s (%ld)\n"),
669*7f2fe78bSCy Schubert                      target_user, (long) target_pwd->pw_uid);
670*7f2fe78bSCy Schubert     }else{
671*7f2fe78bSCy Schubert         print_status(_("Changing uid to %s (%ld)\n"),
672*7f2fe78bSCy Schubert                      target_user, (long) target_pwd->pw_uid);
673*7f2fe78bSCy Schubert     }
674*7f2fe78bSCy Schubert 
675*7f2fe78bSCy Schubert #ifdef  HAVE_SETLUID
676*7f2fe78bSCy Schubert     /*
677*7f2fe78bSCy Schubert      * If we're on a system which keeps track of login uids, then
678*7f2fe78bSCy Schubert      * set the login uid. If this fails this opens up a problem on DEC OSF
679*7f2fe78bSCy Schubert      * with C2 enabled.
680*7f2fe78bSCy Schubert      */
681*7f2fe78bSCy Schubert     if (setluid((uid_t) pwd->pw_uid) < 0) {
682*7f2fe78bSCy Schubert         perror("setluid");
683*7f2fe78bSCy Schubert         exit(1);
684*7f2fe78bSCy Schubert     }
685*7f2fe78bSCy Schubert #endif  /* HAVE_SETLUID */
686*7f2fe78bSCy Schubert 
687*7f2fe78bSCy Schubert     if (setuid(target_pwd->pw_uid) < 0) {
688*7f2fe78bSCy Schubert         perror("ksu: setuid");
689*7f2fe78bSCy Schubert         exit(1);
690*7f2fe78bSCy Schubert     }
691*7f2fe78bSCy Schubert 
692*7f2fe78bSCy Schubert     retval = resolve_target_cache(ksu_context, client, &cc_target, &cc_reused);
693*7f2fe78bSCy Schubert     if (retval)
694*7f2fe78bSCy Schubert         exit(1);
695*7f2fe78bSCy Schubert     retval = krb5_cc_get_full_name(ksu_context, cc_target, &cc_target_tag);
696*7f2fe78bSCy Schubert     if (retval) {
697*7f2fe78bSCy Schubert         com_err(prog_name, retval, _("while getting name of target ccache"));
698*7f2fe78bSCy Schubert         sweep_up(ksu_context, cc_target);
699*7f2fe78bSCy Schubert         exit(1);
700*7f2fe78bSCy Schubert     }
701*7f2fe78bSCy Schubert     if (auth_debug)
702*7f2fe78bSCy Schubert         fprintf(stderr, " target cache =  %s\n", cc_target_tag);
703*7f2fe78bSCy Schubert     if (cc_reused)
704*7f2fe78bSCy Schubert         keep_target_cache = TRUE;
705*7f2fe78bSCy Schubert 
706*7f2fe78bSCy Schubert     if (stored) {
707*7f2fe78bSCy Schubert         retval = krb5_ccache_copy(ksu_context, cc_tmp, client, cc_target,
708*7f2fe78bSCy Schubert                                   FALSE, client, &stored);
709*7f2fe78bSCy Schubert         if (retval) {
710*7f2fe78bSCy Schubert             com_err(prog_name, retval, _("while copying cache %s to %s"),
711*7f2fe78bSCy Schubert                     KS_TEMPORARY_CACHE, cc_target_tag);
712*7f2fe78bSCy Schubert             exit(1);
713*7f2fe78bSCy Schubert         }
714*7f2fe78bSCy Schubert 
715*7f2fe78bSCy Schubert         if (!ks_ccache_is_initialized(ksu_context, cc_target)) {
716*7f2fe78bSCy Schubert             com_err(prog_name, errno,
717*7f2fe78bSCy Schubert                     _("%s does not have correct permissions for %s, "
718*7f2fe78bSCy Schubert                       "%s aborted"), target_user, cc_target_tag, prog_name);
719*7f2fe78bSCy Schubert             exit(1);
720*7f2fe78bSCy Schubert         }
721*7f2fe78bSCy Schubert     }
722*7f2fe78bSCy Schubert 
723*7f2fe78bSCy Schubert     krb5_free_string(ksu_context, cc_target_tag);
724*7f2fe78bSCy Schubert 
725*7f2fe78bSCy Schubert     /* Set the cc env name to target. */
726*7f2fe78bSCy Schubert     retval = set_ccname_env(ksu_context, cc_target);
727*7f2fe78bSCy Schubert     if (retval != 0) {
728*7f2fe78bSCy Schubert         sweep_up(ksu_context, cc_target);
729*7f2fe78bSCy Schubert         exit(1);
730*7f2fe78bSCy Schubert     }
731*7f2fe78bSCy Schubert 
732*7f2fe78bSCy Schubert     if (cmd){
733*7f2fe78bSCy Schubert         if ((source_uid == 0) || (source_uid == target_uid )){
734*7f2fe78bSCy Schubert             exec_cmd = cmd;
735*7f2fe78bSCy Schubert         }
736*7f2fe78bSCy Schubert 
737*7f2fe78bSCy Schubert         if( !exec_cmd){
738*7f2fe78bSCy Schubert             fprintf(stderr, _("Internal error: command %s did not get "
739*7f2fe78bSCy Schubert                               "resolved\n"), cmd);
740*7f2fe78bSCy Schubert             exit(1);
741*7f2fe78bSCy Schubert         }
742*7f2fe78bSCy Schubert 
743*7f2fe78bSCy Schubert         params[0] = exec_cmd;
744*7f2fe78bSCy Schubert     }
745*7f2fe78bSCy Schubert     else{
746*7f2fe78bSCy Schubert         params[0] = shell;
747*7f2fe78bSCy Schubert     }
748*7f2fe78bSCy Schubert 
749*7f2fe78bSCy Schubert     if (auth_debug){
750*7f2fe78bSCy Schubert         fprintf(stderr, "program to be execed %s\n",params[0]);
751*7f2fe78bSCy Schubert     }
752*7f2fe78bSCy Schubert 
753*7f2fe78bSCy Schubert     if( keep_target_cache ) {
754*7f2fe78bSCy Schubert         execv(params[0], params);
755*7f2fe78bSCy Schubert         com_err(prog_name, errno, _("while trying to execv %s"), params[0]);
756*7f2fe78bSCy Schubert         sweep_up(ksu_context, cc_target);
757*7f2fe78bSCy Schubert         exit(1);
758*7f2fe78bSCy Schubert     }else{
759*7f2fe78bSCy Schubert         statusp = 1;
760*7f2fe78bSCy Schubert         switch ((child_pid = fork())) {
761*7f2fe78bSCy Schubert         default:
762*7f2fe78bSCy Schubert             if (auth_debug){
763*7f2fe78bSCy Schubert                 printf(" The child pid is %ld\n", (long) child_pid);
764*7f2fe78bSCy Schubert                 printf(" The parent pid is %ld\n", (long) getpid());
765*7f2fe78bSCy Schubert             }
766*7f2fe78bSCy Schubert             while ((ret_pid = waitpid(child_pid, &statusp, WUNTRACED)) != -1) {
767*7f2fe78bSCy Schubert                 if (WIFSTOPPED(statusp)) {
768*7f2fe78bSCy Schubert                     child_pgrp = tcgetpgrp(1);
769*7f2fe78bSCy Schubert                     kill(getpid(), SIGSTOP);
770*7f2fe78bSCy Schubert                     tcsetpgrp(1, child_pgrp);
771*7f2fe78bSCy Schubert                     kill(child_pid, SIGCONT);
772*7f2fe78bSCy Schubert                     statusp = 1;
773*7f2fe78bSCy Schubert                     continue;
774*7f2fe78bSCy Schubert                 }
775*7f2fe78bSCy Schubert                 break;
776*7f2fe78bSCy Schubert             }
777*7f2fe78bSCy Schubert             if (auth_debug){
778*7f2fe78bSCy Schubert                 printf("The exit status of the child is %d\n", statusp);
779*7f2fe78bSCy Schubert             }
780*7f2fe78bSCy Schubert             if (ret_pid == -1) {
781*7f2fe78bSCy Schubert                 com_err(prog_name, errno, _("while calling waitpid"));
782*7f2fe78bSCy Schubert             }
783*7f2fe78bSCy Schubert             sweep_up(ksu_context, cc_target);
784*7f2fe78bSCy Schubert             exit (statusp);
785*7f2fe78bSCy Schubert         case -1:
786*7f2fe78bSCy Schubert             com_err(prog_name, errno, _("while trying to fork."));
787*7f2fe78bSCy Schubert             sweep_up(ksu_context, cc_target);
788*7f2fe78bSCy Schubert             exit (1);
789*7f2fe78bSCy Schubert         case 0:
790*7f2fe78bSCy Schubert             execv(params[0], params);
791*7f2fe78bSCy Schubert             com_err(prog_name, errno, _("while trying to execv %s"),
792*7f2fe78bSCy Schubert                     params[0]);
793*7f2fe78bSCy Schubert             exit (1);
794*7f2fe78bSCy Schubert         }
795*7f2fe78bSCy Schubert     }
796*7f2fe78bSCy Schubert }
797*7f2fe78bSCy Schubert 
798*7f2fe78bSCy Schubert static krb5_error_code
init_ksu_context(krb5_context * context_out)799*7f2fe78bSCy Schubert init_ksu_context(krb5_context *context_out)
800*7f2fe78bSCy Schubert {
801*7f2fe78bSCy Schubert     krb5_error_code retval;
802*7f2fe78bSCy Schubert     const char *env_ccname;
803*7f2fe78bSCy Schubert     krb5_context context;
804*7f2fe78bSCy Schubert 
805*7f2fe78bSCy Schubert     *context_out = NULL;
806*7f2fe78bSCy Schubert 
807*7f2fe78bSCy Schubert     retval = krb5_init_secure_context(&context);
808*7f2fe78bSCy Schubert     if (retval)
809*7f2fe78bSCy Schubert         return retval;
810*7f2fe78bSCy Schubert 
811*7f2fe78bSCy Schubert     /* We want to obey KRB5CCNAME in this context even though this is a setuid
812*7f2fe78bSCy Schubert      * program.  (It will only be used when operating as the real uid.) */
813*7f2fe78bSCy Schubert     env_ccname = getenv(KRB5_ENV_CCNAME);
814*7f2fe78bSCy Schubert     if (env_ccname != NULL) {
815*7f2fe78bSCy Schubert         retval = krb5_cc_set_default_name(context, env_ccname);
816*7f2fe78bSCy Schubert         if (retval) {
817*7f2fe78bSCy Schubert             krb5_free_context(context);
818*7f2fe78bSCy Schubert             return retval;
819*7f2fe78bSCy Schubert         }
820*7f2fe78bSCy Schubert     }
821*7f2fe78bSCy Schubert 
822*7f2fe78bSCy Schubert     *context_out = context;
823*7f2fe78bSCy Schubert     return 0;
824*7f2fe78bSCy Schubert }
825*7f2fe78bSCy Schubert 
826*7f2fe78bSCy Schubert /* Set KRB5CCNAME in the environment to point to ccache.  Print an error
827*7f2fe78bSCy Schubert  * message on failure. */
828*7f2fe78bSCy Schubert static krb5_error_code
set_ccname_env(krb5_context ksu_context,krb5_ccache ccache)829*7f2fe78bSCy Schubert set_ccname_env(krb5_context ksu_context, krb5_ccache ccache)
830*7f2fe78bSCy Schubert {
831*7f2fe78bSCy Schubert     krb5_error_code retval;
832*7f2fe78bSCy Schubert     char *ccname;
833*7f2fe78bSCy Schubert 
834*7f2fe78bSCy Schubert     retval = krb5_cc_get_full_name(ksu_context, ccache, &ccname);
835*7f2fe78bSCy Schubert     if (retval) {
836*7f2fe78bSCy Schubert         com_err(prog_name, retval, _("while reading cache name from ccache"));
837*7f2fe78bSCy Schubert         return retval;
838*7f2fe78bSCy Schubert     }
839*7f2fe78bSCy Schubert     if (set_env_var(KRB5_ENV_CCNAME, ccname)) {
840*7f2fe78bSCy Schubert         retval = errno;
841*7f2fe78bSCy Schubert         fprintf(stderr,
842*7f2fe78bSCy Schubert                 _("ksu: couldn't set environment variable %s\n"),
843*7f2fe78bSCy Schubert                 KRB5_ENV_CCNAME);
844*7f2fe78bSCy Schubert     }
845*7f2fe78bSCy Schubert     krb5_free_string(ksu_context, ccname);
846*7f2fe78bSCy Schubert     return retval;
847*7f2fe78bSCy Schubert }
848*7f2fe78bSCy Schubert 
849*7f2fe78bSCy Schubert /*
850*7f2fe78bSCy Schubert  * Get the configured default ccache name.  Unset KRB5CCNAME and force a
851*7f2fe78bSCy Schubert  * recomputation so we don't use values for the source user.  Print an error
852*7f2fe78bSCy Schubert  * message on failure.
853*7f2fe78bSCy Schubert  */
854*7f2fe78bSCy Schubert static krb5_error_code
get_configured_defccname(krb5_context context,char ** target_out)855*7f2fe78bSCy Schubert get_configured_defccname(krb5_context context, char **target_out)
856*7f2fe78bSCy Schubert {
857*7f2fe78bSCy Schubert     krb5_error_code retval;
858*7f2fe78bSCy Schubert     const char *defname;
859*7f2fe78bSCy Schubert     char *target = NULL;
860*7f2fe78bSCy Schubert 
861*7f2fe78bSCy Schubert     *target_out = NULL;
862*7f2fe78bSCy Schubert 
863*7f2fe78bSCy Schubert     unsetenv(KRB5_ENV_CCNAME);
864*7f2fe78bSCy Schubert 
865*7f2fe78bSCy Schubert     /* Make sure we don't have a cached value for a different uid. */
866*7f2fe78bSCy Schubert     retval = krb5_cc_set_default_name(context, NULL);
867*7f2fe78bSCy Schubert     if (retval != 0) {
868*7f2fe78bSCy Schubert         com_err(prog_name, retval, _("while resetting target ccache name"));
869*7f2fe78bSCy Schubert         return retval;
870*7f2fe78bSCy Schubert     }
871*7f2fe78bSCy Schubert 
872*7f2fe78bSCy Schubert     defname = krb5_cc_default_name(context);
873*7f2fe78bSCy Schubert     if (defname != NULL) {
874*7f2fe78bSCy Schubert         if (strchr(defname, ':') != NULL) {
875*7f2fe78bSCy Schubert             target = strdup(defname);
876*7f2fe78bSCy Schubert         } else {
877*7f2fe78bSCy Schubert             if (asprintf(&target, "FILE:%s", defname) < 0)
878*7f2fe78bSCy Schubert                 target = NULL;
879*7f2fe78bSCy Schubert         }
880*7f2fe78bSCy Schubert     }
881*7f2fe78bSCy Schubert     if (target == NULL) {
882*7f2fe78bSCy Schubert         com_err(prog_name, ENOMEM, _("while determining target ccache name"));
883*7f2fe78bSCy Schubert         return ENOMEM;
884*7f2fe78bSCy Schubert     }
885*7f2fe78bSCy Schubert     *target_out = target;
886*7f2fe78bSCy Schubert     return 0;
887*7f2fe78bSCy Schubert }
888*7f2fe78bSCy Schubert 
889*7f2fe78bSCy Schubert /* Determine where the target user's creds should be stored.  Print an error
890*7f2fe78bSCy Schubert  * message on failure. */
891*7f2fe78bSCy Schubert static krb5_error_code
resolve_target_cache(krb5_context context,krb5_principal princ,krb5_ccache * ccache_out,krb5_boolean * ccache_reused)892*7f2fe78bSCy Schubert resolve_target_cache(krb5_context context, krb5_principal princ,
893*7f2fe78bSCy Schubert                      krb5_ccache *ccache_out, krb5_boolean *ccache_reused)
894*7f2fe78bSCy Schubert {
895*7f2fe78bSCy Schubert     krb5_error_code retval;
896*7f2fe78bSCy Schubert     krb5_boolean switchable, reused = FALSE;
897*7f2fe78bSCy Schubert     krb5_ccache ccache = NULL;
898*7f2fe78bSCy Schubert     char *sep, *ccname = NULL, *sym = NULL, *target;
899*7f2fe78bSCy Schubert 
900*7f2fe78bSCy Schubert     *ccache_out = NULL;
901*7f2fe78bSCy Schubert     *ccache_reused = FALSE;
902*7f2fe78bSCy Schubert 
903*7f2fe78bSCy Schubert     retval = get_configured_defccname(context, &target);
904*7f2fe78bSCy Schubert     if (retval != 0)
905*7f2fe78bSCy Schubert         return retval;
906*7f2fe78bSCy Schubert 
907*7f2fe78bSCy Schubert     /* Check if the configured default name uses a switchable type. */
908*7f2fe78bSCy Schubert     sep = strchr(target, ':');
909*7f2fe78bSCy Schubert     *sep = '\0';
910*7f2fe78bSCy Schubert     switchable = krb5_cc_support_switch(context, target);
911*7f2fe78bSCy Schubert     *sep = ':';
912*7f2fe78bSCy Schubert 
913*7f2fe78bSCy Schubert     if (!switchable) {
914*7f2fe78bSCy Schubert         /* Try to avoid destroying an in-use target ccache by coming up with
915*7f2fe78bSCy Schubert          * the name of a cache that doesn't exist yet. */
916*7f2fe78bSCy Schubert         do {
917*7f2fe78bSCy Schubert             free(ccname);
918*7f2fe78bSCy Schubert             retval = gen_sym(context, &sym);
919*7f2fe78bSCy Schubert             if (retval) {
920*7f2fe78bSCy Schubert                 com_err(prog_name, retval,
921*7f2fe78bSCy Schubert                         _("while generating part of the target ccache name"));
922*7f2fe78bSCy Schubert                 return retval;
923*7f2fe78bSCy Schubert             }
924*7f2fe78bSCy Schubert             if (asprintf(&ccname, "%s.%s", target, sym) < 0) {
925*7f2fe78bSCy Schubert                 retval = ENOMEM;
926*7f2fe78bSCy Schubert                 free(sym);
927*7f2fe78bSCy Schubert                 com_err(prog_name, retval, _("while allocating memory for the "
928*7f2fe78bSCy Schubert                                              "target ccache name"));
929*7f2fe78bSCy Schubert                 goto cleanup;
930*7f2fe78bSCy Schubert             }
931*7f2fe78bSCy Schubert             free(sym);
932*7f2fe78bSCy Schubert         } while (ks_ccache_name_is_initialized(context, ccname));
933*7f2fe78bSCy Schubert         retval = krb5_cc_resolve(context, ccname, &ccache);
934*7f2fe78bSCy Schubert     } else {
935*7f2fe78bSCy Schubert         /* Look for a cache in the collection that we can reuse. */
936*7f2fe78bSCy Schubert         retval = krb5_cc_cache_match(context, princ, &ccache);
937*7f2fe78bSCy Schubert         if (retval == 0) {
938*7f2fe78bSCy Schubert             reused = TRUE;
939*7f2fe78bSCy Schubert         } else {
940*7f2fe78bSCy Schubert             /* There isn't one, so create a new one. */
941*7f2fe78bSCy Schubert             *sep = '\0';
942*7f2fe78bSCy Schubert             retval = krb5_cc_new_unique(context, target, NULL, &ccache);
943*7f2fe78bSCy Schubert             *sep = ':';
944*7f2fe78bSCy Schubert             if (retval) {
945*7f2fe78bSCy Schubert                 com_err(prog_name, retval,
946*7f2fe78bSCy Schubert                         _("while creating new target ccache"));
947*7f2fe78bSCy Schubert                 goto cleanup;
948*7f2fe78bSCy Schubert             }
949*7f2fe78bSCy Schubert             retval = krb5_cc_initialize(context, ccache, princ);
950*7f2fe78bSCy Schubert             if (retval) {
951*7f2fe78bSCy Schubert                 com_err(prog_name, retval,
952*7f2fe78bSCy Schubert                         _("while initializing target cache"));
953*7f2fe78bSCy Schubert                 goto cleanup;
954*7f2fe78bSCy Schubert             }
955*7f2fe78bSCy Schubert         }
956*7f2fe78bSCy Schubert     }
957*7f2fe78bSCy Schubert 
958*7f2fe78bSCy Schubert     *ccache_out = ccache;
959*7f2fe78bSCy Schubert     *ccache_reused = reused;
960*7f2fe78bSCy Schubert 
961*7f2fe78bSCy Schubert cleanup:
962*7f2fe78bSCy Schubert     free(target);
963*7f2fe78bSCy Schubert     return retval;
964*7f2fe78bSCy Schubert }
965*7f2fe78bSCy Schubert 
966*7f2fe78bSCy Schubert #ifdef HAVE_GETUSERSHELL
967*7f2fe78bSCy Schubert 
standard_shell(sh)968*7f2fe78bSCy Schubert int standard_shell(sh)
969*7f2fe78bSCy Schubert     char *sh;
970*7f2fe78bSCy Schubert {
971*7f2fe78bSCy Schubert     char *cp;
972*7f2fe78bSCy Schubert     char *getusershell();
973*7f2fe78bSCy Schubert 
974*7f2fe78bSCy Schubert     while ((cp = getusershell()) != NULL)
975*7f2fe78bSCy Schubert         if (!strcmp(cp, sh))
976*7f2fe78bSCy Schubert             return (1);
977*7f2fe78bSCy Schubert     return (0);
978*7f2fe78bSCy Schubert }
979*7f2fe78bSCy Schubert 
980*7f2fe78bSCy Schubert #endif /* HAVE_GETUSERSHELL */
981*7f2fe78bSCy Schubert 
ontty()982*7f2fe78bSCy Schubert static char * ontty()
983*7f2fe78bSCy Schubert {
984*7f2fe78bSCy Schubert     char *p;
985*7f2fe78bSCy Schubert     static char buf[MAXPATHLEN + 5];
986*7f2fe78bSCy Schubert     int result;
987*7f2fe78bSCy Schubert 
988*7f2fe78bSCy Schubert     buf[0] = 0;
989*7f2fe78bSCy Schubert     if ((p = ttyname(STDERR_FILENO))) {
990*7f2fe78bSCy Schubert         result = snprintf(buf, sizeof(buf), " on %s", p);
991*7f2fe78bSCy Schubert         if (SNPRINTF_OVERFLOW(result, sizeof(buf))) {
992*7f2fe78bSCy Schubert             fprintf(stderr, _("terminal name %s too long\n"), p);
993*7f2fe78bSCy Schubert             exit (1);
994*7f2fe78bSCy Schubert         }
995*7f2fe78bSCy Schubert     }
996*7f2fe78bSCy Schubert     return (buf);
997*7f2fe78bSCy Schubert }
998*7f2fe78bSCy Schubert 
999*7f2fe78bSCy Schubert 
set_env_var(name,value)1000*7f2fe78bSCy Schubert static int set_env_var(name, value)
1001*7f2fe78bSCy Schubert     char *name;
1002*7f2fe78bSCy Schubert     char *value;
1003*7f2fe78bSCy Schubert {
1004*7f2fe78bSCy Schubert     char * env_var_buf;
1005*7f2fe78bSCy Schubert 
1006*7f2fe78bSCy Schubert     asprintf(&env_var_buf,"%s=%s",name, value);
1007*7f2fe78bSCy Schubert     return putenv(env_var_buf);
1008*7f2fe78bSCy Schubert 
1009*7f2fe78bSCy Schubert }
1010*7f2fe78bSCy Schubert 
sweep_up(context,cc)1011*7f2fe78bSCy Schubert static void sweep_up(context, cc)
1012*7f2fe78bSCy Schubert     krb5_context context;
1013*7f2fe78bSCy Schubert     krb5_ccache cc;
1014*7f2fe78bSCy Schubert {
1015*7f2fe78bSCy Schubert     krb5_error_code retval;
1016*7f2fe78bSCy Schubert 
1017*7f2fe78bSCy Schubert     krb5_seteuid(0);
1018*7f2fe78bSCy Schubert     if (krb5_seteuid(target_uid) < 0) {
1019*7f2fe78bSCy Schubert         com_err(prog_name, errno,
1020*7f2fe78bSCy Schubert                 _("while changing to target uid for destroying ccache"));
1021*7f2fe78bSCy Schubert         exit(1);
1022*7f2fe78bSCy Schubert     }
1023*7f2fe78bSCy Schubert 
1024*7f2fe78bSCy Schubert     if (ks_ccache_is_initialized(context, cc)) {
1025*7f2fe78bSCy Schubert         if ((retval = krb5_cc_destroy(context, cc)))
1026*7f2fe78bSCy Schubert             com_err(prog_name, retval, _("while destroying cache"));
1027*7f2fe78bSCy Schubert     }
1028*7f2fe78bSCy Schubert }
1029*7f2fe78bSCy Schubert 
1030*7f2fe78bSCy Schubert /*****************************************************************
1031*7f2fe78bSCy Schubert get_params is to be called for the -a option or -e option to
1032*7f2fe78bSCy Schubert            collect all params passed in for the shell or for
1033*7f2fe78bSCy Schubert            cmd.  An array is returned containing all params.
1034*7f2fe78bSCy Schubert            optindex is incremented accordingly and the first
1035*7f2fe78bSCy Schubert            element in the returned array is reserved for the
1036*7f2fe78bSCy Schubert            name of the command to be executed or the name of the
1037*7f2fe78bSCy Schubert            shell.
1038*7f2fe78bSCy Schubert *****************************************************************/
1039*7f2fe78bSCy Schubert 
1040*7f2fe78bSCy Schubert krb5_error_code
get_params(optindex,pargc,pargv,params)1041*7f2fe78bSCy Schubert get_params(optindex, pargc, pargv, params)
1042*7f2fe78bSCy Schubert     int *optindex;
1043*7f2fe78bSCy Schubert     int pargc;
1044*7f2fe78bSCy Schubert     char **pargv;
1045*7f2fe78bSCy Schubert     char ***params;
1046*7f2fe78bSCy Schubert {
1047*7f2fe78bSCy Schubert 
1048*7f2fe78bSCy Schubert     int i,j;
1049*7f2fe78bSCy Schubert     char ** ret_params;
1050*7f2fe78bSCy Schubert     int size = pargc - *optindex + 2;
1051*7f2fe78bSCy Schubert 
1052*7f2fe78bSCy Schubert     if ((ret_params = (char **) calloc(size, sizeof (char *)))== NULL ){
1053*7f2fe78bSCy Schubert         return ENOMEM;
1054*7f2fe78bSCy Schubert     }
1055*7f2fe78bSCy Schubert 
1056*7f2fe78bSCy Schubert     for (i = *optindex, j=1; i < pargc; i++,j++){
1057*7f2fe78bSCy Schubert         ret_params[j] = pargv[i];
1058*7f2fe78bSCy Schubert         *optindex = *optindex + 1;
1059*7f2fe78bSCy Schubert     }
1060*7f2fe78bSCy Schubert 
1061*7f2fe78bSCy Schubert     ret_params[size-1] = NULL;
1062*7f2fe78bSCy Schubert     *params = ret_params;
1063*7f2fe78bSCy Schubert     return 0;
1064*7f2fe78bSCy Schubert }
1065*7f2fe78bSCy Schubert 
1066*7f2fe78bSCy Schubert static
print_status(const char * fmt,...)1067*7f2fe78bSCy Schubert void print_status(const char *fmt, ...)
1068*7f2fe78bSCy Schubert {
1069*7f2fe78bSCy Schubert     va_list ap;
1070*7f2fe78bSCy Schubert     if (! quiet){
1071*7f2fe78bSCy Schubert         va_start(ap, fmt);
1072*7f2fe78bSCy Schubert         vfprintf(stderr, fmt, ap);
1073*7f2fe78bSCy Schubert         va_end(ap);
1074*7f2fe78bSCy Schubert     }
1075*7f2fe78bSCy Schubert }
1076*7f2fe78bSCy Schubert 
1077*7f2fe78bSCy Schubert krb5_error_code
ksu_tgtname(context,server,client,tgtprinc)1078*7f2fe78bSCy Schubert ksu_tgtname(context, server, client, tgtprinc)
1079*7f2fe78bSCy Schubert     krb5_context context;
1080*7f2fe78bSCy Schubert     const krb5_data *server, *client;
1081*7f2fe78bSCy Schubert     krb5_principal *tgtprinc;
1082*7f2fe78bSCy Schubert {
1083*7f2fe78bSCy Schubert     return krb5_build_principal_ext(context, tgtprinc, client->length, client->data,
1084*7f2fe78bSCy Schubert                                     KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME,
1085*7f2fe78bSCy Schubert                                     server->length, server->data,
1086*7f2fe78bSCy Schubert                                     0);
1087*7f2fe78bSCy Schubert }
1088