]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
auth: multiple tickets handling
authorYehuda Sadeh <yehuda@hq.newdream.net>
Wed, 9 Sep 2009 21:35:08 +0000 (14:35 -0700)
committerYehuda Sadeh <yehuda@hq.newdream.net>
Wed, 9 Sep 2009 21:35:08 +0000 (14:35 -0700)
src/auth/Auth.cc
src/auth/Auth.h
src/auth/AuthClientHandler.cc
src/auth/AuthClientHandler.h
src/auth/AuthServiceManager.cc

index 991722fbc051b1cac662fc8a7f167d11910d3208..61d7b42e39ad7582cb7819e56fd2cbc201749a28 100644 (file)
@@ -4,6 +4,23 @@
 
 #include "config.h"
 
+static void hexdump(string msg, const char *s, int len)
+{
+  int buf_len = len*4;
+  char buf[buf_len];
+  int pos = 0;
+  for (unsigned int i=0; i<len && pos<buf_len - 8; i++) {
+    if (i && !(i%8))
+      pos += snprintf(&buf[pos], buf_len-pos, " ");
+    if (i && !(i%16))
+      pos += snprintf(&buf[pos], buf_len-pos, "\n");
+    pos += snprintf(&buf[pos], buf_len-pos, "%.2x ", (int)(unsigned char)s[i]);
+  }
+  dout(0) << msg << ":\n" << buf << dendl;
+}
+
+
+
 
 /*
  * Authentication
@@ -14,7 +31,7 @@
  *
  * principal_name, principal_addr.  "please authenticate me."
  */
