From f530986d76c4a3c1c5bfbcd075cb3bd471f985de Mon Sep 17 00:00:00 2001 From: anwleung Date: Mon, 5 Mar 2007 17:38:43 +0000 Subject: [PATCH] base of update protocol there git-svn-id: https://ceph.svn.sf.net/svnroot/ceph@1169 29311d96-e01e-0410-9327-a35deaab8ce9 --- .../aleung/security1/ceph/client/Client.cc | 15 ++++ .../aleung/security1/ceph/client/Client.h | 6 +- branches/aleung/security1/ceph/config.cc | 9 +++ branches/aleung/security1/ceph/config.h | 3 + .../aleung/security1/ceph/crypto/CapCache.h | 6 +- .../aleung/security1/ceph/crypto/CapGroup.h | 54 ++++++++++++++ .../aleung/security1/ceph/crypto/ExtCap.h | 29 +++++++- branches/aleung/security1/ceph/mds/Locker.cc | 20 ++++- branches/aleung/security1/ceph/mds/MDS.h | 4 + .../aleung/security1/ceph/messages/MOSDOp.h | 5 ++ branches/aleung/security1/ceph/msg/Message.cc | 4 + branches/aleung/security1/ceph/msg/Message.h | 3 + branches/aleung/security1/ceph/osd/OSD.cc | 73 ++++++++++++++++--- branches/aleung/security1/ceph/osd/OSD.h | 9 ++- .../aleung/security1/ceph/osdc/Objecter.cc | 10 ++- 15 files changed, 225 insertions(+), 25 deletions(-) create mode 100644 branches/aleung/security1/ceph/crypto/CapGroup.h diff --git a/branches/aleung/security1/ceph/client/Client.cc b/branches/aleung/security1/ceph/client/Client.cc index a119bef6f9bb3..2ed2149e5e360 100644 --- a/branches/aleung/security1/ceph/client/Client.cc +++ b/branches/aleung/security1/ceph/client/Client.cc @@ -712,6 +712,15 @@ void Client::put_user_ticket(Ticket *tk) user_ticket_ref.erase(uid); } +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); +} // ------------------------ // incoming messages @@ -729,6 +738,9 @@ void Client::dispatch(Message *m) case MSG_OSD_MAP: objecter->handle_osd_map((class MOSDMap*)m); break; + case MSG_OSD_UPDATE: + handle_osd_update((MOSDUpdate*)m); + break; // client case MSG_MDS_MAP: @@ -753,6 +765,9 @@ void Client::dispatch(Message *m) case MSG_CLIENT_UNMOUNT: handle_unmount_ack(m); break; + // case MSG_OSD_UPDATE: + // + break; default: diff --git a/branches/aleung/security1/ceph/client/Client.h b/branches/aleung/security1/ceph/client/Client.h index b06858fdd74ef..1ddb3bfe1409e 100644 --- a/branches/aleung/security1/ceph/client/Client.h +++ b/branches/aleung/security1/ceph/client/Client.h @@ -27,6 +27,7 @@ #include "messages/MClientRequest.h" #include "messages/MClientReply.h" +#include "messages/MOSDUpdate.h" //#include "msgthread.h" @@ -43,7 +44,7 @@ using namespace CryptoLib; #include "crypto/Ticket.h" -//#include "User.h" +#include "crypto/CapGroup.h" // stl #include @@ -509,12 +510,15 @@ protected: map user_pub_key; map user_priv_key; + map groups; + // user map //map user_identity; Ticket *get_user_ticket(uid_t uid, gid_t gid); void put_user_ticket(Ticket *tk); + void handle_osd_update(MOSDUpdate *m); // friends friend class SyntheticClient; diff --git a/branches/aleung/security1/ceph/config.cc b/branches/aleung/security1/ceph/config.cc index 9f676d8f1024a..a481af1f28c05 100644 --- a/branches/aleung/security1/ceph/config.cc +++ b/branches/aleung/security1/ceph/config.cc @@ -303,6 +303,9 @@ md_config_t g_conf = { //security (all principals) secure_io: true, + mds_group: 0, /* 0=none, 1=unix, 2=batch, 3=def, 4=predict */ + mds_collection: 0, /* 0=none, 1=unix, 3=def */ + client_aux: 0, /* 0=off, 1=on */ sign_scheme: 0, /* 0=esign, 1=RSA */ hash_scheme: 0, /* 0=sha-1, 1=sha-256, 2=sha-512, 3 = md5 */ @@ -775,6 +778,12 @@ void parse_config_options(std::vector& args) // security flag to turn off security else if (strcmp(args[i], "--no_sec") == 0) g_conf.secure_io = false; + else if (strcmp(args[i], "--mds_group") == 0) + g_conf.mds_group = atoi(args[++i]); + else if (strcmp(args[i], "--mds_collection") == 0) + g_conf.mds_collection = atoi(args[++i]); + else if (strcmp(args[i], "--client_aux") == 0) + g_conf.client_aux = atoi(args[++i]); else if (strcmp(args[i], "--file_layout_ssize") == 0) g_OSD_FileLayout.stripe_size = atoi(args[++i]); diff --git a/branches/aleung/security1/ceph/config.h b/branches/aleung/security1/ceph/config.h index 6ab7c4e750837..9ba18aeef317a 100644 --- a/branches/aleung/security1/ceph/config.h +++ b/branches/aleung/security1/ceph/config.h @@ -292,6 +292,9 @@ struct md_config_t { // security (all princiapls) bool secure_io; + int mds_group; + int mds_collection; + int client_aux; int sign_scheme; int hash_scheme; int crypt_scheme; diff --git a/branches/aleung/security1/ceph/crypto/CapCache.h b/branches/aleung/security1/ceph/crypto/CapCache.h index 5eaf48bae0126..ae318ff1ccab3 100644 --- a/branches/aleung/security1/ceph/crypto/CapCache.h +++ b/branches/aleung/security1/ceph/crypto/CapCache.h @@ -13,10 +13,10 @@ #ifndef __CAPCACHE_H #define __CAPCACHE_H -#include -using namespace std; +//#include +//using namespace std; -#include "crypto/ExtCap.h" +//#include "crypto/ExtCap.h" class CapCache { private: diff --git a/branches/aleung/security1/ceph/crypto/CapGroup.h b/branches/aleung/security1/ceph/crypto/CapGroup.h new file mode 100644 index 0000000000000..a5703e168019f --- /dev/null +++ b/branches/aleung/security1/ceph/crypto/CapGroup.h @@ -0,0 +1,54 @@ +// -*- 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 __CAPGROUP_H +#define __CAPGROUP_H + +#include +using namespace std; + +#include "include/types.h" + +class CapGroup { + private: + gid_t group_id; + list users; + + public: + friend class OSD; + friend class Locker; + CapGroup () { } + CapGroup (gid_t id) { group_id = id; } + + gid_t get_gid() { return group_id; } + void set_gid(gid_t id) { group_id = id; } + + void add_user(uid_t user) { + users.push_back(user); + } + void remove_user(uid_t user) { + users.remove(user); + } + + bool contains(uid_t user) { + for (list::iterator ui = users.begin(); + ui != users.end(); + ui++) { + //uid_t test& = *ui; + if (*ui == user) + return true; + } + return false; + } +}; + +#endif diff --git a/branches/aleung/security1/ceph/crypto/ExtCap.h b/branches/aleung/security1/ceph/crypto/ExtCap.h index fadf391286eec..64362ab25f009 100644 --- a/branches/aleung/security1/ceph/crypto/ExtCap.h +++ b/branches/aleung/security1/ceph/crypto/ExtCap.h @@ -24,6 +24,9 @@ using namespace std; #include "crypto/CryptoLib.h" using namespace CryptoLib; +#define NO_GROUP 0 +#define UNIX_GROUP 1 + struct cap_id_t { int cid; int mds_id; @@ -73,16 +76,19 @@ private: utime_t t_s; // creation time utime_t t_e; // expiration time int mode; // I/O mode - __uint8_t comp; // specify users/pubkey (for delegation) - + __uint8_t type; // specify mds policy + + // single user ident uid_t uid; // user id + //unix group idents gid_t gid; // group id + bool world; + inodeno_t ino; // inode number }; cap_data_t data; byte sigArray[ESIGNSIGSIZE]; - //SigBuf signature; public: friend class Client; @@ -107,6 +113,7 @@ public: data.t_e += 3600; data.mode = m; data.uid = u; + data.gid = 0; data.ino = n; } @@ -121,6 +128,19 @@ public: // capability for many named users, too many files // capability for too many users, single file + // --> unix grouping, issue cap to must general mode + ExtCap(int m, uid_t u, gid_t g, inodeno_t n) + { + data.id.cid = 0; + data.id.mds_id = 0; + data.t_s = g_clock.now(); + data.t_e = data.t_s; + data.t_e += 3600; + data.mode = m; + data.uid = u; + data.gid = g; + data.ino = n; + } // capability for too many user, many named files @@ -135,7 +155,7 @@ public: gid_t get_gid() const { return data.gid; } inodeno_t get_ino() const { return data.ino; } int mode() const { return data.mode; } - __int8_t comp() const { return data.comp; } + __int8_t get_type() const { return data.type; } // in case the mode needs to be changed // FYI, you should resign the cap after this @@ -144,6 +164,7 @@ public: data.id.cid = new_id; data.id.mds_id = new_mds_id; } + void set_type(__int8_t new_type) { data.type = new_type;} const cap_data_t* get_data() const { return (&data); diff --git a/branches/aleung/security1/ceph/mds/Locker.cc b/branches/aleung/security1/ceph/mds/Locker.cc index a59e6c017f3ef..dd51a2f1300d5 100644 --- a/branches/aleung/security1/ceph/mds/Locker.cc +++ b/branches/aleung/security1/ceph/mds/Locker.cc @@ -226,6 +226,7 @@ ExtCap* Locker::issue_new_extcaps(CInode *in, int mode, MClientRequest *req) { // get the uid uid_t my_user = req->get_caller_uid(); + gid_t my_group = req->get_caller_gid(); int my_want = 0; // issue most generic cap (RW) my_want |= FILE_MODE_RW; @@ -235,7 +236,24 @@ ExtCap* Locker::issue_new_extcaps(CInode *in, int mode, MClientRequest *req) { if (!ext_cap) { // make new cap - ext_cap = new ExtCap(my_want, my_user, in->ino()); + // 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->set_type(1); + } + // default no grouping + else + ext_cap = new ExtCap(my_want, my_user, in->ino()); + ext_cap->set_id(cap_id_count, mds->get_nodeid()); // increment capability count cap_id_count++; diff --git a/branches/aleung/security1/ceph/mds/MDS.h b/branches/aleung/security1/ceph/mds/MDS.h index 0db713f49e585..85d53914aab95 100644 --- a/branches/aleung/security1/ceph/mds/MDS.h +++ b/branches/aleung/security1/ceph/mds/MDS.h @@ -46,6 +46,7 @@ using namespace __gnu_cxx; using namespace CryptoLib; #include "crypto/ExtCap.h" +#include "crypto/CapGroup.h" #define MDS_PORT_MAIN 0 #define MDS_PORT_SERVER 1 @@ -153,6 +154,9 @@ class MDS : public Dispatcher { public: map peer_mdsmap_epoch; + // user groups + map unix_groups; + void queue_waitfor_active(Context *c) { waitfor_active.push_back(c); } bool is_dne() { return state == MDSMap::STATE_DNE; } diff --git a/branches/aleung/security1/ceph/messages/MOSDOp.h b/branches/aleung/security1/ceph/messages/MOSDOp.h index 8a9d56d863b77..3733784156249 100644 --- a/branches/aleung/security1/ceph/messages/MOSDOp.h +++ b/branches/aleung/security1/ceph/messages/MOSDOp.h @@ -84,6 +84,8 @@ private: // who's asking? entity_inst_t client; reqid_t reqid; // minor weirdness: entity_name_t is in reqid_t too. + + uid_t user; // for replication tid_t rep_tid; @@ -151,6 +153,9 @@ private: const bool wants_ack() { return st.want_ack; } const bool wants_commit() { return st.want_commit; } + uid_t get_user() { return st.user; } + void set_user(uid_t uid) { st.user = uid; } + ExtCap* get_capability() { return &ext_cap; } void set_capability(ExtCap *cap) { ext_cap = (*cap); } diff --git a/branches/aleung/security1/ceph/msg/Message.cc b/branches/aleung/security1/ceph/msg/Message.cc index cb2af2704ecb9..2de00c770bb74 100644 --- a/branches/aleung/security1/ceph/msg/Message.cc +++ b/branches/aleung/security1/ceph/msg/Message.cc @@ -43,6 +43,7 @@ using namespace std; #include "messages/MOSDPGQuery.h" #include "messages/MOSDPGLog.h" #include "messages/MOSDPGRemove.h" +#include "messages/MOSDUpdate.h" #include "messages/MClientBoot.h" #include "messages/MClientMount.h" @@ -230,6 +231,9 @@ decode_message(msg_envelope_t& env, bufferlist& payload) case MSG_OSD_PG_REMOVE: m = new MOSDPGRemove(); break; + case MSG_OSD_UPDATE: + m = new MOSDUpdate(); + 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 f95c3199e427d..cf8d14003798d 100644 --- a/branches/aleung/security1/ceph/msg/Message.h +++ b/branches/aleung/security1/ceph/msg/Message.h @@ -73,6 +73,9 @@ #define MSG_OSD_PG_LOG 53 #define MSG_OSD_PG_REMOVE 54 +// osd group update +#define MSG_OSD_UPDATE 55 + #define MSG_CLIENT_REQUEST 60 #define MSG_CLIENT_REPLY 61 //#define MSG_CLIENT_DONE 62 diff --git a/branches/aleung/security1/ceph/osd/OSD.cc b/branches/aleung/security1/ceph/osd/OSD.cc index 1938fbab8a380..9d56a52d2e7a8 100644 --- a/branches/aleung/security1/ceph/osd/OSD.cc +++ b/branches/aleung/security1/ceph/osd/OSD.cc @@ -371,6 +371,53 @@ int OSD::read_superblock() // security operations +// checks that the access rights in the cap are correct +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(); + 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; + } + } + // check users match + else if (op->get_user() != op_capability->get_uid()) { + cout << "User did in cap did not match request" << endl; + return false; + } + // check mode matches + if (op->get_op() == OSD_OP_WRITE && + op_capability->mode() & FILE_MODE_W == 0) { + cout << "Write mode in cap did not match request" << endl; + return false; + } + if (op->get_op() == OSD_OP_READ && + op_capability->mode() & FILE_MODE_R == 0) { + cout << "Read mode in cap did not match request" << endl; + return false; + } + // check object matches + if (op->get_oid().ino != op_capability->get_ino()) { + cout << "File in cap did not match request" << endl; + return false; + } + return true; +} + +// gets group information from client (will block!) +void OSD::update_group(entity_inst_t client, gid_t group) { + // set up reply + MOSDUpdate *update = new MOSDUpdate(group); + + // send it + messenger->send_message(update, client); +} + // assumes the request and cap contents has already been checked bool OSD::verify_cap(ExtCap *cap) { @@ -2884,15 +2931,14 @@ void OSD::op_read(MOSDOp *op)//, PG *pg) if (op->get_source().is_client()) { ExtCap *op_capability = op->get_capability(); assert(op_capability); + // check accesses are right + if (check_request(op, op_capability)) { + cout << "Access permissions are correct" << endl; + } + else + cout << "Access permissions are incorrect" << endl; assert(verify_cap(op_capability)); - //if (verify_cap(op_capability)) - //cout << "OSD successfully verified a read capability" << endl; - //else - //cout << "OSD failed to verify a read capability" << endl; } - //else - //cout << "Received some read with no cap from " << - //op->get_source().type() << endl; } long r = 0; @@ -3240,14 +3286,17 @@ void OSD::op_modify(MOSDOp *op, PG *pg) // i know, i know...not secure but they should all have caps if (op->get_op() == OSD_OP_WRITE && op->get_source().is_client()) { + ExtCap *op_capability = op->get_capability(); assert(op_capability); + // check accesses are right + if (check_request(op, op_capability)) { + cout << "Access permissions are correct" << endl; + } + else + cout << "Access permissions are incorrect" << endl; + assert(verify_cap(op_capability)); - // have i already verified this cap? - //if (verify_cap(op_capability)) - //cout << "OSD successfully verified a write capability" << endl; - //else - //cout << "OSD failed to verify a write capability" << endl; } //else //cout << "Received some write with no cap from " << diff --git a/branches/aleung/security1/ceph/osd/OSD.h b/branches/aleung/security1/ceph/osd/OSD.h index 678e9767e1190..b6199315108d1 100644 --- a/branches/aleung/security1/ceph/osd/OSD.h +++ b/branches/aleung/security1/ceph/osd/OSD.h @@ -32,10 +32,12 @@ using namespace std; using namespace __gnu_cxx; #include "messages/MOSDOp.h" +#include "messages/MOSDUpdate.h" -#include"crypto/CryptoLib.h" +#include "crypto/CryptoLib.h" using namespace CryptoLib; #include "crypto/CapCache.h" +#include "crypto/CapGroup.h" class Messenger; class Message; @@ -109,6 +111,9 @@ public: int hb_stat_qlen; // cumulative queue length since last hb hash_map peer_qlen; + + // unix group cache + map unix_groups; // per-pg locking (serializing) hash_set pg_lock; @@ -262,6 +267,8 @@ public: int shutdown(); // security ops + bool check_request(class MOSDOp *op, ExtCap *op_capability); + void update_group(entity_inst_t client, gid_t group); bool verify_cap(ExtCap *cap); // messages diff --git a/branches/aleung/security1/ceph/osdc/Objecter.cc b/branches/aleung/security1/ceph/osdc/Objecter.cc index fe505461a7fbf..ea190e57e3fd4 100644 --- a/branches/aleung/security1/ceph/osdc/Objecter.cc +++ b/branches/aleung/security1/ceph/osdc/Objecter.cc @@ -393,8 +393,10 @@ tid_t Objecter::readx_submit(OSDRead *rd, ObjectExtent &ex) // set ext cap // FIXME mds currently is writing without caps...so we let it // all other (client) writes should have cap - if (m->get_client().is_client()) + if (m->get_client().is_client()) { + m->set_user(rd->ext_cap->get_uid()); m->set_capability(rd->ext_cap); + } dout(10) << "readx_submit " << rd << " tid " << last_tid << " oid " << ex.oid << " " << ex.start << "~" << ex.length << " (" << ex.buffer_extents.size() << " buffer fragments)" @@ -664,8 +666,10 @@ tid_t Objecter::modifyx_submit(OSDModify *wr, ObjectExtent &ex, tid_t usetid) // only cap for a write, fix later // FIXME mds does writes through this interface without a cap // we let it for now - if (wr->op == OSD_OP_WRITE && m->get_client().is_client()) - m->set_capability(wr->modify_cap); + if (wr->op == OSD_OP_WRITE && m->get_client().is_client()) { + m->set_user(wr->modify_cap->get_uid()); + m->set_capability(wr->modify_cap); + } if (wr->tid_version.count(tid)) m->set_version(wr->tid_version[tid]); // we're replaying this op! -- 2.39.5