tests: Fix distcheck.
[gnupg.git] / g13 / backend.c
1 /* backend.c - Dispatcher to the various backends.
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 <https://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
28 #include "g13.h"
29 #include "../common/i18n.h"
30 #include "keyblob.h"
31 #include "backend.h"
32 #include "be-encfs.h"
33 #include "be-truecrypt.h"
34 #include "be-dmcrypt.h"
35 #include "call-syshelp.h"
36
37 #define no_such_backend(a) _no_such_backend ((a), __func__)
38 static gpg_error_t
39 _no_such_backend (int conttype, const char *func)
40 {
41   log_error ("invalid backend %d given in %s - this is most likely a bug\n",
42              conttype, func);
43   return gpg_error (GPG_ERR_INTERNAL);
44 }
45
46
47 /* Parse NAME and return the corresponding content type.  If the name
48    is not known, a error message is printed and zero returned.  If
49    NAME is NULL the supported backend types are listed and 0 is
50    returned. */
51 int
52 be_parse_conttype_name (const char *name)
53 {
54   static struct { const char *name; int conttype; } names[] = {
55     { "encfs",    CONTTYPE_ENCFS },
56     { "dm-crypt", CONTTYPE_DM_CRYPT }
57   };
58   int i;
59
60   if (!name)
61     {
62       log_info ("Known backend types:\n");
63       for (i=0; i < DIM (names); i++)
64         log_info ("    %s\n", names[i].name);
65       return 0;
66     }
67
68   for (i=0; i < DIM (names); i++)
69     {
70       if (!strcmp (names[i].name, name))
71         return names[i].conttype;
72     }
73
74   log_error ("invalid backend type '%s' given\n", name);
75   return 0;
76 }
77
78
79 /* Return true if CONTTYPE is supported by us.  */
80 int
81 be_is_supported_conttype (int conttype)
82 {
83   switch (conttype)
84     {
85     case CONTTYPE_ENCFS:
86     case CONTTYPE_DM_CRYPT:
87       return 1;
88
89     default:
90       return 0;
91     }
92 }
93
94
95 /* Create a lock file for the container FNAME and store the lock at
96  * R_LOCK and return 0.  On error return an error code and store NULL
97  * at R_LOCK.  */
98 gpg_error_t
99 be_take_lock_for_create (ctrl_t ctrl, const char *fname, dotlock_t *r_lock)
100 {
101   gpg_error_t err;
102   dotlock_t lock = NULL;
103   struct stat sb;
104
105   *r_lock = NULL;
106
107   /* A DM-crypt container requires special treatment by using the
108      syshelper fucntions.  */
109   if (ctrl->conttype == CONTTYPE_DM_CRYPT)
110     {
111       /*  */
112       err = call_syshelp_set_device (ctrl, fname);
113       goto leave;
114     }
115
116
117   /* A quick check to see that no container with that name already
118      exists.  */
119   if (!access (fname, F_OK))
120     {
121       err = gpg_error (GPG_ERR_EEXIST);
122       goto leave;
123     }
124
125   /* Take a lock and proceed with the creation.  If there is a lock we
126      immediately return an error because for creation it does not make
127      sense to wait.  */
128   lock = dotlock_create (fname, 0);
129   if (!lock)
130     {
131       err = gpg_error_from_syserror ();
132       goto leave;
133     }
134   if (dotlock_take (lock, 0))
135     {
136       err = gpg_error_from_syserror ();
137       goto leave;
138     }
139
140   /* Check again that the file does not exist.  */
141   err = stat (fname, &sb)? 0 : gpg_error (GPG_ERR_EEXIST);
142
143  leave:
144   if (!err)
145     {
146       *r_lock = lock;
147       lock = NULL;
148     }
149   dotlock_destroy (lock);
150   return err;
151 }
152
153
154 /* If the backend requires a separate file or directory for the
155    container, return its name by computing it from FNAME which gives
156    the g13 filename.  The new file name is allocated and stored at
157    R_NAME, if this is expected to be a directory true is stored at
158    R_ISDIR.  If no detached name is expected or an error occurs NULL
159    is stored at R_NAME. The function returns 0 on success or an error
160    code.  */
161 gpg_error_t
162 be_get_detached_name (int conttype, const char *fname,
163                       char **r_name, int *r_isdir)
164 {
165   *r_name = NULL;
166   *r_isdir = 0;
167   switch (conttype)
168     {
169     case CONTTYPE_ENCFS:
170       return be_encfs_get_detached_name (fname, r_name, r_isdir);
171
172     case CONTTYPE_DM_CRYPT:
173       return 0;
174
175     default:
176       return no_such_backend (conttype);
177     }
178 }
179
180
181 gpg_error_t
182 be_create_new_keys (int conttype, membuf_t *mb)
183 {
184   switch (conttype)
185     {
186     case CONTTYPE_ENCFS:
187       return be_encfs_create_new_keys (mb);
188
189     case CONTTYPE_TRUECRYPT:
190       return be_truecrypt_create_new_keys (mb);
191
192     case CONTTYPE_DM_CRYPT:
193       return 0;
194
195     default:
196       return no_such_backend (conttype);
197     }
198 }
199
200
201 /* Dispatcher to the backend's create function.  */
202 gpg_error_t
203 be_create_container (ctrl_t ctrl, int conttype,
204                      const char *fname, int fd, tupledesc_t tuples,
205                      unsigned int *r_id)
206 {
207   (void)fd;  /* Not yet used.  */
208
209   switch (conttype)
210     {
211     case CONTTYPE_ENCFS:
212       return be_encfs_create_container (ctrl, fname, tuples, r_id);
213
214     case CONTTYPE_DM_CRYPT:
215       return be_dmcrypt_create_container (ctrl);
216
217     default:
218       return no_such_backend (conttype);
219     }
220 }
221
222
223 /* Dispatcher to the backend's mount function.  */
224 gpg_error_t
225 be_mount_container (ctrl_t ctrl, int conttype,
226                     const char *fname,  const char *mountpoint,
227                     tupledesc_t tuples, unsigned int *r_id)
228 {
229   switch (conttype)
230     {
231     case CONTTYPE_ENCFS:
232       return be_encfs_mount_container (ctrl, fname, mountpoint, tuples, r_id);
233
234     case CONTTYPE_DM_CRYPT:
235       return be_dmcrypt_mount_container (ctrl, fname, mountpoint, tuples);
236
237     default:
238       return no_such_backend (conttype);
239     }
240 }
241
242
243 /* Dispatcher to the backend's umount function.  */
244 gpg_error_t
245 be_umount_container (ctrl_t ctrl, int conttype, const char *fname)
246 {
247   switch (conttype)
248     {
249     case CONTTYPE_ENCFS:
250       return gpg_error (GPG_ERR_NOT_SUPPORTED);
251
252     case CONTTYPE_DM_CRYPT:
253       return be_dmcrypt_umount_container (ctrl, fname);
254
255     default:
256       return no_such_backend (conttype);
257     }
258 }
259
260
261 /* Dispatcher to the backend's suspend function.  */
262 gpg_error_t
263 be_suspend_container (ctrl_t ctrl, int conttype, const char *fname)
264 {
265   switch (conttype)
266     {
267     case CONTTYPE_ENCFS:
268       return gpg_error (GPG_ERR_NOT_SUPPORTED);
269
270     case CONTTYPE_DM_CRYPT:
271       return be_dmcrypt_suspend_container (ctrl, fname);
272
273     default:
274       return no_such_backend (conttype);
275     }
276 }
277
278
279 /* Dispatcher to the backend's resume function.  */
280 gpg_error_t
281 be_resume_container (ctrl_t ctrl, int conttype, const char *fname,
282                      tupledesc_t tuples)
283 {
284   switch (conttype)
285     {
286     case CONTTYPE_ENCFS:
287       return gpg_error (GPG_ERR_NOT_SUPPORTED);
288
289     case CONTTYPE_DM_CRYPT:
290       return be_dmcrypt_resume_container (ctrl, fname, tuples);
291
292     default:
293       return no_such_backend (conttype);
294     }
295 }