[Pkg-shadow-commits] r3345 - in upstream/trunk: . src
Nicolas FRANÇOIS
nekral-guest at alioth.debian.org
Mon Jun 13 18:26:16 UTC 2011
Author: nekral-guest
Date: 2011-06-13 18:26:16 +0000 (Mon, 13 Jun 2011)
New Revision: 3345
Modified:
upstream/trunk/ChangeLog
upstream/trunk/src/su.c
Log:
* src/su.c: Extract the authentication from the main function.
Modified: upstream/trunk/ChangeLog
===================================================================
--- upstream/trunk/ChangeLog 2011-06-13 18:26:10 UTC (rev 3344)
+++ upstream/trunk/ChangeLog 2011-06-13 18:26:16 UTC (rev 3345)
@@ -16,6 +16,7 @@
* src/su.c: Define shellstr before the environment so that
restricted_shell is called only once. This will allow moving the
environment definition after the switch to the new user.
+ * src/su.c: Extract the authentication from the main function.
2011-06-10 Nicolas François <nicolas.francois at centraliens.net>
Modified: upstream/trunk/src/su.c
===================================================================
--- upstream/trunk/src/su.c 2011-06-13 18:26:10 UTC (rev 3344)
+++ upstream/trunk/src/su.c 2011-06-13 18:26:16 UTC (rev 3345)
@@ -114,6 +114,7 @@
static RETSIGTYPE die (int);
static bool iswheel (const char *);
#endif /* !USE_PAM */
+static void check_perms (void);
#ifndef USE_PAM
/*
@@ -407,6 +408,189 @@
}
/*
+ * check_perms - check permissions to switch to the user 'name'
+ *
+ * In case of subsystem login, the user is first authenticated in the
+ * caller's root subsystem, and then in the user's target subsystem.
+ */
+static void check_perms (void)
+{
+ /*
+ * The password file entries for the user is gotten and the account
+ * validated.
+ */
+ pw = xgetpwnam (name);
+ if (NULL == pw) {
+ (void) fprintf (stderr, _("Unknown id: %s\n"), name);
+ closelog ();
+ exit (1);
+ }
+#ifndef USE_PAM
+ spwd = NULL;
+ if (strcmp (pw->pw_passwd, SHADOW_PASSWD_STRING) == 0) {
+ spwd = getspnam (name); /* !USE_PAM, no need for xgetspnam */
+ if (NULL != spwd) {
+ pw->pw_passwd = spwd->sp_pwdp;
+ }
+ }
+#endif /* !USE_PAM */
+ pwent = *pw;
+
+#ifndef USE_PAM
+ /*
+ * BSD systems only allow "wheel" to SU to root. USG systems don't,
+ * so we make this a configurable option.
+ */
+
+ /* The original Shadow 3.3.2 did this differently. Do it like BSD:
+ *
+ * - check for UID 0 instead of name "root" - there are systems with
+ * several root accounts under different names,
+ *
+ * - check the contents of /etc/group instead of the current group
+ * set (you must be listed as a member, GID 0 is not sufficient).
+ *
+ * In addition to this traditional feature, we now have complete su
+ * access control (allow, deny, no password, own password). Thanks
+ * to Chris Evans <lady0110 at sable.ox.ac.uk>.
+ */
+
+ if (!amroot) {
+ if ( (0 == pwent.pw_uid)
+ && getdef_bool ("SU_WHEEL_ONLY")
+ && !iswheel (oldname)) {
+ fprintf (stderr,
+ _("You are not authorized to su %s\n"),
+ name);
+ exit (1);
+ }
+#ifdef SU_ACCESS
+ switch (check_su_auth (oldname, name)) {
+ case 0: /* normal su, require target user's password */
+ break;
+ case 1: /* require no password */
+ pwent.pw_passwd = ""; /* XXX warning: const */
+ break;
+ case 2: /* require own password */
+ puts (_("(Enter your own password)"));
+ pwent.pw_passwd = oldpass;
+ break;
+ default: /* access denied (-1) or unexpected value */
+ fprintf (stderr,
+ _("You are not authorized to su %s\n"),
+ name);
+ exit (1);
+ }
+#endif /* SU_ACCESS */
+ }
+#endif /* !USE_PAM */
+
+ (void) signal (SIGINT, SIG_IGN);
+ (void) signal (SIGQUIT, SIG_IGN);
+#ifdef USE_PAM
+ ret = pam_authenticate (pamh, 0);
+ if (PAM_SUCCESS != ret) {
+ SYSLOG ((LOG_ERR, "pam_authenticate: %s",
+ pam_strerror (pamh, ret)));
+ fprintf (stderr, _("%s: %s\n"), Prog, pam_strerror (pamh, ret));
+ (void) pam_end (pamh, ret);
+ su_failure (tty);
+ }
+
+ ret = pam_acct_mgmt (pamh, 0);
+ if (PAM_SUCCESS != ret) {
+ if (amroot) {
+ fprintf (stderr,
+ _("%s: %s\n(Ignored)\n"),
+ Prog, pam_strerror (pamh, ret));
+ } else if (PAM_NEW_AUTHTOK_REQD == ret) {
+ ret = pam_chauthtok (pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
+ if (PAM_SUCCESS != ret) {
+ SYSLOG ((LOG_ERR, "pam_chauthtok: %s",
+ pam_strerror (pamh, ret)));
+ fprintf (stderr,
+ _("%s: %s\n"),
+ Prog, pam_strerror (pamh, ret));
+ (void) pam_end (pamh, ret);
+ su_failure (tty);
+ }
+ } else {
+ SYSLOG ((LOG_ERR, "pam_acct_mgmt: %s",
+ pam_strerror (pamh, ret)));
+ fprintf (stderr,
+ _("%s: %s\n"),
+ Prog, pam_strerror (pamh, ret));
+ (void) pam_end (pamh, ret);
+ su_failure (tty);
+ }
+ }
+#else /* !USE_PAM */
+ /*
+ * Set up a signal handler in case the user types QUIT.
+ */
+ die (0);
+ oldsig = signal (SIGQUIT, die);
+
+ /*
+ * See if the system defined authentication method is being used.
+ * The first character of an administrator defined method is an '@'
+ * character.
+ */
+ if ( !amroot
+ && (pw_auth (pwent.pw_passwd, name, PW_SU, (char *) 0) != 0)) {
+ SYSLOG (((pwent.pw_uid != 0)? LOG_NOTICE : LOG_WARN,
+ "Authentication failed for %s", name));
+ fprintf(stderr, _("%s: Authentication failure\n"), Prog);
+ su_failure (tty);
+ }
+ (void) signal (SIGQUIT, oldsig);
+
+ /*
+ * Check to see if the account is expired. root gets to ignore any
+ * expired accounts, but normal users can't become a user with an
+ * expired password.
+ */
+ if ((!amroot) && (NULL != spwd)) {
+ (void) expire (&pwent, spwd);
+ }
+
+ /*
+ * Check to see if the account permits "su". root gets to ignore any
+ * restricted accounts, but normal users can't become a user if
+ * there is a "SU" entry in the /etc/porttime file denying access to
+ * the account.
+ */
+ if (!amroot) {
+ if (!isttytime (pwent.pw_name, "SU", time ((time_t *) 0))) {
+ SYSLOG (((0 != pwent.pw_uid) ? LOG_WARN : LOG_CRIT,
+ "SU by %s to restricted account %s",
+ oldname, name));
+ fprintf (stderr,
+ _("%s: You are not authorized to su at that time\n"),
+ Prog);
+ su_failure (tty);
+ }
+ }
+#endif /* !USE_PAM */
+
+ (void) signal (SIGINT, SIG_DFL);
+ (void) signal (SIGQUIT, SIG_DFL);
+
+ /*
+ * Even if --shell is specified, the subsystem login test is based on
+ * the shell specified in /etc/passwd (not the one specified with
+ * --shell, which will be the one executed in the chroot later).
+ */
+ if ('*' == pwent.pw_shell[0]) { /* subsystem root required */
+ subsystem (&pwent); /* change to the subsystem root */
+ endpwent (); /* close the old password databases */
+ endspent ();
+ return check_perms (); /* authenticate in the subsystem */
+ }
+
+}
+
+/*
* su - switch user id
*
* su changes the user's ids to the values for the specified user. if
@@ -626,184 +810,8 @@
}
#endif /* USE_PAM */
- top:
- /*
- * This is the common point for validating a user whose name is
- * known. It will be reached either by normal processing, or if the
- * user is to be logged into a subsystem root.
- *
- * The password file entries for the user is gotten and the account
- * validated.
- */
- pw = xgetpwnam (name);
- if (NULL == pw) {
- (void) fprintf (stderr, _("Unknown id: %s\n"), name);
- closelog ();
- exit (1);
- }
-#ifndef USE_PAM
- spwd = NULL;
- if (strcmp (pw->pw_passwd, SHADOW_PASSWD_STRING) == 0) {
- spwd = getspnam (name); /* !USE_PAM, no need for xgetspnam */
- if (NULL != spwd) {
- pw->pw_passwd = spwd->sp_pwdp;
- }
- }
-#endif /* !USE_PAM */
- pwent = *pw;
+ check_perms ();
-#ifndef USE_PAM
- /*
- * BSD systems only allow "wheel" to SU to root. USG systems don't,
- * so we make this a configurable option.
- */
-
- /* The original Shadow 3.3.2 did this differently. Do it like BSD:
- *
- * - check for UID 0 instead of name "root" - there are systems with
- * several root accounts under different names,
- *
- * - check the contents of /etc/group instead of the current group
- * set (you must be listed as a member, GID 0 is not sufficient).
- *
- * In addition to this traditional feature, we now have complete su
- * access control (allow, deny, no password, own password). Thanks
- * to Chris Evans <lady0110 at sable.ox.ac.uk>.
- */
-
- if (!amroot) {
- if ( (0 == pwent.pw_uid)
- && getdef_bool ("SU_WHEEL_ONLY")
- && !iswheel (oldname)) {
- fprintf (stderr,
- _("You are not authorized to su %s\n"),
- name);
- exit (1);
- }
-#ifdef SU_ACCESS
- switch (check_su_auth (oldname, name)) {
- case 0: /* normal su, require target user's password */
- break;
- case 1: /* require no password */
- pwent.pw_passwd = ""; /* XXX warning: const */
- break;
- case 2: /* require own password */
- puts (_("(Enter your own password)"));
- pwent.pw_passwd = oldpass;
- break;
- default: /* access denied (-1) or unexpected value */
- fprintf (stderr,
- _("You are not authorized to su %s\n"),
- name);
- exit (1);
- }
-#endif /* SU_ACCESS */
- }
-#endif /* !USE_PAM */
-
- (void) signal (SIGINT, SIG_IGN);
- (void) signal (SIGQUIT, SIG_IGN);
-#ifdef USE_PAM
- ret = pam_authenticate (pamh, 0);
- if (PAM_SUCCESS != ret) {
- SYSLOG ((LOG_ERR, "pam_authenticate: %s",
- pam_strerror (pamh, ret)));
- fprintf (stderr, _("%s: %s\n"), Prog, pam_strerror (pamh, ret));
- (void) pam_end (pamh, ret);
- su_failure (tty);
- }
-
- ret = pam_acct_mgmt (pamh, 0);
- if (PAM_SUCCESS != ret) {
- if (amroot) {
- fprintf (stderr,
- _("%s: %s\n(Ignored)\n"),
- Prog, pam_strerror (pamh, ret));
- } else if (PAM_NEW_AUTHTOK_REQD == ret) {
- ret = pam_chauthtok (pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
- if (PAM_SUCCESS != ret) {
- SYSLOG ((LOG_ERR, "pam_chauthtok: %s",
- pam_strerror (pamh, ret)));
- fprintf (stderr,
- _("%s: %s\n"),
- Prog, pam_strerror (pamh, ret));
- (void) pam_end (pamh, ret);
- su_failure (tty);
- }
- } else {
- SYSLOG ((LOG_ERR, "pam_acct_mgmt: %s",
- pam_strerror (pamh, ret)));
- fprintf (stderr,
- _("%s: %s\n"),
- Prog, pam_strerror (pamh, ret));
- (void) pam_end (pamh, ret);
- su_failure (tty);
- }
- }
-#else /* !USE_PAM */
- /*
- * Set up a signal handler in case the user types QUIT.
- */
- die (0);
- oldsig = signal (SIGQUIT, die);
-
- /*
- * See if the system defined authentication method is being used.
- * The first character of an administrator defined method is an '@'
- * character.
- */
- if ( !amroot
- && (pw_auth (pwent.pw_passwd, name, PW_SU, (char *) 0) != 0)) {
- SYSLOG (((pwent.pw_uid != 0)? LOG_NOTICE : LOG_WARN,
- "Authentication failed for %s", name));
- fprintf(stderr, _("%s: Authentication failure\n"), Prog);
- su_failure (tty);
- }
- (void) signal (SIGQUIT, oldsig);
-
- /*
- * Check to see if the account is expired. root gets to ignore any
- * expired accounts, but normal users can't become a user with an
- * expired password.
- */
- if ((!amroot) && (NULL != spwd)) {
- (void) expire (&pwent, spwd);
- }
-
- /*
- * Check to see if the account permits "su". root gets to ignore any
- * restricted accounts, but normal users can't become a user if
- * there is a "SU" entry in the /etc/porttime file denying access to
- * the account.
- */
- if (!amroot) {
- if (!isttytime (pwent.pw_name, "SU", time ((time_t *) 0))) {
- SYSLOG (((0 != pwent.pw_uid) ? LOG_WARN : LOG_CRIT,
- "SU by %s to restricted account %s",
- oldname, name));
- fprintf (stderr,
- _("%s: You are not authorized to su at that time\n"),
- Prog);
- su_failure (tty);
- }
- }
-#endif /* !USE_PAM */
-
- (void) signal (SIGINT, SIG_DFL);
- (void) signal (SIGQUIT, SIG_DFL);
-
- /*
- * Even if --shell is specified, the subsystem login test is based on
- * the shell specified in /etc/passwd (not the one specified with
- * --shell, which will be the one executed in the chroot later).
- */
- if ('*' == pwent.pw_shell[0]) { /* subsystem root required */
- subsystem (&pwent); /* change to the subsystem root */
- endpwent (); /* close the old password databases */
- endspent ();
- goto top; /* authenticate in the subsystem */
- }
-
/* If the user do not want to change the environment,
* use the current SHELL.
* (unless another shell is required by the command line)
More information about the Pkg-shadow-commits
mailing list