po/
[gnupg.git] / g13 / mount.c
blobdc23b6b2b3d7b3910fadd841934b487e255168e3
1 /* mount.c - Mount a crypto container
2 * Copyright (C) 2009 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * GnuPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include <config.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <unistd.h>
26 #include <sys/stat.h>
27 #include <assert.h>
29 #include "g13.h"
30 #include "i18n.h"
31 #include "mount.h"
33 #include "keyblob.h"
34 #include "backend.h"
35 #include "utils.h"
36 #include "call-gpg.h"
37 #include "estream.h"
38 #include "mountinfo.h"
39 #include "runner.h"
42 /* Parse the header prefix and return the length of the entire header. */
43 static gpg_error_t
44 parse_header (const char *filename,
45 const unsigned char *packet, size_t packetlen,
46 size_t *r_headerlen)
48 unsigned int len;
50 if (packetlen != 32)
51 return gpg_error (GPG_ERR_BUG);
53 len = ((packet[2] << 24) | (packet[3] << 16)
54 | (packet[4] << 8) | packet[5]);
55 if (packet[0] != (0xc0|61) || len < 26
56 || memcmp (packet+6, "GnuPG/G13", 10))
58 log_error ("file `%s' is not valid container\n", filename);
59 return gpg_error (GPG_ERR_INV_OBJ);
61 if (packet[16] != 1)
63 log_error ("unknown version %u of container `%s'\n",
64 (unsigned int)packet[16], filename);
65 return gpg_error (GPG_ERR_INV_OBJ);
67 if (packet[17] || packet[18]
68 || packet[26] || packet[27] || packet[28] || packet[29]
69 || packet[30] || packet[31])
70 log_info ("WARNING: unknown meta information in `%s'\n", filename);
71 if (packet[19])
72 log_info ("WARNING: OS flag is not supported in `%s'\n", filename);
73 if (packet[24] != 1 || packet[25] != 0)
75 log_error ("meta data copies in `%s' are not supported\n", filename);
76 return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
79 len = ((packet[20] << 24) | (packet[21] << 16)
80 | (packet[22] << 8) | packet[23]);
82 /* Do a basic sanity check on the length. */
83 if (len < 32 || len > 1024*1024)
85 log_error ("bad length given in container `%s'\n", filename);
86 return gpg_error (GPG_ERR_INV_OBJ);
89 *r_headerlen = len;
90 return 0;
94 /* Read the prefix of the keyblob and do some basic parsing. On
95 success returns an open estream file at R_FP and the length of the
96 header at R_HEADERLEN. */
97 static gpg_error_t
98 read_keyblob_prefix (const char *filename, estream_t *r_fp, size_t *r_headerlen)
100 gpg_error_t err;
101 estream_t fp;
102 unsigned char packet[32];
104 *r_fp = NULL;
106 fp = es_fopen (filename, "rb");
107 if (!fp)
109 err = gpg_error_from_syserror ();
110 log_error ("error reading `%s': %s\n", filename, gpg_strerror (err));
111 return err;
114 /* Read the header. It is defined as 32 bytes thus we read it in one go. */
115 if (es_fread (packet, 32, 1, fp) != 1)
117 err = gpg_error_from_syserror ();
118 log_error ("error reading the header of `%s': %s\n",
119 filename, gpg_strerror (err));
120 es_fclose (fp);
121 return err;
124 err = parse_header (filename, packet, 32, r_headerlen);
125 if (err)
126 es_fclose (fp);
127 else
128 *r_fp = fp;
130 return err;
134 /* Read the keyblob at FILENAME. The caller should have acquired a
135 lockfile and checked that the file exists. */
136 static gpg_error_t
137 read_keyblob (const char *filename,
138 void **r_enckeyblob, size_t *r_enckeybloblen)
140 gpg_error_t err;
141 estream_t fp = NULL;
142 size_t headerlen, msglen;
143 void *msg = NULL;
145 *r_enckeyblob = NULL;
146 *r_enckeybloblen = 0;
148 err = read_keyblob_prefix (filename, &fp, &headerlen);
149 if (err)
150 goto leave;
152 if (opt.verbose)
153 log_info ("header length of `%s' is %zu\n", filename, headerlen);
155 /* Read everything including the padding. We should eventually do a
156 regular OpenPGP parsing to detect the padding packet and pass
157 only the actual used OpenPGP data to the engine. This is in
158 particular required when supporting CMS which will be
159 encapsulated in an OpenPGP packet. */
160 assert (headerlen >= 32);
161 msglen = headerlen - 32;
162 if (!msglen)
164 err = gpg_error (GPG_ERR_NO_DATA);
165 goto leave;
167 msg = xtrymalloc (msglen);
168 if (!msglen)
170 err = gpg_error_from_syserror ();
171 goto leave;
173 if (es_fread (msg, msglen, 1, fp) != 1)
175 err = gpg_error_from_syserror ();
176 log_error ("error reading keyblob of `%s': %s\n",
177 filename, gpg_strerror (err));
178 goto leave;
181 *r_enckeyblob = msg;
182 msg = NULL;
183 *r_enckeybloblen = msglen;
185 leave:
186 xfree (msg);
187 es_fclose (fp);
189 return err;
195 /* Decrypt the keyblob (ENCKEYBLOB,ENCKEYBLOBLEN) and store the result at
196 (R_KEYBLOB, R_KEYBLOBLEN). Returns 0 on success or an error code.
197 On error R_KEYBLOB is set to NULL. */
198 static gpg_error_t
199 decrypt_keyblob (ctrl_t ctrl, const void *enckeyblob, size_t enckeybloblen,
200 void **r_keyblob, size_t *r_keybloblen)
202 gpg_error_t err;
204 /* FIXME: For now we only implement OpenPGP. */
205 err = gpg_decrypt_blob (ctrl, enckeyblob, enckeybloblen,
206 r_keyblob, r_keybloblen);
208 return err;
212 static void
213 dump_keyblob (tupledesc_t tuples)
215 size_t n;
216 unsigned int tag;
217 const void *value;
219 log_info ("keyblob dump:\n");
220 tag = KEYBLOB_TAG_BLOBVERSION;
221 value = find_tuple (tuples, tag, &n);
222 while (value)
224 log_info (" tag: %-5u len: %-2u value: ", tag, (unsigned int)n);
225 if (tag == KEYBLOB_TAG_ENCKEY
226 || tag == KEYBLOB_TAG_MACKEY)
227 log_printf ("[confidential]\n");
228 else if (!n)
229 log_printf ("[none]\n");
230 else
231 log_printhex ("", value, n);
232 value = next_tuple (tuples, &tag, &n);
238 /* Mount the container with name FILENAME at MOUNTPOINT. */
239 gpg_error_t
240 g13_mount_container (ctrl_t ctrl, const char *filename, const char *mountpoint)
242 gpg_error_t err;
243 dotlock_t lock;
244 void *enckeyblob = NULL;
245 size_t enckeybloblen;
246 void *keyblob = NULL;
247 size_t keybloblen;
248 tupledesc_t tuples = NULL;
249 size_t n;
250 const unsigned char *value;
251 int conttype;
252 unsigned int rid;
254 /* A quick check to see whether the container exists. */
255 if (access (filename, R_OK))
256 return gpg_error_from_syserror ();
258 /* Try to take a lock. */
259 lock = create_dotlock (filename);
260 if (!lock)
261 return gpg_error_from_syserror ();
263 if (make_dotlock (lock, 0))
265 err = gpg_error_from_syserror ();
266 goto leave;
268 else
269 err = 0;
271 /* Check again that the file exists. */
273 struct stat sb;
275 if (stat (filename, &sb))
277 err = gpg_error_from_syserror ();
278 goto leave;
282 /* Read the encrypted keyblob. */
283 err = read_keyblob (filename, &enckeyblob, &enckeybloblen);
284 if (err)
285 goto leave;
287 /* Decrypt that keyblob and store it in a tuple descriptor. */
288 err = decrypt_keyblob (ctrl, enckeyblob, enckeybloblen,
289 &keyblob, &keybloblen);
290 if (err)
291 goto leave;
292 xfree (enckeyblob);
293 enckeyblob = NULL;
295 err = create_tupledesc (&tuples, keyblob, keybloblen);
296 if (!err)
297 keyblob = NULL;
298 else
300 if (gpg_err_code (err) == GPG_ERR_NOT_SUPPORTED)
301 log_error ("unknown keyblob version\n");
302 goto leave;
304 if (opt.verbose)
305 dump_keyblob (tuples);
307 value = find_tuple (tuples, KEYBLOB_TAG_CONTTYPE, &n);
308 if (!value || n != 2)
309 conttype = 0;
310 else
311 conttype = (value[0] << 8 | value[1]);
312 if (!be_is_supported_conttype (conttype))
314 log_error ("content type %d is not supported\n", conttype);
315 err = gpg_error (GPG_ERR_NOT_SUPPORTED);
316 goto leave;
318 err = be_mount_container (ctrl, conttype, filename, mountpoint, tuples, &rid);
319 if (!err)
321 err = mountinfo_add_mount (filename, mountpoint, conttype, rid);
322 /* Fixme: What shall we do if this fails? Add a provisional
323 mountinfo entry first and remove it on error? */
326 leave:
327 destroy_tupledesc (tuples);
328 xfree (keyblob);
329 xfree (enckeyblob);
330 destroy_dotlock (lock);
331 return err;
335 /* Unmount the container with name FILENAME or the one mounted at
336 MOUNTPOINT. If both are given the FILENAME takes precedence. */
337 gpg_error_t
338 g13_umount_container (ctrl_t ctrl, const char *filename, const char *mountpoint)
340 gpg_error_t err;
341 unsigned int rid;
342 runner_t runner;
344 (void)ctrl;
346 if (!filename && !mountpoint)
347 return gpg_error (GPG_ERR_ENOENT);
348 err = mountinfo_find_mount (filename, mountpoint, &rid);
349 if (err)
350 return err;
352 runner = runner_find_by_rid (rid);
353 if (!runner)
355 log_error ("runner %u not found\n", rid);
356 return gpg_error (GPG_ERR_NOT_FOUND);
359 runner_cancel (runner);
360 runner_release (runner);
362 return 0;
366 /* Test whether the container with name FILENAME is a suitable G13
367 container. This function may even be called on a mounted
368 container. */
369 gpg_error_t
370 g13_is_container (ctrl_t ctrl, const char *filename)
372 gpg_error_t err;
373 estream_t fp = NULL;
374 size_t dummy;
376 (void)ctrl;
378 /* Read just the prefix of the header. */
379 err = read_keyblob_prefix (filename, &fp, &dummy);
380 if (!err)
381 es_fclose (fp);
382 return err;