]> granicus.if.org Git - sudo/commitdiff
Add a struct sudo_conv_callback that contains on_suspend and on_resume
authorTodd C. Miller <Todd.Miller@courtesan.com>
Mon, 7 Sep 2015 12:06:08 +0000 (06:06 -0600)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Mon, 7 Sep 2015 12:06:08 +0000 (06:06 -0600)
function pointer args plus a closure pointer and at it to the
conversation function.

28 files changed:
doc/sudo_plugin.cat
doc/sudo_plugin.man.in
doc/sudo_plugin.mdoc.in
include/sudo_fatal.h
include/sudo_plugin.h
lib/util/fatal.c
plugins/sudoers/auth/afs.c
plugins/sudoers/auth/aix_auth.c
plugins/sudoers/auth/bsdauth.c
plugins/sudoers/auth/dce.c
plugins/sudoers/auth/fwtk.c
plugins/sudoers/auth/kerb5.c
plugins/sudoers/auth/pam.c
plugins/sudoers/auth/passwd.c
plugins/sudoers/auth/rfc1938.c
plugins/sudoers/auth/secureware.c
plugins/sudoers/auth/securid5.c
plugins/sudoers/auth/sia.c
plugins/sudoers/auth/sudo_auth.c
plugins/sudoers/auth/sudo_auth.h
plugins/sudoers/check.c
plugins/sudoers/sudo_nss.c
plugins/sudoers/sudoers.h
src/conversation.c
src/sudo.c
src/sudo.h
src/sudo_plugin_int.h
src/tgetpass.c

index b8795efbca29987df23e3a75d1a5546c35459776..daa3c6e861384c8ec993907220fe4da45fda1179 100644 (file)
@@ -1297,9 +1297,26 @@ D\bDE\bES\bSC\bCR\bRI\bIP\bPT\bTI\bIO\bON\bN
          char *reply;
      };
 
+     /* Conversation callback API version major/minor */
+     #define SUDO_CONV_CALLBACK_VERSION_MAJOR 1
+     #define SUDO_CONV_CALLBACK_VERSION_MINOR 0
+     #define SUDO_CONV_CALLBACK_MKVERSION(x, y) ((x << 16) | y)
+     #define SUDO_CONV_CALLBACK_VERSION \
+         SUDO_CONV_CALLBACK_MKVERSION(SUDO_CONV_CALLBACK_VERSION_MAJOR, \
+         SUDO_CONV_CALLBACK_VERSION_MINOR)
+
+     typedef int (*sudo_conv_callback_fn_t)(int signo, void *closure);
+     struct sudo_conv_callback {
+         unsigned int version;
+         void *closure;
+         sudo_conv_callback_fn_t on_suspend;
+         sudo_conv_callback_fn_t on_resume;
+     };
+
      typedef int (*sudo_conv_t)(int num_msgs,
                   const struct sudo_conv_message msgs[],
-                  struct sudo_conv_reply replies[]);
+                  struct sudo_conv_reply replies[],
+                  struct sudo_conv_callback *callback);
 
      typedef int (*sudo_printf_t)(int msg_type, const char *fmt, ...);
 
@@ -1309,13 +1326,21 @@ D\bDE\bES\bSC\bCR\bRI\bIP\bPT\bTI\bIO\bON\bN
      To use the c\bco\bon\bnv\bve\ber\brs\bsa\bat\bti\bio\bon\bn() function, the plugin must pass an array of
      sudo_conv_message and sudo_conv_reply structures.  There must be a struct
      sudo_conv_message and struct sudo_conv_reply for each message in the
-     conversation.  The plugin is responsible for freeing the reply buffer
-     located in each struct sudo_conv_reply, if it is not NULL.
-     SUDO_CONV_REPL_MAX represents the maximum length of the reply buffer (not
-     including the trailing NUL character).  In practical terms, this is the
-     longest password s\bsu\bud\bdo\bo will support.  It is also useful as a maximum value
-     for the m\bme\bem\bms\bse\bet\bt_\b_s\bs() function when clearing passwords filled in by the
-     conversation function.
+     conversation.  The struct sudo_conv_callback pointer, if not NULL,
+     contains function pointers that are called when the s\bsu\bud\bdo\bo process is
+     suspended and/or resumed during conversation input.  The functions are
+     passed the signal that caused s\bsu\bud\bdo\bo to be suspended and the _\bc_\bl_\bo_\bs_\bu_\br_\be
+     pointer.  This allows the plugin to release resources such as locks that
+     should not be held indefinitely on suspend and reacquire them on resume.
+     Note that the functions are not actually invoked from within a signal
+     handler.
+
+     The plugin is responsible for freeing the reply buffer located in each
+     struct sudo_conv_reply, if it is not NULL.  SUDO_CONV_REPL_MAX represents
+     the maximum length of the reply buffer (not including the trailing NUL
+     character).  In practical terms, this is the longest password s\bsu\bud\bdo\bo will
+     support.  It is also useful as a maximum value for the m\bme\bem\bms\bse\bet\bt_\b_s\bs()
+     function when clearing passwords filled in by the conversation function.
 
      The p\bpr\bri\bin\bnt\btf\bf()-style function uses the same underlying mechanism as the
      c\bco\bon\bnv\bve\ber\brs\bsa\bat\bti\bio\bon\bn() function but only supports SUDO_CONV_INFO_MSG and
@@ -1490,6 +1515,12 @@ P\bPL\bLU\bUG\bGI\bIN\bN A\bAP\bPI\bI C\bCH\bHA\bAN\bNG\bGE\bEL\bLO\bOG\bG
      Version 1.8 (sudo 1.8.15)
            The _\bs_\bu_\bd_\bo_\be_\bd_\bi_\bt_\b__\bf_\bo_\bl_\bl_\bo_\bw entry was added to the command_info list.
 
