- make LOGIN_CAP mandatory

- eliminate global pamh
- use setusercontext() properly (ideas borrowed from FreeBSD)
- remove stray debugging.

This now works.
This commit is contained in:
christos 2005-01-10 23:33:53 +00:00
parent 6b47b9b52a
commit 81b53d0cfa
1 changed files with 31 additions and 41 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: su_pam.c,v 1.1 2005/01/10 03:11:50 christos Exp $ */ /* $NetBSD: su_pam.c,v 1.2 2005/01/10 23:33:53 christos Exp $ */
/* /*
* Copyright (c) 1988 The Regents of the University of California. * Copyright (c) 1988 The Regents of the University of California.
@ -40,7 +40,7 @@ __COPYRIGHT(
#if 0 #if 0
static char sccsid[] = "@(#)su.c 8.3 (Berkeley) 4/2/94";*/ static char sccsid[] = "@(#)su.c 8.3 (Berkeley) 4/2/94";*/
#else #else
__RCSID("$NetBSD: su_pam.c,v 1.1 2005/01/10 03:11:50 christos Exp $"); __RCSID("$NetBSD: su_pam.c,v 1.2 2005/01/10 23:33:53 christos Exp $");
#endif #endif
#endif /* not lint */ #endif /* not lint */
@ -60,17 +60,13 @@ __RCSID("$NetBSD: su_pam.c,v 1.1 2005/01/10 03:11:50 christos Exp $");
#include <time.h> #include <time.h>
#include <tzfile.h> #include <tzfile.h>
#include <unistd.h> #include <unistd.h>
#ifdef LOGIN_CAP
#include <login_cap.h> #include <login_cap.h>
#endif
#include <security/pam_appl.h> #include <security/pam_appl.h>
#include <security/openpam.h> /* for openpam_ttyconv() */ #include <security/openpam.h> /* for openpam_ttyconv() */
static pam_handle_t *pamh = NULL;
static const struct pam_conv pamc = { &openpam_ttyconv, NULL }; static const struct pam_conv pamc = { &openpam_ttyconv, NULL };
static int chshell(const char *); static int chshell(const char *);
static char *ontty(void); static char *ontty(void);
@ -91,7 +87,7 @@ main(int argc, char **argv)
struct passwd *pwd; struct passwd *pwd;
char *p; char *p;
uid_t ruid; uid_t ruid;
int asme, ch, asthem, fastlogin, prio, gohome; int asme, ch, asthem, fastlogin, prio, gohome, setwhat;
enum { UNSET, YES, NO } iscsh = UNSET; enum { UNSET, YES, NO } iscsh = UNSET;
char *user, *shell, *avshell, *username, **np; char *user, *shell, *avshell, *username, **np;
char *class; char *class;
@ -101,9 +97,8 @@ main(int argc, char **argv)
char *tty; char *tty;
const char *func; const char *func;
const void *newuser; const void *newuser;
#ifdef LOGIN_CAP
login_cap_t *lc; login_cap_t *lc;
#endif pam_handle_t *pamh = NULL;
#ifdef PAM_DEBUG #ifdef PAM_DEBUG
extern int _openpam_debug; extern int _openpam_debug;
_openpam_debug = 1; _openpam_debug = 1;
@ -114,11 +109,9 @@ main(int argc, char **argv)
shell = class = NULL; shell = class = NULL;
while ((ch = getopt(argc, argv, ARGSTR)) != -1) while ((ch = getopt(argc, argv, ARGSTR)) != -1)
switch((char)ch) { switch((char)ch) {
#ifdef LOGIN_CAP
case 'c': case 'c':
class = optarg; class = optarg;
break; break;
#endif
case 'd': case 'd':
asme = 0; asme = 0;
asthem = 1; asthem = 1;
@ -263,7 +256,6 @@ main(int argc, char **argv)
err args; \ err args; \
} while (/* CONSTOCOND */0) } while (/* CONSTOCOND */0)
#ifdef LOGIN_CAP
/* force the usage of specified class */ /* force the usage of specified class */
if (class) { if (class) {
if (ruid) if (ruid)
@ -271,9 +263,9 @@ main(int argc, char **argv)
pwd->pw_class = class; pwd->pw_class = class;
} }
if ((lc = login_getclass(pwd->pw_class)) == NULL) if ((lc = login_getclass(pwd->pw_class)) == NULL)
ERRX_PAM_END((1, "Unknown class %s\n", pwd->pw_class)); ERRX_PAM_END((1, "Unknown class %s\n", pwd->pw_class));
#endif
if (asme) { if (asme) {
/* if asme and non-standard target shell, must be root */ /* if asme and non-standard target shell, must be root */
@ -296,27 +288,16 @@ main(int argc, char **argv)
if (iscsh == UNSET) if (iscsh == UNSET)
iscsh = strstr(avshell, "csh") ? YES : NO; iscsh = strstr(avshell, "csh") ? YES : NO;
/* /*
* Set permissions. We change the user credentials (UID) here * Initialize the supplemental groups before pam gets to them,
* XXX PAM should come before LOGIN_CAP so that the class * so that other pam modules get a chance to add more when
* specified through -c can override PAM. But as we might drop * we do setcred. Note, we don't relinguish our set-userid yet
* root UID on both operations, it is not possible to do that.
* If a login class was specified, skip PAM.
*/ */
#ifdef LOGIN_CAP if (setusercontext(lc, pwd, pwd->pw_uid, LOGIN_SETGROUP) < 0)
if (class) { ERR_PAM_END((1, "setting user context"));
if (setusercontext(lc, pwd, pwd->pw_uid,
(asthem ? (LOGIN_SETPRIORITY | LOGIN_SETUMASK) : 0) | if ((pam_err = pam_setcred(pamh, PAM_ESTABLISH_CRED)) != PAM_SUCCESS)
LOGIN_SETRESOURCES | LOGIN_SETGROUP | LOGIN_SETUSER)) PAM_END("pam_setcred");
ERR_PAM_END((1, "setting user context"));
printf("%d %d\n", asthem, pwd->pw_uid);
} else
#endif
{
pam_err = pam_setcred(pamh, PAM_ESTABLISH_CRED);
if (pam_err != PAM_SUCCESS)
PAM_END("pam_setcred");
}
/* /*
* Manage session. * Manage session.
@ -432,12 +413,8 @@ main(int argc, char **argv)
free(pamenv); free(pamenv);
} }
#ifdef LOGIN_CAP
if (setusercontext(lc, pwd, pwd->pw_uid, LOGIN_SETPATH)) if (setusercontext(lc, pwd, pwd->pw_uid, LOGIN_SETPATH))
err(1, "setting user context"); err(1, "setting user context");
#else
(void)setenv("PATH", _PATH_DEFPATH, 1);
#endif
if (p) if (p)
(void)setenv("TERM", p, 1); (void)setenv("TERM", p, 1);
if (gohome && chdir(pwd->pw_dir) < 0) if (gohome && chdir(pwd->pw_dir) < 0)
@ -477,10 +454,23 @@ main(int argc, char **argv)
syslog(LOG_NOTICE, "%s to %s%s", syslog(LOG_NOTICE, "%s to %s%s",
username, pwd->pw_name, ontty()); username, pwd->pw_name, ontty());
/* Raise our priority back to what we had before */ /*
(void)setpriority(PRIO_PROCESS, 0, prio); * Set user context, except for umask, and the stuff
* we have done before.
*/
setwhat = LOGIN_SETALL & ~(LOGIN_SETENV|LOGIN_SETUMASK|
LOGIN_SETLOGIN|LOGIN_SETPATH|LOGIN_SETGROUP);
/*
* Don't touch resource/priority settings if -m has been used
* or -l and -c hasn't, and we're not su'ing to root.
*/
if ((asme || (!asthem && class == NULL)) && pwd->pw_uid)
setwhat &= ~(LOGIN_SETPRIORITY|LOGIN_SETRESOURCES);
if (setusercontext(lc, pwd, pwd->pw_uid, setwhat) == -1)
err(1, "setusercontext");
printf("%d %d\n", geteuid(), getuid());
(void)execv(shell, np); (void)execv(shell, np);
err(1, "%s", shell); err(1, "%s", shell);
done: done: