s3:script: Replace --merge by --merge-by-timestamp in samba-log-parser
[Samba.git] / source4 / kdc / hdb-samba4.c
blob482b546d019e6b298d949a18cf0f1f185db2b804
1 /*
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>
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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
32 * SUCH DAMAGE.
35 #include "includes.h"
36 #include "kdc/kdc-glue.h"
37 #include "kdc/db-glue.h"
38 #include "auth/auth_sam.h"
39 #include "auth/common_auth.h"
40 #include "auth/authn_policy.h"
41 #include <ldb.h>
42 #include "sdb.h"
43 #include "sdb_hdb.h"
44 #include "dsdb/samdb/samdb.h"
45 #include "param/param.h"
46 #include "../lib/tsocket/tsocket.h"
47 #include "librpc/gen_ndr/ndr_winbind_c.h"
48 #include "lib/messaging/irpc.h"
49 #include "hdb.h"
50 #include <kdc-audit.h>
51 #include <kdc-plugin.h>
53 #undef DBGC_CLASS
54 #define DBGC_CLASS DBGC_KERBEROS
56 static krb5_error_code hdb_samba4_open(krb5_context context, HDB *db, int flags, mode_t mode)
58 if (db->hdb_master_key_set) {
59 krb5_error_code ret = HDB_ERR_NOENTRY;
60 krb5_warnx(context, "hdb_samba4_open: use of a master key incompatible with LDB\n");
61 krb5_set_error_message(context, ret, "hdb_samba4_open: use of a master key incompatible with LDB\n");
62 return ret;
65 return 0;
68 static krb5_error_code hdb_samba4_close(krb5_context context, HDB *db)
70 return 0;
73 static krb5_error_code hdb_samba4_lock(krb5_context context, HDB *db, int operation)
75 return 0;
78 static krb5_error_code hdb_samba4_unlock(krb5_context context, HDB *db)
80 return 0;
83 static krb5_error_code hdb_samba4_rename(krb5_context context, HDB *db, const char *new_name)
85 return HDB_ERR_DB_INUSE;
88 static krb5_error_code hdb_samba4_store(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry)
90 return HDB_ERR_DB_INUSE;
94 * If we ever want kadmin to work fast, we might try and reopen the
95 * ldb with LDB_NOSYNC
97 static krb5_error_code hdb_samba4_set_sync(krb5_context context, struct HDB *db, int set_sync)
99 return 0;
102 static void hdb_samba4_free_entry_context(krb5_context context, struct HDB *db, hdb_entry *entry)
105 * This function is now called for every HDB entry, not just those with
106 * 'context' set, so we have to check that the context is not NULL.
108 if (entry->context != NULL) {
109 struct samba_kdc_entry *skdc_entry =
110 talloc_get_type_abort(entry->context,
111 struct samba_kdc_entry);
113 /* this function is called only from hdb_free_entry().
114 * Make sure we neutralize the destructor or we will
115 * get a double free later when hdb_free_entry() will
116 * try to call free_hdb_entry() */
117 entry->context = NULL;
118 skdc_entry->kdc_entry = NULL;
119 TALLOC_FREE(skdc_entry);
123 static krb5_error_code hdb_samba4_fetch_fast_cookie(krb5_context context,
124 struct samba_kdc_db_context *kdc_db_ctx,
125 hdb_entry *entry)
127 DBG_ERR("Looked up HDB entry for unsupported FX-COOKIE.\n");
128 return HDB_ERR_NOENTRY;
131 static krb5_error_code hdb_samba4_fetch_kvno(krb5_context context, HDB *db,
132 krb5_const_principal principal,
133 unsigned flags,
134 krb5_kvno kvno,
135 hdb_entry *entry)
137 struct samba_kdc_db_context *kdc_db_ctx;
138 struct sdb_entry sentry = {};
139 krb5_error_code code, ret;
140 uint32_t sflags;
142 kdc_db_ctx = talloc_get_type_abort(db->hdb_db,
143 struct samba_kdc_db_context);
145 if (flags & HDB_F_GET_FAST_COOKIE) {
146 return hdb_samba4_fetch_fast_cookie(context,
147 kdc_db_ctx,
148 entry);
151 sflags = (flags & SDB_F_HDB_MASK);
153 ret = samba_kdc_fetch(context,
154 kdc_db_ctx,
155 principal,
156 sflags,
157 kvno,
158 &sentry);
159 switch (ret) {
160 case 0:
161 code = 0;
162 break;
163 case SDB_ERR_WRONG_REALM:
165 * If SDB_ERR_WRONG_REALM is returned we need to process the
166 * sdb_entry to fill the principal in the HDB entry.
168 code = HDB_ERR_WRONG_REALM;
169 break;
170 case SDB_ERR_NOENTRY:
171 return HDB_ERR_NOENTRY;
172 case SDB_ERR_NOT_FOUND_HERE:
173 return HDB_ERR_NOT_FOUND_HERE;
174 default:
175 return ret;
178 ret = sdb_entry_to_hdb_entry(context, &sentry, entry);
179 sdb_entry_free(&sentry);
181 if (code != 0 && ret != 0) {
182 code = ret;
185 return code;
188 static krb5_error_code hdb_samba4_kpasswd_fetch_kvno(krb5_context context, HDB *db,
189 krb5_const_principal _principal,
190 unsigned flags,
191 krb5_kvno _kvno,
192 hdb_entry *entry)
194 struct samba_kdc_db_context *kdc_db_ctx = NULL;
195 krb5_error_code ret;
196 krb5_principal kpasswd_principal = NULL;
198 kdc_db_ctx = talloc_get_type_abort(db->hdb_db,
199 struct samba_kdc_db_context);
201 ret = smb_krb5_make_principal(context, &kpasswd_principal,
202 lpcfg_realm(kdc_db_ctx->lp_ctx),
203 "kadmin", "changepw",
204 NULL);
205 if (ret) {
206 return ret;
208 smb_krb5_principal_set_type(context, kpasswd_principal, KRB5_NT_SRV_INST);
211 * For the kpasswd service, always ensure we get the latest kvno. This
212 * also means we (correctly) refuse RODC-issued tickets.
214 flags &= ~HDB_F_KVNO_SPECIFIED;
216 /* Don't bother looking up a client or krbtgt. */
217 flags &= ~(SDB_F_GET_CLIENT|SDB_F_GET_KRBTGT);
219 ret = hdb_samba4_fetch_kvno(context, db,
220 kpasswd_principal,
221 flags,
223 entry);
225 krb5_free_principal(context, kpasswd_principal);
226 return ret;
229 static krb5_error_code hdb_samba4_firstkey(krb5_context context, HDB *db, unsigned flags,
230 hdb_entry *entry)
232 struct samba_kdc_db_context *kdc_db_ctx;
233 struct sdb_entry sentry = {};
234 krb5_error_code ret;
236 kdc_db_ctx = talloc_get_type_abort(db->hdb_db,
237 struct samba_kdc_db_context);
239 ret = samba_kdc_firstkey(context, kdc_db_ctx, &sentry);
240 switch (ret) {
241 case 0:
242 break;
243 case SDB_ERR_WRONG_REALM:
244 return HDB_ERR_WRONG_REALM;
245 case SDB_ERR_NOENTRY:
246 return HDB_ERR_NOENTRY;
247 case SDB_ERR_NOT_FOUND_HERE:
248 return HDB_ERR_NOT_FOUND_HERE;
249 default:
250 return ret;
253 ret = sdb_entry_to_hdb_entry(context, &sentry, entry);
254 sdb_entry_free(&sentry);
255 return ret;
258 static krb5_error_code hdb_samba4_nextkey(krb5_context context, HDB *db, unsigned flags,
259 hdb_entry *entry)
261 struct samba_kdc_db_context *kdc_db_ctx;
262 struct sdb_entry sentry = {};
263 krb5_error_code ret;
265 kdc_db_ctx = talloc_get_type_abort(db->hdb_db,
266 struct samba_kdc_db_context);
268 ret = samba_kdc_nextkey(context, kdc_db_ctx, &sentry);
269 switch (ret) {
270 case 0:
271 break;
272 case SDB_ERR_WRONG_REALM:
273 return HDB_ERR_WRONG_REALM;
274 case SDB_ERR_NOENTRY:
275 return HDB_ERR_NOENTRY;
276 case SDB_ERR_NOT_FOUND_HERE:
277 return HDB_ERR_NOT_FOUND_HERE;
278 default:
279 return ret;
282 ret = sdb_entry_to_hdb_entry(context, &sentry, entry);
283 sdb_entry_free(&sentry);
284 return ret;
287 static krb5_error_code hdb_samba4_nextkey_panic(krb5_context context, HDB *db,
288 unsigned flags,
289 hdb_entry *entry)
291 DBG_ERR("Attempt to iterate kpasswd keytab => PANIC\n");
292 smb_panic("hdb_samba4_nextkey_panic: Attempt to iterate kpasswd keytab");
295 static krb5_error_code hdb_samba4_destroy(krb5_context context, HDB *db)
297 talloc_free(db);
298 return 0;
301 static krb5_error_code
302 hdb_samba4_check_constrained_delegation(krb5_context context, HDB *db,
303 hdb_entry *entry,
304 krb5_const_principal target_principal)
306 struct samba_kdc_db_context *kdc_db_ctx = NULL;
307 struct samba_kdc_entry *skdc_entry = NULL;
309 kdc_db_ctx = talloc_get_type_abort(db->hdb_db,
310 struct samba_kdc_db_context);
311 skdc_entry = talloc_get_type_abort(entry->context,
312 struct samba_kdc_entry);
314 return samba_kdc_check_s4u2proxy(context, kdc_db_ctx,
315 skdc_entry,
316 target_principal);
319 static krb5_error_code
320 hdb_samba4_check_rbcd(krb5_context context, HDB *db,
321 krb5_const_principal client_principal,
322 krb5_const_principal server_principal,
323 krb5_const_pac header_pac,
324 const hdb_entry *proxy)
326 struct samba_kdc_db_context *kdc_db_ctx = NULL;
327 struct samba_kdc_entry *proxy_skdc_entry = NULL;
329 kdc_db_ctx = talloc_get_type_abort(db->hdb_db,
330 struct samba_kdc_db_context);
331 proxy_skdc_entry = talloc_get_type_abort(proxy->context,
332 struct samba_kdc_entry);
334 return samba_kdc_check_s4u2proxy_rbcd(context,
335 kdc_db_ctx,
336 client_principal,
337 server_principal,
338 header_pac,
339 proxy_skdc_entry);
342 static krb5_error_code
343 hdb_samba4_check_pkinit_ms_upn_match(krb5_context context, HDB *db,
344 hdb_entry *entry,
345 krb5_const_principal certificate_principal)
347 struct samba_kdc_db_context *kdc_db_ctx;
348 struct samba_kdc_entry *skdc_entry;
349 krb5_error_code ret;
351 kdc_db_ctx = talloc_get_type_abort(db->hdb_db,
352 struct samba_kdc_db_context);
353 skdc_entry = talloc_get_type_abort(entry->context,
354 struct samba_kdc_entry);
356 ret = samba_kdc_check_pkinit_ms_upn_match(context, kdc_db_ctx,
357 skdc_entry,
358 certificate_principal);
359 switch (ret) {
360 case 0:
361 break;
362 case SDB_ERR_WRONG_REALM:
363 ret = HDB_ERR_WRONG_REALM;
364 break;
365 case SDB_ERR_NOENTRY:
366 ret = HDB_ERR_NOENTRY;
367 break;
368 case SDB_ERR_NOT_FOUND_HERE:
369 ret = HDB_ERR_NOT_FOUND_HERE;
370 break;
371 default:
372 break;
375 return ret;
378 static krb5_error_code
379 hdb_samba4_check_client_matches_target_service(krb5_context context, HDB *db,
380 hdb_entry *client_entry,
381 hdb_entry *server_target_entry)
383 struct samba_kdc_entry *skdc_client_entry
384 = talloc_get_type_abort(client_entry->context,
385 struct samba_kdc_entry);
386 struct samba_kdc_entry *skdc_server_target_entry
387 = talloc_get_type_abort(server_target_entry->context,
388 struct samba_kdc_entry);
390 return samba_kdc_check_client_matches_target_service(context,
391 skdc_client_entry,
392 skdc_server_target_entry);
395 static void reset_bad_password_netlogon(TALLOC_CTX *mem_ctx,
396 struct samba_kdc_db_context *kdc_db_ctx,
397 struct netr_SendToSamBase *send_to_sam)
399 struct dcerpc_binding_handle *irpc_handle;
400 struct winbind_SendToSam req;
401 struct tevent_req *subreq = NULL;
403 irpc_handle = irpc_binding_handle_by_name(mem_ctx, kdc_db_ctx->msg_ctx,
404 "winbind_server",
405 &ndr_table_winbind);
407 if (irpc_handle == NULL) {
408 DEBUG(0, ("No winbind_server running!\n"));
409 return;
412 req.in.message = *send_to_sam;
415 * This seem to rely on the current IRPC implementation,
416 * which delivers the message in the _send function.
418 * TODO: we need a ONE_WAY IRPC handle and register
419 * a callback and wait for it to be triggered!
421 subreq = dcerpc_winbind_SendToSam_r_send(mem_ctx, kdc_db_ctx->ev_ctx,
422 irpc_handle, &req);
424 /* we aren't interested in a reply */
425 TALLOC_FREE(subreq);
428 #define SAMBA_HDB_AUTHN_AUDIT_INFO_OBJ "samba:authn_audit_info_obj"
429 #define SAMBA_HDB_CLIENT_AUDIT_INFO "samba:client_audit_info"
430 #define SAMBA_HDB_SERVER_AUDIT_INFO "samba:server_audit_info"
432 #define SAMBA_HDB_NT_STATUS_OBJ "samba:nt_status_obj"
433 #define SAMBA_HDB_NT_STATUS "samba:nt_status"
435 struct hdb_audit_info_obj {
436 struct authn_audit_info *audit_info;
439 static void hdb_audit_info_obj_dealloc(void *ptr)
441 struct hdb_audit_info_obj *audit_info_obj = ptr;
443 if (audit_info_obj == NULL) {
444 return;
447 TALLOC_FREE(audit_info_obj->audit_info);
451 * Set talloc-allocated auditing information of the KDC request. On success,
452 * ‘audit_info’ is invalidated and may no longer be used by the caller.
454 static krb5_error_code hdb_samba4_set_steal_audit_info(astgs_request_t r,
455 const char *key,
456 struct authn_audit_info *audit_info)
458 struct hdb_audit_info_obj *audit_info_obj = NULL;
460 audit_info_obj = kdc_object_alloc(sizeof (*audit_info_obj),
461 SAMBA_HDB_AUTHN_AUDIT_INFO_OBJ,
462 hdb_audit_info_obj_dealloc);
463 if (audit_info_obj == NULL) {
464 return ENOMEM;
468 * Steal a handle to the audit information onto the NULL context —
469 * Heimdal will be responsible for the deallocation of the object.
471 audit_info_obj->audit_info = talloc_steal(NULL, audit_info);
473 heim_audit_setkv_object((heim_svc_req_desc)r, key, audit_info_obj);
474 heim_release(audit_info_obj);
476 return 0;
480 * Set talloc-allocated client auditing information of the KDC request. On
481 * success, ‘client_audit_info’ is invalidated and may no longer be used by the
482 * caller.
484 krb5_error_code hdb_samba4_set_steal_client_audit_info(astgs_request_t r,
485 struct authn_audit_info *client_audit_info)
487 return hdb_samba4_set_steal_audit_info(r,
488 SAMBA_HDB_CLIENT_AUDIT_INFO,
489 client_audit_info);
492 static const struct authn_audit_info *hdb_samba4_get_client_audit_info(hdb_request_t r)
494 const struct hdb_audit_info_obj *audit_info_obj = NULL;
496 audit_info_obj = heim_audit_getkv((heim_svc_req_desc)r, SAMBA_HDB_CLIENT_AUDIT_INFO);
497 if (audit_info_obj == NULL) {
498 return NULL;
501 return audit_info_obj->audit_info;
505 * Set talloc-allocated server auditing information of the KDC request. On
506 * success, ‘server_audit_info’ is invalidated and may no longer be used by the
507 * caller.
509 krb5_error_code hdb_samba4_set_steal_server_audit_info(astgs_request_t r,
510 struct authn_audit_info *server_audit_info)
512 return hdb_samba4_set_steal_audit_info(r,
513 SAMBA_HDB_SERVER_AUDIT_INFO,
514 server_audit_info);
517 static const struct authn_audit_info *hdb_samba4_get_server_audit_info(hdb_request_t r)
519 const struct hdb_audit_info_obj *audit_info_obj = NULL;
521 audit_info_obj = heim_audit_getkv((heim_svc_req_desc)r, SAMBA_HDB_SERVER_AUDIT_INFO);
522 if (audit_info_obj == NULL) {
523 return NULL;
526 return audit_info_obj->audit_info;
529 struct hdb_ntstatus_obj {
530 NTSTATUS status;
531 krb5_error_code current_error;
535 * Add an NTSTATUS code to a Kerberos request. ‘error’ is the error value we
536 * want to return to the client. When it comes time to generating the error
537 * request, we shall compare this error value to whatever error we are about to
538 * return; if the two match, we shall replace the ‘e-data’ field in the reply
539 * with the NTSTATUS code.
541 krb5_error_code hdb_samba4_set_ntstatus(astgs_request_t r,
542 const NTSTATUS status,
543 const krb5_error_code error)
545 struct hdb_ntstatus_obj *status_obj = NULL;
547 status_obj = kdc_object_alloc(sizeof (*status_obj),
548 SAMBA_HDB_NT_STATUS_OBJ,
549 NULL);
550 if (status_obj == NULL) {
551 return ENOMEM;
554 *status_obj = (struct hdb_ntstatus_obj) {
555 .status = status,
556 .current_error = error,
559 heim_audit_setkv_object((heim_svc_req_desc)r, SAMBA_HDB_NT_STATUS, status_obj);
560 heim_release(status_obj);
562 return 0;
565 static krb5_error_code hdb_samba4_make_nt_status_edata(const NTSTATUS status,
566 const uint32_t flags,
567 krb5_data *edata_out)
569 const uint32_t status_code = NT_STATUS_V(status);
570 const uint32_t zero = 0;
571 KERB_ERROR_DATA error_data;
572 krb5_data e_data;
574 krb5_error_code ret;
575 size_t size;
577 /* The raw KERB-ERR-TYPE-EXTENDED structure. */
578 uint8_t data[12];
580 PUSH_LE_U32(data, 0, status_code);
581 PUSH_LE_U32(data, 4, zero);
582 PUSH_LE_U32(data, 8, flags);
584 e_data = (krb5_data) {
585 .data = &data,
586 .length = sizeof(data),
589 error_data = (KERB_ERROR_DATA) {
590 .data_type = kERB_ERR_TYPE_EXTENDED,
591 .data_value = &e_data,
594 ASN1_MALLOC_ENCODE(KERB_ERROR_DATA,
595 edata_out->data, edata_out->length,
596 &error_data,
597 &size, ret);
598 if (ret) {
599 return ret;
601 if (size != edata_out->length) {
602 /* Internal ASN.1 encoder error */
603 krb5_data_free(edata_out);
604 return KRB5KRB_ERR_GENERIC;
607 return 0;
610 static krb5_error_code hdb_samba4_set_edata_from_ntstatus(hdb_request_t r, const NTSTATUS status)
612 const KDC_REQ *req = kdc_request_get_req((astgs_request_t)r);
613 krb5_error_code ret = 0;
614 krb5_data e_data;
615 uint32_t flags = 1;
617 if (req->msg_type == krb_tgs_req) {
618 /* This flag is used to indicate a TGS-REQ. */
619 flags |= 2;
622 ret = hdb_samba4_make_nt_status_edata(status, flags, &e_data);
623 if (ret) {
624 return ret;
627 ret = kdc_set_e_data((astgs_request_t)r, e_data);
628 if (ret) {
629 krb5_data_free(&e_data);
632 return ret;
635 static NTSTATUS hdb_samba4_get_ntstatus(hdb_request_t r)
637 struct hdb_ntstatus_obj *status_obj = NULL;
639 status_obj = heim_audit_getkv((heim_svc_req_desc)r, SAMBA_HDB_NT_STATUS);
640 if (status_obj == NULL) {
641 return NT_STATUS_OK;
644 if (r->error_code != status_obj->current_error) {
646 * The error code has changed from what we expect. Consider the
647 * NTSTATUS to be invalidated.
649 return NT_STATUS_OK;
652 return status_obj->status;
655 static krb5_error_code hdb_samba4_tgs_audit(const struct samba_kdc_db_context *kdc_db_ctx,
656 const hdb_entry *entry,
657 hdb_request_t r)
659 TALLOC_CTX *frame = talloc_stackframe();
660 const struct authn_audit_info *server_audit_info = NULL;
661 struct tsocket_address *remote_host = NULL;
662 struct samba_kdc_entry *client_entry = NULL;
663 struct dom_sid sid_buf = {};
664 const char *account_name = NULL;
665 const char *domain_name = NULL;
666 const struct dom_sid *sid = NULL;
667 size_t sa_socklen = 0;
668 NTSTATUS auth_status = NT_STATUS_OK;
669 krb5_error_code ret = 0;
670 krb5_error_code final_ret = 0;
672 /* Have we got a status code indicating an error? */
673 auth_status = hdb_samba4_get_ntstatus(r);
674 if (!NT_STATUS_IS_OK(auth_status)) {
676 * Include this status code in the ‘e-data’ field of the reply.
678 ret = hdb_samba4_set_edata_from_ntstatus(r, auth_status);
679 if (ret) {
680 final_ret = ret;
682 } else if (entry == NULL) {
683 auth_status = NT_STATUS_NO_SUCH_USER;
684 } else if (r->error_code) {
686 * Don’t include a status code in the reply. Just log the
687 * request as being unsuccessful.
689 auth_status = NT_STATUS_UNSUCCESSFUL;
692 switch (r->addr->sa_family) {
693 case AF_INET:
694 sa_socklen = sizeof(struct sockaddr_in);
695 break;
696 #ifdef HAVE_IPV6
697 case AF_INET6:
698 sa_socklen = sizeof(struct sockaddr_in6);
699 break;
700 #endif
703 ret = tsocket_address_bsd_from_sockaddr(frame, r->addr,
704 sa_socklen,
705 &remote_host);
706 if (ret != 0) {
707 remote_host = NULL;
708 /* Ignore the error. */
711 server_audit_info = hdb_samba4_get_server_audit_info(r);
713 if (entry != NULL) {
714 client_entry = talloc_get_type_abort(entry->context,
715 struct samba_kdc_entry);
717 ret = samdb_result_dom_sid_buf(client_entry->msg, "objectSid", &sid_buf);
718 if (ret) {
719 /* Ignore the error. */
720 } else {
721 sid = &sid_buf;
724 account_name = ldb_msg_find_attr_as_string(client_entry->msg, "sAMAccountName", NULL);
725 domain_name = lpcfg_sam_name(kdc_db_ctx->lp_ctx);
728 log_authz_event(kdc_db_ctx->msg_ctx,
729 kdc_db_ctx->lp_ctx,
730 remote_host,
731 NULL /* local */,
732 server_audit_info,
733 r->sname,
734 "TGS-REQ with Ticket-Granting Ticket",
735 domain_name,
736 account_name,
737 sid,
738 lpcfg_netbios_name(kdc_db_ctx->lp_ctx),
739 krb5_kdc_get_time(),
740 auth_status);
742 talloc_free(frame);
743 if (final_ret) {
744 r->error_code = final_ret;
746 return final_ret;
749 static krb5_error_code hdb_samba4_audit(krb5_context context,
750 HDB *db,
751 hdb_entry *entry,
752 hdb_request_t r)
754 struct samba_kdc_db_context *kdc_db_ctx = talloc_get_type_abort(db->hdb_db,
755 struct samba_kdc_db_context);
756 struct ldb_dn *domain_dn = ldb_get_default_basedn(kdc_db_ctx->samdb);
757 heim_object_t auth_details_obj = NULL;
758 const char *auth_details = NULL;
759 char *etype_str = NULL;
760 heim_object_t hdb_auth_status_obj = NULL;
761 int hdb_auth_status;
762 heim_object_t pa_type_obj = NULL;
763 const char *pa_type = NULL;
764 struct auth_usersupplied_info ui;
765 size_t sa_socklen = 0;
766 const KDC_REQ *req = kdc_request_get_req((astgs_request_t)r);
767 krb5_error_code final_ret = 0;
768 NTSTATUS edata_status;
770 if (req->msg_type == krb_tgs_req) {
771 return hdb_samba4_tgs_audit(kdc_db_ctx, entry, r);
774 if (r->error_code == KRB5KDC_ERR_PREAUTH_REQUIRED) {
775 /* Let’s not log PREAUTH_REQUIRED errors. */
776 return 0;
779 edata_status = hdb_samba4_get_ntstatus(r);
781 hdb_auth_status_obj = heim_audit_getkv((heim_svc_req_desc)r, KDC_REQUEST_KV_AUTH_EVENT);
782 if (hdb_auth_status_obj == NULL) {
783 /* No status code found, so just return. */
784 return 0;
787 hdb_auth_status = heim_number_get_int(hdb_auth_status_obj);
789 pa_type_obj = heim_audit_getkv((heim_svc_req_desc)r, KDC_REQUEST_KV_PA_NAME);
790 if (pa_type_obj != NULL) {
791 pa_type = heim_string_get_utf8(pa_type_obj);
794 auth_details_obj = heim_audit_getkv((heim_svc_req_desc)r, KDC_REQUEST_KV_PKINIT_CLIENT_CERT);
795 if (auth_details_obj != NULL) {
796 auth_details = heim_string_get_utf8(auth_details_obj);
797 } else {
798 auth_details_obj = heim_audit_getkv((heim_svc_req_desc)r, KDC_REQUEST_KV_GSS_INITIATOR);
799 if (auth_details_obj != NULL) {
800 auth_details = heim_string_get_utf8(auth_details_obj);
801 } else {
802 heim_object_t etype_obj = heim_audit_getkv((heim_svc_req_desc)r, KDC_REQUEST_KV_PA_ETYPE);
803 if (etype_obj != NULL) {
804 int etype = heim_number_get_int(etype_obj);
806 krb5_error_code ret = krb5_enctype_to_string(r->context, etype, &etype_str);
807 if (ret == 0) {
808 auth_details = etype_str;
809 } else {
810 auth_details = "unknown enctype";
817 * Forcing this via the NTLM auth structure is not ideal, but
818 * it is the most practical option right now, and ensures the
819 * logs are consistent, even if some elements are always NULL.
821 ui = (struct auth_usersupplied_info) {
822 .was_mapped = true,
823 .client = {
824 .account_name = r->cname,
825 .domain_name = NULL,
827 .service_description = "Kerberos KDC",
828 .auth_description = "Unknown Auth Description",
829 .password_type = auth_details,
830 .logon_id = generate_random_u64(),
833 switch (r->addr->sa_family) {
834 case AF_INET:
835 sa_socklen = sizeof(struct sockaddr_in);
836 break;
837 #ifdef HAVE_IPV6
838 case AF_INET6:
839 sa_socklen = sizeof(struct sockaddr_in6);
840 break;
841 #endif
844 switch (hdb_auth_status) {
845 default:
847 TALLOC_CTX *frame = talloc_stackframe();
848 struct samba_kdc_entry *p = talloc_get_type_abort(entry->context,
849 struct samba_kdc_entry);
850 struct dom_sid *sid
851 = samdb_result_dom_sid(frame, p->msg, "objectSid");
852 const char *account_name
853 = ldb_msg_find_attr_as_string(p->msg, "sAMAccountName", NULL);
854 const char *domain_name = lpcfg_sam_name(p->kdc_db_ctx->lp_ctx);
855 struct tsocket_address *remote_host;
856 const char *auth_description = NULL;
857 const struct authn_audit_info *client_audit_info = NULL;
858 const struct authn_audit_info *server_audit_info = NULL;
859 NTSTATUS status;
860 int ret;
861 bool rwdc_fallback = false;
863 ret = tsocket_address_bsd_from_sockaddr(frame, r->addr,
864 sa_socklen,
865 &remote_host);
866 if (ret != 0) {
867 ui.remote_host = NULL;
868 } else {
869 ui.remote_host = remote_host;
872 ui.mapped.account_name = account_name;
873 ui.mapped.domain_name = domain_name;
875 if (pa_type != NULL) {
876 auth_description = talloc_asprintf(frame,
877 "%s Pre-authentication",
878 pa_type);
879 if (auth_description == NULL) {
880 auth_description = pa_type;
882 } else {
883 auth_description = "Unknown Pre-authentication";
885 ui.auth_description = auth_description;
887 if (hdb_auth_status == KDC_AUTH_EVENT_CLIENT_AUTHORIZED) {
888 struct netr_SendToSamBase *send_to_sam = NULL;
891 * TODO: We could log the AS-REQ authorization success here as
892 * well. However before we do that, we need to pass
893 * in the PAC here or re-calculate it.
895 status = authsam_logon_success_accounting(kdc_db_ctx->samdb, p->msg,
896 domain_dn, true, frame, &send_to_sam);
897 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCOUNT_LOCKED_OUT)) {
898 edata_status = status;
900 r->error_code = final_ret = KRB5KDC_ERR_CLIENT_REVOKED;
901 rwdc_fallback = kdc_db_ctx->rodc;
902 } else if (!NT_STATUS_IS_OK(status)) {
903 r->error_code = final_ret = KRB5KRB_ERR_GENERIC;
904 rwdc_fallback = kdc_db_ctx->rodc;
905 } else {
906 if (r->error_code == KRB5KDC_ERR_NEVER_VALID) {
907 edata_status = status = NT_STATUS_TIME_DIFFERENCE_AT_DC;
908 } else {
909 status = krb5_to_nt_status(r->error_code);
912 if (kdc_db_ctx->rodc && send_to_sam != NULL) {
913 reset_bad_password_netlogon(frame, kdc_db_ctx, send_to_sam);
917 /* This is the final success */
918 } else if (hdb_auth_status == KDC_AUTH_EVENT_VALIDATED_LONG_TERM_KEY) {
920 * This was only a pre-authentication success,
921 * but we didn't reach the final
922 * KDC_AUTH_EVENT_CLIENT_AUTHORIZED,
923 * so consult the error code.
925 if (r->error_code == 0) {
926 DBG_ERR("ERROR: VALIDATED_LONG_TERM_KEY "
927 "with error=0 => INTERNAL_ERROR\n");
928 status = NT_STATUS_INTERNAL_ERROR;
929 r->error_code = final_ret = KRB5KRB_ERR_GENERIC;
930 } else if (!NT_STATUS_IS_OK(p->reject_status)) {
931 status = p->reject_status;
932 } else {
933 status = krb5_to_nt_status(r->error_code);
935 } else if (hdb_auth_status == KDC_AUTH_EVENT_PREAUTH_SUCCEEDED) {
937 * This was only a pre-authentication success,
938 * but we didn't reach the final
939 * KDC_AUTH_EVENT_CLIENT_AUTHORIZED,
940 * so consult the error code.
942 if (r->error_code == 0) {
943 DBG_ERR("ERROR: PREAUTH_SUCCEEDED "
944 "with error=0 => INTERNAL_ERROR\n");
945 status = NT_STATUS_INTERNAL_ERROR;
946 r->error_code = final_ret = KRB5KRB_ERR_GENERIC;
947 } else if (!NT_STATUS_IS_OK(p->reject_status)) {
948 status = p->reject_status;
949 } else {
950 status = krb5_to_nt_status(r->error_code);
952 } else if (hdb_auth_status == KDC_AUTH_EVENT_CLIENT_FOUND) {
954 * We found the client principal,
955 * but we didn’t reach the final
956 * KDC_AUTH_EVENT_CLIENT_AUTHORIZED,
957 * so consult the error code.
959 if (r->error_code == 0) {
960 DBG_ERR("ERROR: CLIENT_FOUND "
961 "with error=0 => INTERNAL_ERROR\n");
962 status = NT_STATUS_INTERNAL_ERROR;
963 r->error_code = final_ret = KRB5KRB_ERR_GENERIC;
964 } else if (!NT_STATUS_IS_OK(p->reject_status)) {
965 status = p->reject_status;
966 } else {
967 status = krb5_to_nt_status(r->error_code);
969 } else if (hdb_auth_status == KDC_AUTH_EVENT_CLIENT_TIME_SKEW) {
970 status = NT_STATUS_TIME_DIFFERENCE_AT_DC;
971 } else if (hdb_auth_status == KDC_AUTH_EVENT_WRONG_LONG_TERM_KEY) {
972 status = authsam_update_bad_pwd_count(kdc_db_ctx->samdb, p->msg, domain_dn);
973 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCOUNT_LOCKED_OUT)) {
974 edata_status = status;
976 r->error_code = final_ret = KRB5KDC_ERR_CLIENT_REVOKED;
977 } else {
978 status = NT_STATUS_WRONG_PASSWORD;
980 rwdc_fallback = kdc_db_ctx->rodc;
981 } else if (hdb_auth_status == KDC_AUTH_EVENT_HISTORIC_LONG_TERM_KEY) {
983 * The pre-authentication succeeds with a password
984 * from the password history, so we don't
985 * update the badPwdCount, but still return
986 * PREAUTH_FAILED and need to forward to
987 * a RWDC in order to produce an autoritative
988 * response for the client.
990 status = NT_STATUS_WRONG_PASSWORD;
991 rwdc_fallback = kdc_db_ctx->rodc;
992 } else if (hdb_auth_status == KDC_AUTH_EVENT_CLIENT_LOCKED_OUT) {
993 edata_status = status = NT_STATUS_ACCOUNT_LOCKED_OUT;
994 rwdc_fallback = kdc_db_ctx->rodc;
995 } else if (hdb_auth_status == KDC_AUTH_EVENT_CLIENT_NAME_UNAUTHORIZED) {
996 if (pa_type != NULL && strncmp(pa_type, "PK-INIT", strlen("PK-INIT")) == 0) {
997 status = NT_STATUS_PKINIT_NAME_MISMATCH;
998 } else {
999 status = NT_STATUS_ACCOUNT_RESTRICTION;
1001 rwdc_fallback = kdc_db_ctx->rodc;
1002 } else if (hdb_auth_status == KDC_AUTH_EVENT_PREAUTH_FAILED) {
1003 if (pa_type != NULL && strncmp(pa_type, "PK-INIT", strlen("PK-INIT")) == 0) {
1004 status = NT_STATUS_PKINIT_FAILURE;
1005 } else {
1006 status = NT_STATUS_GENERIC_COMMAND_FAILED;
1008 rwdc_fallback = kdc_db_ctx->rodc;
1009 } else {
1010 DBG_ERR("Unhandled hdb_auth_status=%d => INTERNAL_ERROR\n",
1011 hdb_auth_status);
1012 status = NT_STATUS_INTERNAL_ERROR;
1013 r->error_code = final_ret = KRB5KRB_ERR_GENERIC;
1016 if (!NT_STATUS_IS_OK(edata_status)) {
1017 krb5_error_code code;
1019 code = hdb_samba4_set_edata_from_ntstatus(r, edata_status);
1020 if (code) {
1021 r->error_code = final_ret = code;
1025 if (rwdc_fallback) {
1027 * Forward the request to an RWDC in order
1028 * to give an authoritative answer to the client.
1030 auth_description = talloc_asprintf(frame,
1031 "%s,Forward-To-RWDC",
1032 ui.auth_description);
1033 if (auth_description != NULL) {
1034 ui.auth_description = auth_description;
1036 final_ret = HDB_ERR_NOT_FOUND_HERE;
1039 client_audit_info = hdb_samba4_get_client_audit_info(r);
1040 server_audit_info = hdb_samba4_get_server_audit_info(r);
1042 log_authentication_event(kdc_db_ctx->msg_ctx,
1043 kdc_db_ctx->lp_ctx,
1044 &r->tv_start,
1045 &ui,
1046 status,
1047 domain_name,
1048 account_name,
1049 sid,
1050 client_audit_info,
1051 server_audit_info);
1052 if (final_ret == KRB5KRB_ERR_GENERIC && socket_wrapper_enabled()) {
1054 * If we're running under make test
1055 * just panic
1057 DBG_ERR("Unexpected situation => PANIC\n");
1058 smb_panic("hdb_samba4_audit: Unexpected situation");
1060 TALLOC_FREE(frame);
1061 break;
1063 case KDC_AUTH_EVENT_CLIENT_UNKNOWN:
1065 struct tsocket_address *remote_host;
1066 int ret;
1067 TALLOC_CTX *frame = talloc_stackframe();
1068 ret = tsocket_address_bsd_from_sockaddr(frame, r->addr,
1069 sa_socklen,
1070 &remote_host);
1071 if (ret != 0) {
1072 ui.remote_host = NULL;
1073 } else {
1074 ui.remote_host = remote_host;
1077 if (pa_type == NULL) {
1078 pa_type = "AS-REQ";
1081 ui.auth_description = pa_type;
1083 /* Note this is not forwarded to an RWDC */
1085 log_authentication_event(kdc_db_ctx->msg_ctx,
1086 kdc_db_ctx->lp_ctx,
1087 &r->tv_start,
1088 &ui,
1089 NT_STATUS_NO_SUCH_USER,
1090 NULL, NULL,
1091 NULL,
1092 NULL /* client_audit_info */,
1093 NULL /* server_audit_info */);
1094 TALLOC_FREE(frame);
1095 break;
1099 free(etype_str);
1101 return final_ret;
1104 /* This interface is to be called by the KDC and libnet_keytab_dump,
1105 * which is expecting Samba calling conventions.
1106 * It is also called by a wrapper (hdb_samba4_create) from the
1107 * kpasswdd -> krb5 -> keytab_hdb -> hdb code */
1109 NTSTATUS hdb_samba4_create_kdc(struct samba_kdc_base_context *base_ctx,
1110 krb5_context context, struct HDB **db)
1112 struct samba_kdc_db_context *kdc_db_ctx;
1113 NTSTATUS nt_status;
1115 if (hdb_interface_version != HDB_INTERFACE_VERSION) {
1116 krb5_set_error_message(context, EINVAL, "Heimdal HDB interface version mismatch between build-time and run-time libraries!");
1117 return NT_STATUS_ERROR_DS_INCOMPATIBLE_VERSION;
1120 *db = talloc_zero(base_ctx, HDB);
1121 if (!*db) {
1122 krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
1123 return NT_STATUS_NO_MEMORY;
1126 (*db)->hdb_master_key_set = 0;
1127 (*db)->hdb_db = NULL;
1128 (*db)->hdb_capability_flags = HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL;
1130 nt_status = samba_kdc_setup_db_ctx(*db, base_ctx, &kdc_db_ctx);
1131 if (!NT_STATUS_IS_OK(nt_status)) {
1132 talloc_free(*db);
1133 return nt_status;
1135 (*db)->hdb_db = kdc_db_ctx;
1137 (*db)->hdb_dbc = NULL;
1138 (*db)->hdb_open = hdb_samba4_open;
1139 (*db)->hdb_close = hdb_samba4_close;
1140 (*db)->hdb_free_entry_context = hdb_samba4_free_entry_context;
1141 (*db)->hdb_fetch_kvno = hdb_samba4_fetch_kvno;
1142 (*db)->hdb_store = hdb_samba4_store;
1143 (*db)->hdb_firstkey = hdb_samba4_firstkey;
1144 (*db)->hdb_nextkey = hdb_samba4_nextkey;
1145 (*db)->hdb_lock = hdb_samba4_lock;
1146 (*db)->hdb_unlock = hdb_samba4_unlock;
1147 (*db)->hdb_set_sync = hdb_samba4_set_sync;
1148 (*db)->hdb_rename = hdb_samba4_rename;
1149 /* we don't implement these, as we are not a lockable database */
1150 (*db)->hdb__get = NULL;
1151 (*db)->hdb__put = NULL;
1152 /* kadmin should not be used for deletes - use other tools instead */
1153 (*db)->hdb__del = NULL;
1154 (*db)->hdb_destroy = hdb_samba4_destroy;
1156 (*db)->hdb_audit = hdb_samba4_audit;
1157 (*db)->hdb_check_constrained_delegation = hdb_samba4_check_constrained_delegation;
1158 (*db)->hdb_check_rbcd = hdb_samba4_check_rbcd;
1159 (*db)->hdb_check_pkinit_ms_upn_match = hdb_samba4_check_pkinit_ms_upn_match;
1160 (*db)->hdb_check_client_matches_target_service = hdb_samba4_check_client_matches_target_service;
1162 return NT_STATUS_OK;
1165 NTSTATUS hdb_samba4_kpasswd_create_kdc(struct samba_kdc_base_context *base_ctx,
1166 krb5_context context, struct HDB **db)
1168 NTSTATUS nt_status;
1170 nt_status = hdb_samba4_create_kdc(base_ctx, context, db);
1171 if (!NT_STATUS_IS_OK(nt_status)) {
1172 return nt_status;
1175 (*db)->hdb_fetch_kvno = hdb_samba4_kpasswd_fetch_kvno;
1176 (*db)->hdb_firstkey = hdb_samba4_nextkey_panic;
1177 (*db)->hdb_nextkey = hdb_samba4_nextkey_panic;
1179 return NT_STATUS_OK;