From 8b569554f2afcccdddaa0f6ad1dce6147116964c Mon Sep 17 00:00:00 2001 From: Michal Hlavinka Date: Aug 03 2011 14:02:27 +0000 Subject: keyring from auth stack does not survive, use pam_data and delayed keyring initialization --- diff --git a/ecryptfs-utils-87-fixconst.patch b/ecryptfs-utils-87-fixconst.patch new file mode 100644 index 0000000..af01752 --- /dev/null +++ b/ecryptfs-utils-87-fixconst.patch @@ -0,0 +1,159 @@ +diff -up ecryptfs-utils-87/src/include/ecryptfs.h.fixconst ecryptfs-utils-87/src/include/ecryptfs.h +--- ecryptfs-utils-87/src/include/ecryptfs.h.fixconst 2011-08-03 15:35:28.552079157 +0200 ++++ ecryptfs-utils-87/src/include/ecryptfs.h 2011-08-03 15:39:40.654497299 +0200 +@@ -528,8 +528,8 @@ int ecryptfs_eval_decision_graph(struct + struct val_node **head, + struct param_node *root_node, + struct ecryptfs_name_val_pair *nvp_head); +-int ecryptfs_add_passphrase_key_to_keyring(char *auth_tok_sig, char *passphrase, +- char *salt); ++int ecryptfs_add_passphrase_key_to_keyring(char *auth_tok_sig, const char *passphrase, ++ const char *salt); + int ecryptfs_add_key_module_key_to_keyring(char *auth_tok_sig, + struct ecryptfs_key_mod *key_mod); + int ecryptfs_read_salt_hex_from_rc(char *salt_hex); +@@ -545,11 +545,11 @@ int parse_packet(struct ecryptfs_ctx *ct + struct ecryptfs_message **reply); + int ecryptfs_find_key_mod(struct ecryptfs_key_mod **key_mod, + struct ecryptfs_ctx *ctx, char *key_mod_alias); +-int generate_passphrase_sig(char *passphrase_sig, char *fekek, char *salt, +- char *passphrase); ++int generate_passphrase_sig(char *passphrase_sig, char *fekek, const char *salt, ++ const char *passphrase); + int + generate_payload(struct ecryptfs_auth_tok *auth_tok, char *passphrase_sig, +- char *salt, char *session_key_encryption_key); ++ const char *salt, char *session_key_encryption_key); + int + ecryptfs_generate_key_payload(struct ecryptfs_auth_tok *auth_tok, + struct ecryptfs_key_mod *key_mod, char *sig, +@@ -573,15 +573,15 @@ int ecryptfs_read_salt_hex_from_rc(char + int ecryptfs_check_sig(char *auth_tok_sig, char *sig_cache_filename, + int *flags); + int ecryptfs_append_sig(char *auth_tok_sig, char *sig_cache_filename); +-int ecryptfs_wrap_passphrase_file(char *dest, char *wrapping_passphrase, +- char *wrapping_salt, char *src); +-int ecryptfs_wrap_passphrase(char *filename, char *wrapping_passphrase, +- char *wrapping_salt, char *decrypted_passphrase); +-int ecryptfs_unwrap_passphrase(char *decrypted_passphrase, char *filename, +- char *wrapping_passphrase, char *wrapping_salt); ++int ecryptfs_wrap_passphrase_file(const char *dest, const char *wrapping_passphrase, ++ const char *wrapping_salt, const char *src); ++int ecryptfs_wrap_passphrase(const char *filename, const char *wrapping_passphrase, ++ const char *wrapping_salt, char *decrypted_passphrase); ++int ecryptfs_unwrap_passphrase(char *decrypted_passphrase, const char *filename, ++ const char *wrapping_passphrase, const char *wrapping_salt); + int ecryptfs_insert_wrapped_passphrase_into_keyring( +- char *auth_tok_sig, char *filename, char *wrapping_passphrase, +- char *salt); ++ char *auth_tok_sig, char *filename, const char *wrapping_passphrase, ++ const char *salt); + char *ecryptfs_get_wrapped_passphrase_filename(); + struct ecryptfs_key_mod_ops *passphrase_get_key_mod_ops(void); + int ecryptfs_validate_keyring(void); +@@ -629,7 +629,7 @@ char *ecryptfs_get_passphrase(char *prom + int ecryptfs_run_daemon(struct ecryptfs_messaging_ctx *mctx); + + #define ECRYPTFS_PRIVATE_DIR "Private" +-char *ecryptfs_fetch_private_mnt(char *pw_dir); ++char *ecryptfs_fetch_private_mnt(const char *pw_dir); + int ecryptfs_private_is_mounted(char *dev, char *mnt, char *sig, int mounting); + + #endif +diff -up ecryptfs-utils-87/src/libecryptfs/key_management.c.fixconst ecryptfs-utils-87/src/libecryptfs/key_management.c +--- ecryptfs-utils-87/src/libecryptfs/key_management.c.fixconst 2011-08-03 15:35:28.434082255 +0200 ++++ ecryptfs-utils-87/src/libecryptfs/key_management.c 2011-08-03 15:39:26.382868090 +0200 +@@ -53,7 +53,7 @@ + */ + int ecryptfs_generate_passphrase_auth_tok(struct ecryptfs_auth_tok **auth_tok, + char *auth_tok_sig, char *fekek, +- char *salt, char *passphrase) ++ const char *salt, const char *passphrase) + { + int rc; + +@@ -190,8 +190,8 @@ int ecryptfs_add_blob_to_keyring(char *b + * + * Returns 0 on add, 1 on pre-existed, negative on failure. + */ +-int ecryptfs_add_passphrase_key_to_keyring(char *auth_tok_sig, char *passphrase, +- char *salt) ++int ecryptfs_add_passphrase_key_to_keyring(char *auth_tok_sig, const char *passphrase, ++ const char *salt) + { + int rc; + char fekek[ECRYPTFS_MAX_KEY_BYTES]; +@@ -220,8 +220,8 @@ out: + return rc; + } + +-int ecryptfs_wrap_passphrase_file(char *dest, char *wrapping_passphrase, +- char *salt, char *src) ++int ecryptfs_wrap_passphrase_file(const char *dest, const char *wrapping_passphrase, ++ const char *salt, const char *src) + { + int rc = 0; + ssize_t size; +@@ -264,8 +264,8 @@ out: + return rc; + } + +-int ecryptfs_wrap_passphrase(char *filename, char *wrapping_passphrase, +- char *wrapping_salt, char *decrypted_passphrase) ++int ecryptfs_wrap_passphrase(const char *filename, const char *wrapping_passphrase, ++ const char *wrapping_salt, char *decrypted_passphrase) + { + char wrapping_auth_tok_sig[ECRYPTFS_SIG_SIZE_HEX + 1]; + char wrapping_key[ECRYPTFS_MAX_KEY_BYTES]; +@@ -410,8 +410,8 @@ out: + * decryptfs_passphrase must be able to hold + * ECRYPTFS_MAX_PASSPHRASE_BYTES + 1 bytes + */ +-int ecryptfs_unwrap_passphrase(char *decrypted_passphrase, char *filename, +- char *wrapping_passphrase, char *wrapping_salt) ++int ecryptfs_unwrap_passphrase(char *decrypted_passphrase, const char *filename, ++ const char *wrapping_passphrase, const char *wrapping_salt) + { + char wrapping_auth_tok_sig[ECRYPTFS_SIG_SIZE_HEX + 1]; + char wrapping_auth_tok_sig_from_file[ECRYPTFS_SIG_SIZE_HEX + 1]; +@@ -546,8 +546,8 @@ out: + * into the user session keyring. + */ + int ecryptfs_insert_wrapped_passphrase_into_keyring( +- char *auth_tok_sig, char *filename, char *wrapping_passphrase, +- char *salt) ++ char *auth_tok_sig, char *filename, const char *wrapping_passphrase, ++ const char *salt) + { + char decrypted_passphrase[ECRYPTFS_MAX_PASSPHRASE_BYTES + 1] ; + uint32_t version; +diff -up ecryptfs-utils-87/src/libecryptfs/main.c.fixconst ecryptfs-utils-87/src/libecryptfs/main.c +--- ecryptfs-utils-87/src/libecryptfs/main.c.fixconst 2011-08-03 15:35:28.553079131 +0200 ++++ ecryptfs-utils-87/src/libecryptfs/main.c 2011-08-03 15:35:28.577078501 +0200 +@@ -93,7 +93,7 @@ out: + /* Read ecryptfs private mount from file + * Allocate and return a string + */ +-char *ecryptfs_fetch_private_mnt(char *pw_dir) { ++char *ecryptfs_fetch_private_mnt(const char *pw_dir) { + char *mnt_file = NULL; + char *mnt_default = NULL; + char *mnt = NULL; +@@ -209,7 +209,7 @@ int ecryptfs_private_is_mounted(char *de + */ + int + generate_passphrase_sig(char *passphrase_sig, char *fekek, +- char *salt, char *passphrase) ++ const char *salt, const char *passphrase) + { + char salt_and_passphrase[ECRYPTFS_MAX_PASSPHRASE_BYTES + + ECRYPTFS_SALT_SIZE]; +@@ -253,7 +253,7 @@ generate_passphrase_sig(char *passphrase + */ + int + generate_payload(struct ecryptfs_auth_tok *auth_tok, char *passphrase_sig, +- char *salt, char *session_key_encryption_key) ++ const char *salt, char *session_key_encryption_key) + { + int rc = 0; + int major, minor; diff --git a/ecryptfs-utils-87-fixexecgid.patch b/ecryptfs-utils-87-fixexecgid.patch index 2367a2a..ed9c2e6 100644 --- a/ecryptfs-utils-87-fixexecgid.patch +++ b/ecryptfs-utils-87-fixexecgid.patch @@ -9,23 +9,13 @@ diff -up ecryptfs-utils-87/src/pam_ecryptfs/pam_ecryptfs.c.fixexecgid ecryptfs-u #include #include #include -@@ -303,6 +304,22 @@ static int private_dir(pam_handle_t *pam +@@ -303,6 +304,12 @@ static int private_dir(pam_handle_t *pam return 1; } if (pid == 0) { -+ /* explicitely change group to ecryptfs if user is member of that group, changing uid is not enough */ -+ gid_t *groups; -+ int grn = 0; -+ -+ getgrouplist(pwd->pw_name,pwd->pw_gid,NULL,&grn); -+ groups = malloc(sizeof(gid_t)*grn); -+ if (groups == NULL) { -+ syslog(LOG_ERR, "Error allocating memory for group list"); -+ _exit(255); -+ } -+ getgrouplist(pwd->pw_name, pwd->pw_gid, groups, &grn); -+ if (setgroups(grn, groups) < 0) { -+ syslog(LOG_ERR, "Unable to set user's supplementary groups : %m"); ++ /* set user's groups, we may need ecryptfs group for (u)mount */ ++ if (initgroups(pwd->pw_name, pwd->pw_gid) != 0) { ++ syslog(LOG_ERR, "Unable to set user's groups : %m"); + _exit(255); + } + diff --git a/ecryptfs-utils-87-pamdata.patch b/ecryptfs-utils-87-pamdata.patch new file mode 100644 index 0000000..9553414 --- /dev/null +++ b/ecryptfs-utils-87-pamdata.patch @@ -0,0 +1,281 @@ +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,22 @@ + + #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) ++{ ++ 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 +80,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 +112,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 +158,31 @@ 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); + 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 (pam_set_data(pamh, ECRYPTFS_PAM_DATA, epd, pam_free_ecryptfsdata) != PAM_SUCCESS) { ++ ++ syslog(LOG_ERR, "Unable to store ecryptfs pam data : %m"); ++ 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 +327,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 (pam_get_data(pamh, ECRYPTFS_PAM_DATA, (const void **)&epd) != PAM_SUCCESS) ++ { ++ syslog(LOG_ERR,"Unable to get ecryptfs pam data : %m"); ++ 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; + } diff --git a/ecryptfs-utils.spec b/ecryptfs-utils.spec index 91a55bf..8046854 100644 --- a/ecryptfs-utils.spec +++ b/ecryptfs-utils.spec @@ -5,7 +5,7 @@ Name: ecryptfs-utils Version: 87 -Release: 7%{?dist} +Release: 8%{?dist} Summary: The eCryptfs mount helper and support libraries Group: System Environment/Base License: GPLv2+ @@ -56,6 +56,12 @@ Patch14: ecryptfs-utils-87-fixexecgid.patch # do not use zombie process, it causes lock ups at least for ssh login Patch15: ecryptfs-utils-87-nozombies.patch +# if we do not use zombies, we have to store passphrase in pam_data and init keyring later +Patch16: ecryptfs-utils-87-pamdata.patch + +# patch16 needs propper const on some places +Patch17: ecryptfs-utils-87-fixconst.patch + BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) Requires: keyutils, cryptsetup-luks, util-linux-ng, gettext BuildRequires: libgcrypt-devel keyutils-libs-devel openssl-devel pam-devel @@ -107,6 +113,8 @@ the interface supplied by the ecryptfs-utils library. %patch13 -p1 -b .fixpamfork %patch14 -p1 -b .fixexecgid %patch15 -p1 -b .nozombies +%patch16 -p1 -b .pamdata +%patch17 -p1 -b .fixconst %build export CFLAGS="$RPM_OPT_FLAGS -Werror -Wtype-limits" @@ -234,6 +242,10 @@ rm -rf $RPM_BUILD_ROOT %{python_sitearch}/ecryptfs-utils/_libecryptfs.so %changelog +* Wed Aug 03 2011 Michal Hlavinka - 87-8 +- keyring from auth stack does not survive, use pam_data and delayed + keyring initialization + * Thu Jul 21 2011 Michal Hlavinka - 87-7 - fix pam module to set ecryptfs gid before mount helper execution - do not use zombie process, it causes lock ups in ssh