~ecryptfs/ecryptfs/trunk

« back to all changes in this revision

Viewing changes to src/pam_ecryptfs/pam_ecryptfs.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:
1
 
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*-
2
 
 *
 
1
/**
3
2
 * pam_ecryptfs.c: PAM module that sends the user's authentication
4
3
 * tokens into the kernel keyring.
5
4
 *
6
5
 * Copyright (C) 2007 International Business Machines
7
6
 * Author(s): Michael Halcrow <mhalcrow@us.ibm.com>
8
 
 *            Dustin Kirkland <kirkland@ubuntu.com>
 
7
 *            Dustin Kirkland <kirkland@canonical.com>
9
8
 *
10
9
 * This program is free software; you can redistribute it and/or
11
10
 * modify it under the terms of the GNU General Public License as
23
22
 * 02111-1307, USA.
24
23
 */
25
24
 
 
25
#include "config.h"
26
26
#include <stdio.h>
27
27
#include <stdlib.h>
28
28
#include <stdint.h>
31
31
#include <unistd.h>
32
32
#include <errno.h>
33
33
#include <syslog.h>
34
 
#include <limits.h>
35
34
#include <pwd.h>
36
35
#include <sys/types.h>
37
36
#include <sys/wait.h>
38
37
#include <sys/types.h>
39
38
#include <sys/stat.h>
40
 
#include <sys/fsuid.h>
41
 
#include <grp.h>
42
39
#include <fcntl.h>
43
40
#include <security/pam_modules.h>
44
 
#include <security/pam_ext.h>
45
41
#include "../include/ecryptfs.h"
46
42
 
47
43
#define PRIVATE_DIR "Private"
48
44
 
49
 
/* returns: 0 if file does not exist, 1 if it exists, <0 for error */
50
 
static int file_exists_dotecryptfs(const char *homedir, char *filename)
51
 
{
52
 
        char *file_path;
53
 
        int rc = 0;
54
 
        struct stat s;
55
 
        if (asprintf(&file_path, "%s/.ecryptfs/%s", homedir, filename) == -1)
56
 
                return -ENOMEM;
57
 
        if (stat(file_path, &s) != 0) {
58
 
                if (errno != ENOENT)
59
 
                        rc = -errno;
60
 
                goto out;
61
 
        }
62
 
        rc = 1;
63
 
out:
64
 
        free(file_path);
65
 
        return rc;
66
 
}
67
 
 
68
 
static int wrap_passphrase_if_necessary(const char *username, uid_t uid, char *wrapped_pw_filename, char *passphrase, char *salt)
69
 
{
70
 
        char *unwrapped_pw_filename = NULL;
71
 
        struct stat s;
72
 
        int rc = 0;
73
 
 
74
 
        rc = asprintf(&unwrapped_pw_filename, "/dev/shm/.ecryptfs-%s", username);
75
 
        if (rc == -1) {
76
 
                syslog(LOG_ERR, "pam_ecryptfs: Unable to allocate memory\n");
77
 
                return -ENOMEM;
78
 
        }
79
 
        /* If /dev/shm/.ecryptfs-$USER exists and owned by the user
80
 
           and ~/.ecryptfs/wrapped-passphrase does not exist
81
 
           and a passphrase is set:
82
 
           wrap the unwrapped passphrase file */
83
 
        if (stat(unwrapped_pw_filename, &s) == 0 && (s.st_uid == uid) &&
84
 
            stat(wrapped_pw_filename, &s) != 0  &&
85
 
            passphrase != NULL && *passphrase != '\0' &&
86
 
            username != NULL && *username != '\0') {
87
 
                setuid(uid);
88
 
                rc = ecryptfs_wrap_passphrase_file(wrapped_pw_filename, passphrase, salt, unwrapped_pw_filename);
89
 
                if (rc != 0) {
90
 
                        syslog(LOG_ERR, "pam_ecryptfs: Error wrapping cleartext password; " "rc = [%d]\n", rc);
91
 
                }
92
 
                return rc;
93
 
        }
94
 
        return 0;
 
45
static void error(const char *msg)
 
46
{
 
47
        syslog(LOG_ERR, "errno = [%i]; strerror = [%m]\n", errno);
 
48
        switch (errno) {
 
49
        case ENOKEY:
 
50
                syslog(LOG_ERR, "%s: Requested key not available\n", msg);
 
51
                return;
 
52
 
 
53
        case EKEYEXPIRED:
 
54
                syslog(LOG_ERR, "%s: Key has expired\n", msg);
 
55
                return;
 
56
 
 
57
        case EKEYREVOKED:
 
58
                syslog(LOG_ERR, "%s: Key has been revoked\n", msg);
 
59
                return;
 
60
 
 
61
        case EKEYREJECTED:
 
62
                syslog(LOG_ERR, "%s: Key was rejected by service\n", msg);
 
63
                return;
 
64
        default:
 
65
                syslog(LOG_ERR, "%s: Unknown key error\n", msg);
 
66
                return;
 
67
        }
95
68
}
96
69
 
97
70
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc,
98
71
                                   const char **argv)
