From 171e5c502dc085026ce73703353e9097f8c3aa31 Mon Sep 17 00:00:00 2001 From: anwleung Date: Tue, 6 Mar 2007 05:16:29 +0000 Subject: [PATCH] merkle trees added, full cap stuff almost done git-svn-id: https://ceph.svn.sf.net/svnroot/ceph@1173 29311d96-e01e-0410-9327-a35deaab8ce9 --- .../aleung/security1/ceph/client/Client.cc | 17 ++-- .../aleung/security1/ceph/client/Client.h | 2 + .../aleung/security1/ceph/crypto/CapGroup.h | 20 +++- .../aleung/security1/ceph/crypto/ExtCap.h | 11 +++ .../aleung/security1/ceph/crypto/MerkleTree.h | 98 +++++++++++++++++++ .../aleung/security1/ceph/crypto/driver.cc | 15 +++ branches/aleung/security1/ceph/mds/Locker.cc | 9 +- branches/aleung/security1/ceph/mds/MDS.h | 2 + .../security1/ceph/messages/MClientUpdate.h | 50 ++++++++++ .../security1/ceph/messages/MOSDUpdate.h | 64 ++++++++++++ .../security1/ceph/messages/MOSDUpdateReply.h | 51 ++++++++++ branches/aleung/security1/ceph/msg/Message.cc | 5 + branches/aleung/security1/ceph/msg/Message.h | 2 + branches/aleung/security1/ceph/osd/OSD.cc | 59 ++++++++++- branches/aleung/security1/ceph/osd/OSD.h | 8 +- 15 files changed, 394 insertions(+), 19 deletions(-) create mode 100644 branches/aleung/security1/ceph/crypto/MerkleTree.h create mode 100644 branches/aleung/security1/ceph/messages/MClientUpdate.h create mode 100644 branches/aleung/security1/ceph/messages/MOSDUpdate.h create mode 100644 branches/aleung/security1/ceph/messages/MOSDUpdateReply.h diff --git a/branches/aleung/security1/ceph/client/Client.cc b/branches/aleung/security1/ceph/client/Client.cc index 2ed2149e5e360..63f43af8257bc 100644 --- a/branches/aleung/security1/ceph/client/Client.cc +++ b/branches/aleung/security1/ceph/client/Client.cc @@ -713,13 +713,18 @@ void Client::put_user_ticket(Ticket *tk) } void Client::handle_osd_update(MOSDUpdate *m) { - cout << "Received a request to resolve group " << m->get_group() << endl; // check local cache - if (groups.count(m->get_group())) { - - } - // else, ask mds, pass it, cache it - assert(0); + MOSDUpdateReply *reply; + gid_t my_group = m->get_group(); + cout << "Received a request to resolve group " << my_group << endl; + // if we dont have it cached, ask mds, cache it + //if (groups.count(my_group) == 0) { + // MClientUpdate *update = new MClientUpdate(my_group); + //} + //reply = new MOSDUpdateReply(groups[my_group].get_list()); + reply = new MOSDUpdateReply(my_group); + + messenger->send_message(reply, m->get_source_inst()); } // ------------------------ diff --git a/branches/aleung/security1/ceph/client/Client.h b/branches/aleung/security1/ceph/client/Client.h index 1ddb3bfe1409e..0cadf3d7c79df 100644 --- a/branches/aleung/security1/ceph/client/Client.h +++ b/branches/aleung/security1/ceph/client/Client.h @@ -28,6 +28,8 @@ #include "messages/MClientRequest.h" #include "messages/MClientReply.h" #include "messages/MOSDUpdate.h" +#include "messages/MOSDUpdateReply.h" +#include "messages/MClientUpdate.h" //#include "msgthread.h" diff --git a/branches/aleung/security1/ceph/crypto/CapGroup.h b/branches/aleung/security1/ceph/crypto/CapGroup.h index a5703e168019f..77f96a7b278ed 100644 --- a/branches/aleung/security1/ceph/crypto/CapGroup.h +++ b/branches/aleung/security1/ceph/crypto/CapGroup.h @@ -16,21 +16,28 @@ #include using namespace std; -#include "include/types.h" +//#include "include/types.h" +#include "crypto/MerkleTree.h" class CapGroup { private: - gid_t group_id; + //gid_t group_id; + hash_t root_hash; list users; public: friend class OSD; friend class Locker; CapGroup () { } - CapGroup (gid_t id) { group_id = id; } + //CapGroup (gid_t id) { group_id = id; } + CapGroup (hash_t rhash, list& ulist) : + root_hash(rhash), users(ulist) { } - gid_t get_gid() { return group_id; } - void set_gid(gid_t id) { group_id = id; } + //gid_t get_gid() { return group_id; } + //void set_gid(gid_t id) { group_id = id; } + + hash_t get_root_hash() { return root_hash; } + void set_root_hash(hash_t nhash) { root_hash = nhash; } void add_user(uid_t user) { users.push_back(user); @@ -49,6 +56,9 @@ class CapGroup { } return false; } + + void set_list(list& nlist) { users = nlist; } + list& get_list() { return users; } }; #endif diff --git a/branches/aleung/security1/ceph/crypto/ExtCap.h b/branches/aleung/security1/ceph/crypto/ExtCap.h index 64362ab25f009..b7f2229dd428c 100644 --- a/branches/aleung/security1/ceph/crypto/ExtCap.h +++ b/branches/aleung/security1/ceph/crypto/ExtCap.h @@ -23,6 +23,7 @@ using namespace std; #include "crypto/CryptoLib.h" using namespace CryptoLib; +#include "crypto/MerkleTree.h" #define NO_GROUP 0 #define UNIX_GROUP 1 @@ -84,6 +85,10 @@ private: gid_t gid; // group id bool world; + // hash based users and files + hash_t user_group; + hash_t file_group; + inodeno_t ino; // inode number }; @@ -166,6 +171,12 @@ public: } void set_type(__int8_t new_type) { data.type = new_type;} + void set_user_hash(hash_t nhash) { user_group = nhash; } + void set_file_hash(hash_t nhash) { file_group = nhash; } + + hash_t get_user_hash() { return user_group; } + hash_t get_file_hash() { return file_group; } + const cap_data_t* get_data() const { return (&data); } diff --git a/branches/aleung/security1/ceph/crypto/MerkleTree.h b/branches/aleung/security1/ceph/crypto/MerkleTree.h new file mode 100644 index 0000000000000..06d4c1e455bdd --- /dev/null +++ b/branches/aleung/security1/ceph/crypto/MerkleTree.h @@ -0,0 +1,98 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2004-2006 Sage Weil + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ +#ifndef __MERKLETREE_H +#define __MERKLETREE_H + +#include +#include +using namespace std; + +#include "crypto/CryptoLib.h" +using namespace CryptoLib; + +struct hash_t{ + byte val[SHA1DIGESTSIZE]; +}; + +// comparison operators +inline bool operator==(const hash_t& a, const hash_t& b) +{ + return (memcmp((void*)&a, (void*)&b, sizeof(hash_t)) == 0); +} +inline bool operator>(const hash_t& a, const hash_t& b) +{ + return (memcmp((void*)&a, (void*)&b, sizeof(hash_t)) > 0); +} +inline bool operator<(const hash_t& a, const hash_t& b) +{ + return (memcmp((void*)&a, (void*)&b, sizeof(hash_t)) < 0); +} +// ostream +inline std::ostream& operator<<(std::ostream& out, const hash_t& c) +{ + byte hexArray[SHA1DIGESTSIZE]; + memset(hexArray, 0x00, sizeof(hexArray)); + toHex(c.val, hexArray, SHA1DIGESTSIZE, SHA1DIGESTSIZE); + out << string((const char*)hexArray); + return out; +} + +class MerkleTree { + private: + // the root hash of the tree + hash_t root_hash; + + public: + // default constructor + MerkleTree () { memset(&root_hash, 0x00, sizeof(root_hash)); } + + // constructor from an initial list of users + MerkleTree (list< uid_t >& input) { + memset(&root_hash, 0x00, sizeof(root_hash)); + uid_t uidArray[input.size()]; + int counter = 0; + + // FIXME just do a linear hash first for root hash + // copy list into buffer + for (list::iterator li = input.begin(); + li != input.end(); + li++) { + uidArray[counter] = *li; + counter++; + } + // zero the array + sha1((byte*)uidArray, (byte*)&root_hash, sizeof(uidArray)); + } + + void add_user(uid_t user) { + // hash the user + hash_t user_hash; + sha1((byte*)&user, (byte*)&user_hash, sizeof(user)); + // join the user and root_hash + hash_t conjunction[2]; + conjunction[0] = root_hash; + conjunction[1] = user_hash; + // hash em both + sha1((byte*)&conjunction, (byte*)&root_hash, sizeof(conjunction)); + } + + hash_t& get_root_hash() { return root_hash; } +}; + +// ostream +inline std::ostream& operator<<(std::ostream& out, MerkleTree& c) +{ + return out << c.get_root_hash(); +} + +#endif diff --git a/branches/aleung/security1/ceph/crypto/driver.cc b/branches/aleung/security1/ceph/crypto/driver.cc index d940dd79a2a80..a13222d7e83a3 100644 --- a/branches/aleung/security1/ceph/crypto/driver.cc +++ b/branches/aleung/security1/ceph/crypto/driver.cc @@ -13,6 +13,7 @@ * Author: Andrew Leung Nov., 2006 ******************************/ #include"CryptoLib.h" +#include "MerkleTree.h" #include using namespace std; @@ -22,6 +23,20 @@ int main(int argc, char* argv[]) { // message to hash const byte* msg = (const byte*)"hash me"; + // test merkle trees + MerkleTree mtree; + uid_t user1 = 1000; + mtree.add_user(user1); + cout << "My root hash: " << mtree << endl; + MerkleTree mtree2 = mtree; + uid_t user2 = 2000; + mtree2.add_user(user2); + cout << "My update root hash " << mtree2 << endl; + if (mtree2.get_root_hash() > mtree.get_root_hash()) + cout << "mtree2 is bigger" << endl; + else + cout << "mtree is bigger" << endl; + // sha-1 byte digest[SHA1DIGESTSIZE]; byte digestHex[2*SHA1DIGESTSIZE]; diff --git a/branches/aleung/security1/ceph/mds/Locker.cc b/branches/aleung/security1/ceph/mds/Locker.cc index dd51a2f1300d5..dec9f918f7358 100644 --- a/branches/aleung/security1/ceph/mds/Locker.cc +++ b/branches/aleung/security1/ceph/mds/Locker.cc @@ -222,11 +222,12 @@ Capability* Locker::issue_new_caps(CInode *in, * This function does nothing for synchronization **********/ ExtCap* Locker::issue_new_extcaps(CInode *in, int mode, MClientRequest *req) { - dout(3) << "issue_new_EXTcaps for mode " << mode << " on " << *in << endl; + dout(3) << "issue_new_extcaps for mode " << mode << " on " << *in << endl; // get the uid uid_t my_user = req->get_caller_uid(); gid_t my_group = req->get_caller_gid(); + gid_t file_group = req->get_gid(); int my_want = 0; // issue most generic cap (RW) my_want |= FILE_MODE_RW; @@ -238,16 +239,16 @@ ExtCap* Locker::issue_new_extcaps(CInode *in, int mode, MClientRequest *req) { // make new cap // unix grouping if (g_conf.mds_group == 1) { - ext_cap = new ExtCap(my_want, my_user, my_group, in->ino()); - // configure group if (mds->unix_groups.count(my_group) == 0) mds->unix_groups[my_group].set_gid(my_group); - + // add user to group if not know already if (!(mds->unix_groups[my_group].contains(my_user))) mds->unix_groups[my_group].add_user(my_user); + ext_cap = new ExtCap(my_want, my_user, my_group, in->ino()); + ext_cap->set_type(1); } // default no grouping diff --git a/branches/aleung/security1/ceph/mds/MDS.h b/branches/aleung/security1/ceph/mds/MDS.h index 85d53914aab95..1dd7feb28567a 100644 --- a/branches/aleung/security1/ceph/mds/MDS.h +++ b/branches/aleung/security1/ceph/mds/MDS.h @@ -47,6 +47,7 @@ using namespace CryptoLib; #include "crypto/ExtCap.h" #include "crypto/CapGroup.h" +#include "crypto/MerkleTree.h" #define MDS_PORT_MAIN 0 #define MDS_PORT_SERVER 1 @@ -156,6 +157,7 @@ public: // user groups map unix_groups; + map user_groups; void queue_waitfor_active(Context *c) { waitfor_active.push_back(c); } diff --git a/branches/aleung/security1/ceph/messages/MClientUpdate.h b/branches/aleung/security1/ceph/messages/MClientUpdate.h new file mode 100644 index 0000000000000..919f337f006b5 --- /dev/null +++ b/branches/aleung/security1/ceph/messages/MClientUpdate.h @@ -0,0 +1,50 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2004-2006 Sage Weil + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#ifndef __MCLIENTUPDATE_H +#define __MCLIENTUPDATE_H + +#include "msg/Message.h" +#include "osd/osd_types.h" + +class MClientUpdate : public Message { +private: + struct { + gid_t group; + entity_inst_t asking_client; + } mds_update_st; +public: + MClientUpdate () : Message(MSG_CLIENT_UPDATE) { } + MClientUpdate (gid_t gid) : Message(MSG_CLIENT_UPDATE) { + memset(&mds_update_st, 0, sizeof(mds_update_st)); + this->mds_update_st.group = gid; + } + + gid_t get_group () { return mds_update_st.group; } + + virtual void encode_payload() { + payload.append((char*)&mds_update_st, sizeof(mds_update_st)); + } + virtual void decode_payload() { + int off = 0; + payload.copy(off, sizeof(mds_update_st), (char*)&mds_update_st); + off += sizeof(mds_update_st); + } + virtual char *get_type_name() { return "mds_update"; } + void print(ostream& out) { + out << "mds_update(" << mds_update_st.group + << ")"; + } +}; + +#endif diff --git a/branches/aleung/security1/ceph/messages/MOSDUpdate.h b/branches/aleung/security1/ceph/messages/MOSDUpdate.h new file mode 100644 index 0000000000000..6ba2c0ae35552 --- /dev/null +++ b/branches/aleung/security1/ceph/messages/MOSDUpdate.h @@ -0,0 +1,64 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2004-2006 Sage Weil + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#ifndef __MOSDUPDATE_H +#define __MOSDUPDATE_H + +#include "msg/Message.h" +#include "osd/osd_types.h" + +class MOSDUpdate : public Message { +private: + struct { + gid_t group; + entity_inst_t client; + entity_inst_t asker; + } update_st; +public: + gid_t get_group() { return update_st.group; } + entity_inst_t get_client_inst() { return update_st.client; } + entity_inst_t get_asker() { return update_st.asker; } + + MOSDUpdate () { } + + MOSDUpdate(gid_t upGr) : Message(MSG_OSD_UPDATE) { + memset(&update_st,0, sizeof(update_st)); + this->update_st.group = upGr; + } + + MOSDUpdate(entity_inst_t asking_osd, entity_inst_t target_client, + gid_t upGr) : Message(MSG_OSD_UPDATE) { + memset(&update_st,0, sizeof(update_st)); + this->update_st.group = upGr; + this->update_st.client = target_client; + this->update_st.asker = asking_osd; + } + + virtual void decode_payload() { + int off = 0; + payload.copy(off, sizeof(update_st), (char*)&update_st); + off += sizeof(update_st); + } + virtual void encode_payload() { + payload.append((char*)&update_st, sizeof(update_st)); + } + + virtual char *get_type_name() { return "oop_update"; } + void print(ostream& out) { + out << "osd_update(" << update_st.group + << ")"; + } +}; + +#endif + diff --git a/branches/aleung/security1/ceph/messages/MOSDUpdateReply.h b/branches/aleung/security1/ceph/messages/MOSDUpdateReply.h new file mode 100644 index 0000000000000..29035a57e7a08 --- /dev/null +++ b/branches/aleung/security1/ceph/messages/MOSDUpdateReply.h @@ -0,0 +1,51 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2004-2006 Sage Weil + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#ifndef __MOSDUPDATEREPLY_H +#define __MOSDUPDATEREPLY_H + +#include "msg/Message.h" +#include "osd/osd_types.h" + +class MOSDUpdateReply : public Message { +private: + gid_t group; + list updated_users; +public: + MOSDUpdateReply () : Message(MSG_OSD_UPDATE_REPLY) { } + MOSDUpdateReply(gid_t gid) : Message(MSG_OSD_UPDATE_REPLY), + group(gid) { } + MOSDUpdateReply (gid_t gid, list users) : + Message(MSG_OSD_UPDATE_REPLY), group(gid), updated_users(users) { } + + gid_t get_group() { return group; } + list& get_list() { return updated_users; } + + virtual void encode_payload() { + payload.append((char*)&group, sizeof(group)); + _encode(updated_users, payload); + } + virtual void decode_payload() { + int off = 0; + payload.copy(off, sizeof(group), (char*)&group); + off += sizeof(group); + _decode(updated_users, payload, off); + } + virtual char *get_type_name() { return "oop_update_reply"; } + void print(ostream& out) { + out << "osd_update_reply(" << group + << ")"; + } +}; + +#endif diff --git a/branches/aleung/security1/ceph/msg/Message.cc b/branches/aleung/security1/ceph/msg/Message.cc index 2de00c770bb74..31f65f863fdcb 100644 --- a/branches/aleung/security1/ceph/msg/Message.cc +++ b/branches/aleung/security1/ceph/msg/Message.cc @@ -44,6 +44,7 @@ using namespace std; #include "messages/MOSDPGLog.h" #include "messages/MOSDPGRemove.h" #include "messages/MOSDUpdate.h" +#include "messages/MOSDUpdateReply.h" #include "messages/MClientBoot.h" #include "messages/MClientMount.h" @@ -53,6 +54,7 @@ using namespace std; #include "messages/MClientRequest.h" #include "messages/MClientReply.h" #include "messages/MClientFileCaps.h" +#include "messages/MClientUpdate.h" #include "messages/MMDSGetMap.h" #include "messages/MMDSMap.h" @@ -234,6 +236,9 @@ decode_message(msg_envelope_t& env, bufferlist& payload) case MSG_OSD_UPDATE: m = new MOSDUpdate(); break; + case MSG_OSD_UPDATE_REPLY: + m = new MOSDUpdateReply(); + break; // clients case MSG_CLIENT_BOOT: diff --git a/branches/aleung/security1/ceph/msg/Message.h b/branches/aleung/security1/ceph/msg/Message.h index cf8d14003798d..74bba6d7d01ef 100644 --- a/branches/aleung/security1/ceph/msg/Message.h +++ b/branches/aleung/security1/ceph/msg/Message.h @@ -75,12 +75,14 @@ // osd group update #define MSG_OSD_UPDATE 55 +#define MSG_OSD_UPDATE_REPLY 56 #define MSG_CLIENT_REQUEST 60 #define MSG_CLIENT_REPLY 61 //#define MSG_CLIENT_DONE 62 #define MSG_CLIENT_FILECAPS 63 #define MSG_CLIENT_INODEAUTHUPDATE 64 +#define MSG_CLIENT_UPDATE 65 #define MSG_CLIENT_BOOT 70 #define MSG_CLIENT_MOUNT 71 diff --git a/branches/aleung/security1/ceph/osd/OSD.cc b/branches/aleung/security1/ceph/osd/OSD.cc index 9d56a52d2e7a8..016d5e81210d6 100644 --- a/branches/aleung/security1/ceph/osd/OSD.cc +++ b/branches/aleung/security1/ceph/osd/OSD.cc @@ -377,11 +377,18 @@ bool OSD::check_request(MOSDOp *op, ExtCap *op_capability) { if (op_capability->get_type() == UNIX_GROUP) { // check if user is in group gid_t my_group = op_capability->get_gid(); + + // do we have group cached? if not, update group + // this will block till we have the group!! + if (unix_groups.count(my_group) == 0) { + update_group(op->get_client_inst(), my_group); + } + + // now we should have the group, is the client in it? if (!(unix_groups[my_group].contains(op_capability->get_uid()))) { // do update to get new unix groups cout << "User " << op_capability->get_uid() << " not in group " << my_group << endl; - update_group(op->get_client_inst(), my_group); return false; } } @@ -413,9 +420,51 @@ bool OSD::check_request(MOSDOp *op, ExtCap *op_capability) { void OSD::update_group(entity_inst_t client, gid_t group) { // set up reply MOSDUpdate *update = new MOSDUpdate(group); + Cond cond; + + // if no one has already requested the ticket + if (update_waiter_cond.count(group) == 0) { + dout(10) << "update_group requesting update for gid " << group << endl; + // send it + messenger->send_message(update, client); + } else { + // don't request, someone else already did. just wait! + dout(10) << "update_group waiting for update for gid " << group << endl; + } + + // wait for reply + update_waiter_cond[group].push_back( &cond ); + + // naively assume we'll get an update FIXME + while (unix_groups.count(group) == 0) { + cond.Wait(osd_lock); + //cout << "Received a singal, going to check group " << group << endl; + } + cout << "Received updated group, returning" << endl; + +} - // send it - messenger->send_message(update, client); +// gets reply for group and wakes up waiters +void OSD::handle_osd_update_reply(MOSDUpdateReply *m) { + + // store the new list into group + gid_t my_group = m->get_group(); + + cout << "hande_osd_update_reply for " << my_group << endl; + dout(10) << "hande_osd_update_reply for " << my_group << endl; + + // add the new list to our cache + unix_groups[my_group].set_list(m->get_list()); + + // wait up the waiter(s) + // this signals all update waiters + for (list::iterator p = update_waiter_cond[my_group].begin(); + p != update_waiter_cond[my_group].end(); + ++p) { + (*p)->Signal(); + } + + update_waiter_cond.erase(my_group); } // assumes the request and cap contents has already been checked @@ -777,6 +826,10 @@ void OSD::dispatch(Message *m) case MSG_OSD_OPREPLY: handle_op_reply((MOSDOpReply*)m); break; + // for updating security groups + case MSG_OSD_UPDATE_REPLY: + handle_osd_update_reply((MOSDUpdateReply*)m); + break; default: diff --git a/branches/aleung/security1/ceph/osd/OSD.h b/branches/aleung/security1/ceph/osd/OSD.h index b6199315108d1..e2248abbcfa02 100644 --- a/branches/aleung/security1/ceph/osd/OSD.h +++ b/branches/aleung/security1/ceph/osd/OSD.h @@ -33,11 +33,13 @@ using namespace __gnu_cxx; #include "messages/MOSDOp.h" #include "messages/MOSDUpdate.h" +#include "messages/MOSDUpdateReply.h" #include "crypto/CryptoLib.h" using namespace CryptoLib; #include "crypto/CapCache.h" #include "crypto/CapGroup.h" +#include "crypto/MerkleTree.h" class Messenger; class Message; @@ -113,7 +115,11 @@ public: hash_map peer_qlen; // unix group cache - map unix_groups; + //map unix_groups; + map user_groups; + //map > update_waiter_cond; + map > update_waiter_cond; + void handle_osd_update_reply(MOSDUpdateReply *m); // per-pg locking (serializing) hash_set pg_lock; -- 2.39.5