2
* Copyright (C) 2006 International Business Machines
3
* Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com>
4
* Stephan Mueller <smueller@chronox.de>
5
* Tyler Hicks <tyhicks@ou.edu>
6
* Michael C. Thompson <mcthomps@us.ibm.com>
8
* This program is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU General Public License as
10
* published by the Free Software Foundation; either version 2 of the
11
* License, or (at your option) any later version.
13
* This program is distributed in the hope that it will be useful, but
14
* WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
* General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
34
#include <sys/mount.h>
36
#include <sys/types.h>
39
#include "decision_graph.h"
42
#define NUM_REQUIRED_ARGS 3
46
fprintf(stderr, "\teCryptfs mount helper\n\tusage: "
47
"mount -t ecryptfs [lower directory] [ecryptfs mount point]\n"
48
"Available options:\n"
50
"\n\t\tAvailable pki aliases: passphrase\n"
52
"\tplaintext_passthrough\n"
58
* This function will malloc any argument that is passed in as non-NULL.
59
* In the event of a failure, all returned pointers are invalid and no
60
* memory is left allocated.
62
* returns 0 on success
64
static int parse_arguments(int argc, char **argv, char **src, char **target,
80
len = strlen(ptr) + 1; /* + NULL terminator */
83
fprintf(stderr, "Unable to allocate source buffer\n");
87
memcpy(*src, ptr, len);
88
if ((*src)[len - 1] == '/')
89
(*src)[len - 1] = '\0';
93
len = strlen(ptr) + 1; /* + NULL-terminator */
94
*target = malloc(len);
96
fprintf(stderr, "Unable to allocate target buffer\n");
100
memcpy(*target, ptr, len);
101
if ((*target)[len - 1] == '/')
102
(*target)[len - 1] = '\0';
104
if (options && (argc == NUM_REQUIRED_ARGS)) {
105
fprintf(stderr, "Not enough remaining data for options\n");
107
} else if ((options) && (argc > NUM_REQUIRED_ARGS)) {
111
for (i = 3; i < (argc-1); i++)
112
if (!strcmp("-o", argv[i])) {
117
fprintf(stderr, "Unable to find a list of options to "
118
"parse, defaulting to interactive "
123
len = strlen(ptr) + 1; /* + NULL-terminator */
124
*options = malloc(len);
126
fprintf(stderr, "Unable to allocate memory for options "
131
memcpy(*options, ptr, len);
137
if (target && *target)
139
if (options && *options)
144
static int ecryptfs_generate_mount_flags(char *options, int *flags)
151
end = strchr(options, '\0');
154
if ((next_opt = strchr(opt, ',')))
156
/* the following mount options should be
157
* stripped out from what is passed into the
158
* kernel since these eight options are best
159
* passed as the mount flags rather than
160
* redundantly to the kernel and could
161
* generate spurious warnings depending on the
162
* level of the corresponding cifs vfs kernel
164
if (!strncmp(opt, "nosuid", 6))
166
else if (!strncmp(opt, "suid", 4))
167
*flags &= ~MS_NOSUID;
168
else if (!strncmp(opt, "nodev", 5))
170
else if (!strncmp(opt, "dev", 3))
172
else if (!strncmp(opt, "noexec", 6))
174
else if (!strncmp(opt, "exec", 4))
175
*flags &= ~MS_NOEXEC;
176
else if (!strncmp(opt, "ro", 2))
178
else if (!strncmp(opt, "rw", 2))
179
*flags &= ~MS_RDONLY;
180
else if (!strncmp(opt, "remount", 7))
181
*flags |= MS_REMOUNT;
195
memcpy(opt, next_opt, end - next_opt);
196
end = end - (next_opt - opt);
202
char *parameters_to_scrub[] = {
215
char *parameters_to_not_scrub[] = {
220
static int parameter_should_not_be_scrubbed(char *str) {
223
for (i = 0; parameters_to_not_scrub[i]; i++)
224
if (strstr(str, parameters_to_not_scrub[i]) == str)
229
static int parameter_should_be_scrubbed(char *str)
233
for (i = 0; parameters_to_scrub[i]; i++)
234
if (strstr(str, parameters_to_scrub[i]) == str
235
&& !parameter_should_not_be_scrubbed(str))
241
* Remove from the options string known options which should not be passed
242
* into the kernel. Any options that are unknown will be passed in.
243
* This is to account for options like "rw".
245
* Returns zero on success, non-zero otherwise
247
static int strip_userland_opts(char *options)
249
char *cur = NULL, *next = NULL;
250
char *temp, *temp_end;
252
int used = 0, first = 1;
254
len = (strlen(options) + 1);
255
if ((temp = (char*)malloc(len)) == NULL) {
256
fprintf(stderr, "Out of memory\n");
260
memset(temp, 0, len);
265
next = strstr(cur, ",");
270
if (!parameter_should_be_scrubbed(cur)) {
272
memcpy(temp_end, ",", 1);
275
opt_len = strlen(cur);
276
memcpy(temp_end, cur, opt_len);
277
temp_end = temp_end + opt_len;
283
memcpy(options,temp,len);
288
static int process_sig(char *auth_tok_sig)
293
char *sig_cache_filename = NULL;
294
char *dot_ecryptfs_dir;
307
rc = asprintf(&dot_ecryptfs_dir, "%s/.ecryptfs", home);
312
mkdir(dot_ecryptfs_dir, S_IRWXU);
313
free(dot_ecryptfs_dir);
314
rc = asprintf(&sig_cache_filename, "%s/.ecryptfs/sig-cache.txt",
321
if ((rc = ecryptfs_check_sig(auth_tok_sig, sig_cache_filename,
324
if (flags & ECRYPTFS_SIG_FLAG_NOENT) {
325
printf("WARNING: Based on the contents of [%s],\n"
326
"it looks like you have never mounted with this key \n"
327
"before. This could mean that you have typed your \n"
328
"passphrase wrong.\n\n", sig_cache_filename);
329
printf("Would you like to proceed with the mount (yes/no)? ");
332
yesno[i++] = mygetchar();
333
} while (yesno[i-1] != '\n' && i < 3);
335
if (yesno[i-1] != '\n')
336
while (mygetchar() != '\n');
337
if (memcmp(yesno, "yes", 3) == 0) {
338
printf("Would you like to append sig [%s] to\n"
340
"in order to avoid this warning in the future "
341
"(yes/no)? ", auth_tok_sig, sig_cache_filename);
344
yesno[i++] = mygetchar();
345
} while (yesno[i-1] != '\n' && i < 3);
347
if (yesno[i-1] != '\n')
348
while (mygetchar() != '\n');
349
if (memcmp(yesno, "yes", 3) == 0) {
350
if ((rc = ecryptfs_append_sig(
352
sig_cache_filename))) {
353
printf("Error appending to [%s]; rc = "
354
"[%d]. Aborting mount.\n",
355
sig_cache_filename, rc);
358
printf("Successfully appended new sig to user "
361
printf("Not adding sig to user sig cache "
362
"file; continuing with mount.\n");
364
printf("Aborting mount.\n");
370
free(sig_cache_filename);
374
static int opts_str_contains_option(char *options, char *option)
379
int option_len = strlen(option);
381
end = strchr(options, '\0');
384
if ((next_opt = strchr(opt, ',')))
386
if (!strncmp(opt, option, option_len))
400
memcpy(opt, next_opt, end - next_opt);
401
end = end - (next_opt - opt);
407
char *required_mount_opts[] = {
408
"ecryptfs_key_bytes=",
412
static int ecryptfs_validate_mount_opts(char *opts)
417
while (required_mount_opts[i]) {
418
if (!opts_str_contains_option(opts, required_mount_opts[i])) {
419
printf("Required mount option not provided: [%s]\n",
420
required_mount_opts[i]);
434
* The mount options actually sent to the kernel are in the @params
435
* linked list of struct val_node objects. params <-
436
* ecryptfs_process_decision_graph(head) -> decision_graph_mount(head)
437
* -> eval_param_tree(val_stack_head) -> do_transition(val_stack_head)
438
* -> trans_func(head).
440
static int ecryptfs_do_mount(int argc, char **argv, struct val_node *mnt_params,
446
char *src = NULL, *targ = NULL, *opts = NULL, *new_opts = NULL, *temp;
449
if ((rc = parse_arguments(argc, argv, &src, &targ, &opts))) {
450
fprintf(stderr, "Unable to understand the mount options\n");
453
rc = strip_userland_opts(opts);
456
num_opts = ecryptfs_generate_mount_flags(opts, &flags);
457
asprintf(&new_opts, "%s", opts);
458
printf("Attempting to mount with the following options:\n");
459
while (!stack_pop_val(&mnt_params, (void *)&val)) {
463
printf(" %s\n", val);
464
if (sig_cache && memcmp(val, "ecryptfs_sig=", 13) == 0) {
465
if ((rc = process_sig(&val[13]))) {
466
printf("Error processing sig; rc = [%d]\n", rc);
470
rc = asprintf(&new_opts, "%s,%s", val, temp);
479
if ((rc = ecryptfs_validate_mount_opts(new_opts)) != 0) {
480
printf("Invalid mount options; aborting. rc = [%d]\n",
484
rc = ecryptfs_mount(src, targ, flags, new_opts);
493
static int dump_args = 0;
495
int main(int argc, char **argv)
499
struct val_node *mnt_params;
500
struct ecryptfs_ctx ctx;
504
rc = mlockall(MCL_FUTURE);
506
fprintf(stderr, "Exiting. Unable to mlockall address space\n");
512
for (i = 0; i < argc; i++)
513
printf("argv[%d] = [%s]\n", i, argv[i]);
515
if (argc < NUM_REQUIRED_ARGS) {
516
fprintf(stderr, "Insufficient number of arguments\n");
521
rc = ecryptfs_get_version(&version);
523
printf("\nUnable to get the version number of the kernel\n");
524
printf("module. Please make sure that you have the eCryptfs\n");
525
printf("kernel module loaded, you have sysfs mounted, and\n");
526
printf("the sysfs mount point is in /etc/mtab. This is\n");
527
printf("necessary so that the mount helper knows which \n");
528
printf("kernel options are supported.\n\n");
529
printf("Make sure that your system is set up to auto-load\n"
530
"your filesystem kernel module on mount.\n\n");
531
printf("Enabling passphrase-mode only for now.\n\n");
532
version = ECRYPTFS_VERSIONING_PASSPHRASE;
534
if ((rc = ecryptfs_validate_keyring())) {
535
printf("Unable to link the KEY_SPEC_USER_KEYRING into the "
536
"KEY_SPEC_SESSION_KEYRING; there is something wrong "
537
"with your kernel keyring. Did you build key retention "
538
"support into your kernel?\n");
541
mnt_params = malloc(sizeof(struct val_node));
542
memset(mnt_params, 0, sizeof(struct val_node));
543
memset(&ctx, 0, sizeof(struct ecryptfs_ctx));
544
ctx.get_string = &get_string_stdin;
545
if ((rc = parse_arguments(argc, argv, NULL, NULL, &opts_str)))
547
if (opts_str_contains_option(opts_str, "verbose"))
548
ecryptfs_verbosity = 1;
549
if (!opts_str_contains_option(opts_str, "remount")) {
550
if (opts_str_contains_option(opts_str, "no_sig_cache"))
552
rc = ecryptfs_process_decision_graph(
553
&ctx, &mnt_params, version, opts_str,
554
ECRYPTFS_ASK_FOR_ALL_MOUNT_OPTIONS);
556
printf("Error attempting to evaluate mount options; "
557
"rc = [%d]. Try updating/reinstalling your "
558
"ecryptfs-utils package, or submit a bug "
562
rc = ecryptfs_do_mount(argc, argv, mnt_params, sig_cache);
566
printf("Error mounting eCryptfs; rc = [%d]; strerr = "
567
"[%s]. Check your system logs; visit "
568
"<http://ecryptfs.sourceforge.net/"
569
"ecryptfs-faq.html>.\n", rc, strerror(-rc));
571
printf("Try ``modprobe ecryptfs''\n");
573
printf("Mounted eCryptfs\n");
575
fprintf(stderr, "When are remounting eCryptfs, you need "
576
"to pass the mount utility the -i parameter to avoid "
577
"calling the mount helper\n");