+           The sudo _\bc_\bo_\bn_\bv_\be_\br_\bs_\ba_\bt_\bi_\bo_\bn function now takes a pointer to a struct
+           sudo_conv_callback as its fourth argument.  The sudo_conv_t
+           definition has been updated to match.  The plugin must specify that
+           it supports plugin API version 1.8 or higher to receive a
+           conversation function pointer that supports this argument.
+
 S\bSE\bEE\bE A\bAL\bLS\bSO\bO
      sudo.conf(4), sudoers(4), sudo(1m)
 
@@ -1519,4 +1550,4 @@ D\bDI\bIS\bSC\bCL\bLA\bAI\bIM\bME\bER\bR
      file distributed with s\bsu\bud\bdo\bo or http://www.sudo.ws/license.html for
      complete details.
 
-Sudo 1.8.15                     August 6, 2015                     Sudo 1.8.15
+Sudo 1.8.15                    September 2, 2015                   Sudo 1.8.15
index 8987d7efbc5657a46bccb6aa86386daa13f9088c..d7a44136c3d231315b57b303aef28bdef35a5a9f 100644 (file)
@@ -16,7 +16,7 @@
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.TH "SUDO_PLUGIN" "5" "August 6, 2015" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
+.TH "SUDO_PLUGIN" "5" "September 2, 2015" "Sudo @PACKAGE_VERSION@" "File Formats Manual"
 .nh
 .if n .ad l
 .SH "NAME"
@@ -2293,9 +2293,26 @@ struct sudo_conv_reply {
     char *reply;
 };
 
+/* Conversation callback API version major/minor */
+#define SUDO_CONV_CALLBACK_VERSION_MAJOR 1
+#define SUDO_CONV_CALLBACK_VERSION_MINOR 0
+#define SUDO_CONV_CALLBACK_MKVERSION(x, y) ((x << 16) | y)
+#define SUDO_CONV_CALLBACK_VERSION \e
+    SUDO_CONV_CALLBACK_MKVERSION(SUDO_CONV_CALLBACK_VERSION_MAJOR, \e
+    SUDO_CONV_CALLBACK_VERSION_MINOR)
+
+typedef int (*sudo_conv_callback_fn_t)(int signo, void *closure);
+struct sudo_conv_callback {
+    unsigned int version;
+    void *closure;
+    sudo_conv_callback_fn_t on_suspend;
+    sudo_conv_callback_fn_t on_resume;
+};
+
 typedef int (*sudo_conv_t)(int num_msgs,
              const struct sudo_conv_message msgs[],
-             struct sudo_conv_reply replies[]);
+             struct sudo_conv_reply replies[],
+            struct sudo_conv_callback *callback);
 
 typedef int (*sudo_printf_t)(int msg_type, const char *fmt, ...);
 .RE
@@ -2323,6 +2340,23 @@ and
 \fRstruct sudo_conv_reply\fR
 for
 each message in the conversation.
+The
+\fRstruct sudo_conv_callback\fR
+pointer, if not
+\fRNULL\fR,
+contains function pointers that are called when the
+\fBsudo\fR
+process is suspended and/or resumed during conversation input.
+The functions are passed the signal that caused
+\fBsudo\fR
+to be suspended and the
+\fIclosure\fR
+pointer.
+This allows the plugin to release resources such as locks that
+should not be held indefinitely on suspend and reacquire them
+on resume.
+Note that the functions are not actually invoked from within a signal handler.
+.PP
 The plugin is responsible for freeing the reply buffer located in each
 \fRstruct sudo_conv_reply\fR,
 if it is not
@@ -2662,6 +2696,17 @@ The
 entry was added to the
 \fRcommand_info\fR
 list.
+.sp
+The sudo
+\fIconversation\fR
+function now takes a pointer to a
+\fRstruct sudo_conv_callback\fR
+as its fourth argument.
+The
+\fRsudo_conv_t\fR
+definition has been updated to match.
+The plugin must specify that it supports plugin API version 1.8 or higher
+to receive a conversation function pointer that supports this argument.
 .SH "SEE ALSO"
 sudo.conf(@mansectform@),
 sudoers(@mansectform@),
index 34549cc8fa25ce1a5d68ba42a38751af96184997..b49699aad7a18e889c13cfd22d9311156bbe47c5 100644 (file)
@@ -14,7 +14,7 @@
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd August 6, 2015
+.Dd September 2, 2015
 .Dt SUDO_PLUGIN @mansectform@
 .Os Sudo @PACKAGE_VERSION@
 .Sh NAME
@@ -1999,9 +1999,26 @@ struct sudo_conv_reply {
     char *reply;
 };
 
+/* Conversation callback API version major/minor */
+#define SUDO_CONV_CALLBACK_VERSION_MAJOR 1
+#define SUDO_CONV_CALLBACK_VERSION_MINOR 0
+#define SUDO_CONV_CALLBACK_MKVERSION(x, y) ((x << 16) | y)
+#define SUDO_CONV_CALLBACK_VERSION \e
+    SUDO_CONV_CALLBACK_MKVERSION(SUDO_CONV_CALLBACK_VERSION_MAJOR, \e
+    SUDO_CONV_CALLBACK_VERSION_MINOR)
+
+typedef int (*sudo_conv_callback_fn_t)(int signo, void *closure);
+struct sudo_conv_callback {
+    unsigned int version;
+    void *closure;
+    sudo_conv_callback_fn_t on_suspend;
+    sudo_conv_callback_fn_t on_resume;
+};
+
 typedef int (*sudo_conv_t)(int num_msgs,
              const struct sudo_conv_message msgs[],
-             struct sudo_conv_reply replies[]);
+             struct sudo_conv_reply replies[],
+            struct sudo_conv_callback *callback);
 
 typedef int (*sudo_printf_t)(int msg_type, const char *fmt, ...);
 .Ed
