From f19be6da311a2c1f22ca92ca2d1183e0e7a852da Mon Sep 17 00:00:00 2001
From: "Todd C. Miller" <Todd.Miller@courtesan.com>
Date: Tue, 13 Apr 2010 09:36:43 -0400
Subject: [PATCH] Handle plugin's open function returning -2 (usage error).

---
 doc/sudo_plugin.cat    | 102 ++++++++++++++++++++---------------------
 doc/sudo_plugin.man.in |  25 ++++++----
 doc/sudo_plugin.pod    |  23 ++++++----
 src/parse_args.c       |   1 +
 src/sudo.c             |  23 +++++++---
 5 files changed, 100 insertions(+), 74 deletions(-)

diff --git a/doc/sudo_plugin.cat b/doc/sudo_plugin.cat
index e72bc7f4d..d4ad795ea 100644
--- a/doc/sudo_plugin.cat
+++ b/doc/sudo_plugin.cat
@@ -61,7 +61,7 @@ SSuuddoo PPlluuggiinn AAPPII
 
 
 
-1.8.0a1                   March 21, 2010                        1
+1.8.0a1                   April 13, 2010                        1
 
 
 
@@ -104,7 +104,9 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
                         char * const settings[], char * const user_info[],
                         char * const user_env[]);
 
-           Returns 1 on success, 0 on failure and -1 on error.  On error, the
+           Returns 1 on success, 0 on failure, -1 if a general error ocurred,
+           or -2 if there was a usage error.  In the latter case, ssuuddoo will
+           print a usage message before it exits.  If an error occurs, the
            plugin may optionally call the conversation function with
            SUDO_CONF_ERROR_MSG to present additional error information to the
            user.
@@ -122,12 +124,10 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
 
            settings
                A vector of user-supplied ssuuddoo settings in the form of
-               "name=value" strings.  The vector is terminated by a NULL
-               pointer.  These settings correspond to flags the user specified
 
 
 
-1.8.0a1                   March 21, 2010                        2
+1.8.0a1                   April 13, 2010                        2
 
 
 
@@ -136,6 +136,8 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
 SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
 
 
+               "name=value" strings.  The vector is terminated by a NULL
+               pointer.  These settings correspond to flags the user specified
                when running ssuuddoo.  As such, they will only be present when the
                corresponding flag has been specified on the command line.
 
@@ -188,12 +190,10 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
 
                ignore_ticket=bool
                    Set to true if the user specified the -k flag along with a
-                   command, indicating that the user wishes to ignore any
-                   cached authentication credentials.
 
 
 
-1.8.0a1                   March 21, 2010                        3
+1.8.0a1                   April 13, 2010                        3
 
 
 
@@ -202,6 +202,9 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
 SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
 
 
+                   command, indicating that the user wishes to ignore any
+                   cached authentication credentials.
+
                login_class=string
                    BSD login class to use when setting resource limits and
                    nice value, if specified by the -c flag.
@@ -253,13 +256,10 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
                tty=string
                    The path to the user's terminal device.  If the user has no
                    terminal device associated with the session, the value will
-                   be empty, as in tty=.
-
 
 
 
-
-1.8.0a1                   March 21, 2010                        4
+1.8.0a1                   April 13, 2010                        4
 
 
 
@@ -268,6 +268,8 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
 SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
 
 
+                   be empty, as in tty=.
+
                host=string
                    The local machine's hostname as returned by the
                    gethostname() system call.
@@ -319,13 +321,11 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
            If the user requests detailed version information, the verbose flag
            will be set.
 
-       check_policy
-
 
 
 
 
-1.8.0a1                   March 21, 2010                        5
+1.8.0a1                   April 13, 2010                        5
 
 
 
@@ -334,6 +334,7 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
 SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
 
 
+       check_policy
             int (*check_policy)(int argc, char * const argv[]
                                 char *env_add[], char **command_info[],
                                 char **argv_out[], char **user_env_out[]);
