2 Unix SMB/CIFS implementation.
4 PAC Glue between Samba and the KDC
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2009
7 Copyright (C) Simo Sorce <idra@samba.org> 2010
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 3 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, see <http://www.gnu.org/licenses/>.
25 #include "kdc/authn_policy_util.h"
26 #include "kdc/kdc-glue.h"
27 #include "kdc/db-glue.h"
28 #include "kdc/pac-glue.h"
31 #include "librpc/gen_ndr/auth.h"
32 #include <krb5_locl.h>
33 #include "lib/replace/system/filesys.h"
36 #define DBGC_CLASS DBGC_KERBEROS
38 static bool samba_wdc_is_s4u2self_req(astgs_request_t r
)
40 const KDC_REQ
*req
= kdc_request_get_req(r
);
41 const PA_DATA
*pa_for_user
= NULL
;
43 if (req
->msg_type
!= krb_tgs_req
) {
47 if (req
->padata
!= NULL
) {
50 pa_for_user
= krb5_find_padata(req
->padata
->val
,
56 if (pa_for_user
!= NULL
) {
64 * Given the right private pointer from hdb_samba4,
65 * get a PAC from the attached ldb messages.
67 * For PKINIT we also get pk_reply_key and can add PAC_CREDENTIAL_INFO.
69 static krb5_error_code
samba_wdc_get_pac(void *priv
,
73 const krb5_keyblock
*pk_reply_key
,
74 uint64_t pac_attributes
,
77 krb5_context context
= kdc_request_get_context((kdc_request_t
)r
);
79 DATA_BLOB
*logon_blob
= NULL
;
80 DATA_BLOB
*cred_ndr
= NULL
;
81 DATA_BLOB
**cred_ndr_ptr
= NULL
;
82 DATA_BLOB _cred_blob
= data_blob_null
;
83 DATA_BLOB
*cred_blob
= NULL
;
84 DATA_BLOB
*upn_blob
= NULL
;
85 DATA_BLOB
*pac_attrs_blob
= NULL
;
86 DATA_BLOB
*requester_sid_blob
= NULL
;
87 DATA_BLOB client_claims_blob
= {};
90 struct samba_kdc_entry
*skdc_entry
=
91 talloc_get_type_abort(client
->context
,
92 struct samba_kdc_entry
);
93 const struct samba_kdc_entry
*server_entry
=
94 talloc_get_type_abort(server
->context
,
95 struct samba_kdc_entry
);
96 bool is_krbtgt
= krb5_principal_is_krbtgt(context
, server
->principal
);
97 enum auth_group_inclusion group_inclusion
;
98 bool is_s4u2self
= samba_wdc_is_s4u2self_req(r
);
99 enum samba_asserted_identity asserted_identity
=
101 SAMBA_ASSERTED_IDENTITY_SERVICE
:
102 SAMBA_ASSERTED_IDENTITY_AUTHENTICATION_AUTHORITY
;
103 struct authn_audit_info
*server_audit_info
= NULL
;
104 NTSTATUS reply_status
= NT_STATUS_OK
;
106 const struct auth_user_info_dc
*user_info_dc_const
= NULL
;
107 struct auth_user_info_dc
*user_info_dc_shallow_copy
= NULL
;
108 struct auth_claims auth_claims
= {};
110 /* Only include resource groups in a service ticket. */
112 group_inclusion
= AUTH_EXCLUDE_RESOURCE_GROUPS
;
113 } else if (server_entry
->supported_enctypes
& KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED
) {
114 group_inclusion
= AUTH_INCLUDE_RESOURCE_GROUPS
;
116 group_inclusion
= AUTH_INCLUDE_RESOURCE_GROUPS_COMPRESSED
;
119 mem_ctx
= talloc_named(client
->context
, 0, "samba_wdc_get_pac context");
124 if (pk_reply_key
!= NULL
) {
125 cred_ndr_ptr
= &cred_ndr
;
128 ret
= samba_kdc_get_user_info_from_db(mem_ctx
,
129 server_entry
->kdc_db_ctx
->samdb
,
132 &user_info_dc_const
);
134 talloc_free(mem_ctx
);
138 /* Make a shallow copy of the user_info_dc structure. */
139 nt_status
= authsam_shallow_copy_user_info_dc(mem_ctx
,
141 &user_info_dc_shallow_copy
);
142 user_info_dc_const
= NULL
;
144 if (!NT_STATUS_IS_OK(nt_status
)) {
145 DBG_ERR("Failed to allocate user_info_dc SIDs: %s\n",
146 nt_errstr(nt_status
));
147 talloc_free(mem_ctx
);
148 return map_errno_from_nt_status(nt_status
);
151 nt_status
= samba_kdc_add_asserted_identity(asserted_identity
,
152 user_info_dc_shallow_copy
);
153 if (!NT_STATUS_IS_OK(nt_status
)) {
154 DBG_ERR("Failed to add asserted identity: %s\n",
155 nt_errstr(nt_status
));
156 talloc_free(mem_ctx
);
157 return map_errno_from_nt_status(nt_status
);
160 nt_status
= samba_kdc_add_claims_valid(user_info_dc_shallow_copy
);
161 if (!NT_STATUS_IS_OK(nt_status
)) {
162 DBG_ERR("Failed to add Claims Valid: %s\n",
163 nt_errstr(nt_status
));
164 talloc_free(mem_ctx
);
165 return map_errno_from_nt_status(nt_status
);
168 ret
= samba_kdc_get_claims_data_from_db(server_entry
->kdc_db_ctx
->samdb
,
170 &auth_claims
.user_claims
);
172 talloc_free(mem_ctx
);
176 nt_status
= claims_data_encoded_claims_set(mem_ctx
,
177 auth_claims
.user_claims
,
178 &client_claims_blob
);
179 if (!NT_STATUS_IS_OK(nt_status
)) {
180 talloc_free(mem_ctx
);
181 return map_errno_from_nt_status(nt_status
);
185 * For an S4U2Self request, the authentication policy is not enforced.
187 if (!is_s4u2self
&& authn_policy_restrictions_present(server_entry
->server_policy
)) {
188 const hdb_entry
*device
= kdc_request_get_armor_client(r
);
189 const struct auth_user_info_dc
*device_info
= NULL
;
191 if (device
!= NULL
) {
192 const hdb_entry
*device_krbtgt
= NULL
;
193 struct samba_kdc_entry
*device_skdc_entry
= NULL
;
194 const struct samba_kdc_entry
*device_krbtgt_skdc_entry
= NULL
;
195 const krb5_const_pac device_pac
= kdc_request_get_armor_pac(r
);
196 struct samba_kdc_entry_pac device_pac_entry
= {};
198 device_skdc_entry
= talloc_get_type_abort(device
->context
,
199 struct samba_kdc_entry
);
201 device_krbtgt
= kdc_request_get_armor_server(r
);
202 if (device_krbtgt
!= NULL
) {
203 device_krbtgt_skdc_entry
= talloc_get_type_abort(device_krbtgt
->context
,
204 struct samba_kdc_entry
);
207 device_pac_entry
= samba_kdc_entry_pac(device_pac
,
209 samba_kdc_entry_is_trust(device_krbtgt_skdc_entry
));
211 ret
= samba_kdc_get_user_info_dc(mem_ctx
,
213 server_entry
->kdc_db_ctx
->samdb
,
216 NULL
/* resource_groups_out */);
218 talloc_free(mem_ctx
);
222 ret
= samba_kdc_get_claims_data(mem_ctx
,
224 server_entry
->kdc_db_ctx
->samdb
,
226 &auth_claims
.device_claims
);
228 talloc_free(mem_ctx
);
233 ret
= samba_kdc_allowed_to_authenticate_to(mem_ctx
,
234 server_entry
->kdc_db_ctx
->samdb
,
235 server_entry
->kdc_db_ctx
->lp_ctx
,
237 user_info_dc_shallow_copy
,
243 if (server_audit_info
!= NULL
) {
244 krb5_error_code ret2
;
246 ret2
= hdb_samba4_set_steal_server_audit_info(r
, server_audit_info
);
251 if (!NT_STATUS_IS_OK(reply_status
)) {
252 krb5_error_code ret2
;
254 ret2
= hdb_samba4_set_ntstatus(r
, reply_status
, ret
);
260 talloc_free(mem_ctx
);
265 nt_status
= samba_kdc_get_logon_info_blob(mem_ctx
,
266 user_info_dc_shallow_copy
,
269 if (!NT_STATUS_IS_OK(nt_status
)) {
270 talloc_free(mem_ctx
);
271 return map_errno_from_nt_status(nt_status
);
274 if (cred_ndr_ptr
!= NULL
) {
275 nt_status
= samba_kdc_get_cred_ndr_blob(mem_ctx
,
278 if (!NT_STATUS_IS_OK(nt_status
)) {
279 talloc_free(mem_ctx
);
280 return map_errno_from_nt_status(nt_status
);
284 nt_status
= samba_kdc_get_upn_info_blob(mem_ctx
,
285 user_info_dc_shallow_copy
,
287 if (!NT_STATUS_IS_OK(nt_status
)) {
288 talloc_free(mem_ctx
);
289 return map_errno_from_nt_status(nt_status
);
293 nt_status
= samba_kdc_get_pac_attrs_blob(mem_ctx
,
296 if (!NT_STATUS_IS_OK(nt_status
)) {
297 talloc_free(mem_ctx
);
298 return map_errno_from_nt_status(nt_status
);
301 nt_status
= samba_kdc_get_requester_sid_blob(mem_ctx
,
302 user_info_dc_shallow_copy
,
303 &requester_sid_blob
);
304 if (!NT_STATUS_IS_OK(nt_status
)) {
305 talloc_free(mem_ctx
);
306 return map_errno_from_nt_status(nt_status
);
310 if (pk_reply_key
!= NULL
&& cred_ndr
!= NULL
) {
311 ret
= samba_kdc_encrypt_pac_credentials(context
,
317 talloc_free(mem_ctx
);
320 cred_blob
= &_cred_blob
;
323 ret
= krb5_pac_init(context
, pac
);
325 talloc_free(mem_ctx
);
329 ret
= samba_make_krb5_pac(context
, logon_blob
, cred_blob
,
330 upn_blob
, pac_attrs_blob
,
331 requester_sid_blob
, NULL
,
332 &client_claims_blob
, NULL
, NULL
,
335 talloc_free(mem_ctx
);
339 static krb5_error_code
samba_wdc_verify_pac2(astgs_request_t r
,
340 const hdb_entry
*delegated_proxy
,
341 const hdb_entry
*client
,
342 const hdb_entry
*krbtgt
,
344 krb5_cksumtype ctype
)
346 krb5_context context
= kdc_request_get_context((kdc_request_t
)r
);
347 struct samba_kdc_entry
*client_skdc_entry
= NULL
;
348 struct samba_kdc_entry
*krbtgt_skdc_entry
=
349 talloc_get_type_abort(krbtgt
->context
, struct samba_kdc_entry
);
350 struct samba_kdc_entry_pac client_pac_entry
= {};
351 TALLOC_CTX
*mem_ctx
= NULL
;
353 bool is_s4u2self
= samba_wdc_is_s4u2self_req(r
);
354 bool is_in_db
= false;
355 bool is_trusted
= false;
362 mem_ctx
= talloc_named(NULL
, 0, "samba_wdc_verify_pac2 context");
363 if (mem_ctx
== NULL
) {
367 if (client
!= NULL
) {
368 client_skdc_entry
= talloc_get_type_abort(client
->context
,
369 struct samba_kdc_entry
);
373 * If the krbtgt was generated by an RODC, and we are not that
374 * RODC, then we need to regenerate the PAC - we can't trust
375 * it, and confirm that the RODC was permitted to print this ticket
377 * Because of the samba_kdc_validate_pac_blob() step we can be
378 * sure that the record in 'client' matches the SID in the
381 ret
= samba_krbtgt_is_in_db(krbtgt_skdc_entry
, &is_in_db
, &is_trusted
);
386 krb5_pac_set_trusted(pac
, is_trusted
);
387 client_pac_entry
= samba_kdc_entry_pac(pac
,
389 samba_kdc_entry_is_trust(krbtgt_skdc_entry
));
392 flags
|= SAMBA_KDC_FLAG_PROTOCOL_TRANSITION
;
395 if (delegated_proxy
!= NULL
) {
401 * The RODC-issued PAC was signed by a KDC entry that we
402 * don't have a key for. The server signature is not
403 * trustworthy, since it could have been created by the
404 * server we got the ticket from. We must not proceed as
405 * otherwise the ticket signature is unchecked.
407 ret
= HDB_ERR_NOT_FOUND_HERE
;
411 /* Fetch the correct key depending on the checksum type. */
412 if (ctype
== CKSUMTYPE_HMAC_MD5
) {
413 etype
= ENCTYPE_ARCFOUR_HMAC
;
415 ret
= krb5_cksumtype_to_enctype(context
,
422 ret
= hdb_enctype2key(context
, krbtgt
, NULL
, etype
, &key
);
427 /* Check the KDC, whole-PAC and ticket signatures. */
428 ret
= krb5_pac_verify(context
,
435 DBG_WARNING("PAC KDC signature failed to verify\n");
439 flags
|= SAMBA_KDC_FLAG_CONSTRAINED_DELEGATION
;
442 ret
= samba_kdc_verify_pac(mem_ctx
,
444 krbtgt_skdc_entry
->kdc_db_ctx
->samdb
,
453 talloc_free(mem_ctx
);
457 /* Re-sign (and reform, including possibly new groups) a PAC */
459 static krb5_error_code
samba_wdc_reget_pac(void *priv
, astgs_request_t r
,
460 krb5_const_principal _client_principal
,
461 hdb_entry
*delegated_proxy
,
462 krb5_const_pac delegated_proxy_pac
,
468 krb5_context context
= kdc_request_get_context((kdc_request_t
)r
);
469 struct samba_kdc_entry
*delegated_proxy_skdc_entry
= NULL
;
470 krb5_const_principal delegated_proxy_principal
= NULL
;
471 struct samba_kdc_entry_pac delegated_proxy_pac_entry
= {};
472 struct samba_kdc_entry
*client_skdc_entry
= NULL
;
473 struct samba_kdc_entry_pac client_pac_entry
= {};
474 struct samba_kdc_entry_pac device
= {};
475 const struct samba_kdc_entry
*server_skdc_entry
=
476 talloc_get_type_abort(server
->context
, struct samba_kdc_entry
);
477 const struct samba_kdc_entry
*krbtgt_skdc_entry
=
478 talloc_get_type_abort(krbtgt
->context
, struct samba_kdc_entry
);
479 TALLOC_CTX
*mem_ctx
= NULL
;
480 krb5_pac new_pac
= NULL
;
481 struct authn_audit_info
*server_audit_info
= NULL
;
483 NTSTATUS reply_status
= NT_STATUS_OK
;
490 mem_ctx
= talloc_named(NULL
, 0, "samba_wdc_reget_pac context");
491 if (mem_ctx
== NULL
) {
495 if (delegated_proxy
!= NULL
) {
496 delegated_proxy_skdc_entry
= talloc_get_type_abort(delegated_proxy
->context
,
497 struct samba_kdc_entry
);
498 delegated_proxy_principal
= delegated_proxy
->principal
;
501 delegated_proxy_pac_entry
= samba_kdc_entry_pac(delegated_proxy_pac
,
502 delegated_proxy_skdc_entry
,
504 * evidence ticket could
505 * not have been signed
506 * or issued by a krbtgt
508 false /* is_from_trust */);
510 if (client
!= NULL
) {
511 client_skdc_entry
= talloc_get_type_abort(client
->context
,
512 struct samba_kdc_entry
);
515 device
= samba_kdc_get_device_pac(r
);
517 ret
= krb5_pac_init(context
, &new_pac
);
523 client_pac_entry
= samba_kdc_entry_pac(*pac
,
525 samba_kdc_entry_is_trust(krbtgt_skdc_entry
));
527 ret
= samba_kdc_update_pac(mem_ctx
,
529 krbtgt_skdc_entry
->kdc_db_ctx
->samdb
,
530 krbtgt_skdc_entry
->kdc_db_ctx
->lp_ctx
,
535 delegated_proxy_principal
,
536 delegated_proxy_pac_entry
,
541 if (server_audit_info
!= NULL
) {
542 krb5_error_code ret2
;
544 ret2
= hdb_samba4_set_steal_server_audit_info(r
, server_audit_info
);
549 if (!NT_STATUS_IS_OK(reply_status
)) {
550 krb5_error_code ret2
;
552 ret2
= hdb_samba4_set_ntstatus(r
, reply_status
, ret
);
558 krb5_pac_free(context
, new_pac
);
559 if (ret
== ENOATTR
) {
560 krb5_pac_free(context
, *pac
);
567 /* Replace the pac */
568 krb5_pac_free(context
, *pac
);
572 talloc_free(mem_ctx
);
576 /* Verify a PAC's SID and signatures */
578 static krb5_error_code
samba_wdc_verify_pac(void *priv
, astgs_request_t r
,
579 krb5_const_principal _client_principal
,
580 hdb_entry
*delegated_proxy
,
584 EncTicketPart
*ticket
,
587 krb5_context context
= kdc_request_get_context((kdc_request_t
)r
);
588 krb5_kdc_configuration
*config
= kdc_request_get_config((kdc_request_t
)r
);
589 struct samba_kdc_entry
*krbtgt_skdc_entry
=
590 talloc_get_type_abort(krbtgt
->context
,
591 struct samba_kdc_entry
);
593 krb5_cksumtype ctype
= CKSUMTYPE_NONE
;
594 hdb_entry signing_krbtgt_hdb
;
596 if (delegated_proxy
) {
597 uint16_t pac_kdc_signature_rodc_id
;
598 const unsigned int local_tgs_rodc_id
= krbtgt_skdc_entry
->kdc_db_ctx
->my_krbtgt_number
;
599 const uint16_t header_ticket_rodc_id
= krbtgt
->kvno
>> 16;
602 * We're using delegated_proxy for the moment to indicate cases
603 * where the ticket was encrypted with the server key, and not a
604 * krbtgt key. This cannot be trusted, so we need to find a
605 * krbtgt key that signs the PAC in order to trust the ticket.
607 * The krbtgt passed in to this function refers to the krbtgt
608 * used to decrypt the ticket of the server requesting
611 * When we implement service ticket renewal, we need to check
612 * the PAC, and this will need to be updated.
614 ret
= krb5_pac_get_kdc_checksum_info(context
,
617 &pac_kdc_signature_rodc_id
);
619 DBG_WARNING("Failed to get PAC checksum info\n");
624 * We need to check the KDC and ticket signatures, fetching the
625 * correct key based on the enctype.
627 if (local_tgs_rodc_id
!= 0) {
629 * If we are an RODC, and we are not the KDC that signed
630 * the evidence ticket, then we need to proxy the
633 if (local_tgs_rodc_id
!= pac_kdc_signature_rodc_id
) {
634 return HDB_ERR_NOT_FOUND_HERE
;
638 * If we are a DC, the ticket may have been signed by a
639 * different KDC than the one that issued the header
642 if (pac_kdc_signature_rodc_id
!= header_ticket_rodc_id
) {
643 struct sdb_entry signing_krbtgt_sdb
;
646 * Fetch our key from the database. To support
647 * key rollover, we're going to need to try
648 * multiple keys by trial and error. For now,
649 * krbtgt keys aren't assumed to change.
651 ret
= samba_kdc_fetch(context
,
652 krbtgt_skdc_entry
->kdc_db_ctx
,
654 SDB_F_GET_KRBTGT
| SDB_F_RODC_NUMBER_SPECIFIED
| SDB_F_CANON
,
655 ((uint32_t)pac_kdc_signature_rodc_id
) << 16,
656 &signing_krbtgt_sdb
);
661 ret
= sdb_entry_to_hdb_entry(context
,
663 &signing_krbtgt_hdb
);
664 sdb_entry_free(&signing_krbtgt_sdb
);
670 * Replace the krbtgt entry with our own entry
671 * for further processing.
673 krbtgt
= &signing_krbtgt_hdb
;
676 } else if (!krbtgt_skdc_entry
->is_trust
) {
678 * We expect to have received a TGT, so check that we haven't
679 * been given a kpasswd ticket instead. We don't need to do this
680 * check for an incoming trust, as they use a different secret
681 * and can't be confused with a normal TGT.
684 struct timeval now
= krb5_kdc_get_time();
687 * Check if the ticket is in the last two minutes of its
690 KerberosTime lifetime
= rk_time_sub(ticket
->endtime
, now
.tv_sec
);
691 if (lifetime
<= CHANGEPW_LIFETIME
) {
693 * This ticket has at most two minutes left to live. It
694 * may be a kpasswd ticket rather than a TGT, so don't
697 kdc_audit_addreason((kdc_request_t
)r
,
698 "Ticket is not a ticket-granting ticket");
699 return KRB5KRB_AP_ERR_TKT_EXPIRED
;
703 ret
= samba_wdc_verify_pac2(r
,
710 if (krbtgt
== &signing_krbtgt_hdb
) {
711 hdb_free_entry(context
, config
->db
[0], &signing_krbtgt_hdb
);
717 static char *get_netbios_name(TALLOC_CTX
*mem_ctx
, HostAddresses
*addrs
)
719 char *nb_name
= NULL
;
723 for (i
= 0; addrs
&& i
< addrs
->len
; i
++) {
724 if (addrs
->val
[i
].addr_type
!= KRB5_ADDRESS_NETBIOS
) {
727 len
= MIN(addrs
->val
[i
].address
.length
, 15);
728 nb_name
= talloc_strndup(mem_ctx
,
729 addrs
->val
[i
].address
.data
, len
);
735 if ((nb_name
== NULL
) || (nb_name
[0] == '\0')) {
739 /* Strip space padding */
740 for (len
= strlen(nb_name
) - 1;
741 (len
> 0) && (nb_name
[len
] == ' ');
749 static krb5_error_code
samba_wdc_check_client_access(void *priv
,
752 krb5_context context
= kdc_request_get_context((kdc_request_t
)r
);
753 TALLOC_CTX
*tmp_ctx
= NULL
;
754 const hdb_entry
*client
= NULL
;
755 struct samba_kdc_entry
*kdc_entry
;
756 struct samba_kdc_entry_pac device
= {};
757 struct authn_audit_info
*client_audit_info
= NULL
;
758 bool password_change
;
761 NTSTATUS check_device_status
= NT_STATUS_OK
;
762 krb5_error_code ret
= 0;
764 client
= kdc_request_get_client(r
);
766 tmp_ctx
= talloc_named(client
->context
, 0, "samba_wdc_check_client_access");
767 if (tmp_ctx
== NULL
) {
771 kdc_entry
= talloc_get_type_abort(client
->context
, struct samba_kdc_entry
);
773 device
= samba_kdc_get_device_pac(r
);
775 ret
= samba_kdc_check_device(tmp_ctx
,
777 kdc_entry
->kdc_db_ctx
->samdb
,
778 kdc_entry
->kdc_db_ctx
->lp_ctx
,
780 kdc_entry
->client_policy
,
782 &check_device_status
);
783 if (client_audit_info
!= NULL
) {
784 krb5_error_code ret2
;
786 ret2
= hdb_samba4_set_steal_client_audit_info(r
, client_audit_info
);
791 kdc_entry
->reject_status
= check_device_status
;
792 if (!NT_STATUS_IS_OK(check_device_status
)) {
793 krb5_error_code ret2
;
796 * Add the NTSTATUS to the request so we can return it in the
797 * ‘e-data’ field later.
799 ret2
= hdb_samba4_set_ntstatus(r
, check_device_status
, ret
);
807 * As we didn’t get far enough to check the server policy, only
808 * the client policy will be referenced in the authentication
812 talloc_free(tmp_ctx
);
816 workstation
= get_netbios_name(tmp_ctx
,
817 kdc_request_get_req(r
)->req_body
.addresses
);
818 password_change
= (kdc_request_get_server(r
) && kdc_request_get_server(r
)->flags
.change_pw
);
820 nt_status
= samba_kdc_check_client_access(kdc_entry
,
821 kdc_request_get_cname((kdc_request_t
)r
),
825 kdc_entry
->reject_status
= nt_status
;
826 if (!NT_STATUS_IS_OK(nt_status
)) {
827 krb5_error_code ret2
;
829 if (NT_STATUS_EQUAL(nt_status
, NT_STATUS_NO_MEMORY
)) {
830 talloc_free(tmp_ctx
);
834 ret
= samba_kdc_map_policy_err(nt_status
);
837 * Add the NTSTATUS to the request so we can return it in the
838 * ‘e-data’ field later.
840 ret2
= hdb_samba4_set_ntstatus(r
, nt_status
, ret
);
845 talloc_free(tmp_ctx
);
849 /* Now do the standard Heimdal check */
850 talloc_free(tmp_ctx
);
851 return KRB5_PLUGIN_NO_HANDLE
;
854 /* this function allocates 'data' using malloc.
855 * The caller is responsible for freeing it */
856 static krb5_error_code
samba_kdc_build_supported_etypes(uint32_t supported_etypes
,
859 e_data
->data
= malloc(4);
860 if (e_data
->data
== NULL
) {
865 PUSH_LE_U32(e_data
->data
, 0, supported_etypes
);
870 static krb5_error_code
samba_wdc_finalize_reply(void *priv
,
873 struct samba_kdc_entry
*server_kdc_entry
;
874 uint32_t supported_enctypes
;
876 server_kdc_entry
= talloc_get_type(kdc_request_get_server(r
)->context
, struct samba_kdc_entry
);
879 * If the canonicalize flag is set, add PA-SUPPORTED-ENCTYPES padata
880 * type to indicate what encryption types the server supports.
882 supported_enctypes
= server_kdc_entry
->supported_enctypes
;
883 if (kdc_request_get_req(r
)->req_body
.kdc_options
.canonicalize
&& supported_enctypes
!= 0) {
888 ret
= samba_kdc_build_supported_etypes(supported_enctypes
, &md
.padata_value
);
893 md
.padata_type
= KRB5_PADATA_SUPPORTED_ETYPES
;
895 ret
= kdc_request_add_encrypted_padata(r
, &md
);
898 * So we do not leak the allocated
899 * memory on md in the error case
901 krb5_data_free(&md
.padata_value
);
908 static krb5_error_code
samba_wdc_plugin_init(krb5_context context
, void **ptr
)
914 static void samba_wdc_plugin_fini(void *ptr
)
919 static krb5_error_code
samba_wdc_referral_policy(void *priv
,
922 return kdc_request_get_error_code((kdc_request_t
)r
);
925 struct krb5plugin_kdc_ftable kdc_plugin_table
= {
926 .minor_version
= KRB5_PLUGIN_KDC_VERSION_11
,
927 .init
= samba_wdc_plugin_init
,
928 .fini
= samba_wdc_plugin_fini
,
929 .pac_verify
= samba_wdc_verify_pac
,
930 .pac_update
= samba_wdc_reget_pac
,
931 .client_access
= samba_wdc_check_client_access
,
932 .finalize_reply
= samba_wdc_finalize_reply
,
933 .pac_generate
= samba_wdc_get_pac
,
934 .referral_policy
= samba_wdc_referral_policy
,