Add a struct sudo_conv_callback that contains on_suspend and on_resume

function pointer args plus a closure pointer and at it to the
conversation function.
This commit is contained in:
Todd C. Miller
2015-09-07 06:06:08 -06:00
parent af47293800
commit 98a15d9879
28 changed files with 247 additions and 78 deletions

View File

@@ -1297,9 +1297,26 @@ DDEESSCCRRIIPPTTIIOONN
char *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)
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, typedef int (*sudo_conv_t)(int num_msgs,
const struct sudo_conv_message 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, ...); typedef int (*sudo_printf_t)(int msg_type, const char *fmt, ...);
@@ -1309,13 +1326,21 @@ DDEESSCCRRIIPPTTIIOONN
To use the ccoonnvveerrssaattiioonn() function, the plugin must pass an array of To use the ccoonnvveerrssaattiioonn() 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 sudo_conv_reply structures. There must be a struct
sudo_conv_message and struct sudo_conv_reply for each message in the sudo_conv_message and struct sudo_conv_reply for each message in the
conversation. The plugin is responsible for freeing the reply buffer conversation. The struct sudo_conv_callback pointer, if not NULL,
located in each struct sudo_conv_reply, if it is not NULL. contains function pointers that are called when the ssuuddoo process is
SUDO_CONV_REPL_MAX represents the maximum length of the reply buffer (not suspended and/or resumed during conversation input. The functions are
including the trailing NUL character). In practical terms, this is the passed the signal that caused ssuuddoo to be suspended and the _c_l_o_s_u_r_e
longest password ssuuddoo will support. It is also useful as a maximum value pointer. This allows the plugin to release resources such as locks that
for the mmeemmsseett__ss() function when clearing passwords filled in by the should not be held indefinitely on suspend and reacquire them on resume.
conversation function. 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 ssuuddoo will
support. It is also useful as a maximum value for the mmeemmsseett__ss()
function when clearing passwords filled in by the conversation function.
The pprriinnttff()-style function uses the same underlying mechanism as the The pprriinnttff()-style function uses the same underlying mechanism as the
ccoonnvveerrssaattiioonn() function but only supports SUDO_CONV_INFO_MSG and ccoonnvveerrssaattiioonn() function but only supports SUDO_CONV_INFO_MSG and
@@ -1490,6 +1515,12 @@ PPLLUUGGIINN AAPPII CCHHAANNGGEELLOOGG
Version 1.8 (sudo 1.8.15) Version 1.8 (sudo 1.8.15)
The _s_u_d_o_e_d_i_t___f_o_l_l_o_w entry was added to the command_info list. The _s_u_d_o_e_d_i_t___f_o_l_l_o_w entry was added to the command_info list.
The sudo _c_o_n_v_e_r_s_a_t_i_o_n 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.
SSEEEE AALLSSOO SSEEEE AALLSSOO
sudo.conf(4), sudoers(4), sudo(1m) sudo.conf(4), sudoers(4), sudo(1m)
@@ -1519,4 +1550,4 @@ DDIISSCCLLAAIIMMEERR
file distributed with ssuuddoo or http://www.sudo.ws/license.html for file distributed with ssuuddoo or http://www.sudo.ws/license.html for
complete details. complete details.
Sudo 1.8.15 August 6, 2015 Sudo 1.8.15 Sudo 1.8.15 September 2, 2015 Sudo 1.8.15

View File

