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