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

Generated by: LCOV version 1.14