scd: Error code map fix for older Yubikey.
[gnupg.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 "../common/status.h"
31 #include "../common/iobuf.h"
32 #include "keydb.h"
33 #include "../common/util.h"
34 #include "main.h"
35 #include "../common/status.h"
36 #include "../common/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
52   pfx = new_progress_context ();
53
54   /* Open the message file.  */
55   fp = iobuf_open (filename);
56   if (fp && is_secured_file (iobuf_get_fd (fp)))
57     {
58       iobuf_close (fp);
59       fp = NULL;
60       gpg_err_set_errno (EPERM);
61     }
62   if ( !fp )
63     {
64       rc = gpg_error_from_syserror ();
65       log_error (_("can't open '%s': %s\n"), print_fname_stdin(filename),
66                  gpg_strerror (rc));
67       release_progress_context (pfx);
68       return rc;
69     }
70
71   handle_progress (pfx, fp, filename);
72
73   if ( !opt.no_armor )
74     {
75       if ( use_armor_filter( fp ) )
76         {
77           afx = new_armor_context ();
78           push_armor_filter ( afx, fp );
79         }
80     }
81
82   if (!opt.outfile)
83     {
84       opt.outfile = "-";
85       opt.flags.dummy_outfile = 1;
86     }
87   else
88     opt.flags.dummy_outfile = 0;
89   rc = proc_encryption_packets (ctrl, NULL, fp );
90   if (opt.flags.dummy_outfile)
91     opt.outfile = NULL;
92
93   iobuf_close (fp);
94   release_armor_context (afx);
95   release_progress_context (pfx);
96   return rc;
97 }
98
99
100 /* Same as decrypt_message but takes a file descriptor for input and
101    output.  */
102 gpg_error_t
103 decrypt_message_fd (ctrl_t ctrl, int input_fd, int output_fd)
104 {
105 #ifdef HAVE_W32_SYSTEM
106   /* No server mode yet.  */
107   (void)ctrl;
108   (void)input_fd;
109   (void)output_fd;
110   return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
111 #else
112   gpg_error_t err;
113   IOBUF fp;
114   armor_filter_context_t *afx = NULL;
115   progress_filter_context_t *pfx;
116
117   if (opt.outfp)
118     return gpg_error (GPG_ERR_BUG);
119
120   pfx = new_progress_context ();
121
122   /* Open the message file.  */
123   fp = iobuf_fdopen_nc (FD2INT(input_fd), "rb");
124   if (fp && is_secured_file (iobuf_get_fd (fp)))
125     {
126       iobuf_close (fp);
127       fp = NULL;
128       gpg_err_set_errno (EPERM);
129     }
130   if (!fp)
131     {
132       char xname[64];
133
134       err = gpg_error_from_syserror ();
135       snprintf (xname, sizeof xname, "[fd %d]", input_fd);
136       log_error (_("can't open '%s': %s\n"), xname, gpg_strerror (err));
137       release_progress_context (pfx);
138       return err;
139     }
140
141 #ifdef HAVE_W32CE_SYSTEM
142 #warning Need to fix this if we want to use g13
143   opt.outfp = NULL;
144 #else
145   opt.outfp = es_fdopen_nc (output_fd, "wb");
146 #endif
147   if (!opt.outfp)
148     {
149       char xname[64];
150
151       err = gpg_error_from_syserror ();
152       snprintf (xname, sizeof xname, "[fd %d]", output_fd);
153       log_error (_("can't open '%s': %s\n"), xname, gpg_strerror (err));
154       iobuf_close (fp);
155       release_progress_context (pfx);
156       return err;
157     }
158
159   if (!opt.no_armor)
160     {
161       if (use_armor_filter (fp))
162         {
163           afx = new_armor_context ();
164           push_armor_filter ( afx, fp );
165         }
166     }
167
168   err = proc_encryption_packets (ctrl, NULL, fp );
169
170   iobuf_close (fp);
171   es_fclose (opt.outfp);
172   opt.outfp = NULL;
173   release_armor_context (afx);
174   release_progress_context (pfx);
175   return err;
176 #endif
177 }
178
179
180 void
181 decrypt_messages (ctrl_t ctrl, int nfiles, char *files[])
182 {
183   IOBUF fp;
184   progress_filter_context_t *pfx;
185   char *p, *output = NULL;
186   int rc=0,use_stdin=0;
187   unsigned int lno=0;
188
189   if (opt.outfile)
190     {
191       log_error(_("--output doesn't work for this command\n"));
192       return;
193     }
194
195   pfx = new_progress_context ();
196
197   if(!nfiles)
198     use_stdin=1;
199
200   for(;;)
201     {
202       char line[2048];
203       char *filename=NULL;
204
205       if(use_stdin)
206         {
207           if(fgets(line, DIM(line), stdin))
208             {
209               lno++;
210               if (!*line || line[strlen(line)-1] != '\n')
211                 log_error("input line %u too long or missing LF\n", lno);
212               else
213                 {
214                   line[strlen(line)-1] = '\0';
215                   filename=line;
216                 }
217             }
218         }
219       else
220         {
221           if(nfiles)
222             {
223               filename=*files;
224               nfiles--;
225               files++;
226             }
227         }
228
229       if(filename==NULL)
230         break;
231
232       print_file_status(STATUS_FILE_START, filename, 3);
233       output = make_outfile_name(filename);
234       if (!output)
235         goto next_file;
236       fp = iobuf_open(filename);
237       if (fp)
238         iobuf_ioctl (fp, IOBUF_IOCTL_NO_CACHE, 1, NULL);
239       if (fp && is_secured_file (iobuf_get_fd (fp)))
240         {
241           iobuf_close (fp);
242           fp = NULL;
243           gpg_err_set_errno (EPERM);
244         }
245       if (!fp)
246         {
247           log_error(_("can't open '%s'\n"), print_fname_stdin(filename));
248           goto next_file;
249         }
250
251       handle_progress (pfx, fp, filename);
252
253       if (!opt.no_armor)
254         {
255           if (use_armor_filter(fp))
256             {
257               armor_filter_context_t *afx = new_armor_context ();
258               rc = push_armor_filter (afx, fp);
259               if (rc)
260                 log_error("failed to push armor filter");
261               release_armor_context (afx);
262             }
263         }
264       rc = proc_packets (ctrl,NULL, fp);
265       iobuf_close(fp);
266       if (rc)
267         log_error("%s: decryption failed: %s\n", print_fname_stdin(filename),
268                   gpg_strerror (rc));
269       p = get_last_passphrase();
270       set_next_passphrase(p);
271       xfree (p);
272
273     next_file:
274       /* Note that we emit file_done even after an error. */
275       write_status( STATUS_FILE_DONE );
276       xfree(output);
277       reset_literals_seen();
278     }
279
280   set_next_passphrase(NULL);
281   release_progress_context (pfx);
282 }