/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 | } |