|
|
bcbcca |
diff -up ecryptfs-utils-100/src/pam_ecryptfs/pam_ecryptfs.c.pamdata ecryptfs-utils-100/src/pam_ecryptfs/pam_ecryptfs.c
|
|
|
bcbcca |
--- ecryptfs-utils-100/src/pam_ecryptfs/pam_ecryptfs.c.pamdata 2012-08-20 14:39:10.895860230 +0200
|
|
|
bcbcca |
+++ ecryptfs-utils-100/src/pam_ecryptfs/pam_ecryptfs.c 2012-08-20 14:39:52.177176922 +0200
|
|
|
538c2f |
@@ -47,6 +47,26 @@
|
|
|
8b5695 |
|
|
|
8b5695 |
#define PRIVATE_DIR "Private"
|
|
|
8b5695 |
|
|
|
8b5695 |
+#define ECRYPTFS_PAM_DATA "ecryptfs:passphrase"
|
|
|
8b5695 |
+
|
|
|
8b5695 |
+struct ecryptfs_pam_data {
|
|
|
8b5695 |
+ int unwrap;
|
|
|
8b5695 |
+ uid_t uid;
|
|
|
538c2f |
+ gid_t gid;
|
|
|
8b5695 |
+ char *passphrase;
|
|
|
8b5695 |
+ const char *homedir;
|
|
|
8b5695 |
+ const char *username;
|
|
|
8b5695 |
+ char salt[ECRYPTFS_SALT_SIZE];
|
|
|
8b5695 |
+};
|
|
|
8b5695 |
+
|
|
|
8b5695 |
+static void pam_free_ecryptfsdata(pam_handle_t *pamh, void *data, int error_status)
|
|
|
8b5695 |
+{
|
|
|
7a13e7 |
+ if (data) {
|
|
|
7a13e7 |
+ free(((struct ecryptfs_pam_data *)data)->passphrase);
|
|
|
7a13e7 |
+ free(data);
|
|
|
7a13e7 |
+ }
|
|
|
8b5695 |
+}
|
|
|
8b5695 |
+
|
|
|
8b5695 |
/* returns: 0 if file does not exist, 1 if it exists, <0 for error */
|
|
|
8b5695 |
static int file_exists_dotecryptfs(const char *homedir, char *filename)
|
|
|
8b5695 |
{
|
|
|
538c2f |
@@ -66,7 +86,7 @@ out:
|
|
|
8b5695 |
return rc;
|
|
|
8b5695 |
}
|
|
|
8b5695 |
|
|
|
8b5695 |
-static int wrap_passphrase_if_necessary(const char *username, uid_t uid, char *wrapped_pw_filename, char *passphrase, char *salt)
|
|
|
8b5695 |
+static int wrap_passphrase_if_necessary(const char *username, uid_t uid, const char *wrapped_pw_filename, const char *passphrase, const char *salt)
|
|
|
8b5695 |
{
|
|
|
8b5695 |
char *unwrapped_pw_filename = NULL;
|
|
|
8b5695 |
struct stat s;
|
|
|
bcbcca |
@@ -98,138 +118,63 @@ static int wrap_passphrase_if_necessary(
|
|
|
8b5695 |
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc,
|
|
|
8b5695 |
const char **argv)
|
|
|
8b5695 |
{
|
|
|
538c2f |
- uid_t uid = 0, oeuid = 0;
|
|
|
538c2f |
- long ngroups_max = sysconf(_SC_NGROUPS_MAX);
|
|
|
538c2f |
- gid_t gid = 0, oegid = 0, groups[ngroups_max+1];
|
|
|
538c2f |
- int ngids = 0;
|
|
|
8b5695 |
- char *homedir = NULL;
|
|
|
8b5695 |
- const char *username;
|
|
|
8b5695 |
- char *passphrase = NULL;
|
|
|
8b5695 |
- char salt[ECRYPTFS_SALT_SIZE];
|
|
|
8b5695 |
char salt_hex[ECRYPTFS_SALT_SIZE_HEX];
|
|
|
8b5695 |
- char *auth_tok_sig;
|
|
|
8b5695 |
char *private_mnt = NULL;
|
|
|
8b5695 |
- pid_t child_pid, tmp_pid;
|
|
|
538c2f |
long rc;
|
|
|
8b5695 |
+ struct ecryptfs_pam_data *epd = {0,};
|
|
|
8b5695 |
|
|
|
8b5695 |
- rc = pam_get_user(pamh, &username, NULL);
|
|
|
8b5695 |
+ if ((epd = malloc(sizeof(struct ecryptfs_pam_data))) == NULL) {
|
|
|
8b5695 |
+ syslog(LOG_ERR,"Memory allocation failed");
|
|
|
8b5695 |
+ rc = -ENOMEM;
|
|
|
8b5695 |
+ goto out;
|
|
|
8b5695 |
+ }
|
|
|
8b5695 |
+
|
|
|
8b5695 |
+ rc = pam_get_user(pamh, &epd->username, NULL);
|
|
|
8b5695 |
if (rc == PAM_SUCCESS) {
|
|
|
8b5695 |
struct passwd *pwd;
|
|
|
8b5695 |
|
|
|
8b5695 |
- pwd = getpwnam(username);
|
|
|
8b5695 |
+ pwd = getpwnam(epd->username);
|
|
|
8b5695 |
if (pwd) {
|
|
|
8b5695 |
- uid = pwd->pw_uid;
|
|
|
538c2f |
- gid = pwd->pw_gid;
|
|
|
8b5695 |
- homedir = pwd->pw_dir;
|
|
|
8b5695 |
+ epd->uid = pwd->pw_uid;
|
|
|
538c2f |
+ epd->gid = pwd->pw_gid;
|
|
|
8b5695 |
+ epd->homedir = pwd->pw_dir;
|
|
|
8b5695 |
}
|
|
|
8b5695 |
} else {
|
|
|
7731a0 |
- syslog(LOG_ERR, "pam_ecryptfs: Error getting passwd info for user [%s]; rc = [%ld]\n", username, rc);
|
|
|
bcbcca |
+ syslog(LOG_ERR, "pam_ecryptfs: Error getting passwd info for user; rc = [%ld]\n", rc);
|
|
|
bcbcca |
goto out;
|
|
|
bcbcca |
}
|
|
|
bcbcca |
|
|
|
538c2f |
- if ((oeuid = geteuid()) < 0 || (oegid = getegid()) < 0 ||
|
|
|
538c2f |
- (ngids = getgroups(sizeof(groups)/sizeof(gid_t), groups)) < 0) {
|
|
|
538c2f |
- syslog(LOG_ERR, "pam_ecryptfs: geteuid error");
|
|
|
538c2f |
- goto outnouid;
|
|
|
538c2f |
- }
|
|
|
538c2f |
-
|
|
|
538c2f |
- if (setegid(gid) < 0 || setgroups(1, &gid) < 0 || seteuid(uid) < 0) {
|
|
|
538c2f |
- syslog(LOG_ERR, "pam_ecryptfs: seteuid error");
|
|
|
8b5695 |
+ if (!file_exists_dotecryptfs(epd->homedir, "auto-mount"))
|
|
|
8b5695 |
goto out;
|
|
|
bcbcca |
- }
|
|
|
bcbcca |
-
|
|
|
bcbcca |
- if (!file_exists_dotecryptfs(homedir, "auto-mount"))
|
|
|
bcbcca |
- goto out;
|
|
|
8b5695 |
- private_mnt = ecryptfs_fetch_private_mnt(homedir);
|
|
|
8b5695 |
+ private_mnt = ecryptfs_fetch_private_mnt(epd->homedir);
|
|
|
8b5695 |
if (ecryptfs_private_is_mounted(NULL, private_mnt, NULL, 1)) {
|
|
|
7731a0 |
- syslog(LOG_DEBUG, "pam_ecryptfs: %s: %s is already mounted\n", __FUNCTION__, homedir);
|
|
|
7731a0 |
+ syslog(LOG_DEBUG, "pam_ecryptfs: %s: %s is already mounted\n", __FUNCTION__, epd->homedir);
|
|
|
8b5695 |
/* If private/home is already mounted, then we can skip
|
|
|
8b5695 |
costly loading of keys */
|
|
|
8b5695 |
goto out;
|
|
|
7d5fb1 |
}
|
|
|
8b5695 |
- if(file_exists_dotecryptfs(homedir, "wrapping-independent") == 1)
|
|
|
8b5695 |
- rc = pam_prompt(pamh, PAM_PROMPT_ECHO_OFF, &passphrase, "Encryption passphrase: ");
|
|
|
8b5695 |
+ if(file_exists_dotecryptfs(epd->homedir, "wrapping-independent") == 1)
|
|
|
8b5695 |
+ rc = pam_prompt(pamh, PAM_PROMPT_ECHO_OFF, &epd->passphrase, "Encryption passphrase: ");
|
|
|
8b5695 |
else
|
|
|
8b5695 |
- rc = pam_get_item(pamh, PAM_AUTHTOK, (const void **)&passphrase);
|
|
|
8b5695 |
+ rc = pam_get_item(pamh, PAM_AUTHTOK, (const void **)&epd->passphrase);
|
|
|
7a13e7 |
+ epd->passphrase = strdup(epd->passphrase);
|
|
|
8b5695 |
if (rc != PAM_SUCCESS) {
|
|
|
7731a0 |
syslog(LOG_ERR, "pam_ecryptfs: Error retrieving passphrase; rc = [%ld]\n",
|
|
|
8b5695 |
rc);
|
|
|
8b5695 |
goto out;
|
|
|
8b5695 |
}
|
|
|
8b5695 |
- auth_tok_sig = malloc(ECRYPTFS_SIG_SIZE_HEX + 1);
|
|
|
8b5695 |
- if (!auth_tok_sig) {
|
|
|
8b5695 |
- rc = -ENOMEM;
|
|
|
7731a0 |
- syslog(LOG_ERR, "pam_ecryptfs: Out of memory\n");
|
|
|
8b5695 |
- goto out;
|
|
|
8b5695 |
- }
|
|
|
8b5695 |
rc = ecryptfs_read_salt_hex_from_rc(salt_hex);
|
|
|
8b5695 |
if (rc) {
|
|
|
8b5695 |
- from_hex(salt, ECRYPTFS_DEFAULT_SALT_HEX, ECRYPTFS_SALT_SIZE);
|
|
|
8b5695 |
+ from_hex(epd->salt, ECRYPTFS_DEFAULT_SALT_HEX, ECRYPTFS_SALT_SIZE);
|
|
|
8b5695 |
} else
|
|
|
8b5695 |
- from_hex(salt, salt_hex, ECRYPTFS_SALT_SIZE);
|
|
|
8b5695 |
- if ((child_pid = fork()) == 0) {
|
|
|
538c2f |
- /* temp regain uid 0 to drop privs */
|
|
|
538c2f |
- seteuid(oeuid);
|
|
|
538c2f |
- /* setgroups() already called */
|
|
|
538c2f |
- if (setgid(gid) < 0 || setuid(uid) < 0)
|
|
|
538c2f |
- goto out_child;
|
|
|
538c2f |
-
|
|
|
8b5695 |
- if (passphrase == NULL) {
|
|
|
7731a0 |
- syslog(LOG_ERR, "pam_ecryptfs: NULL passphrase; aborting\n");
|
|
|
8b5695 |
- rc = -EINVAL;
|
|
|
8b5695 |
- goto out_child;
|
|
|
8b5695 |
- }
|
|
|
8b5695 |
- if ((rc = ecryptfs_validate_keyring())) {
|
|
|
7731a0 |
- syslog(LOG_WARNING, "pam_ecryptfs: Cannot validate keyring integrity\n");
|
|
|
8b5695 |
- }
|
|
|
8b5695 |
- rc = 0;
|
|
|
8b5695 |
- if ((argc == 1)
|
|
|
8b5695 |
- && (memcmp(argv[0], "unwrap\0", 7) == 0)) {
|
|
|
8b5695 |
- char *wrapped_pw_filename;
|
|
|
7731a0 |
-
|
|
|
8b5695 |
- rc = asprintf(
|
|
|
8b5695 |
- &wrapped_pw_filename, "%s/.ecryptfs/%s",
|
|
|
8b5695 |
- homedir,
|
|
|
8b5695 |
- ECRYPTFS_DEFAULT_WRAPPED_PASSPHRASE_FILENAME);
|
|
|
8b5695 |
- if (rc == -1) {
|
|
|
7731a0 |
- syslog(LOG_ERR, "pam_ecryptfs: Unable to allocate memory\n");
|
|
|
8b5695 |
- rc = -ENOMEM;
|
|
|
8b5695 |
- goto out_child;
|
|
|
8b5695 |
- }
|
|
|
8b5695 |
- if (wrap_passphrase_if_necessary(username, uid, wrapped_pw_filename, passphrase, salt) == 0) {
|
|
|
7731a0 |
- syslog(LOG_DEBUG, "pam_ecryptfs: Passphrase file wrapped");
|
|
|
8b5695 |
- } else {
|
|
|
8b5695 |
- goto out_child;
|
|
|
8b5695 |
- }
|
|
|
8b5695 |
- rc = ecryptfs_insert_wrapped_passphrase_into_keyring(
|
|
|
8b5695 |
- auth_tok_sig, wrapped_pw_filename, passphrase,
|
|
|
8b5695 |
- salt);
|
|
|
8b5695 |
- free(wrapped_pw_filename);
|
|
|
8b5695 |
- } else {
|
|
|
8b5695 |
- rc = ecryptfs_add_passphrase_key_to_keyring(
|
|
|
8b5695 |
- auth_tok_sig, passphrase, salt);
|
|
|
8b5695 |
- }
|
|
|
8b5695 |
- if (rc == 1) {
|
|
|
8b5695 |
- goto out_child;
|
|
|
8b5695 |
- }
|
|
|
8b5695 |
- if (rc) {
|
|
|
7731a0 |
- syslog(LOG_ERR, "pam_ecryptfs: Error adding passphrase key token to user session keyring; rc = [%ld]\n", rc);
|
|
|
8b5695 |
- goto out_child;
|
|
|
8b5695 |
- }
|
|
|
8b5695 |
-out_child:
|
|
|
8b5695 |
- free(auth_tok_sig);
|
|
|
8b5695 |
- _exit(0);
|
|
|
7731a0 |
+ from_hex(epd->salt, salt_hex, ECRYPTFS_SALT_SIZE);
|
|
|
8b5695 |
+ epd->unwrap = ((argc == 1) && (memcmp(argv[0], "unwrap\0", 7) == 0));
|
|
|
7a13e7 |
+ if ((rc=pam_set_data(pamh, ECRYPTFS_PAM_DATA, epd, pam_free_ecryptfsdata)) != PAM_SUCCESS) {
|
|
|
7a13e7 |
+ syslog(LOG_ERR, "Unable to store ecryptfs pam data : %s", pam_strerror(pamh, rc));
|
|
|
8b5695 |
+ goto out;
|
|
|
8b5695 |
}
|
|
|
8b5695 |
- tmp_pid = waitpid(child_pid, NULL, 0);
|
|
|
8b5695 |
- if (tmp_pid == -1)
|
|
|
7731a0 |
- syslog(LOG_WARNING, "pam_ecryptfs: waitpid() returned with error condition\n");
|
|
|
538c2f |
-out:
|
|
|
bcbcca |
-
|
|
|
538c2f |
- seteuid(oeuid);
|
|
|
538c2f |
- setegid(oegid);
|
|
|
538c2f |
- setgroups(ngids, groups);
|
|
|
bcbcca |
|
|
|
538c2f |
-outnouid:
|
|
|
538c2f |
+out:
|
|
|
8b5695 |
if (private_mnt != NULL)
|
|
|
8b5695 |
free(private_mnt);
|
|
|
538c2f |
return PAM_SUCCESS;
|
|
|
bcbcca |
@@ -374,10 +319,119 @@ static int umount_private_dir(pam_handle
|
|
|
8b5695 |
return private_dir(pamh, 0);
|
|
|
8b5695 |
}
|
|
|
8b5695 |
|
|
|
8b5695 |
+static int fill_keyring(pam_handle_t *pamh)
|
|
|
8b5695 |
+{
|
|
|
8b5695 |
+ pid_t child_pid,tmp_pid;
|
|
|
538c2f |
+ uid_t oeuid = 0;
|
|
|
538c2f |
+ long ngroups_max = sysconf(_SC_NGROUPS_MAX);
|
|
|
538c2f |
+ gid_t oegid = 0, groups[ngroups_max+1];
|
|
|
538c2f |
+ int ngids = 0;
|
|
|
8b5695 |
+ int rc = 0;
|
|
|
8b5695 |
+ const struct ecryptfs_pam_data *epd;
|
|
|
8b5695 |
+ char *auth_tok_sig;
|
|
|
8b5695 |
+ auth_tok_sig = malloc(ECRYPTFS_SIG_SIZE_HEX + 1);
|
|
|
538c2f |
+
|
|
|
7a13e7 |
+ if ((rc=pam_get_data(pamh, ECRYPTFS_PAM_DATA, (const void **)&epd)) != PAM_SUCCESS)
|
|
|
8b5695 |
+ {
|
|
|
7a13e7 |
+ syslog(LOG_ERR,"Unable to get ecryptfs pam data : %s", pam_strerror(pamh, rc));
|
|
|
8b5695 |
+ return -EINVAL;
|
|
|
8b5695 |
+ }
|
|
|
8b5695 |
+
|
|
|
538c2f |
+ oeuid = geteuid();
|
|
|
538c2f |
+ oegid = getegid();
|
|
|
538c2f |
+ if ((ngids = getgroups(sizeof(groups)/sizeof(gid_t), groups)) < 0) {
|
|
|
538c2f |
+ syslog(LOG_ERR, "pam_ecryptfs: geteuid error");
|
|
|
538c2f |
+ goto outnouid;
|
|
|
538c2f |
+ }
|
|
|
538c2f |
+
|
|
|
538c2f |
+ if (setegid(epd->gid) < 0 || setgroups(1, &epd->gid) < 0 || seteuid(epd->uid) < 0) {
|
|
|
538c2f |
+ syslog(LOG_ERR, "pam_ecryptfs: seteuid error");
|
|
|
538c2f |
+ goto out;
|
|
|
538c2f |
+ }
|
|
|
538c2f |
+
|
|
|
538c2f |
+ if (!auth_tok_sig) {
|
|
|
538c2f |
+ syslog(LOG_ERR, "Out of memory\n");
|
|
|
538c2f |
+ return -ENOMEM;
|
|
|
538c2f |
+ }
|
|
|
538c2f |
+
|
|
|
8b5695 |
+ if ((child_pid = fork()) == 0) {
|
|
|
538c2f |
+ /* temp regain uid 0 to drop privs */
|
|
|
bcbcca |
+ if (seteuid(oeuid) < 0)
|
|
|
bcbcca |
+ {
|
|
|
bcbcca |
+ syslog(LOG_ERR, "pam_ecryptfs: seteuid error");
|
|
|
bcbcca |
+ goto out_child;
|
|
|
bcbcca |
+ }
|
|
|
538c2f |
+ /* setgroups() already called */
|
|
|
538c2f |
+ if (setgid(epd->gid) < 0 || setuid(epd->uid) < 0)
|
|
|
538c2f |
+ goto out_child;
|
|
|
538c2f |
+
|
|
|
8b5695 |
+ if (epd->passphrase == NULL) {
|
|
|
8b5695 |
+ syslog(LOG_ERR, "NULL passphrase; aborting\n");
|
|
|
8b5695 |
+ rc = -EINVAL;
|
|
|
8b5695 |
+ goto out_child;
|
|
|
8b5695 |
+ }
|
|
|
8b5695 |
+ if ((rc = ecryptfs_validate_keyring())) {
|
|
|
8b5695 |
+ syslog(LOG_WARNING,
|
|
|
8b5695 |
+ "Cannot validate keyring integrity\n");
|
|
|
8b5695 |
+ }
|
|
|
8b5695 |
+ rc = 0;
|
|
|
8b5695 |
+ if (epd->unwrap) {
|
|
|
8b5695 |
+ char *wrapped_pw_filename;
|
|
|
8b5695 |
+
|
|
|
8b5695 |
+ rc = asprintf(
|
|
|
8b5695 |
+ &wrapped_pw_filename, "%s/.ecryptfs/%s",
|
|
|
8b5695 |
+ epd->homedir,
|
|
|
8b5695 |
+ ECRYPTFS_DEFAULT_WRAPPED_PASSPHRASE_FILENAME);
|
|
|
8b5695 |
+ if (rc == -1) {
|
|
|
8b5695 |
+ syslog(LOG_ERR, "Unable to allocate memory\n");
|
|
|
8b5695 |
+ rc = -ENOMEM;
|
|
|
8b5695 |
+ goto out_child;
|
|
|
8b5695 |
+ }
|
|
|
8b5695 |
+ if (wrap_passphrase_if_necessary(epd->username, epd->uid, wrapped_pw_filename, epd->passphrase, epd->salt) == 0) {
|
|
|
8b5695 |
+ syslog(LOG_INFO, "Passphrase file wrapped");
|
|
|
8b5695 |
+ } else {
|
|
|
8b5695 |
+ goto out_child;
|
|
|
8b5695 |
+ }
|
|
|
8b5695 |
+ rc = ecryptfs_insert_wrapped_passphrase_into_keyring(
|
|
|
8b5695 |
+ auth_tok_sig, wrapped_pw_filename, epd->passphrase,
|
|
|
8b5695 |
+ epd->salt);
|
|
|
8b5695 |
+ free(wrapped_pw_filename);
|
|
|
8b5695 |
+ } else {
|
|
|
8b5695 |
+ rc = ecryptfs_add_passphrase_key_to_keyring(
|
|
|
8b5695 |
+ auth_tok_sig, epd->passphrase, epd->salt);
|
|
|
8b5695 |
+ }
|
|
|
8b5695 |
+ if (rc == 1) {
|
|
|
8b5695 |
+ goto out_child;
|
|
|
8b5695 |
+ }
|
|
|
8b5695 |
+ if (rc) {
|
|
|
8b5695 |
+ syslog(LOG_ERR, "Error adding passphrase key token to "
|
|
|
8b5695 |
+ "user session keyring; rc = [%d]\n", rc);
|
|
|
8b5695 |
+ goto out_child;
|
|
|
8b5695 |
+ }
|
|
|
8b5695 |
+out_child:
|
|
|
8b5695 |
+ free(auth_tok_sig);
|
|
|
8b5695 |
+ _exit(0);
|
|
|
8b5695 |
+ }
|
|
|
8b5695 |
+ tmp_pid = waitpid(child_pid, NULL, 0);
|
|
|
8b5695 |
+ if (tmp_pid == -1)
|
|
|
8b5695 |
+ syslog(LOG_WARNING,
|
|
|
8b5695 |
+ "waitpid() returned with error condition\n");
|
|
|
538c2f |
+out:
|
|
|
bcbcca |
+ rc = seteuid(oeuid);
|
|
|
bcbcca |
+ rc = setegid(oegid);
|
|
|
bcbcca |
+ rc = setgroups(ngids, groups);
|
|
|
538c2f |
+
|
|
|
538c2f |
+outnouid:
|
|
|
8b5695 |
+
|
|
|
8b5695 |
+ return 0;
|
|
|
8b5695 |
+}
|
|
|
8b5695 |
+
|
|
|
8b5695 |
+
|
|
|
8b5695 |
PAM_EXTERN int
|
|
|
8b5695 |
pam_sm_open_session(pam_handle_t *pamh, int flags,
|
|
|
8b5695 |
int argc, const char *argv[])
|
|
|
8b5695 |
{
|
|
|
8b5695 |
+ fill_keyring(pamh);
|
|
|
8b5695 |
mount_private_dir(pamh);
|
|
|
8b5695 |
return PAM_SUCCESS;
|
|
|
8b5695 |
}
|