From 2c9ad41ad7c00e7baa1c0624ff9fd5ce95a3a748 Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Tue, 29 Sep 2009 14:08:13 -0700 Subject: [PATCH] auth: authenticate in the x-env protocol --- src/auth/Auth.h | 84 ------------ src/auth/AuthClientHandler.cc | 21 ++- src/auth/AuthProtocol.h | 231 +++++++++++++++++++++------------ src/auth/AuthServiceManager.cc | 33 ++++- src/auth/Crypto.cc | 2 +- src/auth/Crypto.h | 1 + src/auth/KeysServer.cc | 1 + 7 files changed, 194 insertions(+), 179 deletions(-) diff --git a/src/auth/Auth.h b/src/auth/Auth.h index a0c54898345e4..bb2684db7d38f 100644 --- a/src/auth/Auth.h +++ b/src/auth/Auth.h @@ -32,90 +32,6 @@ struct AuthContext { Cond *cond; }; -struct EntityName { - uint32_t entity_type; - string name; - - void encode(bufferlist& bl) const { - ::encode(entity_type, bl); - ::encode(name, bl); - } - void decode(bufferlist::iterator& bl) { - ::decode(entity_type, bl); - ::decode(name, bl); - } - - void to_str(string& str) const { - switch (entity_type) { - case CEPHX_PRINCIPAL_AUTH: - str = "auth"; - break; - case CEPHX_PRINCIPAL_MON: - str = "mon"; - break; - case CEPHX_PRINCIPAL_OSD: - str = "osd"; - break; - case CEPHX_PRINCIPAL_MDS: - str = "mds"; - break; - case CEPHX_PRINCIPAL_CLIENT: - str = "client"; - break; - default: - str = "???"; - break; - } - str.append("."); - str.append(name); - } - string to_str() const { - string s; - to_str(s); - return s; - } - - bool from_str(string& s) { - int pos = s.find('.'); - - if (pos < 0) - return false; - if (pos >= (int)s.size()) - return false; - - string pre = s.substr(0, pos); - const char *pres = pre.c_str(); - - set_type(pres); - - name = s.substr(pos + 1); - - return true; - } - - void set_type(const char *type) { - if (strcmp(type, "auth") == 0) { - entity_type = CEPHX_PRINCIPAL_AUTH; - } else if (strcmp(type, "mon") == 0) { - entity_type = CEPHX_PRINCIPAL_MON; - } else if (strcmp(type, "osd") == 0) { - entity_type = CEPHX_PRINCIPAL_OSD; - } else if (strcmp(type, "mds") == 0) { - entity_type = CEPHX_PRINCIPAL_MDS; - } else { - entity_type = CEPHX_PRINCIPAL_CLIENT; - } - } - void from_type_id(const char *type, const char *id) { - set_type(type); - name = id; - } -}; -WRITE_CLASS_ENCODER(EntityName); - -inline bool operator<(const EntityName& a, const EntityName& b) { - return a.entity_type < b.entity_type || (a.entity_type == b.entity_type && a.name < b.name); -} /* * The ticket (if properly validated) authorizes the principal use * services as described by 'caps' during the specified validity diff --git a/src/auth/AuthClientHandler.cc b/src/auth/AuthClientHandler.cc index 9a3aa2ac28cf3..4f715693bf32d 100644 --- a/src/auth/AuthClientHandler.cc +++ b/src/auth/AuthClientHandler.cc @@ -138,7 +138,10 @@ int AuthClientAuthenticateHandler::generate_authenticate_request(bufferlist& bl) /* initialize */ { CephXEnvRequest1 req; - req.init(); + req.name = client->name; + set<__u32> supported; + supported.insert(CEPH_AUTH_CEPH); + ::encode(supported, bl); ::encode(req, bl); } break; @@ -147,8 +150,20 @@ int AuthClientAuthenticateHandler::generate_authenticate_request(bufferlist& bl) { /* FIXME: init req fields */ CephXEnvRequest2 req; - memset(&req.client_challenge, 0x88, sizeof(req.client_challenge)); - req.key = req.client_challenge ^ server_challenge; + CryptoKey secret; + g_keyring.get_master(secret); + bufferlist key, key_enc; + get_random_bytes((char *)&req.client_challenge, sizeof(req.client_challenge)); + ::encode(server_challenge, key); + ::encode(req.client_challenge, key); + int ret = encode_encrypt(key, secret, key_enc); + if (ret < 0) + return ret; + req.key = 0; + const uint64_t *p = (const uint64_t *)key_enc.c_str(); + for (int pos = 0; pos + sizeof(req.key) <= key_enc.length(); pos+=sizeof(req.key), p++) { + req.key ^= *p; + } req.piggyback = 1; ::encode(req, bl); request_state++; diff --git a/src/auth/AuthProtocol.h b/src/auth/AuthProtocol.h index efebb7e52b213..f680e77377d7c 100644 --- a/src/auth/AuthProtocol.h +++ b/src/auth/AuthProtocol.h @@ -23,92 +23,6 @@ using namespace std; #include "config.h" -class Monitor; - -struct CephXPremable { - uint32_t trans_id; - - void encode(bufferlist& bl) const { - ::encode(trans_id, bl); - } - - void decode(bufferlist::iterator& bl) { - ::decode(trans_id, bl); - } -}; -WRITE_CLASS_ENCODER(CephXPremable) - -/* - Ceph X-Envelope protocol -*/ -struct CephXEnvRequest1 { - map auth_types; - - void encode(bufferlist& bl) const { - uint32_t num_auth = auth_types.size(); - ::encode(num_auth, bl); - - map::const_iterator iter = auth_types.begin(); - - for (iter = auth_types.begin(); iter != auth_types.end(); ++iter) { - uint32_t auth_type = iter->first; - ::encode(auth_type, bl); - } - } - void decode(bufferlist::iterator& bl) { - uint32_t num_auth; - ::decode(num_auth, bl); - - auth_types.clear(); - - for (uint32_t i=0; i= (int)s.size()) + return false; + + string pre = s.substr(0, pos); + const char *pres = pre.c_str(); + + set_type(pres); + + name = s.substr(pos + 1); + + return true; + } + + void set_type(const char *type) { + if (strcmp(type, "auth") == 0) { + entity_type = CEPHX_PRINCIPAL_AUTH; + } else if (strcmp(type, "mon") == 0) { + entity_type = CEPHX_PRINCIPAL_MON; + } else if (strcmp(type, "osd") == 0) { + entity_type = CEPHX_PRINCIPAL_OSD; + } else if (strcmp(type, "mds") == 0) { + entity_type = CEPHX_PRINCIPAL_MDS; + } else { + entity_type = CEPHX_PRINCIPAL_CLIENT; + } + } + void from_type_id(const char *type, const char *id) { + set_type(type); + name = id; + } +}; +WRITE_CLASS_ENCODER(EntityName); + +inline bool operator<(const EntityName& a, const EntityName& b) { + return (a.entity_type < b.entity_type) || (a.entity_type == b.entity_type && a.name < b.name); +} + +struct CephXPremable { + uint32_t trans_id; + + void encode(bufferlist& bl) const { + ::encode(trans_id, bl); + } + + void decode(bufferlist::iterator& bl) { + ::decode(trans_id, bl); + } +}; +WRITE_CLASS_ENCODER(CephXPremable) + +/* + Ceph X-Envelope protocol +*/ +struct CephXEnvRequest1 { + EntityName name; + + void encode(bufferlist& bl) const { + ::encode(name, bl); + } + void decode(bufferlist::iterator& bl) { + ::decode(name, bl); + } +}; +WRITE_CLASS_ENCODER(CephXEnvRequest1) + +struct CephXEnvResponse1 { + uint64_t server_challenge; + + void encode(bufferlist& bl) const { + ::encode(server_challenge, bl); + } + void decode(bufferlist::iterator& bl) { + ::decode(server_challenge, bl); + } +}; +WRITE_CLASS_ENCODER(CephXEnvResponse1); + +struct CephXEnvRequest2 { + uint64_t client_challenge; + uint64_t key; + char piggyback; /* do we piggyback X protocol */ + + void encode(bufferlist& bl) const { + ::encode(client_challenge, bl); + ::encode(key, bl); + ::encode(piggyback, bl); + } + void decode(bufferlist::iterator& bl) { + ::decode(client_challenge, bl); + ::decode(key, bl); + ::decode(piggyback, bl); + } +}; +WRITE_CLASS_ENCODER(CephXEnvRequest2); + struct CephXRequestHeader { uint16_t request_type; diff --git a/src/auth/AuthServiceManager.cc b/src/auth/AuthServiceManager.cc index 245282ec3de6d..a626c66a3c4da 100644 --- a/src/auth/AuthServiceManager.cc +++ b/src/auth/AuthServiceManager.cc @@ -95,6 +95,7 @@ static CephAuthServer auth_server; class CephAuthService_X : public AuthServiceHandler { int state; uint64_t server_challenge; + EntityName entity_name; public: CephAuthService_X(Monitor *m) : AuthServiceHandler(m), state(0) {} @@ -117,8 +118,11 @@ int CephAuthService_X::handle_request(bufferlist::iterator& indata, bufferlist& switch(state) { case 0: { + CephXEnvRequest1 req; + ::decode(req, indata); + entity_name = req.name; CephXEnvResponse1 response; - server_challenge = 0x1234ffff; + get_random_bytes((char *)&server_challenge, sizeof(server_challenge)); response.server_challenge = server_challenge; ::encode(response, result_bl); ret = -EAGAIN; @@ -128,17 +132,36 @@ int CephAuthService_X::handle_request(bufferlist::iterator& indata, bufferlist& { CephXEnvRequest2 req; ::decode(req, indata); - uint64_t expected_key = (server_challenge ^ req.client_challenge); /* FIXME: obviously not */ + + CryptoKey secret; + map caps; + dout(0) << "entity_name=" << entity_name.to_str() << dendl; + if (!mon->keys_server.get_secret(entity_name, secret, caps)) { + ret = -EPERM; + break; + } + + bufferlist key, key_enc; + ::encode(server_challenge, key); + ::encode(req.client_challenge, key); + ret = encode_encrypt(key, secret, key_enc); + if (ret < 0) + break; + uint64_t expected_key = 0; + const uint64_t *p = (const uint64_t *)key_enc.c_str(); + for (int pos = 0; pos + sizeof(req.key) <= key_enc.length(); pos+=sizeof(req.key), p++) { + expected_key ^= *p; + } + dout(0) << "checking key: req.key=" << hex << req.key << " expected_key=" << expected_key << dec << dendl; if (req.key != expected_key) { dout(0) << "unexpected key: req.key=" << req.key << " expected_key=" << expected_key << dendl; ret = -EPERM; } else { ret = 0; + piggyback = req.piggyback; } - - piggyback = req.piggyback; - break; } + break; case 2: return handle_cephx_protocol(indata, result_bl); diff --git a/src/auth/Crypto.cc b/src/auth/Crypto.cc index 03d0ab201f2ca..36cea8c94eb9a 100644 --- a/src/auth/Crypto.cc +++ b/src/auth/Crypto.cc @@ -21,7 +21,7 @@ #include -static int get_random_bytes(char *buf, int len) +int get_random_bytes(char *buf, int len) { char *t = buf; int fd = ::open("/dev/urandom", O_RDONLY); diff --git a/src/auth/Crypto.h b/src/auth/Crypto.h index 74596ce803151..2cc6d6fef969a 100644 --- a/src/auth/Crypto.h +++ b/src/auth/Crypto.h @@ -75,6 +75,7 @@ public: extern CryptoManager ceph_crypto_mgr; +extern int get_random_bytes(char *buf, int len); extern void generate_random_string(string& s, int len); diff --git a/src/auth/KeysServer.cc b/src/auth/KeysServer.cc index 2b53f7143c061..4e98f4a286f14 100644 --- a/src/auth/KeysServer.cc +++ b/src/auth/KeysServer.cc @@ -70,6 +70,7 @@ bool KeysServerData::get_secret(EntityName& name, CryptoKey& secret, mapsecond; + return true; } -- 2.39.5