~ecryptfs/ecryptfs/trunk

« back to all changes in this revision

Viewing changes to src/utils/mount.ecryptfs_private.c

  • Committer: Dustin Kirkland
  • Date: 2016-02-27 00:00:23 UTC
  • Revision ID: kirkland@ubuntu.com-20160227000023-h0e4oui5y1vbaurd
openingĀ 112

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
 *
26
26
 */
27
27
 
28
 
#define _GNU_SOURCE
29
 
 
30
28
#include <sys/file.h>
31
29
#include <sys/mount.h>
32
30
#include <sys/param.h>
33
31
#include <sys/stat.h>
34
32
#include <sys/types.h>
 
33
#include <sys/vfs.h>
 
34
#include <fcntl.h>
 
35
#include <ctype.h>
35
36
#include <errno.h>
36
37
#include <keyutils.h>
37
38
#include <mntent.h>
53
54
#define FSTYPE "ecryptfs"
54
55
#define TMP "/dev/shm"
55
56
 
56
 
int saved_errno;
57
 
 
58
 
int read_config(char *pw_dir, int uid, char *alias, char **s, char **d, char **o) {
 
57
int read_config(char *pw_dir, uid_t uid, char *alias, char **s, char **d, char **o) {
59
58
/* Read an fstab(5) style config file */
60
59
        char *fnam;
61
60
        struct stat mstat;
95
94
        *s = strdup(e->mnt_fsname);
96
95
        if (!*s)
97
96
                return -2;
98
 
out:
 
97
 
99
98
        return 0;
100
99
}
101
100
 
110
109
        int i;
111
110
        char c;
112
111
        int len;
 
112
 
 
113
        if (u == NULL)
 
114
                goto empty;
113
115
        len = strlen(u);
114
 
        if (u == NULL || len == 0) {
115
 
                fputs("Username is empty\n", stderr);
116
 
                return 1;
117
 
        }
 
116
        if (len == 0)
 
117
                goto empty;
 
118
 
118
119
        for (i=0; i<len; i++) {
119
120
                c = u[i];
120
121
                if (    !(c>='a' && c<='z') && !(c>='A' && c<='Z') &&
128
129
                }
129
130
        }
130
131
        return 0;
 
132
empty:
 
133
        fputs("Username is empty\n", stderr);
 
134
        return 1;
131
135
}
132
136
 
133
 
