// -*- 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 * * 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 #include #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(&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(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 (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 ("gss_target_name")); gss_buffer_in.length = gss_service_name.length(); gss_buffer_in.value = (const_cast(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(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(&m_gss_buffer_out)); }