Coverage Report

Created: 2022-12-08 06:09

/src/gnupg/g10/openfile.c
Line
Count
Source (jump to first uncovered line)
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
0
#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
0
{
64
0
  if ( iobuf_is_pipe_filename (fname) )
65
0
    return 1; /* Writing to stdout is always okay.  */
66
67
0
  if ( gnupg_access( fname, F_OK ) )
68
0
    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
0
{
95
0
  size_t n;
96
97
0
  if (iobuf_is_pipe_filename (iname))
98
0
    return xstrdup ("-");
99
100
0
  n = strlen (iname);
101
0
  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
0
    {
106
0
      char *buf = xstrdup (iname);
107
0
      buf[n-4] = 0;
108
0
      return buf;
109
0
    }
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
0
  log_info (_("%s: unknown suffix\n"), iname);
118
0
  return NULL;
119
0
}
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
0
  defname = name && namelen? make_printable_string (name, namelen, 0) : NULL;
140
141
0
  s = _("Enter new filename");
142
0
  n = strlen(s) + (defname?strlen (defname):0) + 10;
143
0
  prompt = xmalloc (n);
144
0
  if (defname)
145
0
    snprintf (prompt, n, "%s [%s]: ", s, defname );
146
0
  else
147
0
    snprintf (prompt, n, "%s: ", s );
148
0
  tty_enable_completion(NULL);
149
0
  fname = cpr_get ("openfile.askoutname", prompt );
150
0
  cpr_kill_prompt ();
151
0
  tty_disable_completion ();
152
0
  xfree (prompt);
153
0
  if ( !*fname )
154
0
    {
155
0
      xfree (fname);
156
0
      fname = defname;
157
0
      defname = NULL;
158
0
    }
159
0
  xfree (defname);
160
0
  if (fname)
161
0
    trim_spaces (fname);
162
0
  return fname;
163
0
}
164
165
166
/*
167
 * Make an output filename for the inputfile INAME.
168
 * Returns an IOBUF and an errorcode
169
 * Mode 0 = use ".gpg"
170
 *  1 = use ".asc"
171
 *  2 = use ".sig"
172
 *      3 = use ".rev"
173
 *
174
 * With RESTRICTEDPERM a file will be created with mode 700 if
175
 * possible.
176
 *
177
 * If OUT_FD is not -1 the function simply creates an IOBUF for that
178
 * file descriptor and ignores INAME and MODE.  Note that OUT_FD won't
179
 * be closed if the returned IOBUF is closed.  This is used for gpg's
180
 * --server mode.  */
181
int
182
open_outfile (int out_fd, const char *iname, int mode, int restrictedperm,
183
              iobuf_t *a)
184
0
{
185
0
  int rc = 0;
186
187
0
  *a = NULL;
188
0
  if (out_fd != -1)
189
0
    {
190
0
      char xname[64];
191
192
0
      *a = iobuf_fdopen_nc (out_fd, "wb");
193
0
      if (!*a)
194
0
        {
195
0
          rc = gpg_error_from_syserror ();
196
0
          snprintf (xname, sizeof xname, "[fd %d]", out_fd);
197
0
          log_error (_("can't open '%s': %s\n"), xname, gpg_strerror (rc));
198
0
        }
199
0
      else if (opt.verbose)
200
0
        {
201
0
          snprintf (xname, sizeof xname, "[fd %d]", out_fd);
202
0
          log_info (_("writing to '%s'\n"), xname);
203
0
        }
204
0
    }
205
0
  else if (iobuf_is_pipe_filename (iname) && !opt.outfile)
206
0
    {
207
0
      *a = iobuf_create (NULL, 0);
208
0
      if ( !*a )
209
0
        {
210
0
          rc = gpg_error_from_syserror ();
211
0
          log_error (_("can't open '%s': %s\n"), "[stdout]", strerror(errno) );
212
0
        }
213
0
      else if ( opt.verbose )
214
0
        log_info (_("writing to stdout\n"));
215
0
    }
216
0
  else
217
0
    {
218
0
      char *buf = NULL;
219
0
      const char *name;
220
221
0
      if (opt.dry_run)
222
0
        name = NAME_OF_DEV_NULL;
223
0
      else if (opt.outfile)
224
0
        name = opt.outfile;
225
0
      else
226
0
        {
227
#ifdef USE_ONLY_8DOT3
228
          if (opt.mangle_dos_filenames)
229
            {
230
              /* It is quite common for DOS systems to have only one
231
                 dot in a filename.  If we have something like this,
232
                 we simple replace the suffix except in cases where
233
                 the suffix is larger than 3 characters and not the
234
                 same as the new one.  We don't map the filenames to
235
                 8.3 because this is a duty of the file system.  */
236
              char *dot;
237
              const char *newsfx;
238
239
              newsfx = (mode==1 ? ".asc" :
240
                        mode==2 ? ".sig" :
241
                        mode==3 ? ".rev" : ".gpg");
242
243
              buf = xmalloc (strlen(iname)+4+1);
244
              strcpy (buf, iname);
245
              dot = strchr (buf, '.' );
246
              if ( dot && dot > buf && dot[1] && strlen(dot) <= 4
247
                   && CMP_FILENAME (newsfx, dot) )
248
                strcpy (dot, newsfx);
249
              else if (dot && !dot[1]) /* Do not duplicate a dot.  */
250
                strcpy (dot, newsfx+1);
251
              else
252
                strcat (buf, newsfx);
253
            }
254
          if (!buf)
255
#endif /* USE_ONLY_8DOT3 */
256
0
            {
257
0
              buf = xstrconcat (iname,
258
0
                                (mode==1 ? EXTSEP_S "asc" :
259
0
                                 mode==2 ? EXTSEP_S "sig" :
260
0
                                 mode==3 ? EXTSEP_S "rev" :
261
                                 /*     */ EXTSEP_S GPGEXT_GPG),
262
0
                                NULL);
263
0
            }
264
0
          name = buf;
265
0
        }
266
267
0
      rc = 0;
268
0
      while ( !overwrite_filep (name) )
269
0
        {
270
0
          char *tmp = ask_outfile_name (NULL, 0);
271
0
          if ( !tmp || !*tmp )
272
0
            {
273
0
              xfree (tmp);
274
0
              rc = gpg_error (GPG_ERR_EEXIST);
275
0
              break;
276
0
            }
277
0
          xfree (buf);
278
0
          name = buf = tmp;
279
0
        }
280
281
0
      if ( !rc )
282
0
        {
283
0
          if (is_secured_filename (name) )
284
0
            {
285
0
              *a = NULL;
286
0
              gpg_err_set_errno (EPERM);
287
0
            }
288
0
          else
289
0
            *a = iobuf_create (name, restrictedperm);
290
0
          if (!*a)
291
0
            {
292
0
              rc = gpg_error_from_syserror ();
293
0
              log_error(_("can't create '%s': %s\n"), name, strerror(errno) );
294
0
            }
295
0
          else if( opt.verbose )
296
0
            log_info (_("writing to '%s'\n"), name );
297
0
        }
298
0
      xfree(buf);
299
0
    }
300
301
0
  if (*a)
302
0
    iobuf_ioctl (*a, IOBUF_IOCTL_NO_CACHE, 1, NULL);
303
304
0
  return rc;
305
0
}
306
307
308
/* Find a matching data file for the signature file SIGFILENAME and
309
   return it as a malloced string.  If no matching data file is found,
310
   return NULL.  */
