Reworked the server commands.
[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 "estream.h"
38 #include "mountinfo.h"
39 #include "runner.h"
40
41
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)
47 {
48   unsigned int len;
49
50   if (packetlen != 32)
51     return gpg_error (GPG_ERR_BUG);
52
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))
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 = ((packet[20] << 24) | (packet[21] << 16)
80          | (packet[22] << 8) | packet[23]);
81
82   /* Do a basic sanity check on the length.  */
83   if (len < 32 || len > 1024*1024)
84     {
85       log_error ("bad length given in container `%s'\n", filename);
86       return gpg_error (GPG_ERR_INV_OBJ);
87     }
88      
89   *r_headerlen = len;
90   return 0;
91 }
92
93
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)
99 {
100   gpg_error_t err;
101   estream_t fp;
102   unsigned char packet[32];
103   
104   *r_fp = NULL;
105
106   fp = es_fopen (filename, "rb");
107   if (!fp)
108     {
109       err = gpg_error_from_syserror ();
110       log_error ("error reading `%s': %s\n", filename, gpg_strerror (err));
111       return err;
112     }
113   
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)
116     {
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;
122     }
123   
124   err = parse_header (filename, packet, 32, r_headerlen);
125   if (err)
126     es_fclose (fp);
127   else
128     *r_fp = fp;
129
130   return err;
131 }
132
133
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)
139 {
140   gpg_error_t err;
141   estream_t fp = NULL;
142   size_t headerlen, 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
254   /* A quick check to see whether the container exists.  */
255   if (access (filename, R_OK))
256     return gpg_error_from_syserror ();
257
258   /* Try to take a lock.  */
259   lock = create_dotlock (filename);
260   if (!lock)
261     return gpg_error_from_syserror ();
262
263   if (make_dotlock (lock, 0))
264     {
265       err = gpg_error_from_syserror ();
266       goto leave;
267     }
268   else
269     err = 0;
270
271   /* Check again that the file exists.  */
272   {
273     struct stat sb;
274     
275     if (stat (filename, &sb))
276       {
277         err = gpg_error_from_syserror ();
278         goto leave;
279       }
280   }
281
282   /* Read the encrypted keyblob.  */
283   err = read_keyblob (filename, &enckeyblob, &enckeybloblen);
284   if (err)
285     goto leave;
286
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;
294
295   err = create_tupledesc (&tuples, keyblob, keybloblen);
296   if (!err)
297     keyblob = NULL;
298   else
299     {
300       if (gpg_err_code (err) == GPG_ERR_NOT_SUPPORTED)
301         log_error ("unknown keyblob version\n");
302       goto leave;
303     }
304   if (opt.verbose)
305     dump_keyblob (tuples);
306
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))
313     {
314       log_error ("content type %d is not supported\n", conttype);
315       err = gpg_error (GPG_ERR_NOT_SUPPORTED);
316       goto leave;
317     }
318   err = be_mount_container (ctrl, conttype, filename, mountpoint, tuples, &rid);
319   if (!err)
320     {
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? */
324     }
325
326  leave:
327   destroy_tupledesc (tuples);
328   xfree (keyblob);
329   xfree (enckeyblob);
330   destroy_dotlock (lock);
331   return err;
332 }
333
334
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)
339 {
340   gpg_error_t err;
341   unsigned int rid;
342   runner_t runner;
343
344   (void)ctrl;
345
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;
351   
352   runner = runner_find_by_rid (rid);
353   if (!runner)
354     {
355       log_error ("runner %u not found\n", rid);
356       return gpg_error (GPG_ERR_NOT_FOUND);
357     }
358
359   runner_cancel (runner);
360   runner_release (runner);
361   
362   return 0;
363 }
364
365
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)
371 {
372   gpg_error_t err;
373   estream_t fp = NULL;
374   size_t dummy;
375
376   (void)ctrl;
377
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;
383 }
384
385