Add open/close session to sudo auth, only used by PAM.
This allows us to open (and close) the PAM session from sudoers.
This commit is contained in:
@@ -81,7 +81,7 @@ static int gotintr;
|
|||||||
#define PAM_DATA_SILENT 0
|
#define PAM_DATA_SILENT 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static pam_handle_t *pamh; /* global due to pam_prep_user() */
|
static pam_handle_t *pamh;
|
||||||
|
|
||||||
int
|
int
|
||||||
pam_init(pw, promptp, auth)
|
pam_init(pw, promptp, auth)
|
||||||
@@ -189,7 +189,7 @@ pam_cleanup(pw, auth)
|
|||||||
{
|
{
|
||||||
int *pam_status = (int *) auth->data;
|
int *pam_status = (int *) auth->data;
|
||||||
|
|
||||||
/* If successful, we can't close the session until pam_prep_user() */
|
/* If successful, we can't close the session until pam_end_session() */
|
||||||
if (auth->status == AUTH_SUCCESS)
|
if (auth->status == AUTH_SUCCESS)
|
||||||
return(AUTH_SUCCESS);
|
return(AUTH_SUCCESS);
|
||||||
|
|
||||||
@@ -198,10 +198,11 @@ pam_cleanup(pw, auth)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
pam_prep_user(pw)
|
pam_begin_session(pw, auth)
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
|
sudo_auth *auth;
|
||||||
{
|
{
|
||||||
int eval;
|
int status;
|
||||||
|
|
||||||
if (pamh == NULL)
|
if (pamh == NULL)
|
||||||
pam_init(pw, NULL, NULL);
|
pam_init(pw, NULL, NULL);
|
||||||
@@ -229,17 +230,25 @@ pam_prep_user(pw)
|
|||||||
* can at least cause pam_limits to be run by opening and then
|
* can at least cause pam_limits to be run by opening and then
|
||||||
* immediately closing the session.
|
* immediately closing the session.
|
||||||
*/
|
*/
|
||||||
if ((eval = pam_open_session(pamh, 0)) != PAM_SUCCESS) {
|
status = pam_open_session(pamh, 0);
|
||||||
(void) pam_end(pamh, eval | PAM_DATA_SILENT);
|
if (status != PAM_SUCCESS)
|
||||||
return(AUTH_FAILURE);
|
(void) pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT);
|
||||||
|
#endif
|
||||||
|
return(status == PAM_SUCCESS ? AUTH_SUCCESS : AUTH_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
pam_end_session(auth)
|
||||||
|
sudo_auth *auth;
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
|
||||||
|
#ifndef NO_PAM_SESSION
|
||||||
(void) pam_close_session(pamh, 0);
|
(void) pam_close_session(pamh, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT) == PAM_SUCCESS)
|
status = pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT);
|
||||||
return(AUTH_SUCCESS);
|
return(status == PAM_SUCCESS ? AUTH_SUCCESS : AUTH_FAILURE);
|
||||||
else
|
|
||||||
return(AUTH_FAILURE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -57,33 +57,37 @@ sudo_auth auth_switch[] = {
|
|||||||
AUTH_STANDALONE
|
AUTH_STANDALONE
|
||||||
#else
|
#else
|
||||||
# ifndef WITHOUT_PASSWD
|
# ifndef WITHOUT_PASSWD
|
||||||
AUTH_ENTRY(0, "passwd", passwd_init, NULL, passwd_verify, NULL)
|
AUTH_ENTRY(0, "passwd", passwd_init, NULL, passwd_verify, NULL, NULL, NULL)
|
||||||
# endif
|
# endif
|
||||||
# if defined(HAVE_GETPRPWNAM) && !defined(WITHOUT_PASSWD)
|
# if defined(HAVE_GETPRPWNAM) && !defined(WITHOUT_PASSWD)
|
||||||
AUTH_ENTRY(0, "secureware", secureware_init, NULL, secureware_verify, NULL)
|
AUTH_ENTRY(0, "secureware", secureware_init, NULL, secureware_verify, NULL, NULL, NULL)
|
||||||
# endif
|
# endif
|
||||||
# ifdef HAVE_AFS
|
# ifdef HAVE_AFS
|
||||||
AUTH_ENTRY(0, "afs", NULL, NULL, afs_verify, NULL)
|
AUTH_ENTRY(0, "afs", NULL, NULL, afs_verify, NULL, NULL, NULL)
|
||||||
# endif
|
# endif
|
||||||
# ifdef HAVE_DCE
|
# ifdef HAVE_DCE
|
||||||
AUTH_ENTRY(0, "dce", NULL, NULL, dce_verify, NULL)
|
AUTH_ENTRY(0, "dce", NULL, NULL, dce_verify, NULL, NULL, NULL)
|
||||||
# endif
|
# endif
|
||||||
# ifdef HAVE_KERB4
|
# ifdef HAVE_KERB4
|
||||||
AUTH_ENTRY(0, "kerb4", kerb4_init, NULL, kerb4_verify, NULL)
|
AUTH_ENTRY(0, "kerb4", kerb4_init, NULL, kerb4_verify, NULL, NULL, NULL)
|
||||||
# endif
|
# endif
|
||||||
# ifdef HAVE_KERB5
|
# ifdef HAVE_KERB5
|
||||||
AUTH_ENTRY(0, "kerb5", kerb5_init, NULL, kerb5_verify, kerb5_cleanup)
|
AUTH_ENTRY(0, "kerb5", kerb5_init, NULL, kerb5_verify, kerb5_cleanup, NULL, NULL)
|
||||||
# endif
|
# endif
|
||||||
# ifdef HAVE_SKEY
|
# ifdef HAVE_SKEY
|
||||||
AUTH_ENTRY(0, "S/Key", NULL, rfc1938_setup, rfc1938_verify, NULL)
|
AUTH_ENTRY(0, "S/Key", NULL, rfc1938_setup, rfc1938_verify, NULL, NULL, NULL)
|
||||||
# endif
|
# endif
|
||||||
# ifdef HAVE_OPIE
|
# ifdef HAVE_OPIE
|
||||||
AUTH_ENTRY(0, "OPIE", NULL, rfc1938_setup, rfc1938_verify, NULL)
|
AUTH_ENTRY(0, "OPIE", NULL, rfc1938_setup, rfc1938_verify, NULL, NULL, NULL)
|
||||||
# endif
|
# endif
|
||||||
#endif /* AUTH_STANDALONE */
|
#endif /* AUTH_STANDALONE */
|
||||||
AUTH_ENTRY(0, NULL, NULL, NULL, NULL, NULL)
|
AUTH_ENTRY(0, NULL, NULL, NULL, NULL, NULL, NULL, NULL)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern char **NewArgv; /* XXX - for auditing */
|
||||||
|
|
||||||
|
static void pass_warn(void);
|
||||||
|
|
||||||
int
|
int
|
||||||
verify_user(struct passwd *pw, char *prompt)
|
verify_user(struct passwd *pw, char *prompt)
|
||||||
{
|
{
|
||||||
@@ -93,7 +97,6 @@ verify_user(struct passwd *pw, char *prompt)
|
|||||||
char *p;
|
char *p;
|
||||||
sudo_auth *auth;
|
sudo_auth *auth;
|
||||||
sigaction_t sa, osa;
|
sigaction_t sa, osa;
|
||||||
extern char **NewArgv; /* XXX */
|
|
||||||
|
|
||||||
/* Enable suspend during password entry. */
|
/* Enable suspend during password entry. */
|
||||||
sigemptyset(&sa.sa_mask);
|
sigemptyset(&sa.sa_mask);
|
||||||
@@ -181,8 +184,6 @@ verify_user(struct passwd *pw, char *prompt)
|
|||||||
if (p)
|
if (p)
|
||||||
zero_bytes(p, strlen(p));
|
zero_bytes(p, strlen(p));
|
||||||
#endif
|
#endif
|
||||||
/* XXX - need way to know if askpass was used */
|
|
||||||
//if (!ISSET(tgetpass_flags, TGP_ASKPASS))
|
|
||||||
pass_warn();
|
pass_warn();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,7 +234,40 @@ cleanup:
|
|||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int begin_session(struct passwd *pw)
|
||||||
|
{
|
||||||
|
sudo_auth *auth;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
for (auth = auth_switch; auth->name; auth++) {
|
||||||
|
if (auth->begin_session && IS_CONFIGURED(auth)) {
|
||||||
|
status = (auth->begin_session)(pw, auth);
|
||||||
|
if (status == AUTH_FATAL) { /* XXX log */
|
||||||
|
audit_failure(NewArgv, "authentication failure");
|
||||||
|
return -1; /* assume error msg already printed */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int end_session(void)
|
||||||
|
{
|
||||||
|
sudo_auth *auth;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
for (auth = auth_switch; auth->name; auth++) {
|
||||||
|
if (auth->end_session && IS_CONFIGURED(auth)) {
|
||||||
|
status = (auth->end_session)(auth);
|
||||||
|
if (status == AUTH_FATAL) { /* XXX log */
|
||||||
|
return -1; /* assume error msg already printed */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
pass_warn(void)
|
pass_warn(void)
|
||||||
{
|
{
|
||||||
struct sudo_conv_message msg[2];
|
struct sudo_conv_message msg[2];
|
||||||
|
@@ -32,6 +32,8 @@ typedef struct sudo_auth {
|
|||||||
int (*setup)(struct passwd *pw, char **prompt, struct sudo_auth *auth);
|
int (*setup)(struct passwd *pw, char **prompt, struct sudo_auth *auth);
|
||||||
int (*verify)(struct passwd *pw, char *p, struct sudo_auth *auth);
|
int (*verify)(struct passwd *pw, char *p, struct sudo_auth *auth);
|
||||||
int (*cleanup)(struct passwd *pw, struct sudo_auth *auth);
|
int (*cleanup)(struct passwd *pw, struct sudo_auth *auth);
|
||||||
|
int (*begin_session)(struct passwd *pw, struct sudo_auth *auth);
|
||||||
|
int (*end_session)(struct sudo_auth *auth);
|
||||||
} sudo_auth;
|
} sudo_auth;
|
||||||
|
|
||||||
/* Values for sudo_auth.flags. */
|
/* Values for sudo_auth.flags. */
|
||||||
@@ -58,6 +60,8 @@ int fwtk_cleanup(struct passwd *pw, sudo_auth *auth);
|
|||||||
int pam_init(struct passwd *pw, char **prompt, sudo_auth *auth);
|
int pam_init(struct passwd *pw, char **prompt, sudo_auth *auth);
|
||||||
int pam_verify(struct passwd *pw, char *prompt, sudo_auth *auth);
|
int pam_verify(struct passwd *pw, char *prompt, sudo_auth *auth);
|
||||||
int pam_cleanup(struct passwd *pw, sudo_auth *auth);
|
int pam_cleanup(struct passwd *pw, sudo_auth *auth);
|
||||||
|
int pam_begin_session(struct passwd *pw, sudo_auth *auth);
|
||||||
|
int pam_end_session(sudo_auth *auth);
|
||||||
int sia_setup(struct passwd *pw, char **prompt, sudo_auth *auth);
|
int sia_setup(struct passwd *pw, char **prompt, sudo_auth *auth);
|
||||||
int sia_verify(struct passwd *pw, char *prompt, sudo_auth *auth);
|
int sia_verify(struct passwd *pw, char *prompt, sudo_auth *auth);
|
||||||
int sia_cleanup(struct passwd *pw, sudo_auth *auth);
|
int sia_cleanup(struct passwd *pw, sudo_auth *auth);
|
||||||
@@ -86,34 +90,34 @@ int securid_setup(struct passwd *pw, char **prompt, sudo_auth *auth);
|
|||||||
int securid_verify(struct passwd *pw, char *pass, sudo_auth *auth);
|
int securid_verify(struct passwd *pw, char *pass, sudo_auth *auth);
|
||||||
|
|
||||||
/* Fields: need_root, name, init, setup, verify, cleanup */
|
/* Fields: need_root, name, init, setup, verify, cleanup */
|
||||||
#define AUTH_ENTRY(r, n, i, s, v, c) \
|
#define AUTH_ENTRY(r, n, i, s, v, c, b, e) \
|
||||||
{ (r|FLAG_CONFIGURED), AUTH_FAILURE, n, NULL, i, s, v, c },
|
{ (r|FLAG_CONFIGURED), AUTH_FAILURE, n, NULL, i, s, v, c , b, e },
|
||||||
|
|
||||||
/* Some methods cannots (or should not) interoperate with any others */
|
/* Some methods cannot (or should not) interoperate with any others */
|
||||||
#if defined(HAVE_PAM)
|
#if defined(HAVE_PAM)
|
||||||
# define AUTH_STANDALONE \
|
# define AUTH_STANDALONE \
|
||||||
AUTH_ENTRY(0, "pam", \
|
AUTH_ENTRY(0, "pam", \
|
||||||
pam_init, NULL, pam_verify, pam_cleanup)
|
pam_init, NULL, pam_verify, pam_cleanup, pam_begin_session, pam_end_session)
|
||||||
#elif defined(HAVE_SECURID)
|
#elif defined(HAVE_SECURID)
|
||||||
# define AUTH_STANDALONE \
|
# define AUTH_STANDALONE \
|
||||||
AUTH_ENTRY(0, "SecurId", \
|
AUTH_ENTRY(0, "SecurId", \
|
||||||
securid_init, securid_setup, securid_verify, NULL)
|
securid_init, securid_setup, securid_verify, NULL, NULL, NULL)
|
||||||
#elif defined(HAVE_SIA_SES_INIT)
|
#elif defined(HAVE_SIA_SES_INIT)
|
||||||
# define AUTH_STANDALONE \
|
# define AUTH_STANDALONE \
|
||||||
AUTH_ENTRY(0, "sia", \
|
AUTH_ENTRY(0, "sia", \
|
||||||
NULL, sia_setup, sia_verify, sia_cleanup)
|
NULL, sia_setup, sia_verify, sia_cleanup, NULL, NULL)
|
||||||
#elif defined(HAVE_AIXAUTH)
|
#elif defined(HAVE_AIXAUTH)
|
||||||
# define AUTH_STANDALONE \
|
# define AUTH_STANDALONE \
|
||||||
AUTH_ENTRY(0, "aixauth", \
|
AUTH_ENTRY(0, "aixauth", \
|
||||||
NULL, NULL, aixauth_verify, aixauth_cleanup)
|
NULL, NULL, aixauth_verify, aixauth_cleanup, NULL, NULL)
|
||||||
#elif defined(HAVE_FWTK)
|
#elif defined(HAVE_FWTK)
|
||||||
# define AUTH_STANDALONE \
|
# define AUTH_STANDALONE \
|
||||||
AUTH_ENTRY(0, "fwtk", \
|
AUTH_ENTRY(0, "fwtk", \
|
||||||
fwtk_init, NULL, fwtk_verify, fwtk_cleanup)
|
fwtk_init, NULL, fwtk_verify, fwtk_cleanup, NULL, NULL)
|
||||||
#elif defined(HAVE_BSD_AUTH_H)
|
#elif defined(HAVE_BSD_AUTH_H)
|
||||||
# define AUTH_STANDALONE \
|
# define AUTH_STANDALONE \
|
||||||
AUTH_ENTRY(0, "bsdauth", \
|
AUTH_ENTRY(0, "bsdauth", \
|
||||||
bsdauth_init, NULL, bsdauth_verify, bsdauth_cleanup)
|
bsdauth_init, NULL, bsdauth_verify, bsdauth_cleanup, NULL, NULL)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* SUDO_AUTH_H */
|
#endif /* SUDO_AUTH_H */
|
||||||
|
@@ -60,9 +60,6 @@
|
|||||||
/*
|
/*
|
||||||
* Prototypes
|
* Prototypes
|
||||||
*/
|
*/
|
||||||
#if 0
|
|
||||||
static void runas_setup(void);
|
|
||||||
#endif
|
|
||||||
static void runas_setgroups(void);
|
static void runas_setgroups(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -969,51 +966,3 @@ runas_setgroups()
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif /* HAVE_INITGROUPS */
|
#endif /* HAVE_INITGROUPS */
|
||||||
|
|
||||||
#if 0
|
|
||||||
static void
|
|
||||||
runas_setup()
|
|
||||||
{
|
|
||||||
gid_t gid;
|
|
||||||
#ifdef HAVE_LOGIN_CAP_H
|
|
||||||
int flags;
|
|
||||||
extern login_cap_t *lc;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (runas_pw->pw_name != NULL) {
|
|
||||||
gid = runas_gr ? runas_gr->gr_gid : runas_pw->pw_gid;
|
|
||||||
#ifdef HAVE_GETUSERATTR
|
|
||||||
aix_setlimits(runas_pw->pw_name);
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_PAM
|
|
||||||
/* XXX - move this */
|
|
||||||
pam_prep_user(runas_pw);
|
|
||||||
#endif /* HAVE_PAM */
|
|
||||||
|
|
||||||
#ifdef HAVE_LOGIN_CAP_H
|
|
||||||
if (def_use_loginclass) {
|
|
||||||
/*
|
|
||||||
* We only use setusercontext() to set the nice value and rlimits.
|
|
||||||
*/
|
|
||||||
flags = LOGIN_SETRESOURCES|LOGIN_SETPRIORITY;
|
|
||||||
if (setusercontext(lc, runas_pw, runas_pw->pw_uid, flags)) {
|
|
||||||
if (runas_pw->pw_uid != ROOT_UID)
|
|
||||||
error(1, "unable to set user context");
|
|
||||||
else
|
|
||||||
warning("unable to set user context");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* HAVE_LOGIN_CAP_H */
|
|
||||||
/*
|
|
||||||
* Initialize group vector
|
|
||||||
*/
|
|
||||||
runas_setgroups();
|
|
||||||
#ifdef HAVE_SETEUID
|
|
||||||
if (setegid(gid))
|
|
||||||
warning("cannot set egid to runas gid");
|
|
||||||
#endif
|
|
||||||
if (setgid(gid))
|
|
||||||
warning("cannot set gid to runas gid");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
@@ -276,6 +276,7 @@ sudoers_policy_close(int exit_status, int error_code)
|
|||||||
/* We do not currently log the exit status. */
|
/* We do not currently log the exit status. */
|
||||||
if (error_code)
|
if (error_code)
|
||||||
warningx("unable to execute %s: %s", safe_cmnd, strerror(error_code));
|
warningx("unable to execute %s: %s", safe_cmnd, strerror(error_code));
|
||||||
|
end_session();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -627,6 +628,15 @@ sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[],
|
|||||||
|
|
||||||
restore_perms();
|
restore_perms();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ideally we would like to do session setup (currently only PAM)
|
||||||
|
* from inside sudo itself, but this should be close enough.
|
||||||
|
*/
|
||||||
|
if (ISSET(sudo_mode, MODE_RUN))
|
||||||
|
rval = begin_session(runas_pw);
|
||||||
|
if (ISSET(sudo_mode, MODE_EDIT))
|
||||||
|
rval = begin_session(sudo_user.pw);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
@@ -210,7 +210,8 @@ int user_is_exempt(void);
|
|||||||
|
|
||||||
/* sudo_auth.c */
|
/* sudo_auth.c */
|
||||||
int verify_user(struct passwd *, char *);
|
int verify_user(struct passwd *, char *);
|
||||||
void pass_warn(void);
|
int begin_session(struct passwd *);
|
||||||
|
int end_session();
|
||||||
|
|
||||||
#ifdef HAVE_LDAP
|
#ifdef HAVE_LDAP
|
||||||
/* ldap.c */
|
/* ldap.c */
|
||||||
|
Reference in New Issue
Block a user