~ubuntu-branches/ubuntu/trusty/libpam-mount/trusty-proposed

« back to all changes in this revision

Viewing changes to src/crypto-dmc.c

  • Committer: Bazaar Package Importer
  • Author(s): Bastian Kleineidam
  • Date: 2010-05-09 10:46:01 UTC
  • mfrom: (1.4.4 upstream) (27.2.7 maverick)
  • Revision ID: james.westby@ubuntu.com-20100509104601-cip885tmppv2tc52
Tags: 2.1+git20100509-1
* New upstream release, plus git changes until 9.5.2010
  + Works now with other password slots than zero on crypted mounts
    (Closes: #580636)
  + Certainly includes old patch fixing the cron segfaults
    (Closes: #484122)
* Only warn about missing fskey hash when an fskey path has been given.
  (Closes: #580430)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 *      Copyright © Jan Engelhardt, 2008 - 2009
 
2
 *      Copyright © Jan Engelhardt, 2008 - 2010
3
3
 *
4
4
 *      This file is part of pam_mount; you can redistribute it and/or
5
5
 *      modify it under the terms of the GNU Lesser General Public License
6
6
 *      as published by the Free Software Foundation; either version 2.1
7
7
 *      of the License, or (at your option) any later version.
8
8
 */
9
 
#ifdef __linux__
 
9
#include "config.h"
 
10
#ifdef HAVE_LIBCRYPTSETUP
10
11
#include <assert.h>
11
12
#include <errno.h>
12
13
#include <stdbool.h>
17
18
#include <libHX/defs.h>
18
19
#include <libHX/proc.h>
19
20
#include <libHX/string.h>
 
21
#include <libcryptsetup.h>
20
22
#include "pam_mount.h"
21
23
 
22
24
/**
26
28
 */
27
29
int dmc_is_luks(const char *path, bool blkdev)
28
30
{
29
 
        const char *lukscheck_args[] = {
30
 
                "cryptsetup", "isLuks", path, NULL,
31
 
        };
 
31
        struct crypt_device *cd;
 
32
        const char *device = path;
32
33
        char *loop_device;
33
34
        int ret;
34
35
 
42
43
                                __func__, strerror(-ret));
43
44
                        return ret;
44
45
                }
45
 
                lukscheck_args[2] = loop_device;
46
 
        }
47
 
 
48
 
        if ((ret = HXproc_run_sync(lukscheck_args, HXPROC_VERBOSE)) < 0)
49
 
                fprintf(stderr, "run_sync: %s\n", strerror(-ret));
50
 
        else if (ret > 0xFFFF)
51
 
                /* terminated */
52
 
                ret = -1;
53
 
        else
54
 
                /* exited, and we need success or fail */
55
 
                ret = ret == 0;
56
 
 
 
46
                device = loop_device;
 
47
        }
 
48
 
 
49
        ret = crypt_init(&cd, device);
 
50
        if (ret == 0) {
 
51
                ret = crypt_load(cd, CRYPT_LUKS1, NULL);
 
52
                if (ret == -EINVAL)
 
53
                        ret = false;
 
54
                else if (ret == 0)
 
55
                        ret = true;
 
56
                /* else keep ret as-is */
 
57
                crypt_free(cd);
 
58
        }
57
59
        if (!blkdev)
58
60
                pmt_loop_release(loop_device);
59
61
        return ret;
73
75
 