311
char *
312
get_matching_datafile (const char *sigfilename)
313
182k
{
314
182k
  char *fname = NULL;
315
182k
  size_t len;
316
317
182k
  if (iobuf_is_pipe_filename (sigfilename))
318
0
    return NULL;
319
320
182k
  len = strlen (sigfilename);
321
182k
  if (len > 4
322
182k
      && (!strcmp (sigfilename + len - 4, EXTSEP_S "sig")
323
182k
          || (len > 5 && !strcmp(sigfilename + len - 5, EXTSEP_S "sign"))
324
182k
          || !strcmp(sigfilename + len - 4, EXTSEP_S "asc")))
325
0
    {
326
327
0
      fname = xstrdup (sigfilename);
328
0
      fname[len-(fname[len-1]=='n'?5:4)] = 0 ;
329
0
      if (gnupg_access (fname, R_OK ))
330
0
        {
331
          /* Not found or other error.  */
332
0
          xfree (fname);
333
0
          fname = NULL;
334
0
        }
335
0
    }
336
337
182k
  return fname;
338
182k
}
339
340
341
/*
342
 * Try to open a file without the extension ".sig" or ".asc"
343
 * Return NULL if such a file is not available.
344
 */
345
iobuf_t
346
open_sigfile (const char *sigfilename, progress_filter_context_t *pfx)
347
182k
{
348
182k
  iobuf_t a = NULL;
349
182k
  char *buf;
350
351
182k
  buf = get_matching_datafile (sigfilename);
352
182k
  if (buf)
353
0
    {
354
0
      a = iobuf_open (buf);
355
0
      if (a && is_secured_file (iobuf_get_fd (a)))
356
0
        {
357
0
          iobuf_close (a);
358
0
          a = NULL;
359
0
          gpg_err_set_errno (EPERM);
360
0
        }
361
0
      if (a)
362
0
        log_info (_("assuming signed data in '%s'\n"), buf);
363
0
      if (a && pfx)
364
0
        handle_progress (pfx, a, buf);
365
0
      xfree (buf);
366
0
    }
367
368
182k
  return a;
369
182k
}
370
371
372
/* Create the directory only if the supplied directory name is the
373
   same as the default one.  This way we avoid to create arbitrary
374
   directories when a non-default home directory is used.  To cope
375
   with HOME, we do compare only the suffix if we see that the default
376
   homedir does start with a tilde.  */
377
void
378
try_make_homedir (const char *fname)
379
0
{
380
0
  if ( opt.dry_run || opt.no_homedir_creation )
381
0
    return;
382
383
0
  gnupg_maybe_make_homedir (fname, opt.quiet);
384
0
}
385
386
387
/* Get and if needed create a string with the directory used to store
388
   openpgp revocations.  */
389
char *
390
get_openpgp_revocdir (const char *home)
391
0
{
392
0
  char *fname;
393
0
  struct stat statbuf;
394
395
0
  fname = make_filename (home, GNUPG_OPENPGP_REVOC_DIR, NULL);
396
0
  if (gnupg_stat (fname, &statbuf) && errno == ENOENT)
397
0
    {
398
0
      if (gnupg_mkdir (fname, "-rwx"))
399
0
        log_error (_("can't create directory '%s': %s\n"),
400
0
                   fname, strerror (errno) );
401
0
      else if (!opt.quiet)
402
0
        log_info (_("directory '%s' created\n"), fname);
403
0
    }
404
0
  return fname;
405
0
}