diff --git a/common/status.h b/common/status.h index 509e04439..e50827fe0 100644 --- a/common/status.h +++ b/common/status.h @@ -141,6 +141,7 @@ enum STATUS_PLAINTEXT_FOLLOWS, /* Used by g13-syshelp */ STATUS_ERROR, + STATUS_WARNING, STATUS_SUCCESS, STATUS_FAILURE, diff --git a/doc/DETAILS b/doc/DETAILS index 7c3e67c61..69c2e5b00 100644 --- a/doc/DETAILS +++ b/doc/DETAILS @@ -840,7 +840,12 @@ pkd:0:1024:B665B1435F4C2 .... FF26ABB: should not contain spaces. The error code is a either a string commencing with a letter or such a string prefixed with a numerical error code and an underscore; e.g.: "151011327_EOF". - +*** WARNING [] + This is a generic warning status message, it might be followed by + error location specific data. and + should not contain spaces. The error code is a either a string + commencing with a letter or such a string prefixed with a + numerical error code and an underscore; e.g.: "151011327_EOF". *** SUCCESS [] Postive confirmation that an operation succeeded. It is used similar to ISO-C's EXIT_SUCCESS. is optional but if diff --git a/g10/call-agent.c b/g10/call-agent.c index 3600579bd..83fabcc32 100644 --- a/g10/call-agent.c +++ b/g10/call-agent.c @@ -253,6 +253,40 @@ check_hijacking (assuan_context_t ctx) +/* Print a warning if the server's version number is less than our + version number. Returns an error code on a connection problem. */ +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 = 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)) + { + 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); + write_status_strings (STATUS_WARNING, "server_version_mismatch 0", + " ", warn, NULL); + xfree (warn); + } + } + xfree (serverversion); + return err; +} + + /* Try to connect to the agent via socket or fork it off and work by pipes. Handle the server's initial greeting */ static int @@ -286,7 +320,8 @@ start_agent (ctrl_t ctrl, int for_card) log_info (_("no gpg-agent running in this session\n")); } } - else if (!rc) + else if (!rc + && !(rc = warn_version_mismatch (agent_ctx, GPG_AGENT_NAME, 0))) { /* Tell the agent that we support Pinentry notifications. No error checking so that it will work also with older @@ -324,9 +359,12 @@ start_agent (ctrl_t ctrl, int for_card) struct agent_card_info_s info; memset (&info, 0, sizeof info); - rc = assuan_transact (agent_ctx, "SCD SERIALNO openpgp", - NULL, NULL, NULL, NULL, - learn_status_cb, &info); + + rc = warn_version_mismatch (agent_ctx, SCDAEMON_NAME, 2); + if (!rc) + rc = assuan_transact (agent_ctx, "SCD SERIALNO openpgp", + NULL, NULL, NULL, NULL, + learn_status_cb, &info); if (rc) { switch (gpg_err_code (rc)) diff --git a/g10/call-dirmngr.c b/g10/call-dirmngr.c index b1c856d77..360e12743 100644 --- a/g10/call-dirmngr.c +++ b/g10/call-dirmngr.c @@ -38,6 +38,7 @@ #include "i18n.h" #include "asshelp.h" #include "keyserver.h" +#include "status.h" #include "call-dirmngr.h" @@ -132,6 +133,40 @@ gpg_dirmngr_deinit_session_data (ctrl_t ctrl) } +/* Print a warning if the server's version number is less than our + version number. Returns an error code on a connection problem. */ +static gpg_error_t +warn_version_mismatch (assuan_context_t ctx, const char *servername) +{ + gpg_error_t err; + char *serverversion; + const char *myversion = 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)) + { + 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); + write_status_strings (STATUS_WARNING, "server_version_mismatch 0", + " ", warn, NULL); + xfree (warn); + } + } + xfree (serverversion); + return err; +} + + /* Try to connect to the Dirmngr via a socket or spawn it if possible. Handle the server's initial greeting and set global options. */ static gpg_error_t @@ -157,7 +192,7 @@ create_context (ctrl_t ctrl, assuan_context_t *r_ctx) log_info (_("no dirmngr running in this session\n")); } } - else if (!err) + else if (!err && !(err = warn_version_mismatch (ctx, DIRMNGR_NAME))) { char *line; diff --git a/sm/call-agent.c b/sm/call-agent.c index b881fb8c4..c7d4c5a88 100644 --- a/sm/call-agent.c +++ b/sm/call-agent.c @@ -76,6 +76,41 @@ struct import_key_parm_s +/* Print a warning if the server's version number is less than our + version number. Returns an error code on a connection problem. */ +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 = 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)) + { + 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); + gpgsm_status2 (ctrl, STATUS_WARNING, "server_version_mismatch 0", + warn, NULL); + xfree (warn); + } + } + xfree (serverversion); + return err; +} + + /* Try to connect to the agent via socket or fork it off and work by pipes. Handle the server's initial greeting */ static int @@ -108,7 +143,8 @@ start_agent (ctrl_t ctrl) log_info (_("no gpg-agent running in this session\n")); } } - else if (!rc) + else if (!rc && !(rc = warn_version_mismatch (ctrl, agent_ctx, + GPG_AGENT_NAME, 0))) { /* Tell the agent that we support Pinentry notifications. No error checking so that it will work also with older @@ -919,6 +955,10 @@ gpgsm_agent_learn (ctrl_t ctrl) if (rc) return rc; + rc = warn_version_mismatch (ctrl, agent_ctx, SCDAEMON_NAME, 2); + if (rc) + return rc; + init_membuf (&data, 4096); learn_parm.error = 0; learn_parm.ctrl = ctrl; diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c index 379d7e9cc..881c484d5 100644 --- a/sm/call-dirmngr.c +++ b/sm/call-dirmngr.c @@ -149,6 +149,41 @@ get_membuf (struct membuf *mb, size_t *len) } +/* Print a warning if the server's version number is less than our + version number. Returns an error code on a connection problem. */ +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 = 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)) + { + 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); + gpgsm_status2 (ctrl, STATUS_WARNING, "server_version_mismatch 0", + warn, NULL); + xfree (warn); + } + } + xfree (serverversion); + return err; +} + + /* This function prepares the dirmngr for a new session. The audit-events option is used so that other dirmngr clients won't get disturbed by such events. */ @@ -157,6 +192,9 @@ prepare_dirmngr (ctrl_t ctrl, assuan_context_t ctx, gpg_error_t err) { struct keyserver_spec *server; + if (!err) + err = warn_version_mismatch (ctrl, ctx, DIRMNGR_NAME, 0); + if (!err) { err = assuan_transact (ctx, "OPTION audit-events=1",