@@ -16,7 +16,7 @@
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" 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 .nh
.if n .ad l .if n .ad l
.SH "NAME" .SH "NAME"
@@ -2293,9 +2293,26 @@ struct sudo_conv_reply {
char *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, typedef int (*sudo_conv_t)(int num_msgs,
const struct sudo_conv_message 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, ...); typedef int (*sudo_printf_t)(int msg_type, const char *fmt, ...);
.RE .RE
@@ -2323,6 +2340,23 @@ and
\fRstruct sudo_conv_reply\fR \fRstruct sudo_conv_reply\fR
for for
each message in the conversation. 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 The plugin is responsible for freeing the reply buffer located in each
\fRstruct sudo_conv_reply\fR, \fRstruct sudo_conv_reply\fR,
if it is not if it is not
@@ -2662,6 +2696,17 @@ The
entry was added to the entry was added to the
\fRcommand_info\fR \fRcommand_info\fR
list. 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" .SH "SEE ALSO"
sudo.conf(@mansectform@), sudo.conf(@mansectform@),
sudoers(@mansectform@), sudoers(@mansectform@),

View File

@@ -14,7 +14,7 @@
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\" .\"
.Dd August 6, 2015 .Dd September 2, 2015
.Dt SUDO_PLUGIN @mansectform@ .Dt SUDO_PLUGIN @mansectform@
.Os Sudo @PACKAGE_VERSION@ .Os Sudo @PACKAGE_VERSION@
.Sh NAME .Sh NAME
@@ -1999,9 +1999,26 @@ struct sudo_conv_reply {
char *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, typedef int (*sudo_conv_t)(int num_msgs,
const struct sudo_conv_message 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, ...); typedef int (*sudo_printf_t)(int msg_type, const char *fmt, ...);
.Ed .Ed
@@ -2028,6 +2045,23 @@ and
.Li struct sudo_conv_reply .Li struct sudo_conv_reply
for for
each message in the conversation. 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 The plugin is responsible for freeing the reply buffer located in each
.Li struct sudo_conv_reply , .Li struct sudo_conv_reply ,
if it is not if it is not
@@ -2329,6 +2363,17 @@ The
entry was added to the entry was added to the
.Li command_info .Li command_info
list. 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 .El
.Sh SEE ALSO .Sh SEE ALSO
.Xr sudo.conf @mansectform@ , .Xr sudo.conf @mansectform@ ,

View File

@@ -121,6 +121,7 @@ typedef void (*sudo_fatal_callback_t)(void);
struct sudo_conv_message; struct sudo_conv_message;
struct sudo_conv_reply; 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_deregister_v1(sudo_fatal_callback_t func);
__dso_public int sudo_fatal_callback_register_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_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_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_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_deregister(_a) sudo_fatal_callback_deregister_v1((_a))
#define sudo_fatal_callback_register(_a) sudo_fatal_callback_register_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_vwarn_nodebug(_a, _b) sudo_vwarn_nodebug_v1((_a), (_b))
#define sudo_vwarnx_nodebug(_a, _b) sudo_vwarnx_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)
#define sudo_warn_set_conversation(_a) sudo_warn_set_conversation_v1(_a)
#ifdef DEFAULT_TEXT_DOMAIN #ifdef DEFAULT_TEXT_DOMAIN
# define sudo_warn_gettext(_a) sudo_warn_gettext_v1(DEFAULT_TEXT_DOMAIN, (_a)) # define sudo_warn_gettext(_a) sudo_warn_gettext_v1(DEFAULT_TEXT_DOMAIN, (_a))

View File

@@ -61,8 +61,27 @@ struct sudo_conv_reply {
char *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[], 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, ...); typedef int (*sudo_printf_t)(int msg_type, const char *fmt, ...);
/* /*

View 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_type = SUDO_CONV_ERROR_MSG;
msgs[nmsgs++].msg = "\n"; msgs[nmsgs++].msg = "\n";
sudo_warn_conversation(nmsgs, msgs, NULL); sudo_warn_conversation(nmsgs, msgs, NULL, NULL);
if (buf != static_buf) if (buf != static_buf)
free(buf); free(buf);
} else { } else {

View File

@@ -42,7 +42,7 @@
#include "sudo_auth.h" #include "sudo_auth.h"
int 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_encryptionKey afs_key;
struct ktc_token afs_token; struct ktc_token afs_token;

View File

@@ -128,7 +128,7 @@ sudo_aix_init(struct passwd *pw, sudo_auth *auth)
} }
int 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; char *pass, *message = NULL;
int result = 1, reenter = 0; int result = 1, reenter = 0;
@@ -137,7 +137,7 @@ sudo_aix_verify(struct passwd *pw, char *prompt, sudo_auth *auth)
do { do {
pass = auth_getpass(prompt, def_passwd_timeout * 60, pass = auth_getpass(prompt, def_passwd_timeout * 60,
SUDO_CONV_PROMPT_ECHO_OFF); SUDO_CONV_PROMPT_ECHO_OFF, callback);
if (pass == NULL) if (pass == NULL)
break; break;
free(message); 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_type = SUDO_CONV_ERROR_MSG;
msg.msg = message; msg.msg = message;
memset(&repl, 0, sizeof(repl)); memset(&repl, 0, sizeof(repl));
sudo_conv(1, &msg, &repl); sudo_conv(1, &msg, &repl, NULL);
} }
rval = pass ? AUTH_FAILURE : AUTH_INTR; rval = pass ? AUTH_FAILURE : AUTH_INTR;
} }

View File

@@ -98,7 +98,7 @@ bsdauth_init(struct passwd *pw, sudo_auth *auth)
} }
int 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 *pass;
char *s; char *s;
@@ -121,9 +121,9 @@ bsdauth_verify(struct passwd *pw, char *prompt, sudo_auth *auth)
* S/Key. * S/Key.
*/ */
if ((s = auth_challenge(as)) == NULL) { 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 { } 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 (pass && *pass == '\0') {
if ((prompt = strrchr(s, '\n'))) if ((prompt = strrchr(s, '\n')))
prompt++; prompt++;
@@ -142,7 +142,7 @@ bsdauth_verify(struct passwd *pw, char *prompt, sudo_auth *auth)
debug_return_int(AUTH_FATAL); debug_return_int(AUTH_FATAL);
} }
pass = auth_getpass(prompt, def_passwd_timeout * 60, pass = auth_getpass(prompt, def_passwd_timeout * 60,
SUDO_CONV_PROMPT_ECHO_ON); SUDO_CONV_PROMPT_ECHO_ON, callback);
free(s); free(s);
} }
} }

