Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/usr.bin/su Rewrite PAMification of su.
details: https://anonhg.NetBSD.org/src/rev/2fb5a5877642
branches: trunk
changeset: 572652:2fb5a5877642
user: manu <manu%NetBSD.org@localhost>
date: Sun Jan 09 21:32:38 2005 +0000
description:
Rewrite PAMification of su.
- don't try to fallback to plain old authentication. It could lead to unix
authentication to be used while the administrator wanted to forbid it.
Moreover, a broken PAM setup can be fixed by just rebooting in single user.
- In order to make the code more readable, make two main(), with and aithout
PAM.
- Outstanding issues that seem impossible to fix:
The -K flag die with PAM.
-c cause PAM credentials to be ignored.
diffstat:
usr.bin/su/su.c | 601 ++++++++++++++++++++++++++++++++++++++++---------------
1 files changed, 439 insertions(+), 162 deletions(-)
diffs (truncated from 745 to 300 lines):
diff -r 06616012b65d -r 2fb5a5877642 usr.bin/su/su.c
--- a/usr.bin/su/su.c Sun Jan 09 21:32:08 2005 +0000
+++ b/usr.bin/su/su.c Sun Jan 09 21:32:38 2005 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: su.c,v 1.62 2005/01/08 22:16:23 manu Exp $ */
+/* $NetBSD: su.c,v 1.63 2005/01/09 21:32:38 manu Exp $ */
/*
* Copyright (c) 1988 The Regents of the University of California.
@@ -40,16 +40,16 @@
#if 0
static char sccsid[] = "@(#)su.c 8.3 (Berkeley) 4/2/94";*/
#else
-__RCSID("$NetBSD: su.c,v 1.62 2005/01/08 22:16:23 manu Exp $");
+__RCSID("$NetBSD: su.c,v 1.63 2005/01/09 21:32:38 manu Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/time.h>
+#include <sys/resource.h>
#ifdef USE_PAM
#include <sys/wait.h>
#endif
-#include <sys/resource.h>
#include <err.h>
#include <errno.h>
#include <grp.h>
@@ -69,32 +69,16 @@
#ifdef USE_PAM
#include <security/pam_appl.h>
#include <security/openpam.h> /* for openpam_ttyconv() */
-
-static pam_handle_t *pamh;
-static struct pam_conv pamc;
-
-#define fatal(x) do { \
- if (pam_err == PAM_SUCCESS) \
- pam_end(pamh, pam_err); \
- err x; \
-} while (/*CONSTCOND*/ 0)
-#define fatalx(x) do { \
- if (pam_err == PAM_SUCCESS) \
- pam_end(pamh, pam_err); \
- errx x; \
-} while (/*CONSTCOND*/ 0)
-
-#else
-#define fatal(x) err x
-#define fatalx(x) errx x
-
+
+static pam_handle_t *pamh = NULL;
+static const struct pam_conv pamc = { &openpam_ttyconv, NULL };
#endif
#ifdef LOGIN_CAP
#include <login_cap.h>
#endif
-#ifdef KERBEROS
+#if defined(KERBEROS) && !defined(USE_PAM)
#include <des.h>
#include <krb.h>
#include <netdb.h>
@@ -104,7 +88,7 @@
#endif
-#ifdef KERBEROS5
+#if defined(KERBEROS5) && !defined(USE_PAM)
#include <krb5.h>
static int kerberos5 __P((char *, char *, int));
@@ -135,9 +119,12 @@
static int chshell __P((const char *));
static char *ontty __P((void));
+#ifndef USE_PAM
static int check_ingroup __P((int, const char *, const char *, int));
+#endif
+#ifndef USE_PAM
int
main(argc, argv)
int argc;
@@ -159,18 +146,6 @@
#ifdef LOGIN_CAP
login_cap_t *lc;
#endif
-#ifdef USE_PAM
- char **pam_envlist, **pam_env;
- char hostname[MAXHOSTNAMELEN];
- const char **usernamep;
- char *tty;
- int pam_err, status;
- pid_t pid;
-#ifdef notdef
- extern int _openpam_debug;
- _openpam_debug = 1;
-#endif
-#endif
asme = asthem = fastlogin = 0;
gohome = 1;
@@ -225,99 +200,16 @@
/* get current login name and shell */
ruid = getuid();
username = getlogin();
- /* get target login information, default to root */
- user = *argv ? *argv : "root";
-
-#ifdef USE_PAM
- pamc.conv = &openpam_ttyconv;
- pam_start("su", user, &pamc, &pamh);
-
- /* Fill in hostname, username and tty */
- if ((pam_err = pam_set_item(pamh, PAM_RUSER, username)) != PAM_SUCCESS)
- goto pam_failed;
-
- gethostname(hostname, sizeof(hostname));
- if ((pam_err = pam_set_item(pamh, PAM_RHOST, hostname)) != PAM_SUCCESS)
- goto pam_failed;
-
- tty = ttyname(STDERR_FILENO);
- if ((pam_err = pam_set_item(pamh, PAM_TTY, tty)) != PAM_SUCCESS)
- goto pam_failed;
-
- /* authentication */
- if ((pam_err = pam_authenticate(pamh, 0)) != PAM_SUCCESS)
- goto pam_failed;
-
- if ((pam_err = pam_acct_mgmt(pamh, 0)) == PAM_NEW_AUTHTOK_REQD)
- pam_err = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
- if (pam_err != PAM_SUCCESS)
- goto pam_failed;
-
- /* Get user credentials */
- if ((pam_err = pam_setcred(pamh, PAM_ESTABLISH_CRED)) != PAM_SUCCESS)
- goto pam_failed;
-
- /* Open the session */
- if ((pam_err = pam_open_session(pamh, 0)) != PAM_SUCCESS)
- goto pam_failed;
-
- /* New user name? */
- usernamep = (const char **)&username;
- pam_err = pam_get_item(pamh, PAM_USER, (const void **)usernamep);
- if (pam_err != PAM_SUCCESS)
- goto pam_failed;
-
-pam_failed:
- /*
- * If PAM is broken, fallback to plain old authentication.
- * Do not do that on authentication errors.
- */
- switch(pam_err) {
- case PAM_SUCCESS:
- break;
-
- case PAM_ABORT:
- case PAM_BUF_ERR:
- case PAM_SYMBOL_ERR:
- case PAM_SYSTEM_ERR:
- warnx("PAM failed: %s", pam_strerror(pamh, pam_err));
- warnx("fallback to plain old authentication");
- pam_end(pamh, pam_err);
- username = getlogin();
- break;
-
- default:
- fatalx((1, "Sorry: %s\n", pam_strerror(pamh, pam_err)));
- break;
- }
-
- /*
- * Now any failure should use fatal/fatalx instead of err/errx
- * so that pam_end() is called on errors.
- */
-#endif
if (username == NULL || (pwd = getpwnam(username)) == NULL ||
pwd->pw_uid != ruid)
pwd = getpwuid(ruid);
if (pwd == NULL)
- fatalx((1, "who are you?"));
-
+ errx(1, "who are you?");
username = strdup(pwd->pw_name);
userpass = strdup(pwd->pw_passwd);
if (username == NULL || userpass == NULL)
- fatal((1, "strdup"));
+ err(1, "strdup");
-#ifdef USE_PAM
- /* Get PAM environment */
- if ((pam_err == PAM_SUCCESS) &&
- ((pam_envlist = pam_getenvlist(pamh)) != NULL)) {
- for (pam_env = pam_envlist; *pam_env != NULL; ++pam_env) {
- putenv(*pam_env);
- free(*pam_env);
- }
- free(pam_envlist);
- }
-#endif
if (asme) {
if (pwd->pw_shell && *pwd->pw_shell) {
@@ -328,20 +220,23 @@
iscsh = NO;
}
}
+ /* get target login information, default to root */
+ user = *argv ? *argv : "root";
np = *argv ? argv : argv-1;
if ((pwd = getpwnam(user)) == NULL)
- fatalx((1, "unknown login %s", user));
+ errx(1, "unknown login %s", user);
#ifdef LOGIN_CAP
/* force the usage of specified class */
if (class) {
if (ruid)
- fatalx((1, "Only root may use -c"));
+ errx(1, "Only root may use -c");
pwd->pw_class = class;
}
- lc = login_getclass(pwd->pw_class);
+ if ((lc = login_getclass(pwd->pw_class)) == NULL)
+ errx(1, "Unknown class %s\n", pwd->pw_class);
pw_warntime = login_getcaptime(lc, "password-warn",
_PASSWORD_WARNDAYS * SECSPERDAY,
@@ -349,9 +244,6 @@
#endif
if (ruid
-#ifdef USE_PAM
- && (pam_err != PAM_SUCCESS)
-#endif
#ifdef KERBEROS5
&& (!use_kerberos || kerberos5(username, user, pwd->pw_uid))
#endif
@@ -383,18 +275,17 @@
ok = check_ingroup(-1, SU_GROUP, username, 1);
}
if (!ok)
- fatalx((1,
+ errx(1,
"you are not listed in the correct secondary group (%s) to su %s.",
- SU_GROUP, user));
+ SU_GROUP, user);
/* if target requires a password, verify it */
if (*pass) {
p = getpass("Password:");
#ifdef SKEY
if (strcasecmp(p, "s/key") == 0) {
- if (skey_haskey(user)) {
- fatalx((1,
- "Sorry, you have no s/key."));
- } else {
+ if (skey_haskey(user))
+ errx(1, "Sorry, you have no s/key.");
+ else {
if (skey_authenticate(user)) {
goto badlogin;
}
@@ -418,7 +309,7 @@
if (asme) {
/* if asme and non-standard target shell, must be root */
if (!chshell(pwd->pw_shell) && ruid)
- fatalx((1,"permission denied (shell)."));
+ errx(1,"permission denied (shell).");
} else if (pwd->pw_shell && *pwd->pw_shell) {
shell = pwd->pw_shell;
iscsh = UNSET;
@@ -436,34 +327,6 @@
if (iscsh == UNSET)
iscsh = strstr(avshell, "csh") ? YES : NO;
-#ifdef USE_PAM
- /*
- * If PAM is in use, we must release PAM resources and close
- * the session after su child exits. That requires a fork now,
- * before we drop the root privs (needed for PAM)
- */
- if (pam_err == PAM_SUCCESS) {
- switch(pid = fork()) {
- case -1:
- fatal((1, "fork"));
- break;
- case 0: /* child */
- break;
- default: /* parent */
- waitpid(pid, &status, 0);
- pam_err = pam_close_session(pamh, 0);
- pam_end(pamh, pam_err);
-
Home |
Main Index |
Thread Index |
Old Index