LCOV - code coverage report
Current view: top level - source4/rpc_server/netlogon - dcerpc_netlogon.c (source / functions) Hit Total Coverage
Test: coverage report for master 70ed9daf Lines: 1639 2077 78.9 %
Date: 2024-01-11 09:59:51 Functions: 58 68 85.3 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    endpoint server for the netlogon pipe
       5             : 
       6             :    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008
       7             :    Copyright (C) Stefan Metzmacher <metze@samba.org>  2005
       8             :    Copyright (C) Matthias Dieter Wallnöfer            2009-2010
       9             : 
      10             :    This program is free software; you can redistribute it and/or modify
      11             :    it under the terms of the GNU General Public License as published by
      12             :    the Free Software Foundation; either version 3 of the License, or
      13             :    (at your option) any later version.
      14             : 
      15             :    This program is distributed in the hope that it will be useful,
      16             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :    GNU General Public License for more details.
      19             : 
      20             :    You should have received a copy of the GNU General Public License
      21             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      22             : */
      23             : 
      24             : #include "includes.h"
      25             : #include "rpc_server/dcerpc_server.h"
      26             : #include "rpc_server/common/common.h"
      27             : #include "auth/auth.h"
      28             : #include "auth/auth_sam_reply.h"
      29             : #include "dsdb/samdb/samdb.h"
      30             : #include "../lib/util/util_ldb.h"
      31             : #include "../libcli/auth/schannel.h"
      32             : #include "libcli/security/security.h"
      33             : #include "param/param.h"
      34             : #include "lib/messaging/irpc.h"
      35             : #include "librpc/gen_ndr/ndr_irpc_c.h"
      36             : #include "../libcli/ldap/ldap_ndr.h"
      37             : #include "dsdb/samdb/ldb_modules/util.h"
      38             : #include "lib/tsocket/tsocket.h"
      39             : #include "librpc/gen_ndr/ndr_netlogon.h"
      40             : #include "librpc/gen_ndr/ndr_lsa.h"
      41             : #include "librpc/gen_ndr/ndr_samr.h"
      42             : #include "librpc/gen_ndr/ndr_irpc.h"
      43             : #include "librpc/gen_ndr/ndr_winbind.h"
      44             : #include "librpc/gen_ndr/ndr_winbind_c.h"
      45             : #include "librpc/rpc/server/netlogon/schannel_util.h"
      46             : #include "lib/socket/netif.h"
      47             : #include "lib/util/util_str_escape.h"
      48             : #include "lib/param/loadparm.h"
      49             : 
      50             : #define DCESRV_INTERFACE_NETLOGON_BIND(context, iface) \
      51             :        dcesrv_interface_netlogon_bind(context, iface)
      52             : 
      53             : #undef strcasecmp
      54             : 
      55             : /*
      56             :  * This #define allows the netlogon interface to accept invalid
      57             :  * association groups, because association groups are to coordinate
      58             :  * handles, and handles are not used in NETLOGON. This in turn avoids
      59             :  * the need to coordinate these across multiple possible NETLOGON
      60             :  * processes
      61             :  */
      62             : #define DCESRV_INTERFACE_NETLOGON_FLAGS DCESRV_INTERFACE_FLAGS_HANDLES_NOT_USED
      63             : 
      64        2955 : static NTSTATUS dcesrv_interface_netlogon_bind(struct dcesrv_connection_context *context,
      65             :                                                const struct dcesrv_interface *iface)
      66             : {
      67        2955 :         struct loadparm_context *lp_ctx = context->conn->dce_ctx->lp_ctx;
      68        2955 :         bool global_allow_nt4_crypto = lpcfg_allow_nt4_crypto(lp_ctx);
      69        2955 :         bool global_reject_md5_client = lpcfg_reject_md5_clients(lp_ctx);
      70        2955 :         int schannel = lpcfg_server_schannel(lp_ctx);
      71        2955 :         bool schannel_global_required = (schannel == true);
      72        2955 :         bool global_require_seal = lpcfg_server_schannel_require_seal(lp_ctx);
      73         270 :         static bool warned_global_nt4_once = false;
      74         270 :         static bool warned_global_md5_once = false;
      75         270 :         static bool warned_global_schannel_once = false;
      76         270 :         static bool warned_global_seal_once = false;
      77             : 
      78        2955 :         if (global_allow_nt4_crypto && !warned_global_nt4_once) {
      79             :                 /*
      80             :                  * We want admins to notice their misconfiguration!
      81             :                  */
      82           0 :                 D_ERR("CVE-2022-38023 (and others): "
      83             :                       "Please configure 'allow nt4 crypto = no' (the default), "
      84             :                       "See https://bugzilla.samba.org/show_bug.cgi?id=15240\n");
      85           0 :                 warned_global_nt4_once = true;
      86             :         }
      87             : 
      88        2955 :         if (!global_reject_md5_client && !warned_global_md5_once) {
      89             :                 /*
      90             :                  * We want admins to notice their misconfiguration!
      91             :                  */
      92           0 :                 D_ERR("CVE-2022-38023: "
      93             :                       "Please configure 'reject md5 clients = yes' (the default), "
      94             :                       "See https://bugzilla.samba.org/show_bug.cgi?id=15240\n");
      95           0 :                 warned_global_md5_once = true;
      96             :         }
      97             : 
      98        2955 :         if (!schannel_global_required && !warned_global_schannel_once) {
      99             :                 /*
     100             :                  * We want admins to notice their misconfiguration!
     101             :                  */
     102           0 :                 D_ERR("CVE-2020-1472(ZeroLogon): "
     103             :                       "Please configure 'server schannel = yes' (the default), "
     104             :                       "See https://bugzilla.samba.org/show_bug.cgi?id=14497\n");
     105           0 :                 warned_global_schannel_once = true;
     106             :         }
     107             : 
     108        2955 :         if (!global_require_seal && !warned_global_seal_once) {
     109             :                 /*
     110             :                  * We want admins to notice their misconfiguration!
     111             :                  */
     112           0 :                 D_ERR("CVE-2022-38023 (and others): "
     113             :                       "Please configure 'server schannel require seal = yes' (the default), "
     114             :                       "See https://bugzilla.samba.org/show_bug.cgi?id=15240\n");
     115           0 :                 warned_global_seal_once = true;
     116             :         }
     117             : 
     118        2955 :         return dcesrv_interface_bind_reject_connect(context, iface);
     119             : }
     120             : 
     121       10185 : static NTSTATUS dcesrv_netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     122             :                                         struct netr_ServerReqChallenge *r)
     123             : {
     124       10185 :         struct netlogon_server_pipe_state *pipe_state = NULL;
     125         683 :         NTSTATUS ntstatus;
     126             : 
     127       10185 :         ZERO_STRUCTP(r->out.return_credentials);
     128             : 
     129       10185 :         pipe_state = dcesrv_iface_state_find_conn(dce_call,
     130             :                         NETLOGON_SERVER_PIPE_STATE_MAGIC,
     131             :                         struct netlogon_server_pipe_state);
     132       10185 :         TALLOC_FREE(pipe_state);
     133             : 
     134       10185 :         pipe_state = talloc_zero(dce_call,
     135             :                                  struct netlogon_server_pipe_state);
     136       10185 :         if (pipe_state == NULL) {
     137           0 :                 return NT_STATUS_NO_MEMORY;
     138             :         }
     139             : 
     140       10185 :         pipe_state->client_challenge = *r->in.credentials;
     141             : 
     142       10185 :         netlogon_creds_random_challenge(&pipe_state->server_challenge);
     143             : 
     144       10185 :         *r->out.return_credentials = pipe_state->server_challenge;
     145             : 
     146       10185 :         ntstatus = dcesrv_iface_state_store_conn(dce_call,
     147             :                         NETLOGON_SERVER_PIPE_STATE_MAGIC,
     148             :                         pipe_state);
     149       10185 :         if (!NT_STATUS_IS_OK(ntstatus)) {
     150           0 :                 return ntstatus;
     151             :         }
     152             : 
     153       10868 :         ntstatus = schannel_save_challenge(dce_call->conn->dce_ctx->lp_ctx,
     154       10185 :                                            &pipe_state->client_challenge,
     155        9502 :                                            &pipe_state->server_challenge,
     156             :                                            r->in.computer_name);
     157       10185 :         if (!NT_STATUS_IS_OK(ntstatus)) {
     158           0 :                 TALLOC_FREE(pipe_state);
     159           0 :                 return ntstatus;
     160             :         }
     161             : 
     162       10185 :         return NT_STATUS_OK;
     163             : }
     164             : 
     165        1887 : static NTSTATUS dcesrv_netr_ServerAuthenticate3_check_downgrade(
     166             :         struct dcesrv_call_state *dce_call,
     167             :         struct netr_ServerAuthenticate3 *r,
     168             :         struct netlogon_server_pipe_state *pipe_state,
     169             :         uint32_t negotiate_flags,
     170             :         const char *trust_account_in_db,
     171             :         NTSTATUS orig_status)
     172             : {
     173        1887 :         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
     174        1887 :         bool global_allow_nt4_crypto = lpcfg_allow_nt4_crypto(lp_ctx);
     175        1887 :         bool account_allow_nt4_crypto = global_allow_nt4_crypto;
     176        1887 :         const char *explicit_nt4_opt = NULL;
     177        1887 :         bool global_reject_md5_client = lpcfg_reject_md5_clients(lp_ctx);
     178        1887 :         bool account_reject_md5_client = global_reject_md5_client;
     179        1887 :         const char *explicit_md5_opt = NULL;
     180         222 :         bool reject_des_client;
     181         222 :         bool allow_nt4_crypto;
     182         222 :         bool reject_md5_client;
     183        1887 :         bool need_des = true;
     184        1887 :         bool need_md5 = true;
     185        1887 :         int CVE_2022_38023_warn_level = lpcfg_parm_int(lp_ctx, NULL,
     186             :                         "CVE_2022_38023", "warn_about_unused_debug_level", DBGLVL_ERR);
     187        1887 :         int CVE_2022_38023_error_level = lpcfg_parm_int(lp_ctx, NULL,
     188             :                         "CVE_2022_38023", "error_debug_level", DBGLVL_ERR);
     189             : 
     190             :         /*
     191             :          * We don't use lpcfg_parm_bool(), as we
     192             :          * need the explicit_opt pointer in order to
     193             :          * adjust the debug messages.
     194             :          */
     195             : 
     196        1887 :         if (trust_account_in_db != NULL) {
     197        1881 :                 explicit_nt4_opt = lpcfg_get_parametric(lp_ctx,
     198             :                                                         NULL,
     199             :                                                         "allow nt4 crypto",
     200             :                                                         trust_account_in_db);
     201             :         }
     202        1887 :         if (explicit_nt4_opt != NULL) {
     203         393 :                 account_allow_nt4_crypto = lp_bool(explicit_nt4_opt);
     204             :         }
     205        1887 :         allow_nt4_crypto = account_allow_nt4_crypto;
     206        1887 :         if (trust_account_in_db != NULL) {
     207        1881 :                 explicit_md5_opt = lpcfg_get_parametric(lp_ctx,
     208             :                                                         NULL,
     209             :                                                         "server reject md5 schannel",
     210             :                                                         trust_account_in_db);
     211             :         }
     212        1887 :         if (explicit_md5_opt != NULL) {
     213        1146 :                 account_reject_md5_client = lp_bool(explicit_md5_opt);
     214             :         }
     215        1887 :         reject_md5_client = account_reject_md5_client;
     216             : 
     217        1887 :         reject_des_client = !allow_nt4_crypto;
     218             : 
     219             :         /*
     220             :          * If weak crypto is disabled, do not announce that we support RC4.
     221             :          */
     222        1887 :         if (lpcfg_weak_crypto(lp_ctx) == SAMBA_WEAK_CRYPTO_DISALLOWED) {
     223             :                 /* Without RC4 and DES we require AES */
     224           0 :                 reject_des_client = true;
     225           0 :                 reject_md5_client = true;
     226             :         }
     227             : 
     228        1887 :         if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) {
     229        1300 :                 need_des = false;
     230        1300 :                 reject_des_client = false;
     231             :         }
     232             : 
     233        1887 :         if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
     234        1391 :                 need_des = false;
     235        1391 :                 need_md5 = false;
     236        1391 :                 reject_des_client = false;
     237        1391 :                 reject_md5_client = false;
     238             :         }
     239             : 
     240        1887 :         if (reject_des_client || reject_md5_client) {
     241         175 :                 TALLOC_CTX *frame = talloc_stackframe();
     242             : 
     243         175 :                 if (lpcfg_weak_crypto(lp_ctx) == SAMBA_WEAK_CRYPTO_DISALLOWED) {
     244           0 :                         if (CVE_2022_38023_error_level < DBGLVL_NOTICE) {
     245           0 :                                 CVE_2022_38023_error_level = DBGLVL_NOTICE;
     246             :                         }
     247           0 :                         DEBUG(CVE_2022_38023_error_level, (
     248             :                               "CVE-2022-38023: "
     249             :                               "client_account[%s] computer_name[%s] "
     250             :                               "schannel_type[%u] "
     251             :                               "client_negotiate_flags[0x%x] "
     252             :                               "%s%s%s "
     253             :                               "NT_STATUS_DOWNGRADE_DETECTED "
     254             :                               "WEAK_CRYPTO_DISALLOWED\n",
     255             :                               log_escape(frame, r->in.account_name),
     256             :                               log_escape(frame, r->in.computer_name),
     257             :                               r->in.secure_channel_type,
     258             :                               (unsigned)*r->in.negotiate_flags,
     259             :                               trust_account_in_db ? "real_account[" : "",
     260             :                               trust_account_in_db ? trust_account_in_db : "",
     261             :                               trust_account_in_db ? "]" : ""));
     262           0 :                         goto return_downgrade;
     263             :                 }
     264             : 
     265         175 :                 DEBUG(CVE_2022_38023_error_level, (
     266             :                       "CVE-2022-38023: "
     267             :                       "client_account[%s] computer_name[%s] "
     268             :                       "schannel_type[%u] "
     269             :                       "client_negotiate_flags[0x%x] "
     270             :                       "%s%s%s "
     271             :                       "NT_STATUS_DOWNGRADE_DETECTED "
     272             :                       "reject_des[%u] reject_md5[%u]\n",
     273             :                       log_escape(frame, r->in.account_name),
     274             :                       log_escape(frame, r->in.computer_name),
     275             :                       r->in.secure_channel_type,
     276             :                       (unsigned)*r->in.negotiate_flags,
     277             :                       trust_account_in_db ? "real_account[" : "",
     278             :                       trust_account_in_db ? trust_account_in_db : "",
     279             :                       trust_account_in_db ? "]" : "",
     280             :                       reject_des_client,
     281             :                       reject_md5_client));
     282         175 :                 if (trust_account_in_db == NULL) {
     283           4 :                         goto return_downgrade;
     284             :                 }
     285             : 
     286         171 :                 if (reject_md5_client && explicit_md5_opt == NULL) {
     287           0 :                         DEBUG(CVE_2022_38023_error_level, (
     288             :                               "CVE-2022-38023: Check if option "
     289             :                               "'server reject md5 schannel:%s = no' "
     290             :                               "might be needed for a legacy client.\n",
     291             :                               trust_account_in_db));
     292             :                 }
     293         171 :                 if (reject_des_client && explicit_nt4_opt == NULL) {
     294         171 :                         DEBUG(CVE_2022_38023_error_level, (
     295             :                               "CVE-2022-38023: Check if option "
     296             :                               "'allow nt4 crypto:%s = yes' "
     297             :                               "might be needed for a legacy client.\n",
     298             :                               trust_account_in_db));
     299             :                 }
     300             : 
     301           0 : return_downgrade:
     302             :                 /*
     303             :                  * Here we match Windows 2012 and return no flags.
     304             :                  */
     305         175 :                 *r->out.negotiate_flags = 0;
     306         175 :                 TALLOC_FREE(frame);
     307         175 :                 return NT_STATUS_DOWNGRADE_DETECTED;
     308             :         }
     309             : 
     310             :         /*
     311             :          * This talloc_free is important to prevent re-use of the
     312             :          * challenge.  We have to delay it this far due to NETApp
     313             :          * servers per:
     314             :          * https://bugzilla.samba.org/show_bug.cgi?id=11291
     315             :          */
     316        1712 :         TALLOC_FREE(pipe_state);
     317             : 
     318             :         /*
     319             :          * At this point we must also cleanup the TDB cache
     320             :          * entry, if we fail the client needs to call
     321             :          * netr_ServerReqChallenge again.
     322             :          *
     323             :          * Note: this handles a non existing record just fine,
     324             :          * the r->in.computer_name might not be the one used
     325             :          * in netr_ServerReqChallenge(), but we are trying to
     326             :          * just tidy up the normal case to prevent re-use.
     327             :          */
     328        1712 :         schannel_delete_challenge(dce_call->conn->dce_ctx->lp_ctx,
     329             :                                   r->in.computer_name);
     330             : 
     331             :         /*
     332             :          * According to Microsoft (see bugid #6099)
     333             :          * Windows 7 looks at the negotiate_flags
     334             :          * returned in this structure *even if the
     335             :          * call fails with access denied!
     336             :          */
     337        1712 :         *r->out.negotiate_flags = negotiate_flags;
     338             : 
     339        1712 :         if (!NT_STATUS_IS_OK(orig_status) || trust_account_in_db == NULL) {
     340           2 :                 return orig_status;
     341             :         }
     342             : 
     343        1710 :         if (global_reject_md5_client && account_reject_md5_client && explicit_md5_opt) {
     344           0 :                 D_INFO("CVE-2022-38023: Check if option "
     345             :                        "'server reject md5 schannel:%s = yes' not needed!?\n",
     346             :                        trust_account_in_db);
     347        1710 :         } else if (need_md5 && !account_reject_md5_client && explicit_md5_opt) {
     348         321 :                 D_INFO("CVE-2022-38023: Check if option "
     349             :                          "'server reject md5 schannel:%s = no' "
     350             :                          "still needed for a legacy client.\n",
     351             :                          trust_account_in_db);
     352        1389 :         } else if (need_md5 && explicit_md5_opt == NULL) {
     353           0 :                 DEBUG(CVE_2022_38023_error_level, (
     354             :                       "CVE-2022-38023: Check if option "
     355             :                       "'server reject md5 schannel:%s = no' "
     356             :                       "might be needed for a legacy client.\n",
     357             :                       trust_account_in_db));
     358        1389 :         } else if (!account_reject_md5_client && explicit_md5_opt) {
     359         654 :                 DEBUG(CVE_2022_38023_warn_level, (
     360             :                       "CVE-2022-38023: Check if option "
     361             :                       "'server reject md5 schannel:%s = no' not needed!?\n",
     362             :                       trust_account_in_db));
     363             :         }
     364             : 
     365        1710 :         if (!global_allow_nt4_crypto && !account_allow_nt4_crypto && explicit_nt4_opt) {
     366           0 :                 D_INFO("CVE-2022-38023: Check if option "
     367             :                        "'allow nt4 crypto:%s = no' not needed!?\n",
     368             :                        trust_account_in_db);
     369        1710 :         } else if (need_des && account_allow_nt4_crypto && explicit_nt4_opt) {
     370         144 :                 D_INFO("CVE-2022-38023: Check if option "
     371             :                          "'allow nt4 crypto:%s = yes' "
     372             :                          "still needed for a legacy client.\n",
     373             :                          trust_account_in_db);
     374        1566 :         } else if (need_des && explicit_nt4_opt == NULL) {
     375           0 :                 DEBUG(CVE_2022_38023_error_level, (
     376             :                       "CVE-2022-38023: Check if option "
     377             :                       "'allow nt4 crypto:%s = yes' "
     378             :                       "might be needed for a legacy client.\n",
     379             :                       trust_account_in_db));
     380        1566 :         } else if (account_allow_nt4_crypto && explicit_nt4_opt) {
     381         249 :                 DEBUG(CVE_2022_38023_warn_level, (
     382             :                       "CVE-2022-38023: Check if option "
     383             :                       "'allow nt4 crypto:%s = yes' not needed!?\n",
     384             :                       trust_account_in_db));
     385             :         }
     386             : 
     387        1710 :         return orig_status;
     388             : }
     389             : 
     390             : /*
     391             :  * Do the actual processing of a netr_ServerAuthenticate3 message.
     392             :  * called from dcesrv_netr_ServerAuthenticate3, which handles the logging.
     393             :  */
     394        1887 : static NTSTATUS dcesrv_netr_ServerAuthenticate3_helper(
     395             :         struct dcesrv_call_state *dce_call,
     396             :         TALLOC_CTX *mem_ctx,
     397             :         struct netr_ServerAuthenticate3 *r,
     398             :         const char **trust_account_for_search,
     399             :         const char **trust_account_in_db,
     400             :         struct dom_sid **sid)
     401             : {
     402        1887 :         struct netlogon_server_pipe_state *pipe_state = NULL;
     403        1887 :         bool challenge_valid = false;
     404         222 :         struct netlogon_server_pipe_state challenge;
     405         222 :         struct netlogon_creds_CredentialState *creds;
     406         222 :         struct ldb_context *sam_ctx;
     407        1887 :         struct samr_Password *curNtHash = NULL;
     408        1887 :         struct samr_Password *prevNtHash = NULL;
     409         222 :         uint32_t user_account_control;
     410         222 :         int num_records;
     411         222 :         struct ldb_message **msgs;
     412         222 :         NTSTATUS nt_status;
     413        1887 :         const char *attrs[] = {"unicodePwd", "userAccountControl",
     414             :                                "objectSid", "samAccountName", NULL};
     415        1887 :         uint32_t server_flags = 0;
     416        1887 :         uint32_t negotiate_flags = 0;
     417             : 
     418        1887 :         ZERO_STRUCTP(r->out.return_credentials);
     419        1887 :         *r->out.negotiate_flags = 0;
     420        1887 :         *r->out.rid = 0;
     421             : 
     422        1887 :         pipe_state = dcesrv_iface_state_find_conn(dce_call,
     423             :                         NETLOGON_SERVER_PIPE_STATE_MAGIC,
     424             :                         struct netlogon_server_pipe_state);
     425        1887 :         if (pipe_state != NULL) {
     426             :                 /*
     427             :                  * If we had a challenge remembered on the connection
     428             :                  * consider this for usage. This can't be cleanup
     429             :                  * by other clients.
     430             :                  *
     431             :                  * This is the default code path for typical clients
     432             :                  * which call netr_ServerReqChallenge() and
     433             :                  * netr_ServerAuthenticate3() on the same dcerpc connection.
     434             :                  */
     435        1743 :                 challenge = *pipe_state;
     436             : 
     437        1743 :                 challenge_valid = true;
     438             : 
     439             :         } else {
     440          24 :                 NTSTATUS ntstatus;
     441             : 
     442             :                 /*
     443             :                  * Fallback and try to get the challenge from
     444             :                  * the global cache.
     445             :                  *
     446             :                  * If too many clients are using this code path,
     447             :                  * they may destroy their cache entries as the
     448             :                  * TDB has a fixed size limited via a lossy hash
     449             :                  *
     450             :                  * The TDB used is the schannel store, which is
     451             :                  * initialised at startup.
     452             :                  *
     453             :                  * NOTE: The challenge is deleted from the DB as soon as it is
     454             :                  * fetched, to prevent reuse.
     455             :                  *
     456             :                  */
     457             : 
     458         144 :                 ntstatus = schannel_get_challenge(dce_call->conn->dce_ctx->lp_ctx,
     459             :                                                   &challenge.client_challenge,
     460             :                                                   &challenge.server_challenge,
     461             :                                                   r->in.computer_name);
     462             : 
     463         144 :                 if (!NT_STATUS_IS_OK(ntstatus)) {
     464          72 :                         ZERO_STRUCT(challenge);
     465             :                 } else {
     466          60 :                         challenge_valid = true;
     467             :                 }
     468             :         }
     469             : 
     470        1887 :         server_flags = NETLOGON_NEG_ACCOUNT_LOCKOUT |
     471             :                        NETLOGON_NEG_PERSISTENT_SAMREPL |
     472             :                        NETLOGON_NEG_ARCFOUR |
     473             :                        NETLOGON_NEG_PROMOTION_COUNT |
     474             :                        NETLOGON_NEG_CHANGELOG_BDC |
     475             :                        NETLOGON_NEG_FULL_SYNC_REPL |
     476             :                        NETLOGON_NEG_MULTIPLE_SIDS |
     477             :                        NETLOGON_NEG_REDO |
     478             :                        NETLOGON_NEG_PASSWORD_CHANGE_REFUSAL |
     479             :                        NETLOGON_NEG_SEND_PASSWORD_INFO_PDC |
     480             :                        NETLOGON_NEG_GENERIC_PASSTHROUGH |
     481             :                        NETLOGON_NEG_CONCURRENT_RPC |
     482             :                        NETLOGON_NEG_AVOID_ACCOUNT_DB_REPL |
     483             :                        NETLOGON_NEG_AVOID_SECURITYAUTH_DB_REPL |
     484             :                        NETLOGON_NEG_STRONG_KEYS |
     485             :                        NETLOGON_NEG_TRANSITIVE_TRUSTS |
     486             :                        NETLOGON_NEG_DNS_DOMAIN_TRUSTS |
     487             :                        NETLOGON_NEG_PASSWORD_SET2 |
     488             :                        NETLOGON_NEG_GETDOMAININFO |
     489             :                        NETLOGON_NEG_CROSS_FOREST_TRUSTS |
     490             :                        NETLOGON_NEG_NEUTRALIZE_NT4_EMULATION |
     491             :                        NETLOGON_NEG_RODC_PASSTHROUGH |
     492             :                        NETLOGON_NEG_SUPPORTS_AES |
     493             :                        NETLOGON_NEG_AUTHENTICATED_RPC_LSASS |
     494             :                        NETLOGON_NEG_AUTHENTICATED_RPC;
     495             : 
     496             :         /*
     497             :          * If weak crypto is disabled, do not announce that we support RC4.
     498             :          */
     499        1887 :         if (lpcfg_weak_crypto(dce_call->conn->dce_ctx->lp_ctx) ==
     500             :             SAMBA_WEAK_CRYPTO_DISALLOWED) {
     501           0 :                 server_flags &= ~NETLOGON_NEG_ARCFOUR;
     502             :         }
     503             : 
     504        1887 :         negotiate_flags = *r->in.negotiate_flags & server_flags;
     505             : 
     506        1887 :         switch (r->in.secure_channel_type) {
     507        1665 :         case SEC_CHAN_WKSTA:
     508             :         case SEC_CHAN_DNS_DOMAIN:
     509             :         case SEC_CHAN_DOMAIN:
     510             :         case SEC_CHAN_BDC:
     511             :         case SEC_CHAN_RODC:
     512        1887 :                 break;
     513           0 :         case SEC_CHAN_NULL:
     514           0 :                 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
     515             :                                 dce_call, r, pipe_state, negotiate_flags,
     516             :                                 NULL, /* trust_account_in_db */
     517           0 :                                 NT_STATUS_INVALID_PARAMETER);
     518           0 :         default:
     519           0 :                 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
     520             :                           r->in.secure_channel_type));
     521           0 :                 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
     522             :                                 dce_call, r, pipe_state, negotiate_flags,
     523             :                                 NULL, /* trust_account_in_db */
     524           0 :                                 NT_STATUS_INVALID_PARAMETER);
     525             :         }
     526             : 
     527        1887 :         sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
     528        1887 :         if (sam_ctx == NULL) {
     529           0 :                 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
     530             :                                 dce_call, r, pipe_state, negotiate_flags,
     531             :                                 NULL, /* trust_account_in_db */
     532           0 :                                 NT_STATUS_INVALID_SYSTEM_SERVICE);
     533             :         }
     534             : 
     535        1887 :         if (r->in.secure_channel_type == SEC_CHAN_DOMAIN ||
     536        1572 :             r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN)
     537         304 :         {
     538         304 :                 struct ldb_message *tdo_msg = NULL;
     539         304 :                 const char * const tdo_attrs[] = {
     540             :                         "trustAuthIncoming",
     541             :                         "trustAttributes",
     542             :                         "flatName",
     543             :                         NULL
     544             :                 };
     545         304 :                 char *encoded_name = NULL;
     546           0 :                 size_t len;
     547         304 :                 const char *flatname = NULL;
     548         304 :                 char trailer = '$';
     549         304 :                 bool require_trailer = true;
     550         304 :                 const char *netbios = NULL;
     551         304 :                 const char *dns = NULL;
     552             : 
     553         304 :                 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
     554         211 :                         trailer = '.';
     555         211 :                         require_trailer = false;
     556             :                 }
     557             : 
     558         304 :                 encoded_name = ldb_binary_encode_string(mem_ctx,
     559             :                                                         r->in.account_name);
     560         304 :                 if (encoded_name == NULL) {
     561           0 :                         return dcesrv_netr_ServerAuthenticate3_check_downgrade(
     562             :                                 dce_call, r, pipe_state, negotiate_flags,
     563             :                                 NULL, /* trust_account_in_db */
     564           0 :                                 NT_STATUS_NO_MEMORY);
     565             :                 }
     566             : 
     567         304 :                 len = strlen(encoded_name);
     568         304 :                 if (len < 2) {
     569           0 :                         return dcesrv_netr_ServerAuthenticate3_check_downgrade(
     570             :                                 dce_call, r, pipe_state, negotiate_flags,
     571             :                                 NULL, /* trust_account_in_db */
     572           0 :                                 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
     573             :                 }
     574             : 
     575         304 :                 if (require_trailer && encoded_name[len - 1] != trailer) {
     576           0 :                         return dcesrv_netr_ServerAuthenticate3_check_downgrade(
     577             :                                 dce_call, r, pipe_state, negotiate_flags,
     578             :                                 NULL, /* trust_account_in_db */
     579           0 :                                 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
     580             :                 }
     581         304 :                 encoded_name[len - 1] = '\0';
     582             : 
     583         304 :                 if (r->in.secure_channel_type == SEC_CHAN_DNS_DOMAIN) {
     584         211 :                         dns = encoded_name;
     585             :                 } else {
     586          93 :                         netbios = encoded_name;
     587             :                 }
     588             : 
     589         304 :                 nt_status = dsdb_trust_search_tdo(sam_ctx,
     590             :                                                   netbios, dns,
     591             :                                                   tdo_attrs, mem_ctx, &tdo_msg);
     592         304 :                 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
     593           0 :                         DEBUG(2, ("Client asked for a trusted domain secure channel, "
     594             :                                   "but there's no tdo for [%s] => [%s] \n",
     595             :                                   log_escape(mem_ctx, r->in.account_name),
     596             :                                   encoded_name));
     597           0 :                         return dcesrv_netr_ServerAuthenticate3_check_downgrade(
     598             :                                 dce_call, r, pipe_state, negotiate_flags,
     599             :                                 NULL, /* trust_account_in_db */
     600           0 :                                 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
     601             :                 }
     602         304 :                 if (!NT_STATUS_IS_OK(nt_status)) {
     603           0 :                         return dcesrv_netr_ServerAuthenticate3_check_downgrade(
     604             :                                 dce_call, r, pipe_state, negotiate_flags,
     605             :                                 NULL, /* trust_account_in_db */
     606             :                                 nt_status);
     607             :                 }
     608             : 
     609         304 :                 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
     610             :                                                               &curNtHash,
     611             :                                                               &prevNtHash);
     612         304 :                 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_DISABLED)) {
     613           0 :                         return dcesrv_netr_ServerAuthenticate3_check_downgrade(
     614             :                                 dce_call, r, pipe_state, negotiate_flags,
     615             :                                 NULL, /* trust_account_in_db */
     616           0 :                                 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
     617             :                 }
     618         304 :                 if (!NT_STATUS_IS_OK(nt_status)) {
     619           0 :                         return dcesrv_netr_ServerAuthenticate3_check_downgrade(
     620             :                                 dce_call, r, pipe_state, negotiate_flags,
     621             :                                 NULL, /* trust_account_in_db */
     622             :                                 nt_status);
     623             :                 }
     624             : 
     625         304 :                 flatname = ldb_msg_find_attr_as_string(tdo_msg, "flatName", NULL);
     626         304 :                 if (flatname == NULL) {
     627           0 :                         return dcesrv_netr_ServerAuthenticate3_check_downgrade(
     628             :                                 dce_call, r, pipe_state, negotiate_flags,
     629             :                                 NULL, /* trust_account_in_db */
     630           0 :                                 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
     631             :                 }
     632             : 
     633         304 :                 *trust_account_for_search = talloc_asprintf(mem_ctx, "%s$", flatname);
     634         304 :                 if (*trust_account_for_search == NULL) {
     635           0 :                         return dcesrv_netr_ServerAuthenticate3_check_downgrade(
     636             :                                 dce_call, r, pipe_state, negotiate_flags,
     637             :                                 NULL, /* trust_account_in_db */
     638           0 :                                 NT_STATUS_NO_MEMORY);
     639             :                 }
     640             :         } else {
     641        1583 :                 *trust_account_for_search = r->in.account_name;
     642             :         }
     643             : 
     644             :         /* pull the user attributes */
     645        1887 :         num_records = gendb_search(sam_ctx, mem_ctx, NULL, &msgs, attrs,
     646             :                                    "(&(sAMAccountName=%s)(objectclass=user))",
     647             :                                    ldb_binary_encode_string(mem_ctx,
     648             :                                                             *trust_account_for_search));
     649             : 
     650        1887 :         if (num_records == 0) {
     651           6 :                 DEBUG(3,("Couldn't find user [%s] in samdb.\n",
     652             :                          log_escape(mem_ctx, r->in.account_name)));
     653           6 :                 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
     654             :                                 dce_call, r, pipe_state, negotiate_flags,
     655             :                                 NULL, /* trust_account_in_db */
     656           6 :                                 NT_STATUS_NO_TRUST_SAM_ACCOUNT);
     657             :         }
     658             : 
     659        1881 :         if (num_records > 1) {
     660           0 :                 DEBUG(0,("Found %d records matching user [%s]\n",
     661             :                          num_records,
     662             :                          log_escape(mem_ctx, r->in.account_name)));
     663           0 :                 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
     664             :                                 dce_call, r, pipe_state, negotiate_flags,
     665             :                                 NULL, /* trust_account_in_db */
     666           0 :                                 NT_STATUS_INTERNAL_DB_CORRUPTION);
     667             :         }
     668             : 
     669        1881 :         *trust_account_in_db = ldb_msg_find_attr_as_string(msgs[0],
     670             :                                                            "samAccountName",
     671             :                                                            NULL);
     672        1881 :         if (*trust_account_in_db == NULL) {
     673           0 :                 DEBUG(0,("No samAccountName returned in record matching user [%s]\n",
     674             :                          r->in.account_name));
     675           0 :                 return dcesrv_netr_ServerAuthenticate3_check_downgrade(
     676             :                                 dce_call, r, pipe_state, negotiate_flags,
     677             :                                 NULL, /* trust_account_in_db */
     678           0 :                                 NT_STATUS_INTERNAL_DB_CORRUPTION);
     679             :         }
     680             : 
     681        2103 :         nt_status = dcesrv_netr_ServerAuthenticate3_check_downgrade(
     682             :                         dce_call, r, pipe_state, negotiate_flags,
     683             :                         *trust_account_in_db,
     684        1881 :                         NT_STATUS_OK);
     685        1881 :         if (!NT_STATUS_IS_OK(nt_status)) {
     686         171 :                 return nt_status;
     687             :         }
     688             : 
     689        1710 :         user_account_control = ldb_msg_find_attr_as_uint(msgs[0], "userAccountControl", 0);
     690             : 
     691        1710 :         if (user_account_control & UF_ACCOUNTDISABLE) {
     692           0 :                 DEBUG(1, ("Account [%s] is disabled\n",
     693             :                           log_escape(mem_ctx, r->in.account_name)));
     694           0 :                 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
     695             :         }
     696             : 
     697        1710 :         switch (r->in.secure_channel_type) {
     698         449 :         case SEC_CHAN_WKSTA:
     699         449 :                 if (!(user_account_control & UF_WORKSTATION_TRUST_ACCOUNT)) {
     700           0 :                         DBG_WARNING("Client asked for a workstation "
     701             :                                     "secure channel, but is not a workstation "
     702             :                                     "(member server) acb flags: 0x%x\n",
     703             :                                     user_account_control);
     704           0 :                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
     705             :                 }
     706         417 :                 break;
     707             : 
     708         304 :         case SEC_CHAN_DOMAIN:
     709           0 :                 FALL_THROUGH;
     710             :         case SEC_CHAN_DNS_DOMAIN:
     711         304 :                 if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
     712           0 :                         DBG_WARNING("Client asked for a trusted domain "
     713             :                                     "secure channel, but is not a trusted "
     714             :                                     "domain: acb flags: 0x%x\n",
     715             :                                     user_account_control);
     716           0 :                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
     717             :                 }
     718         304 :                 break;
     719             : 
     720         955 :         case SEC_CHAN_BDC:
     721         955 :                 if (!(user_account_control & UF_SERVER_TRUST_ACCOUNT)) {
     722           0 :                         DBG_WARNING("Client asked for a server "
     723             :                                     "secure channel, but is not a server "
     724             :                                     "(domain controller): acb flags: 0x%x\n",
     725             :                                     user_account_control);
     726           0 :                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
     727             :                 }
     728         813 :                 break;
     729             : 
     730           2 :         case SEC_CHAN_RODC:
     731           2 :                 if (!(user_account_control & UF_PARTIAL_SECRETS_ACCOUNT)) {
     732           0 :                         DBG_WARNING("Client asked for a RODC secure channel, "
     733             :                                     "but is not a RODC: acb flags: 0x%x\n",
     734             :                                     user_account_control);
     735           0 :                         return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
     736             :                 }
     737           2 :                 break;
     738             : 
     739           0 :         default:
     740             :                 /* we should never reach this */
     741           0 :                 return NT_STATUS_INTERNAL_ERROR;
     742             :         }
     743             : 
     744        1710 :         if (!(user_account_control & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
     745        1580 :                 nt_status = samdb_result_passwords_no_lockout(mem_ctx,
     746        1406 :                                         dce_call->conn->dce_ctx->lp_ctx,
     747             :                                         msgs[0], &curNtHash);
     748        1406 :                 if (!NT_STATUS_IS_OK(nt_status)) {
     749           0 :                         return NT_STATUS_ACCESS_DENIED;
     750             :                 }
     751             :         }
     752             : 
     753        1710 :         if (curNtHash == NULL) {
     754           0 :                 return NT_STATUS_ACCESS_DENIED;
     755             :         }
     756             : 
     757        1710 :         if (!challenge_valid) {
     758          72 :                 DEBUG(1, ("No challenge requested by client [%s/%s], "
     759             :                           "cannot authenticate\n",
     760             :                           log_escape(mem_ctx, r->in.computer_name),
     761             :                           log_escape(mem_ctx, r->in.account_name)));
     762          72 :                 return NT_STATUS_ACCESS_DENIED;
     763             :         }
     764             : 
     765        1800 :         creds = netlogon_creds_server_init(mem_ctx,
     766             :                                            r->in.account_name,
     767             :                                            r->in.computer_name,
     768        1638 :                                            r->in.secure_channel_type,
     769             :                                            &challenge.client_challenge,
     770             :                                            &challenge.server_challenge,
     771             :                                            curNtHash,
     772        1638 :                                            r->in.credentials,
     773             :                                            r->out.return_credentials,
     774             :                                            negotiate_flags);
     775        1638 :         if (creds == NULL && prevNtHash != NULL) {
     776             :                 /*
     777             :                  * We fallback to the previous password for domain trusts.
     778             :                  *
     779             :                  * Note that lpcfg_old_password_allowed_period() doesn't
     780             :                  * apply here.
     781             :                  */
     782         126 :                 creds = netlogon_creds_server_init(mem_ctx,
     783             :                                                    r->in.account_name,
     784             :                                                    r->in.computer_name,
     785         126 :                                                    r->in.secure_channel_type,
     786             :                                                    &challenge.client_challenge,
     787             :                                                    &challenge.server_challenge,
     788             :                                                    prevNtHash,
     789         126 :                                                    r->in.credentials,
     790             :                                                    r->out.return_credentials,
     791             :                                                    negotiate_flags);
     792             :         }
     793             : 
     794        1638 :         if (creds == NULL) {
     795          56 :                 return NT_STATUS_ACCESS_DENIED;
     796             :         }
     797        1582 :         creds->sid = samdb_result_dom_sid(creds, msgs[0], "objectSid");
     798        1582 :         *sid = talloc_memdup(mem_ctx, creds->sid, sizeof(struct dom_sid));
     799             : 
     800        1739 :         nt_status = schannel_save_creds_state(mem_ctx,
     801        1582 :                                               dce_call->conn->dce_ctx->lp_ctx,
     802             :                                               creds);
     803        1582 :         if (!NT_STATUS_IS_OK(nt_status)) {
     804          18 :                 ZERO_STRUCTP(r->out.return_credentials);
     805          18 :                 return nt_status;
     806             :         }
     807             : 
     808        1564 :         *r->out.rid = samdb_result_rid_from_sid(mem_ctx, msgs[0],
     809             :                                                 "objectSid", 0);
     810             : 
     811        1564 :         return NT_STATUS_OK;
     812             : }
     813             : 
     814             : /*
     815             :  * Log a netr_ServerAuthenticate3 request, and then invoke
     816             :  * dcesrv_netr_ServerAuthenticate3_helper to perform the actual processing
     817             :  */
     818        1887 : static NTSTATUS dcesrv_netr_ServerAuthenticate3(
     819             :         struct dcesrv_call_state *dce_call,
     820             :         TALLOC_CTX *mem_ctx,
     821             :         struct netr_ServerAuthenticate3 *r)
     822             : {
     823         222 :         NTSTATUS status;
     824        1887 :         struct dom_sid *sid = NULL;
     825        1887 :         const char *trust_account_for_search = NULL;
     826        1887 :         const char *trust_account_in_db = NULL;
     827         222 :         struct imessaging_context *imsg_ctx =
     828        1887 :                 dcesrv_imessaging_context(dce_call->conn);
     829        3774 :         struct auth_usersupplied_info ui = {
     830        1887 :                 .local_host = dce_call->conn->local_address,
     831        1887 :                 .remote_host = dce_call->conn->remote_address,
     832             :                 .client = {
     833        1887 :                         .account_name = r->in.account_name,
     834        1887 :                         .domain_name = lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx),
     835             :                 },
     836             :                 .service_description = "NETLOGON",
     837             :                 .auth_description = "ServerAuthenticate",
     838             :                 .netlogon_trust_account = {
     839        1887 :                         .computer_name = r->in.computer_name,
     840        1887 :                         .negotiate_flags = *r->in.negotiate_flags,
     841        1887 :                         .secure_channel_type = r->in.secure_channel_type,
     842             :                 },
     843             :         };
     844             : 
     845        1887 :         status = dcesrv_netr_ServerAuthenticate3_helper(dce_call,
     846             :                                                         mem_ctx,
     847             :                                                         r,
     848             :                                                         &trust_account_for_search,
     849             :                                                         &trust_account_in_db,
     850             :                                                         &sid);
     851        1887 :         ui.netlogon_trust_account.sid = sid;
     852        1887 :         ui.netlogon_trust_account.account_name = trust_account_in_db;
     853        1887 :         ui.mapped.account_name = trust_account_for_search;
     854        3774 :         log_authentication_event(
     855             :                 imsg_ctx,
     856        1887 :                 dce_call->conn->dce_ctx->lp_ctx,
     857             :                 NULL,
     858             :                 &ui,
     859             :                 status,
     860        1887 :                 lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx),
     861             :                 trust_account_in_db,
     862             :                 sid,
     863             :                 NULL /* client_audit_info */,
     864             :                 NULL /* server_audit_info */);
     865             : 
     866        1887 :         return status;
     867             : }
     868         276 : static NTSTATUS dcesrv_netr_ServerAuthenticate(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     869             :                                         struct netr_ServerAuthenticate *r)
     870             : {
     871          42 :         struct netr_ServerAuthenticate3 a;
     872          42 :         uint32_t rid;
     873             :         /* TODO:
     874             :          * negotiate_flags is used as an [in] parameter
     875             :          * so it need to be initialised.
     876             :          *
     877             :          * (I think ... = 0; seems wrong here --metze)
     878             :          */
     879         276 :         uint32_t negotiate_flags_in = 0;
     880         276 :         uint32_t negotiate_flags_out = 0;
     881             : 
     882         276 :         a.in.server_name                = r->in.server_name;
     883         276 :         a.in.account_name               = r->in.account_name;
     884         276 :         a.in.secure_channel_type        = r->in.secure_channel_type;
     885         276 :         a.in.computer_name              = r->in.computer_name;
     886         276 :         a.in.credentials                = r->in.credentials;
     887         276 :         a.in.negotiate_flags            = &negotiate_flags_in;
     888             : 
     889         276 :         a.out.return_credentials        = r->out.return_credentials;
     890         276 :         a.out.rid                       = &rid;
     891         276 :         a.out.negotiate_flags           = &negotiate_flags_out;
     892             : 
     893         276 :         return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &a);
     894             : }
     895             : 
     896         875 : static NTSTATUS dcesrv_netr_ServerAuthenticate2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     897             :                                          struct netr_ServerAuthenticate2 *r)
     898             : {
     899         126 :         struct netr_ServerAuthenticate3 r3;
     900         875 :         uint32_t rid = 0;
     901             : 
     902         875 :         r3.in.server_name = r->in.server_name;
     903         875 :         r3.in.account_name = r->in.account_name;
     904         875 :         r3.in.secure_channel_type = r->in.secure_channel_type;
     905         875 :         r3.in.computer_name = r->in.computer_name;
     906         875 :         r3.in.credentials = r->in.credentials;
     907         875 :         r3.out.return_credentials = r->out.return_credentials;
     908         875 :         r3.in.negotiate_flags = r->in.negotiate_flags;
     909         875 :         r3.out.negotiate_flags = r->out.negotiate_flags;
     910         875 :         r3.out.rid = &rid;
     911             : 
     912         875 :         return dcesrv_netr_ServerAuthenticate3(dce_call, mem_ctx, &r3);
     913             : }
     914             : 
     915             : /*
     916             :   Change the machine account password for the currently connected
     917             :   client.  Supplies only the NT#.
     918             : */
     919             : 
     920          56 : static NTSTATUS dcesrv_netr_ServerPasswordSet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     921             :                                        struct netr_ServerPasswordSet *r)
     922             : {
     923           7 :         struct netlogon_creds_CredentialState *creds;
     924           7 :         struct ldb_context *sam_ctx;
     925           7 :         NTSTATUS nt_status;
     926             : 
     927          56 :         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
     928             :                                                         mem_ctx,
     929             :                                                         r->in.computer_name,
     930             :                                                         r->in.credential, r->out.return_authenticator,
     931             :                                                         &creds);
     932          56 :         NT_STATUS_NOT_OK_RETURN(nt_status);
     933             : 
     934          50 :         sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
     935          50 :         if (sam_ctx == NULL) {
     936           0 :                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
     937             :         }
     938             : 
     939          50 :         nt_status = netlogon_creds_des_decrypt(creds, r->in.new_password);
     940          50 :         NT_STATUS_NOT_OK_RETURN(nt_status);
     941             : 
     942             :         /* Using the sid for the account as the key, set the password */
     943          56 :         nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
     944          50 :                                            creds->sid,
     945             :                                            NULL, /* Don't have version */
     946             :                                            NULL, /* Don't have plaintext */
     947          50 :                                            r->in.new_password,
     948             :                                            DSDB_PASSWORD_CHECKED_AND_CORRECT, /* Password change */
     949             :                                            NULL, NULL);
     950          50 :         return nt_status;
     951             : }
     952             : 
     953             : /*
     954             :   Change the machine account password for the currently connected
     955             :   client.  Supplies new plaintext.
     956             : */
     957         342 : static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     958             :                                        struct netr_ServerPasswordSet2 *r)
     959             : {
     960          37 :         struct netlogon_creds_CredentialState *creds;
     961          37 :         struct ldb_context *sam_ctx;
     962         342 :         struct NL_PASSWORD_VERSION version = {};
     963         342 :         const uint32_t *new_version = NULL;
     964          37 :         NTSTATUS nt_status;
     965         342 :         DATA_BLOB new_password = data_blob_null;
     966          37 :         size_t confounder_len;
     967         342 :         DATA_BLOB dec_blob = data_blob_null;
     968         342 :         DATA_BLOB enc_blob = data_blob_null;
     969          37 :         struct samr_CryptPassword password_buf;
     970             : 
     971         342 :         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
     972             :                                                         mem_ctx,
     973             :                                                         r->in.computer_name,
     974             :                                                         r->in.credential, r->out.return_authenticator,
     975             :                                                         &creds);
     976         342 :         NT_STATUS_NOT_OK_RETURN(nt_status);
     977             : 
     978         336 :         sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
     979         336 :         if (sam_ctx == NULL) {
     980           0 :                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
     981             :         }
     982             : 
     983         336 :         memcpy(password_buf.data, r->in.new_password->data, 512);
     984         336 :         SIVAL(password_buf.data, 512, r->in.new_password->length);
     985             : 
     986         336 :         if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
     987         216 :                 nt_status = netlogon_creds_aes_decrypt(creds,
     988             :                                                        password_buf.data,
     989             :                                                        516);
     990             :         } else {
     991         120 :                 nt_status = netlogon_creds_arcfour_crypt(creds,
     992             :                                                          password_buf.data,
     993             :                                                          516);
     994             :         }
     995             : 
     996         336 :         if (!NT_STATUS_IS_OK(nt_status)) {
     997           0 :                 return nt_status;
     998             :         }
     999             : 
    1000         336 :         switch (creds->secure_channel_type) {
    1001          60 :         case SEC_CHAN_DOMAIN:
    1002             :         case SEC_CHAN_DNS_DOMAIN: {
    1003          60 :                 uint32_t len = IVAL(password_buf.data, 512);
    1004          60 :                 if (len <= 500) {
    1005          60 :                         uint32_t ofs = 500 - len;
    1006           0 :                         uint8_t *p;
    1007             : 
    1008          60 :                         p = password_buf.data + ofs;
    1009             : 
    1010          60 :                         version.ReservedField = IVAL(p, 0);
    1011          60 :                         version.PasswordVersionNumber = IVAL(p, 4);
    1012          60 :                         version.PasswordVersionPresent = IVAL(p, 8);
    1013             : 
    1014          60 :                         if (version.PasswordVersionPresent == NETLOGON_PASSWORD_VERSION_NUMBER_PRESENT) {
    1015          60 :                                 new_version = &version.PasswordVersionNumber;
    1016             :                         }
    1017             :                 }}
    1018          60 :                 break;
    1019         240 :         default:
    1020         240 :                 break;
    1021             :         }
    1022             : 
    1023         336 :         if (!extract_pw_from_buffer(mem_ctx, password_buf.data, &new_password)) {
    1024           0 :                 DEBUG(3,("samr: failed to decode password buffer\n"));
    1025           0 :                 return NT_STATUS_WRONG_PASSWORD;
    1026             :         }
    1027             : 
    1028             :         /*
    1029             :          * Make sure the length field was encrypted,
    1030             :          * otherwise we are under attack.
    1031             :          */
    1032         336 :         if (new_password.length == r->in.new_password->length) {
    1033           9 :                 DBG_WARNING("Length[%zu] field not encrypted\n",
    1034             :                             new_password.length);
    1035           9 :                 return NT_STATUS_WRONG_PASSWORD;
    1036             :         }
    1037             : 
    1038             :         /*
    1039             :          * We don't allow empty passwords for machine accounts.
    1040             :          */
    1041         327 :         if (new_password.length < 2) {
    1042          51 :                 DBG_WARNING("Empty password Length[%zu]\n",
    1043             :                             new_password.length);
    1044          51 :                 return NT_STATUS_WRONG_PASSWORD;
    1045             :         }
    1046             : 
    1047             :         /*
    1048             :          * Make sure the confounder part of CryptPassword
    1049             :          * buffer was encrypted, otherwise we are under attack.
    1050             :          */
    1051         276 :         confounder_len = 512 - new_password.length;
    1052         276 :         enc_blob = data_blob_const(r->in.new_password->data, confounder_len);
    1053         276 :         dec_blob = data_blob_const(password_buf.data, confounder_len);
    1054         276 :         if (confounder_len > 0 && data_blob_equal_const_time(&dec_blob, &enc_blob)) {
    1055           9 :                 DBG_WARNING("Confounder buffer not encrypted Length[%zu]\n",
    1056             :                             confounder_len);
    1057           9 :                 return NT_STATUS_WRONG_PASSWORD;
    1058             :         }
    1059             : 
    1060             :         /*
    1061             :          * Check that the password part was actually encrypted,
    1062             :          * otherwise we are under attack.
    1063             :          */
    1064         267 :         enc_blob = data_blob_const(r->in.new_password->data + confounder_len,
    1065             :                                    new_password.length);
    1066         267 :         dec_blob = data_blob_const(password_buf.data + confounder_len,
    1067             :                                    new_password.length);
    1068         267 :         if (data_blob_equal_const_time(&dec_blob, &enc_blob)) {
    1069           9 :                 DBG_WARNING("Password buffer not encrypted Length[%zu]\n",
    1070             :                             new_password.length);
    1071           9 :                 return NT_STATUS_WRONG_PASSWORD;
    1072             :         }
    1073             : 
    1074             :         /*
    1075             :          * don't allow zero buffers
    1076             :          */
    1077         258 :         if (all_zero(new_password.data, new_password.length)) {
    1078           9 :                 DBG_WARNING("Password zero buffer Length[%zu]\n",
    1079             :                             new_password.length);
    1080           9 :                 return NT_STATUS_WRONG_PASSWORD;
    1081             :         }
    1082             : 
    1083             :         /* Using the sid for the account as the key, set the password */
    1084         274 :         nt_status = samdb_set_password_sid(sam_ctx, mem_ctx,
    1085         249 :                                            creds->sid,
    1086             :                                            new_version,
    1087             :                                            &new_password, /* we have plaintext */
    1088             :                                            NULL,
    1089             :                                            DSDB_PASSWORD_CHECKED_AND_CORRECT, /* Password change */
    1090             :                                            NULL, NULL);
    1091         249 :         return nt_status;
    1092             : }
    1093             : 
    1094             : 
    1095             : /*
    1096             :   netr_LogonUasLogon
    1097             : */
    1098          18 : static WERROR dcesrv_netr_LogonUasLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    1099             :                                  struct netr_LogonUasLogon *r)
    1100             : {
    1101          18 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    1102             : }
    1103             : 
    1104             : 
    1105             : /*
    1106             :   netr_LogonUasLogoff
    1107             : */
    1108          18 : static WERROR dcesrv_netr_LogonUasLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    1109             :                        struct netr_LogonUasLogoff *r)
    1110             : {
    1111          18 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    1112             : }
    1113             : 
    1114             : 
    1115       19182 : static NTSTATUS dcesrv_netr_LogonSamLogon_check(struct dcesrv_call_state *dce_call,
    1116             :                                                 const struct netr_LogonSamLogonEx *r)
    1117             : {
    1118       19182 :         enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
    1119             : 
    1120       19182 :         switch (r->in.logon_level) {
    1121         655 :         case NetlogonInteractiveInformation:
    1122             :         case NetlogonServiceInformation:
    1123             :         case NetlogonInteractiveTransitiveInformation:
    1124             :         case NetlogonServiceTransitiveInformation:
    1125         655 :                 if (r->in.logon->password == NULL) {
    1126           0 :                         return NT_STATUS_INVALID_PARAMETER;
    1127             :                 }
    1128             : 
    1129         655 :                 switch (r->in.validation_level) {
    1130         655 :                 case NetlogonValidationSamInfo:  /* 2 */
    1131             :                 case NetlogonValidationSamInfo2: /* 3 */
    1132             :                 case NetlogonValidationSamInfo4: /* 6 */
    1133         655 :                         break;
    1134           0 :                 default:
    1135           0 :                         return NT_STATUS_INVALID_INFO_CLASS;
    1136             :                 }
    1137             : 
    1138         655 :                 break;
    1139       15157 :         case NetlogonNetworkInformation:
    1140             :         case NetlogonNetworkTransitiveInformation:
    1141       15157 :                 if (r->in.logon->network == NULL) {
    1142           0 :                         return NT_STATUS_INVALID_PARAMETER;
    1143             :                 }
    1144             : 
    1145       15157 :                 switch (r->in.validation_level) {
    1146       13055 :                 case NetlogonValidationSamInfo:  /* 2 */
    1147             :                 case NetlogonValidationSamInfo2: /* 3 */
    1148             :                 case NetlogonValidationSamInfo4: /* 6 */
    1149       13055 :                         break;
    1150         780 :                 default:
    1151         780 :                         return NT_STATUS_INVALID_INFO_CLASS;
    1152             :                 }
    1153             : 
    1154       13055 :                 break;
    1155             : 
    1156         250 :         case NetlogonGenericInformation:
    1157         250 :                 if (r->in.logon->generic == NULL) {
    1158           0 :                         return NT_STATUS_INVALID_PARAMETER;
    1159             :                 }
    1160             : 
    1161         250 :                 switch (r->in.validation_level) {
    1162             :                 /* TODO: case NetlogonValidationGenericInfo: 4 */
    1163         250 :                 case NetlogonValidationGenericInfo2: /* 5 */
    1164         250 :                         break;
    1165           0 :                 default:
    1166           0 :                         return NT_STATUS_INVALID_INFO_CLASS;
    1167             :                 }
    1168             : 
    1169         250 :                 break;
    1170        3120 :         default:
    1171        3120 :                 return NT_STATUS_INVALID_PARAMETER;
    1172             :         }
    1173             : 
    1174       15282 :         dcesrv_call_auth_info(dce_call, NULL, &auth_level);
    1175             : 
    1176       15282 :         switch (r->in.validation_level) {
    1177        4092 :         case NetlogonValidationSamInfo4: /* 6 */
    1178        4092 :                 if (auth_level < DCERPC_AUTH_LEVEL_PRIVACY) {
    1179           0 :                         return NT_STATUS_INVALID_PARAMETER;
    1180             :                 }
    1181        4020 :                 break;
    1182             : 
    1183        9940 :         default:
    1184        9940 :                 break;
    1185             :         }
    1186             : 
    1187       15282 :         return NT_STATUS_OK;
    1188             : }
    1189             : 
    1190             : struct dcesrv_netr_LogonSamLogon_base_state {
    1191             :         struct dcesrv_call_state *dce_call;
    1192             : 
    1193             :         TALLOC_CTX *mem_ctx;
    1194             : 
    1195             :         struct netlogon_creds_CredentialState *creds;
    1196             : 
    1197             :         struct netr_LogonSamLogonEx r;
    1198             : 
    1199             :         uint32_t _ignored_flags;
    1200             : 
    1201             :         struct {
    1202             :                 struct netr_LogonSamLogon *lsl;
    1203             :                 struct netr_LogonSamLogonWithFlags *lslwf;
    1204             :                 struct netr_LogonSamLogonEx *lslex;
    1205             :         } _r;
    1206             : 
    1207             :         struct kdc_check_generic_kerberos kr;
    1208             : };
    1209             : 
    1210             : static void dcesrv_netr_LogonSamLogon_base_auth_done(struct tevent_req *subreq);
    1211             : static void dcesrv_netr_LogonSamLogon_base_krb5_done(struct tevent_req *subreq);
    1212             : static void dcesrv_netr_LogonSamLogon_base_reply(
    1213             :         struct dcesrv_netr_LogonSamLogon_base_state *state);
    1214             : 
    1215             : /*
    1216             :   netr_LogonSamLogon_base
    1217             : 
    1218             :   This version of the function allows other wrappers to say 'do not check the credentials'
    1219             : 
    1220             :   We can't do the traditional 'wrapping' format completely, as this
    1221             :   function must only run under schannel
    1222             : */
    1223       15282 : static NTSTATUS dcesrv_netr_LogonSamLogon_base_call(struct dcesrv_netr_LogonSamLogon_base_state *state)
    1224             : {
    1225       15282 :         struct dcesrv_call_state *dce_call = state->dce_call;
    1226        1322 :         struct imessaging_context *imsg_ctx =
    1227       15282 :                 dcesrv_imessaging_context(dce_call->conn);
    1228       15282 :         TALLOC_CTX *mem_ctx = state->mem_ctx;
    1229       15282 :         struct netr_LogonSamLogonEx *r = &state->r;
    1230       15282 :         struct netlogon_creds_CredentialState *creds = state->creds;
    1231       15282 :         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
    1232       15282 :         const char *workgroup = lpcfg_workgroup(lp_ctx);
    1233       15282 :         struct auth4_context *auth_context = NULL;
    1234       15282 :         struct auth_usersupplied_info *user_info = NULL;
    1235        1322 :         NTSTATUS nt_status;
    1236       15282 :         struct tevent_req *subreq = NULL;
    1237       15282 :         enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
    1238       15282 :         enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
    1239             : 
    1240       15282 :         dcesrv_call_auth_info(dce_call, &auth_type, &auth_level);
    1241             : 
    1242       15282 :         switch (dce_call->pkt.u.request.opnum) {
    1243        8221 :         case NDR_NETR_LOGONSAMLOGON:
    1244             :         case NDR_NETR_LOGONSAMLOGONWITHFLAGS:
    1245             :                 /*
    1246             :                  * These already called dcesrv_netr_check_schannel()
    1247             :                  * via dcesrv_netr_creds_server_step_check()
    1248             :                  */
    1249        8221 :                 break;
    1250        6179 :         case NDR_NETR_LOGONSAMLOGONEX:
    1251             :         default:
    1252        6179 :                 if (auth_type != DCERPC_AUTH_TYPE_SCHANNEL) {
    1253         252 :                         return NT_STATUS_ACCESS_DENIED;
    1254             :                 }
    1255             : 
    1256        5927 :                 nt_status = dcesrv_netr_check_schannel(dce_call,
    1257             :                                                        creds,
    1258             :                                                        auth_type,
    1259             :                                                        auth_level,
    1260        5535 :                                                        dce_call->pkt.u.request.opnum);
    1261        5927 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    1262           0 :                         return nt_status;
    1263             :                 }
    1264        5535 :                 break;
    1265             :         }
    1266             : 
    1267       15030 :         *r->out.authoritative = 1;
    1268             : 
    1269       15030 :         if (*r->in.flags & NETLOGON_SAMLOGON_FLAG_PASS_TO_FOREST_ROOT) {
    1270             :                 /*
    1271             :                  * Currently we're always the forest root ourself.
    1272             :                  */
    1273           0 :                 return NT_STATUS_NO_SUCH_USER;
    1274             :         }
    1275             : 
    1276       15030 :         if (*r->in.flags & NETLOGON_SAMLOGON_FLAG_PASS_CROSS_FOREST_HOP) {
    1277             :                 /*
    1278             :                  * Currently we don't support trusts correctly yet.
    1279             :                  */
    1280           0 :                 return NT_STATUS_NO_SUCH_USER;
    1281             :         }
    1282             : 
    1283       15030 :         user_info = talloc_zero(mem_ctx, struct auth_usersupplied_info);
    1284       15030 :         NT_STATUS_HAVE_NO_MEMORY(user_info);
    1285             : 
    1286       15030 :         user_info->service_description = "SamLogon";
    1287             : 
    1288       15030 :         nt_status = netlogon_creds_decrypt_samlogon_logon(creds,
    1289             :                                                           r->in.logon_level,
    1290             :                                                           r->in.logon);
    1291       15030 :         NT_STATUS_NOT_OK_RETURN(nt_status);
    1292             : 
    1293       15030 :         switch (r->in.logon_level) {
    1294       14780 :         case NetlogonInteractiveInformation:
    1295             :         case NetlogonServiceInformation:
    1296             :         case NetlogonInteractiveTransitiveInformation:
    1297             :         case NetlogonServiceTransitiveInformation:
    1298             :         case NetlogonNetworkInformation:
    1299             :         case NetlogonNetworkTransitiveInformation:
    1300             : 
    1301       16054 :                 nt_status = auth_context_create_for_netlogon(mem_ctx,
    1302             :                                         dce_call->event_ctx,
    1303             :                                         imsg_ctx,
    1304       14780 :                                         dce_call->conn->dce_ctx->lp_ctx,
    1305             :                                         &auth_context);
    1306       14780 :                 NT_STATUS_NOT_OK_RETURN(nt_status);
    1307             : 
    1308       14780 :                 user_info->remote_host = dce_call->conn->remote_address;
    1309       14780 :                 user_info->local_host = dce_call->conn->local_address;
    1310             : 
    1311        1274 :                 user_info->netlogon_trust_account.secure_channel_type
    1312       14780 :                         = creds->secure_channel_type;
    1313        1274 :                 user_info->netlogon_trust_account.negotiate_flags
    1314       14780 :                         = creds->negotiate_flags;
    1315             : 
    1316             :                 /*
    1317             :                  * These two can be unrelated when the account is
    1318             :                  * actually that of a trusted domain, so we want to
    1319             :                  * know which DC in that trusted domain contacted
    1320             :                  * us
    1321             :                  */
    1322        1274 :                 user_info->netlogon_trust_account.computer_name
    1323       14780 :                         = creds->computer_name;
    1324        1274 :                 user_info->netlogon_trust_account.account_name
    1325       14780 :                         = creds->account_name;
    1326        1274 :                 user_info->netlogon_trust_account.sid
    1327       14780 :                         = creds->sid;
    1328             : 
    1329       14780 :                 break;
    1330         250 :         default:
    1331             :                 /* We do not need to set up the user_info in this case */
    1332         250 :                 break;
    1333             :         }
    1334             : 
    1335       15030 :         switch (r->in.logon_level) {
    1336         655 :         case NetlogonInteractiveInformation:
    1337             :         case NetlogonServiceInformation:
    1338             :         case NetlogonInteractiveTransitiveInformation:
    1339             :         case NetlogonServiceTransitiveInformation:
    1340         655 :                 user_info->auth_description = "interactive";
    1341             : 
    1342           0 :                 user_info->logon_parameters
    1343         655 :                         = r->in.logon->password->identity_info.parameter_control;
    1344           0 :                 user_info->client.account_name
    1345         655 :                         = r->in.logon->password->identity_info.account_name.string;
    1346           0 :                 user_info->client.domain_name
    1347         655 :                         = r->in.logon->password->identity_info.domain_name.string;
    1348           0 :                 user_info->workstation_name
    1349         655 :                         = r->in.logon->password->identity_info.workstation.string;
    1350         655 :                 user_info->flags |= USER_INFO_INTERACTIVE_LOGON;
    1351         655 :                 user_info->password_state = AUTH_PASSWORD_HASH;
    1352             : 
    1353         655 :                 user_info->password.hash.lanman = talloc(user_info, struct samr_Password);
    1354         655 :                 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.lanman);
    1355         655 :                 *user_info->password.hash.lanman = r->in.logon->password->lmpassword;
    1356             : 
    1357         655 :                 user_info->password.hash.nt = talloc(user_info, struct samr_Password);
    1358         655 :                 NT_STATUS_HAVE_NO_MEMORY(user_info->password.hash.nt);
    1359         655 :                 *user_info->password.hash.nt = r->in.logon->password->ntpassword;
    1360             : 
    1361           0 :                 user_info->logon_id
    1362         655 :                     = r->in.logon->password->identity_info.logon_id;
    1363             : 
    1364         655 :                 break;
    1365       14125 :         case NetlogonNetworkInformation:
    1366             :         case NetlogonNetworkTransitiveInformation:
    1367       14125 :                 user_info->auth_description = "network";
    1368             : 
    1369       15399 :                 nt_status = auth_context_set_challenge(
    1370             :                         auth_context,
    1371       14125 :                         r->in.logon->network->challenge,
    1372             :                         "netr_LogonSamLogonWithFlags");
    1373       14125 :                 NT_STATUS_NOT_OK_RETURN(nt_status);
    1374             : 
    1375        1274 :                 user_info->logon_parameters
    1376       14125 :                         = r->in.logon->network->identity_info.parameter_control;
    1377        1274 :                 user_info->client.account_name
    1378       14125 :                         = r->in.logon->network->identity_info.account_name.string;
    1379        1274 :                 user_info->client.domain_name
    1380       14125 :                         = r->in.logon->network->identity_info.domain_name.string;
    1381        1274 :                 user_info->workstation_name
    1382       14125 :                         = r->in.logon->network->identity_info.workstation.string;
    1383             : 
    1384       14125 :                 user_info->password_state = AUTH_PASSWORD_RESPONSE;
    1385       14125 :                 user_info->password.response.lanman = data_blob_talloc(mem_ctx, r->in.logon->network->lm.data, r->in.logon->network->lm.length);
    1386       14125 :                 user_info->password.response.nt = data_blob_talloc(mem_ctx, r->in.logon->network->nt.data, r->in.logon->network->nt.length);
    1387             : 
    1388        1274 :                 user_info->logon_id
    1389       14125 :                     = r->in.logon->network->identity_info.logon_id;
    1390             : 
    1391       14125 :                 nt_status = NTLMv2_RESPONSE_verify_netlogon_creds(
    1392             :                                         user_info->client.account_name,
    1393             :                                         user_info->client.domain_name,
    1394             :                                         user_info->password.response.nt,
    1395             :                                         creds, workgroup);
    1396       14125 :                 NT_STATUS_NOT_OK_RETURN(nt_status);
    1397             : 
    1398       12851 :                 break;
    1399             : 
    1400             : 
    1401         250 :         case NetlogonGenericInformation:
    1402             :         {
    1403         250 :                 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
    1404             :                         /* OK */
    1405         125 :                 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
    1406             :                         /* OK */
    1407             :                 } else {
    1408             :                         /* Using DES to verify kerberos tickets makes no sense */
    1409           0 :                         return NT_STATUS_INVALID_PARAMETER;
    1410             :                 }
    1411             : 
    1412         250 :                 if (strcmp(r->in.logon->generic->package_name.string, "Kerberos") == 0) {
    1413           0 :                         struct dcerpc_binding_handle *irpc_handle;
    1414         250 :                         struct netr_GenericInfo2 *generic = talloc_zero(mem_ctx, struct netr_GenericInfo2);
    1415         250 :                         NT_STATUS_HAVE_NO_MEMORY(generic);
    1416             : 
    1417         250 :                         r->out.validation->generic = generic;
    1418             : 
    1419           0 :                         user_info->logon_id
    1420         250 :                             = r->in.logon->generic->identity_info.logon_id;
    1421             : 
    1422         250 :                         irpc_handle = irpc_binding_handle_by_name(mem_ctx,
    1423             :                                                                   imsg_ctx,
    1424             :                                                                   "kdc_server",
    1425             :                                                                   &ndr_table_irpc);
    1426         250 :                         if (irpc_handle == NULL) {
    1427           0 :                                 return NT_STATUS_NO_LOGON_SERVERS;
    1428             :                         }
    1429             : 
    1430           0 :                         state->kr.in.generic_request =
    1431         250 :                                 data_blob_const(r->in.logon->generic->data,
    1432         250 :                                                 r->in.logon->generic->length);
    1433             : 
    1434             :                         /*
    1435             :                          * 60 seconds should be enough
    1436             :                          */
    1437         250 :                         dcerpc_binding_handle_set_timeout(irpc_handle, 60);
    1438         250 :                         subreq = dcerpc_kdc_check_generic_kerberos_r_send(state,
    1439         250 :                                                 state->dce_call->event_ctx,
    1440             :                                                 irpc_handle, &state->kr);
    1441         250 :                         if (subreq == NULL) {
    1442           0 :                                 return NT_STATUS_NO_MEMORY;
    1443             :                         }
    1444         250 :                         state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
    1445         250 :                         tevent_req_set_callback(subreq,
    1446             :                                         dcesrv_netr_LogonSamLogon_base_krb5_done,
    1447             :                                         state);
    1448         250 :                         return NT_STATUS_OK;
    1449             :                 }
    1450             : 
    1451             :                 /* Until we get an implementation of these other packages */
    1452           0 :                 return NT_STATUS_INVALID_PARAMETER;
    1453             :         }
    1454           0 :         default:
    1455           0 :                 return NT_STATUS_INVALID_PARAMETER;
    1456             :         }
    1457             : 
    1458       14780 :         subreq = auth_check_password_send(state, state->dce_call->event_ctx,
    1459             :                                           auth_context, user_info);
    1460       14780 :         state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
    1461       14780 :         tevent_req_set_callback(subreq,
    1462             :                                 dcesrv_netr_LogonSamLogon_base_auth_done,
    1463             :                                 state);
    1464       14780 :         return NT_STATUS_OK;
    1465             : }
    1466             : 
    1467       14780 : static void dcesrv_netr_LogonSamLogon_base_auth_done(struct tevent_req *subreq)
    1468             : {
    1469        1274 :         struct dcesrv_netr_LogonSamLogon_base_state *state =
    1470       14780 :                 tevent_req_callback_data(subreq,
    1471             :                 struct dcesrv_netr_LogonSamLogon_base_state);
    1472       14780 :         TALLOC_CTX *mem_ctx = state->mem_ctx;
    1473       14780 :         struct netr_LogonSamLogonEx *r = &state->r;
    1474       14780 :         struct auth_user_info_dc *user_info_dc = NULL;
    1475       14780 :         struct netr_SamInfo2 *sam2 = NULL;
    1476       14780 :         struct netr_SamInfo3 *sam3 = NULL;
    1477       14780 :         struct netr_SamInfo6 *sam6 = NULL;
    1478        1274 :         NTSTATUS nt_status;
    1479             : 
    1480       14780 :         nt_status = auth_check_password_recv(subreq, mem_ctx,
    1481             :                                              &user_info_dc,
    1482             :                                              r->out.authoritative);
    1483       14780 :         TALLOC_FREE(subreq);
    1484       14780 :         if (!NT_STATUS_IS_OK(nt_status)) {
    1485        3752 :                 r->out.result = nt_status;
    1486        3752 :                 dcesrv_netr_LogonSamLogon_base_reply(state);
    1487        3752 :                 return;
    1488             :         }
    1489             : 
    1490       11028 :         switch (r->in.validation_level) {
    1491        4254 :         case 2:
    1492        4254 :                 nt_status = auth_convert_user_info_dc_saminfo2(mem_ctx,
    1493             :                                                                user_info_dc,
    1494             :                                                                AUTH_INCLUDE_RESOURCE_GROUPS,
    1495             :                                                                &sam2);
    1496        4254 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    1497           0 :                         r->out.result = nt_status;
    1498           0 :                         dcesrv_netr_LogonSamLogon_base_reply(state);
    1499           0 :                         return;
    1500             :                 }
    1501             : 
    1502        4254 :                 r->out.validation->sam2 = sam2;
    1503        4254 :                 break;
    1504             : 
    1505        4362 :         case 3:
    1506        4362 :                 nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
    1507             :                                                                user_info_dc,
    1508             :                                                                AUTH_INCLUDE_RESOURCE_GROUPS,
    1509             :                                                                &sam3, NULL);
    1510        4362 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    1511           0 :                         r->out.result = nt_status;
    1512           0 :                         dcesrv_netr_LogonSamLogon_base_reply(state);
    1513           0 :                         return;
    1514             :                 }
    1515             : 
    1516        4362 :                 r->out.validation->sam3 = sam3;
    1517        4362 :                 break;
    1518             : 
    1519        2412 :         case 6:
    1520        2412 :                 nt_status = auth_convert_user_info_dc_saminfo6(mem_ctx,
    1521             :                                                                user_info_dc,
    1522             :                                                                AUTH_INCLUDE_RESOURCE_GROUPS,
    1523             :                                                                &sam6, NULL);
    1524        2412 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    1525           0 :                         r->out.result = nt_status;
    1526           0 :                         dcesrv_netr_LogonSamLogon_base_reply(state);
    1527           0 :                         return;
    1528             :                 }
    1529             : 
    1530        2412 :                 r->out.validation->sam6 = sam6;
    1531        2412 :                 break;
    1532             : 
    1533           0 :         default:
    1534           0 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    1535           0 :                         r->out.result = NT_STATUS_INVALID_INFO_CLASS;
    1536           0 :                         dcesrv_netr_LogonSamLogon_base_reply(state);
    1537           0 :                         return;
    1538             :                 }
    1539             :         }
    1540             : 
    1541             :         /* TODO: Describe and deal with these flags */
    1542       11028 :         *r->out.flags = 0;
    1543             : 
    1544       11028 :         r->out.result = NT_STATUS_OK;
    1545             : 
    1546       11028 :         dcesrv_netr_LogonSamLogon_base_reply(state);
    1547             : }
    1548             : 
    1549         250 : static void dcesrv_netr_LogonSamLogon_base_krb5_done(struct tevent_req *subreq)
    1550             : {
    1551           0 :         struct dcesrv_netr_LogonSamLogon_base_state *state =
    1552         250 :                 tevent_req_callback_data(subreq,
    1553             :                 struct dcesrv_netr_LogonSamLogon_base_state);
    1554         250 :         TALLOC_CTX *mem_ctx = state->mem_ctx;
    1555         250 :         struct netr_LogonSamLogonEx *r = &state->r;
    1556         250 :         struct netr_GenericInfo2 *generic = NULL;
    1557           0 :         NTSTATUS status;
    1558             : 
    1559         250 :         status = dcerpc_kdc_check_generic_kerberos_r_recv(subreq, mem_ctx);
    1560         250 :         TALLOC_FREE(subreq);
    1561         250 :         if (!NT_STATUS_IS_OK(status)) {
    1562         200 :                 r->out.result = status;
    1563         200 :                 dcesrv_netr_LogonSamLogon_base_reply(state);
    1564         200 :                 return;
    1565             :         }
    1566             : 
    1567          50 :         generic = r->out.validation->generic;
    1568          50 :         generic->length = state->kr.out.generic_reply.length;
    1569          50 :         generic->data = state->kr.out.generic_reply.data;
    1570             : 
    1571             :         /* TODO: Describe and deal with these flags */
    1572          50 :         *r->out.flags = 0;
    1573             : 
    1574          50 :         r->out.result = NT_STATUS_OK;
    1575             : 
    1576          50 :         dcesrv_netr_LogonSamLogon_base_reply(state);
    1577             : }
    1578             : 
    1579       15030 : static void dcesrv_netr_LogonSamLogon_base_reply(
    1580             :         struct dcesrv_netr_LogonSamLogon_base_state *state)
    1581             : {
    1582       15030 :         struct netr_LogonSamLogonEx *r = &state->r;
    1583        1274 :         NTSTATUS status;
    1584             : 
    1585       15030 :         if (NT_STATUS_IS_OK(r->out.result)) {
    1586       11078 :                 status = netlogon_creds_encrypt_samlogon_validation(state->creds,
    1587       11078 :                                                                     r->in.validation_level,
    1588             :                                                                     r->out.validation);
    1589       11078 :                 if (!NT_STATUS_IS_OK(status)) {
    1590          50 :                         DBG_ERR("netlogon_creds_encrypt_samlogon_validation() "
    1591             :                                 "failed - %s\n",
    1592             :                                 nt_errstr(status));
    1593             :                 }
    1594             :         }
    1595             : 
    1596       15030 :         if (state->_r.lslex != NULL) {
    1597        5927 :                 struct netr_LogonSamLogonEx *_r = state->_r.lslex;
    1598        5927 :                 _r->out.result = r->out.result;
    1599        9103 :         } else if (state->_r.lslwf != NULL) {
    1600        2081 :                 struct netr_LogonSamLogonWithFlags *_r = state->_r.lslwf;
    1601        2081 :                 _r->out.result = r->out.result;
    1602        7022 :         } else if (state->_r.lsl != NULL) {
    1603        7022 :                 struct netr_LogonSamLogon *_r = state->_r.lsl;
    1604        7022 :                 _r->out.result = r->out.result;
    1605             :         }
    1606             : 
    1607       15030 :         dcesrv_async_reply(state->dce_call);
    1608       15030 : }
    1609             : 
    1610        6179 : static NTSTATUS dcesrv_netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    1611             :                                      struct netr_LogonSamLogonEx *r)
    1612             : {
    1613         440 :         struct dcesrv_netr_LogonSamLogon_base_state *state;
    1614         440 :         NTSTATUS nt_status;
    1615             : 
    1616        6179 :         *r->out.authoritative = 1;
    1617             : 
    1618        6179 :         state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
    1619        6179 :         if (state == NULL) {
    1620           0 :                 return NT_STATUS_NO_MEMORY;
    1621             :         }
    1622             : 
    1623        6179 :         state->dce_call = dce_call;
    1624        6179 :         state->mem_ctx = mem_ctx;
    1625             : 
    1626        6179 :         state->r.in.server_name      = r->in.server_name;
    1627        6179 :         state->r.in.computer_name    = r->in.computer_name;
    1628        6179 :         state->r.in.logon_level      = r->in.logon_level;
    1629        6179 :         state->r.in.logon            = r->in.logon;
    1630        6179 :         state->r.in.validation_level = r->in.validation_level;
    1631        6179 :         state->r.in.flags            = r->in.flags;
    1632        6179 :         state->r.out.validation      = r->out.validation;
    1633        6179 :         state->r.out.authoritative   = r->out.authoritative;
    1634        6179 :         state->r.out.flags           = r->out.flags;
    1635             : 
    1636        6179 :         state->_r.lslex = r;
    1637             : 
    1638        6179 :         nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
    1639        6179 :         if (!NT_STATUS_IS_OK(nt_status)) {
    1640           0 :                 return nt_status;
    1641             :         }
    1642             : 
    1643        6619 :         nt_status = schannel_get_creds_state(mem_ctx,
    1644        6179 :                                              dce_call->conn->dce_ctx->lp_ctx,
    1645             :                                              r->in.computer_name, &state->creds);
    1646        6179 :         if (!NT_STATUS_IS_OK(nt_status)) {
    1647           0 :                 return nt_status;
    1648             :         }
    1649             : 
    1650        6179 :         nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
    1651             : 
    1652        6179 :         if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
    1653        5927 :                 return nt_status;
    1654             :         }
    1655             : 
    1656         252 :         return nt_status;
    1657             : }
    1658             : 
    1659             : /*
    1660             :   netr_LogonSamLogonWithFlags
    1661             : 
    1662             : */
    1663        2081 : static NTSTATUS dcesrv_netr_LogonSamLogonWithFlags(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    1664             :                                             struct netr_LogonSamLogonWithFlags *r)
    1665             : {
    1666           0 :         struct dcesrv_netr_LogonSamLogon_base_state *state;
    1667           0 :         NTSTATUS nt_status;
    1668             : 
    1669        2081 :         *r->out.authoritative = 1;
    1670             : 
    1671        2081 :         state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
    1672        2081 :         if (state == NULL) {
    1673           0 :                 return NT_STATUS_NO_MEMORY;
    1674             :         }
    1675             : 
    1676        2081 :         state->dce_call = dce_call;
    1677        2081 :         state->mem_ctx = mem_ctx;
    1678             : 
    1679        2081 :         state->r.in.server_name      = r->in.server_name;
    1680        2081 :         state->r.in.computer_name    = r->in.computer_name;
    1681        2081 :         state->r.in.logon_level      = r->in.logon_level;
    1682        2081 :         state->r.in.logon            = r->in.logon;
    1683        2081 :         state->r.in.validation_level = r->in.validation_level;
    1684        2081 :         state->r.in.flags            = r->in.flags;
    1685        2081 :         state->r.out.validation      = r->out.validation;
    1686        2081 :         state->r.out.authoritative   = r->out.authoritative;
    1687        2081 :         state->r.out.flags           = r->out.flags;
    1688             : 
    1689        2081 :         state->_r.lslwf = r;
    1690             : 
    1691        2081 :         nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
    1692        2081 :         if (!NT_STATUS_IS_OK(nt_status)) {
    1693           0 :                 return nt_status;
    1694             :         }
    1695             : 
    1696        2081 :         r->out.return_authenticator = talloc_zero(mem_ctx,
    1697             :                                                   struct netr_Authenticator);
    1698        2081 :         if (r->out.return_authenticator == NULL) {
    1699           0 :                 return NT_STATUS_NO_MEMORY;
    1700             :         }
    1701             : 
    1702        2081 :         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
    1703             :                                                         mem_ctx,
    1704             :                                                         r->in.computer_name,
    1705             :                                                         r->in.credential,
    1706             :                                                         r->out.return_authenticator,
    1707             :                                                         &state->creds);
    1708        2081 :         if (!NT_STATUS_IS_OK(nt_status)) {
    1709           0 :                 return nt_status;
    1710             :         }
    1711             : 
    1712        2081 :         nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
    1713             : 
    1714        2081 :         if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
    1715        2081 :                 return nt_status;
    1716             :         }
    1717             : 
    1718           0 :         return nt_status;
    1719             : }
    1720             : 
    1721             : /*
    1722             :   netr_LogonSamLogon
    1723             : */
    1724       10922 : static NTSTATUS dcesrv_netr_LogonSamLogon(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    1725             :                                    struct netr_LogonSamLogon *r)
    1726             : {
    1727        1617 :         struct dcesrv_netr_LogonSamLogon_base_state *state;
    1728        1617 :         NTSTATUS nt_status;
    1729             : 
    1730       10922 :         *r->out.authoritative = 1;
    1731             : 
    1732       10922 :         state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonSamLogon_base_state);
    1733       10922 :         if (state == NULL) {
    1734           0 :                 return NT_STATUS_NO_MEMORY;
    1735             :         }
    1736             : 
    1737       10922 :         state->dce_call = dce_call;
    1738       10922 :         state->mem_ctx = mem_ctx;
    1739             : 
    1740       10922 :         state->r.in.server_name      = r->in.server_name;
    1741       10922 :         state->r.in.computer_name    = r->in.computer_name;
    1742       10922 :         state->r.in.logon_level      = r->in.logon_level;
    1743       10922 :         state->r.in.logon            = r->in.logon;
    1744       10922 :         state->r.in.validation_level = r->in.validation_level;
    1745       10922 :         state->r.in.flags            = &state->_ignored_flags;
    1746       10922 :         state->r.out.validation      = r->out.validation;
    1747       10922 :         state->r.out.authoritative   = r->out.authoritative;
    1748       10922 :         state->r.out.flags           = &state->_ignored_flags;
    1749             : 
    1750       10922 :         state->_r.lsl = r;
    1751             : 
    1752       10922 :         nt_status = dcesrv_netr_LogonSamLogon_check(dce_call, &state->r);
    1753       10922 :         if (!NT_STATUS_IS_OK(nt_status)) {
    1754        3900 :                 return nt_status;
    1755             :         }
    1756             : 
    1757        7022 :         r->out.return_authenticator = talloc_zero(mem_ctx,
    1758             :                                                   struct netr_Authenticator);
    1759        7022 :         if (r->out.return_authenticator == NULL) {
    1760           0 :                 return NT_STATUS_NO_MEMORY;
    1761             :         }
    1762             : 
    1763        7022 :         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
    1764             :                                                         mem_ctx,
    1765             :                                                         r->in.computer_name,
    1766             :                                                         r->in.credential,
    1767             :                                                         r->out.return_authenticator,
    1768             :                                                         &state->creds);
    1769        7022 :         if (!NT_STATUS_IS_OK(nt_status)) {
    1770           0 :                 return nt_status;
    1771             :         }
    1772             : 
    1773        7022 :         nt_status = dcesrv_netr_LogonSamLogon_base_call(state);
    1774             : 
    1775        7022 :         if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
    1776        7022 :                 return nt_status;
    1777             :         }
    1778             : 
    1779           0 :         return nt_status;
    1780             : }
    1781             : 
    1782             : 
    1783             : /*
    1784             :   netr_LogonSamLogoff
    1785             : */
    1786           0 : static NTSTATUS dcesrv_netr_LogonSamLogoff(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    1787             :                        struct netr_LogonSamLogoff *r)
    1788             : {
    1789           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    1790             : }
    1791             : 
    1792             : 
    1793             : 
    1794             : /*
    1795             :   netr_DatabaseDeltas
    1796             : */
    1797           0 : static NTSTATUS dcesrv_netr_DatabaseDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    1798             :                        struct netr_DatabaseDeltas *r)
    1799             : {
    1800           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    1801             : }
    1802             : 
    1803             : 
    1804             : /*
    1805             :   netr_DatabaseSync2
    1806             : */
    1807          24 : static NTSTATUS dcesrv_netr_DatabaseSync2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    1808             :                        struct netr_DatabaseSync2 *r)
    1809             : {
    1810             :         /* win2k3 native mode returns  "NOT IMPLEMENTED" for this call */
    1811          24 :         return NT_STATUS_NOT_IMPLEMENTED;
    1812             : }
    1813             : 
    1814             : 
    1815             : /*
    1816             :   netr_DatabaseSync
    1817             : */
    1818          18 : static NTSTATUS dcesrv_netr_DatabaseSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    1819             :                        struct netr_DatabaseSync *r)
    1820             : {
    1821           3 :         struct netr_DatabaseSync2 r2;
    1822           3 :         NTSTATUS status;
    1823             : 
    1824          18 :         ZERO_STRUCT(r2);
    1825             : 
    1826          18 :         r2.in.logon_server = r->in.logon_server;
    1827          18 :         r2.in.computername = r->in.computername;
    1828          18 :         r2.in.credential = r->in.credential;
    1829          18 :         r2.in.database_id = r->in.database_id;
    1830          18 :         r2.in.restart_state = SYNCSTATE_NORMAL_STATE;
    1831          18 :         r2.in.sync_context = r->in.sync_context;
    1832          18 :         r2.out.sync_context = r->out.sync_context;
    1833          18 :         r2.out.delta_enum_array = r->out.delta_enum_array;
    1834          18 :         r2.in.preferredmaximumlength = r->in.preferredmaximumlength;
    1835             : 
    1836          18 :         status = dcesrv_netr_DatabaseSync2(dce_call, mem_ctx, &r2);
    1837             : 
    1838          18 :         return status;
    1839             : }
    1840             : 
    1841             : 
    1842             : /*
    1843             :   netr_AccountDeltas
    1844             : */
    1845          15 : static NTSTATUS dcesrv_netr_AccountDeltas(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    1846             :                        struct netr_AccountDeltas *r)
    1847             : {
    1848             :         /* w2k3 returns "NOT IMPLEMENTED" for this call */
    1849          15 :         return NT_STATUS_NOT_IMPLEMENTED;
    1850             : }
    1851             : 
    1852             : 
    1853             : /*
    1854             :   netr_AccountSync
    1855             : */
    1856          15 : static NTSTATUS dcesrv_netr_AccountSync(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    1857             :                        struct netr_AccountSync *r)
    1858             : {
    1859             :         /* w2k3 returns "NOT IMPLEMENTED" for this call */
    1860          15 :         return NT_STATUS_NOT_IMPLEMENTED;
    1861             : }
    1862             : 
    1863             : 
    1864             : /*
    1865             :   netr_GetDcName
    1866             : */
    1867          18 : static WERROR dcesrv_netr_GetDcName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    1868             :                        struct netr_GetDcName *r)
    1869             : {
    1870          18 :         const char * const attrs[] = { NULL };
    1871           3 :         struct ldb_context *sam_ctx;
    1872           3 :         struct ldb_message **res;
    1873           3 :         struct ldb_dn *domain_dn;
    1874           3 :         int ret;
    1875           3 :         const char *dcname;
    1876             : 
    1877             :         /*
    1878             :          * [MS-NRPC] 3.5.5.3.4 NetrGetDCName says
    1879             :          * that the domainname needs to be a valid netbios domain
    1880             :          * name, if it is not NULL.
    1881             :          */
    1882          18 :         if (r->in.domainname) {
    1883          18 :                 const char *dot = strchr(r->in.domainname, '.');
    1884          18 :                 size_t len = strlen(r->in.domainname);
    1885             : 
    1886          18 :                 if (dot || len > 15) {
    1887           0 :                         return WERR_NERR_DCNOTFOUND;
    1888             :                 }
    1889             : 
    1890             :                 /*
    1891             :                  * TODO: Should we also verify that only valid
    1892             :                  *       netbios name characters are used?
    1893             :                  */
    1894             :         }
    1895             : 
    1896          18 :         sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
    1897          18 :         if (sam_ctx == NULL) {
    1898           0 :                 return WERR_DS_UNAVAILABLE;
    1899             :         }
    1900             : 
    1901          18 :         domain_dn = samdb_domain_to_dn(sam_ctx, mem_ctx,
    1902             :                                        r->in.domainname);
    1903          18 :         if (domain_dn == NULL) {
    1904           0 :                 return WERR_NO_SUCH_DOMAIN;
    1905             :         }
    1906             : 
    1907          18 :         ret = gendb_search_dn(sam_ctx, mem_ctx,
    1908             :                               domain_dn, &res, attrs);
    1909          18 :         if (ret != 1) {
    1910           0 :                 return WERR_NO_SUCH_DOMAIN;
    1911             :         }
    1912             : 
    1913             :         /* TODO: - return real IP address
    1914             :          *       - check all r->in.* parameters (server_unc is ignored by w2k3!)
    1915             :          */
    1916          18 :         dcname = talloc_asprintf(mem_ctx, "\\\\%s",
    1917          18 :                                  lpcfg_netbios_name(dce_call->conn->dce_ctx->lp_ctx));
    1918          18 :         W_ERROR_HAVE_NO_MEMORY(dcname);
    1919             : 
    1920          18 :         *r->out.dcname = dcname;
    1921          18 :         return WERR_OK;
    1922             : }
    1923             : 
    1924             : struct dcesrv_netr_LogonControl_base_state {
    1925             :         struct dcesrv_call_state *dce_call;
    1926             : 
    1927             :         TALLOC_CTX *mem_ctx;
    1928             : 
    1929             :         struct netr_LogonControl2Ex r;
    1930             : 
    1931             :         struct {
    1932             :                 struct netr_LogonControl *l;
    1933             :                 struct netr_LogonControl2 *l2;
    1934             :                 struct netr_LogonControl2Ex *l2ex;
    1935             :         } _r;
    1936             : };
    1937             : 
    1938             : static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq);
    1939             : 
    1940        5998 : static WERROR dcesrv_netr_LogonControl_base_call(struct dcesrv_netr_LogonControl_base_state *state)
    1941             : {
    1942        5998 :         struct loadparm_context *lp_ctx = state->dce_call->conn->dce_ctx->lp_ctx;
    1943        1116 :         struct auth_session_info *session_info =
    1944        5998 :                 dcesrv_call_session_info(state->dce_call);
    1945        1116 :         struct imessaging_context *imsg_ctx =
    1946        5998 :                 dcesrv_imessaging_context(state->dce_call->conn);
    1947        1116 :         enum security_user_level security_level;
    1948        1116 :         struct dcerpc_binding_handle *irpc_handle;
    1949        1116 :         struct tevent_req *subreq;
    1950        1116 :         bool ok;
    1951             : 
    1952             :         /* TODO: check for WERR_INVALID_COMPUTERNAME ? */
    1953             : 
    1954        5998 :         if (state->_r.l != NULL) {
    1955             :                 /*
    1956             :                  * netr_LogonControl
    1957             :                  */
    1958        4153 :                 if (state->r.in.level == 0x00000002) {
    1959        1066 :                         return WERR_NOT_SUPPORTED;
    1960        3087 :                 } else if (state->r.in.level != 0x00000001) {
    1961        2079 :                         return WERR_INVALID_LEVEL;
    1962             :                 }
    1963             : 
    1964        1008 :                 switch (state->r.in.function_code) {
    1965         357 :                 case NETLOGON_CONTROL_QUERY:
    1966             :                 case NETLOGON_CONTROL_REPLICATE:
    1967             :                 case NETLOGON_CONTROL_SYNCHRONIZE:
    1968             :                 case NETLOGON_CONTROL_PDC_REPLICATE:
    1969             :                 case NETLOGON_CONTROL_BREAKPOINT:
    1970             :                 case NETLOGON_CONTROL_BACKUP_CHANGE_LOG:
    1971             :                 case NETLOGON_CONTROL_TRUNCATE_LOG:
    1972         357 :                         break;
    1973         567 :                 default:
    1974         567 :                         return WERR_NOT_SUPPORTED;
    1975             :                 }
    1976             :         }
    1977             : 
    1978        2286 :         if (state->r.in.level < 0x00000001) {
    1979           0 :                 return WERR_INVALID_LEVEL;
    1980             :         }
    1981             : 
    1982        2286 :         if (state->r.in.level > 0x00000004) {
    1983         126 :                 return WERR_INVALID_LEVEL;
    1984             :         }
    1985             : 
    1986        2160 :         if (state->r.in.function_code == NETLOGON_CONTROL_QUERY) {
    1987          63 :                 struct netr_NETLOGON_INFO_1 *info1 = NULL;
    1988          63 :                 struct netr_NETLOGON_INFO_3 *info3 = NULL;
    1989             : 
    1990          63 :                 switch (state->r.in.level) {
    1991          63 :                 case 0x00000001:
    1992          63 :                         info1 = talloc_zero(state->mem_ctx,
    1993             :                                             struct netr_NETLOGON_INFO_1);
    1994          63 :                         if (info1 == NULL) {
    1995           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    1996             :                         }
    1997          63 :                         state->r.out.query->info1 = info1;
    1998          63 :                         return WERR_OK;
    1999             : 
    2000           0 :                 case 0x00000003:
    2001           0 :                         info3 = talloc_zero(state->mem_ctx,
    2002             :                                             struct netr_NETLOGON_INFO_3);
    2003           0 :                         if (info3 == NULL) {
    2004           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    2005             :                         }
    2006           0 :                         state->r.out.query->info3 = info3;
    2007           0 :                         return WERR_OK;
    2008             : 
    2009           0 :                 default:
    2010           0 :                         return WERR_INVALID_PARAMETER;
    2011             :                 }
    2012             :         }
    2013             : 
    2014             :         /*
    2015             :          * Some validations are done before the access check
    2016             :          * and some after the access check
    2017             :          */
    2018        2097 :         security_level = security_session_user_level(session_info, NULL);
    2019        2097 :         if (security_level < SECURITY_ADMINISTRATOR) {
    2020        1344 :                 return WERR_ACCESS_DENIED;
    2021             :         }
    2022             : 
    2023         753 :         if (state->_r.l2 != NULL) {
    2024             :                 /*
    2025             :                  * netr_LogonControl2
    2026             :                  */
    2027         273 :                 if (state->r.in.level == 0x00000004) {
    2028           0 :                         return WERR_INVALID_LEVEL;
    2029             :                 }
    2030             :         }
    2031             : 
    2032         753 :         switch (state->r.in.level) {
    2033         238 :         case 0x00000001:
    2034         238 :                 break;
    2035             : 
    2036         249 :         case 0x00000002:
    2037         249 :                 switch (state->r.in.function_code) {
    2038         149 :                 case NETLOGON_CONTROL_REDISCOVER:
    2039             :                 case NETLOGON_CONTROL_TC_QUERY:
    2040             :                 case NETLOGON_CONTROL_TC_VERIFY:
    2041         149 :                         break;
    2042          84 :                 default:
    2043          84 :                         return WERR_INVALID_PARAMETER;
    2044             :                 }
    2045             : 
    2046         149 :                 break;
    2047             : 
    2048         170 :         case 0x00000003:
    2049         170 :                 break;
    2050             : 
    2051           0 :         case 0x00000004:
    2052           0 :                 if (state->r.in.function_code != NETLOGON_CONTROL_FIND_USER) {
    2053           0 :                         return WERR_INVALID_PARAMETER;
    2054             :                 }
    2055             : 
    2056           0 :                 break;
    2057             : 
    2058           0 :         default:
    2059           0 :                 return WERR_INVALID_LEVEL;
    2060             :         }
    2061             : 
    2062         669 :         switch (state->r.in.function_code) {
    2063         333 :         case NETLOGON_CONTROL_REDISCOVER:
    2064             :         case NETLOGON_CONTROL_TC_QUERY:
    2065             :         case NETLOGON_CONTROL_TC_VERIFY:
    2066         333 :                 if (state->r.in.level != 2) {
    2067         168 :                         return WERR_INVALID_PARAMETER;
    2068             :                 }
    2069             : 
    2070         165 :                 if (state->r.in.data == NULL) {
    2071           0 :                         return WERR_INVALID_PARAMETER;
    2072             :                 }
    2073             : 
    2074         165 :                 if (state->r.in.data->domain == NULL) {
    2075           0 :                         return WERR_INVALID_PARAMETER;
    2076             :                 }
    2077             : 
    2078         149 :                 break;
    2079             : 
    2080           0 :         case NETLOGON_CONTROL_CHANGE_PASSWORD:
    2081           0 :                 if (state->r.in.level != 1) {
    2082           0 :                         return WERR_INVALID_PARAMETER;
    2083             :                 }
    2084             : 
    2085           0 :                 if (state->r.in.data == NULL) {
    2086           0 :                         return WERR_INVALID_PARAMETER;
    2087             :                 }
    2088             : 
    2089           0 :                 if (state->r.in.data->domain == NULL) {
    2090           0 :                         return WERR_INVALID_PARAMETER;
    2091             :                 }
    2092             : 
    2093           0 :                 ok = lpcfg_is_my_domain_or_realm(lp_ctx,
    2094           0 :                                                  state->r.in.data->domain);
    2095           0 :                 if (!ok) {
    2096           0 :                         struct ldb_context *sam_ctx;
    2097             : 
    2098           0 :                         sam_ctx = dcesrv_samdb_connect_as_system(state,
    2099             :                                                                  state->dce_call);
    2100           0 :                         if (sam_ctx == NULL) {
    2101           0 :                                 return WERR_DS_UNAVAILABLE;
    2102             :                         }
    2103             : 
    2104             :                         /*
    2105             :                          * Secrets for trusted domains can only be triggered on
    2106             :                          * the PDC.
    2107             :                          */
    2108           0 :                         ok = samdb_is_pdc(sam_ctx);
    2109           0 :                         TALLOC_FREE(sam_ctx);
    2110           0 :                         if (!ok) {
    2111           0 :                                 return WERR_INVALID_DOMAIN_ROLE;
    2112             :                         }
    2113             :                 }
    2114             : 
    2115           0 :                 break;
    2116         336 :         default:
    2117         336 :                 return WERR_NOT_SUPPORTED;
    2118             :         }
    2119             : 
    2120         165 :         irpc_handle = irpc_binding_handle_by_name(state,
    2121             :                                                   imsg_ctx,
    2122             :                                                   "winbind_server",
    2123             :                                                   &ndr_table_winbind);
    2124         165 :         if (irpc_handle == NULL) {
    2125           0 :                 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
    2126           0 :                 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
    2127           0 :                 return WERR_SERVICE_NOT_FOUND;
    2128             :         }
    2129             : 
    2130             :         /*
    2131             :          * 60 seconds timeout should be enough
    2132             :          */
    2133         165 :         dcerpc_binding_handle_set_timeout(irpc_handle, 60);
    2134             : 
    2135         181 :         subreq = dcerpc_winbind_LogonControl_send(state,
    2136         165 :                                                   state->dce_call->event_ctx,
    2137             :                                                   irpc_handle,
    2138             :                                                   state->r.in.function_code,
    2139             :                                                   state->r.in.level,
    2140             :                                                   state->r.in.data,
    2141             :                                                   state->r.out.query);
    2142         165 :         if (subreq == NULL) {
    2143           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    2144             :         }
    2145         165 :         state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
    2146         165 :         tevent_req_set_callback(subreq,
    2147             :                                 dcesrv_netr_LogonControl_base_done,
    2148             :                                 state);
    2149             : 
    2150         165 :         return WERR_OK;
    2151             : }
    2152             : 
    2153         165 : static void dcesrv_netr_LogonControl_base_done(struct tevent_req *subreq)
    2154             : {
    2155          16 :         struct dcesrv_netr_LogonControl_base_state *state =
    2156         165 :                 tevent_req_callback_data(subreq,
    2157             :                 struct dcesrv_netr_LogonControl_base_state);
    2158          16 :         NTSTATUS status;
    2159             : 
    2160         165 :         status = dcerpc_winbind_LogonControl_recv(subreq, state->mem_ctx,
    2161             :                                                   &state->r.out.result);
    2162         165 :         TALLOC_FREE(subreq);
    2163         165 :         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
    2164           0 :                 state->r.out.result = WERR_TIMEOUT;
    2165         165 :         } else if (!NT_STATUS_IS_OK(status)) {
    2166           0 :                 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
    2167           0 :                 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
    2168             :                          nt_errstr(status)));
    2169             :         }
    2170             : 
    2171         165 :         if (state->_r.l2ex != NULL) {
    2172         123 :                 struct netr_LogonControl2Ex *r = state->_r.l2ex;
    2173         123 :                 r->out.result = state->r.out.result;
    2174          42 :         } else if (state->_r.l2 != NULL) {
    2175          42 :                 struct netr_LogonControl2 *r = state->_r.l2;
    2176          42 :                 r->out.result = state->r.out.result;
    2177           0 :         } else if (state->_r.l != NULL) {
    2178           0 :                 struct netr_LogonControl *r = state->_r.l;
    2179           0 :                 r->out.result = state->r.out.result;
    2180             :         }
    2181             : 
    2182         165 :         dcesrv_async_reply(state->dce_call);
    2183         165 : }
    2184             : 
    2185             : /*
    2186             :   netr_LogonControl
    2187             : */
    2188        4153 : static WERROR dcesrv_netr_LogonControl(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    2189             :                        struct netr_LogonControl *r)
    2190             : {
    2191         780 :         struct dcesrv_netr_LogonControl_base_state *state;
    2192         780 :         WERROR werr;
    2193             : 
    2194        4153 :         state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
    2195        4153 :         if (state == NULL) {
    2196           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    2197             :         }
    2198             : 
    2199        4153 :         state->dce_call = dce_call;
    2200        4153 :         state->mem_ctx = mem_ctx;
    2201             : 
    2202        4153 :         state->r.in.logon_server = r->in.logon_server;
    2203        4153 :         state->r.in.function_code = r->in.function_code;
    2204        4153 :         state->r.in.level = r->in.level;
    2205        4153 :         state->r.in.data = NULL;
    2206        4153 :         state->r.out.query = r->out.query;
    2207             : 
    2208        4153 :         state->_r.l = r;
    2209             : 
    2210        4153 :         werr = dcesrv_netr_LogonControl_base_call(state);
    2211             : 
    2212        4153 :         if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
    2213           0 :                 return werr;
    2214             :         }
    2215             : 
    2216        4153 :         return werr;
    2217             : }
    2218             : 
    2219             : /*
    2220             :   netr_LogonControl2
    2221             : */
    2222         882 : static WERROR dcesrv_netr_LogonControl2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    2223             :                        struct netr_LogonControl2 *r)
    2224             : {
    2225         168 :         struct dcesrv_netr_LogonControl_base_state *state;
    2226         168 :         WERROR werr;
    2227             : 
    2228         882 :         state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
    2229         882 :         if (state == NULL) {
    2230           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    2231             :         }
    2232             : 
    2233         882 :         state->dce_call = dce_call;
    2234         882 :         state->mem_ctx = mem_ctx;
    2235             : 
    2236         882 :         state->r.in.logon_server = r->in.logon_server;
    2237         882 :         state->r.in.function_code = r->in.function_code;
    2238         882 :         state->r.in.level = r->in.level;
    2239         882 :         state->r.in.data = r->in.data;
    2240         882 :         state->r.out.query = r->out.query;
    2241             : 
    2242         882 :         state->_r.l2 = r;
    2243             : 
    2244         882 :         werr = dcesrv_netr_LogonControl_base_call(state);
    2245             : 
    2246         882 :         if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
    2247          42 :                 return werr;
    2248             :         }
    2249             : 
    2250         840 :         return werr;
    2251             : }
    2252             : 
    2253             : /*
    2254             :   netr_LogonControl2Ex
    2255             : */
    2256         963 : static WERROR dcesrv_netr_LogonControl2Ex(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    2257             :                        struct netr_LogonControl2Ex *r)
    2258             : {
    2259         168 :         struct dcesrv_netr_LogonControl_base_state *state;
    2260         168 :         WERROR werr;
    2261             : 
    2262         963 :         state = talloc_zero(mem_ctx, struct dcesrv_netr_LogonControl_base_state);
    2263         963 :         if (state == NULL) {
    2264           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    2265             :         }
    2266             : 
    2267         963 :         state->dce_call = dce_call;
    2268         963 :         state->mem_ctx = mem_ctx;
    2269             : 
    2270         963 :         state->r = *r;
    2271         963 :         state->_r.l2ex = r;
    2272             : 
    2273         963 :         werr = dcesrv_netr_LogonControl_base_call(state);
    2274             : 
    2275         963 :         if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
    2276         123 :                 return werr;
    2277             :         }
    2278             : 
    2279         840 :         return werr;
    2280             : }
    2281             : 
    2282             : static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
    2283             :                                          struct ldb_context *sam_ctx,
    2284             :                                          struct netr_DomainTrustList *trusts,
    2285             :                                          uint32_t trust_flags);
    2286             : 
    2287             : /*
    2288             :   netr_GetAnyDCName
    2289             : */
    2290          54 : static WERROR dcesrv_netr_GetAnyDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    2291             :                        struct netr_GetAnyDCName *r)
    2292             : {
    2293           9 :         struct netr_DomainTrustList *trusts;
    2294           9 :         struct ldb_context *sam_ctx;
    2295          54 :         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
    2296           9 :         uint32_t i;
    2297           9 :         WERROR werr;
    2298             : 
    2299          54 :         *r->out.dcname = NULL;
    2300             : 
    2301          54 :         if ((r->in.domainname == NULL) || (r->in.domainname[0] == '\0')) {
    2302             :                 /* if the domainname parameter wasn't set assume our domain */
    2303          36 :                 r->in.domainname = lpcfg_workgroup(lp_ctx);
    2304             :         }
    2305             : 
    2306          54 :         sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
    2307          54 :         if (sam_ctx == NULL) {
    2308           0 :                 return WERR_DS_UNAVAILABLE;
    2309             :         }
    2310             : 
    2311          54 :         if (strcasecmp(r->in.domainname, lpcfg_workgroup(lp_ctx)) == 0) {
    2312             :                 /* well we asked for a DC of our own domain */
    2313          54 :                 if (samdb_is_pdc(sam_ctx)) {
    2314             :                         /* we are the PDC of the specified domain */
    2315          54 :                         return WERR_NO_SUCH_DOMAIN;
    2316             :                 }
    2317             : 
    2318           0 :                 *r->out.dcname = talloc_asprintf(mem_ctx, "\\%s",
    2319             :                                                 lpcfg_netbios_name(lp_ctx));
    2320           0 :                 W_ERROR_HAVE_NO_MEMORY(*r->out.dcname);
    2321             : 
    2322           0 :                 return WERR_OK;
    2323             :         }
    2324             : 
    2325             :         /* Okay, now we have to consider the trusted domains */
    2326             : 
    2327           0 :         trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
    2328           0 :         W_ERROR_HAVE_NO_MEMORY(trusts);
    2329             : 
    2330           0 :         trusts->count = 0;
    2331             : 
    2332           0 :         werr = fill_trusted_domains_array(mem_ctx, sam_ctx, trusts,
    2333             :                                           NETR_TRUST_FLAG_INBOUND
    2334             :                                           | NETR_TRUST_FLAG_OUTBOUND);
    2335           0 :         W_ERROR_NOT_OK_RETURN(werr);
    2336             : 
    2337           0 :         for (i = 0; i < trusts->count; i++) {
    2338           0 :                 if (strcasecmp(r->in.domainname, trusts->array[i].netbios_name) == 0) {
    2339             :                         /* FIXME: Here we need to find a DC for the specified
    2340             :                          * trusted domain. */
    2341             : 
    2342             :                         /* return WERR_OK; */
    2343           0 :                         return WERR_NO_SUCH_DOMAIN;
    2344             :                 }
    2345             :         }
    2346             : 
    2347           0 :         return WERR_NO_SUCH_DOMAIN;
    2348             : }
    2349             : 
    2350             : 
    2351             : /*
    2352             :   netr_DatabaseRedo
    2353             : */
    2354          18 : static NTSTATUS dcesrv_netr_DatabaseRedo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    2355             :                        struct netr_DatabaseRedo *r)
    2356             : {
    2357          18 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    2358             : }
    2359             : 
    2360             : 
    2361             : /*
    2362             :   netr_NetrEnumerateTrustedDomains
    2363             : */
    2364          21 : static NTSTATUS dcesrv_netr_NetrEnumerateTrustedDomains(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    2365             :                        struct netr_NetrEnumerateTrustedDomains *r)
    2366             : {
    2367          21 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    2368             : }
    2369             : 
    2370             : 
    2371             : /*
    2372             :   netr_LogonGetCapabilities
    2373             : */
    2374        2357 : static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    2375             :                        struct netr_LogonGetCapabilities *r)
    2376             : {
    2377         392 :         struct netlogon_creds_CredentialState *creds;
    2378         392 :         NTSTATUS status;
    2379             : 
    2380        2357 :         switch (r->in.query_level) {
    2381         741 :         case 1:
    2382         845 :                 break;
    2383        1512 :         case 2:
    2384             :                 /*
    2385             :                  * Until we know the details behind KB5028166
    2386             :                  * just return DCERPC_NCA_S_FAULT_INVALID_TAG
    2387             :                  * like an unpatched Windows Server.
    2388             :                  */
    2389         288 :                 FALL_THROUGH;
    2390             :         default:
    2391             :                 /*
    2392             :                  * There would not be a way to marshall the
    2393             :                  * the response. Which would mean our final
    2394             :                  * ndr_push would fail an we would return
    2395             :                  * an RPC-level fault with DCERPC_FAULT_BAD_STUB_DATA.
    2396             :                  *
    2397             :                  * But it's important to match a Windows server
    2398             :                  * especially before KB5028166, see also our bug #15418
    2399             :                  * Otherwise Windows client would stop talking to us.
    2400             :                  */
    2401        1512 :                 DCESRV_FAULT(DCERPC_NCA_S_FAULT_INVALID_TAG);
    2402             :         }
    2403             : 
    2404         845 :         status = dcesrv_netr_creds_server_step_check(dce_call,
    2405             :                                                      mem_ctx,
    2406             :                                                      r->in.computer_name,
    2407             :                                                      r->in.credential,
    2408             :                                                      r->out.return_authenticator,
    2409             :                                                      &creds);
    2410         845 :         if (!NT_STATUS_IS_OK(status)) {
    2411           0 :                 DEBUG(0,(__location__ " Bad credentials - error\n"));
    2412             :         }
    2413         845 :         NT_STATUS_NOT_OK_RETURN(status);
    2414             : 
    2415         845 :         r->out.capabilities->server_capabilities = creds->negotiate_flags;
    2416             : 
    2417         845 :         return NT_STATUS_OK;
    2418             : }
    2419             : 
    2420             : 
    2421             : /*
    2422             :   netr_NETRLOGONSETSERVICEBITS
    2423             : */
    2424           0 : static WERROR dcesrv_netr_NETRLOGONSETSERVICEBITS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    2425             :                        struct netr_NETRLOGONSETSERVICEBITS *r)
    2426             : {
    2427           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    2428             : }
    2429             : 
    2430             : 
    2431             : /*
    2432             :   netr_LogonGetTrustRid
    2433             : */
    2434           0 : static WERROR dcesrv_netr_LogonGetTrustRid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    2435             :                        struct netr_LogonGetTrustRid *r)
    2436             : {
    2437           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    2438             : }
    2439             : 
    2440             : 
    2441             : /*
    2442             :   netr_NETRLOGONCOMPUTESERVERDIGEST
    2443             : */
    2444           0 : static WERROR dcesrv_netr_NETRLOGONCOMPUTESERVERDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    2445             :                        struct netr_NETRLOGONCOMPUTESERVERDIGEST *r)
    2446             : {
    2447           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    2448             : }
    2449             : 
    2450             : 
    2451             : /*
    2452             :   netr_NETRLOGONCOMPUTECLIENTDIGEST
    2453             : */
    2454           0 : static WERROR dcesrv_netr_NETRLOGONCOMPUTECLIENTDIGEST(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    2455             :                        struct netr_NETRLOGONCOMPUTECLIENTDIGEST *r)
    2456             : {
    2457           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    2458             : }
    2459             : 
    2460             : 
    2461             : 
    2462             : /*
    2463             :   netr_DsRGetSiteName
    2464             : */
    2465         218 : static WERROR dcesrv_netr_DsRGetSiteName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    2466             :                                   struct netr_DsRGetSiteName *r)
    2467             : {
    2468          12 :         struct ldb_context *sam_ctx;
    2469             : 
    2470         218 :         sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
    2471         218 :         if (sam_ctx == NULL) {
    2472           0 :                 return WERR_DS_UNAVAILABLE;
    2473             :         }
    2474             : 
    2475             :         /*
    2476             :          * We assume to be a DC when we get called over NETLOGON. Hence we
    2477             :          * get our site name always by using "samdb_server_site_name()"
    2478             :          * and not "samdb_client_site_name()".
    2479             :          */
    2480         218 :         *r->out.site = samdb_server_site_name(sam_ctx, mem_ctx);
    2481         218 :         W_ERROR_HAVE_NO_MEMORY(*r->out.site);
    2482             : 
    2483         218 :         return WERR_OK;
    2484             : }
    2485             : 
    2486             : 
    2487             : /*
    2488             :   fill in a netr_OneDomainInfo from our own domain/forest
    2489             : */
    2490         294 : static NTSTATUS fill_our_one_domain_info(TALLOC_CTX *mem_ctx,
    2491             :                                 const struct lsa_TrustDomainInfoInfoEx *our_tdo,
    2492             :                                 struct GUID domain_guid,
    2493             :                                 struct netr_OneDomainInfo *info,
    2494             :                                 bool is_trust_list)
    2495             : {
    2496         294 :         ZERO_STRUCTP(info);
    2497             : 
    2498         294 :         if (is_trust_list) {
    2499         147 :                 struct netr_trust_extension *te = NULL;
    2500         147 :                 struct netr_trust_extension_info *tei = NULL;
    2501             : 
    2502             :                 /* w2k8 only fills this on trusted domains */
    2503         147 :                 te = talloc_zero(mem_ctx, struct netr_trust_extension);
    2504         147 :                 if (te == NULL) {
    2505           0 :                         return NT_STATUS_NO_MEMORY;
    2506             :                 }
    2507         147 :                 tei = &te->info;
    2508         147 :                 tei->flags |= NETR_TRUST_FLAG_PRIMARY;
    2509             : 
    2510             :                 /*
    2511             :                  * We're always within a native forest
    2512             :                  */
    2513         147 :                 tei->flags |= NETR_TRUST_FLAG_IN_FOREST;
    2514         147 :                 tei->flags |= NETR_TRUST_FLAG_NATIVE;
    2515             : 
    2516             :                 /* For now we assume we're always the tree root */
    2517         147 :                 tei->flags |= NETR_TRUST_FLAG_TREEROOT;
    2518         147 :                 tei->parent_index = 0;
    2519             : 
    2520         147 :                 tei->trust_type = our_tdo->trust_type;
    2521             :                 /*
    2522             :                  * This needs to be 0 instead of our_tdo->trust_attributes
    2523             :                  * It means LSA_TRUST_ATTRIBUTE_WITHIN_FOREST won't
    2524             :                  * be set, while NETR_TRUST_FLAG_IN_FOREST is set above.
    2525             :                  */
    2526         147 :                 tei->trust_attributes = 0;
    2527             : 
    2528         147 :                 info->trust_extension.info = te;
    2529             :         }
    2530             : 
    2531         294 :         if (is_trust_list) {
    2532         147 :                 info->dns_domainname.string = our_tdo->domain_name.string;
    2533             : 
    2534             :                 /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
    2535         147 :                 info->dns_forestname.string = NULL;
    2536             :         } else {
    2537         294 :                 info->dns_domainname.string = talloc_asprintf(mem_ctx, "%s.",
    2538         147 :                                                 our_tdo->domain_name.string);
    2539         147 :                 if (info->dns_domainname.string == NULL) {
    2540           0 :                         return NT_STATUS_NO_MEMORY;
    2541             :                 }
    2542             : 
    2543         147 :                 info->dns_forestname.string = info->dns_domainname.string;
    2544             :         }
    2545             : 
    2546         294 :         info->domainname.string = our_tdo->netbios_name.string;
    2547         294 :         info->domain_sid = our_tdo->sid;
    2548         294 :         info->domain_guid = domain_guid;
    2549             : 
    2550         294 :         return NT_STATUS_OK;
    2551             : }
    2552             : 
    2553             : /*
    2554             :   fill in a netr_OneDomainInfo from a trust tdo
    2555             : */
    2556           0 : static NTSTATUS fill_trust_one_domain_info(TALLOC_CTX *mem_ctx,
    2557             :                                 struct GUID domain_guid,
    2558             :                                 const struct lsa_TrustDomainInfoInfoEx *tdo,
    2559             :                                 struct netr_OneDomainInfo *info)
    2560             : {
    2561           0 :         struct netr_trust_extension *te = NULL;
    2562           0 :         struct netr_trust_extension_info *tei = NULL;
    2563             : 
    2564           0 :         ZERO_STRUCTP(info);
    2565             : 
    2566             :         /* w2k8 only fills this on trusted domains */
    2567           0 :         te = talloc_zero(mem_ctx, struct netr_trust_extension);
    2568           0 :         if (te == NULL) {
    2569           0 :                 return NT_STATUS_NO_MEMORY;
    2570             :         }
    2571           0 :         tei = &te->info;
    2572             : 
    2573           0 :         if (tdo->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
    2574           0 :                 tei->flags |= NETR_TRUST_FLAG_INBOUND;
    2575             :         }
    2576           0 :         if (tdo->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
    2577           0 :                 tei->flags |= NETR_TRUST_FLAG_OUTBOUND;
    2578             :         }
    2579           0 :         if (tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
    2580           0 :                 tei->flags |= NETR_TRUST_FLAG_IN_FOREST;
    2581             :         }
    2582             : 
    2583             :         /*
    2584             :          * TODO: once we support multiple domains within our forest,
    2585             :          * we need to fill this correct (or let the caller do it
    2586             :          * for all domains marked with NETR_TRUST_FLAG_IN_FOREST).
    2587             :          */
    2588           0 :         tei->parent_index = 0;
    2589             : 
    2590           0 :         tei->trust_type = tdo->trust_type;
    2591           0 :         tei->trust_attributes = tdo->trust_attributes;
    2592             : 
    2593           0 :         info->trust_extension.info = te;
    2594             : 
    2595           0 :         info->domainname.string = tdo->netbios_name.string;
    2596           0 :         if (tdo->trust_type != LSA_TRUST_TYPE_DOWNLEVEL) {
    2597           0 :                 info->dns_domainname.string = tdo->domain_name.string;
    2598             :         } else {
    2599           0 :                 info->dns_domainname.string = NULL;
    2600             :         }
    2601           0 :         info->domain_sid = tdo->sid;
    2602           0 :         info->domain_guid = domain_guid;
    2603             : 
    2604             :         /* MS-NRPC 3.5.4.3.9 - must be set to NULL for trust list */
    2605           0 :         info->dns_forestname.string = NULL;
    2606             : 
    2607           0 :         return NT_STATUS_OK;
    2608             : }
    2609             : 
    2610             : /*
    2611             :   netr_LogonGetDomainInfo
    2612             :   this is called as part of the ADS domain logon procedure.
    2613             : 
    2614             :   It has an important role in convaying details about the client, such
    2615             :   as Operating System, Version, Service Pack etc.
    2616             : */
    2617         163 : static NTSTATUS dcesrv_netr_LogonGetDomainInfo(struct dcesrv_call_state *dce_call,
    2618             :         TALLOC_CTX *mem_ctx, struct netr_LogonGetDomainInfo *r)
    2619             : {
    2620          21 :         struct netlogon_creds_CredentialState *creds;
    2621         163 :         const char * const trusts_attrs[] = {
    2622             :                 "securityIdentifier",
    2623             :                 "flatName",
    2624             :                 "trustPartner",
    2625             :                 "trustAttributes",
    2626             :                 "trustDirection",
    2627             :                 "trustType",
    2628             :                 NULL
    2629             :         };
    2630         163 :         const char * const attrs2[] = { "sAMAccountName", "dNSHostName",
    2631             :                 "msDS-SupportedEncryptionTypes", NULL };
    2632          21 :         const char *sam_account_name, *old_dns_hostname;
    2633          21 :         struct ldb_context *sam_ctx;
    2634         163 :         const struct GUID *our_domain_guid = NULL;
    2635         163 :         struct lsa_TrustDomainInfoInfoEx *our_tdo = NULL;
    2636          21 :         struct ldb_message **res1, *new_msg;
    2637         163 :         struct ldb_result *trusts_res = NULL;
    2638          21 :         struct ldb_dn *workstation_dn;
    2639          21 :         struct netr_DomainInformation *domain_info;
    2640          21 :         struct netr_LsaPolicyInformation *lsa_policy_info;
    2641         163 :         struct auth_session_info *workstation_session_info = NULL;
    2642         163 :         uint32_t default_supported_enc_types = 0xFFFFFFFF;
    2643         163 :         bool update_dns_hostname = true;
    2644          21 :         int ret, i;
    2645          21 :         NTSTATUS status;
    2646             : 
    2647         163 :         status = dcesrv_netr_creds_server_step_check(dce_call,
    2648             :                                                      mem_ctx,
    2649             :                                                      r->in.computer_name,
    2650             :                                                      r->in.credential,
    2651             :                                                      r->out.return_authenticator,
    2652             :                                                      &creds);
    2653         163 :         if (!NT_STATUS_IS_OK(status)) {
    2654           0 :                 char* local  = NULL;
    2655           0 :                 char* remote = NULL;
    2656           0 :                 TALLOC_CTX *frame = talloc_stackframe();
    2657           0 :                 remote = tsocket_address_string(dce_call->conn->remote_address,
    2658             :                                                 frame);
    2659           0 :                 local  = tsocket_address_string(dce_call->conn->local_address,
    2660             :                                                 frame);
    2661           0 :                 DBG_ERR("Bad credentials - "
    2662             :                         "computer[%s] remote[%s] local[%s]\n",
    2663             :                         log_escape(frame, r->in.computer_name),
    2664             :                         remote,
    2665             :                         local);
    2666           0 :                 talloc_free(frame);
    2667             :         }
    2668         163 :         NT_STATUS_NOT_OK_RETURN(status);
    2669             : 
    2670             :         /* We want to avoid connecting as system. */
    2671         163 :         sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
    2672         163 :         if (sam_ctx == NULL) {
    2673           0 :                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
    2674             :         }
    2675             : 
    2676         163 :         switch (r->in.level) {
    2677         147 :         case 1: /* Domain information */
    2678             : 
    2679         147 :                 if (r->in.query->workstation_info == NULL) {
    2680           0 :                         return NT_STATUS_INVALID_PARAMETER;
    2681             :                 }
    2682             : 
    2683             :                 /* Prepares the workstation DN */
    2684         147 :                 workstation_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
    2685         147 :                                                 dom_sid_string(mem_ctx, creds->sid));
    2686         147 :                 NT_STATUS_HAVE_NO_MEMORY(workstation_dn);
    2687             : 
    2688             :                 /* Get the workstation's session info from the database. */
    2689         168 :                 status = authsam_get_session_info_principal(mem_ctx,
    2690         147 :                                                             dce_call->conn->dce_ctx->lp_ctx,
    2691             :                                                             sam_ctx,
    2692             :                                                             NULL, /* principal */
    2693             :                                                             workstation_dn,
    2694             :                                                             0, /* session_info_flags */
    2695             :                                                             &workstation_session_info);
    2696         147 :                 if (!NT_STATUS_IS_OK(status)) {
    2697           0 :                         return status;
    2698             :                 }
    2699             : 
    2700             :                 /*
    2701             :                  * Reconnect to samdb as the workstation, now that we have its
    2702             :                  * session info. We do this so the database update can be
    2703             :                  * attributed to the workstation account in the audit logs --
    2704             :                  * otherwise it might be incorrectly attributed to
    2705             :                  * SID_NT_ANONYMOUS.
    2706             :                  */
    2707         147 :                 sam_ctx = dcesrv_samdb_connect_session_info(mem_ctx,
    2708             :                                                             dce_call,
    2709             :                                                             workstation_session_info,
    2710             :                                                             workstation_session_info);
    2711         147 :                 if (sam_ctx == NULL) {
    2712           0 :                         return NT_STATUS_INVALID_SYSTEM_SERVICE;
    2713             :                 }
    2714             : 
    2715             :                 /* Lookup for attributes in workstation object */
    2716         147 :                 ret = gendb_search_dn(sam_ctx, mem_ctx, workstation_dn, &res1,
    2717             :                                       attrs2);
    2718         147 :                 if (ret != 1) {
    2719           0 :                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
    2720             :                 }
    2721             : 
    2722             :                 /* Gets the sam account name which is checked against the DNS
    2723             :                  * hostname parameter. */
    2724         147 :                 sam_account_name = ldb_msg_find_attr_as_string(res1[0],
    2725             :                                                                "sAMAccountName",
    2726             :                                                                NULL);
    2727         147 :                 if (sam_account_name == NULL) {
    2728           0 :                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
    2729             :                 }
    2730             : 
    2731         147 :                 if (r->in.query->workstation_info->dns_hostname == NULL) {
    2732          18 :                         update_dns_hostname = false;
    2733             :                 }
    2734             : 
    2735             :                 /* Gets the old DNS hostname */
    2736         147 :                 old_dns_hostname = ldb_msg_find_attr_as_string(res1[0],
    2737             :                                                                "dNSHostName",
    2738             :                                                                NULL);
    2739             : 
    2740             :                 /*
    2741             :                  * Updates the DNS hostname when the client wishes that the
    2742             :                  * server should handle this for him
    2743             :                  * ("NETR_WS_FLAG_HANDLES_SPN_UPDATE" not set).
    2744             :                  * See MS-NRPC section 3.5.4.3.9
    2745             :                  */
    2746         147 :                 if ((r->in.query->workstation_info->workstation_flags
    2747         147 :                     & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
    2748         111 :                         update_dns_hostname = false;
    2749             :                 }
    2750             : 
    2751             :                 /* Gets host information and put them into our directory */
    2752             : 
    2753         147 :                 new_msg = ldb_msg_new(mem_ctx);
    2754         147 :                 NT_STATUS_HAVE_NO_MEMORY(new_msg);
    2755             : 
    2756         147 :                 new_msg->dn = workstation_dn;
    2757             : 
    2758             :                 /* Sets the OS name */
    2759             : 
    2760         147 :                 if (r->in.query->workstation_info->os_name.string == NULL) {
    2761           0 :                         return NT_STATUS_INVALID_PARAMETER;
    2762             :                 }
    2763             : 
    2764         147 :                 ret = ldb_msg_add_string(new_msg, "operatingSystem",
    2765         126 :                                          r->in.query->workstation_info->os_name.string);
    2766         147 :                 if (ret != LDB_SUCCESS) {
    2767           0 :                         return NT_STATUS_NO_MEMORY;
    2768             :                 }
    2769             : 
    2770             :                 /*
    2771             :                  * Sets information from "os_version". On an empty structure
    2772             :                  * the values are cleared.
    2773             :                  */
    2774         147 :                 if (r->in.query->workstation_info->os_version.os != NULL) {
    2775           6 :                         struct netr_OsVersionInfoEx *os_version;
    2776           6 :                         const char *os_version_str;
    2777             : 
    2778          36 :                         os_version = &r->in.query->workstation_info->os_version.os->os;
    2779             : 
    2780          36 :                         if (os_version->CSDVersion == NULL) {
    2781           0 :                                 return NT_STATUS_INVALID_PARAMETER;
    2782             :                         }
    2783             : 
    2784          36 :                         os_version_str = talloc_asprintf(new_msg, "%u.%u (%u)",
    2785             :                                                          os_version->MajorVersion,
    2786             :                                                          os_version->MinorVersion,
    2787             :                                                          os_version->BuildNumber);
    2788          36 :                         NT_STATUS_HAVE_NO_MEMORY(os_version_str);
    2789             : 
    2790          36 :                         if (strlen(os_version->CSDVersion) != 0) {
    2791          18 :                                 ret = ldb_msg_add_string(new_msg,
    2792             :                                                          "operatingSystemServicePack",
    2793             :                                                          os_version->CSDVersion);
    2794             :                         } else {
    2795          18 :                                 ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
    2796             :                                                            "operatingSystemServicePack");
    2797             :                         }
    2798          36 :                         if (ret != LDB_SUCCESS) {
    2799           0 :                                 return NT_STATUS_NO_MEMORY;
    2800             :                         }
    2801             : 
    2802          36 :                         ret = ldb_msg_add_string(new_msg,
    2803             :                                                  "operatingSystemVersion",
    2804             :                                                  os_version_str);
    2805          36 :                         if (ret != LDB_SUCCESS) {
    2806           0 :                                 return NT_STATUS_NO_MEMORY;
    2807             :                         }
    2808             :                 } else {
    2809         111 :                         ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
    2810             :                                                    "operatingSystemServicePack");
    2811         111 :                         if (ret != LDB_SUCCESS) {
    2812           0 :                                 return NT_STATUS_NO_MEMORY;
    2813             :                         }
    2814             : 
    2815         111 :                         ret = samdb_msg_add_delete(sam_ctx, mem_ctx, new_msg,
    2816             :                                                    "operatingSystemVersion");
    2817         111 :                         if (ret != LDB_SUCCESS) {
    2818           0 :                                 return NT_STATUS_NO_MEMORY;
    2819             :                         }
    2820             :                 }
    2821             : 
    2822             :                 /*
    2823             :                  * If the boolean "update_dns_hostname" remained true, then we
    2824             :                  * are fine to start the update.
    2825             :                  */
    2826         147 :                 if (update_dns_hostname) {
    2827          39 :                         ret = ldb_msg_add_string(new_msg,
    2828             :                                                  "dNSHostname",
    2829          36 :                                                  r->in.query->workstation_info->dns_hostname);
    2830          36 :                         if (ret != LDB_SUCCESS) {
    2831           0 :                                 return NT_STATUS_NO_MEMORY;
    2832             :                         }
    2833             : 
    2834             :                         /* This manual "servicePrincipalName" generation is
    2835             :                          * still needed! Since the update in the samldb LDB
    2836             :                          * module does only work if the entries already exist
    2837             :                          * which isn't always the case. */
    2838          36 :                         ret = ldb_msg_add_string(new_msg,
    2839             :                                                  "servicePrincipalName",
    2840          36 :                                                  talloc_asprintf(new_msg, "HOST/%s",
    2841             :                                                  r->in.computer_name));
    2842          36 :                         if (ret != LDB_SUCCESS) {
    2843           0 :                                 return NT_STATUS_NO_MEMORY;
    2844             :                         }
    2845             : 
    2846          36 :                         ret = ldb_msg_add_string(new_msg,
    2847             :                                                  "servicePrincipalName",
    2848          36 :                                                  talloc_asprintf(new_msg, "HOST/%s",
    2849          36 :                                                  r->in.query->workstation_info->dns_hostname));
    2850          36 :                         if (ret != LDB_SUCCESS) {
    2851           0 :                                 return NT_STATUS_NO_MEMORY;
    2852             :                         }
    2853             :                 }
    2854             : 
    2855         147 :                 if (dsdb_replace(sam_ctx, new_msg, DSDB_FLAG_FORCE_ALLOW_VALIDATED_DNS_HOSTNAME_SPN_WRITE) != LDB_SUCCESS) {
    2856          30 :                         DEBUG(3,("Impossible to update samdb: %s\n",
    2857             :                                 ldb_errstring(sam_ctx)));
    2858             :                 }
    2859             : 
    2860         147 :                 talloc_free(new_msg);
    2861             : 
    2862             :                 /* Writes back the domain information */
    2863             : 
    2864         147 :                 our_domain_guid = samdb_domain_guid(sam_ctx);
    2865         147 :                 if (our_domain_guid == NULL) {
    2866           0 :                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
    2867             :                 }
    2868             : 
    2869         147 :                 status = dsdb_trust_local_tdo_info(mem_ctx, sam_ctx, &our_tdo);
    2870         147 :                 if (!NT_STATUS_IS_OK(status)) {
    2871           0 :                         return status;
    2872             :                 }
    2873             : 
    2874         147 :                 status = dsdb_trust_search_tdos(sam_ctx,
    2875             :                                                 NULL, /* exclude */
    2876             :                                                 trusts_attrs,
    2877             :                                                 mem_ctx,
    2878             :                                                 &trusts_res);
    2879         147 :                 if (!NT_STATUS_IS_OK(status)) {
    2880           0 :                         return status;
    2881             :                 }
    2882             : 
    2883         147 :                 domain_info = talloc(mem_ctx, struct netr_DomainInformation);
    2884         147 :                 NT_STATUS_HAVE_NO_MEMORY(domain_info);
    2885             : 
    2886         147 :                 ZERO_STRUCTP(domain_info);
    2887             : 
    2888             :                 /* Information about the local and trusted domains */
    2889             : 
    2890         147 :                 status = fill_our_one_domain_info(mem_ctx,
    2891             :                                                   our_tdo,
    2892             :                                                   *our_domain_guid,
    2893             :                                                   &domain_info->primary_domain,
    2894             :                                                   false);
    2895         147 :                 if (!NT_STATUS_IS_OK(status)) {
    2896           0 :                         return status;
    2897             :                 }
    2898             : 
    2899         147 :                 domain_info->trusted_domain_count = trusts_res->count + 1;
    2900         147 :                 domain_info->trusted_domains = talloc_zero_array(mem_ctx,
    2901             :                         struct netr_OneDomainInfo,
    2902             :                         domain_info->trusted_domain_count);
    2903         147 :                 NT_STATUS_HAVE_NO_MEMORY(domain_info->trusted_domains);
    2904             : 
    2905         147 :                 for (i=0; i < trusts_res->count; i++) {
    2906           0 :                         struct netr_OneDomainInfo *o =
    2907           0 :                                 &domain_info->trusted_domains[i];
    2908             :                         /* we can't know the guid of trusts outside our forest */
    2909           0 :                         struct GUID trust_domain_guid = GUID_zero();
    2910           0 :                         struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
    2911             : 
    2912           0 :                         status = dsdb_trust_parse_tdo_info(mem_ctx,
    2913           0 :                                                            trusts_res->msgs[i],
    2914             :                                                            &tdo);
    2915           0 :                         if (!NT_STATUS_IS_OK(status)) {
    2916           0 :                                 return status;
    2917             :                         }
    2918             : 
    2919           0 :                         status = fill_trust_one_domain_info(mem_ctx,
    2920             :                                                             trust_domain_guid,
    2921             :                                                             tdo,
    2922             :                                                             o);
    2923           0 :                         if (!NT_STATUS_IS_OK(status)) {
    2924           0 :                                 return status;
    2925             :                         }
    2926             :                 }
    2927             : 
    2928         168 :                 status = fill_our_one_domain_info(mem_ctx,
    2929             :                                                   our_tdo,
    2930             :                                                   *our_domain_guid,
    2931         147 :                                                   &domain_info->trusted_domains[i],
    2932             :                                                   true);
    2933         147 :                 if (!NT_STATUS_IS_OK(status)) {
    2934           0 :                         return status;
    2935             :                 }
    2936             : 
    2937             :                 /* Sets the supported encryption types */
    2938         147 :                 domain_info->supported_enc_types = ldb_msg_find_attr_as_uint(res1[0],
    2939             :                         "msDS-SupportedEncryptionTypes",
    2940             :                         default_supported_enc_types);
    2941             : 
    2942             :                 /* Other host domain information */
    2943             : 
    2944         147 :                 lsa_policy_info = talloc(mem_ctx,
    2945             :                         struct netr_LsaPolicyInformation);
    2946         147 :                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
    2947         147 :                 ZERO_STRUCTP(lsa_policy_info);
    2948             : 
    2949         147 :                 domain_info->lsa_policy = *lsa_policy_info;
    2950             : 
    2951             :                 /* The DNS hostname is only returned back when there is a chance
    2952             :                  * for a change. */
    2953         147 :                 if ((r->in.query->workstation_info->workstation_flags
    2954         147 :                     & NETR_WS_FLAG_HANDLES_SPN_UPDATE) != 0) {
    2955         111 :                         domain_info->dns_hostname.string = old_dns_hostname;
    2956             :                 } else {
    2957          36 :                         domain_info->dns_hostname.string = NULL;
    2958             :                 }
    2959             : 
    2960         147 :                 domain_info->workstation_flags =
    2961         147 :                         r->in.query->workstation_info->workstation_flags & (
    2962             :                         NETR_WS_FLAG_HANDLES_SPN_UPDATE | NETR_WS_FLAG_HANDLES_INBOUND_TRUSTS);
    2963             : 
    2964         147 :                 r->out.info->domain_info = domain_info;
    2965         147 :         break;
    2966          16 :         case 2: /* LSA policy information - not used at the moment */
    2967          16 :                 lsa_policy_info = talloc(mem_ctx,
    2968             :                         struct netr_LsaPolicyInformation);
    2969          16 :                 NT_STATUS_HAVE_NO_MEMORY(lsa_policy_info);
    2970          16 :                 ZERO_STRUCTP(lsa_policy_info);
    2971             : 
    2972          16 :                 r->out.info->lsa_policy_info = lsa_policy_info;
    2973          16 :         break;
    2974           0 :         default:
    2975           0 :                 return NT_STATUS_INVALID_LEVEL;
    2976             :         break;
    2977             :         }
    2978             : 
    2979         163 :         return NT_STATUS_OK;
    2980             : }
    2981             : 
    2982             : 
    2983             : /*
    2984             :   netr_ServerPasswordGet
    2985             : */
    2986          18 : static NTSTATUS dcesrv_netr_ServerPasswordGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    2987             :                        struct netr_ServerPasswordGet *r)
    2988             : {
    2989          18 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    2990             : }
    2991             : 
    2992          17 : static bool sam_rodc_access_check(struct ldb_context *sam_ctx,
    2993             :                                   TALLOC_CTX *mem_ctx,
    2994             :                                   struct dom_sid *user_sid,
    2995             :                                   struct ldb_dn *obj_dn)
    2996             : {
    2997          17 :         const char *rodc_attrs[] = { "msDS-NeverRevealGroup",
    2998             :                                      "msDS-RevealOnDemandGroup",
    2999             :                                      "userAccountControl",
    3000             :                                      NULL };
    3001          17 :         const char *obj_attrs[] = { "tokenGroups", "objectSid", "UserAccountControl", "msDS-KrbTgtLinkBL", NULL };
    3002           0 :         struct ldb_dn *rodc_dn;
    3003           0 :         int ret;
    3004          17 :         struct ldb_result *rodc_res = NULL, *obj_res = NULL;
    3005           0 :         WERROR werr;
    3006             : 
    3007          17 :         rodc_dn = ldb_dn_new_fmt(mem_ctx, sam_ctx, "<SID=%s>",
    3008             :                                  dom_sid_string(mem_ctx, user_sid));
    3009          17 :         if (!ldb_dn_validate(rodc_dn)) goto denied;
    3010             : 
    3011             :         /*
    3012             :          * do the two searches we need
    3013             :          * We need DSDB_SEARCH_SHOW_EXTENDED_DN as we get a SID list
    3014             :          * out of the extended DNs
    3015             :          */
    3016          17 :         ret = dsdb_search_dn(sam_ctx, mem_ctx, &rodc_res, rodc_dn, rodc_attrs,
    3017             :                              DSDB_SEARCH_SHOW_EXTENDED_DN);
    3018          17 :         if (ret != LDB_SUCCESS || rodc_res->count != 1) goto denied;
    3019             : 
    3020          17 :         ret = dsdb_search_dn(sam_ctx, mem_ctx, &obj_res, obj_dn, obj_attrs, 0);
    3021          17 :         if (ret != LDB_SUCCESS || obj_res->count != 1) goto denied;
    3022             : 
    3023          17 :         werr = samdb_confirm_rodc_allowed_to_repl_to(sam_ctx,
    3024             :                                                      user_sid,
    3025          17 :                                                      rodc_res->msgs[0],
    3026          17 :                                                      obj_res->msgs[0]);
    3027             : 
    3028          17 :         if (W_ERROR_IS_OK(werr)) {
    3029           6 :                 goto allowed;
    3030             :         }
    3031          11 : denied:
    3032          11 :         return false;
    3033           6 : allowed:
    3034           6 :         return true;
    3035             : 
    3036             : }
    3037             : 
    3038             : /*
    3039             :   netr_NetrLogonSendToSam
    3040             : */
    3041          17 : static NTSTATUS dcesrv_netr_NetrLogonSendToSam(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    3042             :                                                struct netr_NetrLogonSendToSam *r)
    3043             : {
    3044           0 :         struct netlogon_creds_CredentialState *creds;
    3045           0 :         struct ldb_context *sam_ctx;
    3046           0 :         NTSTATUS nt_status;
    3047           0 :         DATA_BLOB decrypted_blob;
    3048           0 :         enum ndr_err_code ndr_err;
    3049          17 :         struct netr_SendToSamBase base_msg = { 0 };
    3050             : 
    3051          17 :         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
    3052             :                                                         mem_ctx,
    3053             :                                                         r->in.computer_name,
    3054             :                                                         r->in.credential,
    3055             :                                                         r->out.return_authenticator,
    3056             :                                                         &creds);
    3057             : 
    3058          17 :         NT_STATUS_NOT_OK_RETURN(nt_status);
    3059             : 
    3060          17 :         switch (creds->secure_channel_type) {
    3061          17 :         case SEC_CHAN_BDC:
    3062             :         case SEC_CHAN_RODC:
    3063          17 :                 break;
    3064           0 :         case SEC_CHAN_WKSTA:
    3065             :         case SEC_CHAN_DNS_DOMAIN:
    3066             :         case SEC_CHAN_DOMAIN:
    3067             :         case SEC_CHAN_NULL:
    3068           0 :                 return NT_STATUS_INVALID_PARAMETER;
    3069           0 :         default:
    3070           0 :                 DEBUG(1, ("Client asked for an invalid secure channel type: %d\n",
    3071             :                           creds->secure_channel_type));
    3072           0 :                 return NT_STATUS_INVALID_PARAMETER;
    3073             :         }
    3074             : 
    3075          17 :         sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
    3076          17 :         if (sam_ctx == NULL) {
    3077           0 :                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
    3078             :         }
    3079             : 
    3080             :         /* Buffer is meant to be 16-bit aligned */
    3081          17 :         if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
    3082          17 :                 nt_status = netlogon_creds_aes_decrypt(creds,
    3083             :                                                        r->in.opaque_buffer,
    3084          17 :                                                        r->in.buffer_len);
    3085             :         } else {
    3086           0 :                 nt_status = netlogon_creds_arcfour_crypt(creds,
    3087             :                                                          r->in.opaque_buffer,
    3088           0 :                                                          r->in.buffer_len);
    3089             :         }
    3090          17 :         if (!NT_STATUS_IS_OK(nt_status)) {
    3091           0 :                 return nt_status;
    3092             :         }
    3093             : 
    3094          17 :         decrypted_blob.data = r->in.opaque_buffer;
    3095          17 :         decrypted_blob.length = r->in.buffer_len;
    3096             : 
    3097          17 :         ndr_err = ndr_pull_struct_blob(&decrypted_blob, mem_ctx, &base_msg,
    3098             :                                        (ndr_pull_flags_fn_t)ndr_pull_netr_SendToSamBase);
    3099             : 
    3100          17 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    3101             :                 /* We only partially implement SendToSam */
    3102           0 :                 return NT_STATUS_NOT_IMPLEMENTED;
    3103             :         }
    3104             : 
    3105             :         /* Now 'send' to SAM */
    3106          17 :         switch (base_msg.message_type) {
    3107          17 :         case SendToSamResetBadPasswordCount:
    3108             :         {
    3109          17 :                 struct ldb_message *msg = ldb_msg_new(mem_ctx);
    3110          17 :                 struct ldb_dn *dn = NULL;
    3111          17 :                 int ret = 0;
    3112             : 
    3113             : 
    3114          17 :                 ret = ldb_transaction_start(sam_ctx);
    3115          17 :                 if (ret != LDB_SUCCESS) {
    3116           0 :                         return NT_STATUS_INTERNAL_ERROR;
    3117             :                 }
    3118             : 
    3119          17 :                 ret = dsdb_find_dn_by_guid(sam_ctx,
    3120             :                                            mem_ctx,
    3121             :                                            &base_msg.message.reset_bad_password.guid,
    3122             :                                            0,
    3123             :                                            &dn);
    3124          17 :                 if (ret != LDB_SUCCESS) {
    3125           0 :                         ldb_transaction_cancel(sam_ctx);
    3126           0 :                         return NT_STATUS_INVALID_PARAMETER;
    3127             :                 }
    3128             : 
    3129          17 :                 if (creds->secure_channel_type == SEC_CHAN_RODC &&
    3130          17 :                     !sam_rodc_access_check(sam_ctx, mem_ctx, creds->sid, dn)) {
    3131          11 :                         DEBUG(1, ("Client asked to reset bad password on "
    3132             :                                   "an arbitrary user: %s\n",
    3133             :                                   ldb_dn_get_linearized(dn)));
    3134          11 :                         ldb_transaction_cancel(sam_ctx);
    3135          11 :                         return NT_STATUS_INVALID_PARAMETER;
    3136             :                 }
    3137             : 
    3138           6 :                 msg->dn = dn;
    3139             : 
    3140           6 :                 ret = samdb_msg_add_int(sam_ctx, mem_ctx, msg, "badPwdCount", 0);
    3141           6 :                 if (ret != LDB_SUCCESS) {
    3142           0 :                         ldb_transaction_cancel(sam_ctx);
    3143           0 :                         return NT_STATUS_INVALID_PARAMETER;
    3144             :                 }
    3145             : 
    3146           6 :                 ret = dsdb_replace(sam_ctx, msg, 0);
    3147           6 :                 if (ret != LDB_SUCCESS) {
    3148           0 :                         ldb_transaction_cancel(sam_ctx);
    3149           0 :                         return NT_STATUS_INVALID_PARAMETER;
    3150             :                 }
    3151             : 
    3152           6 :                 ret = ldb_transaction_commit(sam_ctx);
    3153           6 :                 if (ret != LDB_SUCCESS) {
    3154           0 :                         ldb_transaction_cancel(sam_ctx);
    3155           0 :                         return NT_STATUS_INTERNAL_ERROR;
    3156             :                 }
    3157             : 
    3158           6 :                 break;
    3159             :         }
    3160           0 :         default:
    3161           0 :                 return NT_STATUS_NOT_IMPLEMENTED;
    3162             :         }
    3163             : 
    3164           6 :         return NT_STATUS_OK;
    3165             : }
    3166             : 
    3167             : struct dcesrv_netr_DsRGetDCName_base_state {
    3168             :         struct dcesrv_call_state *dce_call;
    3169             :         TALLOC_CTX *mem_ctx;
    3170             : 
    3171             :         struct netr_DsRGetDCNameEx2 r;
    3172             :         const char *client_site;
    3173             : 
    3174             :         struct {
    3175             :                 struct netr_DsRGetDCName *dc;
    3176             :                 struct netr_DsRGetDCNameEx *dcex;
    3177             :                 struct netr_DsRGetDCNameEx2 *dcex2;
    3178             :         } _r;
    3179             : };
    3180             : 
    3181             : static void dcesrv_netr_DsRGetDCName_base_done(struct tevent_req *subreq);
    3182             : 
    3183             : /* Returns a nonzero value if multiple bits in 'val' are set. */
    3184         686 : static bool multiple_bits_set(uint32_t val)
    3185             : {
    3186             :         /*
    3187             :          * Subtracting one from an integer has the effect of flipping all the
    3188             :          * bits from the least significant bit up to and including the least
    3189             :          * significant '1' bit. For example,
    3190             :          *
    3191             :          *   0b101000 - 1
    3192             :          * = 0b100111
    3193             :          *       ====
    3194             :          *
    3195             :          * If 'val' is zero, all the bits will be flipped and thus the bitwise
    3196             :          * AND of 'val' with 'val - 1' will be zero.
    3197             :          *
    3198             :          * If the integer is nonzero, the least significant '1' bit will be
    3199             :          * ANDed with a '0' bit and so will be reset in the final result, but
    3200             :          * all other '1' bits will remain set. In other words, the effect of
    3201             :          * this expression is to mask off the least significant bit that is
    3202             :          * set. Therefore iff the result of 'val & (val - 1)' is non-zero, 'val'
    3203             :          * must contain multiple set bits.
    3204             :          */
    3205         686 :         return val & (val - 1);
    3206             : }
    3207             : 
    3208         343 : static WERROR dcesrv_netr_DsRGetDCName_base_call(struct dcesrv_netr_DsRGetDCName_base_state *state)
    3209             : {
    3210         343 :         struct dcesrv_call_state *dce_call = state->dce_call;
    3211          26 :         struct imessaging_context *imsg_ctx =
    3212         343 :                 dcesrv_imessaging_context(dce_call->conn);
    3213         343 :         TALLOC_CTX *mem_ctx = state->mem_ctx;
    3214         343 :         struct netr_DsRGetDCNameEx2 *r = &state->r;
    3215          26 :         struct ldb_context *sam_ctx;
    3216          26 :         struct netr_DsRGetDCNameInfo *info;
    3217         343 :         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
    3218          26 :         const struct tsocket_address *local_address;
    3219         343 :         char *local_addr = NULL;
    3220          26 :         const struct tsocket_address *remote_address;
    3221         343 :         char *remote_addr = NULL;
    3222          26 :         const char *server_site_name;
    3223          26 :         char *guid_str;
    3224          26 :         struct netlogon_samlogon_response response;
    3225          26 :         NTSTATUS status;
    3226         343 :         const char *dc_name = NULL;
    3227         343 :         const char *domain_name = NULL;
    3228          26 :         const char *pdc_ip;
    3229         343 :         bool different_domain = true;
    3230         343 :         bool force_remote_lookup = false;
    3231          26 :         uint32_t valid_flags;
    3232          26 :         uint32_t this_dc_valid_flags;
    3233          26 :         int dc_level;
    3234             : 
    3235         343 :         ZERO_STRUCTP(r->out.info);
    3236             : 
    3237         343 :         sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
    3238         343 :         if (sam_ctx == NULL) {
    3239           0 :                 return WERR_DS_UNAVAILABLE;
    3240             :         }
    3241             : 
    3242         343 :         local_address = dcesrv_connection_get_local_address(dce_call->conn);
    3243         343 :         if (tsocket_address_is_inet(local_address, "ip")) {
    3244         245 :                 local_addr = tsocket_address_inet_addr_string(local_address, state);
    3245         245 :                 W_ERROR_HAVE_NO_MEMORY(local_addr);
    3246             :         }
    3247             : 
    3248         343 :         remote_address = dcesrv_connection_get_remote_address(dce_call->conn);
    3249         343 :         if (tsocket_address_is_inet(remote_address, "ip")) {
    3250         245 :                 remote_addr = tsocket_address_inet_addr_string(remote_address, state);
    3251         245 :                 W_ERROR_HAVE_NO_MEMORY(remote_addr);
    3252             :         }
    3253             : 
    3254             :         /* "server_unc" is ignored by w2k3 */
    3255             : 
    3256             :         /*
    3257             :          * With the following flags:
    3258             :          * DS_FORCE_REDISCOVERY (Flag A)
    3259             :          * DS_DIRECTORY_SERVICE_REQUIRED (Flag B)
    3260             :          * DS_DIRECTORY_SERVICE_PREFERRED (Flag C)
    3261             :          * DS_GC_SERVER_REQUIRED (Flag D)
    3262             :          * DS_PDC_REQUIRED (Flag E)
    3263             :          * DS_BACKGROUND_ONLY (Flag F)
    3264             :          * DS_IP_REQUIRED (Flag G)
    3265             :          * DS_KDC_REQUIRED (Flag H)
    3266             :          * DS_TIMESERV_REQUIRED (Flag I)
    3267             :          * DS_WRITABLE_REQUIRED (Flag J)
    3268             :          * DS_GOOD_TIMESERV_PREFERRED (Flag K)
    3269             :          * DS_AVOID_SELF (Flag L)
    3270             :          * DS_ONLY_LDAP_NEEDED (Flag M)
    3271             :          * DS_IS_FLAT_NAME (Flag N)
    3272             :          * DS_IS_DNS_NAME (Flag O)
    3273             :          * DS_TRY_NEXTCLOSEST_SITE (Flag P)
    3274             :          * DS_DIRECTORY_SERVICE_6_REQUIRED  (Flag Q)
    3275             :          * DS_WEB_SERVICE_REQUIRED (Flag T)
    3276             :          * DS_DIRECTORY_SERVICE_8_REQUIRED  (Flag U)
    3277             :          * DS_DIRECTORY_SERVICE_9_REQUIRED  (Flag V)
    3278             :          * DS_DIRECTORY_SERVICE_10_REQUIRED (Flag W)
    3279             :          * DS_RETURN_DNS_NAME (Flag R)
    3280             :          * DS_RETURN_FLAT_NAME (Flag S)
    3281             :          *
    3282             :          * MS-NRPC 3.5.4.3.1 says:
    3283             :          * ...
    3284             :          * On receiving this call, the server MUST perform the following Flags
    3285             :          * parameter validations:
    3286             :          * - Flags D, E, and H MUST NOT be combined with each other.
    3287             :          * - Flag N MUST NOT be combined with the O flag.
    3288             :          * - Flag R MUST NOT be combined with the S flag.
    3289             :          * - Flags B, Q, U, V, and W MUST NOT be combined with each other.
    3290             :          * - Flag K MUST NOT be combined with any of the flags: B, C, D, E, or H.
    3291             :          * - Flag P MUST NOT be set when the SiteName parameter is provided.
    3292             :          * The server MUST return ERROR_INVALID_FLAGS for any of the previously
    3293             :          * mentioned conflicting combinations.
    3294             :          * ...
    3295             :          */
    3296             : 
    3297         343 :         valid_flags = DSGETDC_VALID_FLAGS;
    3298             : 
    3299         343 :         if (r->in.flags & ~valid_flags) {
    3300             :                 /*
    3301             :                  * TODO: add tests to prove this (maybe based on the
    3302             :                  * msDS-Behavior-Version levels of dc, domain and/or forest
    3303             :                  */
    3304           0 :                 return WERR_INVALID_FLAGS;
    3305             :         }
    3306             : 
    3307             :         /* Flags D, E, and H MUST NOT be combined with each other. */
    3308             : #define _DEH (DS_GC_SERVER_REQUIRED|DS_PDC_REQUIRED|DS_KDC_REQUIRED)
    3309         343 :         if (multiple_bits_set(r->in.flags & _DEH)) {
    3310           0 :                 return WERR_INVALID_FLAGS;
    3311             :         }
    3312             : 
    3313             :         /* Flag N MUST NOT be combined with the O flag. */
    3314         343 :         if (r->in.flags & DS_IS_FLAT_NAME &&
    3315           0 :             r->in.flags & DS_IS_DNS_NAME) {
    3316           0 :                 return WERR_INVALID_FLAGS;
    3317             :         }
    3318             : 
    3319             :         /* Flag R MUST NOT be combined with the S flag. */
    3320         343 :         if (r->in.flags & DS_RETURN_DNS_NAME &&
    3321         243 :             r->in.flags & DS_RETURN_FLAT_NAME) {
    3322           0 :                 return WERR_INVALID_FLAGS;
    3323             :         }
    3324             : 
    3325             :         /* Flags B, Q, U, V, and W MUST NOT be combined with each other */
    3326             : #define _BQUVW ( \
    3327             :         DS_DIRECTORY_SERVICE_REQUIRED | \
    3328             :         DS_DIRECTORY_SERVICE_6_REQUIRED | \
    3329             :         DS_DIRECTORY_SERVICE_8_REQUIRED | \
    3330             :         DS_DIRECTORY_SERVICE_9_REQUIRED | \
    3331             :         DS_DIRECTORY_SERVICE_10_REQUIRED | \
    3332             : 0)
    3333         343 :         if (multiple_bits_set(r->in.flags & _BQUVW)) {
    3334           0 :                 return WERR_INVALID_FLAGS;
    3335             :         }
    3336             : 
    3337             :         /*
    3338             :          * Flag K MUST NOT be combined with any of the flags:
    3339             :          * B, C, D, E, or H.
    3340             :          */
    3341         343 :         if (r->in.flags & DS_GOOD_TIMESERV_PREFERRED &&
    3342           0 :             r->in.flags &
    3343             :             (DS_DIRECTORY_SERVICE_REQUIRED |
    3344             :              DS_DIRECTORY_SERVICE_PREFERRED |
    3345             :              DS_GC_SERVER_REQUIRED |
    3346             :              DS_PDC_REQUIRED |
    3347             :              DS_KDC_REQUIRED)) {
    3348           0 :                 return WERR_INVALID_FLAGS;
    3349             :         }
    3350             : 
    3351             :         /* Flag P MUST NOT be set when the SiteName parameter is provided. */
    3352         343 :         if (r->in.flags & DS_TRY_NEXTCLOSEST_SITE &&
    3353           0 :             r->in.site_name) {
    3354           0 :                 return WERR_INVALID_FLAGS;
    3355             :         }
    3356             : 
    3357             :         /*
    3358             :          * If we send an all-zero GUID, we should ignore it as winbind actually
    3359             :          * checks it with a DNS query. Windows also appears to ignore it.
    3360             :          */
    3361         343 :         if (r->in.domain_guid != NULL && GUID_all_zero(r->in.domain_guid)) {
    3362           4 :                 r->in.domain_guid = NULL;
    3363             :         }
    3364             : 
    3365             :         /* Attempt winbind search only if we suspect the domain is incorrect */
    3366         343 :         if (r->in.domain_name != NULL && strcmp("", r->in.domain_name) != 0) {
    3367         202 :                 if (r->in.flags & DS_IS_FLAT_NAME) {
    3368           0 :                         if (strcasecmp_m(r->in.domain_name,
    3369             :                                          lpcfg_sam_name(lp_ctx)) == 0) {
    3370           0 :                                 different_domain = false;
    3371             :                         }
    3372         202 :                 } else if (r->in.flags & DS_IS_DNS_NAME) {
    3373           0 :                         if (strcasecmp_m(r->in.domain_name,
    3374             :                                          lpcfg_dnsdomain(lp_ctx)) == 0) {
    3375           0 :                                 different_domain = false;
    3376             :                         }
    3377             :                 } else {
    3378         202 :                         if (strcasecmp_m(r->in.domain_name,
    3379         120 :                                          lpcfg_sam_name(lp_ctx)) == 0 ||
    3380         120 :                             strcasecmp_m(r->in.domain_name,
    3381             :                                          lpcfg_dnsdomain(lp_ctx)) == 0) {
    3382         137 :                                 different_domain = false;
    3383             :                         }
    3384             :                 }
    3385             :         } else {
    3386             :                 /*
    3387             :                  * We need to be able to handle empty domain names, where we
    3388             :                  * revert to our domain by default.
    3389             :                  */
    3390         136 :                 different_domain = false;
    3391             :         }
    3392             : 
    3393         317 :         if (!different_domain) {
    3394         299 :                 dc_level = dsdb_dc_functional_level(sam_ctx);
    3395             : 
    3396             :                 /*
    3397             :                  * Do not return a local response if we do not support the
    3398             :                  * functional level or feature (eg web services)
    3399             :                  */
    3400         299 :                 this_dc_valid_flags = valid_flags;
    3401             : 
    3402             :                 /* Samba does not implement this */
    3403         299 :                 this_dc_valid_flags &= ~DS_WEB_SERVICE_REQUIRED;
    3404             : 
    3405         299 :                 if (dc_level < DS_DOMAIN_FUNCTION_2012) {
    3406         154 :                         this_dc_valid_flags &= ~DS_DIRECTORY_SERVICE_8_REQUIRED;
    3407             :                 }
    3408         299 :                 if (dc_level < DS_DOMAIN_FUNCTION_2012_R2) {
    3409         154 :                         this_dc_valid_flags &= ~DS_DIRECTORY_SERVICE_9_REQUIRED;
    3410             :                 }
    3411         299 :                 if (dc_level < DS_DOMAIN_FUNCTION_2016) {
    3412         154 :                         this_dc_valid_flags &= ~DS_DIRECTORY_SERVICE_10_REQUIRED;
    3413             :                 }
    3414         299 :                 if (r->in.flags & ~this_dc_valid_flags) {
    3415           6 :                         DBG_INFO("Forcing remote lookup to find another DC "
    3416             :                                  "in this domain %s with more features, "
    3417             :                                  "as this Samba DC is Functional level %d but flags are 0x08%x\n",
    3418             :                                  r->in.domain_name, dc_level, (unsigned int)r->in.flags);
    3419           6 :                         force_remote_lookup = true;
    3420             :                 }
    3421             :         }
    3422             : 
    3423             :         /* Proof server site parameter "site_name" if it was specified */
    3424         343 :         server_site_name = samdb_server_site_name(sam_ctx, state);
    3425         343 :         W_ERROR_HAVE_NO_MEMORY(server_site_name);
    3426         343 :         if (force_remote_lookup
    3427         337 :             || different_domain
    3428         303 :             || (r->in.site_name != NULL &&
    3429          10 :                 (strcasecmp_m(r->in.site_name,
    3430             :                               server_site_name) != 0))) {
    3431             : 
    3432          56 :                 struct dcerpc_binding_handle *irpc_handle = NULL;
    3433          56 :                 struct tevent_req *subreq = NULL;
    3434             : 
    3435             :                 /*
    3436             :                  * Retrieve the client site to override the winbind response.
    3437             :                  *
    3438             :                  * DO NOT use Windows fallback for client site.
    3439             :                  * In the case of multiple domains, this is plainly wrong.
    3440             :                  *
    3441             :                  * Note: It's possible that the client may belong to multiple
    3442             :                  * subnets across domains. It's not clear what this would mean,
    3443             :                  * but here we only return what this domain knows.
    3444             :                  */
    3445          56 :                 state->client_site = samdb_client_site_name(sam_ctx,
    3446             :                                                             state,
    3447             :                                                             remote_addr,
    3448             :                                                             NULL,
    3449             :                                                             false);
    3450             : 
    3451          56 :                 irpc_handle = irpc_binding_handle_by_name(state,
    3452             :                                                           imsg_ctx,
    3453             :                                                           "winbind_server",
    3454             :                                                           &ndr_table_winbind);
    3455          56 :                 if (irpc_handle == NULL) {
    3456           0 :                         DEBUG(0,("Failed to get binding_handle for "
    3457             :                                  "winbind_server task\n"));
    3458           0 :                         dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
    3459           0 :                         return WERR_SERVICE_NOT_FOUND;
    3460             :                 }
    3461             : 
    3462          56 :                 dcerpc_binding_handle_set_timeout(irpc_handle, 60);
    3463             : 
    3464          56 :                 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
    3465             : 
    3466          56 :                 subreq = dcerpc_wbint_DsGetDcName_send(state,
    3467             :                                                        dce_call->event_ctx,
    3468             :                                                        irpc_handle,
    3469             :                                                        r->in.domain_name,
    3470             :                                                        r->in.domain_guid,
    3471             :                                                        r->in.site_name,
    3472             :                                                        r->in.flags,
    3473             :                                                        r->out.info);
    3474          56 :                 if (subreq == NULL) {
    3475           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    3476             :                 }
    3477             : 
    3478          56 :                 tevent_req_set_callback(subreq,
    3479             :                                         dcesrv_netr_DsRGetDCName_base_done,
    3480             :                                         state);
    3481             : 
    3482          56 :                 return WERR_OK;
    3483             :         }
    3484             : 
    3485         574 :         guid_str = r->in.domain_guid != NULL ?
    3486         287 :                  GUID_string(state, r->in.domain_guid) : NULL;
    3487             : 
    3488         287 :         status = fill_netlogon_samlogon_response(sam_ctx, mem_ctx,
    3489             :                                                  r->in.domain_name,
    3490             :                                                  r->in.domain_name,
    3491             :                                                  NULL, guid_str,
    3492             :                                                  r->in.client_account,
    3493             :                                                  r->in.mask, remote_addr,
    3494             :                                                  NETLOGON_NT_VERSION_5EX_WITH_IP,
    3495             :                                                  lp_ctx, &response, true);
    3496         287 :         if (!NT_STATUS_IS_OK(status)) {
    3497           0 :                 return ntstatus_to_werror(status);
    3498             :         }
    3499             : 
    3500             :         /*
    3501             :          * According to MS-NRPC 2.2.1.2.1 we should set the "DS_DNS_FOREST_ROOT"
    3502             :          * (O) flag when the returned forest name is in DNS format. This is here
    3503             :          * always the case (see below).
    3504             :          */
    3505         287 :         response.data.nt5_ex.server_type |= DS_DNS_FOREST_ROOT;
    3506             : 
    3507         287 :         if (r->in.flags & DS_RETURN_DNS_NAME) {
    3508         205 :                 dc_name = response.data.nt5_ex.pdc_dns_name;
    3509         205 :                 domain_name = response.data.nt5_ex.dns_domain;
    3510             :                 /*
    3511             :                  * According to MS-NRPC 2.2.1.2.1 we should set the
    3512             :                  * "DS_DNS_CONTROLLER" (M) and "DS_DNS_DOMAIN" (N) flags when
    3513             :                  * the returned information is in DNS form.
    3514             :                  */
    3515         205 :                 response.data.nt5_ex.server_type |=
    3516             :                         DS_DNS_CONTROLLER | DS_DNS_DOMAIN;
    3517          82 :         } else if (r->in.flags & DS_RETURN_FLAT_NAME) {
    3518          20 :                 dc_name = response.data.nt5_ex.pdc_name;
    3519          20 :                 domain_name = response.data.nt5_ex.domain_name;
    3520             :         } else {
    3521             : 
    3522             :                 /*
    3523             :                  * TODO: autodetect what we need to return
    3524             :                  * based on the given arguments
    3525             :                  */
    3526          62 :                 dc_name = response.data.nt5_ex.pdc_name;
    3527          62 :                 domain_name = response.data.nt5_ex.domain_name;
    3528             :         }
    3529             : 
    3530         287 :         if (!dc_name || !dc_name[0]) {
    3531           0 :                 return WERR_NO_SUCH_DOMAIN;
    3532             :         }
    3533             : 
    3534         287 :         if (!domain_name || !domain_name[0]) {
    3535           0 :                 return WERR_NO_SUCH_DOMAIN;
    3536             :         }
    3537             : 
    3538         287 :         info = talloc(mem_ctx, struct netr_DsRGetDCNameInfo);
    3539         287 :         W_ERROR_HAVE_NO_MEMORY(info);
    3540         574 :         info->dc_unc = talloc_asprintf(mem_ctx, "%s%s",
    3541         287 :                         dc_name[0] != '\\'? "\\\\":"",
    3542             :                         talloc_strdup(mem_ctx, dc_name));
    3543         287 :         W_ERROR_HAVE_NO_MEMORY(info->dc_unc);
    3544             : 
    3545         287 :         pdc_ip = local_addr;
    3546         287 :         if (pdc_ip == NULL) {
    3547          98 :                 pdc_ip = "127.0.0.1";
    3548             :         }
    3549         287 :         info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s", pdc_ip);
    3550         287 :         W_ERROR_HAVE_NO_MEMORY(info->dc_address);
    3551         287 :         info->dc_address_type  = DS_ADDRESS_TYPE_INET;
    3552         287 :         info->domain_guid      = response.data.nt5_ex.domain_uuid;
    3553         287 :         info->domain_name      = domain_name;
    3554         287 :         info->forest_name      = response.data.nt5_ex.forest;
    3555         287 :         info->dc_flags         = response.data.nt5_ex.server_type;
    3556         287 :         if (r->in.flags & DS_RETURN_DNS_NAME) {
    3557             :                 /* As MS-NRPC.pdf in 2.2.1.2.1 the DS_DNS_CONTROLLER flag should be
    3558             :                  * returned if we are returning info->dc_unc containing a FQDN.
    3559             :                  * This attribute is called DomainControllerName in the specs,
    3560             :                  * it seems that we decide to return FQDN or netbios depending on
    3561             :                  * DS_RETURN_DNS_NAME.
    3562             :                  */
    3563         205 :                 info->dc_flags |= DS_DNS_CONTROLLER;
    3564             :         }
    3565         287 :         info->dc_site_name     = response.data.nt5_ex.server_site;
    3566         287 :         info->client_site_name = response.data.nt5_ex.client_site;
    3567             : 
    3568         287 :         *r->out.info = info;
    3569             : 
    3570         287 :         return WERR_OK;
    3571             : }
    3572             : 
    3573          56 : static void dcesrv_netr_DsRGetDCName_base_done(struct tevent_req *subreq)
    3574             : {
    3575           0 :         struct dcesrv_netr_DsRGetDCName_base_state *state =
    3576          56 :                 tevent_req_callback_data(subreq,
    3577             :                 struct dcesrv_netr_DsRGetDCName_base_state);
    3578          56 :         struct dcesrv_call_state *dce_call = state->dce_call;
    3579           0 :         NTSTATUS result, status;
    3580             : 
    3581          56 :         status = dcerpc_wbint_DsGetDcName_recv(subreq,
    3582             :                                                state->mem_ctx,
    3583             :                                                &result);
    3584          56 :         TALLOC_FREE(subreq);
    3585             : 
    3586          56 :         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
    3587           0 :                 state->r.out.result = WERR_TIMEOUT;
    3588           0 :                 goto finished;
    3589             :         }
    3590             : 
    3591          56 :         if (!NT_STATUS_IS_OK(status)) {
    3592           0 :                 DBG_ERR(__location__ ": IRPC callback failed %s\n",
    3593             :                         nt_errstr(status));
    3594           0 :                 state->r.out.result = WERR_GEN_FAILURE;
    3595           0 :                 goto finished;
    3596             :         }
    3597             : 
    3598          56 :         if (!NT_STATUS_IS_OK(result)) {
    3599          12 :                 DBG_NOTICE("DC location via winbind failed - %s\n",
    3600             :                            nt_errstr(result));
    3601          12 :                 state->r.out.result = WERR_NO_SUCH_DOMAIN;
    3602          12 :                 goto finished;
    3603             :         }
    3604             : 
    3605          44 :         if (state->r.out.info == NULL || state->r.out.info[0] == NULL) {
    3606           0 :                 DBG_ERR("DC location via winbind returned no results\n");
    3607           0 :                 state->r.out.result = WERR_GEN_FAILURE;
    3608           0 :                 goto finished;
    3609             :         }
    3610             : 
    3611          44 :         if (state->r.out.info[0]->dc_unc == NULL) {
    3612           0 :                 DBG_ERR("DC location via winbind returned no DC unc\n");
    3613           0 :                 state->r.out.result = WERR_GEN_FAILURE;
    3614           0 :                 goto finished;
    3615             :         }
    3616             : 
    3617             :         /*
    3618             :          * Either the supplied site name is NULL (possibly via
    3619             :          * TRY_NEXT_CLOSEST_SITE) or the resulting site name matches
    3620             :          * the input match name.
    3621             :          *
    3622             :          * TODO: Currently this means that requests with NETBIOS domain
    3623             :          * names can fail because they do not return the site name.
    3624             :          */
    3625          60 :         if (state->r.in.site_name == NULL ||
    3626          16 :             strcasecmp_m("", state->r.in.site_name) == 0 ||
    3627          24 :             (state->r.out.info[0]->dc_site_name != NULL &&
    3628          12 :              strcasecmp_m(state->r.out.info[0]->dc_site_name,
    3629          36 :                           state->r.in.site_name) == 0)) {
    3630             : 
    3631          72 :                 state->r.out.info[0]->client_site_name =
    3632          36 :                         talloc_move(state->mem_ctx, &state->client_site);
    3633             : 
    3634             :                 /*
    3635             :                  * Make sure to return our DC UNC with // prefix.
    3636             :                  * Winbind currently doesn't send the leading slashes
    3637             :                  * for some reason.
    3638             :                  */
    3639          36 :                 if (strlen(state->r.out.info[0]->dc_unc) > 2 &&
    3640          36 :                     strncmp("\\\\", state->r.out.info[0]->dc_unc, 2) != 0) {
    3641           0 :                         const char *dc_unc = NULL;
    3642             : 
    3643           0 :                         dc_unc = talloc_asprintf(state->mem_ctx,
    3644             :                                                  "\\\\%s",
    3645           0 :                                                  state->r.out.info[0]->dc_unc);
    3646           0 :                         state->r.out.info[0]->dc_unc = dc_unc;
    3647             :                 }
    3648             : 
    3649          36 :                 state->r.out.result = WERR_OK;
    3650             :         } else {
    3651           8 :                 state->r.out.info = NULL;
    3652           8 :                 state->r.out.result = WERR_NO_SUCH_DOMAIN;
    3653             :         }
    3654             : 
    3655          56 : finished:
    3656          56 :         if (state->_r.dcex2 != NULL) {
    3657          10 :                 struct netr_DsRGetDCNameEx2 *r = state->_r.dcex2;
    3658          10 :                 r->out.result = state->r.out.result;
    3659          46 :         } else if (state->_r.dcex != NULL) {
    3660          34 :                 struct netr_DsRGetDCNameEx *r = state->_r.dcex;
    3661          34 :                 r->out.result = state->r.out.result;
    3662          12 :         } else if (state->_r.dc != NULL) {
    3663          12 :                 struct netr_DsRGetDCName *r = state->_r.dc;
    3664          12 :                 r->out.result = state->r.out.result;
    3665             :         }
    3666             : 
    3667          56 :         TALLOC_FREE(state);
    3668          56 :         dcesrv_async_reply(dce_call);
    3669          56 : }
    3670             : 
    3671             : /*
    3672             :   netr_DsRGetDCNameEx2
    3673             : */
    3674         205 : static WERROR dcesrv_netr_DsRGetDCNameEx2(struct dcesrv_call_state *dce_call,
    3675             :                                           TALLOC_CTX *mem_ctx,
    3676             :                                           struct netr_DsRGetDCNameEx2 *r)
    3677             : {
    3678          14 :         struct dcesrv_netr_DsRGetDCName_base_state *state;
    3679             : 
    3680         205 :         state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
    3681         205 :         if (state == NULL) {
    3682           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    3683             :         }
    3684             : 
    3685         205 :         state->dce_call = dce_call;
    3686         205 :         state->mem_ctx = mem_ctx;
    3687             : 
    3688         205 :         state->r = *r;
    3689         205 :         state->_r.dcex2 = r;
    3690             : 
    3691         205 :         return dcesrv_netr_DsRGetDCName_base_call(state);
    3692             : }
    3693             : 
    3694             : /*
    3695             :   netr_DsRGetDCNameEx
    3696             : */
    3697          84 : static WERROR dcesrv_netr_DsRGetDCNameEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    3698             :                                   struct netr_DsRGetDCNameEx *r)
    3699             : {
    3700           6 :         struct dcesrv_netr_DsRGetDCName_base_state *state;
    3701             : 
    3702          84 :         state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
    3703          84 :         if (state == NULL) {
    3704           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    3705             :         }
    3706             : 
    3707          84 :         state->dce_call = dce_call;
    3708          84 :         state->mem_ctx = mem_ctx;
    3709             : 
    3710          84 :         state->r.in.server_unc = r->in.server_unc;
    3711          84 :         state->r.in.client_account = NULL;
    3712          84 :         state->r.in.mask = 0;
    3713          84 :         state->r.in.domain_guid = r->in.domain_guid;
    3714          84 :         state->r.in.domain_name = r->in.domain_name;
    3715          84 :         state->r.in.site_name = r->in.site_name;
    3716          84 :         state->r.in.flags = r->in.flags;
    3717          84 :         state->r.out.info = r->out.info;
    3718             : 
    3719          84 :         state->_r.dcex = r;
    3720             : 
    3721          84 :         return dcesrv_netr_DsRGetDCName_base_call(state);
    3722             : }
    3723             : 
    3724             : /*
    3725             :  * netr_DsRGetDCName
    3726             :  *
    3727             :  * This function is a predecessor to DsrGetDcNameEx2 according to [MS-NRPC].
    3728             :  * Although it has a site-guid parameter, the documentation 3.5.4.3.3 DsrGetDcName
    3729             :  * insists that it be ignored.
    3730             :  */
    3731          54 : static WERROR dcesrv_netr_DsRGetDCName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    3732             :                                        struct netr_DsRGetDCName *r)
    3733             : {
    3734           6 :         struct dcesrv_netr_DsRGetDCName_base_state *state;
    3735             : 
    3736          54 :         state = talloc_zero(mem_ctx, struct dcesrv_netr_DsRGetDCName_base_state);
    3737          54 :         if (state == NULL) {
    3738           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    3739             :         }
    3740             : 
    3741          54 :         state->dce_call = dce_call;
    3742          54 :         state->mem_ctx = mem_ctx;
    3743             : 
    3744          54 :         state->r.in.server_unc = r->in.server_unc;
    3745          54 :         state->r.in.client_account = NULL;
    3746          54 :         state->r.in.mask = 0;
    3747          54 :         state->r.in.domain_name = r->in.domain_name;
    3748          54 :         state->r.in.domain_guid = r->in.domain_guid;
    3749             : 
    3750          54 :         state->r.in.site_name = NULL; /* this is correct, we should ignore site GUID */
    3751          54 :         state->r.in.flags = r->in.flags;
    3752          54 :         state->r.out.info = r->out.info;
    3753             : 
    3754          54 :         state->_r.dc = r;
    3755             : 
    3756          54 :         return dcesrv_netr_DsRGetDCName_base_call(state);
    3757             : }
    3758             : /*
    3759             :   netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
    3760             : */
    3761           0 : static WERROR dcesrv_netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    3762             :                        struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN *r)
    3763             : {
    3764           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    3765             : }
    3766             : 
    3767             : 
    3768             : /*
    3769             :   netr_NetrEnumerateTrustedDomainsEx
    3770             : */
    3771          18 : static WERROR dcesrv_netr_NetrEnumerateTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    3772             :                        struct netr_NetrEnumerateTrustedDomainsEx *r)
    3773             : {
    3774          18 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    3775             : }
    3776             : 
    3777             : 
    3778             : /*
    3779             :   netr_DsRAddressToSitenamesExW
    3780             : */
    3781         108 : static WERROR dcesrv_netr_DsRAddressToSitenamesExW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    3782             :                                                    struct netr_DsRAddressToSitenamesExW *r)
    3783             : {
    3784          18 :         struct ldb_context *sam_ctx;
    3785          18 :         struct netr_DsRAddressToSitenamesExWCtr *ctr;
    3786          18 :         sa_family_t sin_family;
    3787          18 :         struct sockaddr_in *addr;
    3788             : #ifdef HAVE_IPV6
    3789          18 :         struct sockaddr_in6 *addr6;
    3790          18 :         char addr_str[INET6_ADDRSTRLEN];
    3791             : #else
    3792             :         char addr_str[INET_ADDRSTRLEN];
    3793             : #endif
    3794          18 :         char *subnet_name;
    3795          18 :         const char *res;
    3796          18 :         uint32_t i;
    3797             : 
    3798         108 :         sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
    3799         108 :         if (sam_ctx == NULL) {
    3800           0 :                 return WERR_DS_UNAVAILABLE;
    3801             :         }
    3802             : 
    3803         108 :         ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr);
    3804         108 :         W_ERROR_HAVE_NO_MEMORY(ctr);
    3805             : 
    3806         108 :         *r->out.ctr = ctr;
    3807             : 
    3808         108 :         ctr->count = r->in.count;
    3809         108 :         ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
    3810         108 :         W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
    3811         108 :         ctr->subnetname = talloc_array(ctr, struct lsa_String, ctr->count);
    3812         108 :         W_ERROR_HAVE_NO_MEMORY(ctr->subnetname);
    3813             : 
    3814         756 :         for (i=0; i<ctr->count; i++) {
    3815         648 :                 ctr->sitename[i].string = NULL;
    3816         648 :                 ctr->subnetname[i].string = NULL;
    3817             : 
    3818         648 :                 if (r->in.addresses[i].size < sizeof(sa_family_t)) {
    3819         144 :                         continue;
    3820             :                 }
    3821             :                 /* The first two byte of the buffer are reserved for the
    3822             :                  * "sin_family" but for now only the first one is used. */
    3823         504 :                 sin_family = r->in.addresses[i].buffer[0];
    3824             : 
    3825         504 :                 switch (sin_family) {
    3826         144 :                 case AF_INET:
    3827         144 :                         if (r->in.addresses[i].size < sizeof(struct sockaddr_in)) {
    3828          36 :                                 continue;
    3829             :                         }
    3830         108 :                         addr = (struct sockaddr_in *) r->in.addresses[i].buffer;
    3831         108 :                         res = inet_ntop(AF_INET, &addr->sin_addr,
    3832             :                                         addr_str, sizeof(addr_str));
    3833         108 :                         break;
    3834             : #ifdef HAVE_IPV6
    3835         144 :                 case AF_INET6:
    3836         144 :                         if (r->in.addresses[i].size < sizeof(struct sockaddr_in6)) {
    3837          36 :                                 continue;
    3838             :                         }
    3839         108 :                         addr6 = (struct sockaddr_in6 *) r->in.addresses[i].buffer;
    3840         108 :                         res = inet_ntop(AF_INET6, &addr6->sin6_addr,
    3841             :                                         addr_str, sizeof(addr_str));
    3842         108 :                         break;
    3843             : #endif
    3844         216 :                 default:
    3845         216 :                         continue;
    3846             :                 }
    3847             : 
    3848         216 :                 if (res == NULL) {
    3849           0 :                         continue;
    3850             :                 }
    3851             : 
    3852         216 :                 ctr->sitename[i].string   = samdb_client_site_name(sam_ctx,
    3853             :                                                                    mem_ctx,
    3854             :                                                                    addr_str,
    3855             :                                                                    &subnet_name,
    3856             :                                                                    true);
    3857         216 :                 W_ERROR_HAVE_NO_MEMORY(ctr->sitename[i].string);
    3858         216 :                 ctr->subnetname[i].string = subnet_name;
    3859             :         }
    3860             : 
    3861         108 :         return WERR_OK;
    3862             : }
    3863             : 
    3864             : 
    3865             : /*
    3866             :   netr_DsRAddressToSitenamesW
    3867             : */
    3868          54 : static WERROR dcesrv_netr_DsRAddressToSitenamesW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    3869             :                        struct netr_DsRAddressToSitenamesW *r)
    3870             : {
    3871           9 :         struct netr_DsRAddressToSitenamesExW r2;
    3872           9 :         struct netr_DsRAddressToSitenamesWCtr *ctr;
    3873           9 :         uint32_t i;
    3874           9 :         WERROR werr;
    3875             : 
    3876          54 :         ZERO_STRUCT(r2);
    3877             : 
    3878          54 :         r2.in.server_name = r->in.server_name;
    3879          54 :         r2.in.count = r->in.count;
    3880          54 :         r2.in.addresses = r->in.addresses;
    3881             : 
    3882          54 :         r2.out.ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesExWCtr *);
    3883          54 :         W_ERROR_HAVE_NO_MEMORY(r2.out.ctr);
    3884             : 
    3885          54 :         ctr = talloc(mem_ctx, struct netr_DsRAddressToSitenamesWCtr);
    3886          54 :         W_ERROR_HAVE_NO_MEMORY(ctr);
    3887             : 
    3888          54 :         *r->out.ctr = ctr;
    3889             : 
    3890          54 :         ctr->count = r->in.count;
    3891          54 :         ctr->sitename = talloc_array(ctr, struct lsa_String, ctr->count);
    3892          54 :         W_ERROR_HAVE_NO_MEMORY(ctr->sitename);
    3893             : 
    3894          54 :         werr = dcesrv_netr_DsRAddressToSitenamesExW(dce_call, mem_ctx, &r2);
    3895             : 
    3896         387 :         for (i=0; i<ctr->count; i++) {
    3897         324 :                 ctr->sitename[i].string   = (*r2.out.ctr)->sitename[i].string;
    3898             :         }
    3899             : 
    3900          54 :         return werr;
    3901             : }
    3902             : 
    3903             : 
    3904             : /*
    3905             :   netr_DsrGetDcSiteCoverageW
    3906             : */
    3907          23 : static WERROR dcesrv_netr_DsrGetDcSiteCoverageW(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    3908             :                        struct netr_DsrGetDcSiteCoverageW *r)
    3909             : {
    3910           3 :         struct ldb_context *sam_ctx;
    3911           3 :         struct DcSitesCtr *ctr;
    3912             : 
    3913          23 :         sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
    3914          23 :         if (sam_ctx == NULL) {
    3915           0 :                 return WERR_DS_UNAVAILABLE;
    3916             :         }
    3917             : 
    3918          23 :         ctr = talloc(mem_ctx, struct DcSitesCtr);
    3919          23 :         W_ERROR_HAVE_NO_MEMORY(ctr);
    3920             : 
    3921          23 :         *r->out.ctr = ctr;
    3922             : 
    3923             :         /* For now only return our default site */
    3924          23 :         ctr->num_sites = 1;
    3925          23 :         ctr->sites = talloc_array(ctr, struct lsa_String, ctr->num_sites);
    3926          23 :         W_ERROR_HAVE_NO_MEMORY(ctr->sites);
    3927          23 :         ctr->sites[0].string = samdb_server_site_name(sam_ctx, mem_ctx);
    3928          23 :         W_ERROR_HAVE_NO_MEMORY(ctr->sites[0].string);
    3929             : 
    3930          23 :         return WERR_OK;
    3931             : }
    3932             : 
    3933             : 
    3934          43 : static WERROR fill_trusted_domains_array(TALLOC_CTX *mem_ctx,
    3935             :                                          struct ldb_context *sam_ctx,
    3936             :                                          struct netr_DomainTrustList *trusts,
    3937             :                                          uint32_t trust_flags)
    3938             : {
    3939           3 :         struct ldb_dn *system_dn;
    3940          43 :         struct ldb_message **dom_res = NULL;
    3941          43 :         const char *trust_attrs[] = { "flatname", "trustPartner",
    3942             :                                       "securityIdentifier", "trustDirection",
    3943             :                                       "trustType", "trustAttributes", NULL };
    3944           3 :         uint32_t n;
    3945           3 :         int i;
    3946           3 :         int ret;
    3947             : 
    3948          43 :         if (!(trust_flags & (NETR_TRUST_FLAG_INBOUND |
    3949             :                              NETR_TRUST_FLAG_OUTBOUND))) {
    3950           0 :                 return WERR_INVALID_FLAGS;
    3951             :         }
    3952             : 
    3953          43 :         system_dn = samdb_system_container_dn(sam_ctx, mem_ctx);
    3954          43 :         if (system_dn == NULL) {
    3955           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    3956             :         }
    3957             : 
    3958          43 :         ret = gendb_search(sam_ctx, mem_ctx, system_dn,
    3959             :                            &dom_res, trust_attrs,
    3960             :                            "(objectclass=trustedDomain)");
    3961             : 
    3962          82 :         for (i = 0; i < ret; i++) {
    3963           0 :                 unsigned int trust_dir;
    3964          36 :                 uint32_t flags = 0;
    3965             : 
    3966          36 :                 trust_dir = ldb_msg_find_attr_as_uint(dom_res[i],
    3967             :                                                       "trustDirection", 0);
    3968             : 
    3969          36 :                 if (trust_dir & LSA_TRUST_DIRECTION_INBOUND) {
    3970          34 :                         flags |= NETR_TRUST_FLAG_INBOUND;
    3971             :                 }
    3972          36 :                 if (trust_dir & LSA_TRUST_DIRECTION_OUTBOUND) {
    3973          28 :                         flags |= NETR_TRUST_FLAG_OUTBOUND;
    3974             :                 }
    3975             : 
    3976          36 :                 if (!(flags & trust_flags)) {
    3977             :                         /* this trust direction was not requested */
    3978           0 :                         continue;
    3979             :                 }
    3980             : 
    3981          36 :                 n = trusts->count;
    3982          36 :                 trusts->array = talloc_realloc(trusts, trusts->array,
    3983             :                                                struct netr_DomainTrust,
    3984             :                                                n + 1);
    3985          36 :                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
    3986             : 
    3987          36 :                 trusts->array[n].netbios_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "flatname", NULL));
    3988          36 :                 if (!trusts->array[n].netbios_name) {
    3989           0 :                         DEBUG(0, ("DB Error, TrustedDomain entry (%s) "
    3990             :                                   "without flatname\n", 
    3991             :                                   ldb_dn_get_linearized(dom_res[i]->dn)));
    3992             :                 }
    3993             : 
    3994          36 :                 trusts->array[n].dns_name = talloc_steal(trusts->array, ldb_msg_find_attr_as_string(dom_res[i], "trustPartner", NULL));
    3995             : 
    3996          36 :                 trusts->array[n].trust_flags = flags;
    3997          36 :                 if ((trust_flags & NETR_TRUST_FLAG_IN_FOREST) &&
    3998          36 :                     !(flags & NETR_TRUST_FLAG_TREEROOT)) {
    3999             :                         /* TODO: find if we have parent in the list */
    4000          36 :                         trusts->array[n].parent_index = 0;
    4001             :                 }
    4002             : 
    4003          72 :                 trusts->array[n].trust_type =
    4004          36 :                                 ldb_msg_find_attr_as_uint(dom_res[i],
    4005             :                                                   "trustType", 0);
    4006          72 :                 trusts->array[n].trust_attributes =
    4007          36 :                                 ldb_msg_find_attr_as_uint(dom_res[i],
    4008             :                                                   "trustAttributes", 0);
    4009             : 
    4010          36 :                 if ((trusts->array[n].trust_type == LSA_TRUST_TYPE_MIT) ||
    4011          36 :                     (trusts->array[n].trust_type == LSA_TRUST_TYPE_DCE)) {
    4012           0 :                         struct dom_sid zero_sid;
    4013           0 :                         ZERO_STRUCT(zero_sid);
    4014           0 :                         trusts->array[n].sid =
    4015           0 :                                 dom_sid_dup(trusts, &zero_sid);
    4016             :                 } else {
    4017          36 :                         trusts->array[n].sid =
    4018          36 :                                 samdb_result_dom_sid(trusts, dom_res[i],
    4019             :                                                      "securityIdentifier");
    4020             :                 }
    4021          36 :                 trusts->array[n].guid = GUID_zero();
    4022             : 
    4023          36 :                 trusts->count = n + 1;
    4024             :         }
    4025             : 
    4026          43 :         talloc_free(dom_res);
    4027          43 :         return WERR_OK;
    4028             : }
    4029             : 
    4030             : /*
    4031             :   netr_DsrEnumerateDomainTrusts
    4032             : */
    4033          48 : static WERROR dcesrv_netr_DsrEnumerateDomainTrusts(struct dcesrv_call_state *dce_call,
    4034             :                                                    TALLOC_CTX *mem_ctx,
    4035             :                                                    struct netr_DsrEnumerateDomainTrusts *r)
    4036             : {
    4037           3 :         struct netr_DomainTrustList *trusts;
    4038           3 :         struct ldb_context *sam_ctx;
    4039           3 :         int ret;
    4040           3 :         struct ldb_message **dom_res;
    4041          48 :         const char * const dom_attrs[] = { "objectSid", "objectGUID", NULL };
    4042          48 :         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
    4043          48 :         const char *dnsdomain = lpcfg_dnsdomain(lp_ctx);
    4044           3 :         const char *p;
    4045           3 :         WERROR werr;
    4046             : 
    4047          48 :         if (r->in.trust_flags & 0xFFFFFE00) {
    4048           0 :                 return WERR_INVALID_FLAGS;
    4049             :         }
    4050             : 
    4051             :         /* TODO: turn to hard check once we are sure this is 100% correct */
    4052          48 :         if (!r->in.server_name) {
    4053           0 :                 DEBUG(3, ("Invalid domain! Expected name in domain [%s]. "
    4054             :                           "But received NULL!\n", dnsdomain));
    4055             :         } else {
    4056          48 :                 p = strchr(r->in.server_name, '.');
    4057          48 :                 if (!p) {
    4058          42 :                         DEBUG(3, ("Invalid domain! Expected name in domain "
    4059             :                                   "[%s]. But received [%s]!\n",
    4060             :                                   dnsdomain, r->in.server_name));
    4061          42 :                         p = r->in.server_name;
    4062             :                 } else {
    4063           6 :                         p++;
    4064             :                 }
    4065          48 :                 if (strcasecmp(p, dnsdomain)) {
    4066          42 :                         DEBUG(3, ("Invalid domain! Expected name in domain "
    4067             :                                   "[%s]. But received [%s]!\n",
    4068             :                                   dnsdomain, r->in.server_name));
    4069             :                 }
    4070             :         }
    4071             : 
    4072          48 :         trusts = talloc_zero(mem_ctx, struct netr_DomainTrustList);
    4073          48 :         W_ERROR_HAVE_NO_MEMORY(trusts);
    4074             : 
    4075          48 :         trusts->count = 0;
    4076          48 :         r->out.trusts = trusts;
    4077             : 
    4078          48 :         sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
    4079          48 :         if (sam_ctx == NULL) {
    4080           0 :                 return WERR_GEN_FAILURE;
    4081             :         }
    4082             : 
    4083          48 :         if ((r->in.trust_flags & NETR_TRUST_FLAG_INBOUND) ||
    4084           5 :             (r->in.trust_flags & NETR_TRUST_FLAG_OUTBOUND)) {
    4085             : 
    4086          43 :                 werr = fill_trusted_domains_array(mem_ctx, sam_ctx,
    4087             :                                                   trusts, r->in.trust_flags);
    4088          43 :                 W_ERROR_NOT_OK_RETURN(werr);
    4089             :         }
    4090             : 
    4091             :         /* NOTE: we currently are always the root of the forest */
    4092          48 :         if (r->in.trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
    4093          48 :                 uint32_t n = trusts->count;
    4094             : 
    4095          48 :                 ret = gendb_search_dn(sam_ctx, mem_ctx, NULL,
    4096             :                                       &dom_res, dom_attrs);
    4097          48 :                 if (ret != 1) {
    4098           0 :                         return WERR_GEN_FAILURE;
    4099             :                 }
    4100             : 
    4101          48 :                 trusts->count = n + 1;
    4102          48 :                 trusts->array = talloc_realloc(trusts, trusts->array,
    4103             :                                                struct netr_DomainTrust,
    4104             :                                                trusts->count);
    4105          48 :                 W_ERROR_HAVE_NO_MEMORY(trusts->array);
    4106             : 
    4107          48 :                 trusts->array[n].netbios_name = lpcfg_workgroup(lp_ctx);
    4108          48 :                 trusts->array[n].dns_name = lpcfg_dnsdomain(lp_ctx);
    4109          48 :                 trusts->array[n].trust_flags =
    4110             :                         NETR_TRUST_FLAG_NATIVE |
    4111             :                         NETR_TRUST_FLAG_TREEROOT |
    4112             :                         NETR_TRUST_FLAG_IN_FOREST |
    4113             :                         NETR_TRUST_FLAG_PRIMARY;
    4114             :                 /* we are always the root domain for now */
    4115          48 :                 trusts->array[n].parent_index = 0;
    4116          48 :                 trusts->array[n].trust_type = LSA_TRUST_TYPE_UPLEVEL;
    4117          48 :                 trusts->array[n].trust_attributes = 0;
    4118          48 :                 trusts->array[n].sid = samdb_result_dom_sid(mem_ctx,
    4119             :                                                             dom_res[0],
    4120             :                                                             "objectSid");
    4121          48 :                 trusts->array[n].guid = samdb_result_guid(dom_res[0],
    4122             :                                                           "objectGUID");
    4123          48 :                 talloc_free(dom_res);
    4124             :         }
    4125             : 
    4126          48 :         return WERR_OK;
    4127             : }
    4128             : 
    4129             : 
    4130             : /*
    4131             :   netr_DsrDeregisterDNSHostRecords
    4132             : */
    4133           0 : static WERROR dcesrv_netr_DsrDeregisterDNSHostRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4134             :                        struct netr_DsrDeregisterDNSHostRecords *r)
    4135             : {
    4136           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    4137             : }
    4138             : 
    4139             : 
    4140             : static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4141             :                        struct netr_ServerGetTrustInfo *r);
    4142             : 
    4143             : /*
    4144             :   netr_ServerTrustPasswordsGet
    4145             : */
    4146          18 : static NTSTATUS dcesrv_netr_ServerTrustPasswordsGet(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4147             :                        struct netr_ServerTrustPasswordsGet *r)
    4148             : {
    4149          18 :         struct netr_ServerGetTrustInfo r2 = {};
    4150          18 :         struct netr_TrustInfo *_ti = NULL;
    4151           3 :         NTSTATUS status;
    4152             : 
    4153          18 :         r2.in.server_name = r->in.server_name;
    4154          18 :         r2.in.account_name = r->in.account_name;
    4155          18 :         r2.in.secure_channel_type = r->in.secure_channel_type;
    4156          18 :         r2.in.computer_name = r->in.computer_name;
    4157          18 :         r2.in.credential = r->in.credential;
    4158             : 
    4159          18 :         r2.out.return_authenticator = r->out.return_authenticator;
    4160          18 :         r2.out.new_owf_password = r->out.new_owf_password;
    4161          18 :         r2.out.old_owf_password = r->out.old_owf_password;
    4162          18 :         r2.out.trust_info = &_ti;
    4163             : 
    4164          18 :         status = dcesrv_netr_ServerGetTrustInfo(dce_call, mem_ctx, &r2);
    4165             : 
    4166          18 :         r->out.return_authenticator = r2.out.return_authenticator;
    4167          18 :         r->out.new_owf_password = r2.out.new_owf_password;
    4168          18 :         r->out.old_owf_password = r2.out.old_owf_password;
    4169             : 
    4170          18 :         return status;
    4171             : }
    4172             : 
    4173             : /*
    4174             :   netr_DsRGetForestTrustInformation
    4175             : */
    4176             : struct dcesrv_netr_DsRGetForestTrustInformation_state {
    4177             :         struct dcesrv_call_state *dce_call;
    4178             :         TALLOC_CTX *mem_ctx;
    4179             :         struct netr_DsRGetForestTrustInformation *r;
    4180             : };
    4181             : 
    4182             : static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq);
    4183             : 
    4184         176 : static WERROR dcesrv_netr_DsRGetForestTrustInformation(struct dcesrv_call_state *dce_call,
    4185             :                                                        TALLOC_CTX *mem_ctx,
    4186             :                                                        struct netr_DsRGetForestTrustInformation *r)
    4187             : {
    4188           7 :         struct auth_session_info *session_info =
    4189         176 :                 dcesrv_call_session_info(dce_call);
    4190           7 :         struct imessaging_context *imsg_ctx =
    4191         176 :                 dcesrv_imessaging_context(dce_call->conn);
    4192           7 :         enum security_user_level security_level;
    4193         176 :         struct ldb_context *sam_ctx = NULL;
    4194         176 :         struct dcesrv_netr_DsRGetForestTrustInformation_state *state = NULL;
    4195         176 :         struct dcerpc_binding_handle *irpc_handle = NULL;
    4196         176 :         struct tevent_req *subreq = NULL;
    4197         176 :         struct ldb_dn *domain_dn = NULL;
    4198         176 :         struct ldb_dn *forest_dn = NULL;
    4199           7 :         int cmp;
    4200           7 :         int forest_level;
    4201             : 
    4202         176 :         security_level = security_session_user_level(session_info, NULL);
    4203         176 :         if (security_level < SECURITY_USER) {
    4204           0 :                 return WERR_ACCESS_DENIED;
    4205             :         }
    4206             : 
    4207         176 :         if (r->in.flags & 0xFFFFFFFE) {
    4208           0 :                 return WERR_INVALID_FLAGS;
    4209             :         }
    4210             : 
    4211         176 :         sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
    4212         176 :         if (sam_ctx == NULL) {
    4213           0 :                 return WERR_GEN_FAILURE;
    4214             :         }
    4215             : 
    4216         176 :         domain_dn = ldb_get_default_basedn(sam_ctx);
    4217         176 :         if (domain_dn == NULL) {
    4218           0 :                 return WERR_GEN_FAILURE;
    4219             :         }
    4220             : 
    4221         176 :         forest_dn = ldb_get_root_basedn(sam_ctx);
    4222         176 :         if (forest_dn == NULL) {
    4223           0 :                 return WERR_GEN_FAILURE;
    4224             :         }
    4225             : 
    4226         176 :         cmp = ldb_dn_compare(domain_dn, forest_dn);
    4227         176 :         if (cmp != 0) {
    4228           0 :                 return WERR_NERR_ACFNOTLOADED;
    4229             :         }
    4230             : 
    4231         176 :         forest_level = dsdb_forest_functional_level(sam_ctx);
    4232         176 :         if (forest_level < DS_DOMAIN_FUNCTION_2003) {
    4233           4 :                 return WERR_INVALID_FUNCTION;
    4234             :         }
    4235             : 
    4236         172 :         if (r->in.flags & DS_GFTI_UPDATE_TDO) {
    4237          16 :                 if (!samdb_is_pdc(sam_ctx)) {
    4238           0 :                         return WERR_NERR_NOTPRIMARY;
    4239             :                 }
    4240             : 
    4241          16 :                 if (r->in.trusted_domain_name == NULL) {
    4242           0 :                         return WERR_INVALID_FLAGS;
    4243             :                 }
    4244             :         }
    4245             : 
    4246         172 :         if (r->in.trusted_domain_name == NULL) {
    4247           7 :                 NTSTATUS status;
    4248             : 
    4249             :                 /*
    4250             :                  * information about our own domain
    4251             :                  */
    4252         152 :                 status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
    4253             :                                                 r->out.forest_trust_info);
    4254         152 :                 if (!NT_STATUS_IS_OK(status)) {
    4255           0 :                         return ntstatus_to_werror(status);
    4256             :                 }
    4257             : 
    4258         152 :                 return WERR_OK;
    4259             :         }
    4260             : 
    4261             :         /*
    4262             :          * Forward the request to winbindd
    4263             :          */
    4264             : 
    4265          20 :         state = talloc_zero(mem_ctx,
    4266             :                         struct dcesrv_netr_DsRGetForestTrustInformation_state);
    4267          20 :         if (state == NULL) {
    4268           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    4269             :         }
    4270          20 :         state->dce_call = dce_call;
    4271          20 :         state->mem_ctx = mem_ctx;
    4272          20 :         state->r = r;
    4273             : 
    4274          20 :         irpc_handle = irpc_binding_handle_by_name(state,
    4275             :                                                   imsg_ctx,
    4276             :                                                   "winbind_server",
    4277             :                                                   &ndr_table_winbind);
    4278          20 :         if (irpc_handle == NULL) {
    4279           0 :                 DEBUG(0,("Failed to get binding_handle for winbind_server task\n"));
    4280           0 :                 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
    4281           0 :                 return WERR_SERVICE_NOT_FOUND;
    4282             :         }
    4283             : 
    4284             :         /*
    4285             :          * 60 seconds timeout should be enough
    4286             :          */
    4287          20 :         dcerpc_binding_handle_set_timeout(irpc_handle, 60);
    4288             : 
    4289          20 :         subreq = dcerpc_winbind_GetForestTrustInformation_send(state,
    4290          20 :                                                 state->dce_call->event_ctx,
    4291             :                                                 irpc_handle,
    4292             :                                                 r->in.trusted_domain_name,
    4293             :                                                 r->in.flags,
    4294             :                                                 r->out.forest_trust_info);
    4295          20 :         if (subreq == NULL) {
    4296           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    4297             :         }
    4298          20 :         state->dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
    4299          20 :         tevent_req_set_callback(subreq,
    4300             :                                 dcesrv_netr_DsRGetForestTrustInformation_done,
    4301             :                                 state);
    4302             : 
    4303          20 :         return WERR_OK;
    4304             : }
    4305             : 
    4306          20 : static void dcesrv_netr_DsRGetForestTrustInformation_done(struct tevent_req *subreq)
    4307             : {
    4308           0 :         struct dcesrv_netr_DsRGetForestTrustInformation_state *state =
    4309          20 :                 tevent_req_callback_data(subreq,
    4310             :                 struct dcesrv_netr_DsRGetForestTrustInformation_state);
    4311           0 :         NTSTATUS status;
    4312             : 
    4313          20 :         status = dcerpc_winbind_GetForestTrustInformation_recv(subreq,
    4314             :                                                         state->mem_ctx,
    4315          20 :                                                         &state->r->out.result);
    4316          20 :         TALLOC_FREE(subreq);
    4317          20 :         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
    4318           0 :                 state->r->out.result = WERR_TIMEOUT;
    4319          20 :         } else if (!NT_STATUS_IS_OK(status)) {
    4320           0 :                 state->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
    4321           0 :                 DEBUG(0,(__location__ ": IRPC callback failed %s\n",
    4322             :                          nt_errstr(status)));
    4323             :         }
    4324             : 
    4325          20 :         dcesrv_async_reply(state->dce_call);
    4326          20 : }
    4327             : 
    4328             : /*
    4329             :   netr_GetForestTrustInformation
    4330             : */
    4331          41 : static NTSTATUS dcesrv_netr_GetForestTrustInformation(struct dcesrv_call_state *dce_call,
    4332             :                                                       TALLOC_CTX *mem_ctx,
    4333             :                                                       struct netr_GetForestTrustInformation *r)
    4334             : {
    4335          41 :         struct netlogon_creds_CredentialState *creds = NULL;
    4336          41 :         struct ldb_context *sam_ctx = NULL;
    4337          41 :         struct ldb_dn *domain_dn = NULL;
    4338          41 :         struct ldb_dn *forest_dn = NULL;
    4339           3 :         int cmp;
    4340           3 :         int forest_level;
    4341           3 :         NTSTATUS status;
    4342             : 
    4343          41 :         status = dcesrv_netr_creds_server_step_check(dce_call,
    4344             :                                                      mem_ctx,
    4345             :                                                      r->in.computer_name,
    4346             :                                                      r->in.credential,
    4347             :                                                      r->out.return_authenticator,
    4348             :                                                      &creds);
    4349          41 :         if (!NT_STATUS_IS_OK(status)) {
    4350           0 :                 return status;
    4351             :         }
    4352             : 
    4353          41 :         if ((creds->secure_channel_type != SEC_CHAN_DNS_DOMAIN) &&
    4354          18 :             (creds->secure_channel_type != SEC_CHAN_DOMAIN)) {
    4355          18 :                 return NT_STATUS_NOT_IMPLEMENTED;
    4356             :         }
    4357             : 
    4358          23 :         sam_ctx = dcesrv_samdb_connect_as_user(mem_ctx, dce_call);
    4359          23 :         if (sam_ctx == NULL) {
    4360           0 :                 return NT_STATUS_INTERNAL_ERROR;
    4361             :         }
    4362             : 
    4363             :         /* TODO: check r->in.server_name is our name */
    4364             : 
    4365          23 :         domain_dn = ldb_get_default_basedn(sam_ctx);
    4366          23 :         if (domain_dn == NULL) {
    4367           0 :                 return NT_STATUS_INTERNAL_ERROR;
    4368             :         }
    4369             : 
    4370          23 :         forest_dn = ldb_get_root_basedn(sam_ctx);
    4371          23 :         if (forest_dn == NULL) {
    4372           0 :                 return NT_STATUS_INTERNAL_ERROR;
    4373             :         }
    4374             : 
    4375          23 :         cmp = ldb_dn_compare(domain_dn, forest_dn);
    4376          23 :         if (cmp != 0) {
    4377           0 :                 return NT_STATUS_INVALID_DOMAIN_STATE;
    4378             :         }
    4379             : 
    4380          23 :         forest_level = dsdb_forest_functional_level(sam_ctx);
    4381          23 :         if (forest_level < DS_DOMAIN_FUNCTION_2003) {
    4382           0 :                 return NT_STATUS_INVALID_DOMAIN_STATE;
    4383             :         }
    4384             : 
    4385          23 :         status = dsdb_trust_xref_forest_info(mem_ctx, sam_ctx,
    4386             :                                              r->out.forest_trust_info);
    4387          23 :         if (!NT_STATUS_IS_OK(status)) {
    4388           0 :                 return status;
    4389             :         }
    4390             : 
    4391          23 :         return NT_STATUS_OK;
    4392             : }
    4393             : 
    4394             : 
    4395             : /*
    4396             :   netr_ServerGetTrustInfo
    4397             : */
    4398         104 : static NTSTATUS dcesrv_netr_ServerGetTrustInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4399             :                        struct netr_ServerGetTrustInfo *r)
    4400             : {
    4401         104 :         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
    4402         104 :         struct netlogon_creds_CredentialState *creds = NULL;
    4403         104 :         struct ldb_context *sam_ctx = NULL;
    4404         104 :         const char * const attrs[] = {
    4405             :                 "unicodePwd",
    4406             :                 "sAMAccountName",
    4407             :                 "userAccountControl",
    4408             :                 NULL
    4409             :         };
    4410         104 :         struct ldb_message **res = NULL;
    4411         104 :         struct samr_Password *curNtHash = NULL, *prevNtHash = NULL;
    4412           9 :         NTSTATUS nt_status;
    4413           9 :         int ret;
    4414         104 :         const char *asid = NULL;
    4415         104 :         uint32_t uac = 0;
    4416         104 :         const char *aname = NULL;
    4417         104 :         struct ldb_message *tdo_msg = NULL;
    4418         104 :         const char * const tdo_attrs[] = {
    4419             :                 "trustAuthIncoming",
    4420             :                 "trustAttributes",
    4421             :                 NULL
    4422             :         };
    4423         104 :         struct netr_TrustInfo *trust_info = NULL;
    4424             : 
    4425         104 :         ZERO_STRUCTP(r->out.new_owf_password);
    4426         104 :         ZERO_STRUCTP(r->out.old_owf_password);
    4427             : 
    4428         104 :         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
    4429             :                                                         mem_ctx,
    4430             :                                                         r->in.computer_name,
    4431             :                                                         r->in.credential,
    4432             :                                                         r->out.return_authenticator,
    4433             :                                                         &creds);
    4434         104 :         if (!NT_STATUS_IS_OK(nt_status)) {
    4435           0 :                 return nt_status;
    4436             :         }
    4437             : 
    4438             :         /* TODO: check r->in.server_name is our name */
    4439             : 
    4440         104 :         if (strcasecmp_m(r->in.account_name, creds->account_name) != 0) {
    4441           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4442             :         }
    4443             : 
    4444         104 :         if (r->in.secure_channel_type != creds->secure_channel_type) {
    4445           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4446             :         }
    4447             : 
    4448         104 :         if (strcasecmp_m(r->in.computer_name, creds->computer_name) != 0) {
    4449           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4450             :         }
    4451             : 
    4452         104 :         sam_ctx = dcesrv_samdb_connect_as_system(mem_ctx, dce_call);
    4453         104 :         if (sam_ctx == NULL) {
    4454           0 :                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
    4455             :         }
    4456             : 
    4457         104 :         asid = ldap_encode_ndr_dom_sid(mem_ctx, creds->sid);
    4458         104 :         if (asid == NULL) {
    4459           0 :                 return NT_STATUS_NO_MEMORY;
    4460             :         }
    4461             : 
    4462         104 :         ret = gendb_search(sam_ctx, mem_ctx, NULL, &res, attrs,
    4463             :                            "(&(objectClass=user)(objectSid=%s))",
    4464             :                            asid);
    4465         104 :         if (ret != 1) {
    4466           0 :                 return NT_STATUS_ACCOUNT_DISABLED;
    4467             :         }
    4468             : 
    4469         104 :         switch (creds->secure_channel_type) {
    4470          50 :         case SEC_CHAN_DNS_DOMAIN:
    4471             :         case SEC_CHAN_DOMAIN:
    4472          50 :                 uac = ldb_msg_find_attr_as_uint(res[0], "userAccountControl", 0);
    4473             : 
    4474          50 :                 if (uac & UF_ACCOUNTDISABLE) {
    4475           0 :                         return NT_STATUS_ACCOUNT_DISABLED;
    4476             :                 }
    4477             : 
    4478          50 :                 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
    4479           0 :                         return NT_STATUS_ACCOUNT_DISABLED;
    4480             :                 }
    4481             : 
    4482          50 :                 aname = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
    4483          50 :                 if (aname == NULL) {
    4484           0 :                         return NT_STATUS_ACCOUNT_DISABLED;
    4485             :                 }
    4486             : 
    4487          50 :                 nt_status = dsdb_trust_search_tdo_by_type(sam_ctx,
    4488             :                                                 SEC_CHAN_DOMAIN, aname,
    4489             :                                                 tdo_attrs, mem_ctx, &tdo_msg);
    4490          50 :                 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
    4491           0 :                         return NT_STATUS_ACCOUNT_DISABLED;
    4492             :                 }
    4493          50 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    4494           0 :                         return nt_status;
    4495             :                 }
    4496             : 
    4497          50 :                 nt_status = dsdb_trust_get_incoming_passwords(tdo_msg, mem_ctx,
    4498             :                                                               &curNtHash,
    4499             :                                                               &prevNtHash);
    4500          50 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    4501           0 :                         return nt_status;
    4502             :                 }
    4503             : 
    4504          50 :                 trust_info = talloc_zero(mem_ctx, struct netr_TrustInfo);
    4505          50 :                 if (trust_info == NULL) {
    4506           0 :                         return NT_STATUS_NO_MEMORY;
    4507             :                 }
    4508             : 
    4509          50 :                 trust_info->count = 1;
    4510          50 :                 trust_info->data = talloc_array(trust_info, uint32_t,
    4511             :                                                 trust_info->count);
    4512          50 :                 if (trust_info->data == NULL) {
    4513           0 :                         return NT_STATUS_NO_MEMORY;
    4514             :                 }
    4515             : 
    4516          50 :                 trust_info->data[0] = ldb_msg_find_attr_as_uint(tdo_msg,
    4517             :                                                         "trustAttributes",
    4518             :                                                         0);
    4519          50 :                 break;
    4520             : 
    4521          54 :         default:
    4522          54 :                 nt_status = samdb_result_passwords_no_lockout(mem_ctx, lp_ctx,
    4523             :                                                               res[0],
    4524             :                                                               &curNtHash);
    4525          54 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    4526           0 :                         return nt_status;
    4527             :                 }
    4528             : 
    4529          54 :                 prevNtHash = talloc(mem_ctx, struct samr_Password);
    4530          54 :                 if (prevNtHash == NULL) {
    4531           0 :                         return NT_STATUS_NO_MEMORY;
    4532             :                 }
    4533             : 
    4534          54 :                 E_md4hash("", prevNtHash->hash);
    4535          54 :                 break;
    4536             :         }
    4537             : 
    4538         104 :         if (curNtHash != NULL) {
    4539         104 :                 *r->out.new_owf_password = *curNtHash;
    4540         104 :                 nt_status = netlogon_creds_des_encrypt(creds, r->out.new_owf_password);
    4541         104 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    4542           0 :                         return nt_status;
    4543             :                 }
    4544             :         }
    4545         104 :         if (prevNtHash != NULL) {
    4546         104 :                 *r->out.old_owf_password = *prevNtHash;
    4547         104 :                 nt_status = netlogon_creds_des_encrypt(creds, r->out.old_owf_password);
    4548         104 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    4549           0 :                         return nt_status;
    4550             :                 }
    4551             :         }
    4552             : 
    4553         104 :         if (trust_info != NULL) {
    4554          50 :                 *r->out.trust_info = trust_info;
    4555             :         }
    4556             : 
    4557         104 :         return NT_STATUS_OK;
    4558             : }
    4559             : 
    4560             : /*
    4561             :   netr_Unused47
    4562             : */
    4563           0 : static NTSTATUS dcesrv_netr_Unused47(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4564             :                                      struct netr_Unused47 *r)
    4565             : {
    4566           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    4567             : }
    4568             : 
    4569             : 
    4570             : struct netr_dnsupdate_RODC_state {
    4571             :         struct dcesrv_call_state *dce_call;
    4572             :         struct netr_DsrUpdateReadOnlyServerDnsRecords *r;
    4573             :         struct dnsupdate_RODC *r2;
    4574             : };
    4575             : 
    4576             : /*
    4577             :   called when the forwarded RODC dns update request is finished
    4578             :  */
    4579           5 : static void netr_dnsupdate_RODC_callback(struct tevent_req *subreq)
    4580             : {
    4581           0 :         struct netr_dnsupdate_RODC_state *st =
    4582           5 :                 tevent_req_callback_data(subreq,
    4583             :                                          struct netr_dnsupdate_RODC_state);
    4584           0 :         NTSTATUS status;
    4585             : 
    4586           5 :         status = dcerpc_dnsupdate_RODC_r_recv(subreq, st->dce_call);
    4587           5 :         TALLOC_FREE(subreq);
    4588           5 :         if (!NT_STATUS_IS_OK(status)) {
    4589           0 :                 DEBUG(0,(__location__ ": IRPC callback failed %s\n", nt_errstr(status)));
    4590           0 :                 st->dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
    4591             :         }
    4592             : 
    4593           5 :         st->r->out.dns_names = talloc_steal(st->dce_call, st->r2->out.dns_names);
    4594             : 
    4595           5 :         dcesrv_async_reply(st->dce_call);
    4596           5 : }
    4597             : 
    4598             : /*
    4599             :   netr_DsrUpdateReadOnlyServerDnsRecords
    4600             : */
    4601           5 : static NTSTATUS dcesrv_netr_DsrUpdateReadOnlyServerDnsRecords(struct dcesrv_call_state *dce_call,
    4602             :                                                               TALLOC_CTX *mem_ctx,
    4603             :                                                               struct netr_DsrUpdateReadOnlyServerDnsRecords *r)
    4604             : {
    4605           0 :         struct netlogon_creds_CredentialState *creds;
    4606           0 :         NTSTATUS nt_status;
    4607           0 :         struct dcerpc_binding_handle *binding_handle;
    4608           0 :         struct netr_dnsupdate_RODC_state *st;
    4609           0 :         struct tevent_req *subreq;
    4610           0 :         struct imessaging_context *imsg_ctx =
    4611           5 :                 dcesrv_imessaging_context(dce_call->conn);
    4612             : 
    4613           5 :         nt_status = dcesrv_netr_creds_server_step_check(dce_call,
    4614             :                                                         mem_ctx,
    4615             :                                                         r->in.computer_name,
    4616             :                                                         r->in.credential,
    4617             :                                                         r->out.return_authenticator,
    4618             :                                                         &creds);
    4619           5 :         NT_STATUS_NOT_OK_RETURN(nt_status);
    4620             : 
    4621           5 :         if (creds->secure_channel_type != SEC_CHAN_RODC) {
    4622           0 :                 return NT_STATUS_ACCESS_DENIED;
    4623             :         }
    4624             : 
    4625           5 :         st = talloc_zero(mem_ctx, struct netr_dnsupdate_RODC_state);
    4626           5 :         NT_STATUS_HAVE_NO_MEMORY(st);
    4627             : 
    4628           5 :         st->dce_call = dce_call;
    4629           5 :         st->r = r;
    4630           5 :         st->r2 = talloc_zero(st, struct dnsupdate_RODC);
    4631           5 :         NT_STATUS_HAVE_NO_MEMORY(st->r2);
    4632             : 
    4633           5 :         st->r2->in.dom_sid = creds->sid;
    4634           5 :         st->r2->in.site_name = r->in.site_name;
    4635           5 :         st->r2->in.dns_ttl = r->in.dns_ttl;
    4636           5 :         st->r2->in.dns_names = r->in.dns_names;
    4637           5 :         st->r2->out.dns_names = r->out.dns_names;
    4638             : 
    4639           5 :         binding_handle = irpc_binding_handle_by_name(st,
    4640             :                                                      imsg_ctx,
    4641             :                                                      "dnsupdate",
    4642             :                                                      &ndr_table_irpc);
    4643           5 :         if (binding_handle == NULL) {
    4644           0 :                 DEBUG(0,("Failed to get binding_handle for dnsupdate task\n"));
    4645           0 :                 dce_call->fault_code = DCERPC_FAULT_CANT_PERFORM;
    4646           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    4647             :         }
    4648             : 
    4649             :         /* forward the call */
    4650           5 :         subreq = dcerpc_dnsupdate_RODC_r_send(st, dce_call->event_ctx,
    4651             :                                               binding_handle, st->r2);
    4652           5 :         NT_STATUS_HAVE_NO_MEMORY(subreq);
    4653             : 
    4654           5 :         dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC;
    4655             : 
    4656             :         /* setup the callback */
    4657           5 :         tevent_req_set_callback(subreq, netr_dnsupdate_RODC_callback, st);
    4658             : 
    4659           5 :         return NT_STATUS_OK;
    4660             : }
    4661             : 
    4662             : 
    4663             : /* include the generated boilerplate */
    4664             : #include "librpc/gen_ndr/ndr_netlogon_s.c"

Generated by: LCOV version 1.14