@@ -2028,6 +2045,23 @@ and
 .Li struct sudo_conv_reply
 for
 each message in the conversation.
+The
+.Li struct sudo_conv_callback
+pointer, if not
+.Dv NULL ,
+contains function pointers that are called when the
+.Nm sudo
+process is suspended and/or resumed during conversation input.
+The functions are passed the signal that caused
+.Nm sudo
+to be suspended and the
+.Fa closure
+pointer.
+This allows the plugin to release resources such as locks that
+should not be held indefinitely on suspend and reacquire them
+on resume.
+Note that the functions are not actually invoked from within a signal handler.
+.Pp
 The plugin is responsible for freeing the reply buffer located in each
 .Li struct sudo_conv_reply ,
 if it is not
@@ -2329,6 +2363,17 @@ The
 entry was added to the
 .Li command_info
 list.
+.Pp
+The sudo
+.Em conversation
+function now takes a pointer to a
+.Li struct sudo_conv_callback
+as its fourth argument.
+The
+.Li sudo_conv_t
+definition has been updated to match.
+The plugin must specify that it supports plugin API version 1.8 or higher
+to receive a conversation function pointer that supports this argument.
 .El
 .Sh SEE ALSO
 .Xr sudo.conf @mansectform@ ,
index f38b56355dfc327725a9ed22b4c713fb2a4cf0c8..43a1ce02da8164c0ed4075489bd91ccc71daa7e5 100644 (file)
@@ -121,6 +121,7 @@ typedef void (*sudo_fatal_callback_t)(void);
 
 struct sudo_conv_message;
 struct sudo_conv_reply;
+struct sudo_conv_callback;
 
 __dso_public int  sudo_fatal_callback_deregister_v1(sudo_fatal_callback_t func);
 __dso_public int  sudo_fatal_callback_register_v1(sudo_fatal_callback_t func);
@@ -134,7 +135,7 @@ __dso_public void sudo_warn_nodebug_v1(const char *fmt, ...) __printf0like(1, 2)
 __dso_public void sudo_warnx_nodebug_v1(const char *fmt, ...) __printflike(1, 2);
 __dso_public void sudo_vwarn_nodebug_v1(const char *fmt, va_list ap) __printf0like(1, 0);
 __dso_public void sudo_vwarnx_nodebug_v1(const char *fmt, va_list ap) __printflike(1, 0);
-__dso_public void sudo_warn_set_conversation_v1(int (*conv)(int num_msgs, const struct sudo_conv_message *msgs, struct sudo_conv_reply *replies));
+__dso_public void sudo_warn_set_conversation_v1(int (*conv)(int num_msgs, const struct sudo_conv_message *msgs, struct sudo_conv_reply *replies, struct sudo_conv_callback *callback));
 
 #define sudo_fatal_callback_deregister(_a) sudo_fatal_callback_deregister_v1((_a))
 #define sudo_fatal_callback_register(_a) sudo_fatal_callback_register_v1((_a))
