18fadf6a614190fe84298b8ad1f27a92e0569041
[metze/samba/wip.git] / source4 / kdc / hdb-samba4.c
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.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  *
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.
17  *
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.
21  *
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.
33  */
34
35 #include "includes.h"
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"
42 #include <ldb.h>
43 #include "sdb.h"
44 #include "sdb_hdb.h"
45 #include "dsdb/samdb/samdb.h"
46 #include "param/param.h"
47 #include "../lib/tsocket/tsocket.h"
48 #include "librpc/gen_ndr/ndr_netlogon.h"
49 #include "librpc/gen_ndr/ndr_winbind_c.h"
50 #include "lib/messaging/irpc.h"
51 #include "hdb.h"
52 #include <kdc-audit.h>
53 #include <kdc-plugin.h>
54
55 #undef DBGC_CLASS
56 #define DBGC_CLASS DBGC_KERBEROS
57
58 static krb5_error_code hdb_samba4_open(krb5_context context, HDB *db, int flags, mode_t mode)
59 {
60         if (db->hdb_master_key_set) {
61                 krb5_error_code ret = HDB_ERR_NOENTRY;
62                 krb5_warnx(context, "hdb_samba4_open: use of a master key incompatible with LDB\n");
63                 krb5_set_error_message(context, ret, "hdb_samba4_open: use of a master key incompatible with LDB\n");
64                 return ret;
65         }
66
67         return 0;
68 }
69
70 static krb5_error_code hdb_samba4_close(krb5_context context, HDB *db)
71 {
72         return 0;
73 }
74
75 static krb5_error_code hdb_samba4_lock(krb5_context context, HDB *db, int operation)
76 {
77         return 0;
78 }
79
80 static krb5_error_code hdb_samba4_unlock(krb5_context context, HDB *db)
81 {
82         return 0;
83 }
84
85 static krb5_error_code hdb_samba4_rename(krb5_context context, HDB *db, const char *new_name)
86 {
87         return HDB_ERR_DB_INUSE;
88 }
89
90 static krb5_error_code hdb_samba4_store(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry)
91 {
92         return HDB_ERR_DB_INUSE;
93 }
94
95 /*
96  * If we ever want kadmin to work fast, we might try and reopen the
97  * ldb with LDB_NOSYNC
98  */
99 static krb5_error_code hdb_samba4_set_sync(krb5_context context, struct HDB *db, int set_sync)
100 {
101         return 0;
102 }
103
104 static void hdb_samba4_free_entry_context(krb5_context context, struct HDB *db, hdb_entry *entry)
105 {
106         /*
107          * This function is now called for every HDB entry, not just those with
108          * 'context' set, so we have to check that the context is not NULL.
109         */
110         if (entry->context != NULL) {
111                 struct samba_kdc_entry *skdc_entry =
112                         talloc_get_type_abort(entry->context,
113                         struct samba_kdc_entry);
114
115                 /* this function is called only from hdb_free_entry().
116                  * Make sure we neutralize the destructor or we will
117                  * get a double free later when hdb_free_entry() will
118                  * try to call free_hdb_entry() */
119                 entry->context = NULL;
120                 skdc_entry->kdc_entry = NULL;
121                 TALLOC_FREE(skdc_entry);
122         }
123 }
124
125 static krb5_error_code hdb_samba4_fetch_fast_cookie(krb5_context context,
126                                                     struct samba_kdc_db_context *kdc_db_ctx,
127                                                     hdb_entry *entry)
128 {
129         DBG_ERR("Looked up HDB entry for unsupported FX-COOKIE.\n");
130         return HDB_ERR_NOENTRY;
131 }
132
133 static krb5_error_code hdb_samba4_fetch_kvno(krb5_context context, HDB *db,
134                                              krb5_const_principal principal,
135                                              unsigned flags,
136                                              krb5_kvno kvno,
137                                              hdb_entry *entry)
138 {
139         struct samba_kdc_db_context *kdc_db_ctx;
140         struct sdb_entry sentry = {};
141         krb5_error_code code, ret;
142         uint32_t sflags;
143
144         kdc_db_ctx = talloc_get_type_abort(db->hdb_db,
145                                            struct samba_kdc_db_context);
146
147         if (flags & HDB_F_GET_FAST_COOKIE) {
148                 return hdb_samba4_fetch_fast_cookie(context,
149                                                     kdc_db_ctx,
150                                                     entry);
151         }
152
153         sflags = (flags & SDB_F_HDB_MASK);
154
155         ret = samba_kdc_fetch(context,
156                               kdc_db_ctx,
157                               principal,
158                               sflags,
159                               kvno,
160                               &sentry);
161         switch (ret) {
162         case 0:
163                 code = 0;
164                 break;
165         case SDB_ERR_WRONG_REALM:
166                 /*
167                  * If SDB_ERR_WRONG_REALM is returned we need to process the
168                  * sdb_entry to fill the principal in the HDB entry.
169                  */
170                 code = HDB_ERR_WRONG_REALM;
171                 break;
172         case SDB_ERR_NOENTRY:
173                 return HDB_ERR_NOENTRY;
174         case SDB_ERR_NOT_FOUND_HERE:
175                 return HDB_ERR_NOT_FOUND_HERE;
176         default:
177                 return ret;
178         }
179
180         ret = sdb_entry_to_hdb_entry(context, &sentry, entry);
181         sdb_entry_free(&sentry);
182
183         if (code == 0) {
184                 code = ret;
185         }
186
187         return code;
188 }
189
190 static krb5_error_code hdb_samba4_kpasswd_fetch_kvno(krb5_context context, HDB *db,
191                                                      krb5_const_principal _principal,
192                                                      unsigned flags,
193                                                      krb5_kvno _kvno,
194                                                      hdb_entry *entry)
195 {
196         struct samba_kdc_db_context *kdc_db_ctx = NULL;
197         krb5_error_code ret;
198         krb5_principal kpasswd_principal = NULL;
199
200         kdc_db_ctx = talloc_get_type_abort(db->hdb_db,
201                                            struct samba_kdc_db_context);
202
203         ret = smb_krb5_make_principal(context, &kpasswd_principal,
204                                       lpcfg_realm(kdc_db_ctx->lp_ctx),
205                                       "kadmin", "changepw",
206                                       NULL);
207         if (ret) {
208                 return ret;
209         }
210         smb_krb5_principal_set_type(context, kpasswd_principal, KRB5_NT_SRV_INST);
211
212         /*
213          * For the kpasswd service, always ensure we get the latest kvno. This
214          * also means we (correctly) refuse RODC-issued tickets.
215          */
216         flags &= ~HDB_F_KVNO_SPECIFIED;
217
218         /* Don't bother looking up a client or krbtgt. */
219         flags &= ~(HDB_F_GET_CLIENT|HDB_F_GET_KRBTGT);
220
221         ret = hdb_samba4_fetch_kvno(context, db,
222                                     kpasswd_principal,
223                                     flags,
224                                     0,
225                                     entry);
226
227         krb5_free_principal(context, kpasswd_principal);
228         return ret;
229 }
230
231 static krb5_error_code hdb_samba4_firstkey(krb5_context context, HDB *db, unsigned flags,
232                                         hdb_entry *entry)
233 {
234         struct samba_kdc_db_context *kdc_db_ctx;
235         struct sdb_entry sentry = {};
236         krb5_error_code ret;
237
238         kdc_db_ctx = talloc_get_type_abort(db->hdb_db,
239                                            struct samba_kdc_db_context);
240
241         ret = samba_kdc_firstkey(context, kdc_db_ctx, &sentry);
242         switch (ret) {
243         case 0:
244                 break;
245         case SDB_ERR_WRONG_REALM:
246                 return HDB_ERR_WRONG_REALM;
247         case SDB_ERR_NOENTRY:
248                 return HDB_ERR_NOENTRY;
249         case SDB_ERR_NOT_FOUND_HERE:
250                 return HDB_ERR_NOT_FOUND_HERE;
251         default:
252                 return ret;
253         }
254
255         ret = sdb_entry_to_hdb_entry(context, &sentry, entry);
256         sdb_entry_free(&sentry);
257         return ret;
258 }
259
260 static krb5_error_code hdb_samba4_nextkey(krb5_context context, HDB *db, unsigned flags,
261                                    hdb_entry *entry)
262 {
263         struct samba_kdc_db_context *kdc_db_ctx;
264         struct sdb_entry sentry = {};
265         krb5_error_code ret;
266
267         kdc_db_ctx = talloc_get_type_abort(db->hdb_db,
268                                            struct samba_kdc_db_context);
269
270         ret = samba_kdc_nextkey(context, kdc_db_ctx, &sentry);
271         switch (ret) {
272         case 0:
273                 break;
274         case SDB_ERR_WRONG_REALM:
275                 return HDB_ERR_WRONG_REALM;
276         case SDB_ERR_NOENTRY:
277                 return HDB_ERR_NOENTRY;
278         case SDB_ERR_NOT_FOUND_HERE:
279                 return HDB_ERR_NOT_FOUND_HERE;
280         default:
281                 return ret;
282         }
283
284         ret = sdb_entry_to_hdb_entry(context, &sentry, entry);
285         sdb_entry_free(&sentry);
286         return ret;
287 }
288
289 static krb5_error_code hdb_samba4_nextkey_panic(krb5_context context, HDB *db,
290                                                 unsigned flags,
291                                                 hdb_entry *entry)
292 {
293         DBG_ERR("Attempt to iterate kpasswd keytab => PANIC\n");
294         smb_panic("hdb_samba4_nextkey_panic: Attempt to iterate kpasswd keytab");
295 }
296
297 static krb5_error_code hdb_samba4_destroy(krb5_context context, HDB *db)
298 {
299         talloc_free(db);
300         return 0;
301 }
302
303 static krb5_error_code
304 hdb_samba4_check_constrained_delegation(krb5_context context, HDB *db,
305                                         hdb_entry *entry,
306                                         krb5_const_principal target_principal)
307 {
308         struct samba_kdc_db_context *kdc_db_ctx = NULL;
309         struct samba_kdc_entry *skdc_entry = NULL;
310
311         kdc_db_ctx = talloc_get_type_abort(db->hdb_db,
312                                            struct samba_kdc_db_context);
313         skdc_entry = talloc_get_type_abort(entry->context,
314                                            struct samba_kdc_entry);
315
316         return samba_kdc_check_s4u2proxy(context, kdc_db_ctx,
317                                          skdc_entry,
318                                          target_principal);
319 }
320
321 static krb5_error_code
322 hdb_samba4_check_rbcd(krb5_context context, HDB *db,
323                       const hdb_entry *client_krbtgt,
324                       const hdb_entry *client,
325                       const hdb_entry *device_krbtgt,
326                       const hdb_entry *device,
327                       krb5_const_principal server_principal,
328                       krb5_const_pac header_pac,
329                       krb5_const_pac device_pac,
330                       const hdb_entry *proxy)
331 {
332         struct samba_kdc_db_context *kdc_db_ctx = NULL;
333         struct samba_kdc_entry *client_skdc_entry = NULL;
334         const struct samba_kdc_entry *client_krbtgt_skdc_entry = NULL;
335         struct samba_kdc_entry *proxy_skdc_entry = NULL;
336         const struct auth_user_info_dc *client_info = NULL;
337         const struct auth_user_info_dc *device_info = NULL;
338         struct samba_kdc_entry_pac client_pac_entry = {};
339         struct auth_claims auth_claims = {};
340         TALLOC_CTX *mem_ctx = NULL;
341         krb5_error_code code;
342
343         kdc_db_ctx = talloc_get_type_abort(db->hdb_db,
344                                            struct samba_kdc_db_context);
345         client_skdc_entry = talloc_get_type_abort(client->context,
346                                                   struct samba_kdc_entry);
347         client_krbtgt_skdc_entry = talloc_get_type_abort(client_krbtgt->context,
348                                                          struct samba_kdc_entry);
349         proxy_skdc_entry = talloc_get_type_abort(proxy->context,
350                                                  struct samba_kdc_entry);
351
352         mem_ctx = talloc_new(kdc_db_ctx);
353         if (mem_ctx == NULL) {
354                 return ENOMEM;
355         }
356
357         client_pac_entry = samba_kdc_entry_pac(header_pac,
358                                                client_skdc_entry,
359                                                samba_kdc_entry_is_trust(client_krbtgt_skdc_entry));
360
361         code = samba_kdc_get_user_info_dc(mem_ctx,
362                                           context,
363                                           kdc_db_ctx->samdb,
364                                           client_pac_entry,
365                                           &client_info,
366                                           NULL /* resource_groups_out */);
367         if (code != 0) {
368                 goto out;
369         }
370
371         code = samba_kdc_get_claims_data(mem_ctx,
372                                          context,
373                                          kdc_db_ctx->samdb,
374                                          client_pac_entry,
375                                          &auth_claims.user_claims);
376         if (code) {
377                 goto out;
378         }
379
380         if (device != NULL) {
381                 struct samba_kdc_entry *device_skdc_entry = NULL;
382                 const struct samba_kdc_entry *device_krbtgt_skdc_entry = NULL;
383                 struct samba_kdc_entry_pac device_pac_entry = {};
384
385                 device_skdc_entry = talloc_get_type_abort(device->context,
386                                                           struct samba_kdc_entry);
387
388                 if (device_krbtgt != NULL) {
389                         device_krbtgt_skdc_entry = talloc_get_type_abort(device_krbtgt->context,
390                                                                          struct samba_kdc_entry);
391                 }
392
393                 device_pac_entry = samba_kdc_entry_pac(device_pac,
394                                                        device_skdc_entry,
395                                                        samba_kdc_entry_is_trust(device_krbtgt_skdc_entry));
396
397                 code = samba_kdc_get_user_info_dc(mem_ctx,
398                                                   context,
399                                                   kdc_db_ctx->samdb,
400                                                   device_pac_entry,
401                                                   &device_info,
402                                                   NULL /* resource_groups_out */);
403                 if (code) {
404                         goto out;
405                 }
406
407                 code = samba_kdc_get_claims_data(mem_ctx,
408                                                  context,
409                                                  kdc_db_ctx->samdb,
410                                                  device_pac_entry,
411                                                  &auth_claims.device_claims);
412                 if (code) {
413                         goto out;
414                 }
415         }
416
417         code = samba_kdc_check_s4u2proxy_rbcd(context,
418                                               kdc_db_ctx,
419                                               client->principal,
420                                               server_principal,
421                                               client_info,
422                                               device_info,
423                                               auth_claims,
424                                               proxy_skdc_entry);
425 out:
426         talloc_free(mem_ctx);
427         return code;
428 }
429
430 static krb5_error_code
431 hdb_samba4_check_pkinit_ms_upn_match(krb5_context context, HDB *db,
432                                      hdb_entry *entry,
433                                      krb5_const_principal certificate_principal)
434 {
435         struct samba_kdc_db_context *kdc_db_ctx;
436         struct samba_kdc_entry *skdc_entry;
437         krb5_error_code ret;
438
439         kdc_db_ctx = talloc_get_type_abort(db->hdb_db,
440                                            struct samba_kdc_db_context);
441         skdc_entry = talloc_get_type_abort(entry->context,
442                                            struct samba_kdc_entry);
443
444         ret = samba_kdc_check_pkinit_ms_upn_match(context, kdc_db_ctx,
445                                                   skdc_entry,
446                                                   certificate_principal);
447         switch (ret) {
448         case 0:
449                 break;
450         case SDB_ERR_WRONG_REALM:
451                 ret = HDB_ERR_WRONG_REALM;
452                 break;
453         case SDB_ERR_NOENTRY:
454                 ret = HDB_ERR_NOENTRY;
455                 break;
456         case SDB_ERR_NOT_FOUND_HERE:
457                 ret = HDB_ERR_NOT_FOUND_HERE;
458                 break;
459         default:
460                 break;
461         }
462
463         return ret;
464 }
465
466 static krb5_error_code
467 hdb_samba4_check_client_matches_target_service(krb5_context context, HDB *db,
468                           hdb_entry *client_entry,
469                           hdb_entry *server_target_entry)
470 {
471         struct samba_kdc_entry *skdc_client_entry
472                 = talloc_get_type_abort(client_entry->context,
473                                         struct samba_kdc_entry);
474         struct samba_kdc_entry *skdc_server_target_entry
475                 = talloc_get_type_abort(server_target_entry->context,
476                                         struct samba_kdc_entry);
477
478         return samba_kdc_check_client_matches_target_service(context,
479                                                              skdc_client_entry,
480                                                              skdc_server_target_entry);
481 }
482
483 static void reset_bad_password_netlogon(TALLOC_CTX *mem_ctx,
484                                         struct samba_kdc_db_context *kdc_db_ctx,
485                                         struct netr_SendToSamBase *send_to_sam)
486 {
487         struct dcerpc_binding_handle *irpc_handle;
488         struct winbind_SendToSam req;
489         struct tevent_req *subreq = NULL;
490
491         NDR_PRINT_DEBUG(netr_SendToSamBase, send_to_sam);
492         irpc_handle = irpc_binding_handle_by_name(mem_ctx, kdc_db_ctx->msg_ctx,
493                                                   "winbind_server",
494                                                   &ndr_table_winbind);
495
496         if (irpc_handle == NULL) {
497                 DBG_ERR("No winbind_server running!\n");
498                 return;
499         }
500
501         req.in.message = *send_to_sam;
502
503         /*
504          * This seem to rely on the current IRPC implementation,
505          * which delivers the message in the _send function.
506          *
507          * TODO: we need a ONE_WAY IRPC handle and register
508          * a callback and wait for it to be triggered!
509          */
510         DBG_ERR("calling dcerpc_winbind_SendToSam_r_send\n");
511         subreq = dcerpc_winbind_SendToSam_r_send(mem_ctx, kdc_db_ctx->ev_ctx,
512                                                  irpc_handle, &req);
513
514         /* we aren't interested in a reply */
515         DBG_ERR("before talloc_free(subreq)\n");
516         TALLOC_FREE(subreq);
517         DBG_ERR("after talloc_free(subreq)\n");
518         NDR_PRINT_DEBUG(netr_SendToSamBase, send_to_sam);
519 }
520
521 #define SAMBA_HDB_AUTHN_AUDIT_INFO_OBJ "samba:authn_audit_info_obj"
522 #define SAMBA_HDB_CLIENT_AUDIT_INFO "samba:client_audit_info"
523 #define SAMBA_HDB_SERVER_AUDIT_INFO "samba:server_audit_info"
524
525 #define SAMBA_HDB_NT_STATUS_OBJ "samba:nt_status_obj"
526 #define SAMBA_HDB_NT_STATUS "samba:nt_status"
527
528 struct hdb_audit_info_obj {
529         struct authn_audit_info *audit_info;
530 };
531
532 static void hdb_audit_info_obj_dealloc(void *ptr)
533 {
534         struct hdb_audit_info_obj *audit_info_obj = ptr;
535
536         if (audit_info_obj == NULL) {
537                 return;
538         }
539
540         TALLOC_FREE(audit_info_obj->audit_info);
541 }
542
543 /*
544  * Set talloc-allocated auditing information of the KDC request. On success,
545  * â€˜audit_info’ is invalidated and may no longer be used by the caller.
546  */
547 static krb5_error_code hdb_samba4_set_steal_audit_info(astgs_request_t r,
548                                                        const char *key,
549                                                        struct authn_audit_info *audit_info)
550 {
551         struct hdb_audit_info_obj *audit_info_obj = NULL;
552
553         audit_info_obj = kdc_object_alloc(sizeof (*audit_info_obj),
554                                           SAMBA_HDB_AUTHN_AUDIT_INFO_OBJ,
555                                           hdb_audit_info_obj_dealloc);
556         if (audit_info_obj == NULL) {
557                 return ENOMEM;
558         }
559
560         /*
561          * Steal a handle to the audit information onto the NULL context â€”
562          * Heimdal will be responsible for the deallocation of the object.
563          */
564         audit_info_obj->audit_info = talloc_steal(NULL, audit_info);
565
566         heim_audit_setkv_object((heim_svc_req_desc)r, key, audit_info_obj);
567         heim_release(audit_info_obj);
568
569         return 0;
570 }
571
572 /*
573  * Set talloc-allocated client auditing information of the KDC request. On
574  * success, â€˜client_audit_info’ is invalidated and may no longer be used by the
575  * caller.
576  */
577 krb5_error_code hdb_samba4_set_steal_client_audit_info(astgs_request_t r,
578                                                        struct authn_audit_info *client_audit_info)
579 {
580         return hdb_samba4_set_steal_audit_info(r,
581                                                SAMBA_HDB_CLIENT_AUDIT_INFO,
582                                                client_audit_info);
583 }
584
585 static const struct authn_audit_info *hdb_samba4_get_client_audit_info(hdb_request_t r)
586 {
587         const struct hdb_audit_info_obj *audit_info_obj = NULL;
588
589         audit_info_obj = heim_audit_getkv((heim_svc_req_desc)r, SAMBA_HDB_CLIENT_AUDIT_INFO);
590         if (audit_info_obj == NULL) {
591                 return NULL;
592         }
593
594         return audit_info_obj->audit_info;
595 }
596
597 /*
598  * Set talloc-allocated server auditing information of the KDC request. On
599  * success, â€˜server_audit_info’ is invalidated and may no longer be used by the
600  * caller.
601  */
602 krb5_error_code hdb_samba4_set_steal_server_audit_info(astgs_request_t r,
603                                                        struct authn_audit_info *server_audit_info)
604 {
605         return hdb_samba4_set_steal_audit_info(r,
606                                                SAMBA_HDB_SERVER_AUDIT_INFO,
607                                                server_audit_info);
608 }
609
610 static const struct authn_audit_info *hdb_samba4_get_server_audit_info(hdb_request_t r)
611 {
612         const struct hdb_audit_info_obj *audit_info_obj = NULL;
613
614         audit_info_obj = heim_audit_getkv((heim_svc_req_desc)r, SAMBA_HDB_SERVER_AUDIT_INFO);
615         if (audit_info_obj == NULL) {
616                 return NULL;
617         }
618
619         return audit_info_obj->audit_info;
620 }
621
622 struct hdb_ntstatus_obj {
623         NTSTATUS status;
624         krb5_error_code current_error;
625 };
626
627 /*
628  * Add an NTSTATUS code to a Kerberos request. â€˜error’ is the error value we
629  * want to return to the client. When it comes time to generating the error
630  * request, we shall compare this error value to whatever error we are about to
631  * return; if the two match, we shall replace the â€˜e-data’ field in the reply
632  * with the NTSTATUS code.
633  */
634 krb5_error_code hdb_samba4_set_ntstatus(astgs_request_t r,
635                                         const NTSTATUS status,
636                                         const krb5_error_code error)
637 {
638         struct hdb_ntstatus_obj *status_obj = NULL;
639
640         status_obj = kdc_object_alloc(sizeof (*status_obj),
641                                       SAMBA_HDB_NT_STATUS_OBJ,
642                                       NULL);
643         if (status_obj == NULL) {
644                 return ENOMEM;
645         }
646
647         *status_obj = (struct hdb_ntstatus_obj) {
648                 .status = status,
649                 .current_error = error,
650         };
651
652         heim_audit_setkv_object((heim_svc_req_desc)r, SAMBA_HDB_NT_STATUS, status_obj);
653         heim_release(status_obj);
654
655         return 0;
656 }
657
658 static krb5_error_code hdb_samba4_make_nt_status_edata(const NTSTATUS status,
659                                                        const uint32_t flags,
660                                                        krb5_data *edata_out)
661 {
662     const uint32_t status_code = NT_STATUS_V(status);
663     const uint32_t zero = 0;
664     KERB_ERROR_DATA error_data;
665     krb5_data e_data;
666
667     krb5_error_code ret;
668     size_t size;
669
670     /* The raw KERB-ERR-TYPE-EXTENDED structure. */
671     uint8_t data[12];
672
673     PUSH_LE_U32(data, 0, status_code);
674     PUSH_LE_U32(data, 4, zero);
675     PUSH_LE_U32(data, 8, flags);
676
677     e_data = (krb5_data) {
678             .data = &data,
679             .length = sizeof(data),
680     };
681
682     error_data = (KERB_ERROR_DATA) {
683             .data_type = kERB_ERR_TYPE_EXTENDED,
684             .data_value = &e_data,
685     };
686
687     ASN1_MALLOC_ENCODE(KERB_ERROR_DATA,
688                        edata_out->data, edata_out->length,
689                        &error_data,
690                        &size, ret);
691     if (ret) {
692             return ret;
693     }
694     if (size != edata_out->length) {
695             /* Internal ASN.1 encoder error */
696             krb5_data_free(edata_out);
697             return KRB5KRB_ERR_GENERIC;
698     }
699
700     return 0;
701 }
702
703 static krb5_error_code hdb_samba4_set_edata_from_ntstatus(hdb_request_t r, const NTSTATUS status)
704 {
705         const KDC_REQ *req = kdc_request_get_req((astgs_request_t)r);
706         krb5_error_code ret = 0;
707         krb5_data e_data;
708         uint32_t flags = 1;
709
710         if (req->msg_type == krb_tgs_req) {
711                 /* This flag is used to indicate a TGS-REQ. */
712                 flags |= 2;
713         }
714
715         ret = hdb_samba4_make_nt_status_edata(status, flags, &e_data);
716         if (ret) {
717                 return ret;
718         }
719
720         ret = kdc_request_set_e_data((astgs_request_t)r, e_data);
721         if (ret) {
722                 krb5_data_free(&e_data);
723         }
724
725         return ret;
726 }
727
728 static NTSTATUS hdb_samba4_get_ntstatus(hdb_request_t r)
729 {
730         struct hdb_ntstatus_obj *status_obj = NULL;
731
732         status_obj = heim_audit_getkv((heim_svc_req_desc)r, SAMBA_HDB_NT_STATUS);
733         if (status_obj == NULL) {
734                 return NT_STATUS_OK;
735         }
736
737         if (r->error_code != status_obj->current_error) {
738                 /*
739                  * The error code has changed from what we expect. Consider the
740                  * NTSTATUS to be invalidated.
741                  */
742                 return NT_STATUS_OK;
743         }
744
745         return status_obj->status;
746 }
747
748 static krb5_error_code hdb_samba4_tgs_audit(const struct samba_kdc_db_context *kdc_db_ctx,
749                                             const hdb_entry *entry,
750                                             hdb_request_t r)
751 {
752         TALLOC_CTX *frame = talloc_stackframe();
753         const struct authn_audit_info *server_audit_info = NULL;
754         struct tsocket_address *remote_host = NULL;
755         struct samba_kdc_entry *client_entry = NULL;
756         struct dom_sid sid_buf = {};
757         const char *account_name = NULL;
758         const char *domain_name = NULL;
759         const struct dom_sid *sid = NULL;
760         size_t sa_socklen = 0;
761         NTSTATUS auth_status = NT_STATUS_OK;
762         krb5_error_code ret = 0;
763         krb5_error_code final_ret = 0;
764
765         /* Have we got a status code indicating an error? */
766         auth_status = hdb_samba4_get_ntstatus(r);
767         if (!NT_STATUS_IS_OK(auth_status)) {
768                 /*
769                  * Include this status code in the â€˜e-data’ field of the reply.
770                  */
771                 ret = hdb_samba4_set_edata_from_ntstatus(r, auth_status);
772                 if (ret) {
773                         final_ret = ret;
774                 }
775         } else if (entry == NULL) {
776                 auth_status = NT_STATUS_NO_SUCH_USER;
777         } else if (r->error_code) {
778                 /*
779                  * Don’t include a status code in the reply. Just log the
780                  * request as being unsuccessful.
781                  */
782                 auth_status = NT_STATUS_UNSUCCESSFUL;
783         }
784
785         switch (r->addr->sa_family) {
786         case AF_INET:
787                 sa_socklen = sizeof(struct sockaddr_in);
788                 break;
789 #ifdef HAVE_IPV6
790         case AF_INET6:
791                 sa_socklen = sizeof(struct sockaddr_in6);
792                 break;
793 #endif
794         }
795
796         ret = tsocket_address_bsd_from_sockaddr(frame, r->addr,
797                                                 sa_socklen,
798                                                 &remote_host);
799         if (ret != 0) {
800                 remote_host = NULL;
801                 /* Ignore the error. */
802         }
803
804         server_audit_info = hdb_samba4_get_server_audit_info(r);
805
806         if (entry != NULL) {
807                 client_entry = talloc_get_type_abort(entry->context,
808                                                      struct samba_kdc_entry);
809
810                 ret = samdb_result_dom_sid_buf(client_entry->msg, "objectSid", &sid_buf);
811                 if (ret) {
812                         /* Ignore the error. */
813                 } else {
814                         sid = &sid_buf;
815                 }
816
817                 account_name = ldb_msg_find_attr_as_string(client_entry->msg, "sAMAccountName", NULL);
818                 domain_name = lpcfg_sam_name(kdc_db_ctx->lp_ctx);
819         }
820
821         log_authz_event(kdc_db_ctx->msg_ctx,
822                         kdc_db_ctx->lp_ctx,
823                         remote_host,
824                         NULL /* local */,
825                         server_audit_info,
826                         r->sname,
827                         "TGS-REQ with Ticket-Granting Ticket",
828                         domain_name,
829                         account_name,
830                         sid,
831                         lpcfg_netbios_name(kdc_db_ctx->lp_ctx),
832                         krb5_kdc_get_time(),
833                         auth_status);
834
835         talloc_free(frame);
836         if (final_ret) {
837                 r->error_code = final_ret;
838         }
839         return final_ret;
840 }
841
842 static krb5_error_code hdb_samba4_audit(krb5_context context,
843                                         HDB *db,
844                                         hdb_entry *entry,
845                                         hdb_request_t r)
846 {
847         struct samba_kdc_db_context *kdc_db_ctx = talloc_get_type_abort(db->hdb_db,
848                                                                         struct samba_kdc_db_context);
849         struct ldb_dn *domain_dn = ldb_get_default_basedn(kdc_db_ctx->samdb);
850         heim_object_t auth_details_obj = NULL;
851         const char *auth_details = NULL;
852         char *etype_str = NULL;
853         heim_object_t hdb_auth_status_obj = NULL;
854         int hdb_auth_status;
855         heim_object_t pa_type_obj = NULL;
856         const char *pa_type = NULL;
857         struct auth_usersupplied_info ui;
858         size_t sa_socklen = 0;
859         const KDC_REQ *req = kdc_request_get_req((astgs_request_t)r);
860         krb5_error_code final_ret = 0;
861         NTSTATUS edata_status;
862
863         if (req->msg_type == krb_tgs_req) {
864                 return hdb_samba4_tgs_audit(kdc_db_ctx, entry, r);
865         }
866
867         if (r->error_code == KRB5KDC_ERR_PREAUTH_REQUIRED) {
868                 /* Let’s not log PREAUTH_REQUIRED errors. */
869                 return 0;
870         }
871
872         edata_status = hdb_samba4_get_ntstatus(r);
873
874         hdb_auth_status_obj = heim_audit_getkv((heim_svc_req_desc)r, KDC_REQUEST_KV_AUTH_EVENT);
875         if (hdb_auth_status_obj == NULL) {
876                 /* No status code found, so just return. */
877                 return 0;
878         }
879
880         hdb_auth_status = heim_number_get_int(hdb_auth_status_obj);
881
882         pa_type_obj = heim_audit_getkv((heim_svc_req_desc)r, KDC_REQUEST_KV_PA_NAME);
883         if (pa_type_obj != NULL) {
884                 pa_type = heim_string_get_utf8(pa_type_obj);
885         }
886
887         auth_details_obj = heim_audit_getkv((heim_svc_req_desc)r, KDC_REQUEST_KV_PKINIT_CLIENT_CERT);
888         if (auth_details_obj != NULL) {
889                 auth_details = heim_string_get_utf8(auth_details_obj);
890         } else {
891                 auth_details_obj = heim_audit_getkv((heim_svc_req_desc)r, KDC_REQUEST_KV_GSS_INITIATOR);
892                 if (auth_details_obj != NULL) {
893                         auth_details = heim_string_get_utf8(auth_details_obj);
894                 } else {
895                         heim_object_t etype_obj = heim_audit_getkv((heim_svc_req_desc)r, KDC_REQUEST_KV_PA_ETYPE);
896                         if (etype_obj != NULL) {
897                                 int etype = heim_number_get_int(etype_obj);
898
899                                 krb5_error_code ret = krb5_enctype_to_string(r->context, etype, &etype_str);
900                                 if (ret == 0) {
901                                         auth_details = etype_str;
902                                 } else {
903                                         auth_details = "unknown enctype";
904                                 }
905                         }
906                 }
907         }
908
909         /*
910          * Forcing this via the NTLM auth structure is not ideal, but
911          * it is the most practical option right now, and ensures the
912          * logs are consistent, even if some elements are always NULL.
913          */
914         ui = (struct auth_usersupplied_info) {
915                 .was_mapped = true,
916                 .client = {
917                         .account_name = r->cname,
918                         .domain_name = NULL,
919                 },
920                 .service_description = "Kerberos KDC",
921                 .auth_description = "Unknown Auth Description",
922                 .password_type = auth_details,
923                 .logon_id = generate_random_u64(),
924         };
925
926         switch (r->addr->sa_family) {
927         case AF_INET:
928                 sa_socklen = sizeof(struct sockaddr_in);
929                 break;
930 #ifdef HAVE_IPV6
931         case AF_INET6:
932                 sa_socklen = sizeof(struct sockaddr_in6);
933                 break;
934 #endif
935         }
936
937         switch (hdb_auth_status) {
938         default:
939         {
940                 TALLOC_CTX *frame = talloc_stackframe();
941                 struct samba_kdc_entry *p = talloc_get_type_abort(entry->context,
942                                                                   struct samba_kdc_entry);
943                 struct dom_sid *sid
944                         = samdb_result_dom_sid(frame, p->msg, "objectSid");
945                 const char *account_name
946                         = ldb_msg_find_attr_as_string(p->msg, "sAMAccountName", NULL);
947                 const char *domain_name = lpcfg_sam_name(p->kdc_db_ctx->lp_ctx);
948                 struct tsocket_address *remote_host;
949                 const char *auth_description = NULL;
950                 const struct authn_audit_info *client_audit_info = NULL;
951                 const struct authn_audit_info *server_audit_info = NULL;
952                 NTSTATUS status;
953                 int ret;
954                 bool rwdc_fallback = false;
955
956                 ret = tsocket_address_bsd_from_sockaddr(frame, r->addr,
957                                                         sa_socklen,
958                                                         &remote_host);
959                 if (ret != 0) {
960                         ui.remote_host = NULL;
961                 } else {
962                         ui.remote_host = remote_host;
963                 }
964
965                 ui.mapped.account_name = account_name;
966                 ui.mapped.domain_name = domain_name;
967
968                 if (pa_type != NULL) {
969                         auth_description = talloc_asprintf(frame,
970                                                            "%s Pre-authentication",
971                                                            pa_type);
972                         if (auth_description == NULL) {
973                                 auth_description = pa_type;
974                         }
975                 } else {
976                         auth_description = "Unknown Pre-authentication";
977                 }
978                 ui.auth_description = auth_description;
979
980                 if (hdb_auth_status == KDC_AUTH_EVENT_CLIENT_AUTHORIZED) {
981                         struct netr_SendToSamBase *send_to_sam = NULL;
982
983                         /*
984                          * TODO: We could log the AS-REQ authorization success here as
985                          * well.  However before we do that, we need to pass
986                          * in the PAC here or re-calculate it.
987                          */
988                         status = authsam_logon_success_accounting(kdc_db_ctx->samdb, p->msg,
989                                                                   domain_dn, true, frame, &send_to_sam);
990                         if (NT_STATUS_EQUAL(status, NT_STATUS_ACCOUNT_LOCKED_OUT)) {
991                                 edata_status = status;
992
993                                 r->error_code = final_ret = KRB5KDC_ERR_CLIENT_REVOKED;
994                                 rwdc_fallback = kdc_db_ctx->rodc;
995                         } else if (!NT_STATUS_IS_OK(status)) {
996                                 r->error_code = final_ret = KRB5KDC_ERR_CLIENT_REVOKED;
997                                 rwdc_fallback = kdc_db_ctx->rodc;
998                         } else {
999                                 if (r->error_code == KRB5KDC_ERR_NEVER_VALID) {
1000                                         edata_status = status = NT_STATUS_TIME_DIFFERENCE_AT_DC;
1001                                 } else {
1002                                         status = krb5_to_nt_status(r->error_code);
1003                                 }
1004
1005                                 if (kdc_db_ctx->rodc && send_to_sam != NULL) {
1006                                         reset_bad_password_netlogon(frame, kdc_db_ctx, send_to_sam);
1007                                 }
1008                         }
1009
1010                         /* This is the final success */
1011                 } else if (hdb_auth_status == KDC_AUTH_EVENT_VALIDATED_LONG_TERM_KEY) {
1012                         /*
1013                          * This was only a pre-authentication success,
1014                          * but we didn't reach the final
1015                          * KDC_AUTH_EVENT_CLIENT_AUTHORIZED,
1016                          * so consult the error code.
1017                          */
1018                         if (r->error_code == 0) {
1019                                 DBG_ERR("ERROR: VALIDATED_LONG_TERM_KEY "
1020                                         "with error=0 => INTERNAL_ERROR\n");
1021                                 status = NT_STATUS_INTERNAL_ERROR;
1022                                 r->error_code = final_ret = KRB5KRB_ERR_GENERIC;
1023                         } else if (!NT_STATUS_IS_OK(p->reject_status)) {
1024                                 status = p->reject_status;
1025                         } else {
1026                                 status = krb5_to_nt_status(r->error_code);
1027                         }
1028                 } else if (hdb_auth_status == KDC_AUTH_EVENT_PREAUTH_SUCCEEDED) {
1029                         /*
1030                          * This was only a pre-authentication success,
1031                          * but we didn't reach the final
1032                          * KDC_AUTH_EVENT_CLIENT_AUTHORIZED,
1033                          * so consult the error code.
1034                          */
1035                         if (r->error_code == 0) {
1036                                 DBG_ERR("ERROR: PREAUTH_SUCCEEDED "
1037                                         "with error=0 => INTERNAL_ERROR\n");
1038                                 status = NT_STATUS_INTERNAL_ERROR;
1039                                 r->error_code = final_ret = KRB5KRB_ERR_GENERIC;
1040                         } else if (!NT_STATUS_IS_OK(p->reject_status)) {
1041                                 status = p->reject_status;
1042                         } else {
1043                                 status = krb5_to_nt_status(r->error_code);
1044                         }
1045                 } else if (hdb_auth_status == KDC_AUTH_EVENT_CLIENT_FOUND) {
1046                         /*
1047                          * We found the client principal,
1048                          * but we didn’t reach the final
1049                          * KDC_AUTH_EVENT_CLIENT_AUTHORIZED,
1050                          * so consult the error code.
1051                          */
1052                         if (r->error_code == 0) {
1053                                 DBG_ERR("ERROR: CLIENT_FOUND "
1054                                         "with error=0 => INTERNAL_ERROR\n");
1055                                 status = NT_STATUS_INTERNAL_ERROR;
1056                                 r->error_code = final_ret = KRB5KRB_ERR_GENERIC;
1057                         } else if (!NT_STATUS_IS_OK(p->reject_status)) {
1058                                 status = p->reject_status;
1059                         } else {
1060                                 status = krb5_to_nt_status(r->error_code);
1061                         }
1062                 } else if (hdb_auth_status == KDC_AUTH_EVENT_CLIENT_TIME_SKEW) {
1063                         status = NT_STATUS_TIME_DIFFERENCE_AT_DC;
1064                 } else if (hdb_auth_status == KDC_AUTH_EVENT_WRONG_LONG_TERM_KEY) {
1065                         status = authsam_update_bad_pwd_count(kdc_db_ctx->samdb, p->msg, domain_dn);
1066                         if (NT_STATUS_EQUAL(status, NT_STATUS_ACCOUNT_LOCKED_OUT)) {
1067                                 edata_status = status;
1068
1069                                 r->error_code = final_ret = KRB5KDC_ERR_CLIENT_REVOKED;
1070                         } else {
1071                                 status = NT_STATUS_WRONG_PASSWORD;
1072                         }
1073                         rwdc_fallback = kdc_db_ctx->rodc;
1074                 } else if (hdb_auth_status == KDC_AUTH_EVENT_HISTORIC_LONG_TERM_KEY) {
1075                         /*
1076                          * The pre-authentication succeeds with a password
1077                          * from the password history, so we don't
1078                          * update the badPwdCount, but still return
1079                          * PREAUTH_FAILED and need to forward to
1080                          * a RWDC in order to produce an authoritative
1081                          * response for the client.
1082                          */
1083                         status = NT_STATUS_WRONG_PASSWORD;
1084                         rwdc_fallback = kdc_db_ctx->rodc;
1085                 } else if (hdb_auth_status == KDC_AUTH_EVENT_CLIENT_LOCKED_OUT) {
1086                         edata_status = status = NT_STATUS_ACCOUNT_LOCKED_OUT;
1087                         rwdc_fallback = kdc_db_ctx->rodc;
1088                 } else if (hdb_auth_status == KDC_AUTH_EVENT_CLIENT_NAME_UNAUTHORIZED) {
1089                         if (pa_type != NULL && strncmp(pa_type, "PK-INIT", strlen("PK-INIT")) == 0) {
1090                                 status = NT_STATUS_PKINIT_NAME_MISMATCH;
1091                         } else {
1092                                 status = NT_STATUS_ACCOUNT_RESTRICTION;
1093                         }
1094                         rwdc_fallback = kdc_db_ctx->rodc;
1095                 } else if (hdb_auth_status == KDC_AUTH_EVENT_PREAUTH_FAILED) {
1096                         if (pa_type != NULL && strncmp(pa_type, "PK-INIT", strlen("PK-INIT")) == 0) {
1097                                 status = NT_STATUS_PKINIT_FAILURE;
1098                         } else {
1099                                 status = NT_STATUS_GENERIC_COMMAND_FAILED;
1100                         }
1101                         rwdc_fallback = kdc_db_ctx->rodc;
1102                 } else {
1103                         DBG_ERR("Unhandled hdb_auth_status=%d => INTERNAL_ERROR\n",
1104                                 hdb_auth_status);
1105                         status = NT_STATUS_INTERNAL_ERROR;
1106                         r->error_code = final_ret = KRB5KRB_ERR_GENERIC;
1107                 }
1108
1109                 if (!NT_STATUS_IS_OK(edata_status)) {
1110                         krb5_error_code code;
1111
1112                         code = hdb_samba4_set_edata_from_ntstatus(r, edata_status);
1113                         if (code) {
1114                                 r->error_code = final_ret = code;
1115                         }
1116                 }
1117
1118                 if (rwdc_fallback) {
1119                         /*
1120                          * Forward the request to an RWDC in order
1121                          * to give an authoritative answer to the client.
1122                          */
1123                         auth_description = talloc_asprintf(frame,
1124                                                            "%s,Forward-To-RWDC",
1125                                                            ui.auth_description);
1126                         if (auth_description != NULL) {
1127                                 ui.auth_description = auth_description;
1128                         }
1129                         final_ret = HDB_ERR_NOT_FOUND_HERE;
1130                 }
1131
1132                 client_audit_info = hdb_samba4_get_client_audit_info(r);
1133                 server_audit_info = hdb_samba4_get_server_audit_info(r);
1134
1135                 log_authentication_event(kdc_db_ctx->msg_ctx,
1136                                          kdc_db_ctx->lp_ctx,
1137                                          &r->tv_start,
1138                                          &ui,
1139                                          status,
1140                                          domain_name,
1141                                          account_name,
1142                                          sid,
1143                                          client_audit_info,
1144                                          server_audit_info);
1145                 if (final_ret == KRB5KRB_ERR_GENERIC && socket_wrapper_enabled()) {
1146                         /*
1147                          * If we're running under make test
1148                          * just panic
1149                          */
1150                         DBG_ERR("Unexpected situation => PANIC\n");
1151                         smb_panic("hdb_samba4_audit: Unexpected situation");
1152                 }
1153                 TALLOC_FREE(frame);
1154                 break;
1155         }
1156         case KDC_AUTH_EVENT_CLIENT_UNKNOWN:
1157         {
1158                 struct tsocket_address *remote_host;
1159                 int ret;
1160                 TALLOC_CTX *frame = talloc_stackframe();
1161                 ret = tsocket_address_bsd_from_sockaddr(frame, r->addr,
1162                                                         sa_socklen,
1163                                                         &remote_host);
1164                 if (ret != 0) {
1165                         ui.remote_host = NULL;
1166                 } else {
1167                         ui.remote_host = remote_host;
1168                 }
1169
1170                 if (pa_type == NULL) {
1171                         pa_type = "AS-REQ";
1172                 }
1173
1174                 ui.auth_description = pa_type;
1175
1176                 /* Note this is not forwarded to an RWDC */
1177
1178                 log_authentication_event(kdc_db_ctx->msg_ctx,
1179                                          kdc_db_ctx->lp_ctx,
1180                                          &r->tv_start,
1181                                          &ui,
1182                                          NT_STATUS_NO_SUCH_USER,
1183                                          NULL, NULL,
1184                                          NULL,
1185                                          NULL /* client_audit_info */,
1186                                          NULL /* server_audit_info */);
1187                 TALLOC_FREE(frame);
1188                 break;
1189         }
1190         }
1191
1192         free(etype_str);
1193
1194         return final_ret;
1195 }
1196
1197 /* This interface is to be called by the KDC and libnet_keytab_dump,
1198  * which is expecting Samba calling conventions.
1199  * It is also called by a wrapper (hdb_samba4_create) from the
1200  * kpasswdd -> krb5 -> keytab_hdb -> hdb code */
1201
1202 NTSTATUS hdb_samba4_create_kdc(struct samba_kdc_base_context *base_ctx,
1203                                krb5_context context, struct HDB **db)
1204 {
1205         struct samba_kdc_db_context *kdc_db_ctx = NULL;
1206         NTSTATUS nt_status;
1207
1208         if (hdb_interface_version != HDB_INTERFACE_VERSION) {
1209                 krb5_set_error_message(context, EINVAL, "Heimdal HDB interface version mismatch between build-time and run-time libraries!");
1210                 return NT_STATUS_ERROR_DS_INCOMPATIBLE_VERSION;
1211         }
1212
1213         *db = talloc_zero(base_ctx, HDB);
1214         if (!*db) {
1215                 krb5_set_error_message(context, ENOMEM, "talloc_zero: out of memory");
1216                 return NT_STATUS_NO_MEMORY;
1217         }
1218
1219         (*db)->hdb_master_key_set = 0;
1220         (*db)->hdb_db = NULL;
1221         (*db)->hdb_capability_flags = HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL;
1222
1223         nt_status = samba_kdc_setup_db_ctx(*db, base_ctx, &kdc_db_ctx);
1224         if (!NT_STATUS_IS_OK(nt_status)) {
1225                 talloc_free(*db);
1226                 return nt_status;
1227         }
1228         (*db)->hdb_db = kdc_db_ctx;
1229
1230         (*db)->hdb_dbc = NULL;
1231         (*db)->hdb_open = hdb_samba4_open;
1232         (*db)->hdb_close = hdb_samba4_close;
1233         (*db)->hdb_free_entry_context = hdb_samba4_free_entry_context;
1234         (*db)->hdb_fetch_kvno = hdb_samba4_fetch_kvno;
1235         (*db)->hdb_store = hdb_samba4_store;
1236         (*db)->hdb_firstkey = hdb_samba4_firstkey;
1237         (*db)->hdb_nextkey = hdb_samba4_nextkey;
1238         (*db)->hdb_lock = hdb_samba4_lock;
1239         (*db)->hdb_unlock = hdb_samba4_unlock;
1240         (*db)->hdb_set_sync = hdb_samba4_set_sync;
1241         (*db)->hdb_rename = hdb_samba4_rename;
1242         /* we don't implement these, as we are not a lockable database */
1243         (*db)->hdb__get = NULL;
1244         (*db)->hdb__put = NULL;
1245         /* kadmin should not be used for deletes - use other tools instead */
1246         (*db)->hdb__del = NULL;
1247         (*db)->hdb_destroy = hdb_samba4_destroy;
1248
1249         (*db)->hdb_audit = hdb_samba4_audit;
1250         (*db)->hdb_check_constrained_delegation = hdb_samba4_check_constrained_delegation;
1251         (*db)->hdb_check_rbcd = hdb_samba4_check_rbcd;
1252         (*db)->hdb_check_pkinit_ms_upn_match = hdb_samba4_check_pkinit_ms_upn_match;
1253         (*db)->hdb_check_client_matches_target_service = hdb_samba4_check_client_matches_target_service;
1254
1255         return NT_STATUS_OK;
1256 }
1257
1258 NTSTATUS hdb_samba4_kpasswd_create_kdc(struct samba_kdc_base_context *base_ctx,
1259                                        krb5_context context, struct HDB **db)
1260 {
1261         NTSTATUS nt_status;
1262
1263         nt_status = hdb_samba4_create_kdc(base_ctx, context, db);
1264         if (!NT_STATUS_IS_OK(nt_status)) {
1265                 return nt_status;
1266         }
1267
1268         (*db)->hdb_fetch_kvno = hdb_samba4_kpasswd_fetch_kvno;
1269         (*db)->hdb_firstkey = hdb_samba4_nextkey_panic;
1270         (*db)->hdb_nextkey = hdb_samba4_nextkey_panic;
1271
1272         return NT_STATUS_OK;
1273 }