char *name; /* name of the method in string form */
void *data; /* method-specific data pointer */
- int (*init)(struct passwd *pw, char **prompt, sudo_auth *auth);
+ int (*init)(struct passwd *pw, sudo_auth *auth);
int (*setup)(struct passwd *pw, char **prompt, sudo_auth *auth);
int (*verify)(struct passwd *pw, char *p, sudo_auth *auth);
int (*cleanup)(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(struct passwd *pw, char **promptp, sudo_auth *auth)
+bsdauth_init(struct passwd *pw, sudo_auth *auth)
{
static auth_session_t *as;
extern login_cap_t *lc; /* from sudo.c */
#include "sudo_auth.h"
int
-fwtk_init(struct passwd *pw, char **promptp, sudo_auth *auth)
+fwtk_init(struct passwd *pw, sudo_auth *auth)
{
static Cfg *confp; /* Configuration entry struct */
char resp[128]; /* Response from the server */
#include "sudo_auth.h"
int
-kerb4_init(struct passwd *pw, char **promptp, sudo_auth *auth)
+kerb4_init(struct passwd *pw, sudo_auth *auth)
{
static char realm[REALM_SZ];
#endif
int
-kerb5_init(struct passwd *pw, char **promptp, sudo_auth *auth)
+kerb5_setup(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(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,
static pam_handle_t *pamh;
int
-pam_init(struct passwd *pw, char **promptp, sudo_auth *auth)
+pam_init(struct passwd *pw, sudo_auth *auth)
{
static struct pam_conv pam_conv;
static int pam_status;
int *pam_status = (int *) auth->data;
/* If successful, we can't close the session until pam_end_session() */
- if (auth->status == AUTH_SUCCESS)
+ 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;
}
goto done;
}
- /* If the user did not have to authenticate there is no pam handle yet. */
- if (pamh == NULL)
- pam_init(pw, NULL, NULL);
-
/*
* Update PAM_USER to reference the user we are running the command
* as, as opposed to the user we authenticated as.
{
int status = PAM_SUCCESS;
+ if (pamh != NULL) {
#ifndef NO_PAM_SESSION
- /* If the user did not have to authenticate there is no pam handle yet. */
- if (pamh == NULL)
- pam_init(pw, NULL, NULL);
-
- /*
- * 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);
+ /*
+ * 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
-
- if (pamh != NULL)
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(struct passwd *pw, char **promptp, sudo_auth *auth)
+passwd_init(struct passwd *pw, sudo_auth *auth)
{
#ifdef HAVE_SKEYACCESS
if (skeyaccess(pw, user_tty, NULL, NULL) == 0)
#include "sudo_auth.h"
int
-secureware_init(struct passwd *pw, char **promptp, sudo_auth *auth)
+secureware_init(struct passwd *pw, sudo_auth *auth)
{
#ifdef __alpha
extern int crypt_type;
union config_record configure;
int
-securid_init(struct passwd *pw, char **promptp, sudo_auth *auth)
+securid_init(struct passwd *pw, 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(struct passwd *pw, char **promptp, sudo_auth *auth)
+securid_init(struct passwd *pw, sudo_auth *auth)
{
static SDI_HANDLE sd_dat; /* SecurID handle */
AUTH_ENTRY("kerb4", 0, kerb4_init, NULL, kerb4_verify, NULL, NULL, NULL)
#endif
#ifdef HAVE_KERB5
- AUTH_ENTRY("kerb5", 0, kerb5_init, NULL, kerb5_verify, kerb5_cleanup, NULL, NULL)
+ AUTH_ENTRY("kerb5", 0, kerb5_init, kerb5_setup, kerb5_verify, kerb5_cleanup, NULL, NULL)
#endif
#ifdef HAVE_SKEY
AUTH_ENTRY("S/Key", 0, NULL, rfc1938_setup, rfc1938_verify, NULL, NULL, NULL)
AUTH_ENTRY(NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL)
};
+static int standalone;
+
extern char **NewArgv; /* XXX - for auditing */
static void pass_warn(void);
int
-verify_user(struct passwd *pw, char *prompt)
+sudo_auth_init(struct passwd *pw)
{
- int counter = def_passwd_tries + 1;
- int success = AUTH_FAILURE;
- int flags, status, standalone, rval;
- char *p;
sudo_auth *auth;
- sigaction_t sa, osa;
-
- /* Enable suspend during password entry. */
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_RESTART;
- sa.sa_handler = SIG_DFL;
- (void) sigaction(SIGTSTP, &sa, &osa);
- /* Make sure we have at least one auth method. */
- if (auth_switch[0].name == NULL) {
- audit_failure(NewArgv, "no authentication methods");
- log_error(0,
- _("There are no authentication methods compiled into sudo! "
- "If you want to turn off authentication, use the "
- "--disable-authentication configure option."));
- return -1;
- }
+ if (auth_switch[0].name == NULL)
+ return AUTH_SUCCESS;
/* Make sure we haven't mixed standalone and shared auth methods. */
standalone = IS_STANDALONE(&auth_switch[0]);
if (NEEDS_USER(auth))
set_perms(PERM_USER);
- status = (auth->init)(pw, &prompt, auth);
- if (status == AUTH_FAILURE)
- SET(auth->flags, FLAG_DISABLED);
- else if (status == AUTH_FATAL) { /* XXX log */
+ switch ((auth->init)(pw, auth)) {
+ case AUTH_FAILURE:
+ SET(auth->flags, FLAG_DISABLED);
+ break;
+ case AUTH_FATAL:
+ /* XXX log */
+ audit_failure(NewArgv, "authentication failure");
+ return -1; /* assume error msg already printed */
+ }
+
+ if (NEEDS_USER(auth))
+ restore_perms();
+ }
+ }
+ return AUTH_SUCCESS;
+}
+
+int
+sudo_auth_cleanup(struct passwd *pw)
+{
+ sudo_auth *auth;
+
+ /* Call cleanup routines. */
+ for (auth = auth_switch; auth->name; auth++) {
+ if (auth->cleanup && !IS_DISABLED(auth)) {
+ if (NEEDS_USER(auth))
+ set_perms(PERM_USER);
+
+ if ((auth->cleanup)(pw, auth) == AUTH_FATAL) {
+ /* XXX log */
audit_failure(NewArgv, "authentication failure");
return -1; /* assume error msg already printed */
}
restore_perms();
}
}
+ return AUTH_SUCCESS;
+}
+
+int
+verify_user(struct passwd *pw, char *prompt)
+{
+ int counter = def_passwd_tries + 1;
+ int success = AUTH_FAILURE;
+ int flags, status, rval;
+ char *p;
+ sudo_auth *auth;
+ sigaction_t sa, osa;
+
+ /* Enable suspend during password entry. */
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_RESTART;
+ sa.sa_handler = SIG_DFL;
+ (void) sigaction(SIGTSTP, &sa, &osa);
+
+ /* Make sure we have at least one auth method. */
+ /* XXX - check FLAG_DISABLED too */
+ if (auth_switch[0].name == NULL) {
+ audit_failure(NewArgv, "no authentication methods");
+ log_error(0,
+ _("There are no authentication methods compiled into sudo! "
+ "If you want to turn off authentication, use the "
+ "--disable-authentication configure option."));
+ return -1;
+ }
while (--counter) {
/* Do any per-method setup and unconfigure the method if needed */
restore_perms();
if (auth->status != AUTH_FAILURE)
- goto cleanup;
+ goto done;
}
if (!standalone)
zero_bytes(p, strlen(p));
pass_warn();
}
-cleanup:
- /* Call cleanup routines. */
- for (auth = auth_switch; auth->name; auth++) {
- if (auth->cleanup && !IS_DISABLED(auth)) {
- if (NEEDS_USER(auth))
- set_perms(PERM_USER);
-
- status = (auth->cleanup)(pw, auth);
- if (status == AUTH_FATAL) { /* XXX log */
- audit_failure(NewArgv, "authentication failure");
- return -1; /* assume error msg already printed */
- }
-
- if (NEEDS_USER(auth))
- restore_perms();
- }
- }
-
+done:
switch (success) {
case AUTH_SUCCESS:
(void) sigaction(SIGTSTP, &osa, NULL);
return rval;
}
-int auth_begin_session(struct passwd *pw)
+int
+sudo_auth_begin_session(struct passwd *pw)
{
sudo_auth *auth;
int status;
return TRUE;
}
-int auth_end_session(struct passwd *pw)
+int
+sudo_auth_end_session(struct passwd *pw)
{
sudo_auth *auth;
int status;
int status; /* status from verify routine */
char *name; /* name of the method as a string */
void *data; /* method-specific data pointer */
- int (*init)(struct passwd *pw, char **prompt, struct sudo_auth *auth);
+ int (*init)(struct passwd *pw, 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 (*cleanup)(struct passwd *pw, struct sudo_auth *auth);
extern sudo_conv_t sudo_conv;
/* Prototypes for standalone methods */
-int fwtk_init(struct passwd *pw, char **prompt, sudo_auth *auth);
+int fwtk_init(struct passwd *pw, sudo_auth *auth);
int fwtk_verify(struct passwd *pw, char *prompt, sudo_auth *auth);
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, 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_begin_session(struct passwd *pw, sudo_auth *auth);
int sia_cleanup(struct passwd *pw, sudo_auth *auth);
int aixauth_verify(struct passwd *pw, char *pass, sudo_auth *auth);
int aixauth_cleanup(struct passwd *pw, sudo_auth *auth);
-int bsdauth_init(struct passwd *pw, char **prompt, sudo_auth *auth);
+int bsdauth_init(struct passwd *pw, sudo_auth *auth);
int bsdauth_verify(struct passwd *pw, char *prompt, sudo_auth *auth);
int bsdauth_cleanup(struct passwd *pw, sudo_auth *auth);
/* Prototypes for normal methods */
-int passwd_init(struct passwd *pw, char **prompt, sudo_auth *auth);
+int passwd_init(struct passwd *pw, sudo_auth *auth);
int passwd_verify(struct passwd *pw, char *pass, sudo_auth *auth);
int passwd_cleanup(struct passwd *pw, sudo_auth *auth);
-int secureware_init(struct passwd *pw, char **prompt, sudo_auth *auth);
+int secureware_init(struct passwd *pw, sudo_auth *auth);
int secureware_verify(struct passwd *pw, char *pass, sudo_auth *auth);
int secureware_cleanup(struct passwd *pw, sudo_auth *auth);
int rfc1938_setup(struct passwd *pw, char **prompt, sudo_auth *auth);
int rfc1938_verify(struct passwd *pw, char *pass, sudo_auth *auth);
int afs_verify(struct passwd *pw, char *pass, sudo_auth *auth);
int dce_verify(struct passwd *pw, char *pass, sudo_auth *auth);
-int kerb4_init(struct passwd *pw, char **prompt, sudo_auth *auth);
+int kerb4_init(struct passwd *pw, sudo_auth *auth);
int kerb4_verify(struct passwd *pw, char *pass, sudo_auth *auth);
-int kerb5_init(struct passwd *pw, char **prompt, sudo_auth *auth);
+int kerb5_init(struct passwd *pw, sudo_auth *auth);
+int kerb5_setup(struct passwd *pw, char **prompt, sudo_auth *auth);
int kerb5_verify(struct passwd *pw, char *pass, sudo_auth *auth);
int kerb5_cleanup(struct passwd *pw, sudo_auth *auth);
-int securid_init(struct passwd *pw, char **prompt, sudo_auth *auth);
+int securid_init(struct passwd *pw, sudo_auth *auth);
int securid_setup(struct passwd *pw, char **prompt, sudo_auth *auth);
int securid_verify(struct passwd *pw, char *pass, sudo_auth *auth);
int
check_user(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);
+ pw_delref(auth_pw);
+
/* Always prompt for a password when -k was specified with the command. */
if (ISSET(mode, MODE_IGNORE_TICKET)) {
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 TRUE;
+ goto done;
}
- if (build_timestamp(×tampdir, ×tampfile) == -1)
- return -1;
+ if (build_timestamp(×tampdir, ×tampfile) == -1) {
+ rval = -1;
+ goto done;
+ }
status = timestamp_status(timestampdir, timestampfile, user_name,
TS_MAKE_DIRS);
/* Bail out if we are non-interactive and a password is required */
if (ISSET(mode, MODE_NONINTERACTIVE)) {
warningx(_("sorry, a password is required to run %s"), getprogname());
- return -1;
+ rval = -1;
+ goto done;
}
/* XXX - should not lecture if askpass helper is being used. */
efree(timestampdir);
efree(timestampfile);
+done:
+ sudo_auth_cleanup(auth_pw);
+
return rval;
}
/* Close the session we opened in sudoers_policy_init_session(). */
if (ISSET(sudo_mode, MODE_RUN|MODE_EDIT))
- (void)auth_end_session(runas_pw);
+ (void)sudo_auth_end_session(runas_pw);
/* Free remaining references to password and group entries. */
pw_delref(sudo_user.pw);
return -1;
}
- return auth_begin_session(pwd);
+ return sudo_auth_begin_session(pwd);
}
static int
/* sudo_auth.c */
int verify_user(struct passwd *, char *);
-int auth_begin_session(struct passwd *);
-int auth_end_session();
+int sudo_auth_begin_session(struct passwd *);
+int sudo_auth_end_session(struct passwd *);
+int sudo_auth_init(struct passwd *pw);
+int sudo_auth_cleanup(struct passwd *pw);
/* parse.c */
int sudo_file_open(struct sudo_nss *);