@@ -148,7 +149,6 @@ __dso_public void sudo_warn_set_conversation_v1(int (*conv)(int num_msgs, const
 #define sudo_vwarn_nodebug(_a, _b) sudo_vwarn_nodebug_v1((_a), (_b))
 #define sudo_vwarnx_nodebug(_a, _b) sudo_vwarnx_nodebug_v1((_a), (_b))
 #define sudo_warn_set_conversation(_a) sudo_warn_set_conversation_v1(_a)
-#define sudo_warn_set_conversation(_a) sudo_warn_set_conversation_v1(_a)
 
 #ifdef DEFAULT_TEXT_DOMAIN
 # define sudo_warn_gettext(_a) sudo_warn_gettext_v1(DEFAULT_TEXT_DOMAIN, (_a))
index d2c65fcf1c41a264bc0c2e9109c4bb168de9c6f2..b8fa44591ed369c4767eb3491483defb4a9b9260 100644 (file)
@@ -61,8 +61,27 @@ struct sudo_conv_reply {
     char *reply;
 };
 
+/* Conversation callback API version major/minor */
+#define SUDO_CONV_CALLBACK_VERSION_MAJOR       1
+#define SUDO_CONV_CALLBACK_VERSION_MINOR       0
+#define SUDO_CONV_CALLBACK_MKVERSION(x, y) ((x << 16) | y)
+#define SUDO_CONV_CALLBACK_VERSION SUDO_CONV_CALLBACK_MKVERSION(SUDO_CONV_CALLBACK_VERSION_MAJOR, SUDO_CONV_CALLBACK_VERSION_MINOR)
+
+/*
+ * Callback struct to be passed to the conversation function.
+ * Can be used to perform operations on suspend/resume such
+ * as dropping/acquiring locks.
+ */
+typedef int (*sudo_conv_callback_fn_t)(int signo, void *closure);
+struct sudo_conv_callback {
+    unsigned int version;
+    void *closure;
+    sudo_conv_callback_fn_t on_suspend;
+    sudo_conv_callback_fn_t on_resume;
+};
+
 typedef int (*sudo_conv_t)(int num_msgs, const struct sudo_conv_message msgs[],
-       struct sudo_conv_reply replies[]);
+       struct sudo_conv_reply replies[], struct sudo_conv_callback *callback);
 typedef int (*sudo_printf_t)(int msg_type, const char *fmt, ...);
 
 /*
index 295cfe3c18c75ce47854a50a660d0e2fe369da96..f1b24ea844d8629208f5675209355f42bcc48bcf 100644 (file)
@@ -179,7 +179,7 @@ warning(int errnum, const char *fmt, va_list ap)
         }
        msgs[nmsgs].msg_type = SUDO_CONV_ERROR_MSG;
        msgs[nmsgs++].msg = "\n";
-       sudo_warn_conversation(nmsgs, msgs, NULL);
+       sudo_warn_conversation(nmsgs, msgs, NULL, NULL);
        if (buf != static_buf)
            free(buf);
     } else {
index 5693cb18b5ff6b534f60eb8bb00d0daf0b11f560..de223578071eb67248d977b9863c37469aff6bf0 100644 (file)
@@ -42,7 +42,7 @@
 #include "sudo_auth.h"
 
 int
-sudo_afs_verify(struct passwd *pw, char *pass, sudo_auth *auth)
+sudo_afs_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback)
 {
     struct ktc_encryptionKey afs_key;
     struct ktc_token afs_token;
index 66a0b23e1230f165b81cf242db368dba7b8f9fe0..4bc3ae5e2b5bd4fc8f0e2f3df93a768d498efc78 100644 (file)
@@ -128,7 +128,7 @@ sudo_aix_init(struct passwd *pw, sudo_auth *auth)
 }
 
 int
-sudo_aix_verify(struct passwd *pw, char *prompt, sudo_auth *auth)
+sudo_aix_verify(struct passwd *pw, char *prompt, sudo_auth *auth, struct sudo_conv_callback *callback)
 {
     char *pass, *message = NULL;
     int result = 1, reenter = 0;
@@ -137,7 +137,7 @@ sudo_aix_verify(struct passwd *pw, char *prompt, sudo_auth *auth)
 
     do {
        pass = auth_getpass(prompt, def_passwd_timeout * 60,
-           SUDO_CONV_PROMPT_ECHO_OFF);
+           SUDO_CONV_PROMPT_ECHO_OFF, callback);
        if (pass == NULL)
            break;
        free(message);
@@ -157,7 +157,7 @@ sudo_aix_verify(struct passwd *pw, char *prompt, sudo_auth *auth)
            msg.msg_type = SUDO_CONV_ERROR_MSG;
            msg.msg = message;
            memset(&repl, 0, sizeof(repl));
-           sudo_conv(1, &msg, &repl);
+           sudo_conv(1, &msg, &repl, NULL);
        }
        rval = pass ? AUTH_FAILURE : AUTH_INTR;
     }
index e01b6944a1e08ed1ef8f18225f70cc98b0d75741..18a25e32f3e4f13796f3045353dd7f738a2ff6e2 100644 (file)
@@ -98,7 +98,7 @@ bsdauth_init(struct passwd *pw, sudo_auth *auth)
 }
 
 int
-bsdauth_verify(struct passwd *pw, char *prompt, sudo_auth *auth)
+bsdauth_verify(struct passwd *pw, char *prompt, sudo_auth *auth, struct sudo_conv_callback *callback)
 {
     char *pass;
     char *s;
@@ -121,9 +121,9 @@ bsdauth_verify(struct passwd *pw, char *prompt, sudo_auth *auth)
      * S/Key.
      */
     if ((s = auth_challenge(as)) == NULL) {
-       pass = auth_getpass(prompt, def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_OFF);
+       pass = auth_getpass(prompt, def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_OFF, callback);
     } else {
-       pass = auth_getpass(prompt, def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_OFF);
+       pass = auth_getpass(prompt, def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_OFF, callback);
        if (pass && *pass == '\0') {
            if ((prompt = strrchr(s, '\n')))
                prompt++;
@@ -142,7 +142,7 @@ bsdauth_verify(struct passwd *pw, char *prompt, sudo_auth *auth)
                debug_return_int(AUTH_FATAL);
            }
            pass = auth_getpass(prompt, def_passwd_timeout * 60,
-               SUDO_CONV_PROMPT_ECHO_ON);
+               SUDO_CONV_PROMPT_ECHO_ON, callback);
            free(s);
        }
     }
index e5966152e5c24fbfd93446c74f733876d28b0d3c..262b4ef14b6ca0e204196ea98006d7782ccb60b2 100644 (file)
@@ -59,7 +59,7 @@
 static int check_dce_status(error_status_t, char *);
 
 int
-sudo_dce_verify(struct passwd *pw, char *plain_pw, sudo_auth *auth)
+sudo_dce_verify(struct passwd *pw, char *plain_pw, sudo_auth *auth, struct sudo_conv_callback *callback)
 {
     struct passwd              temp_pw;
     sec_passwd_rec_t           password_rec;
index 73094d6c2b3022a13cff83f14e7f3d75c5d5f421..e144d3cdfff83423baeabc46b911cf8771de2971 100644 (file)
@@ -72,7 +72,7 @@ sudo_fwtk_init(struct passwd *pw, sudo_auth *auth)
 }
 
 int
