155682Smarkm/*
2233294Sstas * Copyright (c) 1999 - 2008 Kungliga Tekniska H��gskolan
3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden).
4233294Sstas * All rights reserved.
555682Smarkm *
6233294Sstas * Redistribution and use in source and binary forms, with or without
7233294Sstas * modification, are permitted provided that the following conditions
8233294Sstas * are met:
955682Smarkm *
10233294Sstas * 1. Redistributions of source code must retain the above copyright
11233294Sstas *    notice, this list of conditions and the following disclaimer.
1255682Smarkm *
13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright
14233294Sstas *    notice, this list of conditions and the following disclaimer in the
15233294Sstas *    documentation and/or other materials provided with the distribution.
1655682Smarkm *
1755682Smarkm * 3. Neither the name of KTH nor the names of its contributors may be
1855682Smarkm *    used to endorse or promote products derived from this software without
1955682Smarkm *    specific prior written permission.
2055682Smarkm *
2155682Smarkm * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY
2255682Smarkm * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2355682Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2455682Smarkm * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE
2555682Smarkm * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2655682Smarkm * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2755682Smarkm * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
2855682Smarkm * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
2955682Smarkm * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
3055682Smarkm * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
3155682Smarkm * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
3255682Smarkm
3355682Smarkm#include <config.h>
3455682Smarkm
35233294SstasRCSID("$Id$");
3655682Smarkm
3755682Smarkm#include <stdio.h>
3855682Smarkm#include <stdlib.h>
3955682Smarkm#include <string.h>
4055682Smarkm
4155682Smarkm#include <syslog.h>
4255682Smarkm
4355682Smarkm#ifdef HAVE_PATHS_H
4455682Smarkm#include <paths.h>
4555682Smarkm#endif
4655682Smarkm
4755682Smarkm#ifdef HAVE_SHADOW_H
4855682Smarkm#include <shadow.h>
4955682Smarkm#endif
5055682Smarkm
5155682Smarkm#include <pwd.h>
52178828Sdfr#ifdef HAVE_CRYPT_H
53178828Sdfr#include <crypt.h>
54178828Sdfr#endif
5555682Smarkm
56103423Snectar#include "crypto-headers.h"
57102644Snectar#ifdef KRB5
5855682Smarkm#include <krb5.h>
59102644Snectar#endif
6055682Smarkm#include <kafs.h>
6155682Smarkm#include <err.h>
6255682Smarkm#include <roken.h>
6355682Smarkm#include <getarg.h>
6455682Smarkm
65178828Sdfr#include "supaths.h"
6655682Smarkm
67233294Sstas#if !HAVE_DECL_ENVIRON
68233294Sstasextern char **environ;
69233294Sstas#endif
70233294Sstas
7155682Smarkmint kerberos_flag = 1;
7255682Smarkmint csh_f_flag;
7355682Smarkmint full_login;
7455682Smarkmint env_flag;
7555682Smarkmchar *kerberos_instance = "root";
7655682Smarkmint help_flag;
7755682Smarkmint version_flag;
7855682Smarkmchar *cmd;
79102644Snectarchar tkfile[256];
8055682Smarkm
8155682Smarkmstruct getargs args[] = {
8255682Smarkm    { "kerberos", 'K', arg_negative_flag, &kerberos_flag,
8355682Smarkm      "don't use kerberos" },
8455682Smarkm    { NULL,	  'f', arg_flag,	  &csh_f_flag,
8555682Smarkm      "don't read .cshrc" },
8655682Smarkm    { "full",	  'l', arg_flag,          &full_login,
8755682Smarkm      "simulate full login" },
8855682Smarkm    { NULL,	  'm', arg_flag,          &env_flag,
8955682Smarkm      "leave environment unmodified" },
9055682Smarkm    { "instance", 'i', arg_string,        &kerberos_instance,
9155682Smarkm      "root instance to use" },
9255682Smarkm    { "command",  'c', arg_string,        &cmd,
9355682Smarkm      "command to execute" },
9455682Smarkm    { "help", 	  'h', arg_flag,          &help_flag },
9555682Smarkm    { "version",  0,   arg_flag,          &version_flag },
9655682Smarkm};
9755682Smarkm
9855682Smarkm
9955682Smarkmstatic void
10055682Smarkmusage (int ret)
10155682Smarkm{
10255682Smarkm    arg_printusage (args,
10355682Smarkm		    sizeof(args)/sizeof(*args),
10455682Smarkm		    NULL,
10555682Smarkm		    "[login [shell arguments]]");
10655682Smarkm    exit (ret);
10755682Smarkm}
10855682Smarkm
10990926Snectarstatic void
11090926Snectarfree_info(struct passwd *p)
11190926Snectar{
11290926Snectar    free (p->pw_name);
11390926Snectar    free (p->pw_passwd);
11490926Snectar    free (p->pw_dir);
11590926Snectar    free (p->pw_shell);
11690926Snectar    free (p);
11790926Snectar}
11890926Snectar
11955682Smarkmstatic struct passwd*
12090926Snectardup_info(const struct passwd *pwd)
12155682Smarkm{
12255682Smarkm    struct passwd *info;
12390926Snectar
12455682Smarkm    info = malloc(sizeof(*info));
12555682Smarkm    if(info == NULL)
12655682Smarkm	return NULL;
12755682Smarkm    info->pw_name = strdup(pwd->pw_name);
12855682Smarkm    info->pw_passwd = strdup(pwd->pw_passwd);
12955682Smarkm    info->pw_uid = pwd->pw_uid;
13055682Smarkm    info->pw_gid = pwd->pw_gid;
13155682Smarkm    info->pw_dir = strdup(pwd->pw_dir);
13255682Smarkm    info->pw_shell = strdup(pwd->pw_shell);
13355682Smarkm    if(info->pw_name == NULL || info->pw_passwd == NULL ||
13490926Snectar       info->pw_dir == NULL || info->pw_shell == NULL) {
13590926Snectar	free_info (info);
13655682Smarkm	return NULL;
13790926Snectar    }
13855682Smarkm    return info;
13955682Smarkm}
14055682Smarkm
14155682Smarkm#ifdef KRB5
14255682Smarkmstatic krb5_context context;
14355682Smarkmstatic krb5_ccache ccache;
14455682Smarkm
14555682Smarkmstatic int
14690926Snectarkrb5_verify(const struct passwd *login_info,
14790926Snectar	    const struct passwd *su_info,
14855682Smarkm	    const char *kerberos_instance)
14955682Smarkm{
15055682Smarkm    krb5_error_code ret;
15155682Smarkm    krb5_principal p;
152178828Sdfr    krb5_realm *realms, *r;
15389402Snectar    char *login_name = NULL;
154178828Sdfr    int user_ok = 0;
155233294Sstas
15689402Snectar#if defined(HAVE_GETLOGIN) && !defined(POSIX_GETLOGIN)
15789402Snectar    login_name = getlogin();
15889402Snectar#endif
15955682Smarkm    ret = krb5_init_context (&context);
16055682Smarkm    if (ret) {
16155682Smarkm#if 0
16272445Sassar	warnx("krb5_init_context failed: %d", ret);
16355682Smarkm#endif
16455682Smarkm	return 1;
16555682Smarkm    }
166233294Sstas
167178828Sdfr    ret = krb5_get_default_realms(context, &realms);
168233294Sstas    if (ret)
16955682Smarkm	return 1;
170178828Sdfr
171178828Sdfr    /* Check all local realms */
172178828Sdfr    for (r = realms; *r != NULL && !user_ok; r++) {
173233294Sstas
174233294Sstas	if (login_name == NULL || strcmp (login_name, "root") == 0)
175178828Sdfr	    login_name = login_info->pw_name;
176178828Sdfr	if (strcmp (su_info->pw_name, "root") == 0)
177233294Sstas	    ret = krb5_make_principal(context, &p, *r,
178178828Sdfr				      login_name,
179178828Sdfr				      kerberos_instance,
180178828Sdfr				      NULL);
181178828Sdfr	else
182233294Sstas	    ret = krb5_make_principal(context, &p, *r,
183178828Sdfr				      su_info->pw_name,
184178828Sdfr				      NULL);
185178828Sdfr	if (ret) {
186178828Sdfr	    krb5_free_host_realm(context, realms);
187178828Sdfr	    return 1;
188178828Sdfr	}
189233294Sstas
190178828Sdfr	/* if we are su-ing too root, check with krb5_kuserok */
191178828Sdfr	if (su_info->pw_uid == 0 && !krb5_kuserok(context, p, su_info->pw_name))
192178828Sdfr	    continue;
193233294Sstas
194233294Sstas	ret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &ccache);
19555682Smarkm	if(ret) {
196178828Sdfr	    krb5_free_host_realm(context, realms);
19772445Sassar	    krb5_free_principal (context, p);
19855682Smarkm	    return 1;
19955682Smarkm	}
200178828Sdfr  	ret = krb5_verify_user(context, p, ccache, NULL, TRUE, NULL);
20172445Sassar	krb5_free_principal (context, p);
202178828Sdfr	switch (ret) {
203178828Sdfr	case 0:
204178828Sdfr	    user_ok = 1;
205178828Sdfr	    break;
206178828Sdfr	case KRB5_LIBOS_PWDINTR :
20755682Smarkm	    krb5_cc_destroy(context, ccache);
208178828Sdfr	    break;
209178828Sdfr	case KRB5KRB_AP_ERR_BAD_INTEGRITY:
210178828Sdfr	case KRB5KRB_AP_ERR_MODIFIED:
211178828Sdfr	    krb5_cc_destroy(context, ccache);
212178828Sdfr	    krb5_warnx(context, "Password incorrect");
213178828Sdfr	    break;
214178828Sdfr	default :
215178828Sdfr	    krb5_cc_destroy(context, ccache);
216178828Sdfr	    krb5_warn(context, ret, "krb5_verify_user");
217178828Sdfr	    break;
21855682Smarkm	}
21955682Smarkm    }
220178828Sdfr    krb5_free_host_realm(context, realms);
221178828Sdfr    if (!user_ok)
222178828Sdfr	return 1;
223178828Sdfr    return 0;
22455682Smarkm}
22555682Smarkm
22655682Smarkmstatic int
22755682Smarkmkrb5_start_session(void)
22855682Smarkm{
22955682Smarkm    krb5_ccache ccache2;
23055682Smarkm    char *cc_name;
23155682Smarkm    int ret;
23255682Smarkm
233233294Sstas    ret = krb5_cc_new_unique(context, krb5_cc_type_file, NULL, &ccache2);
23455682Smarkm    if (ret) {
23555682Smarkm	krb5_cc_destroy(context, ccache);
23655682Smarkm	return 1;
23755682Smarkm    }
23855682Smarkm
23955682Smarkm    ret = krb5_cc_copy_cache(context, ccache, ccache2);
240233294Sstas    if (ret) {
241233294Sstas	krb5_cc_destroy(context, ccache);
242233294Sstas	krb5_cc_destroy(context, ccache2);
243233294Sstas	return 1;
244233294Sstas    }
24555682Smarkm
246178828Sdfr    ret = asprintf(&cc_name, "%s:%s", krb5_cc_get_type(context, ccache2),
247178828Sdfr		   krb5_cc_get_name(context, ccache2));
248233294Sstas    if (ret == -1) {
249233294Sstas	krb5_cc_destroy(context, ccache);
250233294Sstas	krb5_cc_destroy(context, ccache2);
251178828Sdfr	errx(1, "malloc - out of memory");
252233294Sstas    }
25372445Sassar    esetenv("KRB5CCNAME", cc_name, 1);
25472445Sassar
25572445Sassar    /* convert creds? */
25655682Smarkm    if(k_hasafs()) {
25755682Smarkm	if (k_setpag() == 0)
25855682Smarkm	    krb5_afslog(context, ccache2, NULL, NULL);
25955682Smarkm    }
260233294Sstas
26155682Smarkm    krb5_cc_close(context, ccache2);
26255682Smarkm    krb5_cc_destroy(context, ccache);
26355682Smarkm    return 0;
26455682Smarkm}
26555682Smarkm#endif
26655682Smarkm
267102644Snectar
268178828Sdfr#define GROUP_MEMBER		0
269178828Sdfr#define GROUP_MISSING		1
270178828Sdfr#define GROUP_EMPTY		2
271178828Sdfr#define GROUP_NOT_MEMBER	3
272178828Sdfr
273102644Snectarstatic int
274178828Sdfrgroup_member_p(const char *group, const char *user)
27555682Smarkm{
276178828Sdfr    struct group *g;
277178828Sdfr    int i;
278178828Sdfr    g = getgrnam(group);
279178828Sdfr    if(g == NULL)
280178828Sdfr	return GROUP_MISSING;
281178828Sdfr    if(g->gr_mem[0] == NULL)
282178828Sdfr	return GROUP_EMPTY;
283178828Sdfr    for(i = 0; g->gr_mem[i] != NULL; i++)
284178828Sdfr	if(strcmp(user, g->gr_mem[i]) == 0)
285178828Sdfr	    return GROUP_MEMBER;
286178828Sdfr    return GROUP_NOT_MEMBER;
287178828Sdfr}
288178828Sdfr
289178828Sdfrstatic int
290178828Sdfrverify_unix(struct passwd *login, struct passwd *su)
291178828Sdfr{
29255682Smarkm    char prompt[128];
29355682Smarkm    char pw_buf[1024];
29455682Smarkm    char *pw;
29555682Smarkm    int r;
29655682Smarkm    if(su->pw_passwd != NULL && *su->pw_passwd != '\0') {
29772445Sassar	snprintf(prompt, sizeof(prompt), "%s's password: ", su->pw_name);
298178828Sdfr	r = UI_UTIL_read_pw_string(pw_buf, sizeof(pw_buf), prompt, 0);
29955682Smarkm	if(r != 0)
30055682Smarkm	    exit(0);
30155682Smarkm	pw = crypt(pw_buf, su->pw_passwd);
30255682Smarkm	memset(pw_buf, 0, sizeof(pw_buf));
303178828Sdfr	if(strcmp(pw, su->pw_passwd) != 0) {
304178828Sdfr	    syslog (LOG_ERR | LOG_AUTH, "%s to %s: incorrect password",
305178828Sdfr		    login->pw_name, su->pw_name);
30655682Smarkm	    return 1;
307178828Sdfr	}
30855682Smarkm    }
309178828Sdfr    /* if su:ing to root, check membership of group wheel or root; if
310178828Sdfr       that group doesn't exist, or is empty, allow anyone to su
311178828Sdfr       root */
312178828Sdfr    if(su->pw_uid == 0) {
313178828Sdfr#ifndef ROOT_GROUP
314178828Sdfr#define ROOT_GROUP "wheel"
315178828Sdfr#endif
316178828Sdfr	int gs = group_member_p(ROOT_GROUP, login->pw_name);
317178828Sdfr	if(gs == GROUP_NOT_MEMBER) {
318178828Sdfr	    syslog (LOG_ERR | LOG_AUTH, "%s to %s: not in group %s",
319178828Sdfr		    login->pw_name, su->pw_name, ROOT_GROUP);
320178828Sdfr	    return 1;
321178828Sdfr	}
322178828Sdfr	return 0;
323178828Sdfr    }
32455682Smarkm    return 0;
32555682Smarkm}
32655682Smarkm
32755682Smarkmint
32855682Smarkmmain(int argc, char **argv)
32955682Smarkm{
33055682Smarkm    int i, optind = 0;
33155682Smarkm    char *su_user;
33255682Smarkm    struct passwd *su_info;
33355682Smarkm    struct passwd *login_info;
33455682Smarkm
33555682Smarkm    struct passwd *pwd;
33655682Smarkm
33755682Smarkm    char *shell;
33855682Smarkm
33955682Smarkm    int ok = 0;
34055682Smarkm
34178527Sassar    setprogname (argv[0]);
34255682Smarkm
34355682Smarkm    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optind))
34455682Smarkm	usage(1);
34555682Smarkm
34655682Smarkm    for (i=0; i < optind; i++)
34755682Smarkm      if (strcmp(argv[i], "-") == 0) {
34855682Smarkm	 full_login = 1;
34955682Smarkm	 break;
35055682Smarkm      }
351233294Sstas
35255682Smarkm    if(help_flag)
35355682Smarkm	usage(0);
35455682Smarkm    if(version_flag) {
35555682Smarkm	print_version(NULL);
35655682Smarkm	exit(0);
35755682Smarkm    }
35855682Smarkm    if(optind >= argc)
35955682Smarkm	su_user = "root";
36055682Smarkm    else
36155682Smarkm	su_user = argv[optind++];
36255682Smarkm
363178828Sdfr    if (!issuid() && getuid() != 0)
364233294Sstas	warnx("Not setuid and you are not root, expect this to fail");
365178828Sdfr
36655682Smarkm    pwd = k_getpwnam(su_user);
36755682Smarkm    if(pwd == NULL)
36855682Smarkm	errx (1, "unknown login %s", su_user);
36955682Smarkm    if (pwd->pw_uid == 0 && strcmp ("root", su_user) != 0) {
37055682Smarkm	syslog (LOG_ALERT, "NIS attack, user %s has uid 0", su_user);
37155682Smarkm	errx (1, "unknown login %s", su_user);
37255682Smarkm    }
37390926Snectar    su_info = dup_info(pwd);
37490926Snectar    if (su_info == NULL)
37590926Snectar	errx (1, "malloc: out of memory");
376233294Sstas
37755682Smarkm	pwd = getpwuid(getuid());
37855682Smarkm    if(pwd == NULL)
37955682Smarkm	errx(1, "who are you?");
38090926Snectar    login_info = dup_info(pwd);
38190926Snectar    if (login_info == NULL)
38290926Snectar	errx (1, "malloc: out of memory");
38355682Smarkm    if(env_flag)
38455682Smarkm	shell = login_info->pw_shell;
38555682Smarkm    else
38655682Smarkm	shell = su_info->pw_shell;
38755682Smarkm    if(shell == NULL || *shell == '\0')
38855682Smarkm	shell = _PATH_BSHELL;
389102644Snectar
390233294Sstas
391102644Snectar#ifdef KRB5
39255682Smarkm    if(kerberos_flag && ok == 0 &&
393233294Sstas       krb5_verify(login_info, su_info, kerberos_instance) == 0)
394102644Snectar	ok = 5;
395102644Snectar#endif
39655682Smarkm
397178828Sdfr    if(ok == 0 && login_info->pw_uid && verify_unix(login_info, su_info) != 0) {
39855682Smarkm	printf("Sorry!\n");
39955682Smarkm	exit(1);
40055682Smarkm    }
40155682Smarkm
40255682Smarkm#ifdef HAVE_GETSPNAM
40355682Smarkm   {  struct spwd *sp;
40455682Smarkm      long    today;
405233294Sstas
40672445Sassar    sp = getspnam(su_info->pw_name);
40772445Sassar    if (sp != NULL) {
40872445Sassar	today = time(0)/(24L * 60 * 60);
40972445Sassar	if (sp->sp_expire > 0) {
41072445Sassar	    if (today >= sp->sp_expire) {
411233294Sstas		if (login_info->pw_uid)
41272445Sassar		    errx(1,"Your account has expired.");
41372445Sassar		else
41472445Sassar		    printf("Your account has expired.");
41555682Smarkm            }
416233294Sstas            else if (sp->sp_expire - today < 14)
41755682Smarkm                printf("Your account will expire in %d days.\n",
41872445Sassar		       (int)(sp->sp_expire - today));
419233294Sstas	}
42072445Sassar	if (sp->sp_max > 0) {
42172445Sassar	    if (today >= sp->sp_lstchg + sp->sp_max) {
422233294Sstas		if (login_info->pw_uid)
42372445Sassar		    errx(1,"Your password has expired. Choose a new one.");
42472445Sassar		else
42572445Sassar		    printf("Your password has expired. Choose a new one.");
42672445Sassar	    }
42772445Sassar	    else if (today >= sp->sp_lstchg + sp->sp_max - sp->sp_warn)
42872445Sassar		printf("Your account will expire in %d days.\n",
42972445Sassar		       (int)(sp->sp_lstchg + sp->sp_max -today));
43072445Sassar	}
43155682Smarkm    }
43255682Smarkm    }
43355682Smarkm#endif
43455682Smarkm    {
43555682Smarkm	char *tty = ttyname (STDERR_FILENO);
436178828Sdfr	syslog (LOG_NOTICE | LOG_AUTH, tty ? "%s to %s on %s" : "%s to %s",
43755682Smarkm		login_info->pw_name, su_info->pw_name, tty);
43855682Smarkm    }
43955682Smarkm
44055682Smarkm
44155682Smarkm    if(!env_flag) {
44255682Smarkm	if(full_login) {
44355682Smarkm	    char *t = getenv ("TERM");
444178828Sdfr	    char **newenv = NULL;
445178828Sdfr	    int i, j;
446178828Sdfr
447178828Sdfr	    i = read_environment(_PATH_ETC_ENVIRONMENT, &newenv);
448178828Sdfr
449178828Sdfr	    environ = malloc ((10 + i) * sizeof (char *));
45055682Smarkm	    if (environ == NULL)
45155682Smarkm		err (1, "malloc");
45255682Smarkm	    environ[0] = NULL;
453178828Sdfr
454178828Sdfr	    for (j = 0; j < i; j++) {
455178828Sdfr		char *p = strchr(newenv[j], '=');
456233294Sstas		if (p == NULL)
457233294Sstas		    errx(1, "enviroment '%s' missing '='", newenv[j]);
458178828Sdfr		*p++ = 0;
459178828Sdfr		esetenv (newenv[j], p, 1);
460178828Sdfr	    }
461178828Sdfr	    free(newenv);
462178828Sdfr
46372445Sassar	    esetenv ("PATH", _PATH_DEFPATH, 1);
46455682Smarkm	    if (t)
46572445Sassar		esetenv ("TERM", t, 1);
46655682Smarkm	    if (chdir (su_info->pw_dir) < 0)
46755682Smarkm		errx (1, "no directory");
46855682Smarkm	}
46955682Smarkm	if (full_login || su_info->pw_uid)
47072445Sassar	    esetenv ("USER", su_info->pw_name, 1);
47172445Sassar	esetenv("HOME", su_info->pw_dir, 1);
47272445Sassar	esetenv("SHELL", shell, 1);
47355682Smarkm    }
47455682Smarkm
47555682Smarkm    {
47655682Smarkm	int i;
47755682Smarkm	char **args;
47855682Smarkm	char *p;
47955682Smarkm
48055682Smarkm	p = strrchr(shell, '/');
48155682Smarkm	if(p)
48255682Smarkm	    p++;
48355682Smarkm	else
48455682Smarkm	    p = shell;
48555682Smarkm
48655682Smarkm	if (strcmp(p, "csh") != 0)
48755682Smarkm	    csh_f_flag = 0;
48855682Smarkm
48955682Smarkm        args = malloc(((cmd ? 2 : 0) + 1 + argc - optind + 1 + csh_f_flag) * sizeof(*args));
49055682Smarkm	if (args == NULL)
49155682Smarkm	    err (1, "malloc");
49255682Smarkm	i = 0;
493178828Sdfr	if(full_login) {
494178828Sdfr	    if (asprintf(&args[i++], "-%s", p) == -1)
495178828Sdfr		errx (1, "malloc");
496178828Sdfr	} else
49755682Smarkm	    args[i++] = p;
49855682Smarkm	if (cmd) {
49955682Smarkm	   args[i++] = "-c";
50055682Smarkm	   args[i++] = cmd;
501233294Sstas	}
502233294Sstas
50355682Smarkm	if (csh_f_flag)
50455682Smarkm	    args[i++] = "-f";
50555682Smarkm
50655682Smarkm	for (argv += optind; *argv; ++argv)
50755682Smarkm	   args[i++] = *argv;
50855682Smarkm	args[i] = NULL;
509233294Sstas
51055682Smarkm	if(setgid(su_info->pw_gid) < 0)
51155682Smarkm	    err(1, "setgid");
51255682Smarkm	if (initgroups (su_info->pw_name, su_info->pw_gid) < 0)
51355682Smarkm	    err (1, "initgroups");
51472445Sassar	if(setuid(su_info->pw_uid) < 0
51572445Sassar	   || (su_info->pw_uid != 0 && setuid(0) == 0))
51655682Smarkm	    err(1, "setuid");
51755682Smarkm
51855682Smarkm#ifdef KRB5
519102644Snectar        if (ok == 5)
52055682Smarkm           krb5_start_session();
52155682Smarkm#endif
522233294Sstas	execve(shell, args, environ);
52355682Smarkm    }
524233294Sstas
52555682Smarkm    exit(1);
52655682Smarkm}
527