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
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 #define DBGC_CLASS DBGC_AUTH
31 enum GENSEC_KRB5_STATE
{
32 GENSEC_KRB5_SERVER_START
,
33 GENSEC_KRB5_CLIENT_START
,
34 GENSEC_KRB5_CLIENT_MUTUAL_AUTH
,
38 struct gensec_krb5_state
{
39 DATA_BLOB session_key
;
40 struct PAC_LOGON_INFO
*logon_info
;
41 enum GENSEC_KRB5_STATE state_position
;
42 krb5_context krb5_context
;
43 krb5_auth_context krb5_auth_context
;
44 krb5_ccache krb5_ccache
;
46 krb5_keyblock krb5_keyblock
;
50 #ifdef KRB5_DO_VERIFY_PAC
51 static NTSTATUS
gensec_krb5_pac_checksum(DATA_BLOB pac_data
,
52 struct PAC_SIGNATURE_DATA
*sig
,
53 struct gensec_krb5_state
*gensec_krb5_state
,
61 cksum
.cksumtype
= (CKSUMTYPE
)sig
->type
;
62 cksum
.checksum
.length
= sizeof(sig
->signature
);
63 cksum
.checksum
.data
= sig
->signature
;
66 ret
= krb5_crypto_init(gensec_krb5_state
->krb5_context
,
67 &gensec_krb5_state
->krb5_keyblock
,
71 DEBUG(0,("krb5_crypto_init() failed\n"));
72 return NT_STATUS_FOOBAR
;
74 for (i
=0; i
< 40; i
++) {
76 ret
= krb5_verify_checksum(gensec_krb5_state
->krb5_context
,
83 DEBUG(0,("PAC Verified: keyusage: %d\n", keyusage
));
87 krb5_crypto_destroy(gensec_krb5_state
->krb5_context
, crypto
);
90 DEBUG(0,("NOT verifying PAC checksums yet!\n"));
91 //return NT_STATUS_LOGON_FAILURE;
93 DEBUG(0,("PAC checksums verified!\n"));
100 static NTSTATUS
gensec_krb5_decode_pac(TALLOC_CTX
*mem_ctx
,
101 struct PAC_LOGON_INFO
**logon_info_out
,
103 struct gensec_krb5_state
*gensec_krb5_state
)
106 struct PAC_SIGNATURE_DATA srv_sig
;
107 struct PAC_SIGNATURE_DATA
*srv_sig_ptr
;
108 struct PAC_SIGNATURE_DATA kdc_sig
;
109 struct PAC_SIGNATURE_DATA
*kdc_sig_ptr
;
110 struct PAC_LOGON_INFO
*logon_info
= NULL
;
111 struct PAC_DATA pac_data
;
112 #ifdef KRB5_DO_VERIFY_PAC
113 DATA_BLOB tmp_blob
= data_blob(NULL
, 0);
117 status
= ndr_pull_struct_blob(&blob
, mem_ctx
, &pac_data
,
118 (ndr_pull_flags_fn_t
)ndr_pull_PAC_DATA
);
119 if (!NT_STATUS_IS_OK(status
)) {
120 DEBUG(0,("can't parse the PAC\n"));
123 NDR_PRINT_DEBUG(PAC_DATA
, &pac_data
);
125 if (pac_data
.num_buffers
< 3) {
126 /* we need logon_ingo, service_key and kdc_key */
127 DEBUG(0,("less than 3 PAC buffers\n"));
128 return NT_STATUS_FOOBAR
;
131 for (i
=0; i
< pac_data
.num_buffers
; i
++) {
132 switch (pac_data
.buffers
[i
].type
) {
133 case PAC_TYPE_LOGON_INFO
:
134 if (!pac_data
.buffers
[i
].info
) {
137 logon_info
= &pac_data
.buffers
[i
].info
->logon_info
;
139 case PAC_TYPE_SRV_CHECKSUM
:
140 if (!pac_data
.buffers
[i
].info
) {
143 srv_sig_ptr
= &pac_data
.buffers
[i
].info
->srv_cksum
;
144 srv_sig
= pac_data
.buffers
[i
].info
->srv_cksum
;
146 case PAC_TYPE_KDC_CHECKSUM
:
147 if (!pac_data
.buffers
[i
].info
) {
150 kdc_sig_ptr
= &pac_data
.buffers
[i
].info
->kdc_cksum
;
151 kdc_sig
= pac_data
.buffers
[i
].info
->kdc_cksum
;
153 case PAC_TYPE_UNKNOWN_10
:
161 DEBUG(0,("PAC no logon_info\n"));
162 return NT_STATUS_FOOBAR
;
166 DEBUG(0,("PAC no srv_key\n"));
167 return NT_STATUS_FOOBAR
;
171 DEBUG(0,("PAC no kdc_key\n"));
172 return NT_STATUS_FOOBAR
;
174 #ifdef KRB5_DO_VERIFY_PAC
175 /* clear the kdc_key */
176 /* memset((void *)kdc_sig_ptr , '\0', sizeof(*kdc_sig_ptr));*/
178 status
= ndr_push_struct_blob(&tmp_blob
, mem_ctx
, &pac_data
,
179 (ndr_push_flags_fn_t
)ndr_push_PAC_DATA
);
180 if (!NT_STATUS_IS_OK(status
)) {
183 status
= ndr_pull_struct_blob(&tmp_blob
, mem_ctx
, &pac_data
,
184 (ndr_pull_flags_fn_t
)ndr_pull_PAC_DATA
);
185 if (!NT_STATUS_IS_OK(status
)) {
186 DEBUG(0,("can't parse the PAC\n"));
189 /*NDR_PRINT_DEBUG(PAC_DATA, &pac_data);*/
191 /* verify by kdc_key */
192 status
= gensec_krb5_pac_checksum(tmp_blob
, &kdc_sig
, gensec_krb5_state
, 0);
194 if (!NT_STATUS_IS_OK(status
)) {
198 /* clear the service_key */
199 /* memset((void *)srv_sig_ptr , '\0', sizeof(*srv_sig_ptr));*/
201 status
= ndr_push_struct_blob(&tmp_blob
, mem_ctx
, &pac_data
,
202 (ndr_push_flags_fn_t
)ndr_push_PAC_DATA
);
203 if (!NT_STATUS_IS_OK(status
)) {
206 status
= ndr_pull_struct_blob(&tmp_blob
, mem_ctx
, &pac_data
,
207 (ndr_pull_flags_fn_t
)ndr_pull_PAC_DATA
);
208 if (!NT_STATUS_IS_OK(status
)) {
209 DEBUG(0,("can't parse the PAC\n"));
212 NDR_PRINT_DEBUG(PAC_DATA
, &pac_data
);
214 /* verify by servie_key */
215 status
= gensec_krb5_pac_checksum(tmp_blob
, &srv_sig
, gensec_krb5_state
, 0);
217 if (!NT_STATUS_IS_OK(status
)) {
221 DEBUG(0,("account_name: %s [%s]\n",logon_info
->account_name
.string
, logon_info
->full_name
.string
));
222 *logon_info_out
= logon_info
;
227 static void gensec_krb5_end(struct gensec_security
*gensec_security
)
229 struct gensec_krb5_state
*gensec_krb5_state
= gensec_security
->private_data
;
231 if (gensec_krb5_state
->ticket
.length
) {
232 /* Hmm, early heimdal dooesn't have this - correct call would be krb5_data_free */
233 #ifdef HAVE_KRB5_FREE_DATA_CONTENTS
234 krb5_free_data_contents(gensec_krb5_state
->krb5_context
, &gensec_krb5_state
->ticket
);
237 if (gensec_krb5_state
->krb5_ccache
) {
238 /* current heimdal - 0.6.3, which we need anyway, fixes segfaults here */
239 krb5_cc_close(gensec_krb5_state
->krb5_context
, gensec_krb5_state
->krb5_ccache
);
242 krb5_free_keyblock_contents(gensec_krb5_state
->krb5_context
,
243 &gensec_krb5_state
->krb5_keyblock
);
245 if (gensec_krb5_state
->krb5_auth_context
) {
246 krb5_auth_con_free(gensec_krb5_state
->krb5_context
,
247 gensec_krb5_state
->krb5_auth_context
);
250 if (gensec_krb5_state
->krb5_context
) {
251 krb5_free_context(gensec_krb5_state
->krb5_context
);
254 talloc_free(gensec_krb5_state
);
255 gensec_security
->private_data
= NULL
;
259 static NTSTATUS
gensec_krb5_start(struct gensec_security
*gensec_security
)
261 struct gensec_krb5_state
*gensec_krb5_state
;
262 krb5_error_code ret
= 0;
264 gensec_krb5_state
= talloc_p(gensec_security
, struct gensec_krb5_state
);
265 if (!gensec_krb5_state
) {
266 return NT_STATUS_NO_MEMORY
;
269 gensec_security
->private_data
= gensec_krb5_state
;
271 initialize_krb5_error_table();
272 gensec_krb5_state
->krb5_context
= NULL
;
273 gensec_krb5_state
->krb5_auth_context
= NULL
;
274 gensec_krb5_state
->krb5_ccache
= NULL
;
275 ZERO_STRUCT(gensec_krb5_state
->ticket
);
276 ZERO_STRUCT(gensec_krb5_state
->krb5_keyblock
);
277 gensec_krb5_state
->session_key
= data_blob(NULL
, 0);
279 ret
= krb5_init_context(&gensec_krb5_state
->krb5_context
);
281 DEBUG(1,("gensec_krb5_start: krb5_init_context failed (%s)\n", error_message(ret
)));
282 return NT_STATUS_INTERNAL_ERROR
;
285 if (lp_realm() && *lp_realm()) {
286 ret
= krb5_set_default_realm(gensec_krb5_state
->krb5_context
, lp_realm());
288 DEBUG(1,("gensec_krb5_start: krb5_set_default_realm failed (%s)\n", error_message(ret
)));
289 return NT_STATUS_INTERNAL_ERROR
;
293 ret
= krb5_auth_con_init(gensec_krb5_state
->krb5_context
, &gensec_krb5_state
->krb5_auth_context
);
295 DEBUG(1,("gensec_krb5_start: krb5_auth_con_init failed (%s)\n", error_message(ret
)));
296 return NT_STATUS_INTERNAL_ERROR
;
302 static NTSTATUS
gensec_krb5_server_start(struct gensec_security
*gensec_security
)
305 struct gensec_krb5_state
*gensec_krb5_state
;
307 nt_status
= gensec_krb5_start(gensec_security
);
308 if (!NT_STATUS_IS_OK(nt_status
)) {
312 gensec_krb5_state
= gensec_security
->private_data
;
313 gensec_krb5_state
->state_position
= GENSEC_KRB5_SERVER_START
;
318 static NTSTATUS
gensec_krb5_client_start(struct gensec_security
*gensec_security
)
320 struct gensec_krb5_state
*gensec_krb5_state
;
324 nt_status
= gensec_krb5_start(gensec_security
);
325 if (!NT_STATUS_IS_OK(nt_status
)) {
329 gensec_krb5_state
= gensec_security
->private_data
;
330 gensec_krb5_state
->state_position
= GENSEC_KRB5_CLIENT_START
;
332 /* TODO: This is effecivly a static/global variable... */
333 ret
= krb5_cc_default(gensec_krb5_state
->krb5_context
, &gensec_krb5_state
->krb5_ccache
);
335 DEBUG(1,("krb5_cc_default failed (%s)\n",
336 error_message(ret
)));
337 return NT_STATUS_INTERNAL_ERROR
;
341 if (gensec_security
->target
.principal
) {
342 DEBUG(5, ("Finding ticket for target [%s]\n", gensec_security
->target
.principal
));
343 ret
= ads_krb5_mk_req(gensec_krb5_state
->krb5_context
,
344 &gensec_krb5_state
->krb5_auth_context
,
345 AP_OPTS_USE_SUBKEY
| AP_OPTS_MUTUAL_REQUIRED
,
346 gensec_security
->target
.principal
,
347 gensec_krb5_state
->krb5_ccache
,
348 &gensec_krb5_state
->ticket
);
350 DEBUG(1,("ads_krb5_mk_req failed (%s)\n",
351 error_message(ret
)));
355 const char *hostname
= gensec_get_target_hostname(gensec_security
);
357 DEBUG(1, ("Could not determine hostname for target computer, cannot use kerberos\n"));
358 return NT_STATUS_ACCESS_DENIED
;
363 ret
= krb5_mk_req(gensec_krb5_state
->krb5_context
,
364 &gensec_krb5_state
->krb5_auth_context
,
365 AP_OPTS_USE_SUBKEY
| AP_OPTS_MUTUAL_REQUIRED
,
366 gensec_get_target_service(gensec_security
),
368 &in_data
, gensec_krb5_state
->krb5_ccache
,
369 &gensec_krb5_state
->ticket
);
371 DEBUG(1,("krb5_mk_req failed (%s)\n",
372 error_message(ret
)));
379 case KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN
:
380 DEBUG(3, ("Server is not registered with our KDC: %s\n",
381 error_message(ret
)));
382 return NT_STATUS_ACCESS_DENIED
;
383 case KRB5KDC_ERR_PREAUTH_FAILED
:
384 case KRB5KRB_AP_ERR_TKT_EXPIRED
:
387 DEBUG(3, ("kerberos: %s\n",
388 error_message(ret
)));
389 /* fall down to remaining code */
391 /* just don't print a message for these really ordinary messages */
392 case KRB5_FCC_NOFILE
:
393 case KRB5_CC_NOTFOUND
:
397 nt_status
= gensec_get_password(gensec_security
,
400 if (!NT_STATUS_IS_OK(nt_status
)) {
404 ret
= kerberos_kinit_password_cc(gensec_krb5_state
->krb5_context
, gensec_krb5_state
->krb5_ccache
,
405 gensec_get_client_principal(gensec_security
, gensec_security
),
406 password
, NULL
, &kdc_time
);
408 /* cope with ticket being in the future due to clock skew */
409 if ((unsigned)kdc_time
> time(NULL
)) {
410 time_t t
= time(NULL
);
411 int time_offset
=(unsigned)kdc_time
-t
;
412 DEBUG(4,("Advancing clock by %d seconds to cope with clock skew\n", time_offset
));
413 krb5_set_real_time(gensec_krb5_state
->krb5_context
, t
+ time_offset
+ 1, 0);
417 DEBUG(1,("kinit failed (%s)\n",
418 error_message(ret
)));
419 return NT_STATUS_WRONG_PASSWORD
;
424 DEBUG(0, ("kerberos: %s\n",
425 error_message(ret
)));
426 return NT_STATUS_UNSUCCESSFUL
;
433 * Next state function for the Krb5 GENSEC mechanism
435 * @param gensec_krb5_state KRB5 State
436 * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
437 * @param in The request, as a DATA_BLOB
438 * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
439 * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent,
440 * or NT_STATUS_OK if the user is authenticated.
443 static NTSTATUS
gensec_krb5_update(struct gensec_security
*gensec_security
, TALLOC_CTX
*out_mem_ctx
,
444 const DATA_BLOB in
, DATA_BLOB
*out
)
446 struct gensec_krb5_state
*gensec_krb5_state
= gensec_security
->private_data
;
447 krb5_error_code ret
= 0;
451 switch (gensec_krb5_state
->state_position
) {
452 case GENSEC_KRB5_CLIENT_START
:
455 DEBUG(1,("ads_krb5_mk_req (request ticket) failed (%s)\n",
456 error_message(ret
)));
457 nt_status
= NT_STATUS_LOGON_FAILURE
;
459 DATA_BLOB unwrapped_out
;
461 #ifndef GENSEC_SEND_UNWRAPPED_KRB5 /* This should be a switch for the torture code to set */
462 unwrapped_out
= data_blob_talloc(out_mem_ctx
, gensec_krb5_state
->ticket
.data
, gensec_krb5_state
->ticket
.length
);
464 /* wrap that up in a nice GSS-API wrapping */
465 *out
= gensec_gssapi_gen_krb5_wrap(out_mem_ctx
, &unwrapped_out
, TOK_ID_KRB_AP_REQ
);
467 *out
= data_blob_talloc(out_mem_ctx
, gensec_krb5_state
->ticket
.data
, gensec_krb5_state
->ticket
.length
);
469 gensec_krb5_state
->state_position
= GENSEC_KRB5_CLIENT_MUTUAL_AUTH
;
470 nt_status
= NT_STATUS_MORE_PROCESSING_REQUIRED
;
476 case GENSEC_KRB5_CLIENT_MUTUAL_AUTH
:
479 krb5_ap_rep_enc_part
*repl
= NULL
;
481 DATA_BLOB unwrapped_in
;
483 if (!gensec_gssapi_parse_krb5_wrap(out_mem_ctx
, &in
, &unwrapped_in
, tok_id
)) {
484 DEBUG(1,("gensec_gssapi_parse_krb5_wrap(mutual authentication) failed to parse\n"));
485 dump_data_pw("Mutual authentication message:\n", in
.data
, in
.length
);
486 return NT_STATUS_INVALID_PARAMETER
;
488 /* TODO: check the tok_id */
490 inbuf
.data
= unwrapped_in
.data
;
491 inbuf
.length
= unwrapped_in
.length
;
492 ret
= krb5_rd_rep(gensec_krb5_state
->krb5_context
,
493 gensec_krb5_state
->krb5_auth_context
,
496 DEBUG(1,("krb5_rd_rep (mutual authentication) failed (%s)\n",
497 error_message(ret
)));
498 dump_data_pw("Mutual authentication message:\n", inbuf
.data
, inbuf
.length
);
499 nt_status
= NT_STATUS_ACCESS_DENIED
;
501 *out
= data_blob(NULL
, 0);
502 nt_status
= NT_STATUS_OK
;
503 gensec_krb5_state
->state_position
= GENSEC_KRB5_DONE
;
506 krb5_free_ap_rep_enc_part(gensec_krb5_state
->krb5_context
, repl
);
511 case GENSEC_KRB5_SERVER_START
:
514 DATA_BLOB unwrapped_in
;
515 DATA_BLOB unwrapped_out
;
518 /* Parse the GSSAPI wrapping, if it's there... (win2k3 allows it to be omited) */
519 if (!gensec_gssapi_parse_krb5_wrap(out_mem_ctx
, &in
, &unwrapped_in
, tok_id
)) {
520 nt_status
= ads_verify_ticket(out_mem_ctx
,
521 gensec_krb5_state
->krb5_context
,
522 gensec_krb5_state
->krb5_auth_context
,
524 &principal
, &pac
, &unwrapped_out
,
525 &gensec_krb5_state
->krb5_keyblock
);
527 /* TODO: check the tok_id */
528 nt_status
= ads_verify_ticket(out_mem_ctx
,
529 gensec_krb5_state
->krb5_context
,
530 gensec_krb5_state
->krb5_auth_context
,
531 lp_realm(), &unwrapped_in
,
532 &principal
, &pac
, &unwrapped_out
,
533 &gensec_krb5_state
->krb5_keyblock
);
536 if (!NT_STATUS_IS_OK(nt_status
)) {
541 /* decode and verify the pac */
542 nt_status
= gensec_krb5_decode_pac(gensec_krb5_state
, &gensec_krb5_state
->logon_info
, pac
,
545 /* NULL PAC, we might need to figure this information out the hard way */
546 gensec_krb5_state
->logon_info
= NULL
;
549 if (NT_STATUS_IS_OK(nt_status
)) {
550 gensec_krb5_state
->state_position
= GENSEC_KRB5_DONE
;
551 /* wrap that up in a nice GSS-API wrapping */
552 *out
= gensec_gssapi_gen_krb5_wrap(out_mem_ctx
, &unwrapped_out
, TOK_ID_KRB_AP_REP
);
554 gensec_krb5_state
->peer_principal
= talloc_steal(gensec_krb5_state
, principal
);
558 case GENSEC_KRB5_DONE
:
562 return NT_STATUS_INVALID_PARAMETER
;
565 static NTSTATUS
gensec_krb5_session_key(struct gensec_security
*gensec_security
,
566 DATA_BLOB
*session_key
)
568 struct gensec_krb5_state
*gensec_krb5_state
= gensec_security
->private_data
;
569 krb5_context context
= gensec_krb5_state
->krb5_context
;
570 krb5_auth_context auth_context
= gensec_krb5_state
->krb5_auth_context
;
574 if (gensec_krb5_state
->session_key
.data
) {
575 *session_key
= gensec_krb5_state
->session_key
;
579 switch (gensec_security
->gensec_role
) {
581 err
= krb5_auth_con_getlocalsubkey(context
, auth_context
, &skey
);
584 err
= krb5_auth_con_getremotesubkey(context
, auth_context
, &skey
);
587 if (err
== 0 && skey
!= NULL
) {
588 DEBUG(10, ("Got KRB5 session key of length %d\n", KRB5_KEY_LENGTH(skey
)));
589 gensec_krb5_state
->session_key
= data_blob_talloc(gensec_krb5_state
,
590 KRB5_KEY_DATA(skey
), KRB5_KEY_LENGTH(skey
));
591 *session_key
= gensec_krb5_state
->session_key
;
592 dump_data_pw("KRB5 Session Key:\n", session_key
->data
, session_key
->length
);
594 krb5_free_keyblock(context
, skey
);
597 DEBUG(10, ("KRB5 error getting session key %d\n", err
));
598 return NT_STATUS_NO_USER_SESSION_KEY
;
602 static NTSTATUS
gensec_krb5_session_info(struct gensec_security
*gensec_security
,
603 struct auth_session_info
**session_info_out
)
606 struct gensec_krb5_state
*gensec_krb5_state
= gensec_security
->private_data
;
607 struct auth_serversupplied_info
*server_info
= NULL
;
608 struct auth_session_info
*session_info
= NULL
;
609 struct PAC_LOGON_INFO
*logon_info
= gensec_krb5_state
->logon_info
;
610 struct nt_user_token
*ptoken
;
615 *session_info_out
= NULL
;
617 nt_status
= make_server_info(gensec_security
, &server_info
, gensec_krb5_state
->peer_principal
);
618 if (!NT_STATUS_IS_OK(nt_status
)) {
622 server_info
->guest
= False
;
624 principal
= talloc_strdup(server_info
, gensec_krb5_state
->peer_principal
);
625 p
= strchr(principal
, '@');
629 server_info
->account_name
= principal
;
630 server_info
->domain
= talloc_strdup(server_info
, p
++);
631 if (!server_info
->domain
) {
632 free_server_info(&server_info
);
633 return NT_STATUS_NO_MEMORY
;
636 nt_status
= make_session_info(server_info
, &session_info
);
637 if (!NT_STATUS_IS_OK(nt_status
)) {
638 free_server_info(&server_info
);
642 /* IF we have the PAC - otherwise (TODO) we need to get this
643 * data from elsewere - local ldb, or lookup of some
647 ptoken
= talloc_p(session_info
, struct nt_user_token
);
649 return NT_STATUS_NO_MEMORY
;
652 ptoken
->num_sids
= 0;
654 ptoken
->user_sids
= talloc_array_p(ptoken
, struct dom_sid
*, logon_info
->groups_count
+ 2);
655 if (!ptoken
->user_sids
) {
656 return NT_STATUS_NO_MEMORY
;
660 sid
= dom_sid_dup(session_info
, logon_info
->dom_sid
);
661 ptoken
->user_sids
[0] = dom_sid_add_rid(session_info
, sid
, logon_info
->user_rid
);
663 sid
= dom_sid_dup(session_info
, logon_info
->dom_sid
);
664 ptoken
->user_sids
[1] = dom_sid_add_rid(session_info
, sid
, logon_info
->group_rid
);
667 for (;ptoken
->num_sids
< logon_info
->groups_count
; ptoken
->num_sids
++) {
668 sid
= dom_sid_dup(session_info
, logon_info
->dom_sid
);
669 ptoken
->user_sids
[ptoken
->num_sids
] = dom_sid_add_rid(session_info
, sid
, logon_info
->groups
[ptoken
->num_sids
- 2].rid
);
672 debug_nt_user_token(DBGC_AUTH
, 0, ptoken
);
674 session_info
->nt_user_token
= ptoken
;
676 session_info
->nt_user_token
= NULL
;
679 nt_status
= gensec_krb5_session_key(gensec_security
, &session_info
->session_key
);
681 session_info
->workstation
= NULL
;
683 *session_info_out
= session_info
;
689 static const struct gensec_security_ops gensec_krb5_security_ops
= {
691 .auth_type
= DCERPC_AUTH_TYPE_KRB5
,
692 .oid
= OID_KERBEROS5
,
693 .client_start
= gensec_krb5_client_start
,
694 .server_start
= gensec_krb5_server_start
,
695 .update
= gensec_krb5_update
,
696 .session_key
= gensec_krb5_session_key
,
697 .session_info
= gensec_krb5_session_info
,
698 .end
= gensec_krb5_end
701 static const struct gensec_security_ops gensec_ms_krb5_security_ops
= {
703 .auth_type
= DCERPC_AUTH_TYPE_KRB5
,
704 .oid
= OID_KERBEROS5_OLD
,
705 .client_start
= gensec_krb5_client_start
,
706 .server_start
= gensec_krb5_server_start
,
707 .update
= gensec_krb5_update
,
708 .session_key
= gensec_krb5_session_key
,
709 .session_info
= gensec_krb5_session_info
,
710 .end
= gensec_krb5_end
714 NTSTATUS
gensec_krb5_init(void)
718 ret
= register_backend("gensec", &gensec_krb5_security_ops
);
719 if (!NT_STATUS_IS_OK(ret
)) {
720 DEBUG(0,("Failed to register '%s' gensec backend!\n",
721 gensec_krb5_security_ops
.name
));
725 ret
= register_backend("gensec", &gensec_ms_krb5_security_ops
);
726 if (!NT_STATUS_IS_OK(ret
)) {
727 DEBUG(0,("Failed to register '%s' gensec backend!\n",
728 gensec_krb5_security_ops
.name
));