-sudo_fwtk_verify(struct passwd *pw, char *prompt, sudo_auth *auth)
+sudo_fwtk_verify(struct passwd *pw, char *prompt, sudo_auth *auth, struct sudo_conv_callback *callback)
 {
     char *pass;                                /* Password from the user */
     char buf[SUDO_CONV_REPL_MAX + 12]; /* General prupose buffer */
@@ -91,17 +91,17 @@ restart:
     /* Get the password/response from the user. */
     if (strncmp(resp, "challenge ", 10) == 0) {
        (void) snprintf(buf, sizeof(buf), "%s\nResponse: ", &resp[10]);
-       pass = auth_getpass(buf, def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_OFF);
+       pass = auth_getpass(buf, def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_OFF, callback);
        if (pass && *pass == '\0') {
            pass = auth_getpass("Response [echo on]: ",
-               def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_ON);
+               def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_ON, callback);
        }
     } else if (strncmp(resp, "chalnecho ", 10) == 0) {
        pass = auth_getpass(&resp[10], def_passwd_timeout * 60,
-           SUDO_CONV_PROMPT_ECHO_OFF);
+           SUDO_CONV_PROMPT_ECHO_OFF, callback);
     } else if (strncmp(resp, "password", 8) == 0) {
        pass = auth_getpass(prompt, def_passwd_timeout * 60,
-           SUDO_CONV_PROMPT_ECHO_OFF);
+           SUDO_CONV_PROMPT_ECHO_OFF, callback);
     } else if (strncmp(resp, "display ", 8) == 0) {
        fprintf(stderr, "%s\n", &resp[8]);
        strlcpy(buf, "response dummy", sizeof(buf));
index 8c7aff6f854c484baa1548949f17f00038b07929..ca31f99aab38408149d5dbc29ed9dfaa8ca0ef28 100644 (file)
@@ -180,7 +180,7 @@ done:
 
 #ifdef HAVE_KRB5_VERIFY_USER
 int
-sudo_krb5_verify(struct passwd *pw, char *pass, sudo_auth *auth)
+sudo_krb5_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback)
 {
     krb5_context       sudo_context;
     krb5_principal     princ;
index ccd0d1ebc1053573699eeb23cb8719795137cefb..4c85ebb6a0f3113a3fbd597353d7abf839acbab5 100644 (file)
@@ -71,7 +71,8 @@
 
 static int converse(int, PAM_CONST struct pam_message **,
                    struct pam_response **, void *);
-static struct pam_conv pam_conv = { converse, NULL };
+static struct sudo_conv_callback *conv_callback;
+static struct pam_conv pam_conv = { converse, &conv_callback };
 static char *def_prompt = PASSPROMPT;
 static bool getpass_error;
 static pam_handle_t *pamh;
@@ -137,7 +138,7 @@ sudo_pam_init(struct passwd *pw, sudo_auth *auth)
 }
 
 int
-sudo_pam_verify(struct passwd *pw, char *prompt, sudo_auth *auth)
+sudo_pam_verify(struct passwd *pw, char *prompt, sudo_auth *auth, struct sudo_conv_callback *callback)
 {
     const char *s;
     int *pam_status = (int *) auth->data;
@@ -145,6 +146,7 @@ sudo_pam_verify(struct passwd *pw, char *prompt, sudo_auth *auth)
 
     def_prompt = prompt;       /* for converse */
     getpass_error = false;     /* set by converse if user presses ^C */
+    conv_callback = callback;  /* passed to conversation function */
 
     /* PAM_SILENT prevents the authentication service from generating output. */
     *pam_status = pam_authenticate(pamh, PAM_SILENT);
@@ -375,7 +377,7 @@ sudo_pam_end_session(struct passwd *pw, sudo_auth *auth)
  */
 static int
 converse(int num_msg, PAM_CONST struct pam_message **msg,
-    struct pam_response **response, void *appdata_ptr)
+    struct pam_response **response, void *callback)
 {
     struct pam_response *pr;
     PAM_CONST struct pam_message *pm;
@@ -427,7 +429,7 @@ converse(int num_msg, PAM_CONST struct pam_message **msg,
                        prompt = pm->msg;
                }
                /* Read the password unless interrupted. */
-               pass = auth_getpass(prompt, def_passwd_timeout * 60, type);
+               pass = auth_getpass(prompt, def_passwd_timeout * 60, type, callback);
                if (pass == NULL) {
                    /* Error (or ^C) reading password, don't try again. */
                    getpass_error = true;
index 9173ff35a406d6c77b40fa06b121874a5431e1e8..7318f09d37740bbfba461677acfd90df6eb423de 100644 (file)
@@ -54,7 +54,7 @@ sudo_passwd_init(struct passwd *pw, sudo_auth *auth)
 }
 
 int
-sudo_passwd_verify(struct passwd *pw, char *pass, sudo_auth *auth)
+sudo_passwd_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback)
 {
     char sav, *epass;
     char *pw_epasswd = auth->data;
index cf2e37eda55c94acb16fade646703fc9c139ef55..e1474c6eff3caaf7c2ea6f499a14d7e1b83c7b27 100644 (file)
@@ -124,7 +124,7 @@ sudo_rfc1938_setup(struct passwd *pw, char **promptp, sudo_auth *auth)
 }
 
 int
-sudo_rfc1938_verify(struct passwd *pw, char *pass, sudo_auth *auth)
+sudo_rfc1938_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback)
 {
     debug_decl(sudo_rfc1938_verify, SUDOERS_DEBUG_AUTH)
 
index a44a3cb0d435b4316b5c2eb35d12eb107ed5e858..1e349a902e18ef2d019ff4d0b83130a162a5d42f 100644 (file)
@@ -65,7 +65,7 @@ sudo_secureware_init(struct passwd *pw, sudo_auth *auth)
 }
 
 int
