aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/gpg.texi26
-rw-r--r--g10/main.h5
-rw-r--r--g10/mainproc.c38
-rw-r--r--g10/openfile.c76
-rw-r--r--g10/plaintext.c31
5 files changed, 125 insertions, 51 deletions
diff --git a/doc/gpg.texi b/doc/gpg.texi
index 499df8770..634b4e26b 100644
--- a/doc/gpg.texi
+++ b/doc/gpg.texi
@@ -214,16 +214,22 @@ files which don't begin with an encrypted message.
@item --verify
@opindex verify
-Assume that the first argument is a signed file or a detached signature
-and verify it without generating any output. With no arguments, the
-signature packet is read from STDIN. If only a sigfile is given, it may
-be a complete signature or a detached signature, in which case the
-signed stuff is expected in a file without the ".sig" or ".asc"
-extension. With more than 1 argument, the first should be a detached
-signature and the remaining files are the signed stuff. To read the
-signed stuff from STDIN, use @samp{-} as the second filename. For
-security reasons a detached signature cannot read the signed material
-from STDIN without denoting it in the above way.
+Assume that the first argument is a signed file and verify it without
+generating any output. With no arguments, the signature packet is
+read from STDIN. If only a one argument is given, it is expected to
+be a complete signature.
+
+With more than 1 argument, the first should be a detached signature
+and the remaining files ake up the the signed data. To read the signed
+data from STDIN, use @samp{-} as the second filename. For security
+reasons a detached signature cannot read the signed material from
+STDIN without denoting it in the above way.
+
+Note: If the option @option{--batch} is not used, @command{@gpgname}
+may assume that a single argument is a file with a detached signature
+and it will try to find a matching data file by stripping certain
+suffixes. Using this historical feature to verify a detached
+signature is strongly discouraged; always specify the data file too.
Note: When verifying a cleartext signature, @command{gpg} verifies
only what makes up the cleartext signed data and not any extra data
diff --git a/g10/main.h b/g10/main.h
index 76541c771..d313afb1c 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -286,7 +286,8 @@ char *make_outfile_name( const char *iname );
char *ask_outfile_name( const char *name, size_t namelen );
int open_outfile (int inp_fd, const char *iname, int mode,
int restrictedperm, iobuf_t *a);
-iobuf_t open_sigfile( const char *iname, progress_filter_context_t *pfx );
+char *get_matching_datafile (const char *sigfilename);
+iobuf_t open_sigfile (const char *sigfilename, progress_filter_context_t *pfx);
void try_make_homedir( const char *fname );
char *get_openpgp_revocdir (const char *home);
@@ -374,7 +375,7 @@ void decrypt_messages (ctrl_t ctrl, int nfiles, char *files[]);
/*-- plaintext.c --*/
int hash_datafiles( gcry_md_hd_t md, gcry_md_hd_t md2,
- strlist_t files, const char *sigfilename, int textmode );
+ strlist_t files, const char *sigfilename, int textmode);
int hash_datafile_by_fd ( gcry_md_hd_t md, gcry_md_hd_t md2, int data_fd,
int textmode );
PKT_plaintext *setup_plaintext_name(const char *filename,IOBUF iobuf);
diff --git a/g10/mainproc.c b/g10/mainproc.c
index bc186d3f9..b84607a7b 100644
--- a/g10/mainproc.c
+++ b/g10/mainproc.c
@@ -2008,6 +2008,44 @@ check_sig_and_print (CTX c, kbnode_t node)
*pkstrbuf?_(", key algorithm "):"",
pkstrbuf);
+ if (!rc && !c->signed_data.used)
+ {
+ /* Signature is basically good but we test whether the
+ deprecated command
+ gpg --verify FILE.sig
+ was used instead of
+ gpg --verify FILE.sig FILE
+ to verify a detached signature. If we figure out that a
+ data file with a matching name exists, we print a warning.
+
+ The problem is that the first form would also verify a
+ standard signature. This behavior could be used to
+ create a made up .sig file for a tarball by creating a
+ standard signature from a valid detached signature packet
+ (for example from a signed git tag). Then replace the
+ sig file on the FTP server along with a changed tarball.
+ Using the first form the verify command would correctly
+ verify the signature but don't even consider the tarball. */
+ kbnode_t n;
+ char *dfile;
+
+ dfile = get_matching_datafile (c->sigfilename);
+ if (dfile)
+ {
+ for (n = c->list; n; n = n->next)
+ if (n->pkt->pkttype != PKT_SIGNATURE)
+ break;
+ if (n)
+ {
+ /* Not only signature packets in the tree thus this
+ is not a detached signature. */
+ log_info (_("WARNING: not a detached signature; "
+ "file '%s' was NOT verified!\n"), dfile);
+ }
+ xfree (dfile);
+ }
+ }
+
if (rc)
g10_errors_seen = 1;
if (opt.batch && rc)
diff --git a/g10/openfile.c b/g10/openfile.c
index ab27f44e3..76961e5f6 100644
--- a/g10/openfile.c
+++ b/g10/openfile.c
@@ -310,40 +310,64 @@ open_outfile (int inp_fd, const char *iname, int mode, int restrictedperm,
}
+/* Find a matching data file for the signature file SIGFILENAME and
+ return it as a malloced string. If no matching data file is found,
+ return NULL. */
+char *
+get_matching_datafile (const char *sigfilename)
+{
+ char *fname = NULL;
+ size_t len;
+
+ if (iobuf_is_pipe_filename (sigfilename))
+ return NULL;
+
+ len = strlen (sigfilename);
+ if (len > 4
+ && (!strcmp (sigfilename + len - 4, EXTSEP_S "sig")
+ || (len > 5 && !strcmp(sigfilename + len - 5, EXTSEP_S "sign"))
+ || !strcmp(sigfilename + len - 4, EXTSEP_S "asc")))
+ {
+
+ fname = xstrdup (sigfilename);
+ fname[len-(fname[len-1]=='n'?5:4)] = 0 ;
+ if (access (fname, R_OK ))
+ {
+ /* Not found or other error. */
+ xfree (fname);
+ fname = NULL;
+ }
+ }
+
+ return fname;
+}
+
+
/*
* Try to open a file without the extension ".sig" or ".asc"
* Return NULL if such a file is not available.
*/
-IOBUF
-open_sigfile( const char *iname, progress_filter_context_t *pfx )
+iobuf_t
+open_sigfile (const char *sigfilename, progress_filter_context_t *pfx)
{
- IOBUF a = NULL;
- size_t len;
+ iobuf_t a = NULL;
+ char *buf;
- if (!iobuf_is_pipe_filename (iname))
+ buf = get_matching_datafile (sigfilename);
+ if (buf)
{
- len = strlen(iname);
- if( len > 4 && (!strcmp(iname + len - 4, EXTSEP_S "sig")
- || (len > 5 && !strcmp(iname + len - 5, EXTSEP_S "sign"))
- || !strcmp(iname + len - 4, EXTSEP_S "asc")))
+ a = iobuf_open (buf);
+ if (a && is_secured_file (iobuf_get_fd (a)))
{
- char *buf;
-
- buf = xstrdup(iname);
- buf[len-(buf[len-1]=='n'?5:4)] = 0 ;
- a = iobuf_open( buf );
- if (a && is_secured_file (iobuf_get_fd (a)))
- {
- iobuf_close (a);
- a = NULL;
- gpg_err_set_errno (EPERM);
- }
- if (a && opt.verbose)
- log_info (_("assuming signed data in '%s'\n"), buf);
- if (a && pfx)
- handle_progress (pfx, a, buf);
- xfree (buf);
- }
+ iobuf_close (a);
+ a = NULL;
+ gpg_err_set_errno (EPERM);
+ }
+ if (a)
+ log_info (_("assuming signed data in '%s'\n"), buf);
+ if (a && pfx)
+ handle_progress (pfx, a, buf);
+ xfree (buf);
}
return a;
diff --git a/g10/plaintext.c b/g10/plaintext.c
index 54541986a..5d343c6d2 100644
--- a/g10/plaintext.c
+++ b/g10/plaintext.c
@@ -607,10 +607,8 @@ leave:
-/****************
- * Hash the given files and append the hash to hash context md.
- * If FILES is NULL, hash stdin.
- */
+/* Hash the given files and append the hash to hash contexts MD and
+ * MD2. If FILES is NULL, stdin is hashed. */
int
hash_datafiles (gcry_md_hd_t md, gcry_md_hd_t md2, strlist_t files,
const char *sigfilename, int textmode)
@@ -623,15 +621,22 @@ hash_datafiles (gcry_md_hd_t md, gcry_md_hd_t md2, strlist_t files,
if (!files)
{
- /* check whether we can open the signed material */
- fp = open_sigfile (sigfilename, pfx);
- if (fp)
- {
- do_hash (md, md2, fp, textmode);
- iobuf_close (fp);
- release_progress_context (pfx);
- return 0;
- }
+ /* Check whether we can open the signed material. We avoid
+ trying to open a file if run in batch mode. This assumed
+ data file for a sig file feature is just a convenience thing
+ for the command line and the user needs to read possible
+ warning messages. */
+ if (!opt.batch)
+ {
+ fp = open_sigfile (sigfilename, pfx);
+ if (fp)
+ {
+ do_hash (md, md2, fp, textmode);
+ iobuf_close (fp);
+ release_progress_context (pfx);
+ return 0;
+ }
+ }
log_error (_("no signed data\n"));
release_progress_context (pfx);
return gpg_error (GPG_ERR_NO_DATA);