View File

@@ -59,7 +59,7 @@
static int check_dce_status(error_status_t, char *); static int check_dce_status(error_status_t, char *);
int 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; struct passwd temp_pw;
sec_passwd_rec_t password_rec; sec_passwd_rec_t password_rec;

View File

@@ -72,7 +72,7 @@ sudo_fwtk_init(struct passwd *pw, sudo_auth *auth)
} }
int 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 *pass; /* Password from the user */
char buf[SUDO_CONV_REPL_MAX + 12]; /* General prupose buffer */ char buf[SUDO_CONV_REPL_MAX + 12]; /* General prupose buffer */
@@ -91,17 +91,17 @@ restart:
/* Get the password/response from the user. */ /* Get the password/response from the user. */
if (strncmp(resp, "challenge ", 10) == 0) { if (strncmp(resp, "challenge ", 10) == 0) {
(void) snprintf(buf, sizeof(buf), "%s\nResponse: ", &resp[10]); (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') { if (pass && *pass == '\0') {
pass = auth_getpass("Response [echo on]: ", 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) { } else if (strncmp(resp, "chalnecho ", 10) == 0) {
pass = auth_getpass(&resp[10], def_passwd_timeout * 60, 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) { } else if (strncmp(resp, "password", 8) == 0) {
pass = auth_getpass(prompt, def_passwd_timeout * 60, 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) { } else if (strncmp(resp, "display ", 8) == 0) {
fprintf(stderr, "%s\n", &resp[8]); fprintf(stderr, "%s\n", &resp[8]);
strlcpy(buf, "response dummy", sizeof(buf)); strlcpy(buf, "response dummy", sizeof(buf));

View File

@@ -180,7 +180,7 @@ done:
#ifdef HAVE_KRB5_VERIFY_USER #ifdef HAVE_KRB5_VERIFY_USER
int 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_context sudo_context;
krb5_principal princ; krb5_principal princ;

View File

@@ -71,7 +71,8 @@
static int converse(int, PAM_CONST struct pam_message **, static int converse(int, PAM_CONST struct pam_message **,
struct pam_response **, void *); 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 char *def_prompt = PASSPROMPT;
static bool getpass_error; static bool getpass_error;
static pam_handle_t *pamh; static pam_handle_t *pamh;
@@ -137,7 +138,7 @@ sudo_pam_init(struct passwd *pw, sudo_auth *auth)
} }
int 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; const char *s;
int *pam_status = (int *) auth->data; 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 */ def_prompt = prompt; /* for converse */
getpass_error = false; /* set by converse if user presses ^C */ 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_SILENT prevents the authentication service from generating output. */
*pam_status = pam_authenticate(pamh, PAM_SILENT); *pam_status = pam_authenticate(pamh, PAM_SILENT);
@@ -375,7 +377,7 @@ sudo_pam_end_session(struct passwd *pw, sudo_auth *auth)
*/ */
static int static int
converse(int num_msg, PAM_CONST struct pam_message **msg, 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; struct pam_response *pr;
PAM_CONST struct pam_message *pm; PAM_CONST struct pam_message *pm;
@@ -427,7 +429,7 @@ converse(int num_msg, PAM_CONST struct pam_message **msg,
prompt = pm->msg; prompt = pm->msg;
} }
/* Read the password unless interrupted. */ /* 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) { if (pass == NULL) {
/* Error (or ^C) reading password, don't try again. */ /* Error (or ^C) reading password, don't try again. */
getpass_error = true; getpass_error = true;

View File

@@ -54,7 +54,7 @@ sudo_passwd_init(struct passwd *pw, sudo_auth *auth)
} }
int 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 sav, *epass;
char *pw_epasswd = auth->data; char *pw_epasswd = auth->data;

View File

@@ -124,7 +124,7 @@ sudo_rfc1938_setup(struct passwd *pw, char **promptp, sudo_auth *auth)
} }
int 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) debug_decl(sudo_rfc1938_verify, SUDOERS_DEBUG_AUTH)

