Coverage Report

Created: 2026-01-10 07:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gnupg/g10/openfile.c
Line
Count
Source
1
/* openfile.c
2
 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2009,
3
 *               2010 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
#include <sys/types.h>
27
#include <sys/stat.h>
28
#include <fcntl.h>
29
#include <unistd.h>
30
31
#include "gpg.h"
32
#include "../common/util.h"
33
#include "../common/ttyio.h"
34
#include "options.h"
35
#include "main.h"
36
#include "../common/status.h"
37
#include "../common/i18n.h"
38
39
#ifdef HAVE_W32_SYSTEM
40
#define NAME_OF_DEV_NULL "nul"
41
#else
42
0
#define NAME_OF_DEV_NULL "/dev/null"
43
#endif
44
45
46
#if defined (HAVE_DRIVE_LETTERS) || defined (__riscos__)
47
#define CMP_FILENAME(a,b) ascii_strcasecmp( (a), (b) )
48
#else
49
52
#define CMP_FILENAME(a,b) strcmp( (a), (b) )
50
#endif
51
52
53
/* FIXME:  Implement opt.interactive. */
54
55
/*
56
 * Check whether FNAME exists and ask if it's okay to overwrite an
57
 * existing one.
58
 * Returns: True: it's okay to overwrite or the file does not exist
59
 *      False: Do not overwrite
60
 */
61
int
62
overwrite_filep( const char *fname )
63
1
{
64
1
  if ( iobuf_is_pipe_filename (fname) )
65
0
    return 1; /* Writing to stdout is always okay.  */
66
67
1
  if ( gnupg_access( fname, F_OK ) )
68
1
    return 1; /* Does not exist.  */
69
70
0
  if ( !compare_filenames (fname, NAME_OF_DEV_NULL) )
71
0
    return 1; /* Does not do any harm.  */
72
73
0
  if (opt.answer_yes)
74
0
    return 1;
75
0
  if (opt.answer_no || opt.batch)
76
0
    return 0;  /* Do not overwrite.  */
77
78
0
  tty_printf (_("File '%s' exists. "), fname);
79
0
  if (cpr_enabled ())
80
0
    tty_printf ("\n");
81
0
  if (cpr_get_answer_is_yes ("openfile.overwrite.okay",
82
0
                             _("Overwrite? (y/N) ")) )
83
0
    return 1;
84
0
  return 0;
85
0
}
86
87
88
/*
89
 * Strip known extensions from iname and return a newly allocated
90
 * filename.  Return NULL if we can't do that.
91
 */
92
char *
93
make_outfile_name (const char *iname)
94
13
{
95
13
  size_t n;
96
97
13
  if (iobuf_is_pipe_filename (iname))
98
0
    return xstrdup ("-");
99
100
13
  n = strlen (iname);
101
13
  if (n > 4 && (!CMP_FILENAME(iname+n-4, EXTSEP_S GPGEXT_GPG)
102
0
                || !CMP_FILENAME(iname+n-4, EXTSEP_S "pgp")
103
0
                || !CMP_FILENAME(iname+n-4, EXTSEP_S "sig")
104
0
                || !CMP_FILENAME(iname+n-4, EXTSEP_S "asc")))
105
13
    {
106
13
      char *buf = xstrdup (iname);
107
13
      buf[n-4] = 0;
108
13
      return buf;
109
13
    }
110
0
  else if (n > 5 && !CMP_FILENAME(iname+n-5, EXTSEP_S "sign"))
111
0
    {
112
0
      char *buf = xstrdup (iname);
113
0
      buf[n-5] = 0;
114
0
      return buf;
115
0
    }
116
117
13
  log_info (_("%s: unknown suffix\n"), iname);
118
0
  return NULL;
119
13
}
120
121
122
/* Ask for an output filename; use the given one as default.  Return
123
   NULL if no file has been given or if it is not possible to ask the
124
   user.  NAME is the template len which might contain enbedded Nuls.
125
   NAMELEN is its actual length.
126
 */