99
72
{
100
 
        uid_t uid = 0, oeuid = 0;
101
 
        long ngroups_max = sysconf(_SC_NGROUPS_MAX);
102
 
        gid_t gid = 0, oegid = 0, groups[ngroups_max+1];
103
 
        int ngids = 0;
 
73
        uid_t uid = 0;
104
74
        char *homedir = NULL;
 
75
        uid_t saved_uid = 0;
105
76
        const char *username;
106
77
        char *passphrase = NULL;
107
78
        char salt[ECRYPTFS_SALT_SIZE];
108
79
        char salt_hex[ECRYPTFS_SALT_SIZE_HEX];
109
 
        char *auth_tok_sig = NULL;
110
 
        char *private_mnt = NULL;
 
80
        char *auth_tok_sig;
111
81
        pid_t child_pid, tmp_pid;
112
82
        long rc;
113
83
 
 
84
        syslog(LOG_INFO, "%s: Called\n", __FUNCTION__);
114
85
        rc = pam_get_user(pamh, &username, NULL);
115
86
        if (rc == PAM_SUCCESS) {
116
87
                struct passwd *pwd;
117
88
 
 
89
                syslog(LOG_INFO, "%s: username = [%s]\n", __FUNCTION__,
 
90
                       username);
118
91
                pwd = getpwnam(username);
119
92
                if (pwd) {
120
93
                        uid = pwd->pw_uid;
121
 
                        gid = pwd->pw_gid;
122
94
                        homedir = pwd->pw_dir;
123
95
                }
124
96
        } else {
125
 
                syslog(LOG_ERR, "pam_ecryptfs: Error getting passwd info for user [%s]; rc = [%ld]\n", username, rc);
126
 
                goto out;
127
 
        }
128
 
 
129
 
        oeuid = geteuid();
130
 
        oegid = getegid();
131
 
        if ((ngids = getgroups(sizeof(groups)/sizeof(gid_t), groups)) < 0) {
132
 
                syslog(LOG_ERR, "pam_ecryptfs: geteuid error");
133
 
                goto outnouid;
134
 
        }
135
 
 
136
 
        if (setegid(gid) < 0 || setgroups(1, &gid) < 0 || seteuid(uid) < 0) {
137
 
                syslog(LOG_ERR, "pam_ecryptfs: seteuid error");
138
 
                goto out;
139
 
        }
140
 
 
141
 
        if (!file_exists_dotecryptfs(homedir, "auto-mount"))
142
 
                goto out;
143
 
        private_mnt = ecryptfs_fetch_private_mnt(homedir);
144
 
        if (ecryptfs_private_is_mounted(NULL, private_mnt, NULL, 1)) {
145
 
                syslog(LOG_DEBUG, "pam_ecryptfs: %s: %s is already mounted\n", __FUNCTION__, homedir);
146
 
                /* If private/home is already mounted, then we can skip
147
 
                   costly loading of keys */
148
 
                goto out;
149
 
        }
150
 
        if(file_exists_dotecryptfs(homedir, "wrapping-independent") == 1)
151
 
                rc = pam_prompt(pamh, PAM_PROMPT_ECHO_OFF, &passphrase, "Encryption passphrase: ");
152
 
        else
153
 
                rc = pam_get_item(pamh, PAM_AUTHTOK, (const void **)&passphrase);
 
97
                syslog(LOG_ERR, "Error getting passwd info for user [%s]; "
 
98
                       "rc = [%ld]\n", username, rc);
 
99
                goto out;
 
100
        }
 
