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

Generated by: LCOV version 1.14