Coverage Report

Created: 2026-02-26 06:54

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gnupg/g10/decrypt.c
Line
Count
Source
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
 * Copyright (C) 2024 g10 Code GmbH
5
 *
6
 * This file is part of GnuPG.
7
 *
8
 * GnuPG is free software; you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation; either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * GnuPG is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, see <https://www.gnu.org/licenses/>.
20
 * SPDX-License-Identifier: GPL-3.0-or-later
21
 */
22
23
#include <config.h>
24
#include <stdio.h>
25
#include <stdlib.h>
26
#include <string.h>
27
#include <errno.h>
28
29
#include "gpg.h"
30
#include "options.h"
31
#include "packet.h"
32
#include "../common/status.h"
33
#include "../common/iobuf.h"
34
#include "keydb.h"
35
#include "../common/util.h"
36
#include "main.h"
37
#include "../common/status.h"
38
#include "../common/i18n.h"
39
40
41
42
/* Assume that the input is an encrypted message and decrypt
43
 * (and if signed, verify the signature on) it.
44
 * This command differs from the default operation, as it never
45
 * writes to the filename which is included in the file and it
46
 * rejects files which don't begin with an encrypted message.
47
 *
48
 * REMUSR is only used in the modify_recipients mode and speicifies
49
 * the additional or new recipients to use.
50
 */
51
gpg_error_t
52
decrypt_message (ctrl_t ctrl, const char *filename, strlist_t remusr)
53
11
{
54
11
  gpg_error_t err;
55
11
  iobuf_t fp;
56
11
  armor_filter_context_t *afx = NULL;
57
11
  progress_filter_context_t *pfx;
58
11
  DEK *dek = NULL;
59
11
  struct seskey_enc_list *sesenc_list = NULL;
60
61
11
  pfx = new_progress_context ();
62
63
  /* Open the message file.  */
64
11
  fp = iobuf_open (filename);
65
11
  if (fp && is_secured_file (iobuf_get_fd (fp)))
66
0
    {
67
0
      iobuf_close (fp);
68
0
      fp = NULL;
69
0
      gpg_err_set_errno (EPERM);
70
0
    }
71
11
  if ( !fp )
72
0
    {
73
0
      err = gpg_error_from_syserror ();
74
0
      log_error (_("can't open '%s': %s\n"), print_fname_stdin(filename),
75
0
                 gpg_strerror (err));
76
0
      release_progress_context (pfx);
77
0
      return err;
78
0
    }
79
80
  /* Push the progress filter unless we are in add recipient mode.
81
   * The latter may also work but for now we better avoid any possible
82
   * complications.  */
83
11
  if (!ctrl->modify_recipients)
84
11
    handle_progress (pfx, fp, filename);
85
86
11
  if ( !opt.no_armor )
87
11
    {
88
11
      if ( use_armor_filter( fp ) )
89
7
        {
90
7
          afx = new_armor_context ();
91
7
          push_armor_filter ( afx, fp );
92
7
  }
93
11
    }
94
95
11
  if (!opt.outfile)
96
11
    {
97
11
      opt.outfile = "-";
98
11
      opt.flags.dummy_outfile = 1;
99
11
    }
100
0
  else
101
0
    opt.flags.dummy_outfile = 0;
102
11
  if (!ctrl->modify_recipients)
103
11
    err = proc_encryption_packets (ctrl, NULL, fp, NULL, NULL);
104
0
  else
105
0
    err = proc_encryption_packets (ctrl, NULL, fp, &dek, &sesenc_list);
106
11
  if (opt.flags.dummy_outfile)
107
11
    opt.outfile = NULL;
108
109
11
  if (ctrl->modify_recipients && (err || !dek) )
110
11
    log_error (_("modifying the recipients is not possible: %s\n"),
111
0
               err? gpg_strerror (err) : _("decryption failed"));
112
11
  else if (ctrl->modify_recipients)
113
0
    {
114
      /* We apply an armor to the output if --armor was used or if the
115
       * input was already armored and --no-armor was not given.  */
116
0
      int armor = opt.armor || (was_armored (afx) && !opt.no_armor);
117
118
0
      err = reencrypt_to_new_recipients (ctrl, armor, filename, fp,
119
0
                                         remusr, dek, sesenc_list);
120
0
    }
121
122
11
  xfree (dek);
123
11
  free_seskey_enc_list (sesenc_list);
124
11
  iobuf_close (fp);
125
11
  release_armor_context (afx);
126
11
  release_progress_context (pfx);
127
11
  return err;
128
11
}
129
130
131
/* Same as decrypt_message but takes a file descriptor for input and
132
   output.  Only used by the unfinished server mode.  */
133
gpg_error_t
134
decrypt_message_fd (ctrl_t ctrl, gnupg_fd_t input_fd,
135
                    gnupg_fd_t output_fd)
