~ecryptfs/ecryptfs/trunk

« back to all changes in this revision

Viewing changes to src/libecryptfs/key_mod.c

  • Committer: mhalcrow@us.ibm.com
  • Date: 2007-11-06 22:56:01 UTC
  • Revision ID: git-v1:f8357de9d554b274497b5cce9db4347254b7e7eb
Initial import of eCryptfs filesystem userspace utilities (mount helper, daemon component,
etc.)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * Copyright (C) 2007 International Business Machines
 
3
 * Author(s): Mike Halcrow <mhalcrow@us.ibm.com>
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or
 
6
 * modify it under the terms of the GNU General Public License as
 
7
 * published by the Free Software Foundation; either version 2 of the
 
8
 * License, or (at your option) any later version.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful, but
 
11
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
 * General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this program; if not, write to the Free Software
 
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 
18
 * 02111-1307, USA.
 
19
 */
 
20
 
 
21
#include <dirent.h>
 
22
#include <stdlib.h>
 
23
#include <string.h>
 
24
#ifndef S_SPLINT_S
 
25
#include <syslog.h>
 
26
#include <stdio.h>
 
27
#endif
 
28
#include <errno.h>
 
29
#include <fcntl.h>
 
30
#include <dlfcn.h>
 
31
#include <sys/stat.h>
 
32
#include "config.h"
 
33
#include "../include/ecryptfs.h"
 
34
 
 
35
static struct ecryptfs_key_mod_ops *
 
36
(*builtin_get_key_mod_ops[])(void) = {
 
37
        &passphrase_get_key_mod_ops,
 
38
        NULL
 
39
};
 
40
 
 
41
/**
 
42
 * ecryptfs_generate_sig_from_key_data
 
43
 * @sig:
 
44
 * @key_data:
 
45
 * @key_data_len:
 
46
 */
 
47
int ecryptfs_generate_sig_from_key_data(unsigned char *sig,
 
48
                                        unsigned char *key_data,
 
49
                                        size_t key_data_len)
 
50
{
 
51
        uint32_t key_type;
 
52
        int rc = 0;
 
53
 
 
54
        memcpy(&key_type, key_data, sizeof(uint32_t));
 
55
        key_type = ntohl(key_type);
 
56
        switch (key_type) {
 
57
        default:
 
58
                rc = -EINVAL;
 
59
                goto out;
 
60
        };
 
61
out:
 
62
        return rc;
 
63
}
 
64
 
 
65
static int ecryptfs_dummy_init(char **alias)
 
66
{
 
67
        syslog(LOG_WARNING, "%s: Dummy function substituted for unimplemented "
 
68
               "function in key module\n", __FUNCTION__);
 
69
        (*alias) = NULL;
 
70
        return 0;
 
71
}
 
72
 
 
73
static int ecryptfs_dummy_get_gen_key_params(struct key_mod_param **params,
 
74
                                             uint32_t *num_params)
 
75
{
 
76
        if (ecryptfs_verbosity)
 
77
                syslog(LOG_INFO,
 
78
                       "%s: Dummy function substituted for unimplemented "
 
79
                       "function in key module\n", __FUNCTION__);
 
80
        (*params) = NULL;
 
81
        (*num_params) = 0;
 
82
        return 0;
 
83
}
 
84
 
 
85
static int
 
86
ecryptfs_dummy_get_gen_key_subgraph_trans_node(struct transition_node **trans,
 
87
                                               uint32_t version)
 
88
{
 
89
        if (ecryptfs_verbosity)
 
90
                syslog(LOG_INFO,
 
91
                       "%s: Dummy function substituted for unimplemented "
 
92
                       "function in key module\n", __FUNCTION__);
 
93
        (*trans) = NULL;
 
94
        return 0;
 
95
}
 
96
 
 
97
static int
 
98
ecryptfs_dummy_get_params(struct key_mod_param **params, uint32_t *num_params)
 
