]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
auth: better encapsulate cephx protocol
authorSage Weil <sage@newdream.net>
Fri, 23 Oct 2009 18:30:26 +0000 (11:30 -0700)
committerSage Weil <sage@newdream.net>
Fri, 23 Oct 2009 19:01:21 +0000 (12:01 -0700)
So far mostly just the client side is done.

23 files changed:
src/Makefile.am
src/auth/Auth.cc
src/auth/Auth.h
src/auth/AuthClientHandler.cc
src/auth/AuthClientHandler.h
src/auth/AuthProtocol.h [deleted file]
src/auth/AuthServiceHandler.cc
src/auth/AuthServiceHandler.h
src/auth/KeyServer.cc
src/auth/cephx/CephxClientHandler.cc [new file with mode: 0644]
src/auth/cephx/CephxClientHandler.h [new file with mode: 0644]
src/auth/cephx/CephxProtocol.h [new file with mode: 0644]
src/include/ceph_fs.h
src/librados.cc
src/messages/MAuth.h
src/messages/MAuthReply.h
src/messages/MAuthorize.h [deleted file]
src/mon/AuthMonitor.cc
src/mon/MonClient.cc
src/mon/MonClient.h
src/mon/Monitor.cc
src/mon/Monitor.h
src/msg/Message.cc

index 97838dfc61d1727df330ad3fb5b41f8b7a5d405f..fe4ff757482979f268f764d7b98de24a3e77a080 100644 (file)
@@ -294,6 +294,7 @@ libcommon_a_SOURCES = \
 libcommon_files = \
        auth/Auth.cc \
        auth/AuthClientHandler.cc \
+       auth/cephx/CephxClientHandler.cc \
        auth/Crypto.cc \
        auth/ExportControl.cc \
        auth/KeyRing.cc \
@@ -398,8 +399,9 @@ libclient_a_SOURCES = \
 # headers... and everything else we want to include in a 'make dist' 
 # that autotools doesn't magically identify.
 noinst_HEADERS = \
+       auth/cephx/CephxProtocol.h\
+       auth/cephx/CephxClientHandler.h\
        auth/Auth.h\
-       auth/AuthProtocol.h\
        auth/AuthServiceHandler.h\
        auth/KeyRing.h\
        auth/KeyServer.h\
@@ -541,7 +543,6 @@ noinst_HEADERS = \
         mds/mdstypes.h\
         mds/snap.h\
         messages/MAuth.h\
-        messages/MAuthorize.h\
         messages/MAuthReply.h\
         messages/MAuthRotating.h\
        messages/MClass.h\
