~ecryptfs/ecryptfs/trunk

« back to all changes in this revision

Viewing changes to src/utils/umount.ecryptfs.c

  • Committer: Tyler Hicks
  • Date: 2017-06-08 23:06:20 UTC
  • mfrom: (885.1.2 ecryptfs)
  • Revision ID: tyhicks@canonical.com-20170608230620-vcosxagt2cwab9eo
ecryptfs-migrate-home: Pass --nopwcheck to ecryptfs-setup-private (LP: #1630477)

[tyhicks: Remove extra spaces in usage output and add changelog entry]

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * Copyright (C) 2009 International Business Machines
 
3
 * Author(s): Tyler Hicks <tyhicks@linux.vnet.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 <errno.h>
 
22
#include <mntent.h>
 
23
#include <stdio.h>
 
24
#include <stdlib.h>
 
25
#include <string.h>
 
26
#include <unistd.h>
 
27
#include "ecryptfs.h"
 
28
 
 
29
static void usage()
 
30
{
 
31
        fprintf(stderr, "\teCryptfs umount helper\n\tusage: "
 
32
                "umount [ecryptfs mount point]\n"
 
33
                );
 
34
        exit(-EINVAL);
 
35
}
 
36
 
 
37
 /**
 
38
 * Parses a string of mount options, searching for an option name, and returns
 
39
 * a pointer to the option value.  For example, if name was "ecryptfs_sig=",
 
40
 * it would set value to a string containing the sig, up to the first
 
41
 * comma or NULL character in the mount options.  Name must end with an = sign.
 
42
 * value must be freed by the caller.
 
43
 */
 
44
static int get_mount_opt_value(char *mnt_opts, char *name, char **value)
 
45
{
 
46
        char *name_start, *val_start, *val_stop;
 
47
        size_t name_len, val_len;
 
48
        int rc = 0;
 
49
 
 
50
        name_len = strlen(name);
 
51
        if (name[name_len - 1] != '=') {
 
52
                rc = EINVAL;
 
53
                goto out;
 
54
        }
 
55
 
 
56
        name_start = strstr(mnt_opts, name);
 
57
        if (!name_start) {
 
58
                rc = EINVAL;
 
59
                goto out;
 
60
        }
 
61
 
 
62
        val_start = name_start + name_len;
 
63
        val_stop = strstr(val_start, ",");
 
64
        if (!val_stop)
 
65
                val_stop = mnt_opts + strlen(mnt_opts);
 
66
 
 
67
        val_len = val_stop - val_start;
 
68
        *value = malloc(val_len + 1);
 
69
        if (!(*value)) {
 
70
                rc = ENOMEM;
 
71
                goto out;
 
72
        }
 
73
        memcpy(*value, val_start, val_len);
 
74
        (*value)[val_len] = '\0';
 
75
out:
 
76
        return rc;
 
77
}
 
78
 
 
79
static int unlink_keys_from_keyring(const char *mnt_point)
 
80
{
 
81
        struct mntent *mntent;
 
82
        FILE *file;
 
83
        char *fekek_sig = NULL, *fnek_sig = NULL;
 
84
        int fekek_fail = 0, fnek_fail = 0;
 
85
        int rc;
 
86
 
 
87
        file = setmntent("/etc/mtab", "r");
 
88
        if (!file) {
 
89
                rc = EINVAL;
 
90
                goto out;
 
91
        }
 
92
        while ((mntent = getmntent(file))) {
 
93
                if (strcmp("ecryptfs", mntent->mnt_type))
 
94
                        continue;
 
95
                if (strcmp(mnt_point, mntent->mnt_dir))
 
96
                        continue;
 
97
                break;
 
98
        }
 
99
        if (!mntent) {
 
100
                rc = EINVAL;
 
101
                goto end_out;
 
102
        }
 
103
        if (!hasmntopt(mntent, "ecryptfs_unlink_sigs")) {
 
104
                rc = 0;
 
105
                goto end_out;
 
106
        }
 
107
        rc = get_mount_opt_value(mntent->mnt_opts, "ecryptfs_sig=", &fekek_sig);
 
108
        if (!rc) {
 
109
                fekek_fail = ecryptfs_remove_auth_tok_from_keyring(fekek_sig);
 
110
                if (fekek_fail == ENOKEY)
 
111
                        fekek_fail = 0;
 
112
                if (fekek_fail)
 
113
                        fprintf(stderr, "Failed to remove fekek with sig [%s] "
 
114
                                "from keyring: %s\n", fekek_sig,
 
115
                                strerror(fekek_fail));
 
116
        } else {
 
117
                fekek_fail = rc;
 
118
        }
 
119
        if (!get_mount_opt_value(mntent->mnt_opts,
 
120
                                 "ecryptfs_fnek_sig=", &fnek_sig)
 
121
            && strcmp(fekek_sig, fnek_sig)) {
 
122
                fnek_fail = ecryptfs_remove_auth_tok_from_keyring(fnek_sig);
 
123
                if (fnek_fail == ENOKEY)
 
124
                        fnek_fail = 0;
 
125
                if (fnek_fail) {
 
126
                        fprintf(stderr, "Failed to remove fnek with sig [%s] "
 
127
                                "from keyring: %s\n", fnek_sig, 
 
128
                                strerror(fnek_fail));
 
129
                }
 
130
        }
 
131
        free(fekek_sig);
 
132
        free(fnek_sig);
 
133
end_out:
 
134
        endmntent(file);
 
135
out:
 
136
        return (fekek_fail ? fekek_fail : (fnek_fail ? fnek_fail : rc));
 
137
}
 
138
 
 
139
static int construct_umount_args(int argc, char **argv, char ***new_argv)
 
140
{
 
141
        int new_argc = argc + 1;
 
142
        int i, rc;
 
143
 
 
144
        *new_argv = malloc(sizeof(char *) * (new_argc + 1));
 
145
        if (!*new_argv) {
 
146
                rc = errno;
 
147
                goto out;
 
148
        }
 
149
        (*new_argv)[0] = "umount";
 
150
        (*new_argv)[1] = "-i";
 
151
        for (i = 2; i < new_argc; i++)
 
152
                (*new_argv)[i] = argv[i - 1];
 
153
        (*new_argv)[i] = NULL;
 
154
        rc = 0;
 
155
out:
 
156
        return rc;
 
157
}
 
158
 
 
159
#define UMOUNT_PATH     "/bin/umount"
 
160
int main(int argc, char **argv)
 
161
{
 
162
        char **new_argv;
 
163
        int rc;
 
164
 
 
165
        if (argc<2)
 
166
                usage();
 
167
 
 
168
        if (unlink_keys_from_keyring(argv[1]))
 
169
                fprintf(stderr, "Could not unlink the key(s) from your keying. "
 
170
                        "Please use `keyctl unlink` if you wish to remove the "
 
171
                        "key(s). Proceeding with umount.\n");
 
172
        rc = construct_umount_args(argc, argv, &new_argv);
 
173
        if (rc) {
 
174
                fprintf(stderr, "Failed to construct umount arguments: %s\n",
 
175
                        strerror(rc));
 
176
                goto out;
 
177
        }
 
178
        rc = execv(UMOUNT_PATH, new_argv);
 
179
        if (rc < 0) {
 
180
                rc = errno;
 
181
                fprintf(stderr, "Failed to execute %s: %m\n", UMOUNT_PATH);
 
182
                goto free_out;
 
183
        }
 
184
        rc = 0;
 
185
free_out:
 
186
        free(new_argv);
 
187
out:
 
188
        return rc;
 
189
}
 
190