99
{
 
100
        if (ecryptfs_verbosity)
 
101
                syslog(LOG_INFO,
 
102
                       "%s: Dummy function substituted for unimplemented "
 
103
                       "function in key module\n", __FUNCTION__);
 
104
        (*params) = NULL;
 
105
        (*num_params) = 0;
 
106
        return 0;
 
107
}
 
108
 
 
109
static int
 
110
ecryptfs_dummy_get_param_subgraph_trans_node(struct transition_node **trans,
 
111
                                             uint32_t version)
 
112
{
 
113
        if (ecryptfs_verbosity)
 
114
                syslog(LOG_INFO,
 
115
                       "%s: Dummy function substituted for unimplemented "
 
116
                       "function in key module\n", __FUNCTION__);
 
117
        (*trans) = NULL;
 
118
        return 0;
 
119
}
 
120
 
 
121
static int ecryptfs_dummy_get_blob(unsigned char *blob, size_t *blob_size,
 
122
                                   struct key_mod_param_val *param_vals,
 
123
                                   uint32_t num_param_vals)
 
124
{
 
125
        syslog(LOG_WARNING, "%s: Dummy function substituted for unimplemented "
 
126
               "function in key module\n", __FUNCTION__);
 
127
        (*blob_size) = 0;
 
128
        return 0;
 
129
}
 
130
 
 
131
static int
 
132
ecryptfs_dummy_get_key_data(unsigned char *key_data, size_t *key_data_len,
 
133
                            unsigned char *blob)
 
134
{
 
135
        if (ecryptfs_verbosity)
 
136
                syslog(LOG_INFO,
 
137
                       "%s: Dummy function substituted for unimplemented "
 
138
                       "function in key module\n", __FUNCTION__);
 
139
        (*key_data_len) = 0;
 
140
        return 0;
 
141
}
 
142
 
 
143
static int
 
144
ecryptfs_dummy_get_key_sig(unsigned char *sig, unsigned char *blob)
 
145
{
 
146
        if (ecryptfs_verbosity)
 
147
                syslog(LOG_INFO,
 
148
                       "%s: Dummy function substituted for unimplemented "
 
149
                       "function in key module\n", __FUNCTION__);
 
150
        sig[0] = '\0';
 
151
        return 0;
 
152
}
 
153
 
 
154
static int ecryptfs_dummy_get_key_hint(unsigned char *hint, size_t *hint_len,
 
155
                                       unsigned char *blob)
 
156
{
 
157
        if (ecryptfs_verbosity)
 
158
                syslog(LOG_WARNING,
 
159
                       "%s: Dummy function substituted for unimplemented "
 
160
                       "function in key module\n", __FUNCTION__);
 
161
        (*hint_len) = 0;
 
162
        return 0;
 
163
}
 
164
 
 
165
static int
 
166
ecryptfs_dummy_encrypt(char *to, size_t *to_size, char *from, size_t from_size,
 
167
                       unsigned char *blob, int blob_type)
 
168
{
 
169
        syslog(LOG_WARNING, "%s: Dummy function substituted for unimplemented "
 
170
               "function in key module\n", __FUNCTION__);
 
171
        (*to_size) = 0;
 
172
        return 0;
 
173
}
 
174
 
 
175
static int
 
176
ecryptfs_dummy_decrypt(char *to, size_t *to_size, char *from, size_t from_size,
 
177
                       unsigned char *blob, int blob_type)
 
178
{
 
179
        syslog(LOG_WARNING, "%s: Dummy function substituted for unimplemented "
 
180
               "function in key module\n", __FUNCTION__);
 
181
        (*to_size) = 0;
 
182
        return 0;
 
183
}
 
184
 
 
185
static int ecryptfs_dummy_destroy(unsigned char *blob)
 
186
{
 
187
        if (ecryptfs_verbosity)         
 
188
                syslog(LOG_INFO,
 
189
                       "%s: Dummy function substituted for unimplemented "
 
190
                       "function in key module\n", __FUNCTION__);
 
191
        return 0;
 
192
}
 
