LCOV - code coverage report
Current view: top level - source4/kdc - hdb-samba4.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 404 569 71.0 %
Date: 2024-04-21 15:09:00 Functions: 25 34 73.5 %

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

Generated by: LCOV version 1.14