101
        saved_uid = geteuid();
 
102
        seteuid(uid);
 
103
        rc = pam_get_item(pamh, PAM_AUTHTOK, (const void **)&passphrase);
 
104
        seteuid(saved_uid);
154
105
        if (rc != PAM_SUCCESS) {
155
 
                syslog(LOG_ERR, "pam_ecryptfs: Error retrieving passphrase; rc = [%ld]\n",
 
106
                syslog(LOG_ERR, "Error retrieving passphrase; rc = [%ld]\n",
156
107
                       rc);
157
108
                goto out;
158
109
        }
159
110
        auth_tok_sig = malloc(ECRYPTFS_SIG_SIZE_HEX + 1);
160
111
        if (!auth_tok_sig) {
161
112
                rc = -ENOMEM;
162
 
                syslog(LOG_ERR, "pam_ecryptfs: Out of memory\n");
 
113
                syslog(LOG_ERR, "Out of memory\n");
163
114
                goto out;
164
115
        }
165
116
        rc = ecryptfs_read_salt_hex_from_rc(salt_hex);
166
117
        if (rc) {
 
118
                syslog(LOG_WARNING, "%s\n", ECRYPTFS_WARN_DEFAULT_SALT);
167
119
                from_hex(salt, ECRYPTFS_DEFAULT_SALT_HEX, ECRYPTFS_SALT_SIZE);
168
120
        } else
169
121
                from_hex(salt, salt_hex, ECRYPTFS_SALT_SIZE);
170
122
        if ((child_pid = fork()) == 0) {
171
 
                /* temp regain uid 0 to drop privs */
172
 
                seteuid(oeuid);
173
 
                /* setgroups() already called */
174
 
                if (setgid(gid) < 0 || setuid(uid) < 0)
175
 
                        goto out_child;
176
 
 
 
123
                setuid(uid);
177
124
                if (passphrase == NULL) {
178
 
                        syslog(LOG_ERR, "pam_ecryptfs: NULL passphrase; aborting\n");
 
125
                        syslog(LOG_ERR, "NULL passphrase; aborting\n");
179
126
                        rc = -EINVAL;
180
127
                        goto out_child;
181
128
                }
182
129
                if ((rc = ecryptfs_validate_keyring())) {
183
 
                        syslog(LOG_WARNING, "pam_ecryptfs: Cannot validate keyring integrity\n");
 
130
                        syslog(LOG_WARNING,
 
131
                               "Cannot validate keyring integrity\n");
184
132
                }
185
133
                rc = 0;
186
134
                if ((argc == 1)
187
135
                    && (memcmp(argv[0], "unwrap\0", 7) == 0)) {
188
136
                        char *wrapped_pw_filename;
189
 
 
 
137
                        
190
138
                        rc = asprintf(
191
139
                                &wrapped_pw_filename, "%s/.ecryptfs/%s",
192
140
                                homedir,
193
141
                                ECRYPTFS_DEFAULT_WRAPPED_PASSPHRASE_FILENAME);
194
142
                        if (rc == -1) {
195
 
                                syslog(LOG_ERR, "pam_ecryptfs: Unable to allocate memory\n");
 
143
                                syslog(LOG_ERR, "Unable to allocate memory\n");
196
144
                                rc = -ENOMEM;
197
145
                                goto out_child;
198
146
                        }
199
 
                        if (wrap_passphrase_if_necessary(username, uid, wrapped_pw_filename, passphrase, salt) == 0) {
200
 
                                syslog(LOG_DEBUG, "pam_ecryptfs: Passphrase file wrapped");
201
 
                        } else {
202
 
                                goto out_child;
203
 
                        }
204
147
                        rc = ecryptfs_insert_wrapped_passphrase_into_keyring(
205
148
                                auth_tok_sig, wrapped_pw_filename, passphrase,
206
149
                                salt);
210
153
                                auth_tok_sig, passphrase, salt);
211
154
                }
212
155
                if (rc == 1) {
 
156
                        syslog(LOG_WARNING, "There is already a key in the "
 
157
                               "user session keyring for the given "
 
158
                               "passphrase.\n");
213
159
                        goto out_child;
214
160
                }
215
161
                if (rc) {
216
 
                        syslog(LOG_ERR, "pam_ecryptfs: Error adding passphrase key token to user session keyring; rc = [%ld]\n", rc);
 
162
                        syslog(LOG_ERR, "Error adding passphrase key token to "
 
163
                               "user session keyring; rc = [%ld]\n", rc);
217
164
                        goto out_child;
218
165
                }
219
166
                if (fork() == 0) {
220
167
                        if ((rc = ecryptfs_set_zombie_session_placeholder())) {
221
 
                                syslog(LOG_ERR, "pam_ecryptfs: Error attempting to create and register zombie process; rc = [%ld]\n", rc);
 
168
                                syslog(LOG_ERR, "Error attempting to create "
 
169
                                       "and register zombie process; "
 
170
                                       "rc = [%ld]\n", rc);
222
171
                        }
223
172
                }
224
173
out_child:
227
176
        }