193
 
 
194
static int ecryptfs_dummy_finalize(void)
 
195
{
 
196
        if (ecryptfs_verbosity)         
 
197
                syslog(LOG_INFO,
 
198
                       "%s: Dummy function substituted for unimplemented "
 
199
                       "function in key module\n", __FUNCTION__);
 
200
        return 0;       
 
201
}
 
202
 
 
203
int ecryptfs_fill_in_dummy_ops(struct ecryptfs_key_mod_ops *key_mod_ops)
 
204
{
 
205
        if (!key_mod_ops->init)
 
206
                key_mod_ops->init = &ecryptfs_dummy_init;
 
207
        if (!key_mod_ops->get_gen_key_params)
 
208
                key_mod_ops->get_gen_key_params =
 
209
                        &ecryptfs_dummy_get_gen_key_params;
 
210
        if (!key_mod_ops->get_gen_key_subgraph_trans_node)
 
211
                key_mod_ops->get_gen_key_subgraph_trans_node =
 
212
                        &ecryptfs_dummy_get_gen_key_subgraph_trans_node;
 
213
        if (!key_mod_ops->get_params)
 
214
                key_mod_ops->get_params = &ecryptfs_dummy_get_params;
 
215
        if (!key_mod_ops->get_param_subgraph_trans_node)
 
216
                key_mod_ops->get_param_subgraph_trans_node =
 
217
                        &ecryptfs_dummy_get_param_subgraph_trans_node;
 
218
        if (!key_mod_ops->get_blob)
 
219
                key_mod_ops->get_blob = &ecryptfs_dummy_get_blob;
 
220
        if (!key_mod_ops->get_key_data)
 
221
                key_mod_ops->get_key_data = &ecryptfs_dummy_get_key_data;
 
222
        if (!key_mod_ops->get_key_sig)
 
223
                key_mod_ops->get_key_sig = &ecryptfs_dummy_get_key_sig;
 
224
        if (!key_mod_ops->get_key_hint)
 
225
                key_mod_ops->get_key_hint = &ecryptfs_dummy_get_key_hint;
 
226
        if (!key_mod_ops->encrypt)
 
227
                key_mod_ops->encrypt = &ecryptfs_dummy_encrypt;
 
228
        if (!key_mod_ops->decrypt)
 
229
                key_mod_ops->decrypt = &ecryptfs_dummy_decrypt;
 
230
        if (!key_mod_ops->destroy)
 
231
                key_mod_ops->destroy = &ecryptfs_dummy_destroy;
 
232
        if (!key_mod_ops->finalize)
 
233
                key_mod_ops->finalize = &ecryptfs_dummy_finalize;
 
234
        return 0;
 
235
}
 
236
 
 
237
/**
 
238
 * Called from: src/libecryptfs/module_mgr.c::ecryptfs_process_decision_graph
 
239
 */
 
240
int ecryptfs_register_key_modules(struct ecryptfs_ctx* ctx)
 
