chiark / gitweb /
gpg: Handle critical marked 'Reason for Revocation'.
[gnupg2.git] / g10 / decrypt.c
1 /* decrypt.c - decrypt and verify data
2  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
3  *               2007, 2009 Free Software Foundation, Inc.
4  *
5  * This file is part of GnuPG.
6  *
7  * GnuPG is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * GnuPG is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, see <https://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26
27 #include "gpg.h"
28 #include "options.h"
29 #include "packet.h"
30 #include "status.h"
31 #include "iobuf.h"
32 #include "keydb.h"
33 #include "util.h"
34 #include "main.h"
35 #include "status.h"
36 #include "i18n.h"
37
38 /* Assume that the input is an encrypted message and decrypt
39  * (and if signed, verify the signature on) it.
40  * This command differs from the default operation, as it never
41  * writes to the filename which is included in the file and it
42  * rejects files which don't begin with an encrypted message.
43  */
44 int
45 decrypt_message (ctrl_t ctrl, const char *filename)
46 {
47   IOBUF fp;
48   armor_filter_context_t *afx = NULL;
49   progress_filter_context_t *pfx;
50   int rc;
51   int no_out = 0;
52
53   pfx = new_progress_context ();
54
55   /* Open the message file.  */
56   fp = iobuf_open (filename);
57   if (fp && is_secured_file (iobuf_get_fd (fp)))
58     {
59       iobuf_close (fp);
60       fp = NULL;
61       gpg_err_set_errno (EPERM);
62     }
63   if ( !fp )
64     {
65       rc = gpg_error_from_syserror ();
66       log_error (_("can't open '%s': %s\n"), print_fname_stdin(filename),
67                  gpg_strerror (rc));
68       release_progress_context (pfx);
69       return rc;
70     }
71
72   handle_progress (pfx, fp, filename);
73
74   if ( !opt.no_armor )
75     {
76       if ( use_armor_filter( fp ) )
77         {
78           afx = new_armor_context ();
79           push_armor_filter ( afx, fp );
80         }
81     }
82
83   if (!opt.outfile)
84     {
85       no_out = 1;
86       opt.outfile = "-";
87     }
88   rc = proc_encryption_packets (ctrl, NULL, fp );
89   if (no_out)
90     opt.outfile = NULL;
91
92   iobuf_close (fp);
93   release_armor_context (afx);
94   release_progress_context (pfx);
95   return rc;
96 }
97
98
99 /* Same as decrypt_message but takes a file descriptor for input and
100    output.  */
101 gpg_error_t
102 decrypt_message_fd (ctrl_t ctrl, int input_fd, int output_fd)
103 {
104 #ifdef HAVE_W32_SYSTEM
105   /* No server mode yet.  */
106   (void)ctrl;
107   (void)input_fd;
108   (void)output_fd;
109   return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
110 #else
111   gpg_error_t err;
112   IOBUF fp;
113   armor_filter_context_t *afx = NULL;
114   progress_filter_context_t *pfx;
115
116   if (opt.outfp)
117     return gpg_error (GPG_ERR_BUG);
118
119   pfx = new_progress_context ();
120
121   /* Open the message file.  */
122   fp = iobuf_fdopen_nc (FD2INT(input_fd), "rb");
123   if (fp && is_secured_file (iobuf_get_fd (fp)))
124     {
125       iobuf_close (fp);
126       fp = NULL;
127       gpg_err_set_errno (EPERM);
128     }
129   if (!fp)
130     {
131       char xname[64];
132
133       err = gpg_error_from_syserror ();
134       snprintf (xname, sizeof xname, "[fd %d]", input_fd);
135       log_error (_("can't open '%s': %s\n"), xname, gpg_strerror (err));
136       release_progress_context (pfx);
137       return err;
138     }
139
140 #ifdef HAVE_W32CE_SYSTEM
141 #warning Need to fix this if we want to use g13
142   opt.outfp = NULL;
143 #else
144   opt.outfp = es_fdopen_nc (output_fd, "wb");
145 #endif
146   if (!opt.outfp)
147     {
148       char xname[64];
149
150       err = gpg_error_from_syserror ();
151       snprintf (xname, sizeof xname, "[fd %d]", output_fd);
152       log_error (_("can't open '%s': %s\n"), xname, gpg_strerror (err));
153       iobuf_close (fp);
154       release_progress_context (pfx);
155       return err;
156     }
157
158   if (!opt.no_armor)
159     {
160       if (use_armor_filter (fp))
161         {
162           afx = new_armor_context ();
163           push_armor_filter ( afx, fp );
164         }
165     }
166
167   err = proc_encryption_packets (ctrl, NULL, fp );
168
169   iobuf_close (fp);
170   es_fclose (opt.outfp);
171   opt.outfp = NULL;
172   release_armor_context (afx);
173   release_progress_context (pfx);
174   return err;
175 #endif
176 }
177
178
179 void
180 decrypt_messages (ctrl_t ctrl, int nfiles, char *files[])
181 {
182   IOBUF fp;
183   progress_filter_context_t *pfx;
184   char *p, *output = NULL;
185   int rc=0,use_stdin=0;
186   unsigned int lno=0;
187
188   if (opt.outfile)
189     {
190       log_error(_("--output doesn't work for this command\n"));
191       return;
192     }
193
194   pfx = new_progress_context ();
195
196   if(!nfiles)
197     use_stdin=1;
198
199   for(;;)
200     {
201       char line[2048];
202       char *filename=NULL;
203
204       if(use_stdin)
205         {
206           if(fgets(line, DIM(line), stdin))
207             {
208               lno++;
209               if (!*line || line[strlen(line)-1] != '\n')
210                 log_error("input line %u too long or missing LF\n", lno);
211               else
212                 {
213                   line[strlen(line)-1] = '\0';
214                   filename=line;
215                 }
216             }
217         }
218       else
219         {
220           if(nfiles)
221             {
222               filename=*files;
223               nfiles--;
224               files++;
225             }
226         }
227
228       if(filename==NULL)
229         break;
230
231       print_file_status(STATUS_FILE_START, filename, 3);
232       output = make_outfile_name(filename);
233       if (!output)
234         goto next_file;
235       fp = iobuf_open(filename);
236       if (fp)
237         iobuf_ioctl (fp, IOBUF_IOCTL_NO_CACHE, 1, NULL);
238       if (fp && is_secured_file (iobuf_get_fd (fp)))
239         {
240           iobuf_close (fp);
241           fp = NULL;
242           gpg_err_set_errno (EPERM);
243         }
244       if (!fp)
245         {
246           log_error(_("can't open '%s'\n"), print_fname_stdin(filename));
247           goto next_file;
248         }
249
250       handle_progress (pfx, fp, filename);
251
252       if (!opt.no_armor)
253         {
254           if (use_armor_filter(fp))
255             {
256               armor_filter_context_t *afx = new_armor_context ();
257               rc = push_armor_filter (afx, fp);
258               if (rc)
259                 log_error("failed to push armor filter");
260               release_armor_context (afx);
261             }
262         }
263       rc = proc_packets (ctrl,NULL, fp);
264       iobuf_close(fp);
265       if (rc)
266         log_error("%s: decryption failed: %s\n", print_fname_stdin(filename),
267                   gpg_strerror (rc));
268       p = get_last_passphrase();
269       set_next_passphrase(p);
270       xfree (p);
271
272     next_file:
273       /* Note that we emit file_done even after an error. */
274       write_status( STATUS_FILE_DONE );
275       xfree(output);
276       reset_literals_seen();
277     }
278
279   set_next_passphrase(NULL);
280   release_progress_context (pfx);
281 }