228
177
        tmp_pid = waitpid(child_pid, NULL, 0);
229
178
        if (tmp_pid == -1)
230
 
                syslog(LOG_WARNING, "pam_ecryptfs: waitpid() returned with error condition\n");
 
179
                syslog(LOG_WARNING,
 
180
                       "waitpid() returned with error condition\n");
231
181
out:
232
 
 
233
 
        seteuid(oeuid);
234
 
        setegid(oegid);
235
 
        setgroups(ngids, groups);
236
 
 
237
 
outnouid:
238
 
        if (private_mnt != NULL)
239
 
                free(private_mnt);
240
 
        if (auth_tok_sig != NULL)
241
 
                free(auth_tok_sig);
242
182
        return PAM_SUCCESS;
243
183
}
244
184
 
256
196
 
257
197
        rc = pam_get_user(pamh, &username, NULL);
258
198
        if (rc != PAM_SUCCESS || username == NULL) {
259
 
                syslog(LOG_ERR, "pam_ecryptfs: Error getting passwd info for user [%s]; rc = [%ld]\n", username, rc);
 
199
                syslog(LOG_ERR, "Error getting passwd info for user [%s]; "
 
200
                                "rc = [%ld]\n", username, rc);
260
201
                return NULL;
261
202
        }
262
203
        pwd = getpwnam(username);
263
204
        if (pwd == NULL) {
264
 
                syslog(LOG_ERR, "pam_ecryptfs: Error getting passwd info for user [%s]; rc = [%ld]\n", username, rc);
 
205
                syslog(LOG_ERR, "Error getting passwd info for user [%s]; "
 
206
                                "rc = [%ld]\n", username, rc);
265
207
                return NULL;
266
208
        }
267
209
        return pwd;
269
211
 