136
0
{
137
#ifdef HAVE_W32_SYSTEM
138
  /* No server mode yet.  */
139
  (void)ctrl;
140
  (void)input_fd;
141
  (void)output_fd;
142
  return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
143
#else
144
0
  gpg_error_t err;
145
0
  IOBUF fp;
146
0
  armor_filter_context_t *afx = NULL;
147
0
  progress_filter_context_t *pfx;
148
149
0
  if (opt.outfp)
150
0
    return gpg_error (GPG_ERR_BUG);
151
152
0
  pfx = new_progress_context ();
153
154
  /* Open the message file.  */
155
0
  fp = iobuf_fdopen_nc (input_fd, "rb");
156
0
  if (fp && is_secured_file (iobuf_get_fd (fp)))
157
0
    {
158
0
      iobuf_close (fp);
159
0
      fp = NULL;
160
0
      gpg_err_set_errno (EPERM);
161
0
    }
162
0
  if (!fp)
163
0
    {
164
0
      char xname[64];
165
166
0
      err = gpg_error_from_syserror ();
167
0
      snprintf (xname, sizeof xname, "[fd %d]", input_fd);
168
0
      log_error (_("can't open '%s': %s\n"), xname, gpg_strerror (err));
169
0
      release_progress_context (pfx);
170
0
      return err;
171
0
    }
172
173
0
  if (is_secured_file (output_fd))
174
0
    {
175
0
      char xname[64];
176
177
0
      err = gpg_error (GPG_ERR_EPERM);
178
0
      snprintf (xname, sizeof xname, "[fd %d]", FD_DBG (output_fd));
179
0
      log_error (_("can't open '%s': %s\n"), xname, gpg_strerror (err));
180
0
      iobuf_close (fp);
181
0
      release_progress_context (pfx);
182
0
      return err;
183
0
    }
184
185
0
  opt.outfp = open_stream_nc (output_fd, "w");
186
0
  if (!opt.outfp)
187
0
    {
188
0
      char xname[64];
189
190
0
      err = gpg_error_from_syserror ();
191
0
      snprintf (xname, sizeof xname, "[fd %d]", FD_DBG (output_fd));
192
0
      log_error (_("can't open '%s': %s\n"), xname, gpg_strerror (err));
193
0
      iobuf_close (fp);
194
0
      release_progress_context (pfx);
195
0
      return err;
196
0
    }
197
198
0
  if (!opt.no_armor)
199
0
    {
200
0
      if (use_armor_filter (fp))
201
0
        {
202
0
          afx = new_armor_context ();
203
0
          push_armor_filter ( afx, fp );
204
0
  }
205
0
    }
206
207
0
  err = proc_encryption_packets (ctrl, NULL, fp, NULL, NULL);
208
209
0
  iobuf_close (fp);
210
0
  es_fclose (opt.outfp);
211
0
  opt.outfp = NULL;
212
0
  release_armor_context (afx);
213
0
  release_progress_context (pfx);
214
0
  return err;
215
0
#endif
216
0
}
217
218
219
void
220
decrypt_messages (ctrl_t ctrl, int nfiles, char *files[])
221
11
{
222
11
  IOBUF fp;
223
11
  progress_filter_context_t *pfx;
224
11
  char *p, *output = NULL;
225
11
  int rc=0,use_stdin=0;
226
11
  unsigned int lno=0;
227
228
11
  if (opt.outfile)
229
0
    {
230
0
      log_error(_("--output doesn't work for this command\n"));
231
0
      return;
232
0
    }
233
234
11
  pfx = new_progress_context ();
235
236
11
  if(!nfiles)
237
0
    use_stdin=1;
238
239
11
  for(;;)
240
22
    {
241
22
      char line[2048];
242
22
      char *filename=NULL;
243
244
22
      if(use_stdin)
245
0
  {
246
0
    if(fgets(line, DIM(line), stdin))
247
0
      {
248
0
        lno++;
249
0
        if (!*line || line[strlen(line)-1] != '\n')
250
0
    log_error("input line %u too long or missing LF\n", lno);
251
0
        else
252
0
    {
253
0
      line[strlen(line)-1] = '\0';
254
0
      filename=line;
255
0
    }
256
0
      }
257
0
  }
258
22
      else
259
22
  {
260
22
    if(nfiles)
261
11
      {
262
11
        filename=*files;
263
11
        nfiles--;
264
11
        files++;
265
11
      }
266
22
  }
267
268
22
      if(filename==NULL)
269
11
  break;
270
271
11
      print_file_status(STATUS_FILE_START, filename, 3);
272
11
      output = make_outfile_name(filename);
273
11
      if (!output)
274
0
        goto next_file;
275
11
      fp = iobuf_open(filename);
276
11
      if (fp)
277
11
        iobuf_ioctl (fp, IOBUF_IOCTL_NO_CACHE, 1, NULL);
278
11
      if (fp && is_secured_file (iobuf_get_fd (fp)))
279
0
        {
280
0
          iobuf_close (fp);
281
0
          fp = NULL;
282
0
          gpg_err_set_errno (EPERM);
283
0
        }
284
11
      if (!fp)
285
0
        {
286
0
          log_error(_("can't open '%s'\n"), print_fname_stdin(filename));
287
0
          goto next_file;
288
0
        }
289
290
11
      handle_progress (pfx, fp, filename);
291
292
11
      if (!opt.no_armor)
293
11
        {
294
11
          if (use_armor_filter(fp))
295
7
            {
296
7
              armor_filter_context_t *afx = new_armor_context ();
297
7
              rc = push_armor_filter (afx, fp);
298
7
              if (rc)
299
7
                log_error("failed to push armor filter");
300
7
              release_armor_context (afx);
301
7
            }
302
11
        }
303
11
      rc = proc_packets (ctrl,NULL, fp);
304
11
      iobuf_close(fp);
305
11
      if (rc)
306
11
        log_error("%s: decryption failed: %s\n", print_fname_stdin(filename),
307
2
                  gpg_strerror (rc));
308
11
      p = get_last_passphrase();
309
11
      set_next_passphrase(p);
310
11
      xfree (p);
311
312
11
    next_file:
313
      /* Note that we emit file_done even after an error. */
314
11
      write_status( STATUS_FILE_DONE );
315
11
      xfree(output);
316
11
      reset_literals_seen();
317
11
    }
318
319
11
  set_next_passphrase(NULL);
320
11
  release_progress_context (pfx);
321
11
}