From f82e57cfaa3fbf5870282886f85856e1b214c2e2 Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Tue, 15 Sep 2009 12:49:52 -0700 Subject: [PATCH] auth: comprehensive overhaul (not working yet) --- src/auth/Auth.cc | 6 +- src/auth/Auth.h | 8 +- src/auth/AuthClientHandler.cc | 230 +++++++++++++++++++++------------- src/auth/AuthClientHandler.h | 168 ++++++++++++++++--------- src/auth/AuthProtocol.h | 14 +++ src/mon/MonClient.cc | 2 +- 6 files changed, 270 insertions(+), 158 deletions(-) diff --git a/src/auth/Auth.cc b/src/auth/Auth.cc index 41ceba56fe8e3..f6e95eba82441 100644 --- a/src/auth/Auth.cc +++ b/src/auth/Auth.cc @@ -182,7 +182,7 @@ bool AuthTicketsManager::verify_service_ticket_reply(CryptoKey& secret, * * ticket, {timestamp, nonce}^session_key */ -bool AuthTicketHandler::build_authorizer(bufferlist& bl, AuthorizeContext& ctx) +bool AuthTicketHandler::build_authorizer(bufferlist& bl, AuthContext& ctx) { ctx.timestamp = g_clock.now(); @@ -202,7 +202,7 @@ bool AuthTicketHandler::build_authorizer(bufferlist& bl, AuthorizeContext& ctx) * * ticket, {timestamp, nonce}^session_key */ -bool AuthTicketsManager::build_authorizer(uint32_t service_id, bufferlist& bl, AuthorizeContext& ctx) +bool AuthTicketsManager::build_authorizer(uint32_t service_id, bufferlist& bl, AuthContext& ctx) { map::iterator iter = tickets_map.find(service_id); if (iter == tickets_map.end()) @@ -257,7 +257,7 @@ bool AuthTicketHandler::decode_reply_authorizer(bufferlist::iterator& indata, Au /* * PRINCIPAL: verify reply is authentic */ -bool AuthTicketHandler::verify_reply_authorizer(AuthorizeContext& ctx, AuthAuthorizeReply& reply) +bool AuthTicketHandler::verify_reply_authorizer(AuthContext& ctx, AuthAuthorizeReply& reply) { if (ctx.timestamp == reply.timestamp) { return true; diff --git a/src/auth/Auth.h b/src/auth/Auth.h index 54a6adedc238f..7aaf9a77f2b29 100644 --- a/src/auth/Auth.h +++ b/src/auth/Auth.h @@ -20,7 +20,7 @@ class Cond; -struct AuthorizeContext { +struct AuthContext { int status; int id; utime_t timestamp; @@ -168,9 +168,9 @@ struct AuthTicketHandler { bool get_session_keys(uint32_t keys, entity_addr_t& principal_addr, bufferlist& bl); #endif // to access the service - bool build_authorizer(bufferlist& bl, AuthorizeContext& ctx); + bool build_authorizer(bufferlist& bl, AuthContext& ctx); bool decode_reply_authorizer(bufferlist::iterator& indata, AuthAuthorizeReply& reply); - bool verify_reply_authorizer(AuthorizeContext& ctx, AuthAuthorizeReply& reply); + bool verify_reply_authorizer(AuthContext& ctx, AuthAuthorizeReply& reply); bool has_key() { return has_key_flag; } }; @@ -184,7 +184,7 @@ struct AuthTicketsManager { bool get_session_keys(uint32_t keys, entity_addr_t& principal_addr, bufferlist& bl); AuthTicketHandler& get_handler(uint32_t type) { return tickets_map[type]; } - bool build_authorizer(uint32_t service_id, bufferlist& bl, AuthorizeContext& context); + bool build_authorizer(uint32_t service_id, bufferlist& bl, AuthContext& context); }; struct AuthServiceTicketRequest { diff --git a/src/auth/AuthClientHandler.cc b/src/auth/AuthClientHandler.cc index fa56926d8ff3a..829960e12cac8 100644 --- a/src/auth/AuthClientHandler.cc +++ b/src/auth/AuthClientHandler.cc @@ -21,7 +21,7 @@ #include "messages/MAuth.h" #include "messages/MAuthReply.h" -int AuthClientHandler::generate_authenticate_request(bufferlist& bl) +int AuthClientAuthenticateHandler::generate_authenticate_request(bufferlist& bl) { dout(0) << "status=" << status << dendl; if (status < 0) { @@ -62,33 +62,44 @@ int AuthClientHandler::generate_authenticate_request(bufferlist& bl) return 0; } +AuthClientProtocolHandler *AuthClientHandler::_get_proto_handler(uint32_t id) +{ + map::iterator iter = handlers_map.find(id); + if (iter == handlers_map.end()) + return NULL; + + return iter->second; +} + +uint32_t AuthClientHandler::_add_proto_handler(AuthClientProtocolHandler *handler) +{ + uint32_t id = max_proto_handlers++; + handlers_map[id] = handler; + return id; +} + int AuthClientHandler::handle_response(Message *response) { bufferlist bl; int ret; -#if 0 - char buf[4096]; - const char *s = bl.c_str(); - int pos = 0; - for (unsigned int i=0; iname, client->addr, CEPHX_PRINCIPAL_AUTH, false, key, blob, bl); cephx_request_state = 1; return 0; @@ -152,32 +163,41 @@ int AuthClientHandler::generate_cephx_authenticate_request(bufferlist& bl) header.request_type = CEPHX_GET_PRINCIPAL_SESSION_KEY; ::encode(header, bl); - build_service_ticket_request(name, addr, want, + build_service_ticket_request(client->name, client->addr, want, true, ticket_handler.session_key, ticket_handler.ticket, bl); return 0; } -int AuthClientHandler::generate_cephx_authorize_request(uint32_t service_id, bufferlist& bl, AuthorizeContext& ctx) +int AuthClientAuthorizeHandler::_build_request() { CephXRequestHeader header; - if (!(have & service_id)) { + if (!(client->have & service_id)) { dout(0) << "can't authorize: missing service key" << dendl; return -EPERM; } header.request_type = CEPHX_OPEN_SESSION; + bufferlist& bl = msg->get_auth_payload(); + ::encode(header, bl); - //AuthorizeContext& ctx = context_map.create(); utime_t now; - if (!tickets.build_authorizer(service_id, bl, ctx)) +#if 0 + if (!client->tickets.build_authorizer(service_id, bl, ctx)) return -EINVAL; - +#endif return 0; } -int AuthClientHandler::handle_cephx_response(bufferlist::iterator& indata) +int AuthClientAuthorizeHandler::_handle_response(int ret, bufferlist::iterator& iter) +{ + /* FIXME: implement */ + + return 0; +} + +int AuthClientAuthenticateHandler::handle_cephx_response(bufferlist::iterator& indata) { int ret = 0; struct CephXResponseHeader header; @@ -194,10 +214,10 @@ int AuthClientHandler::handle_cephx_response(bufferlist::iterator& indata) #define PRINCIPAL_SECRET "123456789ABCDEF0" { bufferptr p(PRINCIPAL_SECRET, sizeof(PRINCIPAL_SECRET) - 1); - secret.set_secret(CEPH_SECRET_AES, p); + client->secret.set_secret(CEPH_SECRET_AES, p); // AuthTicketHandler& ticket_handler = tickets.get_handler(CEPHX_PRINCIPAL_AUTH); - if (!tickets.verify_service_ticket_reply(secret, indata)) { + if (!client->tickets.verify_service_ticket_reply(client->secret, indata)) { dout(0) << "could not verify service_ticket reply" << dendl; return -EPERM; } @@ -211,9 +231,9 @@ int AuthClientHandler::handle_cephx_response(bufferlist::iterator& indata) cephx_response_state = 2; dout(0) << "CEPHX_GET_PRINCIPAL_SESSION_KEY" << dendl; { - AuthTicketHandler& ticket_handler = tickets.get_handler(CEPHX_PRINCIPAL_AUTH); + AuthTicketHandler& ticket_handler = client->tickets.get_handler(CEPHX_PRINCIPAL_AUTH); - if (!tickets.verify_service_ticket_reply(ticket_handler.session_key, indata)) { + if (!client->tickets.verify_service_ticket_reply(ticket_handler.session_key, indata)) { dout(0) << "could not verify service_ticket reply" << dendl; return -EPERM; } @@ -223,13 +243,13 @@ int AuthClientHandler::handle_cephx_response(bufferlist::iterator& indata) case CEPHX_OPEN_SESSION: { - AuthTicketHandler& ticket_handler = tickets.get_handler(CEPHX_PRINCIPAL_AUTH); + AuthTicketHandler& ticket_handler = client->tickets.get_handler(CEPHX_PRINCIPAL_AUTH); AuthAuthorizeReply reply; if (!ticket_handler.decode_reply_authorizer(indata, reply)) { ret = -EINVAL; break; } - AuthorizeContext *ctx = context_map.get(reply.trans_id); + AuthContext *ctx = client->context_map.get(reply.trans_id); if (!ctx) { ret = -EINVAL; break; @@ -254,8 +274,8 @@ int AuthClientHandler::handle_cephx_response(bufferlist::iterator& indata) return ret; } -bool AuthClientHandler::request_pending() { - dout(0) << "request_pending(): cephx_request_state=" << cephx_request_state << " cephx_response_state=" << cephx_response_state << dendl; +bool AuthClientAuthenticateHandler::request_pending() { + dout(0) << "request_pending(): request_state=" << cephx_request_state << " cephx_response_state=" << cephx_response_state << dendl; return (request_state != response_state) || (cephx_request_state != cephx_response_state); } @@ -267,40 +287,68 @@ int AuthClientHandler::start_session(AuthClient *client, double timeout) Mutex::Locker l(lock); this->client = client; dout(10) << "start_session" << dendl; - _reset(); + + AuthClientAuthenticateHandler handler(this, want, have); + + int err; do { - status = 0; - int err = _do_authenticate_request(timeout); - dout(0) << "_do_authenticate_request returned " << err << dendl; + err = handler.build_request(); + if (err < 0) + return err; + + err = handler.do_request(timeout); + dout(0) << "handler.do_request returned " << err << dendl; if (err < 0) return err; - } while (status == -EAGAIN); + } while (err == -EAGAIN); - return status; + return err; } -int AuthClientHandler::authorize(uint32_t service_id, double timeout) +AuthClientProtocolHandler::AuthClientProtocolHandler(AuthClientHandler *client) : + msg(NULL), got_response(false), got_timeout(false), + timeout_event(NULL) +{ + this->client = client; + reset(); + id = client->_add_proto_handler(this); +} + +AuthClientProtocolHandler::~AuthClientProtocolHandler() +{ + if (msg) + delete msg; +} + +int AuthClientProtocolHandler::build_request() { - MAuth *msg = new MAuth; + msg = new MAuth; if (!msg) - return NULL; + return -ENOMEM; + bufferlist& bl = msg->get_auth_payload(); + CephXPremable pre; + pre.trans_id = id; + ::encode(pre, bl); - AuthorizeContext& ctx = context_map.create(); + int ret = _build_request(); - int err = generate_cephx_authorize_request(service_id, bl, ctx); - if (err < 0) { - context_map.remove(ctx.id); - } + return ret; +} + +int AuthClientHandler::authorize(uint32_t service_id, double timeout) +{ + AuthClientAuthorizeHandler handler(this, service_id); - Cond cond; + int ret = handler.build_request(); + if (ret < 0) + return ret; - ctx.cond = &cond; - err = _do_request_generic(timeout, msg, cond); + ret = handler.do_request(timeout); - return err; + return ret; } void AuthClientHandler::tick() @@ -312,83 +360,84 @@ void AuthClientHandler::tick() } -Message *AuthClientHandler::build_authenticate_request() +int AuthClientAuthenticateHandler::_build_request() { - MAuth *msg = new MAuth; + msg = new MAuth; if (!msg) - return NULL; + return -ENOMEM; + bufferlist& bl = msg->get_auth_payload(); - if (generate_authenticate_request(bl) < 0) { + int ret = generate_authenticate_request(bl); + if (ret < 0) { delete msg; - return NULL; } - return msg; + return ret; } -int AuthClientHandler::_do_authenticate_request(double timeout) +#if 0 +int AuthClientAuthenticateHandler::_do_request() { Message *msg = build_authenticate_request(); if (!msg) return -EIO; - Cond request_cond; - cur_request_cond = &request_cond; - got_authenticate_response = false; - - int ret = _do_request_generic(timeout, msg, request_cond); - - cur_request_cond = NULL; + int ret = _do_request_generic(timeout, msg); return ret; } +#endif -int AuthClientHandler::_do_request_generic(double timeout, Message *msg, Cond& request_cond) +int AuthClientProtocolHandler::do_request(double timeout) { - client->send_message(msg); + got_response = false; + client->client->send_message(msg); // schedule timeout? assert(timeout_event == 0); timeout_event = new C_OpTimeout(this, timeout); - timer.add_event_after(timeout, timeout_event); + client->timer.add_event_after(timeout, timeout_event); - dout(0) << "got_authenticate_response=" << got_authenticate_response << " got_timeout=" << got_authenticate_timeout << dendl; + dout(0) << "got_response=" << got_response << " got_timeout=" << got_timeout << dendl; - request_cond.Wait(lock); + cond.Wait(client->lock); // finish. - timer.cancel_event(timeout_event); + client->timer.cancel_event(timeout_event); timeout_event = NULL; return 0; } -void AuthClientHandler::_authenticate_request_timeout(double timeout) +void AuthClientProtocolHandler::_request_timeout(double timeout) { - Mutex::Locker l(lock); - dout(10) << "_op_timeout" << dendl; + Mutex::Locker l(client->lock); + dout(10) << "_request_timeout" << dendl; timeout_event = 0; - if (!got_authenticate_response) { - got_authenticate_timeout = 1; - assert(cur_request_cond); - cur_request_cond->Signal(); + if (!got_response) { + got_timeout = 1; + cond.Signal(); } status = -ETIMEDOUT; } -void AuthClientHandler::handle_auth_reply(MAuthReply *m) +int AuthClientProtocolHandler::handle_response(int ret, bufferlist::iterator& iter) { - Mutex::Locker l(lock); + Mutex::Locker l(client->lock); - status = handle_response(m); - cur_request_cond->Signal(); + got_response = true; + + status = _handle_response(ret, iter); + cond.Signal(); + + return status; } -AuthorizeContext& AuthorizeContextMap::create() +AuthContext& AuthContextMap::create() { Mutex::Locker l(lock); - AuthorizeContext& ctx = m[max_id]; + AuthContext& ctx = m[max_id]; ctx.id = max_id; ctx.cond = NULL; ++max_id; @@ -396,18 +445,19 @@ AuthorizeContext& AuthorizeContextMap::create() return ctx; } -void AuthorizeContextMap::remove(int id) +void AuthContextMap::remove(int id) { - std::map::iterator iter = m.find(id); + Mutex::Locker l(lock); + std::map::iterator iter = m.find(id); if (iter != m.end()) { m.erase(iter); } } -AuthorizeContext *AuthorizeContextMap::get(int id) +AuthContext *AuthContextMap::get(int id) { Mutex::Locker l(lock); - std::map::iterator iter = m.find(id); + std::map::iterator iter = m.find(id); if (iter != m.end()) return &iter->second; diff --git a/src/auth/AuthClientHandler.h b/src/auth/AuthClientHandler.h index 57c1931cc2302..5ee3ed72818b6 100644 --- a/src/auth/AuthClientHandler.h +++ b/src/auth/AuthClientHandler.h @@ -24,109 +24,156 @@ #include "common/Timer.h" +class MAuth; class MAuthReply; class Message; class AuthClient; -class AuthorizeContextMap { - map m; +class AuthContextMap { + map m; Mutex lock; int max_id; public: - AuthorizeContextMap() : lock("AuthorizeMap") {} - AuthorizeContext& create(); + AuthContextMap() : lock("AuthorizeMap") {} + AuthContext& create(); void remove(int id); - AuthorizeContext *get(int id); + AuthContext *get(int id); }; -class AuthClientHandler { - Mutex lock; - Cond keys_cond; - Cond *cur_request_cond; - Context *timeout_event; +class AuthClientHandler; - uint32_t want; - uint32_t have; +class AuthClientProtocolHandler { + class C_OpTimeout : public Context { + protected: + AuthClientProtocolHandler *client; + double timeout; + public: + C_OpTimeout(AuthClientProtocolHandler *handler, double to) : + client(handler), timeout(to) { + } + void finish(int r) { + if (r >= 0) client->_request_timeout(timeout); + } + }; - // session state - int request_state; - int response_state; +protected: + AuthClientHandler *client; + MAuth *msg; + bool got_response; + bool got_timeout; + Context *timeout_event; + uint32_t id; + // session state int status; - int cephx_request_state; - int cephx_response_state; + virtual void _reset() {} - bool got_authenticate_response; - bool got_authenticate_timeout; + void reset() { + status = 0; + _reset(); + } - EntityName name; - entity_addr_t addr; + Cond cond; - /* envelope protocol parameters */ - uint64_t server_challenge; + virtual int _handle_response(int ret, bufferlist::iterator& iter) = 0; + virtual int _build_request() = 0; - /* ceph-x protocol */ - utime_t auth_ts; - AuthTicketsManager tickets; + void _request_timeout(double timeout); +public: + AuthClientProtocolHandler(AuthClientHandler *ch); + virtual ~AuthClientProtocolHandler(); + int build_request(); - CryptoKey secret; + int handle_response(int ret, bufferlist::iterator& iter); + int do_request(double timeout); +}; - AuthClient *client; +class AuthClientAuthenticateHandler : public AuthClientProtocolHandler { + int request_state; + int response_state; - AuthorizeContextMap context_map; + int cephx_request_state; + int cephx_response_state; - bool request_pending(); - Message *build_authenticate_request(); + /* envelope protocol parameters */ + uint64_t server_challenge; + /* envelope protocol */ int generate_authenticate_request(bufferlist& bl); - int handle_response(Message *response); - - /* cephx requests */ + /* auth protocol */ int generate_cephx_authenticate_request(bufferlist& bl); - int generate_cephx_authorize_request(uint32_t service_id, bufferlist& bl, AuthorizeContext& ctx); - - /* cephx responses */ int handle_cephx_response(bufferlist::iterator& indata); - void _reset() { + uint32_t want; + uint32_t have; + +protected: + void reset() { request_state = 0; response_state = 0; - status = 0; cephx_request_state = 0; cephx_response_state = 0; - got_authenticate_response = false; - got_authenticate_timeout = false; timeout_event = NULL; - cur_request_cond = NULL; } + bool request_pending(); + + int _build_request(); + int _handle_response(int ret, bufferlist::iterator& iter); +public: + AuthClientAuthenticateHandler(AuthClientHandler *client, uint32_t _want, uint32_t _have) : + AuthClientProtocolHandler(client), want(_want), have(_have) {} +}; + +class AuthClientAuthorizeHandler : public AuthClientProtocolHandler { + uint32_t service_id; +protected: + int _build_request(); + int _handle_response(int ret, bufferlist::iterator& iter); +public: + AuthClientAuthorizeHandler(AuthClientHandler *client, uint32_t sid) : AuthClientProtocolHandler(client), service_id(sid) {} +}; + +class AuthClientHandler { + friend class AuthClientProtocolHandler; + + Mutex lock; + Cond keys_cond; + + + /* ceph-x protocol */ + utime_t auth_ts; + + AuthClient *client; + + Message *build_authenticate_request(); + + SafeTimer timer; - class C_OpTimeout : public Context { - protected: - AuthClientHandler *client_handler; - double timeout; - public: - C_OpTimeout(AuthClientHandler *handler, double to) : - client_handler(handler), timeout(to) { - } - void finish(int r) { - if (r >= 0) client_handler->_authenticate_request_timeout(timeout); - } - }; + uint32_t max_proto_handlers; + map handlers_map; + + AuthClientProtocolHandler *_get_proto_handler(uint32_t id); + uint32_t _add_proto_handler(AuthClientProtocolHandler *handler); void _authenticate_request_timeout(double timeout); int _do_authenticate_request(double timeout); - int _do_request_generic(double timeout, Message *msg, Cond& request_cond); - public: + EntityName name; + entity_addr_t addr; + uint32_t want; + uint32_t have; + CryptoKey secret; + + AuthContextMap context_map; + AuthTicketsManager tickets; + AuthClientHandler() : lock("AuthClientHandler::lock"), - want(0), have(0), client(NULL), timer(lock) { - _reset(); - } + client(NULL), timer(lock), max_proto_handlers(0) { } void set_want_keys(__u32 keys) { Mutex::Locker l(lock); @@ -149,9 +196,10 @@ public: return (want & have) == have; } + int handle_response(Message *response); + int start_session(AuthClient *client, double timeout); int authorize(uint32_t service_id, double timeout); - void handle_auth_reply(MAuthReply *m); void tick(); }; diff --git a/src/auth/AuthProtocol.h b/src/auth/AuthProtocol.h index 16df79539b325..4c47ed0b6dbb2 100644 --- a/src/auth/AuthProtocol.h +++ b/src/auth/AuthProtocol.h @@ -25,6 +25,19 @@ using namespace std; 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 */ @@ -190,6 +203,7 @@ WRITE_CLASS_ENCODER(CephXRequestHeader); struct CephXResponseHeader { uint16_t request_type; + uint32_t trans_id; int32_t status; void encode(bufferlist& bl) const { diff --git a/src/mon/MonClient.cc b/src/mon/MonClient.cc index 6569e46f7f386..88bc37b0b7502 100644 --- a/src/mon/MonClient.cc +++ b/src/mon/MonClient.cc @@ -172,7 +172,7 @@ bool MonClient::ms_dispatch(Message *m) return true; case CEPH_MSG_AUTH_REPLY: - auth.handle_auth_reply((MAuthReply*)m); + auth.handle_response((MAuthReply*)m); delete m; return true; -- 2.39.5