summaryrefslogtreecommitdiffstats
path: root/src/auth/krb/KrbServiceHandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/auth/krb/KrbServiceHandler.cpp')
-rw-r--r--src/auth/krb/KrbServiceHandler.cpp225
1 files changed, 225 insertions, 0 deletions
diff --git a/src/auth/krb/KrbServiceHandler.cpp b/src/auth/krb/KrbServiceHandler.cpp
new file mode 100644
index 000000000..c2ca3bbf2
--- /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 = (-EACCES);
+ 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 (-EACCES);
+ } 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));
+}
+