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 right hook */
100 return NT_STATUS_INVALID_PARAMETER;
103 if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
104 gensec_gssapi_state->want_flags |= GSS_C_INTEG_FLAG;
106 if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
107 gensec_gssapi_state->want_flags |= GSS_C_CONF_FLAG;
109 if (gensec_security->want_features & GENSEC_FEATURE_DCE_STYLE) {
110 #ifndef GSS_C_DCE_STYLE
111 /* GSSAPI won't give us the session keys, without the right hook */
112 return NT_STATUS_INVALID_PARAMETER;
114 gensec_gssapi_state->want_flags |= GSS_C_DCE_STYLE;
118 if ((strcmp(gensec_security->ops->oid, GENSEC_OID_KERBEROS5) == 0)
119 || (strcmp(gensec_security->ops->oid, GENSEC_OID_KERBEROS5_OLD) == 0)) {
120 gensec_gssapi_state->gss_oid = &gensec_gss_krb5_mechanism_oid_desc;
121 } else if (strcmp(gensec_security->ops->oid, GENSEC_OID_SPNEGO) == 0) {
122 gensec_gssapi_state->gss_oid = &gensec_gss_spnego_mechanism_oid_desc;
124 DEBUG(1, ("gensec_gssapi incorrectly configured - cannot determine gss OID from %s\n",
125 gensec_security->ops->oid));
126 return NT_STATUS_INVALID_PARAMETER;
132 static NTSTATUS gensec_gssapi_server_start(struct gensec_security *gensec_security)
135 struct gensec_gssapi_state *gensec_gssapi_state;
137 nt_status = gensec_gssapi_start(gensec_security);
138 if (!NT_STATUS_IS_OK(nt_status)) {
142 gensec_gssapi_state = gensec_security->private_data;
147 static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_security)
149 struct gensec_gssapi_state *gensec_gssapi_state;
151 gss_buffer_desc name_token;
152 OM_uint32 maj_stat, min_stat;
154 gss_OID_desc hostbased = {10,
155 (void *)discard_const_p(char, "\x2a\x86\x48\x86\xf7\x12"
156 "\x01\x02\x01\x04")};
158 nt_status = gensec_gssapi_start(gensec_security);
159 if (!NT_STATUS_IS_OK(nt_status)) {
163 gensec_gssapi_state = gensec_security->private_data;
165 name_token.value = talloc_asprintf(gensec_gssapi_state, "%s@%s", gensec_get_target_service(gensec_security),
166 gensec_get_target_hostname(gensec_security));
167 DEBUG(0, ("name: %s\n", (char *)name_token.value));
168 name_token.length = strlen(name_token.value);
170 maj_stat = gss_import_name (&min_stat,
173 &gensec_gssapi_state->server_name);
177 return NT_STATUS_UNSUCCESSFUL;
185 * Next state function for the GSSAPI GENSEC mechanism
187 * @param gensec_gssapi_state GSSAPI State
188 * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
189 * @param in The request, as a DATA_BLOB
190 * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
191 * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent,
192 * or NT_STATUS_OK if the user is authenticated.
195 static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security,
196 TALLOC_CTX *out_mem_ctx,
197 const DATA_BLOB in, DATA_BLOB *out)
199 struct gensec_gssapi_state *gensec_gssapi_state = gensec_security->private_data;
200 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
201 OM_uint32 maj_stat, min_stat;
203 gss_buffer_desc input_token, output_token;
205 input_token.length = in.length;
206 input_token.value = in.data;
208 switch (gensec_security->gensec_role) {
211 maj_stat = gss_init_sec_context(&min_stat,
213 &gensec_gssapi_state->gssapi_context,
214 gensec_gssapi_state->server_name,
215 discard_const_p(gss_OID_desc, gensec_gssapi_state->gss_oid),
216 gensec_gssapi_state->want_flags,
218 gensec_gssapi_state->input_chan_bindings,
222 &gensec_gssapi_state->got_flags, /* ret flags */
228 maj_stat = gss_accept_sec_context(&min_stat,
229 &gensec_gssapi_state->gssapi_context,
232 gensec_gssapi_state->input_chan_bindings,
233 &gensec_gssapi_state->client_name,
236 &gensec_gssapi_state->got_flags,
239 gensec_gssapi_state->gss_oid = gss_oid_p;
243 return NT_STATUS_INVALID_PARAMETER;
247 *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length);
248 gss_release_buffer(&min_stat2, &output_token);
250 if (maj_stat == GSS_S_COMPLETE) {
252 } else if (maj_stat == GSS_S_CONTINUE_NEEDED) {
253 return NT_STATUS_MORE_PROCESSING_REQUIRED;
255 gss_buffer_desc msg1, msg2;
256 OM_uint32 msg_ctx = 0;
260 gss_display_status(&min_stat2, maj_stat, GSS_C_GSS_CODE,
261 GSS_C_NULL_OID, &msg_ctx, &msg1);
262 gss_display_status(&min_stat2, min_stat, GSS_C_MECH_CODE,
263 GSS_C_NULL_OID, &msg_ctx, &msg2);
264 DEBUG(1, ("gensec_gssapi_update: %s : %s\n", (char *)msg1.value, (char *)msg2.value));
265 gss_release_buffer(&min_stat2, &msg1);
266 gss_release_buffer(&min_stat2, &msg2);
273 static NTSTATUS gensec_gssapi_wrap(struct gensec_security *gensec_security,
278 struct gensec_gssapi_state *gensec_gssapi_state = gensec_security->private_data;
279 OM_uint32 maj_stat, min_stat;
280 gss_buffer_desc input_token, output_token;
282 input_token.length = in->length;
283 input_token.value = in->data;
285 maj_stat = gss_wrap(&min_stat,
286 gensec_gssapi_state->gssapi_context,
287 gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL),
292 if (GSS_ERROR(maj_stat)) {
293 return NT_STATUS_ACCESS_DENIED;
295 *out = data_blob_talloc(mem_ctx, output_token.value, output_token.length);
297 gss_release_buffer(&min_stat, &output_token);
299 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
301 return NT_STATUS_ACCESS_DENIED;
306 static NTSTATUS gensec_gssapi_unwrap(struct gensec_security *gensec_security,
311 struct gensec_gssapi_state *gensec_gssapi_state = gensec_security->private_data;
312 OM_uint32 maj_stat, min_stat;
313 gss_buffer_desc input_token, output_token;
316 input_token.length = in->length;
317 input_token.value = in->data;
319 maj_stat = gss_unwrap(&min_stat,
320 gensec_gssapi_state->gssapi_context,
325 if (GSS_ERROR(maj_stat)) {
326 return NT_STATUS_ACCESS_DENIED;
328 *out = data_blob_talloc(mem_ctx, output_token.value, output_token.length);
330 gss_release_buffer(&min_stat, &output_token);
332 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
334 return NT_STATUS_ACCESS_DENIED;
339 static size_t gensec_gssapi_sig_size(struct gensec_security *gensec_security)
341 /* not const but work for DCERPC packets and arcfour */
345 static NTSTATUS gensec_gssapi_seal_packet(struct gensec_security *gensec_security,
347 uint8_t *data, size_t length,
348 const uint8_t *whole_pdu, size_t pdu_length,
351 struct gensec_gssapi_state *gensec_gssapi_state = gensec_security->private_data;
352 OM_uint32 maj_stat, min_stat;
353 gss_buffer_desc input_token, output_token;
355 ssize_t sig_length = 0;
357 input_token.length = length;
358 input_token.value = data;
360 maj_stat = gss_wrap(&min_stat,
361 gensec_gssapi_state->gssapi_context,
362 gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL),
367 if (GSS_ERROR(maj_stat)) {
368 return NT_STATUS_ACCESS_DENIED;
371 if (output_token.length < length) {
372 return NT_STATUS_INTERNAL_ERROR;
377 memcpy(data, ((uint8_t *)output_token.value) + sig_length, length);
378 *sig = data_blob_talloc(mem_ctx, (uint8_t *)output_token.value, sig_length);
380 DEBUG(0,("gensec_gssapi_seal_packet: siglen: %d inlen: %d, wrap_len: %d\n", sig->length, length, output_token.length - sig_length));
381 dump_data(0,sig->data, sig->length);
382 dump_data(0,data, length);
383 dump_data(0,((uint8_t *)output_token.value) + sig_length, output_token.length - sig_length);
385 gss_release_buffer(&min_stat, &output_token);
387 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
389 return NT_STATUS_ACCESS_DENIED;
394 static NTSTATUS gensec_gssapi_unseal_packet(struct gensec_security *gensec_security,
396 uint8_t *data, size_t length,
397 const uint8_t *whole_pdu, size_t pdu_length,
398 const DATA_BLOB *sig)
400 struct gensec_gssapi_state *gensec_gssapi_state = gensec_security->private_data;
401 OM_uint32 maj_stat, min_stat;
402 gss_buffer_desc input_token, output_token;
407 DEBUG(0,("gensec_gssapi_unseal_packet: siglen: %d\n", sig->length));
408 dump_data(0,sig->data, sig->length);
410 in = data_blob_talloc(mem_ctx, NULL, sig->length + length);
412 memcpy(in.data, sig->data, sig->length);
413 memcpy(in.data + sig->length, data, length);
415 input_token.length = in.length;
416 input_token.value = in.data;
418 maj_stat = gss_unwrap(&min_stat,
419 gensec_gssapi_state->gssapi_context,
424 if (GSS_ERROR(maj_stat)) {
425 return NT_STATUS_ACCESS_DENIED;
428 if (output_token.length != length) {
429 return NT_STATUS_INTERNAL_ERROR;
432 memcpy(data, output_token.value, length);
434 gss_release_buffer(&min_stat, &output_token);
436 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)
438 return NT_STATUS_ACCESS_DENIED;
443 static NTSTATUS gensec_gssapi_sign_packet(struct gensec_security *gensec_security,
445 const uint8_t *data, size_t length,
446 const uint8_t *whole_pdu, size_t pdu_length,
449 struct gensec_gssapi_state *gensec_gssapi_state = gensec_security->private_data;
450 OM_uint32 maj_stat, min_stat;
451 gss_buffer_desc input_token, output_token;
453 ssize_t sig_length = 0;
455 input_token.length = length;
456 input_token.value = discard_const_p(uint8_t *, data);
458 maj_stat = gss_wrap(&min_stat,
459 gensec_gssapi_state->gssapi_context,
465 if (GSS_ERROR(maj_stat)) {
466 return NT_STATUS_ACCESS_DENIED;
469 if (output_token.length < length) {
470 return NT_STATUS_INTERNAL_ERROR;
475 /*memcpy(data, ((uint8_t *)output_token.value) + sig_length, length);*/
476 *sig = data_blob_talloc(mem_ctx, (uint8_t *)output_token.value, sig_length);
478 DEBUG(0,("gensec_gssapi_sign_packet: siglen: %d\n", sig->length));
479 dump_data(0,sig->data, sig->length);
481 gss_release_buffer(&min_stat, &output_token);
486 static NTSTATUS gensec_gssapi_check_packet(struct gensec_security *gensec_security,
488 const uint8_t *data, size_t length,
489 const uint8_t *whole_pdu, size_t pdu_length,
490 const DATA_BLOB *sig)
492 struct gensec_gssapi_state *gensec_gssapi_state = gensec_security->private_data;
493 OM_uint32 maj_stat, min_stat;
494 gss_buffer_desc input_token, output_token;
499 DEBUG(0,("gensec_gssapi_check_packet: siglen: %d\n", sig->length));
500 dump_data(0,sig->data, sig->length);
502 in = data_blob_talloc(mem_ctx, NULL, sig->length + length);
504 memcpy(in.data, sig->data, sig->length);
505 memcpy(in.data + sig->length, data, length);
507 input_token.length = in.length;
508 input_token.value = in.data;
510 maj_stat = gss_unwrap(&min_stat,
511 gensec_gssapi_state->gssapi_context,
516 if (GSS_ERROR(maj_stat)) {
517 return NT_STATUS_ACCESS_DENIED;
520 if (output_token.length != length) {
521 return NT_STATUS_INTERNAL_ERROR;
524 /*memcpy(data, output_token.value, length);*/
526 gss_release_buffer(&min_stat, &output_token);
531 static BOOL gensec_gssapi_have_feature(struct gensec_security *gensec_security,
534 struct gensec_gssapi_state *gensec_gssapi_state = gensec_security->private_data;
535 if (feature & GENSEC_FEATURE_SIGN) {
536 return gensec_gssapi_state->got_flags & GSS_C_INTEG_FLAG;
538 if (feature & GENSEC_FEATURE_SEAL) {
539 return gensec_gssapi_state->got_flags & GSS_C_CONF_FLAG;
541 if (feature & GENSEC_FEATURE_SESSION_KEY) {
542 #ifdef HAVE_GSSKRB5_GET_INITIATOR_SUBKEY
543 if ((gensec_gssapi_state->gss_oid->length == gensec_gss_krb5_mechanism_oid_desc.length)
544 && (memcmp(gensec_gssapi_state->gss_oid->elements, gensec_gss_krb5_mechanism_oid_desc.elements, gensec_gssapi_state->gss_oid->length) == 0)) {
552 static NTSTATUS gensec_gssapi_session_key(struct gensec_security *gensec_security,
553 DATA_BLOB *session_key)
555 struct gensec_gssapi_state *gensec_gssapi_state = gensec_security->private_data;
557 if (gensec_gssapi_state->session_key.data) {
558 *session_key = gensec_gssapi_state->session_key;
562 #ifdef HAVE_GSSKRB5_GET_INITIATOR_SUBKEY
563 if ((gensec_gssapi_state->gss_oid->length == gensec_gss_krb5_mechanism_oid_desc.length)
564 && (memcmp(gensec_gssapi_state->gss_oid->elements, gensec_gss_krb5_mechanism_oid_desc.elements, gensec_gssapi_state->gss_oid->length) == 0)) {
565 OM_uint32 maj_stat, min_stat;
566 gss_buffer_desc skey;
568 maj_stat = gsskrb5_get_initiator_subkey(&min_stat,
569 gensec_gssapi_state->gssapi_context,
573 DEBUG(10, ("Got KRB5 session key of length %d\n", skey.length));
574 gensec_gssapi_state->session_key = data_blob_talloc(gensec_gssapi_state,
575 skey.value, skey.length);
576 *session_key = gensec_gssapi_state->session_key;
577 dump_data_pw("KRB5 Session Key:\n", session_key->data, session_key->length);
579 gss_release_buffer(&min_stat, &skey);
582 return NT_STATUS_NO_USER_SESSION_KEY;
586 DEBUG(1, ("NO session key for this mech\n"));
587 return NT_STATUS_NO_USER_SESSION_KEY;
590 static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_security,
591 struct auth_session_info **_session_info)
594 struct gensec_gssapi_state *gensec_gssapi_state = gensec_security->private_data;
595 struct auth_serversupplied_info *server_info = NULL;
596 struct auth_session_info *session_info = NULL;
599 const char *account_name;
601 OM_uint32 maj_stat, min_stat;
602 gss_buffer_desc name_token;
604 maj_stat = gss_display_name (&min_stat,
605 gensec_gssapi_state->client_name,
609 return NT_STATUS_FOOBAR;
612 principal = talloc_strndup(gensec_gssapi_state, name_token.value, name_token.length);
614 gss_release_buffer(&min_stat, &name_token);
616 NT_STATUS_HAVE_NO_MEMORY(principal);
618 p = strchr(principal, '@');
626 account_name = principal;
628 /* IF we have the PAC - otherwise we need to get this
629 * data from elsewere - local ldb, or (TODO) lookup of some
632 * when heimdal can generate the PAC, we should fail if there's
637 DATA_BLOB user_sess_key = data_blob(NULL, 0);
638 DATA_BLOB lm_sess_key = data_blob(NULL, 0);
639 /* TODO: should we pass the krb5 session key in here? */
640 nt_status = sam_get_server_info(gensec_gssapi_state, account_name, realm,
641 user_sess_key, lm_sess_key,
643 talloc_free(principal);
644 NT_STATUS_NOT_OK_RETURN(nt_status);
647 /* references the server_info into the session_info */
648 nt_status = auth_generate_session_info(gensec_gssapi_state, server_info, &session_info);
649 talloc_free(server_info);
650 NT_STATUS_NOT_OK_RETURN(nt_status);
652 nt_status = gensec_gssapi_session_key(gensec_security, &session_info->session_key);
653 NT_STATUS_NOT_OK_RETURN(nt_status);
655 *_session_info = session_info;
660 /* As a server, this could in theory accept any GSSAPI mech */
661 static const struct gensec_security_ops gensec_gssapi_krb5_security_ops = {
662 .name = "gssapi_krb5",
663 .sasl_name = "GSSAPI",
664 .auth_type = DCERPC_AUTH_TYPE_KRB5,
665 .oid = GENSEC_OID_KERBEROS5,
666 .client_start = gensec_gssapi_client_start,
667 .server_start = gensec_gssapi_server_start,
668 .update = gensec_gssapi_update,
669 .session_key = gensec_gssapi_session_key,
670 .session_info = gensec_gssapi_session_info,
671 .sig_size = gensec_gssapi_sig_size,
672 .sign_packet = gensec_gssapi_sign_packet,
673 .check_packet = gensec_gssapi_check_packet,
674 .seal_packet = gensec_gssapi_seal_packet,
675 .unseal_packet = gensec_gssapi_unseal_packet,
676 .wrap = gensec_gssapi_wrap,
677 .unwrap = gensec_gssapi_unwrap,
678 .have_feature = gensec_gssapi_have_feature,
683 /* As a server, this could in theory accept any GSSAPI mech */
684 static const struct gensec_security_ops gensec_gssapi_ms_krb5_security_ops = {
685 .name = "gssapi_ms_krb5",
686 .oid = GENSEC_OID_KERBEROS5_OLD,
687 .client_start = gensec_gssapi_client_start,
688 .server_start = gensec_gssapi_server_start,
689 .update = gensec_gssapi_update,
690 .session_key = gensec_gssapi_session_key,
691 .session_info = gensec_gssapi_session_info,
692 .sig_size = gensec_gssapi_sig_size,
693 .sign_packet = gensec_gssapi_sign_packet,
694 .check_packet = gensec_gssapi_check_packet,
695 .seal_packet = gensec_gssapi_seal_packet,
696 .unseal_packet = gensec_gssapi_unseal_packet,
697 .wrap = gensec_gssapi_wrap,
698 .unwrap = gensec_gssapi_unwrap,
699 .have_feature = gensec_gssapi_have_feature,
704 static const struct gensec_security_ops gensec_gssapi_spnego_security_ops = {
705 .name = "gssapi_spnego",
706 .sasl_name = "GSS-SPNEGO",
707 .oid = GENSEC_OID_SPNEGO,
708 .client_start = gensec_gssapi_client_start,
709 .server_start = gensec_gssapi_server_start,
710 .update = gensec_gssapi_update,
711 .session_key = gensec_gssapi_session_key,
712 .sig_size = gensec_gssapi_sig_size,
713 .sign_packet = gensec_gssapi_sign_packet,
714 .check_packet = gensec_gssapi_check_packet,
715 .seal_packet = gensec_gssapi_seal_packet,
716 .unseal_packet = gensec_gssapi_unseal_packet,
717 .wrap = gensec_gssapi_wrap,
718 .unwrap = gensec_gssapi_unwrap,
719 .have_feature = gensec_gssapi_have_feature,
723 NTSTATUS gensec_gssapi_init(void)
727 ret = gensec_register(&gensec_gssapi_krb5_security_ops);
728 if (!NT_STATUS_IS_OK(ret)) {
729 DEBUG(0,("Failed to register '%s' gensec backend!\n",
730 gensec_gssapi_krb5_security_ops.name));
735 ret = gensec_register(&gensec_gssapi_ms_krb5_security_ops);
736 if (!NT_STATUS_IS_OK(ret)) {
737 DEBUG(0,("Failed to register '%s' gensec backend!\n",
738 gensec_gssapi_ms_krb5_security_ops.name));
742 ret = gensec_register(&gensec_gssapi_spnego_security_ops);
743 if (!NT_STATUS_IS_OK(ret)) {
744 DEBUG(0,("Failed to register '%s' gensec backend!\n",
745 gensec_gssapi_spnego_security_ops.name));