2 Unix SMB/CIFS implementation.
4 Kerberos backend for GENSEC
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004
7 Copyright (C) Andrew Tridgell 2001
8 Copyright (C) Luke Howard 2002-2003
9 Copyright (C) Stefan Metzmacher 2004-2005
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 #include "system/kerberos.h"
29 #include "auth/kerberos/kerberos.h"
30 #include "librpc/gen_ndr/ndr_krb5pac.h"
31 #include "auth/auth.h"
33 enum GENSEC_KRB5_STATE {
34 GENSEC_KRB5_SERVER_START,
35 GENSEC_KRB5_CLIENT_START,
36 GENSEC_KRB5_CLIENT_MUTUAL_AUTH,
40 struct gensec_krb5_state {
41 DATA_BLOB session_key;
43 enum GENSEC_KRB5_STATE state_position;
44 struct smb_krb5_context *smb_krb5_context;
45 krb5_auth_context auth_context;
47 krb5_keyblock *keyblock;
52 static int gensec_krb5_destroy(void *ptr)
54 struct gensec_krb5_state *gensec_krb5_state = ptr;
56 if (!gensec_krb5_state->smb_krb5_context) {
57 /* We can't clean anything else up unless we started up this far */
60 if (gensec_krb5_state->enc_ticket.length) {
61 kerberos_free_data_contents(gensec_krb5_state->smb_krb5_context->krb5_context,
62 &gensec_krb5_state->enc_ticket);
65 if (gensec_krb5_state->ticket) {
66 krb5_free_ticket(gensec_krb5_state->smb_krb5_context->krb5_context,
67 gensec_krb5_state->ticket);
70 /* ccache freed in a child destructor */
72 krb5_free_keyblock(gensec_krb5_state->smb_krb5_context->krb5_context,
73 gensec_krb5_state->keyblock);
75 if (gensec_krb5_state->auth_context) {
76 krb5_auth_con_free(gensec_krb5_state->smb_krb5_context->krb5_context,
77 gensec_krb5_state->auth_context);
83 static NTSTATUS gensec_krb5_start(struct gensec_security *gensec_security)
86 struct gensec_krb5_state *gensec_krb5_state;
87 struct cli_credentials *creds;
89 creds = gensec_get_credentials(gensec_security);
91 return NT_STATUS_INVALID_PARAMETER;
94 gensec_krb5_state = talloc(gensec_security, struct gensec_krb5_state);
95 if (!gensec_krb5_state) {
96 return NT_STATUS_NO_MEMORY;
99 gensec_security->private_data = gensec_krb5_state;
100 gensec_krb5_state->smb_krb5_context = NULL;
101 gensec_krb5_state->auth_context = NULL;
102 gensec_krb5_state->ticket = NULL;
103 ZERO_STRUCT(gensec_krb5_state->enc_ticket);
104 gensec_krb5_state->keyblock = NULL;
105 gensec_krb5_state->session_key = data_blob(NULL, 0);
106 gensec_krb5_state->pac = data_blob(NULL, 0);
107 gensec_krb5_state->gssapi = False;
109 talloc_set_destructor(gensec_krb5_state, gensec_krb5_destroy);
111 if (cli_credentials_get_krb5_context(creds, &gensec_krb5_state->smb_krb5_context)) {
112 talloc_free(gensec_krb5_state);
113 return NT_STATUS_INTERNAL_ERROR;
116 ret = krb5_auth_con_init(gensec_krb5_state->smb_krb5_context->krb5_context, &gensec_krb5_state->auth_context);
118 DEBUG(1,("gensec_krb5_start: krb5_auth_con_init failed (%s)\n",
119 smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context,
120 ret, gensec_krb5_state)));
121 talloc_free(gensec_krb5_state);
122 return NT_STATUS_INTERNAL_ERROR;
125 ret = krb5_auth_con_setflags(gensec_krb5_state->smb_krb5_context->krb5_context,
126 gensec_krb5_state->auth_context,
127 KRB5_AUTH_CONTEXT_DO_SEQUENCE);
129 DEBUG(1,("gensec_krb5_start: krb5_auth_con_setflags failed (%s)\n",
130 smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context,
131 ret, gensec_krb5_state)));
132 talloc_free(gensec_krb5_state);
133 return NT_STATUS_INTERNAL_ERROR;
139 static NTSTATUS gensec_krb5_server_start(struct gensec_security *gensec_security)
142 struct gensec_krb5_state *gensec_krb5_state;
144 nt_status = gensec_krb5_start(gensec_security);
145 if (!NT_STATUS_IS_OK(nt_status)) {
149 gensec_krb5_state = gensec_security->private_data;
150 gensec_krb5_state->state_position = GENSEC_KRB5_SERVER_START;
155 static NTSTATUS gensec_fake_gssapi_krb5_server_start(struct gensec_security *gensec_security)
157 NTSTATUS nt_status = gensec_krb5_server_start(gensec_security);
159 if (NT_STATUS_IS_OK(nt_status)) {
160 struct gensec_krb5_state *gensec_krb5_state;
161 gensec_krb5_state = gensec_security->private_data;
162 gensec_krb5_state->gssapi = True;
167 static NTSTATUS gensec_krb5_client_start(struct gensec_security *gensec_security)
169 struct gensec_krb5_state *gensec_krb5_state;
172 struct ccache_container *ccache_container;
173 const char *hostname;
174 krb5_flags ap_req_options = AP_OPTS_USE_SUBKEY | AP_OPTS_MUTUAL_REQUIRED;
176 const char *principal;
179 hostname = gensec_get_target_hostname(gensec_security);
181 DEBUG(1, ("Could not determine hostname for target computer, cannot use kerberos\n"));
182 return NT_STATUS_INVALID_PARAMETER;
184 if (is_ipaddress(hostname)) {
185 DEBUG(2, ("Cannot do krb5 to an IP address"));
186 return NT_STATUS_INVALID_PARAMETER;
188 if (strequal(hostname, "localhost")) {
189 DEBUG(2, ("krb5 to 'localhost' does not make sense"));
190 return NT_STATUS_INVALID_PARAMETER;
193 nt_status = gensec_krb5_start(gensec_security);
194 if (!NT_STATUS_IS_OK(nt_status)) {
198 gensec_krb5_state = gensec_security->private_data;
199 gensec_krb5_state->state_position = GENSEC_KRB5_CLIENT_START;
201 ret = cli_credentials_get_ccache(gensec_get_credentials(gensec_security), &ccache_container);
203 DEBUG(1,("gensec_krb5_start: cli_credentials_get_ccache failed: %s\n",
204 error_message(ret)));
205 return NT_STATUS_UNSUCCESSFUL;
210 principal = gensec_get_target_principal(gensec_security);
211 if (principal && lp_client_use_spnego_principal()) {
212 krb5_principal target_principal;
213 ret = krb5_parse_name(gensec_krb5_state->smb_krb5_context->krb5_context, principal,
216 ret = krb5_mk_req_exact(gensec_krb5_state->smb_krb5_context->krb5_context,
217 &gensec_krb5_state->auth_context,
220 &in_data, ccache_container->ccache,
221 &gensec_krb5_state->enc_ticket);
222 krb5_free_principal(gensec_krb5_state->smb_krb5_context->krb5_context,
226 ret = krb5_mk_req(gensec_krb5_state->smb_krb5_context->krb5_context,
227 &gensec_krb5_state->auth_context,
229 gensec_get_target_service(gensec_security),
231 &in_data, ccache_container->ccache,
232 &gensec_krb5_state->enc_ticket);
237 case KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN:
238 DEBUG(3, ("Server [%s] is not registered with our KDC: %s\n",
239 hostname, smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state)));
240 return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */
241 case KRB5_KDC_UNREACH:
242 DEBUG(3, ("Cannot reach a KDC we require to contact host [%s]: %s\n",
243 hostname, smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state)));
244 return NT_STATUS_INVALID_PARAMETER; /* Make SPNEGO ignore us, we can't go any further here */
245 case KRB5KDC_ERR_PREAUTH_FAILED:
246 case KRB5KRB_AP_ERR_TKT_EXPIRED:
248 /* Too much clock skew - we will need to kinit to re-skew the clock */
249 case KRB5KRB_AP_ERR_SKEW:
250 case KRB5_KDCREP_SKEW:
252 DEBUG(3, ("kerberos (mk_req) failed: %s\n",
253 smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state)));
254 /* fall down to remaining code */
258 /* just don't print a message for these really ordinary messages */
259 case KRB5_FCC_NOFILE:
260 case KRB5_CC_NOTFOUND:
263 return NT_STATUS_UNSUCCESSFUL;
267 DEBUG(0, ("kerberos: %s\n",
268 smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, gensec_krb5_state)));
269 return NT_STATUS_UNSUCCESSFUL;
273 static NTSTATUS gensec_fake_gssapi_krb5_client_start(struct gensec_security *gensec_security)
275 NTSTATUS nt_status = gensec_krb5_client_start(gensec_security);
277 if (NT_STATUS_IS_OK(nt_status)) {
278 struct gensec_krb5_state *gensec_krb5_state;
279 gensec_krb5_state = gensec_security->private_data;
280 gensec_krb5_state->gssapi = True;
286 * Check if the packet is one for this mechansim
288 * @param gensec_security GENSEC state
289 * @param in The request, as a DATA_BLOB
290 * @return Error, INVALID_PARAMETER if it's not a packet for us
291 * or NT_STATUS_OK if the packet is ok.
294 static NTSTATUS gensec_fake_gssapi_krb5_magic(struct gensec_security *gensec_security,
297 if (gensec_gssapi_check_oid(in, GENSEC_OID_KERBEROS5)) {
300 return NT_STATUS_INVALID_PARAMETER;
306 * Next state function for the Krb5 GENSEC mechanism
308 * @param gensec_krb5_state KRB5 State
309 * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
310 * @param in The request, as a DATA_BLOB
311 * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
312 * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent,
313 * or NT_STATUS_OK if the user is authenticated.
316 static NTSTATUS gensec_krb5_update(struct gensec_security *gensec_security,
317 TALLOC_CTX *out_mem_ctx,
318 const DATA_BLOB in, DATA_BLOB *out)
320 struct gensec_krb5_state *gensec_krb5_state = gensec_security->private_data;
321 krb5_error_code ret = 0;
324 switch (gensec_krb5_state->state_position) {
325 case GENSEC_KRB5_CLIENT_START:
327 DATA_BLOB unwrapped_out;
329 if (gensec_krb5_state->gssapi) {
330 unwrapped_out = data_blob_talloc(out_mem_ctx, gensec_krb5_state->enc_ticket.data, gensec_krb5_state->enc_ticket.length);
332 /* wrap that up in a nice GSS-API wrapping */
333 *out = gensec_gssapi_gen_krb5_wrap(out_mem_ctx, &unwrapped_out, TOK_ID_KRB_AP_REQ);
335 *out = data_blob_talloc(out_mem_ctx, gensec_krb5_state->enc_ticket.data, gensec_krb5_state->enc_ticket.length);
337 gensec_krb5_state->state_position = GENSEC_KRB5_CLIENT_MUTUAL_AUTH;
338 nt_status = NT_STATUS_MORE_PROCESSING_REQUIRED;
342 case GENSEC_KRB5_CLIENT_MUTUAL_AUTH:
344 DATA_BLOB unwrapped_in;
346 krb5_ap_rep_enc_part *repl = NULL;
349 if (gensec_krb5_state->gssapi) {
350 if (!gensec_gssapi_parse_krb5_wrap(out_mem_ctx, &in, &unwrapped_in, tok_id)) {
351 DEBUG(1,("gensec_gssapi_parse_krb5_wrap(mutual authentication) failed to parse\n"));
352 dump_data_pw("Mutual authentication message:\n", in.data, in.length);
353 return NT_STATUS_INVALID_PARAMETER;
358 /* TODO: check the tok_id */
360 inbuf.data = unwrapped_in.data;
361 inbuf.length = unwrapped_in.length;
362 ret = krb5_rd_rep(gensec_krb5_state->smb_krb5_context->krb5_context,
363 gensec_krb5_state->auth_context,
366 DEBUG(1,("krb5_rd_rep (mutual authentication) failed (%s)\n",
367 smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context, ret, out_mem_ctx)));
368 dump_data_pw("Mutual authentication message:\n", inbuf.data, inbuf.length);
369 nt_status = NT_STATUS_ACCESS_DENIED;
371 *out = data_blob(NULL, 0);
372 nt_status = NT_STATUS_OK;
373 gensec_krb5_state->state_position = GENSEC_KRB5_DONE;
376 krb5_free_ap_rep_enc_part(gensec_krb5_state->smb_krb5_context->krb5_context, repl);
381 case GENSEC_KRB5_SERVER_START:
383 DATA_BLOB unwrapped_in;
384 DATA_BLOB unwrapped_out = data_blob(NULL, 0);
388 return NT_STATUS_INVALID_PARAMETER;
391 /* Parse the GSSAPI wrapping, if it's there... (win2k3 allows it to be omited) */
392 if (gensec_krb5_state->gssapi
393 && gensec_gssapi_parse_krb5_wrap(out_mem_ctx, &in, &unwrapped_in, tok_id)) {
394 nt_status = ads_verify_ticket(out_mem_ctx,
395 gensec_krb5_state->smb_krb5_context,
396 &gensec_krb5_state->auth_context,
397 gensec_get_credentials(gensec_security),
398 gensec_get_target_service(gensec_security), &unwrapped_in,
399 &gensec_krb5_state->ticket, &unwrapped_out,
400 &gensec_krb5_state->keyblock);
402 /* TODO: check the tok_id */
403 nt_status = ads_verify_ticket(out_mem_ctx,
404 gensec_krb5_state->smb_krb5_context,
405 &gensec_krb5_state->auth_context,
406 gensec_get_credentials(gensec_security),
407 gensec_get_target_service(gensec_security),
409 &gensec_krb5_state->ticket, &unwrapped_out,
410 &gensec_krb5_state->keyblock);
413 if (!NT_STATUS_IS_OK(nt_status)) {
417 if (NT_STATUS_IS_OK(nt_status)) {
418 gensec_krb5_state->state_position = GENSEC_KRB5_DONE;
419 /* wrap that up in a nice GSS-API wrapping */
420 if (gensec_krb5_state->gssapi) {
421 *out = gensec_gssapi_gen_krb5_wrap(out_mem_ctx, &unwrapped_out, TOK_ID_KRB_AP_REP);
423 *out = unwrapped_out;
428 case GENSEC_KRB5_DONE:
432 return NT_STATUS_INVALID_PARAMETER;
435 static NTSTATUS gensec_krb5_session_key(struct gensec_security *gensec_security,
436 DATA_BLOB *session_key)
438 struct gensec_krb5_state *gensec_krb5_state = gensec_security->private_data;
439 krb5_context context = gensec_krb5_state->smb_krb5_context->krb5_context;
440 krb5_auth_context auth_context = gensec_krb5_state->auth_context;
442 krb5_error_code err = -1;
444 if (gensec_krb5_state->session_key.data) {
445 *session_key = gensec_krb5_state->session_key;
449 switch (gensec_security->gensec_role) {
451 err = krb5_auth_con_getlocalsubkey(context, auth_context, &skey);
454 err = krb5_auth_con_getremotesubkey(context, auth_context, &skey);
457 if (err == 0 && skey != NULL) {
458 DEBUG(10, ("Got KRB5 session key of length %d\n",
459 (int)KRB5_KEY_LENGTH(skey)));
460 gensec_krb5_state->session_key = data_blob_talloc(gensec_krb5_state,
461 KRB5_KEY_DATA(skey), KRB5_KEY_LENGTH(skey));
462 *session_key = gensec_krb5_state->session_key;
463 dump_data_pw("KRB5 Session Key:\n", session_key->data, session_key->length);
465 krb5_free_keyblock(context, skey);
468 DEBUG(10, ("KRB5 error getting session key %d\n", err));
469 return NT_STATUS_NO_USER_SESSION_KEY;
473 static NTSTATUS gensec_krb5_session_info(struct gensec_security *gensec_security,
474 struct auth_session_info **_session_info)
476 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
477 struct gensec_krb5_state *gensec_krb5_state = gensec_security->private_data;
478 krb5_context context = gensec_krb5_state->smb_krb5_context->krb5_context;
479 struct auth_serversupplied_info *server_info = NULL;
480 struct auth_session_info *session_info = NULL;
481 struct PAC_LOGON_INFO *logon_info;
483 krb5_principal client_principal;
490 TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
492 return NT_STATUS_NO_MEMORY;
495 ret = krb5_ticket_get_authorization_data_type(context, gensec_krb5_state->ticket,
496 KRB5_AUTHDATA_WIN2K_PAC,
500 DEBUG(5, ("krb5_ticket_get_authorization_data_type failed to find PAC: %s\n",
501 smb_get_krb5_error_message(context,
504 pac = data_blob_talloc(mem_ctx, pac_data.data, pac_data.length);
506 return NT_STATUS_NO_MEMORY;
509 ret = krb5_ticket_get_client(context, gensec_krb5_state->ticket, &client_principal);
511 DEBUG(5, ("krb5_ticket_get_client failed to get cleint principal: %s\n",
512 smb_get_krb5_error_message(context,
514 return NT_STATUS_NO_MEMORY;
517 /* decode and verify the pac */
518 nt_status = kerberos_pac_logon_info(gensec_krb5_state, &logon_info, pac,
519 gensec_krb5_state->smb_krb5_context->krb5_context,
520 NULL, gensec_krb5_state->keyblock,
522 gensec_krb5_state->ticket->ticket.authtime, NULL);
523 krb5_free_principal(context, client_principal);
525 if (NT_STATUS_IS_OK(nt_status)) {
526 union netr_Validation validation;
527 validation.sam3 = &logon_info->info3;
528 nt_status = make_server_info_netlogon_validation(gensec_krb5_state,
533 talloc_free(mem_ctx);
538 /* IF we have the PAC - otherwise we need to get this
539 * data from elsewere - local ldb, or (TODO) lookup of some
542 if (!NT_STATUS_IS_OK(nt_status)) {
543 /* NO pac, or can't parse or verify it */
544 char *principal_string;
545 ret = krb5_ticket_get_client(context, gensec_krb5_state->ticket, &client_principal);
547 DEBUG(5, ("krb5_ticket_get_client failed to get cleint principal: %s\n",
548 smb_get_krb5_error_message(context,
550 return NT_STATUS_NO_MEMORY;
553 ret = krb5_unparse_name(gensec_krb5_state->smb_krb5_context->krb5_context,
554 client_principal, &principal_string);
555 krb5_free_principal(context, client_principal);
557 return NT_STATUS_NO_MEMORY;
560 nt_status = sam_get_server_info_principal(mem_ctx, principal_string,
562 free(principal_string);
564 if (!NT_STATUS_IS_OK(nt_status)) {
565 talloc_free(mem_ctx);
570 /* references the server_info into the session_info */
571 nt_status = auth_generate_session_info(gensec_krb5_state, server_info, &session_info);
572 talloc_free(mem_ctx);
574 NT_STATUS_NOT_OK_RETURN(nt_status);
576 nt_status = gensec_krb5_session_key(gensec_security, &session_info->session_key);
577 NT_STATUS_NOT_OK_RETURN(nt_status);
579 *_session_info = session_info;
584 static NTSTATUS gensec_krb5_wrap(struct gensec_security *gensec_security,
589 struct gensec_krb5_state *gensec_krb5_state = gensec_security->private_data;
590 krb5_context context = gensec_krb5_state->smb_krb5_context->krb5_context;
591 krb5_auth_context auth_context = gensec_krb5_state->auth_context;
593 krb5_data input, output;
594 input.length = in->length;
595 input.data = in->data;
597 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
598 ret = krb5_mk_priv(context, auth_context, &input, &output, NULL);
600 DEBUG(1, ("krb5_mk_priv failed: %s\n",
601 smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context,
603 return NT_STATUS_ACCESS_DENIED;
605 *out = data_blob_talloc(mem_ctx, output.data, output.length);
607 krb5_data_free(&output);
609 return NT_STATUS_ACCESS_DENIED;
614 static NTSTATUS gensec_krb5_unwrap(struct gensec_security *gensec_security,
619 struct gensec_krb5_state *gensec_krb5_state = gensec_security->private_data;
620 krb5_context context = gensec_krb5_state->smb_krb5_context->krb5_context;
621 krb5_auth_context auth_context = gensec_krb5_state->auth_context;
623 krb5_data input, output;
624 krb5_replay_data replay;
625 input.length = in->length;
626 input.data = in->data;
628 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
629 ret = krb5_rd_priv(context, auth_context, &input, &output, &replay);
631 DEBUG(1, ("krb5_rd_priv failed: %s\n",
632 smb_get_krb5_error_message(gensec_krb5_state->smb_krb5_context->krb5_context,
634 return NT_STATUS_ACCESS_DENIED;
636 *out = data_blob_talloc(mem_ctx, output.data, output.length);
638 krb5_data_free(&output);
640 return NT_STATUS_ACCESS_DENIED;
645 static BOOL gensec_krb5_have_feature(struct gensec_security *gensec_security,
648 struct gensec_krb5_state *gensec_krb5_state = gensec_security->private_data;
649 if (feature & GENSEC_FEATURE_SESSION_KEY) {
652 if (!gensec_krb5_state->gssapi &&
653 (feature & GENSEC_FEATURE_SEAL)) {
660 static const char *gensec_krb5_oids[] = {
661 GENSEC_OID_KERBEROS5,
662 GENSEC_OID_KERBEROS5_OLD,
666 static const struct gensec_security_ops gensec_fake_gssapi_krb5_security_ops = {
667 .name = "fake_gssapi_krb5",
668 .sasl_name = "GSSAPI",
669 .auth_type = DCERPC_AUTH_TYPE_KRB5,
670 .oid = gensec_krb5_oids,
671 .client_start = gensec_fake_gssapi_krb5_client_start,
672 .server_start = gensec_fake_gssapi_krb5_server_start,
673 .update = gensec_krb5_update,
674 .magic = gensec_fake_gssapi_krb5_magic,
675 .session_key = gensec_krb5_session_key,
676 .session_info = gensec_krb5_session_info,
677 .have_feature = gensec_krb5_have_feature,
681 static const struct gensec_security_ops gensec_krb5_security_ops = {
683 .client_start = gensec_krb5_client_start,
684 .server_start = gensec_krb5_server_start,
685 .update = gensec_krb5_update,
686 .session_key = gensec_krb5_session_key,
687 .session_info = gensec_krb5_session_info,
688 .have_feature = gensec_krb5_have_feature,
689 .wrap = gensec_krb5_wrap,
690 .unwrap = gensec_krb5_unwrap,
694 NTSTATUS gensec_krb5_init(void)
698 ret = gensec_register(&gensec_krb5_security_ops);
699 if (!NT_STATUS_IS_OK(ret)) {
700 DEBUG(0,("Failed to register '%s' gensec backend!\n",
701 gensec_krb5_security_ops.name));
705 ret = gensec_register(&gensec_fake_gssapi_krb5_security_ops);
706 if (!NT_STATUS_IS_OK(ret)) {
707 DEBUG(0,("Failed to register '%s' gensec backend!\n",
708 gensec_krb5_security_ops.name));