1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (c) 2018 SUSE LLC.
7 * Author: Daniel Oliveira <doliveira@suse.com>
9 * This is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License version 2.1, as published by the Free Software
12 * Foundation. See file COPYING.
16 #include "KrbClientHandler.hpp"
20 #include "KrbProtocol.hpp"
22 #include "auth/KeyRing.h"
23 #include "include/random.h"
24 #include "common/ceph_context.h"
25 #include "common/config.h"
26 #include "common/dout.h"
28 #define dout_subsys ceph_subsys_auth
30 #define dout_prefix *_dout << "krb5/gssapi client request: "
32 struct AuthAuthorizer
;
35 KrbClientHandler::build_authorizer(uint32_t service_id
) const
38 << "KrbClientHandler::build_authorizer(): Service: "
39 << ceph_entity_type_name(service_id
) << dendl
;
41 KrbAuthorizer
* krb_auth
= new KrbAuthorizer();
43 krb_auth
->build_authorizer(cct
->_conf
->name
, global_id
);
49 KrbClientHandler::~KrbClientHandler()
51 OM_uint32
gss_minor_status(0);
53 gss_release_name(&gss_minor_status
, &m_gss_client_name
);
54 gss_release_name(&gss_minor_status
, &m_gss_service_name
);
55 gss_release_cred(&gss_minor_status
, &m_gss_credentials
);
56 gss_delete_sec_context(&gss_minor_status
, &m_gss_sec_ctx
, GSS_C_NO_BUFFER
);
57 gss_release_buffer(&gss_minor_status
,
58 static_cast<gss_buffer_t
>(&m_gss_buffer_out
));
62 int KrbClientHandler::build_request(bufferlist
& buff_list
) const
65 << "KrbClientHandler::build_request() " << dendl
;
67 KrbTokenBlob krb_token
;
68 KrbRequest krb_request
;
70 krb_request
.m_request_type
=
71 static_cast<int>(GSSAuthenticationRequest::GSS_TOKEN
);
74 encode(krb_request
, buff_list
);
76 if (m_gss_buffer_out
.length
!= 0) {
77 krb_token
.m_token_blob
.append(buffer::create_static(
78 m_gss_buffer_out
.length
,
79 reinterpret_cast<char*>
80 (m_gss_buffer_out
.value
)));
82 encode(krb_token
, buff_list
);
84 << "KrbClientHandler::build_request() : Token Blob: " << "\n";
85 krb_token
.m_token_blob
.hexdump(*_dout
);
92 int KrbClientHandler::handle_response(
94 bufferlist::const_iterator
& buff_list
,
95 CryptoKey
*session_key
,
96 std::string
*connection_secret
)
99 gss_buffer_desc gss_buffer_in
= {0, nullptr};
100 gss_OID_set_desc gss_mechs_wanted
= {0, nullptr};
101 OM_uint32
gss_major_status(0);
102 OM_uint32
gss_minor_status(0);
103 OM_uint32
gss_wanted_flags(GSS_C_MUTUAL_FLAG
|
105 OM_uint32
gss_result_flags(0);
108 << "KrbClientHandler::handle_response() " << dendl
;
114 gss_mechs_wanted
.elements
= const_cast<gss_OID
>(&GSS_API_SPNEGO_OID_PTR
);
115 gss_mechs_wanted
.count
= 1;
117 KrbResponse krb_response
;
120 decode(krb_response
, buff_list
);
121 if (m_gss_credentials
== GSS_C_NO_CREDENTIAL
) {
122 gss_OID krb_client_type
= GSS_C_NT_USER_NAME
;
123 std::string
krb_client_name(cct
->_conf
->name
.to_str());
125 gss_buffer_in
.length
= krb_client_name
.length();
126 gss_buffer_in
.value
= (const_cast<char*>(krb_client_name
.c_str()));
128 if (cct
->_conf
->name
.get_type() == CEPH_ENTITY_TYPE_CLIENT
) {
129 gss_major_status
= gss_import_name(&gss_minor_status
,
133 if (gss_major_status
!= GSS_S_COMPLETE
) {
134 auto status_str(gss_auth_show_status(gss_major_status
,
137 << "ERROR: KrbClientHandler::handle_response() "
138 "[gss_import_name(gss_client_name)] failed! "
139 << gss_major_status
<< " "
140 << gss_minor_status
<< " "
146 gss_major_status
= gss_acquire_cred(&gss_minor_status
,
154 if (gss_major_status
!= GSS_S_COMPLETE
) {
155 auto status_str(gss_auth_show_status(gss_major_status
,
158 << "ERROR: KrbClientHandler::handle_response() "
159 "[gss_acquire_cred()] failed! "
160 << gss_major_status
<< " "
161 << gss_minor_status
<< " "
167 gss_buffer_desc krb_input_name_buff
= {0, nullptr};
168 gss_OID krb_input_type
= GSS_C_NT_HOSTBASED_SERVICE
;
169 std::string
gss_target_name(cct
->_conf
.get_val
<std::string
>
170 ("gss_target_name"));
171 krb_input_name_buff
.length
= gss_target_name
.length();
172 krb_input_name_buff
.value
= (const_cast<char*>(gss_target_name
.c_str()));
174 gss_major_status
= gss_import_name(&gss_minor_status
,
175 &krb_input_name_buff
,
177 &m_gss_service_name
);
178 if (gss_major_status
!= GSS_S_COMPLETE
) {
179 auto status_str(gss_auth_show_status(gss_major_status
,
182 << "ERROR: KrbClientHandler::handle_response() "
183 "[gss_import_name(gss_service_name)] failed! "
184 << gss_major_status
<< " "
185 << gss_minor_status
<< " "
190 KrbTokenBlob krb_token
;
193 decode(krb_token
, buff_list
);
195 << "KrbClientHandler::handle_response() : Token Blob: " << "\n";
196 krb_token
.m_token_blob
.hexdump(*_dout
);
199 gss_buffer_in
.length
= krb_token
.m_token_blob
.length();
200 gss_buffer_in
.value
= krb_token
.m_token_blob
.c_str();
203 const gss_OID gss_mech_type
= gss_mechs_wanted
.elements
;
204 if (m_gss_buffer_out
.length
!= 0) {
205 gss_release_buffer(&gss_minor_status
,
206 static_cast<gss_buffer_t
>(&m_gss_buffer_out
));
209 gss_major_status
= gss_init_sec_context(&gss_minor_status
,
222 switch (gss_major_status
) {
223 case GSS_S_CONTINUE_NEEDED
:
225 << "KrbClientHandler::handle_response() : "
226 "[gss_init_sec_context(GSS_S_CONTINUE_NEEDED)] " << dendl
;
232 << "KrbClientHandler::handle_response() : "
233 "[gss_init_sec_context(GSS_S_COMPLETE)] " << dendl
;
238 auto status_str(gss_auth_show_status(gss_major_status
,
241 << "ERROR: KrbClientHandler::handle_response() "
242 "[gss_init_sec_context()] failed! "
243 << gss_major_status
<< " "
244 << gss_minor_status
<< " "