-sudo_secureware_verify(struct passwd *pw, char *pass, sudo_auth *auth)
+sudo_secureware_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback)
 {
     char *pw_epasswd = auth->data;
     char *epass = NULL;
index 7274de0feea9c30c5032cf583f5c052d61d437d9..41eec085f198ef57151127f1547f662bd19d1eec 100644 (file)
@@ -139,14 +139,14 @@ sudo_securid_setup(struct passwd *pw, char **promptp, sudo_auth *auth)
  *                   incorrect authentication, fatal on errors
  */
 int
-sudo_securid_verify(struct passwd *pw, char *pass, sudo_auth *auth)
+sudo_securid_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback)
 {
     SDI_HANDLE *sd = (SDI_HANDLE *) auth->data;
     int rval;
     debug_decl(sudo_securid_verify, SUDOERS_DEBUG_AUTH)
 
     pass = auth_getpass("Enter your PASSCODE: ",
-       def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_OFF);
+       def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_OFF, callback);
 
     /* Have ACE verify password */
     switch (SD_Check(*sd, pass, pw->pw_name)) {
@@ -181,7 +181,7 @@ sudo_securid_verify(struct passwd *pw, char *pass, sudo_auth *auth)
 !!! ATTENTION !!!\n\
 Wait for the token code to change, \n\
 then enter the new token code.\n", \
-               def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_OFF);
+               def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_OFF, callback);
 
                if (SD_Next(*sd, pass) == ACM_OK) {
                        rval = AUTH_SUCCESS;
index b6c757f4abbb2f01f1506c5ebe30f477dfbd57e8..a7d262c1826832a758c248233aed0fb52a444ca8 100644 (file)
@@ -126,7 +126,7 @@ sudo_sia_setup(struct passwd *pw, char **promptp, sudo_auth *auth)
 }
 
 int
-sudo_sia_verify(struct passwd *pw, char *prompt, sudo_auth *auth)
+sudo_sia_verify(struct passwd *pw, char *prompt, sudo_auth *auth, struct sudo_conv_callback *callback)
 {
     SIAENTITY *siah = (SIAENTITY *) auth->data;
     debug_decl(sudo_sia_verify, SUDOERS_DEBUG_AUTH)
index 9b86f3855d50679ac09b5ba9836036fa2a653873..eeba9bdfc3c7b37240cd37078c98993a95a28d25 100644 (file)
@@ -209,7 +209,8 @@ user_interrupted(void)
  * Returns true if verified, false if not or -1 on error.
  */
 int
-verify_user(struct passwd *pw, char *prompt, int validated)
+verify_user(struct passwd *pw, char *prompt, int validated,
+    struct sudo_conv_callback *callback)
 {
     unsigned int ntries;
     int rval, status, success = AUTH_FAILURE;
@@ -281,7 +282,7 @@ verify_user(struct passwd *pw, char *prompt, int validated)
            p = prompt;
        } else {
            p = auth_getpass(prompt, def_passwd_timeout * 60,
-               SUDO_CONV_PROMPT_ECHO_OFF);
+               SUDO_CONV_PROMPT_ECHO_OFF, callback);
            if (p == NULL)
                break;
        }
@@ -291,7 +292,7 @@ verify_user(struct passwd *pw, char *prompt, int validated)
            if (IS_DISABLED(auth))
                continue;
 
-           success = auth->status = (auth->verify)(pw, p, auth);
+           success = auth->status = (auth->verify)(pw, p, auth, callback);
            if (success != AUTH_FAILURE)
                break;
        }
@@ -387,7 +388,8 @@ sudo_auth_end_session(struct passwd *pw)
 }
 
 char *
-auth_getpass(const char *prompt, int timeout, int type)
+auth_getpass(const char *prompt, int timeout, int type,
+    struct sudo_conv_callback *callback)
 {
     struct sudo_conv_message msg;
     struct sudo_conv_reply repl;
@@ -415,7 +417,7 @@ auth_getpass(const char *prompt, int timeout, int type)
     msg.timeout = def_passwd_timeout * 60;
     msg.msg = prompt;
     memset(&repl, 0, sizeof(repl));
-    sudo_conv(1, &msg, &repl);
+    sudo_conv(1, &msg, &repl, callback);
     /* XXX - check for ENOTTY? */
 
     /* Restore previous signal mask. */
index e2e48b4040bd466c84d838897c577bf608fa8818..1e12f86071d234c151e8dd976e7eb01ee74f081f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999-2005, 2007-2012 Todd C. Miller <Todd.Miller@courtesan.com>
+ * Copyright (c) 1999-2005, 2007-2015 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
@@ -30,7 +30,7 @@ typedef struct sudo_auth {
     void *data;                        /* method-specific data pointer */
     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 (*verify)(struct passwd *pw, char *p, struct sudo_auth *auth, struct sudo_conv_callback *callback);
     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);
@@ -47,47 +47,48 @@ typedef struct sudo_auth {
 #define IS_ONEANDONLY(x)       ((x)->flags & FLAG_ONEANDONLY)
 
 /* Like tgetpass() but uses conversation function */
-char *auth_getpass(const char *prompt, int timeout, int type);
+char *auth_getpass(const char *prompt, int timeout, int type,
+    struct sudo_conv_callback *callback);
 
 /* Pointer to conversation function to use with auth_getpass(). */
 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);
+int bsdauth_verify(struct passwd *pw, char *prompt, sudo_auth *auth, struct sudo_conv_callback *callback);
 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);
+int sudo_aix_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback);
 int sudo_aix_cleanup(struct passwd *pw, sudo_auth *auth);
 int sudo_fwtk_init(struct passwd *pw, sudo_auth *auth);
-int sudo_fwtk_verify(struct passwd *pw, char *prompt, sudo_auth *auth);
+int sudo_fwtk_verify(struct passwd *pw, char *prompt, sudo_auth *auth, struct sudo_conv_callback *callback);
 int sudo_fwtk_cleanup(struct passwd *pw, sudo_auth *auth);
 int sudo_pam_init(struct passwd *pw, sudo_auth *auth);
-int sudo_pam_verify(struct passwd *pw, char *prompt, sudo_auth *auth);
+int sudo_pam_verify(struct passwd *pw, char *prompt, sudo_auth *auth, struct sudo_conv_callback *callback);
 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_securid_init(struct passwd *pw, sudo_auth *auth);
 int sudo_securid_setup(struct passwd *pw, char **prompt, sudo_auth *auth);
