2 * Copyright (c) 1999-2001, 2003, PADL Software Pty Ltd.
3 * Copyright (c) 2004-2009, Andrew Bartlett <abartlet@samba.org>.
4 * Copyright (c) 2004, Stefan Metzmacher <metze@samba.org>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of PADL Software nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 #include "kdc/kdc-glue.h"
37 #include "kdc/db-glue.h"
38 #include "kdc/pac-glue.h"
39 #include "auth/auth_sam.h"
40 #include "auth/common_auth.h"
41 #include "auth/authn_policy.h"
45 #include "dsdb/samdb/samdb.h"
46 #include "param/param.h"
47 #include "../lib/tsocket/tsocket.h"
48 #include "librpc/gen_ndr/ndr_winbind_c.h"
49 #include "lib/messaging/irpc.h"
51 #include <kdc-audit.h>
52 #include <kdc-plugin.h>
55 #define DBGC_CLASS DBGC_KERBEROS
57 static krb5_error_code
hdb_samba4_open(krb5_context context
, HDB
*db
, int flags
, mode_t mode
)
59 if (db
->hdb_master_key_set
) {
60 krb5_error_code ret
= HDB_ERR_NOENTRY
;
61 krb5_warnx(context
, "hdb_samba4_open: use of a master key incompatible with LDB\n");
62 krb5_set_error_message(context
, ret
, "hdb_samba4_open: use of a master key incompatible with LDB\n");
69 static krb5_error_code
hdb_samba4_close(krb5_context context
, HDB
*db
)
74 static krb5_error_code
hdb_samba4_lock(krb5_context context
, HDB
*db
, int operation
)
79 static krb5_error_code
hdb_samba4_unlock(krb5_context context
, HDB
*db
)
84 static krb5_error_code
hdb_samba4_rename(krb5_context context
, HDB
*db
, const char *new_name
)
86 return HDB_ERR_DB_INUSE
;
89 static krb5_error_code
hdb_samba4_store(krb5_context context
, HDB
*db
, unsigned flags
, hdb_entry
*entry
)
91 return HDB_ERR_DB_INUSE
;
95 * If we ever want kadmin to work fast, we might try and reopen the
98 static krb5_error_code
hdb_samba4_set_sync(krb5_context context
, struct HDB
*db
, int set_sync
)
103 static void hdb_samba4_free_entry_context(krb5_context context
, struct HDB
*db
, hdb_entry
*entry
)
106 * This function is now called for every HDB entry, not just those with
107 * 'context' set, so we have to check that the context is not NULL.
109 if (entry
->context
!= NULL
) {
110 struct samba_kdc_entry
*skdc_entry
=
111 talloc_get_type_abort(entry
->context
,
112 struct samba_kdc_entry
);
114 /* this function is called only from hdb_free_entry().
115 * Make sure we neutralize the destructor or we will
116 * get a double free later when hdb_free_entry() will
117 * try to call free_hdb_entry() */
118 entry
->context
= NULL
;
119 skdc_entry
->kdc_entry
= NULL
;
120 TALLOC_FREE(skdc_entry
);
124 static krb5_error_code
hdb_samba4_fetch_fast_cookie(krb5_context context
,
125 struct samba_kdc_db_context
*kdc_db_ctx
,
128 DBG_ERR("Looked up HDB entry for unsupported FX-COOKIE.\n");
129 return HDB_ERR_NOENTRY
;
132 static krb5_error_code
hdb_samba4_fetch_kvno(krb5_context context
, HDB
*db
,
133 krb5_const_principal principal
,
138 struct samba_kdc_db_context
*kdc_db_ctx
;
139 struct sdb_entry sentry
= {};
140 krb5_error_code code
, ret
;
143 kdc_db_ctx
= talloc_get_type_abort(db
->hdb_db
,
144 struct samba_kdc_db_context
);
146 if (flags
& HDB_F_GET_FAST_COOKIE
) {
147 return hdb_samba4_fetch_fast_cookie(context
,
152 sflags
= (flags
& SDB_F_HDB_MASK
);
154 ret
= samba_kdc_fetch(context
,
164 case SDB_ERR_WRONG_REALM
:
166 * If SDB_ERR_WRONG_REALM is returned we need to process the
167 * sdb_entry to fill the principal in the HDB entry.
169 code
= HDB_ERR_WRONG_REALM
;
171 case SDB_ERR_NOENTRY
:
172 return HDB_ERR_NOENTRY
;
173 case SDB_ERR_NOT_FOUND_HERE
:
174 return HDB_ERR_NOT_FOUND_HERE
;
179 ret
= sdb_entry_to_hdb_entry(context
, &sentry
, entry
);
180 sdb_entry_free(&sentry
);
189 static krb5_error_code
hdb_samba4_kpasswd_fetch_kvno(krb5_context context
, HDB
*db
,
190 krb5_const_principal _principal
,
195 struct samba_kdc_db_context
*kdc_db_ctx
= NULL
;
197 krb5_principal kpasswd_principal
= NULL
;
199 kdc_db_ctx
= talloc_get_type_abort(db
->hdb_db
,
200 struct samba_kdc_db_context
);
202 ret
= smb_krb5_make_principal(context
, &kpasswd_principal
,
203 lpcfg_realm(kdc_db_ctx
->lp_ctx
),
204 "kadmin", "changepw",
209 smb_krb5_principal_set_type(context
, kpasswd_principal
, KRB5_NT_SRV_INST
);
212 * For the kpasswd service, always ensure we get the latest kvno. This
213 * also means we (correctly) refuse RODC-issued tickets.
215 flags
&= ~HDB_F_KVNO_SPECIFIED
;
217 /* Don't bother looking up a client or krbtgt. */
218 flags
&= ~(HDB_F_GET_CLIENT
|HDB_F_GET_KRBTGT
);
220 ret
= hdb_samba4_fetch_kvno(context
, db
,
226 krb5_free_principal(context
, kpasswd_principal
);
230 static krb5_error_code
hdb_samba4_firstkey(krb5_context context
, HDB
*db
, unsigned flags
,
233 struct samba_kdc_db_context
*kdc_db_ctx
;
234 struct sdb_entry sentry
= {};
237 kdc_db_ctx
= talloc_get_type_abort(db
->hdb_db
,
238 struct samba_kdc_db_context
);
240 ret
= samba_kdc_firstkey(context
, kdc_db_ctx
, SDB_F_ADMIN_DATA
, &sentry
);
244 case SDB_ERR_WRONG_REALM
:
245 return HDB_ERR_WRONG_REALM
;
246 case SDB_ERR_NOENTRY
:
247 return HDB_ERR_NOENTRY
;
248 case SDB_ERR_NOT_FOUND_HERE
:
249 return HDB_ERR_NOT_FOUND_HERE
;
254 ret
= sdb_entry_to_hdb_entry(context
, &sentry
, entry
);
255 sdb_entry_free(&sentry
);
259 static krb5_error_code
hdb_samba4_nextkey(krb5_context context
, HDB
*db
, unsigned flags
,
262 struct samba_kdc_db_context
*kdc_db_ctx
;
263 struct sdb_entry sentry
= {};
266 kdc_db_ctx
= talloc_get_type_abort(db
->hdb_db
,
267 struct samba_kdc_db_context
);
269 ret
= samba_kdc_nextkey(context
, kdc_db_ctx
, SDB_F_ADMIN_DATA
, &sentry
);
273 case SDB_ERR_WRONG_REALM
:
274 return HDB_ERR_WRONG_REALM
;
275 case SDB_ERR_NOENTRY
:
276 return HDB_ERR_NOENTRY
;
277 case SDB_ERR_NOT_FOUND_HERE
:
278 return HDB_ERR_NOT_FOUND_HERE
;
283 ret
= sdb_entry_to_hdb_entry(context
, &sentry
, entry
);
284 sdb_entry_free(&sentry
);
288 static krb5_error_code
hdb_samba4_nextkey_panic(krb5_context context
, HDB
*db
,
292 DBG_ERR("Attempt to iterate kpasswd keytab => PANIC\n");
293 smb_panic("hdb_samba4_nextkey_panic: Attempt to iterate kpasswd keytab");
296 static krb5_error_code
hdb_samba4_destroy(krb5_context context
, HDB
*db
)
302 static krb5_error_code
303 hdb_samba4_check_constrained_delegation(krb5_context context
, HDB
*db
,
305 krb5_const_principal target_principal
)
307 struct samba_kdc_db_context
*kdc_db_ctx
= NULL
;
308 struct samba_kdc_entry
*skdc_entry
= NULL
;
310 kdc_db_ctx
= talloc_get_type_abort(db
->hdb_db
,
311 struct samba_kdc_db_context
);
312 skdc_entry
= talloc_get_type_abort(entry
->context
,
313 struct samba_kdc_entry
);
315 return samba_kdc_check_s4u2proxy(context
, kdc_db_ctx
,
320 static krb5_error_code
321 hdb_samba4_check_rbcd(krb5_context context
, HDB
*db
,
322 const hdb_entry
*client_krbtgt
,
323 const hdb_entry
*client
,
324 const hdb_entry
*device_krbtgt
,
325 const hdb_entry
*device
,
326 krb5_const_principal server_principal
,
327 krb5_const_pac header_pac
,
328 krb5_const_pac device_pac
,
329 const hdb_entry
*proxy
)
331 struct samba_kdc_db_context
*kdc_db_ctx
= NULL
;
332 struct samba_kdc_entry
*client_skdc_entry
= NULL
;
333 const struct samba_kdc_entry
*client_krbtgt_skdc_entry
= NULL
;
334 struct samba_kdc_entry
*proxy_skdc_entry
= NULL
;
335 const struct auth_user_info_dc
*client_info
= NULL
;
336 const struct auth_user_info_dc
*device_info
= NULL
;
337 struct samba_kdc_entry_pac client_pac_entry
= {};
338 struct auth_claims auth_claims
= {};
339 TALLOC_CTX
*mem_ctx
= NULL
;
340 krb5_error_code code
;
342 kdc_db_ctx
= talloc_get_type_abort(db
->hdb_db
,
343 struct samba_kdc_db_context
);
344 client_skdc_entry
= talloc_get_type_abort(client
->context
,
345 struct samba_kdc_entry
);
346 client_krbtgt_skdc_entry
= talloc_get_type_abort(client_krbtgt
->context
,
347 struct samba_kdc_entry
);
348 proxy_skdc_entry
= talloc_get_type_abort(proxy
->context
,
349 struct samba_kdc_entry
);
351 mem_ctx
= talloc_new(kdc_db_ctx
);
352 if (mem_ctx
== NULL
) {
356 client_pac_entry
= samba_kdc_entry_pac(header_pac
,
358 samba_kdc_entry_is_trust(client_krbtgt_skdc_entry
));
360 code
= samba_kdc_get_user_info_dc(mem_ctx
,
365 NULL
/* resource_groups_out */);
370 code
= samba_kdc_get_claims_data(mem_ctx
,
374 &auth_claims
.user_claims
);
379 if (device
!= NULL
) {
380 struct samba_kdc_entry
*device_skdc_entry
= NULL
;
381 const struct samba_kdc_entry
*device_krbtgt_skdc_entry
= NULL
;
382 struct samba_kdc_entry_pac device_pac_entry
= {};
384 device_skdc_entry
= talloc_get_type_abort(device
->context
,
385 struct samba_kdc_entry
);
387 if (device_krbtgt
!= NULL
) {
388 device_krbtgt_skdc_entry
= talloc_get_type_abort(device_krbtgt
->context
,
389 struct samba_kdc_entry
);
392 device_pac_entry
= samba_kdc_entry_pac(device_pac
,
394 samba_kdc_entry_is_trust(device_krbtgt_skdc_entry
));
396 code
= samba_kdc_get_user_info_dc(mem_ctx
,
401 NULL
/* resource_groups_out */);
406 code
= samba_kdc_get_claims_data(mem_ctx
,
410 &auth_claims
.device_claims
);
416 code
= samba_kdc_check_s4u2proxy_rbcd(context
,
425 talloc_free(mem_ctx
);
429 static krb5_error_code
430 hdb_samba4_check_pkinit_ms_upn_match(krb5_context context
, HDB
*db
,
432 krb5_const_principal certificate_principal
)
434 struct samba_kdc_db_context
*kdc_db_ctx
;
435 struct samba_kdc_entry
*skdc_entry
;
438 kdc_db_ctx
= talloc_get_type_abort(db
->hdb_db
,
439 struct samba_kdc_db_context
);
440 skdc_entry
= talloc_get_type_abort(entry
->context
,
441 struct samba_kdc_entry
);
443 ret
= samba_kdc_check_pkinit_ms_upn_match(context
, kdc_db_ctx
,
445 certificate_principal
);
449 case SDB_ERR_WRONG_REALM
:
450 ret
= HDB_ERR_WRONG_REALM
;
452 case SDB_ERR_NOENTRY
:
453 ret
= HDB_ERR_NOENTRY
;
455 case SDB_ERR_NOT_FOUND_HERE
:
456 ret
= HDB_ERR_NOT_FOUND_HERE
;
465 static krb5_error_code
466 hdb_samba4_check_client_matches_target_service(krb5_context context
, HDB
*db
,
467 hdb_entry
*client_entry
,
468 hdb_entry
*server_target_entry
)
470 struct samba_kdc_entry
*skdc_client_entry
471 = talloc_get_type_abort(client_entry
->context
,
472 struct samba_kdc_entry
);
473 struct samba_kdc_entry
*skdc_server_target_entry
474 = talloc_get_type_abort(server_target_entry
->context
,
475 struct samba_kdc_entry
);
477 return samba_kdc_check_client_matches_target_service(context
,
479 skdc_server_target_entry
);
482 static void reset_bad_password_netlogon(TALLOC_CTX
*mem_ctx
,
483 struct samba_kdc_db_context
*kdc_db_ctx
,
484 struct netr_SendToSamBase
*send_to_sam
)
486 struct dcerpc_binding_handle
*irpc_handle
;
487 struct winbind_SendToSam req
;
488 struct tevent_req
*subreq
= NULL
;
490 irpc_handle
= irpc_binding_handle_by_name(mem_ctx
, kdc_db_ctx
->msg_ctx
,
494 if (irpc_handle
== NULL
) {
495 DBG_ERR("No winbind_server running!\n");
499 req
.in
.message
= *send_to_sam
;
502 * This seem to rely on the current IRPC implementation,
503 * which delivers the message in the _send function.
505 * TODO: we need a ONE_WAY IRPC handle and register
506 * a callback and wait for it to be triggered!
508 subreq
= dcerpc_winbind_SendToSam_r_send(mem_ctx
, kdc_db_ctx
->ev_ctx
,
511 /* we aren't interested in a reply */
515 #define SAMBA_HDB_AUTHN_AUDIT_INFO_OBJ "samba:authn_audit_info_obj"
516 #define SAMBA_HDB_CLIENT_AUDIT_INFO "samba:client_audit_info"
517 #define SAMBA_HDB_SERVER_AUDIT_INFO "samba:server_audit_info"
519 #define SAMBA_HDB_NT_STATUS_OBJ "samba:nt_status_obj"
520 #define SAMBA_HDB_NT_STATUS "samba:nt_status"
522 struct hdb_audit_info_obj
{
523 struct authn_audit_info
*audit_info
;
526 static void hdb_audit_info_obj_dealloc(void *ptr
)
528 struct hdb_audit_info_obj
*audit_info_obj
= ptr
;
530 if (audit_info_obj
== NULL
) {
534 TALLOC_FREE(audit_info_obj
->audit_info
);
538 * Set talloc-allocated auditing information of the KDC request. On success,
539 * ‘audit_info’ is invalidated and may no longer be used by the caller.
541 static krb5_error_code
hdb_samba4_set_steal_audit_info(astgs_request_t r
,
543 struct authn_audit_info
*audit_info
)
545 struct hdb_audit_info_obj
*audit_info_obj
= NULL
;
547 audit_info_obj
= kdc_object_alloc(sizeof (*audit_info_obj
),
548 SAMBA_HDB_AUTHN_AUDIT_INFO_OBJ
,
549 hdb_audit_info_obj_dealloc
);
550 if (audit_info_obj
== NULL
) {
555 * Steal a handle to the audit information onto the NULL context —
556 * Heimdal will be responsible for the deallocation of the object.
558 audit_info_obj
->audit_info
= talloc_steal(NULL
, audit_info
);
560 heim_audit_setkv_object((heim_svc_req_desc
)r
, key
, audit_info_obj
);
561 heim_release(audit_info_obj
);
567 * Set talloc-allocated client auditing information of the KDC request. On
568 * success, ‘client_audit_info’ is invalidated and may no longer be used by the
571 krb5_error_code
hdb_samba4_set_steal_client_audit_info(astgs_request_t r
,
572 struct authn_audit_info
*client_audit_info
)
574 return hdb_samba4_set_steal_audit_info(r
,
575 SAMBA_HDB_CLIENT_AUDIT_INFO
,
579 static const struct authn_audit_info
*hdb_samba4_get_client_audit_info(hdb_request_t r
)
581 const struct hdb_audit_info_obj
*audit_info_obj
= NULL
;
583 audit_info_obj
= heim_audit_getkv((heim_svc_req_desc
)r
, SAMBA_HDB_CLIENT_AUDIT_INFO
);
584 if (audit_info_obj
== NULL
) {
588 return audit_info_obj
->audit_info
;
592 * Set talloc-allocated server auditing information of the KDC request. On
593 * success, ‘server_audit_info’ is invalidated and may no longer be used by the
596 krb5_error_code
hdb_samba4_set_steal_server_audit_info(astgs_request_t r
,
597 struct authn_audit_info
*server_audit_info
)
599 return hdb_samba4_set_steal_audit_info(r
,
600 SAMBA_HDB_SERVER_AUDIT_INFO
,
604 static const struct authn_audit_info
*hdb_samba4_get_server_audit_info(hdb_request_t r
)
606 const struct hdb_audit_info_obj
*audit_info_obj
= NULL
;
608 audit_info_obj
= heim_audit_getkv((heim_svc_req_desc
)r
, SAMBA_HDB_SERVER_AUDIT_INFO
);
609 if (audit_info_obj
== NULL
) {
613 return audit_info_obj
->audit_info
;
616 struct hdb_ntstatus_obj
{
618 krb5_error_code current_error
;
622 * Add an NTSTATUS code to a Kerberos request. ‘error’ is the error value we
623 * want to return to the client. When it comes time to generating the error
624 * request, we shall compare this error value to whatever error we are about to
625 * return; if the two match, we shall replace the ‘e-data’ field in the reply
626 * with the NTSTATUS code.
628 krb5_error_code
hdb_samba4_set_ntstatus(astgs_request_t r
,
629 const NTSTATUS status
,
630 const krb5_error_code error
)
632 struct hdb_ntstatus_obj
*status_obj
= NULL
;
634 status_obj
= kdc_object_alloc(sizeof (*status_obj
),
635 SAMBA_HDB_NT_STATUS_OBJ
,
637 if (status_obj
== NULL
) {
641 *status_obj
= (struct hdb_ntstatus_obj
) {
643 .current_error
= error
,
646 heim_audit_setkv_object((heim_svc_req_desc
)r
, SAMBA_HDB_NT_STATUS
, status_obj
);
647 heim_release(status_obj
);
652 static krb5_error_code
hdb_samba4_make_nt_status_edata(const NTSTATUS status
,
653 const uint32_t flags
,
654 krb5_data
*edata_out
)
656 const uint32_t status_code
= NT_STATUS_V(status
);
657 const uint32_t zero
= 0;
658 KERB_ERROR_DATA error_data
;
664 /* The raw KERB-ERR-TYPE-EXTENDED structure. */
667 PUSH_LE_U32(data
, 0, status_code
);
668 PUSH_LE_U32(data
, 4, zero
);
669 PUSH_LE_U32(data
, 8, flags
);
671 e_data
= (krb5_data
) {
673 .length
= sizeof(data
),
676 error_data
= (KERB_ERROR_DATA
) {
677 .data_type
= kERB_ERR_TYPE_EXTENDED
,
678 .data_value
= &e_data
,
681 ASN1_MALLOC_ENCODE(KERB_ERROR_DATA
,
682 edata_out
->data
, edata_out
->length
,
688 if (size
!= edata_out
->length
) {
689 /* Internal ASN.1 encoder error */
690 krb5_data_free(edata_out
);
691 return KRB5KRB_ERR_GENERIC
;
697 static krb5_error_code
hdb_samba4_set_edata_from_ntstatus(hdb_request_t r
, const NTSTATUS status
)
699 const KDC_REQ
*req
= kdc_request_get_req((astgs_request_t
)r
);
700 krb5_error_code ret
= 0;
704 if (req
->msg_type
== krb_tgs_req
) {
705 /* This flag is used to indicate a TGS-REQ. */
709 ret
= hdb_samba4_make_nt_status_edata(status
, flags
, &e_data
);
714 ret
= kdc_request_set_e_data((astgs_request_t
)r
, e_data
);
716 krb5_data_free(&e_data
);
722 static NTSTATUS
hdb_samba4_get_ntstatus(hdb_request_t r
)
724 struct hdb_ntstatus_obj
*status_obj
= NULL
;
726 status_obj
= heim_audit_getkv((heim_svc_req_desc
)r
, SAMBA_HDB_NT_STATUS
);
727 if (status_obj
== NULL
) {
731 if (r
->error_code
!= status_obj
->current_error
) {
733 * The error code has changed from what we expect. Consider the
734 * NTSTATUS to be invalidated.
739 return status_obj
->status
;
742 static krb5_error_code
hdb_samba4_tgs_audit(const struct samba_kdc_db_context
*kdc_db_ctx
,
743 const hdb_entry
*entry
,
746 TALLOC_CTX
*frame
= talloc_stackframe();
747 const struct authn_audit_info
*server_audit_info
= NULL
;
748 struct tsocket_address
*remote_host
= NULL
;
749 struct samba_kdc_entry
*client_entry
= NULL
;
750 struct dom_sid sid_buf
= {};
751 const char *account_name
= NULL
;
752 const char *domain_name
= NULL
;
753 const struct dom_sid
*sid
= NULL
;
754 size_t sa_socklen
= 0;
755 NTSTATUS auth_status
= NT_STATUS_OK
;
756 krb5_error_code ret
= 0;
757 krb5_error_code final_ret
= 0;
759 /* Have we got a status code indicating an error? */
760 auth_status
= hdb_samba4_get_ntstatus(r
);
761 if (!NT_STATUS_IS_OK(auth_status
)) {
763 * Include this status code in the ‘e-data’ field of the reply.
765 ret
= hdb_samba4_set_edata_from_ntstatus(r
, auth_status
);
769 } else if (entry
== NULL
) {
770 auth_status
= NT_STATUS_NO_SUCH_USER
;
771 } else if (r
->error_code
) {
773 * Don’t include a status code in the reply. Just log the
774 * request as being unsuccessful.
776 auth_status
= NT_STATUS_UNSUCCESSFUL
;
779 switch (r
->addr
->sa_family
) {
781 sa_socklen
= sizeof(struct sockaddr_in
);
785 sa_socklen
= sizeof(struct sockaddr_in6
);
790 ret
= tsocket_address_bsd_from_sockaddr(frame
, r
->addr
,
795 /* Ignore the error. */
798 server_audit_info
= hdb_samba4_get_server_audit_info(r
);
801 client_entry
= talloc_get_type_abort(entry
->context
,
802 struct samba_kdc_entry
);
804 ret
= samdb_result_dom_sid_buf(client_entry
->msg
, "objectSid", &sid_buf
);
806 /* Ignore the error. */
811 account_name
= ldb_msg_find_attr_as_string(client_entry
->msg
, "sAMAccountName", NULL
);
812 domain_name
= lpcfg_sam_name(kdc_db_ctx
->lp_ctx
);
815 log_authz_event(kdc_db_ctx
->msg_ctx
,
821 "TGS-REQ with Ticket-Granting Ticket",
825 lpcfg_netbios_name(kdc_db_ctx
->lp_ctx
),
831 r
->error_code
= final_ret
;
836 static krb5_error_code
hdb_samba4_audit(krb5_context context
,
841 struct samba_kdc_db_context
*kdc_db_ctx
= talloc_get_type_abort(db
->hdb_db
,
842 struct samba_kdc_db_context
);
843 struct ldb_dn
*domain_dn
= ldb_get_default_basedn(kdc_db_ctx
->samdb
);
844 heim_object_t auth_details_obj
= NULL
;
845 const char *auth_details
= NULL
;
846 char *etype_str
= NULL
;
847 heim_object_t hdb_auth_status_obj
= NULL
;
849 heim_object_t pa_type_obj
= NULL
;
850 const char *pa_type
= NULL
;
851 struct auth_usersupplied_info ui
;
852 size_t sa_socklen
= 0;
853 const KDC_REQ
*req
= kdc_request_get_req((astgs_request_t
)r
);
854 krb5_error_code final_ret
= 0;
855 NTSTATUS edata_status
;
857 if (req
->msg_type
== krb_tgs_req
) {
858 return hdb_samba4_tgs_audit(kdc_db_ctx
, entry
, r
);
861 if (r
->error_code
== KRB5KDC_ERR_PREAUTH_REQUIRED
) {
862 /* Let’s not log PREAUTH_REQUIRED errors. */
866 edata_status
= hdb_samba4_get_ntstatus(r
);
868 hdb_auth_status_obj
= heim_audit_getkv((heim_svc_req_desc
)r
, KDC_REQUEST_KV_AUTH_EVENT
);
869 if (hdb_auth_status_obj
== NULL
) {
870 /* No status code found, so just return. */
874 hdb_auth_status
= heim_number_get_int(hdb_auth_status_obj
);
876 pa_type_obj
= heim_audit_getkv((heim_svc_req_desc
)r
, KDC_REQUEST_KV_PA_NAME
);
877 if (pa_type_obj
!= NULL
) {
878 pa_type
= heim_string_get_utf8(pa_type_obj
);
881 auth_details_obj
= heim_audit_getkv((heim_svc_req_desc
)r
, KDC_REQUEST_KV_PKINIT_CLIENT_CERT
);
882 if (auth_details_obj
!= NULL
) {
883 auth_details
= heim_string_get_utf8(auth_details_obj
);
885 auth_details_obj
= heim_audit_getkv((heim_svc_req_desc
)r
, KDC_REQUEST_KV_GSS_INITIATOR
);
886 if (auth_details_obj
!= NULL
) {
887 auth_details
= heim_string_get_utf8(auth_details_obj
);
889 heim_object_t etype_obj
= heim_audit_getkv((heim_svc_req_desc
)r
, KDC_REQUEST_KV_PA_ETYPE
);
890 if (etype_obj
!= NULL
) {
891 int etype
= heim_number_get_int(etype_obj
);
893 krb5_error_code ret
= krb5_enctype_to_string(r
->context
, etype
, &etype_str
);
895 auth_details
= etype_str
;
897 auth_details
= "unknown enctype";
904 * Forcing this via the NTLM auth structure is not ideal, but
905 * it is the most practical option right now, and ensures the
906 * logs are consistent, even if some elements are always NULL.
908 ui
= (struct auth_usersupplied_info
) {
911 .account_name
= r
->cname
,
914 .service_description
= "Kerberos KDC",
915 .auth_description
= "Unknown Auth Description",
916 .password_type
= auth_details
,
917 .logon_id
= generate_random_u64(),
920 switch (r
->addr
->sa_family
) {
922 sa_socklen
= sizeof(struct sockaddr_in
);
926 sa_socklen
= sizeof(struct sockaddr_in6
);
931 switch (hdb_auth_status
) {
934 TALLOC_CTX
*frame
= talloc_stackframe();
935 struct samba_kdc_entry
*p
= talloc_get_type_abort(entry
->context
,
936 struct samba_kdc_entry
);
938 = samdb_result_dom_sid(frame
, p
->msg
, "objectSid");
939 const char *account_name
940 = ldb_msg_find_attr_as_string(p
->msg
, "sAMAccountName", NULL
);
941 const char *domain_name
= lpcfg_sam_name(p
->kdc_db_ctx
->lp_ctx
);
942 struct tsocket_address
*remote_host
;
943 const char *auth_description
= NULL
;
944 const struct authn_audit_info
*client_audit_info
= NULL
;
945 const struct authn_audit_info
*server_audit_info
= NULL
;
948 bool rwdc_fallback
= false;
950 ret
= tsocket_address_bsd_from_sockaddr(frame
, r
->addr
,
954 ui
.remote_host
= NULL
;
956 ui
.remote_host
= remote_host
;
959 ui
.mapped
.account_name
= account_name
;
960 ui
.mapped
.domain_name
= domain_name
;
962 if (pa_type
!= NULL
) {
963 auth_description
= talloc_asprintf(frame
,
964 "%s Pre-authentication",
966 if (auth_description
== NULL
) {
967 auth_description
= pa_type
;
970 auth_description
= "Unknown Pre-authentication";
972 ui
.auth_description
= auth_description
;
974 if (hdb_auth_status
== KDC_AUTH_EVENT_CLIENT_AUTHORIZED
) {
975 struct netr_SendToSamBase
*send_to_sam
= NULL
;
978 * TODO: We could log the AS-REQ authorization success here as
979 * well. However before we do that, we need to pass
980 * in the PAC here or re-calculate it.
982 status
= authsam_logon_success_accounting(kdc_db_ctx
->samdb
, p
->msg
,
983 domain_dn
, true, frame
, &send_to_sam
);
984 if (NT_STATUS_EQUAL(status
, NT_STATUS_ACCOUNT_LOCKED_OUT
)) {
985 edata_status
= status
;
987 r
->error_code
= final_ret
= KRB5KDC_ERR_CLIENT_REVOKED
;
988 rwdc_fallback
= kdc_db_ctx
->rodc
;
989 } else if (!NT_STATUS_IS_OK(status
)) {
990 r
->error_code
= final_ret
= KRB5KDC_ERR_CLIENT_REVOKED
;
991 rwdc_fallback
= kdc_db_ctx
->rodc
;
993 if (r
->error_code
== KRB5KDC_ERR_NEVER_VALID
) {
994 edata_status
= status
= NT_STATUS_TIME_DIFFERENCE_AT_DC
;
996 status
= krb5_to_nt_status(r
->error_code
);
999 if (kdc_db_ctx
->rodc
&& send_to_sam
!= NULL
) {
1000 reset_bad_password_netlogon(frame
, kdc_db_ctx
, send_to_sam
);
1004 /* This is the final success */
1005 } else if (hdb_auth_status
== KDC_AUTH_EVENT_VALIDATED_LONG_TERM_KEY
) {
1007 * This was only a pre-authentication success,
1008 * but we didn't reach the final
1009 * KDC_AUTH_EVENT_CLIENT_AUTHORIZED,
1010 * so consult the error code.
1012 if (r
->error_code
== 0) {
1013 DBG_ERR("ERROR: VALIDATED_LONG_TERM_KEY "
1014 "with error=0 => INTERNAL_ERROR\n");
1015 status
= NT_STATUS_INTERNAL_ERROR
;
1016 r
->error_code
= final_ret
= KRB5KRB_ERR_GENERIC
;
1017 } else if (!NT_STATUS_IS_OK(p
->reject_status
)) {
1018 status
= p
->reject_status
;
1020 status
= krb5_to_nt_status(r
->error_code
);
1022 } else if (hdb_auth_status
== KDC_AUTH_EVENT_PREAUTH_SUCCEEDED
) {
1024 * This was only a pre-authentication success,
1025 * but we didn't reach the final
1026 * KDC_AUTH_EVENT_CLIENT_AUTHORIZED,
1027 * so consult the error code.
1029 if (r
->error_code
== 0) {
1030 DBG_ERR("ERROR: PREAUTH_SUCCEEDED "
1031 "with error=0 => INTERNAL_ERROR\n");
1032 status
= NT_STATUS_INTERNAL_ERROR
;
1033 r
->error_code
= final_ret
= KRB5KRB_ERR_GENERIC
;
1034 } else if (!NT_STATUS_IS_OK(p
->reject_status
)) {
1035 status
= p
->reject_status
;
1037 status
= krb5_to_nt_status(r
->error_code
);
1039 } else if (hdb_auth_status
== KDC_AUTH_EVENT_CLIENT_FOUND
) {
1041 * We found the client principal,
1042 * but we didn’t reach the final
1043 * KDC_AUTH_EVENT_CLIENT_AUTHORIZED,
1044 * so consult the error code.
1046 if (r
->error_code
== 0) {
1047 DBG_ERR("ERROR: CLIENT_FOUND "
1048 "with error=0 => INTERNAL_ERROR\n");
1049 status
= NT_STATUS_INTERNAL_ERROR
;
1050 r
->error_code
= final_ret
= KRB5KRB_ERR_GENERIC
;
1051 } else if (!NT_STATUS_IS_OK(p
->reject_status
)) {
1052 status
= p
->reject_status
;
1054 status
= krb5_to_nt_status(r
->error_code
);
1056 } else if (hdb_auth_status
== KDC_AUTH_EVENT_CLIENT_TIME_SKEW
) {
1057 status
= NT_STATUS_TIME_DIFFERENCE_AT_DC
;
1058 } else if (hdb_auth_status
== KDC_AUTH_EVENT_WRONG_LONG_TERM_KEY
) {
1059 status
= authsam_update_bad_pwd_count(kdc_db_ctx
->samdb
, p
->msg
, domain_dn
);
1060 if (NT_STATUS_EQUAL(status
, NT_STATUS_ACCOUNT_LOCKED_OUT
)) {
1061 edata_status
= status
;
1063 r
->error_code
= final_ret
= KRB5KDC_ERR_CLIENT_REVOKED
;
1065 status
= NT_STATUS_WRONG_PASSWORD
;
1067 rwdc_fallback
= kdc_db_ctx
->rodc
;
1068 } else if (hdb_auth_status
== KDC_AUTH_EVENT_HISTORIC_LONG_TERM_KEY
) {
1070 * The pre-authentication succeeds with a password
1071 * from the password history, so we don't
1072 * update the badPwdCount, but still return
1073 * PREAUTH_FAILED and need to forward to
1074 * a RWDC in order to produce an authoritative
1075 * response for the client.
1077 status
= NT_STATUS_WRONG_PASSWORD
;
1078 rwdc_fallback
= kdc_db_ctx
->rodc
;
1079 } else if (hdb_auth_status
== KDC_AUTH_EVENT_CLIENT_LOCKED_OUT
) {
1080 edata_status
= status
= NT_STATUS_ACCOUNT_LOCKED_OUT
;
1081 rwdc_fallback
= kdc_db_ctx
->rodc
;
1082 } else if (hdb_auth_status
== KDC_AUTH_EVENT_CLIENT_NAME_UNAUTHORIZED
) {
1083 if (pa_type
!= NULL
&& strncmp(pa_type
, "PK-INIT", strlen("PK-INIT")) == 0) {
1084 status
= NT_STATUS_PKINIT_NAME_MISMATCH
;
1086 status
= NT_STATUS_ACCOUNT_RESTRICTION
;
1088 rwdc_fallback
= kdc_db_ctx
->rodc
;
1089 } else if (hdb_auth_status
== KDC_AUTH_EVENT_PREAUTH_FAILED
) {
1090 if (pa_type
!= NULL
&& strncmp(pa_type
, "PK-INIT", strlen("PK-INIT")) == 0) {
1091 status
= NT_STATUS_PKINIT_FAILURE
;
1093 status
= NT_STATUS_GENERIC_COMMAND_FAILED
;
1095 rwdc_fallback
= kdc_db_ctx
->rodc
;
1097 DBG_ERR("Unhandled hdb_auth_status=%d => INTERNAL_ERROR\n",
1099 status
= NT_STATUS_INTERNAL_ERROR
;
1100 r
->error_code
= final_ret
= KRB5KRB_ERR_GENERIC
;
1103 if (!NT_STATUS_IS_OK(edata_status
)) {
1104 krb5_error_code code
;
1106 code
= hdb_samba4_set_edata_from_ntstatus(r
, edata_status
);
1108 r
->error_code
= final_ret
= code
;
1112 if (rwdc_fallback
) {
1114 * Forward the request to an RWDC in order
1115 * to give an authoritative answer to the client.
1117 auth_description
= talloc_asprintf(frame
,
1118 "%s,Forward-To-RWDC",
1119 ui
.auth_description
);
1120 if (auth_description
!= NULL
) {
1121 ui
.auth_description
= auth_description
;
1123 final_ret
= HDB_ERR_NOT_FOUND_HERE
;
1126 client_audit_info
= hdb_samba4_get_client_audit_info(r
);
1127 server_audit_info
= hdb_samba4_get_server_audit_info(r
);
1129 log_authentication_event(kdc_db_ctx
->msg_ctx
,
1139 if (final_ret
== KRB5KRB_ERR_GENERIC
&& socket_wrapper_enabled()) {
1141 * If we're running under make test
1144 DBG_ERR("Unexpected situation => PANIC\n");
1145 smb_panic("hdb_samba4_audit: Unexpected situation");
1150 case KDC_AUTH_EVENT_CLIENT_UNKNOWN
:
1152 struct tsocket_address
*remote_host
;
1154 TALLOC_CTX
*frame
= talloc_stackframe();
1155 ret
= tsocket_address_bsd_from_sockaddr(frame
, r
->addr
,
1159 ui
.remote_host
= NULL
;
1161 ui
.remote_host
= remote_host
;
1164 if (pa_type
== NULL
) {
1168 ui
.auth_description
= pa_type
;
1170 /* Note this is not forwarded to an RWDC */
1172 log_authentication_event(kdc_db_ctx
->msg_ctx
,
1176 NT_STATUS_NO_SUCH_USER
,
1179 NULL
/* client_audit_info */,
1180 NULL
/* server_audit_info */);
1191 /* This interface is to be called by the KDC and libnet_keytab_dump,
1192 * which is expecting Samba calling conventions.
1193 * It is also called by a wrapper (hdb_samba4_create) from the
1194 * kpasswdd -> krb5 -> keytab_hdb -> hdb code */
1196 NTSTATUS
hdb_samba4_create_kdc(struct samba_kdc_base_context
*base_ctx
,
1197 krb5_context context
, struct HDB
**db
,
1198 struct samba_kdc_db_context
**kdc_db_ctx
)
1202 if (hdb_interface_version
!= HDB_INTERFACE_VERSION
) {
1203 krb5_set_error_message(context
, EINVAL
, "Heimdal HDB interface version mismatch between build-time and run-time libraries!");
1204 return NT_STATUS_ERROR_DS_INCOMPATIBLE_VERSION
;
1207 *db
= talloc_zero(base_ctx
, HDB
);
1209 krb5_set_error_message(context
, ENOMEM
, "talloc_zero: out of memory");
1210 return NT_STATUS_NO_MEMORY
;
1213 (*db
)->hdb_master_key_set
= 0;
1214 (*db
)->hdb_db
= NULL
;
1215 (*db
)->hdb_capability_flags
= HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL
;
1217 nt_status
= samba_kdc_setup_db_ctx(*db
, base_ctx
, kdc_db_ctx
);
1218 if (!NT_STATUS_IS_OK(nt_status
)) {
1222 (*db
)->hdb_db
= *kdc_db_ctx
;
1224 (*db
)->hdb_dbc
= NULL
;
1225 (*db
)->hdb_open
= hdb_samba4_open
;
1226 (*db
)->hdb_close
= hdb_samba4_close
;
1227 (*db
)->hdb_free_entry_context
= hdb_samba4_free_entry_context
;
1228 (*db
)->hdb_fetch_kvno
= hdb_samba4_fetch_kvno
;
1229 (*db
)->hdb_store
= hdb_samba4_store
;
1230 (*db
)->hdb_firstkey
= hdb_samba4_firstkey
;
1231 (*db
)->hdb_nextkey
= hdb_samba4_nextkey
;
1232 (*db
)->hdb_lock
= hdb_samba4_lock
;
1233 (*db
)->hdb_unlock
= hdb_samba4_unlock
;
1234 (*db
)->hdb_set_sync
= hdb_samba4_set_sync
;
1235 (*db
)->hdb_rename
= hdb_samba4_rename
;
1236 /* we don't implement these, as we are not a lockable database */
1237 (*db
)->hdb__get
= NULL
;
1238 (*db
)->hdb__put
= NULL
;
1239 /* kadmin should not be used for deletes - use other tools instead */
1240 (*db
)->hdb__del
= NULL
;
1241 (*db
)->hdb_destroy
= hdb_samba4_destroy
;
1243 (*db
)->hdb_audit
= hdb_samba4_audit
;
1244 (*db
)->hdb_check_constrained_delegation
= hdb_samba4_check_constrained_delegation
;
1245 (*db
)->hdb_check_rbcd
= hdb_samba4_check_rbcd
;
1246 (*db
)->hdb_check_pkinit_ms_upn_match
= hdb_samba4_check_pkinit_ms_upn_match
;
1247 (*db
)->hdb_check_client_matches_target_service
= hdb_samba4_check_client_matches_target_service
;
1249 return NT_STATUS_OK
;
1252 NTSTATUS
hdb_samba4_kpasswd_create_kdc(struct samba_kdc_base_context
*base_ctx
,
1253 krb5_context context
, struct HDB
**db
)
1257 /* This is only used in other callers */
1258 struct samba_kdc_db_context
*kdc_db_ctx
= NULL
;
1260 nt_status
= hdb_samba4_create_kdc(base_ctx
, context
, db
, &kdc_db_ctx
);
1261 if (!NT_STATUS_IS_OK(nt_status
)) {
1265 (*db
)->hdb_fetch_kvno
= hdb_samba4_kpasswd_fetch_kvno
;
1266 (*db
)->hdb_firstkey
= hdb_samba4_nextkey_panic
;
1267 (*db
)->hdb_nextkey
= hdb_samba4_nextkey_panic
;
1269 return NT_STATUS_OK
;