~ecryptfs/ecryptfs/trunk

« back to all changes in this revision

Viewing changes to src/libecryptfs/main.c

  • Committer: Dustin Kirkland
  • Date: 2009-02-13 15:57:24 UTC
  • Revision ID: kirkland@canonical.com-20090213155724-1q3qz2o0cbyimu9x
debian/ubuntu packaging

Initial checkin of the Debian/Ubuntu packaging

Signed-off-by: Dustin Kirkland <kirkland@canonical.com>

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
 * 02111-1307, USA.
20
20
 */
21
21
 
 
22
#include "config.h"
22
23
#include <errno.h>
 
24
#ifdef ENABLE_NSS
23
25
#include <nss.h>
24
26
#include <pk11func.h>
 
27
#else
 
28
#include <gcrypt.h>
 
29
#endif /* #ifdef ENABLE_NSS */
25
30
#include <mntent.h>
26
31
#ifndef S_SPLINT_S
27
32
#include <stdio.h>
32
37
#include <signal.h>
33
38
#include <sys/mount.h>
34
39
#include <getopt.h>
 
40
#include <keyutils.h>
35
41
#include <sys/types.h>
36
 
#include <keyutils.h>
37
42
#include <sys/ipc.h>
38
 
#include <sys/param.h>
39
43
#include <sys/shm.h>
40
44
#include <sys/sem.h>
41
45
#include "../include/ecryptfs.h"
73
77
 
74
78
int do_hash(char *src, int src_size, char *dst, int algo)
75
79
{
 
80
#ifdef ENABLE_NSS
76
81
        SECStatus err;
 
82
#else
 
83
        gcry_md_hd_t hd;
 
84
        gcry_error_t err = 0;
 
85
        unsigned char * hash;
 
86
        unsigned int mdlen;
 
87
#endif /* #ifdef ENABLE_NSS */
77
88
 
 
89
#ifdef ENABLE_NSS
78
90
        NSS_NoDB_Init(NULL);
79
91
        err = PK11_HashBuf(algo, (unsigned char *)dst, (unsigned char *)src,
80
92
                           src_size);
85
97
                err = -EINVAL;
86
98
                goto out;
87
99
        }
 
100
#else
 
101
        err = gcry_md_open(&hd, algo, 0);
 
102
        mdlen = gcry_md_get_algo_dlen(algo);
 
103
        if (err) {
 
104
                syslog(LOG_ERR, "Failed to open hash algo [%d]: "
 
105
                       "[%d]\n", algo, err);
 
106
                goto out;
 
107
        }
 
108
        gcry_md_write(hd, src, src_size);
 
109
        hash = gcry_md_read(hd, algo);
 
110
        memcpy(dst, hash, mdlen);
 
111
        gcry_md_close(hd);
 
112
#endif /* #ifdef ENABLE_NSS */
88
113
out:
89
114
        return (int)err;
90
115
}
91
116
 
92
 
/* Read ecryptfs private mount from file
93
 
 * Allocate and return a string
94
 
 */
95
 
char *ecryptfs_fetch_private_mnt(char *pw_dir) {
96
 
        char *mnt_file = NULL;
97
 
        char *mnt_default = NULL;
98
 
        char *mnt = NULL;
99
 
        FILE *fh = NULL;
100
 
        /* Construct mnt file name */
101
 
        if (asprintf(&mnt_default, "%s/%s", pw_dir, ECRYPTFS_PRIVATE_DIR) < 0
102
 
                        || mnt_default == NULL) {
103
 
                perror("asprintf");
104
 
                return NULL;
105
 
        }
106
 
        if (
107
 
                        asprintf(&mnt_file, "%s/.ecryptfs/%s.mnt", pw_dir, ECRYPTFS_PRIVATE_DIR) < 0
108
 
                        || mnt_file == NULL) {
109
 
                perror("asprintf");
110
 
                return NULL;
111
 
        }
112
 
        fh = fopen(mnt_file, "r");
113
 
        if (fh == NULL) {
114
 
                mnt = mnt_default;
115
 
        } else {
116
 
                flockfile(fh);
117
 
                if ((mnt = (char *)malloc(MAXPATHLEN+1)) == NULL) {
118
 
                        fclose(fh);
119
 
                        perror("malloc");
120
 
                        return NULL;
121
 
                }
122
 
                if (fgets(mnt, MAXPATHLEN, fh) == NULL) {
123
 
                        free(mnt);
124
 
                        mnt = mnt_default;
125
 
                } else {
126
 
                        /* Ensure that mnt doesn't contain newlines */
127
 
                        char *nl = strchr(mnt, '\n');
128
 
                        if (nl)
129
 
                                *nl = '\0';
130
 
                }
131
 
                fclose(fh);
132
 
        }
133
 
        if (mnt_file != NULL)
134
 
                free(mnt_file);
135
 
        if (mnt_default != NULL && mnt != mnt_default)
136
 
                free(mnt_default);
137
 
        return mnt;
138
 
}
139
 
 
140
 
 
141
 
