core: Support GPGME_AUDITLOG_DIAG for gpgsm.
* src/engine-gpgsm.c (struct engine_gpgsm): Add fields diag_cb and diagnostics. (close_notify_handler): Close the diag fd on status fd close. Handle diag close. (gpgsm_cancel): Handle diag. (gpgsm_release): Free DIAGNOSTICS. (gpgsm_new): Support the diag feature. (start): Set a handler for the diag fd. (gpgsm_getauditlog): Support GPGME_AUDITLOG_DIAG. -- Co-authored-by: Andre Heinecke <aheinecke@gnupg.org> Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
c4cc47ee8f
commit
dd21ec997c
@ -82,6 +82,7 @@ struct engine_gpgsm
|
||||
iocb_data_t output_cb;
|
||||
|
||||
iocb_data_t message_cb;
|
||||
iocb_data_t diag_cb;
|
||||
|
||||
struct
|
||||
{
|
||||
@ -109,6 +110,9 @@ struct engine_gpgsm
|
||||
char request_origin[10];
|
||||
|
||||
struct gpgme_io_cbs io_cbs;
|
||||
|
||||
/* Memory data containing diagnostics (--logger-fd) of gpgsm */
|
||||
gpgme_data_t diagnostics;
|
||||
};
|
||||
|
||||
typedef struct engine_gpgsm *engine_gpgsm_t;
|
||||
@ -146,6 +150,13 @@ close_notify_handler (int fd, void *opaque)
|
||||
(*gpgsm->io_cbs.remove) (gpgsm->status_cb.tag);
|
||||
gpgsm->status_cb.fd = -1;
|
||||
gpgsm->status_cb.tag = NULL;
|
||||
/* Because the server keeps on running as long as the
|
||||
* gpgme_ctx_t is valid the diag fd will not receive a close and
|
||||
* thus the operation gets stuck trying to read the diag fd.
|
||||
* The status fd however is closed right after it received the
|
||||
* "OK" from the command. So we use this event to also close
|
||||
* the diag fd. */
|
||||
_gpgme_io_close (gpgsm->diag_cb.fd);
|
||||
}
|
||||
else if (gpgsm->input_cb.fd == fd)
|
||||
{
|
||||
@ -178,6 +189,13 @@ close_notify_handler (int fd, void *opaque)
|
||||
gpgsm->message_cb.fd = -1;
|
||||
gpgsm->message_cb.tag = NULL;
|
||||
}
|
||||
else if (gpgsm->diag_cb.fd == fd)
|
||||
{
|
||||
if (gpgsm->diag_cb.tag)
|
||||
(*gpgsm->io_cbs.remove) (gpgsm->diag_cb.tag);
|
||||
gpgsm->diag_cb.fd = -1;
|
||||
gpgsm->diag_cb.tag = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -213,6 +231,8 @@ gpgsm_cancel (void *engine)
|
||||
_gpgme_io_close (gpgsm->output_cb.fd);
|
||||
if (gpgsm->message_cb.fd != -1)
|
||||
_gpgme_io_close (gpgsm->message_cb.fd);
|
||||
if (gpgsm->diag_cb.fd != -1)
|
||||
_gpgme_io_close (gpgsm->diag_cb.fd);
|
||||
|
||||
if (gpgsm->assuan_ctx)
|
||||
{
|
||||
@ -234,6 +254,8 @@ gpgsm_release (void *engine)
|
||||
|
||||
gpgsm_cancel (engine);
|
||||
|
||||
gpgme_data_release (gpgsm->diagnostics);
|
||||
|
||||
free (gpgsm->colon.attic.line);
|
||||
free (gpgsm);
|
||||
}
|
||||
@ -246,17 +268,18 @@ gpgsm_new (void **engine, const char *file_name, const char *home_dir,
|
||||
gpgme_error_t err = 0;
|
||||
engine_gpgsm_t gpgsm;
|
||||
const char *pgmname;
|
||||
const char *argv[5];
|
||||
const char *argv[7];
|
||||
char *diag_fd_str = NULL;
|
||||
int argc;
|
||||
#if !USE_DESCRIPTOR_PASSING
|
||||
int fds[2];
|
||||
int child_fds[4];
|
||||
#endif
|
||||
int child_fds[5];
|
||||
int nchild_fds;
|
||||
char *dft_display = NULL;
|
||||
char dft_ttyname[64];
|
||||
char *env_tty = NULL;
|
||||
char *dft_ttytype = NULL;
|
||||
char *optstr;
|
||||
unsigned int connect_flags;
|
||||
|
||||
(void)version; /* Not yet used. */
|
||||
|
||||
@ -284,6 +307,11 @@ gpgsm_new (void **engine, const char *file_name, const char *home_dir,
|
||||
gpgsm->message_cb.tag = 0;
|
||||
gpgsm->message_cb.server_fd = -1;
|
||||
*gpgsm->message_cb.server_fd_str = 0;
|
||||
gpgsm->diag_cb.fd = -1;
|
||||
gpgsm->diag_cb.dir = 1;
|
||||
gpgsm->diag_cb.tag = 0;
|
||||
gpgsm->diag_cb.server_fd = -1;
|
||||
*gpgsm->diag_cb.server_fd_str = 0;
|
||||
|
||||
gpgsm->status.fnc = 0;
|
||||
gpgsm->colon.fnc = 0;
|
||||
@ -300,7 +328,20 @@ gpgsm_new (void **engine, const char *file_name, const char *home_dir,
|
||||
gpgsm->io_cbs.event = NULL;
|
||||
gpgsm->io_cbs.event_priv = NULL;
|
||||
|
||||
#if !USE_DESCRIPTOR_PASSING
|
||||
if (_gpgme_io_pipe (fds, 1) < 0)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
gpgsm->diag_cb.fd = fds[0];
|
||||
gpgsm->diag_cb.server_fd = fds[1];
|
||||
|
||||
#if USE_DESCRIPTOR_PASSING
|
||||
child_fds[0] = gpgsm->diag_cb.server_fd;
|
||||
child_fds[1] = -1;
|
||||
nchild_fds = 2;
|
||||
connect_flags = ASSUAN_PIPE_CONNECT_FDPASSING;
|
||||
#else /*!USE_DESCRIPTOR_PASSING*/
|
||||
if (_gpgme_io_pipe (fds, 0) < 0)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
@ -328,8 +369,11 @@ gpgsm_new (void **engine, const char *file_name, const char *home_dir,
|
||||
child_fds[0] = gpgsm->input_cb.server_fd;
|
||||
child_fds[1] = gpgsm->output_cb.server_fd;
|
||||
child_fds[2] = gpgsm->message_cb.server_fd;
|
||||
child_fds[3] = -1;
|
||||
#endif
|
||||
child_fds[3] = gpgsm->diag_cb.server_fd;
|
||||
child_fds[4] = -1;
|
||||
nchild_fds = 5;
|
||||
connect_flags = 0;
|
||||
#endif /*!USE_DESCRIPTOR_PASSING*/
|
||||
|
||||
pgmname = file_name ? file_name : _gpgme_get_default_gpgsm_name ();
|
||||
|
||||
@ -340,6 +384,18 @@ gpgsm_new (void **engine, const char *file_name, const char *home_dir,
|
||||
argv[argc++] = "--homedir";
|
||||
argv[argc++] = home_dir;
|
||||
}
|
||||
/* Set up diagnostics */
|
||||
err = gpgme_data_new (&gpgsm->diagnostics);
|
||||
if (err)
|
||||
goto leave;
|
||||
gpgsm->diag_cb.data = gpgsm->diagnostics;
|
||||
argv[argc++] = "--logger-fd";
|
||||
if (gpgrt_asprintf (&diag_fd_str, "%i", gpgsm->diag_cb.server_fd) == -1)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
argv[argc++] = diag_fd_str;
|
||||
argv[argc++] = "--server";
|
||||
argv[argc++] = NULL;
|
||||
|
||||
@ -350,26 +406,24 @@ gpgsm_new (void **engine, const char *file_name, const char *home_dir,
|
||||
goto leave;
|
||||
assuan_ctx_set_system_hooks (gpgsm->assuan_ctx, &_gpgme_assuan_system_hooks);
|
||||
|
||||
#if USE_DESCRIPTOR_PASSING
|
||||
err = assuan_pipe_connect (gpgsm->assuan_ctx, pgmname, argv,
|
||||
NULL, NULL, NULL, ASSUAN_PIPE_CONNECT_FDPASSING);
|
||||
#else
|
||||
{
|
||||
assuan_fd_t achild_fds[4];
|
||||
assuan_fd_t achild_fds[5];
|
||||
int i;
|
||||
|
||||
/* For now... */
|
||||
for (i = 0; i < 4; i++)
|
||||
for (i = 0; i < nchild_fds; i++)
|
||||
achild_fds[i] = (assuan_fd_t) child_fds[i];
|
||||
|
||||
err = assuan_pipe_connect (gpgsm->assuan_ctx, pgmname, argv,
|
||||
achild_fds, NULL, NULL, 0);
|
||||
achild_fds, NULL, NULL, connect_flags);
|
||||
|
||||
/* For now... */
|
||||
for (i = 0; i < 4; i++)
|
||||
/* FIXME: Check whether our Windows code still updates the list.*/
|
||||
for (i = 0; i < nchild_fds; i++)
|
||||
child_fds[i] = (int) achild_fds[i];
|
||||
}
|
||||
|
||||
|
||||
#if !USE_DESCRIPTOR_PASSING
|
||||
/* On Windows, handles are inserted in the spawned process with
|
||||
DuplicateHandle, and child_fds contains the server-local names
|
||||
for the inserted handles when assuan_pipe_connect returns. */
|
||||
@ -387,6 +441,8 @@ gpgsm_new (void **engine, const char *file_name, const char *home_dir,
|
||||
sizeof gpgsm->output_cb.server_fd_str, "%d", child_fds[1]);
|
||||
snprintf (gpgsm->message_cb.server_fd_str,
|
||||
sizeof gpgsm->message_cb.server_fd_str, "%d", child_fds[2]);
|
||||
snprintf (gpgsm->diag_cb.server_fd_str,
|
||||
sizeof gpgsm->diag_cb.server_fd_str, "%d", child_fds[3]);
|
||||
}
|
||||
#endif
|
||||
if (err)
|
||||
@ -493,12 +549,20 @@ gpgsm_new (void **engine, const char *file_name, const char *home_dir,
|
||||
|| _gpgme_io_set_close_notify (gpgsm->output_cb.fd,
|
||||
close_notify_handler, gpgsm)
|
||||
|| _gpgme_io_set_close_notify (gpgsm->message_cb.fd,
|
||||
close_notify_handler, gpgsm)
|
||||
|| _gpgme_io_set_close_notify (gpgsm->diag_cb.fd,
|
||||
close_notify_handler, gpgsm)))
|
||||
{
|
||||
err = gpg_error (GPG_ERR_GENERAL);
|
||||
goto leave;
|
||||
}
|
||||
#endif
|
||||
if (!err && _gpgme_io_set_close_notify (gpgsm->diag_cb.fd,
|
||||
close_notify_handler, gpgsm))
|
||||
{
|
||||
err = gpg_error (GPG_ERR_GENERAL);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
leave:
|
||||
/* Close the server ends of the pipes (because of this, we must use
|
||||
@ -511,13 +575,15 @@ gpgsm_new (void **engine, const char *file_name, const char *home_dir,
|
||||
_gpgme_io_close (gpgsm->output_cb.server_fd);
|
||||
if (gpgsm->message_cb.server_fd != -1)
|
||||
_gpgme_io_close (gpgsm->message_cb.server_fd);
|
||||
if (gpgsm->diag_cb.server_fd != -1)
|
||||
_gpgme_io_close (gpgsm->diag_cb.server_fd);
|
||||
#endif
|
||||
|
||||
if (err)
|
||||
gpgsm_release (gpgsm);
|
||||
else
|
||||
*engine = gpgsm;
|
||||
|
||||
free (diag_fd_str);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1139,6 +1205,8 @@ start (engine_gpgsm_t gpgsm, const char *command)
|
||||
err = add_io_cb (gpgsm, &gpgsm->output_cb, _gpgme_data_inbound_handler);
|
||||
if (!err && gpgsm->message_cb.fd != -1)
|
||||
err = add_io_cb (gpgsm, &gpgsm->message_cb, _gpgme_data_outbound_handler);
|
||||
if (!err && gpgsm->diag_cb.fd != -1)
|
||||
err = add_io_cb (gpgsm, &gpgsm->diag_cb, _gpgme_data_inbound_handler);
|
||||
|
||||
if (!err)
|
||||
err = assuan_write_line (gpgsm->assuan_ctx, command);
|
||||
@ -2069,12 +2137,40 @@ gpgsm_getauditlog (void *engine, gpgme_data_t output, unsigned int flags)
|
||||
engine_gpgsm_t gpgsm = engine;
|
||||
gpgme_error_t err = 0;
|
||||
|
||||
|
||||
if (!gpgsm || !output)
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
|
||||
if ((flags & GPGME_AUDITLOG_DIAG))
|
||||
if ((flags & GPGME_AUDITLOG_DIAG) && (flags & GPGME_AUDITLOG_HTML))
|
||||
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
||||
|
||||
if ((flags & GPGME_AUDITLOG_DIAG))
|
||||
{
|
||||
char buf[BUFFER_SIZE];
|
||||
int nread;
|
||||
int any_written = 0;
|
||||
gpgme_data_rewind (gpgsm->diagnostics);
|
||||
|
||||
while ((nread = gpgme_data_read (gpgsm->diagnostics,
|
||||
buf, BUFFER_SIZE)) > 0)
|
||||
{
|
||||
any_written = 1;
|
||||
if (gpgme_data_write (output, buf, nread) == -1)
|
||||
return gpg_error_from_syserror ();
|
||||
}
|
||||
if (!any_written)
|
||||
return gpg_error (GPG_ERR_NO_DATA);
|
||||
|
||||
if (nread == -1)
|
||||
return gpg_error_from_syserror ();
|
||||
|
||||
gpgme_data_rewind (output);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!gpgsm->assuan_ctx)
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
|
||||
#if USE_DESCRIPTOR_PASSING
|
||||
gpgsm->output_cb.data = output;
|
||||
err = gpgsm_set_fd (gpgsm, OUTPUT_FD, 0);
|
||||
|
Loading…
Reference in New Issue
Block a user