241
{
 
242
        DIR *dp = NULL;
 
243
        struct dirent *ep;
 
244
        char *dir_name = NULL;
 
245
        int i;
 
246
        struct ecryptfs_key_mod *curr_key_mod = &(ctx->key_mod_list_head);
 
247
        struct ecryptfs_key_mod_ops *(*walker)(void);
 
248
        int rc = 0;
 
249
 
 
250
        if (asprintf(&dir_name, "%s", ECRYPTFS_DEFAULT_KEY_MOD_DIR) == -1) {
 
251
                rc = -ENOMEM;
 
252
                goto out;
 
253
        }
 
254
        if (!(dp = opendir(dir_name))) {
 
255
                syslog(LOG_WARNING,
 
256
                       "ERROR: Could not open key_mod directory\n");
 
257
                rc = -EPERM;
 
258
                goto out;
 
259
        }
 
260
        while ((ep = readdir(dp))) {
 
261
                struct ecryptfs_key_mod *new_key_mod = NULL;
 
262
                size_t dir_length;
 
263
                char *path = NULL;
 
264
                char *key_mod_dir = ECRYPTFS_DEFAULT_KEY_MOD_DIR;
 
265
                void *handle;
 
266
                struct ecryptfs_key_mod_ops *(*get_key_mod_ops)(void);
 
267
 
 
268
                /* Check if file ends with .so */
 
269
                dir_length = strlen(ep->d_name);
 
270
                if ((dir_length < 3)
 
271
                    || strcmp((ep->d_name + (dir_length - 3)), ".so"))
 
272
                        continue;
 
273
                if (asprintf(&path, "%s/%s", key_mod_dir, ep->d_name) == -1) {
 
274
                        syslog(LOG_ERR, "Out of memory\n");
 
275
                        rc = -ENOMEM;
 
276
                        goto out;
 
277
                }
 
278
                rc = 0;
 
279
                handle = dlopen(path, RTLD_LAZY);
 
280
                if (!handle) {
 
281
                        syslog(LOG_ERR, "Could not open library handle\n");
 
282
                        goto end_loop;
 
283
                }
 
284
                get_key_mod_ops = (struct ecryptfs_key_mod_ops *(*)(void))
 
285
                        dlsym(handle, "get_key_mod_ops");
 
286
                if (!get_key_mod_ops) {
 
287
                        syslog (LOG_ERR, "Error attempting to get the symbol "
 
288
                                "[get_key_mod_ops] from key module [%s]: "
 
289
                                "err = [%s]. The key module is likely using "
 
290
                                "the deprecated key module API.\n", path,
 
291
                                dlerror());
 
292
                        goto end_loop;
 
293
                }
 
294
                new_key_mod = malloc(sizeof(struct ecryptfs_key_mod));
 
295
                if (!new_key_mod) {
 
296
                        syslog(LOG_ERR, "Out of memory\n");
 
297
                        free(path);
 
298
                        rc = -ENOMEM;
 
299
                        goto out;
 
300
                }
 
301
                memset(new_key_mod, 0, sizeof(struct ecryptfs_key_mod));
 
302
                new_key_mod->ops = (get_key_mod_ops)();
 
303
                if (!new_key_mod->ops) {
 
304
                        syslog (LOG_ERR, "Library function get_key_mod_ops() "
 
305
                                "failed to return ops for [%s]\n", path);
 
306
                        free(new_key_mod);
 
307
                        rc = 0;
 
308
                        goto end_loop;
 
309
                }
 
310
                if ((rc = ecryptfs_fill_in_dummy_ops(new_key_mod->ops))) {
 
311
                        syslog (LOG_ERR, "Error attempting to fill in missing  "
 
312
                                "key module operations for [%s]; rc = [%d]\n",
 
313
                                path, rc);
 
314
                        free(new_key_mod);
 
315
                        rc = 0;
 
316
                        goto end_loop;                  
 
317
                }
 
318
                if ((rc = new_key_mod->ops->init(&new_key_mod->alias))) {
 
319
                        syslog(LOG_ERR, "Error initializing key module [%s]; "
 
320
                               "rc = [%d]\n", path, rc);
 
321
                        free(new_key_mod);
 
322
                        rc = 0;
 
323
                        goto end_loop;
 
324
                }
 
325
                new_key_mod->lib_handle = handle;
 
326
                new_key_mod->lib_path = path;
 
327
                curr_key_mod->next = new_key_mod;
 
328
                curr_key_mod = new_key_mod;
 
329
                continue;
 
330
        end_loop:
 
331
                free(path);
 
332
        }
 
333
        closedir(dp);
 
334
        i = 0;
 
335
        walker = builtin_get_key_mod_ops[i];
 
336
        while (walker) {
 
337
                struct ecryptfs_key_mod *new_key_mod;
 
338
                struct ecryptfs_key_mod *tmp_key_mod;
 
339
 
 
340
                if (!(new_key_mod = malloc(sizeof(struct ecryptfs_key_mod)))) {
 
341
                        syslog(LOG_ERR, "Out of memory\n");
 
342
                        rc = -ENOMEM;
 
343
                        goto out;
 
344
                }
 
345
                memset(new_key_mod, 0, sizeof(struct ecryptfs_key_mod));
 
346
                new_key_mod->ops = (walker)();
 
347
                if (!new_key_mod->ops) {
 
348
                        syslog (LOG_ERR, "Library function get_key_mod_ops() "
 
349
                                "failed to return ops for built-in key "
 
350
                                "module in array position [%d]\n", i);
 
351
                        free(new_key_mod);
 
352
                        rc = 0;
 
353
                        goto end_loop_2;
 
354
                }
 
355
                if ((rc = new_key_mod->ops->init(&new_key_mod->alias))) {
 
356
                        syslog(LOG_ERR, "Error initializing key module in "
 
357
                               "array position [%d]\n", i);
 
358
                        free(new_key_mod);
 
359
                        rc = 0;
 
360
                        goto end_loop_2;
 
361
                }
 
362
                tmp_key_mod = ctx->key_mod_list_head.next;
 
363
                while (tmp_key_mod) {
 
364
                        if (strcmp(tmp_key_mod->alias, new_key_mod->alias)
 
365
                            == 0) {
 
366
                                free(new_key_mod->alias);
 
367
                                free(new_key_mod);
 
368
                                if (ecryptfs_verbosity)
 
369
                                        syslog(LOG_INFO,
 
370
                                               "Preferring [%s] file over "
 
371
                                               "built-in module for key module "
 
372
                                               "with name [%s]\n",
 
373
                                               tmp_key_mod->lib_path,
 
374
                                               tmp_key_mod->alias);
 
375
                                goto end_loop_2;
 
376
                        }
 
377
                        tmp_key_mod = tmp_key_mod->next;
 
378
                }
 
379
                curr_key_mod->next = new_key_mod;
 
380
                curr_key_mod = new_key_mod;
 
381
end_loop_2:
 
382
                i++;
 
383
                walker = builtin_get_key_mod_ops[i];
 
384
        }
 
385
out:
 
386
        free(dir_name);
 
387
        return rc;
 
388
}
 