View File

@@ -65,7 +65,7 @@ sudo_secureware_init(struct passwd *pw, sudo_auth *auth)
} }
int 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 *pw_epasswd = auth->data;
char *epass = NULL; char *epass = NULL;

View File

@@ -139,14 +139,14 @@ sudo_securid_setup(struct passwd *pw, char **promptp, sudo_auth *auth)
* incorrect authentication, fatal on errors * incorrect authentication, fatal on errors
*/ */
int 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; SDI_HANDLE *sd = (SDI_HANDLE *) auth->data;
int rval; int rval;
debug_decl(sudo_securid_verify, SUDOERS_DEBUG_AUTH) debug_decl(sudo_securid_verify, SUDOERS_DEBUG_AUTH)
pass = auth_getpass("Enter your PASSCODE: ", 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 */ /* Have ACE verify password */
switch (SD_Check(*sd, pass, pw->pw_name)) { 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\ !!! ATTENTION !!!\n\
Wait for the token code to change, \n\ Wait for the token code to change, \n\
then enter the new token code.\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) { if (SD_Next(*sd, pass) == ACM_OK) {
rval = AUTH_SUCCESS; rval = AUTH_SUCCESS;

View File

@@ -126,7 +126,7 @@ sudo_sia_setup(struct passwd *pw, char **promptp, sudo_auth *auth)
} }
int 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; SIAENTITY *siah = (SIAENTITY *) auth->data;
debug_decl(sudo_sia_verify, SUDOERS_DEBUG_AUTH) debug_decl(sudo_sia_verify, SUDOERS_DEBUG_AUTH)

View File

@@ -209,7 +209,8 @@ user_interrupted(void)
* Returns true if verified, false if not or -1 on error. * Returns true if verified, false if not or -1 on error.
*/ */
int 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; unsigned int ntries;
int rval, status, success = AUTH_FAILURE; int rval, status, success = AUTH_FAILURE;
@@ -281,7 +282,7 @@ verify_user(struct passwd *pw, char *prompt, int validated)
p = prompt; p = prompt;
} else { } else {
p = auth_getpass(prompt, def_passwd_timeout * 60, p = auth_getpass(prompt, def_passwd_timeout * 60,
SUDO_CONV_PROMPT_ECHO_OFF); SUDO_CONV_PROMPT_ECHO_OFF, callback);
if (p == NULL) if (p == NULL)
break; break;
} }
@@ -291,7 +292,7 @@ verify_user(struct passwd *pw, char *prompt, int validated)
if (IS_DISABLED(auth)) if (IS_DISABLED(auth))
continue; continue;
success = auth->status = (auth->verify)(pw, p, auth); success = auth->status = (auth->verify)(pw, p, auth, callback);
if (success != AUTH_FAILURE) if (success != AUTH_FAILURE)
break; break;
} }
@@ -387,7 +388,8 @@ sudo_auth_end_session(struct passwd *pw)
} }
char * 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_message msg;
struct sudo_conv_reply repl; 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.timeout = def_passwd_timeout * 60;
msg.msg = prompt; msg.msg = prompt;
memset(&repl, 0, sizeof(repl)); memset(&repl, 0, sizeof(repl));
sudo_conv(1, &msg, &repl); sudo_conv(1, &msg, &repl, callback);
/* XXX - check for ENOTTY? */ /* XXX - check for ENOTTY? */
/* Restore previous signal mask. */ /* Restore previous signal mask. */

