Package: gnupg2 / 2.0.26-6+deb8u2

0016-gpg-Make-the-use-of-verify-FILE-for-detached-sigs-ha.patch Patch series | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
From a5ca45e6168e75aa6f3743b764d601ab3df966b7 Mon Sep 17 00:00:00 2001
From: Werner Koch <wk@gnupg.org>
Date: Fri, 14 Nov 2014 09:36:19 +0100
Subject: [PATCH 16/31] gpg: Make the use of "--verify FILE" for detached sigs
 harder.

* g10/openfile.c (open_sigfile): Factor some code out to ...
(get_matching_datafile): new function.
* g10/plaintext.c (hash_datafiles): Do not try to find matching file
in batch mode.
* g10/mainproc.c (check_sig_and_print): Print a warning if a possibly
matching data file is not used by a standard signatures.
--

Allowing to use the abbreviated form for detached signatures is a long
standing bug which has only been noticed by the public with the
release of 2.1.0.  :-(

What we do is to remove the ability to check detached signature in
--batch using the one file abbreviated mode.  This should exhibit
problems in scripts which use this insecure practice.  We also print a
warning if a matching data file exists but was not considered because
the detached signature was actually a standard signature:

  gpgv: Good signature from "Werner Koch (dist sig)"
  gpgv: WARNING: not a detached signature; \
  file 'gnupg-2.1.0.tar.bz2' was NOT verified!

We can only print a warning because it is possible that a standard
signature is indeed to be verified but by coincidence a file with a
matching name is stored alongside the standard signature.

Reported-by: Simon Nicolussi (to gnupg-users on Nov 7)
Signed-off-by: Werner Koch <wk@gnupg.org>

(backported from commit 69384568f66a48eff3968bb1714aa13925580e9f)
(modified by dkg 2015-01-04 to avoid a needless whitespace change)
---
 g10/main.h      |  3 ++-
 g10/mainproc.c  | 38 ++++++++++++++++++++++++++
 g10/openfile.c  | 83 ++++++++++++++++++++++++++++++++++++++-------------------
 g10/plaintext.c | 32 +++++++++++++---------
 4 files changed, 116 insertions(+), 40 deletions(-)

diff --git a/g10/main.h b/g10/main.h
index e97b936..b55a184 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -253,7 +253,8 @@ int overwrite_filep( const char *fname );
 char *make_outfile_name( const char *iname );
 char *ask_outfile_name( const char *name, size_t namelen );
 int   open_outfile( const char *iname, int mode, 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 );
 
 /*-- seskey.c --*/
diff --git a/g10/mainproc.c b/g10/mainproc.c
index 551ab58..3abcb15 100644
--- a/g10/mainproc.c
+++ b/g10/mainproc.c
@@ -1959,6 +1959,44 @@ check_sig_and_print( CTX c, KBNODE node )
 		   sig->sig_class==0x01?_("textmode"):_("unknown"),
 		   gcry_md_algo_name (sig->digest_algo));
 
+        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 db5cdc2..dc9dfd0 100644
--- a/g10/openfile.c
+++ b/g10/openfile.c
@@ -287,41 +287,70 @@ open_outfile( const char *iname, int mode, IOBUF *a )
 }
 
 
+/* 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;
-
-    if( !iobuf_is_pipe_filename (iname) ) {
-	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")) ) {
-	    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;
-                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_t a = NULL;
+  char *buf;
+
+  buf = get_matching_datafile (sigfilename);
+  if (buf)
+    {
+      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)
+        log_info (_("assuming signed data in '%s'\n"), buf);
+      if (a && pfx)
+        handle_progress (pfx, a, buf);
+      xfree (buf);
     }
-    return a;
+
+  return a;
 }
 
+
 /****************
  * Copy the option file skeleton to the given directory.
  */
diff --git a/g10/plaintext.c b/g10/plaintext.c
index 3777648..d24c640 100644
--- a/g10/plaintext.c
+++ b/g10/plaintext.c
@@ -546,17 +546,25 @@ hash_datafiles( gcry_md_hd_t md, gcry_md_hd_t md2, strlist_t files,
     pfx = new_progress_context ();
 
     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;
-	}
-        log_error (_("no signed data\n"));
-        release_progress_context (pfx);
-        return gpg_error (GPG_ERR_NO_DATA);
+      /* 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);
     }
 
 
-- 
2.1.4