74
76
static bool dmc_run(const struct ehd_mtreq *req, struct ehd_mount *mt)
75
77
{
76
 
        int ret, argk;
77
 
        bool is_luks = false;
78
 
        const char *start_args[12];
79
 
        struct HXproc proc;
80
 
        char key_size[HXSIZEOF_Z32+2];
 
78
        struct crypt_device *cd;
 
79
        unsigned int flags = 0;
 
80
        char *cipher = NULL, *mode;
 
81
        int ret;
81
82
 
82
 
        ret = dmc_is_luks(mt->lower_device, true);
 
83
        ret = crypt_init(&cd, mt->lower_device);
83
84
        if (ret < 0) {
84
 
                l0g("cryptsetup isLuks got terminated\n");
 
85
                fprintf(stderr, "crypt_init: %s\n", strerror(-ret));
85
86
                return false;
86
87
        }
87
 
 
88
 
        argk = 0;
89
 
        is_luks = ret == 1;
90
 
        start_args[argk++] = "cryptsetup";
91
88
        if (req->readonly)
92
 
                start_args[argk++] = "--readonly";
93
 
        if (req->fs_cipher != NULL) {
94
 
                start_args[argk++] = "-c";
95
 
                start_args[argk++] = req->fs_cipher;
96
 
        }
97
 
        if (is_luks) {
98
 
                start_args[argk++] = "luksOpen";
99
 
                start_args[argk++] = mt->lower_device;
100
 
                start_args[argk++] = mt->crypto_name;
 
89
                flags |= CRYPT_ACTIVATE_READONLY;
 
90
 
 
91
        ret = crypt_load(cd, CRYPT_LUKS1, NULL);
 
92
        if (ret == 0) {
 
93
                ret = crypt_activate_by_passphrase(cd, mt->crypto_name,
 
94
                      CRYPT_ANY_SLOT, req->key_data, req->key_size, flags);
 
95
                if (ret < 0) {
 
96
                        fprintf(stderr, "crypt_activate_by_passphrase: %s\n",
 
97
                                strerror(-ret));
 
98
                        goto out;
 
99
                }
101
100
        } else {
102
 
                start_args[argk++] = "--key-file=-";
103
 
                start_args[argk++] = "-h";
104
 
                start_args[argk++] = req->fs_hash;
105
 
                if (req->trunc_keysize != 0) {
106
 
                        snprintf(key_size, sizeof(key_size), "-s%u",
107
 
                                 req->trunc_keysize);
108
 
                        start_args[argk++] = key_size;
109
 
                }
110
 
                start_args[argk++] = "create";
111
 
                start_args[argk++] = mt->crypto_name;
112
 
                start_args[argk++] = mt->lower_device;
113
 
        }
114
 
        start_args[argk] = NULL;
115
 
        assert(argk < ARRAY_SIZE(start_args));
116
 
 
117
 
        if (Debug)
118
 
                arglist_llog(start_args);
119
 
 
120
 
        memset(&proc, 0, sizeof(proc));
121
 
        proc.p_flags = HXPROC_VERBOSE | HXPROC_STDIN;
122
 
        if ((ret = HXproc_run_async(start_args, &proc)) <= 0) {
123
 
                l0g("Error setting up crypto device: %s\n", strerror(-ret));
124
 
                return false;
125
 
        }
126
 
 
127
 
        /* Ignore return value, we can't do much in case it fails */
128
 
        if (write(proc.p_stdin, req->key_data, req->key_size) < 0)
129
 
                w4rn("%s: password send erro: %s\n", __func__, strerror(errno));
130
 
        close(proc.p_stdin);
131
 
        if ((ret = HXproc_wait(&proc)) != 0) {
132
 
                w4rn("cryptsetup exited with non-zero status %d\n", ret);
133
 
                return false;
134
 
        }
135
 
 
136
 
        return true;
 
101
                struct crypt_params_plain params = {.hash = req->fs_hash};
 
102
 
 
103
                cipher = HX_strdup(req->fs_cipher);
 
104
                if (cipher == NULL) {
 
105
                        ret = -errno;
 
106
                        goto out;
 
107
                }
 
108
                /* stuff like aes-cbc-essiv:sha256 => aes, cbc-essiv:sha256 */
 
109
                mode = strchr(cipher, '-');
 
110
                if (mode != NULL)
 
111
                        *mode++ = '\0';
 
112
                else
 
113
                        mode = "plain";
 
114
 
 
115
                ret = crypt_format(cd, CRYPT_PLAIN, cipher, mode, NULL, NULL,
 
116
                      req->trunc_keysize, &params);
 
117
                if (ret < 0) {
 
118
                        fprintf(stderr, "crypt_format: %s\n", strerror(-ret));
 
119
                        goto out;
 
120
                }
 
121
 
 
122
                if (strcmp(req->fs_hash, "plain") == 0)
 
123
                        ret = crypt_activate_by_volume_key(cd, mt->crypto_name,
 
124
                              req->key_data, req->key_size, flags);
 
125
                else
 
126
                        ret = crypt_activate_by_passphrase(cd, mt->crypto_name,
 
127
                              CRYPT_ANY_SLOT, req->key_data, req->key_size,
 
128
                              flags);
 
129
                if (ret < 0) {
 
130
                        fprintf(stderr, "crypt_activate: %s\n", strerror(-ret));
 
131
                        goto out;
 
132
                }
 
133
        }
 
134
 
 
135
 out:
 
136
        free(cipher);
 
137
        crypt_free(cd);
 
138
        return ret >= 0 ? true : false;
137
139
}
138
140
 
139
141
static int dmc_load(const struct ehd_mtreq *req, struct ehd_mount *mt)
148
150
 
149
151
static int dmc_unload(const struct ehd_mount *mt)
150
152
{
151
 
        const char *args[] = {
152
 
                "cryptsetup", "remove", NULL, NULL,
153
 
        };
154
 
        int ret = 1;
155
 
 
156
 
        if (mt->crypto_name != NULL)
157
 
                args[2] = mt->crypto_name;
158
 
        else if (mt->crypto_device != NULL)
159
 
                args[2] = mt->crypto_device;
160
 
        if (args[2] != NULL) {
161
 
                ret = HXproc_run_sync(args, HXPROC_VERBOSE);
162
 
                if (ret != 0)
163
 
                        l0g("Could not unload dm-crypt device \"%s\", "
164
 
                            "cryptsetup returned HXproc status %d\n",
165
 
                            mt->crypto_device, ret);
166
 
                ret = !ret;
167
 
        }
168
 
 
169
 
        return ret;
 
153
        struct crypt_device *cd;
 
154
        const char *cname;
 
155
        int ret;
 
156
 
 
157
        ret = crypt_init(&cd, mt->crypto_device);
 
158
        if (ret < 0)
 
159
                return ret;
 
160
 
 
161
        cname = (mt->crypto_name != NULL) ? mt->crypto_name :
 
162
                HX_basename(mt->crypto_device);
 
163
        ret = crypt_deactivate(cd, cname);
 
164
        crypt_free(cd);
 
165
        return (ret < 0) ? ret : 1;
170
166
}
171
167
 
172
168
const struct ehd_crypto_ops ehd_dmcrypt_ops = {
174
170
        .unload = dmc_unload,
175
171
};
176
172
 
177
 
#endif /* __linux__ */
 
173
#endif /* HAVE_LIBCRYPTSETUP */