View 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 * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * 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 */ void *data; /* method-specific data pointer */
int (*init)(struct passwd *pw, struct sudo_auth *auth); int (*init)(struct passwd *pw, struct sudo_auth *auth);
int (*setup)(struct passwd *pw, char **prompt, struct sudo_auth *auth); int (*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 (*cleanup)(struct passwd *pw, struct sudo_auth *auth);
int (*begin_session)(struct passwd *pw, char **user_env[], 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); 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) #define IS_ONEANDONLY(x) ((x)->flags & FLAG_ONEANDONLY)
/* Like tgetpass() but uses conversation function */ /* 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(). */ /* Pointer to conversation function to use with auth_getpass(). */
extern sudo_conv_t sudo_conv; extern sudo_conv_t sudo_conv;
/* Prototypes for standalone methods */ /* Prototypes for standalone methods */
int bsdauth_init(struct passwd *pw, sudo_auth *auth); int bsdauth_init(struct passwd *pw, sudo_auth *auth);
int bsdauth_verify(struct passwd *pw, char *prompt, sudo_auth *auth); int bsdauth_verify(struct passwd *pw, char *prompt, sudo_auth *auth, struct sudo_conv_callback *callback);
int bsdauth_cleanup(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_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_aix_cleanup(struct passwd *pw, sudo_auth *auth);
int sudo_fwtk_init(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_fwtk_cleanup(struct passwd *pw, sudo_auth *auth);
int sudo_pam_init(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_cleanup(struct passwd *pw, sudo_auth *auth);
int sudo_pam_begin_session(struct passwd *pw, char **user_env[], 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_pam_end_session(struct passwd *pw, sudo_auth *auth);
int sudo_securid_init(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_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_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); int sudo_sia_cleanup(struct passwd *pw, sudo_auth *auth);
/* Prototypes for normal methods */ /* Prototypes for normal methods */
int sudo_afs_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); 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_init(struct passwd *pw, sudo_auth *auth);
int sudo_krb5_setup(struct passwd *pw, char **prompt, 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_krb5_cleanup(struct passwd *pw, sudo_auth *auth);
int sudo_passwd_init(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_passwd_cleanup(struct passwd *pw, sudo_auth *auth);
int sudo_rfc1938_setup(struct passwd *pw, char **prompt, 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_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); int sudo_secureware_cleanup(struct passwd *pw, sudo_auth *auth);
/* Fields: name, flags, init, setup, verify, cleanup, begin_sess, end_sess */ /* Fields: name, flags, init, setup, verify, cleanup, begin_sess, end_sess */

View File

@@ -96,7 +96,7 @@ check_user_interactive(int validated, int mode, struct passwd *auth_pw)
if (prompt == NULL) if (prompt == NULL)
goto done; goto done;
rval = verify_user(auth_pw, prompt, validated); rval = verify_user(auth_pw, prompt, validated, NULL); /* XXX */
if (rval == true && lectured) { if (rval == true && lectured) {
if (set_lectured() == -1) if (set_lectured() == -1)
rval = -1; rval = -1;
@@ -192,7 +192,7 @@ display_lecture(int status)
buf[nread] = '\0'; buf[nread] = '\0';
msg.msg_type = SUDO_CONV_ERROR_MSG; msg.msg_type = SUDO_CONV_ERROR_MSG;
msg.msg = buf; msg.msg = buf;
sudo_conv(1, &msg, &repl); sudo_conv(1, &msg, &repl, NULL);
} }
fclose(fp); fclose(fp);
} else { } else {
@@ -203,7 +203,7 @@ display_lecture(int status)
" #1) Respect the privacy of others.\n" " #1) Respect the privacy of others.\n"
" #2) Think before you type.\n" " #2) Think before you type.\n"
" #3) With great power comes great responsibility.\n\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); debug_return_bool(true);
} }

View File

@@ -261,7 +261,7 @@ output(const char *buf)
msg.msg_type = SUDO_CONV_INFO_MSG; msg.msg_type = SUDO_CONV_INFO_MSG;
msg.msg = buf; msg.msg = buf;
memset(&repl, 0, sizeof(repl)); 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(0);
debug_return_int(strlen(buf)); debug_return_int(strlen(buf));
} }

View File

@@ -243,7 +243,7 @@ int set_lectured(void);
/* sudo_auth.c */ /* sudo_auth.c */
bool sudo_auth_needs_end_session(void); 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_begin_session(struct passwd *pw, char **user_env[]);
int sudo_auth_end_session(struct passwd *pw); int sudo_auth_end_session(struct passwd *pw);
int sudo_auth_init(struct passwd *pw); int sudo_auth_init(struct passwd *pw);

View File

@@ -43,7 +43,7 @@ extern int tgetpass_flags; /* XXX */
*/ */
int int
sudo_conversation(int num_msgs, const struct sudo_conv_message msgs[], 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; struct sudo_conv_reply *repl;
const struct sudo_conv_message *msg; 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)) if (ISSET(msg->msg_type, SUDO_CONV_PROMPT_ECHO_OK))
SET(flags, TGP_NOECHO_TRY); SET(flags, TGP_NOECHO_TRY);
/* Read the password unless interrupted. */ /* Read the password unless interrupted. */
pass = tgetpass(msg->msg, msg->timeout, flags); pass = tgetpass(msg->msg, msg->timeout, flags, callback);
if (pass == NULL) if (pass == NULL)
goto err; goto err;
if ((repl->reply = strdup(pass)) == NULL) { if ((repl->reply = strdup(pass)) == NULL) {
@@ -103,6 +103,13 @@ err:
return -1; 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 int
sudo_conversation_printf(int msg_type, const char *fmt, ...) sudo_conversation_printf(int msg_type, const char *fmt, ...)
{ {

View 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, 0):
case SUDO_API_MKVERSION(1, 1): case SUDO_API_MKVERSION(1, 1):
rval = plugin->u.policy_1_0->open(plugin->u.io_1_0->version, 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); user_info, user_env);
break; break;
default: default:
@@ -1346,12 +1346,12 @@ iolog_open(struct plugin_container *plugin, struct sudo_settings *settings,
switch (plugin->u.generic->version) { switch (plugin->u.generic->version) {
case SUDO_API_MKVERSION(1, 0): case SUDO_API_MKVERSION(1, 0):
rval = plugin->u.io_1_0->open(plugin->u.io_1_0->version, 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); user_info, argc, argv, user_env);
break; break;
case SUDO_API_MKVERSION(1, 1): case SUDO_API_MKVERSION(1, 1):
rval = plugin->u.io_1_1->open(plugin->u.io_1_1->version, 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); user_info, command_info, argc, argv, user_env);
break; break;
default: default:

View File

@@ -183,7 +183,8 @@ struct timeval;
void cleanup(int); void cleanup(int);
/* tgetpass.c */ /* tgetpass.c */
char *tgetpass(const char *, int, int); char *tgetpass(const char *prompt, int timeout, int flags,
struct sudo_conv_callback *callback);
/* exec.c */ /* exec.c */
int pipe_nonblock(int fds[2]); int pipe_nonblock(int fds[2]);

View File

@@ -26,13 +26,16 @@ struct generic_plugin {
/* the rest depends on the type... */ /* 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. * Backwards-compatible structures for API bumps.
*/ */
struct policy_plugin_1_0 { struct policy_plugin_1_0 {
unsigned int type; unsigned int type;
unsigned int version; 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[], sudo_printf_t sudo_printf, char * const settings[],
char * const user_info[], char * const user_env[]); char * const user_info[], char * const user_env[]);
void (*close)(int exit_status, int error); /* wait status or error */ 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 { struct io_plugin_1_0 {
unsigned int type; unsigned int type;
unsigned int version; 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[], sudo_printf_t sudo_printf, char * const settings[],
char * const user_info[], int argc, char * const argv[], char * const user_info[], int argc, char * const argv[],
char * const user_env[]); char * const user_env[]);
@@ -64,7 +67,7 @@ struct io_plugin_1_0 {
struct io_plugin_1_1 { struct io_plugin_1_1 {
unsigned int type; unsigned int type;
unsigned int version; 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[], sudo_printf_t sudo_printf, char * const settings[],
char * const user_info[], char * const command_info[], char * const user_info[], char * const command_info[],
int argc, char * const argv[], char * const user_env[]); 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; extern struct plugin_container_list io_plugins;
int sudo_conversation(int num_msgs, const struct sudo_conv_message msgs[], 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[]); struct sudo_conv_reply replies[]);
int sudo_conversation_printf(int msg_type, const char *fmt, ...); int sudo_conversation_printf(int msg_type, const char *fmt, ...);

View File

@@ -55,7 +55,8 @@ static char *sudo_askpass(const char *, const char *);
* Like getpass(3) but with timeout and echo flags. * Like getpass(3) but with timeout and echo flags.
*/ */
char * 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 sa, savealrm, saveint, savehup, savequit, saveterm;
sigaction_t savetstp, savettin, savettou, savepipe; sigaction_t savetstp, savettin, savettou, savepipe;
@@ -173,11 +174,21 @@ restore:
*/ */
for (i = 0; i < NSIG; i++) { for (i = 0; i < NSIG; i++) {
if (signo[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); kill(getpid(), i);
switch (i) { switch (i) {
case SIGTSTP: case SIGTSTP:
case SIGTTIN: case SIGTTIN:
case SIGTTOU: case SIGTTOU:
if (callback != NULL && callback->on_resume != NULL)
callback->on_resume(i, callback->closure);
need_restart = 1; need_restart = 1;
break; break;
} }