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 (*verify)(struct passwd *pw, char *p, sudo_auth *auth, struct sudo_conv_callback *callback);
+ int (*approval)(struct passwd *pw, sudo_auth *auth);
int (*cleanup)(struct passwd *pw, sudo_auth *auth);
- int (*begin_session)(struct passwd *pw, sudo_auth *auth);
- int (*end_session)(sudo_auth *auth);
+ int (*begin_session)(struct passwd *pw, char **user_env[], struct sudo_auth *auth);
+ int (*end_session)(struct passwd *pw, struct sudo_auth *auth);
} sudo_auth;
The variables in the struct are as follows:
pointer to the prompt string may be used to add method-specific
info to the prompt.
- int verify(struct passwd *pw, char *p, sudo_auth *auth)
+ int verify(struct passwd *pw, char *p, sudo_auth *auth, struct sudo_conv_callback *callback)
Function to do user verification for this auth method. For
standalone auth methods ``p'' is the prompt string. For
normal auth methods, ``p'' is the password the user entered.
+ The callback should be passed to auth_getpass() to allow sudoers
+ to unlock the ticket file when sudo is suspended.
Note that standalone auth methods are responsible for
rerading the password themselves.
+ int approval(struct passwd *pw, struct sudo_auth *auth)
+ Function to perform account management and approval *after*
+ the user has authenticated successfully. This function may
+ check for expired accounts, perform time of day restrictions, etc.
+ For PAM, this calls pam_acct_mgmt(). For BSD auth, it calls
+ auth_approval().
+
int cleanup(struct passwd *pw, sudo_auth *auth)
Function to do per-auth method cleanup. This is only run
at the end of the authentication process, after the user
The ``auth->status'' variable contains the result of the
last authentication attempt which may be interesting.
+ int begin_session(struct passwd *pw, char **user_env[], struct sudo_auth *auth)
+ Function to begin a user session. This is used for session handling
+ in PAM and SIA.
+
+ int end_session(struct passwd *pw, struct sudo_auth *auth)
+ Function to end a user session. This is used for session handling
+ in PAM and SIA.
+
A note about standalone methods. Some authentication methods can't
coexist with any others. This may be because they encapsulate other
methods (pam, sia) or because they have a special way of interacting
debug_return_int(AUTH_FAILURE);
}
+int
+bsdauth_approval(struct passwd *pw, sudo_auth *auth)
+{
+ struct bsdauth_state *state = auth->data;
+ debug_decl(bsdauth_approval, SUDOERS_DEBUG_AUTH)
+
+ if (auth_approval(state->as, state->lc, pw->pw_name, "auth-sudo") == 0) {
+ if (auth_getstate(state->as) & AUTH_EXPIRED)
+ log_warningx(0, "%s", N_("your account has expired"));
+ else
+ log_warningx(0, "%s", N_("approval failed"));
+ debug_return_int(AUTH_FAILURE);
+ }
+ debug_return_int(AUTH_SUCCESS);
+}
+
int
bsdauth_cleanup(struct passwd *pw, sudo_auth *auth)
{
/*
- * Copyright (c) 1999-2005, 2007-2015 Todd C. Miller <Todd.Miller@sudo.ws>
+ * Copyright (c) 1999-2005, 2007-2018 Todd C. Miller <Todd.Miller@sudo.ws>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
}
switch (*pam_status) {
case PAM_SUCCESS:
- *pam_status = pam_acct_mgmt(pamh, PAM_SILENT);
- switch (*pam_status) {
- case PAM_SUCCESS:
- debug_return_int(AUTH_SUCCESS);
- case PAM_AUTH_ERR:
- log_warningx(0, N_("account validation failure, "
- "is your account locked?"));
- debug_return_int(AUTH_FATAL);
- case PAM_NEW_AUTHTOK_REQD:
- log_warningx(0, N_("Account or password is "
- "expired, reset your password and try again"));
- *pam_status = pam_chauthtok(pamh,
- PAM_CHANGE_EXPIRED_AUTHTOK);
- if (*pam_status == PAM_SUCCESS)
- debug_return_int(AUTH_SUCCESS);
- if ((s = pam_strerror(pamh, *pam_status)) != NULL) {
- log_warningx(0,
- N_("unable to change expired password: %s"), s);
- }
- debug_return_int(AUTH_FAILURE);
- case PAM_AUTHTOK_EXPIRED:
- log_warningx(0,
- N_("Password expired, contact your system administrator"));
- debug_return_int(AUTH_FATAL);
- case PAM_ACCT_EXPIRED:
- log_warningx(0,
- N_("Account expired or PAM config lacks an \"account\" "
- "section for sudo, contact your system administrator"));
- debug_return_int(AUTH_FATAL);
- }
- /* FALLTHROUGH */
+ debug_return_int(AUTH_SUCCESS);
case PAM_AUTH_ERR:
case PAM_AUTHINFO_UNAVAIL:
case PAM_MAXTRIES:
case PAM_PERM_DENIED:
sudo_debug_printf(SUDO_DEBUG_WARN|SUDO_DEBUG_LINENO,
- "pam_acct_mgmt: %d", *pam_status);
+ "pam_authenticate: %d", *pam_status);
debug_return_int(AUTH_FAILURE);
default:
if ((s = pam_strerror(pamh, *pam_status)) != NULL)
}
}
+int
+sudo_pam_approval(struct passwd *pw, sudo_auth *auth)
+{
+ const char *s;
+ int *pam_status = (int *) auth->data;
+ debug_decl(sudo_pam_approval, SUDOERS_DEBUG_AUTH)
+
+ *pam_status = pam_acct_mgmt(pamh, PAM_SILENT);
+ switch (*pam_status) {
+ case PAM_SUCCESS:
+ debug_return_int(AUTH_SUCCESS);
+ case PAM_AUTH_ERR:
+ log_warningx(0, N_("account validation failure, "
+ "is your account locked?"));
+ debug_return_int(AUTH_FATAL);
+ case PAM_NEW_AUTHTOK_REQD:
+ log_warningx(0, N_("Account or password is "
+ "expired, reset your password and try again"));
+ *pam_status = pam_chauthtok(pamh,
+ PAM_CHANGE_EXPIRED_AUTHTOK);
+ if (*pam_status == PAM_SUCCESS)
+ debug_return_int(AUTH_SUCCESS);
+ if ((s = pam_strerror(pamh, *pam_status)) == NULL)
+ s = "unknown error";
+ log_warningx(0,
+ N_("unable to change expired password: %s"), s);
+ debug_return_int(AUTH_FAILURE);
+ case PAM_AUTHTOK_EXPIRED:
+ log_warningx(0,
+ N_("Password expired, contact your system administrator"));
+ debug_return_int(AUTH_FATAL);
+ case PAM_ACCT_EXPIRED:
+ log_warningx(0,
+ N_("Account expired or PAM config lacks an \"account\" "
+ "section for sudo, contact your system administrator"));
+ debug_return_int(AUTH_FATAL);
+ case PAM_AUTHINFO_UNAVAIL:
+ case PAM_MAXTRIES:
+ case PAM_PERM_DENIED:
+ s = pam_strerror(pamh, *pam_status);
+ log_warningx(0, N_("PAM account management error: %s"),
+ s ? s : "unknown error");
+ debug_return_int(AUTH_FAILURE);
+ default:
+ s = pam_strerror(pamh, *pam_status);
+ log_warningx(0, N_("PAM account management error: %s"),
+ s ? s : "unknown error");
+ debug_return_int(AUTH_FATAL);
+ }
+}
+
int
sudo_pam_cleanup(struct passwd *pw, sudo_auth *auth)
{
/*
- * Copyright (c) 1999-2005, 2008-2016 Todd C. Miller <Todd.Miller@sudo.ws>
+ * Copyright (c) 1999-2005, 2008-2018 Todd C. Miller <Todd.Miller@sudo.ws>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
static sudo_auth auth_switch[] = {
/* Standalone entries first */
#ifdef HAVE_AIXAUTH
- AUTH_ENTRY("aixauth", FLAG_STANDALONE, sudo_aix_init, NULL, sudo_aix_verify, sudo_aix_cleanup, NULL, NULL)
+ AUTH_ENTRY("aixauth", FLAG_STANDALONE, sudo_aix_init, NULL, sudo_aix_verify, NULL, sudo_aix_cleanup, NULL, NULL)
#endif
#ifdef HAVE_PAM
- AUTH_ENTRY("pam", FLAG_STANDALONE, sudo_pam_init, NULL, sudo_pam_verify, sudo_pam_cleanup, sudo_pam_begin_session, sudo_pam_end_session)
+ AUTH_ENTRY("pam", FLAG_STANDALONE, sudo_pam_init, NULL, sudo_pam_verify, sudo_pam_approval, sudo_pam_cleanup, sudo_pam_begin_session, sudo_pam_end_session)
#endif
#ifdef HAVE_SECURID
- AUTH_ENTRY("SecurId", FLAG_STANDALONE, sudo_securid_init, sudo_securid_setup, sudo_securid_verify, NULL, NULL, NULL)
+ AUTH_ENTRY("SecurId", FLAG_STANDALONE, sudo_securid_init, sudo_securid_setup, sudo_securid_verify, NULL, NULL, NULL, NULL)
#endif
#ifdef HAVE_SIA_SES_INIT
- AUTH_ENTRY("sia", FLAG_STANDALONE, NULL, sudo_sia_setup, sudo_sia_verify, sudo_sia_cleanup, sudo_sia_begin_session, NULL)
+ AUTH_ENTRY("sia", FLAG_STANDALONE, NULL, sudo_sia_setup, sudo_sia_verify, NULL, sudo_sia_cleanup, sudo_sia_begin_session, NULL)
#endif
#ifdef HAVE_FWTK
- AUTH_ENTRY("fwtk", FLAG_STANDALONE, sudo_fwtk_init, NULL, sudo_fwtk_verify, sudo_fwtk_cleanup, NULL, NULL)
+ AUTH_ENTRY("fwtk", FLAG_STANDALONE, sudo_fwtk_init, NULL, sudo_fwtk_verify, NULL, sudo_fwtk_cleanup, NULL, NULL)
#endif
#ifdef HAVE_BSD_AUTH_H
- AUTH_ENTRY("bsdauth", FLAG_STANDALONE, bsdauth_init, NULL, bsdauth_verify, bsdauth_cleanup, NULL, NULL)
+ AUTH_ENTRY("bsdauth", FLAG_STANDALONE, bsdauth_init, NULL, bsdauth_verify, bsdauth_approval, bsdauth_cleanup, NULL, NULL)
#endif
/* Non-standalone entries */
#ifndef WITHOUT_PASSWD
- AUTH_ENTRY("passwd", 0, sudo_passwd_init, NULL, sudo_passwd_verify, sudo_passwd_cleanup, NULL, NULL)
+ AUTH_ENTRY("passwd", 0, sudo_passwd_init, NULL, sudo_passwd_verify, NULL, sudo_passwd_cleanup, NULL, NULL)
#endif
#if defined(HAVE_GETPRPWNAM) && !defined(WITHOUT_PASSWD)
- AUTH_ENTRY("secureware", 0, sudo_secureware_init, NULL, sudo_secureware_verify, sudo_secureware_cleanup, NULL, NULL)
+ AUTH_ENTRY("secureware", 0, sudo_secureware_init, NULL, sudo_secureware_verify, NULL, sudo_secureware_cleanup, NULL, NULL)
#endif
#ifdef HAVE_AFS
- AUTH_ENTRY("afs", 0, NULL, NULL, sudo_afs_verify, NULL, NULL, NULL)
+ AUTH_ENTRY("afs", 0, NULL, NULL, sudo_afs_verify, NULL, NULL, NULL, NULL)
#endif
#ifdef HAVE_DCE
- AUTH_ENTRY("dce", 0, NULL, NULL, sudo_dce_verify, NULL, NULL, NULL)
+ AUTH_ENTRY("dce", 0, NULL, NULL, sudo_dce_verify, NULL, NULL, NULL, NULL)
#endif
#ifdef HAVE_KERB5
- AUTH_ENTRY("kerb5", 0, sudo_krb5_init, sudo_krb5_setup, sudo_krb5_verify, sudo_krb5_cleanup, NULL, NULL)
+ AUTH_ENTRY("kerb5", 0, sudo_krb5_init, sudo_krb5_setup, sudo_krb5_verify, NULL, sudo_krb5_cleanup, NULL, NULL)
#endif
#ifdef HAVE_SKEY
- AUTH_ENTRY("S/Key", 0, NULL, sudo_rfc1938_setup, sudo_rfc1938_verify, NULL, NULL, NULL)
+ AUTH_ENTRY("S/Key", 0, NULL, sudo_rfc1938_setup, sudo_rfc1938_verify, NULL, NULL, NULL, NULL)
#endif
#ifdef HAVE_OPIE
- AUTH_ENTRY("OPIE", 0, NULL, sudo_rfc1938_setup, sudo_rfc1938_verify, NULL, NULL, NULL)
+ AUTH_ENTRY("OPIE", 0, NULL, sudo_rfc1938_setup, sudo_rfc1938_verify, NULL, NULL, NULL, NULL)
#endif
- AUTH_ENTRY(NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL)
+ AUTH_ENTRY(NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL)
};
static bool standalone;
debug_return_int(status == AUTH_FATAL ? -1 : 0);
}
+/*
+ * Cleanup all authentication approval methods.
+ * Returns true on success, false on failure and -1 on error.
+ */
+int
+sudo_auth_approval(struct passwd *pw, int validated)
+{
+ sudo_auth *auth;
+ debug_decl(sudo_auth_approval, SUDOERS_DEBUG_AUTH)
+
+ /* Call approval routines. */
+ for (auth = auth_switch; auth->name; auth++) {
+ if (auth->approval && !IS_DISABLED(auth)) {
+ int status = (auth->approval)(pw, auth);
+ if (status != AUTH_SUCCESS) {
+ /* Assume error msg already printed. */
+ log_auth_failure(validated, 0);
+ debug_return_int(status == AUTH_FAILURE ? false : -1);
+ }
+ }
+ }
+ debug_return_int(true);
+}
+
/*
* Cleanup all authentication methods.
* Returns 0 on success and -1 on error.
sudo_auth_cleanup(struct passwd *pw)
{
sudo_auth *auth;
- int status = AUTH_SUCCESS;
debug_decl(sudo_auth_cleanup, SUDOERS_DEBUG_AUTH)
/* Call cleanup routines. */
for (auth = auth_switch; auth->name; auth++) {
if (auth->cleanup && !IS_DISABLED(auth)) {
- status = (auth->cleanup)(pw, auth);
- if (status == AUTH_FATAL)
- break; /* assume error msg already printed */
+ int status = (auth->cleanup)(pw, auth);
+ if (status == AUTH_FATAL) {
+ /* Assume error msg already printed. */
+ debug_return_int(-1);
+ }
}
}
- debug_return_int(status == AUTH_FATAL ? -1 : 0);
+ debug_return_int(0);
}
static void
break;
case AUTH_FATAL:
default:
- log_auth_failure(validated | FLAG_AUTH_ERROR, 0);
+ log_auth_failure(validated, 0);
ret = -1;
break;
}
sudo_auth_begin_session(struct passwd *pw, char **user_env[])
{
sudo_auth *auth;
- int status = AUTH_SUCCESS;
debug_decl(sudo_auth_begin_session, SUDOERS_DEBUG_AUTH)
for (auth = auth_switch; auth->name; auth++) {
if (auth->begin_session && !IS_DISABLED(auth)) {
- status = (auth->begin_session)(pw, user_env, auth);
- if (status != AUTH_SUCCESS)
- break; /* assume error msg already printed */
+ int status = (auth->begin_session)(pw, user_env, auth);
+ if (status != AUTH_SUCCESS) {
+ /* Assume error msg already printed. */
+ debug_return_int(-1);
+ }
}
}
- debug_return_int(status == AUTH_SUCCESS ? 1 : -1);
+ debug_return_int(1);
}
bool
sudo_auth_end_session(struct passwd *pw)
{
sudo_auth *auth;
- int status = AUTH_SUCCESS;
+ int status;
debug_decl(sudo_auth_end_session, SUDOERS_DEBUG_AUTH)
for (auth = auth_switch; auth->name; auth++) {
if (auth->end_session && !IS_DISABLED(auth)) {
status = (auth->end_session)(pw, auth);
- if (status == AUTH_FATAL)
- break; /* assume error msg already printed */
+ if (status == AUTH_FATAL) {
+ /* Assume error msg already printed. */
+ debug_return_int(-1);
+ }
}
}
- debug_return_int(status == AUTH_FATAL ? -1 : 1);
+ debug_return_int(1);
}
/*
/*
- * Copyright (c) 1999-2005, 2007-2015 Todd C. Miller <Todd.Miller@sudo.ws>
+ * Copyright (c) 1999-2005, 2007-2016, 2018 Todd C. Miller <Todd.Miller@sudo.ws>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
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, struct sudo_conv_callback *callback);
+ int (*approval)(struct passwd *pw, struct sudo_auth *auth);
int (*cleanup)(struct passwd *pw, struct sudo_auth *auth);
int (*begin_session)(struct passwd *pw, char **user_env[], struct sudo_auth *auth);
int (*end_session)(struct passwd *pw, struct sudo_auth *auth);
/* Prototypes for standalone methods */
int bsdauth_init(struct passwd *pw, sudo_auth *auth);
int bsdauth_verify(struct passwd *pw, char *prompt, sudo_auth *auth, struct sudo_conv_callback *callback);
+int bsdauth_approval(struct passwd *pw, sudo_auth *auth);
int bsdauth_cleanup(struct passwd *pw, sudo_auth *auth);
int sudo_aix_init(struct passwd *pw, sudo_auth *auth);
int sudo_aix_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback);
int sudo_pam_init(struct passwd *pw, sudo_auth *auth);
int sudo_pam_init_quiet(struct passwd *pw, sudo_auth *auth);
int sudo_pam_verify(struct passwd *pw, char *prompt, sudo_auth *auth, struct sudo_conv_callback *callback);
+int sudo_pam_approval(struct passwd *pw, sudo_auth *auth);
int sudo_pam_cleanup(struct passwd *pw, sudo_auth *auth);
int sudo_pam_begin_session(struct passwd *pw, char **user_env[], sudo_auth *auth);
int sudo_pam_end_session(struct passwd *pw, sudo_auth *auth);
int sudo_secureware_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback);
int sudo_secureware_cleanup(struct passwd *pw, sudo_auth *auth);
-/* Fields: name, flags, init, setup, verify, cleanup, begin_sess, end_sess */
-#define AUTH_ENTRY(n, f, i, s, v, c, b, e) \
- { (f), AUTH_FAILURE, (n), NULL, (i), (s), (v), (c) , (b), (e) },
+/* Fields: name, flags, init, setup, verify, approval, cleanup, begin_sess, end_sess */
+#define AUTH_ENTRY(n, f, i, s, v, a, c, b, e) \
+ { (f), AUTH_FAILURE, (n), NULL, (i), (s), (v), (a), (c) , (b), (e) },
#endif /* SUDO_AUTH_H */
ret = check_user_interactive(validated, mode, auth_pw);
done:
+ if (ret == true) {
+ /* The approval function may disallow a user post-authentication. */
+ ret = sudo_auth_approval(auth_pw, validated);
+ }
sudo_auth_cleanup(auth_pw);
sudo_pw_delref(auth_pw);
#define FLAG_NO_CHECK 0x080
#define FLAG_NON_INTERACTIVE 0x100
#define FLAG_BAD_PASSWORD 0x200
-#define FLAG_AUTH_ERROR 0x400
-#define FLAG_NOPASSWD 0x800
+#define FLAG_NOPASSWD 0x400
/*
* find_path()/set_cmnd() return values
int sudo_auth_begin_session(struct passwd *pw, char **user_env[]);
int sudo_auth_end_session(struct passwd *pw);
int sudo_auth_init(struct passwd *pw);
+int sudo_auth_approval(struct passwd *pw, int validated);
int sudo_auth_cleanup(struct passwd *pw);
/* set_perms.c */