]> granicus.if.org Git - sudo/commitdiff
Add an approval function to the sudo auth API which is run after
authorTodd C. Miller <Todd.Miller@sudo.ws>
Tue, 16 Jan 2018 17:27:58 +0000 (10:27 -0700)
committerTodd C. Miller <Todd.Miller@sudo.ws>
Tue, 16 Jan 2018 17:27:58 +0000 (10:27 -0700)
the user's password has been verified.  The approval function is
run even if no password is required.  This is currently only used
for PAM (use pam_acct_mgmt) and BSD auth (auth_approval).

plugins/sudoers/auth/API
plugins/sudoers/auth/bsdauth.c
plugins/sudoers/auth/pam.c
plugins/sudoers/auth/sudo_auth.c
plugins/sudoers/auth/sudo_auth.h
plugins/sudoers/check.c
plugins/sudoers/sudoers.h

index 55d2dfc0c0b81a7c2a7293068e36e1c97a243b75..901cc885154996f969550d88ec8433a15e641b7b 100644 (file)
@@ -14,10 +14,11 @@ typedef struct sudo_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 (*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:
@@ -71,13 +72,22 @@ The functions 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
@@ -85,6 +95,14 @@ The functions in the struct are as follows:
        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
index 8bf775dcf761241e17b1a75d9579aada8d784000..e34b686761ab3c5df7cad843c0089f44521d4546 100644 (file)
@@ -168,6 +168,22 @@ bsdauth_verify(struct passwd *pw, char *prompt, sudo_auth *auth, struct sudo_con
     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)
 {
index 898cc99ffa03272d67ae266deb74c0359b55fb46..dcd7f2a22e2783d7de7a287ace6df3fb3bebe4c5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -186,43 +186,13 @@ sudo_pam_verify(struct passwd *pw, char *prompt, sudo_auth *auth, struct sudo_co
     }
     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)
@@ -231,6 +201,57 @@ sudo_pam_verify(struct passwd *pw, char *prompt, sudo_auth *auth, struct sudo_co
     }
 }
 
+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)
 {
index dc2bd5e3cc043b950837bea392794319b43a44d4..76569ee9165f0f91e65d22c8b20d69e9fceea3de 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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;
@@ -158,6 +158,30 @@ sudo_auth_init(struct passwd *pw)
     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.
@@ -166,18 +190,19 @@ int
 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
@@ -322,7 +347,7 @@ done:
            break;
        case AUTH_FATAL:
        default:
-           log_auth_failure(validated | FLAG_AUTH_ERROR, 0);
+           log_auth_failure(validated, 0);
            ret = -1;
            break;
     }
@@ -338,17 +363,18 @@ int
 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
@@ -375,17 +401,19 @@ int
 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);
 }
 
 /*
index abbaf614b1a8deb955e554c7178b144f1d91b0c7..6e3128071a4d754446d1943782506255c042c5ce 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -31,6 +31,7 @@ typedef struct sudo_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, 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);
@@ -56,6 +57,7 @@ extern sudo_conv_t sudo_conv;
 /* 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);
@@ -66,6 +68,7 @@ int sudo_fwtk_cleanup(struct passwd *pw, sudo_auth *auth);
 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);
@@ -93,8 +96,8 @@ int sudo_secureware_init(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 */
index fa5998d452fbe62f5fec9690a405da040739cb0e..8a68d4d04cd3bc42f525ac44f68076eb55416d38 100644 (file)
@@ -219,6 +219,10 @@ check_user(int validated, int mode)
     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);
 
index 945d29b95ac1c99d62d233d7ffe11ed991262912..0825181f8fbcc20158eeb4fb902489fb3a3e70bf 100644 (file)
@@ -136,8 +136,7 @@ struct sudo_user {
 #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
@@ -265,6 +264,7 @@ int verify_user(struct passwd *pw, char *prompt, int validated, struct sudo_conv
 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 */