char *name; /* name of the method in string form */
void *data; /* method-specific data pointer */
- int (*init) __P((struct passwd *pw, char **prompt, sudo_auth *auth));
+ int (*init) __P((struct passwd *pw, sudo_auth *auth));
int (*setup) __P((struct passwd *pw, char **prompt, sudo_auth *auth));
int (*verify) __P((struct passwd *pw, char *p, sudo_auth *auth));
int (*cleanup) __P((struct passwd *pw, sudo_auth *auth));
The functions in the struct are as follows:
- int init(struct passwd *pw, char **prompt, sudo_auth *auth)
+ int init(struct passwd *pw, sudo_auth *auth)
Function to do any one-time initialization for the auth
method. All of the "init" functions are run before anything
- else. A pointer to the prompt string may be used to add
- method-specific info to the prompt.
+ else.
int setup(struct passwd *pw, char **prompt, sudo_auth *auth)
Function to do method-specific setup. All the "setup"
extern char *login_style; /* from sudo.c */
int
-bsdauth_init(pw, promptp, auth)
+bsdauth_init(pw, auth)
struct passwd *pw;
- char **promptp;
sudo_auth *auth;
{
static auth_session_t *as;
#include "sudo_auth.h"
int
-fwtk_init(pw, promptp, auth)
+fwtk_init(pw, auth)
struct passwd *pw;
- char **promptp;
sudo_auth *auth;
{
static Cfg *confp; /* Configuration entry struct */
#include "sudo_auth.h"
int
-kerb4_init(pw, promptp, auth)
+kerb4_init(pw, auth)
struct passwd *pw;
- char **promptp;
sudo_auth *auth;
{
static char realm[REALM_SZ];
#endif
int
-kerb5_init(pw, promptp, auth)
+kerb5_setup(pw, promptp, auth)
struct passwd *pw;
char **promptp;
sudo_auth *auth;
+{
+ static char *krb5_prompt;
+
+ if (krb5_prompt == NULL) {
+ krb5_context sudo_context;
+ krb5_principal princ;
+ char *pname;
+ krb5_error_code error;
+
+ sudo_context = ((sudo_krb5_datap) auth->data)->sudo_context;
+ princ = ((sudo_krb5_datap) auth->data)->princ;
+
+ /*
+ * Really, we need to tell the caller not to prompt for password. The
+ * API does not currently provide this unless the auth is standalone.
+ */
+ if ((error = krb5_unparse_name(sudo_context, princ, &pname))) {
+ log_error(NO_EXIT|NO_MAIL,
+ "%s: unable to unparse princ ('%s'): %s", auth->name,
+ pw->pw_name, error_message(error));
+ return AUTH_FAILURE;
+ }
+
+ /* Only rewrite prompt if user didn't specify their own. */
+ /*if (!strcmp(prompt, PASSPROMPT)) { */
+ easprintf(&krb5_prompt, "Password for %s: ", pname);
+ /*}*/
+ free(pname);
+ }
+ *promptp = krb5_prompt;
+
+ return AUTH_SUCCESS;
+}
+
+int
+kerb5_init(pw, auth)
+ struct passwd *pw;
+ sudo_auth *auth;
{
krb5_context sudo_context;
krb5_ccache ccache;
krb5_principal princ;
krb5_error_code error;
char cache_name[64];
- char *pname;
auth->data = (void *) &sudo_krb5_data; /* Stash all our data here */
}
princ = sudo_krb5_data.princ;
- /*
- * Really, we need to tell the caller not to prompt for password.
- * The API does not currently provide this unless the auth is standalone.
- */
-#if 1
- if ((error = krb5_unparse_name(sudo_context, princ, &pname))) {
- log_error(NO_EXIT|NO_MAIL,
- "%s: unable to unparse princ ('%s'): %s", auth->name,
- pw->pw_name, error_message(error));
- return AUTH_FAILURE;
- }
-
- /* Only rewrite prompt if user didn't specify their own. */
- /*if (!strcmp(prompt, PASSPROMPT)) { */
- easprintf(promptp, "Password for %s: ", pname);
- /*}*/
- free(pname);
-#endif
-
(void) snprintf(cache_name, sizeof(cache_name), "MEMORY:sudocc_%ld",
(long) getpid());
if ((error = krb5_cc_resolve(sudo_context, cache_name,
/*
- * Copyright (c) 1999-2005, 2007-2010 Todd C. Miller <Todd.Miller@courtesan.com>
+ * Copyright (c) 1999-2005, 2007-2011 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
#define PAM_DATA_SILENT 0
#endif
-static pam_handle_t *pamh; /* global due to pam_prep_user() */
+static pam_handle_t *pamh;
int
-pam_init(pw, promptp, auth)
+pam_init(pw, auth)
struct passwd *pw;
- char **promptp;
sudo_auth *auth;
{
static struct pam_conv pam_conv;
{
int *pam_status = (int *) auth->data;
- /* If successful, we can't close the session until pam_prep_user() */
- if (auth->status == AUTH_SUCCESS)
+ /* If successful, we can't close the session until pam_end_session() */
+ if (*pam_status == AUTH_SUCCESS)
return AUTH_SUCCESS;
*pam_status = pam_end(pamh, *pam_status | PAM_DATA_SILENT);
+ pamh = NULL;
return *pam_status == PAM_SUCCESS ? AUTH_SUCCESS : AUTH_FAILURE;
}
pam_begin_session(pw)
struct passwd *pw;
{
- int status = PAM_SUCCESS;
+ int status = PAM_SUCCESS;
- /* If the user did not have to authenticate there is no pam handle yet. */
- if (pamh == NULL)
- pam_init(pw, NULL, NULL);
+ /*
+ * If there is no valid user we cannot open a PAM session.
+ * This is not an error as sudo can run commands with arbitrary
+ * uids, it just means we are done from a session management standpoint.
+ */
+ if (pw == NULL) {
+ if (pamh != NULL) {
+ (void) pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT);
+ pamh = NULL;
+ }
+ goto done;
+ }
/*
* Update PAM_USER to reference the user we are running the command
#ifndef NO_PAM_SESSION
status = pam_open_session(pamh, 0);
- if (status != PAM_SUCCESS) {
+ if (status != PAM_SUCCESS) {
(void) pam_end(pamh, status | PAM_DATA_SILENT);
pamh = NULL;
}
#endif
+
+done:
return status == PAM_SUCCESS ? AUTH_SUCCESS : AUTH_FAILURE;
}
int
-pam_end_session()
+pam_end_session(pw)
+ struct passwd *pw;
{
int status = PAM_SUCCESS;
if (pamh != NULL) {
#ifndef NO_PAM_SESSION
- (void) pam_close_session(pamh, 0);
+ /*
+ * Update PAM_USER to reference the user we are running the command
+ * as to match the call to pam_open_session().
+ */
+ (void) pam_set_item(pamh, PAM_USER, pw->pw_name);
+ (void) pam_close_session(pamh, PAM_SILENT);
#endif
status = pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT);
+ pamh = NULL;
}
+
return status == PAM_SUCCESS ? AUTH_SUCCESS : AUTH_FAILURE;
}
#define HAS_AGEINFO(p, l) (l == 18 && p[DESLEN] == ',')
int
-passwd_init(pw, promptp, auth)
+passwd_init(pw, auth)
struct passwd *pw;
- char **promptp;
sudo_auth *auth;
{
#ifdef HAVE_SKEYACCESS
#include "sudo_auth.h"
int
-secureware_init(pw, promptp, auth)
+secureware_init(pw, auth)
struct passwd *pw;
- char **promptp;
sudo_auth *auth;
{
#ifdef __alpha
union config_record configure;
int
-securid_init(pw, promptp, auth)
+securid_init(pw, auth)
struct passwd *pw;
- char **promptp;
sudo_auth *auth;
{
static struct SD_CLIENT sd_dat; /* SecurID data block */
* securid_init - Initialises communications with ACE server
* Arguments in:
* pw - UNUSED
- * promptp - UNUSED
* auth - sudo authentication structure
*
* Results out:
* success.
*/
int
-securid_init(pw, promptp, auth)
+securid_init(pw, auth)
struct passwd *pw;
- char **promptp;
sudo_auth *auth;
{
static SDI_HANDLE sd_dat; /* SecurID handle */
AUTH_ENTRY(0, "kerb4", kerb4_init, NULL, kerb4_verify, NULL)
# endif
# ifdef HAVE_KERB5
- AUTH_ENTRY(0, "kerb5", kerb5_init, NULL, kerb5_verify, kerb5_cleanup)
+ AUTH_ENTRY(0, "kerb5", kerb5_init, kerb5_setup, kerb5_verify, kerb5_cleanup)
# endif
# ifdef HAVE_SKEY
AUTH_ENTRY(0, "S/Key", NULL, rfc1938_setup, rfc1938_verify, NULL)
AUTH_ENTRY(0, NULL, NULL, NULL, NULL, NULL)
};
+void
+sudo_auth_init(pw)
+ struct passwd *pw;
+{
+ sudo_auth *auth;
+ int status;
+
+ if (auth_switch[0].name == NULL)
+ return;
+
+ /* Set FLAG_ONEANDONLY if there is only one auth method. */
+ if (auth_switch[1].name == NULL)
+ SET(auth_switch[0].flags, FLAG_ONEANDONLY);
+
+ /* Initialize auth methods and unconfigure the method if necessary. */
+ for (auth = auth_switch; auth->name; auth++) {
+ if (auth->init && IS_CONFIGURED(auth)) {
+ if (NEEDS_USER(auth))
+ set_perms(PERM_USER);
+
+ status = (auth->init)(pw, auth);
+
+ if (NEEDS_USER(auth))
+ set_perms(PERM_ROOT);
+
+ if (status == AUTH_FAILURE)
+ CLR(auth->flags, FLAG_CONFIGURED);
+ else if (status == AUTH_FATAL) { /* XXX log */
+#ifdef HAVE_BSM_AUDIT
+ audit_failure(NewArgv, "authentication failure");
+#endif
+ exit(1); /* assume error msg already printed */
+ }
+ }
+ }
+}
+
+void
+sudo_auth_cleanup(pw)
+ struct passwd *pw;
+{
+ sudo_auth *auth;
+ int status;
+
+ /* Call cleanup routines. */
+ for (auth = auth_switch; auth->name; auth++) {
+ if (auth->cleanup && IS_CONFIGURED(auth)) {
+ if (NEEDS_USER(auth))
+ set_perms(PERM_USER);
+
+ status = (auth->cleanup)(pw, auth);
+
+ if (NEEDS_USER(auth))
+ set_perms(PERM_ROOT);
+
+ if (status == AUTH_FATAL) { /* XXX log */
+#ifdef HAVE_BSM_AUDIT
+ audit_failure(NewArgv, "authentication failure");
+#endif
+ exit(1); /* assume error msg already printed */
+ }
+ }
+ }
+}
+
void
verify_user(pw, prompt)
struct passwd *pw;
"--disable-authentication configure option.");
}
- /* Set FLAG_ONEANDONLY if there is only one auth method. */
- if (auth_switch[1].name == NULL)
- SET(auth_switch[0].flags, FLAG_ONEANDONLY);
-
- /* Initialize auth methods and unconfigure the method if necessary. */
- for (auth = auth_switch; auth->name; auth++) {
- if (auth->init && IS_CONFIGURED(auth)) {
- if (NEEDS_USER(auth))
- set_perms(PERM_USER);
-
- status = (auth->init)(pw, &prompt, auth);
- if (status == AUTH_FAILURE)
- CLR(auth->flags, FLAG_CONFIGURED);
- else if (status == AUTH_FATAL) { /* XXX log */
-#ifdef HAVE_BSM_AUDIT
- audit_failure(NewArgv, "authentication failure");
-#endif
- exit(1); /* assume error msg already printed */
- }
-
- if (NEEDS_USER(auth))
- set_perms(PERM_ROOT);
- }
- }
-
while (--counter) {
/* Do any per-method setup and unconfigure the method if needed */
for (auth = auth_switch; auth->name; auth++) {
set_perms(PERM_USER);
status = (auth->setup)(pw, &prompt, auth);
+
+ if (NEEDS_USER(auth))
+ set_perms(PERM_ROOT);
+
if (status == AUTH_FAILURE)
CLR(auth->flags, FLAG_CONFIGURED);
else if (status == AUTH_FATAL) {/* XXX log */
#endif
exit(1); /* assume error msg already printed */
}
-
- if (NEEDS_USER(auth))
- set_perms(PERM_ROOT);
}
}
set_perms(PERM_ROOT);
if (auth->status != AUTH_FAILURE)
- goto cleanup;
+ goto done;
}
#ifndef AUTH_STANDALONE
if (p == NULL)
pass_warn(stderr);
}
-cleanup:
- /* Call cleanup routines. */
- for (auth = auth_switch; auth->name; auth++) {
- if (auth->cleanup && IS_CONFIGURED(auth)) {
- if (NEEDS_USER(auth))
- set_perms(PERM_USER);
-
- status = (auth->cleanup)(pw, auth);
- if (status == AUTH_FATAL) { /* XXX log */
-#ifdef HAVE_BSM_AUDIT
- audit_failure(NewArgv, "authentication failure");
-#endif
- exit(1); /* assume error msg already printed */
- }
-
- if (NEEDS_USER(auth))
- set_perms(PERM_ROOT);
- }
- }
-
+done:
switch (success) {
case AUTH_SUCCESS:
(void) sigaction(SIGTSTP, &osa, NULL);
short status; /* status from verify routine */
char *name; /* name of the method as a string */
void *data; /* method-specific data pointer */
- int (*init) __P((struct passwd *pw, char **prompt, struct sudo_auth *auth));
+ int (*init) __P((struct passwd *pw, struct sudo_auth *auth));
int (*setup) __P((struct passwd *pw, char **prompt, struct sudo_auth *auth));
int (*verify) __P((struct passwd *pw, char *p, struct sudo_auth *auth));
int (*cleanup) __P((struct passwd *pw, struct sudo_auth *auth));
#define IS_ONEANDONLY(x) ((x)->flags & FLAG_ONEANDONLY)
/* Prototypes for standalone methods */
-int fwtk_init __P((struct passwd *pw, char **prompt, sudo_auth *auth));
+int fwtk_init __P((struct passwd *pw, sudo_auth *auth));
int fwtk_verify __P((struct passwd *pw, char *prompt, sudo_auth *auth));
int fwtk_cleanup __P((struct passwd *pw, sudo_auth *auth));
-int pam_init __P((struct passwd *pw, char **prompt, sudo_auth *auth));
+int pam_init __P((struct passwd *pw, sudo_auth *auth));
int pam_verify __P((struct passwd *pw, char *prompt, sudo_auth *auth));
int pam_cleanup __P((struct passwd *pw, sudo_auth *auth));
int sia_setup __P((struct passwd *pw, char **prompt, sudo_auth *auth));
int sia_cleanup __P((struct passwd *pw, sudo_auth *auth));
int aixauth_verify __P((struct passwd *pw, char *pass, sudo_auth *auth));
int aixauth_cleanup __P((struct passwd *pw, sudo_auth *auth));
-int bsdauth_init __P((struct passwd *pw, char **prompt, sudo_auth *auth));
+int bsdauth_init __P((struct passwd *pw, sudo_auth *auth));
int bsdauth_verify __P((struct passwd *pw, char *prompt, sudo_auth *auth));
int bsdauth_cleanup __P((struct passwd *pw, sudo_auth *auth));
/* Prototypes for normal methods */
-int passwd_init __P((struct passwd *pw, char **prompt, sudo_auth *auth));
+int passwd_init __P((struct passwd *pw, sudo_auth *auth));
int passwd_verify __P((struct passwd *pw, char *pass, sudo_auth *auth));
int passwd_cleanup __P((struct passwd *pw, sudo_auth *auth));
-int secureware_init __P((struct passwd *pw, char **prompt, sudo_auth *auth));
+int secureware_init __P((struct passwd *pw, sudo_auth *auth));
int secureware_verify __P((struct passwd *pw, char *pass, sudo_auth *auth));
int secureware_cleanup __P((struct passwd *pw, sudo_auth *auth));
int rfc1938_setup __P((struct passwd *pw, char **prompt, sudo_auth *auth));
int rfc1938_verify __P((struct passwd *pw, char *pass, sudo_auth *auth));
int afs_verify __P((struct passwd *pw, char *pass, sudo_auth *auth));
int dce_verify __P((struct passwd *pw, char *pass, sudo_auth *auth));
-int kerb4_init __P((struct passwd *pw, char **prompt, sudo_auth *auth));
+int kerb4_init __P((struct passwd *pw, sudo_auth *auth));
int kerb4_verify __P((struct passwd *pw, char *pass, sudo_auth *auth));
-int kerb5_init __P((struct passwd *pw, char **prompt, sudo_auth *auth));
+int kerb5_init __P((struct passwd *pw, sudo_auth *auth));
+int kerb5_setup __P((struct passwd *pw, char **prompt, sudo_auth *auth));
int kerb5_verify __P((struct passwd *pw, char *pass, sudo_auth *auth));
int kerb5_cleanup __P((struct passwd *pw, sudo_auth *auth));
-int securid_init __P((struct passwd *pw, char **prompt, sudo_auth *auth));
+int securid_init __P((struct passwd *pw, sudo_auth *auth));
int securid_setup __P((struct passwd *pw, char **prompt, sudo_auth *auth));
int securid_verify __P((struct passwd *pw, char *pass, sudo_auth *auth));
int validated;
int mode;
{
+ struct passwd *auth_pw;
char *timestampdir = NULL;
char *timestampfile = NULL;
char *prompt;
ctim_get(&sb, &tty_info.ctime);
}
+ /* Init authentication system regardless of whether we need a password. */
+ auth_pw = get_authpw();
+ sudo_auth_init(auth_pw);
+
/* Always prompt for a password when -k was specified with the command. */
if (ISSET(mode, MODE_INVALIDATE)) {
SET(validated, FLAG_CHECK_USER);
if (user_uid == 0 || (user_uid == runas_pw->pw_uid &&
(!runas_gr || user_in_group(sudo_user.pw, runas_gr->gr_name))) ||
user_is_exempt())
- return;
+ goto done;
}
build_timestamp(×tampdir, ×tampfile);
TS_MAKE_DIRS);
if (status != TS_CURRENT || ISSET(validated, FLAG_CHECK_USER)) {
- struct passwd *auth_pw;
-
/* Bail out if we are non-interactive and a password is required */
if (ISSET(mode, MODE_NONINTERACTIVE))
errorx(1, "sorry, a password is required to run %s", getprogname());
prompt = expand_prompt(user_prompt ? user_prompt : def_passprompt,
user_name, user_shost);
- auth_pw = get_authpw();
verify_user(auth_pw, prompt);
- pw_delref(auth_pw);
}
/* Only update timestamp if user was validated. */
if (ISSET(validated, VALIDATE_OK) && !ISSET(mode, MODE_INVALIDATE) && status != TS_ERROR)
update_timestamp(timestampdir, timestampfile);
efree(timestampdir);
efree(timestampfile);
+
+done:
+ sudo_auth_cleanup(auth_pw);
+ pw_delref(auth_pw);
}
/*
break;
}
#ifdef HAVE_PAM
- pam_end_session();
+ pam_end_session(runas_pw);
#endif /* HAVE_PAM */
#ifdef _PATH_SUDO_IO_LOGDIR
io_log_close();
/* pam.c */
int pam_begin_session __P((struct passwd *));
-int pam_end_session __P((void));
+int pam_end_session __P((struct passwd *));
/* parse.c */
int sudo_file_open __P((struct sudo_nss *));
void verify_user __P((struct passwd *, char *));
void pass_warn __P((FILE *));
void dump_auth_methods __P((void));
+void sudo_auth_init __P((struct passwd *));
+void sudo_auth_cleanup __P((struct passwd *));
/* sudo_nss.c */
void display_privs __P((struct sudo_nss_list *, struct passwd *));