@@ -386,12 +387,11 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
                    Effective user ID to run the command as.  If not specified,
                    the value of _r_u_n_a_s___u_i_d is used.
 
-               runas_gid=gid
-                   Group ID to run the command as.
 
 
 
-1.8.0a1                   March 21, 2010                        6
+
+1.8.0a1                   April 13, 2010                        6
 
 
 
@@ -400,6 +400,9 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
 SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
 
 
+               runas_gid=gid
+                   Group ID to run the command as.
+
                runas_egid=gid
                    Effective group ID to run the command as.  If not
                    specified, the value of _r_u_n_a_s___g_i_d is used.
@@ -451,13 +454,10 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
            argv_out
                The NULL-terminated argument vector to pass to the _e_x_e_c_v_e_(_)
                system call when executing the command.  The plugin is
-               responsible for allocating and populating the vector.
-
-
 
 
 
-1.8.0a1                   March 21, 2010                        7
+1.8.0a1                   April 13, 2010                        7
 
 
 
@@ -466,6 +466,8 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
 SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
 
 
+               responsible for allocating and populating the vector.
+
            user_env_out
                The NULL-terminated environment vector to use when executing
                the command.  The plugin is responsible for allocating and
@@ -518,12 +520,10 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
            SUDO_CONF_ERROR_MSG to present additional error information to the
            user.
 
-       invalidate
-            void (*invalidate)(int remove);
 
 
 
-1.8.0a1                   March 21, 2010                        8
+1.8.0a1                   April 13, 2010                        8
 
 
 
@@ -532,6 +532,9 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
 SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
 
 
+       invalidate
+            void (*invalidate)(int remove);
+
            The invalidate function is called when ssuuddoo is called with the -k
            or -K flag.  For policy plugins such as _s_u_d_o_e_r_s that cache
            authentication credentials, this function will invalidate the
@@ -586,10 +589,7 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
 
 
 
-
-
-
-1.8.0a1                   March 21, 2010                        9
+1.8.0a1                   April 13, 2010                        9
 
 
 
@@ -636,10 +636,15 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
                         char * const settings[], char * const user_info[],
                         char * const user_env[]);
 
-           Returns 1 on success, 0 if the command should not be logged and -1
-           on error.  On error, the plugin may optionally call the
-           conversation function with SUDO_CONF_ERROR_MSG to present
-           additional error information to the user.
+           The _o_p_e_n function is run before the _l_o_g___i_n_p_u_t, _l_o_g___o_u_t_p_u_t or
+           _s_h_o_w___v_e_r_s_i_o_n functions are called.  It is only called if the
+           version is being requested or the _c_h_e_c_k___p_o_l_i_c_y function has
+           returned successfully.  It returns 1 on success, 0 on failure, -1
+           if a general error ocurred, or -2 if there was a usage error.  In
+           the latter case, ssuuddoo will print a usage message before it exits.
+           If an error occurs, the plugin may optionally call the conversation
+           function with SUDO_CONF_ERROR_MSG to present additional error
+           information to the user.
 
            The function arguments are as follows:
 
@@ -648,14 +653,9 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
                the major and minor version number of the plugin API supported
                by ssuuddoo.
 
-           conversation
-               A pointer to the conversation function that may be used by the
-               _s_h_o_w___v_e_r_s_i_o_n function to display version information (see
-               show_version below).  The conversation function may also be
-
 
 
-1.8.0a1                   March 21, 2010                       10
+1.8.0a1                   April 13, 2010                       10
 
 
 
@@ -664,6 +664,10 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
 SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
 
 
+           conversation
+               A pointer to the conversation function that may be used by the
+               _s_h_o_w___v_e_r_s_i_o_n function to display version information (see
+               show_version below).  The conversation function may also be
                used to display additional error message to the user.
 
            settings
@@ -713,15 +717,11 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
                call.  The value of exit_status is undefined if error is non-
                zero.
 