389
 
 
390
/**
 
391
 * ecryptfs_find_key_mod
 
392
 *
 
393
 * Get the key_mod struct for the given alias.
 
394
 */
 
395
int ecryptfs_find_key_mod(struct ecryptfs_key_mod **key_mod,
 
396
                          struct ecryptfs_ctx *ctx, char *key_mod_alias)
 
397
{
 
398
        struct ecryptfs_key_mod *curr;
 
399
        int rc = 0;
 
400
 
 
401
        curr = ctx->key_mod_list_head.next;
 
402
        while (curr) {
 
403
                if (!strncmp(curr->alias, key_mod_alias,
 
404
                             strlen(curr->alias))) {
 
405
                        *key_mod = curr;
 
406
                        goto out;
 
407
                }
 
408
                curr = curr->next;
 
409
        }
 
410
        rc = 1;
 
411
out:
 
412
        return rc;
 
413
}
 
414
 
 
415
int ecryptfs_free_key_mod_list(struct ecryptfs_ctx *ctx)
 
416
{
 
417
        struct ecryptfs_key_mod *curr = ctx->key_mod_list_head.next;
 
418
        struct ecryptfs_key_mod *temp;
 
419
 
 
420
        while (curr) {
 
421
                curr->ops->finalize();
 
422
                dlclose (curr->lib_handle);
 
423
                free(curr->lib_path);
 
424
                temp = curr;
 
425
                curr = curr->next;
 
426
                free(temp);
 
427
        }
 
428
        return 0;
 
429
}