-void build_authenticate_request(EntityName& principal_name, entity_addr_t& principal_addr,
+void build_service_ticket_request(EntityName& principal_name, entity_addr_t& principal_addr,
                                 uint32_t keys,
                                 bool encrypt,
                                 CryptoKey& session_key,
@@ -29,6 +46,8 @@ void build_authenticate_request(EntityName& principal_name, entity_addr_t& princ
   if (!encrypt) {
     ::encode(ticket_req, request);
   } else {
+    bufferptr& s1 = session_key.get_secret();
+    hexdump("encoding, session key", s1.c_str(), s1.length());
     encode_encrypt(ticket_req, session_key, request);
   }
   ::encode(ticket_info, request);
@@ -42,23 +61,35 @@ void build_authenticate_request(EntityName& principal_name, entity_addr_t& princ
  * {session key, validity, nonce}^principal_secret
  * {principal_ticket, session key}^service_secret  ... "enc_ticket"
  */
-bool build_authenticate_reply(AuthTicket& ticket,
-                     CryptoKey& session_key,
+bool build_service_ticket_reply(
                      CryptoKey& principal_secret,
-                     CryptoKey& service_secret,
+                     vector<SessionAuthInfo> ticket_info,
                      bufferlist& reply)
 {
-  AuthServiceTicket msg_a;
+  vector<SessionAuthInfo>::iterator ticket_iter = ticket_info.begin(); 
 
-  msg_a.session_key = session_key;
-  if (encode_encrypt(msg_a, principal_secret, reply) < 0)
-    return false;
+  uint32_t num = ticket_info.size();
+  ::encode(num, reply);
 
-  AuthServiceTicketInfo ticket_info;
-  ticket_info.session_key = session_key;
-  ticket_info.ticket = ticket;
-  if (encode_encrypt(ticket_info, service_secret, reply) < 0)
-    return false;
+  while (ticket_iter != ticket_info.end()) {
+    SessionAuthInfo& info = *ticket_iter;
+
+    ::encode(info.service_id, reply);
+
+    AuthServiceTicket msg_a;
+
+    msg_a.session_key = info.session_key;
+    if (encode_encrypt(msg_a, principal_secret, reply) < 0)
+      return false;
+
+    AuthServiceTicketInfo ticket_info;
+    ticket_info.session_key = info.session_key;
+    ticket_info.ticket = info.ticket;
+    if (encode_encrypt(ticket_info, info.service_secret, reply) < 0)
+      return false;
+
+    ++ticket_iter;
+  }
   return true;
 }
 
@@ -71,6 +102,9 @@ bool verify_service_ticket_request(bool encrypted,
   AuthServiceTicketRequest msg;
 
   if (encrypted) {
+    bufferptr& s1 = session_key.get_secret();
+    hexdump("decoding, session key", s1.c_str(), s1.length());
+    
     dout(0) << "verify encrypted service ticket request" << dendl;
     if (decode_decrypt(msg, session_key, indata) < 0)
       return false;
@@ -102,16 +136,44 @@ bool AuthTicketHandler::verify_service_ticket_reply(CryptoKey& secret,
                                              bufferlist::iterator& indata)
 {
   AuthServiceTicket msg_a;
+
+  bufferptr& s1 = secret.get_secret();
+  hexdump("decoding, session key", s1.c_str(), s1.length());
   if (decode_decrypt(msg_a, secret, indata) < 0)
     return false;
-
+  /* FIXME: decode into relevant ticket */
   ::decode(ticket, indata);
 
+  bufferptr& s = msg_a.session_key.get_secret();
+  hexdump("decoded ticket.session key", s.c_str(), s.length());
+  session_key = msg_a.session_key;
+  has_key_flag = true;
+
+  return true;
+}
+
+/*
+ * PRINCIPAL: verify our attempt to authenticate succeeded.  fill out
+ * this ServiceTicket with the result.
+ */
+bool AuthTicketsManager::verify_service_ticket_reply(CryptoKey& secret,
+                                             bufferlist::iterator& indata)
+{
+  uint32_t num;
+  ::decode(num, indata);
+  dout(0) << "received " << num << " keys" << dendl;
+
+  for (int i=0; i<(int)num; i++) {
+    uint32_t type;
+    ::decode(type, indata);
+    dout(0) << "received key type=" << type << dendl;
+    if (!tickets_map[type].verify_service_ticket_reply(secret, indata))
+      return false;
+  }
+
   if (!indata.end())
     return false;
 
-  has_key_flag = true;
-
   return true;
 }
 
index f536c5d6e977a135f79cdc5ef667e1a7d6252be6..b219d07808068cde9eda90638b42205a949e718e 100644 (file)
@@ -18,6 +18,7 @@
 #include "Crypto.h"
 #include "msg/msg_types.h"
 
+
 struct EntityName {
   uint32_t entity_type;
   string name;
@@ -33,7 +34,6 @@ struct EntityName {
 };
 WRITE_CLASS_ENCODER(EntityName);
 
-
 /*
  * The ticket (if properly validated) authorizes the principal use
  * services as described by 'caps' during the specified validity
@@ -69,14 +69,41 @@ struct AuthTicket {
 };
 WRITE_CLASS_ENCODER(AuthTicket)
 
+struct AuthBlob {
+  bufferlist blob;
+
+  void encode(bufferlist& bl) const {
+    ::encode(blob, bl);
+  }
+
+  void decode(bufferlist::iterator& bl) {
+    ::decode(blob, bl);
+  }
+};
+WRITE_CLASS_ENCODER(AuthBlob);
+
+struct SessionAuthInfo {
+  uint32_t service_id;
+  AuthTicket ticket;
+  CryptoKey session_key;
+  CryptoKey service_secret;
+};
+
+
 /*
  * Authentication
  */
-extern void build_authenticate_request(EntityName& principal_name, entity_addr_t principal_addr,
-                                      bufferlist& request);
-extern bool build_authenticate_reply(AuthTicket& principal_ticket, CryptoKey& principal_secret,
-                                    CryptoKey& session_key, CryptoKey& service_secret,
-                                    bufferlist& reply);
+extern void build_service_ticket_request(EntityName& principal_name, entity_addr_t& principal_addr,
+                                uint32_t keys,
+                                bool encrypt,
+                                CryptoKey& session_key,
+                                AuthBlob& ticket_info,
+                               bufferlist& request);
+
+extern bool build_service_ticket_reply(
+                     CryptoKey& principal_secret,
+                     vector<SessionAuthInfo> ticket_info,
+                     bufferlist& reply);
 
 class AuthenticateRequest {
   EntityName name;
@@ -95,22 +122,8 @@ public:
 };
 WRITE_CLASS_ENCODER(AuthenticateRequest)
 
-struct AuthBlob {
-  bufferlist blob;
-
-  void encode(bufferlist& bl) const {
-    ::encode(blob, bl);
-  }
-
-  void decode(bufferlist::iterator& bl) {
-    ::decode(blob, bl);
-  }
-};
-WRITE_CLASS_ENCODER(AuthBlob);
-
 /*
- * ServiceTicket gives a principal access to some service
- * (monitor, osd, mds).
+ * AuthTicketHandler
  */
 struct AuthTicketHandler {
   CryptoKey session_key;
@@ -127,17 +140,27 @@ struct AuthTicketHandler {
   // to build our ServiceTicket
   bool verify_service_ticket_reply(CryptoKey& principal_secret,
                                 bufferlist::iterator& indata);
-
+#if 0
   // to build a new ServiceTicket, to access different service
   bool get_session_keys(uint32_t keys, entity_addr_t& principal_addr, bufferlist& bl);
-
+#endif
   // to access the service
   utime_t build_authenticator(bufferlist& bl);
   bool verify_reply_authenticator(utime_t then, bufferlist& enc_reply);
 
   bool has_key() { return has_key_flag; }
 };
-//WRITE_CLASS_ENCODER(ServiceTicket)
+
+struct AuthTicketsManager {
+  map<uint32_t, AuthTicketHandler> tickets_map;
+
+  bool verify_service_ticket_reply(CryptoKey& principal_secret,
+                                bufferlist::iterator& indata);
+
+  bool get_session_keys(uint32_t keys, entity_addr_t& principal_addr, bufferlist& bl);
+
+  AuthTicketHandler& get_handler(uint32_t type) { return tickets_map[type]; }
+};
 
 struct AuthServiceTicketRequest {
   entity_addr_t addr;
index 10ad7da728950561a8db575a69ec33292ef346e5..6c7da6c582fa0c0a4a62c3e0fc852281c123be60 100644 (file)
@@ -62,15 +62,15 @@ int AuthClientHandler::generate_request(bufferlist& bl)
 
 int AuthClientHandler::handle_response(int ret, bufferlist& bl)
 {
-char buf[1024];
+char buf[4096];
       const char *s = bl.c_str();
       int pos = 0;
-      for (unsigned int i=0; i<bl.length(); i++) {
-        pos += snprintf(&buf[pos], 1024-pos, "%.2x ", (int)(unsigned char)s[i]);
+      for (unsigned int i=0; i<bl.length() && pos<sizeof(buf) - 8; i++) {
+        pos += snprintf(&buf[pos], sizeof(buf)-pos, "%.2x ", (int)(unsigned char)s[i]);
         if (i && !(i%8))
-          pos += snprintf(&buf[pos], 1024-pos, " ");
+          pos += snprintf(&buf[pos], sizeof(buf)-pos, " ");
         if (i && !(i%16))
-          pos += snprintf(&buf[pos], 1024-pos, "\n");
+          pos += snprintf(&buf[pos], sizeof(buf)-pos, "\n");
       }
       dout(0) << "result_buf=" << buf << dendl;
 
@@ -112,7 +112,7 @@ char buf[1024];
 int AuthClientHandler::generate_cephx_protocol_request(bufferlist& bl)
 {
   CephXRequestHeader header;
-
+  AuthTicketHandler& ticket_handler = tickets.get_handler(CEPHX_PRINCIPAL_AUTH);
   if (!ticket_handler.has_key()) {
     dout(0) << "auth ticket: doesn't have key" << dendl;
     /* we first need to get the principle/auth session key */
@@ -122,7 +122,7 @@ int AuthClientHandler::generate_cephx_protocol_request(bufferlist& bl)
    ::encode(header, bl);
     CryptoKey key;
     AuthBlob blob;
-    build_authenticate_request(name, addr, CEPHX_PRINCIPAL_AUTH,
+    build_service_ticket_request(name, addr, CEPHX_PRINCIPAL_AUTH,
                                false, key, blob, bl);
     cephx_request_state = 1;
     return 0;
@@ -140,7 +140,7 @@ int AuthClientHandler::generate_cephx_protocol_request(bufferlist& bl)
   header.request_type = CEPHX_GET_PRINCIPAL_SESSION_KEY;
 
   ::encode(header, bl);
-  build_authenticate_request(name, addr, want_keys,
+  build_service_ticket_request(name, addr, want_keys,
                              true, ticket_handler.session_key, ticket_handler.ticket, bl);
   
   return 0;
@@ -164,9 +164,10 @@ int AuthClientHandler::handle_cephx_protocol_response(bufferlist::iterator& inda
     {
       bufferptr p(PRINCIPAL_SECRET, sizeof(PRINCIPAL_SECRET) - 1);
       secret.set_secret(CEPH_SECRET_AES, p);
+      // AuthTicketHandler& ticket_handler = tickets.get_handler(CEPHX_PRINCIPAL_AUTH);
   
-      if (!ticket_handler.verify_service_ticket_reply(secret, indata)) {
-        dout(0) << "could not verify authenticate reply" << dendl;
+      if (!tickets.verify_service_ticket_reply(secret, indata)) {
+        dout(0) << "could not verify service_ticket reply" << dendl;
         return -EPERM;
       }
 
@@ -179,6 +180,12 @@ int AuthClientHandler::handle_cephx_protocol_response(bufferlist::iterator& inda
     cephx_response_state = 2;
     dout(0) << "CEPHX_GET_PRINCIPAL_SESSION_KEY" << dendl;
     {
+      AuthTicketHandler& ticket_handler = tickets.get_handler(CEPHX_PRINCIPAL_AUTH);
+  
+      if (!tickets.verify_service_ticket_reply(ticket_handler.session_key, indata)) {
+        dout(0) << "could not verify service_ticket reply" << dendl;
+        return -EPERM;
+      }
     }
     ret = 0;
     break;
index 337e10b80293ed720de3f659df1c5f70ca2bbadd..357210ef01a67c459a4e82f18a886d9b2f59dce4 100644 (file)
@@ -39,7 +39,7 @@ class AuthClientHandler {
 
   /* ceph-x protocol */
   utime_t auth_ts;
-  AuthTicketHandler ticket_handler;
+  AuthTicketsManager tickets;
 
   CryptoKey secret;
 
index 8954d3efbc53cbb55ef5bc30d0539618f4c15362..3fc8f9ff52fb3cb325919f2bc4a867354173d107 100644 (file)
 /* FIXME */
 #define SERVICE_SECRET   "0123456789ABCDEF"
 #define AUTH_SESSION_KEY "23456789ABCDEF01"
-#define TEST_SESSION_KEY "456789ABCDEF0123"
+#define SESSION_KEY "456789ABCDEF0123"
 
 #define PRINCIPAL_CLIENT_SECRET "123456789ABCDEF0"
 #define PRINCIPAL_OSD_SECRET "3456789ABCDEF012"
 
+static inline void hexdump(string msg, const char *s, int len)
+{
+  int buf_len = len*4;
+  char buf[buf_len];
+  int pos = 0;
+  for (unsigned int i=0; i<len && pos<buf_len - 8; i++) {
+    if (i && !(i%8))
+      pos += snprintf(&buf[pos], buf_len-pos, " ");
+    if (i && !(i%16))
+      pos += snprintf(&buf[pos], buf_len-pos, "\n");
+    pos += snprintf(&buf[pos], buf_len-pos, "%.2x ", (int)(unsigned char)s[i]);
+  }
+  dout(0) << msg << ":\n" << buf << dendl;
+}
+
+
 class CephAuthServer {
   /* FIXME: this is all temporary */
   AuthTicket ticket;
   CryptoKey client_secret;
-  CryptoKey osd_secret;
   CryptoKey auth_session_key;
   CryptoKey service_secret;
-  CryptoKey test_session_key;
   
 public:
   CephAuthServer() {
@@ -47,14 +61,8 @@ public:
     bufferptr ptr2(PRINCIPAL_CLIENT_SECRET, sizeof(PRINCIPAL_CLIENT_SECRET) - 1);
     client_secret.set_secret(CEPH_SECRET_AES, ptr2);
 
-    bufferptr ptr3(PRINCIPAL_OSD_SECRET, sizeof(PRINCIPAL_OSD_SECRET) - 1);
-    osd_secret.set_secret(CEPH_SECRET_AES, ptr2);
-
     bufferptr ptr4(AUTH_SESSION_KEY, sizeof(AUTH_SESSION_KEY) - 1);
-    auth_session_key.set_secret(CEPH_SECRET_AES, ptr3);
-
-    bufferptr ptr5(TEST_SESSION_KEY, sizeof(TEST_SESSION_KEY) - 1);
-    test_session_key.set_secret(CEPH_SECRET_AES, ptr5);
+    auth_session_key.set_secret(CEPH_SECRET_AES, ptr4);
    }
 
 /* FIXME: temporary stabs */
@@ -63,23 +71,23 @@ public:
      return 0;
   }
 
-  int get_osd_secret(CryptoKey& secret) {
-     secret = osd_secret;
-     return 0;
-  }
+  int get_service_secret(CryptoKey& secret, uint32_t service_id) {
+    char buf[16];
+    memcpy(buf, SERVICE_SECRET, 16);
+    buf[0] = service_id & 0xFF;
+    bufferptr ptr(buf, 16);
+    secret.set_secret(CEPH_SECRET_AES, ptr);
 
-  int get_service_secret(CryptoKey& secret) {
-    secret = service_secret;
     return 0;
   }
 
-  int get_auth_session_key(CryptoKey& key) {
-    key = auth_session_key; 
-    return 0;
-  }
+  int get_service_session_key(CryptoKey& secret, uint32_t service_id) {
+    char buf[16];
+    memcpy(buf, SERVICE_SECRET, 16);
+    buf[0] = service_id & 0xFF;
+    bufferptr ptr(buf, 16);
+    secret.set_secret(CEPH_SECRET_AES, ptr);
 
-  int get_test_session_key(CryptoKey& key) {
-    key = test_session_key; 
     return 0;
   }
 };
@@ -165,25 +173,31 @@ int CephAuthService_X::handle_cephx_protocol(bufferlist::iterator& indata, buffe
       AuthTicket ticket;
       CryptoKey principal_secret;
       CryptoKey session_key;
-      CryptoKey service_secret;
+      CryptoKey auth_secret;
 
       ticket.expires = g_clock.now();
 
       uint32_t keys;
 
-     if (!verify_service_ticket_request(false, service_secret,
-                                     session_key, keys, indata)) {
-        ret = -EPERM;
-        break;
-      }
-
       auth_server.get_client_secret(principal_secret);
-      auth_server.get_auth_session_key(session_key);
-      auth_server.get_service_secret(service_secret);
+      auth_server.get_service_session_key(session_key, CEPHX_PRINCIPAL_AUTH);
+      auth_server.get_service_secret(auth_secret, CEPHX_PRINCIPAL_AUTH);
 
+      if (!verify_service_ticket_request(false, auth_secret,
+                                     session_key, keys, indata)) {
+         ret = -EPERM;
+         break;
+       }
 
       build_cephx_response_header(request_type, 0, result_bl);
-      if (!build_authenticate_reply(ticket, session_key, principal_secret, service_secret, result_bl)) {
+      vector<SessionAuthInfo> info_vec;
+      SessionAuthInfo info;
+      info.ticket = ticket;
+      info.service_id = CEPHX_PRINCIPAL_AUTH;
+      info.session_key = session_key;
+      info.service_secret = auth_secret;
+      info_vec.push_back(info);
+      if (!build_service_ticket_reply(principal_secret, info_vec, result_bl)) {
         ret = -EIO;
         break;
       }
@@ -194,29 +208,49 @@ int CephAuthService_X::handle_cephx_protocol(bufferlist::iterator& indata, buffe
     {
       EntityName name; /* FIXME should take it from the request */
       entity_addr_t addr;
+      CryptoKey auth_secret;
       CryptoKey auth_session_key;
       CryptoKey session_key;
       CryptoKey service_secret;
       uint32_t keys;
 
-      auth_server.get_auth_session_key(session_key);
-      auth_server.get_service_secret(service_secret);
-      auth_server.get_test_session_key(session_key);
+      auth_server.get_service_secret(auth_secret, CEPHX_PRINCIPAL_AUTH);
+      auth_server.get_service_session_key(auth_session_key, CEPHX_PRINCIPAL_AUTH);
+
+      vector<SessionAuthInfo> info_vec;
 
-      if (!verify_service_ticket_request(true, service_secret,
+      if (!verify_service_ticket_request(true, auth_secret,
                                      auth_session_key, keys, indata)) {
         ret = -EPERM;
         break;
       }
 
-      AuthTicket service_ticket;
-      CryptoKey osd_secret;
-      auth_server.get_osd_secret(osd_secret);
+      auth_server.get_service_session_key(auth_session_key, CEPHX_PRINCIPAL_AUTH);
+
+      for (uint32_t service_id = 1; service_id != (CEPHX_PRINCIPAL_TYPE_MASK + 1); service_id <<= 1) {
+        if (keys & service_id) {
+          auth_server.get_service_secret(service_secret, service_id);
+
+          SessionAuthInfo info;
+
+          AuthTicket service_ticket;
+          /* FIXME: initialize service_ticket */
+
+          auth_server.get_service_secret(service_secret, service_id);
+          auth_server.get_service_session_key(session_key, service_id);
+
+          info.service_id = service_id;
+          info.ticket = service_ticket;
+          info.session_key = session_key;
+          info.service_secret = service_secret;
+
+          info_vec.push_back(info);
+        }
+      }
 
-      auth_server.get_osd_secret(osd_secret);
       build_cephx_response_header(request_type, ret, result_bl);
+      build_service_ticket_reply(auth_session_key, info_vec, result_bl);
 
-      build_authenticate_reply(service_ticket, session_key, auth_session_key, osd_secret, result_bl);
       ret = 0;
     }
     break;