-int sudo_securid_verify(struct passwd *pw, char *pass, sudo_auth *auth);
+int sudo_securid_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback);
 int sudo_sia_setup(struct passwd *pw, char **prompt, sudo_auth *auth);
-int sudo_sia_verify(struct passwd *pw, char *prompt, sudo_auth *auth);
+int sudo_sia_verify(struct passwd *pw, char *prompt, sudo_auth *auth, struct sudo_conv_callback *callback);
 int sudo_sia_cleanup(struct passwd *pw, sudo_auth *auth);
 
 /* Prototypes for normal methods */
-int sudo_afs_verify(struct passwd *pw, char *pass, sudo_auth *auth);
-int sudo_dce_verify(struct passwd *pw, char *pass, sudo_auth *auth);
+int sudo_afs_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback);
+int sudo_dce_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback);
 int sudo_krb5_init(struct passwd *pw, sudo_auth *auth);
 int sudo_krb5_setup(struct passwd *pw, char **prompt, sudo_auth *auth);
-int sudo_krb5_verify(struct passwd *pw, char *pass, sudo_auth *auth);
+int sudo_krb5_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback);
 int sudo_krb5_cleanup(struct passwd *pw, sudo_auth *auth);
 int sudo_passwd_init(struct passwd *pw, sudo_auth *auth);
-int sudo_passwd_verify(struct passwd *pw, char *pass, sudo_auth *auth);
+int sudo_passwd_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback);
 int sudo_passwd_cleanup(struct passwd *pw, sudo_auth *auth);
 int sudo_rfc1938_setup(struct passwd *pw, char **prompt, sudo_auth *auth);
-int sudo_rfc1938_verify(struct passwd *pw, char *pass, sudo_auth *auth);
+int sudo_rfc1938_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback);
 int sudo_secureware_init(struct passwd *pw, sudo_auth *auth);
-int sudo_secureware_verify(struct passwd *pw, char *pass, 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 */
index f29b103e3c67758ac9cd65350127e98a0c6f4b5e..6dbddabd16e7ca077d2f80428a8f61abf8f7a4d5 100644 (file)
@@ -96,7 +96,7 @@ check_user_interactive(int validated, int mode, struct passwd *auth_pw)
        if (prompt == NULL)
            goto done;
 
-       rval = verify_user(auth_pw, prompt, validated);
+       rval = verify_user(auth_pw, prompt, validated, NULL); /* XXX */
        if (rval == true && lectured) {
            if (set_lectured() == -1)
                rval = -1;
@@ -192,7 +192,7 @@ display_lecture(int status)
            buf[nread] = '\0';
            msg.msg_type = SUDO_CONV_ERROR_MSG;
            msg.msg = buf;
-           sudo_conv(1, &msg, &repl);
+           sudo_conv(1, &msg, &repl, NULL);
        }
        fclose(fp);
     } else {
@@ -203,7 +203,7 @@ display_lecture(int status)
            "    #1) Respect the privacy of others.\n"
            "    #2) Think before you type.\n"
            "    #3) With great power comes great responsibility.\n\n");
-       sudo_conv(1, &msg, &repl);
+       sudo_conv(1, &msg, &repl, NULL);
     }
     debug_return_bool(true);
 }
index 4f7f27aec71d213de54bdeec5ea9391f3b119f87..77e095f4258b2b90cfcaae66159e231533c3e29c 100644 (file)
@@ -261,7 +261,7 @@ output(const char *buf)
     msg.msg_type = SUDO_CONV_INFO_MSG;
     msg.msg = buf;
     memset(&repl, 0, sizeof(repl));
-    if (sudo_conv(1, &msg, &repl) == -1)
+    if (sudo_conv(1, &msg, &repl, NULL) == -1)
        debug_return_int(0);
     debug_return_int(strlen(buf));
 }
index 3100cd3f2a275f5b0e7f82612b4b44af90d12b2f..c76b9f489dcd20c53a30cc7d61a24a880d396954 100644 (file)
@@ -243,7 +243,7 @@ int set_lectured(void);
 
 /* sudo_auth.c */
 bool sudo_auth_needs_end_session(void);
-int verify_user(struct passwd *pw, char *prompt, int validated);
+int verify_user(struct passwd *pw, char *prompt, int validated, struct sudo_conv_callback *callback);
 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);