-           error
-               If the command could not be executed, this is set to the value
-               of errno set by the _e_x_e_c_v_e(2) system call.  If the command was
-               successfully executed, the value of error is 0.
 
 
 
 
-1.8.0a1                   March 21, 2010                       11
+1.8.0a1                   April 13, 2010                       11
 
 
 
@@ -730,6 +730,11 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
 SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
 
 
+           error
+               If the command could not be executed, this is set to the value
+               of errno set by the _e_x_e_c_v_e(2) system call.  If the command was
+               successfully executed, the value of error is 0.
+
        show_version
             int (*show_version)(int verbose);
 
@@ -782,12 +787,7 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
 
 
 
-
-
-
-
-
-1.8.0a1                   March 21, 2010                       12
+1.8.0a1                   April 13, 2010                       12
 
 
 
@@ -853,6 +853,6 @@ SUDO_PLUGIN(1m)        MAINTENANCE COMMANDS       SUDO_PLUGIN(1m)
 
 
 
-1.8.0a1                   March 21, 2010                       13
+1.8.0a1                   April 13, 2010                       13
 
 
diff --git a/doc/sudo_plugin.man.in b/doc/sudo_plugin.man.in
index dbbc91350..572dc89ef 100644
--- a/doc/sudo_plugin.man.in
+++ b/doc/sudo_plugin.man.in
@@ -139,7 +139,7 @@
 .\" ========================================================================
 .\"
 .IX Title "SUDO_PLUGIN @mansectsu@"
-.TH SUDO_PLUGIN @mansectsu@ "March 21, 2010" "1.8.0a1" "MAINTENANCE COMMANDS"
+.TH SUDO_PLUGIN @mansectsu@ "April 13, 2010" "1.8.0a1" "MAINTENANCE COMMANDS"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
@@ -240,10 +240,12 @@ built against.
 \&             char * const user_env[]);
 .Ve
 .Sp