/* Check if an ecryptfs private device or mount point is mounted.
142
 
 * Return 1 if a filesystem in mtab matches dev && mnt && sig.
143
 
 * Return 0 otherwise.
144
 
 */
145
 
int ecryptfs_private_is_mounted(char *dev, char *mnt, char *sig, int mounting) {
146
 
        FILE *fh = NULL;
147
 
        struct mntent *m = NULL;
148
 
        char *opt = NULL;
149
 
        int mounted;
150
 
        if (sig && asprintf(&opt, "ecryptfs_sig=%s", sig) < 0) {
151
 
                perror("asprintf");
152
 
                return 0;
153
 
        }
154
 
        fh = setmntent("/proc/mounts", "r");
155
 
        if (fh == NULL) {
156
 
                perror("setmntent");
157
 
                return 0;
158
 
        }
159
 
        mounted = 0;
160
 
        flockfile(fh);
161
 
        while ((m = getmntent(fh)) != NULL) {
162
 
                if (strcmp(m->mnt_type, "ecryptfs") != 0)
163
 
                        /* Skip if this entry is not an ecryptfs mount */
164
 
                        continue;
165
 
                if (mounting == 1) {
166
 
                        /* If mounting, return "already mounted" if EITHER the
167
 
                         * dev or the mnt dir shows up in mtab/mounts;
168
 
                         * regardless of the signature of such mounts;
169
 
                         */
170
 
                        if (dev != NULL && strcmp(m->mnt_fsname, dev) == 0) {
171
 
                                mounted = 1;
172
 
                                break;
173
 
                        }
174
 
                        if (mnt != NULL && strcmp(m->mnt_dir, mnt) == 0) {
175
 
                                mounted = 1;
176
 
                                break;
177
 
                        }
178
 
                } else {
179
 
                        /* Otherwise, we're unmounting, and we need to be
180
 
                         * very conservative in finding a perfect match
181
 
                         * to unmount.  The device, mountpoint, and signature
182
 
                         * must *all* match perfectly.
183
 
                         */
184
 
                        if (
185
 
                            strcmp(m->mnt_fsname, dev) == 0 &&
186
 
                            strcmp(m->mnt_dir, mnt) == 0 &&
187
 
                            (!opt || hasmntopt(m, opt) != NULL)
188
 
                        ) {
189
 
                                mounted = 1;
190
 
                                break;
191
 
                        }
192
 
                }
193
 
        }
194
 
        endmntent(fh);
195
 
        if (opt != NULL)
196
 
                free(opt);
197
 
        return mounted;
198
 
}
199
 
 
200
 
 
201
117
/**
202
118
 * TODO: We need to support more hash algs
203
119
 * @fekek: ECRYPTFS_MAX_KEY_BYTES bytes of allocated memory
217
133
        char salt_and_passphrase[ECRYPTFS_MAX_PASSPHRASE_BYTES
218
134
                                 + ECRYPTFS_SALT_SIZE];
219
135
        int passphrase_size;
 
136
#ifdef ENABLE_NSS
220
137
        int alg = SEC_OID_SHA512;
 
138
#else
 
139
        int alg = GCRY_MD_SHA512;
 
140
#endif /* #ifdef ENABLE_NSS */
221
141
        int dig_len = SHA512_DIGEST_LENGTH;
222
142
        char buf[SHA512_DIGEST_LENGTH];
223
143
        int hash_iterations = ECRYPTFS_DEFAULT_NUM_HASH_ITERATIONS;
383
303
        return rc;
384
304
}
385
305
 
 
306
int ecryptfs_mount(char *source, char *target, unsigned long flags, char *opts)
 
