Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : Kerberos backend for GENSEC
5 :
6 : Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
7 : Copyright (C) Stefan Metzmacher <metze@samba.org> 2004-2005
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 :
20 : You should have received a copy of the GNU General Public License
21 : along with this program. If not, see <http://www.gnu.org/licenses/>.
22 : */
23 :
24 : #include "includes.h"
25 : #include <tevent.h>
26 : #include "lib/util/tevent_ntstatus.h"
27 : #include "lib/events/events.h"
28 : #include "system/kerberos.h"
29 : #include "system/gssapi.h"
30 : #include "auth/kerberos/kerberos.h"
31 : #include "librpc/gen_ndr/krb5pac.h"
32 : #include "auth/auth.h"
33 : #include <ldb.h>
34 : #include "auth/auth_sam.h"
35 : #include "librpc/gen_ndr/dcerpc.h"
36 : #include "auth/credentials/credentials.h"
37 : #include "auth/credentials/credentials_krb5.h"
38 : #include "auth/gensec/gensec.h"
39 : #include "auth/gensec/gensec_internal.h"
40 : #include "auth/gensec/gensec_proto.h"
41 : #include "auth/gensec/gensec_toplevel_proto.h"
42 : #include "param/param.h"
43 : #include "auth/session_proto.h"
44 : #include "gensec_gssapi.h"
45 : #include "lib/util/util_net.h"
46 : #include "auth/kerberos/pac_utils.h"
47 : #include "auth/kerberos/gssapi_helper.h"
48 : #include "lib/util/smb_strtox.h"
49 :
50 : #ifndef gss_mech_spnego
51 : gss_OID_desc spnego_mech_oid_desc =
52 : { 6, discard_const_p(void, "\x2b\x06\x01\x05\x05\x02") };
53 : #define gss_mech_spnego (&spnego_mech_oid_desc)
54 : #endif
55 :
56 : _PUBLIC_ NTSTATUS gensec_gssapi_init(TALLOC_CTX *);
57 :
58 : static size_t gensec_gssapi_max_input_size(struct gensec_security *gensec_security);
59 : static size_t gensec_gssapi_max_wrapped_size(struct gensec_security *gensec_security);
60 : static size_t gensec_gssapi_sig_size(struct gensec_security *gensec_security, size_t data_size);
61 :
62 79400 : static int gensec_gssapi_destructor(struct gensec_gssapi_state *gensec_gssapi_state)
63 : {
64 3221 : OM_uint32 min_stat;
65 :
66 79400 : if (gensec_gssapi_state->delegated_cred_handle != GSS_C_NO_CREDENTIAL) {
67 96 : gss_release_cred(&min_stat,
68 : &gensec_gssapi_state->delegated_cred_handle);
69 : }
70 :
71 79400 : if (gensec_gssapi_state->gssapi_context != GSS_C_NO_CONTEXT) {
72 61247 : gss_delete_sec_context(&min_stat,
73 : &gensec_gssapi_state->gssapi_context,
74 : GSS_C_NO_BUFFER);
75 : }
76 :
77 79400 : if (gensec_gssapi_state->server_name != GSS_C_NO_NAME) {
78 29938 : gss_release_name(&min_stat,
79 : &gensec_gssapi_state->server_name);
80 : }
81 79400 : if (gensec_gssapi_state->client_name != GSS_C_NO_NAME) {
82 31334 : gss_release_name(&min_stat,
83 : &gensec_gssapi_state->client_name);
84 : }
85 :
86 79400 : return 0;
87 : }
88 :
89 29996 : static NTSTATUS gensec_gssapi_setup_server_principal(TALLOC_CTX *mem_ctx,
90 : const char *target_principal,
91 : const char *service,
92 : const char *hostname,
93 : const char *realm,
94 : const gss_OID mech,
95 : char **pserver_principal,
96 : gss_name_t *pserver_name)
97 : {
98 29996 : char *server_principal = NULL;
99 1042 : gss_buffer_desc name_token;
100 1042 : gss_OID name_type;
101 29996 : OM_uint32 maj_stat, min_stat = 0;
102 :
103 29996 : if (target_principal != NULL) {
104 219 : server_principal = talloc_strdup(mem_ctx, target_principal);
105 219 : name_type = GSS_C_NULL_OID;
106 : } else {
107 29777 : server_principal = talloc_asprintf(mem_ctx,
108 : "%s/%s@%s",
109 : service, hostname, realm);
110 29777 : name_type = GSS_C_NT_USER_NAME;
111 : }
112 29996 : if (server_principal == NULL) {
113 0 : return NT_STATUS_NO_MEMORY;
114 : }
115 :
116 29996 : name_token.value = (uint8_t *)server_principal;
117 29996 : name_token.length = strlen(server_principal);
118 :
119 29996 : maj_stat = gss_import_name(&min_stat,
120 : &name_token,
121 : name_type,
122 : pserver_name);
123 29996 : if (maj_stat) {
124 0 : DBG_WARNING("GSS Import name of %s failed: %s\n",
125 : server_principal,
126 : gssapi_error_string(mem_ctx,
127 : maj_stat,
128 : min_stat,
129 : mech));
130 0 : TALLOC_FREE(server_principal);
131 0 : return NT_STATUS_INVALID_PARAMETER;
132 : }
133 :
134 29996 : *pserver_principal = server_principal;
135 :
136 29996 : return NT_STATUS_OK;
137 : }
138 :
139 79420 : static NTSTATUS gensec_gssapi_start(struct gensec_security *gensec_security)
140 : {
141 3226 : struct gensec_gssapi_state *gensec_gssapi_state;
142 3226 : krb5_error_code ret;
143 : #ifdef SAMBA4_USES_HEIMDAL
144 3226 : const char *realm;
145 : #endif
146 :
147 79420 : gensec_gssapi_state = talloc_zero(gensec_security, struct gensec_gssapi_state);
148 79420 : if (!gensec_gssapi_state) {
149 0 : return NT_STATUS_NO_MEMORY;
150 : }
151 :
152 79420 : gensec_security->private_data = gensec_gssapi_state;
153 :
154 79420 : gensec_gssapi_state->gssapi_context = GSS_C_NO_CONTEXT;
155 :
156 79420 : if (gensec_security->channel_bindings != NULL) {
157 196 : gensec_gssapi_state->_input_chan_bindings.initiator_addrtype =
158 196 : gensec_security->channel_bindings->initiator_addrtype;
159 196 : gensec_gssapi_state->_input_chan_bindings.initiator_address.value =
160 196 : gensec_security->channel_bindings->initiator_address.data;
161 196 : gensec_gssapi_state->_input_chan_bindings.initiator_address.length =
162 196 : gensec_security->channel_bindings->initiator_address.length;
163 :
164 196 : gensec_gssapi_state->_input_chan_bindings.acceptor_addrtype =
165 196 : gensec_security->channel_bindings->acceptor_addrtype;
166 196 : gensec_gssapi_state->_input_chan_bindings.acceptor_address.value =
167 196 : gensec_security->channel_bindings->acceptor_address.data;
168 196 : gensec_gssapi_state->_input_chan_bindings.acceptor_address.length =
169 196 : gensec_security->channel_bindings->acceptor_address.length;
170 :
171 196 : gensec_gssapi_state->_input_chan_bindings.application_data.value =
172 196 : gensec_security->channel_bindings->application_data.data;
173 196 : gensec_gssapi_state->_input_chan_bindings.application_data.length =
174 196 : gensec_security->channel_bindings->application_data.length;
175 :
176 196 : gensec_gssapi_state->input_chan_bindings =
177 196 : &gensec_gssapi_state->_input_chan_bindings;
178 : } else {
179 79224 : gensec_gssapi_state->input_chan_bindings = GSS_C_NO_CHANNEL_BINDINGS;
180 : }
181 :
182 79420 : gensec_gssapi_state->server_name = GSS_C_NO_NAME;
183 79420 : gensec_gssapi_state->client_name = GSS_C_NO_NAME;
184 :
185 79420 : gensec_gssapi_state->gss_want_flags = 0;
186 79420 : gensec_gssapi_state->expire_time = GENSEC_EXPIRE_TIME_INFINITY;
187 :
188 79420 : if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "delegation_by_kdc_policy", true)) {
189 79420 : gensec_gssapi_state->gss_want_flags |= GSS_C_DELEG_POLICY_FLAG;
190 : }
191 79420 : if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "mutual", true)) {
192 79420 : gensec_gssapi_state->gss_want_flags |= GSS_C_MUTUAL_FLAG;
193 : }
194 79420 : if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "delegation", false)) {
195 0 : gensec_gssapi_state->gss_want_flags |= GSS_C_DELEG_FLAG;
196 : }
197 79420 : if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "replay", true)) {
198 79420 : gensec_gssapi_state->gss_want_flags |= GSS_C_REPLAY_FLAG;
199 : }
200 79420 : if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "sequence", true)) {
201 79420 : gensec_gssapi_state->gss_want_flags |= GSS_C_SEQUENCE_FLAG;
202 : }
203 :
204 79420 : if (gensec_security->want_features & GENSEC_FEATURE_SESSION_KEY) {
205 33413 : gensec_gssapi_state->gss_want_flags |= GSS_C_INTEG_FLAG;
206 : }
207 79420 : if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
208 24190 : gensec_gssapi_state->gss_want_flags |= GSS_C_INTEG_FLAG;
209 : }
210 79420 : if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
211 22770 : gensec_gssapi_state->gss_want_flags |= GSS_C_INTEG_FLAG;
212 22770 : gensec_gssapi_state->gss_want_flags |= GSS_C_CONF_FLAG;
213 : }
214 79420 : if (gensec_security->want_features & GENSEC_FEATURE_DCE_STYLE) {
215 8343 : gensec_gssapi_state->gss_want_flags |= GSS_C_DCE_STYLE;
216 : }
217 :
218 79420 : gensec_gssapi_state->gss_got_flags = 0;
219 :
220 79420 : switch (gensec_security->ops->auth_type) {
221 0 : case DCERPC_AUTH_TYPE_SPNEGO:
222 0 : gensec_gssapi_state->gss_oid = gss_mech_spnego;
223 0 : break;
224 79420 : case DCERPC_AUTH_TYPE_KRB5:
225 : default:
226 79420 : gensec_gssapi_state->gss_oid =
227 : discard_const_p(void, gss_mech_krb5);
228 79420 : break;
229 : }
230 :
231 82646 : ret = smb_krb5_init_context(gensec_gssapi_state,
232 79420 : gensec_security->settings->lp_ctx,
233 : &gensec_gssapi_state->smb_krb5_context);
234 79420 : if (ret) {
235 0 : DEBUG(1,("gensec_gssapi_start: smb_krb5_init_context failed (%s)\n",
236 : error_message(ret)));
237 0 : talloc_free(gensec_gssapi_state);
238 0 : return NT_STATUS_INTERNAL_ERROR;
239 : }
240 :
241 79420 : gensec_gssapi_state->client_cred = NULL;
242 79420 : gensec_gssapi_state->server_cred = NULL;
243 :
244 79420 : gensec_gssapi_state->delegated_cred_handle = GSS_C_NO_CREDENTIAL;
245 :
246 79420 : gensec_gssapi_state->sasl = false;
247 79420 : gensec_gssapi_state->sasl_state = STAGE_GSS_NEG;
248 79420 : gensec_gssapi_state->sasl_protection = 0;
249 :
250 3226 : gensec_gssapi_state->max_wrap_buf_size
251 79420 : = gensec_setting_int(gensec_security->settings, "gensec_gssapi", "max wrap buf size", 65536);
252 79420 : gensec_gssapi_state->gss_exchange_count = 0;
253 79420 : gensec_gssapi_state->sig_size = 0;
254 :
255 79420 : talloc_set_destructor(gensec_gssapi_state, gensec_gssapi_destructor);
256 :
257 : #ifdef SAMBA4_USES_HEIMDAL
258 58886 : realm = lpcfg_realm(gensec_security->settings->lp_ctx);
259 58886 : if (realm != NULL) {
260 58886 : ret = gsskrb5_set_default_realm(realm);
261 58886 : if (ret) {
262 0 : DEBUG(1,("gensec_gssapi_start: gsskrb5_set_default_realm failed\n"));
263 0 : talloc_free(gensec_gssapi_state);
264 0 : return NT_STATUS_INTERNAL_ERROR;
265 : }
266 : }
267 :
268 : /* don't do DNS lookups of any kind, it might/will fail for a netbios name */
269 58886 : ret = gsskrb5_set_dns_canonicalize(false);
270 58886 : if (ret) {
271 0 : DEBUG(1,("gensec_gssapi_start: gsskrb5_set_dns_canonicalize failed\n"));
272 0 : talloc_free(gensec_gssapi_state);
273 0 : return NT_STATUS_INTERNAL_ERROR;
274 : }
275 : #endif
276 79420 : return NT_STATUS_OK;
277 : }
278 :
279 48017 : static NTSTATUS gensec_gssapi_server_start(struct gensec_security *gensec_security)
280 : {
281 2184 : NTSTATUS nt_status;
282 2184 : int ret;
283 2184 : struct gensec_gssapi_state *gensec_gssapi_state;
284 2184 : struct cli_credentials *machine_account;
285 2184 : struct gssapi_creds_container *gcc;
286 :
287 48017 : nt_status = gensec_gssapi_start(gensec_security);
288 48017 : if (!NT_STATUS_IS_OK(nt_status)) {
289 0 : return nt_status;
290 : }
291 :
292 48017 : gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
293 :
294 48017 : machine_account = gensec_get_credentials(gensec_security);
295 :
296 48017 : if (!machine_account) {
297 0 : DEBUG(3, ("No machine account credentials specified\n"));
298 0 : return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
299 : } else {
300 50201 : ret = cli_credentials_get_server_gss_creds(machine_account,
301 48017 : gensec_security->settings->lp_ctx, &gcc);
302 48017 : if (ret) {
303 0 : DEBUG(1, ("Acquiring acceptor credentials failed: %s\n",
304 : error_message(ret)));
305 0 : return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
306 : }
307 : }
308 :
309 48017 : gensec_gssapi_state->server_cred = gcc;
310 48017 : return NT_STATUS_OK;
311 :
312 : }
313 :
314 121 : static NTSTATUS gensec_gssapi_sasl_server_start(struct gensec_security *gensec_security)
315 : {
316 0 : NTSTATUS nt_status;
317 0 : struct gensec_gssapi_state *gensec_gssapi_state;
318 121 : nt_status = gensec_gssapi_server_start(gensec_security);
319 :
320 121 : if (NT_STATUS_IS_OK(nt_status)) {
321 121 : gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
322 121 : gensec_gssapi_state->sasl = true;
323 : }
324 121 : return nt_status;
325 : }
326 :
327 60393 : static NTSTATUS gensec_gssapi_client_creds(struct gensec_security *gensec_security,
328 : struct tevent_context *ev)
329 : {
330 1929 : struct gensec_gssapi_state *gensec_gssapi_state;
331 1929 : struct gssapi_creds_container *gcc;
332 60393 : struct cli_credentials *creds = gensec_get_credentials(gensec_security);
333 1929 : const char *error_string;
334 1929 : int ret;
335 :
336 60393 : gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
337 :
338 : /* Only run this the first time the update() call is made */
339 60393 : if (gensec_gssapi_state->client_cred) {
340 28990 : return NT_STATUS_OK;
341 : }
342 :
343 32445 : ret = cli_credentials_get_client_gss_creds(creds,
344 : ev,
345 31403 : gensec_security->settings->lp_ctx, &gcc, &error_string);
346 31403 : switch (ret) {
347 28948 : case 0:
348 29990 : break;
349 0 : case EINVAL:
350 0 : DEBUG(3, ("Cannot obtain client GSS credentials we need to contact %s : %s\n", gensec_gssapi_state->target_principal, error_string));
351 1413 : return NT_STATUS_INVALID_PARAMETER;
352 173 : case KRB5KDC_ERR_PREAUTH_FAILED:
353 : case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
354 : case KRB5KRB_AP_ERR_BAD_INTEGRITY:
355 173 : DEBUG(1, ("Wrong username or password: %s\n", error_string));
356 173 : return NT_STATUS_LOGON_FAILURE;
357 23 : case KRB5KDC_ERR_CLIENT_REVOKED:
358 23 : DEBUG(1, ("Account locked out: %s\n", error_string));
359 23 : return NT_STATUS_ACCOUNT_LOCKED_OUT;
360 1214 : case KRB5_REALM_UNKNOWN:
361 : case KRB5_KDC_UNREACH:
362 1214 : DEBUG(3, ("Cannot reach a KDC we require to contact %s : %s\n", gensec_gssapi_state->target_principal, error_string));
363 1214 : return NT_STATUS_NO_LOGON_SERVERS;
364 0 : case KRB5_CC_NOTFOUND:
365 : case KRB5_CC_END:
366 0 : DEBUG(2, ("Error obtaining ticket we require to contact %s: (possibly due to clock skew between us and the KDC) %s\n", gensec_gssapi_state->target_principal, error_string));
367 0 : return NT_STATUS_TIME_DIFFERENCE_AT_DC;
368 3 : default:
369 3 : DEBUG(1, ("Acquiring initiator credentials failed: %s\n", error_string));
370 3 : return NT_STATUS_UNSUCCESSFUL;
371 : }
372 :
373 29990 : gensec_gssapi_state->client_cred = gcc;
374 29990 : if (!talloc_reference(gensec_gssapi_state, gcc)) {
375 0 : return NT_STATUS_NO_MEMORY;
376 : }
377 :
378 29990 : return NT_STATUS_OK;
379 : }
380 :
381 41089 : static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_security)
382 : {
383 1048 : struct gensec_gssapi_state *gensec_gssapi_state;
384 41089 : struct cli_credentials *creds = gensec_get_credentials(gensec_security);
385 1048 : NTSTATUS nt_status;
386 :
387 41089 : nt_status = gensec_kerberos_possible(gensec_security);
388 41089 : if (!NT_STATUS_IS_OK(nt_status)) {
389 9686 : char *target_name = NULL;
390 9686 : char *cred_name = NULL;
391 :
392 9686 : target_name = gensec_get_unparsed_target_principal(gensec_security,
393 : gensec_security);
394 9686 : cred_name = cli_credentials_get_unparsed_name(creds,
395 : gensec_security);
396 :
397 9686 : DBG_NOTICE("Not using kerberos to %s as %s: %s\n",
398 : target_name, cred_name, nt_errstr(nt_status));
399 :
400 9686 : TALLOC_FREE(target_name);
401 9686 : TALLOC_FREE(cred_name);
402 9686 : return nt_status;
403 : }
404 :
405 31403 : nt_status = gensec_gssapi_start(gensec_security);
406 31403 : if (!NT_STATUS_IS_OK(nt_status)) {
407 0 : return nt_status;
408 : }
409 :
410 31403 : gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
411 :
412 : #ifdef HAVE_CLIENT_GSS_C_CHANNEL_BOUND_FLAG
413 : /*
414 : * We can only use GSS_C_CHANNEL_BOUND_FLAG if the kerberos library
415 : * supports that in order to add KERB_AP_OPTIONS_CBT.
416 : *
417 : * See:
418 : * https://github.com/heimdal/heimdal/pull/1234
419 : * https://github.com/krb5/krb5/pull/1329
420 : */
421 23639 : if (!(gensec_security->want_features & GENSEC_FEATURE_CB_OPTIONAL)) {
422 23607 : gensec_gssapi_state->gss_want_flags |= GSS_C_CHANNEL_BOUND_FLAG;
423 : }
424 : #endif
425 :
426 31403 : if (cli_credentials_get_impersonate_principal(creds)) {
427 45 : gensec_gssapi_state->gss_want_flags &= ~(GSS_C_DELEG_FLAG|GSS_C_DELEG_POLICY_FLAG);
428 : }
429 :
430 31403 : return NT_STATUS_OK;
431 : }
432 :
433 139 : static NTSTATUS gensec_gssapi_sasl_client_start(struct gensec_security *gensec_security)
434 : {
435 0 : NTSTATUS nt_status;
436 0 : struct gensec_gssapi_state *gensec_gssapi_state;
437 139 : nt_status = gensec_gssapi_client_start(gensec_security);
438 :
439 139 : if (NT_STATUS_IS_OK(nt_status)) {
440 139 : gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
441 139 : gensec_gssapi_state->sasl = true;
442 : }
443 139 : return nt_status;
444 : }
445 :
446 96216 : static NTSTATUS gensec_gssapi_update_internal(struct gensec_security *gensec_security,
447 : TALLOC_CTX *out_mem_ctx,
448 : struct tevent_context *ev,
449 : const DATA_BLOB in, DATA_BLOB *out)
450 : {
451 2913 : struct gensec_gssapi_state *gensec_gssapi_state
452 96216 : = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
453 2913 : NTSTATUS nt_status;
454 2913 : OM_uint32 maj_stat, min_stat;
455 2913 : OM_uint32 min_stat2;
456 96216 : gss_buffer_desc input_token = { 0, NULL };
457 96216 : gss_buffer_desc output_token = { 0, NULL };
458 96216 : struct cli_credentials *cli_creds = gensec_get_credentials(gensec_security);
459 96216 : const char *target_principal = gensec_get_target_principal(gensec_security);
460 96216 : const char *hostname = gensec_get_target_hostname(gensec_security);
461 96216 : const char *service = gensec_get_target_service(gensec_security);
462 96216 : gss_OID gss_oid_p = NULL;
463 96216 : OM_uint32 time_req = 0;
464 96216 : OM_uint32 time_rec = 0;
465 2913 : struct timeval tv;
466 :
467 96216 : time_req = gensec_setting_int(gensec_security->settings,
468 : "gensec_gssapi", "requested_life_time",
469 : time_req);
470 :
471 96216 : input_token.length = in.length;
472 96216 : input_token.value = in.data;
473 :
474 96216 : switch (gensec_gssapi_state->sasl_state) {
475 95871 : case STAGE_GSS_NEG:
476 : {
477 95871 : switch (gensec_security->gensec_role) {
478 60393 : case GENSEC_CLIENT:
479 : {
480 60393 : const char *client_realm = NULL;
481 : #ifdef SAMBA4_USES_HEIMDAL
482 1929 : struct gsskrb5_send_to_kdc send_to_kdc;
483 1929 : krb5_error_code ret;
484 : #else
485 14898 : bool fallback = false;
486 : #endif
487 :
488 60393 : nt_status = gensec_gssapi_client_creds(gensec_security, ev);
489 60393 : if (!NT_STATUS_IS_OK(nt_status)) {
490 1413 : return nt_status;
491 : }
492 :
493 : #ifdef SAMBA4_USES_HEIMDAL
494 44331 : send_to_kdc.func = smb_krb5_send_and_recv_func;
495 44331 : send_to_kdc.ptr = ev;
496 :
497 44331 : min_stat = gsskrb5_set_send_to_kdc(&send_to_kdc);
498 44331 : if (min_stat) {
499 0 : DEBUG(1,("gensec_gssapi_update: gsskrb5_set_send_to_kdc failed\n"));
500 0 : return NT_STATUS_INTERNAL_ERROR;
501 : }
502 : #endif
503 :
504 : /*
505 : * With credentials for
506 : * administrator@FOREST1.EXAMPLE.COM this patch changes
507 : * the target_principal for the ldap service of host
508 : * dc2.forest2.example.com from
509 : *
510 : * ldap/dc2.forest2.example.com@FOREST1.EXAMPLE.COM
511 : *
512 : * to
513 : *
514 : * ldap/dc2.forest2.example.com@FOREST2.EXAMPLE.COM
515 : *
516 : * Typically
517 : * ldap/dc2.forest2.example.com@FOREST1.EXAMPLE.COM
518 : * should be used in order to allow the KDC of
519 : * FOREST1.EXAMPLE.COM to generate a referral ticket
520 : * for krbtgt/FOREST2.EXAMPLE.COM@FOREST1.EXAMPLE.COM.
521 : *
522 : * The problem is that KDCs only return such referral
523 : * tickets if there's a forest trust between
524 : * FOREST1.EXAMPLE.COM and FOREST2.EXAMPLE.COM. If
525 : * there's only an external domain trust between
526 : * FOREST1.EXAMPLE.COM and FOREST2.EXAMPLE.COM the KDC
527 : * of FOREST1.EXAMPLE.COM will respond with
528 : * S_PRINCIPAL_UNKNOWN when being asked for
529 : * ldap/dc2.forest2.example.com@FOREST1.EXAMPLE.COM.
530 : *
531 : * In the case of an external trust the client can
532 : * still ask explicitly for
533 : * krbtgt/FOREST2.EXAMPLE.COM@FOREST1.EXAMPLE.COM and
534 : * the KDC of FOREST1.EXAMPLE.COM will generate it.
535 : *
536 : * From there the client can use the
537 : * krbtgt/FOREST2.EXAMPLE.COM@FOREST1.EXAMPLE.COM
538 : * ticket and ask a KDC of FOREST2.EXAMPLE.COM for a
539 : * service ticket for
540 : * ldap/dc2.forest2.example.com@FOREST2.EXAMPLE.COM.
541 : *
542 : * With Heimdal we'll get the fallback on
543 : * S_PRINCIPAL_UNKNOWN behavior when we pass
544 : * ldap/dc2.forest2.example.com@FOREST2.EXAMPLE.COM as
545 : * target principal. As _krb5_get_cred_kdc_any() first
546 : * calls get_cred_kdc_referral() (which always starts
547 : * with the client realm) and falls back to
548 : * get_cred_kdc_capath() (which starts with the given
549 : * realm).
550 : *
551 : * MIT krb5 only tries the given realm of the target
552 : * principal, if we want to autodetect support for
553 : * transitive forest trusts, would have to do the
554 : * fallback ourself.
555 : */
556 58980 : client_realm = cli_credentials_get_realm(cli_creds);
557 : #ifndef SAMBA4_USES_HEIMDAL
558 14649 : if (gensec_gssapi_state->server_name == NULL) {
559 7499 : nt_status = gensec_gssapi_setup_server_principal(gensec_gssapi_state,
560 : target_principal,
561 : service,
562 : hostname,
563 : client_realm,
564 : gensec_gssapi_state->gss_oid,
565 : &gensec_gssapi_state->target_principal,
566 : &gensec_gssapi_state->server_name);
567 7499 : if (!NT_STATUS_IS_OK(nt_status)) {
568 0 : return nt_status;
569 : }
570 :
571 7499 : maj_stat = gss_init_sec_context(&min_stat,
572 7499 : gensec_gssapi_state->client_cred->creds,
573 : &gensec_gssapi_state->gssapi_context,
574 : gensec_gssapi_state->server_name,
575 : gensec_gssapi_state->gss_oid,
576 : gensec_gssapi_state->gss_want_flags,
577 : time_req,
578 : gensec_gssapi_state->input_chan_bindings,
579 : &input_token,
580 : &gss_oid_p,
581 : &output_token,
582 : &gensec_gssapi_state->gss_got_flags, /* ret flags */
583 : &time_rec);
584 7499 : if (maj_stat != GSS_S_FAILURE) {
585 7492 : goto init_sec_context_done;
586 : }
587 7 : if (min_stat != (OM_uint32)KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN) {
588 0 : goto init_sec_context_done;
589 : }
590 7 : if (target_principal != NULL) {
591 0 : goto init_sec_context_done;
592 : }
593 :
594 7 : fallback = true;
595 7 : TALLOC_FREE(gensec_gssapi_state->target_principal);
596 7 : gss_release_name(&min_stat2, &gensec_gssapi_state->server_name);
597 : }
598 : #endif /* !SAMBA4_USES_HEIMDAL */
599 51488 : if (gensec_gssapi_state->server_name == NULL) {
600 22498 : const char *server_realm = NULL;
601 :
602 22498 : server_realm = smb_krb5_get_realm_from_hostname(gensec_gssapi_state,
603 : hostname,
604 : client_realm);
605 22498 : if (server_realm == NULL) {
606 0 : return NT_STATUS_NO_MEMORY;
607 : }
608 :
609 : #ifndef SAMBA4_USES_HEIMDAL
610 14 : if (fallback &&
611 7 : strequal(client_realm, server_realm)) {
612 1 : goto init_sec_context_done;
613 : }
614 : #endif /* !SAMBA4_USES_HEIMDAL */
615 :
616 22497 : nt_status = gensec_gssapi_setup_server_principal(gensec_gssapi_state,
617 : target_principal,
618 : service,
619 : hostname,
620 : server_realm,
621 : gensec_gssapi_state->gss_oid,
622 : &gensec_gssapi_state->target_principal,
623 : &gensec_gssapi_state->server_name);
624 22497 : if (!NT_STATUS_IS_OK(nt_status)) {
625 0 : return nt_status;
626 : }
627 : }
628 :
629 53416 : maj_stat = gss_init_sec_context(&min_stat,
630 51487 : gensec_gssapi_state->client_cred->creds,
631 : &gensec_gssapi_state->gssapi_context,
632 44331 : gensec_gssapi_state->server_name,
633 : gensec_gssapi_state->gss_oid,
634 : gensec_gssapi_state->gss_want_flags,
635 : time_req,
636 : gensec_gssapi_state->input_chan_bindings,
637 : &input_token,
638 : &gss_oid_p,
639 : &output_token,
640 : &gensec_gssapi_state->gss_got_flags, /* ret flags */
641 : &time_rec);
642 51487 : goto init_sec_context_done;
643 : /* JUMP! */
644 58980 : init_sec_context_done:
645 58980 : if (gss_oid_p) {
646 58977 : gensec_gssapi_state->gss_oid = gss_oid_p;
647 : }
648 :
649 : #ifdef SAMBA4_USES_HEIMDAL
650 44331 : send_to_kdc.func = smb_krb5_send_and_recv_func;
651 44331 : send_to_kdc.ptr = NULL;
652 :
653 44331 : ret = gsskrb5_set_send_to_kdc(&send_to_kdc);
654 44331 : if (ret) {
655 0 : DEBUG(1,("gensec_gssapi_update: gsskrb5_set_send_to_kdc failed\n"));
656 0 : return NT_STATUS_INTERNAL_ERROR;
657 : }
658 : #endif
659 58980 : break;
660 : }
661 35478 : case GENSEC_SERVER:
662 : {
663 36462 : maj_stat = gss_accept_sec_context(&min_stat,
664 : &gensec_gssapi_state->gssapi_context,
665 35478 : gensec_gssapi_state->server_cred->creds,
666 : &input_token,
667 : gensec_gssapi_state->input_chan_bindings,
668 : &gensec_gssapi_state->client_name,
669 : &gss_oid_p,
670 : &output_token,
671 : &gensec_gssapi_state->gss_got_flags,
672 : &time_rec,
673 : &gensec_gssapi_state->delegated_cred_handle);
674 35478 : if (gss_oid_p) {
675 34885 : gensec_gssapi_state->gss_oid = gss_oid_p;
676 : }
677 : #ifdef GSS_C_CHANNEL_BOUND_FLAG
678 35478 : if (maj_stat == GSS_S_COMPLETE &&
679 31303 : gensec_security->channel_bindings != NULL &&
680 69 : !(gensec_security->want_features & GENSEC_FEATURE_CB_OPTIONAL) &&
681 36 : !(gensec_gssapi_state->gss_got_flags & GSS_C_CHANNEL_BOUND_FLAG))
682 : {
683 : /*
684 : * If we require valid channel bindings
685 : * we need to check the client provided
686 : * them.
687 : *
688 : * We detect this if
689 : * GSS_C_CHANNEL_BOUND_FLAG is given.
690 : *
691 : * Recent heimdal and MIT releases support this
692 : * with older releases (e.g. MIT > 1.19).
693 : *
694 : * It means client with zero channel bindings
695 : * on a server with non-zero channel bindings
696 : * won't generate GSS_S_BAD_BINDINGS directly
697 : * unless KERB_AP_OPTIONS_CBT was also
698 : * provides by the client.
699 : *
700 : * So we need to convert a missing
701 : * GSS_C_CHANNEL_BOUND_FLAG into
702 : * GSS_S_BAD_BINDINGS by default
703 : * (unless GENSEC_FEATURE_CB_OPTIONAL is given).
704 : */
705 12 : maj_stat = GSS_S_BAD_BINDINGS;
706 12 : min_stat = 0;
707 : }
708 : #endif /* GSS_C_CHANNEL_BOUND_FLAG */
709 :
710 34494 : break;
711 : }
712 0 : default:
713 0 : return NT_STATUS_INVALID_PARAMETER;
714 :
715 : }
716 :
717 94458 : gensec_gssapi_state->gss_exchange_count++;
718 :
719 94458 : if (maj_stat == GSS_S_COMPLETE) {
720 60281 : *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length);
721 60281 : gss_release_buffer(&min_stat2, &output_token);
722 :
723 60281 : if (gensec_gssapi_state->gss_got_flags & GSS_C_DELEG_FLAG &&
724 58089 : gensec_gssapi_state->delegated_cred_handle != GSS_C_NO_CREDENTIAL) {
725 29945 : DEBUG(5, ("gensec_gssapi: credentials were delegated\n"));
726 : } else {
727 30336 : DEBUG(5, ("gensec_gssapi: NO credentials were delegated\n"));
728 : }
729 :
730 60281 : tv = timeval_current_ofs(time_rec, 0);
731 60281 : gensec_gssapi_state->expire_time = timeval_to_nttime(&tv);
732 :
733 : /* We may have been invoked as SASL, so there
734 : * is more work to do */
735 60281 : if (gensec_gssapi_state->sasl) {
736 230 : gensec_gssapi_state->sasl_state = STAGE_SASL_SSF_NEG;
737 230 : return NT_STATUS_MORE_PROCESSING_REQUIRED;
738 : } else {
739 60051 : gensec_gssapi_state->sasl_state = STAGE_DONE;
740 :
741 60051 : if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
742 40183 : DEBUG(5, ("GSSAPI Connection will be cryptographically sealed\n"));
743 19868 : } else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
744 19514 : DEBUG(5, ("GSSAPI Connection will be cryptographically signed\n"));
745 : } else {
746 354 : DEBUG(5, ("GSSAPI Connection will have no cryptographic protection\n"));
747 : }
748 :
749 60051 : return NT_STATUS_OK;
750 : }
751 34177 : } else if (maj_stat == GSS_S_CONTINUE_NEEDED) {
752 34084 : *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length);
753 34084 : gss_release_buffer(&min_stat2, &output_token);
754 :
755 34084 : return NT_STATUS_MORE_PROCESSING_REQUIRED;
756 93 : } else if (maj_stat == GSS_S_BAD_BINDINGS) {
757 64 : DBG_WARNING("Got GSS_S_BAD_BINDINGS\n");
758 64 : return NT_STATUS_BAD_BINDINGS;
759 29 : } else if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
760 0 : gss_cred_id_t creds = NULL;
761 0 : gss_name_t name;
762 0 : gss_buffer_desc buffer;
763 0 : OM_uint32 lifetime = 0;
764 0 : gss_cred_usage_t usage;
765 0 : const char *role = NULL;
766 :
767 0 : switch (gensec_security->gensec_role) {
768 0 : case GENSEC_CLIENT:
769 0 : creds = gensec_gssapi_state->client_cred->creds;
770 0 : role = "client";
771 0 : break;
772 0 : case GENSEC_SERVER:
773 0 : creds = gensec_gssapi_state->server_cred->creds;
774 0 : role = "server";
775 0 : break;
776 : }
777 :
778 0 : DBG_ERR("GSS %s Update(krb5)(%d) failed, credentials "
779 : "expired during GSSAPI handshake!\n",
780 : role,
781 : gensec_gssapi_state->gss_exchange_count);
782 :
783 0 : maj_stat = gss_inquire_cred(&min_stat,
784 : creds,
785 : &name, &lifetime, &usage, NULL);
786 :
787 0 : if (maj_stat == GSS_S_COMPLETE) {
788 0 : const char *usage_string = NULL;
789 0 : switch (usage) {
790 0 : case GSS_C_BOTH:
791 0 : usage_string = "GSS_C_BOTH";
792 0 : break;
793 0 : case GSS_C_ACCEPT:
794 0 : usage_string = "GSS_C_ACCEPT";
795 0 : break;
796 0 : case GSS_C_INITIATE:
797 0 : usage_string = "GSS_C_INITIATE";
798 0 : break;
799 : }
800 0 : maj_stat = gss_display_name(&min_stat, name, &buffer, NULL);
801 0 : if (maj_stat) {
802 0 : buffer.value = NULL;
803 0 : buffer.length = 0;
804 : }
805 0 : if (lifetime > 0) {
806 0 : DEBUG(0, ("GSSAPI gss_inquire_cred indicates expiry of %*.*s in %u sec for %s\n",
807 : (int)buffer.length, (int)buffer.length, (char *)buffer.value,
808 : lifetime, usage_string));
809 : } else {
810 0 : DEBUG(0, ("GSSAPI gss_inquire_cred indicates %*.*s has already expired for %s\n",
811 : (int)buffer.length, (int)buffer.length, (char *)buffer.value,
812 : usage_string));
813 : }
814 0 : gss_release_buffer(&min_stat, &buffer);
815 0 : gss_release_name(&min_stat, &name);
816 0 : } else if (maj_stat != GSS_S_COMPLETE) {
817 0 : DEBUG(0, ("inquiry of credential lifetime via GSSAPI gss_inquire_cred failed: %s\n",
818 : gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
819 : }
820 0 : return NT_STATUS_INVALID_PARAMETER;
821 29 : } else if (smb_gss_oid_equal(gensec_gssapi_state->gss_oid,
822 : gss_mech_krb5)) {
823 29 : switch (min_stat) {
824 0 : case (OM_uint32)KRB5KRB_AP_ERR_TKT_NYV:
825 0 : DEBUG(1, ("Error with ticket to contact %s: possible clock skew between us and the KDC or target server: %s\n",
826 : gensec_gssapi_state->target_principal,
827 : gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
828 0 : return NT_STATUS_TIME_DIFFERENCE_AT_DC; /* Make SPNEGO ignore us, we can't go any further here */
829 0 : case (OM_uint32)KRB5KRB_AP_ERR_TKT_EXPIRED:
830 0 : DEBUG(1, ("Error with ticket to contact %s: ticket is expired, possible clock skew between us and the KDC or target server: %s\n",
831 : gensec_gssapi_state->target_principal,
832 : gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
833 0 : return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */
834 0 : case (OM_uint32)KRB5_KDC_UNREACH:
835 0 : DEBUG(3, ("Cannot reach a KDC we require in order to obtain a ticket to %s: %s\n",
836 : gensec_gssapi_state->target_principal,
837 : gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
838 0 : return NT_STATUS_NO_LOGON_SERVERS; /* Make SPNEGO ignore us, we can't go any further here */
839 12 : case (OM_uint32)KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN:
840 12 : DEBUG(3, ("Server %s is not registered with our KDC: %s\n",
841 : gensec_gssapi_state->target_principal,
842 : gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
843 12 : return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */
844 0 : case (OM_uint32)KRB5KRB_AP_ERR_MSG_TYPE:
845 : /* garbage input, possibly from the auto-mech detection */
846 0 : return NT_STATUS_INVALID_PARAMETER;
847 17 : default:
848 17 : DEBUG(1, ("GSS %s Update(krb5)(%d) Update failed: %s\n",
849 : gensec_security->gensec_role == GENSEC_CLIENT ? "client" : "server",
850 : gensec_gssapi_state->gss_exchange_count,
851 : gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
852 17 : return NT_STATUS_LOGON_FAILURE;
853 : }
854 : } else {
855 0 : DEBUG(1, ("GSS %s Update(%d) failed: %s\n",
856 : gensec_security->gensec_role == GENSEC_CLIENT ? "client" : "server",
857 : gensec_gssapi_state->gss_exchange_count,
858 : gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
859 0 : return NT_STATUS_LOGON_FAILURE;
860 : }
861 0 : break;
862 : }
863 :
864 : /* These last two stages are only done if we were invoked as SASL */
865 230 : case STAGE_SASL_SSF_NEG:
866 : {
867 230 : switch (gensec_security->gensec_role) {
868 115 : case GENSEC_CLIENT:
869 : {
870 0 : uint8_t maxlength_proposed[4];
871 0 : uint8_t maxlength_accepted[4];
872 0 : uint8_t security_supported;
873 0 : int conf_state;
874 0 : gss_qop_t qop_state;
875 115 : input_token.length = in.length;
876 115 : input_token.value = in.data;
877 :
878 : /* As a client, we have just send a
879 : * zero-length blob to the server (after the
880 : * normal GSSAPI exchange), and it has replied
881 : * with it's SASL negotiation */
882 :
883 115 : maj_stat = gss_unwrap(&min_stat,
884 90 : gensec_gssapi_state->gssapi_context,
885 : &input_token,
886 : &output_token,
887 : &conf_state,
888 : &qop_state);
889 115 : if (GSS_ERROR(maj_stat)) {
890 0 : DEBUG(1, ("gensec_gssapi_update: GSS UnWrap of SASL protection negotiation failed: %s\n",
891 : gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
892 0 : return NT_STATUS_ACCESS_DENIED;
893 : }
894 :
895 115 : if (output_token.length < 4) {
896 0 : gss_release_buffer(&min_stat, &output_token);
897 0 : return NT_STATUS_INVALID_PARAMETER;
898 : }
899 :
900 115 : memcpy(maxlength_proposed, output_token.value, 4);
901 115 : gss_release_buffer(&min_stat, &output_token);
902 :
903 : /* first byte is the proposed security */
904 115 : security_supported = maxlength_proposed[0];
905 115 : maxlength_proposed[0] = '\0';
906 :
907 : /* Rest is the proposed max wrap length */
908 115 : gensec_gssapi_state->max_wrap_buf_size = MIN(RIVAL(maxlength_proposed, 0),
909 : gensec_gssapi_state->max_wrap_buf_size);
910 115 : gensec_gssapi_state->sasl_protection = 0;
911 115 : if (security_supported & NEG_SEAL) {
912 21 : if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
913 21 : gensec_gssapi_state->sasl_protection |= NEG_SEAL;
914 : }
915 : }
916 115 : if (security_supported & NEG_SIGN) {
917 21 : if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
918 21 : gensec_gssapi_state->sasl_protection |= NEG_SIGN;
919 : }
920 : }
921 115 : if (security_supported & NEG_NONE) {
922 115 : gensec_gssapi_state->sasl_protection |= NEG_NONE;
923 : }
924 115 : if (gensec_gssapi_state->sasl_protection == 0) {
925 0 : DEBUG(1, ("Remote server does not support unprotected connections\n"));
926 0 : return NT_STATUS_ACCESS_DENIED;
927 : }
928 :
929 : /* Send back the negotiated max length */
930 :
931 115 : RSIVAL(maxlength_accepted, 0, gensec_gssapi_state->max_wrap_buf_size);
932 :
933 115 : maxlength_accepted[0] = gensec_gssapi_state->sasl_protection;
934 :
935 115 : input_token.value = maxlength_accepted;
936 115 : input_token.length = sizeof(maxlength_accepted);
937 :
938 115 : maj_stat = gss_wrap(&min_stat,
939 90 : gensec_gssapi_state->gssapi_context,
940 : false,
941 : GSS_C_QOP_DEFAULT,
942 : &input_token,
943 : &conf_state,
944 : &output_token);
945 115 : if (GSS_ERROR(maj_stat)) {
946 0 : DEBUG(1, ("GSS Update(SSF_NEG): GSS Wrap failed: %s\n",
947 : gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
948 0 : return NT_STATUS_ACCESS_DENIED;
949 : }
950 :
951 115 : *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length);
952 115 : gss_release_buffer(&min_stat, &output_token);
953 :
954 : /* quirk: This changes the value that gensec_have_feature returns, to be that after SASL negotiation */
955 115 : gensec_gssapi_state->sasl_state = STAGE_DONE;
956 :
957 115 : if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
958 21 : DEBUG(3, ("SASL/GSSAPI Connection to server will be cryptographically sealed\n"));
959 94 : } else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
960 0 : DEBUG(3, ("SASL/GSSAPI Connection to server will be cryptographically signed\n"));
961 : } else {
962 94 : DEBUG(3, ("SASL/GSSAPI Connection to server will have no cryptographic protection\n"));
963 : }
964 :
965 115 : return NT_STATUS_OK;
966 : }
967 115 : case GENSEC_SERVER:
968 : {
969 0 : uint8_t maxlength_proposed[4];
970 115 : uint8_t security_supported = 0x0;
971 0 : int conf_state;
972 :
973 : /* As a server, we have just been sent a zero-length blob (note this, but it isn't fatal) */
974 115 : if (in.length != 0) {
975 0 : DEBUG(1, ("SASL/GSSAPI: client sent non-zero length starting SASL negotiation!\n"));
976 : }
977 :
978 : /* Give the client some idea what we will support */
979 :
980 115 : RSIVAL(maxlength_proposed, 0, gensec_gssapi_state->max_wrap_buf_size);
981 : /* first byte is the proposed security */
982 115 : maxlength_proposed[0] = '\0';
983 :
984 115 : gensec_gssapi_state->sasl_protection = 0;
985 115 : if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
986 21 : security_supported |= NEG_SEAL;
987 : }
988 115 : if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
989 21 : security_supported |= NEG_SIGN;
990 : }
991 115 : if (security_supported == 0) {
992 : /* If we don't support anything, this must be 0 */
993 94 : RSIVAL(maxlength_proposed, 0, 0x0);
994 : }
995 :
996 : /* TODO: We may not wish to support this */
997 115 : security_supported |= NEG_NONE;
998 115 : maxlength_proposed[0] = security_supported;
999 :
1000 115 : input_token.value = maxlength_proposed;
1001 115 : input_token.length = sizeof(maxlength_proposed);
1002 :
1003 115 : maj_stat = gss_wrap(&min_stat,
1004 90 : gensec_gssapi_state->gssapi_context,
1005 : false,
1006 : GSS_C_QOP_DEFAULT,
1007 : &input_token,
1008 : &conf_state,
1009 : &output_token);
1010 115 : if (GSS_ERROR(maj_stat)) {
1011 0 : DEBUG(1, ("GSS Update(SSF_NEG): GSS Wrap failed: %s\n",
1012 : gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
1013 0 : return NT_STATUS_ACCESS_DENIED;
1014 : }
1015 :
1016 115 : *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length);
1017 115 : gss_release_buffer(&min_stat, &output_token);
1018 :
1019 115 : gensec_gssapi_state->sasl_state = STAGE_SASL_SSF_ACCEPT;
1020 115 : return NT_STATUS_MORE_PROCESSING_REQUIRED;
1021 : }
1022 0 : default:
1023 0 : return NT_STATUS_INVALID_PARAMETER;
1024 :
1025 : }
1026 : }
1027 : /* This is s server-only stage */
1028 115 : case STAGE_SASL_SSF_ACCEPT:
1029 : {
1030 0 : uint8_t maxlength_accepted[4];
1031 0 : uint8_t security_accepted;
1032 0 : int conf_state;
1033 0 : gss_qop_t qop_state;
1034 115 : input_token.length = in.length;
1035 115 : input_token.value = in.data;
1036 :
1037 115 : maj_stat = gss_unwrap(&min_stat,
1038 90 : gensec_gssapi_state->gssapi_context,
1039 : &input_token,
1040 : &output_token,
1041 : &conf_state,
1042 : &qop_state);
1043 115 : if (GSS_ERROR(maj_stat)) {
1044 0 : DEBUG(1, ("gensec_gssapi_update: GSS UnWrap of SASL protection negotiation failed: %s\n",
1045 : gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
1046 0 : return NT_STATUS_ACCESS_DENIED;
1047 : }
1048 :
1049 115 : if (output_token.length < 4) {
1050 0 : gss_release_buffer(&min_stat, &output_token);
1051 0 : return NT_STATUS_INVALID_PARAMETER;
1052 : }
1053 :
1054 115 : memcpy(maxlength_accepted, output_token.value, 4);
1055 115 : gss_release_buffer(&min_stat, &output_token);
1056 :
1057 : /* first byte is the proposed security */
1058 115 : security_accepted = maxlength_accepted[0];
1059 115 : maxlength_accepted[0] = '\0';
1060 :
1061 : /* Rest is the proposed max wrap length */
1062 115 : gensec_gssapi_state->max_wrap_buf_size = MIN(RIVAL(maxlength_accepted, 0),
1063 : gensec_gssapi_state->max_wrap_buf_size);
1064 :
1065 115 : gensec_gssapi_state->sasl_protection = 0;
1066 115 : if (security_accepted & NEG_SEAL) {
1067 21 : if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
1068 0 : DEBUG(1, ("Remote client wanted seal, but gensec refused\n"));
1069 0 : return NT_STATUS_ACCESS_DENIED;
1070 : }
1071 21 : gensec_gssapi_state->sasl_protection |= NEG_SEAL;
1072 : }
1073 115 : if (security_accepted & NEG_SIGN) {
1074 21 : if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
1075 0 : DEBUG(1, ("Remote client wanted sign, but gensec refused\n"));
1076 0 : return NT_STATUS_ACCESS_DENIED;
1077 : }
1078 21 : gensec_gssapi_state->sasl_protection |= NEG_SIGN;
1079 : }
1080 115 : if (security_accepted & NEG_NONE) {
1081 115 : gensec_gssapi_state->sasl_protection |= NEG_NONE;
1082 : }
1083 :
1084 : /* quirk: This changes the value that gensec_have_feature returns, to be that after SASL negotiation */
1085 115 : gensec_gssapi_state->sasl_state = STAGE_DONE;
1086 115 : if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
1087 21 : DEBUG(5, ("SASL/GSSAPI Connection from client will be cryptographically sealed\n"));
1088 94 : } else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
1089 0 : DEBUG(5, ("SASL/GSSAPI Connection from client will be cryptographically signed\n"));
1090 : } else {
1091 94 : DEBUG(5, ("SASL/GSSAPI Connection from client will have no cryptographic protection\n"));
1092 : }
1093 :
1094 115 : *out = data_blob(NULL, 0);
1095 115 : return NT_STATUS_OK;
1096 : }
1097 0 : default:
1098 0 : return NT_STATUS_INVALID_PARAMETER;
1099 : }
1100 : }
1101 :
1102 : struct gensec_gssapi_update_state {
1103 : NTSTATUS status;
1104 : DATA_BLOB out;
1105 : };
1106 :
1107 96216 : static struct tevent_req *gensec_gssapi_update_send(TALLOC_CTX *mem_ctx,
1108 : struct tevent_context *ev,
1109 : struct gensec_security *gensec_security,
1110 : const DATA_BLOB in)
1111 : {
1112 96216 : struct tevent_req *req = NULL;
1113 96216 : struct gensec_gssapi_update_state *state = NULL;
1114 2913 : NTSTATUS status;
1115 :
1116 96216 : req = tevent_req_create(mem_ctx, &state,
1117 : struct gensec_gssapi_update_state);
1118 96216 : if (req == NULL) {
1119 0 : return NULL;
1120 : }
1121 :
1122 96216 : status = gensec_gssapi_update_internal(gensec_security,
1123 : state, ev, in,
1124 96216 : &state->out);
1125 96216 : state->status = status;
1126 96216 : if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1127 34429 : tevent_req_done(req);
1128 34429 : return tevent_req_post(req, ev);
1129 : }
1130 61787 : if (tevent_req_nterror(req, status)) {
1131 1506 : return tevent_req_post(req, ev);
1132 : }
1133 :
1134 60281 : tevent_req_done(req);
1135 60281 : return tevent_req_post(req, ev);
1136 : }
1137 :
1138 96216 : static NTSTATUS gensec_gssapi_update_recv(struct tevent_req *req,
1139 : TALLOC_CTX *out_mem_ctx,
1140 : DATA_BLOB *out)
1141 : {
1142 2913 : struct gensec_gssapi_update_state *state =
1143 96216 : tevent_req_data(req,
1144 : struct gensec_gssapi_update_state);
1145 2913 : NTSTATUS status;
1146 :
1147 96216 : *out = data_blob_null;
1148 :
1149 96216 : if (tevent_req_is_nterror(req, &status)) {
1150 1506 : tevent_req_received(req);
1151 1506 : return status;
1152 : }
1153 :
1154 94710 : *out = state->out;
1155 94710 : talloc_steal(out_mem_ctx, state->out.data);
1156 94710 : status = state->status;
1157 94710 : tevent_req_received(req);
1158 94710 : return status;
1159 : }
1160 :
1161 1017584 : static NTSTATUS gensec_gssapi_wrap(struct gensec_security *gensec_security,
1162 : TALLOC_CTX *mem_ctx,
1163 : const DATA_BLOB *in,
1164 : DATA_BLOB *out)
1165 : {
1166 930 : struct gensec_gssapi_state *gensec_gssapi_state
1167 1017584 : = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1168 930 : OM_uint32 maj_stat, min_stat;
1169 930 : gss_buffer_desc input_token, output_token;
1170 930 : int conf_state;
1171 1017584 : input_token.length = in->length;
1172 1017584 : input_token.value = in->data;
1173 :
1174 1019444 : maj_stat = gss_wrap(&min_stat,
1175 744051 : gensec_gssapi_state->gssapi_context,
1176 1017584 : gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL),
1177 : GSS_C_QOP_DEFAULT,
1178 : &input_token,
1179 : &conf_state,
1180 : &output_token);
1181 1017584 : if (GSS_ERROR(maj_stat)) {
1182 0 : DEBUG(1, ("gensec_gssapi_wrap: GSS Wrap failed: %s\n",
1183 : gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
1184 0 : return NT_STATUS_ACCESS_DENIED;
1185 : }
1186 :
1187 1017584 : *out = data_blob_talloc(mem_ctx, output_token.value, output_token.length);
1188 1017584 : gss_release_buffer(&min_stat, &output_token);
1189 :
1190 1017584 : if (gensec_gssapi_state->sasl) {
1191 12 : size_t max_wrapped_size = gensec_gssapi_max_wrapped_size(gensec_security);
1192 12 : if (max_wrapped_size < out->length) {
1193 0 : DEBUG(1, ("gensec_gssapi_wrap: when wrapped, INPUT data (%u) is grew to be larger than SASL negotiated maximum output size (%u > %u)\n",
1194 : (unsigned)in->length,
1195 : (unsigned)out->length,
1196 : (unsigned int)max_wrapped_size));
1197 0 : return NT_STATUS_INVALID_PARAMETER;
1198 : }
1199 : }
1200 :
1201 1017584 : if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
1202 1017048 : && !conf_state) {
1203 0 : return NT_STATUS_ACCESS_DENIED;
1204 : }
1205 1017584 : return NT_STATUS_OK;
1206 : }
1207 :
1208 1017603 : static NTSTATUS gensec_gssapi_unwrap(struct gensec_security *gensec_security,
1209 : TALLOC_CTX *mem_ctx,
1210 : const DATA_BLOB *in,
1211 : DATA_BLOB *out)
1212 : {
1213 930 : struct gensec_gssapi_state *gensec_gssapi_state
1214 1017603 : = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1215 930 : OM_uint32 maj_stat, min_stat;
1216 930 : gss_buffer_desc input_token, output_token;
1217 930 : int conf_state;
1218 930 : gss_qop_t qop_state;
1219 1017603 : input_token.length = in->length;
1220 1017603 : input_token.value = in->data;
1221 :
1222 1017603 : if (gensec_gssapi_state->sasl) {
1223 12 : size_t max_wrapped_size = gensec_gssapi_max_wrapped_size(gensec_security);
1224 12 : if (max_wrapped_size < in->length) {
1225 0 : DEBUG(1, ("gensec_gssapi_unwrap: WRAPPED data is larger than SASL negotiated maximum size\n"));
1226 0 : return NT_STATUS_INVALID_PARAMETER;
1227 : }
1228 : }
1229 :
1230 : /*
1231 : * FIXME: input_message_buffer is marked const, but gss_unwrap() may
1232 : * modify it (see calls to rrc_rotate() in _gssapi_unwrap_cfx()).
1233 : */
1234 1018533 : maj_stat = gss_unwrap(&min_stat,
1235 744064 : gensec_gssapi_state->gssapi_context,
1236 : &input_token,
1237 : &output_token,
1238 : &conf_state,
1239 : &qop_state);
1240 1017603 : if (GSS_ERROR(maj_stat)) {
1241 0 : DEBUG(1, ("gensec_gssapi_unwrap: GSS UnWrap failed: %s\n",
1242 : gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
1243 0 : return NT_STATUS_ACCESS_DENIED;
1244 : }
1245 :
1246 1017603 : *out = data_blob_talloc(mem_ctx, output_token.value, output_token.length);
1247 1017603 : gss_release_buffer(&min_stat, &output_token);
1248 :
1249 1017603 : if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
1250 1017067 : && !conf_state) {
1251 0 : return NT_STATUS_ACCESS_DENIED;
1252 : }
1253 1017603 : return NT_STATUS_OK;
1254 : }
1255 :
1256 : /* Find out the maximum input size negotiated on this connection */
1257 :
1258 34191 : static size_t gensec_gssapi_max_input_size(struct gensec_security *gensec_security)
1259 : {
1260 244 : struct gensec_gssapi_state *gensec_gssapi_state
1261 34191 : = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1262 244 : OM_uint32 maj_stat, min_stat;
1263 244 : OM_uint32 max_input_size;
1264 :
1265 60009 : maj_stat = gss_wrap_size_limit(&min_stat,
1266 25574 : gensec_gssapi_state->gssapi_context,
1267 34191 : gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL),
1268 : GSS_C_QOP_DEFAULT,
1269 34191 : gensec_gssapi_state->max_wrap_buf_size,
1270 : &max_input_size);
1271 34191 : if (GSS_ERROR(maj_stat)) {
1272 0 : TALLOC_CTX *mem_ctx = talloc_new(NULL);
1273 0 : DEBUG(1, ("gensec_gssapi_max_input_size: determining signature size with gss_wrap_size_limit failed: %s\n",
1274 : gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
1275 0 : talloc_free(mem_ctx);
1276 0 : return 0;
1277 : }
1278 :
1279 34191 : return max_input_size;
1280 : }
1281 :
1282 : /* Find out the maximum output size negotiated on this connection */
1283 34215 : static size_t gensec_gssapi_max_wrapped_size(struct gensec_security *gensec_security)
1284 : {
1285 34215 : struct gensec_gssapi_state *gensec_gssapi_state = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);;
1286 33971 : return gensec_gssapi_state->max_wrap_buf_size;
1287 : }
1288 :
1289 339018 : static NTSTATUS gensec_gssapi_seal_packet(struct gensec_security *gensec_security,
1290 : TALLOC_CTX *mem_ctx,
1291 : uint8_t *data, size_t length,
1292 : const uint8_t *whole_pdu, size_t pdu_length,
1293 : DATA_BLOB *sig)
1294 : {
1295 1313 : struct gensec_gssapi_state *gensec_gssapi_state
1296 339018 : = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1297 339018 : bool hdr_signing = false;
1298 339018 : size_t sig_size = 0;
1299 1313 : NTSTATUS status;
1300 :
1301 339018 : if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
1302 333527 : hdr_signing = true;
1303 : }
1304 :
1305 339018 : sig_size = gensec_gssapi_sig_size(gensec_security, length);
1306 :
1307 339018 : status = gssapi_seal_packet(gensec_gssapi_state->gssapi_context,
1308 : gensec_gssapi_state->gss_oid,
1309 : hdr_signing, sig_size,
1310 : data, length,
1311 : whole_pdu, pdu_length,
1312 : mem_ctx, sig);
1313 339018 : if (!NT_STATUS_IS_OK(status)) {
1314 0 : DEBUG(0, ("gssapi_seal_packet(hdr_signing=%u,sig_size=%zu,"
1315 : "data=%zu,pdu=%zu) failed: %s\n",
1316 : hdr_signing, sig_size, length, pdu_length,
1317 : nt_errstr(status)));
1318 0 : return status;
1319 : }
1320 :
1321 339018 : return NT_STATUS_OK;
1322 : }
1323 :
1324 338982 : static NTSTATUS gensec_gssapi_unseal_packet(struct gensec_security *gensec_security,
1325 : uint8_t *data, size_t length,
1326 : const uint8_t *whole_pdu, size_t pdu_length,
1327 : const DATA_BLOB *sig)
1328 : {
1329 1312 : struct gensec_gssapi_state *gensec_gssapi_state
1330 338982 : = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1331 338982 : bool hdr_signing = false;
1332 1312 : NTSTATUS status;
1333 :
1334 338982 : if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
1335 333491 : hdr_signing = true;
1336 : }
1337 :
1338 338982 : status = gssapi_unseal_packet(gensec_gssapi_state->gssapi_context,
1339 : gensec_gssapi_state->gss_oid,
1340 : hdr_signing,
1341 : data, length,
1342 : whole_pdu, pdu_length,
1343 : sig);
1344 338982 : if (!NT_STATUS_IS_OK(status)) {
1345 0 : DEBUG(0, ("gssapi_unseal_packet(hdr_signing=%u,sig_size=%zu,"
1346 : "data=%zu,pdu=%zu) failed: %s\n",
1347 : hdr_signing, sig->length, length, pdu_length,
1348 : nt_errstr(status)));
1349 0 : return status;
1350 : }
1351 :
1352 338982 : return NT_STATUS_OK;
1353 : }
1354 :
1355 67460 : static NTSTATUS gensec_gssapi_sign_packet(struct gensec_security *gensec_security,
1356 : TALLOC_CTX *mem_ctx,
1357 : const uint8_t *data, size_t length,
1358 : const uint8_t *whole_pdu, size_t pdu_length,
1359 : DATA_BLOB *sig)
1360 : {
1361 316 : struct gensec_gssapi_state *gensec_gssapi_state
1362 67460 : = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1363 67460 : bool hdr_signing = false;
1364 316 : NTSTATUS status;
1365 :
1366 67460 : if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
1367 53032 : hdr_signing = true;
1368 : }
1369 :
1370 67460 : status = gssapi_sign_packet(gensec_gssapi_state->gssapi_context,
1371 : gensec_gssapi_state->gss_oid,
1372 : hdr_signing,
1373 : data, length,
1374 : whole_pdu, pdu_length,
1375 : mem_ctx, sig);
1376 67460 : if (!NT_STATUS_IS_OK(status)) {
1377 0 : DEBUG(0, ("gssapi_sign_packet(hdr_signing=%u,"
1378 : "data=%zu,pdu=%zu) failed: %s\n",
1379 : hdr_signing, length, pdu_length,
1380 : nt_errstr(status)));
1381 0 : return status;
1382 : }
1383 :
1384 67460 : return NT_STATUS_OK;
1385 : }
1386 :
1387 67365 : static NTSTATUS gensec_gssapi_check_packet(struct gensec_security *gensec_security,
1388 : const uint8_t *data, size_t length,
1389 : const uint8_t *whole_pdu, size_t pdu_length,
1390 : const DATA_BLOB *sig)
1391 : {
1392 316 : struct gensec_gssapi_state *gensec_gssapi_state
1393 67365 : = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1394 67365 : bool hdr_signing = false;
1395 316 : NTSTATUS status;
1396 :
1397 67365 : if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
1398 53024 : hdr_signing = true;
1399 : }
1400 :
1401 67365 : status = gssapi_check_packet(gensec_gssapi_state->gssapi_context,
1402 : gensec_gssapi_state->gss_oid,
1403 : hdr_signing,
1404 : data, length,
1405 : whole_pdu, pdu_length,
1406 : sig);
1407 67365 : if (!NT_STATUS_IS_OK(status)) {
1408 6 : DEBUG(0, ("gssapi_check_packet(hdr_signing=%u,sig_size=%zu,"
1409 : "data=%zu,pdu=%zu) failed: %s\n",
1410 : hdr_signing, sig->length, length, pdu_length,
1411 : nt_errstr(status)));
1412 6 : return status;
1413 : }
1414 :
1415 67359 : return NT_STATUS_OK;
1416 : }
1417 :
1418 : /* Try to figure out what features we actually got on the connection */
1419 8093053 : static bool gensec_gssapi_have_feature(struct gensec_security *gensec_security,
1420 : uint32_t feature)
1421 : {
1422 38690 : struct gensec_gssapi_state *gensec_gssapi_state
1423 8093053 : = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1424 8093053 : if (feature & GENSEC_FEATURE_SIGN) {
1425 : /* If we are going GSSAPI SASL, then we honour the second negotiation */
1426 1885789 : if (gensec_gssapi_state->sasl
1427 468 : && gensec_gssapi_state->sasl_state == STAGE_DONE) {
1428 311 : return ((gensec_gssapi_state->sasl_protection & NEG_SIGN)
1429 311 : && (gensec_gssapi_state->gss_got_flags & GSS_C_INTEG_FLAG));
1430 : }
1431 1885478 : return gensec_gssapi_state->gss_got_flags & GSS_C_INTEG_FLAG;
1432 : }
1433 6207264 : if (feature & GENSEC_FEATURE_SEAL) {
1434 : /* If we are going GSSAPI SASL, then we honour the second negotiation */
1435 4677684 : if (gensec_gssapi_state->sasl
1436 556 : && gensec_gssapi_state->sasl_state == STAGE_DONE) {
1437 399 : return ((gensec_gssapi_state->sasl_protection & NEG_SEAL)
1438 399 : && (gensec_gssapi_state->gss_got_flags & GSS_C_CONF_FLAG));
1439 : }
1440 4677285 : return gensec_gssapi_state->gss_got_flags & GSS_C_CONF_FLAG;
1441 : }
1442 1529580 : if (feature & GENSEC_FEATURE_SESSION_KEY) {
1443 : /* Only for GSSAPI/Krb5 */
1444 28747 : if (smb_gss_oid_equal(gensec_gssapi_state->gss_oid,
1445 : gss_mech_krb5)) {
1446 27431 : return true;
1447 : }
1448 : }
1449 1500833 : if (feature & GENSEC_FEATURE_DCE_STYLE) {
1450 1338372 : return gensec_gssapi_state->gss_got_flags & GSS_C_DCE_STYLE;
1451 : }
1452 162461 : if (feature & GENSEC_FEATURE_NEW_SPNEGO) {
1453 983 : NTSTATUS status;
1454 983 : uint32_t keytype;
1455 :
1456 32953 : if (!(gensec_gssapi_state->gss_got_flags & GSS_C_INTEG_FLAG)) {
1457 72 : return false;
1458 : }
1459 :
1460 32881 : if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "force_new_spnego", false)) {
1461 0 : return true;
1462 : }
1463 32881 : if (gensec_setting_bool(gensec_security->settings, "gensec_gssapi", "disable_new_spnego", false)) {
1464 0 : return false;
1465 : }
1466 :
1467 32881 : status = gssapi_get_session_key(gensec_gssapi_state,
1468 : gensec_gssapi_state->gssapi_context, NULL, &keytype);
1469 : /*
1470 : * We should do a proper sig on the mechListMic unless
1471 : * we know we have to be backwards compatible with
1472 : * earlier windows versions.
1473 : *
1474 : * Negotiating a non-krb5
1475 : * mech for example should be regarded as having
1476 : * NEW_SPNEGO
1477 : */
1478 32881 : if (NT_STATUS_IS_OK(status)) {
1479 32881 : switch (keytype) {
1480 2263 : case ENCTYPE_DES_CBC_CRC:
1481 : case ENCTYPE_DES_CBC_MD5:
1482 : case ENCTYPE_ARCFOUR_HMAC:
1483 : case ENCTYPE_DES3_CBC_SHA1:
1484 2263 : return false;
1485 : }
1486 : }
1487 30618 : return true;
1488 : }
1489 : /* We can always do async (rather than strict request/reply) packets. */
1490 129508 : if (feature & GENSEC_FEATURE_ASYNC_REPLIES) {
1491 119775 : return true;
1492 : }
1493 8346 : if (feature & GENSEC_FEATURE_SIGN_PKT_HEADER) {
1494 8346 : return true;
1495 : }
1496 0 : return false;
1497 : }
1498 :
1499 23530 : static NTTIME gensec_gssapi_expire_time(struct gensec_security *gensec_security)
1500 : {
1501 649 : struct gensec_gssapi_state *gensec_gssapi_state =
1502 23530 : talloc_get_type_abort(gensec_security->private_data,
1503 : struct gensec_gssapi_state);
1504 :
1505 23530 : return gensec_gssapi_state->expire_time;
1506 : }
1507 :
1508 : /*
1509 : * Extract the 'session key' needed by SMB signing and ncacn_np
1510 : * (for encrypting some passwords).
1511 : *
1512 : * This breaks all the abstractions, but what do you expect...
1513 : */
1514 45587 : static NTSTATUS gensec_gssapi_session_key(struct gensec_security *gensec_security,
1515 : TALLOC_CTX *mem_ctx,
1516 : DATA_BLOB *session_key)
1517 : {
1518 1546 : struct gensec_gssapi_state *gensec_gssapi_state
1519 45587 : = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1520 45587 : return gssapi_get_session_key(mem_ctx, gensec_gssapi_state->gssapi_context, session_key, NULL);
1521 : }
1522 :
1523 : /* Get some basic (and authorization) information about the user on
1524 : * this session. This uses either the PAC (if present) or a local
1525 : * database lookup */
1526 31197 : static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_security,
1527 : TALLOC_CTX *mem_ctx,
1528 : struct auth_session_info **_session_info)
1529 : {
1530 888 : NTSTATUS nt_status;
1531 888 : TALLOC_CTX *tmp_ctx;
1532 888 : struct gensec_gssapi_state *gensec_gssapi_state
1533 31197 : = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1534 31197 : struct auth_session_info *session_info = NULL;
1535 888 : OM_uint32 maj_stat, min_stat;
1536 31197 : DATA_BLOB pac_blob, *pac_blob_ptr = NULL;
1537 :
1538 888 : gss_buffer_desc name_token;
1539 888 : char *principal_string;
1540 :
1541 31197 : tmp_ctx = talloc_named(mem_ctx, 0, "gensec_gssapi_session_info context");
1542 31197 : NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1543 :
1544 32085 : maj_stat = gss_display_name (&min_stat,
1545 23353 : gensec_gssapi_state->client_name,
1546 : &name_token,
1547 : NULL);
1548 31197 : if (GSS_ERROR(maj_stat)) {
1549 0 : DEBUG(1, ("GSS display_name failed: %s\n",
1550 : gssapi_error_string(tmp_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid)));
1551 0 : talloc_free(tmp_ctx);
1552 0 : return NT_STATUS_FOOBAR;
1553 : }
1554 :
1555 32085 : principal_string = talloc_strndup(tmp_ctx,
1556 31197 : (const char *)name_token.value,
1557 : name_token.length);
1558 :
1559 31197 : gss_release_buffer(&min_stat, &name_token);
1560 :
1561 31197 : if (!principal_string) {
1562 0 : talloc_free(tmp_ctx);
1563 0 : return NT_STATUS_NO_MEMORY;
1564 : }
1565 :
1566 31197 : nt_status = gssapi_obtain_pac_blob(tmp_ctx, gensec_gssapi_state->gssapi_context,
1567 : gensec_gssapi_state->client_name,
1568 : &pac_blob);
1569 :
1570 : /* IF we have the PAC - otherwise we need to get this
1571 : * data from elsewhere - local ldb, or (TODO) lookup of some
1572 : * kind...
1573 : */
1574 31197 : if (NT_STATUS_IS_OK(nt_status)) {
1575 31192 : pac_blob_ptr = &pac_blob;
1576 : }
1577 31197 : nt_status = gensec_generate_session_info_pac(tmp_ctx,
1578 : gensec_security,
1579 : gensec_gssapi_state->smb_krb5_context,
1580 : pac_blob_ptr, principal_string,
1581 : gensec_get_remote_address(gensec_security),
1582 : &session_info);
1583 31197 : if (!NT_STATUS_IS_OK(nt_status)) {
1584 5 : talloc_free(tmp_ctx);
1585 5 : return nt_status;
1586 : }
1587 :
1588 31192 : nt_status = gensec_gssapi_session_key(gensec_security, session_info, &session_info->session_key);
1589 31192 : if (!NT_STATUS_IS_OK(nt_status)) {
1590 0 : talloc_free(tmp_ctx);
1591 0 : return nt_status;
1592 : }
1593 :
1594 31192 : if (gensec_gssapi_state->gss_got_flags & GSS_C_DELEG_FLAG &&
1595 29925 : gensec_gssapi_state->delegated_cred_handle != GSS_C_NO_CREDENTIAL) {
1596 888 : krb5_error_code ret;
1597 888 : const char *error_string;
1598 :
1599 29861 : DEBUG(10, ("gensec_gssapi: delegated credentials supplied by client\n"));
1600 :
1601 : /*
1602 : * Create anonymous credentials for now.
1603 : *
1604 : * We will update them with the provided client gss creds.
1605 : */
1606 29861 : session_info->credentials = cli_credentials_init_anon(session_info);
1607 29861 : if (session_info->credentials == NULL) {
1608 0 : talloc_free(tmp_ctx);
1609 0 : return NT_STATUS_NO_MEMORY;
1610 : }
1611 :
1612 30749 : ret = cli_credentials_set_client_gss_creds(session_info->credentials,
1613 29861 : gensec_security->settings->lp_ctx,
1614 : gensec_gssapi_state->delegated_cred_handle,
1615 : CRED_SPECIFIED, &error_string);
1616 29861 : if (ret) {
1617 0 : talloc_free(tmp_ctx);
1618 0 : DEBUG(2,("Failed to get gss creds: %s\n", error_string));
1619 0 : return NT_STATUS_NO_MEMORY;
1620 : }
1621 :
1622 : /* This credential handle isn't useful for password authentication, so ensure nobody tries to do that */
1623 29861 : cli_credentials_set_kerberos_state(session_info->credentials,
1624 : CRED_USE_KERBEROS_REQUIRED,
1625 : CRED_SPECIFIED);
1626 :
1627 : /* It has been taken from this place... */
1628 29861 : gensec_gssapi_state->delegated_cred_handle = GSS_C_NO_CREDENTIAL;
1629 : } else {
1630 1331 : DEBUG(10, ("gensec_gssapi: NO delegated credentials supplied by client\n"));
1631 : }
1632 :
1633 31192 : *_session_info = talloc_steal(mem_ctx, session_info);
1634 31192 : talloc_free(tmp_ctx);
1635 :
1636 31192 : return NT_STATUS_OK;
1637 : }
1638 :
1639 459937 : static size_t gensec_gssapi_sig_size(struct gensec_security *gensec_security, size_t data_size)
1640 : {
1641 2682 : struct gensec_gssapi_state *gensec_gssapi_state
1642 459937 : = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1643 2682 : size_t sig_size;
1644 :
1645 459937 : if (gensec_gssapi_state->sig_size > 0) {
1646 449371 : return gensec_gssapi_state->sig_size;
1647 : }
1648 :
1649 8070 : sig_size = gssapi_get_sig_size(gensec_gssapi_state->gssapi_context,
1650 : gensec_gssapi_state->gss_oid,
1651 : gensec_gssapi_state->gss_got_flags,
1652 : data_size);
1653 :
1654 8070 : gensec_gssapi_state->sig_size = sig_size;
1655 8070 : return gensec_gssapi_state->sig_size;
1656 : }
1657 :
1658 31192 : static const char *gensec_gssapi_final_auth_type(struct gensec_security *gensec_security)
1659 : {
1660 888 : struct gensec_gssapi_state *gensec_gssapi_state
1661 31192 : = talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
1662 : /* Only return the string for GSSAPI/Krb5 */
1663 31192 : if (smb_gss_oid_equal(gensec_gssapi_state->gss_oid,
1664 : gss_mech_krb5)) {
1665 30304 : return GENSEC_FINAL_AUTH_TYPE_KRB5;
1666 : } else {
1667 0 : return "gensec_gssapi: UNKNOWN MECH";
1668 : }
1669 : }
1670 :
1671 : static const char *gensec_gssapi_krb5_oids[] = {
1672 : GENSEC_OID_KERBEROS5_OLD,
1673 : GENSEC_OID_KERBEROS5,
1674 : NULL
1675 : };
1676 :
1677 : static const char *gensec_gssapi_spnego_oids[] = {
1678 : GENSEC_OID_SPNEGO,
1679 : NULL
1680 : };
1681 :
1682 : /* As a server, this could in theory accept any GSSAPI mech */
1683 : static const struct gensec_security_ops gensec_gssapi_spnego_security_ops = {
1684 : .name = "gssapi_spnego",
1685 : .sasl_name = "GSS-SPNEGO",
1686 : .auth_type = DCERPC_AUTH_TYPE_SPNEGO,
1687 : .oid = gensec_gssapi_spnego_oids,
1688 : .client_start = gensec_gssapi_client_start,
1689 : .server_start = gensec_gssapi_server_start,
1690 : .magic = gensec_magic_check_krb5_oid,
1691 : .update_send = gensec_gssapi_update_send,
1692 : .update_recv = gensec_gssapi_update_recv,
1693 : .session_key = gensec_gssapi_session_key,
1694 : .session_info = gensec_gssapi_session_info,
1695 : .sign_packet = gensec_gssapi_sign_packet,
1696 : .check_packet = gensec_gssapi_check_packet,
1697 : .seal_packet = gensec_gssapi_seal_packet,
1698 : .unseal_packet = gensec_gssapi_unseal_packet,
1699 : .max_input_size = gensec_gssapi_max_input_size,
1700 : .max_wrapped_size = gensec_gssapi_max_wrapped_size,
1701 : .wrap = gensec_gssapi_wrap,
1702 : .unwrap = gensec_gssapi_unwrap,
1703 : .have_feature = gensec_gssapi_have_feature,
1704 : .expire_time = gensec_gssapi_expire_time,
1705 : .final_auth_type = gensec_gssapi_final_auth_type,
1706 : .enabled = false,
1707 : .kerberos = true,
1708 : .priority = GENSEC_GSSAPI
1709 : };
1710 :
1711 : /* As a server, this could in theory accept any GSSAPI mech */
1712 : static const struct gensec_security_ops gensec_gssapi_krb5_security_ops = {
1713 : .name = "gssapi_krb5",
1714 : .auth_type = DCERPC_AUTH_TYPE_KRB5,
1715 : .oid = gensec_gssapi_krb5_oids,
1716 : .client_start = gensec_gssapi_client_start,
1717 : .server_start = gensec_gssapi_server_start,
1718 : .magic = gensec_magic_check_krb5_oid,
1719 : .update_send = gensec_gssapi_update_send,
1720 : .update_recv = gensec_gssapi_update_recv,
1721 : .session_key = gensec_gssapi_session_key,
1722 : .session_info = gensec_gssapi_session_info,
1723 : .sig_size = gensec_gssapi_sig_size,
1724 : .sign_packet = gensec_gssapi_sign_packet,
1725 : .check_packet = gensec_gssapi_check_packet,
1726 : .seal_packet = gensec_gssapi_seal_packet,
1727 : .unseal_packet = gensec_gssapi_unseal_packet,
1728 : .max_input_size = gensec_gssapi_max_input_size,
1729 : .max_wrapped_size = gensec_gssapi_max_wrapped_size,
1730 : .wrap = gensec_gssapi_wrap,
1731 : .unwrap = gensec_gssapi_unwrap,
1732 : .have_feature = gensec_gssapi_have_feature,
1733 : .expire_time = gensec_gssapi_expire_time,
1734 : .final_auth_type = gensec_gssapi_final_auth_type,
1735 : .enabled = true,
1736 : .kerberos = true,
1737 : .priority = GENSEC_GSSAPI
1738 : };
1739 :
1740 : /* As a server, this could in theory accept any GSSAPI mech */
1741 : static const struct gensec_security_ops gensec_gssapi_sasl_krb5_security_ops = {
1742 : .name = "gssapi_krb5_sasl",
1743 : .sasl_name = "GSSAPI",
1744 : .client_start = gensec_gssapi_sasl_client_start,
1745 : .server_start = gensec_gssapi_sasl_server_start,
1746 : .update_send = gensec_gssapi_update_send,
1747 : .update_recv = gensec_gssapi_update_recv,
1748 : .session_key = gensec_gssapi_session_key,
1749 : .session_info = gensec_gssapi_session_info,
1750 : .max_input_size = gensec_gssapi_max_input_size,
1751 : .max_wrapped_size = gensec_gssapi_max_wrapped_size,
1752 : .wrap = gensec_gssapi_wrap,
1753 : .unwrap = gensec_gssapi_unwrap,
1754 : .have_feature = gensec_gssapi_have_feature,
1755 : .expire_time = gensec_gssapi_expire_time,
1756 : .final_auth_type = gensec_gssapi_final_auth_type,
1757 : .enabled = true,
1758 : .kerberos = true,
1759 : .priority = GENSEC_GSSAPI
1760 : };
1761 :
1762 53162 : _PUBLIC_ NTSTATUS gensec_gssapi_init(TALLOC_CTX *ctx)
1763 : {
1764 1228 : NTSTATUS ret;
1765 :
1766 53162 : ret = gensec_register(ctx, &gensec_gssapi_spnego_security_ops);
1767 53162 : if (!NT_STATUS_IS_OK(ret)) {
1768 0 : DEBUG(0,("Failed to register '%s' gensec backend!\n",
1769 : gensec_gssapi_spnego_security_ops.name));
1770 0 : return ret;
1771 : }
1772 :
1773 53162 : ret = gensec_register(ctx, &gensec_gssapi_krb5_security_ops);
1774 53162 : if (!NT_STATUS_IS_OK(ret)) {
1775 0 : DEBUG(0,("Failed to register '%s' gensec backend!\n",
1776 : gensec_gssapi_krb5_security_ops.name));
1777 0 : return ret;
1778 : }
1779 :
1780 53162 : ret = gensec_register(ctx, &gensec_gssapi_sasl_krb5_security_ops);
1781 53162 : if (!NT_STATUS_IS_OK(ret)) {
1782 0 : DEBUG(0,("Failed to register '%s' gensec backend!\n",
1783 : gensec_gssapi_sasl_krb5_security_ops.name));
1784 0 : return ret;
1785 : }
1786 :
1787 53162 : return ret;
1788 : }
|