From 2cd8bae23d7382588cf096df3eed83e02331a2bf Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 1 Sep 2020 20:43:57 +0200 Subject: [PATCH] Use only one copy of the warn_server_mismatch function. * common/asshelp.c (warn_server_version_mismatch): New. Actually a slightly modified version of warn_version_mismatch found in other modules. * common/status.c (gnupg_status_strings): New. * g10/cpr.c (write_status_strings2): New. * g10/call-agent.c (warn_version_mismatch): Use the new unified warn_server_version_mismatch function. * g10/call-dirmngr.c (warn_version_mismatch): Ditto. * g10/call-keyboxd.c (warn_version_mismatch): Ditto. * sm/call-agent.c (warn_version_mismatch): Ditto. * sm/call-dirmngr.c (warn_version_mismatch): Ditto. * tools/card-call-scd.c (warn_version_mismatch): Ditto. Signed-off-by: Werner Koch --- common/asshelp.c | 54 +++++++++++++++++++++++++++++++++++++++++++ common/asshelp.h | 10 ++++++++ common/asshelp2.c | 2 +- common/status.c | 41 ++++++++++++++++++++++++++++++++ common/status.h | 4 ++++ g10/call-agent.c | 38 +++--------------------------- g10/call-dirmngr.c | 37 +++-------------------------- g10/call-keyboxd.c | 37 +++-------------------------- g10/cpr.c | 44 +++++++++++++++++++++++++++++++++++ g10/main.h | 2 ++ sm/call-agent.c | 37 +++-------------------------- sm/call-dirmngr.c | 36 +++-------------------------- tools/card-call-scd.c | 38 +++--------------------------- 13 files changed, 174 insertions(+), 206 deletions(-) diff --git a/common/asshelp.c b/common/asshelp.c index fe49aa83a..0d903fd5f 100644 --- a/common/asshelp.c +++ b/common/asshelp.c @@ -696,3 +696,57 @@ get_assuan_server_version (assuan_context_t ctx, int mode, char **r_version) } return err; } + + +/* Print a warning if the server's version number is less than our + * version number. Returns an error code on a connection problem. + * CTX is the Assuan context, SERVERNAME is the name of teh server, + * STATUS_FUNC and STATUS_FUNC_DATA is a callback to emit status + * messages. If PRINT_HINTS is set additional hints are printed. For + * MODE see get_assuan_server_version. */ +gpg_error_t +warn_server_version_mismatch (assuan_context_t ctx, + const char *servername, int mode, + gpg_error_t (*status_func)(ctrl_t ctrl, + int status_no, + ...), + void *status_func_ctrl, + int print_hints) +{ + gpg_error_t err; + char *serverversion; + const char *myversion = gpgrt_strusage (13); + + err = get_assuan_server_version (ctx, mode, &serverversion); + if (err) + log_log (gpg_err_code (err) == GPG_ERR_NOT_SUPPORTED? + GPGRT_LOGLVL_INFO : GPGRT_LOGLVL_ERROR, + _("error getting version from '%s': %s\n"), + servername, gpg_strerror (err)); + else if (compare_version_strings (serverversion, myversion) < 0) + { + char *warn; + + warn = xtryasprintf (_("server '%s' is older than us (%s < %s)"), + servername, serverversion, myversion); + if (!warn) + err = gpg_error_from_syserror (); + else + { + log_info (_("WARNING: %s\n"), warn); + if (print_hints) + { + log_info (_("Note: Outdated servers may lack important" + " security fixes.\n")); + log_info (_("Note: Use the command \"%s\" to restart them.\n"), + "gpgconf --kill all"); + } + if (status_func) + status_func (status_func_ctrl, STATUS_WARNING, + "server_version_mismatch 0", warn, NULL); + xfree (warn); + } + } + xfree (serverversion); + return err; +} diff --git a/common/asshelp.h b/common/asshelp.h index b2f4e538f..e7e43bd1b 100644 --- a/common/asshelp.h +++ b/common/asshelp.h @@ -89,6 +89,16 @@ start_new_dirmngr (assuan_context_t *r_ctx, gpg_error_t get_assuan_server_version (assuan_context_t ctx, int mode, char **r_version); +/* Print a server version mismatch warning. */ +gpg_error_t warn_server_version_mismatch (assuan_context_t ctx, + const char *servername, int mode, + gpg_error_t (*status_fnc) + (ctrl_t ctrl, + int status_id, + ...), + void *status_func_ctrl, + int print_hints); + /*-- asshelp2.c --*/ diff --git a/common/asshelp2.c b/common/asshelp2.c index a62189df9..4aad8a242 100644 --- a/common/asshelp2.c +++ b/common/asshelp2.c @@ -173,7 +173,7 @@ status_printf (ctrl_t ctrl, const char *keyword, const char *format, ...) } -/* Same as sytus_printf but takes a status number instead of a +/* Same as status_printf but takes a status number instead of a * keyword. */ gpg_error_t status_no_printf (ctrl_t ctrl, int no, const char *format, ...) diff --git a/common/status.c b/common/status.c index 269ffea5d..b752c12c6 100644 --- a/common/status.c +++ b/common/status.c @@ -105,6 +105,47 @@ gnupg_status_printf (int no, const char *format, ...) } +/* Write a status line with code NO followed by the remaining + * arguments which must be a list of strings terminated by a NULL. + * Embedded CR and LFs in the strings are C-style escaped. All + * strings are printed with a space as delimiter. */ +gpg_error_t +gnupg_status_strings (ctrl_t dummy, int no, ...) +{ + va_list arg_ptr; + const char *s; + + (void)dummy; + + if (!statusfp) + return 0; /* Not enabled. */ + + va_start (arg_ptr, no); + + es_fputs ("[GNUPG:] ", statusfp); + es_fputs (get_status_string (no), statusfp); + while ((s = va_arg (arg_ptr, const char*))) + { + if (*s) + es_putc (' ', statusfp); + for (; *s; s++) + { + if (*s == '\n') + es_fputs ("\\n", statusfp); + else if (*s == '\r') + es_fputs ("\\r", statusfp); + else + es_fputc (*(const byte *)s, statusfp); + } + } + es_putc ('\n', statusfp); + es_fflush (statusfp); + + va_end (arg_ptr); + return 0; +} + + const char * get_inv_recpsgnr_code (gpg_error_t err) { diff --git a/common/status.h b/common/status.h index aeab54202..477b29eaa 100644 --- a/common/status.h +++ b/common/status.h @@ -30,6 +30,8 @@ #ifndef GNUPG_COMMON_STATUS_H #define GNUPG_COMMON_STATUS_H +#include "../common/fwddecl.h" + enum { STATUS_ENTER, @@ -166,6 +168,8 @@ const char *get_status_string (int code); void gnupg_set_status_fd (int fd); void gnupg_status_printf (int no, const char *format, ...) GPGRT_ATTR_PRINTF(2,3); +gpg_error_t gnupg_status_strings (ctrl_t dummy, int no, + ...) GPGRT_ATTR_SENTINEL(0); const char *get_inv_recpsgnr_code (gpg_error_t err); diff --git a/g10/call-agent.c b/g10/call-agent.c index 806475de9..4e3bdf9e4 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -220,41 +220,9 @@ default_inq_cb (void *opaque, const char *line) static gpg_error_t warn_version_mismatch (assuan_context_t ctx, const char *servername, int mode) { - gpg_error_t err; - char *serverversion; - const char *myversion = gpgrt_strusage (13); - - err = get_assuan_server_version (ctx, mode, &serverversion); - if (err) - log_log (gpg_err_code (err) == GPG_ERR_NOT_SUPPORTED? - GPGRT_LOGLVL_INFO : GPGRT_LOGLVL_ERROR, - _("error getting version from '%s': %s\n"), - servername, gpg_strerror (err)); - else if (compare_version_strings (serverversion, myversion) < 0) - { - char *warn; - - warn = xtryasprintf (_("server '%s' is older than us (%s < %s)"), - servername, serverversion, myversion); - if (!warn) - err = gpg_error_from_syserror (); - else - { - log_info (_("WARNING: %s\n"), warn); - if (!opt.quiet) - { - log_info (_("Note: Outdated servers may lack important" - " security fixes.\n")); - log_info (_("Note: Use the command \"%s\" to restart them.\n"), - "gpgconf --kill all"); - } - write_status_strings (STATUS_WARNING, "server_version_mismatch 0", - " ", warn, NULL); - xfree (warn); - } - } - xfree (serverversion); - return err; + return warn_server_version_mismatch (ctx, servername, mode, + write_status_strings2, NULL, + !opt.quiet); } diff --git a/g10/call-dirmngr.c b/g10/call-dirmngr.c index 02d1edb9f..1282ae192 100644 --- a/g10/call-dirmngr.c +++ b/g10/call-dirmngr.c @@ -144,40 +144,9 @@ gpg_dirmngr_deinit_session_data (ctrl_t ctrl) static gpg_error_t warn_version_mismatch (assuan_context_t ctx, const char *servername) { - gpg_error_t err; - char *serverversion; - const char *myversion = gpgrt_strusage (13); - - err = get_assuan_server_version (ctx, 0, &serverversion); - if (err) - log_error (_("error getting version from '%s': %s\n"), - servername, gpg_strerror (err)); - else if (compare_version_strings (serverversion, myversion) < 0) - { - char *warn; - - warn = xtryasprintf (_("server '%s' is older than us (%s < %s)"), - servername, serverversion, myversion); - if (!warn) - err = gpg_error_from_syserror (); - else - { - log_info (_("WARNING: %s\n"), warn); - if (!opt.quiet) - { - log_info (_("Note: Outdated servers may lack important" - " security fixes.\n")); - log_info (_("Note: Use the command \"%s\" to restart them.\n"), - "gpgconf --kill all"); - } - - write_status_strings (STATUS_WARNING, "server_version_mismatch 0", - " ", warn, NULL); - xfree (warn); - } - } - xfree (serverversion); - return err; + return warn_server_version_mismatch (ctx, servername, 0, + write_status_strings2, NULL, + !opt.quiet); } diff --git a/g10/call-keyboxd.c b/g10/call-keyboxd.c index 181f33fed..e09fa20e3 100644 --- a/g10/call-keyboxd.c +++ b/g10/call-keyboxd.c @@ -142,40 +142,9 @@ gpg_keyboxd_deinit_session_data (ctrl_t ctrl) static gpg_error_t warn_version_mismatch (assuan_context_t ctx, const char *servername) { - gpg_error_t err; - char *serverversion; - const char *myversion = gpgrt_strusage (13); - - err = get_assuan_server_version (ctx, 0, &serverversion); - if (err) - log_error (_("error getting version from '%s': %s\n"), - servername, gpg_strerror (err)); - else if (compare_version_strings (serverversion, myversion) < 0) - { - char *warn; - - warn = xtryasprintf (_("server '%s' is older than us (%s < %s)"), - servername, serverversion, myversion); - if (!warn) - err = gpg_error_from_syserror (); - else - { - log_info (_("WARNING: %s\n"), warn); - if (!opt.quiet) - { - log_info (_("Note: Outdated servers may lack important" - " security fixes.\n")); - log_info (_("Note: Use the command \"%s\" to restart them.\n"), - "gpgconf --kill all"); - } - - write_status_strings (STATUS_WARNING, "server_version_mismatch 0", - " ", warn, NULL); - xfree (warn); - } - } - xfree (serverversion); - return err; + return warn_server_version_mismatch (ctx, servername, 0, + write_status_strings2, NULL, + !opt.quiet); } diff --git a/g10/cpr.c b/g10/cpr.c index d502e8b52..5a39913c5 100644 --- a/g10/cpr.c +++ b/g10/cpr.c @@ -181,6 +181,50 @@ write_status_strings (int no, const char *text, ...) } +/* Write a status line with code NO followed by the remaining + * arguments which must be a list of strings terminated by a NULL. + * Embedded CR and LFs in the strings are C-style escaped. All + * strings are printed with a space as delimiter. */ +gpg_error_t +write_status_strings2 (ctrl_t dummy, int no, ...) +{ + va_list arg_ptr; + const char *s; + + (void)dummy; + + if (!statusfp || !status_currently_allowed (no) ) + return 0; /* Not enabled or allowed. */ + + va_start (arg_ptr, no); + + es_fputs ("[GNUPG:] ", statusfp); + es_fputs (get_status_string (no), statusfp); + while ((s = va_arg (arg_ptr, const char*))) + { + if (*s) + es_putc (' ', statusfp); + for (; *s; s++) + { + if (*s == '\n') + es_fputs ("\\n", statusfp); + else if (*s == '\r') + es_fputs ("\\r", statusfp); + else + es_fputc (*(const byte *)s, statusfp); + } + } + es_putc ('\n', statusfp); + + va_end (arg_ptr); + + if (es_fflush (statusfp) && opt.exit_on_status_write_error) + g10_exit (0); + + return 0; +} + + void write_status_text (int no, const char *text) { diff --git a/g10/main.h b/g10/main.h index f13b1b929..7b5754648 100644 --- a/g10/main.h +++ b/g10/main.h @@ -208,6 +208,8 @@ void write_status_printf (int no, const char *format, ...) GPGRT_ATTR_PRINTF(2,3); void write_status_strings (int no, const char *text, ...) GPGRT_ATTR_SENTINEL(0); +gpg_error_t write_status_strings2 (ctrl_t dummy, int no, + ...) GPGRT_ATTR_SENTINEL(0); void write_status_buffer ( int no, const char *buffer, size_t len, int wrap ); void write_status_text_and_buffer ( int no, const char *text, diff --git a/sm/call-agent.c b/sm/call-agent.c index 0b556a7e5..868497e0d 100644 --- a/sm/call-agent.c +++ b/sm/call-agent.c @@ -95,42 +95,11 @@ static gpg_error_t warn_version_mismatch (ctrl_t ctrl, assuan_context_t ctx, const char *servername, int mode) { - gpg_error_t err; - char *serverversion; - const char *myversion = gpgrt_strusage (13); - - err = get_assuan_server_version (ctx, mode, &serverversion); - if (err) - log_error (_("error getting version from '%s': %s\n"), - servername, gpg_strerror (err)); - else if (compare_version_strings (serverversion, myversion) < 0) - { - char *warn; - - warn = xtryasprintf (_("server '%s' is older than us (%s < %s)"), - servername, serverversion, myversion); - if (!warn) - err = gpg_error_from_syserror (); - else - { - log_info (_("WARNING: %s\n"), warn); - if (!opt.quiet) - { - log_info (_("Note: Outdated servers may lack important" - " security fixes.\n")); - log_info (_("Note: Use the command \"%s\" to restart them.\n"), - "gpgconf --kill all"); - } - gpgsm_status2 (ctrl, STATUS_WARNING, "server_version_mismatch 0", - warn, NULL); - xfree (warn); - } - } - xfree (serverversion); - return err; + return warn_server_version_mismatch (ctx, servername, mode, + gpgsm_status2, ctrl, + !opt.quiet); } - /* Try to connect to the agent via socket or fork it off and work by pipes. Handle the server's initial greeting */ static int diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c index c9ec8f1e7..7619f60df 100644 --- a/sm/call-dirmngr.c +++ b/sm/call-dirmngr.c @@ -155,39 +155,9 @@ static gpg_error_t warn_version_mismatch (ctrl_t ctrl, assuan_context_t ctx, const char *servername, int mode) { - gpg_error_t err; - char *serverversion; - const char *myversion = gpgrt_strusage (13); - - err = get_assuan_server_version (ctx, mode, &serverversion); - if (err) - log_error (_("error getting version from '%s': %s\n"), - servername, gpg_strerror (err)); - else if (compare_version_strings (serverversion, myversion) < 0) - { - char *warn; - - warn = xtryasprintf (_("server '%s' is older than us (%s < %s)"), - servername, serverversion, myversion); - if (!warn) - err = gpg_error_from_syserror (); - else - { - log_info (_("WARNING: %s\n"), warn); - if (!opt.quiet) - { - log_info (_("Note: Outdated servers may lack important" - " security fixes.\n")); - log_info (_("Note: Use the command \"%s\" to restart them.\n"), - "gpgconf --kill all"); - } - gpgsm_status2 (ctrl, STATUS_WARNING, "server_version_mismatch 0", - warn, NULL); - xfree (warn); - } - } - xfree (serverversion); - return err; + return warn_server_version_mismatch (ctx, servername, mode, + gpgsm_status2, ctrl, + !opt.quiet); } diff --git a/tools/card-call-scd.c b/tools/card-call-scd.c index 160d9480e..8800c5b52 100644 --- a/tools/card-call-scd.c +++ b/tools/card-call-scd.c @@ -268,41 +268,9 @@ default_inq_cb (void *opaque, const char *line) static gpg_error_t warn_version_mismatch (assuan_context_t ctx, const char *servername, int mode) { - gpg_error_t err; - char *serverversion; - const char *myversion = gpgrt_strusage (13); - - err = get_assuan_server_version (ctx, mode, &serverversion); - if (err) - log_log (gpg_err_code (err) == GPG_ERR_NOT_SUPPORTED? - GPGRT_LOGLVL_INFO : GPGRT_LOGLVL_ERROR, - _("error getting version from '%s': %s\n"), - servername, gpg_strerror (err)); - else if (compare_version_strings (serverversion, myversion) < 0) - { - char *warn; - - warn = xtryasprintf (_("server '%s' is older than us (%s < %s)"), - servername, serverversion, myversion); - if (!warn) - err = gpg_error_from_syserror (); - else - { - log_info (_("WARNING: %s\n"), warn); - if (!opt.quiet) - { - log_info (_("Note: Outdated servers may lack important" - " security fixes.\n")); - log_info (_("Note: Use the command \"%s\" to restart them.\n"), - "gpgconf --kill all"); - } - gnupg_status_printf (STATUS_WARNING, "server_version_mismatch 0 %s", - warn); - xfree (warn); - } - } - xfree (serverversion); - return err; + return warn_server_version_mismatch (ctx, servername, mode, + gnupg_status_strings, NULL, + !opt.quiet); }