summaryrefslogtreecommitdiffstats
path: root/src/auth/krb
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/auth/krb/KrbAuthorizeHandler.cpp53
-rw-r--r--src/auth/krb/KrbAuthorizeHandler.hpp46
-rw-r--r--src/auth/krb/KrbClientHandler.cpp253
-rw-r--r--src/auth/krb/KrbClientHandler.hpp84
-rw-r--r--src/auth/krb/KrbProtocol.cpp86
-rw-r--r--src/auth/krb/KrbProtocol.hpp160
-rw-r--r--src/auth/krb/KrbServiceHandler.cpp225
-rw-r--r--src/auth/krb/KrbServiceHandler.hpp61
-rw-r--r--src/auth/krb/KrbSessionHandler.hpp37
9 files changed, 1005 insertions, 0 deletions
diff --git a/src/auth/krb/KrbAuthorizeHandler.cpp b/src/auth/krb/KrbAuthorizeHandler.cpp
new file mode 100644
index 00000000..1faad8bb
--- /dev/null
+++ b/src/auth/krb/KrbAuthorizeHandler.cpp
@@ -0,0 +1,53 @@
+// -*- 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) 2018 SUSE LLC.
+ * Author: Daniel Oliveira <doliveira@suse.com>
+ *
+ * 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 "KrbAuthorizeHandler.hpp"
+
+#include "common/debug.h"
+
+#define dout_subsys ceph_subsys_auth
+
+bool KrbAuthorizeHandler::verify_authorizer(
+ CephContext* ceph_ctx,
+ KeyStore* keys,
+ const bufferlist& authorizer_data,
+ size_t connection_secret_required_len,
+ bufferlist *authorizer_reply,
+ EntityName *entity_name,
+ uint64_t *global_id,
+ AuthCapsInfo *caps_info,
+ CryptoKey *session_key,
+ std::string *connection_secret,
+ std::unique_ptr<AuthAuthorizerChallenge>* challenge)
+{
+ auto itr(authorizer_data.cbegin());
+
+ try {
+ uint8_t value = (1);
+
+ using ceph::decode;
+ decode(value, itr);
+ decode(*entity_name, itr);
+ decode(*global_id, itr);
+ } catch (const buffer::error& err) {
+ ldout(ceph_ctx, 0)
+ << "Error: KrbAuthorizeHandler::verify_authorizer() failed!" << dendl;
+ return false;
+ }
+ caps_info->allow_all = true;
+ return true;
+}
+
+
diff --git a/src/auth/krb/KrbAuthorizeHandler.hpp b/src/auth/krb/KrbAuthorizeHandler.hpp
new file mode 100644
index 00000000..bc8eac62
--- /dev/null
+++ b/src/auth/krb/KrbAuthorizeHandler.hpp
@@ -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) 2018 SUSE LLC.
+ * Author: Daniel Oliveira <doliveira@suse.com>
+ *
+ * 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 KRB_AUTHORIZE_HANDLER_HPP
+#define KRB_AUTHORIZE_HANDLER_HPP
+
+#include "auth/AuthAuthorizeHandler.h"
+
+class KrbAuthorizeHandler : public AuthAuthorizeHandler {
+ bool verify_authorizer(
+ CephContext*,
+ KeyStore*,
+ const bufferlist&,
+ size_t,
+ bufferlist *,
+ EntityName *,
+ uint64_t *,
+ AuthCapsInfo *,
+ CryptoKey *,
+ std::string *connection_secret,
+ std::unique_ptr<
+ AuthAuthorizerChallenge>* = nullptr) override;
+
+ int authorizer_session_crypto() override {
+ return SESSION_SYMMETRIC_AUTHENTICATE;
+ };
+
+ ~KrbAuthorizeHandler() override = default;
+
+};
+
+
+#endif //-- KRB_AUTHORIZE_HANDLER_HPP
+
diff --git a/src/auth/krb/KrbClientHandler.cpp b/src/auth/krb/KrbClientHandler.cpp
new file mode 100644
index 00000000..e39d074e
--- /dev/null
+++ b/src/auth/krb/KrbClientHandler.cpp
@@ -0,0 +1,253 @@
+// -*- 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) 2018 SUSE LLC.
+ * Author: Daniel Oliveira <doliveira@suse.com>
+ *
+ * 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 "KrbClientHandler.hpp"
+
+#include <errno.h>
+#include <string>
+#include "KrbProtocol.hpp"
+
+#include "auth/KeyRing.h"
+#include "include/random.h"
+#include "common/ceph_context.h"
+#include "common/config.h"
+#include "common/dout.h"
+
+#define dout_subsys ceph_subsys_auth
+#undef dout_prefix
+#define dout_prefix *_dout << "krb5/gssapi client request: "
+
+struct AuthAuthorizer;
+
+AuthAuthorizer*
+KrbClientHandler::build_authorizer(uint32_t service_id) const
+{
+ ldout(cct, 20)
+ << "KrbClientHandler::build_authorizer(): Service: "
+ << ceph_entity_type_name(service_id) << dendl;
+
+ KrbAuthorizer* krb_auth = new KrbAuthorizer();
+ if (krb_auth) {
+ krb_auth->build_authorizer(cct->_conf->name, global_id);
+ }
+ return krb_auth;
+}
+
+
+KrbClientHandler::~KrbClientHandler()
+{
+ OM_uint32 gss_minor_status(0);
+
+ gss_release_name(&gss_minor_status, &m_gss_client_name);
+ gss_release_name(&gss_minor_status, &m_gss_service_name);
+ gss_release_cred(&gss_minor_status, &m_gss_credentials);
+ gss_delete_sec_context(&gss_minor_status, &m_gss_sec_ctx, GSS_C_NO_BUFFER);
+ gss_release_buffer(&gss_minor_status,
+ static_cast<gss_buffer_t>(&m_gss_buffer_out));
+}
+
+
+int KrbClientHandler::build_request(bufferlist& buff_list) const
+{
+ ldout(cct, 20)
+ << "KrbClientHandler::build_request() " << dendl;
+
+ KrbTokenBlob krb_token;
+ KrbRequest krb_request;
+
+ krb_request.m_request_type =
+ static_cast<int>(GSSAuthenticationRequest::GSS_TOKEN);
+
+ using ceph::encode;
+ encode(krb_request, buff_list);
+
+ if (m_gss_buffer_out.length != 0) {
+ krb_token.m_token_blob.append(buffer::create_static(
+ m_gss_buffer_out.length,
+ reinterpret_cast<char*>
+ (m_gss_buffer_out.value)));
+
+ encode(krb_token, buff_list);
+ ldout(cct, 20)
+ << "KrbClientHandler::build_request() : Token Blob: " << "\n";
+ krb_token.m_token_blob.hexdump(*_dout);
+ *_dout << dendl;
+ }
+ return 0;
+}
+
+
+int KrbClientHandler::handle_response(
+ int ret,
+ bufferlist::const_iterator& buff_list,
+ CryptoKey *session_key,
+ std::string *connection_secret)
+{
+ auto result(ret);
+ gss_buffer_desc gss_buffer_in = {0, nullptr};
+ gss_OID_set_desc gss_mechs_wanted = {0, nullptr};
+ OM_uint32 gss_major_status(0);
+ OM_uint32 gss_minor_status(0);
+ OM_uint32 gss_wanted_flags(GSS_C_MUTUAL_FLAG |
+ GSS_C_INTEG_FLAG);
+ OM_uint32 gss_result_flags(0);
+
+ ldout(cct, 20)
+ << "KrbClientHandler::handle_response() " << dendl;
+
+ if (result < 0) {
+ return result;
+ }
+
+ gss_mechs_wanted.elements = const_cast<gss_OID>(&GSS_API_SPNEGO_OID_PTR);
+ gss_mechs_wanted.count = 1;
+
+ KrbResponse krb_response;
+
+ using ceph::decode;
+ decode(krb_response, buff_list);
+ if (m_gss_credentials == GSS_C_NO_CREDENTIAL) {
+ gss_OID krb_client_type = GSS_C_NT_USER_NAME;
+ std::string krb_client_name(cct->_conf->name.to_str());
+
+ gss_buffer_in.length = krb_client_name.length();
+ gss_buffer_in.value = (const_cast<char*>(krb_client_name.c_str()));
+
+ if (cct->_conf->name.get_type() == CEPH_ENTITY_TYPE_CLIENT) {
+ gss_major_status = gss_import_name(&gss_minor_status,
+ &gss_buffer_in,
+ krb_client_type,
+ &m_gss_client_name);
+ if (gss_major_status != GSS_S_COMPLETE) {
+ auto status_str(gss_auth_show_status(gss_major_status,
+ gss_minor_status));
+ ldout(cct, 0)
+ << "ERROR: KrbClientHandler::handle_response() "
+ "[gss_import_name(gss_client_name)] failed! "
+ << gss_major_status << " "
+ << gss_minor_status << " "
+ << status_str
+ << dendl;
+ }
+ }
+
+ gss_major_status = gss_acquire_cred(&gss_minor_status,
+ m_gss_client_name,
+ 0,
+ &gss_mechs_wanted,
+ GSS_C_INITIATE,
+ &m_gss_credentials,
+ nullptr,
+ nullptr);
+ if (gss_major_status != GSS_S_COMPLETE) {
+ auto status_str(gss_auth_show_status(gss_major_status,
+ gss_minor_status));
+ ldout(cct, 20)
+ << "ERROR: KrbClientHandler::handle_response() "
+ "[gss_acquire_cred()] failed! "
+ << gss_major_status << " "
+ << gss_minor_status << " "
+ << status_str
+ << dendl;
+ return (-EPERM);
+ }
+
+ gss_buffer_desc krb_input_name_buff = {0, nullptr};
+ gss_OID krb_input_type = GSS_C_NT_HOSTBASED_SERVICE;
+ std::string gss_target_name(cct->_conf.get_val<std::string>
+ ("gss_target_name"));
+ krb_input_name_buff.length = gss_target_name.length();
+ krb_input_name_buff.value = (const_cast<char*>(gss_target_name.c_str()));
+
+ gss_major_status = gss_import_name(&gss_minor_status,
+ &krb_input_name_buff,
+ krb_input_type,
+ &m_gss_service_name);
+ if (gss_major_status != GSS_S_COMPLETE) {
+ auto status_str(gss_auth_show_status(gss_major_status,
+ gss_minor_status));
+ ldout(cct, 0)
+ << "ERROR: KrbClientHandler::handle_response() "
+ "[gss_import_name(gss_service_name)] failed! "
+ << gss_major_status << " "
+ << gss_minor_status << " "
+ << status_str
+ << dendl;
+ }
+ } else {
+ KrbTokenBlob krb_token;
+
+ using ceph::decode;
+ decode(krb_token, buff_list);
+ ldout(cct, 20)
+ << "KrbClientHandler::handle_response() : Token Blob: " << "\n";
+ krb_token.m_token_blob.hexdump(*_dout);
+ *_dout << dendl;
+
+ gss_buffer_in.length = krb_token.m_token_blob.length();
+ gss_buffer_in.value = krb_token.m_token_blob.c_str();
+ }
+
+ const gss_OID gss_mech_type = gss_mechs_wanted.elements;
+ if (m_gss_buffer_out.length != 0) {
+ gss_release_buffer(&gss_minor_status,
+ static_cast<gss_buffer_t>(&m_gss_buffer_out));
+ }
+
+ gss_major_status = gss_init_sec_context(&gss_minor_status,
+ m_gss_credentials,
+ &m_gss_sec_ctx,
+ m_gss_service_name,
+ gss_mech_type,
+ gss_wanted_flags,
+ 0,
+ nullptr,
+ &gss_buffer_in,
+ nullptr,
+ &m_gss_buffer_out,
+ &gss_result_flags,
+ nullptr);
+ switch (gss_major_status) {
+ case GSS_S_CONTINUE_NEEDED:
+ ldout(cct, 20)
+ << "KrbClientHandler::handle_response() : "
+ "[gss_init_sec_context(GSS_S_CONTINUE_NEEDED)] " << dendl;
+ result = (-EAGAIN);
+ break;
+
+ case GSS_S_COMPLETE:
+ ldout(cct, 20)
+ << "KrbClientHandler::handle_response() : "
+ "[gss_init_sec_context(GSS_S_COMPLETE)] " << dendl;
+ result = 0;
+ break;
+
+ default:
+ auto status_str(gss_auth_show_status(gss_major_status,
+ gss_minor_status));
+ ldout(cct, 0)
+ << "ERROR: KrbClientHandler::handle_response() "
+ "[gss_init_sec_context()] failed! "
+ << gss_major_status << " "
+ << gss_minor_status << " "
+ << status_str
+ << dendl;
+ result = (-EPERM);
+ break;
+ }
+
+ return result;
+}
+
diff --git a/src/auth/krb/KrbClientHandler.hpp b/src/auth/krb/KrbClientHandler.hpp
new file mode 100644
index 00000000..f1546dbb
--- /dev/null
+++ b/src/auth/krb/KrbClientHandler.hpp
@@ -0,0 +1,84 @@
+// -*- 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) 2018 SUSE LLC.
+ * Author: Daniel Oliveira <doliveira@suse.com>
+ *
+ * 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 KRB_CLIENT_HANDLER_HPP
+#define KRB_CLIENT_HANDLER_HPP
+
+#include "auth/AuthClientHandler.h"
+#include "auth/RotatingKeyRing.h"
+
+#include "KrbProtocol.hpp"
+
+#include <gssapi.h>
+#include <gssapi/gssapi_generic.h>
+#include <gssapi/gssapi_krb5.h>
+#include <gssapi/gssapi_ext.h>
+
+
+class CephContext;
+class Keyring;
+
+
+class KrbClientHandler : public AuthClientHandler {
+
+ public:
+ KrbClientHandler(CephContext* ceph_ctx = nullptr)
+ : AuthClientHandler(ceph_ctx) {
+ reset();
+ }
+ ~KrbClientHandler() override;
+
+ KrbClientHandler* clone() const override {
+ return new KrbClientHandler(*this);
+ }
+
+ int get_protocol() const override { return CEPH_AUTH_GSS; }
+ void reset() override {
+ m_gss_client_name = GSS_C_NO_NAME;
+ m_gss_service_name = GSS_C_NO_NAME;
+ m_gss_credentials = GSS_C_NO_CREDENTIAL;
+ m_gss_sec_ctx = GSS_C_NO_CONTEXT;
+ m_gss_buffer_out = {0, 0};
+ }
+
+ void prepare_build_request() override { };
+ int build_request(bufferlist& buff_list) const override;
+ int handle_response(int ret,
+ bufferlist::const_iterator& buff_list,
+ CryptoKey *session_key,
+ std::string *connection_secret) override;
+
+ bool build_rotating_request(bufferlist& buff_list) const override {
+ return false;
+ }
+
+ AuthAuthorizer* build_authorizer(uint32_t service_id) const override;
+ bool need_tickets() override { return false; }
+ void set_global_id(uint64_t guid) override { global_id = guid; }
+
+
+ private:
+ gss_name_t m_gss_client_name;
+ gss_name_t m_gss_service_name;
+ gss_cred_id_t m_gss_credentials;
+ gss_ctx_id_t m_gss_sec_ctx;
+ gss_buffer_desc m_gss_buffer_out;
+
+ protected:
+ void validate_tickets() override { }
+};
+
+#endif //-- KRB_CLIENT_HANDLER_HPP
+
diff --git a/src/auth/krb/KrbProtocol.cpp b/src/auth/krb/KrbProtocol.cpp
new file mode 100644
index 00000000..6988d355
--- /dev/null
+++ b/src/auth/krb/KrbProtocol.cpp
@@ -0,0 +1,86 @@
+// -*- 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) 2018 SUSE LLC.
+ * Author: Daniel Oliveira <doliveira@suse.com>
+ *
+ * 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 "KrbProtocol.hpp"
+
+#include "common/Clock.h"
+#include "common/config.h"
+#include "common/debug.h"
+#include "include/buffer.h"
+
+#define dout_subsys ceph_subsys_auth
+#undef dout_prefix
+#define dout_prefix *_dout << "krb5/gssapi protocol: "
+
+
+std::string gss_auth_show_status(const OM_uint32 gss_major_status,
+ const OM_uint32 gss_minor_status)
+{
+ const std::string STR_DOT(".");
+ const std::string STR_BLANK(" ");
+
+ gss_buffer_desc gss_str_status = {0, nullptr};
+ OM_uint32 gss_maj_status(0);
+ OM_uint32 gss_min_status(0);
+ OM_uint32 gss_ctx_message(-1);
+
+ std::string str_status("");
+
+ const auto gss_complete_status_str_format = [&](const uint32_t gss_status) {
+ if (gss_status == GSS_S_COMPLETE) {
+ std::string str_tmp("");
+ str_tmp.append(reinterpret_cast<char*>(gss_str_status.value),
+ gss_str_status.length);
+ str_tmp += STR_DOT;
+ if (gss_ctx_message != 0) {
+ str_tmp += STR_BLANK;
+ }
+ return str_tmp;
+ }
+ return STR_BLANK;
+ };
+
+ while (gss_ctx_message != 0) {
+ gss_maj_status = gss_display_status(&gss_min_status,
+ gss_major_status,
+ GSS_C_GSS_CODE,
+ GSS_C_NO_OID,
+ &gss_ctx_message,
+ &gss_str_status);
+
+ if (gss_maj_status == GSS_S_COMPLETE) {
+ str_status += gss_complete_status_str_format(gss_maj_status);
+ gss_release_buffer(&gss_min_status, &gss_str_status);
+ }
+ }
+
+ if (gss_major_status == GSS_S_FAILURE) {
+ gss_ctx_message = -1;
+ while (gss_ctx_message != 0) {
+ gss_maj_status = gss_display_status(&gss_min_status,
+ gss_minor_status,
+ GSS_C_MECH_CODE,
+ const_cast<gss_OID>(&GSS_API_KRB5_OID_PTR),
+ &gss_ctx_message,
+ &gss_str_status);
+ if (gss_maj_status == GSS_S_COMPLETE) {
+ str_status += gss_complete_status_str_format(gss_maj_status);
+ gss_release_buffer(&gss_min_status, &gss_str_status);
+ }
+ }
+ }
+ return str_status;
+}
+
diff --git a/src/auth/krb/KrbProtocol.hpp b/src/auth/krb/KrbProtocol.hpp
new file mode 100644
index 00000000..abddb584
--- /dev/null
+++ b/src/auth/krb/KrbProtocol.hpp
@@ -0,0 +1,160 @@
+// -*- 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) 2018 SUSE LLC.
+ * Author: Daniel Oliveira <doliveira@suse.com>
+ *
+ * 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 KRB_PROTOCOL_HPP
+#define KRB_PROTOCOL_HPP
+
+#include "auth/Auth.h"
+
+#include <errno.h>
+#include <gssapi.h>
+#include <gssapi/gssapi_generic.h>
+#include <gssapi/gssapi_krb5.h>
+#include <gssapi/gssapi_ext.h>
+
+#include <map>
+#include <sstream>
+#include <string>
+
+/*
+ Kerberos Version 5 GSS-API Mechanism
+ OID {1.2.840.113554.1.2.2}
+ RFC https://tools.ietf.org/html/rfc1964
+*/
+static const gss_OID_desc GSS_API_KRB5_OID_PTR =
+ { 9, (void *)"\052\206\110\206\367\022\001\002\002" };
+
+/*
+ Kerberos Version 5 GSS-API Mechanism
+ Simple and Protected GSS-API Negotiation Mechanism
+ OID {1.3.6.1.5.5.2}
+ RFC https://tools.ietf.org/html/rfc4178
+*/
+static const gss_OID_desc GSS_API_SPNEGO_OID_PTR =
+ {6, (void *)"\x2b\x06\x01\x05\x05\x02"};
+
+static const std::string KRB_SERVICE_NAME("kerberos/gssapi");
+static const std::string GSS_API_SPNEGO_OID("{1.3.6.1.5.5.2}");
+static const std::string GSS_API_KRB5_OID("{1.2.840.113554.1.2.2}");
+
+enum class GSSAuthenticationRequest {
+ GSS_CRYPTO_ERR = 1,
+ GSS_MUTUAL = 0x100,
+ GSS_TOKEN = 0x200,
+ GSS_REQUEST_MASK = 0x0F00
+};
+
+enum class GSSKeyExchange {
+ USERAUTH_GSSAPI_RESPONSE = 70,
+ USERAUTH_GSSAPI_TOKEN,
+ USERAUTH_GSSAPI_EXCHANGE_COMPLETE,
+ USERAUTH_GSSAPI_ERROR,
+ USERAUTH_GSSAPI_ERRTOK,
+ USERAUTH_GSSAPI_MIC,
+};
+static constexpr auto CEPH_GSS_OIDTYPE(0x07);
+
+struct AuthAuthorizer;
+
+
+class KrbAuthorizer : public AuthAuthorizer {
+
+ public:
+ KrbAuthorizer() : AuthAuthorizer(CEPH_AUTH_GSS) { }
+ ~KrbAuthorizer() = default;
+ bool build_authorizer(const EntityName& entity_name,
+ const uint64_t guid) {
+ uint8_t value = (1);
+
+ using ceph::encode;
+ encode(value, bl, 0);
+ encode(entity_name, bl, 0);
+ encode(guid, bl, 0);
+ return false;
+ }
+
+ bool verify_reply(bufferlist::const_iterator& buff_list,
+ std::string *connection_secret) override {
+ return true;
+ }
+ bool add_challenge(CephContext* ceph_ctx,
+ const bufferlist& buff_list) override {
+ return true;
+ }
+};
+
+class KrbRequest {
+
+ public:
+ void decode(bufferlist::const_iterator& buff_list) {
+ using ceph::decode;
+ decode(m_request_type, buff_list);
+ }
+
+ void encode(bufferlist& buff_list) const {
+ using ceph::encode;
+ encode(m_request_type, buff_list);
+ }
+
+ uint16_t m_request_type;
+};
+WRITE_CLASS_ENCODER(KrbRequest);
+
+class KrbResponse {
+
+ public:
+ void decode(bufferlist::const_iterator& buff_list) {
+ using ceph::decode;
+ decode(m_response_type, buff_list);
+ }
+
+ void encode(bufferlist& buff_list) const {
+ using ceph::encode;
+ encode(m_response_type, buff_list);
+ }
+
+ uint16_t m_response_type;
+};
+WRITE_CLASS_ENCODER(KrbResponse);
+
+class KrbTokenBlob {
+
+ public:
+ void decode(bufferlist::const_iterator& buff_list) {
+ uint8_t value = (0);
+
+ using ceph::decode;
+ decode(value, buff_list);
+ decode(m_token_blob, buff_list);
+ }
+
+ void encode(bufferlist& buff_list) const {
+ uint8_t value = (1);
+
+ using ceph::encode;
+ encode(value, buff_list, 0);
+ encode(m_token_blob, buff_list, 0);
+ }
+
+ bufferlist m_token_blob;
+};
+WRITE_CLASS_ENCODER(KrbTokenBlob);
+
+
+std::string gss_auth_show_status(const OM_uint32 gss_major_status,
+ const OM_uint32 gss_minor_status);
+
+#endif //-- KRB_PROTOCOL_HPP
+
diff --git a/src/auth/krb/KrbServiceHandler.cpp b/src/auth/krb/KrbServiceHandler.cpp
new file mode 100644
index 00000000..94858876
--- /dev/null
+++ b/src/auth/krb/KrbServiceHandler.cpp
@@ -0,0 +1,225 @@
+// -*- 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) 2018 SUSE LLC.
+ * Author: Daniel Oliveira <doliveira@suse.com>
+ *
+ * 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 "KrbServiceHandler.hpp"
+#include "KrbProtocol.hpp"
+#include <errno.h>
+#include <sstream>
+
+#include "common/config.h"
+#include "common/debug.h"
+
+#define dout_subsys ceph_subsys_auth
+#undef dout_prefix
+#define dout_prefix *_dout << "krb5/gssapi service: " << entity_name << " : "
+
+
+int KrbServiceHandler::handle_request(
+ bufferlist::const_iterator& indata,
+ size_t connection_secret_required_length,
+ bufferlist *buff_list,
+ AuthCapsInfo *caps,
+ CryptoKey *session_key,
+ std::string *connection_secret)
+{
+ auto result(0);
+ gss_buffer_desc gss_buffer_in = {0, nullptr};
+ gss_name_t gss_client_name = GSS_C_NO_NAME;
+ gss_OID gss_object_id = {0};
+ OM_uint32 gss_major_status(0);
+ OM_uint32 gss_minor_status(0);
+ OM_uint32 gss_result_flags(0);
+ std::string status_str(" ");
+
+ ldout(cct, 20)
+ << "KrbServiceHandler::handle_request() " << dendl;
+
+ KrbRequest krb_request;
+ KrbTokenBlob krb_token;
+
+ using ceph::decode;
+ decode(krb_request, indata);
+ decode(krb_token, indata);
+
+ gss_buffer_in.length = krb_token.m_token_blob.length();
+ gss_buffer_in.value = krb_token.m_token_blob.c_str();
+
+ ldout(cct, 20)
+ << "KrbClientHandler::handle_request() : Token Blob: "
+ << "\n";
+ krb_token.m_token_blob.hexdump(*_dout);
+ *_dout << dendl;
+
+ if (m_gss_buffer_out.length != 0) {
+ gss_release_buffer(&gss_minor_status,
+ static_cast<gss_buffer_t>(&m_gss_buffer_out));
+ }
+
+ gss_major_status = gss_accept_sec_context(&gss_minor_status,
+ &m_gss_sec_ctx,
+ m_gss_credentials,
+ &gss_buffer_in,
+ GSS_C_NO_CHANNEL_BINDINGS,
+ &gss_client_name,
+ &gss_object_id,
+ &m_gss_buffer_out,
+ &gss_result_flags,
+ nullptr,
+ nullptr);
+ switch (gss_major_status) {
+ case GSS_S_CONTINUE_NEEDED:
+ {
+ ldout(cct, 20)
+ << "KrbServiceHandler::handle_response() : "
+ "[KrbServiceHandler(GSS_S_CONTINUE_NEEDED)] " << dendl;
+ result = 0;
+ break;
+ }
+
+ case GSS_S_COMPLETE:
+ {
+ result = 0;
+ ldout(cct, 20)
+ << "KrbServiceHandler::handle_response() : "
+ "[KrbServiceHandler(GSS_S_COMPLETE)] " << dendl;
+ if (!m_key_server->get_service_caps(entity_name,
+ CEPH_ENTITY_TYPE_MON,
+ *caps)) {
+ result = (-EACCES);
+ ldout(cct, 0)
+ << "KrbServiceHandler::handle_response() : "
+ "ERROR: Could not get MONITOR CAPS : " << entity_name << dendl;
+ } else {
+ if (!caps->caps.c_str()) {
+ result = (-EACCES);
+ ldout(cct, 0)
+ << "KrbServiceHandler::handle_response() : "
+ "ERROR: MONITOR CAPS invalid : " << entity_name << dendl;
+ }
+ }
+ break;
+ }
+
+ default:
+ {
+ status_str = gss_auth_show_status(gss_major_status,
+ gss_minor_status);
+ ldout(cct, 0)
+ << "ERROR: KrbServiceHandler::handle_response() "
+ "[gss_accept_sec_context()] failed! "
+ << gss_major_status << " "
+ << gss_minor_status << " "
+ << status_str
+ << dendl;
+ result = (-EPERM);
+ break;
+ }
+ }
+
+ if (m_gss_buffer_out.length != 0) {
+ KrbResponse krb_response;
+ KrbTokenBlob krb_token;
+ krb_response.m_response_type =
+ static_cast<int>(GSSAuthenticationRequest::GSS_TOKEN);
+
+ using ceph::encode;
+ encode(krb_response, *buff_list);
+
+ krb_token.m_token_blob.append(buffer::create_static(
+ m_gss_buffer_out.length,
+ reinterpret_cast<char*>
+ (m_gss_buffer_out.value)));
+ encode(krb_token, *buff_list);
+ ldout(cct, 20)
+ << "KrbServiceHandler::handle_request() : Token Blob: " << "\n";
+ krb_token.m_token_blob.hexdump(*_dout);
+ *_dout << dendl;
+ }
+ gss_release_name(&gss_minor_status, &gss_client_name);
+ return result;
+}
+
+int KrbServiceHandler::do_start_session(
+ bool is_new_global_id,
+ bufferlist *buff_list,
+ AuthCapsInfo *caps)
+{
+ gss_buffer_desc gss_buffer_in = {0, nullptr};
+ gss_OID gss_object_id = GSS_C_NT_HOSTBASED_SERVICE;
+ gss_OID_set gss_mechs_wanted = GSS_C_NO_OID_SET;
+ OM_uint32 gss_major_status(0);
+ OM_uint32 gss_minor_status(0);
+ std::string gss_service_name(cct->_conf.get_val<std::string>
+ ("gss_target_name"));
+
+ gss_buffer_in.length = gss_service_name.length();
+ gss_buffer_in.value = (const_cast<char*>(gss_service_name.c_str()));
+
+ gss_major_status = gss_import_name(&gss_minor_status,
+ &gss_buffer_in,
+ gss_object_id,
+ &m_gss_service_name);
+ if (gss_major_status != GSS_S_COMPLETE) {
+ auto status_str(gss_auth_show_status(gss_major_status,
+ gss_minor_status));
+ ldout(cct, 0)
+ << "ERROR: KrbServiceHandler::start_session() "
+ "[gss_import_name(gss_client_name)] failed! "
+ << gss_major_status << " "
+ << gss_minor_status << " "
+ << status_str
+ << dendl;
+ }
+
+ gss_major_status = gss_acquire_cred(&gss_minor_status,
+ m_gss_service_name,
+ 0,
+ gss_mechs_wanted,
+ GSS_C_ACCEPT,
+ &m_gss_credentials,
+ nullptr,
+ nullptr);
+ if (gss_major_status != GSS_S_COMPLETE) {
+ auto status_str(gss_auth_show_status(gss_major_status,
+ gss_minor_status));
+ ldout(cct, 0)
+ << "ERROR: KrbServiceHandler::start_session() "
+ "[gss_acquire_cred()] failed! "
+ << gss_major_status << " "
+ << gss_minor_status << " "
+ << status_str
+ << dendl;
+ return (-EPERM);
+ } else {
+ KrbResponse krb_response;
+ krb_response.m_response_type =
+ static_cast<int>(GSSAuthenticationRequest::GSS_MUTUAL);
+
+ using ceph::encode;
+ encode(krb_response, *buff_list);
+ return (CEPH_AUTH_GSS);
+ }
+}
+
+KrbServiceHandler::~KrbServiceHandler()
+{
+ OM_uint32 gss_minor_status(0);
+
+ gss_release_name(&gss_minor_status, &m_gss_service_name);
+ gss_release_cred(&gss_minor_status, &m_gss_credentials);
+ gss_delete_sec_context(&gss_minor_status, &m_gss_sec_ctx, GSS_C_NO_BUFFER);
+ gss_release_buffer(&gss_minor_status, static_cast<gss_buffer_t>(&m_gss_buffer_out));
+}
+
diff --git a/src/auth/krb/KrbServiceHandler.hpp b/src/auth/krb/KrbServiceHandler.hpp
new file mode 100644
index 00000000..ee91baa5
--- /dev/null
+++ b/src/auth/krb/KrbServiceHandler.hpp
@@ -0,0 +1,61 @@
+// -*- 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) 2018 SUSE LLC.
+ * Author: Daniel Oliveira <doliveira@suse.com>
+ *
+ * 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 KRB_SERVICE_HANDLER_HPP
+#define KRB_SERVICE_HANDLER_HPP
+
+#include "auth/AuthServiceHandler.h"
+#include "auth/Auth.h"
+#include "auth/cephx/CephxKeyServer.h"
+
+#include <gssapi.h>
+#include <gssapi/gssapi_generic.h>
+#include <gssapi/gssapi_krb5.h>
+#include <gssapi/gssapi_ext.h>
+
+
+class KrbServiceHandler : public AuthServiceHandler {
+
+ public:
+ explicit KrbServiceHandler(CephContext* ceph_ctx, KeyServer* kserver) :
+ AuthServiceHandler(ceph_ctx),
+ m_gss_buffer_out({0, nullptr}),
+ m_gss_credentials(GSS_C_NO_CREDENTIAL),
+ m_gss_sec_ctx(GSS_C_NO_CONTEXT),
+ m_gss_service_name(GSS_C_NO_NAME),
+ m_key_server(kserver) { }
+ ~KrbServiceHandler();
+ int handle_request(bufferlist::const_iterator& indata,
+ size_t connection_secret_required_length,
+ bufferlist *buff_list,
+ AuthCapsInfo *caps,
+ CryptoKey *session_key,
+ std::string *connection_secret) override;
+
+ private:
+ int do_start_session(bool is_new_global_id,
+ bufferlist *buff_list,
+ AuthCapsInfo *caps) override;
+
+ gss_buffer_desc m_gss_buffer_out;
+ gss_cred_id_t m_gss_credentials;
+ gss_ctx_id_t m_gss_sec_ctx;
+ gss_name_t m_gss_service_name;
+ KeyServer* m_key_server;
+
+};
+
+#endif //-- KRB_SERVICE_HANDLER_HPP
+
diff --git a/src/auth/krb/KrbSessionHandler.hpp b/src/auth/krb/KrbSessionHandler.hpp
new file mode 100644
index 00000000..ee80d790
--- /dev/null
+++ b/src/auth/krb/KrbSessionHandler.hpp
@@ -0,0 +1,37 @@
+// -*- 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) 2018 SUSE LLC.
+ * Author: Daniel Oliveira <doliveira@suse.com>
+ *
+ * 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 KRB_SESSION_HANDLER_HPP
+#define KRB_SESSION_HANDLER_HPP
+
+#include "auth/AuthSessionHandler.h"
+#include "auth/Auth.h"
+
+#include "KrbProtocol.hpp"
+#include <errno.h>
+#include <sstream>
+
+#include "common/config.h"
+#include "include/ceph_features.h"
+#include "msg/Message.h"
+
+#define dout_subsys ceph_subsys_auth
+
+struct KrbSessionHandler : DummyAuthSessionHandler {
+};
+
+#endif //-- KRB_SESSION_HANDLER_HPP
+
+