add support for shadow passwords and rewrite some logic. From
Miroslav Ruda <ruda@ics.muni.cz> git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@6718 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
145
appl/su/su.c
145
appl/su/su.c
@@ -44,12 +44,18 @@ RCSID("$Id$");
|
|||||||
#include <paths.h>
|
#include <paths.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SHADOW_H
|
||||||
|
#include <shadow.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
|
|
||||||
#include <krb5.h>
|
#include <krb5.h>
|
||||||
|
#include <kafs.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <roken.h>
|
#include <roken.h>
|
||||||
#include <getarg.h>
|
#include <getarg.h>
|
||||||
|
#include <kafs.h>
|
||||||
|
|
||||||
#ifndef _PATH_DEFPATH
|
#ifndef _PATH_DEFPATH
|
||||||
#define _PATH_DEFPATH "/usr/bin:/bin"
|
#define _PATH_DEFPATH "/usr/bin:/bin"
|
||||||
@@ -115,15 +121,18 @@ make_info(struct passwd *pwd)
|
|||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef KRB5
|
||||||
|
static krb5_context context;
|
||||||
|
static krb5_ccache ccache;
|
||||||
|
#endif
|
||||||
|
|
||||||
static int
|
static int
|
||||||
verify_krb5(struct passwd *login_info, struct passwd *su_info,
|
krb5_verify(struct passwd *login_info, struct passwd *su_info,
|
||||||
const char *kerberos_instance)
|
const char *kerberos_instance)
|
||||||
{
|
{
|
||||||
#ifdef KRB5
|
#ifdef KRB5
|
||||||
krb5_context context;
|
|
||||||
krb5_error_code ret;
|
krb5_error_code ret;
|
||||||
krb5_principal p;
|
krb5_principal p;
|
||||||
krb5_ccache ccache;
|
|
||||||
|
|
||||||
ret = krb5_init_context (&context);
|
ret = krb5_init_context (&context);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@@ -140,7 +149,7 @@ verify_krb5(struct passwd *login_info, struct passwd *su_info,
|
|||||||
NULL);
|
NULL);
|
||||||
else
|
else
|
||||||
ret = krb5_make_principal(context, &p, NULL,
|
ret = krb5_make_principal(context, &p, NULL,
|
||||||
login_info->pw_name,
|
su_info->pw_name,
|
||||||
NULL);
|
NULL);
|
||||||
if(ret)
|
if(ret)
|
||||||
return 1;
|
return 1;
|
||||||
@@ -153,51 +162,59 @@ verify_krb5(struct passwd *login_info, struct passwd *su_info,
|
|||||||
#endif
|
#endif
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
krb5_cc_initialize (context, ccache, p);
|
||||||
ret = krb5_verify_user(context, p, ccache, NULL, TRUE, NULL);
|
ret = krb5_verify_user(context, p, ccache, NULL, TRUE, NULL);
|
||||||
if(ret) {
|
if(ret) {
|
||||||
|
krb5_free_principal (context, p);
|
||||||
krb5_cc_destroy(context, ccache);
|
krb5_cc_destroy(context, ccache);
|
||||||
#if 1
|
|
||||||
switch (ret) {
|
switch (ret) {
|
||||||
case KRB5KRB_AP_ERR_BAD_INTEGRITY:
|
case KRB5KRB_AP_ERR_BAD_INTEGRITY:
|
||||||
case KRB5KRB_AP_ERR_MODIFIED:
|
case KRB5KRB_AP_ERR_MODIFIED:
|
||||||
krb5_warnx(context, "Password incorrect");
|
krb5_warnx(context, "Password incorrect");
|
||||||
|
break;
|
||||||
default :
|
default :
|
||||||
krb5_warn(context, ret, "krb5_verify_user");
|
krb5_warn(context, ret, "krb5_verify_user");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
{
|
|
||||||
krb5_ccache ccache2;
|
|
||||||
char *cc_name;
|
|
||||||
|
|
||||||
if (seteuid(su_info->pw_uid))
|
|
||||||
krb5_err (context, 1, errno, "seteuid");
|
|
||||||
ret = krb5_cc_gen_new(context, &krb5_fcc_ops, &ccache2);
|
|
||||||
if (ret) {
|
|
||||||
if (seteuid (0))
|
|
||||||
krb5_err (context, 1, errno, "seteuid");
|
|
||||||
krb5_cc_destroy(context, ccache);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = krb5_cc_copy_cache(context, ccache, ccache2);
|
|
||||||
if (seteuid(0))
|
|
||||||
krb5_err (context, 1, errno, "seteuid");
|
|
||||||
|
|
||||||
asprintf(&cc_name, "%s:%s", krb5_cc_get_type(context, ccache2),
|
|
||||||
krb5_cc_get_name(context, ccache2));
|
|
||||||
setenv("KRB5CCNAME", cc_name, 1);
|
|
||||||
ret = krb5_cc_close(context, ccache2);
|
|
||||||
}
|
|
||||||
krb5_cc_destroy(context, ccache);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef KRB5
|
||||||
|
static int
|
||||||
|
krb5_start_session(void)
|
||||||
|
{
|
||||||
|
krb5_ccache ccache2;
|
||||||
|
char *cc_name;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = krb5_cc_gen_new(context, &krb5_fcc_ops, &ccache2);
|
||||||
|
if (ret) {
|
||||||
|
krb5_cc_destroy(context, ccache);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = krb5_cc_copy_cache(context, ccache, ccache2);
|
||||||
|
|
||||||
|
asprintf(&cc_name, "%s:%s", krb5_cc_get_type(context, ccache2),
|
||||||
|
krb5_cc_get_name(context, ccache2));
|
||||||
|
setenv("KRB5CCNAME", cc_name, 1);
|
||||||
|
|
||||||
|
if(k_hasafs()) {
|
||||||
|
if (k_setpag() == 0)
|
||||||
|
krb5_afslog(context, ccache2, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
krb5_cc_close(context, ccache2);
|
||||||
|
krb5_cc_destroy(context, ccache);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int
|
static int
|
||||||
verify_unix(struct passwd *su)
|
verify_unix(struct passwd *su)
|
||||||
{
|
{
|
||||||
@@ -221,7 +238,7 @@ verify_unix(struct passwd *su)
|
|||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int optind = 0;
|
int i, optind = 0;
|
||||||
char *su_user;
|
char *su_user;
|
||||||
struct passwd *su_info;
|
struct passwd *su_info;
|
||||||
char *login_user = NULL;
|
char *login_user = NULL;
|
||||||
@@ -232,12 +249,19 @@ main(int argc, char **argv)
|
|||||||
char *shell;
|
char *shell;
|
||||||
|
|
||||||
int ok = 0;
|
int ok = 0;
|
||||||
|
int kerberos_error=1;
|
||||||
|
|
||||||
set_progname (argv[0]);
|
set_progname (argv[0]);
|
||||||
|
|
||||||
if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optind))
|
if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optind))
|
||||||
usage(1);
|
usage(1);
|
||||||
|
|
||||||
|
for (i=0; i < optind; i++)
|
||||||
|
if (strcmp(argv[i], "-") == 0) {
|
||||||
|
full_login = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if(help_flag)
|
if(help_flag)
|
||||||
usage(0);
|
usage(0);
|
||||||
if(version_flag) {
|
if(version_flag) {
|
||||||
@@ -273,23 +297,56 @@ main(int argc, char **argv)
|
|||||||
if(shell == NULL || *shell == '\0')
|
if(shell == NULL || *shell == '\0')
|
||||||
shell = _PATH_BSHELL;
|
shell = _PATH_BSHELL;
|
||||||
|
|
||||||
if(ok == 0 && verify_krb5(login_info, su_info, kerberos_instance) == 0)
|
if(kerberos_flag && ok == 0 &&
|
||||||
|
(kerberos_error=krb5_verify(login_info, su_info, kerberos_instance)) == 0)
|
||||||
ok++;
|
ok++;
|
||||||
|
|
||||||
if(ok == 0 && verify_unix(su_info) != 0) {
|
if(ok == 0 && login_info->pw_uid && verify_unix(su_info) != 0) {
|
||||||
printf("Sorry!\n");
|
printf("Sorry!\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_GETSPNAM
|
||||||
|
{ struct spwd *sp;
|
||||||
|
long today;
|
||||||
|
|
||||||
|
sp=getspnam(su_info->pw_name);
|
||||||
|
if (sp==NULL)
|
||||||
|
errx(1,"Have not rights to read shadow passwords!");
|
||||||
|
today = time(0)/(24L * 60 * 60);
|
||||||
|
if (sp->sp_expire > 0) {
|
||||||
|
if (today >= sp->sp_expire) {
|
||||||
|
if (login_info->pw_uid)
|
||||||
|
errx(1,"Your account has expired.");
|
||||||
|
else
|
||||||
|
printf("Your account has expired.");
|
||||||
|
}
|
||||||
|
else if (sp->sp_expire - today < 14)
|
||||||
|
printf("Your account will expire in %d days.\n",
|
||||||
|
(int)(sp->sp_expire - today));
|
||||||
|
}
|
||||||
|
if (sp->sp_max > 0) {
|
||||||
|
if (today >= sp->sp_lstchg + sp->sp_max) {
|
||||||
|
if (login_info->pw_uid)
|
||||||
|
errx(1,"Your password has expired. Choose a new one.");
|
||||||
|
else
|
||||||
|
printf("Your password has expired. Choose a new one.");
|
||||||
|
}
|
||||||
|
else if (today >= sp->sp_lstchg + sp->sp_max - sp->sp_warn)
|
||||||
|
printf("Your account will expire in %d days.\n",
|
||||||
|
(int)(sp->sp_lstchg + sp->sp_max -today));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
char *tty = ttyname (STDERR_FILENO);
|
char *tty = ttyname (STDERR_FILENO);
|
||||||
syslog (LOG_NOTICE | LOG_AUTH, tty ? "%s to %s" : "%s to %s on %s",
|
syslog (LOG_NOTICE | LOG_AUTH, tty ? "%s to %s" : "%s to %s on %s",
|
||||||
login_info->pw_name, su_info->pw_name, tty);
|
login_info->pw_name, su_info->pw_name, tty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if(!env_flag) {
|
if(!env_flag) {
|
||||||
if(full_login) {
|
if(full_login) {
|
||||||
char *k = getenv ("KRBTKFILE");
|
|
||||||
char *t = getenv ("TERM");
|
char *t = getenv ("TERM");
|
||||||
|
|
||||||
environ = malloc (10 * sizeof (char *));
|
environ = malloc (10 * sizeof (char *));
|
||||||
@@ -299,9 +356,7 @@ main(int argc, char **argv)
|
|||||||
setenv ("PATH", _PATH_DEFPATH, 1);
|
setenv ("PATH", _PATH_DEFPATH, 1);
|
||||||
if (t)
|
if (t)
|
||||||
setenv ("TERM", t, 1);
|
setenv ("TERM", t, 1);
|
||||||
if (k)
|
if (chdir (su_info->pw_dir) < 0)
|
||||||
setenv ("KRBTKFILE", k, 1);
|
|
||||||
if (chdir (pwd->pw_dir) < 0)
|
|
||||||
errx (1, "no directory");
|
errx (1, "no directory");
|
||||||
}
|
}
|
||||||
if (full_login || su_info->pw_uid)
|
if (full_login || su_info->pw_uid)
|
||||||
@@ -324,7 +379,7 @@ main(int argc, char **argv)
|
|||||||
if (strcmp(p, "csh") != 0)
|
if (strcmp(p, "csh") != 0)
|
||||||
csh_f_flag = 0;
|
csh_f_flag = 0;
|
||||||
|
|
||||||
args = malloc((1 + argc - optind + 1 + csh_f_flag) * sizeof(*args));
|
args = malloc(((cmd ? 2 : 0) + 1 + argc - optind + 1 + csh_f_flag) * sizeof(*args));
|
||||||
if (args == NULL)
|
if (args == NULL)
|
||||||
err (1, "malloc");
|
err (1, "malloc");
|
||||||
i = 0;
|
i = 0;
|
||||||
@@ -332,12 +387,18 @@ main(int argc, char **argv)
|
|||||||
asprintf(&args[i++], "-%s", p);
|
asprintf(&args[i++], "-%s", p);
|
||||||
else
|
else
|
||||||
args[i++] = p;
|
args[i++] = p;
|
||||||
|
if (cmd) {
|
||||||
|
args[i++] = "-c";
|
||||||
|
args[i++] = cmd;
|
||||||
|
}
|
||||||
|
|
||||||
if (csh_f_flag)
|
if (csh_f_flag)
|
||||||
args[i++] = "-f";
|
args[i++] = "-f";
|
||||||
|
|
||||||
for(; i < argc - optind + i; i++)
|
for (argv += optind; *argv; ++argv)
|
||||||
args[i] = argv[optind + i - 1];
|
args[i++] = *argv;
|
||||||
args[i] = NULL;
|
args[i] = NULL;
|
||||||
|
|
||||||
if(setgid(su_info->pw_gid) < 0)
|
if(setgid(su_info->pw_gid) < 0)
|
||||||
err(1, "setgid");
|
err(1, "setgid");
|
||||||
if (initgroups (su_info->pw_name, su_info->pw_gid) < 0)
|
if (initgroups (su_info->pw_name, su_info->pw_gid) < 0)
|
||||||
@@ -345,6 +406,10 @@ main(int argc, char **argv)
|
|||||||
if(setuid(su_info->pw_uid) < 0)
|
if(setuid(su_info->pw_uid) < 0)
|
||||||
err(1, "setuid");
|
err(1, "setuid");
|
||||||
|
|
||||||
|
#ifdef KRB5
|
||||||
|
if (!kerberos_error)
|
||||||
|
krb5_start_session();
|
||||||
|
#endif
|
||||||
execv(shell, args);
|
execv(shell, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user