LCOV - code coverage report
Current view: top level - source4/rpc_server/netlogon - dcerpc_netlogon.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 1501 1910 78.6 %
Date: 2024-06-13 04:01:37 Functions: 58 68 85.3 %

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

Generated by: LCOV version 1.13