-Returns 1 on success, 0 on failure and \-1 on error.
-On error, the plugin may optionally call the conversation function with
-\&\f(CW\*(C`SUDO_CONF_ERROR_MSG\*(C'\fR to present additional error information to the
-user.
+Returns 1 on success, 0 on failure, \-1 if a general error ocurred,
+or \-2 if there was a usage error.  In the latter case, \fBsudo\fR will
+print a usage message before it exits.  If an error occurs, the
+plugin may optionally call the conversation function with
+\&\f(CW\*(C`SUDO_CONF_ERROR_MSG\*(C'\fR to present additional error information to
+the user.
 .Sp
 The function arguments are as follows:
 .RS 4
@@ -705,10 +707,15 @@ built against.
 \&             char * const user_env[]);
 .Ve
 .Sp
-Returns 1 on success, 0 if the command should not be logged and \-1 on error.
-On error, the plugin may optionally call the conversation function with
-\&\f(CW\*(C`SUDO_CONF_ERROR_MSG\*(C'\fR to present additional error information to the
-user.
+The \fIopen\fR function is run before the \fIlog_input\fR, \fIlog_output\fR
+or \fIshow_version\fR functions are called.  It is only called if the
+version is being requested or the \fIcheck_policy\fR function has
+returned successfully.  It returns 1 on success, 0 on failure, \-1
+if a general error ocurred, or \-2 if there was a usage error.  In
+the latter case, \fBsudo\fR will print a usage message before it exits.
+If an error occurs, the plugin may optionally call the conversation
+function with \f(CW\*(C`SUDO_CONF_ERROR_MSG\*(C'\fR to present additional error
+information to the user.
 .Sp
 The function arguments are as follows:
 .RS 4
diff --git a/doc/sudo_plugin.pod b/doc/sudo_plugin.pod
index 6b4da39f3..3282908e6 100644
--- a/doc/sudo_plugin.pod
+++ b/doc/sudo_plugin.pod
@@ -112,10 +112,12 @@ built against.
              char * const settings[], char * const user_info[],
              char * const user_env[]);
 
-Returns 1 on success, 0 on failure and -1 on error.
-On error, the plugin may optionally call the conversation function with
-C<SUDO_CONF_ERROR_MSG> to present additional error information to the
-user.
+Returns 1 on success, 0 on failure, -1 if a general error ocurred,
+or -2 if there was a usage error.  In the latter case, B<sudo> will
+print a usage message before it exits.  If an error occurs, the
+plugin may optionally call the conversation function with
+C<SUDO_CONF_ERROR_MSG> to present additional error information to
+the user.
 
 The function arguments are as follows:
 
@@ -629,10 +631,15 @@ built against.
              char * const settings[], char * const user_info[],
              char * const user_env[]);
 
-Returns 1 on success, 0 if the command should not be logged and -1 on error.
-On error, the plugin may optionally call the conversation function with
-C<SUDO_CONF_ERROR_MSG> to present additional error information to the
-user.
+The I<open> function is run before the I<log_input>, I<log_output>
+or I<show_version> functions are called.  It is only called if the
+version is being requested or the I<check_policy> function has
+returned successfully.  It returns 1 on success, 0 on failure, -1
+if a general error ocurred, or -2 if there was a usage error.  In
+the latter case, B<sudo> will print a usage message before it exits.
+If an error occurs, the plugin may optionally call the conversation
+function with C<SUDO_CONF_ERROR_MSG> to present additional error
+information to the user.
 
 The function arguments are as follows:
 
diff --git a/src/parse_args.c b/src/parse_args.c
index 1c55f77e9..68c89a7ec 100644
--- a/src/parse_args.c
+++ b/src/parse_args.c
@@ -465,6 +465,7 @@ usage(int exit_val)
 	lbuf_print(&lbuf);
     }
     lbuf_destroy(&lbuf);
+    cleanup(0);
     exit(exit_val);
 }
 
diff --git a/src/sudo.c b/src/sudo.c
index 75162d2b6..c8196cd54 100644
--- a/src/sudo.c
+++ b/src/sudo.c
@@ -149,8 +149,12 @@ main(int argc, char *argv[], char *envp[])
     /* Open policy plugin. */
     ok = policy_plugin.u.policy->open(SUDO_API_VERSION, sudo_conversation,
 	settings, user_info, envp);
-    if (ok != TRUE)
-	errorx(1, "unable to initialize policy plugin");
+    if (ok != TRUE) {
+	if (ok == -2)
+	    usage(1);
+	else
+	    errorx(1, "unable to initialize policy plugin");
+    }
 
     sudo_debug(9, "sudo_mode %d", sudo_mode);
     switch (sudo_mode & MODE_MASK) {
@@ -159,7 +163,7 @@ main(int argc, char *argv[], char *envp[])
 	    tq_foreach_fwd(&io_plugins, plugin) {
 		ok = plugin->u.io->open(SUDO_API_VERSION, sudo_conversation,
 		    settings, user_info, envp);
-		if (ok)
+		if (ok == TRUE)
 		    plugin->u.io->show_version(user_details.uid == ROOT_UID);
 	    }
 	    break;
@@ -210,11 +214,18 @@ main(int argc, char *argv[], char *envp[])
 		next = plugin->next;
 		ok = plugin->u.io->open(SUDO_API_VERSION, sudo_conversation, settings,
 		    user_info, envp);
-		if (ok == -1)
-		    errorx(1, "error initializing I/O plugin %s", plugin->name);
-		if (!ok) {
+		switch (ok) {
+		case TRUE:
+		    break;
+		case FALSE:
 		    /* I/O plugin asked to be disabled, remove from list. */
 		    tq_remove(&io_plugins, plugin);
+		    break;
+		case -2:
+		    usage(1);
+		    break;
+		default:
+		    errorx(1, "error initializing I/O plugin %s", plugin->name);
 		}
 	    }
 	    command_info_to_details(command_info, &command_details);
-- 
2.40.0