2
* pam_ecryptfs.c: PAM module that sends the user's authentication
3
* tokens into the kernel keyring.
5
* Copyright (C) 2007 International Business Machines
6
* Author(s): Michael Halcrow <mhalcrow@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
33
#include <sys/types.h>
35
#include <sys/types.h>
38
#include <security/pam_modules.h>
40
#include "../include/ecryptfs.h"
42
static void error(const char *msg)
44
syslog(LOG_ERR, "errno = [%i]; strerror = [%s]\n", errno,
48
syslog(LOG_ERR, "%s: Requested key not available\n", msg);
52
syslog(LOG_ERR, "%s: Key has expired\n", msg);
56
syslog(LOG_ERR, "%s: Key has been revoked\n", msg);
60
syslog(LOG_ERR, "%s: Key was rejected by service\n", msg);
63
syslog(LOG_ERR, "%s: Unknown key error\n", msg);
68
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc,
75
char *passphrase = NULL;
76
char salt[ECRYPTFS_SALT_SIZE];
77
char salt_hex[ECRYPTFS_SALT_SIZE_HEX];
79
pid_t child_pid, tmp_pid;
82
syslog(LOG_INFO, "%s: Called\n", __FUNCTION__);
83
rc = pam_get_user(pamh, &username, NULL);
84
if (rc == PAM_SUCCESS) {
87
syslog(LOG_INFO, "%s: username = [%s]\n", __FUNCTION__,
89
pwd = getpwnam(username);
92
homedir = pwd->pw_dir;
95
syslog(LOG_ERR, "Error getting passwd info for user [%s]; "
96
"rc = [%ld]\n", username, rc);
99
saved_uid = geteuid();
101
rc = pam_get_item(pamh, PAM_AUTHTOK, (const void **)&passphrase);
103
if (rc != PAM_SUCCESS) {
104
syslog(LOG_ERR, "Error retrieving passphrase; rc = [%d]\n",
108
auth_tok_sig = malloc(ECRYPTFS_SIG_SIZE_HEX + 1);
111
syslog(LOG_ERR, "Out of memory\n");
114
rc = ecryptfs_read_salt_hex_from_rc(salt_hex);
116
syslog(LOG_WARNING, "Unable to read salt value from user's "
117
".ecryptfsrc file; using default\n");
118
from_hex(salt, ECRYPTFS_DEFAULT_SALT_HEX, ECRYPTFS_SALT_SIZE);
120
from_hex(salt, salt_hex, ECRYPTFS_SALT_SIZE);
121
if ((child_pid = fork()) == 0) {
123
if (passphrase == NULL) {
124
syslog(LOG_ERR, "NULL passphrase; aborting\n");
128
if ((rc = ecryptfs_validate_keyring())) {
130
"Cannot validate keyring integrity\n");
134
&& (memcmp(argv[0], "unwrap\0", 7) == 0)) {
135
char *wrapped_pw_filename;
138
&wrapped_pw_filename, "%s/.ecryptfs/%s",
140
ECRYPTFS_DEFAULT_WRAPPED_PASSPHRASE_FILENAME);
142
syslog(LOG_ERR, "Unable to allocate memory\n");
146
rc = ecryptfs_insert_wrapped_passphrase_into_keyring(
147
auth_tok_sig, wrapped_pw_filename, passphrase,
149
free(wrapped_pw_filename);
151
rc = ecryptfs_add_passphrase_key_to_keyring(
152
auth_tok_sig, passphrase, salt);
155
syslog(LOG_WARNING, "There is already a key in the "
156
"user session keyring for the given "
161
syslog(LOG_ERR, "Error adding passphrase key token to "
162
"user session keyring; rc = [%d]\n", rc);
166
if ((rc = ecryptfs_set_zombie_session_placeholder())) {
167
syslog(LOG_ERR, "Error attempting to create "
168
"and register zombie process; "
176
tmp_pid = waitpid(child_pid, NULL, 0);
179
"waitpid() returned with error condition\n");
184
PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc,
191
pam_sm_open_session(pam_handle_t *pamh, int flags,
192
int argc, const char *argv[])
198
pam_sm_close_session(pam_handle_t *pamh, int flags,
199
int argc, const char *argv[])
204
PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
205
int argc, const char **argv)
208
char *homedir = NULL;
210
const char *username;
211
char *old_passphrase = NULL;
212
char *new_passphrase = NULL;
213
char *wrapped_pw_filename;
214
char salt[ECRYPTFS_SALT_SIZE];
215
char salt_hex[ECRYPTFS_SALT_SIZE_HEX];
216
pid_t child_pid, tmp_pid;
217
int rc = PAM_SUCCESS;
219
rc = pam_get_user(pamh, &username, NULL);
220
if (rc == PAM_SUCCESS) {
223
pwd = getpwnam(username);
226
homedir = pwd->pw_dir;
229
syslog(LOG_ERR, "Error getting passwd info for user [%s]; "
230
"rc = [%ld]\n", username, rc);
233
saved_uid = geteuid();
235
if ((rc = pam_get_item(pamh, PAM_OLDAUTHTOK,
236
(const void **)&old_passphrase))
238
syslog(LOG_ERR, "Error retrieving old passphrase; rc = [%d]\n",
243
if ((rc = pam_get_item(pamh, PAM_AUTHTOK,
244
(const void **)&new_passphrase))
246
syslog(LOG_ERR, "Error retrieving new passphrase; rc = [%d]\n",
252
if (!old_passphrase || !new_passphrase) {
253
syslog(LOG_WARNING, "eCryptfs PAM passphrase change module "
254
"retrieved at least one NULL passphrase; nothing to "
258
if ((rc = asprintf(&wrapped_pw_filename, "%s/.ecryptfs/%s", homedir,
259
ECRYPTFS_DEFAULT_WRAPPED_PASSPHRASE_FILENAME))
261
syslog(LOG_ERR, "Unable to allocate memory\n");
265
if ((rc = ecryptfs_read_salt_hex_from_rc(salt_hex))) {
266
syslog(LOG_WARNING, "Unable to read salt value from user's "
267
".ecryptfsrc file; using default\n");
268
from_hex(salt, ECRYPTFS_DEFAULT_SALT_HEX, ECRYPTFS_SALT_SIZE);
270
from_hex(salt, salt_hex, ECRYPTFS_SALT_SIZE);
272
if ((child_pid = fork()) == 0) {
273
char passphrase[ECRYPTFS_MAX_PASSWORD_LENGTH + 1];
276
if ((rc = ecryptfs_unwrap_passphrase(passphrase,
278
old_passphrase, salt))) {
279
syslog(LOG_ERR, "Error attempting to unwrap "
280
"passphrase; rc = [%d]\n", rc);
283
if ((rc = ecryptfs_wrap_passphrase(wrapped_pw_filename,
284
new_passphrase, salt,
286
syslog(LOG_ERR, "Error attempting to wrap passphrase; "
293
if ((tmp_pid = waitpid(child_pid, NULL, 0)) == -1)
295
"waitpid() returned with error condition\n");
296
free(wrapped_pw_filename);