512e29d1a652a35a302092755fe111748631854a
[gnupg.git] / g13 / mount.c
1 /* mount.c - Mount a crypto container
2  * Copyright (C) 2009 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
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.
10  *
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.
15  *
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/>.
18  */
19
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>
28
29 #include "g13.h"
30 #include "i18n.h"
31 #include "mount.h"
32
33 #include "keyblob.h"
34 #include "backend.h"
35 #include "utils.h"
36 #include "call-gpg.h"
37 #include "mountinfo.h"
38 #include "runner.h"
39
40
41 /* Parse the header prefix and return the length of the entire header.  */
42 static gpg_error_t
43 parse_header (const char *filename,
44               const unsigned char *packet, size_t packetlen,
45               size_t *r_headerlen)
46 {
47   unsigned int len;
48
49   if (packetlen != 32)
50     return gpg_error (GPG_ERR_BUG);
51
52   len = ((packet[2] << 24) | (packet[3] << 16)
53          | (packet[4] << 8) | packet[5]);
54   if (packet[0] != (0xc0|61) || len < 26
55       || memcmp (packet+6, "GnuPG/G13", 10))
56     {
57       log_error ("file '%s' is not valid container\n", filename);
58       return gpg_error (GPG_ERR_INV_OBJ);
59     }
60   if (packet[16] != 1)
61     {
62       log_error ("unknown version %u of container '%s'\n",
63                  (unsigned int)packet[16], filename);
64       return gpg_error (GPG_ERR_INV_OBJ);
65     }
66   if (packet[17] || packet[18]
67       || packet[26] || packet[27] || packet[28] || packet[29]
68       || packet[30] || packet[31])
69     log_info ("WARNING: unknown meta information in '%s'\n", filename);
70   if (packet[19])
71     log_info ("WARNING: OS flag is not supported in '%s'\n", filename);
72   if (packet[24] != 1 || packet[25] != 0)
73     {
74       log_error ("meta data copies in '%s' are not supported\n", filename);
75       return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
76     }
77
78   len = ((packet[20] << 24) | (packet[21] << 16)
79          | (packet[22] << 8) | packet[23]);
80
81   /* Do a basic sanity check on the length.  */
82   if (len < 32 || len > 1024*1024)
83     {
84       log_error ("bad length given in container '%s'\n", filename);
85       return gpg_error (GPG_ERR_INV_OBJ);
86     }
87
88   *r_headerlen = len;
89   return 0;
90 }
91
92
93 /* Read the prefix of the keyblob and do some basic parsing.  On
94    success returns an open estream file at R_FP and the length of the
95    header at R_HEADERLEN.  */
96 static gpg_error_t
97 read_keyblob_prefix (const char *filename, estream_t *r_fp, size_t *r_headerlen)
98 {
99   gpg_error_t err;
100   estream_t fp;
101   unsigned char packet[32];
102
103   *r_fp = NULL;
104
105   fp = es_fopen (filename, "rb");
106   if (!fp)
107     {
108       err = gpg_error_from_syserror ();
109       log_error ("error reading '%s': %s\n", filename, gpg_strerror (err));
110       return err;
111     }
112
113   /* Read the header.  It is defined as 32 bytes thus we read it in one go.  */
114   if (es_fread (packet, 32, 1, fp) != 1)
115     {
116       err = gpg_error_from_syserror ();
117       log_error ("error reading the header of '%s': %s\n",
118                  filename, gpg_strerror (err));
119       es_fclose (fp);
120       return err;
121     }
122
123   err = parse_header (filename, packet, 32, r_headerlen);
124   if (err)
125     es_fclose (fp);
126   else
127     *r_fp = fp;
128
129   return err;
130 }
131
132
133 /* Read the keyblob at FILENAME.  The caller should have acquired a
134    lockfile and checked that the file exists.  */
135 static gpg_error_t
136 read_keyblob (const char *filename,
137               void **r_enckeyblob, size_t *r_enckeybloblen)
138 {
139   gpg_error_t err;
140   estream_t fp = NULL;
141   size_t headerlen, msglen;
142   void *msg = NULL;
143
144   *r_enckeyblob = NULL;
145   *r_enckeybloblen = 0;
146
147   err = read_keyblob_prefix (filename, &fp, &headerlen);
148   if (err)
149     goto leave;
150
151   if (opt.verbose)
152     log_info ("header length of '%s' is %zu\n", filename, headerlen);
153
154   /* Read everything including the padding.  We should eventually do a
155      regular OpenPGP parsing to detect the padding packet and pass
156      only the actual used OpenPGP data to the engine.  This is in
157      particular required when supporting CMS which will be
158      encapsulated in an OpenPGP packet.  */
159   assert (headerlen >= 32);
160   msglen = headerlen - 32;
161   if (!msglen)
162     {
163       err = gpg_error (GPG_ERR_NO_DATA);
164       goto leave;
165     }
166   msg = xtrymalloc (msglen);
167   if (!msglen)
168     {
169       err = gpg_error_from_syserror ();
170       goto leave;
171     }
172   if (es_fread (msg, msglen, 1, fp) != 1)
173     {
174       err = gpg_error_from_syserror ();
175       log_error ("error reading keyblob of '%s': %s\n",
176                  filename, gpg_strerror (err));
177       goto leave;
178     }
179
180   *r_enckeyblob = msg;
181   msg = NULL;
182   *r_enckeybloblen = msglen;
183
184  leave:
185   xfree (msg);
186   es_fclose (fp);
187
188   return err;
189 }
190
191
192
193
194 /* Decrypt the keyblob (ENCKEYBLOB,ENCKEYBLOBLEN) and store the result at
195    (R_KEYBLOB, R_KEYBLOBLEN).  Returns 0 on success or an error code.
196    On error R_KEYBLOB is set to NULL.  */
197 static gpg_error_t
198 decrypt_keyblob (ctrl_t ctrl, const void *enckeyblob, size_t enckeybloblen,
199                  void **r_keyblob, size_t *r_keybloblen)
200 {
201   gpg_error_t err;
202
203   /* FIXME:  For now we only implement OpenPGP.  */
204   err = gpg_decrypt_blob (ctrl, enckeyblob, enckeybloblen,
205                           r_keyblob, r_keybloblen);
206
207   return err;
208 }
209
210
211 static void
212 dump_keyblob (tupledesc_t tuples)
213 {
214   size_t n;
215   unsigned int tag;
216   const void *value;
217
218   log_info ("keyblob dump:\n");
219   tag = KEYBLOB_TAG_BLOBVERSION;
220   value = find_tuple (tuples, tag, &n);
221   while (value)
222     {
223       log_info ("   tag: %-5u len: %-2u value: ", tag, (unsigned int)n);
224       if (tag == KEYBLOB_TAG_ENCKEY
225           ||  tag == KEYBLOB_TAG_MACKEY)
226         log_printf ("[confidential]\n");
227       else if (!n)
228         log_printf ("[none]\n");
229       else
230         log_printhex ("", value, n);
231       value = next_tuple (tuples, &tag, &n);
232     }
233 }
234
235
236
237 /* Mount the container with name FILENAME at MOUNTPOINT.  */
238 gpg_error_t
239 g13_mount_container (ctrl_t ctrl, const char *filename, const char *mountpoint)
240 {
241   gpg_error_t err;
242   dotlock_t lock;
243   void *enckeyblob = NULL;
244   size_t enckeybloblen;
245   void *keyblob = NULL;
246   size_t keybloblen;
247   tupledesc_t tuples = NULL;
248   size_t n;
249   const unsigned char *value;
250   int conttype;
251   unsigned int rid;
252   char *mountpoint_buffer = NULL;
253
254   /* A quick check to see whether the container exists.  */
255   if (access (filename, R_OK))
256     return gpg_error_from_syserror ();
257
258   if (!mountpoint)
259     {
260       mountpoint_buffer = xtrystrdup ("/tmp/g13-XXXXXX");
261       if (!mountpoint_buffer)
262         return gpg_error_from_syserror ();
263       if (!mkdtemp (mountpoint_buffer))
264         {
265           err = gpg_error_from_syserror ();
266           log_error (_("can't create directory '%s': %s\n"),
267                      "/tmp/g13-XXXXXX", gpg_strerror (err));
268           xfree (mountpoint_buffer);
269           return err;
270         }
271       mountpoint = mountpoint_buffer;
272     }
273
274   /* Try to take a lock.  */
275   lock = dotlock_create (filename, 0);
276   if (!lock)
277     {
278       xfree (mountpoint_buffer);
279       return gpg_error_from_syserror ();
280     }
281
282   if (dotlock_take (lock, 0))
283     {
284       err = gpg_error_from_syserror ();
285       goto leave;
286     }
287   else
288     err = 0;
289
290   /* Check again that the file exists.  */
291   {
292     struct stat sb;
293
294     if (stat (filename, &sb))
295       {
296         err = gpg_error_from_syserror ();
297         goto leave;
298       }
299   }
300
301   /* Read the encrypted keyblob.  */
302   err = read_keyblob (filename, &enckeyblob, &enckeybloblen);
303   if (err)
304     goto leave;
305
306   /* Decrypt that keyblob and store it in a tuple descriptor.  */
307   err = decrypt_keyblob (ctrl, enckeyblob, enckeybloblen,
308                          &keyblob, &keybloblen);
309   if (err)
310     goto leave;
311   xfree (enckeyblob);
312   enckeyblob = NULL;
313
314   err = create_tupledesc (&tuples, keyblob, keybloblen);
315   if (!err)
316     keyblob = NULL;
317   else
318     {
319       if (gpg_err_code (err) == GPG_ERR_NOT_SUPPORTED)
320         log_error ("unknown keyblob version\n");
321       goto leave;
322     }
323   if (opt.verbose)
324     dump_keyblob (tuples);
325
326   value = find_tuple (tuples, KEYBLOB_TAG_CONTTYPE, &n);
327   if (!value || n != 2)
328     conttype = 0;
329   else
330     conttype = (value[0] << 8 | value[1]);
331   if (!be_is_supported_conttype (conttype))
332     {
333       log_error ("content type %d is not supported\n", conttype);
334       err = gpg_error (GPG_ERR_NOT_SUPPORTED);
335       goto leave;
336     }
337   err = be_mount_container (ctrl, conttype, filename, mountpoint, tuples, &rid);
338   if (!err)
339     {
340       err = mountinfo_add_mount (filename, mountpoint, conttype, rid,
341                                  !!mountpoint_buffer);
342       /* Fixme: What shall we do if this fails?  Add a provisional
343          mountinfo entry first and remove it on error? */
344       if (!err)
345         {
346           char *tmp = percent_plus_escape (mountpoint);
347           if (!tmp)
348             err = gpg_error_from_syserror ();
349           else
350             {
351               g13_status (ctrl, STATUS_MOUNTPOINT, tmp, NULL);
352               xfree (tmp);
353             }
354         }
355     }
356
357  leave:
358   destroy_tupledesc (tuples);
359   xfree (keyblob);
360   xfree (enckeyblob);
361   dotlock_destroy (lock);
362   xfree (mountpoint_buffer);
363   return err;
364 }
365
366
367 /* Unmount the container with name FILENAME or the one mounted at
368    MOUNTPOINT.  If both are given the FILENAME takes precedence.  */
369 gpg_error_t
370 g13_umount_container (ctrl_t ctrl, const char *filename, const char *mountpoint)
371 {
372   gpg_error_t err;
373   unsigned int rid;
374   runner_t runner;
375
376   (void)ctrl;
377
378   if (!filename && !mountpoint)
379     return gpg_error (GPG_ERR_ENOENT);
380   err = mountinfo_find_mount (filename, mountpoint, &rid);
381   if (err)
382     return err;
383
384   runner = runner_find_by_rid (rid);
385   if (!runner)
386     {
387       log_error ("runner %u not found\n", rid);
388       return gpg_error (GPG_ERR_NOT_FOUND);
389     }
390
391   runner_cancel (runner);
392   runner_release (runner);
393
394   return 0;
395 }
396
397
398 /* Test whether the container with name FILENAME is a suitable G13
399    container.  This function may even be called on a mounted
400    container.  */
401 gpg_error_t
402 g13_is_container (ctrl_t ctrl, const char *filename)
403 {
404   gpg_error_t err;
405   estream_t fp = NULL;
406   size_t dummy;
407
408   (void)ctrl;
409
410   /* Read just the prefix of the header.  */
411   err = read_keyblob_prefix (filename, &fp, &dummy);
412   if (!err)
413     es_fclose (fp);
414   return err;
415 }