2 Unix SMB/CIFS implementation.
4 Kerberos backend for GENSEC
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004
7 Copyright (C) Stefan Metzmacher <metze@samba.org> 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 2 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, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include "system/kerberos.h"
27 #include "auth/kerberos/kerberos.h"
28 #include "librpc/gen_ndr/ndr_krb5pac.h"
29 #include "auth/auth.h"
32 #define DBGC_CLASS DBGC_AUTH
34 static const gss_OID_desc gensec_gss_krb5_mechanism_oid_desc =
35 {9, (void *)discard_const_p(char, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02")};
37 static const gss_OID_desc gensec_gss_spnego_mechanism_oid_desc =
38 {6, (void *)discard_const_p(char, "\x2b\x06\x01\x05\x05\x02")};
40 struct gensec_gssapi_state {
41 gss_ctx_id_t gssapi_context;
42 struct gss_channel_bindings_struct *input_chan_bindings;
43 gss_name_t server_name;
44 gss_name_t client_name;
45 OM_uint32 want_flags, got_flags;
46 const gss_OID_desc *gss_oid;
48 DATA_BLOB session_key;
51 static int gensec_gssapi_destory(void *ptr)
53 struct gensec_gssapi_state *gensec_gssapi_state = ptr;
54 OM_uint32 maj_stat, min_stat;
56 if (gensec_gssapi_state->gssapi_context != GSS_C_NO_CONTEXT) {
57 maj_stat = gss_delete_sec_context (&min_stat,
58 &gensec_gssapi_state->gssapi_context,
62 if (gensec_gssapi_state->server_name != GSS_C_NO_NAME) {
63 maj_stat = gss_release_name(&min_stat, &gensec_gssapi_state->server_name);
65 if (gensec_gssapi_state->client_name != GSS_C_NO_NAME) {
66 maj_stat = gss_release_name(&min_stat, &gensec_gssapi_state->client_name);
71 static NTSTATUS gensec_gssapi_start(struct gensec_security *gensec_security)
73 struct gensec_gssapi_state *gensec_gssapi_state;
75 gensec_gssapi_state = talloc(gensec_security, struct gensec_gssapi_state);
76 if (!gensec_gssapi_state) {
77 return NT_STATUS_NO_MEMORY;
80 gensec_security->private_data = gensec_gssapi_state;
82 gensec_gssapi_state->gssapi_context = GSS_C_NO_CONTEXT;
83 gensec_gssapi_state->server_name = GSS_C_NO_NAME;
84 gensec_gssapi_state->client_name = GSS_C_NO_NAME;
86 talloc_set_destructor(gensec_gssapi_state, gensec_gssapi_destory);
88 /* TODO: Fill in channel bindings */
89 gensec_gssapi_state->input_chan_bindings = GSS_C_NO_CHANNEL_BINDINGS;
91 gensec_gssapi_state->want_flags = 0;
92 gensec_gssapi_state->got_flags = 0;
94 gensec_gssapi_state->session_key = data_blob(NULL, 0);
95 gensec_gssapi_state->pac = data_blob(NULL, 0);
97 if (gensec_security->want_features & GENSEC_FEATURE_SESSION_KEY) {
98 #ifndef HAVE_GSSKRB5_GET_INITIATOR_SUBKEY
99 /* GSSAPI won't give us the session keys, without the
100 * right hooks. This is critical when requested, so
102 return NT_STATUS_INVALID_PARAMETER;
105 if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
106 gensec_gssapi_state->want_flags |= GSS_C_INTEG_FLAG;
108 if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
109 gensec_gssapi_state->want_flags |= GSS_C_CONF_FLAG;
111 if (gensec_security->want_features & GENSEC_FEATURE_DCE_STYLE) {
112 #ifndef GSS_C_DCE_STYLE
113 /* GSSAPI DCE_STYLE is critical when requested, so
115 return NT_STATUS_INVALID_PARAMETER;
117 gensec_gssapi_state->want_flags |= GSS_C_DCE_STYLE;
121 if ((strcmp(gensec_security->ops->oid, GENSEC_OID_KERBEROS5) == 0)
122 || (strcmp(gensec_security->ops->oid, GENSEC_OID_KERBEROS5_OLD) == 0)) {
123 gensec_gssapi_state->gss_oid = &gensec_gss_krb5_mechanism_oid_desc;
124 } else if (strcmp(gensec_security->ops->oid, GENSEC_OID_SPNEGO) == 0) {
125 gensec_gssapi_state->gss_oid = &gensec_gss_spnego_mechanism_oid_desc;
127 DEBUG(1, ("gensec_gssapi incorrectly configured - cannot determine gss OID from %s\n",
128 gensec_security->ops->oid));
129 return NT_STATUS_INVALID_PARAMETER;
135 static NTSTATUS gensec_gssapi_server_start(struct gensec_security *gensec_security)
138 struct gensec_gssapi_state *gensec_gssapi_state;
140 nt_status = gensec_gssapi_start(gensec_security);
141 if (!NT_STATUS_IS_OK(nt_status)) {
145 gensec_gssapi_state = gensec_security->private_data;
150 static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_security)
152 struct gensec_gssapi_state *gensec_gssapi_state;
154 gss_buffer_desc name_token;
155 OM_uint32 maj_stat, min_stat;
157 gss_OID_desc hostbased = {10,
158 (void *)discard_const_p(char, "\x2a\x86\x48\x86\xf7\x12"
159 "\x01\x02\x01\x04")};
161 nt_status = gensec_gssapi_start(gensec_security);
162 if (!NT_STATUS_IS_OK(nt_status)) {
166 gensec_gssapi_state = gensec_security->private_data;
168 name_token.value = talloc_asprintf(gensec_gssapi_state, "%s@%s", gensec_get_target_service(gensec_security),
169 gensec_get_target_hostname(gensec_security));
170 DEBUG(0, ("name: %s\n", (char *)name_token.value));
171 name_token.length = strlen(name_token.value);
173 maj_stat = gss_import_name (&min_stat,
176 &gensec_gssapi_state->server_name);
180 return NT_STATUS_UNSUCCESSFUL;
188 * Next state function for the GSSAPI GENSEC mechanism
190 * @param gensec_gssapi_state GSSAPI State
191 * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
192 * @param in The request, as a DATA_BLOB
193 * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
194 * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent,
195 * or NT_STATUS_OK if the user is authenticated.
198 static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security,
199 TALLOC_CTX *out_mem_ctx,
200 const DATA_BLOB in, DATA_BLOB *out)
202 struct gensec_gssapi_state *gensec_gssapi_state = gensec_security->private_data;
203 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
204 OM_uint32 maj_stat, min_stat;
206 gss_buffer_desc input_token, output_token;
208 input_token.length = in.length;
209 input_token.value = in.data;
211 switch (gensec_security->gensec_role) {
214 maj_stat = gss_init_sec_context(&min_stat,
216 &gensec_gssapi_state->gssapi_context,
217 gensec_gssapi_state->server_name,
218 discard_const_p(gss_OID_desc, gensec_gssapi_state->gss_oid),
219 gensec_gssapi_state->want_flags,
221 gensec_gssapi_state->input_chan_bindings,
225 &gensec_gssapi_state->got_flags, /* ret flags */
231 maj_stat = gss_accept_sec_context(&min_stat,
232 &gensec_gssapi_state->gssapi_context,
235 gensec_gssapi_state->input_chan_bindings,
236 &gensec_gssapi_state->client_name,
239 &gensec_gssapi_state->got_flags,
242 gensec_gssapi_state->gss_oid = gss_oid_p;
246 return NT_STATUS_INVALID_PARAMETER;
250 *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length);
251 gss_release_buffer(&min_stat2, &output_token);
253 if (maj_stat == GSS_S_COMPLETE) {
255 } else if (maj_stat == GSS_S_CONTINUE_NEEDED) {
256 return NT_STATUS_MORE_PROCESSING_REQUIRED;
258 gss_buffer_desc msg1, msg2;
259 OM_uint32 msg_ctx = 0;
263 gss_display_status(&min_stat2, maj_stat, GSS_C_GSS_CODE,
264 GSS_C_NULL_OID, &msg_ctx, &msg1);
265 gss_display_status(&min_stat2, min_stat, GSS_C_MECH_CODE,
266 GSS_C_NULL_OID, &msg_ctx, &msg2);
267 DEBUG(1, ("gensec_gssapi_update: %s : %s\n", (char *)msg1.value, (char *)msg2.value));
268 gss_release_buffer(&min_stat2, &msg1);
269 gss_release_buffer(&min_stat2, &msg2);
276 static NTSTATUS gensec_gssapi_wrap(struct gensec_security *gensec_security,
281 struct gensec_gssapi_state *gensec_gssapi_state = gensec_security->private_data;
282 OM_uint32 maj_stat, min_stat;
283 gss_buffer_desc input_token, output_token;
285 input_token.length = in->length;
286 input_token.value = in->data;
288 maj_stat = gss_wrap(&min_stat,
289 gensec_gssapi_state->gssapi_context,
290 gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL),
295 if (GSS_ERROR(maj_stat)) {
296 return NT_STATUS_ACCESS_DENIED;
298 *out = data_blob_talloc(mem_ctx, output_token.value, output_token.length);
300 gss_release_buffer(&min_stat, &output_token);
302 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
304 return NT_STATUS_ACCESS_DENIED;
309 static NTSTATUS gensec_gssapi_unwrap(struct gensec_security *gensec_security,
314 struct gensec_gssapi_state *gensec_gssapi_state = gensec_security->private_data;
315 OM_uint32 maj_stat, min_stat;
316 gss_buffer_desc input_token, output_token;
319 input_token.length = in->length;
320 input_token.value = in->data;
322 maj_stat = gss_unwrap(&min_stat,
323 gensec_gssapi_state->gssapi_context,
328 if (GSS_ERROR(maj_stat)) {
329 return NT_STATUS_ACCESS_DENIED;
331 *out = data_blob_talloc(mem_ctx, output_token.value, output_token.length);
333 gss_release_buffer(&min_stat, &output_token);
335 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
337 return NT_STATUS_ACCESS_DENIED;
342 static size_t gensec_gssapi_sig_size(struct gensec_security *gensec_security)
344 /* not const but work for DCERPC packets and arcfour */
348 static NTSTATUS gensec_gssapi_seal_packet(struct gensec_security *gensec_security,
350 uint8_t *data, size_t length,
351 const uint8_t *whole_pdu, size_t pdu_length,
354 struct gensec_gssapi_state *gensec_gssapi_state = gensec_security->private_data;
355 OM_uint32 maj_stat, min_stat;
356 gss_buffer_desc input_token, output_token;
358 ssize_t sig_length = 0;
360 input_token.length = length;
361 input_token.value = data;
363 maj_stat = gss_wrap(&min_stat,
364 gensec_gssapi_state->gssapi_context,
365 gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL),
370 if (GSS_ERROR(maj_stat)) {
371 return NT_STATUS_ACCESS_DENIED;
374 if (output_token.length < length) {
375 return NT_STATUS_INTERNAL_ERROR;
380 memcpy(data, ((uint8_t *)output_token.value) + sig_length, length);
381 *sig = data_blob_talloc(mem_ctx, (uint8_t *)output_token.value, sig_length);
383 DEBUG(0,("gensec_gssapi_seal_packet: siglen: %d inlen: %d, wrap_len: %d\n", sig->length, length, output_token.length - sig_length));
384 dump_data(0,sig->data, sig->length);
385 dump_data(0,data, length);
386 dump_data(0,((uint8_t *)output_token.value) + sig_length, output_token.length - sig_length);
388 gss_release_buffer(&min_stat, &output_token);
390 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
392 return NT_STATUS_ACCESS_DENIED;
397 static NTSTATUS gensec_gssapi_unseal_packet(struct gensec_security *gensec_security,
399 uint8_t *data, size_t length,
400 const uint8_t *whole_pdu, size_t pdu_length,
401 const DATA_BLOB *sig)
403 struct gensec_gssapi_state *gensec_gssapi_state = gensec_security->private_data;
404 OM_uint32 maj_stat, min_stat;
405 gss_buffer_desc input_token, output_token;
410 DEBUG(0,("gensec_gssapi_unseal_packet: siglen: %d\n", sig->length));
411 dump_data(0,sig->data, sig->length);
413 in = data_blob_talloc(mem_ctx, NULL, sig->length + length);
415 memcpy(in.data, sig->data, sig->length);
416 memcpy(in.data + sig->length, data, length);
418 input_token.length = in.length;
419 input_token.value = in.data;
421 maj_stat = gss_unwrap(&min_stat,
422 gensec_gssapi_state->gssapi_context,
427 if (GSS_ERROR(maj_stat)) {
428 return NT_STATUS_ACCESS_DENIED;
431 if (output_token.length != length) {
432 return NT_STATUS_INTERNAL_ERROR;
435 memcpy(data, output_token.value, length);
437 gss_release_buffer(&min_stat, &output_token);
439 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
441 return NT_STATUS_ACCESS_DENIED;
446 static NTSTATUS gensec_gssapi_sign_packet(struct gensec_security *gensec_security,
448 const uint8_t *data, size_t length,
449 const uint8_t *whole_pdu, size_t pdu_length,
452 struct gensec_gssapi_state *gensec_gssapi_state = gensec_security->private_data;
453 OM_uint32 maj_stat, min_stat;
454 gss_buffer_desc input_token, output_token;
456 ssize_t sig_length = 0;
458 input_token.length = length;
459 input_token.value = discard_const_p(uint8_t *, data);
461 maj_stat = gss_wrap(&min_stat,
462 gensec_gssapi_state->gssapi_context,
468 if (GSS_ERROR(maj_stat)) {
469 return NT_STATUS_ACCESS_DENIED;
472 if (output_token.length < length) {
473 return NT_STATUS_INTERNAL_ERROR;
478 /*memcpy(data, ((uint8_t *)output_token.value) + sig_length, length);*/
479 *sig = data_blob_talloc(mem_ctx, (uint8_t *)output_token.value, sig_length);
481 DEBUG(0,("gensec_gssapi_sign_packet: siglen: %d\n", sig->length));
482 dump_data(0,sig->data, sig->length);
484 gss_release_buffer(&min_stat, &output_token);
489 static NTSTATUS gensec_gssapi_check_packet(struct gensec_security *gensec_security,
491 const uint8_t *data, size_t length,
492 const uint8_t *whole_pdu, size_t pdu_length,
493 const DATA_BLOB *sig)
495 struct gensec_gssapi_state *gensec_gssapi_state = gensec_security->private_data;
496 OM_uint32 maj_stat, min_stat;
497 gss_buffer_desc input_token, output_token;
502 DEBUG(0,("gensec_gssapi_check_packet: siglen: %d\n", sig->length));
503 dump_data(0,sig->data, sig->length);
505 in = data_blob_talloc(mem_ctx, NULL, sig->length + length);
507 memcpy(in.data, sig->data, sig->length);
508 memcpy(in.data + sig->length, data, length);
510 input_token.length = in.length;
511 input_token.value = in.data;
513 maj_stat = gss_unwrap(&min_stat,
514 gensec_gssapi_state->gssapi_context,
519 if (GSS_ERROR(maj_stat)) {
520 return NT_STATUS_ACCESS_DENIED;
523 if (output_token.length != length) {
524 return NT_STATUS_INTERNAL_ERROR;
527 /*memcpy(data, output_token.value, length);*/
529 gss_release_buffer(&min_stat, &output_token);
534 static BOOL gensec_gssapi_have_feature(struct gensec_security *gensec_security,
537 struct gensec_gssapi_state *gensec_gssapi_state = gensec_security->private_data;
538 if (feature & GENSEC_FEATURE_SIGN) {
539 return gensec_gssapi_state->got_flags & GSS_C_INTEG_FLAG;
541 if (feature & GENSEC_FEATURE_SEAL) {
542 return gensec_gssapi_state->got_flags & GSS_C_CONF_FLAG;
544 if (feature & GENSEC_FEATURE_SESSION_KEY) {
545 #ifdef HAVE_GSSKRB5_GET_INITIATOR_SUBKEY
546 if ((gensec_gssapi_state->gss_oid->length == gensec_gss_krb5_mechanism_oid_desc.length)
547 && (memcmp(gensec_gssapi_state->gss_oid->elements, gensec_gss_krb5_mechanism_oid_desc.elements, gensec_gssapi_state->gss_oid->length) == 0)) {
555 static NTSTATUS gensec_gssapi_session_key(struct gensec_security *gensec_security,
556 DATA_BLOB *session_key)
558 struct gensec_gssapi_state *gensec_gssapi_state = gensec_security->private_data;
560 if (gensec_gssapi_state->session_key.data) {
561 *session_key = gensec_gssapi_state->session_key;
565 #ifdef HAVE_GSSKRB5_GET_INITIATOR_SUBKEY
566 if ((gensec_gssapi_state->gss_oid->length == gensec_gss_krb5_mechanism_oid_desc.length)
567 && (memcmp(gensec_gssapi_state->gss_oid->elements, gensec_gss_krb5_mechanism_oid_desc.elements, gensec_gssapi_state->gss_oid->length) == 0)) {
568 OM_uint32 maj_stat, min_stat;
569 gss_buffer_desc skey;
571 maj_stat = gsskrb5_get_initiator_subkey(&min_stat,
572 gensec_gssapi_state->gssapi_context,
576 DEBUG(10, ("Got KRB5 session key of length %d\n", skey.length));
577 gensec_gssapi_state->session_key = data_blob_talloc(gensec_gssapi_state,
578 skey.value, skey.length);
579 *session_key = gensec_gssapi_state->session_key;
580 dump_data_pw("KRB5 Session Key:\n", session_key->data, session_key->length);
582 gss_release_buffer(&min_stat, &skey);
585 return NT_STATUS_NO_USER_SESSION_KEY;
589 DEBUG(1, ("NO session key for this mech\n"));
590 return NT_STATUS_NO_USER_SESSION_KEY;
593 static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_security,
594 struct auth_session_info **_session_info)
597 struct gensec_gssapi_state *gensec_gssapi_state = gensec_security->private_data;
598 struct auth_serversupplied_info *server_info = NULL;
599 struct auth_session_info *session_info = NULL;
602 const char *account_name;
604 OM_uint32 maj_stat, min_stat;
605 gss_buffer_desc name_token;
607 maj_stat = gss_display_name (&min_stat,
608 gensec_gssapi_state->client_name,
612 return NT_STATUS_FOOBAR;
615 principal = talloc_strndup(gensec_gssapi_state, name_token.value, name_token.length);
617 gss_release_buffer(&min_stat, &name_token);
619 NT_STATUS_HAVE_NO_MEMORY(principal);
621 p = strchr(principal, '@');
629 account_name = principal;
631 /* IF we have the PAC - otherwise we need to get this
632 * data from elsewere - local ldb, or (TODO) lookup of some
635 * when heimdal can generate the PAC, we should fail if there's
640 DATA_BLOB user_sess_key = data_blob(NULL, 0);
641 DATA_BLOB lm_sess_key = data_blob(NULL, 0);
642 /* TODO: should we pass the krb5 session key in here? */
643 nt_status = sam_get_server_info(gensec_gssapi_state, account_name, realm,
644 user_sess_key, lm_sess_key,
646 talloc_free(principal);
647 NT_STATUS_NOT_OK_RETURN(nt_status);
650 /* references the server_info into the session_info */
651 nt_status = auth_generate_session_info(gensec_gssapi_state, server_info, &session_info);
652 talloc_free(server_info);
653 NT_STATUS_NOT_OK_RETURN(nt_status);
655 nt_status = gensec_gssapi_session_key(gensec_security, &session_info->session_key);
656 NT_STATUS_NOT_OK_RETURN(nt_status);
658 *_session_info = session_info;
663 /* As a server, this could in theory accept any GSSAPI mech */
664 static const struct gensec_security_ops gensec_gssapi_krb5_security_ops = {
665 .name = "gssapi_krb5",
666 .sasl_name = "GSSAPI",
667 .auth_type = DCERPC_AUTH_TYPE_KRB5,
668 .oid = GENSEC_OID_KERBEROS5,
669 .client_start = gensec_gssapi_client_start,
670 .server_start = gensec_gssapi_server_start,
671 .update = gensec_gssapi_update,
672 .session_key = gensec_gssapi_session_key,
673 .session_info = gensec_gssapi_session_info,
674 .sig_size = gensec_gssapi_sig_size,
675 .sign_packet = gensec_gssapi_sign_packet,
676 .check_packet = gensec_gssapi_check_packet,
677 .seal_packet = gensec_gssapi_seal_packet,
678 .unseal_packet = gensec_gssapi_unseal_packet,
679 .wrap = gensec_gssapi_wrap,
680 .unwrap = gensec_gssapi_unwrap,
681 .have_feature = gensec_gssapi_have_feature,
686 /* As a server, this could in theory accept any GSSAPI mech */
687 static const struct gensec_security_ops gensec_gssapi_ms_krb5_security_ops = {
688 .name = "gssapi_ms_krb5",
689 .oid = GENSEC_OID_KERBEROS5_OLD,
690 .client_start = gensec_gssapi_client_start,
691 .server_start = gensec_gssapi_server_start,
692 .update = gensec_gssapi_update,
693 .session_key = gensec_gssapi_session_key,
694 .session_info = gensec_gssapi_session_info,
695 .sig_size = gensec_gssapi_sig_size,
696 .sign_packet = gensec_gssapi_sign_packet,
697 .check_packet = gensec_gssapi_check_packet,
698 .seal_packet = gensec_gssapi_seal_packet,
699 .unseal_packet = gensec_gssapi_unseal_packet,
700 .wrap = gensec_gssapi_wrap,
701 .unwrap = gensec_gssapi_unwrap,
702 .have_feature = gensec_gssapi_have_feature,
707 static const struct gensec_security_ops gensec_gssapi_spnego_security_ops = {
708 .name = "gssapi_spnego",
709 .sasl_name = "GSS-SPNEGO",
710 .oid = GENSEC_OID_SPNEGO,
711 .client_start = gensec_gssapi_client_start,
712 .server_start = gensec_gssapi_server_start,
713 .update = gensec_gssapi_update,
714 .session_key = gensec_gssapi_session_key,
715 .sig_size = gensec_gssapi_sig_size,
716 .sign_packet = gensec_gssapi_sign_packet,
717 .check_packet = gensec_gssapi_check_packet,
718 .seal_packet = gensec_gssapi_seal_packet,
719 .unseal_packet = gensec_gssapi_unseal_packet,
720 .wrap = gensec_gssapi_wrap,
721 .unwrap = gensec_gssapi_unwrap,
722 .have_feature = gensec_gssapi_have_feature,
726 NTSTATUS gensec_gssapi_init(void)
730 ret = gensec_register(&gensec_gssapi_krb5_security_ops);
731 if (!NT_STATUS_IS_OK(ret)) {
732 DEBUG(0,("Failed to register '%s' gensec backend!\n",
733 gensec_gssapi_krb5_security_ops.name));
738 ret = gensec_register(&gensec_gssapi_ms_krb5_security_ops);
739 if (!NT_STATUS_IS_OK(ret)) {
740 DEBUG(0,("Failed to register '%s' gensec backend!\n",
741 gensec_gssapi_ms_krb5_security_ops.name));
745 ret = gensec_register(&gensec_gssapi_spnego_security_ops);
746 if (!NT_STATUS_IS_OK(ret)) {
747 DEBUG(0,("Failed to register '%s' gensec backend!\n",
748 gensec_gssapi_spnego_security_ops.name));