270
212
static int private_dir(pam_handle_t *pamh, int mount)
271
213
{
272
 
        int rc, fd;
 
214
        int rc;
273
215
        struct passwd *pwd = NULL;
274
216
        char *sigfile = NULL;
275
217
        char *autofile = NULL;
276
 
        char *recorded = NULL;
277
218
        char *a;
278
219
        char *automount = "auto-mount";
279
220
        char *autoumount = "auto-umount";
280
221
        struct stat s;
281
222
        pid_t pid;
 
223
        struct utmp *u;
 
224
        int count = 0;
282
225
 
283
226
        if ((pwd = fetch_pwd(pamh)) == NULL) {
284
227
                /* fetch_pwd() logged a message */
292
235
        if (
293
236
            (asprintf(&autofile, "%s/.ecryptfs/%s", pwd->pw_dir, a) < 0)
294
237
             || autofile == NULL) {
295
 
                syslog(LOG_ERR, "pam_ecryptfs: Error allocating memory for autofile name");
 
238
                syslog(LOG_ERR, "Error allocating memory for autofile name");
296
239
                return 1;
297
240
        }
298
241
        if (
299
 
            (asprintf(&sigfile, "%s/.ecryptfs/%s.sig", pwd->pw_dir,
 
242
            (asprintf(&sigfile, "%s/.ecryptfs/%s.sig", pwd->pw_dir, 
300
243
             PRIVATE_DIR) < 0) || sigfile == NULL) {
301
 
                syslog(LOG_ERR, "pam_ecryptfs: Error allocating memory for sigfile name");
 
244
                syslog(LOG_ERR, "Error allocating memory for sigfile name");
302
245
                return 1;
303
246
        }
304
247
        if (stat(sigfile, &s) != 0) {
310
253
                goto out;
311
254
        }
312
255
        if ((pid = fork()) < 0) {
313
 
                syslog(LOG_ERR, "pam_ecryptfs: Error setting up private mount");
 
256
                syslog(LOG_ERR, "Error setting up private mount");
314
257
                return 1;
315
 
        }
 
258
        } 
316
259
        if (pid == 0) {
317
260
                if (mount == 1) {
318
 
                        if ((asprintf(&recorded,
319
 
                            "%s/.ecryptfs/.wrapped-passphrase.recorded",
320
 
                            pwd->pw_dir) < 0) || recorded == NULL) {
321
 
                                syslog(LOG_ERR, "pam_ecryptfs: Error allocating memory for recorded name");
322
 
                                exit(1);
323
 
                        }
324
 
                        if (stat(recorded, &s) != 0 && stat("/usr/share/ecryptfs-utils/ecryptfs-record-passphrase", &s) == 0) {
325
 
                                /* User has not recorded their passphrase */
326
 
                                unlink("/var/lib/update-notifier/user.d/ecryptfs-record-passphrase");
327
 
                                symlink("/usr/share/ecryptfs-utils/ecryptfs-record-passphrase", "/var/lib/update-notifier/user.d/ecryptfs-record-passphrase");
328
 
                                fd = open("/var/lib/update-notifier/dpkg-run-stamp", O_WRONLY|O_CREAT|O_NONBLOCK, 0666);
329
 
                                if (fd != -1)
330
 
                                        close(fd);
331
 
                        }
332
261
                        if (stat(autofile, &s) != 0) {
333
262
                                /* User does not want to auto-mount */
334
 
                                syslog(LOG_DEBUG, "pam_ecryptfs: Skipping automatic eCryptfs mount");
335
 
                                exit(0);
 
263
                                syslog(LOG_INFO,
 
264
                                        "Skipping automatic eCryptfs mount");
 
265
                                return 0;
336
266
                        }
337
 
                        clearenv();
338
 
                        if (setgroups(1, &pwd->pw_gid) < 0 || setgid(pwd->pw_gid) < 0)
339
 
                                exit(-1);
340
267
                        /* run mount.ecryptfs_private as the user */
341
 
                        if (setresuid(pwd->pw_uid, pwd->pw_uid, pwd->pw_uid) < 0)
342
 
                                exit(-1);
343
 
                        execl("/sbin/mount.ecryptfs_private",
 
268
                        setresuid(pwd->pw_uid, pwd->pw_uid, pwd->pw_uid);
 
269
                        execl("/sbin/mount.ecryptfs_private", 
344
270
                              "mount.ecryptfs_private", NULL);
345
271
                } else {
346
272
                        if (stat(autofile, &s) != 0) {
347
273
                                /* User does not want to auto-unmount */
348
 
                                syslog(LOG_DEBUG, "pam_ecryptfs: Skipping automatic eCryptfs unmount");
349
 
                                exit(0);
 
274
                                syslog(LOG_INFO,
 
275
                                        "Skipping automatic eCryptfs unmount");
 
276
                                return 0;
350
277
                        }
351
 
                        clearenv();
352
 
                        if (setgroups(1, &pwd->pw_gid) < 0 || setgid(pwd->pw_gid) < 0)
353
 
                                exit(-1);
354
278
                        /* run umount.ecryptfs_private as the user */
355
 
                        if (setresuid(pwd->pw_uid, pwd->pw_uid, pwd->pw_uid) < 0)
356
 
                                exit(-1);
357
 
                        execl("/sbin/umount.ecryptfs_private",
 
279
                        setresuid(pwd->pw_uid, pwd->pw_uid, pwd->pw_uid);
 
280
                        execl("/sbin/umount.ecryptfs_private", 
358
281
                              "umount.ecryptfs_private", NULL);
359
 
                        exit(1);
360
282
                }
361
 
                exit(1);
 
283
                return 1;
362
284
        } else {
363
285
                waitpid(pid, &rc, 0);
 
286
                syslog(LOG_INFO, 
 
287
                       "Mount of private directory return code [%d]", rc);
 
288
                goto out;
364
289
        }
365
290
out:
366
291
        return 0;
395
320
PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
396
321
                                int argc, const char **argv)
397
322
{
398
 
        uid_t uid = 0, oeuid = 0;
399
 
        long ngroups_max = sysconf(_SC_NGROUPS_MAX);
400
 
        gid_t gid = 0, oegid = 0, groups[ngroups_max+1];
401
 
        int ngids = 0;
 
323
        uid_t uid = 0;
402
324
        char *homedir = NULL;
 
325
        uid_t saved_uid = 0;
403
326
        const char *username;
404
327
        char *old_passphrase = NULL;
405
328
        char *new_passphrase = NULL;
406
329
        char *wrapped_pw_filename;
 
330
        char *unwrapped_pw_filename;
 
331
        char *name = NULL;
407
332
        char salt[ECRYPTFS_SALT_SIZE];
408
333
        char salt_hex[ECRYPTFS_SALT_SIZE_HEX];
409
334
        pid_t child_pid, tmp_pid;
 
335
        struct stat s;
410
336
        int rc = PAM_SUCCESS;
411
337
 
412
338
        rc = pam_get_user(pamh, &username, NULL);
416
342
                pwd = getpwnam(username);
417
343
                if (pwd) {
418
344
                        uid = pwd->pw_uid;
419
 
                        gid = pwd->pw_gid;
420
345
                        homedir = pwd->pw_dir;
 
346
                        name = pwd->pw_name;
421
347
                }
422
348
        } else {
423
 
                syslog(LOG_ERR, "pam_ecryptfs: Error getting passwd info for user [%s]; rc = [%d]\n", username, rc);
424
 
                goto out;
425
 
        }
426
 
 
427
 
        oeuid = geteuid();
428
 
        oegid = getegid();
429
 
        if ((ngids = getgroups(sizeof(groups)/sizeof(gid_t), groups)) < 0) {
430
 
                syslog(LOG_ERR, "pam_ecryptfs: geteuid error");
431
 
                goto outnouid;
432
 
        }
433
 
 
434
 
        if (setegid(gid) < 0 || setgroups(1, &gid) < 0 || seteuid(uid) < 0) {
435
 
                syslog(LOG_ERR, "pam_ecryptfs: seteuid error");
436
 
                goto out;
437
 
        }
438
 
 
 
349
                syslog(LOG_ERR, "Error getting passwd info for user [%s]; "
 
350
                       "rc = [%ld]\n", username, rc);
 
351
                goto out;
 
352
        }
 
353
        saved_uid = geteuid();
 
354
        seteuid(uid);
439
355
        if ((rc = pam_get_item(pamh, PAM_OLDAUTHTOK,
440
356
                               (const void **)&old_passphrase))
441
357
            != PAM_SUCCESS) {
442
 
                syslog(LOG_ERR, "pam_ecryptfs: Error retrieving old passphrase; rc = [%d]\n", rc);
 
358
                syslog(LOG_ERR, "Error retrieving old passphrase; rc = [%d]\n",
 
359
                       rc);
 
360
                seteuid(saved_uid);
443
361
                goto out;
444
362
        }
445
363
        /* On the first pass, do nothing except check that we have a password */
446
364
        if ((flags & PAM_PRELIM_CHECK)) {
447
365
                if (!old_passphrase)
448
366
                {
449
 
                        syslog(LOG_WARNING, "pam_ecryptfs: PAM passphrase change module retrieved a NULL passphrase; nothing to do\n");
 
367
                        syslog(LOG_WARNING, "eCryptfs PAM passphrase change "
 
368
                               "module retrieved a NULL passphrase; nothing to "
 
369
                               "do\n");
450
370
                        rc = PAM_AUTHTOK_RECOVER_ERR;
451
371
                }
 
372
                seteuid(saved_uid);
452
373
                goto out;
453
374
        }
454
375
        if ((rc = pam_get_item(pamh, PAM_AUTHTOK,
455
376
                               (const void **)&new_passphrase))
456
377
            != PAM_SUCCESS) {
457
 
                syslog(LOG_ERR, "pam_ecryptfs: Error retrieving new passphrase; rc = [%d]\n", rc);
 
378
                syslog(LOG_ERR, "Error retrieving new passphrase; rc = [%d]\n",
 
379
                       rc);
 
380
                seteuid(saved_uid);
458
381
                goto out;
459
382
        }
460
383
        if ((rc = asprintf(&wrapped_pw_filename, "%s/.ecryptfs/%s", homedir,
461
384
                           ECRYPTFS_DEFAULT_WRAPPED_PASSPHRASE_FILENAME))
462
385
            == -1) {
463
 
                syslog(LOG_ERR, "pam_ecryptfs: Unable to allocate memory\n");
 
386
                syslog(LOG_ERR, "Unable to allocate memory\n");
 
387
                rc = -ENOMEM;
 
388
                goto out;
 
389
        }
 
390
        rc = asprintf(&unwrapped_pw_filename, "/dev/shm/.ecryptfs-%s", name);
 
391
        if (rc == -1) {
 
392
                syslog(LOG_ERR, "Unable to allocate memory\n");
464
393
                rc = -ENOMEM;
465
394
                goto out;
466
395
        }
467
396
        if ((rc = ecryptfs_read_salt_hex_from_rc(salt_hex))) {
 
397
                syslog(LOG_WARNING, "%s\n", ECRYPTFS_WARN_DEFAULT_SALT);
468
398
                from_hex(salt, ECRYPTFS_DEFAULT_SALT_HEX, ECRYPTFS_SALT_SIZE);
469
399
        } else {
470
400
                from_hex(salt, salt_hex, ECRYPTFS_SALT_SIZE);
471
401
        }
472
 
        if (wrap_passphrase_if_necessary(username, uid, wrapped_pw_filename, new_passphrase, salt) == 0) {
473
 
                syslog(LOG_DEBUG, "pam_ecryptfs: Passphrase file wrapped");
474
 
        } else {
 
402
        /* If /dev/shm/.ecryptfs-$USER exists and owned by the user
 
403
           and ~/.ecryptfs/wrapped-passphrase does not exist
 
404
           and a new_passphrase is set:
 
405
           wrap the unwrapped passphrase file */
 
406
        if (stat(unwrapped_pw_filename, &s) == 0 && (s.st_uid == uid) &&
 
407
            stat(wrapped_pw_filename, &s) != 0  &&
 
408
            new_passphrase != NULL && *new_passphrase != '\0' &&
 
409
            name != NULL && *name != '\0') {
 
410
                setuid(uid);
 
411
                rc = ecryptfs_wrap_passphrase_file(wrapped_pw_filename,
 
412
                        new_passphrase, salt, unwrapped_pw_filename);
 
413
                if (rc != 0) {
 
414
                        syslog(LOG_ERR,
 
415
                          "Error wrapping cleartext password; "
 
416
                          "rc = [%d]\n", rc);
 
417
                }
475
418
                goto out;
476
419
        }
477
 
 
 
420
        seteuid(saved_uid);
478
421
        if (!old_passphrase || !new_passphrase || *new_passphrase == '\0') {
479
 
                syslog(LOG_WARNING, "pam_ecryptfs: PAM passphrase change module retrieved at least one NULL passphrase; nothing to do\n");
 
422
                syslog(LOG_WARNING, "eCryptfs PAM passphrase change module "
 
423
                       "retrieved at least one NULL passphrase; nothing to "
 
424
                       "do\n");
480
425
                rc = PAM_AUTHTOK_RECOVER_ERR;
481
426
                goto out;
482
427
        }
484
429
        if ((child_pid = fork()) == 0) {
485
430
                char passphrase[ECRYPTFS_MAX_PASSWORD_LENGTH + 1];
486
431
 
487
 
                /* temp regain uid 0 to drop privs */
488
 
                seteuid(oeuid);
489
 
                /* setgroups() already called */
490
 
                if (setgid(gid) < 0 || setuid(uid) < 0)
491
 
                        goto out_child;
492
 
 
 
432
                setuid(uid);
493
433
                if ((rc = ecryptfs_unwrap_passphrase(passphrase,
494
434
                                                     wrapped_pw_filename,
495
435
                                                     old_passphrase, salt))) {
496
 
                        syslog(LOG_ERR, "pam_ecryptfs: Error attempting to unwrap passphrase; rc = [%d]\n", rc);
 
436
                        syslog(LOG_ERR, "Error attempting to unwrap "
 
437
                               "passphrase; rc = [%d]\n", rc);
497
438
                        goto out_child;
498
439
                }
499
440
                if ((rc = ecryptfs_wrap_passphrase(wrapped_pw_filename,
500
441
                                                   new_passphrase, salt,
501
442
                                                   passphrase))) {
502
 
                        syslog(LOG_ERR, "pam_ecryptfs: Error attempting to wrap passphrase; rc = [%d]", rc);
 
443
                        syslog(LOG_ERR, "Error attempting to wrap passphrase; "
 
444
                               "rc = [%d]", rc);
503
445
                        goto out_child;
504
446
                }
505
447
out_child:
506
448
                exit(0);
507
449
        }
508
450
        if ((tmp_pid = waitpid(child_pid, NULL, 0)) == -1)
509
 
                syslog(LOG_WARNING, "pam_ecryptfs: waitpid() returned with error condition\n");
 
451
                syslog(LOG_WARNING,
 
452
                       "waitpid() returned with error condition\n");
510
453
        free(wrapped_pw_filename);
511
454
out:
512
 
 
513
 
        seteuid(oeuid);
514
 
        setegid(oegid);
515
 
        setgroups(ngids, groups);
516
 
 
517
 
outnouid:
518
455
        return rc;
519
456
}