[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1300362538-11502-4-git-send-email-roberto.sassu@polito.it>
Date: Thu, 17 Mar 2011 12:48:52 +0100
From: Roberto Sassu <roberto.sassu@...ito.it>
To: tyhicks@...ux.vnet.ibm.com
Cc: kirkland@...onical.com, dhowells@...hat.com, jmorris@...ei.org,
linux-fsdevel@...r.kernel.org, keyrings@...ux-nfs.org,
linux-kernel@...r.kernel.org,
Roberto Sassu <roberto.sassu@...ito.it>
Subject: [PATCH 3/5] eCryptfs: verify authentication tokens before their use
Authentication tokens content may change if another requestor calls the
update() method of the corresponding key. The new function
ecryptfs_verify_auth_tok_from_key() retrieves the authentication token from
the provided key and verifies if it is still valid before being used to
encrypt or decrypt an eCryptfs file.
Signed-off-by: Roberto Sassu <roberto.sassu@...ito.it>
---
fs/ecryptfs/ecryptfs_kernel.h | 3 +-
fs/ecryptfs/keystore.c | 107 ++++++++++++++++++++++++++++-------------
fs/ecryptfs/main.c | 4 +-
3 files changed, 77 insertions(+), 37 deletions(-)
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index 8282031..85728e9 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -333,7 +333,6 @@ struct ecryptfs_global_auth_tok {
u32 flags;
struct list_head mount_crypt_stat_list;
struct key *global_auth_tok_key;
- struct ecryptfs_auth_tok *global_auth_tok;
unsigned char sig[ECRYPTFS_SIG_SIZE_HEX + 1];
};
@@ -726,6 +725,8 @@ int ecryptfs_get_tfm_and_mutex_for_cipher_name(struct crypto_blkcipher **tfm,
int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key,
struct ecryptfs_auth_tok **auth_tok,
char *sig);
+int ecryptfs_verify_auth_tok_from_key(struct key *auth_tok_key,
+ struct ecryptfs_auth_tok **auth_tok);
int ecryptfs_write_lower(struct inode *ecryptfs_inode, char *data,
loff_t offset, size_t size);
int ecryptfs_write_lower_page_segment(struct inode *ecryptfs_inode,
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c
index 36b68a6..e35d745 100644
--- a/fs/ecryptfs/keystore.c
+++ b/fs/ecryptfs/keystore.c
@@ -405,25 +405,47 @@ out:
static int
ecryptfs_find_global_auth_tok_for_sig(
- struct ecryptfs_global_auth_tok **global_auth_tok,
+ struct key **auth_tok_key,
+ struct ecryptfs_auth_tok **auth_tok,
struct ecryptfs_mount_crypt_stat *mount_crypt_stat, char *sig)
{
struct ecryptfs_global_auth_tok *walker;
int rc = 0;
- (*global_auth_tok) = NULL;
+ (*auth_tok_key) = NULL;
+ (*auth_tok) = NULL;
mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex);
list_for_each_entry(walker,
&mount_crypt_stat->global_auth_tok_list,
mount_crypt_stat_list) {
if (memcmp(walker->sig, sig, ECRYPTFS_SIG_SIZE_HEX) == 0) {
+ if (walker->flags & ECRYPTFS_AUTH_TOK_INVALID) {
+ rc = -EINVAL;
+ goto out;
+ }
+
rc = key_validate(walker->global_auth_tok_key);
- if (!rc)
- (*global_auth_tok) = walker;
+ if (rc)
+ goto out;
+
+ rc = ecryptfs_verify_auth_tok_from_key(
+ walker->global_auth_tok_key, auth_tok);
+ if (rc) {
+ printk(KERN_WARNING
+ "Invalidating auth tok with sig = [%s]\n",
+ sig);
+ walker->flags |= ECRYPTFS_AUTH_TOK_INVALID;
+ key_put(walker->global_auth_tok_key);
+ walker->global_auth_tok_key = NULL;
+ mount_crypt_stat->num_global_auth_toks--;
+ goto out;
+ }
+ (*auth_tok_key) = walker->global_auth_tok_key;
+ key_get(*auth_tok_key);
goto out;
}
}
- rc = -EINVAL;
+ rc = -ENOENT;
out:
mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex);
return rc;
@@ -451,14 +473,11 @@ ecryptfs_find_auth_tok_for_sig(
struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
char *sig)
{
- struct ecryptfs_global_auth_tok *global_auth_tok;
int rc = 0;
- (*auth_tok_key) = NULL;
- (*auth_tok) = NULL;
- if (ecryptfs_find_global_auth_tok_for_sig(&global_auth_tok,
- mount_crypt_stat, sig)) {
-
+ rc = ecryptfs_find_global_auth_tok_for_sig(auth_tok_key, auth_tok,
+ mount_crypt_stat, sig);
+ if (rc == -ENOENT) {
/* if the flag ECRYPTFS_GLOBAL_MOUNT_AUTH_TOK_ONLY is set in the
* mount_crypt_stat structure, we prevent to use auth toks that
* are not inserted through the ecryptfs_add_global_auth_tok
@@ -470,8 +489,8 @@ ecryptfs_find_auth_tok_for_sig(
rc = ecryptfs_keyring_auth_tok_for_sig(auth_tok_key, auth_tok,
sig);
- } else
- (*auth_tok) = global_auth_tok->global_auth_tok;
+ }
+
return rc;
}
@@ -1566,7 +1585,23 @@ int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key,
(*auth_tok_key) = NULL;
goto out;
}
- (*auth_tok) = ecryptfs_get_key_payload_data(*auth_tok_key);
+
+ rc = ecryptfs_verify_auth_tok_from_key(*auth_tok_key, auth_tok);
+ if (rc) {
+ key_put(*auth_tok_key);
+ (*auth_tok_key) = NULL;
+ goto out;
+ }
+out:
+ return rc;
+}
+
+int ecryptfs_verify_auth_tok_from_key(struct key *auth_tok_key,
+ struct ecryptfs_auth_tok **auth_tok)
+{
+ int rc = 0;
+
+ (*auth_tok) = ecryptfs_get_key_payload_data(auth_tok_key);
if (ecryptfs_verify_version((*auth_tok)->version)) {
printk(KERN_ERR
"Data structure version mismatch. "
@@ -1576,19 +1611,14 @@ int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key,
ECRYPTFS_VERSION_MAJOR,
ECRYPTFS_VERSION_MINOR);
rc = -EINVAL;
- goto out_release_key;
+ goto out;
}
if ((*auth_tok)->token_type != ECRYPTFS_PASSWORD
&& (*auth_tok)->token_type != ECRYPTFS_PRIVATE_KEY) {
printk(KERN_ERR "Invalid auth_tok structure "
"returned from key query\n");
rc = -EINVAL;
- goto out_release_key;
- }
-out_release_key:
- if (rc) {
- key_put(*auth_tok_key);
- (*auth_tok_key) = NULL;
+ goto out;
}
out:
return rc;
@@ -2325,13 +2355,14 @@ ecryptfs_generate_key_packet_set(char *dest_base,
size_t max)
{
struct ecryptfs_auth_tok *auth_tok;
- struct ecryptfs_global_auth_tok *global_auth_tok;
+ struct key *auth_tok_key = NULL;
struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
&ecryptfs_superblock_to_private(
ecryptfs_dentry->d_sb)->mount_crypt_stat;
size_t written;
struct ecryptfs_key_record *key_rec;
struct ecryptfs_key_sig *key_sig;
+ int auth_tok_count = 0;
int rc = 0;
(*len) = 0;
@@ -2344,21 +2375,18 @@ ecryptfs_generate_key_packet_set(char *dest_base,
list_for_each_entry(key_sig, &crypt_stat->keysig_list,
crypt_stat_list) {
memset(key_rec, 0, sizeof(*key_rec));
- rc = ecryptfs_find_global_auth_tok_for_sig(&global_auth_tok,
+ rc = ecryptfs_find_global_auth_tok_for_sig(&auth_tok_key,
+ &auth_tok,
mount_crypt_stat,
key_sig->keysig);
if (rc) {
- printk(KERN_ERR "Error attempting to get the global "
- "auth_tok; rc = [%d]\n", rc);
- goto out_free;
- }
- if (global_auth_tok->flags & ECRYPTFS_AUTH_TOK_INVALID) {
printk(KERN_WARNING
"Skipping invalid auth tok with sig = [%s]\n",
- global_auth_tok->sig);
+ key_sig->keysig);
+ rc = 0;
continue;
}
- auth_tok = global_auth_tok->global_auth_tok;
+ auth_tok_count++;
if (auth_tok->token_type == ECRYPTFS_PASSWORD) {
rc = write_tag_3_packet((dest_base + (*len)),
&max, auth_tok,
@@ -2367,7 +2395,7 @@ ecryptfs_generate_key_packet_set(char *dest_base,
if (rc) {
ecryptfs_printk(KERN_WARNING, "Error "
"writing tag 3 packet\n");
- goto out_free;
+ goto out_release_key;
}
(*len) += written;
/* Write auth tok signature packet */
@@ -2377,7 +2405,7 @@ ecryptfs_generate_key_packet_set(char *dest_base,
if (rc) {
ecryptfs_printk(KERN_ERR, "Error writing "
"auth tok signature packet\n");
- goto out_free;
+ goto out_release_key;
}
(*len) += written;
} else if (auth_tok->token_type == ECRYPTFS_PRIVATE_KEY) {
@@ -2387,15 +2415,23 @@ ecryptfs_generate_key_packet_set(char *dest_base,
if (rc) {
ecryptfs_printk(KERN_WARNING, "Error "
"writing tag 1 packet\n");
- goto out_free;
+ goto out_release_key;
}
(*len) += written;
} else {
ecryptfs_printk(KERN_WARNING, "Unsupported "
"authentication token type\n");
rc = -EINVAL;
- goto out_free;
+ goto out_release_key;
}
+ key_put(auth_tok_key);
+ }
+ if (!auth_tok_count) {
+ printk(KERN_WARNING
+ "Unable to create a new file without a valid "
+ "authentication token\n");
+ rc = -EINVAL;
+ goto out_free;
}
if (likely(max > 0)) {
dest_base[(*len)] = 0x00;
@@ -2403,6 +2439,9 @@ ecryptfs_generate_key_packet_set(char *dest_base,
ecryptfs_printk(KERN_ERR, "Error writing boundary byte\n");
rc = -EIO;
}
+out_release_key:
+ if (rc)
+ key_put(auth_tok_key);
out_free:
kmem_cache_free(ecryptfs_key_record_cache, key_rec);
out:
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c
index 758323a..f079473 100644
--- a/fs/ecryptfs/main.c
+++ b/fs/ecryptfs/main.c
@@ -241,14 +241,14 @@ static int ecryptfs_init_global_auth_toks(
struct ecryptfs_mount_crypt_stat *mount_crypt_stat)
{
struct ecryptfs_global_auth_tok *global_auth_tok;
+ struct ecryptfs_auth_tok *auth_tok;
int rc = 0;
list_for_each_entry(global_auth_tok,
&mount_crypt_stat->global_auth_tok_list,
mount_crypt_stat_list) {
rc = ecryptfs_keyring_auth_tok_for_sig(
- &global_auth_tok->global_auth_tok_key,
- &global_auth_tok->global_auth_tok,
+ &global_auth_tok->global_auth_tok_key, &auth_tok,
global_auth_tok->sig);
if (rc) {
printk(KERN_ERR "Could not find valid key in user "
--
1.7.4
Download attachment "smime.p7s" of type "application/x-pkcs7-signature" (2061 bytes)
Powered by blists - more mailing lists