127
char *
128
ask_outfile_name (const char *name, size_t namelen)
129
0
{
130
0
  size_t n;
131
0
  const char *s;
132
0
  char *prompt;
133
0
  char *fname;
134
0
  char *defname;
135
136
0
  if ( opt.batch )
137
0
    return NULL;
138
139
  /* To avoid tricking the user into using the embedded filename we do
140
   * not anymore include that name in the prompt as default.  For
141
   * modern v5 signature this might make sense as they are now covered
142
   * by the signature but we better leave such a decision to a GUI.  */
143
0
  if (name && namelen && (opt.compat_flags & COMPAT_SUGGEST_EMBEDDED_NAME))
144
0
    defname = make_printable_string (name, namelen, 0);
145
0
  else
146
0
    defname = NULL;
147
0
  s = _("Enter new filename");
148
0
  n = strlen(s) + (defname?strlen (defname):0) + 10;
149
0
  prompt = xmalloc (n);
150
0
  if (defname)
151
0
    snprintf (prompt, n, "%s [%s]: ", s, defname );
152
0
  else
153
0
    snprintf (prompt, n, "%s: ", s );
154
0
  tty_enable_completion(NULL);
155
0
  fname = cpr_get ("openfile.askoutname", prompt );
156
0
  cpr_kill_prompt ();
157
0
  tty_disable_completion ();
158
0
  xfree (prompt);
159
0
  if ( !*fname )
160
0
    {
161
0
      xfree (fname);
162
0
      fname = defname;
163
0
      defname = NULL;
164
0
    }
165
0
  xfree (defname);
166
0
  if (fname)
167
0
    trim_spaces (fname);
168
0
  return fname;
169
0
}
170
171
172
/*
173
 * Make an output filename for the inputfile INAME.
174
 * Returns an IOBUF at A and an errorcode
175
 * Mode 0 = use ".gpg"
176
 *  1 = use ".asc"
177
 *  2 = use ".sig"
178
 *      3 = use ".rev"
179
 *
180
 * With RESTRICTEDPERM a file will be created with mode 700 if
181
 * possible.
182
 *
183
 * If OUT_FD is not -1 the function simply creates an IOBUF for that
184
 * file descriptor and ignores INAME and MODE.  Note that OUT_FD won't
185
 * be closed if the returned IOBUF is closed.  This is used for gpg's
186
 * --server mode.  */
187
int
188
open_outfile (gnupg_fd_t out_fd, const char *iname, int mode,
189
              int restrictedperm, iobuf_t *a)
190
0
{
191
0
  int rc = 0;
192
193
0
  *a = NULL;
194
0
  if (out_fd != GNUPG_INVALID_FD)
195
0
    {
196
0
      char xname[64];
197
198
0
      *a = iobuf_fdopen_nc (out_fd, "wb");
199
0
      if (!*a)
200
0
        {
201
0
          rc = gpg_error_from_syserror ();
202
0
          snprintf (xname, sizeof xname, "[fd %d]", FD_DBG (out_fd));
203
0
          log_error (_("can't open '%s': %s\n"), xname, gpg_strerror (rc));
204
0
        }
205
0
      else if (opt.verbose)
206
0
        {
207
0
          snprintf (xname, sizeof xname, "[fd %d]", FD_DBG (out_fd));
208
0
          log_info (_("writing to '%s'\n"), xname);
209
0
        }
210
0
    }
211
0
  else if (iobuf_is_pipe_filename (iname) && !opt.outfile)
212
0
    {
213
0
      *a = iobuf_create (NULL, 0);
214
0
      if ( !*a )
215
0
        {
216
0
          rc = gpg_error_from_syserror ();
217
0
          log_error (_("can't open '%s': %s\n"), "[stdout]", strerror(errno) );
218
0
        }
219
0
      else if ( opt.verbose )
220
0
        log_info (_("writing to stdout\n"));
221
0
    }
222
0
  else
223
0
    {
224
0
      char *buf = NULL;
225
0
      const char *name;
226
227
0
      if (opt.dry_run)
228
0
        name = NAME_OF_DEV_NULL;
229
0
      else if (opt.outfile)
230
0
        name = opt.outfile;
231
0
      else
232
0
        {
233
#ifdef USE_ONLY_8DOT3
234
          if (opt.mangle_dos_filenames)
235
            {
236
              /* It is quite common for DOS systems to have only one
237
                 dot in a filename.  If we have something like this,
238
                 we simple replace the suffix except in cases where
239
                 the suffix is larger than 3 characters and not the
240
                 same as the new one.  We don't map the filenames to
241
                 8.3 because this is a duty of the file system.  */
242
              char *dot;
243
              const char *newsfx;
244
245
              newsfx = (mode==1 ? ".asc" :
246
                        mode==2 ? ".sig" :
247
                        mode==3 ? ".rev" : ".gpg");
248
249
              buf = xmalloc (strlen(iname)+4+1);
250
              strcpy (buf, iname);
251
              dot = strchr (buf, '.' );
252
              if ( dot && dot > buf && dot[1] && strlen(dot) <= 4
253
                   && CMP_FILENAME (newsfx, dot) )
254
                strcpy (dot, newsfx);
255
              else if (dot && !dot[1]) /* Do not duplicate a dot.  */
256
                strcpy (dot, newsfx+1);
257
              else
258
                strcat (buf, newsfx);
259
            }
260
          if (!buf)
261
#endif /* USE_ONLY_8DOT3 */
262
0
            {
263
0
              buf = xstrconcat (iname,
264
0
                                (mode==1 ? EXTSEP_S "asc" :
265
0
                                 mode==2 ? EXTSEP_S "sig" :
266
0
                                 mode==3 ? EXTSEP_S "rev" :
267
0
                                 /*     */ EXTSEP_S GPGEXT_GPG),
268
0
                                NULL);
269
0
            }
270
0
          name = buf;
271
0
        }
272
273
0
      rc = 0;
274
0
      while ( !overwrite_filep (name) )
275
0
        {
276
0
          char *tmp = ask_outfile_name (NULL, 0);
277
0
          if ( !tmp || !*tmp )
278
0
            {
279
0
              xfree (tmp);
280
0
              rc = gpg_error (GPG_ERR_EEXIST);
281
0
              break;
282
0
            }
283
0
          xfree (buf);
284
0
          name = buf = tmp;
285
0
        }
286
287
0
      if ( !rc )
288
0
        {
289
0
          if (is_secured_filename (name) )
290
0
            {
291
0
              *a = NULL;
292
0
              gpg_err_set_errno (EPERM);
293
0
            }
294
0
          else
295
0
            *a = iobuf_create (name, restrictedperm);
296
0
          if (!*a)
297
0
            {
298
0
              rc = gpg_error_from_syserror ();
299
0
              log_error(_("can't create '%s': %s\n"), name, strerror(errno) );
300
0
            }
301
0
          else if( opt.verbose )
302
0
            log_info (_("writing to '%s'\n"), name );
303
0
        }
304
0
      xfree(buf);
305
0
    }
306
307
0
  if (*a)
308
0
    iobuf_ioctl (*a, IOBUF_IOCTL_NO_CACHE, 1, NULL);
309
310
0
  return rc;
311
0
}
312
313
314
/* Find a matching data file for the signature file SIGFILENAME and
315
   return it as a malloced string.  If no matching data file is found,
316
   return NULL.  */
