diff -up ecryptfs-utils-87/src/pam_ecryptfs/pam_ecryptfs.c.pamdata ecryptfs-utils-87/src/pam_ecryptfs/pam_ecryptfs.c
--- ecryptfs-utils-87/src/pam_ecryptfs/pam_ecryptfs.c.pamdata 2011-08-03 15:40:01.743949759 +0200
+++ ecryptfs-utils-87/src/pam_ecryptfs/pam_ecryptfs.c 2011-08-03 15:52:05.676388743 +0200
@@ -45,6 +45,25 @@
#define PRIVATE_DIR "Private"
+#define ECRYPTFS_PAM_DATA "ecryptfs:passphrase"
+
+struct ecryptfs_pam_data {
+ int unwrap;
+ uid_t uid;
+ char *passphrase;
+ const char *homedir;
+ const char *username;
+ char salt[ECRYPTFS_SALT_SIZE];
+};
+
+static void pam_free_ecryptfsdata(pam_handle_t *pamh, void *data, int error_status)
+{
+ if (data) {
+ free(((struct ecryptfs_pam_data *)data)->passphrase);
+ free(data);
+ }
+}
+
/* returns: 0 if file does not exist, 1 if it exists, <0 for error */
static int file_exists_dotecryptfs(const char *homedir, char *filename)
{
@@ -64,7 +83,7 @@ out:
return rc;
}
-static int wrap_passphrase_if_necessary(const char *username, uid_t uid, char *wrapped_pw_filename, char *passphrase, char *salt)
+static int wrap_passphrase_if_necessary(const char *username, uid_t uid, const char *wrapped_pw_filename, const char *passphrase, const char *salt)
{
char *unwrapped_pw_filename = NULL;
struct stat s;
@@ -96,42 +115,43 @@ static int wrap_passphrase_if_necessary(
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc,
const char **argv)
{
- uid_t uid = 0;
- char *homedir = NULL;
uid_t saved_uid = 0;
- const char *username;
- char *passphrase = NULL;
- char salt[ECRYPTFS_SALT_SIZE];
char salt_hex[ECRYPTFS_SALT_SIZE_HEX];
- char *auth_tok_sig;
char *private_mnt = NULL;
- pid_t child_pid, tmp_pid;
- long rc;
+ long rc = 0;
uint32_t version;
+ struct ecryptfs_pam_data *epd = {0,};
syslog(LOG_INFO, "%s: Called\n", __FUNCTION__);
- rc = pam_get_user(pamh, &username, NULL);
+
+ if ((epd = malloc(sizeof(struct ecryptfs_pam_data))) == NULL) {
+ syslog(LOG_ERR,"Memory allocation failed");
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ rc = pam_get_user(pamh, &epd->username, NULL);
if (rc == PAM_SUCCESS) {
struct passwd *pwd;
syslog(LOG_INFO, "%s: username = [%s]\n", __FUNCTION__,
- username);
- pwd = getpwnam(username);
+ epd->username);
+ pwd = getpwnam(epd->username);
if (pwd) {
- uid = pwd->pw_uid;
- homedir = pwd->pw_dir;
+ epd->uid = pwd->pw_uid;
+ epd->homedir = pwd->pw_dir;
}
} else {
syslog(LOG_ERR, "Error getting passwd info for user [%s]; "
- "rc = [%ld]\n", username, rc);
+ "rc = [%ld]\n", epd->username, rc);
goto out;
}
- if (!file_exists_dotecryptfs(homedir, "auto-mount"))
+ if (!file_exists_dotecryptfs(epd->homedir, "auto-mount"))
goto out;
- private_mnt = ecryptfs_fetch_private_mnt(homedir);
+ private_mnt = ecryptfs_fetch_private_mnt(epd->homedir);
if (ecryptfs_private_is_mounted(NULL, private_mnt, NULL, 1)) {
syslog(LOG_INFO, "%s: %s is already mounted\n", __FUNCTION__,
- homedir);
+ epd->homedir);
/* If private/home is already mounted, then we can skip
costly loading of keys */
goto out;
@@ -141,82 +161,32 @@ PAM_EXTERN int pam_sm_authenticate(pam_h
if (ecryptfs_get_version(&version) != 0)
syslog(LOG_WARNING, "Can't check if kernel supports ecryptfs\n");
saved_uid = geteuid();
- seteuid(uid);
- if(file_exists_dotecryptfs(homedir, "wrapping-independent") == 1)
- rc = pam_prompt(pamh, PAM_PROMPT_ECHO_OFF, &passphrase, "Encryption passphrase: ");
+ seteuid(epd->uid);
+ if(file_exists_dotecryptfs(epd->homedir, "wrapping-independent") == 1)
+ rc = pam_prompt(pamh, PAM_PROMPT_ECHO_OFF, &epd->passphrase, "Encryption passphrase: ");
else
- rc = pam_get_item(pamh, PAM_AUTHTOK, (const void **)&passphrase);
+ rc = pam_get_item(pamh, PAM_AUTHTOK, (const void **)&epd->passphrase);
+ epd->passphrase = strdup(epd->passphrase);
seteuid(saved_uid);
if (rc != PAM_SUCCESS) {
syslog(LOG_ERR, "Error retrieving passphrase; rc = [%ld]\n",
rc);
goto out;
}
- auth_tok_sig = malloc(ECRYPTFS_SIG_SIZE_HEX + 1);
- if (!auth_tok_sig) {
- rc = -ENOMEM;
- syslog(LOG_ERR, "Out of memory\n");
- goto out;
- }
+
rc = ecryptfs_read_salt_hex_from_rc(salt_hex);
if (rc) {
- from_hex(salt, ECRYPTFS_DEFAULT_SALT_HEX, ECRYPTFS_SALT_SIZE);
+ from_hex(epd->salt, ECRYPTFS_DEFAULT_SALT_HEX, ECRYPTFS_SALT_SIZE);
} else
- from_hex(salt, salt_hex, ECRYPTFS_SALT_SIZE);
- if ((child_pid = fork()) == 0) {
- setuid(uid);
- if (passphrase == NULL) {
- syslog(LOG_ERR, "NULL passphrase; aborting\n");
- rc = -EINVAL;
- goto out_child;
- }
- if ((rc = ecryptfs_validate_keyring())) {
- syslog(LOG_WARNING,
- "Cannot validate keyring integrity\n");
- }
- rc = 0;
- if ((argc == 1)
- && (memcmp(argv[0], "unwrap\0", 7) == 0)) {
- char *wrapped_pw_filename;
+ from_hex(epd->salt, salt_hex, ECRYPTFS_SALT_SIZE);
- rc = asprintf(
- &wrapped_pw_filename, "%s/.ecryptfs/%s",
- homedir,
- ECRYPTFS_DEFAULT_WRAPPED_PASSPHRASE_FILENAME);
- if (rc == -1) {
- syslog(LOG_ERR, "Unable to allocate memory\n");
- rc = -ENOMEM;
- goto out_child;
- }
- if (wrap_passphrase_if_necessary(username, uid, wrapped_pw_filename, passphrase, salt) == 0) {
- syslog(LOG_INFO, "Passphrase file wrapped");
- } else {
- goto out_child;
- }
- rc = ecryptfs_insert_wrapped_passphrase_into_keyring(
- auth_tok_sig, wrapped_pw_filename, passphrase,
- salt);
- free(wrapped_pw_filename);
- } else {
- rc = ecryptfs_add_passphrase_key_to_keyring(
- auth_tok_sig, passphrase, salt);
- }
- if (rc == 1) {
- goto out_child;
- }
- if (rc) {
- syslog(LOG_ERR, "Error adding passphrase key token to "
- "user session keyring; rc = [%ld]\n", rc);
- goto out_child;
- }
-out_child:
- free(auth_tok_sig);
- _exit(0);
+ epd->unwrap = ((argc == 1) && (memcmp(argv[0], "unwrap\0", 7) == 0));
+ if ((rc=pam_set_data(pamh, ECRYPTFS_PAM_DATA, epd, pam_free_ecryptfsdata)) != PAM_SUCCESS) {
+
+ syslog(LOG_ERR, "Unable to store ecryptfs pam data : %s", pam_strerror(pamh, rc));
+ goto out;
}
- tmp_pid = waitpid(child_pid, NULL, 0);
- if (tmp_pid == -1)
- syslog(LOG_WARNING,
- "waitpid() returned with error condition\n");
+
out:
if (private_mnt != NULL)
free(private_mnt);
@@ -361,10 +331,88 @@ static int umount_private_dir(pam_handle
return private_dir(pamh, 0);
}
+static int fill_keyring(pam_handle_t *pamh)
+{
+ pid_t child_pid,tmp_pid;
+ int rc = 0;
+ const struct ecryptfs_pam_data *epd;
+ char *auth_tok_sig;
+ auth_tok_sig = malloc(ECRYPTFS_SIG_SIZE_HEX + 1);
+ if (!auth_tok_sig) {
+ syslog(LOG_ERR, "Out of memory\n");
+ return -ENOMEM;
+ }
+
+ if ((rc=pam_get_data(pamh, ECRYPTFS_PAM_DATA, (const void **)&epd)) != PAM_SUCCESS)
+ {
+ syslog(LOG_ERR,"Unable to get ecryptfs pam data : %s", pam_strerror(pamh, rc));
+ return -EINVAL;
+ }
+
+ if ((child_pid = fork()) == 0) {
+ setuid(epd->uid);
+ if (epd->passphrase == NULL) {
+ syslog(LOG_ERR, "NULL passphrase; aborting\n");
+ rc = -EINVAL;
+ goto out_child;
+ }
+ if ((rc = ecryptfs_validate_keyring())) {
+ syslog(LOG_WARNING,
+ "Cannot validate keyring integrity\n");
+ }
+ rc = 0;
+ if (epd->unwrap) {
+ char *wrapped_pw_filename;
+
+ rc = asprintf(
+ &wrapped_pw_filename, "%s/.ecryptfs/%s",
+ epd->homedir,
+ ECRYPTFS_DEFAULT_WRAPPED_PASSPHRASE_FILENAME);
+ if (rc == -1) {
+ syslog(LOG_ERR, "Unable to allocate memory\n");
+ rc = -ENOMEM;
+ goto out_child;
+ }
+ if (wrap_passphrase_if_necessary(epd->username, epd->uid, wrapped_pw_filename, epd->passphrase, epd->salt) == 0) {
+ syslog(LOG_INFO, "Passphrase file wrapped");
+ } else {
+ goto out_child;
+ }
+ rc = ecryptfs_insert_wrapped_passphrase_into_keyring(
+ auth_tok_sig, wrapped_pw_filename, epd->passphrase,
+ epd->salt);
+ free(wrapped_pw_filename);
+ } else {
+ rc = ecryptfs_add_passphrase_key_to_keyring(
+ auth_tok_sig, epd->passphrase, epd->salt);
+ }
+ if (rc == 1) {
+ goto out_child;
+ }
+ if (rc) {
+ syslog(LOG_ERR, "Error adding passphrase key token to "
+ "user session keyring; rc = [%d]\n", rc);
+ goto out_child;
+ }
+out_child:
+ free(auth_tok_sig);
+ _exit(0);
+ }
+ tmp_pid = waitpid(child_pid, NULL, 0);
+ if (tmp_pid == -1)
+ syslog(LOG_WARNING,
+ "waitpid() returned with error condition\n");
+
+
+ return 0;
+}
+
+
PAM_EXTERN int
pam_sm_open_session(pam_handle_t *pamh, int flags,
int argc, const char *argv[])
{
+ fill_keyring(pamh);
mount_private_dir(pamh);
return PAM_SUCCESS;
}