aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--NEWS8
-rw-r--r--configure.ac2
-rw-r--r--doc/gpg.texi20
-rw-r--r--g10/call-dirmngr.c4
-rw-r--r--g10/gpg.c6
-rw-r--r--g10/import.c2
-rw-r--r--g10/keyserver-internal.h11
-rw-r--r--g10/keyserver.c92
-rw-r--r--g10/misc.c22
-rw-r--r--g10/options.h1
-rw-r--r--tools/gpgtar-extract.c5
-rw-r--r--tools/gpgtar-list.c10
12 files changed, 135 insertions, 48 deletions
diff --git a/NEWS b/NEWS
index 64a486efc..9329b05a8 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,11 @@
+Noteworthy changes in version 2.5.12 (unreleased)
+-------------------------------------------------
+
+ * gpgtar: Fix regression in end-of-archive detection. [T7757]
+
+ Release-info: https://dev.gnupg.org/T7756
+
+
Noteworthy changes in version 2.5.11 (2025-07-30)
-------------------------------------------------
diff --git a/configure.ac b/configure.ac
index 023604b8a..eb9a0f1af 100644
--- a/configure.ac
+++ b/configure.ac
@@ -29,7 +29,7 @@ min_automake_version="1.16.3"
m4_define([mym4_package],[gnupg])
m4_define([mym4_major], [2])
m4_define([mym4_minor], [5])
-m4_define([mym4_micro], [11])
+m4_define([mym4_micro], [12])
# To start a new development series, i.e a new major or minor number
# you need to mark an arbitrary commit before the first beta release
diff --git a/doc/gpg.texi b/doc/gpg.texi
index 91bc73e8c..b0e7232a1 100644
--- a/doc/gpg.texi
+++ b/doc/gpg.texi
@@ -2167,10 +2167,6 @@ are available for all keyserver types, some common options are:
are marked on the keyserver as disabled. Note that this option is not
used with HKP keyservers.
- @item auto-key-retrieve
- This is an obsolete alias for the option @option{auto-key-retrieve}.
- Please do not use it; it will be removed in future versions..
-
@item honor-keyserver-url
When using @option{--refresh-keys}, if the key in question has a preferred
keyserver URL, then use that preferred keyserver to refresh the key
@@ -2188,6 +2184,15 @@ are available for all keyserver types, some common options are:
@item only-pubkeys
Do not import secret keys.
+ @item update-before-send
+ Before sending a key to an LDAP server try to retrieve and merge
+ that key first. This is only done if the key is specified by
+ fingerprint. This is enabled by default.
+
+ @item auto-key-retrieve
+ This is an obsolete alias for the option @option{auto-key-retrieve}.
+ Please do not use it; it will be removed in future versions.
+
@item timeout
@itemx http-proxy=@var{value}
@itemx verbose
@@ -2200,9 +2205,10 @@ are available for all keyserver types, some common options are:
@end table
The default list of options is: "self-sigs-only, import-clean,
-repair-keys, repair-pks-subkey-bug, export-attributes". However, if
-the actual used source is an LDAP server "no-self-sigs-only" is
-assumed unless "self-sigs-only" has been explicitly configured.
+repair-keys, repair-pks-subkey-bug, export-attributes,
+update-before-send". However, if the actual used source is an LDAP
+server "no-self-sigs-only" is assumed unless "self-sigs-only" has been
+explicitly configured.
@item --completes-needed @var{n}
diff --git a/g10/call-dirmngr.c b/g10/call-dirmngr.c
index 12469d60a..c1644b886 100644
--- a/g10/call-dirmngr.c
+++ b/g10/call-dirmngr.c
@@ -449,7 +449,9 @@ ks_status_cb (void *opaque, const char *line)
/* Run the "KEYSERVER" command to return the name of the used
- keyserver at R_KEYSERVER. */
+ * keyserver at R_KEYSERVER. This function returns the first
+ * keyserver; it should be extended to handle multiple keyservers or
+ * we disallow the use of several keyservers. */
gpg_error_t
gpg_dirmngr_ks_list (ctrl_t ctrl, char **r_keyserver)
{
diff --git a/g10/gpg.c b/g10/gpg.c
index 5cd546ba0..d0f575d7e 100644
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -2518,7 +2518,7 @@ main (int argc, char **argv)
| IMPORT_COLLAPSE_SUBKEYS
| IMPORT_CLEAN);
opt.keyserver_options.export_options = EXPORT_ATTRIBUTES;
- opt.keyserver_options.options = 0;
+ opt.keyserver_options.options = KEYSERVER_UPDATE_BEFORE_SEND;
opt.verify_options = (LIST_SHOW_UID_VALIDITY
| VERIFY_SHOW_POLICY_URLS
| VERIFY_SHOW_STD_NOTATIONS
@@ -5072,9 +5072,9 @@ main (int argc, char **argv)
for( ; argc; argc--, argv++ )
append_to_strlist2( &sl, *argv, utf8_strings );
if( cmd == aSendKeys )
- rc = keyserver_export (ctrl, sl );
+ rc = keyserver_export (ctrl, sl, 0 );
else if( cmd == aRecvKeys )
- rc = keyserver_import (ctrl, sl );
+ rc = keyserver_import (ctrl, sl, 0);
else
{
export_stats_t stats = export_new_stats ();
diff --git a/g10/import.c b/g10/import.c
index 6e33ac976..1ee818d61 100644
--- a/g10/import.c
+++ b/g10/import.c
@@ -2234,7 +2234,7 @@ import_one_real (ctrl_t ctrl,
log_error (_("key %s: public key not found: %s\n"),
keystr(keyid), gpg_strerror (err));
}
- else if (err && (opt.import_options&IMPORT_MERGE_ONLY) )
+ else if (err && ((opt.import_options|options)&IMPORT_MERGE_ONLY) )
{
if (opt.verbose && !silent )
log_info( _("key %s: new key - skipped\n"), keystr(keyid));
diff --git a/g10/keyserver-internal.h b/g10/keyserver-internal.h
index cb2c005b4..9506fd015 100644
--- a/g10/keyserver-internal.h
+++ b/g10/keyserver-internal.h
@@ -25,8 +25,11 @@
#include "../common/types.h"
/* Flags for the keyserver import functions. */
-#define KEYSERVER_IMPORT_FLAG_QUICK 1
-#define KEYSERVER_IMPORT_FLAG_LDAP 2
+#define KEYSERVER_IMPORT_FLAG_QUICK 1 /* Short time out. */
+#define KEYSERVER_IMPORT_FLAG_LDAP 2 /* Require LDAP server. */
+#define KEYSERVER_IMPORT_FLAG_SILENT 4 /* Do not print stats. */
+#define KEYSERVER_IMPORT_FLAG_ONLYFPR 8 /* Allow only fingerprint specs. */
+#define KEYSERVER_IMPORT_FLAG_UPDSEND 16 /* In updating before send. */
int parse_keyserver_options(char *options);
void free_keyserver_spec(struct keyserver_spec *keyserver);
@@ -35,8 +38,8 @@ struct keyserver_spec *parse_keyserver_uri (const char *string,
int require_scheme);
struct keyserver_spec *parse_preferred_keyserver(PKT_signature *sig);
int keyserver_any_configured (ctrl_t ctrl);
-int keyserver_export (ctrl_t ctrl, strlist_t users);
-int keyserver_import (ctrl_t ctrl, strlist_t users);
+gpg_error_t keyserver_export (ctrl_t ctrl, strlist_t users, int assume_new_key);
+gpg_error_t keyserver_import (ctrl_t ctrl, strlist_t users, unsigned int flags);
int keyserver_import_fpr (ctrl_t ctrl, const byte *fprint,size_t fprint_len,
struct keyserver_spec *keyserver,
unsigned int flags);
diff --git a/g10/keyserver.c b/g10/keyserver.c
index 069c541d2..bdfbde5c3 100644
--- a/g10/keyserver.c
+++ b/g10/keyserver.c
@@ -99,6 +99,8 @@ static struct parse_options keyserver_opts[]=
N_("automatically retrieve keys when verifying signatures")},
{"honor-keyserver-url",KEYSERVER_HONOR_KEYSERVER_URL,NULL,
N_("honor the preferred keyserver URL set on the key")},
+ {"update-before-send", KEYSERVER_UPDATE_BEFORE_SEND,NULL,
+ N_("update a key before sending it")},
{NULL,0,NULL,NULL}
};
@@ -107,7 +109,8 @@ static gpg_error_t keyserver_get (ctrl_t ctrl,
struct keyserver_spec *override_keyserver,
unsigned int flags,
unsigned char **r_fpr, size_t *r_fprlen);
-static gpg_error_t keyserver_put (ctrl_t ctrl, strlist_t keyspecs);
+static gpg_error_t keyserver_put (ctrl_t ctrl, strlist_t keyspecs,
+ int assume_new_key);
/* Reasonable guess. The commonly used test key simon.josefsson.org
@@ -790,8 +793,11 @@ search_line_handler (void *opaque, int special, char *line)
-int
-keyserver_export (ctrl_t ctrl, strlist_t users)
+/* Send all keys specified by USERS to the configured keyserver. If
+ * ASSUME_NEW_KEY is true the KEYSERVER_UPDATE_BEFORE_SEND option will
+ * be ignored. */
+gpg_error_t
+keyserver_export (ctrl_t ctrl, strlist_t users, int assume_new_key)
{
gpg_error_t err;
strlist_t sl=NULL;
@@ -815,7 +821,7 @@ keyserver_export (ctrl_t ctrl, strlist_t users)
if(sl)
{
- rc = keyserver_put (ctrl, sl);
+ rc = keyserver_put (ctrl, sl, assume_new_key);
free_strlist(sl);
}
@@ -898,23 +904,31 @@ keyserver_retrieval_screener (kbnode_t keyblock, void *opaque)
}
-int
-keyserver_import (ctrl_t ctrl, strlist_t users)
+/* Given a list of patterns in USERS, try to import those keys from
+ * the configured keyserver. */
+gpg_error_t
+keyserver_import (ctrl_t ctrl, strlist_t users, unsigned int flags)
{
- gpg_error_t err;
+ gpg_error_t tmperr;
+ gpg_error_t err = 0;
KEYDB_SEARCH_DESC *desc;
int num=100,count=0;
- int rc=0;
/* Build a list of key ids */
- desc=xmalloc(sizeof(KEYDB_SEARCH_DESC)*num);
+ desc = xmalloc (sizeof(KEYDB_SEARCH_DESC)*num);
for(;users;users=users->next)
{
- err = classify_user_id (users->d, &desc[count], 1);
- if (err || (desc[count].mode != KEYDB_SEARCH_MODE_SHORT_KID
- && desc[count].mode != KEYDB_SEARCH_MODE_LONG_KID
- && desc[count].mode != KEYDB_SEARCH_MODE_FPR))
+ tmperr = classify_user_id (users->d, &desc[count], 1);
+ if (!tmperr && (flags & KEYSERVER_IMPORT_FLAG_ONLYFPR)
+ && desc[count].mode != KEYDB_SEARCH_MODE_FPR)
+ {
+ log_info (_("\"%s\" not a fingerprint: skipping\n"), users->d);
+ continue;
+ }
+ if (tmperr || (desc[count].mode != KEYDB_SEARCH_MODE_SHORT_KID
+ && desc[count].mode != KEYDB_SEARCH_MODE_LONG_KID
+ && desc[count].mode != KEYDB_SEARCH_MODE_FPR))
{
log_error (_("\"%s\" not a key ID: skipping\n"), users->d);
continue;
@@ -928,12 +942,12 @@ keyserver_import (ctrl_t ctrl, strlist_t users)
}
}
- if(count>0)
- rc = keyserver_get (ctrl, desc, count, NULL, 0, NULL, NULL);
+ if (count > 0)
+ err = keyserver_get (ctrl, desc, count, NULL, flags, NULL, NULL);
- xfree(desc);
+ xfree (desc);
- return rc;
+ return err;
}
@@ -1517,7 +1531,11 @@ keyserver_get_chunk (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
keyservers. */
/* For LDAP servers we reset IMPORT_SELF_SIGS_ONLY and
- * IMPORT_CLEAN unless they have been set explicitly. */
+ * IMPORT_CLEAN unless they have been set explicitly. We
+ * forcible clear them if that has been requested and also set
+ * the MERGE_ONLY option so that a --send-key can't be tricked
+ * into importing a key by means of the update-before-send
+ * keyserver option. */
options = (opt.keyserver_options.import_options | IMPORT_ONLY_PUBKEYS);
if (source && (!strncmp (source, "ldap:", 5)
|| !strncmp (source, "ldaps:", 6)))
@@ -1527,6 +1545,11 @@ keyserver_get_chunk (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
if (!opt.flags.expl_import_clean)
options &= ~IMPORT_CLEAN;
}
+ if ((flags & KEYSERVER_IMPORT_FLAG_UPDSEND))
+ {
+ options &= ~(IMPORT_SELF_SIGS_ONLY | IMPORT_CLEAN);
+ options |= IMPORT_MERGE_ONLY;
+ }
screenerarg.desc = desc;
screenerarg.ndesc = *r_ndesc_used;
@@ -1575,7 +1598,7 @@ keyserver_get (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
ndesc -= ndesc_used;
}
- if (any_good)
+ if (any_good && !(flags & KEYSERVER_IMPORT_FLAG_SILENT))
import_print_stats (stats_handle);
import_release_stats_handle (stats_handle);
@@ -1583,10 +1606,11 @@ keyserver_get (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
}
-/* Send all keys specified by KEYSPECS to the configured keyserver. */
+/* Send all keys specified by KEYSPECS to the configured keyserver.
+ * If ASSUME_NEW_KEY is true the KEYSERVER_UPDATE_BEFORE_SEND option
+ * will be ignored. */
static gpg_error_t
-keyserver_put (ctrl_t ctrl, strlist_t keyspecs)
-
+keyserver_put (ctrl_t ctrl, strlist_t keyspecs, int assume_new_key)
{
gpg_error_t err;
strlist_t kspec;
@@ -1595,12 +1619,36 @@ keyserver_put (ctrl_t ctrl, strlist_t keyspecs)
if (!keyspecs)
return 0; /* Return success if the list is empty. */
+ /* Get the name of the used keyservers. */
if (gpg_dirmngr_ks_list (ctrl, &ksurl))
{
log_error (_("no keyserver known\n"));
return gpg_error (GPG_ERR_NO_KEYSERVER);
}
+ /* If the option is active, we first try to import the keys given by
+ * fingerprint from the keyserver. For example, if some PKI server
+ * has signed a key and the user has not yet imported that updated
+ * key, an upload would overwrite that key signature. This is only
+ * relevant for LDAP servers but not for the legacy HKP servers. */
+ if ((opt.keyserver_options.options & KEYSERVER_UPDATE_BEFORE_SEND)
+ && !assume_new_key
+ && ksurl && (!strncmp (ksurl, "ldap:", 5)
+ || !strncmp (ksurl, "ldaps:", 6)))
+ {
+ err = keyserver_import (ctrl, keyspecs, (KEYSERVER_IMPORT_FLAG_UPDSEND
+ | KEYSERVER_IMPORT_FLAG_ONLYFPR
+ | KEYSERVER_IMPORT_FLAG_SILENT));
+ if (err)
+ {
+ if (opt.verbose && gpg_err_code (err) != GPG_ERR_NO_DATA)
+ log_info (_("keyserver receive failed: %s\n"),
+ gpg_strerror (err));
+ err = 0;
+ }
+ }
+
+ /* Send key after key to the keyserver. */
for (kspec = keyspecs; kspec; kspec = kspec->next)
{
void *data;
diff --git a/g10/misc.c b/g10/misc.c
index c52091830..43be620e6 100644
--- a/g10/misc.c
+++ b/g10/misc.c
@@ -1578,25 +1578,37 @@ parse_options(char *str,unsigned int *options,
{
char *tok;
- if (str && (!strcmp (str, "help") || !strcmp (str, "full-help")))
+ if (str && (!strcmp (str, "help")
+ || !strcmp (str, "full-help") || !strcmp (str, "fullhelp")))
{
int i,maxlen=0;
int full = *str == 'f';
+ int set;
/* Figure out the longest option name so we can line these up
neatly. */
for(i=0;opts[i].name;i++)
- if(opts[i].help && maxlen<strlen(opts[i].name))
+ if((full || opts[i].help) && maxlen<strlen(opts[i].name))
maxlen=strlen(opts[i].name);
for(i=0;opts[i].name;i++)
if(opts[i].help)
- es_printf("%s%*s%s\n",opts[i].name,
- maxlen+2-(int)strlen(opts[i].name),"",_(opts[i].help));
+ {
+ set = (*options & opts[i].bit);
+ es_printf("%s%*s%s%s%s%s\n",opts[i].name,
+ maxlen+2-(int)strlen(opts[i].name),"",_(opts[i].help),
+ set?" [":"", set? _("enabled"):"", set?"]":"");
+ }
+
if (full)
for (i=0; opts[i].name; i++)
if(!opts[i].help)
- es_printf("%s\n",opts[i].name);
+ {
+ set = (*options & opts[i].bit);
+ es_printf("%s%*s%s%s%s\n",opts[i].name,
+ set? (maxlen+2-(int)strlen(opts[i].name)):0,"",
+ set?"[":"", set? _("enabled"):"", set?"]":"");
+ }
g10_exit(0);
}
diff --git a/g10/options.h b/g10/options.h
index 28fc2207a..c7f21086c 100644
--- a/g10/options.h
+++ b/g10/options.h
@@ -486,6 +486,7 @@ EXTERN_UNLESS_MAIN_MODULE int memory_stat_debug_mode;
#define KEYSERVER_ADD_FAKE_V3 (1<<2)
#define KEYSERVER_AUTO_KEY_RETRIEVE (1<<3)
#define KEYSERVER_HONOR_KEYSERVER_URL (1<<4)
+#define KEYSERVER_UPDATE_BEFORE_SEND (1<<5)
#endif /*G10_OPTIONS_H*/
diff --git a/tools/gpgtar-extract.c b/tools/gpgtar-extract.c
index 5ec22e8f7..d23ccc579 100644
--- a/tools/gpgtar-extract.c
+++ b/tools/gpgtar-extract.c
@@ -492,7 +492,8 @@ gpgtar_extract (const char *filename, int decrypt)
#endif
err = gpgrt_process_spawn (opt.gpg_program, argv,
((filename ? 0 : GPGRT_PROCESS_STDIN_KEEP)
- | GPGRT_PROCESS_STDOUT_PIPE), act, &proc);
+ | GPGRT_PROCESS_STDOUT_PIPE
+ | GPGRT_PROCESS_STDERR_KEEP), act, &proc);
gpgrt_spawn_actions_release (act);
xfree (argv);
if (err)
@@ -525,6 +526,8 @@ gpgtar_extract (const char *filename, int decrypt)
for (;;)
{
err = gpgtar_read_header (stream, tarinfo, &header, &extheader);
+ if (!err && !header)
+ break; /* End of archive. */
if (err || header == NULL)
goto leave;
diff --git a/tools/gpgtar-list.c b/tools/gpgtar-list.c
index 07056575d..9f2eca318 100644
--- a/tools/gpgtar-list.c
+++ b/tools/gpgtar-list.c
@@ -527,7 +527,8 @@ gpgtar_list (const char *filename, int decrypt)
#endif
err = gpgrt_process_spawn (opt.gpg_program, argv,
((filename ? 0 : GPGRT_PROCESS_STDIN_KEEP)
- | GPGRT_PROCESS_STDOUT_PIPE), act, &proc);
+ | GPGRT_PROCESS_STDOUT_PIPE
+ | GPGRT_PROCESS_STDERR_KEEP), act, &proc);
gpgrt_spawn_actions_release (act);
xfree (argv);
if (err)
@@ -559,6 +560,8 @@ gpgtar_list (const char *filename, int decrypt)
for (;;)
{
err = read_header (stream, tarinfo, &header, &extheader);
+ if (!err && !header)
+ break; /* End of archive. */
if (err || header == NULL)
goto leave;
@@ -585,8 +588,9 @@ gpgtar_list (const char *filename, int decrypt)
int exitcode;
gpgrt_process_ctl (proc, GPGRT_PROCESS_GET_EXIT_ID, &exitcode);
- log_error ("running %s failed (exitcode=%d): %s",
- opt.gpg_program, exitcode, gpg_strerror (err));
+ if (exitcode)
+ log_error ("running %s failed (exitcode=%d): %s",
+ opt.gpg_program, exitcode, gpg_strerror (err));
}
gpgrt_process_release (proc);
proc = NULL;