]> git.proxmox.com Git - ceph.git/blob - ceph/src/auth/krb/KrbClientHandler.cpp
import 15.2.0 Octopus source
[ceph.git] / ceph / src / auth / krb / KrbClientHandler.cpp
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (c) 2018 SUSE LLC.
7 * Author: Daniel Oliveira <doliveira@suse.com>
8 *
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.
13 *
14 */
15
16 #include "KrbClientHandler.hpp"
17
18 #include <errno.h>
19 #include <string>
20 #include "KrbProtocol.hpp"
21
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"
27
28 #define dout_subsys ceph_subsys_auth
29 #undef dout_prefix
30 #define dout_prefix *_dout << "krb5/gssapi client request: "
31
32 struct AuthAuthorizer;
33
34 AuthAuthorizer*
35 KrbClientHandler::build_authorizer(uint32_t service_id) const
36 {
37 ldout(cct, 20)
38 << "KrbClientHandler::build_authorizer(): Service: "
39 << ceph_entity_type_name(service_id) << dendl;
40
41 KrbAuthorizer* krb_auth = new KrbAuthorizer();
42 if (krb_auth) {
43 krb_auth->build_authorizer(cct->_conf->name, global_id);
44 }
45 return krb_auth;
46 }
47
48
49 KrbClientHandler::~KrbClientHandler()
50 {
51 OM_uint32 gss_minor_status(0);
52
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));
59 }
60
61
62 int KrbClientHandler::build_request(bufferlist& buff_list) const
63 {
64 ldout(cct, 20)
65 << "KrbClientHandler::build_request() " << dendl;
66
67 KrbTokenBlob krb_token;
68 KrbRequest krb_request;
69
70 krb_request.m_request_type =
71 static_cast<int>(GSSAuthenticationRequest::GSS_TOKEN);
72
73 using ceph::encode;
74 encode(krb_request, buff_list);
75
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)));
81
82 encode(krb_token, buff_list);
83 ldout(cct, 20)
84 << "KrbClientHandler::build_request() : Token Blob: " << "\n";
85 krb_token.m_token_blob.hexdump(*_dout);
86 *_dout << dendl;
87 }
88 return 0;
89 }
90
91
92 int KrbClientHandler::handle_response(
93 int ret,
94 bufferlist::const_iterator& buff_list,
95 CryptoKey *session_key,
96 std::string *connection_secret)
97 {
98 auto result(ret);
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 |
104 GSS_C_INTEG_FLAG);
105 OM_uint32 gss_result_flags(0);
106
107 ldout(cct, 20)
108 << "KrbClientHandler::handle_response() " << dendl;
109
110 if (result < 0) {
111 return result;
112 }
113
114 gss_mechs_wanted.elements = const_cast<gss_OID>(&GSS_API_SPNEGO_OID_PTR);
115 gss_mechs_wanted.count = 1;
116
117 KrbResponse krb_response;
118
119 using ceph::decode;
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());
124
125 gss_buffer_in.length = krb_client_name.length();
126 gss_buffer_in.value = (const_cast<char*>(krb_client_name.c_str()));
127
128 if (cct->_conf->name.get_type() == CEPH_ENTITY_TYPE_CLIENT) {
129 gss_major_status = gss_import_name(&gss_minor_status,
130 &gss_buffer_in,
131 krb_client_type,
132 &m_gss_client_name);
133 if (gss_major_status != GSS_S_COMPLETE) {
134 auto status_str(gss_auth_show_status(gss_major_status,
135 gss_minor_status));
136 ldout(cct, 0)
137 << "ERROR: KrbClientHandler::handle_response() "
138 "[gss_import_name(gss_client_name)] failed! "
139 << gss_major_status << " "
140 << gss_minor_status << " "
141 << status_str
142 << dendl;
143 }
144 }
145
146 gss_major_status = gss_acquire_cred(&gss_minor_status,
147 m_gss_client_name,
148 0,
149 &gss_mechs_wanted,
150 GSS_C_INITIATE,
151 &m_gss_credentials,
152 nullptr,
153 nullptr);
154 if (gss_major_status != GSS_S_COMPLETE) {
155 auto status_str(gss_auth_show_status(gss_major_status,
156 gss_minor_status));
157 ldout(cct, 20)
158 << "ERROR: KrbClientHandler::handle_response() "
159 "[gss_acquire_cred()] failed! "
160 << gss_major_status << " "
161 << gss_minor_status << " "
162 << status_str
163 << dendl;
164 return (-EACCES);
165 }
166
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()));
173
174 gss_major_status = gss_import_name(&gss_minor_status,
175 &krb_input_name_buff,
176 krb_input_type,
177 &m_gss_service_name);
178 if (gss_major_status != GSS_S_COMPLETE) {
179 auto status_str(gss_auth_show_status(gss_major_status,
180 gss_minor_status));
181 ldout(cct, 0)
182 << "ERROR: KrbClientHandler::handle_response() "
183 "[gss_import_name(gss_service_name)] failed! "
184 << gss_major_status << " "
185 << gss_minor_status << " "
186 << status_str
187 << dendl;
188 }
189 } else {
190 KrbTokenBlob krb_token;
191
192 using ceph::decode;
193 decode(krb_token, buff_list);
194 ldout(cct, 20)
195 << "KrbClientHandler::handle_response() : Token Blob: " << "\n";
196 krb_token.m_token_blob.hexdump(*_dout);
197 *_dout << dendl;
198
199 gss_buffer_in.length = krb_token.m_token_blob.length();
200 gss_buffer_in.value = krb_token.m_token_blob.c_str();
201 }
202
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));
207 }
208
209 gss_major_status = gss_init_sec_context(&gss_minor_status,
210 m_gss_credentials,
211 &m_gss_sec_ctx,
212 m_gss_service_name,
213 gss_mech_type,
214 gss_wanted_flags,
215 0,
216 nullptr,
217 &gss_buffer_in,
218 nullptr,
219 &m_gss_buffer_out,
220 &gss_result_flags,
221 nullptr);
222 switch (gss_major_status) {
223 case GSS_S_CONTINUE_NEEDED:
224 ldout(cct, 20)
225 << "KrbClientHandler::handle_response() : "
226 "[gss_init_sec_context(GSS_S_CONTINUE_NEEDED)] " << dendl;
227 result = (-EAGAIN);
228 break;
229
230 case GSS_S_COMPLETE:
231 ldout(cct, 20)
232 << "KrbClientHandler::handle_response() : "
233 "[gss_init_sec_context(GSS_S_COMPLETE)] " << dendl;
234 result = 0;
235 break;
236
237 default:
238 auto status_str(gss_auth_show_status(gss_major_status,
239 gss_minor_status));
240 ldout(cct, 0)
241 << "ERROR: KrbClientHandler::handle_response() "
242 "[gss_init_sec_context()] failed! "
243 << gss_major_status << " "
244 << gss_minor_status << " "
245 << status_str
246 << dendl;
247 result = (-EACCES);
248 break;
249 }
250
251 return result;
252 }
253