char *fetch_sig(char *pw_dir, int entry, char *alias) {
 
137
char **fetch_sig(char *pw_dir, char *alias, int mounting) {
134
138
/* Read ecryptfs signature from file and validate
135
139
 * Return signature as a string, or NULL on failure
136
140
 */
137
 
        char *sig_file, c;
138
 
        FILE *fh;
139
 
        char *sig;
140
 
        int i;
 
141
        char *sig_file;
 
142
        FILE *fh = NULL;
 
143
        char **sig = NULL;
 
144
        unsigned int i, j;
141
145
        /* Construct sig file name */
142
 
        if (
143
 
            asprintf(&sig_file, "%s/.ecryptfs/%s.sig", pw_dir,
144
 
                     alias) < 0
145
 
           ) {
 
146
        if (asprintf(&sig_file, "%s/.ecryptfs/%s.sig", pw_dir, alias) < 0) {
146
147
                perror("asprintf");
147
 
                return NULL;
 
148
                goto err;
148
149
        }
149
150
        fh = fopen(sig_file, "r");
150
151
        if (fh == NULL) {
151
152
                perror("fopen");
152
 
                return NULL;
 
153
                goto err;
153
154
        }
154
 
        if ((sig = (char *)malloc(KEY_BYTES*sizeof(char)+1)) == NULL) {
 
155
        /* Read up to 2 lines from the file */
 
156
        if ((sig = malloc(sizeof(char*) * 2)) == NULL) {
155
157
                perror("malloc");
156
 
                return NULL;
157
 
        }
158
 
        /* Move to the correct line in the file */
159
 
        if (entry == 1) {
160
 
                while ((c = fgetc(fh)) != EOF) {
161
 
                        if (c == '\n') {
162
 
                                break;
163
 
                        }
164
 
                }
165
 
        }
166
 
        i = 0;
167
 
        /* Read KEY_BYTES characters from file */
168
 
        while ((c = fgetc(fh)) != EOF && i < KEY_BYTES) {
169
 
                if ((c>='0' && c<='9') || (c>='a' && c<='f') ||
170
 
                    (c>='A' && c<='F')) {
171
 
                        sig[i] = c;
172
 
                        i++;
173
 
                } else {
174
 
                        fputs("Invalid hex signature\n", stderr);
175
 
                        return NULL;
176
 
                }
177
 
        }
178
 
        fclose(fh);
179
 
        /* Check signature length */
180
 
        if (i != KEY_BYTES) {
181
 
                if (entry == 1 && i == 0) {
182
 
                        /* This means that we have no fnek sig; tis okay */
183
 
                } else {
 
158
                goto err;
 
159
        }
 
160
 
 
161
        sig[0] = NULL;
 
162
        sig[1] = NULL;
 
163
        for (i=0; i<2; i++) {
 
164
                if ((sig[i] = (char *)malloc(KEY_BYTES*sizeof(char)+2)) == NULL) {
 
165
                        perror("malloc");
 
166
                        goto err;
 
167
                }
 
168
                memset(sig[i], '\0', KEY_BYTES+2);
 
169
                /* Read KEY_BYTES characters from line */
 
170
                if (fgets(sig[i], KEY_BYTES+2, fh) == NULL) {
 
171
                        if (i == 0) {
 
172
                                fputs("Missing file encryption signature", stderr);
 
173
                                goto err;
 
174
                        } else {
 
175
                                /* Filename encryption isn't in use */
 
176
                                free(sig[i]);
 
177
                                sig[i] = NULL;
 
178
                                goto out;
 
179
                        }
 
180
                }
 
181
                /* Validate hex signature */
 
182
                for (j=0; j<strlen(sig[i]); j++) {
 
183
                        if (isxdigit(sig[i][j]) == 0 && isspace(sig[i][j]) == 0) {
 
184
                                fputs("Invalid hex signature\n", stderr);
 
185
                                goto err;
 
186
                        }
 
187
                        if (isspace(sig[i][j]) != 0) {
 
188
                                /* truncate at first whitespace */
 
189
                                sig[i][j] = '\0';
 
190
                        }
 
191
                }
 
192
                if (strlen(sig[i]) > 0 && strlen(sig[i]) != KEY_BYTES) {
184
193
                        fputs("Invalid hex signature length\n", stderr);
185
 
                }
186
 
                return NULL;
 
194
                        goto err;
 
195
                }
 
196
                /* Validate that signature is in the current keyring,
 
197
                 * compile with -lkeyutils
 
198
                 */
 
199
                if (keyctl_search(KEY_SPEC_USER_KEYRING, "user", sig[i], 0) < 0) {
 
200
                        if (mounting)
 
201
                                fputs("Signature not found in user keyring\n"
 
202
                                      "Perhaps try the interactive "
 
203
                                      "'ecryptfs-mount-private'\n", stderr);
 
204
                        goto err;
 
205
                }
187
206
        }
188
 
        sig[KEY_BYTES] = '\0';
189
 
        /* Validate that signature is in the current keyring,
190
 
         * compile with -lkeyutils
191
 
         */
192
 
        if (keyctl_search(KEY_SPEC_USER_KEYRING, "user", sig, 0) < 0) {
193
 
                saved_errno = errno;
194
 
                return NULL;
 
207
out:
 
208
        if (fh != NULL) {
 
209
                fclose(fh);
195
210
        }
196
211
        return sig;
197
 
}
198
 
 
199
 
int check_ownerships(int uid, char *path) {
 
212
err:
 
213
        if (fh) {
 
214
                fclose(fh);
 
215
        }
 
216
        /* Clean up malloc'd memory if failure */
 
217
        if (sig) {
 
218
                free(sig[0]);
 
219
                free(sig[1]);
 
220
                free(sig);
 
221
        }
 
222
        return NULL;
 
223
}
 
224
 
 
225
static int check_cwd_f_type()
 
226
{
 
227
        /**
 
228
         * This is *not* a list of compatible lower filesystems list for
 
229
         * eCryptfs. This is a list of filesystems that we reasonably expect to
 
230
         * see mount.ecryptfs_private users mounting on top of. In other words,
 
231
         * the filesystem type of the 'target' parameter of mount(2).
 
232
         *
 
233
         * This whitelist is to prevent malicious mount.ecryptfs_private users
 
234
         * from mounting over filesystem types such as PROC_SUPER_MAGIC to
 
235
         * deceive other programs with a crafted /proc/self/*. See
 
236
         * https://launchpad.net/bugs/1530566 for more details.
 
237
         */
 
238
        __SWORD_TYPE f_type_whitelist[] = {
 
239
                0x61756673 /* AUFS_SUPER_MAGIC */,
 
240
                0x9123683E /* BTRFS_SUPER_MAGIC */,
 
241
                0x00C36400 /* CEPH_SUPER_MAGIC */,
 
242
                0xFF534D42 /* CIFS_MAGIC_NUMBER */,
 
243
                0x0000F15F /* ECRYPTFS_SUPER_MAGIC */,
 
244
                0x0000EF53 /* EXT[234]_SUPER_MAGIC */,
 
245
                0xF2F52010 /* F2FS_SUPER_MAGIC */,
 
246
                0x65735546 /* FUSE_SUPER_MAGIC */,
 
247
                0x01161970 /* GFS2_MAGIC */,
 
248
                0x3153464A /* JFS_SUPER_MAGIC */,
 
249
                0x000072B6 /* JFFS2_SUPER_MAGIC */,
 
250
                0x0000564C /* NCP_SUPER_MAGIC */,
 
251
                0x00006969 /* NFS_SUPER_MAGIC */,
 
252
                0x00003434 /* NILFS_SUPER_MAGIC */,
 
253
                0x5346544E /* NTFS_SB_MAGIC */,
 
254
                0x794C7630 /* OVERLAYFS_SUPER_MAGIC */,
 
255
                0x52654973 /* REISERFS_SUPER_MAGIC */,
 
256
                0x73717368 /* SQUASHFS_MAGIC */,
 
257
                0x01021994 /* TMPFS_MAGIC */,
 
258
                0x24051905 /* UBIFS_SUPER_MAGIC */,
 
259
                0x58465342 /* XFS_SB_MAGIC */,
 
260
                0x2FC12FC1 /* ZFS_SUPER_MAGIC */,
 
261
        };
 
262
        struct statfs buf;
 
263
        size_t i, whitelist_len;
 
264
 
 
265
        if (statfs(".", &buf) != 0) {
 
266
                fprintf(stderr, "Failed to check filesystem type: %m\n");
 
267
                return 1;
 
268
        }
 
269
 
 
270
        whitelist_len = sizeof(f_type_whitelist) / sizeof(*f_type_whitelist);
 
271
        for (i = 0; i < whitelist_len; i++) {
 
272
                if (buf.f_type == f_type_whitelist[i]) {
 
273
                        return 0;
 
274
                }
 
275
        }
 
276
 
 
277
        fprintf(stderr,
 
278
                "Refusing to mount over an unapproved filesystem type: %#lx\n",
 
279
                buf.f_type);
 
280
        return 1;
 
281
}
 
282
 
 
283
int check_ownership_mnt(uid_t uid, char **mnt) {
 
284
/* Check ownership of mount point, chdir into it, and
 
285
 * canonicalize the path for use in mtab updating.
 
286
 * Return 0 if everything is in order, 1 on error.
 
287
 */
 
288
        struct stat s;
 
289
        char *cwd;
 
290
 
 
291
        /* From here on, we'll refer to "." as our mountpoint, to avoid
 
292
         * races.
 
293
         */
 
294
        if (chdir(*mnt) != 0) {
 
295
                fputs("Cannot chdir into mountpoint.\n", stderr);
 
296
                return 1;
 
297
        }
 
298
        if (stat(".", &s) != 0) {
 
299
                fputs("Cannot examine mountpoint.\n", stderr);
 
300
                return 1;
 
301
        }
 
302
        if (!S_ISDIR(s.st_mode)) {
 
303
                fputs("Mountpoint is not a directory.\n", stderr);
 
304
                return 1;
 
305
        }
 
306
        if (s.st_uid != uid) {
 
307
                fputs("You do not own that mountpoint.\n", stderr);
 
308
                return 1;
 
309
        }
 
310
 
 
311
        /* Canonicalize our pathname based on the current directory to
 
312
         * avoid races.
 
313
         */
 
314
        cwd = getcwd(NULL, 0);
 
315
        if (!cwd) {
 
316
                fputs("Failed to get current directory\n", stderr);
 
317
                return 1;
 
318
        }
 
319
        *mnt = cwd;
 
320
        return 0;
 
321
}
 
322
 
 
323
 
 
324
int check_ownerships(uid_t uid, char *path) {
200
325
/* Check ownership of device and mount point.
201
326
 * Return 0 if everything is in order, 1 on error.
202
327
 */
218
343
 
219
344
 
220
345
int update_mtab(char *dev, char *mnt, char *opt) {
221
 
/* Update /etc/mtab with new mount entry.
 
346
/* Update /etc/mtab with new mount entry unless it is a symbolic link
222
347
 * Return 0 on success, 1 on failure.
223
348
 */
224
 
        FILE *fh;
225
 
        struct mntent m;
226
 
        fh = setmntent("/etc/mtab", "a");
227
 
        if (fh == NULL) {
228
 
                perror("setmntent");
229
 
                /* Unmount if mtab cannot be updated */
230
 
                umount(mnt);
231
 
                return 1;
232
 
        }
233
 
        m.mnt_fsname = dev;
234
 
        m.mnt_dir = mnt;
235
 
        m.mnt_type = FSTYPE;
236
 
        m.mnt_opts = opt;
237
 
        m.mnt_freq = 0;
238
 
        m.mnt_passno = 0;
239
 
        flockfile(fh);
240
 
        if (addmntent(fh, &m) != 0) {
 
349
        char dummy;
 
350
        int useMtab;
 
351
        /* Check if mtab is a symlink */
 
352
        useMtab = (readlink("/etc/mtab", &dummy, 1) < 0);
 
353
        if (!useMtab) {
 
354
                /* No need updating mtab */
 
355
                return 0;
 
356
        }
 
357
 
 
358
        int fd;
 
359
        FILE *old_mtab, *new_mtab;
 
360
        struct mntent *old_ent, new_ent;
 
361
        mode_t old_umask;
 
362
 
 
363
        /* Make an attempt to play nice with other mount helpers
 
364
         * by creating an /etc/mtab~ lock file. Of course this
 
365
         * only works if those other helpers actually check for
 
366
         * this.
 
367
         */
 
368
        old_umask = umask(033);
 
369
        fd = open("/etc/mtab~", O_RDONLY | O_CREAT | O_EXCL, 0644);
 
370
        if (fd < 0) {
 
371
                perror("open");
 
372
                return 1;
 
373
        }
 
374
        close(fd);
 
375
 
 
376
        old_mtab = setmntent("/etc/mtab", "r");
 
377
        if (old_mtab == NULL) {
 
378
                perror("setmntent");
 
379
                return 1;
 
380
        }
 
381
 
 
382
        new_mtab = setmntent("/etc/mtab.tmp", "w");
 
383
        if (new_mtab == NULL) {
 
384
                perror("setmntent");
 
385
                goto fail_early;
 
386
        }
 
387
 
 
388
        while ((old_ent = getmntent(old_mtab))) {
 
389
                if (addmntent(new_mtab, old_ent) != 0) {
 
390
                        perror("addmntent");
 
391
                        goto fail;
 
392
                }
 
393
        }
 
394
        endmntent(old_mtab);
 
395
 
 
396
        new_ent.mnt_fsname = dev;
 
397
        new_ent.mnt_dir = mnt;
 
398
        new_ent.mnt_type = FSTYPE;
 
399
        new_ent.mnt_opts = opt;
 
400
        new_ent.mnt_freq = 0;
 
401
        new_ent.mnt_passno = 0;
 
402
 
 
403
        if (addmntent(new_mtab, &new_ent) != 0) {
241
404
                perror("addmntent");
242
 
                endmntent(fh);
243
 
                /* Unmount if mtab cannot be updated */
244
 
                umount(mnt);
245
 
                return 1;
246
 
        }
247
 
        endmntent(fh);
 
405
                goto fail;
 
406
        }
 
407
 
 
408
        if (fchmod(fileno(new_mtab), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < 0) {
 
409
                perror("fchmod");
 
410
                goto fail;
 
411
        }
 
412
        endmntent(new_mtab);
 
413
 
 
414
        if (rename("/etc/mtab.tmp", "/etc/mtab") < 0) {
 
415
                perror("rename");
 
416
                goto fail_late;
 
417
        }
 
418
 
 
419
        unlink("/etc/mtab~");
 
420
 
 
421
        umask(old_umask);
 
422
 
248
423
        return 0;
 
424
 
 
425
fail:
 
426
        endmntent(new_mtab);
 
427
fail_late:
 
428
        unlink("/etc/mtab.tmp");
 
429
fail_early:
 
430
        endmntent(old_mtab);
 
431
        unlink("/etc/mtab~");
 
432
        umask(old_umask);
 
433
        return 1;
249
434
}
250
435
 
251
 
FILE *lock_counter(char *u, int uid, char *alias) {
 
436
FILE *lock_counter(char *u, uid_t uid, char *alias) {
252
437
        char *f;
253
438
        int fd;
254
439
        FILE *fh;
264
449
         * file, or it's not owned by the current user, append iterator
265
450
         * until we find a filename we can use.
266
451
         */
267
 
        while (1) {
268
 
                if (stat(f, &s)==0 && (!S_ISREG(s.st_mode) || s.st_uid!=uid)) {
 
452
        while (i < 50) {
 
453
                if (((fd = open(f, O_RDWR | O_CREAT | O_NOFOLLOW, 0600)) >= 0) &&
 
454
                    (fstat(fd, &s)==0 && (S_ISREG(s.st_mode) && s.st_uid==uid))) {
 
455
                        break;
 
456
                } else {
 
457
                        if (fd >= 0) {
 
458
                                close(fd);
 
459
                                fd = -1;
 
460
                        }
269
461
                        free(f);
270
462
                        if (asprintf(&f, "%s/%s-%s-%s-%d", TMP, FSTYPE, u,
271
463
                            alias, i++) < 0) {
272
464
                                perror("asprintf");
273
465
                                return NULL;
274
466
                        }
275
 
                } else {
276
 
                        break;
277
 
                }
278
 
        }
279
 
        /* open file for reading and writing */
280
 
        if ((fd = open(f, O_RDWR)) < 0) {
281
 
                /* Could not open it, so try to safely create it */
282
 
                if ((fd = open(f, O_RDWR | O_CREAT | O_EXCL, 0600)) < 0) {
283
 
                        perror("open");
284
 
                        return NULL;
285
 
                }
286
 
        }
 
467
                }
 
468
        }
 
469
 
 
470
        if (fd < 0) {
 
471
                perror("open");
 
472
                return NULL;
 
473
        }
 
474
 
287
475
        flock(fd, LOCK_EX);
288
476
        fh = fdopen(fd, "r+");
289
477
        if (fh == NULL) {
344
532
        return bump_counter(fh, -MAXINT+1);
345
533
}
346
534
 
 
535
/* Returns -1 on error, 0 on success, and 1 if the program should exit with 0 */
 
536
static int parse_options(int argc, char *argv[], int *mounting, int *force,
 
537
                         int *nonzero_decrement_is_error, char **alias)
 
538
{
 
539
        const char *optstr, *usagestr;
 
540
        int opt, usage = 0, rc = -1;
 
541
 
 
542
        *force = 0;
 
543
        *nonzero_decrement_is_error = 1;
 
544
        *alias = NULL;
 
545
 
 
546
        /* Determine if mounting or unmounting by looking at the invocation */
 
547
        if (strstr(argv[0], "umount") == NULL) {
 
548
                *mounting = 1;
 
549
                optstr = "h";
 
550
                usagestr = "[ALIAS]\n"
 
551
                           "Mount the default private directory or ALIAS, if specified.\n"
 
552
                           "\n"
 
553
                           "  -h        display this help and exit\n";
 
554
        } else {
 
555
                *mounting = 0;
 
556
                optstr = "hfd";
 
557
                usagestr = "[-f] [-d] [ALIAS]\n"
 
558
                           "Unmount the default private directory or ALIAS, if specified.\n"
 
559
                           "\n"
 
560
                           "  -h        display this help and exit\n"
 
561
                           "  -f        forcibly unmount\n"
 
562
                           "  -d        don't treat a non-zero session counter as an error\n";
 
563
        }
 
564
 
 
565
        while ((opt = getopt(argc, argv, optstr)) != -1) {
 
566
                switch (opt) {
 
567
                        case 'h':
 
568
                                rc = 1;
 
569
                                usage = 1;
 
570
                                goto out;
 
571
                        case 'f':
 
572
                                *force = 1;
 
573
                                break;
 
574
                        case 'd':
 
575
                                *nonzero_decrement_is_error = 0;
 
576
                                break;
 
577
                        default:
 
578
                                usage = 1;
 
579
                                goto out;
 
580
                }
 
581
        }
 
582
 
 
583
        if (optind < (argc - 1)) {
 
584
                usage = 1;
 
585
                goto out;
 
586
        } else if (optind == (argc - 1)) {
 
587
                *alias = argv[optind];
 
588
        }
 
589
 
 
590
        rc = 0;
 
591
out:
 
592
        if (usage)
 
593
                fprintf(stderr, "Usage: %s %s", argv[0], usagestr);
 
594
        return rc;
 
595
}
347
596
 
348
597
/* This program is a setuid-executable allowing a non-privileged user to mount
349
598
 * and unmount an ecryptfs private directory.  This program is necessary to
379
628
 *  c) updating /etc/mtab
380
629
 */
381
630
int main(int argc, char *argv[]) {
382
 
        int uid, mounting;
383
 
        int force = 0;
 
631
        uid_t uid;
 
632
        gid_t gid;
 
633
        int mounting, force, nonzero_decrement_is_error;
384
634
        struct passwd *pwd;
385
635
        char *alias, *src, *dest, *opt, *opts2;
386
 
        char *sig, *sig_fnek;
 
636
        char *sig_fekek = NULL, *sig_fnek = NULL;
 
637
        char **sigs;
387
638
        FILE *fh_counter = NULL;
388
639
 
389
640
        uid = getuid();
 
641
        gid = getgid();
390
642
        /* Non-privileged effective uid is sufficient for all but the code
391
643
         * that mounts, unmounts, and updates /etc/mtab.
392
644
         * Run at a lower privilege until we need it.
400
652
                goto fail;
401
653
        }
402
654
 
 
655
        switch (parse_options(argc, argv, &mounting, &force,
 
656
                              &nonzero_decrement_is_error, &alias)) {
 
657
                case -1:
 
658
                        goto fail;
 
659
                case 1:
 
660
                        goto success;
 
661
                default:
 
662
                        break; /* proceed */
 
663
        }
 
664
 
403
665
        /* If no arguments, default to private dir; but accept at most one
404
666
           argument, an alias for the configuration to read and use.
405
667
         */
406
 
        if (argc == 1) {
 
668
        if (alias == NULL) {
407
669
                /* Use default source and destination dirs */
408
670
                alias = ECRYPTFS_PRIVATE_DIR;
409
671
                if ((asprintf(&src, "%s/.%s", pwd->pw_dir, alias) < 0) || src == NULL) {
415
677
                        perror("asprintf (dest)");
416
678
                        goto fail;
417
679
                }
418
 
        } else if (argc == 2) {
419
 
                alias = argv[1];
 
680
        } else {
420
681
                /* Read the source and destination dirs from .conf file */
421
682
                if (read_config(pwd->pw_dir, uid, alias, &src, &dest, &opts2) < 0) {
422
 
                        fputs("Error reading configuration file", stderr);
 
683
                        fputs("Error reading configuration file\n", stderr);
423
684
                        exit(1);
424
685
                }
425
686
                if (opts2 != NULL && strlen(opts2) != 0 && strcmp(opts2, "none") != 0) {
426
 
                        fputs("Mount options are not supported here", stderr);
 
687
                        fputs("Mount options are not supported here\n", stderr);
427
688
                        exit(1);
428
689
                }
429
 
        } else {
430
 
                fputs("Too many arguments", stderr);
 
690
        }
 
691
 
 
692
        if (strstr(alias, "..")) {
 
693
                fputs("Invalid alias", stderr);
431
694
                exit(1);
432
695
        }
433
696
 
434
697
        /* Lock the counter through the rest of the program */
435
698
        fh_counter = lock_counter(pwd->pw_name, uid, alias);
436
699
        if (fh_counter == NULL) {
437
 
                fputs("Error locking counter", stderr);
 
700
                fputs("Error locking counter\n", stderr);
438
701
                goto fail;
439
702
        }
440
703
 
445
708
                goto fail;
446
709
        }
447
710
 
448
 
        /* Determine if mounting or unmounting by looking at the invocation */
449
 
        if (strstr(argv[0], "umount") == NULL) {
450
 
                mounting = 1;
451
 
        } else {
452
 
                mounting = 0;
453
 
                /* Determine if unmounting is forced */
454
 
                if (argv[1] != NULL && strncmp(argv[1], "-f", 2) == 0) {
455
 
                        force = 1;
456
 
                } else {
457
 
                        force = 0;
458
 
                }
459
 
        }
460
 
 
461
711
        /* Fetch signatures from file */
462
712
        /* First line is the file content encryption key signature */
463
 
        sig = fetch_sig(pwd->pw_dir, 0, alias);
464
 
        if (sig == NULL) {
 
713
        /* Second line, if present, is the filename encryption key signature */
 
714
        sigs = fetch_sig(pwd->pw_dir, alias, mounting);
 
715
        if (!sigs && mounting) {
465
716
                /* if umounting, no sig is ok */
466
 
                if (mounting) {
467
 
                        errno = saved_errno;
468
 
                        perror("keyctl_search");
469
 
                        fputs("Perhaps try the interactive 'ecryptfs-mount-private'\n",
470
 
                                stderr);
471
 
                        goto fail;
472
 
                }
 
717
                goto fail;
 
718
        } else if (sigs) {
 
719
                sig_fekek = sigs[0];
 
720
                sig_fnek = sigs[1];
473
721
        }
474
 
        /* Second line, if present, is the filename encryption key signature */
475
 
        sig_fnek = fetch_sig(pwd->pw_dir, 1, alias);
476
722
 
477
723
        /* Build mount options */
478
724
        if (
479
 
            (asprintf(&opt, "ecryptfs_cipher=%s,ecryptfs_key_bytes=%d,ecryptfs_unlink_sigs%s%s%s%s",
 
725
            (asprintf(&opt, "ecryptfs_check_dev_ruid,ecryptfs_cipher=%s,ecryptfs_key_bytes=%d,ecryptfs_unlink_sigs%s%s%s%s",
480
726
                      KEY_CIPHER,
481
727
                      KEY_BYTES,
482
 
                      sig ? ",ecryptfs_sig=" : "",
483
 
                      sig ? sig : "",
 
728
                      sig_fekek ? ",ecryptfs_sig=" : "",
 
729
                      sig_fekek ? sig_fekek : "",
484
730
                      sig_fnek ? ",ecryptfs_fnek_sig=" : "",
485
731
                      sig_fnek ? sig_fnek : ""
486
732
                     ) < 0
490
736
                goto fail;
491
737
        }
492
738
 
493
 
        /* Check ownership of dest */
494
 
        if (check_ownerships(uid, dest) != 0) {
 
739
        /* Check ownership of the mountpoint. From here on, dest refers
 
740
         * to a canonicalized path, and the mountpoint is the cwd. */
 
741
        if (check_ownership_mnt(uid, &dest) != 0) {
 
742
                goto fail;
 
743
        }
 
744
 
 
745
        if (check_cwd_f_type() != 0) {
495
746
                goto fail;
496
747
        }
497
748
 
501
752
                        fputs("Error incrementing mount counter\n", stderr);
502
753
                }
503
754
                /* Mounting, so exit if already mounted */
504
 
                if (ecryptfs_private_is_mounted(src, dest, sig, mounting) == 1) {
 
755
                if (ecryptfs_private_is_mounted(src, dest, sig_fekek, mounting) == 1) {
505
756
                        goto success;
506
757
                }
507
 
                /* Check ownership of src, if mounting;
508
 
                 * note, umount only operates on dest
509
 
                 */
510
 
                if (check_ownerships(uid, src) != 0) {
511
 
                        goto fail;
512
 
                }
513
758
                /* We must maintain our real uid as the user who called this
514
759
                 * program in order to have access to their kernel keyring.
515
760
                 * Even though root has the power to mount, only a user with
519
764
                 * the real uid to be that of the user.
520
765
                 * And we need the effective uid to be root in order to mount.
521
766
                 */
522
 
                setreuid(-1, 0);
523
 
                /* Perform mount */
524
 
                if (mount(src, dest, FSTYPE, 0, opt) == 0) {
 
767
                if (setreuid(-1, 0) < 0) {
 
768
                        perror("setreuid");
 
769
                        goto fail;
 
770
                }
 
771
                if (setregid(-1, 0) < 0) {
 
772
                        perror("setregid");
 
773
                        goto fail;
 
774
                }
 
775
                /* Perform mount */
 
776
                if (mount(src, ".", FSTYPE, MS_NOSUID | MS_NODEV, opt) == 0) {
525
777
                        if (update_mtab(src, dest, opt) != 0) {
526
778
                                goto fail;
527
779
                        }
531
783
                        if (setreuid(uid, uid) < 0) {
532
784
                                perror("setreuid");
533
785
                        }
 
786
                        if (setregid(gid, gid) < 0) {
 
787
                                perror("setregid");
 
788
                        }
534
789
                        goto fail;
535
790
                }
536
791
        } else {
539
794
                if (force == 1) {
540
795
                        zero(fh_counter);
541
796
                } else if (decrement(fh_counter) > 0) {
 
797
                        if (!nonzero_decrement_is_error)
 
798
                                goto success;
542
799
                        fputs("Sessions still open, not unmounting\n", stderr);
543
800
                        goto fail;
544
801
                }
546
803
                   to prevent root from mounting without the user's key.
547
804
                   This is a best-effort basis, so we'll just print messages
548
805
                   on error. */
549
 
                if (sig != NULL) {
550
 
                        rc = ecryptfs_remove_auth_tok_from_keyring(sig);
 
806
                if (sig_fekek != NULL) {
 
807
                        rc = ecryptfs_remove_auth_tok_from_keyring(sig_fekek);
551
808
                        if (rc != 0 && rc != ENOKEY)
552
809
                                fputs("Could not remove key from keyring, try 'ecryptfs-umount-private'\n", stderr);
553
810
                }
557
814
                                fputs("Could not remove key from keyring, try 'ecryptfs-umount-private'\n", stderr);
558
815
                }
559
816
                /* Unmounting, so exit if not mounted */
560
 
                if (ecryptfs_private_is_mounted(src, dest, sig, mounting) == 0) {
 
817
                if (ecryptfs_private_is_mounted(src, dest, sig_fekek, mounting) == 0) {
561
818
                        goto fail;
562
819
                }
563
820
                /* The key is not needed for unmounting, so we set res=0.
566
823
                 * Do not use the umount.ecryptfs helper (-i).
567
824
                 */
568
825
                setresuid(0,0,0);
569
 
                execl("/bin/umount", "umount", "-i", "-l", dest, NULL);
 
826
                setresgid(0,0,0);
 
827
                clearenv();
 
828
 
 
829
                /* Since we're doing a lazy unmount anyway, just unmount the current
 
830
                 * directory. This avoids a lot of complexity in dealing with race
 
831
                 * conditions, and guarantees that we're only unmounting a filesystem
 
832
                 * that we own. */
 
833
                execl("/bin/umount", "umount", "-i", "-l", ".", NULL);
570
834
                perror("execl unmount failed");
571
835
                goto fail;
572
836
        }