index cb752b88396700970c01844f785b96ceca344d05..df5d8f0ac7c6a06c29901adeb6316542001c27f2 100644 (file)
@@ -43,7 +43,7 @@ extern int tgetpass_flags; /* XXX */
  */
 int
 sudo_conversation(int num_msgs, const struct sudo_conv_message msgs[],
-    struct sudo_conv_reply replies[])
+    struct sudo_conv_reply replies[], struct sudo_conv_callback *callback)
 {
     struct sudo_conv_reply *repl;
     const struct sudo_conv_message *msg;
@@ -65,7 +65,7 @@ sudo_conversation(int num_msgs, const struct sudo_conv_message msgs[],
                if (ISSET(msg->msg_type, SUDO_CONV_PROMPT_ECHO_OK))
                    SET(flags, TGP_NOECHO_TRY);
                /* Read the password unless interrupted. */
-               pass = tgetpass(msg->msg, msg->timeout, flags);
+               pass = tgetpass(msg->msg, msg->timeout, flags, callback);
                if (pass == NULL)
                    goto err;
                if ((repl->reply = strdup(pass)) == NULL) {
@@ -103,6 +103,13 @@ err:
     return -1;
 }
 
+int
+sudo_conversation_1_7(int num_msgs, const struct sudo_conv_message msgs[],
+    struct sudo_conv_reply replies[])
+{
+    return sudo_conversation(num_msgs, msgs, replies, NULL);
+}
+
 int
 sudo_conversation_printf(int msg_type, const char *fmt, ...)
 {
index bfda114e1d1855ded25d79a23d96d7f8f465c424..060c4fba448c1e06fcecbb3038c66170ba66eb9e 100644 (file)
@@ -1187,7 +1187,7 @@ policy_open(struct plugin_container *plugin, struct sudo_settings *settings,
     case SUDO_API_MKVERSION(1, 0):
     case SUDO_API_MKVERSION(1, 1):
        rval = plugin->u.policy_1_0->open(plugin->u.io_1_0->version,
-           sudo_conversation, sudo_conversation_printf, plugin_settings,
+           sudo_conversation_1_7, sudo_conversation_printf, plugin_settings,
            user_info, user_env);
        break;
     default:
@@ -1346,12 +1346,12 @@ iolog_open(struct plugin_container *plugin, struct sudo_settings *settings,
     switch (plugin->u.generic->version) {
     case SUDO_API_MKVERSION(1, 0):
        rval = plugin->u.io_1_0->open(plugin->u.io_1_0->version,
-           sudo_conversation, sudo_conversation_printf, plugin_settings,
+           sudo_conversation_1_7, sudo_conversation_printf, plugin_settings,
            user_info, argc, argv, user_env);
        break;
     case SUDO_API_MKVERSION(1, 1):
        rval = plugin->u.io_1_1->open(plugin->u.io_1_1->version,
-           sudo_conversation, sudo_conversation_printf, plugin_settings,
+           sudo_conversation_1_7, sudo_conversation_printf, plugin_settings,
            user_info, command_info, argc, argv, user_env);
        break;
     default:
index 4536845c66a93c752818e5d9735a028fa84e4564..c1692d7be03a38317ae9602acf1216506c766f24 100644 (file)
@@ -183,7 +183,8 @@ struct timeval;
 void cleanup(int);
 
 /* tgetpass.c */
-char *tgetpass(const char *, int, int);
+char *tgetpass(const char *prompt, int timeout, int flags,
+    struct sudo_conv_callback *callback);
 
 /* exec.c */
 int pipe_nonblock(int fds[2]);
index ea2199826ac72a635936437c47046ededfd88563..3bc6273300fadd5423a6f9761577cf512788a066 100644 (file)
@@ -26,13 +26,16 @@ struct generic_plugin {
     /* the rest depends on the type... */
 };
 
+typedef int (*sudo_conv_1_7_t)(int num_msgs,
+    const struct sudo_conv_message msgs[], struct sudo_conv_reply replies[]);
+
 /*
  * Backwards-compatible structures for API bumps.
  */
 struct policy_plugin_1_0 {
     unsigned int type;
     unsigned int version;
-    int (*open)(unsigned int version, sudo_conv_t conversation,
+    int (*open)(unsigned int version, sudo_conv_1_7_t conversation,
        sudo_printf_t sudo_printf, char * const settings[],
        char * const user_info[], char * const user_env[]);
     void (*close)(int exit_status, int error); /* wait status or error */
@@ -49,7 +52,7 @@ struct policy_plugin_1_0 {
 struct io_plugin_1_0 {
     unsigned int type;
     unsigned int version;
-    int (*open)(unsigned int version, sudo_conv_t conversation,
+    int (*open)(unsigned int version, sudo_conv_1_7_t conversation,
         sudo_printf_t sudo_printf, char * const settings[],
         char * const user_info[], int argc, char * const argv[],
         char * const user_env[]);
@@ -64,7 +67,7 @@ struct io_plugin_1_0 {
 struct io_plugin_1_1 {
     unsigned int type;
     unsigned int version;
-    int (*open)(unsigned int version, sudo_conv_t conversation,
+    int (*open)(unsigned int version, sudo_conv_1_7_t conversation,
        sudo_printf_t sudo_printf, char * const settings[],
        char * const user_info[], char * const command_info[],
        int argc, char * const argv[], char * const user_env[]);
@@ -103,6 +106,8 @@ extern struct plugin_container policy_plugin;
 extern struct plugin_container_list io_plugins;
 
 int sudo_conversation(int num_msgs, const struct sudo_conv_message msgs[],
+    struct sudo_conv_reply replies[], struct sudo_conv_callback *callback);
+int sudo_conversation_1_7(int num_msgs, const struct sudo_conv_message msgs[],
     struct sudo_conv_reply replies[]);
 int sudo_conversation_printf(int msg_type, const char *fmt, ...);
 
index 4786996abc5fc4d03ec9bdf24da903e8f22c4efe..07be9ea98e8baf2a4fbcab1d1c7a0282576c4209 100644 (file)
@@ -55,7 +55,8 @@ static char *sudo_askpass(const char *, const char *);
  * Like getpass(3) but with timeout and echo flags.
  */
 char *
-tgetpass(const char *prompt, int timeout, int flags)
+tgetpass(const char *prompt, int timeout, int flags,
+    struct sudo_conv_callback *callback)
 {
     sigaction_t sa, savealrm, saveint, savehup, savequit, saveterm;
     sigaction_t savetstp, savettin, savettou, savepipe;
@@ -173,11 +174,21 @@ restore:
      */
     for (i = 0; i < NSIG; i++) {
        if (signo[i]) {
+           switch (i) {
+               case SIGTSTP:
+               case SIGTTIN:
+               case SIGTTOU:
+                   if (callback != NULL && callback->on_suspend != NULL)
+                       callback->on_suspend(i, callback->closure);
+                   break;
+           }
            kill(getpid(), i);
            switch (i) {
                case SIGTSTP:
                case SIGTTIN:
                case SIGTTOU:
+                   if (callback != NULL && callback->on_resume != NULL)
+                       callback->on_resume(i, callback->closure);
                    need_restart = 1;
                    break;
            }