}
int Client::add_fscrypt_key(const char *key_data, int key_len,
- ceph_fscrypt_key_identifier *kid)
+ ceph_fscrypt_key_identifier *kid, int user)
{
auto& key_store = fscrypt->get_key_store();
FSCryptKeyHandlerRef kh;
- int r = key_store.create((const char *)key_data, key_len, kh);
+ int r = key_store.create((const char *)key_data, key_len, kh, user);
if (r < 0) {
ldout(cct, 0) << __func__ << "(): failed to create a new key: r=" << r << dendl;
return r;
return 0;
}
-int Client::remove_fscrypt_key(const ceph_fscrypt_key_identifier& kid)
+int Client::remove_fscrypt_key(fscrypt_remove_key_arg* kid, int user)
{
auto& key_store = fscrypt->get_key_store();
- return key_store.invalidate(kid);
+ return key_store.invalidate(kid, user);
}
int Client::set_fscrypt_policy_v2(int fd, const struct fscrypt_policy_v2& policy)
}
/* fscrypt */
- int add_fscrypt_key(const char *key_data, int key_len, ceph_fscrypt_key_identifier *kid);
- int remove_fscrypt_key(const ceph_fscrypt_key_identifier& kid);
+ int add_fscrypt_key(const char *key_data, int key_len, ceph_fscrypt_key_identifier *kid, int user = 0);
+ int remove_fscrypt_key(fscrypt_remove_key_arg* kid, int user = 0);
int set_fscrypt_policy_v2(int fd, const struct fscrypt_policy_v2& policy);
int mds_command(
return key;
}
-int FSCryptKeyStore::create(const char *k, int klen, FSCryptKeyHandlerRef& key_handler)
+//taken from fs/crypto/keyring.h
+bool FSCryptKeyStore::valid_key_spec(const struct fscrypt_key_specifier& k)
+{
+ if (k.__reserved)
+ return false;
+ return master_key_spec_len(k) != 0;
+}
+
+//taken from fs/crypto/fscrypt_private.h
+int FSCryptKeyStore::master_key_spec_len(const struct fscrypt_key_specifier& spec)
+{
+ switch (spec.type) {
+ case FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR:
+ return FSCRYPT_KEY_DESCRIPTOR_SIZE;
+ case FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER:
+ return FSCRYPT_KEY_IDENTIFIER_SIZE;
+ }
+ return 0;
+}
+
+
+
+int FSCryptKeyStore::maybe_add_user(std::list<int>* users, int user)
+{
+ ldout(cct, 10) << __FILE__ << ":" << __LINE__ << " user=" << user << dendl;
+
+ auto it = std::find(users->begin(), users->end(), user);
+ if (it != users->end()) {
+ ldout(cct, 10) << "maybe_add_user user already added!" << dendl;
+ return -EEXIST;
+ }
+
+ ldout(cct, 10) << "maybe_add_user is not found!, adding" << dendl;
+ users->push_back(user);
+ ldout(cct, 10) << "maybe_add_user size is now=" << users->size() << dendl;
+ return 0;
+}
+
+int FSCryptKeyStore::maybe_remove_user(struct fscrypt_remove_key_arg* arg, std::list<int>* users, int user)
+{
+ ldout(cct, 10) << __FILE__ << ":" << __LINE__ << " user=" << user << dendl;
+ uint32_t status_flags = 0;
+ int err = 0;
+ bool removed = false;
+ if (!valid_key_spec(arg->key_spec)) {
+ return -EINVAL;
+ }
+
+ auto it = std::find(users->begin(), users->end(), user);
+ if (it != users->end()) {
+ ldout(cct, 10) << "maybe_remove_user, user found removing!" << dendl;
+ removed = true;
+ users->erase(it);
+ } else {
+ return -ENOKEY;
+ }
+ ldout(cct, 10) << "maybe_add_user size is now=" << users->size() << dendl;
+
+ if (users->size() != 0 && removed) {
+
+ //set bits for removed for requested user
+ status_flags |= FSCRYPT_KEY_REMOVAL_STATUS_FLAG_OTHER_USERS;
+ err = -EBUSY;
+ }
+
+ arg->removal_status_flags = status_flags;
+ return err;
+}
+
+int FSCryptKeyStore::create(const char *k, int klen, FSCryptKeyHandlerRef& key_handler, int user)
{
auto key = std::make_shared<FSCryptKey>();
if (r < 0) {
return r;
}
-
std::unique_lock wl{lock};
const auto& id = key->get_identifier();
-
auto iter = m.find(id);
if (iter != m.end()) {
/* found a key handler entry, check that there is a key there */
key_handler = iter->second;
- if (key_handler->get_key()) {
- return -EEXIST;
+
+ auto& users = key_handler->get_users();
+ r = maybe_add_user(&users, user);
+
+ if (r == -EEXIST) {
+ return 0; //returns 0 regardless
}
key_handler->reset(++epoch, key);
} else {
key_handler = std::make_shared<FSCryptKeyHandler>(++epoch, key);
+
+ auto& users = key_handler->get_users();
+ r = maybe_add_user(&users, user);
+ if (r == -EEXIST) {
+ return 0; //returns 0 regardless
+ }
+
m[id] = key_handler;
}
{
auto iter = m.find(id);
if (iter == m.end()) {
- return -ENOENT;
+ return -ENOKEY;
}
kh = iter->second;
return _find(id, kh);
}
-int FSCryptKeyStore::invalidate(const struct ceph_fscrypt_key_identifier& id)
+int FSCryptKeyStore::invalidate(struct fscrypt_remove_key_arg* arg, int user)
{
std::unique_lock rl{lock};
+ ceph_fscrypt_key_identifier id;
+ int r = id.init(arg->key_spec);
+ if (r < 0) {
+ return r;
+ }
+
FSCryptKeyHandlerRef kh;
- int r = _find(id, kh);
- if (r == -ENOENT) {
- return 0;
- } else if (r < 0) {
+ r = _find(id, kh);
+ if (r < 0) {
+ return r;
+ }
+
+ auto& users = kh->get_users();
+ r = maybe_remove_user(arg, &users, user);
+ if (r < 0) {
return r;
}
class FSCryptKey {
bufferlist key;
ceph_fscrypt_key_identifier identifier;
-
public:
int init(const char *k, int klen);
ceph::shared_mutex lock = ceph::make_shared_mutex("FSCryptKeyHandler");
int64_t epoch = -1;
FSCryptKeyRef key;
+ std::list<int> users;
public:
FSCryptKeyHandler() {}
FSCryptKeyHandler(int64_t epoch, FSCryptKeyRef k) : epoch(epoch), key(k) {}
void reset(int64_t epoch, FSCryptKeyRef k);
int64_t get_epoch();
+ std::list<int>& get_users() { return users; }
FSCryptKeyRef& get_key();
};
public:
FSCryptKeyStore(CephContext *_cct) : cct(_cct) {}
- int create(const char *k, int klen, FSCryptKeyHandlerRef& key);
+ bool valid_key_spec(const struct fscrypt_key_specifier& k);
+ int master_key_spec_len(const struct fscrypt_key_specifier& spec);
+ int maybe_add_user(std::list<int>* users, int user);
+ int maybe_remove_user(struct fscrypt_remove_key_arg* arg, std::list<int>* users, int user);
+ int create(const char *k, int klen, FSCryptKeyHandlerRef& key, int user);
int find(const struct ceph_fscrypt_key_identifier& id, FSCryptKeyHandlerRef& key);
- int invalidate(const struct ceph_fscrypt_key_identifier& id);
+ int invalidate(struct fscrypt_remove_key_arg* id, int user);
};
struct FSCryptKeyValidator {
break;
}
- int r = cfuse->client->add_fscrypt_key((const char *)arg->raw, arg->raw_size, nullptr);
+ int r = cfuse->client->add_fscrypt_key((const char *)arg->raw, arg->raw_size, nullptr, ctx->uid);
if (r < 0) {
generic_dout(0) << __FILE__ << ":" << __LINE__ << ": failed to create a new key: r=" << r << dendl;
fuse_reply_err(req, -r);
}
/* FIXME: handle busy cases */
- r = cfuse->client->remove_fscrypt_key(kid);
+ r = cfuse->client->remove_fscrypt_key(arg, ctx->uid);
if (r < 0) {
fuse_reply_err(req, -r);
break;
}
- arg->removal_status_flags = 0; /* FIXME */
fuse_reply_ioctl(req, 0, arg, sizeof(*arg));
break;
}
/* TODO: return correct info */
arg->status = (found ? FSCRYPT_KEY_STATUS_PRESENT : FSCRYPT_KEY_STATUS_ABSENT);
- arg->status_flags = (found ? 0x1 : 0); /* FIXME */
+ arg->status_flags = 0;//(found ? 0x1 : 0); /* FIXME */
+ //arg->status_flags = (found ? 0x1 : 0); /* FIXME */
arg->user_count = !!found; /* FIXME */
fuse_reply_ioctl(req, 0, arg, sizeof(*arg));
* @returns zero on success, other returns a negative error code.
*/
int ceph_remove_fscrypt_key(struct ceph_mount_info *cmount,
- const struct ceph_fscrypt_key_identifier *kid);
+ struct fscrypt_remove_key_arg *kid);
/**
* Set encryption policy on a directory.
}
extern "C" int ceph_remove_fscrypt_key(struct ceph_mount_info *cmount,
- const struct ceph_fscrypt_key_identifier *kid)
+ struct fscrypt_remove_key_arg *kid)
{
if (!cmount->is_mounted())
return -CEPHFS_ENOTCONN;
- return cmount->get_client()->remove_fscrypt_key(*kid);
+ return cmount->get_client()->remove_fscrypt_key(kid);
}
extern "C" int ceph_set_fscrypt_policy_v2(struct ceph_mount_info *cmount,