LCOV - code coverage report
Current view: top level - source4/rpc_server/netlogon - dcerpc_netlogon.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 1514 1918 78.9 %
Date: 2021-09-23 10:06:22 Functions: 62 72 86.1 %

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

Generated by: LCOV version 1.13