2 Unix SMB/CIFS implementation.
4 Create and parse the krb5 PAC
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005,2008
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 3 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, see <http://www.gnu.org/licenses/>.
27 #include "system/kerberos.h"
28 #include "auth/auth.h"
29 #include "auth/kerberos/kerberos.h"
30 #include "librpc/gen_ndr/ndr_krb5pac.h"
32 #include "auth/auth_sam_reply.h"
34 krb5_error_code
check_pac_checksum(TALLOC_CTX
*mem_ctx
,
36 struct PAC_SIGNATURE_DATA
*sig
,
38 const krb5_keyblock
*keyblock
)
44 cksum
.cksumtype
= (CKSUMTYPE
)sig
->type
;
45 cksum
.checksum
.length
= sig
->signature
.length
;
46 cksum
.checksum
.data
= sig
->signature
.data
;
48 ret
= krb5_crypto_init(context
,
53 DEBUG(0,("krb5_crypto_init() failed: %s\n",
54 smb_get_krb5_error_message(context
, ret
, mem_ctx
)));
57 ret
= krb5_verify_checksum(context
,
63 krb5_crypto_destroy(context
, crypto
);
68 NTSTATUS
kerberos_decode_pac(TALLOC_CTX
*mem_ctx
,
69 struct PAC_DATA
**pac_data_out
,
72 const krb5_keyblock
*krbtgt_keyblock
,
73 const krb5_keyblock
*service_keyblock
,
74 krb5_const_principal client_principal
,
76 krb5_error_code
*k5ret
)
80 enum ndr_err_code ndr_err
;
81 struct PAC_SIGNATURE_DATA
*srv_sig_ptr
= NULL
;
82 struct PAC_SIGNATURE_DATA
*kdc_sig_ptr
= NULL
;
83 struct PAC_SIGNATURE_DATA
*srv_sig_wipe
= NULL
;
84 struct PAC_SIGNATURE_DATA
*kdc_sig_wipe
= NULL
;
85 struct PAC_LOGON_INFO
*logon_info
= NULL
;
86 struct PAC_LOGON_NAME
*logon_name
= NULL
;
87 struct PAC_DATA
*pac_data
;
88 struct PAC_DATA_RAW
*pac_data_raw
;
90 DATA_BLOB
*srv_sig_blob
= NULL
;
91 DATA_BLOB
*kdc_sig_blob
= NULL
;
93 DATA_BLOB modified_pac_blob
;
94 NTTIME tgs_authtime_nttime
;
95 krb5_principal client_principal_pac
;
98 krb5_clear_error_message(context
);
101 *k5ret
= KRB5_PARSE_MALFORMED
;
104 pac_data
= talloc(mem_ctx
, struct PAC_DATA
);
105 pac_data_raw
= talloc(mem_ctx
, struct PAC_DATA_RAW
);
106 kdc_sig_wipe
= talloc(mem_ctx
, struct PAC_SIGNATURE_DATA
);
107 srv_sig_wipe
= talloc(mem_ctx
, struct PAC_SIGNATURE_DATA
);
108 if (!pac_data_raw
|| !pac_data
|| !kdc_sig_wipe
|| !srv_sig_wipe
) {
112 return NT_STATUS_NO_MEMORY
;
115 ndr_err
= ndr_pull_struct_blob(&blob
, pac_data
,
116 pac_data
, (ndr_pull_flags_fn_t
)ndr_pull_PAC_DATA
);
117 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
118 status
= ndr_map_error2ntstatus(ndr_err
);
119 DEBUG(0,("can't parse the PAC: %s\n",
124 if (pac_data
->num_buffers
< 4) {
125 /* we need logon_ingo, service_key and kdc_key */
126 DEBUG(0,("less than 4 PAC buffers\n"));
127 return NT_STATUS_INVALID_PARAMETER
;
130 ndr_err
= ndr_pull_struct_blob(&blob
, pac_data_raw
,
132 (ndr_pull_flags_fn_t
)ndr_pull_PAC_DATA_RAW
);
133 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
134 status
= ndr_map_error2ntstatus(ndr_err
);
135 DEBUG(0,("can't parse the PAC: %s\n",
140 if (pac_data_raw
->num_buffers
< 4) {
141 /* we need logon_ingo, service_key and kdc_key */
142 DEBUG(0,("less than 4 PAC buffers\n"));
143 return NT_STATUS_INVALID_PARAMETER
;
146 if (pac_data
->num_buffers
!= pac_data_raw
->num_buffers
) {
147 /* we need logon_ingo, service_key and kdc_key */
148 DEBUG(0,("misparse! PAC_DATA has %d buffers while PAC_DATA_RAW has %d\n",
149 pac_data
->num_buffers
, pac_data_raw
->num_buffers
));
150 return NT_STATUS_INVALID_PARAMETER
;
153 for (i
=0; i
< pac_data
->num_buffers
; i
++) {
154 if (pac_data
->buffers
[i
].type
!= pac_data_raw
->buffers
[i
].type
) {
155 DEBUG(0,("misparse! PAC_DATA buffer %d has type %d while PAC_DATA_RAW has %d\n",
156 i
, pac_data
->buffers
[i
].type
, pac_data
->buffers
[i
].type
));
157 return NT_STATUS_INVALID_PARAMETER
;
159 switch (pac_data
->buffers
[i
].type
) {
160 case PAC_TYPE_LOGON_INFO
:
161 if (!pac_data
->buffers
[i
].info
) {
164 logon_info
= pac_data
->buffers
[i
].info
->logon_info
.info
;
166 case PAC_TYPE_SRV_CHECKSUM
:
167 if (!pac_data
->buffers
[i
].info
) {
170 srv_sig_ptr
= &pac_data
->buffers
[i
].info
->srv_cksum
;
171 srv_sig_blob
= &pac_data_raw
->buffers
[i
].info
->remaining
;
173 case PAC_TYPE_KDC_CHECKSUM
:
174 if (!pac_data
->buffers
[i
].info
) {
177 kdc_sig_ptr
= &pac_data
->buffers
[i
].info
->kdc_cksum
;
178 kdc_sig_blob
= &pac_data_raw
->buffers
[i
].info
->remaining
;
180 case PAC_TYPE_LOGON_NAME
:
181 logon_name
= &pac_data
->buffers
[i
].info
->logon_name
;
189 DEBUG(0,("PAC no logon_info\n"));
190 return NT_STATUS_INVALID_PARAMETER
;
194 DEBUG(0,("PAC no logon_name\n"));
195 return NT_STATUS_INVALID_PARAMETER
;
198 if (!srv_sig_ptr
|| !srv_sig_blob
) {
199 DEBUG(0,("PAC no srv_key\n"));
200 return NT_STATUS_INVALID_PARAMETER
;
203 if (!kdc_sig_ptr
|| !kdc_sig_blob
) {
204 DEBUG(0,("PAC no kdc_key\n"));
205 return NT_STATUS_INVALID_PARAMETER
;
208 /* Find and zero out the signatures, as required by the signing algorithm */
210 /* We find the data blobs above, now we parse them to get at the exact portion we should zero */
211 ndr_err
= ndr_pull_struct_blob(kdc_sig_blob
, kdc_sig_wipe
,
213 (ndr_pull_flags_fn_t
)ndr_pull_PAC_SIGNATURE_DATA
);
214 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
215 status
= ndr_map_error2ntstatus(ndr_err
);
216 DEBUG(0,("can't parse the KDC signature: %s\n",
221 ndr_err
= ndr_pull_struct_blob(srv_sig_blob
, srv_sig_wipe
,
223 (ndr_pull_flags_fn_t
)ndr_pull_PAC_SIGNATURE_DATA
);
224 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
225 status
= ndr_map_error2ntstatus(ndr_err
);
226 DEBUG(0,("can't parse the SRV signature: %s\n",
231 /* Now zero the decoded structure */
232 memset(kdc_sig_wipe
->signature
.data
, '\0', kdc_sig_wipe
->signature
.length
);
233 memset(srv_sig_wipe
->signature
.data
, '\0', srv_sig_wipe
->signature
.length
);
235 /* and reencode, back into the same place it came from */
236 ndr_err
= ndr_push_struct_blob(kdc_sig_blob
, pac_data_raw
,
238 (ndr_push_flags_fn_t
)ndr_push_PAC_SIGNATURE_DATA
);
239 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
240 status
= ndr_map_error2ntstatus(ndr_err
);
241 DEBUG(0,("can't repack the KDC signature: %s\n",
245 ndr_err
= ndr_push_struct_blob(srv_sig_blob
, pac_data_raw
,
247 (ndr_push_flags_fn_t
)ndr_push_PAC_SIGNATURE_DATA
);
248 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
249 status
= ndr_map_error2ntstatus(ndr_err
);
250 DEBUG(0,("can't repack the SRV signature: %s\n",
255 /* push out the whole structure, but now with zero'ed signatures */
256 ndr_err
= ndr_push_struct_blob(&modified_pac_blob
, pac_data_raw
,
258 (ndr_push_flags_fn_t
)ndr_push_PAC_DATA_RAW
);
259 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
260 status
= ndr_map_error2ntstatus(ndr_err
);
261 DEBUG(0,("can't repack the RAW PAC: %s\n",
266 /* verify by service_key */
267 ret
= check_pac_checksum(mem_ctx
,
268 modified_pac_blob
, srv_sig_ptr
,
272 DEBUG(1, ("PAC Decode: Failed to verify the service signature: %s\n",
273 smb_get_krb5_error_message(context
, ret
, mem_ctx
)));
277 return NT_STATUS_ACCESS_DENIED
;
280 if (krbtgt_keyblock
) {
281 ret
= check_pac_checksum(mem_ctx
,
282 srv_sig_ptr
->signature
, kdc_sig_ptr
,
283 context
, krbtgt_keyblock
);
285 DEBUG(1, ("PAC Decode: Failed to verify the KDC signature: %s\n",
286 smb_get_krb5_error_message(context
, ret
, mem_ctx
)));
290 return NT_STATUS_ACCESS_DENIED
;
294 /* Convert to NT time, so as not to loose accuracy in comparison */
295 unix_to_nt_time(&tgs_authtime_nttime
, tgs_authtime
);
297 if (tgs_authtime_nttime
!= logon_name
->logon_time
) {
298 DEBUG(2, ("PAC Decode: Logon time mismatch between ticket and PAC!\n"));
299 DEBUG(2, ("PAC Decode: PAC: %s\n", nt_time_string(mem_ctx
, logon_name
->logon_time
)));
300 DEBUG(2, ("PAC Decode: Ticket: %s\n", nt_time_string(mem_ctx
, tgs_authtime_nttime
)));
301 return NT_STATUS_ACCESS_DENIED
;
304 ret
= krb5_parse_name_flags(context
, logon_name
->account_name
, KRB5_PRINCIPAL_PARSE_NO_REALM
,
305 &client_principal_pac
);
307 DEBUG(2, ("Could not parse name from incoming PAC: [%s]: %s\n",
308 logon_name
->account_name
,
309 smb_get_krb5_error_message(context
, ret
, mem_ctx
)));
313 return NT_STATUS_INVALID_PARAMETER
;
316 if (!krb5_principal_compare_any_realm(context
, client_principal
, client_principal_pac
)) {
317 DEBUG(2, ("Name in PAC [%s] does not match principal name in ticket\n",
318 logon_name
->account_name
));
319 krb5_free_principal(context
, client_principal_pac
);
320 return NT_STATUS_ACCESS_DENIED
;
323 krb5_free_principal(context
, client_principal_pac
);
326 if (strcasecmp(logon_info
->info3
.base
.account_name
.string
,
327 "Administrator")== 0) {
328 file_save("tmp_pac_data-admin.dat",blob
.data
,blob
.length
);
332 DEBUG(3,("Found account name from PAC: %s [%s]\n",
333 logon_info
->info3
.base
.account_name
.string
,
334 logon_info
->info3
.base
.full_name
.string
));
335 *pac_data_out
= pac_data
;
340 _PUBLIC_ NTSTATUS
kerberos_pac_logon_info(TALLOC_CTX
*mem_ctx
,
341 struct PAC_LOGON_INFO
**logon_info
,
343 krb5_context context
,
344 const krb5_keyblock
*krbtgt_keyblock
,
345 const krb5_keyblock
*service_keyblock
,
346 krb5_const_principal client_principal
,
348 krb5_error_code
*k5ret
)
351 struct PAC_DATA
*pac_data
;
353 nt_status
= kerberos_decode_pac(mem_ctx
,
362 if (!NT_STATUS_IS_OK(nt_status
)) {
367 for (i
=0; i
< pac_data
->num_buffers
; i
++) {
368 if (pac_data
->buffers
[i
].type
!= PAC_TYPE_LOGON_INFO
) {
371 *logon_info
= pac_data
->buffers
[i
].info
->logon_info
.info
;
374 return NT_STATUS_INVALID_PARAMETER
;
379 static krb5_error_code
make_pac_checksum(TALLOC_CTX
*mem_ctx
,
381 struct PAC_SIGNATURE_DATA
*sig
,
382 krb5_context context
,
383 const krb5_keyblock
*keyblock
)
390 ret
= krb5_crypto_init(context
,
395 DEBUG(0,("krb5_crypto_init() failed: %s\n",
396 smb_get_krb5_error_message(context
, ret
, mem_ctx
)));
399 ret
= krb5_create_checksum(context
,
407 DEBUG(2, ("PAC Verification failed: %s\n",
408 smb_get_krb5_error_message(context
, ret
, mem_ctx
)));
411 krb5_crypto_destroy(context
, crypto
);
417 sig
->type
= cksum
.cksumtype
;
418 sig
->signature
= data_blob_talloc(mem_ctx
, cksum
.checksum
.data
, cksum
.checksum
.length
);
419 free_Checksum(&cksum
);
424 krb5_error_code
kerberos_encode_pac(TALLOC_CTX
*mem_ctx
,
425 struct PAC_DATA
*pac_data
,
426 krb5_context context
,
427 const krb5_keyblock
*krbtgt_keyblock
,
428 const krb5_keyblock
*service_keyblock
,
433 enum ndr_err_code ndr_err
;
434 DATA_BLOB zero_blob
= data_blob(NULL
, 0);
435 DATA_BLOB tmp_blob
= data_blob(NULL
, 0);
436 struct PAC_SIGNATURE_DATA
*kdc_checksum
= NULL
;
437 struct PAC_SIGNATURE_DATA
*srv_checksum
= NULL
;
440 /* First, just get the keytypes filled in (and lengths right, eventually) */
441 for (i
=0; i
< pac_data
->num_buffers
; i
++) {
442 if (pac_data
->buffers
[i
].type
!= PAC_TYPE_KDC_CHECKSUM
) {
445 kdc_checksum
= &pac_data
->buffers
[i
].info
->kdc_cksum
,
446 ret
= make_pac_checksum(mem_ctx
, &zero_blob
,
448 context
, krbtgt_keyblock
);
450 DEBUG(2, ("making krbtgt PAC checksum failed: %s\n",
451 smb_get_krb5_error_message(context
, ret
, mem_ctx
)));
452 talloc_free(pac_data
);
457 for (i
=0; i
< pac_data
->num_buffers
; i
++) {
458 if (pac_data
->buffers
[i
].type
!= PAC_TYPE_SRV_CHECKSUM
) {
461 srv_checksum
= &pac_data
->buffers
[i
].info
->srv_cksum
;
462 ret
= make_pac_checksum(mem_ctx
, &zero_blob
,
464 context
, service_keyblock
);
466 DEBUG(2, ("making service PAC checksum failed: %s\n",
467 smb_get_krb5_error_message(context
, ret
, mem_ctx
)));
468 talloc_free(pac_data
);
474 DEBUG(2, ("Invalid PAC constructed for signing, no KDC checksum present!"));
478 DEBUG(2, ("Invalid PAC constructed for signing, no SRV checksum present!"));
482 /* But wipe out the actual signatures */
483 memset(kdc_checksum
->signature
.data
, '\0', kdc_checksum
->signature
.length
);
484 memset(srv_checksum
->signature
.data
, '\0', srv_checksum
->signature
.length
);
486 ndr_err
= ndr_push_struct_blob(&tmp_blob
, mem_ctx
,
488 (ndr_push_flags_fn_t
)ndr_push_PAC_DATA
);
489 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
490 nt_status
= ndr_map_error2ntstatus(ndr_err
);
491 DEBUG(1, ("PAC (presig) push failed: %s\n", nt_errstr(nt_status
)));
492 talloc_free(pac_data
);
496 /* Then sign the result of the previous push, where the sig was zero'ed out */
497 ret
= make_pac_checksum(mem_ctx
, &tmp_blob
, srv_checksum
,
498 context
, service_keyblock
);
500 /* Then sign Server checksum */
501 ret
= make_pac_checksum(mem_ctx
, &srv_checksum
->signature
, kdc_checksum
, context
, krbtgt_keyblock
);
503 DEBUG(2, ("making krbtgt PAC checksum failed: %s\n",
504 smb_get_krb5_error_message(context
, ret
, mem_ctx
)));
505 talloc_free(pac_data
);
509 /* And push it out again, this time to the world. This relies on determanistic pointer values */
510 ndr_err
= ndr_push_struct_blob(&tmp_blob
, mem_ctx
,
512 (ndr_push_flags_fn_t
)ndr_push_PAC_DATA
);
513 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
514 nt_status
= ndr_map_error2ntstatus(ndr_err
);
515 DEBUG(1, ("PAC (final) push failed: %s\n", nt_errstr(nt_status
)));
516 talloc_free(pac_data
);
526 krb5_error_code
kerberos_create_pac(TALLOC_CTX
*mem_ctx
,
527 struct auth_user_info_dc
*user_info_dc
,
528 krb5_context context
,
529 const krb5_keyblock
*krbtgt_keyblock
,
530 const krb5_keyblock
*service_keyblock
,
531 krb5_principal client_principal
,
537 struct PAC_DATA
*pac_data
= talloc(mem_ctx
, struct PAC_DATA
);
538 struct netr_SamInfo3
*sam3
;
539 union PAC_INFO
*u_LOGON_INFO
;
540 struct PAC_LOGON_INFO
*LOGON_INFO
;
541 union PAC_INFO
*u_LOGON_NAME
;
542 struct PAC_LOGON_NAME
*LOGON_NAME
;
543 union PAC_INFO
*u_KDC_CHECKSUM
;
544 union PAC_INFO
*u_SRV_CHECKSUM
;
549 PAC_BUF_LOGON_INFO
= 0,
550 PAC_BUF_LOGON_NAME
= 1,
551 PAC_BUF_SRV_CHECKSUM
= 2,
552 PAC_BUF_KDC_CHECKSUM
= 3,
553 PAC_BUF_NUM_BUFFERS
= 4
560 pac_data
->num_buffers
= PAC_BUF_NUM_BUFFERS
;
561 pac_data
->version
= 0;
563 pac_data
->buffers
= talloc_array(pac_data
,
565 pac_data
->num_buffers
);
566 if (!pac_data
->buffers
) {
567 talloc_free(pac_data
);
572 u_LOGON_INFO
= talloc_zero(pac_data
->buffers
, union PAC_INFO
);
574 talloc_free(pac_data
);
577 pac_data
->buffers
[PAC_BUF_LOGON_INFO
].type
= PAC_TYPE_LOGON_INFO
;
578 pac_data
->buffers
[PAC_BUF_LOGON_INFO
].info
= u_LOGON_INFO
;
581 u_LOGON_NAME
= talloc_zero(pac_data
->buffers
, union PAC_INFO
);
583 talloc_free(pac_data
);
586 pac_data
->buffers
[PAC_BUF_LOGON_NAME
].type
= PAC_TYPE_LOGON_NAME
;
587 pac_data
->buffers
[PAC_BUF_LOGON_NAME
].info
= u_LOGON_NAME
;
588 LOGON_NAME
= &u_LOGON_NAME
->logon_name
;
591 u_SRV_CHECKSUM
= talloc_zero(pac_data
->buffers
, union PAC_INFO
);
592 if (!u_SRV_CHECKSUM
) {
593 talloc_free(pac_data
);
596 pac_data
->buffers
[PAC_BUF_SRV_CHECKSUM
].type
= PAC_TYPE_SRV_CHECKSUM
;
597 pac_data
->buffers
[PAC_BUF_SRV_CHECKSUM
].info
= u_SRV_CHECKSUM
;
600 u_KDC_CHECKSUM
= talloc_zero(pac_data
->buffers
, union PAC_INFO
);
601 if (!u_KDC_CHECKSUM
) {
602 talloc_free(pac_data
);
605 pac_data
->buffers
[PAC_BUF_KDC_CHECKSUM
].type
= PAC_TYPE_KDC_CHECKSUM
;
606 pac_data
->buffers
[PAC_BUF_KDC_CHECKSUM
].info
= u_KDC_CHECKSUM
;
608 /* now the real work begins... */
610 LOGON_INFO
= talloc_zero(u_LOGON_INFO
, struct PAC_LOGON_INFO
);
612 talloc_free(pac_data
);
615 nt_status
= auth_convert_user_info_dc_saminfo3(LOGON_INFO
, user_info_dc
, &sam3
);
616 if (!NT_STATUS_IS_OK(nt_status
)) {
617 DEBUG(1, ("Getting Samba info failed: %s\n", nt_errstr(nt_status
)));
618 talloc_free(pac_data
);
622 u_LOGON_INFO
->logon_info
.info
= LOGON_INFO
;
623 LOGON_INFO
->info3
= *sam3
;
625 ret
= krb5_unparse_name_flags(context
, client_principal
,
626 KRB5_PRINCIPAL_UNPARSE_NO_REALM
, &name
);
630 LOGON_NAME
->account_name
= talloc_strdup(LOGON_NAME
, name
);
633 this logon_time field is absolutely critical. This is what
634 caused all our PAC troubles :-)
636 unix_to_nt_time(&LOGON_NAME
->logon_time
, tgs_authtime
);
638 ret
= kerberos_encode_pac(mem_ctx
,
644 talloc_free(pac_data
);
648 krb5_error_code
kerberos_pac_to_user_info_dc(TALLOC_CTX
*mem_ctx
,
650 krb5_context context
,
651 struct auth_user_info_dc
**user_info_dc
,
652 struct PAC_SIGNATURE_DATA
*pac_srv_sig
,
653 struct PAC_SIGNATURE_DATA
*pac_kdc_sig
)
656 enum ndr_err_code ndr_err
;
659 DATA_BLOB pac_logon_info_in
, pac_srv_checksum_in
, pac_kdc_checksum_in
;
660 krb5_data k5pac_logon_info_in
, k5pac_srv_checksum_in
, k5pac_kdc_checksum_in
;
663 struct auth_user_info_dc
*user_info_dc_out
;
665 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
671 ret
= krb5_pac_get_buffer(context
, pac
, PAC_TYPE_LOGON_INFO
, &k5pac_logon_info_in
);
673 talloc_free(tmp_ctx
);
677 pac_logon_info_in
= data_blob_const(k5pac_logon_info_in
.data
, k5pac_logon_info_in
.length
);
679 ndr_err
= ndr_pull_union_blob(&pac_logon_info_in
, tmp_ctx
, &info
,
681 (ndr_pull_flags_fn_t
)ndr_pull_PAC_INFO
);
682 krb5_data_free(&k5pac_logon_info_in
);
683 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
) || !info
.logon_info
.info
) {
684 nt_status
= ndr_map_error2ntstatus(ndr_err
);
685 DEBUG(0,("can't parse the PAC LOGON_INFO: %s\n", nt_errstr(nt_status
)));
686 talloc_free(tmp_ctx
);
690 /* Pull this right into the normal auth sysstem structures */
691 nt_status
= make_user_info_dc_pac(mem_ctx
,
692 info
.logon_info
.info
,
694 if (!NT_STATUS_IS_OK(nt_status
)) {
695 talloc_free(tmp_ctx
);
700 ret
= krb5_pac_get_buffer(context
, pac
, PAC_TYPE_SRV_CHECKSUM
, &k5pac_srv_checksum_in
);
702 talloc_free(tmp_ctx
);
706 pac_srv_checksum_in
= data_blob_const(k5pac_srv_checksum_in
.data
, k5pac_srv_checksum_in
.length
);
708 ndr_err
= ndr_pull_struct_blob(&pac_srv_checksum_in
, pac_srv_sig
,
710 (ndr_pull_flags_fn_t
)ndr_pull_PAC_SIGNATURE_DATA
);
711 krb5_data_free(&k5pac_srv_checksum_in
);
712 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
713 nt_status
= ndr_map_error2ntstatus(ndr_err
);
714 DEBUG(0,("can't parse the KDC signature: %s\n",
715 nt_errstr(nt_status
)));
721 ret
= krb5_pac_get_buffer(context
, pac
, PAC_TYPE_KDC_CHECKSUM
, &k5pac_kdc_checksum_in
);
723 talloc_free(tmp_ctx
);
727 pac_kdc_checksum_in
= data_blob_const(k5pac_kdc_checksum_in
.data
, k5pac_kdc_checksum_in
.length
);
729 ndr_err
= ndr_pull_struct_blob(&pac_kdc_checksum_in
, pac_kdc_sig
,
731 (ndr_pull_flags_fn_t
)ndr_pull_PAC_SIGNATURE_DATA
);
732 krb5_data_free(&k5pac_kdc_checksum_in
);
733 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
734 nt_status
= ndr_map_error2ntstatus(ndr_err
);
735 DEBUG(0,("can't parse the KDC signature: %s\n",
736 nt_errstr(nt_status
)));
740 *user_info_dc
= user_info_dc_out
;
746 NTSTATUS
kerberos_pac_blob_to_user_info_dc(TALLOC_CTX
*mem_ctx
,
748 krb5_context context
,
749 struct auth_user_info_dc
**user_info_dc
,
750 struct PAC_SIGNATURE_DATA
*pac_srv_sig
,
751 struct PAC_SIGNATURE_DATA
*pac_kdc_sig
)
755 ret
= krb5_pac_parse(context
,
756 pac_blob
.data
, pac_blob
.length
,
759 return map_nt_error_from_unix(ret
);
763 ret
= kerberos_pac_to_user_info_dc(mem_ctx
, pac
, context
, user_info_dc
, pac_srv_sig
, pac_kdc_sig
);
764 krb5_pac_free(context
, pac
);
766 return map_nt_error_from_unix(ret
);