307
{
 
308
        FILE *mtab_fd = NULL;
 
309
        struct mntent mountent;
 
310
        char *fullpath_source = NULL;
 
311
        char *fullpath_target = NULL;
 
312
        int rc;
 
313
 
 
314
        mountent.mnt_opts = NULL;
 
315
        if (!source) {
 
316
                rc = -EINVAL;
 
317
                syslog(LOG_ERR, "Invalid source directory\n");
 
318
                goto out;
 
319
        }
 
320
        if (!target) {
 
321
                rc = -EINVAL;
 
322
                syslog(LOG_ERR, "Invalid target directory\n");
 
323
                goto out;
 
324
        }
 
325
        if (strlen(opts) > 200) {
 
326
                rc = -EINVAL;
 
327
                syslog(LOG_ERR, "Invalid mount options length\n");
 
328
                goto out;
 
329
        }
 
330
 
 
331
        fullpath_source = realpath(source, NULL);
 
332
        if (!fullpath_source) {
 
333
                rc = -errno;
 
334
                syslog(LOG_ERR, "could not resolve full path for source %s [%d]",
 
335
                        source, -errno);
 
336
                goto out;
 
337
        }
 
338
        fullpath_target = realpath(target, NULL);
 
339
        if (!fullpath_target) {
 
340
                rc = -errno;
 
341
                syslog(LOG_ERR, "could not resolve full path for target %s [%d]",
 
342
                        target, -errno);
 
343
                goto out;
 
344
        }
 
345
 
 
346
        if (mount(fullpath_source, fullpath_target, "ecryptfs", flags, opts)) {
 
347
                rc = -errno;
 
348
                syslog(LOG_ERR, "Failed to perform eCryptfs mount: [%m]\n");
 
349
                goto out;
 
350
        }
 
351
        mtab_fd = setmntent("/etc/mtab", "a");
 
352
        if (!mtab_fd) {
 
353
                rc = -EACCES;
 
354
                syslog(LOG_ERR, "Failed to update the mount table\n");
 
355
                goto out;
 
356
        }
 
357
        mountent.mnt_fsname = fullpath_source;
 
358
        mountent.mnt_dir = fullpath_target;
 
359
        mountent.mnt_type = "ecryptfs";
 
360
        /* we need the following byte count:
 
361
         * 200 max for opts
 
362
         * 23  max for strings below
 
363
         * 1   the final \0
 
364
         */
 
365
        mountent.mnt_opts = malloc(224);
 
366
        if (!mountent.mnt_opts) {
 
367
                rc = -ENOMEM;
 
368
                syslog(LOG_ERR, "Failed to allocate memory for mount "
 
369
                       "options\n");
 
370
                goto out;
 
371
        }
 
372
        memset(mountent.mnt_opts, 0, 224);
 
373
        /* reporting the right mount opts */
 
374
        if (flags & MS_RDONLY)
 
375
                strcat(mountent.mnt_opts,"ro");
 
376
        else
 
377
                strcat(mountent.mnt_opts,"rw");
 
378
        if (flags & MS_NOEXEC)
 
379
                strcat(mountent.mnt_opts,",noexec");
 
380
        if (flags & MS_NOSUID)
 
381
                strcat(mountent.mnt_opts,",nosuid");
 
382
        if (flags & MS_NODEV)
 
383
                strcat(mountent.mnt_opts,",nodev");
 
384
        if (opts) {
 
385
                strcat(mountent.mnt_opts, ",");
 
386
                strcat(mountent.mnt_opts, opts);
 
387
        }
 
388
        mountent.mnt_freq = 0;
 
389
        mountent.mnt_passno = 0;
 
390
        if (addmntent(mtab_fd, &mountent)) {
 
391
                rc = -EIO;
 
392
                syslog(LOG_ERR, "Failed to write to the mount "
 
393
                       "table\n");
 
394
                goto out;
 
395
        }
 
396
        rc = 0;
 
397
out:
 
398
        free(fullpath_source);
 
399
        free(fullpath_target);
 
400
        free(mountent.mnt_opts);
 
401
        if (mtab_fd)
 
402
                endmntent(mtab_fd);
 
403
        return rc;
 
404
}
 
405
 
386
406
static int zombie_semaphore_get(void)
387
407
{
388
408
        int sem_id;
498
518
        else {
499
519
                char *shm_virt;
500
520
 
501
 
                if (rc == -1) {
502
 
                        syslog(LOG_ERR, "Error allocating shared memory; "
503
 
                                "errno string = [%m]\n");
504
 
                        rc = -EIO;
505
 
                        zombie_semaphore_unlock((*sem_id));
506
 
                        goto out;
507
 
                }
508
 
 
509
521
                (*shm_id) = rc;
510
522
                shm_virt = shmat((*shm_id), NULL, 0);
511
523
                if (shm_virt == (void *)-1) {
878
890
{
879
891
        return &ctx_ops;
880
892
}
881