1b528cefcSMark Murray /*
2*ae771770SStanislav Sedov * Copyright (c) 1999 - 2008 Kungliga Tekniska Högskolan
3b528cefcSMark Murray * (Royal Institute of Technology, Stockholm, Sweden).
4b528cefcSMark Murray * All rights reserved.
5b528cefcSMark Murray *
6b528cefcSMark Murray * Redistribution and use in source and binary forms, with or without
7b528cefcSMark Murray * modification, are permitted provided that the following conditions
8b528cefcSMark Murray * are met:
9b528cefcSMark Murray *
10b528cefcSMark Murray * 1. Redistributions of source code must retain the above copyright
11b528cefcSMark Murray * notice, this list of conditions and the following disclaimer.
12b528cefcSMark Murray *
13b528cefcSMark Murray * 2. Redistributions in binary form must reproduce the above copyright
14b528cefcSMark Murray * notice, this list of conditions and the following disclaimer in the
15b528cefcSMark Murray * documentation and/or other materials provided with the distribution.
16b528cefcSMark Murray *
17b528cefcSMark Murray * 3. Neither the name of KTH nor the names of its contributors may be
18b528cefcSMark Murray * used to endorse or promote products derived from this software without
19b528cefcSMark Murray * specific prior written permission.
20b528cefcSMark Murray *
21b528cefcSMark Murray * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY
22b528cefcSMark Murray * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23b528cefcSMark Murray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24b528cefcSMark Murray * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE
25b528cefcSMark Murray * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26b528cefcSMark Murray * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27b528cefcSMark Murray * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28b528cefcSMark Murray * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29b528cefcSMark Murray * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30b528cefcSMark Murray * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31b528cefcSMark Murray * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
32b528cefcSMark Murray
33b528cefcSMark Murray #include <config.h>
34b528cefcSMark Murray
35*ae771770SStanislav Sedov RCSID("$Id$");
36b528cefcSMark Murray
37b528cefcSMark Murray #include <stdio.h>
38b528cefcSMark Murray #include <stdlib.h>
39b528cefcSMark Murray #include <string.h>
40b528cefcSMark Murray
41b528cefcSMark Murray #include <syslog.h>
42b528cefcSMark Murray
43b528cefcSMark Murray #ifdef HAVE_PATHS_H
44b528cefcSMark Murray #include <paths.h>
45b528cefcSMark Murray #endif
46b528cefcSMark Murray
47b528cefcSMark Murray #ifdef HAVE_SHADOW_H
48b528cefcSMark Murray #include <shadow.h>
49b528cefcSMark Murray #endif
50b528cefcSMark Murray
51b528cefcSMark Murray #include <pwd.h>
5233f12199SDoug Rabson #ifdef HAVE_CRYPT_H
5333f12199SDoug Rabson #include <crypt.h>
5433f12199SDoug Rabson #endif
55b528cefcSMark Murray
560cadf2f4SJacques Vidrine #include "crypto-headers.h"
578373020dSJacques Vidrine #ifdef KRB5
58b528cefcSMark Murray #include <krb5.h>
598373020dSJacques Vidrine #endif
60bbd80c28SJacques Vidrine #include <kafs.h>
61b528cefcSMark Murray #include <err.h>
62b528cefcSMark Murray #include <roken.h>
63b528cefcSMark Murray #include <getarg.h>
64b528cefcSMark Murray
6533f12199SDoug Rabson #include "supaths.h"
66b528cefcSMark Murray
67*ae771770SStanislav Sedov #if !HAVE_DECL_ENVIRON
68*ae771770SStanislav Sedov extern char **environ;
69*ae771770SStanislav Sedov #endif
70*ae771770SStanislav Sedov
71b528cefcSMark Murray int kerberos_flag = 1;
72b528cefcSMark Murray int csh_f_flag;
73b528cefcSMark Murray int full_login;
74b528cefcSMark Murray int env_flag;
75b528cefcSMark Murray char *kerberos_instance = "root";
76b528cefcSMark Murray int help_flag;
77b528cefcSMark Murray int version_flag;
78b528cefcSMark Murray char *cmd;
798373020dSJacques Vidrine char tkfile[256];
80b528cefcSMark Murray
81b528cefcSMark Murray struct getargs args[] = {
82b528cefcSMark Murray { "kerberos", 'K', arg_negative_flag, &kerberos_flag,
83b528cefcSMark Murray "don't use kerberos" },
84b528cefcSMark Murray { NULL, 'f', arg_flag, &csh_f_flag,
85b528cefcSMark Murray "don't read .cshrc" },
86b528cefcSMark Murray { "full", 'l', arg_flag, &full_login,
87b528cefcSMark Murray "simulate full login" },
88b528cefcSMark Murray { NULL, 'm', arg_flag, &env_flag,
89b528cefcSMark Murray "leave environment unmodified" },
90b528cefcSMark Murray { "instance", 'i', arg_string, &kerberos_instance,
91b528cefcSMark Murray "root instance to use" },
92b528cefcSMark Murray { "command", 'c', arg_string, &cmd,
93b528cefcSMark Murray "command to execute" },
94b528cefcSMark Murray { "help", 'h', arg_flag, &help_flag },
95b528cefcSMark Murray { "version", 0, arg_flag, &version_flag },
96b528cefcSMark Murray };
97b528cefcSMark Murray
98b528cefcSMark Murray
99b528cefcSMark Murray static void
usage(int ret)100b528cefcSMark Murray usage (int ret)
101b528cefcSMark Murray {
102b528cefcSMark Murray arg_printusage (args,
103b528cefcSMark Murray sizeof(args)/sizeof(*args),
104b528cefcSMark Murray NULL,
105b528cefcSMark Murray "[login [shell arguments]]");
106b528cefcSMark Murray exit (ret);
107b528cefcSMark Murray }
108b528cefcSMark Murray
1094137ff4cSJacques Vidrine static void
free_info(struct passwd * p)1104137ff4cSJacques Vidrine free_info(struct passwd *p)
1114137ff4cSJacques Vidrine {
1124137ff4cSJacques Vidrine free (p->pw_name);
1134137ff4cSJacques Vidrine free (p->pw_passwd);
1144137ff4cSJacques Vidrine free (p->pw_dir);
1154137ff4cSJacques Vidrine free (p->pw_shell);
1164137ff4cSJacques Vidrine free (p);
1174137ff4cSJacques Vidrine }
1184137ff4cSJacques Vidrine
119b528cefcSMark Murray static struct passwd*
dup_info(const struct passwd * pwd)1204137ff4cSJacques Vidrine dup_info(const struct passwd *pwd)
121b528cefcSMark Murray {
122b528cefcSMark Murray struct passwd *info;
1234137ff4cSJacques Vidrine
124b528cefcSMark Murray info = malloc(sizeof(*info));
125b528cefcSMark Murray if(info == NULL)
126b528cefcSMark Murray return NULL;
127b528cefcSMark Murray info->pw_name = strdup(pwd->pw_name);
128b528cefcSMark Murray info->pw_passwd = strdup(pwd->pw_passwd);
129b528cefcSMark Murray info->pw_uid = pwd->pw_uid;
130b528cefcSMark Murray info->pw_gid = pwd->pw_gid;
131b528cefcSMark Murray info->pw_dir = strdup(pwd->pw_dir);
132b528cefcSMark Murray info->pw_shell = strdup(pwd->pw_shell);
133b528cefcSMark Murray if(info->pw_name == NULL || info->pw_passwd == NULL ||
1344137ff4cSJacques Vidrine info->pw_dir == NULL || info->pw_shell == NULL) {
1354137ff4cSJacques Vidrine free_info (info);
136b528cefcSMark Murray return NULL;
1374137ff4cSJacques Vidrine }
138b528cefcSMark Murray return info;
139b528cefcSMark Murray }
140b528cefcSMark Murray
141b528cefcSMark Murray #ifdef KRB5
142b528cefcSMark Murray static krb5_context context;
143b528cefcSMark Murray static krb5_ccache ccache;
144b528cefcSMark Murray
145b528cefcSMark Murray static int
krb5_verify(const struct passwd * login_info,const struct passwd * su_info,const char * kerberos_instance)1464137ff4cSJacques Vidrine krb5_verify(const struct passwd *login_info,
1474137ff4cSJacques Vidrine const struct passwd *su_info,
148b528cefcSMark Murray const char *kerberos_instance)
149b528cefcSMark Murray {
150b528cefcSMark Murray krb5_error_code ret;
151b528cefcSMark Murray krb5_principal p;
15233f12199SDoug Rabson krb5_realm *realms, *r;
1535a83b025SJacques Vidrine char *login_name = NULL;
15433f12199SDoug Rabson int user_ok = 0;
155b528cefcSMark Murray
1565a83b025SJacques Vidrine #if defined(HAVE_GETLOGIN) && !defined(POSIX_GETLOGIN)
1575a83b025SJacques Vidrine login_name = getlogin();
1585a83b025SJacques Vidrine #endif
159b528cefcSMark Murray ret = krb5_init_context (&context);
160b528cefcSMark Murray if (ret) {
161b528cefcSMark Murray #if 0
1625e9cd1aeSAssar Westerlund warnx("krb5_init_context failed: %d", ret);
163b528cefcSMark Murray #endif
164b528cefcSMark Murray return 1;
165b528cefcSMark Murray }
166b528cefcSMark Murray
16733f12199SDoug Rabson ret = krb5_get_default_realms(context, &realms);
16833f12199SDoug Rabson if (ret)
16933f12199SDoug Rabson return 1;
17033f12199SDoug Rabson
17133f12199SDoug Rabson /* Check all local realms */
17233f12199SDoug Rabson for (r = realms; *r != NULL && !user_ok; r++) {
17333f12199SDoug Rabson
1745a83b025SJacques Vidrine if (login_name == NULL || strcmp (login_name, "root") == 0)
1755a83b025SJacques Vidrine login_name = login_info->pw_name;
176b528cefcSMark Murray if (strcmp (su_info->pw_name, "root") == 0)
17733f12199SDoug Rabson ret = krb5_make_principal(context, &p, *r,
1785a83b025SJacques Vidrine login_name,
179b528cefcSMark Murray kerberos_instance,
180b528cefcSMark Murray NULL);
181b528cefcSMark Murray else
18233f12199SDoug Rabson ret = krb5_make_principal(context, &p, *r,
183b528cefcSMark Murray su_info->pw_name,
184b528cefcSMark Murray NULL);
18533f12199SDoug Rabson if (ret) {
18633f12199SDoug Rabson krb5_free_host_realm(context, realms);
187b528cefcSMark Murray return 1;
18833f12199SDoug Rabson }
189b528cefcSMark Murray
19033f12199SDoug Rabson /* if we are su-ing too root, check with krb5_kuserok */
19133f12199SDoug Rabson if (su_info->pw_uid == 0 && !krb5_kuserok(context, p, su_info->pw_name))
19233f12199SDoug Rabson continue;
19333f12199SDoug Rabson
194*ae771770SStanislav Sedov ret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &ccache);
195b528cefcSMark Murray if(ret) {
19633f12199SDoug Rabson krb5_free_host_realm(context, realms);
1975e9cd1aeSAssar Westerlund krb5_free_principal (context, p);
198b528cefcSMark Murray return 1;
199b528cefcSMark Murray }
20033f12199SDoug Rabson ret = krb5_verify_user(context, p, ccache, NULL, TRUE, NULL);
201b528cefcSMark Murray krb5_free_principal (context, p);
202b528cefcSMark Murray switch (ret) {
20333f12199SDoug Rabson case 0:
20433f12199SDoug Rabson user_ok = 1;
20533f12199SDoug Rabson break;
2065e9cd1aeSAssar Westerlund case KRB5_LIBOS_PWDINTR :
20733f12199SDoug Rabson krb5_cc_destroy(context, ccache);
2085e9cd1aeSAssar Westerlund break;
209b528cefcSMark Murray case KRB5KRB_AP_ERR_BAD_INTEGRITY:
210b528cefcSMark Murray case KRB5KRB_AP_ERR_MODIFIED:
21133f12199SDoug Rabson krb5_cc_destroy(context, ccache);
212b528cefcSMark Murray krb5_warnx(context, "Password incorrect");
213b528cefcSMark Murray break;
214b528cefcSMark Murray default :
21533f12199SDoug Rabson krb5_cc_destroy(context, ccache);
216b528cefcSMark Murray krb5_warn(context, ret, "krb5_verify_user");
217b528cefcSMark Murray break;
218b528cefcSMark Murray }
219b528cefcSMark Murray }
22033f12199SDoug Rabson krb5_free_host_realm(context, realms);
22133f12199SDoug Rabson if (!user_ok)
22233f12199SDoug Rabson return 1;
223b528cefcSMark Murray return 0;
224b528cefcSMark Murray }
225b528cefcSMark Murray
226b528cefcSMark Murray static int
krb5_start_session(void)227b528cefcSMark Murray krb5_start_session(void)
228b528cefcSMark Murray {
229b528cefcSMark Murray krb5_ccache ccache2;
230b528cefcSMark Murray char *cc_name;
231b528cefcSMark Murray int ret;
232b528cefcSMark Murray
233*ae771770SStanislav Sedov ret = krb5_cc_new_unique(context, krb5_cc_type_file, NULL, &ccache2);
234b528cefcSMark Murray if (ret) {
235b528cefcSMark Murray krb5_cc_destroy(context, ccache);
236b528cefcSMark Murray return 1;
237b528cefcSMark Murray }
238b528cefcSMark Murray
239b528cefcSMark Murray ret = krb5_cc_copy_cache(context, ccache, ccache2);
240*ae771770SStanislav Sedov if (ret) {
241*ae771770SStanislav Sedov krb5_cc_destroy(context, ccache);
242*ae771770SStanislav Sedov krb5_cc_destroy(context, ccache2);
243*ae771770SStanislav Sedov return 1;
244*ae771770SStanislav Sedov }
245b528cefcSMark Murray
24633f12199SDoug Rabson ret = asprintf(&cc_name, "%s:%s", krb5_cc_get_type(context, ccache2),
247b528cefcSMark Murray krb5_cc_get_name(context, ccache2));
248*ae771770SStanislav Sedov if (ret == -1) {
249*ae771770SStanislav Sedov krb5_cc_destroy(context, ccache);
250*ae771770SStanislav Sedov krb5_cc_destroy(context, ccache2);
25133f12199SDoug Rabson errx(1, "malloc - out of memory");
252*ae771770SStanislav Sedov }
2535e9cd1aeSAssar Westerlund esetenv("KRB5CCNAME", cc_name, 1);
2545e9cd1aeSAssar Westerlund
2555e9cd1aeSAssar Westerlund /* convert creds? */
256b528cefcSMark Murray if(k_hasafs()) {
257b528cefcSMark Murray if (k_setpag() == 0)
258b528cefcSMark Murray krb5_afslog(context, ccache2, NULL, NULL);
259b528cefcSMark Murray }
260b528cefcSMark Murray
261b528cefcSMark Murray krb5_cc_close(context, ccache2);
262b528cefcSMark Murray krb5_cc_destroy(context, ccache);
263b528cefcSMark Murray return 0;
264b528cefcSMark Murray }
265b528cefcSMark Murray #endif
266b528cefcSMark Murray
2678373020dSJacques Vidrine
26833f12199SDoug Rabson #define GROUP_MEMBER 0
26933f12199SDoug Rabson #define GROUP_MISSING 1
27033f12199SDoug Rabson #define GROUP_EMPTY 2
27133f12199SDoug Rabson #define GROUP_NOT_MEMBER 3
27233f12199SDoug Rabson
273b528cefcSMark Murray static int
group_member_p(const char * group,const char * user)27433f12199SDoug Rabson group_member_p(const char *group, const char *user)
27533f12199SDoug Rabson {
27633f12199SDoug Rabson struct group *g;
27733f12199SDoug Rabson int i;
27833f12199SDoug Rabson g = getgrnam(group);
27933f12199SDoug Rabson if(g == NULL)
28033f12199SDoug Rabson return GROUP_MISSING;
28133f12199SDoug Rabson if(g->gr_mem[0] == NULL)
28233f12199SDoug Rabson return GROUP_EMPTY;
28333f12199SDoug Rabson for(i = 0; g->gr_mem[i] != NULL; i++)
28433f12199SDoug Rabson if(strcmp(user, g->gr_mem[i]) == 0)
28533f12199SDoug Rabson return GROUP_MEMBER;
28633f12199SDoug Rabson return GROUP_NOT_MEMBER;
28733f12199SDoug Rabson }
28833f12199SDoug Rabson
28933f12199SDoug Rabson static int
verify_unix(struct passwd * login,struct passwd * su)29033f12199SDoug Rabson verify_unix(struct passwd *login, struct passwd *su)
291b528cefcSMark Murray {
292b528cefcSMark Murray char prompt[128];
293b528cefcSMark Murray char pw_buf[1024];
294b528cefcSMark Murray char *pw;
295b528cefcSMark Murray int r;
296b528cefcSMark Murray if(su->pw_passwd != NULL && *su->pw_passwd != '\0') {
2975e9cd1aeSAssar Westerlund snprintf(prompt, sizeof(prompt), "%s's password: ", su->pw_name);
29833f12199SDoug Rabson r = UI_UTIL_read_pw_string(pw_buf, sizeof(pw_buf), prompt, 0);
299b528cefcSMark Murray if(r != 0)
300b528cefcSMark Murray exit(0);
301b528cefcSMark Murray pw = crypt(pw_buf, su->pw_passwd);
302b528cefcSMark Murray memset(pw_buf, 0, sizeof(pw_buf));
30333f12199SDoug Rabson if(strcmp(pw, su->pw_passwd) != 0) {
30433f12199SDoug Rabson syslog (LOG_ERR | LOG_AUTH, "%s to %s: incorrect password",
30533f12199SDoug Rabson login->pw_name, su->pw_name);
306b528cefcSMark Murray return 1;
307b528cefcSMark Murray }
30833f12199SDoug Rabson }
30933f12199SDoug Rabson /* if su:ing to root, check membership of group wheel or root; if
31033f12199SDoug Rabson that group doesn't exist, or is empty, allow anyone to su
31133f12199SDoug Rabson root */
31233f12199SDoug Rabson if(su->pw_uid == 0) {
31333f12199SDoug Rabson #ifndef ROOT_GROUP
31433f12199SDoug Rabson #define ROOT_GROUP "wheel"
31533f12199SDoug Rabson #endif
31633f12199SDoug Rabson int gs = group_member_p(ROOT_GROUP, login->pw_name);
31733f12199SDoug Rabson if(gs == GROUP_NOT_MEMBER) {
31833f12199SDoug Rabson syslog (LOG_ERR | LOG_AUTH, "%s to %s: not in group %s",
31933f12199SDoug Rabson login->pw_name, su->pw_name, ROOT_GROUP);
32033f12199SDoug Rabson return 1;
32133f12199SDoug Rabson }
32233f12199SDoug Rabson return 0;
32333f12199SDoug Rabson }
324b528cefcSMark Murray return 0;
325b528cefcSMark Murray }
326b528cefcSMark Murray
327b528cefcSMark Murray int
main(int argc,char ** argv)328b528cefcSMark Murray main(int argc, char **argv)
329b528cefcSMark Murray {
330b528cefcSMark Murray int i, optind = 0;
331b528cefcSMark Murray char *su_user;
332b528cefcSMark Murray struct passwd *su_info;
333b528cefcSMark Murray struct passwd *login_info;
334b528cefcSMark Murray
335b528cefcSMark Murray struct passwd *pwd;
336b528cefcSMark Murray
337b528cefcSMark Murray char *shell;
338b528cefcSMark Murray
339b528cefcSMark Murray int ok = 0;
340b528cefcSMark Murray
341adb0ddaeSAssar Westerlund setprogname (argv[0]);
342b528cefcSMark Murray
343b528cefcSMark Murray if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optind))
344b528cefcSMark Murray usage(1);
345b528cefcSMark Murray
346b528cefcSMark Murray for (i=0; i < optind; i++)
347b528cefcSMark Murray if (strcmp(argv[i], "-") == 0) {
348b528cefcSMark Murray full_login = 1;
349b528cefcSMark Murray break;
350b528cefcSMark Murray }
351b528cefcSMark Murray
352b528cefcSMark Murray if(help_flag)
353b528cefcSMark Murray usage(0);
354b528cefcSMark Murray if(version_flag) {
355b528cefcSMark Murray print_version(NULL);
356b528cefcSMark Murray exit(0);
357b528cefcSMark Murray }
358b528cefcSMark Murray if(optind >= argc)
359b528cefcSMark Murray su_user = "root";
360b528cefcSMark Murray else
361b528cefcSMark Murray su_user = argv[optind++];
362b528cefcSMark Murray
36333f12199SDoug Rabson if (!issuid() && getuid() != 0)
364*ae771770SStanislav Sedov warnx("Not setuid and you are not root, expect this to fail");
36533f12199SDoug Rabson
366b528cefcSMark Murray pwd = k_getpwnam(su_user);
367b528cefcSMark Murray if(pwd == NULL)
368b528cefcSMark Murray errx (1, "unknown login %s", su_user);
369b528cefcSMark Murray if (pwd->pw_uid == 0 && strcmp ("root", su_user) != 0) {
370b528cefcSMark Murray syslog (LOG_ALERT, "NIS attack, user %s has uid 0", su_user);
371b528cefcSMark Murray errx (1, "unknown login %s", su_user);
372b528cefcSMark Murray }
3734137ff4cSJacques Vidrine su_info = dup_info(pwd);
3744137ff4cSJacques Vidrine if (su_info == NULL)
3754137ff4cSJacques Vidrine errx (1, "malloc: out of memory");
376b528cefcSMark Murray
377b528cefcSMark Murray pwd = getpwuid(getuid());
378b528cefcSMark Murray if(pwd == NULL)
379b528cefcSMark Murray errx(1, "who are you?");
3804137ff4cSJacques Vidrine login_info = dup_info(pwd);
3814137ff4cSJacques Vidrine if (login_info == NULL)
3824137ff4cSJacques Vidrine errx (1, "malloc: out of memory");
383b528cefcSMark Murray if(env_flag)
384b528cefcSMark Murray shell = login_info->pw_shell;
385b528cefcSMark Murray else
386b528cefcSMark Murray shell = su_info->pw_shell;
387b528cefcSMark Murray if(shell == NULL || *shell == '\0')
388b528cefcSMark Murray shell = _PATH_BSHELL;
389b528cefcSMark Murray
3908373020dSJacques Vidrine
3918373020dSJacques Vidrine #ifdef KRB5
392b528cefcSMark Murray if(kerberos_flag && ok == 0 &&
393*ae771770SStanislav Sedov krb5_verify(login_info, su_info, kerberos_instance) == 0)
3948373020dSJacques Vidrine ok = 5;
3958373020dSJacques Vidrine #endif
396b528cefcSMark Murray
39733f12199SDoug Rabson if(ok == 0 && login_info->pw_uid && verify_unix(login_info, su_info) != 0) {
398b528cefcSMark Murray printf("Sorry!\n");
399b528cefcSMark Murray exit(1);
400b528cefcSMark Murray }
401b528cefcSMark Murray
402b528cefcSMark Murray #ifdef HAVE_GETSPNAM
403b528cefcSMark Murray { struct spwd *sp;
404b528cefcSMark Murray long today;
405b528cefcSMark Murray
406b528cefcSMark Murray sp = getspnam(su_info->pw_name);
4075e9cd1aeSAssar Westerlund if (sp != NULL) {
408b528cefcSMark Murray today = time(0)/(24L * 60 * 60);
409b528cefcSMark Murray if (sp->sp_expire > 0) {
410b528cefcSMark Murray if (today >= sp->sp_expire) {
411b528cefcSMark Murray if (login_info->pw_uid)
412b528cefcSMark Murray errx(1,"Your account has expired.");
413b528cefcSMark Murray else
414b528cefcSMark Murray printf("Your account has expired.");
415b528cefcSMark Murray }
416b528cefcSMark Murray else if (sp->sp_expire - today < 14)
417b528cefcSMark Murray printf("Your account will expire in %d days.\n",
418b528cefcSMark Murray (int)(sp->sp_expire - today));
419b528cefcSMark Murray }
420b528cefcSMark Murray if (sp->sp_max > 0) {
421b528cefcSMark Murray if (today >= sp->sp_lstchg + sp->sp_max) {
422b528cefcSMark Murray if (login_info->pw_uid)
423b528cefcSMark Murray errx(1,"Your password has expired. Choose a new one.");
424b528cefcSMark Murray else
425b528cefcSMark Murray printf("Your password has expired. Choose a new one.");
426b528cefcSMark Murray }
427b528cefcSMark Murray else if (today >= sp->sp_lstchg + sp->sp_max - sp->sp_warn)
428b528cefcSMark Murray printf("Your account will expire in %d days.\n",
429b528cefcSMark Murray (int)(sp->sp_lstchg + sp->sp_max -today));
430b528cefcSMark Murray }
431b528cefcSMark Murray }
4325e9cd1aeSAssar Westerlund }
433b528cefcSMark Murray #endif
434b528cefcSMark Murray {
435b528cefcSMark Murray char *tty = ttyname (STDERR_FILENO);
43633f12199SDoug Rabson syslog (LOG_NOTICE | LOG_AUTH, tty ? "%s to %s on %s" : "%s to %s",
437b528cefcSMark Murray login_info->pw_name, su_info->pw_name, tty);
438b528cefcSMark Murray }
439b528cefcSMark Murray
440b528cefcSMark Murray
441b528cefcSMark Murray if(!env_flag) {
442b528cefcSMark Murray if(full_login) {
443b528cefcSMark Murray char *t = getenv ("TERM");
44433f12199SDoug Rabson char **newenv = NULL;
44533f12199SDoug Rabson int i, j;
446b528cefcSMark Murray
44733f12199SDoug Rabson i = read_environment(_PATH_ETC_ENVIRONMENT, &newenv);
44833f12199SDoug Rabson
44933f12199SDoug Rabson environ = malloc ((10 + i) * sizeof (char *));
450b528cefcSMark Murray if (environ == NULL)
451b528cefcSMark Murray err (1, "malloc");
452b528cefcSMark Murray environ[0] = NULL;
45333f12199SDoug Rabson
45433f12199SDoug Rabson for (j = 0; j < i; j++) {
45533f12199SDoug Rabson char *p = strchr(newenv[j], '=');
456*ae771770SStanislav Sedov if (p == NULL)
457*ae771770SStanislav Sedov errx(1, "enviroment '%s' missing '='", newenv[j]);
45833f12199SDoug Rabson *p++ = 0;
45933f12199SDoug Rabson esetenv (newenv[j], p, 1);
46033f12199SDoug Rabson }
46133f12199SDoug Rabson free(newenv);
46233f12199SDoug Rabson
4635e9cd1aeSAssar Westerlund esetenv ("PATH", _PATH_DEFPATH, 1);
464b528cefcSMark Murray if (t)
4655e9cd1aeSAssar Westerlund esetenv ("TERM", t, 1);
466b528cefcSMark Murray if (chdir (su_info->pw_dir) < 0)
467b528cefcSMark Murray errx (1, "no directory");
468b528cefcSMark Murray }
469b528cefcSMark Murray if (full_login || su_info->pw_uid)
4705e9cd1aeSAssar Westerlund esetenv ("USER", su_info->pw_name, 1);
4715e9cd1aeSAssar Westerlund esetenv("HOME", su_info->pw_dir, 1);
4725e9cd1aeSAssar Westerlund esetenv("SHELL", shell, 1);
473b528cefcSMark Murray }
474b528cefcSMark Murray
475b528cefcSMark Murray {
476b528cefcSMark Murray int i;
477b528cefcSMark Murray char **args;
478b528cefcSMark Murray char *p;
479b528cefcSMark Murray
480b528cefcSMark Murray p = strrchr(shell, '/');
481b528cefcSMark Murray if(p)
482b528cefcSMark Murray p++;
483b528cefcSMark Murray else
484b528cefcSMark Murray p = shell;
485b528cefcSMark Murray
486b528cefcSMark Murray if (strcmp(p, "csh") != 0)
487b528cefcSMark Murray csh_f_flag = 0;
488b528cefcSMark Murray
489b528cefcSMark Murray args = malloc(((cmd ? 2 : 0) + 1 + argc - optind + 1 + csh_f_flag) * sizeof(*args));
490b528cefcSMark Murray if (args == NULL)
491b528cefcSMark Murray err (1, "malloc");
492b528cefcSMark Murray i = 0;
49333f12199SDoug Rabson if(full_login) {
49433f12199SDoug Rabson if (asprintf(&args[i++], "-%s", p) == -1)
49533f12199SDoug Rabson errx (1, "malloc");
49633f12199SDoug Rabson } else
497b528cefcSMark Murray args[i++] = p;
498b528cefcSMark Murray if (cmd) {
499b528cefcSMark Murray args[i++] = "-c";
500b528cefcSMark Murray args[i++] = cmd;
501b528cefcSMark Murray }
502b528cefcSMark Murray
503b528cefcSMark Murray if (csh_f_flag)
504b528cefcSMark Murray args[i++] = "-f";
505b528cefcSMark Murray
506b528cefcSMark Murray for (argv += optind; *argv; ++argv)
507b528cefcSMark Murray args[i++] = *argv;
508b528cefcSMark Murray args[i] = NULL;
509b528cefcSMark Murray
510b528cefcSMark Murray if(setgid(su_info->pw_gid) < 0)
511b528cefcSMark Murray err(1, "setgid");
512b528cefcSMark Murray if (initgroups (su_info->pw_name, su_info->pw_gid) < 0)
513b528cefcSMark Murray err (1, "initgroups");
5145e9cd1aeSAssar Westerlund if(setuid(su_info->pw_uid) < 0
5155e9cd1aeSAssar Westerlund || (su_info->pw_uid != 0 && setuid(0) == 0))
516b528cefcSMark Murray err(1, "setuid");
517b528cefcSMark Murray
518b528cefcSMark Murray #ifdef KRB5
5198373020dSJacques Vidrine if (ok == 5)
520b528cefcSMark Murray krb5_start_session();
521b528cefcSMark Murray #endif
522*ae771770SStanislav Sedov execve(shell, args, environ);
523b528cefcSMark Murray }
524b528cefcSMark Murray
525b528cefcSMark Murray exit(1);
526b528cefcSMark Murray }
527