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