2 Unix SMB/CIFS implementation.
4 Kerberos backend for GENSEC
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
7 Copyright (C) Stefan Metzmacher <metze@samba.org> 2004-2005
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.
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.
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/>.
25 #include "lib/events/events.h"
26 #include "system/kerberos.h"
27 #include "auth/kerberos/kerberos.h"
28 #include "librpc/gen_ndr/krb5pac.h"
29 #include "auth/auth.h"
31 #include "auth/auth_sam.h"
32 #include "librpc/rpc/dcerpc.h"
33 #include "auth/credentials/credentials.h"
34 #include "auth/credentials/credentials_krb5.h"
35 #include "auth/gensec/gensec.h"
36 #include "auth/gensec/gensec_proto.h"
37 #include "auth/gensec/gensec_toplevel_proto.h"
38 #include "param/param.h"
39 #include "auth/session_proto.h"
40 #include <gssapi/gssapi.h>
41 #include <gssapi/gssapi_krb5.h>
42 #include <gssapi/gssapi_spnego.h>
43 #include "gensec_gssapi.h"
44 #include "lib/util/util_net.h"
45 #include "auth/kerberos/pac_utils.h"
47 _PUBLIC_ NTSTATUS
gensec_gssapi_init(void);
49 static size_t gensec_gssapi_max_input_size(struct gensec_security
*gensec_security
);
50 static size_t gensec_gssapi_max_wrapped_size(struct gensec_security
*gensec_security
);
52 static int gensec_gssapi_destructor(struct gensec_gssapi_state
*gensec_gssapi_state
)
54 OM_uint32 maj_stat
, min_stat
;
56 if (gensec_gssapi_state
->delegated_cred_handle
!= GSS_C_NO_CREDENTIAL
) {
57 maj_stat
= gss_release_cred(&min_stat
,
58 &gensec_gssapi_state
->delegated_cred_handle
);
61 if (gensec_gssapi_state
->gssapi_context
!= GSS_C_NO_CONTEXT
) {
62 maj_stat
= gss_delete_sec_context (&min_stat
,
63 &gensec_gssapi_state
->gssapi_context
,
67 if (gensec_gssapi_state
->server_name
!= GSS_C_NO_NAME
) {
68 maj_stat
= gss_release_name(&min_stat
, &gensec_gssapi_state
->server_name
);
70 if (gensec_gssapi_state
->client_name
!= GSS_C_NO_NAME
) {
71 maj_stat
= gss_release_name(&min_stat
, &gensec_gssapi_state
->client_name
);
74 if (gensec_gssapi_state
->lucid
) {
75 gss_krb5_free_lucid_sec_context(&min_stat
, gensec_gssapi_state
->lucid
);
81 static NTSTATUS
gensec_gssapi_init_lucid(struct gensec_gssapi_state
*gensec_gssapi_state
)
83 OM_uint32 maj_stat
, min_stat
;
85 if (gensec_gssapi_state
->lucid
) {
89 maj_stat
= gss_krb5_export_lucid_sec_context(&min_stat
,
90 &gensec_gssapi_state
->gssapi_context
,
92 (void **)&gensec_gssapi_state
->lucid
);
93 if (maj_stat
!= GSS_S_COMPLETE
) {
94 DEBUG(0,("gensec_gssapi_init_lucid: %s\n",
95 gssapi_error_string(gensec_gssapi_state
,
97 gensec_gssapi_state
->gss_oid
)));
98 return NT_STATUS_INTERNAL_ERROR
;
101 if (gensec_gssapi_state
->lucid
->version
!= 1) {
102 DEBUG(0,("gensec_gssapi_init_lucid: lucid version[%d] != 1\n",
103 gensec_gssapi_state
->lucid
->version
));
104 gss_krb5_free_lucid_sec_context(&min_stat
, gensec_gssapi_state
->lucid
);
105 gensec_gssapi_state
->lucid
= NULL
;
106 return NT_STATUS_INTERNAL_ERROR
;
112 static NTSTATUS
gensec_gssapi_start(struct gensec_security
*gensec_security
)
114 struct gensec_gssapi_state
*gensec_gssapi_state
;
118 gensec_gssapi_state
= talloc_zero(gensec_security
, struct gensec_gssapi_state
);
119 if (!gensec_gssapi_state
) {
120 return NT_STATUS_NO_MEMORY
;
123 gensec_security
->private_data
= gensec_gssapi_state
;
125 gensec_gssapi_state
->gssapi_context
= GSS_C_NO_CONTEXT
;
127 /* TODO: Fill in channel bindings */
128 gensec_gssapi_state
->input_chan_bindings
= GSS_C_NO_CHANNEL_BINDINGS
;
130 gensec_gssapi_state
->server_name
= GSS_C_NO_NAME
;
131 gensec_gssapi_state
->client_name
= GSS_C_NO_NAME
;
133 gensec_gssapi_state
->gss_want_flags
= 0;
135 if (gensec_setting_bool(gensec_security
->settings
, "gensec_gssapi", "delegation_by_kdc_policy", true)) {
136 gensec_gssapi_state
->gss_want_flags
|= GSS_C_DELEG_POLICY_FLAG
;
138 if (gensec_setting_bool(gensec_security
->settings
, "gensec_gssapi", "mutual", true)) {
139 gensec_gssapi_state
->gss_want_flags
|= GSS_C_MUTUAL_FLAG
;
141 if (gensec_setting_bool(gensec_security
->settings
, "gensec_gssapi", "delegation", true)) {
142 gensec_gssapi_state
->gss_want_flags
|= GSS_C_DELEG_FLAG
;
144 if (gensec_setting_bool(gensec_security
->settings
, "gensec_gssapi", "replay", true)) {
145 gensec_gssapi_state
->gss_want_flags
|= GSS_C_REPLAY_FLAG
;
147 if (gensec_setting_bool(gensec_security
->settings
, "gensec_gssapi", "sequence", true)) {
148 gensec_gssapi_state
->gss_want_flags
|= GSS_C_SEQUENCE_FLAG
;
151 if (gensec_security
->want_features
& GENSEC_FEATURE_SIGN
) {
152 gensec_gssapi_state
->gss_want_flags
|= GSS_C_INTEG_FLAG
;
154 if (gensec_security
->want_features
& GENSEC_FEATURE_SEAL
) {
155 gensec_gssapi_state
->gss_want_flags
|= GSS_C_INTEG_FLAG
;
156 gensec_gssapi_state
->gss_want_flags
|= GSS_C_CONF_FLAG
;
158 if (gensec_security
->want_features
& GENSEC_FEATURE_DCE_STYLE
) {
159 gensec_gssapi_state
->gss_want_flags
|= GSS_C_DCE_STYLE
;
162 gensec_gssapi_state
->gss_got_flags
= 0;
164 switch (gensec_security
->ops
->auth_type
) {
165 case DCERPC_AUTH_TYPE_SPNEGO
:
166 gensec_gssapi_state
->gss_oid
= gss_mech_spnego
;
168 case DCERPC_AUTH_TYPE_KRB5
:
170 gensec_gssapi_state
->gss_oid
= gss_mech_krb5
;
174 ret
= smb_krb5_init_context(gensec_gssapi_state
,
176 gensec_security
->settings
->lp_ctx
,
177 &gensec_gssapi_state
->smb_krb5_context
);
179 DEBUG(1,("gensec_krb5_start: krb5_init_context failed (%s)\n",
180 error_message(ret
)));
181 talloc_free(gensec_gssapi_state
);
182 return NT_STATUS_INTERNAL_ERROR
;
185 gensec_gssapi_state
->client_cred
= NULL
;
186 gensec_gssapi_state
->server_cred
= NULL
;
188 gensec_gssapi_state
->lucid
= NULL
;
190 gensec_gssapi_state
->delegated_cred_handle
= GSS_C_NO_CREDENTIAL
;
192 gensec_gssapi_state
->sasl
= false;
193 gensec_gssapi_state
->sasl_state
= STAGE_GSS_NEG
;
194 gensec_gssapi_state
->sasl_protection
= 0;
196 gensec_gssapi_state
->max_wrap_buf_size
197 = gensec_setting_int(gensec_security
->settings
, "gensec_gssapi", "max wrap buf size", 65536);
198 gensec_gssapi_state
->gss_exchange_count
= 0;
199 gensec_gssapi_state
->sig_size
= 0;
201 talloc_set_destructor(gensec_gssapi_state
, gensec_gssapi_destructor
);
203 realm
= lpcfg_realm(gensec_security
->settings
->lp_ctx
);
205 ret
= gsskrb5_set_default_realm(realm
);
207 DEBUG(1,("gensec_krb5_start: gsskrb5_set_default_realm failed\n"));
208 talloc_free(gensec_gssapi_state
);
209 return NT_STATUS_INTERNAL_ERROR
;
213 /* don't do DNS lookups of any kind, it might/will fail for a netbios name */
214 ret
= gsskrb5_set_dns_canonicalize(gensec_setting_bool(gensec_security
->settings
, "krb5", "set_dns_canonicalize", false));
216 DEBUG(1,("gensec_krb5_start: gsskrb5_set_dns_canonicalize failed\n"));
217 talloc_free(gensec_gssapi_state
);
218 return NT_STATUS_INTERNAL_ERROR
;
224 static NTSTATUS
gensec_gssapi_server_start(struct gensec_security
*gensec_security
)
228 struct gensec_gssapi_state
*gensec_gssapi_state
;
229 struct cli_credentials
*machine_account
;
230 struct gssapi_creds_container
*gcc
;
232 nt_status
= gensec_gssapi_start(gensec_security
);
233 if (!NT_STATUS_IS_OK(nt_status
)) {
237 gensec_gssapi_state
= talloc_get_type(gensec_security
->private_data
, struct gensec_gssapi_state
);
239 machine_account
= gensec_get_credentials(gensec_security
);
241 if (!machine_account
) {
242 DEBUG(3, ("No machine account credentials specified\n"));
243 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
245 ret
= cli_credentials_get_server_gss_creds(machine_account
,
246 gensec_security
->settings
->lp_ctx
, &gcc
);
248 DEBUG(1, ("Aquiring acceptor credentials failed: %s\n",
249 error_message(ret
)));
250 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO
;
254 gensec_gssapi_state
->server_cred
= gcc
;
259 static NTSTATUS
gensec_gssapi_sasl_server_start(struct gensec_security
*gensec_security
)
262 struct gensec_gssapi_state
*gensec_gssapi_state
;
263 nt_status
= gensec_gssapi_server_start(gensec_security
);
265 if (NT_STATUS_IS_OK(nt_status
)) {
266 gensec_gssapi_state
= talloc_get_type(gensec_security
->private_data
, struct gensec_gssapi_state
);
267 gensec_gssapi_state
->sasl
= true;
272 static NTSTATUS
gensec_gssapi_client_creds(struct gensec_security
*gensec_security
,
273 struct tevent_context
*ev
)
275 struct gensec_gssapi_state
*gensec_gssapi_state
;
276 struct gssapi_creds_container
*gcc
;
277 struct cli_credentials
*creds
= gensec_get_credentials(gensec_security
);
278 const char *error_string
;
281 gensec_gssapi_state
= talloc_get_type(gensec_security
->private_data
, struct gensec_gssapi_state
);
283 /* Only run this the first time the update() call is made */
284 if (gensec_gssapi_state
->client_cred
) {
288 ret
= cli_credentials_get_client_gss_creds(creds
,
290 gensec_security
->settings
->lp_ctx
, &gcc
, &error_string
);
295 DEBUG(3, ("Cannot obtain client GSS credentials we need to contact %s : %s\n", gensec_gssapi_state
->target_principal
, error_string
));
296 return NT_STATUS_INVALID_PARAMETER
;
297 case KRB5KDC_ERR_PREAUTH_FAILED
:
298 case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN
:
299 DEBUG(1, ("Wrong username or password: %s\n", error_string
));
300 return NT_STATUS_LOGON_FAILURE
;
301 case KRB5_KDC_UNREACH
:
302 DEBUG(3, ("Cannot reach a KDC we require to contact %s : %s\n", gensec_gssapi_state
->target_principal
, error_string
));
303 return NT_STATUS_NO_LOGON_SERVERS
;
304 case KRB5_CC_NOTFOUND
:
306 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
));
307 return NT_STATUS_TIME_DIFFERENCE_AT_DC
;
309 DEBUG(1, ("Aquiring initiator credentials failed: %s\n", error_string
));
310 return NT_STATUS_UNSUCCESSFUL
;
313 gensec_gssapi_state
->client_cred
= gcc
;
314 if (!talloc_reference(gensec_gssapi_state
, gcc
)) {
315 return NT_STATUS_NO_MEMORY
;
321 static NTSTATUS
gensec_gssapi_client_start(struct gensec_security
*gensec_security
)
323 struct gensec_gssapi_state
*gensec_gssapi_state
;
324 struct cli_credentials
*creds
= gensec_get_credentials(gensec_security
);
326 gss_buffer_desc name_token
;
328 OM_uint32 maj_stat
, min_stat
;
329 const char *hostname
= gensec_get_target_hostname(gensec_security
);
332 DEBUG(1, ("Could not determine hostname for target computer, cannot use kerberos\n"));
333 return NT_STATUS_INVALID_PARAMETER
;
335 if (is_ipaddress(hostname
)) {
336 DEBUG(2, ("Cannot do GSSAPI to an IP address\n"));
337 return NT_STATUS_INVALID_PARAMETER
;
339 if (strcmp(hostname
, "localhost") == 0) {
340 DEBUG(2, ("GSSAPI to 'localhost' does not make sense\n"));
341 return NT_STATUS_INVALID_PARAMETER
;
344 nt_status
= gensec_gssapi_start(gensec_security
);
345 if (!NT_STATUS_IS_OK(nt_status
)) {
349 gensec_gssapi_state
= talloc_get_type(gensec_security
->private_data
, struct gensec_gssapi_state
);
351 if (cli_credentials_get_impersonate_principal(creds
)) {
352 gensec_gssapi_state
->gss_want_flags
&= ~(GSS_C_DELEG_FLAG
|GSS_C_DELEG_POLICY_FLAG
);
355 gensec_gssapi_state
->target_principal
= gensec_get_target_principal(gensec_security
);
356 if (gensec_gssapi_state
->target_principal
) {
357 name_type
= GSS_C_NULL_OID
;
359 gensec_gssapi_state
->target_principal
= talloc_asprintf(gensec_gssapi_state
, "%s/%s@%s",
360 gensec_get_target_service(gensec_security
),
361 hostname
, lpcfg_realm(gensec_security
->settings
->lp_ctx
));
363 name_type
= GSS_C_NT_USER_NAME
;
365 name_token
.value
= discard_const_p(uint8_t, gensec_gssapi_state
->target_principal
);
366 name_token
.length
= strlen(gensec_gssapi_state
->target_principal
);
369 maj_stat
= gss_import_name (&min_stat
,
372 &gensec_gssapi_state
->server_name
);
374 DEBUG(2, ("GSS Import name of %s failed: %s\n",
375 (char *)name_token
.value
,
376 gssapi_error_string(gensec_gssapi_state
, maj_stat
, min_stat
, gensec_gssapi_state
->gss_oid
)));
377 return NT_STATUS_INVALID_PARAMETER
;
383 static NTSTATUS
gensec_gssapi_sasl_client_start(struct gensec_security
*gensec_security
)
386 struct gensec_gssapi_state
*gensec_gssapi_state
;
387 nt_status
= gensec_gssapi_client_start(gensec_security
);
389 if (NT_STATUS_IS_OK(nt_status
)) {
390 gensec_gssapi_state
= talloc_get_type(gensec_security
->private_data
, struct gensec_gssapi_state
);
391 gensec_gssapi_state
->sasl
= true;
398 * Next state function for the GSSAPI GENSEC mechanism
400 * @param gensec_gssapi_state GSSAPI State
401 * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
402 * @param in The request, as a DATA_BLOB
403 * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
404 * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent,
405 * or NT_STATUS_OK if the user is authenticated.
408 static NTSTATUS
gensec_gssapi_update(struct gensec_security
*gensec_security
,
409 TALLOC_CTX
*out_mem_ctx
,
410 struct tevent_context
*ev
,
411 const DATA_BLOB in
, DATA_BLOB
*out
)
413 struct gensec_gssapi_state
*gensec_gssapi_state
414 = talloc_get_type(gensec_security
->private_data
, struct gensec_gssapi_state
);
415 NTSTATUS nt_status
= NT_STATUS_LOGON_FAILURE
;
416 OM_uint32 maj_stat
, min_stat
;
418 gss_buffer_desc input_token
, output_token
;
419 gss_OID gss_oid_p
= NULL
;
420 input_token
.length
= in
.length
;
421 input_token
.value
= in
.data
;
423 switch (gensec_gssapi_state
->sasl_state
) {
426 switch (gensec_security
->gensec_role
) {
429 struct gsskrb5_send_to_kdc send_to_kdc
;
432 nt_status
= gensec_gssapi_client_creds(gensec_security
, ev
);
433 if (!NT_STATUS_IS_OK(nt_status
)) {
437 #ifdef SAMBA4_USES_HEIMDAL
438 send_to_kdc
.func
= smb_krb5_send_and_recv_func
;
439 send_to_kdc
.ptr
= ev
;
442 min_stat
= gsskrb5_set_send_to_kdc(&send_to_kdc
);
444 DEBUG(1,("gensec_krb5_start: gsskrb5_set_send_to_kdc failed\n"));
445 return NT_STATUS_INTERNAL_ERROR
;
448 maj_stat
= gss_init_sec_context(&min_stat
,
449 gensec_gssapi_state
->client_cred
->creds
,
450 &gensec_gssapi_state
->gssapi_context
,
451 gensec_gssapi_state
->server_name
,
452 gensec_gssapi_state
->gss_oid
,
453 gensec_gssapi_state
->gss_want_flags
,
455 gensec_gssapi_state
->input_chan_bindings
,
459 &gensec_gssapi_state
->gss_got_flags
, /* ret flags */
462 gensec_gssapi_state
->gss_oid
= gss_oid_p
;
465 #ifdef SAMBA4_USES_HEIMDAL
466 send_to_kdc
.func
= smb_krb5_send_and_recv_func
;
467 send_to_kdc
.ptr
= NULL
;
470 ret
= gsskrb5_set_send_to_kdc(&send_to_kdc
);
472 DEBUG(1,("gensec_krb5_start: gsskrb5_set_send_to_kdc failed\n"));
473 return NT_STATUS_INTERNAL_ERROR
;
480 maj_stat
= gss_accept_sec_context(&min_stat
,
481 &gensec_gssapi_state
->gssapi_context
,
482 gensec_gssapi_state
->server_cred
->creds
,
484 gensec_gssapi_state
->input_chan_bindings
,
485 &gensec_gssapi_state
->client_name
,
488 &gensec_gssapi_state
->gss_got_flags
,
490 &gensec_gssapi_state
->delegated_cred_handle
);
492 gensec_gssapi_state
->gss_oid
= gss_oid_p
;
497 return NT_STATUS_INVALID_PARAMETER
;
501 gensec_gssapi_state
->gss_exchange_count
++;
503 if (maj_stat
== GSS_S_COMPLETE
) {
504 *out
= data_blob_talloc(out_mem_ctx
, output_token
.value
, output_token
.length
);
505 gss_release_buffer(&min_stat2
, &output_token
);
507 if (gensec_gssapi_state
->gss_got_flags
& GSS_C_DELEG_FLAG
) {
508 DEBUG(5, ("gensec_gssapi: credentials were delegated\n"));
510 DEBUG(5, ("gensec_gssapi: NO credentials were delegated\n"));
513 /* We may have been invoked as SASL, so there
514 * is more work to do */
515 if (gensec_gssapi_state
->sasl
) {
516 gensec_gssapi_state
->sasl_state
= STAGE_SASL_SSF_NEG
;
517 return NT_STATUS_MORE_PROCESSING_REQUIRED
;
519 gensec_gssapi_state
->sasl_state
= STAGE_DONE
;
521 if (gensec_have_feature(gensec_security
, GENSEC_FEATURE_SEAL
)) {
522 DEBUG(5, ("GSSAPI Connection will be cryptographically sealed\n"));
523 } else if (gensec_have_feature(gensec_security
, GENSEC_FEATURE_SIGN
)) {
524 DEBUG(5, ("GSSAPI Connection will be cryptographically signed\n"));
526 DEBUG(5, ("GSSAPI Connection will have no cryptographic protection\n"));
531 } else if (maj_stat
== GSS_S_CONTINUE_NEEDED
) {
532 *out
= data_blob_talloc(out_mem_ctx
, output_token
.value
, output_token
.length
);
533 gss_release_buffer(&min_stat2
, &output_token
);
535 return NT_STATUS_MORE_PROCESSING_REQUIRED
;
536 } else if (maj_stat
== GSS_S_CONTEXT_EXPIRED
) {
539 gss_buffer_desc buffer
;
540 OM_uint32 lifetime
= 0;
541 gss_cred_usage_t usage
;
542 const char *role
= NULL
;
543 DEBUG(0, ("GSS %s Update(krb5)(%d) Update failed, credentials expired during GSSAPI handshake!\n",
545 gensec_gssapi_state
->gss_exchange_count
));
548 switch (gensec_security
->gensec_role
) {
550 creds
= gensec_gssapi_state
->client_cred
->creds
;
553 creds
= gensec_gssapi_state
->server_cred
->creds
;
557 maj_stat
= gss_inquire_cred(&min_stat
,
559 &name
, &lifetime
, &usage
, NULL
);
561 if (maj_stat
== GSS_S_COMPLETE
) {
562 const char *usage_string
;
565 usage_string
= "GSS_C_BOTH";
568 usage_string
= "GSS_C_ACCEPT";
571 usage_string
= "GSS_C_INITIATE";
574 maj_stat
= gss_display_name(&min_stat
, name
, &buffer
, NULL
);
580 DEBUG(0, ("GSSAPI gss_inquire_cred indicates expiry of %*.*s in %u sec for %s\n",
581 (int)buffer
.length
, (int)buffer
.length
, (char *)buffer
.value
,
582 lifetime
, usage_string
));
584 DEBUG(0, ("GSSAPI gss_inquire_cred indicates %*.*s has already expired for %s\n",
585 (int)buffer
.length
, (int)buffer
.length
, (char *)buffer
.value
,
588 gss_release_buffer(&min_stat
, &buffer
);
589 gss_release_name(&min_stat
, &name
);
590 } else if (maj_stat
!= GSS_S_COMPLETE
) {
591 DEBUG(0, ("inquiry of credential lifefime via GSSAPI gss_inquire_cred failed: %s\n",
592 gssapi_error_string(out_mem_ctx
, maj_stat
, min_stat
, gensec_gssapi_state
->gss_oid
)));
594 return NT_STATUS_INVALID_PARAMETER
;
595 } else if (gss_oid_equal(gensec_gssapi_state
->gss_oid
, gss_mech_krb5
)) {
597 case KRB5KRB_AP_ERR_TKT_NYV
:
598 DEBUG(1, ("Error with ticket to contact %s: possible clock skew between us and the KDC or target server: %s\n",
599 gensec_gssapi_state
->target_principal
,
600 gssapi_error_string(out_mem_ctx
, maj_stat
, min_stat
, gensec_gssapi_state
->gss_oid
)));
601 return NT_STATUS_TIME_DIFFERENCE_AT_DC
; /* Make SPNEGO ignore us, we can't go any further here */
602 case KRB5KRB_AP_ERR_TKT_EXPIRED
:
603 DEBUG(1, ("Error with ticket to contact %s: ticket is expired, possible clock skew between us and the KDC or target server: %s\n",
604 gensec_gssapi_state
->target_principal
,
605 gssapi_error_string(out_mem_ctx
, maj_stat
, min_stat
, gensec_gssapi_state
->gss_oid
)));
606 return NT_STATUS_INVALID_PARAMETER
; /* Make SPNEGO ignore us, we can't go any further here */
607 case KRB5_KDC_UNREACH
:
608 DEBUG(3, ("Cannot reach a KDC we require in order to obtain a ticetk to %s: %s\n",
609 gensec_gssapi_state
->target_principal
,
610 gssapi_error_string(out_mem_ctx
, maj_stat
, min_stat
, gensec_gssapi_state
->gss_oid
)));
611 return NT_STATUS_NO_LOGON_SERVERS
; /* Make SPNEGO ignore us, we can't go any further here */
612 case KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN
:
613 DEBUG(3, ("Server %s is not registered with our KDC: %s\n",
614 gensec_gssapi_state
->target_principal
,
615 gssapi_error_string(out_mem_ctx
, maj_stat
, min_stat
, gensec_gssapi_state
->gss_oid
)));
616 return NT_STATUS_INVALID_PARAMETER
; /* Make SPNEGO ignore us, we can't go any further here */
617 case KRB5KRB_AP_ERR_MSG_TYPE
:
618 /* garbage input, possibly from the auto-mech detection */
619 return NT_STATUS_INVALID_PARAMETER
;
621 DEBUG(1, ("GSS %s Update(krb5)(%d) Update failed: %s\n",
622 gensec_security
->gensec_role
== GENSEC_CLIENT
? "client" : "server",
623 gensec_gssapi_state
->gss_exchange_count
,
624 gssapi_error_string(out_mem_ctx
, maj_stat
, min_stat
, gensec_gssapi_state
->gss_oid
)));
628 DEBUG(1, ("GSS %s Update(%d) failed: %s\n",
629 gensec_security
->gensec_role
== GENSEC_CLIENT
? "client" : "server",
630 gensec_gssapi_state
->gss_exchange_count
,
631 gssapi_error_string(out_mem_ctx
, maj_stat
, min_stat
, gensec_gssapi_state
->gss_oid
)));
637 /* These last two stages are only done if we were invoked as SASL */
638 case STAGE_SASL_SSF_NEG
:
640 switch (gensec_security
->gensec_role
) {
643 uint8_t maxlength_proposed
[4];
644 uint8_t maxlength_accepted
[4];
645 uint8_t security_supported
;
648 input_token
.length
= in
.length
;
649 input_token
.value
= in
.data
;
651 /* As a client, we have just send a
652 * zero-length blob to the server (after the
653 * normal GSSAPI exchange), and it has replied
654 * with it's SASL negotiation */
656 maj_stat
= gss_unwrap(&min_stat
,
657 gensec_gssapi_state
->gssapi_context
,
662 if (GSS_ERROR(maj_stat
)) {
663 DEBUG(1, ("gensec_gssapi_update: GSS UnWrap of SASL protection negotiation failed: %s\n",
664 gssapi_error_string(out_mem_ctx
, maj_stat
, min_stat
, gensec_gssapi_state
->gss_oid
)));
665 return NT_STATUS_ACCESS_DENIED
;
668 if (output_token
.length
< 4) {
669 return NT_STATUS_INVALID_PARAMETER
;
672 memcpy(maxlength_proposed
, output_token
.value
, 4);
673 gss_release_buffer(&min_stat
, &output_token
);
675 /* first byte is the proposed security */
676 security_supported
= maxlength_proposed
[0];
677 maxlength_proposed
[0] = '\0';
679 /* Rest is the proposed max wrap length */
680 gensec_gssapi_state
->max_wrap_buf_size
= MIN(RIVAL(maxlength_proposed
, 0),
681 gensec_gssapi_state
->max_wrap_buf_size
);
682 gensec_gssapi_state
->sasl_protection
= 0;
683 if (security_supported
& NEG_SEAL
) {
684 if (gensec_have_feature(gensec_security
, GENSEC_FEATURE_SEAL
)) {
685 gensec_gssapi_state
->sasl_protection
|= NEG_SEAL
;
688 if (security_supported
& NEG_SIGN
) {
689 if (gensec_have_feature(gensec_security
, GENSEC_FEATURE_SIGN
)) {
690 gensec_gssapi_state
->sasl_protection
|= NEG_SIGN
;
693 if (security_supported
& NEG_NONE
) {
694 gensec_gssapi_state
->sasl_protection
|= NEG_NONE
;
696 if (gensec_gssapi_state
->sasl_protection
== 0) {
697 DEBUG(1, ("Remote server does not support unprotected connections\n"));
698 return NT_STATUS_ACCESS_DENIED
;
701 /* Send back the negotiated max length */
703 RSIVAL(maxlength_accepted
, 0, gensec_gssapi_state
->max_wrap_buf_size
);
705 maxlength_accepted
[0] = gensec_gssapi_state
->sasl_protection
;
707 input_token
.value
= maxlength_accepted
;
708 input_token
.length
= sizeof(maxlength_accepted
);
710 maj_stat
= gss_wrap(&min_stat
,
711 gensec_gssapi_state
->gssapi_context
,
717 if (GSS_ERROR(maj_stat
)) {
718 DEBUG(1, ("GSS Update(SSF_NEG): GSS Wrap failed: %s\n",
719 gssapi_error_string(out_mem_ctx
, maj_stat
, min_stat
, gensec_gssapi_state
->gss_oid
)));
720 return NT_STATUS_ACCESS_DENIED
;
723 *out
= data_blob_talloc(out_mem_ctx
, output_token
.value
, output_token
.length
);
724 gss_release_buffer(&min_stat
, &output_token
);
726 /* quirk: This changes the value that gensec_have_feature returns, to be that after SASL negotiation */
727 gensec_gssapi_state
->sasl_state
= STAGE_DONE
;
729 if (gensec_have_feature(gensec_security
, GENSEC_FEATURE_SEAL
)) {
730 DEBUG(3, ("SASL/GSSAPI Connection to server will be cryptographically sealed\n"));
731 } else if (gensec_have_feature(gensec_security
, GENSEC_FEATURE_SIGN
)) {
732 DEBUG(3, ("SASL/GSSAPI Connection to server will be cryptographically signed\n"));
734 DEBUG(3, ("SASL/GSSAPI Connection to server will have no cryptographically protection\n"));
741 uint8_t maxlength_proposed
[4];
742 uint8_t security_supported
= 0x0;
745 /* As a server, we have just been sent a zero-length blob (note this, but it isn't fatal) */
746 if (in
.length
!= 0) {
747 DEBUG(1, ("SASL/GSSAPI: client sent non-zero length starting SASL negotiation!\n"));
750 /* Give the client some idea what we will support */
752 RSIVAL(maxlength_proposed
, 0, gensec_gssapi_state
->max_wrap_buf_size
);
753 /* first byte is the proposed security */
754 maxlength_proposed
[0] = '\0';
756 gensec_gssapi_state
->sasl_protection
= 0;
757 if (gensec_have_feature(gensec_security
, GENSEC_FEATURE_SEAL
)) {
758 security_supported
|= NEG_SEAL
;
760 if (gensec_have_feature(gensec_security
, GENSEC_FEATURE_SIGN
)) {
761 security_supported
|= NEG_SIGN
;
763 if (security_supported
== 0) {
764 /* If we don't support anything, this must be 0 */
765 RSIVAL(maxlength_proposed
, 0, 0x0);
768 /* TODO: We may not wish to support this */
769 security_supported
|= NEG_NONE
;
770 maxlength_proposed
[0] = security_supported
;
772 input_token
.value
= maxlength_proposed
;
773 input_token
.length
= sizeof(maxlength_proposed
);
775 maj_stat
= gss_wrap(&min_stat
,
776 gensec_gssapi_state
->gssapi_context
,
782 if (GSS_ERROR(maj_stat
)) {
783 DEBUG(1, ("GSS Update(SSF_NEG): GSS Wrap failed: %s\n",
784 gssapi_error_string(out_mem_ctx
, maj_stat
, min_stat
, gensec_gssapi_state
->gss_oid
)));
785 return NT_STATUS_ACCESS_DENIED
;
788 *out
= data_blob_talloc(out_mem_ctx
, output_token
.value
, output_token
.length
);
789 gss_release_buffer(&min_stat
, &output_token
);
791 gensec_gssapi_state
->sasl_state
= STAGE_SASL_SSF_ACCEPT
;
792 return NT_STATUS_MORE_PROCESSING_REQUIRED
;
795 return NT_STATUS_INVALID_PARAMETER
;
799 /* This is s server-only stage */
800 case STAGE_SASL_SSF_ACCEPT
:
802 uint8_t maxlength_accepted
[4];
803 uint8_t security_accepted
;
806 input_token
.length
= in
.length
;
807 input_token
.value
= in
.data
;
809 maj_stat
= gss_unwrap(&min_stat
,
810 gensec_gssapi_state
->gssapi_context
,
815 if (GSS_ERROR(maj_stat
)) {
816 DEBUG(1, ("gensec_gssapi_update: GSS UnWrap of SASL protection negotiation failed: %s\n",
817 gssapi_error_string(out_mem_ctx
, maj_stat
, min_stat
, gensec_gssapi_state
->gss_oid
)));
818 return NT_STATUS_ACCESS_DENIED
;
821 if (output_token
.length
< 4) {
822 return NT_STATUS_INVALID_PARAMETER
;
825 memcpy(maxlength_accepted
, output_token
.value
, 4);
826 gss_release_buffer(&min_stat
, &output_token
);
828 /* first byte is the proposed security */
829 security_accepted
= maxlength_accepted
[0];
830 maxlength_accepted
[0] = '\0';
832 /* Rest is the proposed max wrap length */
833 gensec_gssapi_state
->max_wrap_buf_size
= MIN(RIVAL(maxlength_accepted
, 0),
834 gensec_gssapi_state
->max_wrap_buf_size
);
836 gensec_gssapi_state
->sasl_protection
= 0;
837 if (security_accepted
& NEG_SEAL
) {
838 if (!gensec_have_feature(gensec_security
, GENSEC_FEATURE_SEAL
)) {
839 DEBUG(1, ("Remote client wanted seal, but gensec refused\n"));
840 return NT_STATUS_ACCESS_DENIED
;
842 gensec_gssapi_state
->sasl_protection
|= NEG_SEAL
;
844 if (security_accepted
& NEG_SIGN
) {
845 if (!gensec_have_feature(gensec_security
, GENSEC_FEATURE_SIGN
)) {
846 DEBUG(1, ("Remote client wanted sign, but gensec refused\n"));
847 return NT_STATUS_ACCESS_DENIED
;
849 gensec_gssapi_state
->sasl_protection
|= NEG_SIGN
;
851 if (security_accepted
& NEG_NONE
) {
852 gensec_gssapi_state
->sasl_protection
|= NEG_NONE
;
855 /* quirk: This changes the value that gensec_have_feature returns, to be that after SASL negotiation */
856 gensec_gssapi_state
->sasl_state
= STAGE_DONE
;
857 if (gensec_have_feature(gensec_security
, GENSEC_FEATURE_SEAL
)) {
858 DEBUG(5, ("SASL/GSSAPI Connection from client will be cryptographically sealed\n"));
859 } else if (gensec_have_feature(gensec_security
, GENSEC_FEATURE_SIGN
)) {
860 DEBUG(5, ("SASL/GSSAPI Connection from client will be cryptographically signed\n"));
862 DEBUG(5, ("SASL/GSSAPI Connection from client will have no cryptographic protection\n"));
865 *out
= data_blob(NULL
, 0);
869 return NT_STATUS_INVALID_PARAMETER
;
873 static NTSTATUS
gensec_gssapi_wrap(struct gensec_security
*gensec_security
,
878 struct gensec_gssapi_state
*gensec_gssapi_state
879 = talloc_get_type(gensec_security
->private_data
, struct gensec_gssapi_state
);
880 OM_uint32 maj_stat
, min_stat
;
881 gss_buffer_desc input_token
, output_token
;
883 input_token
.length
= in
->length
;
884 input_token
.value
= in
->data
;
886 maj_stat
= gss_wrap(&min_stat
,
887 gensec_gssapi_state
->gssapi_context
,
888 gensec_have_feature(gensec_security
, GENSEC_FEATURE_SEAL
),
893 if (GSS_ERROR(maj_stat
)) {
894 DEBUG(1, ("gensec_gssapi_wrap: GSS Wrap failed: %s\n",
895 gssapi_error_string(mem_ctx
, maj_stat
, min_stat
, gensec_gssapi_state
->gss_oid
)));
896 return NT_STATUS_ACCESS_DENIED
;
899 *out
= data_blob_talloc(mem_ctx
, output_token
.value
, output_token
.length
);
900 gss_release_buffer(&min_stat
, &output_token
);
902 if (gensec_gssapi_state
->sasl
) {
903 size_t max_wrapped_size
= gensec_gssapi_max_wrapped_size(gensec_security
);
904 if (max_wrapped_size
< out
->length
) {
905 DEBUG(1, ("gensec_gssapi_wrap: when wrapped, INPUT data (%u) is grew to be larger than SASL negotiated maximum output size (%u > %u)\n",
906 (unsigned)in
->length
,
907 (unsigned)out
->length
,
908 (unsigned int)max_wrapped_size
));
909 return NT_STATUS_INVALID_PARAMETER
;
913 if (gensec_have_feature(gensec_security
, GENSEC_FEATURE_SEAL
)
915 return NT_STATUS_ACCESS_DENIED
;
920 static NTSTATUS
gensec_gssapi_unwrap(struct gensec_security
*gensec_security
,
925 struct gensec_gssapi_state
*gensec_gssapi_state
926 = talloc_get_type(gensec_security
->private_data
, struct gensec_gssapi_state
);
927 OM_uint32 maj_stat
, min_stat
;
928 gss_buffer_desc input_token
, output_token
;
931 input_token
.length
= in
->length
;
932 input_token
.value
= in
->data
;
934 if (gensec_gssapi_state
->sasl
) {
935 size_t max_wrapped_size
= gensec_gssapi_max_wrapped_size(gensec_security
);
936 if (max_wrapped_size
< in
->length
) {
937 DEBUG(1, ("gensec_gssapi_unwrap: WRAPPED data is larger than SASL negotiated maximum size\n"));
938 return NT_STATUS_INVALID_PARAMETER
;
942 maj_stat
= gss_unwrap(&min_stat
,
943 gensec_gssapi_state
->gssapi_context
,
948 if (GSS_ERROR(maj_stat
)) {
949 DEBUG(1, ("gensec_gssapi_unwrap: GSS UnWrap failed: %s\n",
950 gssapi_error_string(mem_ctx
, maj_stat
, min_stat
, gensec_gssapi_state
->gss_oid
)));
951 return NT_STATUS_ACCESS_DENIED
;
954 *out
= data_blob_talloc(mem_ctx
, output_token
.value
, output_token
.length
);
955 gss_release_buffer(&min_stat
, &output_token
);
957 if (gensec_have_feature(gensec_security
, GENSEC_FEATURE_SEAL
)
959 return NT_STATUS_ACCESS_DENIED
;
964 /* Find out the maximum input size negotiated on this connection */
966 static size_t gensec_gssapi_max_input_size(struct gensec_security
*gensec_security
)
968 struct gensec_gssapi_state
*gensec_gssapi_state
969 = talloc_get_type(gensec_security
->private_data
, struct gensec_gssapi_state
);
970 OM_uint32 maj_stat
, min_stat
;
971 OM_uint32 max_input_size
;
973 maj_stat
= gss_wrap_size_limit(&min_stat
,
974 gensec_gssapi_state
->gssapi_context
,
975 gensec_have_feature(gensec_security
, GENSEC_FEATURE_SEAL
),
977 gensec_gssapi_state
->max_wrap_buf_size
,
979 if (GSS_ERROR(maj_stat
)) {
980 TALLOC_CTX
*mem_ctx
= talloc_new(NULL
);
981 DEBUG(1, ("gensec_gssapi_max_input_size: determinaing signature size with gss_wrap_size_limit failed: %s\n",
982 gssapi_error_string(mem_ctx
, maj_stat
, min_stat
, gensec_gssapi_state
->gss_oid
)));
983 talloc_free(mem_ctx
);
987 return max_input_size
;
990 /* Find out the maximum output size negotiated on this connection */
991 static size_t gensec_gssapi_max_wrapped_size(struct gensec_security
*gensec_security
)
993 struct gensec_gssapi_state
*gensec_gssapi_state
= talloc_get_type(gensec_security
->private_data
, struct gensec_gssapi_state
);;
994 return gensec_gssapi_state
->max_wrap_buf_size
;
997 static NTSTATUS
gensec_gssapi_seal_packet(struct gensec_security
*gensec_security
,
999 uint8_t *data
, size_t length
,
1000 const uint8_t *whole_pdu
, size_t pdu_length
,
1003 struct gensec_gssapi_state
*gensec_gssapi_state
1004 = talloc_get_type(gensec_security
->private_data
, struct gensec_gssapi_state
);
1005 OM_uint32 maj_stat
, min_stat
;
1006 gss_buffer_desc input_token
, output_token
;
1010 input_token
.length
= length
;
1011 input_token
.value
= data
;
1013 maj_stat
= gss_wrap(&min_stat
,
1014 gensec_gssapi_state
->gssapi_context
,
1015 gensec_have_feature(gensec_security
, GENSEC_FEATURE_SEAL
),
1020 if (GSS_ERROR(maj_stat
)) {
1021 DEBUG(1, ("gensec_gssapi_seal_packet: GSS Wrap failed: %s\n",
1022 gssapi_error_string(mem_ctx
, maj_stat
, min_stat
, gensec_gssapi_state
->gss_oid
)));
1023 return NT_STATUS_ACCESS_DENIED
;
1026 if (output_token
.length
< input_token
.length
) {
1027 DEBUG(1, ("gensec_gssapi_seal_packet: GSS Wrap length [%ld] *less* than caller length [%ld]\n",
1028 (long)output_token
.length
, (long)length
));
1029 return NT_STATUS_INTERNAL_ERROR
;
1031 sig_length
= output_token
.length
- input_token
.length
;
1033 memcpy(data
, ((uint8_t *)output_token
.value
) + sig_length
, length
);
1034 *sig
= data_blob_talloc(mem_ctx
, (uint8_t *)output_token
.value
, sig_length
);
1036 dump_data_pw("gensec_gssapi_seal_packet: sig\n", sig
->data
, sig
->length
);
1037 dump_data_pw("gensec_gssapi_seal_packet: clear\n", data
, length
);
1038 dump_data_pw("gensec_gssapi_seal_packet: sealed\n", ((uint8_t *)output_token
.value
) + sig_length
, output_token
.length
- sig_length
);
1040 gss_release_buffer(&min_stat
, &output_token
);
1042 if (gensec_have_feature(gensec_security
, GENSEC_FEATURE_SEAL
)
1044 return NT_STATUS_ACCESS_DENIED
;
1046 return NT_STATUS_OK
;
1049 static NTSTATUS
gensec_gssapi_unseal_packet(struct gensec_security
*gensec_security
,
1050 uint8_t *data
, size_t length
,
1051 const uint8_t *whole_pdu
, size_t pdu_length
,
1052 const DATA_BLOB
*sig
)
1054 struct gensec_gssapi_state
*gensec_gssapi_state
1055 = talloc_get_type(gensec_security
->private_data
, struct gensec_gssapi_state
);
1056 OM_uint32 maj_stat
, min_stat
;
1057 gss_buffer_desc input_token
, output_token
;
1059 gss_qop_t qop_state
;
1062 dump_data_pw("gensec_gssapi_unseal_packet: sig\n", sig
->data
, sig
->length
);
1064 in
= data_blob_talloc(gensec_security
, NULL
, sig
->length
+ length
);
1066 memcpy(in
.data
, sig
->data
, sig
->length
);
1067 memcpy(in
.data
+ sig
->length
, data
, length
);
1069 input_token
.length
= in
.length
;
1070 input_token
.value
= in
.data
;
1072 maj_stat
= gss_unwrap(&min_stat
,
1073 gensec_gssapi_state
->gssapi_context
,
1078 talloc_free(in
.data
);
1079 if (GSS_ERROR(maj_stat
)) {
1080 char *error_string
= gssapi_error_string(NULL
, maj_stat
, min_stat
, gensec_gssapi_state
->gss_oid
);
1081 DEBUG(1, ("gensec_gssapi_unseal_packet: GSS UnWrap failed: %s\n",
1083 talloc_free(error_string
);
1084 return NT_STATUS_ACCESS_DENIED
;
1087 if (output_token
.length
!= length
) {
1088 return NT_STATUS_INTERNAL_ERROR
;
1091 memcpy(data
, output_token
.value
, length
);
1093 gss_release_buffer(&min_stat
, &output_token
);
1095 if (gensec_have_feature(gensec_security
, GENSEC_FEATURE_SEAL
)
1097 return NT_STATUS_ACCESS_DENIED
;
1099 return NT_STATUS_OK
;
1102 static NTSTATUS
gensec_gssapi_sign_packet(struct gensec_security
*gensec_security
,
1103 TALLOC_CTX
*mem_ctx
,
1104 const uint8_t *data
, size_t length
,
1105 const uint8_t *whole_pdu
, size_t pdu_length
,
1108 struct gensec_gssapi_state
*gensec_gssapi_state
1109 = talloc_get_type(gensec_security
->private_data
, struct gensec_gssapi_state
);
1110 OM_uint32 maj_stat
, min_stat
;
1111 gss_buffer_desc input_token
, output_token
;
1113 if (gensec_security
->want_features
& GENSEC_FEATURE_SIGN_PKT_HEADER
) {
1114 input_token
.length
= pdu_length
;
1115 input_token
.value
= discard_const_p(uint8_t *, whole_pdu
);
1117 input_token
.length
= length
;
1118 input_token
.value
= discard_const_p(uint8_t *, data
);
1121 maj_stat
= gss_get_mic(&min_stat
,
1122 gensec_gssapi_state
->gssapi_context
,
1126 if (GSS_ERROR(maj_stat
)) {
1127 DEBUG(1, ("GSS GetMic failed: %s\n",
1128 gssapi_error_string(mem_ctx
, maj_stat
, min_stat
, gensec_gssapi_state
->gss_oid
)));
1129 return NT_STATUS_ACCESS_DENIED
;
1132 *sig
= data_blob_talloc(mem_ctx
, (uint8_t *)output_token
.value
, output_token
.length
);
1134 dump_data_pw("gensec_gssapi_seal_packet: sig\n", sig
->data
, sig
->length
);
1136 gss_release_buffer(&min_stat
, &output_token
);
1138 return NT_STATUS_OK
;
1141 static NTSTATUS
gensec_gssapi_check_packet(struct gensec_security
*gensec_security
,
1142 const uint8_t *data
, size_t length
,
1143 const uint8_t *whole_pdu
, size_t pdu_length
,
1144 const DATA_BLOB
*sig
)
1146 struct gensec_gssapi_state
*gensec_gssapi_state
1147 = talloc_get_type(gensec_security
->private_data
, struct gensec_gssapi_state
);
1148 OM_uint32 maj_stat
, min_stat
;
1149 gss_buffer_desc input_token
;
1150 gss_buffer_desc input_message
;
1151 gss_qop_t qop_state
;
1153 dump_data_pw("gensec_gssapi_seal_packet: sig\n", sig
->data
, sig
->length
);
1155 if (gensec_security
->want_features
& GENSEC_FEATURE_SIGN_PKT_HEADER
) {
1156 input_message
.length
= pdu_length
;
1157 input_message
.value
= discard_const(whole_pdu
);
1159 input_message
.length
= length
;
1160 input_message
.value
= discard_const(data
);
1163 input_token
.length
= sig
->length
;
1164 input_token
.value
= sig
->data
;
1166 maj_stat
= gss_verify_mic(&min_stat
,
1167 gensec_gssapi_state
->gssapi_context
,
1171 if (GSS_ERROR(maj_stat
)) {
1172 char *error_string
= gssapi_error_string(NULL
, maj_stat
, min_stat
, gensec_gssapi_state
->gss_oid
);
1173 DEBUG(1, ("GSS VerifyMic failed: %s\n", error_string
));
1174 talloc_free(error_string
);
1176 return NT_STATUS_ACCESS_DENIED
;
1179 return NT_STATUS_OK
;
1182 /* Try to figure out what features we actually got on the connection */
1183 static bool gensec_gssapi_have_feature(struct gensec_security
*gensec_security
,
1186 struct gensec_gssapi_state
*gensec_gssapi_state
1187 = talloc_get_type(gensec_security
->private_data
, struct gensec_gssapi_state
);
1188 if (feature
& GENSEC_FEATURE_SIGN
) {
1189 /* If we are going GSSAPI SASL, then we honour the second negotiation */
1190 if (gensec_gssapi_state
->sasl
1191 && gensec_gssapi_state
->sasl_state
== STAGE_DONE
) {
1192 return ((gensec_gssapi_state
->sasl_protection
& NEG_SIGN
)
1193 && (gensec_gssapi_state
->gss_got_flags
& GSS_C_INTEG_FLAG
));
1195 return gensec_gssapi_state
->gss_got_flags
& GSS_C_INTEG_FLAG
;
1197 if (feature
& GENSEC_FEATURE_SEAL
) {
1198 /* If we are going GSSAPI SASL, then we honour the second negotiation */
1199 if (gensec_gssapi_state
->sasl
1200 && gensec_gssapi_state
->sasl_state
== STAGE_DONE
) {
1201 return ((gensec_gssapi_state
->sasl_protection
& NEG_SEAL
)
1202 && (gensec_gssapi_state
->gss_got_flags
& GSS_C_CONF_FLAG
));
1204 return gensec_gssapi_state
->gss_got_flags
& GSS_C_CONF_FLAG
;
1206 if (feature
& GENSEC_FEATURE_SESSION_KEY
) {
1207 /* Only for GSSAPI/Krb5 */
1208 if (gss_oid_equal(gensec_gssapi_state
->gss_oid
, gss_mech_krb5
)) {
1212 if (feature
& GENSEC_FEATURE_DCE_STYLE
) {
1213 return gensec_gssapi_state
->gss_got_flags
& GSS_C_DCE_STYLE
;
1215 if (feature
& GENSEC_FEATURE_NEW_SPNEGO
) {
1219 if (!(gensec_gssapi_state
->gss_got_flags
& GSS_C_INTEG_FLAG
)) {
1223 if (gensec_setting_bool(gensec_security
->settings
, "gensec_gssapi", "force_new_spnego", false)) {
1226 if (gensec_setting_bool(gensec_security
->settings
, "gensec_gssapi", "disable_new_spnego", false)) {
1230 status
= gssapi_get_session_key(gensec_gssapi_state
,
1231 gensec_gssapi_state
->gssapi_context
, NULL
, &keytype
);
1233 * We should do a proper sig on the mechListMic unless
1234 * we know we have to be backwards compatible with
1235 * earlier windows versions.
1237 * Negotiating a non-krb5
1238 * mech for example should be regarded as having
1241 if (NT_STATUS_IS_OK(status
)) {
1243 case ENCTYPE_DES_CBC_CRC
:
1244 case ENCTYPE_DES_CBC_MD5
:
1245 case ENCTYPE_ARCFOUR_HMAC
:
1246 case ENCTYPE_DES3_CBC_SHA1
:
1252 /* We can always do async (rather than strict request/reply) packets. */
1253 if (feature
& GENSEC_FEATURE_ASYNC_REPLIES
) {
1260 * Extract the 'sesssion key' needed by SMB signing and ncacn_np
1261 * (for encrypting some passwords).
1263 * This breaks all the abstractions, but what do you expect...
1265 static NTSTATUS
gensec_gssapi_session_key(struct gensec_security
*gensec_security
,
1266 TALLOC_CTX
*mem_ctx
,
1267 DATA_BLOB
*session_key
)
1269 struct gensec_gssapi_state
*gensec_gssapi_state
1270 = talloc_get_type(gensec_security
->private_data
, struct gensec_gssapi_state
);
1271 return gssapi_get_session_key(mem_ctx
, gensec_gssapi_state
->gssapi_context
, session_key
, NULL
);
1274 /* Get some basic (and authorization) information about the user on
1275 * this session. This uses either the PAC (if present) or a local
1276 * database lookup */
1277 static NTSTATUS
gensec_gssapi_session_info(struct gensec_security
*gensec_security
,
1278 TALLOC_CTX
*mem_ctx
,
1279 struct auth_session_info
**_session_info
)
1282 TALLOC_CTX
*tmp_ctx
;
1283 struct gensec_gssapi_state
*gensec_gssapi_state
1284 = talloc_get_type(gensec_security
->private_data
, struct gensec_gssapi_state
);
1285 struct auth_session_info
*session_info
= NULL
;
1286 OM_uint32 maj_stat
, min_stat
;
1287 DATA_BLOB pac_blob
, *pac_blob_ptr
= NULL
;
1289 gss_buffer_desc name_token
;
1290 char *principal_string
;
1292 tmp_ctx
= talloc_named(mem_ctx
, 0, "gensec_gssapi_session_info context");
1293 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx
);
1295 maj_stat
= gss_display_name (&min_stat
,
1296 gensec_gssapi_state
->client_name
,
1299 if (GSS_ERROR(maj_stat
)) {
1300 DEBUG(1, ("GSS display_name failed: %s\n",
1301 gssapi_error_string(tmp_ctx
, maj_stat
, min_stat
, gensec_gssapi_state
->gss_oid
)));
1302 talloc_free(tmp_ctx
);
1303 return NT_STATUS_FOOBAR
;
1306 principal_string
= talloc_strndup(tmp_ctx
,
1307 (const char *)name_token
.value
,
1310 gss_release_buffer(&min_stat
, &name_token
);
1312 if (!principal_string
) {
1313 talloc_free(tmp_ctx
);
1314 return NT_STATUS_NO_MEMORY
;
1317 nt_status
= gssapi_obtain_pac_blob(tmp_ctx
, gensec_gssapi_state
->gssapi_context
,
1318 gensec_gssapi_state
->client_name
,
1321 /* IF we have the PAC - otherwise we need to get this
1322 * data from elsewere - local ldb, or (TODO) lookup of some
1325 if (NT_STATUS_IS_OK(nt_status
)) {
1326 pac_blob_ptr
= &pac_blob
;
1328 nt_status
= gensec_generate_session_info_pac(tmp_ctx
,
1330 gensec_gssapi_state
->smb_krb5_context
,
1331 pac_blob_ptr
, principal_string
,
1332 gensec_get_remote_address(gensec_security
),
1334 if (!NT_STATUS_IS_OK(nt_status
)) {
1335 talloc_free(tmp_ctx
);
1339 nt_status
= gensec_gssapi_session_key(gensec_security
, session_info
, &session_info
->session_key
);
1340 if (!NT_STATUS_IS_OK(nt_status
)) {
1341 talloc_free(tmp_ctx
);
1345 if (!(gensec_gssapi_state
->gss_got_flags
& GSS_C_DELEG_FLAG
)) {
1346 DEBUG(10, ("gensec_gssapi: NO delegated credentials supplied by client\n"));
1348 krb5_error_code ret
;
1349 const char *error_string
;
1351 DEBUG(10, ("gensec_gssapi: delegated credentials supplied by client\n"));
1352 session_info
->credentials
= cli_credentials_init(session_info
);
1353 if (!session_info
->credentials
) {
1354 talloc_free(tmp_ctx
);
1355 return NT_STATUS_NO_MEMORY
;
1358 cli_credentials_set_conf(session_info
->credentials
, gensec_security
->settings
->lp_ctx
);
1359 /* Just so we don't segfault trying to get at a username */
1360 cli_credentials_set_anonymous(session_info
->credentials
);
1362 ret
= cli_credentials_set_client_gss_creds(session_info
->credentials
,
1363 gensec_security
->settings
->lp_ctx
,
1364 gensec_gssapi_state
->delegated_cred_handle
,
1365 CRED_SPECIFIED
, &error_string
);
1367 talloc_free(tmp_ctx
);
1368 DEBUG(2,("Failed to get gss creds: %s\n", error_string
));
1369 return NT_STATUS_NO_MEMORY
;
1372 /* This credential handle isn't useful for password authentication, so ensure nobody tries to do that */
1373 cli_credentials_set_kerberos_state(session_info
->credentials
, CRED_MUST_USE_KERBEROS
);
1375 /* It has been taken from this place... */
1376 gensec_gssapi_state
->delegated_cred_handle
= GSS_C_NO_CREDENTIAL
;
1378 *_session_info
= talloc_steal(mem_ctx
, session_info
);
1379 talloc_free(tmp_ctx
);
1381 return NT_STATUS_OK
;
1384 static size_t gensec_gssapi_sig_size(struct gensec_security
*gensec_security
, size_t data_size
)
1386 struct gensec_gssapi_state
*gensec_gssapi_state
1387 = talloc_get_type(gensec_security
->private_data
, struct gensec_gssapi_state
);
1390 if (gensec_gssapi_state
->sig_size
) {
1391 return gensec_gssapi_state
->sig_size
;
1394 if (gensec_gssapi_state
->gss_got_flags
& GSS_C_CONF_FLAG
) {
1395 gensec_gssapi_state
->sig_size
= 45;
1397 gensec_gssapi_state
->sig_size
= 37;
1400 status
= gensec_gssapi_init_lucid(gensec_gssapi_state
);
1401 if (!NT_STATUS_IS_OK(status
)) {
1402 return gensec_gssapi_state
->sig_size
;
1405 if (gensec_gssapi_state
->lucid
->protocol
== 1) {
1406 if (gensec_gssapi_state
->gss_got_flags
& GSS_C_CONF_FLAG
) {
1408 * TODO: windows uses 76 here, but we don't know
1409 * gss_wrap works with aes keys yet
1411 gensec_gssapi_state
->sig_size
= 76;
1413 gensec_gssapi_state
->sig_size
= 28;
1415 } else if (gensec_gssapi_state
->lucid
->protocol
== 0) {
1416 switch (gensec_gssapi_state
->lucid
->rfc1964_kd
.ctx_key
.type
) {
1418 case KEYTYPE_ARCFOUR
:
1419 case KEYTYPE_ARCFOUR_56
:
1420 if (gensec_gssapi_state
->gss_got_flags
& GSS_C_CONF_FLAG
) {
1421 gensec_gssapi_state
->sig_size
= 45;
1423 gensec_gssapi_state
->sig_size
= 37;
1427 if (gensec_gssapi_state
->gss_got_flags
& GSS_C_CONF_FLAG
) {
1428 gensec_gssapi_state
->sig_size
= 57;
1430 gensec_gssapi_state
->sig_size
= 49;
1436 return gensec_gssapi_state
->sig_size
;
1439 static const char *gensec_gssapi_krb5_oids
[] = {
1440 GENSEC_OID_KERBEROS5_OLD
,
1441 GENSEC_OID_KERBEROS5
,
1445 static const char *gensec_gssapi_spnego_oids
[] = {
1450 /* As a server, this could in theory accept any GSSAPI mech */
1451 static const struct gensec_security_ops gensec_gssapi_spnego_security_ops
= {
1452 .name
= "gssapi_spnego",
1453 .sasl_name
= "GSS-SPNEGO",
1454 .auth_type
= DCERPC_AUTH_TYPE_SPNEGO
,
1455 .oid
= gensec_gssapi_spnego_oids
,
1456 .client_start
= gensec_gssapi_client_start
,
1457 .server_start
= gensec_gssapi_server_start
,
1458 .magic
= gensec_magic_check_krb5_oid
,
1459 .update
= gensec_gssapi_update
,
1460 .session_key
= gensec_gssapi_session_key
,
1461 .session_info
= gensec_gssapi_session_info
,
1462 .sign_packet
= gensec_gssapi_sign_packet
,
1463 .check_packet
= gensec_gssapi_check_packet
,
1464 .seal_packet
= gensec_gssapi_seal_packet
,
1465 .unseal_packet
= gensec_gssapi_unseal_packet
,
1466 .wrap
= gensec_gssapi_wrap
,
1467 .unwrap
= gensec_gssapi_unwrap
,
1468 .have_feature
= gensec_gssapi_have_feature
,
1471 .priority
= GENSEC_GSSAPI
1474 /* As a server, this could in theory accept any GSSAPI mech */
1475 static const struct gensec_security_ops gensec_gssapi_krb5_security_ops
= {
1476 .name
= "gssapi_krb5",
1477 .auth_type
= DCERPC_AUTH_TYPE_KRB5
,
1478 .oid
= gensec_gssapi_krb5_oids
,
1479 .client_start
= gensec_gssapi_client_start
,
1480 .server_start
= gensec_gssapi_server_start
,
1481 .magic
= gensec_magic_check_krb5_oid
,
1482 .update
= gensec_gssapi_update
,
1483 .session_key
= gensec_gssapi_session_key
,
1484 .session_info
= gensec_gssapi_session_info
,
1485 .sig_size
= gensec_gssapi_sig_size
,
1486 .sign_packet
= gensec_gssapi_sign_packet
,
1487 .check_packet
= gensec_gssapi_check_packet
,
1488 .seal_packet
= gensec_gssapi_seal_packet
,
1489 .unseal_packet
= gensec_gssapi_unseal_packet
,
1490 .wrap
= gensec_gssapi_wrap
,
1491 .unwrap
= gensec_gssapi_unwrap
,
1492 .have_feature
= gensec_gssapi_have_feature
,
1495 .priority
= GENSEC_GSSAPI
1498 /* As a server, this could in theory accept any GSSAPI mech */
1499 static const struct gensec_security_ops gensec_gssapi_sasl_krb5_security_ops
= {
1500 .name
= "gssapi_krb5_sasl",
1501 .sasl_name
= "GSSAPI",
1502 .client_start
= gensec_gssapi_sasl_client_start
,
1503 .server_start
= gensec_gssapi_sasl_server_start
,
1504 .update
= gensec_gssapi_update
,
1505 .session_key
= gensec_gssapi_session_key
,
1506 .session_info
= gensec_gssapi_session_info
,
1507 .max_input_size
= gensec_gssapi_max_input_size
,
1508 .max_wrapped_size
= gensec_gssapi_max_wrapped_size
,
1509 .wrap
= gensec_gssapi_wrap
,
1510 .unwrap
= gensec_gssapi_unwrap
,
1511 .have_feature
= gensec_gssapi_have_feature
,
1514 .priority
= GENSEC_GSSAPI
1517 _PUBLIC_ NTSTATUS
gensec_gssapi_init(void)
1521 ret
= gensec_register(&gensec_gssapi_spnego_security_ops
);
1522 if (!NT_STATUS_IS_OK(ret
)) {
1523 DEBUG(0,("Failed to register '%s' gensec backend!\n",
1524 gensec_gssapi_spnego_security_ops
.name
));
1528 ret
= gensec_register(&gensec_gssapi_krb5_security_ops
);
1529 if (!NT_STATUS_IS_OK(ret
)) {
1530 DEBUG(0,("Failed to register '%s' gensec backend!\n",
1531 gensec_gssapi_krb5_security_ops
.name
));
1535 ret
= gensec_register(&gensec_gssapi_sasl_krb5_security_ops
);
1536 if (!NT_STATUS_IS_OK(ret
)) {
1537 DEBUG(0,("Failed to register '%s' gensec backend!\n",
1538 gensec_gssapi_sasl_krb5_security_ops
.name
));