index 32e0e2d988322b37ee4ee0f8abffe2808ce6304b..49b7b545fd3675786261e482bf3bb9eaded81407 100644 (file)
@@ -65,7 +65,7 @@ bool build_service_ticket_reply(
 
   uint32_t num = ticket_info_vec.size();
   ::encode(num, reply);
-  dout(0) << "encoding " << num << " tickets" << dendl;
+  dout(0) << "encoding " << num << " tickets with secret " << principal_secret << dendl;
 
   while (ticket_iter != ticket_info_vec.end()) {
     SessionAuthInfo& info = *ticket_iter;
@@ -112,8 +112,10 @@ bool AuthTicketHandler::verify_service_ticket_reply(CryptoKey& secret,
   if (s1.length()) {
     hexdump("decoding, using key", s1.c_str(), s1.length());
   }
-  if (decode_decrypt(msg_a, secret, indata) < 0)
+  if (decode_decrypt(msg_a, secret, indata) < 0) {
+    dout(0) << "failed service ticket reply decode with secret " << secret << dendl;
     return false;
+  }
   dout(0) << "decoded message" << dendl;
   ::decode(ticket, indata);
   dout(0) << "decoded ticket secret_id=" << ticket.secret_id << dendl;
@@ -122,7 +124,6 @@ bool AuthTicketHandler::verify_service_ticket_reply(CryptoKey& secret,
   hexdump("decoded ticket.session key", s.c_str(), s.length());
   session_key = msg_a.session_key;
   has_key_flag = true;
-
   return true;
 }
 
index c14a37d8e47b5cb34c123cb4cbfe153adaddbd20..5ea28ae3951b2e013caf841e76ee91fd8c8ee1b9 100644 (file)
 #define __AUTHTYPES_H
 
 #include "Crypto.h"
-#include "AuthProtocol.h"
 #include "msg/msg_types.h"
 
+#include "config.h"
+
 #include <errno.h>
 
 class 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 {
+    str.append(ceph_entity_type_name(entity_type));
+    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;
+   
+    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 = CEPH_ENTITY_TYPE_AUTH;
+    } else if (strcmp(type, "mon") == 0) {
+      entity_type = CEPH_ENTITY_TYPE_MON;
+    } else if (strcmp(type, "osd") == 0) {
+      entity_type = CEPH_ENTITY_TYPE_OSD;
+    } else if (strcmp(type, "mds") == 0) {
+      entity_type = CEPH_ENTITY_TYPE_MDS;
+    } else {
+      entity_type = CEPH_ENTITY_TYPE_CLIENT;
+    }
+  }
+  void from_type_id(const char *type, const char *id) {
+    set_type(type);
+    name = id;
+  }
+
+  void get_type_str(string& s) {
+    s = ceph_entity_type_name(entity_type);
+  }
+};
+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);
+}
+
+static inline ostream& operator<<(ostream& out, const EntityName& n) {
+  return out << n.to_str();
+}
+
+
+
 struct EntityAuth {
   CryptoKey key;
   map<string, bufferlist> caps;
@@ -327,13 +402,17 @@ int decode_decrypt(T& t, CryptoKey key, bufferlist::iterator& iter) {
   ::decode(bl_enc, iter);
 
   int ret = key.decrypt(bl_enc, bl);
-  if (ret < 0)
+  if (ret < 0) {
+    generic_dout(0) << "error from decrypt " << ret << dendl;
     return ret;
+  }
 
   bufferlist::iterator iter2 = bl.begin();
   ::decode(magic, iter2);
-  if (magic != AUTH_ENC_MAGIC)
+  if (magic != AUTH_ENC_MAGIC) {
+    generic_dout(0) << "bad magic in decode_decrypt, " << magic << " != " << AUTH_ENC_MAGIC << dendl;
     return -EPERM;
+  }
 
   ::decode(t, iter2);
 
index bb320d043e881811a638b3b5c2b56459faa6161d..f5fdb37645a20db466c555e438bc5d15cc066041 100644 (file)
 
 #include <errno.h>
 
-#include "AuthProtocol.h"
 #include "AuthClientHandler.h"
 #include "KeyRing.h"
 
 #include "messages/MAuth.h"
-#include "messages/MAuthorize.h"
 #include "messages/MAuthReply.h"
 
+#include "cephx/CephxClientHandler.h"
 
-AuthClientProtocolHandler::AuthClientProtocolHandler(AuthClientHandler *client) : 
-                        msg(NULL), got_response(false), lock("AuthClientProtocolHandler")
+AuthClientProtocolHandler *AuthClientHandler::get_protocol_handler(int proto)
 {
-  dout(0) << "AuthClientProtocolHandler::AuthClientProtocolHandler" << dendl;
-  this->client = client;
-  id = client->_add_proto_handler(this);
-}
-
-AuthClientProtocolHandler::~AuthClientProtocolHandler()
-{
-}
-
-int AuthClientProtocolHandler::build_request()
-{
-  msg = _get_new_msg();
-  if (!msg)
-    return -ENOMEM;
-
-  int ret = _build_request(); 
-
-  return ret;
-}
-
-int AuthClientProtocolHandler::do_async_request()
-{
-  got_response = false;
-  client->client->send_auth_message(msg);
-
-  return 0;
-}
-
-int AuthClientProtocolHandler::handle_response(int ret, bufferlist::iterator& iter)
-{
-  if (!client) {
-    derr(0) << "AuthClientProtocolHandler::handle_response() but client is NULL" << dendl;
-    return -EINVAL;
-  }
-
-  Mutex::Locker l(lock);
-
-  status = _handle_response(ret, iter);
-
-  return status;
-}
-
-int AuthClientAuthenticateHandler::generate_authenticate_request(bufferlist& bl)
-{
-  dout(0) << "request_state=" << request_state << " response_state=" << response_state << dendl;
-  if (request_state != response_state) {
-    dout(0) << "can't generate request while waiting for response" << dendl;
-    return -EINVAL;
-  }
-
-  switch (request_state) {
-  case 0:
-    /* initialize  */
-    { 
-      CephXEnvRequest1 req;
-      req.name = client->name;
-      set<__u32> supported;
-      supported.insert(CEPH_AUTH_CEPHX);
-      ::encode(supported, bl);
-      ::encode(req, bl);
-    }
-    break;
-  case 1:
-    /* authenticate */
-    {
-      /* FIXME: init req fields */
-      CephXEnvRequest2 req;
-      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);
-
-      /* we first need to get the principle/auth session key */
-      CephXRequestHeader header;
-      header.request_type = CEPHX_GET_AUTH_SESSION_KEY;
-      ::encode(header, bl);
-      build_authenticate_request(client->name, bl);
-      request_state = 2;
-      return 0;
-    }
-    break;
-
-  case 2:
-    /* get service tickets */
-    {
-      dout(0) << "want=" << hex << want << " have=" << have << dec << dendl;
-      if (want == have) {
-       response_state = 2;
-       return 0;
-      }
-
-      AuthTicketHandler& ticket_handler = client->tickets.get_handler(CEPH_ENTITY_TYPE_AUTH);
-      if (!ticket_handler.build_authorizer(authorizer))
-       return -EINVAL;
-
-      CephXRequestHeader header;
-      header.request_type = CEPHX_GET_PRINCIPAL_SESSION_KEY;
-      ::encode(header, bl);
-      
-      bl.claim_append(authorizer.bl);
-      build_service_ticket_request(want, bl);
-    }
-    break;
-
+  switch (proto) {
+  case CEPH_AUTH_CEPHX:
+    return new CephxClientHandler(this);
   default:
-    assert(0);
+    return NULL;
   }
-  request_state++;
-  return 0;
 }
 
-int AuthClientAuthenticateHandler::_handle_response(int ret, bufferlist::iterator& indata)
-{
-  if (ret != 0 && ret != -EAGAIN) {
-    response_state = request_state;
-    return ret;
-  }
-
-  dout(0) << "AuthClientHandler::handle_response()" << dendl;
-  switch (response_state) {
-  case 0:
-    /* initialize  */
-    { 
-      CephXEnvResponse1 response;
-
-      response_state++;
-      ::decode(response, indata);
-      server_challenge = response.server_challenge;
-    }
-    break;
-  case 1:
-    /* authenticate */
-    {
-      struct CephXResponseHeader header;
-      ::decode(header, indata);
-
-      dout(0) << "request_type=" << hex << header.request_type << dec << dendl;
-      dout(0) << "handle_cephx_response()" << dendl;
-
-      response_state = 2;
-      dout(0) << "CEPHX_GET_AUTH_SESSION_KEY" << dendl;
-      
-      CryptoKey secret;
-      g_keyring.get_master(secret);
-       
-      if (!client->tickets.verify_service_ticket_reply(secret, indata)) {
-       dout(0) << "could not verify service_ticket reply" << dendl;
-       return -EPERM;
-      }
-      dout(0) << "want=" << want << " have=" << have << dendl;
-      if (want != have)
-        ret = -EAGAIN;
-    }
-    break;
 
-  case 2:
-    {
-      struct CephXResponseHeader header;
-      ::decode(header, indata);
-      response_state = 3;
-      dout(0) << "CEPHX_GET_PRINCIPAL_SESSION_KEY" << dendl;
 
-      AuthTicketHandler& ticket_handler = client->tickets.get_handler(CEPH_ENTITY_TYPE_AUTH);
-  
-      if (!client->tickets.verify_service_ticket_reply(ticket_handler.session_key, indata)) {
-        dout(0) << "could not verify service_ticket reply" << dendl;
-        return -EPERM;
-      }
-      ret = 0;
-    }
-    break;
-
-  default:
-    assert(0);
-  }
-  return ret;
-}
-
-int AuthClientAuthenticateHandler::_build_request()
+int AuthClientHandler::handle_response(MAuthReply *m)
 {
-  MAuth *m = (MAuth *)msg;
-  bufferlist& bl = m->get_auth_payload();
-
-  int ret = generate_authenticate_request(bl);
-
-  return ret;
-}
-
-Message *AuthClientAuthenticateHandler::_get_new_msg()
-{
-  MAuth *m = new MAuth;
-  m->trans_id = id;
-  return m;
-}
-
-bufferlist& AuthClientAuthenticateHandler::_get_msg_bl(Message *m)
-{
-  return ((MAuth *)m)->get_auth_payload();
-}
-
-Message *AuthClientAuthorizeHandler::_get_new_msg()
-{
-  MAuthorize *m = new MAuthorize;
-  m->trans_id = id;
-  return m;
-}
-
-bufferlist& AuthClientAuthorizeHandler::_get_msg_bl(Message *m)
-{
-  return ((MAuthorize *)m)->get_auth_payload();
-}
-
-int AuthClientAuthorizeHandler::_build_request()
-{
-  CephXRequestHeader header;
-  if (!client->tickets.has_key(service_id)) {
-    dout(0) << "can't authorize: missing service key" << dendl;
-    return -EPERM;
-  }
-
-  header.request_type = CEPHX_OPEN_SESSION;
-
-  MAuthorize *m = (MAuthorize *)msg;
-  bufferlist& bl = m->get_auth_payload();
-
-  ::encode(header, bl);
-  utime_t now;
-
-  if (!client->tickets.build_authorizer(service_id, authorizer))
-    return -EINVAL;
-
-  bl.claim_append(authorizer.bl);
-
-  return 0;
-}
-
-int AuthClientAuthorizeHandler::_handle_response(int ret, bufferlist::iterator& iter)
-{
-  struct CephXResponseHeader header;
-  ::decode(header, iter);
-
-  dout(0) << "AuthClientAuthorizeHandler::_handle_response() ret=" << ret << dendl;
-
-  if (ret) {
-    return ret;
-  }
+  int ret = m->result;
 
-  switch (header.request_type & CEPHX_REQUEST_TYPE_MASK) {
-  case CEPHX_OPEN_SESSION:
-    {
-      ret = authorizer.verify_reply(iter);
-      break;
+  if (!proto) {
+    // set up protocol
+    proto = get_protocol_handler(m->protocol);
+    if (!proto) {
+      dout(0) << " server selected " << m->protocol << ", but we don't support it?" << dendl;
+      return -EINVAL;
     }
-    break;
-  default:
-    dout(0) << "header.request_type = " << hex << header.request_type << dec << dendl;
-    ret = -EINVAL;
-    break;
   }
 
-  return ret;
-}
-
-AuthClientProtocolHandler *AuthClientHandler::_get_proto_handler(uint32_t id)
-{
-  map<uint32_t, AuthClientProtocolHandler *>::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(int trans_id, Message *response)
-{
-  MAuthReply* m = (MAuthReply *)response;
-  int ret = m->result;
-
-  lock.Lock();
-  AuthClientProtocolHandler *handler = _get_proto_handler(trans_id);
-  lock.Unlock();
-  dout(0) << "AuthClientHandler::handle_response(): got response " << *response << " trans_id=" << trans_id << " handler=" << handler << dendl;
-  if (!handler)
-    return -EINVAL;
+  dout(0) << "AuthClientHandler::handle_response(): got response " << *m << " handler=" << proto << dendl;
 
   bufferlist::iterator iter = m->result_bl.begin();
-  return handler->handle_response(ret, iter);
+  ret = proto->handle_response(ret, iter);
+  if (ret == -EAGAIN) {
+    ret = send_request();
+    if (ret)
+      return ret;
+    return -EAGAIN;
+  }
+  return ret;
 }
 
-int AuthClientHandler::send_session_request(AuthClient *client, AuthClientProtocolHandler *handler)
+int AuthClientHandler::send_request()
 {
   Mutex::Locker l(lock);
-  this->client = client;
   dout(10) << "send_session_request" << dendl;
 
-  int err = handler->build_request();
+  if (!proto) {
+    set<__u32> supported;
+    supported.insert(CEPH_AUTH_CEPHX);
+    dout(0) << " sending supported protocol list " << supported << dendl;
+    bufferlist bl;
+    ::encode(supported, bl);
+    MAuth *m = new MAuth;
+    m->protocol = 0;
+    m->auth_payload = bl;
+    client->send_auth_message(m);
+    return 0;
+  }
+
+  MAuth *m = new MAuth;
+  m->protocol = proto->get_protocol();
+  int err = proto->build_request(m->auth_payload);
   dout(0) << "handler.build_request returned " << err << dendl;
   if (err < 0)
     return err;
-
-  err = handler->do_async_request();
-  dout(0) << "handler.do_async_request returned " << err << dendl;
-
+  client->send_auth_message(m);
   return err;
 }
 
index daad37c64ec130f04e1833c0fe27b11e904b5651..6aaeb542c09d33840eb092cc89fc87182be361e1 100644 (file)
 
 #include "common/Timer.h"
 
-class Message;
+class MAuthReply;
 class AuthClient;
-
 class AuthClientHandler;
 
 class AuthClientProtocolHandler {
 protected:
-  AuthClientHandler *client;
-  Message *msg;
-  bool got_response;
-  uint32_t id;
-  Mutex lock;
   AuthAuthorizer authorizer;
-
-  // session state
-  int status;
-
-  virtual void _reset() {}
-
-  Cond cond;
-
-  virtual int _handle_response(int ret, bufferlist::iterator& iter) = 0;
-  virtual int _build_request() = 0;
-  virtual Message *_get_new_msg() = 0;
-  virtual bufferlist& _get_msg_bl(Message *m) = 0;
+  AuthClientHandler *client;
 
 public:
-  AuthClientProtocolHandler(AuthClientHandler *ch);
-  virtual ~AuthClientProtocolHandler();
-  int build_request();
+  AuthClientProtocolHandler(AuthClientHandler *c) : client(c) {}
+  virtual ~AuthClientProtocolHandler() {}
 
-  int handle_response(int ret, bufferlist::iterator& iter);
-
-  void reset() {
-    status = 0;
-    _reset();
-  }
+  virtual int get_protocol() = 0;
 
- int do_async_request();
+  virtual void reset() = 0;
+  virtual int build_request(bufferlist& bl) = 0;
+  virtual int handle_response(int ret, bufferlist::iterator& iter) = 0;
 };
 
-class AuthClientAuthenticateHandler : public AuthClientProtocolHandler {
-  int request_state;
-  int response_state;
-
-  /* envelope protocol parameters */
-  uint64_t server_challenge;
-
-  int generate_authenticate_request(bufferlist& bl);
 
-  uint32_t want;
-  uint32_t have;
 
-protected:
-  void _reset() {
-    request_state = 0;
-    response_state = 0;
-  }
-
-  int _build_request();
-  int _handle_response(int ret, bufferlist::iterator& iter);
-  Message *_get_new_msg();
-  bufferlist& _get_msg_bl(Message *m);
-public:
-  AuthClientAuthenticateHandler(AuthClientHandler *client, uint32_t _want, uint32_t _have) :
-             AuthClientProtocolHandler(client), want(_want), have(_have) { reset(); }
-  void set_want_keys(__u32 keys) {
-    want = keys;
-  }
-  void add_want_keys(__u32 keys) {
-    want |= keys;
-  }
-};
-
-class AuthClientAuthorizeHandler : public AuthClientProtocolHandler {
-  uint32_t service_id;
-protected:
-  int _build_request();
-  int _handle_response(int ret, bufferlist::iterator& iter);
-  Message *_get_new_msg();
-  bufferlist& _get_msg_bl(Message *m);
-public:
-  AuthClientAuthorizeHandler(AuthClientHandler *client, uint32_t sid) : AuthClientProtocolHandler(client), service_id(sid) {}
-};
+// ----------------------------------------
 
 class AuthClientHandler {
   friend class AuthClientProtocolHandler;
@@ -115,12 +54,9 @@ class AuthClientHandler {
   Mutex lock;
 
   AuthClient *client;
+  AuthClientProtocolHandler *proto;
 
-  uint32_t max_proto_handlers;
-  map<uint32_t, AuthClientProtocolHandler *> handlers_map;
-
-  AuthClientProtocolHandler *_get_proto_handler(uint32_t id);
-  uint32_t _add_proto_handler(AuthClientProtocolHandler *handler);
+  AuthClientProtocolHandler *get_protocol_handler(int id);
 
 public:
   EntityName name;
@@ -129,14 +65,21 @@ public:
 
   AuthTicketManager tickets;
 
-  AuthClientHandler() : lock("AuthClientHandler::lock"),
-                       client(NULL), max_proto_handlers(0) { }
+  AuthClientHandler(AuthClient *c) : lock("AuthClientHandler::lock"),
+                                    client(c), proto(NULL),
+                                    want(0), have(0) { }
+
   void init(EntityName& n) { name = n; }
   
   void set_want_keys(__u32 keys) {
     Mutex::Locker l(lock);
     want = keys;
   }
+  void add_want_keys(__u32 keys) {
+    Mutex::Locker l(lock);
+    want |= keys;
+  }   
+
   bool have_keys(__u32 k) {
     Mutex::Locker l(lock);
     return (k & have) == have;
@@ -145,9 +88,14 @@ public:
     Mutex::Locker l(lock);
     return (want & have) == have;
   }
-  int handle_response(int trans_id, Message *response);
 
-  int send_session_request(AuthClient *client, AuthClientProtocolHandler *handler);
+  void reset() {
+    if (proto)
+      proto->reset();
+  }
+  int send_request();
+  int handle_response(MAuthReply *m);
+
   void tick();
 
   bool build_authorizer(uint32_t service_id, AuthAuthorizer& authorizer);
diff --git a/src/auth/AuthProtocol.h b/src/auth/AuthProtocol.h
deleted file mode 100644 (file)
index 070cfff..0000000
+++ /dev/null
@@ -1,244 +0,0 @@
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 
-// vim: ts=8 sw=2 smarttab
-/*
- * Ceph - scalable distributed file system
- *
- * Copyright (C) 2004-2009 Sage Weil <sage@newdream.net>
- *
- * 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 __AUTHPROTOCOL_H
-#define __AUTHPROTOCOL_H
-
-#include <map>
-#include <set>
-using namespace std;
-
-#include "include/types.h"
-
-#include "config.h"
-
-/*
-  Ceph X protocol
-
-  First, the principal has to authenticate with the authenticator. A
-  shared-secret mechanism is being used, and the negotitaion goes like this:
-
-  A = Authenticator
-  P = Principle
-  S = Service
-
-  1. Obtaining principal/auth session key
-
-  (Authenticate Request)
-  p->a : principal, principal_addr.  authenticate me!
-
- ...authenticator does lookup in database...
-
-  a->p : A= {principal/auth session key, validity}^principal_secret (*)
-         B= {principal ticket, validity, principal/auth session key}^authsecret
-
-  
-  [principal/auth session key, validity] = service ticket
-  [principal ticket, validity, principal/auth session key] = service ticket info
-
-  (*) annotation: ^ signifies 'encrypted by'
-
-  At this point, if is genuine, the principal should have the principal/auth
-  session key at hand. The next step would be to request an authorization to
-  use some other service:
-
-  2. Obtaining principal/service session key
-
-  p->a : B, {principal_addr, timestamp}^principal/auth session key.  authorize
-         me!
-  a->p : E= {service ticket}^svcsecret
-         F= {principal/service session key, validity}^principal/auth session key
-
-  principal_addr, timestamp = authenticator
-
-  service ticket = principal name, client network address, validity, principal/service session key
-
-  Note that steps 1 and 2 are pretty much the same thing; contacting the
-  authenticator and requesting for a key.
-
-  Following this the principal should have a principal/service session key that
-  could be used later on for creating a session:
-
-  3. Opening a session to a service
-
-  p->s : E + {principal_addr, timestamp}^principal/service session key
-  s->p : {timestamp+1}^principal/service/session key
-
-  timestamp+1 = reply authenticator
-
-  Now, the principal is fully authenticated with the service. So, logically we
-  have 2 main actions here. The first one would be to obtain a session key to
-  the service (steps 1 and 2), and the second one would be to authenticate with
-  the service, using that ticket.
-*/
-
-/* authenticate requests */
-#define CEPHX_GET_AUTH_SESSION_KEY      0x0100
-#define CEPHX_GET_PRINCIPAL_SESSION_KEY 0x0200
-
-/* authorize requests */
-#define CEPHX_OPEN_SESSION              0x0300
-
-#define CEPHX_REQUEST_TYPE_MASK         0x0F00
-
-class Monitor;
-
-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 {
-    str.append(ceph_entity_type_name(entity_type));
-    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;
-   
-    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 = CEPH_ENTITY_TYPE_AUTH;
-    } else if (strcmp(type, "mon") == 0) {
-      entity_type = CEPH_ENTITY_TYPE_MON;
-    } else if (strcmp(type, "osd") == 0) {
-      entity_type = CEPH_ENTITY_TYPE_OSD;
-    } else if (strcmp(type, "mds") == 0) {
-      entity_type = CEPH_ENTITY_TYPE_MDS;
-    } else {
-      entity_type = CEPH_ENTITY_TYPE_CLIENT;
-    }
-  }
-  void from_type_id(const char *type, const char *id) {
-    set_type(type);
-    name = id;
-  }
-
-  void get_type_str(string& s) {
-    s = ceph_entity_type_name(entity_type);
-  }
-};
-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);
-}
-
-static inline ostream& operator<<(ostream& out, const EntityName& n) {
-  return out << n.to_str();
-}
-
-
-/* 
-  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;
-
-  void encode(bufferlist& bl) const {
-    ::encode(request_type, bl);
-  }
-  void decode(bufferlist::iterator& bl) {
-    ::decode(request_type, bl);
-  }
-};
-WRITE_CLASS_ENCODER(CephXRequestHeader);
-
-struct CephXResponseHeader {
-  uint16_t request_type;
-  int32_t status;
-
-  void encode(bufferlist& bl) const {
-    ::encode(request_type, bl);
-    ::encode(status, bl);
-  }
-  void decode(bufferlist::iterator& bl) {
-    ::decode(request_type, bl);
-    ::decode(status, bl);
-  }
-};
-WRITE_CLASS_ENCODER(CephXResponseHeader);
-
-
-#endif
index 735bca2a8b02f7bace1b796210b623de250c5d91..94d10171a697ecaf678b962e1cd1ea5ff3c4f11f 100644 (file)
@@ -14,7 +14,7 @@
 
 
 #include "AuthServiceHandler.h"
-#include "AuthProtocol.h"
+#include "cephx/CephxProtocol.h"
 #include "Auth.h"
 
 #include "mon/Monitor.h"
@@ -37,12 +37,23 @@ public:
   CephAuthService_X(Monitor *m) : AuthServiceHandler(m), state(0) {}
   ~CephAuthService_X() {}
 
+  int start_session(bufferlist& result_bl);
   int handle_request(bufferlist::iterator& indata, bufferlist& result_bl);
   int handle_cephx_protocol(bufferlist::iterator& indata, bufferlist& result_bl);
   void build_cephx_response_header(int request_type, int status, bufferlist& bl);
 };
 
 
+int CephAuthService_X::start_session(bufferlist& result_bl)
+{
+  CephXEnvResponse1 response;
+  get_random_bytes((char *)&server_challenge, sizeof(server_challenge));
+  response.server_challenge = server_challenge;
+  ::encode(response, result_bl);
+  state = 1;
+  return CEPH_AUTH_CEPHX;
+}
+
 int CephAuthService_X::handle_request(bufferlist::iterator& indata, bufferlist& result_bl)
 {
   int ret = 0;
@@ -52,22 +63,15 @@ int CephAuthService_X::handle_request(bufferlist::iterator& indata, bufferlist&
 
   switch (state) {
   case 0:
-    {
-      CephXEnvRequest1 req;
-      ::decode(req, indata);
-      entity_name = req.name;
-      CephXEnvResponse1 response;
-      get_random_bytes((char *)&server_challenge, sizeof(server_challenge));
-      response.server_challenge = server_challenge;
-      ::encode(response, result_bl);
-      ret = -EAGAIN;
-    }
+    assert(0);
     break;
   case 1:
     {
-      CephXEnvRequest2 req;
+      CephXGetMonKey req;
       ::decode(req, indata);
 
+      entity_name = req.name;
+
       CryptoKey secret;
       dout(0) << "entity_name=" << entity_name.to_str() << dendl;
       if (!mon->key_server.get_secret(entity_name, secret)) {
@@ -151,18 +155,19 @@ int CephAuthService_X::handle_request(bufferlist::iterator& indata, bufferlist&
         ret = -EPERM;
         break;
       }
+      dout(0) << " ticket_req.keys = " << ticket_req.keys << dendl;
 
       ret = 0;
       vector<SessionAuthInfo> info_vec;
       for (uint32_t service_id = 1; service_id <= ticket_req.keys; service_id <<= 1) {
         if (ticket_req.keys & service_id) {
+         dout(0) << " adding key for service " << service_id << dendl;
           SessionAuthInfo info;
           int r = mon->key_server.build_session_auth_info(service_id, auth_ticket_info, info);
           if (r < 0) {
             ret = r;
             break;
           }
-
           info_vec.push_back(info);
         }
       }
index ffe1c4d0dc5533406d56cd5bc10af641a9a7aaef..1430234acae1ff67f693d6e9ec5cebebc0806132 100644 (file)
@@ -28,6 +28,7 @@ public:
   AuthServiceHandler(Monitor *m) : mon(m) { }
   virtual ~AuthServiceHandler() { }
 
+  virtual int start_session(bufferlist& result) = 0;
   virtual int handle_request(bufferlist::iterator& indata, bufferlist& result) = 0;
 };
 
index b5e37fccd697438dfa5ccdddd0c94690e617aa73..f28a4a3c68c6102298f94d3cc8d3bf9af22b7381 100644 (file)
@@ -19,7 +19,6 @@
 #include "Crypto.h"
 #include "common/Timer.h"
 #include "Auth.h"
-#include "AuthProtocol.h"
 
 #include <sstream>
 
diff --git a/src/auth/cephx/CephxClientHandler.cc b/src/auth/cephx/CephxClientHandler.cc
new file mode 100644 (file)
index 0000000..888bc84
--- /dev/null
@@ -0,0 +1,229 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2004-2009 Sage Weil <sage@newdream.net>
+ *
+ * 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.
+ * 
+ */
+
+
+#include <errno.h>
+
+#include "CephxClientHandler.h"
+#include "CephxProtocol.h"
+
+#include "../KeyRing.h"
+
+int CephxClientHandler::build_request(bufferlist& bl)
+{
+  dout(0) << "state=" << state << dendl;
+
+  switch (state) {
+  case STATE_START:
+    break;
+
+  case STATE_GETTING_MON_KEY:
+    /* authenticate */
+    {
+      /* FIXME: init req fields */
+      CephXGetMonKey req;
+      req.name = client->name;
+      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;
+      }
+      ::encode(req, bl);
+
+      /* we first need to get the principle/auth session key */
+      CephXRequestHeader header;
+      header.request_type = CEPHX_GET_AUTH_SESSION_KEY;
+      ::encode(header, bl);
+      build_authenticate_request(client->name, bl);
+      return 0;
+    }
+    break;
+
+  case STATE_GETTING_SESSION_KEYS:
+    /* get service tickets */
+    {
+      dout(0) << "want=" << hex << client->want << " have=" << client->have << dec << dendl;
+
+      AuthTicketHandler& ticket_handler = client->tickets.get_handler(CEPH_ENTITY_TYPE_AUTH);
+      if (!ticket_handler.build_authorizer(authorizer))
+       return -EINVAL;
+
+      CephXRequestHeader header;
+      header.request_type = CEPHX_GET_PRINCIPAL_SESSION_KEY;
+      ::encode(header, bl);
+      
+      bl.claim_append(authorizer.bl);
+      build_service_ticket_request(client->want, bl);
+    }
+    break;
+
+  case STATE_DONE:
+    break;
+
+  default:
+    assert(0);
+  }
+  return 0;
+}
+
+int CephxClientHandler::handle_response(int ret, bufferlist::iterator& indata)
+{
+  dout(0) << "cephx handle_response ret = " << ret << " state " << state << dendl;
+
+  switch (state) {
+  case STATE_START:
+    /* initialize  */
+    { 
+      CephXEnvResponse1 response;
+      ::decode(response, indata);
+      server_challenge = response.server_challenge;
+      state = STATE_GETTING_MON_KEY;
+      ret = -EAGAIN;
+    }
+    break;
+  case STATE_GETTING_MON_KEY:
+    /* authenticate */
+    {
+      struct CephXResponseHeader header;
+      ::decode(header, indata);
+
+      dout(0) << "request_type=" << hex << header.request_type << dec << dendl;
+      dout(0) << "handle_cephx_response()" << dendl;
+
+      dout(0) << "CEPHX_GET_AUTH_SESSION_KEY" << dendl;
+      
+      CryptoKey secret;
+      g_keyring.get_master(secret);
+       
+      if (!client->tickets.verify_service_ticket_reply(secret, indata)) {
+       dout(0) << "could not verify service_ticket reply" << dendl;
+       return -EPERM;
+      }
+      dout(0) << "want=" << client->want << " have=" << client->have << dendl;
+      if (client->want != client->have) {
+       state = STATE_GETTING_SESSION_KEYS;
+       ret = -EAGAIN;
+      } else {
+       state = STATE_DONE;
+       ret = 0;
+      }
+    }
+    break;
+
+  case STATE_GETTING_SESSION_KEYS:
+    {
+      struct CephXResponseHeader header;
+      ::decode(header, indata);
+
+      AuthTicketHandler& ticket_handler = client->tickets.get_handler(CEPH_ENTITY_TYPE_AUTH);
+      dout(0) << "CEPHX_GET_PRINCIPAL_SESSION_KEY session_key " << ticket_handler.session_key << dendl;
+  
+      if (!client->tickets.verify_service_ticket_reply(ticket_handler.session_key, indata)) {
+        dout(0) << "could not verify service_ticket reply" << dendl;
+        return -EPERM;
+      }
+      if (client->want == client->have) {
+       state = STATE_DONE;
+       ret = 0;
+      }
+    }
+    break;
+
+  case STATE_DONE:
+    // ignore?
+    ret = 0;
+    break;
+
+  default:
+    assert(0);
+  }
+  return ret;
+}
+
+
+
+/*
+
+
+int AuthClientAuthorizeHandler::_build_request()
+{
+  CephXRequestHeader header;
+  if (!client->tickets.has_key(service_id)) {
+    dout(0) << "can't authorize: missing service key" << dendl;
+    return -EPERM;
+  }
+
+  header.request_type = CEPHX_OPEN_SESSION;
+
+  MAuthorize *m = (MAuthorize *)msg;
+  bufferlist& bl = m->get_auth_payload();
+
+  ::encode(header, bl);
+  utime_t now;
+
+  if (!client->tickets.build_authorizer(service_id, authorizer))
+    return -EINVAL;
+
+  bl.claim_append(authorizer.bl);
+
+  return 0;
+}
+
+int AuthClientAuthorizeHandler::_handle_response(int ret, bufferlist::iterator& iter)
+{
+  struct CephXResponseHeader header;
+  ::decode(header, iter);
+
+  dout(0) << "AuthClientAuthorizeHandler::_handle_response() ret=" << ret << dendl;
+
+  if (ret) {
+    return ret;
+  }
+
+  switch (header.request_type & CEPHX_REQUEST_TYPE_MASK) {
+  case CEPHX_OPEN_SESSION:
+    {
+      ret = authorizer.verify_reply(iter);
+      break;
+    }
+    break;
+  default:
+    dout(0) << "header.request_type = " << hex << header.request_type << dec << dendl;
+    ret = -EINVAL;
+    break;
+  }
+
+  return ret;
+}
+
+AuthClientProtocolHandler *AuthClientHandler::_get_proto_handler(uint32_t id)
+{
+  map<uint32_t, AuthClientProtocolHandler *>::iterator iter = handlers_map.find(id);
+  if (iter == handlers_map.end())
+    return NULL;
+
+  return iter->second;
+}
+
+
+*/
diff --git a/src/auth/cephx/CephxClientHandler.h b/src/auth/cephx/CephxClientHandler.h
new file mode 100644 (file)
index 0000000..35f65ef
--- /dev/null
@@ -0,0 +1,46 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2004-2009 Sage Weil <sage@newdream.net>
+ *
+ * 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 __CEPHXLIENTHANDLER_H
+#define __CEPHXCLIENTHANDLER_H
+
+#include "../AuthClientHandler.h"
+
+class CephxClientHandler : public AuthClientProtocolHandler {
+  enum {
+    STATE_START,
+    STATE_GETTING_MON_KEY,
+    STATE_GETTING_SESSION_KEYS,
+    STATE_DONE
+  } state;
+  
+  /* envelope protocol parameters */
+  uint64_t server_challenge;
+  
+
+public:
+  CephxClientHandler(AuthClientHandler *c) : AuthClientProtocolHandler(c) {
+    reset();
+  }
+
+  void reset() {
+    state = STATE_START;
+  }
+  int build_request(bufferlist& bl);
+  int handle_response(int ret, bufferlist::iterator& iter);
+
+  int get_protocol() { return CEPH_AUTH_CEPHX; }
+};
+
+#endif
diff --git a/src/auth/cephx/CephxProtocol.h b/src/auth/cephx/CephxProtocol.h
new file mode 100644 (file)
index 0000000..4b9c676
--- /dev/null
@@ -0,0 +1,155 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2004-2009 Sage Weil <sage@newdream.net>
+ *
+ * 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 __CEPHXPROTOCOL_H
+#define __CEPHXPROTOCOL_H
+
+/*
+  Ceph X protocol
+
+  First, the principal has to authenticate with the authenticator. A
+  shared-secret mechanism is being used, and the negotitaion goes like this:
+
+  A = Authenticator
+  P = Principle
+  S = Service
+
+  1. Obtaining principal/auth session key
+
+  (Authenticate Request)
+  p->a : principal, principal_addr.  authenticate me!
+
+ ...authenticator does lookup in database...
+
+  a->p : A= {principal/auth session key, validity}^principal_secret (*)
+         B= {principal ticket, validity, principal/auth session key}^authsecret
+
+  
+  [principal/auth session key, validity] = service ticket
+  [principal ticket, validity, principal/auth session key] = service ticket info
+
+  (*) annotation: ^ signifies 'encrypted by'
+
+  At this point, if is genuine, the principal should have the principal/auth
+  session key at hand. The next step would be to request an authorization to
+  use some other service:
+
+  2. Obtaining principal/service session key
+
+  p->a : B, {principal_addr, timestamp}^principal/auth session key.  authorize
+         me!
+  a->p : E= {service ticket}^svcsecret
+         F= {principal/service session key, validity}^principal/auth session key
+
+  principal_addr, timestamp = authenticator
+
+  service ticket = principal name, client network address, validity, principal/service session key
+
+  Note that steps 1 and 2 are pretty much the same thing; contacting the
+  authenticator and requesting for a key.
+
+  Following this the principal should have a principal/service session key that
+  could be used later on for creating a session:
+
+  3. Opening a session to a service
+
+  p->s : E + {principal_addr, timestamp}^principal/service session key
+  s->p : {timestamp+1}^principal/service/session key
+
+  timestamp+1 = reply authenticator
+
+  Now, the principal is fully authenticated with the service. So, logically we
+  have 2 main actions here. The first one would be to obtain a session key to
+  the service (steps 1 and 2), and the second one would be to authenticate with
+  the service, using that ticket.
+*/
+
+/* authenticate requests */
+#define CEPHX_GET_AUTH_SESSION_KEY      0x0100
+#define CEPHX_GET_PRINCIPAL_SESSION_KEY 0x0200
+
+/* authorize requests */
+#define CEPHX_OPEN_SESSION              0x0300
+
+#define CEPHX_REQUEST_TYPE_MASK         0x0F00
+
+
+#include "../Auth.h"
+
+
+
+/* 
+  Ceph X-Envelope protocol
+*/
+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 CephXGetMonKey {
+  EntityName name;
+  __u64 client_challenge;
+  __u64 key;
+
+  void encode(bufferlist& bl) const {
+    ::encode(name, bl);
+    ::encode(client_challenge, bl);
+    ::encode(key, bl);
+  }
+  void decode(bufferlist::iterator& bl) {
+    ::decode(name, bl);
+    ::decode(client_challenge, bl);
+     ::decode(key, bl);
+ }
+};
+WRITE_CLASS_ENCODER(CephXGetMonKey)
+
+
+struct CephXRequestHeader {
+  uint16_t request_type;
+
+  void encode(bufferlist& bl) const {
+    ::encode(request_type, bl);
+  }
+  void decode(bufferlist::iterator& bl) {
+    ::decode(request_type, bl);
+  }
+};
+WRITE_CLASS_ENCODER(CephXRequestHeader);
+
+struct CephXResponseHeader {
+  uint16_t request_type;
+  int32_t status;
+
+  void encode(bufferlist& bl) const {
+    ::encode(request_type, bl);
+    ::encode(status, bl);
+  }
+  void decode(bufferlist::iterator& bl) {
+    ::decode(request_type, bl);
+    ::decode(status, bl);
+  }
+};
+WRITE_CLASS_ENCODER(CephXResponseHeader);
+
+
+
+#endif
index b980500f5ed749645d4f10d54bd1ee4e37e685a8..f3dbc9b96f42de1f93b8ca2979232da8cbcd51a2 100644 (file)
@@ -113,8 +113,7 @@ struct ceph_secret {
 #define CEPH_MSG_MON_SUBSCRIBE          15
 #define CEPH_MSG_MON_SUBSCRIBE_ACK      16
 #define CEPH_MSG_AUTH                  17
-#define CEPH_MSG_AUTHORIZE             18
-#define CEPH_MSG_AUTH_REPLY            19
+#define CEPH_MSG_AUTH_REPLY            18
 
 /* client <-> mds */
 #define CEPH_MSG_MDS_MAP                21
index 7d19b22bbf8a587f40535f224a848558b19ec221..0e26234e552fa461fe0c15f80a2faa142fea6f08 100644 (file)
@@ -40,8 +40,6 @@ using namespace std;
 #include "messages/MClientMount.h"
 #include "messages/MClientMountAck.h"
 
-#include "auth/AuthProtocol.h"
-
 #include "include/librados.h"
 
 #define RADOS_LIST_MAX_ENTRIES 1024
index a49e685181cd420a3f5f53fecd36a4889df185d7..1c87980befb7ea9b9c84d4c0ea11df7354433e62 100644 (file)
 #include "messages/PaxosServiceMessage.h"
 
 struct MAuth : public PaxosServiceMessage {
-  __u64 trans_id;
+  __u32 protocol;
   bufferlist auth_payload;
 
-  MAuth() : PaxosServiceMessage(CEPH_MSG_AUTH, 0) { }
+  /* if protocol == 0, then auth_payload is a set<__u32> listing protocols the client supports */
+
+  MAuth() : PaxosServiceMessage(CEPH_MSG_AUTH, 0), protocol(0) { }
 
   const char *get_type_name() { return "auth"; }
   void print(ostream& out) {
-    out << "auth(" << trans_id << " " << auth_payload.length() << " bytes)";
+    out << "auth(proto " << protocol << " " << auth_payload.length() << " bytes)";
   }
 
   void decode_payload() {
     bufferlist::iterator p = payload.begin();
     paxos_decode(p);
-    ::decode(trans_id, p);
+    ::decode(protocol, p);
     ::decode(auth_payload, p);
   }
   void encode_payload() {
     paxos_encode();
-    ::encode(trans_id, payload);
+    ::encode(protocol, payload);
     ::encode(auth_payload, payload);
   }
   bufferlist& get_auth_payload() { return auth_payload; }
index cfbc10688ac9385f03ceab9f009760bd82770327..7eab25d2581ab6369f774203ef5f6defee914fb7 100644 (file)
 #include "msg/Message.h"
 
 struct MAuthReply : public Message {
-  __u64 trans_id;
+  __u32 protocol;
   __s32 result;
   cstring result_msg;
   bufferlist result_bl;
 
-  MAuthReply() : Message(CEPH_MSG_AUTH_REPLY), trans_id(0), result(0) {}
-  MAuthReply(__u64 tid, bufferlist *bl = NULL, int r = 0, const char *msg = 0) :
+  MAuthReply() : Message(CEPH_MSG_AUTH_REPLY), protocol(0), result(0) {}
+  MAuthReply(__u32 p, bufferlist *bl = NULL, int r = 0, const char *msg = 0) :
     Message(CEPH_MSG_AUTH_REPLY),
-    trans_id(tid), result(r),
+    protocol(p), result(r),
     result_msg(msg) {
     if (bl)
       result_bl = *bl;
@@ -35,7 +35,7 @@ struct MAuthReply : public Message {
   const char *get_type_name() { return "auth_reply"; }
   void print(ostream& o) {
     char buf[80];
-    o << "auth_reply(" << trans_id << " " << result << " " << strerror_r(-result, buf, sizeof(buf));
+    o << "auth_reply(proto " << protocol << " " << result << " " << strerror_r(-result, buf, sizeof(buf));
     if (result_msg.length())
       o << ": " << result_msg;
     o << ")";
@@ -43,18 +43,16 @@ struct MAuthReply : public Message {
 
   void decode_payload() {
     bufferlist::iterator p = payload.begin();
-    ::decode(trans_id, p);
+    ::decode(protocol, p);
     ::decode(result, p);
     ::decode(result_bl, p);
     ::decode(result_msg, p);
   }
   void encode_payload() {
-    ::encode(trans_id, payload);
+    ::encode(protocol, payload);
     ::encode(result, payload);
     ::encode(result_bl, payload);
     ::encode(result_msg, payload);
-
-    dout(0) << "MAuthReply size=" << payload.length() << dendl;
   }
 };
 
diff --git a/src/messages/MAuthorize.h b/src/messages/MAuthorize.h
deleted file mode 100644 (file)
index 562968c..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 
-// vim: ts=8 sw=2 smarttab
-/*
- * Ceph - scalable distributed file system
- *
- * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
- *
- * 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 __MAUTHORIZE_H
-#define __MAUTHORIZE_H
-
-#include "msg/Message.h"
-
-struct MAuthorize : public Message {
-  __u64 trans_id;
-  bufferlist auth_payload;
-
-  MAuthorize() : Message(CEPH_MSG_AUTHORIZE) { }
-
-  const char *get_type_name() { return "authorize"; }
-  void print(ostream& out) {
-    out << "authorize(" << trans_id << ")";
-  }
-
-  void decode_payload() {
-    bufferlist::iterator p = payload.begin();
-    ::decode(trans_id, p);
-    ::decode(auth_payload, p);
-  }
-  void encode_payload() {
-    ::encode(trans_id, payload);
-    ::encode(auth_payload, payload);
-  }
-  bufferlist& get_auth_payload() { return auth_payload; }
-};
-
-#endif
index 099e9839180b363527d40bb4fe8f6c28a1f94b2e..7473976a0167389b307fc87787e504761c86fa8b 100644 (file)
@@ -265,25 +265,32 @@ bool AuthMonitor::preprocess_auth(MAuth *m)
   bufferlist response_bl;
   bufferlist::iterator indata = m->auth_payload.begin();
 
-  // set up handler?
-  if (!s->auth_handler) {
-    set<__u32> supported;
-   
-    try {
-      ::decode(supported, indata);
-    } catch (buffer::error *e) {
-      dout(0) << "failed to decode message auth message" << dendl;
-      ret = -EINVAL;
-    }
+  __u32 proto = m->protocol;
 
-    if (!ret) {
-      s->auth_handler = get_auth_handler(mon, supported);
-      if (!s->auth_handler)
-       ret = -EPERM;
+  // set up handler?
+  if (m->protocol == 0) {
+    if (!s->auth_handler) {
+      set<__u32> supported;
+      
+      try {
+       ::decode(supported, indata);
+      } catch (buffer::error *e) {
+       dout(0) << "failed to decode message auth message" << dendl;
+       ret = -EINVAL;
+      }
+      
+      if (!ret) {
+       s->auth_handler = get_auth_handler(mon, supported);
+       if (!s->auth_handler)
+         ret = -EPERM;
+       else {
+         proto = s->auth_handler->start_session(response_bl);
+       }
+      }
+    } else {
+      ret = -EINVAL;  // can only select protocol once per connection
     }
-  }
-
-  if (s->auth_handler && !ret) {
+  } else if (s->auth_handler) {
     // handle the request
     try {
       ret = s->auth_handler->handle_request(indata, response_bl);
@@ -295,8 +302,10 @@ bool AuthMonitor::preprocess_auth(MAuth *m)
       paxos->wait_for_active(new C_RetryMessage(this, m));
       return true;
     }
+  } else {
+    ret = -EINVAL;  // no protocol selected?
   }
-  MAuthReply *reply = new MAuthReply(m->trans_id, &response_bl, ret);
+  MAuthReply *reply = new MAuthReply(proto, &response_bl, ret);
   mon->messenger->send_message(reply, m->get_orig_source_inst());
   return true;
 }
index 48477f25567a542017bab0a219368762795a67ce..e27dd0fd279f52b6026ccbd2242fd8a79a038086 100644 (file)
@@ -31,7 +31,6 @@
 #include "MonMap.h"
 
 #include "auth/Auth.h"
-#include "auth/AuthProtocol.h"
 #include "auth/KeyRing.h"
 
 #include "config.h"
@@ -308,12 +307,18 @@ void MonClient::handle_mount_ack(MClientMountAck* m)
 
 void MonClient::handle_auth(MAuthReply *m)
 {
-  int ret = auth.handle_response(m->trans_id, m);
+  int ret = auth.handle_response(m);
   delete m;
 
-  if (ret == -EAGAIN) {
-    auth.send_session_request(this, &auth_handler);
-  } else {
+  if (ret == 0) {
+    state = MC_STATE_HAVE_SESSION;
+    while (!waiting_for_session.empty()) {
+      _send_mon_message(waiting_for_session.front());
+      waiting_for_session.pop_front();
+    }
+    authenticate_cond.SignalAll();
+  }
+  /*
     switch (state) {
     case MC_STATE_AUTHENTICATING:
       {
@@ -337,6 +342,7 @@ void MonClient::handle_auth(MAuthReply *m)
       assert(false);
     }
   }
+  */
 }
 
 
@@ -375,9 +381,8 @@ void MonClient::_reopen_session()
   // restart authentication process?
   if (state != MC_STATE_HAVE_SESSION) {
     state = MC_STATE_AUTHENTICATING;
-    auth_handler.reset();
-    authorize_handler.reset();
-    auth.send_session_request(this, &auth_handler);
+    auth.reset();
+    auth.send_request();
   }
 
   if (g_keyring.need_rotating_secrets())
index 8c25a1d64f6605435f126a9a4efb138ae82d318f..4f3d719d4d571987df84a3cb51dbef625d7a0822 100644 (file)
@@ -150,8 +150,6 @@ private:
   // auth tickets
 public:
   AuthClientHandler auth;
-  AuthClientAuthenticateHandler auth_handler;
-  AuthClientAuthorizeHandler authorize_handler;
   double auth_timeout;
 public:
   void renew_subs() {
@@ -178,8 +176,7 @@ public:
                timer(monc_lock),
                hunting(false),
                mounting(0), mount_err(0),
-                auth_handler(&auth, CEPH_ENTITY_TYPE_MON, 0),
-                authorize_handler(&auth, CEPH_ENTITY_TYPE_MON) { }
+               auth(this) { }
   ~MonClient() {
     timer.cancel_all_events();
   }
@@ -230,11 +227,11 @@ public:
   }
 
   void set_want_keys(uint32_t want) {
-    auth_handler.set_want_keys(want | CEPH_ENTITY_TYPE_MON);
+    auth.set_want_keys(want | CEPH_ENTITY_TYPE_MON);
   }
 
   void add_want_keys(uint32_t want) {
-    auth_handler.add_want_keys(want);
+    auth.add_want_keys(want);
   }
 };
 
index fe6e4fa8f40b537a631b874c1df18741bbfe846a..5237f9b0cc18c4d43c7710c5141a4f41dc26b75a 100644 (file)
@@ -40,7 +40,6 @@
 #include "messages/MMonSubscribe.h"
 #include "messages/MMonSubscribeAck.h"
 
-#include "messages/MAuthorize.h"
 #include "messages/MAuthReply.h"
 
 #include "common/Timer.h"
@@ -607,11 +606,6 @@ bool Monitor::ms_dispatch(Message *m)
       handle_class((MClass *)m);
       break;
 
-    case CEPH_MSG_AUTHORIZE:
-      handle_authorize((class MAuthorize*)m);
-      break;
-
-      
     default:
       ret = false;
     }
@@ -857,64 +851,6 @@ void Monitor::handle_class(MClass *m)
   }
 }
 
-void Monitor::handle_authorize(MAuthorize *m)
-{
-  dout(0) << "AuthorizeServer::handle_request() blob_size=" << m->get_auth_payload().length() << dendl;
-  int ret = 0;
-
-  Session *s = (Session *)m->get_connection()->get_priv();
-  s->put();
-
-  bufferlist response_bl;
-  bufferlist::iterator indata = m->auth_payload.begin();
-
-  // handle the request
-  try {
-    ret = do_authorize(indata, response_bl);
-  } catch (buffer::error *err) {
-    ret = -EINVAL;
-    dout(0) << "caught error when trying to handle authorize request, probably malformed request" << dendl;
-  }
-  MAuthReply *reply = new MAuthReply(m->trans_id, &response_bl, ret);
-  messenger->send_message(reply, m->get_orig_source_inst());
-}
-
-int Monitor::do_authorize(bufferlist::iterator& indata, bufferlist& result_bl)
-{
-  struct CephXRequestHeader cephx_header;
-
-  ::decode(cephx_header, indata);
-
-  uint16_t request_type = cephx_header.request_type & CEPHX_REQUEST_TYPE_MASK;
-  int ret = 0;
-
-  dout(0) << "request_type=" << request_type << dendl;
-
-  switch (request_type) {
-  case CEPHX_OPEN_SESSION:
-    {
-      dout(0) << "CEPHX_OPEN_SESSION " << cephx_header.request_type << dendl;
-      AuthServiceTicketInfo auth_ticket_info;
-
-      bufferlist tmp_bl;
-      if (!verify_authorizer(key_server, indata, auth_ticket_info, tmp_bl))
-        ret = -EPERM;
-      result_bl.claim_append(tmp_bl);
-    }
-    break;
-  default:
-    ret = -EINVAL;
-    break;
-  }
-
-  struct CephXResponseHeader header;
-  header.request_type = request_type;
-  header.status = ret;
-  ::encode(header, result_bl);
-
-  return ret;
-}
-
 bool Monitor::ms_get_authorizer(int dest_type, AuthAuthorizer& authorizer, bool force_new)
 {
   AuthServiceTicketInfo auth_ticket_info;
index 8d363f2fe9edd10239feda80853dca48ef0ee012..3927e1fb52cf9176e9996df4c3684e88a116ace4 100644 (file)
@@ -49,7 +49,6 @@ class MMonObserve;
 class MMonSubscribe;
 class MClass;
 class MAuthRotating;
-class MAuthorize;
 class MRoute;
 
 class Monitor : public Dispatcher {
@@ -155,9 +154,6 @@ public:
   void handle_observe(MMonObserve *m);
   void handle_class(MClass *m);
   void handle_route(MRoute *m);
-  void handle_authorize(MAuthorize *m);
-
-  int do_authorize(bufferlist::iterator& indata, bufferlist& result_bl);
 
   void reply_command(MMonCommand *m, int rc, const string &rs, version_t version);
   void reply_command(MMonCommand *m, int rc, const string &rs, bufferlist& rdata, version_t version);
index 822fb370fdcf6817e7be411d801e253be5bd0d67..e5c2066232a4aaa0e4a88e5380a4a6ff9ab51920 100644 (file)
@@ -65,7 +65,6 @@ using namespace std;
 #include "messages/MMonGetMap.h"
 
 #include "messages/MAuth.h"
-#include "messages/MAuthorize.h"
 #include "messages/MAuthReply.h"
 #include "messages/MClientMount.h"
 #include "messages/MClientMountAck.h"
@@ -324,9 +323,6 @@ Message *decode_message(ceph_msg_header& header, ceph_msg_footer& footer,
   case CEPH_MSG_AUTH:
     m = new MAuth;
     break;
-  case CEPH_MSG_AUTHORIZE:
-    m = new MAuthorize;
-    break;
   case CEPH_MSG_AUTH_REPLY:
     m = new MAuthReply;
     break;