Imported Upstream version 2.1.2
[platform/upstream/gpg2.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 "../common/sysutils.h"
37 #include "call-gpg.h"
38 #include "mountinfo.h"
39 #include "runner.h"
40 #include "host2net.h"
41
42
43 /* Parse the header prefix and return the length of the entire header.  */
44 static gpg_error_t
45 parse_header (const char *filename,
46               const unsigned char *packet, size_t packetlen,
47               size_t *r_headerlen)
48 {
49   unsigned int len;
50
51   if (packetlen != 32)
52     return gpg_error (GPG_ERR_BUG);
53
54   len = buf32_to_uint (packet+2);
55   if (packet[0] != (0xc0|61) || len < 26
56       || memcmp (packet+6, "GnuPG/G13", 10))
57     {
58       log_error ("file '%s' is not valid container\n", filename);
59       return gpg_error (GPG_ERR_INV_OBJ);
60     }
61   if (packet[16] != 1)
62     {
63       log_error ("unknown version %u of container '%s'\n",
64                  (unsigned int)packet[16], filename);
65       return gpg_error (GPG_ERR_INV_OBJ);
66     }
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)
74     {
75       log_error ("meta data copies in '%s' are not supported\n", filename);
76       return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
77     }
78
79   len = buf32_to_uint (packet+20);
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 = 0;
142   size_t msglen;
143   void *msg = NULL;
144
145   *r_enckeyblob = NULL;
146   *r_enckeybloblen = 0;
147
148   err = read_keyblob_prefix (filename, &fp, &headerlen);
149   if (err)
150     goto leave;
151
152   if (opt.verbose)
153     log_info ("header length of '%s' is %zu\n", filename, headerlen);
154
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)
163     {
164       err = gpg_error (GPG_ERR_NO_DATA);
165       goto leave;
166     }
167   msg = xtrymalloc (msglen);
168   if (!msglen)
169     {
170       err = gpg_error_from_syserror ();
171       goto leave;
172     }
173   if (es_fread (msg, msglen, 1, fp) != 1)
174     {
175       err = gpg_error_from_syserror ();
176       log_error ("error reading keyblob of '%s': %s\n",
177                  filename, gpg_strerror (err));
178       goto leave;
179     }
180
181   *r_enckeyblob = msg;
182   msg = NULL;
183   *r_enckeybloblen = msglen;
184
185  leave:
186   xfree (msg);
187   es_fclose (fp);
188
189   return err;
190 }
191
192
193
194
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)
201 {
202   gpg_error_t err;
203
204   /* FIXME:  For now we only implement OpenPGP.  */
205   err = gpg_decrypt_blob (ctrl, enckeyblob, enckeybloblen,
206                           r_keyblob, r_keybloblen);
207
208   return err;
209 }
210
211
212 static void
213 dump_keyblob (tupledesc_t tuples)
214 {
215   size_t n;
216   unsigned int tag;
217   const void *value;
218
219   log_info ("keyblob dump:\n");
220   tag = KEYBLOB_TAG_BLOBVERSION;
221   value = find_tuple (tuples, tag, &n);
222   while (value)
223     {
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);
233     }
234 }
235
236
237
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)
241 {
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;
253   char *mountpoint_buffer = NULL;
254
255   /* A quick check to see whether the container exists.  */
256   if (access (filename, R_OK))
257     return gpg_error_from_syserror ();
258
259   if (!mountpoint)
260     {
261       mountpoint_buffer = xtrystrdup ("/tmp/g13-XXXXXX");
262       if (!mountpoint_buffer)
263         return gpg_error_from_syserror ();
264       if (!gnupg_mkdtemp (mountpoint_buffer))
265         {
266           err = gpg_error_from_syserror ();
267           log_error (_("can't create directory '%s': %s\n"),
268                      "/tmp/g13-XXXXXX", gpg_strerror (err));
269           xfree (mountpoint_buffer);
270           return err;
271         }
272       mountpoint = mountpoint_buffer;
273     }
274
275   /* Try to take a lock.  */
276   lock = dotlock_create (filename, 0);
277   if (!lock)
278     {
279       xfree (mountpoint_buffer);
280       return gpg_error_from_syserror ();
281     }
282
283   if (dotlock_take (lock, 0))
284     {
285       err = gpg_error_from_syserror ();
286       goto leave;
287     }
288   else
289     err = 0;
290
291   /* Check again that the file exists.  */
292   {
293     struct stat sb;
294
295     if (stat (filename, &sb))
296       {
297         err = gpg_error_from_syserror ();
298         goto leave;
299       }
300   }
301
302   /* Read the encrypted keyblob.  */
303   err = read_keyblob (filename, &enckeyblob, &enckeybloblen);
304   if (err)
305     goto leave;
306
307   /* Decrypt that keyblob and store it in a tuple descriptor.  */
308   err = decrypt_keyblob (ctrl, enckeyblob, enckeybloblen,
309                          &keyblob, &keybloblen);
310   if (err)
311     goto leave;
312   xfree (enckeyblob);
313   enckeyblob = NULL;
314
315   err = create_tupledesc (&tuples, keyblob, keybloblen);
316   if (!err)
317     keyblob = NULL;
318   else
319     {
320       if (gpg_err_code (err) == GPG_ERR_NOT_SUPPORTED)
321         log_error ("unknown keyblob version\n");
322       goto leave;
323     }
324   if (opt.verbose)
325     dump_keyblob (tuples);
326
327   value = find_tuple (tuples, KEYBLOB_TAG_CONTTYPE, &n);
328   if (!value || n != 2)
329     conttype = 0;
330   else
331     conttype = (value[0] << 8 | value[1]);
332   if (!be_is_supported_conttype (conttype))
333     {
334       log_error ("content type %d is not supported\n", conttype);
335       err = gpg_error (GPG_ERR_NOT_SUPPORTED);
336       goto leave;
337     }
338   err = be_mount_container (ctrl, conttype, filename, mountpoint, tuples, &rid);
339   if (!err)
340     {
341       err = mountinfo_add_mount (filename, mountpoint, conttype, rid,
342                                  !!mountpoint_buffer);
343       /* Fixme: What shall we do if this fails?  Add a provisional
344          mountinfo entry first and remove it on error? */
345       if (!err)
346         {
347           char *tmp = percent_plus_escape (mountpoint);
348           if (!tmp)
349             err = gpg_error_from_syserror ();
350           else
351             {
352               g13_status (ctrl, STATUS_MOUNTPOINT, tmp, NULL);
353               xfree (tmp);
354             }
355         }
356     }
357
358  leave:
359   destroy_tupledesc (tuples);
360   xfree (keyblob);
361   xfree (enckeyblob);
362   dotlock_destroy (lock);
363   xfree (mountpoint_buffer);
364   return err;
365 }
366
367
368 /* Unmount the container with name FILENAME or the one mounted at
369    MOUNTPOINT.  If both are given the FILENAME takes precedence.  */
370 gpg_error_t
371 g13_umount_container (ctrl_t ctrl, const char *filename, const char *mountpoint)
372 {
373   gpg_error_t err;
374   unsigned int rid;
375   runner_t runner;
376
377   (void)ctrl;
378
379   if (!filename && !mountpoint)
380     return gpg_error (GPG_ERR_ENOENT);
381   err = mountinfo_find_mount (filename, mountpoint, &rid);
382   if (err)
383     return err;
384
385   runner = runner_find_by_rid (rid);
386   if (!runner)
387     {
388       log_error ("runner %u not found\n", rid);
389       return gpg_error (GPG_ERR_NOT_FOUND);
390     }
391
392   runner_cancel (runner);
393   runner_release (runner);
394
395   return 0;
396 }
397
398
399 /* Test whether the container with name FILENAME is a suitable G13
400    container.  This function may even be called on a mounted
401    container.  */
402 gpg_error_t
403 g13_is_container (ctrl_t ctrl, const char *filename)
404 {
405   gpg_error_t err;
406   estream_t fp = NULL;
407   size_t dummy;
408
409   (void)ctrl;
410
411   /* Read just the prefix of the header.  */
412   err = read_keyblob_prefix (filename, &fp, &dummy);
413   if (!err)
414     es_fclose (fp);
415   return err;
416 }