317
char *
318
get_matching_datafile (const char *sigfilename)
319
209k
{
320
209k
  char *fname = NULL;
321
209k
  size_t len;
322
323
209k
  if (iobuf_is_pipe_filename (sigfilename))
324
0
    return NULL;
325
326
209k
  len = strlen (sigfilename);
327
209k
  if (len > 4
328
209k
      && (!strcmp (sigfilename + len - 4, EXTSEP_S "sig")
329
209k
          || (len > 5 && !strcmp(sigfilename + len - 5, EXTSEP_S "sign"))
330
209k
          || !strcmp(sigfilename + len - 4, EXTSEP_S "asc")))
331
0
    {
332
333
0
      fname = xstrdup (sigfilename);
334
0
      fname[len-(fname[len-1]=='n'?5:4)] = 0 ;
335
0
      if (gnupg_access (fname, R_OK ))
336
0
        {
337
          /* Not found or other error.  */
338
0
          xfree (fname);
339
0
          fname = NULL;
340
0
        }
341
0
    }
342
343
209k
  return fname;
344
209k
}
345
346
347
/*
348
 * Try to open a file without the extension ".sig" or ".asc"
349
 * Return NULL if such a file is not available.
350
 */
351
iobuf_t
352
open_sigfile (const char *sigfilename, progress_filter_context_t *pfx)
353
209k
{
354
209k
  iobuf_t a = NULL;
355
209k
  char *buf;
356
357
209k
  buf = get_matching_datafile (sigfilename);
358
209k
  if (buf)
359
0
    {
360
0
      a = iobuf_open (buf);
361
0
      if (a && is_secured_file (iobuf_get_fd (a)))
362
0
        {
363
0
          iobuf_close (a);
364
0
          a = NULL;
365
0
          gpg_err_set_errno (EPERM);
366
0
        }
367
0
      if (a)
368
0
        log_info (_("assuming signed data in '%s'\n"), buf);
369
0
      if (a && pfx)
370
0
        handle_progress (pfx, a, buf);
371
0
      xfree (buf);
372
0
    }
373
374
209k
  return a;
375
209k
}
376
377
378
/* Create the directory only if the supplied directory name is the
379
   same as the default one.  This way we avoid to create arbitrary
380
   directories when a non-default home directory is used.  To cope
381
   with HOME, we do compare only the suffix if we see that the default
382
   homedir does start with a tilde.  */
383
void
384
try_make_homedir (const char *fname)
385
0
{
386
0
  if ( opt.dry_run || opt.no_homedir_creation )
387
0
    return;
388
389
0
  gnupg_maybe_make_homedir (fname, opt.quiet);
390
0
}
391
392
393
/* Get and if needed create a string with the directory used to store
394
   openpgp revocations.  */
395
char *
396
get_openpgp_revocdir (const char *home)
397
0
{
398
0
  char *fname;
399
0
  struct stat statbuf;
400
401
0
  fname = make_filename (home, GNUPG_OPENPGP_REVOC_DIR, NULL);
402
0
  if (gnupg_stat (fname, &statbuf) && errno == ENOENT)
403
0
    {
404
0
      if (gnupg_mkdir (fname, "-rwx"))
405
0
        log_error (_("can't create directory '%s': %s\n"),
406
0
                   fname, strerror (errno) );
407
0
      else if (!opt.quiet)
408
0
        log_info (_("directory '%s' created\n"), fname);
409
0
    }
410
0
  return fname;
411
0
}