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/>.
38 #include "mountinfo.h"
42 /* Parse the header prefix and return the length of the entire header. */
44 parse_header (const char *filename
,
45 const unsigned char *packet
, size_t packetlen
,
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
);
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
);
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
);
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. */
98 read_keyblob_prefix (const char *filename
, estream_t
*r_fp
, size_t *r_headerlen
)
102 unsigned char packet
[32];
106 fp
= es_fopen (filename
, "rb");
109 err
= gpg_error_from_syserror ();
110 log_error ("error reading `%s': %s\n", filename
, gpg_strerror (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
));
124 err
= parse_header (filename
, packet
, 32, r_headerlen
);
134 /* Read the keyblob at FILENAME. The caller should have acquired a
135 lockfile and checked that the file exists. */
137 read_keyblob (const char *filename
,
138 void **r_enckeyblob
, size_t *r_enckeybloblen
)
142 size_t headerlen
, msglen
;
145 *r_enckeyblob
= NULL
;
146 *r_enckeybloblen
= 0;
148 err
= read_keyblob_prefix (filename
, &fp
, &headerlen
);
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;
164 err
= gpg_error (GPG_ERR_NO_DATA
);
167 msg
= xtrymalloc (msglen
);
170 err
= gpg_error_from_syserror ();
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
));
183 *r_enckeybloblen
= msglen
;
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. */
199 decrypt_keyblob (ctrl_t ctrl
, const void *enckeyblob
, size_t enckeybloblen
,
200 void **r_keyblob
, size_t *r_keybloblen
)
204 /* FIXME: For now we only implement OpenPGP. */
205 err
= gpg_decrypt_blob (ctrl
, enckeyblob
, enckeybloblen
,
206 r_keyblob
, r_keybloblen
);
213 dump_keyblob (tupledesc_t tuples
)
219 log_info ("keyblob dump:\n");
220 tag
= KEYBLOB_TAG_BLOBVERSION
;
221 value
= find_tuple (tuples
, tag
, &n
);
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");
229 log_printf ("[none]\n");
231 log_printhex ("", value
, n
);
232 value
= next_tuple (tuples
, &tag
, &n
);
238 /* Mount the container with name FILENAME at MOUNTPOINT. */
240 g13_mount_container (ctrl_t ctrl
, const char *filename
, const char *mountpoint
)
244 void *enckeyblob
= NULL
;
245 size_t enckeybloblen
;
246 void *keyblob
= NULL
;
248 tupledesc_t tuples
= NULL
;
250 const unsigned char *value
;
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
);
261 return gpg_error_from_syserror ();
263 if (make_dotlock (lock
, 0))
265 err
= gpg_error_from_syserror ();
271 /* Check again that the file exists. */
275 if (stat (filename
, &sb
))
277 err
= gpg_error_from_syserror ();
282 /* Read the encrypted keyblob. */
283 err
= read_keyblob (filename
, &enckeyblob
, &enckeybloblen
);
287 /* Decrypt that keyblob and store it in a tuple descriptor. */
288 err
= decrypt_keyblob (ctrl
, enckeyblob
, enckeybloblen
,
289 &keyblob
, &keybloblen
);
295 err
= create_tupledesc (&tuples
, keyblob
, keybloblen
);
300 if (gpg_err_code (err
) == GPG_ERR_NOT_SUPPORTED
)
301 log_error ("unknown keyblob version\n");
305 dump_keyblob (tuples
);
307 value
= find_tuple (tuples
, KEYBLOB_TAG_CONTTYPE
, &n
);
308 if (!value
|| n
!= 2)
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
);
318 err
= be_mount_container (ctrl
, conttype
, filename
, mountpoint
, tuples
, &rid
);
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? */
327 destroy_tupledesc (tuples
);
330 destroy_dotlock (lock
);
335 /* Unmount the container with name FILENAME or the one mounted at
336 MOUNTPOINT. If both are given the FILENAME takes precedence. */
338 g13_umount_container (ctrl_t ctrl
, const char *filename
, const char *mountpoint
)
346 if (!filename
&& !mountpoint
)
347 return gpg_error (GPG_ERR_ENOENT
);
348 err
= mountinfo_find_mount (filename
, mountpoint
, &rid
);
352 runner
= runner_find_by_rid (rid
);
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
);
366 /* Test whether the container with name FILENAME is a suitable G13
367 container. This function may even be called on a mounted
370 g13_is_container (ctrl_t ctrl
, const char *filename
)
378 /* Read just the prefix of the header. */
379 err
= read_keyblob_prefix (filename
, &fp
, &dummy
);