Fix regression introduced by "editing only change".
[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 <http://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 #include <assert.h>
27
28 #include "gpg.h"
29 #include "options.h"
30 #include "packet.h"
31 #include "status.h"
32 #include "iobuf.h"
33 #include "keydb.h"
34 #include "util.h"
35 #include "main.h"
36 #include "status.h"
37 #include "i18n.h"
38
39 /* Assume that the input is an encrypted message and decrypt
40  * (and if signed, verify the signature on) it.
41  * This command differs from the default operation, as it never
42  * writes to the filename which is included in the file and it
43  * rejects files which don't begin with an encrypted message.
44  */
45 int
46 decrypt_message (ctrl_t ctrl, const char *filename)
47 {
48   IOBUF fp;
49   armor_filter_context_t *afx = NULL;
50   progress_filter_context_t *pfx;
51   int rc;
52   int no_out = 0;
53
54   pfx = new_progress_context ();
55   
56   /* Open the message file.  */
57   fp = iobuf_open (filename);
58   if (fp && is_secured_file (iobuf_get_fd (fp)))
59     {
60       iobuf_close (fp);
61       fp = NULL;
62       gpg_err_set_errno (EPERM);
63     }
64   if ( !fp )
65     {
66       rc = gpg_error_from_syserror ();
67       log_error (_("can't open `%s': %s\n"), print_fname_stdin(filename),
68                  gpg_strerror (rc));
69       release_progress_context (pfx);
70       return rc;
71     }
72
73   handle_progress (pfx, fp, filename);
74
75   if ( !opt.no_armor )
76     {
77       if ( use_armor_filter( fp ) )
78         {
79           afx = new_armor_context ();
80           push_armor_filter ( afx, fp );
81         }
82     }
83
84   if (!opt.outfile)
85     {
86       no_out = 1;
87       opt.outfile = "-";
88     }
89   rc = proc_encryption_packets (ctrl, NULL, fp );
90   if (no_out)
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   gpg_error_t err;
106   IOBUF fp;
107   armor_filter_context_t *afx = NULL;
108   progress_filter_context_t *pfx;
109
110   if (opt.outfp)
111     return gpg_error (GPG_ERR_BUG);
112
113   pfx = new_progress_context ();
114   
115   /* Open the message file.  */
116   fp = iobuf_open_fd_or_name (input_fd, NULL, "rb");
117   if (fp && is_secured_file (iobuf_get_fd (fp)))
118     {
119       iobuf_close (fp);
120       fp = NULL;
121       gpg_err_set_errno (EPERM);
122     }
123   if (!fp)
124     {
125       char xname[64];
126       
127       err = gpg_error_from_syserror ();
128       snprintf (xname, sizeof xname, "[fd %d]", input_fd);
129       log_error (_("can't open `%s': %s\n"), xname, gpg_strerror (err));
130       release_progress_context (pfx);
131       return err;
132     }
133
134 #ifdef HAVE_W32CE_SYSTEM
135 #warning Need to fix this if we want to use g13
136   opt.outfp = NULL;
137 #else
138   opt.outfp = es_fdopen_nc (output_fd, "wb");
139 #endif
140   if (!opt.outfp)
141     {
142       char xname[64];
143
144       err = gpg_error_from_syserror ();
145       snprintf (xname, sizeof xname, "[fd %d]", output_fd);
146       log_error (_("can't open `%s': %s\n"), xname, gpg_strerror (err));
147       iobuf_close (fp);
148       release_progress_context (pfx);
149       return err;
150     }
151
152   if (!opt.no_armor)
153     {
154       if (use_armor_filter (fp))
155         {
156           afx = new_armor_context ();
157           push_armor_filter ( afx, fp );
158         }
159     }
160
161   err = proc_encryption_packets (ctrl, NULL, fp );
162
163   iobuf_close (fp);
164   es_fclose (opt.outfp);
165   opt.outfp = NULL;
166   release_armor_context (afx);
167   release_progress_context (pfx);
168   return err;
169 }
170
171
172 void
173 decrypt_messages (ctrl_t ctrl, int nfiles, char *files[])
174 {
175   IOBUF fp;
176   armor_filter_context_t *afx = NULL;  
177   progress_filter_context_t *pfx;
178   char *p, *output = NULL;
179   int rc=0,use_stdin=0;
180   unsigned int lno=0;
181   
182   if (opt.outfile)
183     {
184       log_error(_("--output doesn't work for this command\n"));
185       return;
186     }
187
188   pfx = new_progress_context ();
189
190   if(!nfiles)
191     use_stdin=1;
192
193   for(;;)
194     {
195       char line[2048];
196       char *filename=NULL;
197
198       if(use_stdin)
199         {
200           if(fgets(line, DIM(line), stdin))
201             {
202               lno++;
203               if (!*line || line[strlen(line)-1] != '\n')
204                 log_error("input line %u too long or missing LF\n", lno);
205               else
206                 {
207                   line[strlen(line)-1] = '\0';
208                   filename=line;
209                 }
210             }
211         }
212       else
213         {
214           if(nfiles)
215             {
216               filename=*files;
217               nfiles--;
218               files++;
219             }
220         }
221
222       if(filename==NULL)
223         break;
224
225       print_file_status(STATUS_FILE_START, filename, 3);      
226       output = make_outfile_name(filename);
227       if (!output)
228         goto next_file;
229       fp = iobuf_open(filename);
230       if (fp)
231         iobuf_ioctl (fp, IOBUF_IOCTL_NO_CACHE, 1, NULL);
232       if (fp && is_secured_file (iobuf_get_fd (fp)))
233         {
234           iobuf_close (fp);
235           fp = NULL;
236           gpg_err_set_errno (EPERM);
237         }
238       if (!fp)
239         {
240           log_error(_("can't open `%s'\n"), print_fname_stdin(filename));
241           goto next_file;
242         }
243
244       handle_progress (pfx, fp, filename);
245
246       if (!opt.no_armor)
247         {
248           if (use_armor_filter(fp))
249             {
250               afx = new_armor_context ();
251               push_armor_filter ( afx, fp );
252             }
253         }
254       rc = proc_packets (ctrl,NULL, fp);
255       iobuf_close(fp);
256       if (rc)
257         log_error("%s: decryption failed: %s\n", print_fname_stdin(filename),
258                   g10_errstr(rc));
259       p = get_last_passphrase();
260       set_next_passphrase(p);
261       xfree (p);
262
263     next_file:
264       /* Note that we emit file_done even after an error. */
265       write_status( STATUS_FILE_DONE );
266       xfree(output);
267       reset_literals_seen();
268     }
269
270   set_next_passphrase(NULL);  
271   release_armor_context (afx);
272   release_progress_context (pfx);
273 }