LCOV - code coverage report
Current view: top level - source4/rpc_server/lsa - dcesrv_lsa.c (source / functions) Hit Total Coverage
Test: coverage report for master 6248eab5 Lines: 1412 2039 69.2 %
Date: 2021-08-25 13:27:56 Functions: 65 115 56.5 %

          Line data    Source code
       1             : /* need access mask/acl implementation */
       2             : 
       3             : /* 
       4             :    Unix SMB/CIFS implementation.
       5             : 
       6             :    endpoint server for the lsarpc pipe
       7             : 
       8             :    Copyright (C) Andrew Tridgell 2004
       9             :    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008
      10             : 
      11             :    This program is free software; you can redistribute it and/or modify
      12             :    it under the terms of the GNU General Public License as published by
      13             :    the Free Software Foundation; either version 3 of the License, or
      14             :    (at your option) any later version.
      15             : 
      16             :    This program is distributed in the hope that it will be useful,
      17             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      18             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19             :    GNU General Public License for more details.
      20             : 
      21             :    You should have received a copy of the GNU General Public License
      22             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      23             : */
      24             : 
      25             : #include "rpc_server/lsa/lsa.h"
      26             : #include "system/kerberos.h"
      27             : #include "auth/kerberos/kerberos.h"
      28             : #include "librpc/gen_ndr/ndr_drsblobs.h"
      29             : #include "librpc/gen_ndr/ndr_lsa.h"
      30             : #include "lib/util/tsort.h"
      31             : #include "dsdb/common/util.h"
      32             : #include "libcli/security/session.h"
      33             : #include "libcli/lsarpc/util_lsarpc.h"
      34             : #include "lib/messaging/irpc.h"
      35             : #include "libds/common/roles.h"
      36             : #include "lib/util/smb_strtox.h"
      37             : #include "lib/param/loadparm.h"
      38             : #include "librpc/rpc/dcerpc_helper.h"
      39             : 
      40             : #include "lib/crypto/gnutls_helpers.h"
      41             : #include <gnutls/gnutls.h>
      42             : #include <gnutls/crypto.h>
      43             : 
      44             : #undef strcasecmp
      45             : 
      46             : #define DCESRV_INTERFACE_LSARPC_BIND(context, iface) \
      47             :        dcesrv_interface_lsarpc_bind(context, iface)
      48        3611 : static NTSTATUS dcesrv_interface_lsarpc_bind(struct dcesrv_connection_context *context,
      49             :                                              const struct dcesrv_interface *iface)
      50             : {
      51        3807 :         return dcesrv_interface_bind_reject_connect(context, iface);
      52             : }
      53             : 
      54             : static NTSTATUS lsarpc__op_init_server(struct dcesrv_context *dce_ctx,
      55             :                                        const struct dcesrv_endpoint_server *ep_server);
      56             : static const struct dcesrv_interface dcesrv_lsarpc_interface;
      57             : 
      58             : #define NCACN_NP_PIPE_NETLOGON "ncacn_np:[\\pipe\\netlogon]"
      59             : #define NCACN_NP_PIPE_LSASS "ncacn_np:[\\pipe\\lsass]"
      60             : #define DCESRV_INTERFACE_LSARPC_NCACN_NP_SECONDARY_ENDPOINT NCACN_NP_PIPE_LSASS
      61             : 
      62             : #define DCESRV_INTERFACE_LSARPC_INIT_SERVER     \
      63             :        dcesrv_interface_lsarpc_init_server
      64          62 : static NTSTATUS dcesrv_interface_lsarpc_init_server(struct dcesrv_context *dce_ctx,
      65             :                                                     const struct dcesrv_endpoint_server *ep_server)
      66             : {
      67          62 :         if (lpcfg_lsa_over_netlogon(dce_ctx->lp_ctx)) {
      68           8 :                 NTSTATUS ret = dcesrv_interface_register(dce_ctx,
      69             :                                                 NCACN_NP_PIPE_NETLOGON,
      70             :                                                 NCACN_NP_PIPE_LSASS,
      71             :                                                 &dcesrv_lsarpc_interface, NULL);
      72           8 :                 if (!NT_STATUS_IS_OK(ret)) {
      73           0 :                         DEBUG(1,("lsarpc_op_init_server: failed to register endpoint '\\pipe\\netlogon'\n"));
      74           0 :                         return ret;
      75             :                 }
      76             :         }
      77          62 :         return lsarpc__op_init_server(dce_ctx, ep_server);
      78             : }
      79             : 
      80             : /*
      81             :   this type allows us to distinguish handle types
      82             : */
      83             : 
      84             : /*
      85             :   state associated with a lsa_OpenAccount() operation
      86             : */
      87             : struct lsa_account_state {
      88             :         struct lsa_policy_state *policy;
      89             :         uint32_t access_mask;
      90             :         struct dom_sid *account_sid;
      91             : };
      92             : 
      93             : 
      94             : /*
      95             :   state associated with a lsa_OpenSecret() operation
      96             : */
      97             : struct lsa_secret_state {
      98             :         struct lsa_policy_state *policy;
      99             :         uint32_t access_mask;
     100             :         struct ldb_dn *secret_dn;
     101             :         struct ldb_context *sam_ldb;
     102             :         bool global;
     103             : };
     104             : 
     105             : /*
     106             :   state associated with a lsa_OpenTrustedDomain() operation
     107             : */
     108             : struct lsa_trusted_domain_state {
     109             :         struct lsa_policy_state *policy;
     110             :         uint32_t access_mask;
     111             :         struct ldb_dn *trusted_domain_dn;
     112             :         struct ldb_dn *trusted_domain_user_dn;
     113             : };
     114             : 
     115         201 : static bool dcesrc_lsa_valid_AccountRight(const char *right)
     116             : {
     117             :         enum sec_privilege priv_id;
     118             :         uint32_t right_bit;
     119             : 
     120         201 :         priv_id = sec_privilege_id(right);
     121         201 :         if (priv_id != SEC_PRIV_INVALID) {
     122         189 :                 return true;
     123             :         }
     124             : 
     125          12 :         right_bit = sec_right_bit(right);
     126          12 :         if (right_bit != 0) {
     127          12 :                 return true;
     128             :         }
     129             : 
     130           0 :         return false;
     131             : }
     132             : 
     133             : /*
     134             :   this is based on the samba3 function make_lsa_object_sd()
     135             :   It uses the same logic, but with samba4 helper functions
     136             :  */
     137          12 : static NTSTATUS dcesrv_build_lsa_sd(TALLOC_CTX *mem_ctx,
     138             :                                     struct security_descriptor **sd,
     139             :                                     struct dom_sid *sid,
     140             :                                     uint32_t sid_access)
     141             : {
     142             :         NTSTATUS status;
     143             :         uint32_t rid;
     144             :         struct dom_sid *domain_sid, *domain_admins_sid;
     145             :         const char *domain_admins_sid_str, *sidstr;
     146          12 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
     147             : 
     148          12 :         status = dom_sid_split_rid(tmp_ctx, sid, &domain_sid, &rid);
     149          12 :         if (!NT_STATUS_IS_OK(status)) {
     150           0 :                 TALLOC_FREE(tmp_ctx);
     151           0 :                 return status;
     152             :         }
     153             : 
     154          12 :         domain_admins_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
     155          12 :         if (domain_admins_sid == NULL) {
     156           0 :                 TALLOC_FREE(tmp_ctx);
     157           0 :                 return NT_STATUS_NO_MEMORY;
     158             :         }
     159             : 
     160          12 :         domain_admins_sid_str = dom_sid_string(tmp_ctx, domain_admins_sid);
     161          12 :         if (domain_admins_sid_str == NULL) {
     162           0 :                 TALLOC_FREE(tmp_ctx);
     163           0 :                 return NT_STATUS_NO_MEMORY;
     164             :         }
     165             : 
     166          12 :         sidstr = dom_sid_string(tmp_ctx, sid);
     167          12 :         if (sidstr == NULL) {
     168           0 :                 TALLOC_FREE(tmp_ctx);
     169           0 :                 return NT_STATUS_NO_MEMORY;
     170             :         }
     171             : 
     172          12 :         *sd = security_descriptor_dacl_create(mem_ctx,
     173             :                                               0, sidstr, NULL,
     174             : 
     175             :                                               SID_WORLD,
     176             :                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
     177             :                                               SEC_GENERIC_EXECUTE | SEC_GENERIC_READ, 0,
     178             : 
     179             :                                               SID_BUILTIN_ADMINISTRATORS,
     180             :                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
     181             :                                               SEC_GENERIC_ALL, 0,
     182             : 
     183             :                                               SID_BUILTIN_ACCOUNT_OPERATORS,
     184             :                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
     185             :                                               SEC_GENERIC_ALL, 0,
     186             : 
     187             :                                               domain_admins_sid_str,
     188             :                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
     189             :                                               SEC_GENERIC_ALL, 0,
     190             : 
     191             :                                               sidstr,
     192             :                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
     193             :                                               sid_access, 0,
     194             : 
     195             :                                               NULL);
     196          12 :         talloc_free(tmp_ctx);
     197             : 
     198          12 :         NT_STATUS_HAVE_NO_MEMORY(*sd);
     199             : 
     200          12 :         return NT_STATUS_OK;
     201             : }
     202             : 
     203             : 
     204             : static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
     205             :                                       TALLOC_CTX *mem_ctx,
     206             :                                       struct lsa_EnumAccountRights *r);
     207             : 
     208             : static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
     209             :                                            TALLOC_CTX *mem_ctx,
     210             :                                            struct lsa_policy_state *state,
     211             :                                            int ldb_flag,
     212             :                                            struct dom_sid *sid,
     213             :                                            const struct lsa_RightSet *rights);
     214             : 
     215             : /*
     216             :   lsa_Close
     217             : */
     218         936 : static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     219             :                           struct lsa_Close *r)
     220             : {
     221         936 :         enum dcerpc_transport_t transport =
     222         936 :                 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
     223             :         struct dcesrv_handle *h;
     224             : 
     225         936 :         if (transport != NCACN_NP && transport != NCALRPC) {
     226           0 :                 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
     227             :         }
     228             : 
     229         936 :         *r->out.handle = *r->in.handle;
     230             : 
     231         936 :         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
     232             : 
     233         759 :         talloc_free(h);
     234             : 
     235         759 :         ZERO_STRUCTP(r->out.handle);
     236             : 
     237         759 :         return NT_STATUS_OK;
     238             : }
     239             : 
     240             : 
     241             : /*
     242             :   lsa_Delete
     243             : */
     244          41 : static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     245             :                            struct lsa_Delete *r)
     246             : {
     247          41 :         return NT_STATUS_NOT_SUPPORTED;
     248             : }
     249             : 
     250             : 
     251             : /*
     252             :   lsa_DeleteObject
     253             : */
     254        1847 : static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     255             :                        struct lsa_DeleteObject *r)
     256             : {
     257        1847 :         struct auth_session_info *session_info =
     258             :                 dcesrv_call_session_info(dce_call);
     259             :         struct dcesrv_handle *h;
     260             :         int ret;
     261             : 
     262        1847 :         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
     263             : 
     264        1847 :         if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
     265        1725 :                 struct lsa_secret_state *secret_state = h->data;
     266             : 
     267             :                 /* Ensure user is permitted to delete this... */
     268        1725 :                 switch (security_session_user_level(session_info, NULL))
     269             :                 {
     270        1725 :                 case SECURITY_SYSTEM:
     271             :                 case SECURITY_ADMINISTRATOR:
     272        1725 :                         break;
     273           0 :                 default:
     274             :                         /* Users and anonymous are not allowed to delete things */
     275           0 :                         return NT_STATUS_ACCESS_DENIED;
     276             :                 }
     277             : 
     278        1725 :                 ret = ldb_delete(secret_state->sam_ldb,
     279             :                                  secret_state->secret_dn);
     280        1725 :                 if (ret != LDB_SUCCESS) {
     281          22 :                         return NT_STATUS_INVALID_HANDLE;
     282             :                 }
     283             : 
     284        1703 :                 ZERO_STRUCTP(r->out.handle);
     285             : 
     286        1703 :                 return NT_STATUS_OK;
     287             : 
     288         122 :         } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
     289         111 :                 struct lsa_trusted_domain_state *trusted_domain_state =
     290         111 :                         talloc_get_type(h->data, struct lsa_trusted_domain_state);
     291         111 :                 ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
     292         111 :                 if (ret != LDB_SUCCESS) {
     293           0 :                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
     294             :                 }
     295             : 
     296         111 :                 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
     297             :                                  trusted_domain_state->trusted_domain_dn);
     298         111 :                 if (ret != LDB_SUCCESS) {
     299           0 :                         ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
     300           0 :                         return NT_STATUS_INVALID_HANDLE;
     301             :                 }
     302             : 
     303         111 :                 if (trusted_domain_state->trusted_domain_user_dn) {
     304          51 :                         ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
     305             :                                          trusted_domain_state->trusted_domain_user_dn);
     306          51 :                         if (ret != LDB_SUCCESS) {
     307           0 :                                 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
     308           0 :                                 return NT_STATUS_INVALID_HANDLE;
     309             :                         }
     310             :                 }
     311             : 
     312         111 :                 ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb);
     313         111 :                 if (ret != LDB_SUCCESS) {
     314           0 :                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
     315             :                 }
     316             : 
     317         111 :                 ZERO_STRUCTP(r->out.handle);
     318             : 
     319         111 :                 return NT_STATUS_OK;
     320             : 
     321          11 :         } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
     322             :                 struct lsa_RightSet *rights;
     323             :                 struct lsa_account_state *astate;
     324             :                 struct lsa_EnumAccountRights r2;
     325             :                 NTSTATUS status;
     326             : 
     327          11 :                 rights = talloc(mem_ctx, struct lsa_RightSet);
     328             : 
     329          11 :                 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
     330             : 
     331          11 :                 astate = h->data;
     332             : 
     333          11 :                 r2.in.handle = &astate->policy->handle->wire_handle;
     334          11 :                 r2.in.sid = astate->account_sid;
     335          11 :                 r2.out.rights = rights;
     336             : 
     337             :                 /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
     338             :                    but we have a LSA_HANDLE_ACCOUNT here, so this call
     339             :                    will always fail */
     340          11 :                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
     341          11 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
     342           5 :                         return NT_STATUS_OK;
     343             :                 }
     344             : 
     345           6 :                 if (!NT_STATUS_IS_OK(status)) {
     346           0 :                         return status;
     347             :                 }
     348             : 
     349           6 :                 status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
     350             :                                                     LDB_FLAG_MOD_DELETE, astate->account_sid,
     351           6 :                                                     r2.out.rights);
     352           6 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
     353           0 :                         return NT_STATUS_OK;
     354             :                 }
     355             : 
     356           6 :                 if (!NT_STATUS_IS_OK(status)) {
     357           0 :                         return status;
     358             :                 }
     359             : 
     360           6 :                 ZERO_STRUCTP(r->out.handle);
     361             : 
     362           6 :                 return NT_STATUS_OK;
     363             :         }
     364             : 
     365           0 :         return NT_STATUS_INVALID_HANDLE;
     366             : }
     367             : 
     368             : 
     369             : /*
     370             :   lsa_EnumPrivs
     371             : */
     372           5 : static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     373             :                               struct lsa_EnumPrivs *r)
     374             : {
     375             :         struct dcesrv_handle *h;
     376             :         uint32_t i;
     377             :         enum sec_privilege priv;
     378             :         const char *privname;
     379             : 
     380           5 :         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
     381             : 
     382           5 :         i = *r->in.resume_handle;
     383             : 
     384         260 :         while (((priv = sec_privilege_from_index(i)) != SEC_PRIV_INVALID) &&
     385         125 :                r->out.privs->count < r->in.max_count) {
     386             :                 struct lsa_PrivEntry *e;
     387         125 :                 privname = sec_privilege_name(priv);
     388         125 :                 r->out.privs->privs = talloc_realloc(r->out.privs,
     389             :                                                        r->out.privs->privs,
     390             :                                                        struct lsa_PrivEntry,
     391             :                                                        r->out.privs->count+1);
     392         125 :                 if (r->out.privs->privs == NULL) {
     393           0 :                         return NT_STATUS_NO_MEMORY;
     394             :                 }
     395         125 :                 e = &r->out.privs->privs[r->out.privs->count];
     396         125 :                 e->luid.low = priv;
     397         125 :                 e->luid.high = 0;
     398         125 :                 e->name.string = privname;
     399         125 :                 r->out.privs->count++;
     400         125 :                 i++;
     401             :         }
     402             : 
     403           5 :         *r->out.resume_handle = i;
     404             : 
     405           5 :         return NT_STATUS_OK;
     406             : }
     407             : 
     408             : 
     409             : /*
     410             :   lsa_QuerySecObj
     411             : */
     412          60 : static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     413             :                                          struct lsa_QuerySecurity *r)
     414             : {
     415          60 :         struct auth_session_info *session_info =
     416             :                 dcesrv_call_session_info(dce_call);
     417             :         struct dcesrv_handle *h;
     418          60 :         const struct security_descriptor *sd = NULL;
     419          60 :         uint32_t access_granted = 0;
     420          60 :         struct sec_desc_buf *sdbuf = NULL;
     421             :         NTSTATUS status;
     422             :         struct dom_sid *sid;
     423             : 
     424          60 :         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
     425             : 
     426          60 :         sid = &session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
     427             : 
     428          60 :         if (h->wire_handle.handle_type == LSA_HANDLE_POLICY) {
     429          48 :                 struct lsa_policy_state *pstate = h->data;
     430             : 
     431          48 :                 sd = pstate->sd;
     432          48 :                 access_granted = pstate->access_mask;
     433             : 
     434          12 :         } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
     435          12 :                 struct lsa_account_state *astate = h->data;
     436          12 :                 struct security_descriptor *_sd = NULL;
     437             : 
     438          12 :                 status = dcesrv_build_lsa_sd(mem_ctx, &_sd, sid,
     439             :                                              LSA_ACCOUNT_ALL_ACCESS);
     440          12 :                 if (!NT_STATUS_IS_OK(status)) {
     441           0 :                         return status;
     442             :                 }
     443          12 :                 sd = _sd;
     444          12 :                 access_granted = astate->access_mask;
     445             :         } else {
     446           0 :                 return NT_STATUS_INVALID_HANDLE;
     447             :         }
     448             : 
     449          60 :         sdbuf = talloc_zero(mem_ctx, struct sec_desc_buf);
     450          60 :         if (sdbuf == NULL) {
     451           0 :                 return NT_STATUS_NO_MEMORY;
     452             :         }
     453             : 
     454          60 :         status = security_descriptor_for_client(sdbuf, sd, r->in.sec_info,
     455             :                                                 access_granted, &sdbuf->sd);
     456          60 :         if (!NT_STATUS_IS_OK(status)) {
     457           0 :                 return status;
     458             :         }
     459             : 
     460          60 :         *r->out.sdbuf = sdbuf;
     461             : 
     462          60 :         return NT_STATUS_OK;
     463             : }
     464             : 
     465             : 
     466             : /*
     467             :   lsa_SetSecObj
     468             : */
     469           0 : static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     470             :                               struct lsa_SetSecObj *r)
     471             : {
     472           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
     473             : }
     474             : 
     475             : 
     476             : /*
     477             :   lsa_ChangePassword
     478             : */
     479           0 : static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     480             :                                    struct lsa_ChangePassword *r)
     481             : {
     482           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
     483             : }
     484             : 
     485             : /*
     486             :   dssetup_DsRoleGetPrimaryDomainInformation
     487             : 
     488             :   This is not an LSA call, but is the only call left on the DSSETUP
     489             :   pipe (after the pipe was truncated), and needs lsa_get_policy_state
     490             : */
     491         119 : static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call,
     492             :                                                  TALLOC_CTX *mem_ctx,
     493             :                                                  struct dssetup_DsRoleGetPrimaryDomainInformation *r)
     494             : {
     495             :         union dssetup_DsRoleInfo *info;
     496             : 
     497         119 :         info = talloc_zero(mem_ctx, union dssetup_DsRoleInfo);
     498         119 :         W_ERROR_HAVE_NO_MEMORY(info);
     499             : 
     500         119 :         switch (r->in.level) {
     501          59 :         case DS_ROLE_BASIC_INFORMATION:
     502             :         {
     503          59 :                 enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
     504          59 :                 uint32_t flags = 0;
     505          59 :                 const char *domain = NULL;
     506          59 :                 const char *dns_domain = NULL;
     507          59 :                 const char *forest = NULL;
     508             :                 struct GUID domain_guid;
     509             :                 struct lsa_policy_state *state;
     510             : 
     511          59 :                 NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx,
     512             :                                                               0, /* we skip access checks */
     513             :                                                               &state);
     514          59 :                 if (!NT_STATUS_IS_OK(status)) {
     515           0 :                         return ntstatus_to_werror(status);
     516             :                 }
     517             : 
     518          59 :                 ZERO_STRUCT(domain_guid);
     519             : 
     520          59 :                 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
     521           0 :                 case ROLE_STANDALONE:
     522           0 :                         role            = DS_ROLE_STANDALONE_SERVER;
     523           0 :                         break;
     524           4 :                 case ROLE_DOMAIN_MEMBER:
     525           4 :                         role            = DS_ROLE_MEMBER_SERVER;
     526           4 :                         break;
     527          55 :                 case ROLE_ACTIVE_DIRECTORY_DC:
     528          55 :                         if (samdb_is_pdc(state->sam_ldb)) {
     529          52 :                                 role    = DS_ROLE_PRIMARY_DC;
     530             :                         } else {
     531           0 :                                 role    = DS_ROLE_BACKUP_DC;
     532             :                         }
     533          52 :                         break;
     534             :                 }
     535             : 
     536          59 :                 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
     537           0 :                 case ROLE_STANDALONE:
     538           0 :                         domain          = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
     539           0 :                         W_ERROR_HAVE_NO_MEMORY(domain);
     540           0 :                         break;
     541           4 :                 case ROLE_DOMAIN_MEMBER:
     542           4 :                         domain          = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
     543           4 :                         W_ERROR_HAVE_NO_MEMORY(domain);
     544             :                         /* TODO: what is with dns_domain and forest and guid? */
     545           4 :                         break;
     546          55 :                 case ROLE_ACTIVE_DIRECTORY_DC:
     547          55 :                         flags           = DS_ROLE_PRIMARY_DS_RUNNING;
     548             : 
     549          55 :                         if (state->mixed_domain == 1) {
     550           0 :                                 flags   |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
     551             :                         }
     552             : 
     553          55 :                         domain          = state->domain_name;
     554          55 :                         dns_domain      = state->domain_dns;
     555          55 :                         forest          = state->forest_dns;
     556             : 
     557          55 :                         domain_guid     = state->domain_guid;
     558          55 :                         flags   |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
     559          52 :                         break;
     560             :                 }
     561             : 
     562          59 :                 info->basic.role        = role;
     563          59 :                 info->basic.flags       = flags;
     564          59 :                 info->basic.domain      = domain;
     565          59 :                 info->basic.dns_domain  = dns_domain;
     566          59 :                 info->basic.forest      = forest;
     567          59 :                 info->basic.domain_guid = domain_guid;
     568             : 
     569          59 :                 r->out.info = info;
     570          59 :                 return WERR_OK;
     571             :         }
     572          30 :         case DS_ROLE_UPGRADE_STATUS:
     573             :         {
     574          30 :                 info->upgrade.upgrading     = DS_ROLE_NOT_UPGRADING;
     575          30 :                 info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
     576             : 
     577          30 :                 r->out.info = info;
     578          30 :                 return WERR_OK;
     579             :         }
     580          30 :         case DS_ROLE_OP_STATUS:
     581             :         {
     582          30 :                 info->opstatus.status = DS_ROLE_OP_IDLE;
     583             : 
     584          30 :                 r->out.info = info;
     585          30 :                 return WERR_OK;
     586             :         }
     587           0 :         default:
     588           0 :                 return WERR_INVALID_PARAMETER;
     589             :         }
     590             : }
     591             : 
     592             : /*
     593             :   fill in the AccountDomain info
     594             : */
     595         699 : static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
     596             :                                        struct lsa_DomainInfo *info)
     597             : {
     598         771 :         info->name.string = state->domain_name;
     599         771 :         info->sid         = state->domain_sid;
     600             : 
     601         699 :         return NT_STATUS_OK;
     602             : }
     603             : 
     604             : /*
     605             :   fill in the DNS domain info
     606             : */
     607         772 : static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
     608             :                              struct lsa_DnsDomainInfo *info)
     609             : {
     610         846 :         info->name.string = state->domain_name;
     611         846 :         info->sid         = state->domain_sid;
     612         846 :         info->dns_domain.string = state->domain_dns;
     613         846 :         info->dns_forest.string = state->forest_dns;
     614         846 :         info->domain_guid       = state->domain_guid;
     615             : 
     616         772 :         return NT_STATUS_OK;
     617             : }
     618             : 
     619             : /*
     620             :   lsa_QueryInfoPolicy2
     621             : */
     622        1851 : static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     623             :                                      struct lsa_QueryInfoPolicy2 *r)
     624             : {
     625             :         struct lsa_policy_state *state;
     626             :         struct dcesrv_handle *h;
     627             :         union lsa_PolicyInformation *info;
     628             : 
     629        1851 :         *r->out.info = NULL;
     630             : 
     631        1851 :         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
     632             : 
     633        1851 :         state = h->data;
     634             : 
     635        1851 :         info = talloc_zero(mem_ctx, union lsa_PolicyInformation);
     636        1851 :         if (!info) {
     637           0 :                 return NT_STATUS_NO_MEMORY;
     638             :         }
     639        1851 :         *r->out.info = info;
     640             : 
     641        1851 :         switch (r->in.level) {
     642          26 :         case LSA_POLICY_INFO_AUDIT_LOG:
     643             :                 /* we don't need to fill in any of this */
     644          26 :                 ZERO_STRUCT(info->audit_log);
     645          26 :                 return NT_STATUS_OK;
     646          26 :         case LSA_POLICY_INFO_AUDIT_EVENTS:
     647             :                 /* we don't need to fill in any of this */
     648          26 :                 ZERO_STRUCT(info->audit_events);
     649          26 :                 return NT_STATUS_OK;
     650          26 :         case LSA_POLICY_INFO_PD:
     651             :                 /* we don't need to fill in any of this */
     652          26 :                 ZERO_STRUCT(info->pd);
     653          26 :                 return NT_STATUS_OK;
     654             : 
     655         579 :         case LSA_POLICY_INFO_DOMAIN:
     656         579 :                 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->domain);
     657         166 :         case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
     658         166 :                 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->account_domain);
     659          26 :         case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
     660          26 :                 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->l_account_domain);
     661             : 
     662          26 :         case LSA_POLICY_INFO_ROLE:
     663          26 :                 info->role.role = LSA_ROLE_PRIMARY;
     664          26 :                 return NT_STATUS_OK;
     665             : 
     666         846 :         case LSA_POLICY_INFO_DNS:
     667             :         case LSA_POLICY_INFO_DNS_INT:
     668         846 :                 return dcesrv_lsa_info_DNS(state, mem_ctx, &info->dns);
     669             : 
     670          26 :         case LSA_POLICY_INFO_REPLICA:
     671          26 :                 ZERO_STRUCT(info->replica);
     672          26 :                 return NT_STATUS_OK;
     673             : 
     674          26 :         case LSA_POLICY_INFO_QUOTA:
     675          26 :                 ZERO_STRUCT(info->quota);
     676          26 :                 return NT_STATUS_OK;
     677             : 
     678          78 :         case LSA_POLICY_INFO_MOD:
     679             :         case LSA_POLICY_INFO_AUDIT_FULL_SET:
     680             :         case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
     681             :                 /* windows gives INVALID_PARAMETER */
     682          78 :                 *r->out.info = NULL;
     683          78 :                 return NT_STATUS_INVALID_PARAMETER;
     684             :         }
     685             : 
     686           0 :         *r->out.info = NULL;
     687           0 :         return NT_STATUS_INVALID_INFO_CLASS;
     688             : }
     689             : 
     690             : /*
     691             :   lsa_QueryInfoPolicy
     692             : */
     693         889 : static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     694             :                                     struct lsa_QueryInfoPolicy *r)
     695             : {
     696             :         struct lsa_QueryInfoPolicy2 r2;
     697             :         NTSTATUS status;
     698             : 
     699         889 :         ZERO_STRUCT(r2);
     700             : 
     701         889 :         r2.in.handle = r->in.handle;
     702         889 :         r2.in.level = r->in.level;
     703         889 :         r2.out.info = r->out.info;
     704             : 
     705         889 :         status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
     706             : 
     707         889 :         return status;
     708             : }
     709             : 
     710             : /*
     711             :   lsa_SetInfoPolicy
     712             : */
     713           0 : static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     714             :                                   struct lsa_SetInfoPolicy *r)
     715             : {
     716             :         /* need to support this */
     717           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
     718             : }
     719             : 
     720             : 
     721             : /*
     722             :   lsa_ClearAuditLog
     723             : */
     724           0 : static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     725             :                                   struct lsa_ClearAuditLog *r)
     726             : {
     727           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
     728             : }
     729             : 
     730             : 
     731             : static const struct generic_mapping dcesrv_lsa_account_mapping = {
     732             :         LSA_ACCOUNT_READ,
     733             :         LSA_ACCOUNT_WRITE,
     734             :         LSA_ACCOUNT_EXECUTE,
     735             :         LSA_ACCOUNT_ALL_ACCESS
     736             : };
     737             : 
     738             : /*
     739             :   lsa_CreateAccount
     740             : 
     741             :   This call does not seem to have any long-term effects, hence no database operations
     742             : 
     743             :   we need to talk to the MS product group to find out what this account database means!
     744             : 
     745             :   answer is that the lsa database is totally separate from the SAM and
     746             :   ldap databases. We are going to need a separate ldb to store these
     747             :   accounts. The SIDs on this account bear no relation to the SIDs in
     748             :   AD
     749             : */
     750           5 : static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     751             :                                   struct lsa_CreateAccount *r)
     752             : {
     753             :         struct lsa_account_state *astate;
     754             : 
     755             :         struct lsa_policy_state *state;
     756             :         struct dcesrv_handle *h, *ah;
     757             : 
     758           5 :         ZERO_STRUCTP(r->out.acct_handle);
     759             : 
     760           5 :         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
     761             : 
     762           5 :         state = h->data;
     763             : 
     764           5 :         astate = talloc(dce_call->conn, struct lsa_account_state);
     765           5 :         if (astate == NULL) {
     766           0 :                 return NT_STATUS_NO_MEMORY;
     767             :         }
     768             : 
     769           5 :         astate->account_sid = dom_sid_dup(astate, r->in.sid);
     770           5 :         if (astate->account_sid == NULL) {
     771           0 :                 talloc_free(astate);
     772           0 :                 return NT_STATUS_NO_MEMORY;
     773             :         }
     774             : 
     775           5 :         astate->policy = talloc_reference(astate, state);
     776           5 :         astate->access_mask = r->in.access_mask;
     777             : 
     778             :         /*
     779             :          * For now we grant all requested access.
     780             :          *
     781             :          * We will fail at the ldb layer later.
     782             :          */
     783           5 :         if (astate->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
     784           5 :                 astate->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
     785           5 :                 astate->access_mask |= LSA_ACCOUNT_ALL_ACCESS;
     786             :         }
     787           5 :         se_map_generic(&astate->access_mask, &dcesrv_lsa_account_mapping);
     788             : 
     789           5 :         DEBUG(10,("%s: %s access desired[0x%08X] granted[0x%08X].\n",
     790             :                   __func__, dom_sid_string(mem_ctx, astate->account_sid),
     791             :                  (unsigned)r->in.access_mask,
     792             :                  (unsigned)astate->access_mask));
     793             : 
     794           5 :         ah = dcesrv_handle_create(dce_call, LSA_HANDLE_ACCOUNT);
     795           5 :         if (!ah) {
     796           0 :                 talloc_free(astate);
     797           0 :                 return NT_STATUS_NO_MEMORY;
     798             :         }
     799             : 
     800           5 :         ah->data = talloc_steal(ah, astate);
     801             : 
     802           5 :         *r->out.acct_handle = ah->wire_handle;
     803             : 
     804           5 :         return NT_STATUS_OK;
     805             : }
     806             : 
     807             : 
     808             : /*
     809             :   lsa_EnumAccounts
     810             : */
     811          28 : static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     812             :                                  struct lsa_EnumAccounts *r)
     813             : {
     814             :         struct dcesrv_handle *h;
     815             :         struct lsa_policy_state *state;
     816             :         int ret;
     817             :         struct ldb_message **res;
     818          28 :         const char * const attrs[] = { "objectSid", NULL};
     819             :         uint32_t count, i;
     820             : 
     821          28 :         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
     822             : 
     823          28 :         state = h->data;
     824             : 
     825             :         /* NOTE: This call must only return accounts that have at least
     826             :            one privilege set
     827             :         */
     828          28 :         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
     829             :                            "(&(objectSid=*)(privilege=*))");
     830          28 :         if (ret < 0) {
     831           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
     832             :         }
     833             : 
     834          28 :         if (*r->in.resume_handle >= ret) {
     835           5 :                 return NT_STATUS_NO_MORE_ENTRIES;
     836             :         }
     837             : 
     838          23 :         count = ret - *r->in.resume_handle;
     839          23 :         if (count > r->in.num_entries) {
     840           0 :                 count = r->in.num_entries;
     841             :         }
     842             : 
     843          23 :         if (count == 0) {
     844           0 :                 return NT_STATUS_NO_MORE_ENTRIES;
     845             :         }
     846             : 
     847          23 :         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
     848          23 :         if (r->out.sids->sids == NULL) {
     849           0 :                 return NT_STATUS_NO_MEMORY;
     850             :         }
     851             : 
     852         173 :         for (i=0;i<count;i++) {
     853         300 :                 r->out.sids->sids[i].sid =
     854         300 :                         samdb_result_dom_sid(r->out.sids->sids,
     855         150 :                                              res[i + *r->in.resume_handle],
     856             :                                              "objectSid");
     857         150 :                 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
     858             :         }
     859             : 
     860          23 :         r->out.sids->num_sids = count;
     861          23 :         *r->out.resume_handle = count + *r->in.resume_handle;
     862             : 
     863          23 :         return NT_STATUS_OK;
     864             : }
     865             : 
     866             : /* This decrypts and returns Trusted Domain Auth Information Internal data */
     867          63 : static NTSTATUS get_trustdom_auth_blob(struct dcesrv_call_state *dce_call,
     868             :                                        TALLOC_CTX *mem_ctx, DATA_BLOB *auth_blob,
     869             :                                        struct trustDomainPasswords *auth_struct)
     870             : {
     871          63 :         DATA_BLOB session_key = data_blob(NULL, 0);
     872             :         enum ndr_err_code ndr_err;
     873             :         NTSTATUS nt_status;
     874          63 :         gnutls_cipher_hd_t cipher_hnd = NULL;
     875             :         gnutls_datum_t _session_key;
     876             :         int rc;
     877          63 :         struct auth_session_info *session_info =
     878             :                 dcesrv_call_session_info(dce_call);
     879          63 :         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
     880             :         bool encrypted;
     881             : 
     882          63 :         encrypted =
     883             :                 dcerpc_is_transport_encrypted(session_info);
     884          63 :         if (lpcfg_weak_crypto(lp_ctx) == SAMBA_WEAK_CRYPTO_DISALLOWED &&
     885           0 :             !encrypted) {
     886           0 :                 DBG_ERR("Transport isn't encrypted and weak crypto disallowed!\n");
     887           0 :                 return NT_STATUS_ACCESS_DENIED;
     888             :         }
     889             : 
     890             : 
     891          63 :         nt_status = dcesrv_transport_session_key(dce_call, &session_key);
     892          63 :         if (!NT_STATUS_IS_OK(nt_status)) {
     893           0 :                 return nt_status;
     894             :         }
     895             : 
     896          63 :         _session_key = (gnutls_datum_t) {
     897          63 :                 .data = session_key.data,
     898          63 :                 .size = session_key.length,
     899             :         };
     900             : 
     901             :         GNUTLS_FIPS140_SET_LAX_MODE();
     902          63 :         rc = gnutls_cipher_init(&cipher_hnd,
     903             :                                 GNUTLS_CIPHER_ARCFOUR_128,
     904             :                                 &_session_key,
     905             :                                 NULL);
     906          63 :         if (rc < 0) {
     907             :                 GNUTLS_FIPS140_SET_STRICT_MODE();
     908           0 :                 nt_status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
     909           0 :                 goto out;
     910             :         }
     911             : 
     912         126 :         rc = gnutls_cipher_decrypt(cipher_hnd,
     913          63 :                                    auth_blob->data,
     914             :                                    auth_blob->length);
     915          63 :         gnutls_cipher_deinit(cipher_hnd);
     916             :         GNUTLS_FIPS140_SET_STRICT_MODE();
     917          63 :         if (rc < 0) {
     918           0 :                 nt_status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
     919           0 :                 goto out;
     920             :         }
     921             : 
     922          63 :         ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
     923             :                                        auth_struct,
     924             :                                        (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
     925          63 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     926           0 :                 return NT_STATUS_INVALID_PARAMETER;
     927             :         }
     928             : 
     929          63 :         nt_status = NT_STATUS_OK;
     930          63 : out:
     931          63 :         return nt_status;
     932             : }
     933             : 
     934         118 : static NTSTATUS get_trustauth_inout_blob(struct dcesrv_call_state *dce_call,
     935             :                                          TALLOC_CTX *mem_ctx,
     936             :                                          struct trustAuthInOutBlob *iopw,
     937             :                                          DATA_BLOB *trustauth_blob)
     938             : {
     939             :         enum ndr_err_code ndr_err;
     940             : 
     941         118 :         if (iopw->current.count != iopw->count) {
     942           0 :                 return NT_STATUS_INVALID_PARAMETER;
     943             :         }
     944             : 
     945         118 :         if (iopw->previous.count > iopw->current.count) {
     946           0 :                 return NT_STATUS_INVALID_PARAMETER;
     947             :         }
     948             : 
     949         118 :         if (iopw->previous.count == 0) {
     950             :                 /*
     951             :                  * If the previous credentials are not present
     952             :                  * we need to make a copy.
     953             :                  */
     954          46 :                 iopw->previous = iopw->current;
     955             :         }
     956             : 
     957         118 :         if (iopw->previous.count < iopw->current.count) {
     958           0 :                 struct AuthenticationInformationArray *c = &iopw->current;
     959           0 :                 struct AuthenticationInformationArray *p = &iopw->previous;
     960             : 
     961             :                 /*
     962             :                  * The previous array needs to have the same size
     963             :                  * as the current one.
     964             :                  *
     965             :                  * We may have to fill with TRUST_AUTH_TYPE_NONE
     966             :                  * elements.
     967             :                  */
     968           0 :                 p->array = talloc_realloc(mem_ctx, p->array,
     969             :                                    struct AuthenticationInformation,
     970             :                                    c->count);
     971           0 :                 if (p->array == NULL) {
     972           0 :                         return NT_STATUS_NO_MEMORY;
     973             :                 }
     974             : 
     975           0 :                 while (p->count < c->count) {
     976           0 :                         struct AuthenticationInformation *a =
     977           0 :                                 &p->array[p->count++];
     978             : 
     979           0 :                         *a = (struct AuthenticationInformation) {
     980           0 :                                 .LastUpdateTime = p->array[0].LastUpdateTime,
     981             :                                 .AuthType = TRUST_AUTH_TYPE_NONE,
     982             :                         };
     983             :                 }
     984             :         }
     985             : 
     986         118 :         ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
     987             :                                        iopw,
     988             :                                        (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
     989         118 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     990           0 :                 return NT_STATUS_INVALID_PARAMETER;
     991             :         }
     992             : 
     993         118 :         return NT_STATUS_OK;
     994             : }
     995             : 
     996          71 : static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
     997             :                                struct ldb_context *sam_ldb,
     998             :                                struct ldb_dn *base_dn,
     999             :                                const char *netbios_name,
    1000             :                                struct trustAuthInOutBlob *in,
    1001             :                                struct ldb_dn **user_dn)
    1002             : {
    1003             :         struct ldb_request *req;
    1004             :         struct ldb_message *msg;
    1005             :         struct ldb_dn *dn;
    1006             :         uint32_t i;
    1007             :         int ret;
    1008             : 
    1009          71 :         dn = ldb_dn_copy(mem_ctx, base_dn);
    1010          71 :         if (!dn) {
    1011           0 :                 return NT_STATUS_NO_MEMORY;
    1012             :         }
    1013          71 :         if (!ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name)) {
    1014           0 :                 return NT_STATUS_NO_MEMORY;
    1015             :         }
    1016             : 
    1017          71 :         msg = ldb_msg_new(mem_ctx);
    1018          71 :         if (!msg) {
    1019           0 :                 return NT_STATUS_NO_MEMORY;
    1020             :         }
    1021          71 :         msg->dn = dn;
    1022             : 
    1023          71 :         ret = ldb_msg_add_string(msg, "objectClass", "user");
    1024          71 :         if (ret != LDB_SUCCESS) {
    1025           0 :                 return NT_STATUS_NO_MEMORY;
    1026             :         }
    1027             : 
    1028          71 :         ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
    1029          71 :         if (ret != LDB_SUCCESS) {
    1030           0 :                 return NT_STATUS_NO_MEMORY;
    1031             :         }
    1032             : 
    1033          71 :         ret = samdb_msg_add_uint(sam_ldb, msg, msg, "userAccountControl",
    1034             :                                  UF_INTERDOMAIN_TRUST_ACCOUNT);
    1035          71 :         if (ret != LDB_SUCCESS) {
    1036           0 :                 return NT_STATUS_NO_MEMORY;
    1037             :         }
    1038             : 
    1039         118 :         for (i = 0; i < in->count; i++) {
    1040             :                 const char *attribute;
    1041             :                 struct ldb_val v;
    1042          47 :                 switch (in->current.array[i].AuthType) {
    1043           0 :                 case TRUST_AUTH_TYPE_NT4OWF:
    1044           0 :                         attribute = "unicodePwd";
    1045           0 :                         v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
    1046           0 :                         v.length = 16;
    1047           0 :                         break;
    1048          47 :                 case TRUST_AUTH_TYPE_CLEAR:
    1049          47 :                         attribute = "clearTextPassword";
    1050          47 :                         v.data = in->current.array[i].AuthInfo.clear.password;
    1051          47 :                         v.length = in->current.array[i].AuthInfo.clear.size;
    1052          47 :                         break;
    1053           0 :                 default:
    1054           0 :                         continue;
    1055             :                 }
    1056             : 
    1057          47 :                 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
    1058          47 :                 if (ret != LDB_SUCCESS) {
    1059           0 :                         return NT_STATUS_NO_MEMORY;
    1060             :                 }
    1061             :         }
    1062             : 
    1063             :         /* create the trusted_domain user account */
    1064          71 :         ret = ldb_build_add_req(&req, sam_ldb, mem_ctx, msg, NULL, NULL,
    1065             :                                 ldb_op_default_callback, NULL);
    1066          71 :         if (ret != LDB_SUCCESS) {
    1067           0 :                 return NT_STATUS_NO_MEMORY;
    1068             :         }
    1069             : 
    1070          71 :         ret = ldb_request_add_control(req, DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID,
    1071             :                                       false, NULL);
    1072          71 :         if (ret != LDB_SUCCESS) {
    1073           0 :                 return NT_STATUS_NO_MEMORY;
    1074             :         }
    1075             : 
    1076          71 :         ret = dsdb_autotransaction_request(sam_ldb, req);
    1077          71 :         if (ret != LDB_SUCCESS) {
    1078           0 :                 DEBUG(0,("Failed to create user record %s: %s\n",
    1079             :                          ldb_dn_get_linearized(msg->dn),
    1080             :                          ldb_errstring(sam_ldb)));
    1081             : 
    1082           0 :                 switch (ret) {
    1083           0 :                 case LDB_ERR_ENTRY_ALREADY_EXISTS:
    1084           0 :                         return NT_STATUS_DOMAIN_EXISTS;
    1085           0 :                 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
    1086           0 :                         return NT_STATUS_ACCESS_DENIED;
    1087           0 :                 default:
    1088           0 :                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
    1089             :                 }
    1090             :         }
    1091             : 
    1092          71 :         if (user_dn) {
    1093          71 :                 *user_dn = dn;
    1094             :         }
    1095          71 :         return NT_STATUS_OK;
    1096             : }
    1097             : 
    1098             : /*
    1099             :   lsa_CreateTrustedDomainEx2
    1100             : */
    1101         135 : static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
    1102             :                                                     TALLOC_CTX *mem_ctx,
    1103             :                                                     struct lsa_CreateTrustedDomainEx2 *r,
    1104             :                                                     int op,
    1105             :                                                     struct lsa_TrustDomainInfoAuthInfo *unencrypted_auth_info)
    1106             : {
    1107             :         struct dcesrv_handle *policy_handle;
    1108             :         struct lsa_policy_state *policy_state;
    1109             :         struct lsa_trusted_domain_state *trusted_domain_state;
    1110             :         struct dcesrv_handle *handle;
    1111             :         struct ldb_message **msgs, *msg;
    1112         135 :         const char *attrs[] = {
    1113             :                 NULL
    1114             :         };
    1115             :         const char *netbios_name;
    1116             :         const char *dns_name;
    1117             :         DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
    1118             :         struct trustDomainPasswords auth_struct;
    1119             :         int ret;
    1120             :         NTSTATUS nt_status;
    1121             :         struct ldb_context *sam_ldb;
    1122         135 :         struct server_id *server_ids = NULL;
    1123         135 :         uint32_t num_server_ids = 0;
    1124             :         NTSTATUS status;
    1125             :         bool ok;
    1126         135 :         char *dns_encoded = NULL;
    1127         135 :         char *netbios_encoded = NULL;
    1128         135 :         char *sid_encoded = NULL;
    1129         135 :         struct imessaging_context *imsg_ctx =
    1130         135 :                 dcesrv_imessaging_context(dce_call->conn);
    1131             : 
    1132         135 :         DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
    1133         135 :         ZERO_STRUCTP(r->out.trustdom_handle);
    1134             : 
    1135         135 :         policy_state = policy_handle->data;
    1136         135 :         sam_ldb = policy_state->sam_ldb;
    1137             : 
    1138         135 :         netbios_name = r->in.info->netbios_name.string;
    1139         135 :         if (!netbios_name) {
    1140           0 :                 return NT_STATUS_INVALID_PARAMETER;
    1141             :         }
    1142             : 
    1143         135 :         dns_name = r->in.info->domain_name.string;
    1144         135 :         if (dns_name == NULL) {
    1145           0 :                 return NT_STATUS_INVALID_PARAMETER;
    1146             :         }
    1147             : 
    1148         135 :         if (r->in.info->sid == NULL) {
    1149           0 :                 return NT_STATUS_INVALID_SID;
    1150             :         }
    1151             : 
    1152             :         /*
    1153             :          * We expect S-1-5-21-A-B-C, but we don't
    1154             :          * allow S-1-5-21-0-0-0 as this is used
    1155             :          * for claims and compound identities.
    1156             :          */
    1157         135 :         ok = dom_sid_is_valid_account_domain(r->in.info->sid);
    1158         135 :         if (!ok) {
    1159           0 :                 return NT_STATUS_INVALID_PARAMETER;
    1160             :         }
    1161             : 
    1162         135 :         dns_encoded = ldb_binary_encode_string(mem_ctx, dns_name);
    1163         135 :         if (dns_encoded == NULL) {
    1164           0 :                 return NT_STATUS_NO_MEMORY;
    1165             :         }
    1166         135 :         netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
    1167         135 :         if (netbios_encoded == NULL) {
    1168           0 :                 return NT_STATUS_NO_MEMORY;
    1169             :         }
    1170         135 :         sid_encoded = ldap_encode_ndr_dom_sid(mem_ctx, r->in.info->sid);
    1171         135 :         if (sid_encoded == NULL) {
    1172           0 :                 return NT_STATUS_NO_MEMORY;
    1173             :         }
    1174             : 
    1175         135 :         trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
    1176         135 :         if (!trusted_domain_state) {
    1177           0 :                 return NT_STATUS_NO_MEMORY;
    1178             :         }
    1179         135 :         trusted_domain_state->policy = policy_state;
    1180             : 
    1181         135 :         if (strcasecmp(netbios_name, "BUILTIN") == 0
    1182         135 :             || (strcasecmp(dns_name, "BUILTIN") == 0)
    1183         135 :             || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
    1184           0 :                 return NT_STATUS_INVALID_PARAMETER;
    1185             :         }
    1186             : 
    1187         135 :         if (strcasecmp(netbios_name, policy_state->domain_name) == 0
    1188         135 :             || strcasecmp(netbios_name, policy_state->domain_dns) == 0
    1189         135 :             || strcasecmp(dns_name, policy_state->domain_dns) == 0
    1190         135 :             || strcasecmp(dns_name, policy_state->domain_name) == 0
    1191         135 :             || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
    1192           0 :                 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
    1193             :         }
    1194             : 
    1195             :         /* While this is a REF pointer, some of the functions that wrap this don't provide this */
    1196         135 :         if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
    1197             :                 /* No secrets are created at this time, for this function */
    1198          36 :                 auth_struct.outgoing.count = 0;
    1199          36 :                 auth_struct.incoming.count = 0;
    1200          99 :         } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX2) {
    1201          63 :                 auth_blob = data_blob_const(r->in.auth_info_internal->auth_blob.data,
    1202          63 :                                             r->in.auth_info_internal->auth_blob.size);
    1203          63 :                 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
    1204             :                                                    &auth_blob, &auth_struct);
    1205          63 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    1206           0 :                         return nt_status;
    1207             :                 }
    1208          36 :         } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
    1209             : 
    1210          36 :                 if (unencrypted_auth_info->incoming_count > 1) {
    1211           0 :                         return NT_STATUS_INVALID_PARAMETER;
    1212             :                 }
    1213             : 
    1214             :                 /* more investigation required here, do not create secrets for
    1215             :                  * now */
    1216          36 :                 auth_struct.outgoing.count = 0;
    1217          36 :                 auth_struct.incoming.count = 0;
    1218             :         } else {
    1219           0 :                 return NT_STATUS_INVALID_PARAMETER;
    1220             :         }
    1221             : 
    1222         135 :         if (auth_struct.incoming.count) {
    1223          59 :                 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
    1224             :                                                      &auth_struct.incoming,
    1225             :                                                      &trustAuthIncoming);
    1226          59 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    1227           0 :                         return nt_status;
    1228             :                 }
    1229             :         } else {
    1230          76 :                 trustAuthIncoming = data_blob(NULL, 0);
    1231             :         }
    1232             : 
    1233         135 :         if (auth_struct.outgoing.count) {
    1234          59 :                 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
    1235             :                                                      &auth_struct.outgoing,
    1236             :                                                      &trustAuthOutgoing);
    1237          59 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    1238           0 :                         return nt_status;
    1239             :                 }
    1240             :         } else {
    1241          76 :                 trustAuthOutgoing = data_blob(NULL, 0);
    1242             :         }
    1243             : 
    1244         135 :         ret = ldb_transaction_start(sam_ldb);
    1245         135 :         if (ret != LDB_SUCCESS) {
    1246           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    1247             :         }
    1248             : 
    1249             :         /* search for the trusted_domain record */
    1250         135 :         ret = gendb_search(sam_ldb,
    1251             :                            mem_ctx, policy_state->system_dn, &msgs, attrs,
    1252             :                            "(&(objectClass=trustedDomain)(|"
    1253             :                              "(flatname=%s)(trustPartner=%s)"
    1254             :                              "(flatname=%s)(trustPartner=%s)"
    1255             :                              "(securityIdentifier=%s)))",
    1256             :                            dns_encoded, dns_encoded,
    1257             :                            netbios_encoded, netbios_encoded,
    1258             :                            sid_encoded);
    1259         135 :         if (ret > 0) {
    1260           0 :                 ldb_transaction_cancel(sam_ldb);
    1261           0 :                 return NT_STATUS_OBJECT_NAME_COLLISION;
    1262             :         }
    1263         135 :         if (ret < 0) {
    1264           0 :                 ldb_transaction_cancel(sam_ldb);
    1265           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    1266             :         }
    1267             : 
    1268         135 :         msg = ldb_msg_new(mem_ctx);
    1269         135 :         if (msg == NULL) {
    1270           0 :                 return NT_STATUS_NO_MEMORY;
    1271             :         }
    1272             : 
    1273         135 :         msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
    1274         135 :         if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", dns_name)) {
    1275           0 :                         ldb_transaction_cancel(sam_ldb);
    1276           0 :                 return NT_STATUS_NO_MEMORY;
    1277             :         }
    1278             : 
    1279         135 :         ret = ldb_msg_add_string(msg, "objectClass", "trustedDomain");
    1280         135 :         if (ret != LDB_SUCCESS) {
    1281           0 :                 ldb_transaction_cancel(sam_ldb);
    1282           0 :                 return NT_STATUS_NO_MEMORY;;
    1283             :         }
    1284             : 
    1285         135 :         ret = ldb_msg_add_string(msg, "flatname", netbios_name);
    1286         135 :         if (ret != LDB_SUCCESS) {
    1287           0 :                 ldb_transaction_cancel(sam_ldb);
    1288           0 :                 return NT_STATUS_NO_MEMORY;
    1289             :         }
    1290             : 
    1291         135 :         ret = ldb_msg_add_string(msg, "trustPartner", dns_name);
    1292         135 :         if (ret != LDB_SUCCESS) {
    1293           0 :                 ldb_transaction_cancel(sam_ldb);
    1294           0 :                 return NT_STATUS_NO_MEMORY;;
    1295             :         }
    1296             : 
    1297         135 :         ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier",
    1298         135 :                                     r->in.info->sid);
    1299         135 :         if (ret != LDB_SUCCESS) {
    1300           0 :                 ldb_transaction_cancel(sam_ldb);
    1301           0 :                 return NT_STATUS_NO_MEMORY;;
    1302             :         }
    1303             : 
    1304         135 :         ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
    1305         135 :         if (ret != LDB_SUCCESS) {
    1306           0 :                 ldb_transaction_cancel(sam_ldb);
    1307           0 :                 return NT_STATUS_NO_MEMORY;;
    1308             :         }
    1309             : 
    1310         135 :         ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
    1311         135 :         if (ret != LDB_SUCCESS) {
    1312           0 :                 ldb_transaction_cancel(sam_ldb);
    1313           0 :                 return NT_STATUS_NO_MEMORY;;
    1314             :         }
    1315             : 
    1316         135 :         ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
    1317         135 :         if (ret != LDB_SUCCESS) {
    1318           0 :                 ldb_transaction_cancel(sam_ldb);
    1319           0 :                 return NT_STATUS_NO_MEMORY;;
    1320             :         }
    1321             : 
    1322         135 :         if (trustAuthIncoming.data) {
    1323          59 :                 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
    1324          59 :                 if (ret != LDB_SUCCESS) {
    1325           0 :                         ldb_transaction_cancel(sam_ldb);
    1326           0 :                         return NT_STATUS_NO_MEMORY;
    1327             :                 }
    1328             :         }
    1329         135 :         if (trustAuthOutgoing.data) {
    1330          59 :                 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
    1331          59 :                 if (ret != LDB_SUCCESS) {
    1332           0 :                         ldb_transaction_cancel(sam_ldb);
    1333           0 :                         return NT_STATUS_NO_MEMORY;
    1334             :                 }
    1335             :         }
    1336             : 
    1337         135 :         trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
    1338             : 
    1339             :         /* create the trusted_domain */
    1340         135 :         ret = ldb_add(sam_ldb, msg);
    1341         135 :         switch (ret) {
    1342         135 :         case  LDB_SUCCESS:
    1343         135 :                 break;
    1344           0 :         case  LDB_ERR_ENTRY_ALREADY_EXISTS:
    1345           0 :                 ldb_transaction_cancel(sam_ldb);
    1346           0 :                 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
    1347             :                          ldb_dn_get_linearized(msg->dn),
    1348             :                          ldb_errstring(sam_ldb)));
    1349           0 :                 return NT_STATUS_DOMAIN_EXISTS;
    1350           0 :         case  LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
    1351           0 :                 ldb_transaction_cancel(sam_ldb);
    1352           0 :                 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
    1353             :                          ldb_dn_get_linearized(msg->dn),
    1354             :                          ldb_errstring(sam_ldb)));
    1355           0 :                 return NT_STATUS_ACCESS_DENIED;
    1356           0 :         default:
    1357           0 :                 ldb_transaction_cancel(sam_ldb);
    1358           0 :                 DEBUG(0,("Failed to create user record %s: %s\n",
    1359             :                          ldb_dn_get_linearized(msg->dn),
    1360             :                          ldb_errstring(sam_ldb)));
    1361           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    1362             :         }
    1363             : 
    1364         135 :         if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
    1365             :                 struct ldb_dn *user_dn;
    1366             :                 /* Inbound trusts must also create a cn=users object to match */
    1367          71 :                 nt_status = add_trust_user(mem_ctx, sam_ldb,
    1368             :                                            policy_state->domain_dn,
    1369             :                                            netbios_name,
    1370             :                                            &auth_struct.incoming,
    1371             :                                            &user_dn);
    1372          71 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    1373           0 :                         ldb_transaction_cancel(sam_ldb);
    1374           0 :                         return nt_status;
    1375             :                 }
    1376             : 
    1377             :                 /* save the trust user dn */
    1378             :                 trusted_domain_state->trusted_domain_user_dn
    1379          71 :                         = talloc_steal(trusted_domain_state, user_dn);
    1380             :         }
    1381             : 
    1382         135 :         ret = ldb_transaction_commit(sam_ldb);
    1383         135 :         if (ret != LDB_SUCCESS) {
    1384           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    1385             :         }
    1386             : 
    1387             :         /*
    1388             :          * Notify winbindd that we have a new trust
    1389             :          */
    1390         135 :         status = irpc_servers_byname(imsg_ctx,
    1391             :                                      mem_ctx,
    1392             :                                      "winbind_server",
    1393             :                                      &num_server_ids,
    1394             :                                      &server_ids);
    1395         135 :         if (NT_STATUS_IS_OK(status) && num_server_ids >= 1) {
    1396         135 :                 imessaging_send(imsg_ctx,
    1397             :                                 server_ids[0],
    1398             :                                 MSG_WINBIND_RELOAD_TRUSTED_DOMAINS,
    1399             :                                 NULL);
    1400             :         }
    1401         135 :         TALLOC_FREE(server_ids);
    1402             : 
    1403         135 :         handle = dcesrv_handle_create(dce_call, LSA_HANDLE_TRUSTED_DOMAIN);
    1404         135 :         if (!handle) {
    1405           0 :                 return NT_STATUS_NO_MEMORY;
    1406             :         }
    1407             : 
    1408         135 :         handle->data = talloc_steal(handle, trusted_domain_state);
    1409             : 
    1410         135 :         trusted_domain_state->access_mask = r->in.access_mask;
    1411         135 :         trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
    1412             : 
    1413         135 :         *r->out.trustdom_handle = handle->wire_handle;
    1414             : 
    1415         135 :         return NT_STATUS_OK;
    1416             : }
    1417             : 
    1418             : /*
    1419             :   lsa_CreateTrustedDomainEx2
    1420             : */
    1421          63 : static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
    1422             :                                            TALLOC_CTX *mem_ctx,
    1423             :                                            struct lsa_CreateTrustedDomainEx2 *r)
    1424             : {
    1425          63 :         return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2, NULL);
    1426             : }
    1427             : /*
    1428             :   lsa_CreateTrustedDomainEx
    1429             : */
    1430          36 : static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
    1431             :                                           TALLOC_CTX *mem_ctx,
    1432             :                                           struct lsa_CreateTrustedDomainEx *r)
    1433             : {
    1434             :         struct lsa_CreateTrustedDomainEx2 r2;
    1435             : 
    1436          36 :         r2.in.policy_handle = r->in.policy_handle;
    1437          36 :         r2.in.info = r->in.info;
    1438          36 :         r2.out.trustdom_handle = r->out.trustdom_handle;
    1439          36 :         return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX, r->in.auth_info);
    1440             : }
    1441             : 
    1442             : /*
    1443             :   lsa_CreateTrustedDomain
    1444             : */
    1445          36 : static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    1446             :                                         struct lsa_CreateTrustedDomain *r)
    1447             : {
    1448             :         struct lsa_CreateTrustedDomainEx2 r2;
    1449             : 
    1450          36 :         r2.in.policy_handle = r->in.policy_handle;
    1451          36 :         r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
    1452          36 :         if (!r2.in.info) {
    1453           0 :                 return NT_STATUS_NO_MEMORY;
    1454             :         }
    1455             : 
    1456          36 :         r2.in.info->domain_name = r->in.info->name;
    1457          36 :         r2.in.info->netbios_name = r->in.info->name;
    1458          36 :         r2.in.info->sid = r->in.info->sid;
    1459          36 :         r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
    1460          36 :         r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
    1461          36 :         r2.in.info->trust_attributes = 0;
    1462             : 
    1463          36 :         r2.in.access_mask = r->in.access_mask;
    1464          36 :         r2.out.trustdom_handle = r->out.trustdom_handle;
    1465             : 
    1466          36 :         return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN, NULL);
    1467             : }
    1468             : 
    1469        3399 : static NTSTATUS dcesrv_lsa_OpenTrustedDomain_common(
    1470             :                                         struct dcesrv_call_state *dce_call,
    1471             :                                         TALLOC_CTX *tmp_mem,
    1472             :                                         struct lsa_policy_state *policy_state,
    1473             :                                         const char *filter,
    1474             :                                         uint32_t access_mask,
    1475             :                                         struct dcesrv_handle **_handle)
    1476             : {
    1477             :         struct lsa_trusted_domain_state *trusted_domain_state;
    1478             :         struct dcesrv_handle *handle;
    1479             :         struct ldb_message **msgs;
    1480        3399 :         const char *attrs[] = {
    1481             :                 "trustDirection",
    1482             :                 "flatname",
    1483             :                 NULL
    1484             :         };
    1485             :         uint32_t direction;
    1486             :         int ret;
    1487             : 
    1488             :         /* TODO: perform access checks */
    1489             : 
    1490             :         /* search for the trusted_domain record */
    1491        3399 :         ret = gendb_search(policy_state->sam_ldb, tmp_mem,
    1492             :                            policy_state->system_dn,
    1493             :                            &msgs, attrs, "%s", filter);
    1494        3399 :         if (ret == 0) {
    1495          55 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    1496             :         }
    1497             : 
    1498        3344 :         if (ret != 1) {
    1499           0 :                 DEBUG(0,("Found %d records matching %s under %s\n", ret,
    1500             :                          filter,
    1501             :                          ldb_dn_get_linearized(policy_state->system_dn)));
    1502           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    1503             :         }
    1504             : 
    1505        3344 :         trusted_domain_state = talloc_zero(tmp_mem,
    1506             :                                            struct lsa_trusted_domain_state);
    1507        3344 :         if (!trusted_domain_state) {
    1508           0 :                 return NT_STATUS_NO_MEMORY;
    1509             :         }
    1510        3344 :         trusted_domain_state->policy = policy_state;
    1511             : 
    1512        3344 :         trusted_domain_state->trusted_domain_dn =
    1513        3344 :                 talloc_steal(trusted_domain_state, msgs[0]->dn);
    1514             : 
    1515        3344 :         direction = ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0);
    1516        3344 :         if (direction & LSA_TRUST_DIRECTION_INBOUND) {
    1517        1576 :                 const char *flatname = ldb_msg_find_attr_as_string(msgs[0],
    1518             :                                                         "flatname", NULL);
    1519             : 
    1520             :                 /* search for the trusted_domain account */
    1521        1576 :                 ret = gendb_search(policy_state->sam_ldb, tmp_mem,
    1522             :                                    policy_state->domain_dn,
    1523             :                                    &msgs, attrs,
    1524             :                                    "(&(samaccountname=%s$)(objectclass=user)"
    1525             :                                    "(userAccountControl:%s:=%u))",
    1526             :                                    flatname,
    1527             :                                    LDB_OID_COMPARATOR_AND,
    1528             :                                    UF_INTERDOMAIN_TRUST_ACCOUNT);
    1529        1576 :                 if (ret == 1) {
    1530        1576 :                         trusted_domain_state->trusted_domain_user_dn =
    1531        1576 :                                 talloc_steal(trusted_domain_state, msgs[0]->dn);
    1532             :                 }
    1533             :         }
    1534             : 
    1535        3344 :         handle = dcesrv_handle_create(dce_call, LSA_HANDLE_TRUSTED_DOMAIN);
    1536        3344 :         if (!handle) {
    1537           0 :                 return NT_STATUS_NO_MEMORY;
    1538             :         }
    1539             : 
    1540        3344 :         handle->data = talloc_steal(handle, trusted_domain_state);
    1541             : 
    1542        3344 :         trusted_domain_state->access_mask = access_mask;
    1543        3344 :         trusted_domain_state->policy = talloc_reference(trusted_domain_state,
    1544             :                                                         policy_state);
    1545             : 
    1546        3344 :         *_handle = handle;
    1547             : 
    1548        3344 :         return NT_STATUS_OK;
    1549             : }
    1550             : 
    1551             : /*
    1552             :   lsa_OpenTrustedDomain
    1553             : */
    1554        1624 : static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    1555             :                                       struct lsa_OpenTrustedDomain *r)
    1556             : {
    1557             :         struct dcesrv_handle *policy_handle;
    1558             :         struct lsa_policy_state *policy_state;
    1559             :         struct dcesrv_handle *handle;
    1560             :         const char *sid_string;
    1561             :         char *filter;
    1562             :         NTSTATUS status;
    1563             : 
    1564        1624 :         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
    1565        1624 :         ZERO_STRUCTP(r->out.trustdom_handle);
    1566        1624 :         policy_state = policy_handle->data;
    1567             : 
    1568        1624 :         sid_string = dom_sid_string(mem_ctx, r->in.sid);
    1569        1624 :         if (!sid_string) {
    1570           0 :                 return NT_STATUS_NO_MEMORY;
    1571             :         }
    1572             : 
    1573        1624 :         filter = talloc_asprintf(mem_ctx,
    1574             :                                  "(&(securityIdentifier=%s)"
    1575             :                                  "(objectclass=trustedDomain))",
    1576             :                                  sid_string);
    1577        1624 :         if (filter == NULL) {
    1578           0 :                 return NT_STATUS_NO_MEMORY;
    1579             :         }
    1580             : 
    1581        1624 :         status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
    1582             :                                                      policy_state,
    1583             :                                                      filter,
    1584             :                                                      r->in.access_mask,
    1585             :                                                      &handle);
    1586        1624 :         if (!NT_STATUS_IS_OK(status)) {
    1587           1 :                 return status;
    1588             :         }
    1589             : 
    1590        1623 :         *r->out.trustdom_handle = handle->wire_handle;
    1591             : 
    1592        1623 :         return NT_STATUS_OK;
    1593             : }
    1594             : 
    1595             : 
    1596             : /*
    1597             :   lsa_OpenTrustedDomainByName
    1598             : */
    1599        1775 : static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
    1600             :                                             TALLOC_CTX *mem_ctx,
    1601             :                                             struct lsa_OpenTrustedDomainByName *r)
    1602             : {
    1603             :         struct dcesrv_handle *policy_handle;
    1604             :         struct lsa_policy_state *policy_state;
    1605             :         struct dcesrv_handle *handle;
    1606             :         char *td_name;
    1607             :         char *filter;
    1608             :         NTSTATUS status;
    1609             : 
    1610        1775 :         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
    1611        1775 :         ZERO_STRUCTP(r->out.trustdom_handle);
    1612        1775 :         policy_state = policy_handle->data;
    1613             : 
    1614        1775 :         if (!r->in.name.string) {
    1615           0 :                 return NT_STATUS_INVALID_PARAMETER;
    1616             :         }
    1617             : 
    1618             :         /* search for the trusted_domain record */
    1619        1775 :         td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
    1620        1775 :         if (td_name == NULL) {
    1621           0 :                 return NT_STATUS_NO_MEMORY;
    1622             :         }
    1623             : 
    1624        1775 :         filter = talloc_asprintf(mem_ctx,
    1625             :                            "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
    1626             :                              "(objectclass=trustedDomain))",
    1627             :                            td_name, td_name, td_name);
    1628        1775 :         if (filter == NULL) {
    1629           0 :                 return NT_STATUS_NO_MEMORY;
    1630             :         }
    1631             : 
    1632        1775 :         status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
    1633             :                                                      policy_state,
    1634             :                                                      filter,
    1635             :                                                      r->in.access_mask,
    1636             :                                                      &handle);
    1637        1775 :         if (!NT_STATUS_IS_OK(status)) {
    1638          54 :                 return status;
    1639             :         }
    1640             : 
    1641        1721 :         *r->out.trustdom_handle = handle->wire_handle;
    1642             : 
    1643        1721 :         return NT_STATUS_OK;
    1644             : }
    1645             : 
    1646             : 
    1647             : 
    1648             : /*
    1649             :   lsa_SetTrustedDomainInfo
    1650             : */
    1651           0 : static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    1652             :                                          struct lsa_SetTrustedDomainInfo *r)
    1653             : {
    1654           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    1655             : }
    1656             : 
    1657             : 
    1658             : 
    1659             : /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
    1660             :  * otherwise at least one must be provided */
    1661          30 : static NTSTATUS get_tdo(struct ldb_context *sam, TALLOC_CTX *mem_ctx,
    1662             :                         struct ldb_dn *basedn, const char *dns_domain,
    1663             :                         const char *netbios, struct dom_sid2 *sid,
    1664             :                         struct ldb_message ***msgs)
    1665             : {
    1666          30 :         const char *attrs[] = { "flatname", "trustPartner",
    1667             :                                 "securityIdentifier", "trustDirection",
    1668             :                                 "trustType", "trustAttributes",
    1669             :                                 "trustPosixOffset",
    1670             :                                 "msDs-supportedEncryptionTypes",
    1671             :                                 "msDS-TrustForestTrustInfo",
    1672             :                                 NULL
    1673             :         };
    1674          30 :         char *dns = NULL;
    1675          30 :         char *nbn = NULL;
    1676          30 :         char *sidstr = NULL;
    1677             :         char *filter;
    1678             :         int ret;
    1679             : 
    1680             : 
    1681          30 :         if (dns_domain || netbios || sid) {
    1682          24 :                 filter = talloc_strdup(mem_ctx,
    1683             :                                    "(&(objectclass=trustedDomain)(|");
    1684             :         } else {
    1685           6 :                 filter = talloc_strdup(mem_ctx,
    1686             :                                        "(objectclass=trustedDomain)");
    1687             :         }
    1688          30 :         if (!filter) {
    1689           0 :                 return NT_STATUS_NO_MEMORY;
    1690             :         }
    1691             : 
    1692          30 :         if (dns_domain) {
    1693          24 :                 dns = ldb_binary_encode_string(mem_ctx, dns_domain);
    1694          24 :                 if (!dns) {
    1695           0 :                         return NT_STATUS_NO_MEMORY;
    1696             :                 }
    1697          24 :                 filter = talloc_asprintf_append(filter,
    1698             :                                                 "(trustPartner=%s)", dns);
    1699          24 :                 if (!filter) {
    1700           0 :                         return NT_STATUS_NO_MEMORY;
    1701             :                 }
    1702             :         }
    1703          30 :         if (netbios) {
    1704          24 :                 nbn = ldb_binary_encode_string(mem_ctx, netbios);
    1705          24 :                 if (!nbn) {
    1706           0 :                         return NT_STATUS_NO_MEMORY;
    1707             :                 }
    1708          24 :                 filter = talloc_asprintf_append(filter,
    1709             :                                                 "(flatname=%s)", nbn);
    1710          24 :                 if (!filter) {
    1711           0 :                         return NT_STATUS_NO_MEMORY;
    1712             :                 }
    1713             :         }
    1714          30 :         if (sid) {
    1715           6 :                 sidstr = dom_sid_string(mem_ctx, sid);
    1716           6 :                 if (!sidstr) {
    1717           0 :                         return NT_STATUS_INVALID_PARAMETER;
    1718             :                 }
    1719           6 :                 filter = talloc_asprintf_append(filter,
    1720             :                                                 "(securityIdentifier=%s)",
    1721             :                                                 sidstr);
    1722           6 :                 if (!filter) {
    1723           0 :                         return NT_STATUS_NO_MEMORY;
    1724             :                 }
    1725             :         }
    1726          30 :         if (dns_domain || netbios || sid) {
    1727          24 :                 filter = talloc_asprintf_append(filter, "))");
    1728          24 :                 if (!filter) {
    1729           0 :                         return NT_STATUS_NO_MEMORY;
    1730             :                 }
    1731             :         }
    1732             : 
    1733          30 :         ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
    1734          30 :         if (ret == 0) {
    1735           0 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    1736             :         }
    1737             : 
    1738          30 :         if (ret != 1) {
    1739           0 :                 return NT_STATUS_OBJECT_NAME_COLLISION;
    1740             :         }
    1741             : 
    1742          30 :         return NT_STATUS_OK;
    1743             : }
    1744             : 
    1745          27 : static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
    1746             :                                       struct ldb_context *sam_ldb,
    1747             :                                       struct ldb_message *orig,
    1748             :                                       struct ldb_message *dest,
    1749             :                                       const char *attribute,
    1750             :                                       uint32_t value,
    1751             :                                       uint32_t *orig_value)
    1752             : {
    1753             :         const struct ldb_val *orig_val;
    1754          27 :         uint32_t orig_uint = 0;
    1755          27 :         unsigned int flags = 0;
    1756             :         int ret;
    1757          27 :         int error = 0;
    1758             : 
    1759          27 :         orig_val = ldb_msg_find_ldb_val(orig, attribute);
    1760          27 :         if (!orig_val || !orig_val->data) {
    1761             :                 /* add new attribute */
    1762          12 :                 flags = LDB_FLAG_MOD_ADD;
    1763             : 
    1764             :         } else {
    1765          15 :                 orig_uint = smb_strtoul((const char *)orig_val->data,
    1766             :                                         NULL,
    1767             :                                         0,
    1768             :                                         &error,
    1769             :                                         SMB_STR_STANDARD);
    1770          15 :                 if (error != 0 || orig_uint != value) {
    1771             :                         /* replace also if can't get value */
    1772           0 :                         flags = LDB_FLAG_MOD_REPLACE;
    1773             :                 }
    1774             :         }
    1775             : 
    1776          27 :         if (flags == 0) {
    1777             :                 /* stored value is identical, nothing to change */
    1778          15 :                 goto done;
    1779             :         }
    1780             : 
    1781          12 :         ret = ldb_msg_add_empty(dest, attribute, flags, NULL);
    1782          12 :         if (ret != LDB_SUCCESS) {
    1783           0 :                 return NT_STATUS_NO_MEMORY;
    1784             :         }
    1785             : 
    1786          12 :         ret = samdb_msg_add_uint(sam_ldb, dest, dest, attribute, value);
    1787          12 :         if (ret != LDB_SUCCESS) {
    1788           0 :                 return NT_STATUS_NO_MEMORY;
    1789             :         }
    1790             : 
    1791          12 : done:
    1792          27 :         if (orig_value) {
    1793          12 :                 *orig_value = orig_uint;
    1794             :         }
    1795          27 :         return NT_STATUS_OK;
    1796             : }
    1797             : 
    1798           0 : static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
    1799             :                                   struct ldb_context *sam_ldb,
    1800             :                                   struct ldb_dn *base_dn,
    1801             :                                   bool delete_user,
    1802             :                                   const char *netbios_name,
    1803             :                                   struct trustAuthInOutBlob *in)
    1804             : {
    1805           0 :         const char *attrs[] = { "userAccountControl", NULL };
    1806             :         struct ldb_message **msgs;
    1807             :         struct ldb_message *msg;
    1808             :         uint32_t uac;
    1809             :         uint32_t i;
    1810             :         int ret;
    1811             : 
    1812           0 :         ret = gendb_search(sam_ldb, mem_ctx,
    1813             :                            base_dn, &msgs, attrs,
    1814             :                            "samAccountName=%s$", netbios_name);
    1815           0 :         if (ret > 1) {
    1816           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    1817             :         }
    1818             : 
    1819           0 :         if (ret == 0) {
    1820           0 :                 if (delete_user) {
    1821           0 :                         return NT_STATUS_OK;
    1822             :                 }
    1823             : 
    1824             :                 /* ok no existing user, add it from scratch */
    1825           0 :                 return add_trust_user(mem_ctx, sam_ldb, base_dn,
    1826             :                                       netbios_name, in, NULL);
    1827             :         }
    1828             : 
    1829             :         /* check user is what we are looking for */
    1830           0 :         uac = ldb_msg_find_attr_as_uint(msgs[0],
    1831             :                                         "userAccountControl", 0);
    1832           0 :         if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
    1833           0 :                 return NT_STATUS_OBJECT_NAME_COLLISION;
    1834             :         }
    1835             : 
    1836           0 :         if (delete_user) {
    1837           0 :                 ret = ldb_delete(sam_ldb, msgs[0]->dn);
    1838           0 :                 switch (ret) {
    1839           0 :                 case LDB_SUCCESS:
    1840           0 :                         return NT_STATUS_OK;
    1841           0 :                 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
    1842           0 :                         return NT_STATUS_ACCESS_DENIED;
    1843           0 :                 default:
    1844           0 :                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
    1845             :                 }
    1846             :         }
    1847             : 
    1848             :         /* entry exists, just modify secret if any */
    1849           0 :         if (in == NULL || in->count == 0) {
    1850           0 :                 return NT_STATUS_OK;
    1851             :         }
    1852             : 
    1853           0 :         msg = ldb_msg_new(mem_ctx);
    1854           0 :         if (!msg) {
    1855           0 :                 return NT_STATUS_NO_MEMORY;
    1856             :         }
    1857           0 :         msg->dn = msgs[0]->dn;
    1858             : 
    1859           0 :         for (i = 0; i < in->count; i++) {
    1860             :                 const char *attribute;
    1861             :                 struct ldb_val v;
    1862           0 :                 switch (in->current.array[i].AuthType) {
    1863           0 :                 case TRUST_AUTH_TYPE_NT4OWF:
    1864           0 :                         attribute = "unicodePwd";
    1865           0 :                         v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
    1866           0 :                         v.length = 16;
    1867           0 :                         break;
    1868           0 :                 case TRUST_AUTH_TYPE_CLEAR:
    1869           0 :                         attribute = "clearTextPassword";
    1870           0 :                         v.data = in->current.array[i].AuthInfo.clear.password;
    1871           0 :                         v.length = in->current.array[i].AuthInfo.clear.size;
    1872           0 :                         break;
    1873           0 :                 default:
    1874           0 :                         continue;
    1875             :                 }
    1876             : 
    1877           0 :                 ret = ldb_msg_add_empty(msg, attribute,
    1878             :                                         LDB_FLAG_MOD_REPLACE, NULL);
    1879           0 :                 if (ret != LDB_SUCCESS) {
    1880           0 :                         return NT_STATUS_NO_MEMORY;
    1881             :                 }
    1882             : 
    1883           0 :                 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
    1884           0 :                 if (ret != LDB_SUCCESS) {
    1885           0 :                         return NT_STATUS_NO_MEMORY;
    1886             :                 }
    1887             :         }
    1888             : 
    1889             :         /* create the trusted_domain user account */
    1890           0 :         ret = ldb_modify(sam_ldb, msg);
    1891           0 :         if (ret != LDB_SUCCESS) {
    1892           0 :                 DEBUG(0,("Failed to create user record %s: %s\n",
    1893             :                          ldb_dn_get_linearized(msg->dn),
    1894             :                          ldb_errstring(sam_ldb)));
    1895             : 
    1896           0 :                 switch (ret) {
    1897           0 :                 case LDB_ERR_ENTRY_ALREADY_EXISTS:
    1898           0 :                         return NT_STATUS_DOMAIN_EXISTS;
    1899           0 :                 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
    1900           0 :                         return NT_STATUS_ACCESS_DENIED;
    1901           0 :                 default:
    1902           0 :                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
    1903             :                 }
    1904             :         }
    1905             : 
    1906           0 :         return NT_STATUS_OK;
    1907             : }
    1908             : 
    1909             : 
    1910          24 : static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
    1911             :                                           struct lsa_policy_state *p_state,
    1912             :                                           TALLOC_CTX *mem_ctx,
    1913             :                                           struct ldb_message *dom_msg,
    1914             :                                           enum lsa_TrustDomInfoEnum level,
    1915             :                                           union lsa_TrustedDomainInfo *info)
    1916             : {
    1917          24 :         uint32_t *posix_offset = NULL;
    1918          24 :         struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
    1919          24 :         struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
    1920          24 :         struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
    1921          24 :         uint32_t *enc_types = NULL;
    1922             :         DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
    1923             :         struct trustDomainPasswords auth_struct;
    1924          24 :         struct trustAuthInOutBlob *current_passwords = NULL;
    1925             :         NTSTATUS nt_status;
    1926             :         struct ldb_message **msgs;
    1927             :         struct ldb_message *msg;
    1928          24 :         bool add_outgoing = false;
    1929          24 :         bool add_incoming = false;
    1930          24 :         bool del_outgoing = false;
    1931          24 :         bool del_incoming = false;
    1932          24 :         bool del_forest_info = false;
    1933          24 :         bool in_transaction = false;
    1934             :         int ret;
    1935             :         bool am_rodc;
    1936             : 
    1937          24 :         switch (level) {
    1938           3 :         case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
    1939           3 :                 posix_offset = &info->posix_offset.posix_offset;
    1940           3 :                 break;
    1941           3 :         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
    1942           3 :                 info_ex = &info->info_ex;
    1943           3 :                 break;
    1944           0 :         case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
    1945           0 :                 auth_info = &info->auth_info;
    1946           0 :                 break;
    1947           3 :         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
    1948           3 :                 posix_offset = &info->full_info.posix_offset.posix_offset;
    1949           3 :                 info_ex = &info->full_info.info_ex;
    1950           3 :                 auth_info = &info->full_info.auth_info;
    1951           3 :                 break;
    1952           0 :         case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
    1953           0 :                 auth_info_int = &info->auth_info_internal;
    1954           0 :                 break;
    1955           0 :         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
    1956           0 :                 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
    1957           0 :                 info_ex = &info->full_info_internal.info_ex;
    1958           0 :                 auth_info_int = &info->full_info_internal.auth_info;
    1959           0 :                 break;
    1960           9 :         case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
    1961           9 :                 enc_types = &info->enc_types.enc_types;
    1962           9 :                 break;
    1963           6 :         default:
    1964           6 :                 return NT_STATUS_INVALID_PARAMETER;
    1965             :         }
    1966             : 
    1967          18 :         if (auth_info) {
    1968           3 :                 nt_status = auth_info_2_auth_blob(mem_ctx, auth_info,
    1969             :                                                   &trustAuthIncoming,
    1970             :                                                   &trustAuthOutgoing);
    1971           3 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    1972           0 :                         return nt_status;
    1973             :                 }
    1974           3 :                 if (trustAuthIncoming.data) {
    1975             :                         /* This does the decode of some of this twice, but it is easier that way */
    1976           0 :                         nt_status = auth_info_2_trustauth_inout(mem_ctx,
    1977             :                                                                 auth_info->incoming_count,
    1978             :                                                                 auth_info->incoming_current_auth_info,
    1979             :                                                                 NULL,
    1980             :                                                                 &current_passwords);
    1981           0 :                         if (!NT_STATUS_IS_OK(nt_status)) {
    1982           0 :                                 return nt_status;
    1983             :                         }
    1984             :                 }
    1985             :         }
    1986             : 
    1987             :         /* decode auth_info_int if set */
    1988          18 :         if (auth_info_int) {
    1989             : 
    1990             :                 /* now decrypt blob */
    1991           0 :                 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
    1992           0 :                                             auth_info_int->auth_blob.size);
    1993             : 
    1994           0 :                 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
    1995             :                                                    &auth_blob, &auth_struct);
    1996           0 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    1997           0 :                         return nt_status;
    1998             :                 }
    1999             :         }
    2000             : 
    2001          18 :         if (info_ex) {
    2002             :                 /* verify data matches */
    2003           6 :                 if (info_ex->trust_attributes &
    2004             :                     LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
    2005             :                         /* TODO: check what behavior level we have */
    2006           6 :                        if (strcasecmp_m(p_state->domain_dns,
    2007             :                                         p_state->forest_dns) != 0) {
    2008           0 :                                 return NT_STATUS_INVALID_DOMAIN_STATE;
    2009             :                         }
    2010             :                 }
    2011             : 
    2012           6 :                 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
    2013           6 :                 if (ret == LDB_SUCCESS && am_rodc) {
    2014           0 :                         return NT_STATUS_NO_SUCH_DOMAIN;
    2015             :                 }
    2016             : 
    2017             :                 /* verify only one object matches the dns/netbios/sid
    2018             :                  * triplet and that this is the one we already have */
    2019           6 :                 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
    2020             :                                     p_state->system_dn,
    2021             :                                     info_ex->domain_name.string,
    2022             :                                     info_ex->netbios_name.string,
    2023             :                                     info_ex->sid, &msgs);
    2024           6 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    2025           0 :                         return nt_status;
    2026             :                 }
    2027           6 :                 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
    2028           0 :                         return NT_STATUS_OBJECT_NAME_COLLISION;
    2029             :                 }
    2030           6 :                 talloc_free(msgs);
    2031             :         }
    2032             : 
    2033             :         /* TODO: should we fetch previous values from the existing entry
    2034             :          * and append them ? */
    2035          18 :         if (auth_info_int && auth_struct.incoming.count) {
    2036           0 :                 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
    2037             :                                                      &auth_struct.incoming,
    2038             :                                                      &trustAuthIncoming);
    2039           0 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    2040           0 :                         return nt_status;
    2041             :                 }
    2042             : 
    2043           0 :                 current_passwords = &auth_struct.incoming;
    2044             : 
    2045             :         } else {
    2046          18 :                 trustAuthIncoming = data_blob(NULL, 0);
    2047             :         }
    2048             : 
    2049          18 :         if (auth_info_int && auth_struct.outgoing.count) {
    2050           0 :                 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
    2051             :                                                      &auth_struct.outgoing,
    2052             :                                                      &trustAuthOutgoing);
    2053           0 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    2054           0 :                         return nt_status;
    2055             :                 }
    2056             :         } else {
    2057          18 :                 trustAuthOutgoing = data_blob(NULL, 0);
    2058             :         }
    2059             : 
    2060          18 :         msg = ldb_msg_new(mem_ctx);
    2061          18 :         if (msg == NULL) {
    2062           0 :                 return NT_STATUS_NO_MEMORY;
    2063             :         }
    2064          18 :         msg->dn = dom_msg->dn;
    2065             : 
    2066          18 :         if (posix_offset) {
    2067           6 :                 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
    2068             :                                                   dom_msg, msg,
    2069             :                                                   "trustPosixOffset",
    2070             :                                                   *posix_offset, NULL);
    2071           6 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    2072           0 :                         return nt_status;
    2073             :                 }
    2074             :         }
    2075             : 
    2076          18 :         if (info_ex) {
    2077             :                 uint32_t origattrs;
    2078             :                 uint32_t changed_attrs;
    2079             :                 uint32_t origdir;
    2080             :                 int origtype;
    2081             : 
    2082           6 :                 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
    2083             :                                                   dom_msg, msg,
    2084             :                                                   "trustDirection",
    2085             :                                                   info_ex->trust_direction,
    2086             :                                                   &origdir);
    2087           6 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    2088           0 :                         return nt_status;
    2089             :                 }
    2090             : 
    2091           6 :                 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
    2092           6 :                         if (auth_info != NULL && trustAuthIncoming.length > 0) {
    2093           0 :                                 add_incoming = true;
    2094             :                         }
    2095             :                 }
    2096           6 :                 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
    2097           6 :                         if (auth_info != NULL && trustAuthOutgoing.length > 0) {
    2098           0 :                                 add_outgoing = true;
    2099             :                         }
    2100             :                 }
    2101             : 
    2102          12 :                 if ((origdir & LSA_TRUST_DIRECTION_INBOUND) &&
    2103           6 :                     !(info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
    2104           0 :                         del_incoming = true;
    2105             :                 }
    2106          12 :                 if ((origdir & LSA_TRUST_DIRECTION_OUTBOUND) &&
    2107           6 :                     !(info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
    2108           0 :                         del_outgoing = true;
    2109             :                 }
    2110             : 
    2111           6 :                 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
    2112           6 :                 if (origtype == -1 || origtype != info_ex->trust_type) {
    2113           0 :                         DEBUG(1, ("Attempted to change trust type! "
    2114             :                                   "Operation not handled\n"));
    2115           0 :                         return NT_STATUS_INVALID_PARAMETER;
    2116             :                 }
    2117             : 
    2118           6 :                 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
    2119             :                                                   dom_msg, msg,
    2120             :                                                   "trustAttributes",
    2121             :                                                   info_ex->trust_attributes,
    2122             :                                                   &origattrs);
    2123           6 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    2124           0 :                         return nt_status;
    2125             :                 }
    2126             :                 /* TODO: check forestFunctionality from ldb opaque */
    2127             :                 /* TODO: check what is set makes sense */
    2128             : 
    2129           6 :                 changed_attrs = origattrs ^ info_ex->trust_attributes;
    2130           6 :                 if (changed_attrs & ~LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
    2131             :                         /*
    2132             :                          * For now we only allow
    2133             :                          * LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE to be changed.
    2134             :                          *
    2135             :                          * TODO: we may need to support more attribute changes
    2136             :                          */
    2137           0 :                         DEBUG(1, ("Attempted to change trust attributes "
    2138             :                                   "(0x%08x != 0x%08x)! "
    2139             :                                   "Operation not handled yet...\n",
    2140             :                                   (unsigned)origattrs,
    2141             :                                   (unsigned)info_ex->trust_attributes));
    2142           0 :                         return NT_STATUS_INVALID_PARAMETER;
    2143             :                 }
    2144             : 
    2145           6 :                 if (!(info_ex->trust_attributes &
    2146             :                       LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE))
    2147             :                 {
    2148           0 :                         struct ldb_message_element *orig_forest_el = NULL;
    2149             : 
    2150           0 :                         orig_forest_el = ldb_msg_find_element(dom_msg,
    2151             :                                                 "msDS-TrustForestTrustInfo");
    2152           0 :                         if (orig_forest_el != NULL) {
    2153           0 :                                 del_forest_info = true;
    2154             :                         }
    2155             :                 }
    2156             :         }
    2157             : 
    2158          18 :         if (enc_types) {
    2159           9 :                 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
    2160             :                                                   dom_msg, msg,
    2161             :                                                   "msDS-SupportedEncryptionTypes",
    2162             :                                                   *enc_types, NULL);
    2163           9 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    2164           0 :                         return nt_status;
    2165             :                 }
    2166             :         }
    2167             : 
    2168          18 :         if (add_incoming || del_incoming) {
    2169           0 :                 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
    2170             :                                         LDB_FLAG_MOD_REPLACE, NULL);
    2171           0 :                 if (ret != LDB_SUCCESS) {
    2172           0 :                         return NT_STATUS_NO_MEMORY;
    2173             :                 }
    2174           0 :                 if (add_incoming) {
    2175           0 :                         ret = ldb_msg_add_value(msg, "trustAuthIncoming",
    2176             :                                                 &trustAuthIncoming, NULL);
    2177           0 :                         if (ret != LDB_SUCCESS) {
    2178           0 :                                 return NT_STATUS_NO_MEMORY;
    2179             :                         }
    2180             :                 }
    2181             :         }
    2182          18 :         if (add_outgoing || del_outgoing) {
    2183           0 :                 ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
    2184             :                                         LDB_FLAG_MOD_REPLACE, NULL);
    2185           0 :                 if (ret != LDB_SUCCESS) {
    2186           0 :                         return NT_STATUS_NO_MEMORY;
    2187             :                 }
    2188           0 :                 if (add_outgoing) {
    2189           0 :                         ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
    2190             :                                                 &trustAuthOutgoing, NULL);
    2191           0 :                         if (ret != LDB_SUCCESS) {
    2192           0 :                                 return NT_STATUS_NO_MEMORY;
    2193             :                         }
    2194             :                 }
    2195             :         }
    2196          18 :         if (del_forest_info) {
    2197           0 :                 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
    2198             :                                         LDB_FLAG_MOD_REPLACE, NULL);
    2199           0 :                 if (ret != LDB_SUCCESS) {
    2200           0 :                         return NT_STATUS_NO_MEMORY;
    2201             :                 }
    2202             :         }
    2203             : 
    2204             :         /* start transaction */
    2205          18 :         ret = ldb_transaction_start(p_state->sam_ldb);
    2206          18 :         if (ret != LDB_SUCCESS) {
    2207           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    2208             :         }
    2209          18 :         in_transaction = true;
    2210             : 
    2211          18 :         if (msg->num_elements) {
    2212          12 :                 ret = ldb_modify(p_state->sam_ldb, msg);
    2213          12 :                 if (ret != LDB_SUCCESS) {
    2214           0 :                         DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
    2215             :                                  ldb_dn_get_linearized(msg->dn),
    2216             :                                  ldb_errstring(p_state->sam_ldb)));
    2217           0 :                         nt_status = dsdb_ldb_err_to_ntstatus(ret);
    2218           0 :                         goto done;
    2219             :                 }
    2220             :         }
    2221             : 
    2222          18 :         if (add_incoming || del_incoming) {
    2223             :                 const char *netbios_name;
    2224             : 
    2225           0 :                 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
    2226             :                                                            "flatname", NULL);
    2227           0 :                 if (!netbios_name) {
    2228           0 :                         nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
    2229           0 :                         goto done;
    2230             :                 }
    2231             : 
    2232             :                 /* We use trustAuthIncoming.data to incidate that auth_struct.incoming is valid */
    2233           0 :                 nt_status = update_trust_user(mem_ctx,
    2234             :                                               p_state->sam_ldb,
    2235             :                                               p_state->domain_dn,
    2236             :                                               del_incoming,
    2237             :                                               netbios_name,
    2238             :                                               current_passwords);
    2239           0 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    2240           0 :                         goto done;
    2241             :                 }
    2242             :         }
    2243             : 
    2244             :         /* ok, all fine, commit transaction and return */
    2245          18 :         ret = ldb_transaction_commit(p_state->sam_ldb);
    2246          18 :         if (ret != LDB_SUCCESS) {
    2247           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    2248             :         }
    2249          18 :         in_transaction = false;
    2250             : 
    2251          18 :         nt_status = NT_STATUS_OK;
    2252             : 
    2253          18 : done:
    2254          18 :         if (in_transaction) {
    2255           0 :                 ldb_transaction_cancel(p_state->sam_ldb);
    2256             :         }
    2257          18 :         return nt_status;
    2258             : }
    2259             : 
    2260             : /*
    2261             :   lsa_SetInfomrationTrustedDomain
    2262             : */
    2263           6 : static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
    2264             :                                 struct dcesrv_call_state *dce_call,
    2265             :                                 TALLOC_CTX *mem_ctx,
    2266             :                                 struct lsa_SetInformationTrustedDomain *r)
    2267             : {
    2268             :         struct dcesrv_handle *h;
    2269             :         struct lsa_trusted_domain_state *td_state;
    2270             :         struct ldb_message **msgs;
    2271             :         NTSTATUS nt_status;
    2272             : 
    2273           6 :         DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
    2274             :                            LSA_HANDLE_TRUSTED_DOMAIN);
    2275             : 
    2276           6 :         td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
    2277             : 
    2278             :         /* get the trusted domain object */
    2279           6 :         nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
    2280             :                             td_state->trusted_domain_dn,
    2281             :                             NULL, NULL, NULL, &msgs);
    2282           6 :         if (!NT_STATUS_IS_OK(nt_status)) {
    2283           0 :                 if (NT_STATUS_EQUAL(nt_status,
    2284             :                                     NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
    2285           0 :                         return nt_status;
    2286             :                 }
    2287           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    2288             :         }
    2289             : 
    2290           6 :         return setInfoTrustedDomain_base(dce_call, td_state->policy, mem_ctx,
    2291             :                                          msgs[0], r->in.level, r->in.info);
    2292             : }
    2293             : 
    2294             : 
    2295             : /*
    2296             :   lsa_DeleteTrustedDomain
    2297             : */
    2298         111 : static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    2299             :                                       struct lsa_DeleteTrustedDomain *r)
    2300             : {
    2301             :         NTSTATUS status;
    2302         111 :         struct lsa_OpenTrustedDomain opn = {{0},{0}};
    2303             :         struct lsa_DeleteObject del;
    2304             :         struct dcesrv_handle *h;
    2305             : 
    2306         111 :         opn.in.handle = r->in.handle;
    2307         111 :         opn.in.sid = r->in.dom_sid;
    2308         111 :         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
    2309         111 :         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
    2310         111 :         if (!opn.out.trustdom_handle) {
    2311           0 :                 return NT_STATUS_NO_MEMORY;
    2312             :         }
    2313         111 :         status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
    2314         111 :         if (!NT_STATUS_IS_OK(status)) {
    2315           0 :                 return status;
    2316             :         }
    2317             : 
    2318         111 :         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
    2319         111 :         talloc_steal(mem_ctx, h);
    2320             : 
    2321         111 :         del.in.handle = opn.out.trustdom_handle;
    2322         111 :         del.out.handle = opn.out.trustdom_handle;
    2323         111 :         status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
    2324         111 :         if (!NT_STATUS_IS_OK(status)) {
    2325           0 :                 return status;
    2326             :         }
    2327         111 :         return NT_STATUS_OK;
    2328             : }
    2329             : 
    2330        2011 : static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
    2331             :                                      struct ldb_message *msg,
    2332             :                                      struct lsa_TrustDomainInfoInfoEx *info_ex)
    2333             : {
    2334             :         info_ex->domain_name.string
    2335        2011 :                 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
    2336             :         info_ex->netbios_name.string
    2337        2011 :                 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
    2338             :         info_ex->sid
    2339        2011 :                 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
    2340             :         info_ex->trust_direction
    2341        2011 :                 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
    2342             :         info_ex->trust_type
    2343        2011 :                 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
    2344             :         info_ex->trust_attributes
    2345        2011 :                 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
    2346        2011 :         return NT_STATUS_OK;
    2347             : }
    2348             : 
    2349             : /*
    2350             :   lsa_QueryTrustedDomainInfo
    2351             : */
    2352        5936 : static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    2353             :                                            struct lsa_QueryTrustedDomainInfo *r)
    2354             : {
    2355        5936 :         union lsa_TrustedDomainInfo *info = NULL;
    2356             :         struct dcesrv_handle *h;
    2357             :         struct lsa_trusted_domain_state *trusted_domain_state;
    2358             :         struct ldb_message *msg;
    2359             :         int ret;
    2360             :         struct ldb_message **res;
    2361        5936 :         const char *attrs[] = {
    2362             :                 "flatname",
    2363             :                 "trustPartner",
    2364             :                 "securityIdentifier",
    2365             :                 "trustDirection",
    2366             :                 "trustType",
    2367             :                 "trustAttributes",
    2368             :                 "msDs-supportedEncryptionTypes",
    2369             :                 NULL
    2370             :         };
    2371             : 
    2372        5936 :         DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
    2373             : 
    2374        5936 :         trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
    2375             : 
    2376             :         /* pull all the user attributes */
    2377        5936 :         ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
    2378             :                               trusted_domain_state->trusted_domain_dn, &res, attrs);
    2379        5936 :         if (ret != 1) {
    2380           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    2381             :         }
    2382        5936 :         msg = res[0];
    2383             : 
    2384        5936 :         info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
    2385        5936 :         if (!info) {
    2386           0 :                 return NT_STATUS_NO_MEMORY;
    2387             :         }
    2388        5936 :         *r->out.info = info;
    2389             : 
    2390        5936 :         switch (r->in.level) {
    2391         435 :         case LSA_TRUSTED_DOMAIN_INFO_NAME:
    2392             :                 info->name.netbios_name.string
    2393         435 :                         = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
    2394         435 :                 break;
    2395         435 :         case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
    2396             :                 info->posix_offset.posix_offset
    2397         435 :                         = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
    2398         435 :                 break;
    2399             : #if 0  /* Win2k3 doesn't implement this */
    2400             :         case LSA_TRUSTED_DOMAIN_INFO_BASIC:
    2401             :                 r->out.info->info_basic.netbios_name.string
    2402             :                         = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
    2403             :                 r->out.info->info_basic.sid
    2404             :                         = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
    2405             :                 break;
    2406             : #endif
    2407         681 :         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
    2408         681 :                 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
    2409             : 
    2410         463 :         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
    2411         463 :                 ZERO_STRUCT(info->full_info);
    2412         463 :                 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
    2413         435 :         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
    2414         435 :                 ZERO_STRUCT(info->full_info2_internal);
    2415             :                 info->full_info2_internal.posix_offset.posix_offset
    2416         435 :                         = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
    2417         435 :                 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
    2418             : 
    2419         463 :         case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
    2420             :                 info->enc_types.enc_types
    2421         463 :                         = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
    2422         463 :                 break;
    2423             : 
    2424         864 :         case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
    2425             :         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
    2426             :                 /* oops, we don't want to return the info after all */
    2427         864 :                 talloc_free(info);
    2428         864 :                 *r->out.info = NULL;
    2429         864 :                 return NT_STATUS_INVALID_PARAMETER;
    2430        2160 :         default:
    2431             :                 /* oops, we don't want to return the info after all */
    2432        2160 :                 talloc_free(info);
    2433        2160 :                 *r->out.info = NULL;
    2434        2160 :                 return NT_STATUS_INVALID_INFO_CLASS;
    2435             :         }
    2436             : 
    2437        1333 :         return NT_STATUS_OK;
    2438             : }
    2439             : 
    2440             : 
    2441             : /*
    2442             :   lsa_QueryTrustedDomainInfoBySid
    2443             : */
    2444        1405 : static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    2445             :                                                 struct lsa_QueryTrustedDomainInfoBySid *r)
    2446             : {
    2447             :         NTSTATUS status;
    2448        1405 :         struct lsa_OpenTrustedDomain opn = {{0},{0}};
    2449             :         struct lsa_QueryTrustedDomainInfo query;
    2450             :         struct dcesrv_handle *h;
    2451             : 
    2452        1405 :         opn.in.handle = r->in.handle;
    2453        1405 :         opn.in.sid = r->in.dom_sid;
    2454        1405 :         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
    2455        1405 :         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
    2456        1405 :         if (!opn.out.trustdom_handle) {
    2457           0 :                 return NT_STATUS_NO_MEMORY;
    2458             :         }
    2459        1405 :         status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
    2460        1405 :         if (!NT_STATUS_IS_OK(status)) {
    2461           1 :                 return status;
    2462             :         }
    2463             : 
    2464             :         /* Ensure this handle goes away at the end of this call */
    2465        1404 :         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
    2466        1404 :         talloc_steal(mem_ctx, h);
    2467             : 
    2468        1404 :         query.in.trustdom_handle = opn.out.trustdom_handle;
    2469        1404 :         query.in.level = r->in.level;
    2470        1404 :         query.out.info = r->out.info;
    2471        1404 :         status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
    2472        1404 :         if (!NT_STATUS_IS_OK(status)) {
    2473         756 :                 return status;
    2474             :         }
    2475             : 
    2476         648 :         return NT_STATUS_OK;
    2477             : }
    2478             : 
    2479             : /*
    2480             :   lsa_SetTrustedDomainInfoByName
    2481             : */
    2482          18 : static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
    2483             :                                                TALLOC_CTX *mem_ctx,
    2484             :                                                struct lsa_SetTrustedDomainInfoByName *r)
    2485             : {
    2486             :         struct dcesrv_handle *policy_handle;
    2487             :         struct lsa_policy_state *policy_state;
    2488             :         struct ldb_message **msgs;
    2489             :         NTSTATUS nt_status;
    2490             : 
    2491          18 :         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
    2492          18 :         policy_state = policy_handle->data;
    2493             : 
    2494             :         /* get the trusted domain object */
    2495          36 :         nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
    2496             :                             policy_state->domain_dn,
    2497          18 :                             r->in.trusted_domain->string,
    2498          18 :                             r->in.trusted_domain->string,
    2499             :                             NULL, &msgs);
    2500          18 :         if (!NT_STATUS_IS_OK(nt_status)) {
    2501           0 :                 if (NT_STATUS_EQUAL(nt_status,
    2502             :                                     NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
    2503           0 :                         return nt_status;
    2504             :                 }
    2505           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    2506             :         }
    2507             : 
    2508          18 :         return setInfoTrustedDomain_base(dce_call, policy_state, mem_ctx,
    2509             :                                          msgs[0], r->in.level, r->in.info);
    2510             : }
    2511             : 
    2512             : /*
    2513             :    lsa_QueryTrustedDomainInfoByName
    2514             : */
    2515        1667 : static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
    2516             :                                                  TALLOC_CTX *mem_ctx,
    2517             :                                                  struct lsa_QueryTrustedDomainInfoByName *r)
    2518             : {
    2519             :         NTSTATUS status;
    2520        1667 :         struct lsa_OpenTrustedDomainByName opn = {{0},{0}};
    2521             :         struct lsa_QueryTrustedDomainInfo query;
    2522             :         struct dcesrv_handle *h;
    2523             : 
    2524        1667 :         opn.in.handle = r->in.handle;
    2525        1667 :         opn.in.name = *r->in.trusted_domain;
    2526        1667 :         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
    2527        1667 :         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
    2528        1667 :         if (!opn.out.trustdom_handle) {
    2529           0 :                 return NT_STATUS_NO_MEMORY;
    2530             :         }
    2531        1667 :         status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
    2532        1667 :         if (!NT_STATUS_IS_OK(status)) {
    2533          54 :                 return status;
    2534             :         }
    2535             : 
    2536             :         /* Ensure this handle goes away at the end of this call */
    2537        1613 :         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
    2538        1613 :         talloc_steal(mem_ctx, h);
    2539             : 
    2540        1613 :         query.in.trustdom_handle = opn.out.trustdom_handle;
    2541        1613 :         query.in.level = r->in.level;
    2542        1613 :         query.out.info = r->out.info;
    2543        1613 :         status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
    2544        1613 :         if (!NT_STATUS_IS_OK(status)) {
    2545         756 :                 return status;
    2546             :         }
    2547             : 
    2548         857 :         return NT_STATUS_OK;
    2549             : }
    2550             : 
    2551             : /*
    2552             :   lsa_CloseTrustedDomainEx
    2553             : */
    2554         108 : static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
    2555             :                                          TALLOC_CTX *mem_ctx,
    2556             :                                          struct lsa_CloseTrustedDomainEx *r)
    2557             : {
    2558             :         /* The result of a bad hair day from an IDL programmer?  Not
    2559             :          * implmented in Win2k3.  You should always just lsa_Close
    2560             :          * anyway. */
    2561         108 :         return NT_STATUS_NOT_IMPLEMENTED;
    2562             : }
    2563             : 
    2564             : 
    2565             : /*
    2566             :   comparison function for sorting lsa_DomainInformation array
    2567             : */
    2568        1148 : static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
    2569             : {
    2570        1148 :         return strcasecmp_m(e1->name.string, e2->name.string);
    2571             : }
    2572             : 
    2573             : /*
    2574             :   lsa_EnumTrustDom
    2575             : */
    2576          66 : static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    2577             :                                  struct lsa_EnumTrustDom *r)
    2578             : {
    2579             :         struct dcesrv_handle *policy_handle;
    2580             :         struct lsa_DomainInfo *entries;
    2581             :         struct lsa_policy_state *policy_state;
    2582             :         struct ldb_message **domains;
    2583          66 :         const char *attrs[] = {
    2584             :                 "flatname",
    2585             :                 "securityIdentifier",
    2586             :                 NULL
    2587             :         };
    2588             : 
    2589             : 
    2590             :         int count, i;
    2591             : 
    2592          66 :         *r->out.resume_handle = 0;
    2593             : 
    2594          66 :         r->out.domains->domains = NULL;
    2595          66 :         r->out.domains->count = 0;
    2596             : 
    2597          66 :         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
    2598             : 
    2599          66 :         policy_state = policy_handle->data;
    2600             : 
    2601             :         /* search for all users in this domain. This could possibly be cached and
    2602             :            resumed based on resume_key */
    2603          66 :         count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
    2604             :                              "objectclass=trustedDomain");
    2605          66 :         if (count < 0) {
    2606           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    2607             :         }
    2608             : 
    2609             :         /* convert to lsa_TrustInformation format */
    2610          66 :         entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
    2611          66 :         if (!entries) {
    2612           0 :                 return NT_STATUS_NO_MEMORY;
    2613             :         }
    2614         495 :         for (i=0;i<count;i++) {
    2615         432 :                 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
    2616         432 :                 entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
    2617             :         }
    2618             : 
    2619             :         /* sort the results by name */
    2620          66 :         TYPESAFE_QSORT(entries, count, compare_DomainInfo);
    2621             : 
    2622          66 :         if (*r->in.resume_handle >= count) {
    2623          30 :                 *r->out.resume_handle = -1;
    2624             : 
    2625          30 :                 return NT_STATUS_NO_MORE_ENTRIES;
    2626             :         }
    2627             : 
    2628             :         /* return the rest, limit by max_size. Note that we
    2629             :            use the w2k3 element size value of 60 */
    2630          36 :         r->out.domains->count = count - *r->in.resume_handle;
    2631          36 :         r->out.domains->count = MIN(r->out.domains->count,
    2632             :                                  1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
    2633             : 
    2634          36 :         r->out.domains->domains = entries + *r->in.resume_handle;
    2635             : 
    2636          36 :         if (r->out.domains->count < count - *r->in.resume_handle) {
    2637          27 :                 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
    2638          27 :                 return STATUS_MORE_ENTRIES;
    2639             :         }
    2640             : 
    2641             :         /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
    2642             :          * always be larger than the previous input resume handle, in
    2643             :          * particular when hitting the last query it is vital to set the
    2644             :          * resume handle correctly to avoid infinite client loops, as
    2645             :          * seen e.g. with Windows XP SP3 when resume handle is 0 and
    2646             :          * status is NT_STATUS_OK - gd */
    2647             : 
    2648           9 :         *r->out.resume_handle = (uint32_t)-1;
    2649             : 
    2650           9 :         return NT_STATUS_OK;
    2651             : }
    2652             : 
    2653             : /*
    2654             :   comparison function for sorting lsa_DomainInformation array
    2655             : */
    2656        1148 : static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
    2657             : {
    2658        1148 :         return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
    2659             : }
    2660             : 
    2661             : /*
    2662             :   lsa_EnumTrustedDomainsEx
    2663             : */
    2664          42 : static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    2665             :                                         struct lsa_EnumTrustedDomainsEx *r)
    2666             : {
    2667             :         struct dcesrv_handle *policy_handle;
    2668             :         struct lsa_TrustDomainInfoInfoEx *entries;
    2669             :         struct lsa_policy_state *policy_state;
    2670             :         struct ldb_message **domains;
    2671          42 :         const char *attrs[] = {
    2672             :                 "flatname",
    2673             :                 "trustPartner",
    2674             :                 "securityIdentifier",
    2675             :                 "trustDirection",
    2676             :                 "trustType",
    2677             :                 "trustAttributes",
    2678             :                 NULL
    2679             :         };
    2680             :         NTSTATUS nt_status;
    2681             : 
    2682             :         int count, i;
    2683             : 
    2684          42 :         *r->out.resume_handle = 0;
    2685             : 
    2686          42 :         r->out.domains->domains = NULL;
    2687          42 :         r->out.domains->count = 0;
    2688             : 
    2689          42 :         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
    2690             : 
    2691          42 :         policy_state = policy_handle->data;
    2692             : 
    2693             :         /* search for all users in this domain. This could possibly be cached and
    2694             :            resumed based on resume_key */
    2695          42 :         count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
    2696             :                              "objectclass=trustedDomain");
    2697          42 :         if (count < 0) {
    2698           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    2699             :         }
    2700             : 
    2701             :         /* convert to lsa_DomainInformation format */
    2702          42 :         entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
    2703          42 :         if (!entries) {
    2704           0 :                 return NT_STATUS_NO_MEMORY;
    2705             :         }
    2706         474 :         for (i=0;i<count;i++) {
    2707         432 :                 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
    2708         432 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    2709           0 :                         return nt_status;
    2710             :                 }
    2711             :         }
    2712             : 
    2713             :         /* sort the results by name */
    2714          42 :         TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
    2715             : 
    2716          42 :         if (*r->in.resume_handle >= count) {
    2717           6 :                 *r->out.resume_handle = -1;
    2718             : 
    2719           6 :                 return NT_STATUS_NO_MORE_ENTRIES;
    2720             :         }
    2721             : 
    2722             :         /* return the rest, limit by max_size. Note that we
    2723             :            use the w2k3 element size value of 60 */
    2724          36 :         r->out.domains->count = count - *r->in.resume_handle;
    2725          36 :         r->out.domains->count = MIN(r->out.domains->count,
    2726             :                                  1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
    2727             : 
    2728          36 :         r->out.domains->domains = entries + *r->in.resume_handle;
    2729             : 
    2730          36 :         if (r->out.domains->count < count - *r->in.resume_handle) {
    2731          27 :                 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
    2732          27 :                 return STATUS_MORE_ENTRIES;
    2733             :         }
    2734             : 
    2735           9 :         *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
    2736             : 
    2737           9 :         return NT_STATUS_OK;
    2738             : }
    2739             : 
    2740             : 
    2741             : /*
    2742             :   lsa_OpenAccount
    2743             : */
    2744          42 : static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    2745             :                                 struct lsa_OpenAccount *r)
    2746             : {
    2747             :         struct dcesrv_handle *h, *ah;
    2748             :         struct lsa_policy_state *state;
    2749             :         struct lsa_account_state *astate;
    2750             : 
    2751          42 :         ZERO_STRUCTP(r->out.acct_handle);
    2752             : 
    2753          42 :         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
    2754             : 
    2755          42 :         state = h->data;
    2756             : 
    2757          42 :         astate = talloc(dce_call->conn, struct lsa_account_state);
    2758          42 :         if (astate == NULL) {
    2759           0 :                 return NT_STATUS_NO_MEMORY;
    2760             :         }
    2761             : 
    2762          42 :         astate->account_sid = dom_sid_dup(astate, r->in.sid);
    2763          42 :         if (astate->account_sid == NULL) {
    2764           0 :                 talloc_free(astate);
    2765           0 :                 return NT_STATUS_NO_MEMORY;
    2766             :         }
    2767             : 
    2768          42 :         astate->policy = talloc_reference(astate, state);
    2769          42 :         astate->access_mask = r->in.access_mask;
    2770             : 
    2771             :         /*
    2772             :          * For now we grant all requested access.
    2773             :          *
    2774             :          * We will fail at the ldb layer later.
    2775             :          */
    2776          42 :         if (astate->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
    2777          42 :                 astate->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
    2778          42 :                 astate->access_mask |= LSA_ACCOUNT_ALL_ACCESS;
    2779             :         }
    2780          42 :         se_map_generic(&astate->access_mask, &dcesrv_lsa_account_mapping);
    2781             : 
    2782          42 :         DEBUG(10,("%s: %s access desired[0x%08X] granted[0x%08X] - success.\n",
    2783             :                   __func__, dom_sid_string(mem_ctx, astate->account_sid),
    2784             :                  (unsigned)r->in.access_mask,
    2785             :                  (unsigned)astate->access_mask));
    2786             : 
    2787          42 :         ah = dcesrv_handle_create(dce_call, LSA_HANDLE_ACCOUNT);
    2788          42 :         if (!ah) {
    2789           0 :                 talloc_free(astate);
    2790           0 :                 return NT_STATUS_NO_MEMORY;
    2791             :         }
    2792             : 
    2793          42 :         ah->data = talloc_steal(ah, astate);
    2794             : 
    2795          42 :         *r->out.acct_handle = ah->wire_handle;
    2796             : 
    2797          42 :         return NT_STATUS_OK;
    2798             : }
    2799             : 
    2800             : 
    2801             : /*
    2802             :   lsa_EnumPrivsAccount
    2803             : */
    2804          30 : static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
    2805             :                                      TALLOC_CTX *mem_ctx,
    2806             :                                      struct lsa_EnumPrivsAccount *r)
    2807             : {
    2808             :         struct dcesrv_handle *h;
    2809             :         struct lsa_account_state *astate;
    2810             :         int ret;
    2811             :         unsigned int i, j;
    2812             :         struct ldb_message **res;
    2813          30 :         const char * const attrs[] = { "privilege", NULL};
    2814             :         struct ldb_message_element *el;
    2815             :         const char *sidstr;
    2816             :         struct lsa_PrivilegeSet *privs;
    2817             : 
    2818          30 :         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
    2819             : 
    2820          30 :         astate = h->data;
    2821             : 
    2822          30 :         privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
    2823          30 :         if (privs == NULL) {
    2824           0 :                 return NT_STATUS_NO_MEMORY;
    2825             :         }
    2826          30 :         privs->count = 0;
    2827          30 :         privs->unknown = 0;
    2828          30 :         privs->set = NULL;
    2829             : 
    2830          30 :         *r->out.privs = privs;
    2831             : 
    2832          30 :         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
    2833          30 :         if (sidstr == NULL) {
    2834           0 :                 return NT_STATUS_NO_MEMORY;
    2835             :         }
    2836             : 
    2837          30 :         ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
    2838             :                            "objectSid=%s", sidstr);
    2839          30 :         if (ret < 0) {
    2840           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    2841             :         }
    2842          30 :         if (ret != 1) {
    2843           0 :                 return NT_STATUS_OK;
    2844             :         }
    2845             : 
    2846          30 :         el = ldb_msg_find_element(res[0], "privilege");
    2847          30 :         if (el == NULL || el->num_values == 0) {
    2848           0 :                 return NT_STATUS_OK;
    2849             :         }
    2850             : 
    2851          30 :         privs->set = talloc_array(privs,
    2852             :                                   struct lsa_LUIDAttribute, el->num_values);
    2853          30 :         if (privs->set == NULL) {
    2854           0 :                 return NT_STATUS_NO_MEMORY;
    2855             :         }
    2856             : 
    2857          30 :         j = 0;
    2858         230 :         for (i=0;i<el->num_values;i++) {
    2859         200 :                 int id = sec_privilege_id((const char *)el->values[i].data);
    2860         200 :                 if (id == SEC_PRIV_INVALID) {
    2861             :                         /* Perhaps an account right, not a privilege */
    2862          40 :                         continue;
    2863             :                 }
    2864         160 :                 privs->set[j].attribute = 0;
    2865         160 :                 privs->set[j].luid.low = id;
    2866         160 :                 privs->set[j].luid.high = 0;
    2867         160 :                 j++;
    2868             :         }
    2869             : 
    2870          30 :         privs->count = j;
    2871             : 
    2872          30 :         return NT_STATUS_OK;
    2873             : }
    2874             : 
    2875             : /*
    2876             :   lsa_EnumAccountRights
    2877             : */
    2878         116 : static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
    2879             :                                       TALLOC_CTX *mem_ctx,
    2880             :                                       struct lsa_EnumAccountRights *r)
    2881             : {
    2882             :         struct dcesrv_handle *h;
    2883             :         struct lsa_policy_state *state;
    2884             :         int ret;
    2885             :         unsigned int i;
    2886             :         struct ldb_message **res;
    2887         116 :         const char * const attrs[] = { "privilege", NULL};
    2888             :         const char *sidstr;
    2889             :         struct ldb_message_element *el;
    2890             : 
    2891         116 :         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
    2892             : 
    2893         116 :         state = h->data;
    2894             : 
    2895         116 :         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
    2896         116 :         if (sidstr == NULL) {
    2897           0 :                 return NT_STATUS_NO_MEMORY;
    2898             :         }
    2899             : 
    2900         116 :         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
    2901             :                            "(&(objectSid=%s)(privilege=*))", sidstr);
    2902         116 :         if (ret == 0) {
    2903          25 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    2904             :         }
    2905          91 :         if (ret != 1) {
    2906           0 :                 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
    2907             :                           dom_sid_string(mem_ctx, r->in.sid),
    2908             :                           ldb_errstring(state->pdb)));
    2909           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    2910             :         }
    2911             : 
    2912          91 :         el = ldb_msg_find_element(res[0], "privilege");
    2913          91 :         if (el == NULL || el->num_values == 0) {
    2914           0 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    2915             :         }
    2916             : 
    2917          91 :         r->out.rights->count = el->num_values;
    2918          91 :         r->out.rights->names = talloc_array(r->out.rights,
    2919             :                                             struct lsa_StringLarge, r->out.rights->count);
    2920          91 :         if (r->out.rights->names == NULL) {
    2921           0 :                 return NT_STATUS_NO_MEMORY;
    2922             :         }
    2923             : 
    2924         791 :         for (i=0;i<el->num_values;i++) {
    2925         700 :                 r->out.rights->names[i].string = (const char *)el->values[i].data;
    2926             :         }
    2927             : 
    2928          91 :         return NT_STATUS_OK;
    2929             : }
    2930             : 
    2931             : 
    2932             : 
    2933             : /*
    2934             :   helper for lsa_AddAccountRights and lsa_RemoveAccountRights
    2935             : */
    2936          70 : static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
    2937             :                                            TALLOC_CTX *mem_ctx,
    2938             :                                            struct lsa_policy_state *state,
    2939             :                                            int ldb_flag,
    2940             :                                            struct dom_sid *sid,
    2941             :                                            const struct lsa_RightSet *rights)
    2942             : {
    2943          70 :         struct auth_session_info *session_info =
    2944             :                 dcesrv_call_session_info(dce_call);
    2945             :         const char *sidstr, *sidndrstr;
    2946             :         struct ldb_message *msg;
    2947             :         struct ldb_message_element *el;
    2948             :         int ret;
    2949             :         uint32_t i;
    2950             :         struct lsa_EnumAccountRights r2;
    2951             :         char *dnstr;
    2952             : 
    2953          70 :         if (security_session_user_level(session_info, NULL) <
    2954             :             SECURITY_ADMINISTRATOR) {
    2955           0 :                 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
    2956           0 :                 return NT_STATUS_ACCESS_DENIED;
    2957             :         }
    2958             : 
    2959          70 :         msg = ldb_msg_new(mem_ctx);
    2960          70 :         if (msg == NULL) {
    2961           0 :                 return NT_STATUS_NO_MEMORY;
    2962             :         }
    2963             : 
    2964          70 :         sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
    2965          70 :         if (sidndrstr == NULL) {
    2966           0 :                 TALLOC_FREE(msg);
    2967           0 :                 return NT_STATUS_NO_MEMORY;
    2968             :         }
    2969             : 
    2970          70 :         sidstr = dom_sid_string(msg, sid);
    2971          70 :         if (sidstr == NULL) {
    2972           0 :                 TALLOC_FREE(msg);
    2973           0 :                 return NT_STATUS_NO_MEMORY;
    2974             :         }
    2975             : 
    2976          70 :         dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
    2977          70 :         if (dnstr == NULL) {
    2978           0 :                 TALLOC_FREE(msg);
    2979           0 :                 return NT_STATUS_NO_MEMORY;
    2980             :         }
    2981             : 
    2982          70 :         msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
    2983          70 :         if (msg->dn == NULL) {
    2984           0 :                 TALLOC_FREE(msg);
    2985           0 :                 return NT_STATUS_NO_MEMORY;
    2986             :         }
    2987             : 
    2988          70 :         if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
    2989             :                 NTSTATUS status;
    2990             : 
    2991          39 :                 r2.in.handle = &state->handle->wire_handle;
    2992          39 :                 r2.in.sid = sid;
    2993          39 :                 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
    2994             : 
    2995          39 :                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
    2996          39 :                 if (!NT_STATUS_IS_OK(status)) {
    2997           8 :                         ZERO_STRUCTP(r2.out.rights);
    2998             :                 }
    2999             :         }
    3000             : 
    3001         146 :         for (i=0;i<rights->count;i++) {
    3002             :                 bool ok;
    3003             : 
    3004          76 :                 ok = dcesrc_lsa_valid_AccountRight(rights->names[i].string);
    3005          76 :                 if (!ok) {
    3006           0 :                         talloc_free(msg);
    3007           0 :                         return NT_STATUS_NO_SUCH_PRIVILEGE;
    3008             :                 }
    3009             : 
    3010          76 :                 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
    3011             :                         uint32_t j;
    3012         215 :                         for (j=0;j<r2.out.rights->count;j++) {
    3013         176 :                                 if (strcasecmp_m(r2.out.rights->names[j].string,
    3014         176 :                                                rights->names[i].string) == 0) {
    3015           0 :                                         break;
    3016             :                                 }
    3017             :                         }
    3018          39 :                         if (j != r2.out.rights->count) continue;
    3019             :                 }
    3020             : 
    3021          76 :                 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
    3022          76 :                 if (ret != LDB_SUCCESS) {
    3023           0 :                         talloc_free(msg);
    3024           0 :                         return NT_STATUS_NO_MEMORY;
    3025             :                 }
    3026             :         }
    3027             : 
    3028          70 :         el = ldb_msg_find_element(msg, "privilege");
    3029          70 :         if (!el) {
    3030           0 :                 talloc_free(msg);
    3031           0 :                 return NT_STATUS_OK;
    3032             :         }
    3033             : 
    3034          70 :         el->flags = ldb_flag;
    3035             : 
    3036          70 :         ret = ldb_modify(state->pdb, msg);
    3037          70 :         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
    3038           8 :                 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
    3039           0 :                         talloc_free(msg);
    3040           0 :                         return NT_STATUS_NO_MEMORY;
    3041             :                 }
    3042           8 :                 ldb_msg_add_string(msg, "comment", "added via LSA");
    3043           8 :                 ret = ldb_add(state->pdb, msg);
    3044             :         }
    3045          70 :         if (ret != LDB_SUCCESS) {
    3046           0 :                 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
    3047           0 :                         talloc_free(msg);
    3048           0 :                         return NT_STATUS_OK;
    3049             :                 }
    3050           0 :                 DEBUG(3, ("Could not %s attributes from %s: %s",
    3051             :                           LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
    3052             :                           ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
    3053           0 :                 talloc_free(msg);
    3054           0 :                 return NT_STATUS_UNEXPECTED_IO_ERROR;
    3055             :         }
    3056             : 
    3057          70 :         talloc_free(msg);
    3058          70 :         return NT_STATUS_OK;
    3059             : }
    3060             : 
    3061             : /*
    3062             :   lsa_AddPrivilegesToAccount
    3063             : */
    3064          25 : static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    3065             :                                            struct lsa_AddPrivilegesToAccount *r)
    3066             : {
    3067             :         struct lsa_RightSet rights;
    3068             :         struct dcesrv_handle *h;
    3069             :         struct lsa_account_state *astate;
    3070             :         uint32_t i;
    3071             : 
    3072          25 :         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
    3073             : 
    3074          25 :         astate = h->data;
    3075             : 
    3076          25 :         rights.count = r->in.privs->count;
    3077          25 :         rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
    3078          25 :         if (rights.names == NULL) {
    3079           0 :                 return NT_STATUS_NO_MEMORY;
    3080             :         }
    3081          50 :         for (i=0;i<rights.count;i++) {
    3082          25 :                 int id = r->in.privs->set[i].luid.low;
    3083          25 :                 if (r->in.privs->set[i].luid.high) {
    3084           0 :                         return NT_STATUS_NO_SUCH_PRIVILEGE;
    3085             :                 }
    3086          25 :                 rights.names[i].string = sec_privilege_name(id);
    3087          25 :                 if (rights.names[i].string == NULL) {
    3088           0 :                         return NT_STATUS_NO_SUCH_PRIVILEGE;
    3089             :                 }
    3090             :         }
    3091             : 
    3092          25 :         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
    3093             :                                           LDB_FLAG_MOD_ADD, astate->account_sid,
    3094             :                                           &rights);
    3095             : }
    3096             : 
    3097             : 
    3098             : /*
    3099             :   lsa_RemovePrivilegesFromAccount
    3100             : */
    3101          25 : static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    3102             :                                                 struct lsa_RemovePrivilegesFromAccount *r)
    3103             : {
    3104             :         struct lsa_RightSet *rights;
    3105             :         struct dcesrv_handle *h;
    3106             :         struct lsa_account_state *astate;
    3107             :         uint32_t i;
    3108             : 
    3109          25 :         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
    3110             : 
    3111          25 :         astate = h->data;
    3112             : 
    3113          25 :         rights = talloc(mem_ctx, struct lsa_RightSet);
    3114             : 
    3115          25 :         if (r->in.remove_all == 1 &&
    3116           0 :             r->in.privs == NULL) {
    3117             :                 struct lsa_EnumAccountRights r2;
    3118             :                 NTSTATUS status;
    3119             : 
    3120           0 :                 r2.in.handle = &astate->policy->handle->wire_handle;
    3121           0 :                 r2.in.sid = astate->account_sid;
    3122           0 :                 r2.out.rights = rights;
    3123             : 
    3124           0 :                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
    3125           0 :                 if (!NT_STATUS_IS_OK(status)) {
    3126           0 :                         return status;
    3127             :                 }
    3128             : 
    3129           0 :                 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
    3130             :                                                   LDB_FLAG_MOD_DELETE, astate->account_sid,
    3131           0 :                                                   r2.out.rights);
    3132             :         }
    3133             : 
    3134          25 :         if (r->in.remove_all != 0) {
    3135           0 :                 return NT_STATUS_INVALID_PARAMETER;
    3136             :         }
    3137             : 
    3138          25 :         rights->count = r->in.privs->count;
    3139          25 :         rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
    3140          25 :         if (rights->names == NULL) {
    3141           0 :                 return NT_STATUS_NO_MEMORY;
    3142             :         }
    3143          50 :         for (i=0;i<rights->count;i++) {
    3144          25 :                 int id = r->in.privs->set[i].luid.low;
    3145          25 :                 if (r->in.privs->set[i].luid.high) {
    3146           0 :                         return NT_STATUS_NO_SUCH_PRIVILEGE;
    3147             :                 }
    3148          25 :                 rights->names[i].string = sec_privilege_name(id);
    3149          25 :                 if (rights->names[i].string == NULL) {
    3150           0 :                         return NT_STATUS_NO_SUCH_PRIVILEGE;
    3151             :                 }
    3152             :         }
    3153             : 
    3154          25 :         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
    3155             :                                           LDB_FLAG_MOD_DELETE, astate->account_sid,
    3156             :                                           rights);
    3157             : }
    3158             : 
    3159             : 
    3160             : /*
    3161             :   lsa_GetQuotasForAccount
    3162             : */
    3163           0 : static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    3164             :                        struct lsa_GetQuotasForAccount *r)
    3165             : {
    3166           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    3167             : }
    3168             : 
    3169             : 
    3170             : /*
    3171             :   lsa_SetQuotasForAccount
    3172             : */
    3173           0 : static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    3174             :                        struct lsa_SetQuotasForAccount *r)
    3175             : {
    3176           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    3177             : }
    3178             : 
    3179             : 
    3180             : /*
    3181             :   lsa_GetSystemAccessAccount
    3182             : */
    3183          42 : static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    3184             :                        struct lsa_GetSystemAccessAccount *r)
    3185             : {
    3186             :         struct dcesrv_handle *h;
    3187             :         struct lsa_account_state *astate;
    3188             :         int ret;
    3189             :         unsigned int i;
    3190             :         struct ldb_message **res;
    3191          42 :         const char * const attrs[] = { "privilege", NULL};
    3192             :         struct ldb_message_element *el;
    3193             :         const char *sidstr;
    3194             : 
    3195          42 :         *(r->out.access_mask) = 0x00000000;
    3196             : 
    3197          42 :         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
    3198             : 
    3199          42 :         astate = h->data;
    3200             : 
    3201          42 :         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
    3202          42 :         if (sidstr == NULL) {
    3203           0 :                 return NT_STATUS_NO_MEMORY;
    3204             :         }
    3205             : 
    3206          42 :         ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
    3207             :                            "objectSid=%s", sidstr);
    3208          42 :         if (ret < 0) {
    3209           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    3210             :         }
    3211          42 :         if (ret != 1) {
    3212           0 :                 return NT_STATUS_OK;
    3213             :         }
    3214             : 
    3215          42 :         el = ldb_msg_find_element(res[0], "privilege");
    3216          42 :         if (el == NULL || el->num_values == 0) {
    3217           0 :                 return NT_STATUS_OK;
    3218             :         }
    3219             : 
    3220         266 :         for (i=0;i<el->num_values;i++) {
    3221         224 :                 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
    3222         224 :                 if (right_bit == 0) {
    3223             :                         /* Perhaps an privilege, not a right */
    3224         172 :                         continue;
    3225             :                 }
    3226          52 :                 *(r->out.access_mask) |= right_bit;
    3227             :         }
    3228             : 
    3229          42 :         return NT_STATUS_OK;
    3230             : }
    3231             : 
    3232             : 
    3233             : /*
    3234             :   lsa_SetSystemAccessAccount
    3235             : */
    3236           0 : static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    3237             :                        struct lsa_SetSystemAccessAccount *r)
    3238             : {
    3239           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    3240             : }
    3241             : /*
    3242             :   lsa_CreateSecret
    3243             : */
    3244        1732 : static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    3245             :                                  struct lsa_CreateSecret *r)
    3246             : {
    3247        1732 :         struct auth_session_info *session_info =
    3248             :                 dcesrv_call_session_info(dce_call);
    3249             :         struct dcesrv_handle *policy_handle;
    3250             :         struct lsa_policy_state *policy_state;
    3251             :         struct lsa_secret_state *secret_state;
    3252             :         struct dcesrv_handle *handle;
    3253             :         struct ldb_message **msgs, *msg;
    3254        1732 :         const char *attrs[] = {
    3255             :                 NULL
    3256             :         };
    3257             : 
    3258             :         const char *name;
    3259             : 
    3260             :         int ret;
    3261             : 
    3262        1732 :         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
    3263        1732 :         ZERO_STRUCTP(r->out.sec_handle);
    3264             : 
    3265        1732 :         switch (security_session_user_level(session_info, NULL))
    3266             :         {
    3267        1732 :         case SECURITY_SYSTEM:
    3268             :         case SECURITY_ADMINISTRATOR:
    3269        1732 :                 break;
    3270           0 :         default:
    3271             :                 /* Users and annonymous are not allowed create secrets */
    3272           0 :                 return NT_STATUS_ACCESS_DENIED;
    3273             :         }
    3274             : 
    3275        1732 :         policy_state = policy_handle->data;
    3276             : 
    3277        1732 :         if (!r->in.name.string) {
    3278           0 :                 return NT_STATUS_INVALID_PARAMETER;
    3279             :         }
    3280             : 
    3281        1732 :         secret_state = talloc(mem_ctx, struct lsa_secret_state);
    3282        1732 :         NT_STATUS_HAVE_NO_MEMORY(secret_state);
    3283        1732 :         secret_state->policy = policy_state;
    3284             : 
    3285        1732 :         msg = ldb_msg_new(mem_ctx);
    3286        1732 :         if (msg == NULL) {
    3287           0 :                 return NT_STATUS_NO_MEMORY;
    3288             :         }
    3289             : 
    3290        1732 :         if (strncmp("G$", r->in.name.string, 2) == 0) {
    3291             :                 const char *name2;
    3292             : 
    3293          24 :                 secret_state->global = true;
    3294             : 
    3295          24 :                 name = &r->in.name.string[2];
    3296          24 :                 if (strlen(name) == 0) {
    3297           0 :                         return NT_STATUS_INVALID_PARAMETER;
    3298             :                 }
    3299             : 
    3300          24 :                 name2 = talloc_asprintf(mem_ctx, "%s Secret",
    3301             :                                         ldb_binary_encode_string(mem_ctx, name));
    3302          24 :                 NT_STATUS_HAVE_NO_MEMORY(name2);
    3303             : 
    3304             :                 /*
    3305             :                  * We need to connect to the database as system, as this is
    3306             :                  * one of the rare RPC calls that must read the secrets
    3307             :                  * (and this is denied otherwise)
    3308             :                  *
    3309             :                  * We also save the current remote session details so they can
    3310             :                  * used by the audit logging module. This allows the audit
    3311             :                  * logging to report the remote users details, rather than the
    3312             :                  * system users details.
    3313             :                  */
    3314          24 :                 secret_state->sam_ldb =
    3315          24 :                         dcesrv_samdb_connect_as_system(secret_state, dce_call);
    3316          24 :                 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
    3317             : 
    3318             :                 /* search for the secret record */
    3319          24 :                 ret = gendb_search(secret_state->sam_ldb,
    3320             :                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
    3321             :                                    "(&(cn=%s)(objectclass=secret))",
    3322             :                                    name2);
    3323          24 :                 if (ret > 0) {
    3324          11 :                         return NT_STATUS_OBJECT_NAME_COLLISION;
    3325             :                 }
    3326             : 
    3327          13 :                 if (ret < 0) {
    3328           0 :                         DEBUG(0,("Failure searching for CN=%s: %s\n",
    3329             :                                  name2, ldb_errstring(secret_state->sam_ldb)));
    3330           0 :                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
    3331             :                 }
    3332             : 
    3333          13 :                 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
    3334          13 :                 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
    3335          13 :                 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
    3336           0 :                         return NT_STATUS_NO_MEMORY;
    3337             :                 }
    3338             : 
    3339          13 :                 ret = ldb_msg_add_string(msg, "cn", name2);
    3340          13 :                 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
    3341             :         } else {
    3342        1708 :                 secret_state->global = false;
    3343             : 
    3344        1708 :                 name = r->in.name.string;
    3345        1708 :                 if (strlen(name) == 0) {
    3346           0 :                         return NT_STATUS_INVALID_PARAMETER;
    3347             :                 }
    3348             : 
    3349        1708 :                 secret_state->sam_ldb = secrets_db_connect(secret_state,
    3350        1708 :                                         dce_call->conn->dce_ctx->lp_ctx);
    3351        1708 :                 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
    3352             : 
    3353             :                 /* search for the secret record */
    3354        1708 :                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
    3355             :                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
    3356             :                                    &msgs, attrs,
    3357             :                                    "(&(cn=%s)(objectclass=secret))",
    3358             :                                    ldb_binary_encode_string(mem_ctx, name));
    3359        1708 :                 if (ret > 0) {
    3360          14 :                         return NT_STATUS_OBJECT_NAME_COLLISION;
    3361             :                 }
    3362             : 
    3363        1694 :                 if (ret < 0) {
    3364           0 :                         DEBUG(0,("Failure searching for CN=%s: %s\n",
    3365             :                                  name, ldb_errstring(secret_state->sam_ldb)));
    3366           0 :                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
    3367             :                 }
    3368             : 
    3369        1694 :                 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
    3370             :                                          "cn=%s,cn=LSA Secrets", name);
    3371        1694 :                 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
    3372        1694 :                 ret = ldb_msg_add_string(msg, "cn", name);
    3373        1694 :                 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
    3374             :         }
    3375             : 
    3376        1707 :         ret = ldb_msg_add_string(msg, "objectClass", "secret");
    3377        1707 :         if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
    3378             : 
    3379        1707 :         secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
    3380        1707 :         NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
    3381             : 
    3382             :         /* create the secret */
    3383        1707 :         ret = ldb_add(secret_state->sam_ldb, msg);
    3384        1707 :         if (ret != LDB_SUCCESS) {
    3385           0 :                 DEBUG(0,("Failed to create secret record %s: %s\n",
    3386             :                          ldb_dn_get_linearized(msg->dn),
    3387             :                          ldb_errstring(secret_state->sam_ldb)));
    3388           0 :                 return NT_STATUS_ACCESS_DENIED;
    3389             :         }
    3390             : 
    3391        1707 :         handle = dcesrv_handle_create(dce_call, LSA_HANDLE_SECRET);
    3392        1707 :         NT_STATUS_HAVE_NO_MEMORY(handle);
    3393             : 
    3394        1707 :         handle->data = talloc_steal(handle, secret_state);
    3395             : 
    3396        1707 :         secret_state->access_mask = r->in.access_mask;
    3397        1707 :         secret_state->policy = talloc_reference(secret_state, policy_state);
    3398        1707 :         NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
    3399             : 
    3400        1707 :         *r->out.sec_handle = handle->wire_handle;
    3401             : 
    3402        1707 :         return NT_STATUS_OK;
    3403             : }
    3404             : 
    3405             : 
    3406             : /*
    3407             :   lsa_OpenSecret
    3408             : */
    3409          54 : static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    3410             :                                struct lsa_OpenSecret *r)
    3411             : {
    3412          54 :         struct auth_session_info *session_info =
    3413             :                 dcesrv_call_session_info(dce_call);
    3414             :         struct dcesrv_handle *policy_handle;
    3415             :         struct lsa_policy_state *policy_state;
    3416             :         struct lsa_secret_state *secret_state;
    3417             :         struct dcesrv_handle *handle;
    3418             :         struct ldb_message **msgs;
    3419          54 :         const char *attrs[] = {
    3420             :                 NULL
    3421             :         };
    3422             :         const char *name;
    3423             :         int ret;
    3424             : 
    3425          54 :         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
    3426          54 :         ZERO_STRUCTP(r->out.sec_handle);
    3427          54 :         policy_state = policy_handle->data;
    3428             : 
    3429          54 :         if (!r->in.name.string) {
    3430           0 :                 return NT_STATUS_INVALID_PARAMETER;
    3431             :         }
    3432             : 
    3433          54 :         switch (security_session_user_level(session_info, NULL))
    3434             :         {
    3435          54 :         case SECURITY_SYSTEM:
    3436             :         case SECURITY_ADMINISTRATOR:
    3437          54 :                 break;
    3438           0 :         default:
    3439             :                 /* Users and annonymous are not allowed to access secrets */
    3440           0 :                 return NT_STATUS_ACCESS_DENIED;
    3441             :         }
    3442             : 
    3443          54 :         secret_state = talloc(mem_ctx, struct lsa_secret_state);
    3444          54 :         if (!secret_state) {
    3445           0 :                 return NT_STATUS_NO_MEMORY;
    3446             :         }
    3447          54 :         secret_state->policy = policy_state;
    3448             : 
    3449          54 :         if (strncmp("G$", r->in.name.string, 2) == 0) {
    3450          29 :                 name = &r->in.name.string[2];
    3451             :                 /*
    3452             :                  * We need to connect to the database as system, as this is
    3453             :                  * one of the rare RPC calls that must read the secrets
    3454             :                  * (and this is denied otherwise)
    3455             :                  *
    3456             :                  * We also save the current remote session details so they can
    3457             :                  * used by the audit logging module. This allows the audit
    3458             :                  * logging to report the remote users details, rather than the
    3459             :                  * system users details.
    3460             :                  */
    3461          29 :                 secret_state->sam_ldb =
    3462          29 :                         dcesrv_samdb_connect_as_system(secret_state, dce_call);
    3463          29 :                 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
    3464          29 :                 secret_state->global = true;
    3465             : 
    3466          29 :                 if (strlen(name) < 1) {
    3467           0 :                         return NT_STATUS_INVALID_PARAMETER;
    3468             :                 }
    3469             : 
    3470             :                 /* search for the secret record */
    3471          29 :                 ret = gendb_search(secret_state->sam_ldb,
    3472             :                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
    3473             :                                    "(&(cn=%s Secret)(objectclass=secret))",
    3474             :                                    ldb_binary_encode_string(mem_ctx, name));
    3475          29 :                 if (ret == 0) {
    3476          11 :                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    3477             :                 }
    3478             : 
    3479          18 :                 if (ret != 1) {
    3480           0 :                         DEBUG(0,("Found %d records matching DN %s\n", ret,
    3481             :                                  ldb_dn_get_linearized(policy_state->system_dn)));
    3482           0 :                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
    3483             :                 }
    3484             :         } else {
    3485          25 :                 secret_state->global = false;
    3486          25 :                 secret_state->sam_ldb = secrets_db_connect(secret_state,
    3487          25 :                                         dce_call->conn->dce_ctx->lp_ctx);
    3488          25 :                 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
    3489             : 
    3490          25 :                 name = r->in.name.string;
    3491          25 :                 if (strlen(name) < 1) {
    3492           0 :                         return NT_STATUS_INVALID_PARAMETER;
    3493             :                 }
    3494             : 
    3495             :                 /* search for the secret record */
    3496          25 :                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
    3497             :                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
    3498             :                                    &msgs, attrs,
    3499             :                                    "(&(cn=%s)(objectclass=secret))",
    3500             :                                    ldb_binary_encode_string(mem_ctx, name));
    3501          25 :                 if (ret == 0) {
    3502          11 :                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    3503             :                 }
    3504             : 
    3505          14 :                 if (ret != 1) {
    3506           0 :                         DEBUG(0,("Found %d records matching CN=%s\n",
    3507             :                                  ret, ldb_binary_encode_string(mem_ctx, name)));
    3508           0 :                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
    3509             :                 }
    3510             :         }
    3511             : 
    3512          32 :         secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
    3513             : 
    3514          32 :         handle = dcesrv_handle_create(dce_call, LSA_HANDLE_SECRET);
    3515          32 :         if (!handle) {
    3516           0 :                 return NT_STATUS_NO_MEMORY;
    3517             :         }
    3518             : 
    3519          32 :         handle->data = talloc_steal(handle, secret_state);
    3520             : 
    3521          32 :         secret_state->access_mask = r->in.access_mask;
    3522          32 :         secret_state->policy = talloc_reference(secret_state, policy_state);
    3523             : 
    3524          32 :         *r->out.sec_handle = handle->wire_handle;
    3525             : 
    3526          32 :         return NT_STATUS_OK;
    3527             : }
    3528             : 
    3529             : 
    3530             : /*
    3531             :   lsa_SetSecret
    3532             : */
    3533        2456 : static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    3534             :                               struct lsa_SetSecret *r)
    3535             : {
    3536             : 
    3537             :         struct dcesrv_handle *h;
    3538             :         struct lsa_secret_state *secret_state;
    3539             :         struct ldb_message *msg;
    3540             :         DATA_BLOB session_key;
    3541             :         DATA_BLOB crypt_secret, secret;
    3542             :         struct ldb_val val;
    3543             :         int ret;
    3544        2456 :         NTSTATUS status = NT_STATUS_OK;
    3545             : 
    3546        2456 :         struct timeval now = timeval_current();
    3547        2456 :         NTTIME nt_now = timeval_to_nttime(&now);
    3548             : 
    3549        2456 :         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
    3550             : 
    3551        2456 :         secret_state = h->data;
    3552             : 
    3553        2456 :         msg = ldb_msg_new(mem_ctx);
    3554        2456 :         if (msg == NULL) {
    3555           0 :                 return NT_STATUS_NO_MEMORY;
    3556             :         }
    3557             : 
    3558        2456 :         msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
    3559        2456 :         if (!msg->dn) {
    3560           0 :                 return NT_STATUS_NO_MEMORY;
    3561             :         }
    3562        2456 :         status = dcesrv_transport_session_key(dce_call, &session_key);
    3563        2456 :         if (!NT_STATUS_IS_OK(status)) {
    3564           0 :                 return status;
    3565             :         }
    3566             : 
    3567        2456 :         if (r->in.old_val) {
    3568             :                 /* Decrypt */
    3569          22 :                 crypt_secret.data = r->in.old_val->data;
    3570          22 :                 crypt_secret.length = r->in.old_val->size;
    3571             : 
    3572          22 :                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
    3573          22 :                 if (!NT_STATUS_IS_OK(status)) {
    3574           0 :                         return status;
    3575             :                 }
    3576             : 
    3577          22 :                 val.data = secret.data;
    3578          22 :                 val.length = secret.length;
    3579             : 
    3580             :                 /* set value */
    3581          22 :                 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
    3582           0 :                         return NT_STATUS_NO_MEMORY;
    3583             :                 }
    3584             : 
    3585             :                 /* set old value mtime */
    3586          22 :                 if (samdb_msg_add_uint64(secret_state->sam_ldb,
    3587             :                                          mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
    3588           0 :                         return NT_STATUS_NO_MEMORY;
    3589             :                 }
    3590             : 
    3591             :         } else {
    3592             :                 /* If the old value is not set, then migrate the
    3593             :                  * current value to the old value */
    3594             :                 const struct ldb_val *old_val;
    3595             :                 NTTIME last_set_time;
    3596             :                 struct ldb_message **res;
    3597        2434 :                 const char *attrs[] = {
    3598             :                         "currentValue",
    3599             :                         "lastSetTime",
    3600             :                         NULL
    3601             :                 };
    3602             : 
    3603             :                 /* search for the secret record */
    3604        2434 :                 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
    3605             :                                       secret_state->secret_dn, &res, attrs);
    3606        2434 :                 if (ret == 0) {
    3607           0 :                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    3608             :                 }
    3609             : 
    3610        2434 :                 if (ret != 1) {
    3611           0 :                         DEBUG(0,("Found %d records matching dn=%s\n", ret,
    3612             :                                  ldb_dn_get_linearized(secret_state->secret_dn)));
    3613           0 :                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
    3614             :                 }
    3615             : 
    3616        2434 :                 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
    3617        2434 :                 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
    3618             : 
    3619        2434 :                 if (old_val) {
    3620             :                         /* set old value */
    3621        1228 :                         if (ldb_msg_add_value(msg, "priorValue",
    3622             :                                               old_val, NULL) != LDB_SUCCESS) {
    3623           0 :                                 return NT_STATUS_NO_MEMORY;
    3624             :                         }
    3625             :                 } else {
    3626        1206 :                         if (samdb_msg_add_delete(secret_state->sam_ldb,
    3627             :                                                  mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
    3628           0 :                                 return NT_STATUS_NO_MEMORY;
    3629             :                         }
    3630             :                 }
    3631             : 
    3632             :                 /* set old value mtime */
    3633        2434 :                 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
    3634        1228 :                         if (samdb_msg_add_uint64(secret_state->sam_ldb,
    3635             :                                                  mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
    3636           0 :                                 return NT_STATUS_NO_MEMORY;
    3637             :                         }
    3638             :                 } else {
    3639        1206 :                         if (samdb_msg_add_uint64(secret_state->sam_ldb,
    3640             :                                                  mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
    3641           0 :                                 return NT_STATUS_NO_MEMORY;
    3642             :                         }
    3643             :                 }
    3644             :         }
    3645             : 
    3646        2456 :         if (r->in.new_val) {
    3647             :                 /* Decrypt */
    3648        2434 :                 crypt_secret.data = r->in.new_val->data;
    3649        2434 :                 crypt_secret.length = r->in.new_val->size;
    3650             : 
    3651        2434 :                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
    3652        2434 :                 if (!NT_STATUS_IS_OK(status)) {
    3653        1206 :                         return status;
    3654             :                 }
    3655             : 
    3656        1228 :                 val.data = secret.data;
    3657        1228 :                 val.length = secret.length;
    3658             : 
    3659             :                 /* set value */
    3660        1228 :                 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
    3661           0 :                         return NT_STATUS_NO_MEMORY;
    3662             :                 }
    3663             : 
    3664             :                 /* set new value mtime */
    3665        1228 :                 if (samdb_msg_add_uint64(secret_state->sam_ldb,
    3666             :                                          mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
    3667           0 :                         return NT_STATUS_NO_MEMORY;
    3668             :                 }
    3669             :         } else {
    3670             :                 /* NULL out the NEW value */
    3671          22 :                 if (samdb_msg_add_uint64(secret_state->sam_ldb,
    3672             :                                          mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
    3673           0 :                         return NT_STATUS_NO_MEMORY;
    3674             :                 }
    3675          22 :                 if (samdb_msg_add_delete(secret_state->sam_ldb,
    3676             :                                          mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
    3677           0 :                         return NT_STATUS_NO_MEMORY;
    3678             :                 }
    3679             :         }
    3680             : 
    3681             :         /* modify the samdb record */
    3682        1250 :         ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
    3683        1250 :         if (ret != LDB_SUCCESS) {
    3684           0 :                 return dsdb_ldb_err_to_ntstatus(ret);
    3685             :         }
    3686             : 
    3687        1250 :         return NT_STATUS_OK;
    3688             : }
    3689             : 
    3690             : 
    3691             : /*
    3692             :   lsa_QuerySecret
    3693             : */
    3694        1256 : static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    3695             :                                 struct lsa_QuerySecret *r)
    3696             : {
    3697        1256 :         struct auth_session_info *session_info =
    3698             :                 dcesrv_call_session_info(dce_call);
    3699             :         struct dcesrv_handle *h;
    3700             :         struct lsa_secret_state *secret_state;
    3701             :         struct ldb_message *msg;
    3702             :         DATA_BLOB session_key;
    3703             :         DATA_BLOB crypt_secret, secret;
    3704             :         int ret;
    3705             :         struct ldb_message **res;
    3706        1256 :         const char *attrs[] = {
    3707             :                 "currentValue",
    3708             :                 "priorValue",
    3709             :                 "lastSetTime",
    3710             :                 "priorSetTime",
    3711             :                 NULL
    3712             :         };
    3713             : 
    3714             :         NTSTATUS nt_status;
    3715             : 
    3716        1256 :         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
    3717             : 
    3718             :         /* Ensure user is permitted to read this... */
    3719        1256 :         switch (security_session_user_level(session_info, NULL))
    3720             :         {
    3721        1256 :         case SECURITY_SYSTEM:
    3722             :         case SECURITY_ADMINISTRATOR:
    3723        1256 :                 break;
    3724           0 :         default:
    3725             :                 /* Users and annonymous are not allowed to read secrets */
    3726           0 :                 return NT_STATUS_ACCESS_DENIED;
    3727             :         }
    3728             : 
    3729        1256 :         secret_state = h->data;
    3730             : 
    3731             :         /* pull all the user attributes */
    3732        1256 :         ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
    3733             :                               secret_state->secret_dn, &res, attrs);
    3734        1256 :         if (ret != 1) {
    3735           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    3736             :         }
    3737        1256 :         msg = res[0];
    3738             : 
    3739        1256 :         nt_status = dcesrv_transport_session_key(dce_call, &session_key);
    3740        1256 :         if (!NT_STATUS_IS_OK(nt_status)) {
    3741           0 :                 return nt_status;
    3742             :         }
    3743             : 
    3744        1256 :         if (r->in.old_val) {
    3745             :                 const struct ldb_val *prior_val;
    3746          44 :                 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
    3747          44 :                 if (!r->out.old_val) {
    3748           0 :                         return NT_STATUS_NO_MEMORY;
    3749             :                 }
    3750          44 :                 prior_val = ldb_msg_find_ldb_val(msg, "priorValue");
    3751             : 
    3752          44 :                 if (prior_val && prior_val->length) {
    3753          44 :                         secret.data = prior_val->data;
    3754          44 :                         secret.length = prior_val->length;
    3755             : 
    3756             :                         /* Encrypt */
    3757          44 :                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
    3758          44 :                         if (!crypt_secret.length) {
    3759           0 :                                 return NT_STATUS_NO_MEMORY;
    3760             :                         }
    3761          44 :                         r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
    3762          44 :                         if (!r->out.old_val->buf) {
    3763           0 :                                 return NT_STATUS_NO_MEMORY;
    3764             :                         }
    3765          44 :                         r->out.old_val->buf->size = crypt_secret.length;
    3766          44 :                         r->out.old_val->buf->length = crypt_secret.length;
    3767          44 :                         r->out.old_val->buf->data = crypt_secret.data;
    3768             :                 }
    3769             :         }
    3770             : 
    3771        1256 :         if (r->in.old_mtime) {
    3772          44 :                 r->out.old_mtime = talloc(mem_ctx, NTTIME);
    3773          44 :                 if (!r->out.old_mtime) {
    3774           0 :                         return NT_STATUS_NO_MEMORY;
    3775             :                 }
    3776          44 :                 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(msg, "priorSetTime", 0);
    3777             :         }
    3778             : 
    3779        1256 :         if (r->in.new_val) {
    3780             :                 const struct ldb_val *new_val;
    3781        1256 :                 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
    3782        1256 :                 if (!r->out.new_val) {
    3783           0 :                         return NT_STATUS_NO_MEMORY;
    3784             :                 }
    3785             : 
    3786        1256 :                 new_val = ldb_msg_find_ldb_val(msg, "currentValue");
    3787             : 
    3788        1256 :                 if (new_val && new_val->length) {
    3789        1234 :                         secret.data = new_val->data;
    3790        1234 :                         secret.length = new_val->length;
    3791             : 
    3792             :                         /* Encrypt */
    3793        1234 :                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
    3794        1234 :                         if (!crypt_secret.length) {
    3795           0 :                                 return NT_STATUS_NO_MEMORY;
    3796             :                         }
    3797        1234 :                         r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
    3798        1234 :                         if (!r->out.new_val->buf) {
    3799           0 :                                 return NT_STATUS_NO_MEMORY;
    3800             :                         }
    3801        1234 :                         r->out.new_val->buf->length = crypt_secret.length;
    3802        1234 :                         r->out.new_val->buf->size = crypt_secret.length;
    3803        1234 :                         r->out.new_val->buf->data = crypt_secret.data;
    3804             :                 }
    3805             :         }
    3806             : 
    3807        1256 :         if (r->in.new_mtime) {
    3808        1250 :                 r->out.new_mtime = talloc(mem_ctx, NTTIME);
    3809        1250 :                 if (!r->out.new_mtime) {
    3810           0 :                         return NT_STATUS_NO_MEMORY;
    3811             :                 }
    3812        1250 :                 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(msg, "lastSetTime", 0);
    3813             :         }
    3814             : 
    3815        1256 :         return NT_STATUS_OK;
    3816             : }
    3817             : 
    3818             : 
    3819             : /*
    3820             :   lsa_LookupPrivValue
    3821             : */
    3822         127 : static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
    3823             :                                     TALLOC_CTX *mem_ctx,
    3824             :                                     struct lsa_LookupPrivValue *r)
    3825             : {
    3826             :         struct dcesrv_handle *h;
    3827             :         int id;
    3828             : 
    3829         127 :         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
    3830             : 
    3831         127 :         id = sec_privilege_id(r->in.name->string);
    3832         127 :         if (id == SEC_PRIV_INVALID) {
    3833           0 :                 return NT_STATUS_NO_SUCH_PRIVILEGE;
    3834             :         }
    3835             : 
    3836         127 :         r->out.luid->low = id;
    3837         127 :         r->out.luid->high = 0;
    3838             : 
    3839         127 :         return NT_STATUS_OK;
    3840             : }
    3841             : 
    3842             : 
    3843             : /*
    3844             :   lsa_LookupPrivName
    3845             : */
    3846         160 : static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
    3847             :                                    TALLOC_CTX *mem_ctx,
    3848             :                                    struct lsa_LookupPrivName *r)
    3849             : {
    3850             :         struct dcesrv_handle *h;
    3851             :         struct lsa_StringLarge *name;
    3852             :         const char *privname;
    3853             : 
    3854         160 :         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
    3855             : 
    3856         160 :         if (r->in.luid->high != 0) {
    3857           0 :                 return NT_STATUS_NO_SUCH_PRIVILEGE;
    3858             :         }
    3859             : 
    3860         160 :         privname = sec_privilege_name(r->in.luid->low);
    3861         160 :         if (privname == NULL) {
    3862           0 :                 return NT_STATUS_NO_SUCH_PRIVILEGE;
    3863             :         }
    3864             : 
    3865         160 :         name = talloc(mem_ctx, struct lsa_StringLarge);
    3866         160 :         if (name == NULL) {
    3867           0 :                 return NT_STATUS_NO_MEMORY;
    3868             :         }
    3869             : 
    3870         160 :         name->string = privname;
    3871             : 
    3872         160 :         *r->out.name = name;
    3873             : 
    3874         160 :         return NT_STATUS_OK;
    3875             : }
    3876             : 
    3877             : 
    3878             : /*
    3879             :   lsa_LookupPrivDisplayName
    3880             : */
    3881         125 : static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
    3882             :                                           TALLOC_CTX *mem_ctx,
    3883             :                                           struct lsa_LookupPrivDisplayName *r)
    3884             : {
    3885             :         struct dcesrv_handle *h;
    3886         125 :         struct lsa_StringLarge *disp_name = NULL;
    3887             :         enum sec_privilege id;
    3888             : 
    3889         125 :         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
    3890             : 
    3891         125 :         id = sec_privilege_id(r->in.name->string);
    3892         125 :         if (id == SEC_PRIV_INVALID) {
    3893           0 :                 return NT_STATUS_NO_SUCH_PRIVILEGE;
    3894             :         }
    3895             : 
    3896         125 :         disp_name = talloc(mem_ctx, struct lsa_StringLarge);
    3897         125 :         if (disp_name == NULL) {
    3898           0 :                 return NT_STATUS_NO_MEMORY;
    3899             :         }
    3900             : 
    3901         125 :         disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
    3902         125 :         if (disp_name->string == NULL) {
    3903           0 :                 return NT_STATUS_INTERNAL_ERROR;
    3904             :         }
    3905             : 
    3906         125 :         *r->out.disp_name = disp_name;
    3907         125 :         *r->out.returned_language_id = 0;
    3908             : 
    3909         125 :         return NT_STATUS_OK;
    3910             : }
    3911             : 
    3912             : 
    3913             : /*
    3914             :   lsa_EnumAccountsWithUserRight
    3915             : */
    3916         125 : static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
    3917             :                                               TALLOC_CTX *mem_ctx,
    3918             :                                               struct lsa_EnumAccountsWithUserRight *r)
    3919             : {
    3920             :         struct dcesrv_handle *h;
    3921             :         struct lsa_policy_state *state;
    3922             :         int ret, i;
    3923             :         struct ldb_message **res;
    3924         125 :         const char * const attrs[] = { "objectSid", NULL};
    3925             :         const char *privname;
    3926             :         bool ok;
    3927             : 
    3928         125 :         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
    3929             : 
    3930         125 :         state = h->data;
    3931             : 
    3932         125 :         if (r->in.name == NULL) {
    3933           0 :                 return NT_STATUS_NO_SUCH_PRIVILEGE;
    3934             :         }
    3935             : 
    3936         125 :         privname = r->in.name->string;
    3937             : 
    3938         125 :         ok = dcesrc_lsa_valid_AccountRight(privname);
    3939         125 :         if (!ok) {
    3940           0 :                 return NT_STATUS_NO_SUCH_PRIVILEGE;
    3941             :         }
    3942             : 
    3943         125 :         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
    3944             :                            "privilege=%s", privname);
    3945         125 :         if (ret < 0) {
    3946           0 :                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
    3947             :         }
    3948         125 :         if (ret == 0) {
    3949          20 :                 return NT_STATUS_NO_MORE_ENTRIES;
    3950             :         }
    3951             : 
    3952         105 :         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
    3953         105 :         if (r->out.sids->sids == NULL) {
    3954           0 :                 return NT_STATUS_NO_MEMORY;
    3955             :         }
    3956         265 :         for (i=0;i<ret;i++) {
    3957         160 :                 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
    3958         160 :                                                                 res[i], "objectSid");
    3959         160 :                 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
    3960             :         }
    3961         105 :         r->out.sids->num_sids = ret;
    3962             : 
    3963         105 :         return NT_STATUS_OK;
    3964             : }
    3965             : 
    3966             : 
    3967             : /*
    3968             :   lsa_AddAccountRights
    3969             : */
    3970          14 : static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
    3971             :                                      TALLOC_CTX *mem_ctx,
    3972             :                                      struct lsa_AddAccountRights *r)
    3973             : {
    3974             :         struct dcesrv_handle *h;
    3975             :         struct lsa_policy_state *state;
    3976             : 
    3977          14 :         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
    3978             : 
    3979          14 :         state = h->data;
    3980             : 
    3981          14 :         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
    3982             :                                           LDB_FLAG_MOD_ADD,
    3983          14 :                                           r->in.sid, r->in.rights);
    3984             : }
    3985             : 
    3986             : 
    3987             : /*
    3988             :   lsa_RemoveAccountRights
    3989             : */
    3990           0 : static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
    3991             :                                         TALLOC_CTX *mem_ctx,
    3992             :                                         struct lsa_RemoveAccountRights *r)
    3993             : {
    3994             :         struct dcesrv_handle *h;
    3995             :         struct lsa_policy_state *state;
    3996             : 
    3997           0 :         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
    3998             : 
    3999           0 :         state = h->data;
    4000             : 
    4001           0 :         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
    4002             :                                           LDB_FLAG_MOD_DELETE,
    4003           0 :                                           r->in.sid, r->in.rights);
    4004             : }
    4005             : 
    4006             : 
    4007             : /*
    4008             :   lsa_StorePrivateData
    4009             : */
    4010           0 : static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4011             :                        struct lsa_StorePrivateData *r)
    4012             : {
    4013           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    4014             : }
    4015             : 
    4016             : 
    4017             : /*
    4018             :   lsa_RetrievePrivateData
    4019             : */
    4020           0 : static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4021             :                        struct lsa_RetrievePrivateData *r)
    4022             : {
    4023           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    4024             : }
    4025             : 
    4026             : 
    4027             : /*
    4028             :   lsa_GetUserName
    4029             : */
    4030         520 : static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4031             :                                 struct lsa_GetUserName *r)
    4032             : {
    4033         520 :         enum dcerpc_transport_t transport =
    4034         520 :                 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
    4035         520 :         struct auth_session_info *session_info =
    4036             :                 dcesrv_call_session_info(dce_call);
    4037         520 :         NTSTATUS status = NT_STATUS_OK;
    4038             :         const char *account_name;
    4039             :         const char *authority_name;
    4040             :         struct lsa_String *_account_name;
    4041         520 :         struct lsa_String *_authority_name = NULL;
    4042             : 
    4043         520 :         if (transport != NCACN_NP && transport != NCALRPC) {
    4044           3 :                 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
    4045             :         }
    4046             : 
    4047             :         /* this is what w2k3 does */
    4048         517 :         r->out.account_name = r->in.account_name;
    4049         517 :         r->out.authority_name = r->in.authority_name;
    4050             : 
    4051         517 :         if (r->in.account_name
    4052         517 :             && *r->in.account_name
    4053             :             /* && *(*r->in.account_name)->string */
    4054             :             ) {
    4055           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4056             :         }
    4057             : 
    4058         517 :         if (r->in.authority_name
    4059         472 :             && *r->in.authority_name
    4060             :             /* && *(*r->in.authority_name)->string */
    4061             :             ) {
    4062           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4063             :         }
    4064             : 
    4065         517 :         account_name = talloc_reference(mem_ctx, session_info->info->account_name);
    4066         517 :         authority_name = talloc_reference(mem_ctx, session_info->info->domain_name);
    4067             : 
    4068         517 :         _account_name = talloc(mem_ctx, struct lsa_String);
    4069         517 :         NT_STATUS_HAVE_NO_MEMORY(_account_name);
    4070         517 :         _account_name->string = account_name;
    4071             : 
    4072         517 :         if (r->in.authority_name) {
    4073         472 :                 _authority_name = talloc(mem_ctx, struct lsa_String);
    4074         472 :                 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
    4075         472 :                 _authority_name->string = authority_name;
    4076             :         }
    4077             : 
    4078         517 :         *r->out.account_name = _account_name;
    4079         517 :         if (r->out.authority_name) {
    4080         472 :                 *r->out.authority_name = _authority_name;
    4081             :         }
    4082             : 
    4083         517 :         return status;
    4084             : }
    4085             : 
    4086             : /*
    4087             :   lsa_SetInfoPolicy2
    4088             : */
    4089           0 : static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
    4090             :                                    TALLOC_CTX *mem_ctx,
    4091             :                                    struct lsa_SetInfoPolicy2 *r)
    4092             : {
    4093             :         /* need to support these */
    4094           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    4095             : }
    4096             : 
    4097          12 : static void kdc_get_policy(TALLOC_CTX *mem_ctx,
    4098             :                            struct loadparm_context *lp_ctx,
    4099             :                            struct smb_krb5_context *smb_krb5_context,
    4100             :                            struct lsa_DomainInfoKerberos *k)
    4101             : {
    4102             :         time_t svc_tkt_lifetime;
    4103             :         time_t usr_tkt_lifetime;
    4104             :         time_t renewal_lifetime;
    4105             : 
    4106             :         /* Our KDC always re-validates the client */
    4107          12 :         k->authentication_options = LSA_POLICY_KERBEROS_VALIDATE_CLIENT;
    4108             : 
    4109          12 :         lpcfg_default_kdc_policy(mem_ctx, lp_ctx, &svc_tkt_lifetime,
    4110             :                                  &usr_tkt_lifetime, &renewal_lifetime);
    4111             : 
    4112          12 :         unix_to_nt_time(&k->service_tkt_lifetime, svc_tkt_lifetime);
    4113          12 :         unix_to_nt_time(&k->user_tkt_lifetime, usr_tkt_lifetime);
    4114          12 :         unix_to_nt_time(&k->user_tkt_renewaltime, renewal_lifetime);
    4115             : #ifdef SAMBA4_USES_HEIMDAL /* MIT lacks krb5_get_max_time_skew.
    4116             :         However in the parent function we basically just did a full
    4117             :         krb5_context init with the only purpose of getting a global
    4118             :         config option (the max skew), it would probably make more sense
    4119             :         to have a lp_ or ldb global option as the samba default */
    4120           9 :         if (smb_krb5_context) {
    4121           9 :                 unix_to_nt_time(&k->clock_skew,
    4122             :                                 krb5_get_max_time_skew(smb_krb5_context->krb5_context));
    4123             :         }
    4124             : #endif
    4125          12 :         k->reserved = 0;
    4126          12 : }
    4127             : /*
    4128             :   lsa_QueryDomainInformationPolicy
    4129             : */
    4130          24 : static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
    4131             :                                                  TALLOC_CTX *mem_ctx,
    4132             :                                                  struct lsa_QueryDomainInformationPolicy *r)
    4133             : {
    4134             :         union lsa_DomainInformationPolicy *info;
    4135             : 
    4136          24 :         info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
    4137          24 :         if (!info) {
    4138           0 :                 return NT_STATUS_NO_MEMORY;
    4139             :         }
    4140             : 
    4141          24 :         switch (r->in.level) {
    4142          12 :         case LSA_DOMAIN_INFO_POLICY_EFS:
    4143          12 :                 talloc_free(info);
    4144          12 :                 *r->out.info = NULL;
    4145          12 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    4146          12 :         case LSA_DOMAIN_INFO_POLICY_KERBEROS:
    4147             :         {
    4148          12 :                 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
    4149             :                 struct smb_krb5_context *smb_krb5_context;
    4150          12 :                 int ret = smb_krb5_init_context(mem_ctx,
    4151          12 :                                                         dce_call->conn->dce_ctx->lp_ctx,
    4152             :                                                         &smb_krb5_context);
    4153          12 :                 if (ret != 0) {
    4154           0 :                         talloc_free(info);
    4155           0 :                         *r->out.info = NULL;
    4156           0 :                         return NT_STATUS_INTERNAL_ERROR;
    4157             :                 }
    4158          12 :                 kdc_get_policy(mem_ctx, dce_call->conn->dce_ctx->lp_ctx,
    4159             :                                smb_krb5_context,
    4160             :                                k);
    4161          12 :                 talloc_free(smb_krb5_context);
    4162          12 :                 *r->out.info = info;
    4163          12 :                 return NT_STATUS_OK;
    4164             :         }
    4165           0 :         default:
    4166           0 :                 talloc_free(info);
    4167           0 :                 *r->out.info = NULL;
    4168           0 :                 return NT_STATUS_INVALID_INFO_CLASS;
    4169             :         }
    4170             : }
    4171             : 
    4172             : /*
    4173             :   lsa_SetDomInfoPolicy
    4174             : */
    4175           0 : static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
    4176             :                                               TALLOC_CTX *mem_ctx,
    4177             :                                               struct lsa_SetDomainInformationPolicy *r)
    4178             : {
    4179           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    4180             : }
    4181             : 
    4182             : /*
    4183             :   lsa_TestCall
    4184             : */
    4185           0 : static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
    4186             :                              TALLOC_CTX *mem_ctx,
    4187             :                              struct lsa_TestCall *r)
    4188             : {
    4189           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    4190             : }
    4191             : 
    4192             : /*
    4193             :   lsa_CREDRWRITE
    4194             : */
    4195           0 : static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4196             :                        struct lsa_CREDRWRITE *r)
    4197             : {
    4198           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    4199             : }
    4200             : 
    4201             : 
    4202             : /*
    4203             :   lsa_CREDRREAD
    4204             : */
    4205           0 : static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4206             :                        struct lsa_CREDRREAD *r)
    4207             : {
    4208           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    4209             : }
    4210             : 
    4211             : 
    4212             : /*
    4213             :   lsa_CREDRENUMERATE
    4214             : */
    4215           0 : static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4216             :                        struct lsa_CREDRENUMERATE *r)
    4217             : {
    4218           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    4219             : }
    4220             : 
    4221             : 
    4222             : /*
    4223             :   lsa_CREDRWRITEDOMAINCREDENTIALS
    4224             : */
    4225           0 : static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4226             :                        struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
    4227             : {
    4228           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    4229             : }
    4230             : 
    4231             : 
    4232             : /*
    4233             :   lsa_CREDRREADDOMAINCREDENTIALS
    4234             : */
    4235           0 : static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4236             :                        struct lsa_CREDRREADDOMAINCREDENTIALS *r)
    4237             : {
    4238           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    4239             : }
    4240             : 
    4241             : 
    4242             : /*
    4243             :   lsa_CREDRDELETE
    4244             : */
    4245           0 : static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4246             :                        struct lsa_CREDRDELETE *r)
    4247             : {
    4248           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    4249             : }
    4250             : 
    4251             : 
    4252             : /*
    4253             :   lsa_CREDRGETTARGETINFO
    4254             : */
    4255           0 : static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4256             :                        struct lsa_CREDRGETTARGETINFO *r)
    4257             : {
    4258           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    4259             : }
    4260             : 
    4261             : 
    4262             : /*
    4263             :   lsa_CREDRPROFILELOADED
    4264             : */
    4265           0 : static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4266             :                        struct lsa_CREDRPROFILELOADED *r)
    4267             : {
    4268           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    4269             : }
    4270             : 
    4271             : 
    4272             : /*
    4273             :   lsa_CREDRGETSESSIONTYPES
    4274             : */
    4275           0 : static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4276             :                        struct lsa_CREDRGETSESSIONTYPES *r)
    4277             : {
    4278           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    4279             : }
    4280             : 
    4281             : 
    4282             : /*
    4283             :   lsa_LSARREGISTERAUDITEVENT
    4284             : */
    4285           0 : static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4286             :                        struct lsa_LSARREGISTERAUDITEVENT *r)
    4287             : {
    4288           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    4289             : }
    4290             : 
    4291             : 
    4292             : /*
    4293             :   lsa_LSARGENAUDITEVENT
    4294             : */
    4295           0 : static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4296             :                        struct lsa_LSARGENAUDITEVENT *r)
    4297             : {
    4298           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    4299             : }
    4300             : 
    4301             : 
    4302             : /*
    4303             :   lsa_LSARUNREGISTERAUDITEVENT
    4304             : */
    4305           0 : static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4306             :                        struct lsa_LSARUNREGISTERAUDITEVENT *r)
    4307             : {
    4308           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    4309             : }
    4310             : 
    4311             : 
    4312             : /*
    4313             :   lsa_lsaRQueryForestTrustInformation
    4314             : */
    4315          86 : static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4316             :                        struct lsa_lsaRQueryForestTrustInformation *r)
    4317             : {
    4318          86 :         struct dcesrv_handle *h = NULL;
    4319          86 :         struct lsa_policy_state *p_state = NULL;
    4320          86 :         int forest_level = DS_DOMAIN_FUNCTION_2000;
    4321          86 :         const char * const trust_attrs[] = {
    4322             :                 "securityIdentifier",
    4323             :                 "flatName",
    4324             :                 "trustPartner",
    4325             :                 "trustAttributes",
    4326             :                 "trustDirection",
    4327             :                 "trustType",
    4328             :                 "msDS-TrustForestTrustInfo",
    4329             :                 NULL
    4330             :         };
    4331          86 :         struct ldb_message *trust_tdo_msg = NULL;
    4332          86 :         struct lsa_TrustDomainInfoInfoEx *trust_tdo = NULL;
    4333          86 :         struct ForestTrustInfo *trust_fti = NULL;
    4334          86 :         struct lsa_ForestTrustInformation *trust_lfti = NULL;
    4335             :         NTSTATUS status;
    4336             : 
    4337          86 :         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
    4338             : 
    4339          86 :         p_state = h->data;
    4340             : 
    4341          86 :         if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
    4342           0 :                 return NT_STATUS_INVALID_DOMAIN_STATE;
    4343             :         }
    4344             : 
    4345          86 :         forest_level = dsdb_forest_functional_level(p_state->sam_ldb);
    4346          86 :         if (forest_level < DS_DOMAIN_FUNCTION_2003) {
    4347           0 :                 return NT_STATUS_INVALID_DOMAIN_STATE;
    4348             :         }
    4349             : 
    4350          86 :         if (r->in.trusted_domain_name->string == NULL) {
    4351           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;
    4352             :         }
    4353             : 
    4354         172 :         status = dsdb_trust_search_tdo(p_state->sam_ldb,
    4355          86 :                                        r->in.trusted_domain_name->string,
    4356          86 :                                        r->in.trusted_domain_name->string,
    4357             :                                        trust_attrs, mem_ctx, &trust_tdo_msg);
    4358          86 :         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
    4359           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;
    4360             :         }
    4361          86 :         if (!NT_STATUS_IS_OK(status)) {
    4362           0 :                 return status;
    4363             :         }
    4364             : 
    4365          86 :         status = dsdb_trust_parse_tdo_info(mem_ctx, trust_tdo_msg, &trust_tdo);
    4366          86 :         if (!NT_STATUS_IS_OK(status)) {
    4367           0 :                 return status;
    4368             :         }
    4369             : 
    4370          86 :         if (!(trust_tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
    4371           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4372             :         }
    4373             : 
    4374          86 :         if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
    4375           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4376             :         }
    4377             : 
    4378          86 :         status = dsdb_trust_parse_forest_info(mem_ctx,
    4379             :                                               trust_tdo_msg,
    4380             :                                               &trust_fti);
    4381          86 :         if (!NT_STATUS_IS_OK(status)) {
    4382           6 :                 return status;
    4383             :         }
    4384             : 
    4385          80 :         status = dsdb_trust_forest_info_to_lsa(mem_ctx, trust_fti,
    4386             :                                                &trust_lfti);
    4387          80 :         if (!NT_STATUS_IS_OK(status)) {
    4388           0 :                 return status;
    4389             :         }
    4390             : 
    4391          80 :         *r->out.forest_trust_info = trust_lfti;
    4392          80 :         return NT_STATUS_OK;
    4393             : }
    4394             : 
    4395             : /*
    4396             :   lsa_lsaRSetForestTrustInformation
    4397             : */
    4398          49 : static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
    4399             :                                                          TALLOC_CTX *mem_ctx,
    4400             :                                                          struct lsa_lsaRSetForestTrustInformation *r)
    4401             : {
    4402             :         struct dcesrv_handle *h;
    4403             :         struct lsa_policy_state *p_state;
    4404          49 :         const char * const trust_attrs[] = {
    4405             :                 "securityIdentifier",
    4406             :                 "flatName",
    4407             :                 "trustPartner",
    4408             :                 "trustAttributes",
    4409             :                 "trustDirection",
    4410             :                 "trustType",
    4411             :                 "msDS-TrustForestTrustInfo",
    4412             :                 NULL
    4413             :         };
    4414          49 :         struct ldb_message *trust_tdo_msg = NULL;
    4415          49 :         struct lsa_TrustDomainInfoInfoEx *trust_tdo = NULL;
    4416          49 :         struct lsa_ForestTrustInformation *step1_lfti = NULL;
    4417          49 :         struct lsa_ForestTrustInformation *step2_lfti = NULL;
    4418          49 :         struct ForestTrustInfo *trust_fti = NULL;
    4419          49 :         struct ldb_result *trusts_res = NULL;
    4420             :         unsigned int i;
    4421          49 :         struct lsa_TrustDomainInfoInfoEx *xref_tdo = NULL;
    4422          49 :         struct lsa_ForestTrustInformation *xref_lfti = NULL;
    4423          49 :         struct lsa_ForestTrustCollisionInfo *c_info = NULL;
    4424          49 :         DATA_BLOB ft_blob = {};
    4425          49 :         struct ldb_message *msg = NULL;
    4426          49 :         struct server_id *server_ids = NULL;
    4427          49 :         uint32_t num_server_ids = 0;
    4428             :         NTSTATUS status;
    4429             :         enum ndr_err_code ndr_err;
    4430             :         int ret;
    4431          49 :         bool in_transaction = false;
    4432          49 :         struct imessaging_context *imsg_ctx =
    4433          49 :                 dcesrv_imessaging_context(dce_call->conn);
    4434             : 
    4435          49 :         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
    4436             : 
    4437          49 :         p_state = h->data;
    4438             : 
    4439          49 :         if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
    4440           0 :                 return NT_STATUS_INVALID_DOMAIN_STATE;
    4441             :         }
    4442             : 
    4443          49 :         if (r->in.check_only == 0) {
    4444          45 :                 ret = ldb_transaction_start(p_state->sam_ldb);
    4445          45 :                 if (ret != LDB_SUCCESS) {
    4446           0 :                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
    4447             :                 }
    4448          45 :                 in_transaction = true;
    4449             :         }
    4450             : 
    4451             :         /*
    4452             :          * abort if we are not a PDC
    4453             :          *
    4454             :          * In future we should use a function like IsEffectiveRoleOwner()
    4455             :          */
    4456          49 :         if (!samdb_is_pdc(p_state->sam_ldb)) {
    4457           0 :                 status = NT_STATUS_INVALID_DOMAIN_ROLE;
    4458           0 :                 goto done;
    4459             :         }
    4460             : 
    4461          49 :         if (r->in.trusted_domain_name->string == NULL) {
    4462           0 :                 status = NT_STATUS_NO_SUCH_DOMAIN;
    4463           0 :                 goto done;
    4464             :         }
    4465             : 
    4466          98 :         status = dsdb_trust_search_tdo(p_state->sam_ldb,
    4467          49 :                                        r->in.trusted_domain_name->string,
    4468          49 :                                        r->in.trusted_domain_name->string,
    4469             :                                        trust_attrs, mem_ctx, &trust_tdo_msg);
    4470          49 :         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
    4471           0 :                 status = NT_STATUS_NO_SUCH_DOMAIN;
    4472           0 :                 goto done;
    4473             :         }
    4474          49 :         if (!NT_STATUS_IS_OK(status)) {
    4475           0 :                 goto done;
    4476             :         }
    4477             : 
    4478          49 :         status = dsdb_trust_parse_tdo_info(mem_ctx, trust_tdo_msg, &trust_tdo);
    4479          49 :         if (!NT_STATUS_IS_OK(status)) {
    4480           0 :                 goto done;
    4481             :         }
    4482             : 
    4483          49 :         if (!(trust_tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
    4484           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    4485           0 :                 goto done;
    4486             :         }
    4487             : 
    4488          49 :         if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
    4489           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    4490           0 :                 goto done;
    4491             :         }
    4492             : 
    4493             :         /*
    4494             :          * verify and normalize the given forest trust info.
    4495             :          *
    4496             :          * Step1: doesn't reorder yet, so step1_lfti might contain
    4497             :          * NULL entries. This means dsdb_trust_verify_forest_info()
    4498             :          * can generate collision entries with the callers index.
    4499             :          */
    4500          49 :         status = dsdb_trust_normalize_forest_info_step1(mem_ctx,
    4501          49 :                                                         r->in.forest_trust_info,
    4502             :                                                         &step1_lfti);
    4503          49 :         if (!NT_STATUS_IS_OK(status)) {
    4504           0 :                 goto done;
    4505             :         }
    4506             : 
    4507          49 :         c_info = talloc_zero(r->out.collision_info,
    4508             :                              struct lsa_ForestTrustCollisionInfo);
    4509          49 :         if (c_info == NULL) {
    4510           0 :                 status = NT_STATUS_NO_MEMORY;
    4511           0 :                 goto done;
    4512             :         }
    4513             : 
    4514             :         /*
    4515             :          * First check our own forest, then other domains/forests
    4516             :          */
    4517             : 
    4518          49 :         status = dsdb_trust_xref_tdo_info(mem_ctx, p_state->sam_ldb,
    4519             :                                           &xref_tdo);
    4520          49 :         if (!NT_STATUS_IS_OK(status)) {
    4521           0 :                 goto done;
    4522             :         }
    4523          49 :         status = dsdb_trust_xref_forest_info(mem_ctx, p_state->sam_ldb,
    4524             :                                              &xref_lfti);
    4525          49 :         if (!NT_STATUS_IS_OK(status)) {
    4526           0 :                 goto done;
    4527             :         }
    4528             : 
    4529             :         /*
    4530             :          * The documentation proposed to generate
    4531             :          * LSA_FOREST_TRUST_COLLISION_XREF collisions.
    4532             :          * But Windows always uses LSA_FOREST_TRUST_COLLISION_TDO.
    4533             :          */
    4534          49 :         status = dsdb_trust_verify_forest_info(xref_tdo, xref_lfti,
    4535             :                                                LSA_FOREST_TRUST_COLLISION_TDO,
    4536             :                                                c_info, step1_lfti);
    4537          49 :         if (!NT_STATUS_IS_OK(status)) {
    4538           0 :                 goto done;
    4539             :         }
    4540             : 
    4541             :         /* fetch all other trusted domain objects */
    4542          49 :         status = dsdb_trust_search_tdos(p_state->sam_ldb,
    4543          49 :                                         trust_tdo->domain_name.string,
    4544             :                                         trust_attrs,
    4545             :                                         mem_ctx, &trusts_res);
    4546          49 :         if (!NT_STATUS_IS_OK(status)) {
    4547           0 :                 goto done;
    4548             :         }
    4549             : 
    4550             :         /*
    4551             :          * now check against the other domains.
    4552             :          * and generate LSA_FOREST_TRUST_COLLISION_TDO collisions.
    4553             :          */
    4554          49 :         for (i = 0; i < trusts_res->count; i++) {
    4555           0 :                 struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
    4556           0 :                 struct ForestTrustInfo *fti = NULL;
    4557           0 :                 struct lsa_ForestTrustInformation *lfti = NULL;
    4558             : 
    4559           0 :                 status = dsdb_trust_parse_tdo_info(mem_ctx,
    4560           0 :                                                    trusts_res->msgs[i],
    4561             :                                                    &tdo);
    4562           0 :                 if (!NT_STATUS_IS_OK(status)) {
    4563           0 :                         goto done;
    4564             :                 }
    4565             : 
    4566           0 :                 status = dsdb_trust_parse_forest_info(tdo,
    4567           0 :                                                       trusts_res->msgs[i],
    4568             :                                                       &fti);
    4569           0 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
    4570           0 :                         continue;
    4571             :                 }
    4572           0 :                 if (!NT_STATUS_IS_OK(status)) {
    4573           0 :                         goto done;
    4574             :                 }
    4575             : 
    4576           0 :                 status = dsdb_trust_forest_info_to_lsa(tdo, fti, &lfti);
    4577           0 :                 if (!NT_STATUS_IS_OK(status)) {
    4578           0 :                         goto done;
    4579             :                 }
    4580             : 
    4581           0 :                 status = dsdb_trust_verify_forest_info(tdo, lfti,
    4582             :                                                 LSA_FOREST_TRUST_COLLISION_TDO,
    4583             :                                                 c_info, step1_lfti);
    4584           0 :                 if (!NT_STATUS_IS_OK(status)) {
    4585           0 :                         goto done;
    4586             :                 }
    4587             : 
    4588           0 :                 TALLOC_FREE(tdo);
    4589             :         }
    4590             : 
    4591          49 :         if (r->in.check_only != 0) {
    4592           4 :                 status = NT_STATUS_OK;
    4593           4 :                 goto done;
    4594             :         }
    4595             : 
    4596             :         /*
    4597             :          * not just a check, write info back
    4598             :          */
    4599             : 
    4600             :         /*
    4601             :          * normalize the given forest trust info.
    4602             :          *
    4603             :          * Step2: adds TOP_LEVEL_NAME[_EX] in reverse order,
    4604             :          * followed by DOMAIN_INFO in reverse order. It also removes
    4605             :          * possible NULL entries from Step1.
    4606             :          */
    4607          45 :         status = dsdb_trust_normalize_forest_info_step2(mem_ctx, step1_lfti,
    4608             :                                                         &step2_lfti);
    4609          45 :         if (!NT_STATUS_IS_OK(status)) {
    4610           0 :                 goto done;
    4611             :         }
    4612             : 
    4613          45 :         status = dsdb_trust_forest_info_from_lsa(mem_ctx, step2_lfti,
    4614             :                                                  &trust_fti);
    4615          45 :         if (!NT_STATUS_IS_OK(status)) {
    4616           0 :                 goto done;
    4617             :         }
    4618             : 
    4619          45 :         ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, trust_fti,
    4620             :                                        (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
    4621          45 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    4622           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    4623           0 :                 goto done;
    4624             :         }
    4625             : 
    4626          45 :         msg = ldb_msg_new(mem_ctx);
    4627          45 :         if (msg == NULL) {
    4628           0 :                 status = NT_STATUS_NO_MEMORY;
    4629           0 :                 goto done;
    4630             :         }
    4631             : 
    4632          45 :         msg->dn = ldb_dn_copy(mem_ctx, trust_tdo_msg->dn);
    4633          45 :         if (!msg->dn) {
    4634           0 :                 status = NT_STATUS_NO_MEMORY;
    4635           0 :                 goto done;
    4636             :         }
    4637             : 
    4638          45 :         ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
    4639             :                                 LDB_FLAG_MOD_REPLACE, NULL);
    4640          45 :         if (ret != LDB_SUCCESS) {
    4641           0 :                 status = NT_STATUS_NO_MEMORY;
    4642           0 :                 goto done;
    4643             :         }
    4644          45 :         ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
    4645             :                                 &ft_blob, NULL);
    4646          45 :         if (ret != LDB_SUCCESS) {
    4647           0 :                 status = NT_STATUS_NO_MEMORY;
    4648           0 :                 goto done;
    4649             :         }
    4650             : 
    4651          45 :         ret = ldb_modify(p_state->sam_ldb, msg);
    4652          45 :         if (ret != LDB_SUCCESS) {
    4653           0 :                 status = dsdb_ldb_err_to_ntstatus(ret);
    4654             : 
    4655           0 :                 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
    4656             :                           ldb_errstring(p_state->sam_ldb)));
    4657             : 
    4658           0 :                 goto done;
    4659             :         }
    4660             : 
    4661             :         /* ok, all fine, commit transaction and return */
    4662          45 :         in_transaction = false;
    4663          45 :         ret = ldb_transaction_commit(p_state->sam_ldb);
    4664          45 :         if (ret != LDB_SUCCESS) {
    4665           0 :                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
    4666           0 :                 goto done;
    4667             :         }
    4668             : 
    4669             :         /*
    4670             :          * Notify winbindd that we have a acquired forest trust info
    4671             :          */
    4672          45 :         status = irpc_servers_byname(imsg_ctx,
    4673             :                                      mem_ctx,
    4674             :                                      "winbind_server",
    4675             :                                      &num_server_ids,
    4676             :                                      &server_ids);
    4677          45 :         if (!NT_STATUS_IS_OK(status)) {
    4678           0 :                 DBG_ERR("irpc_servers_byname failed\n");
    4679           0 :                 goto done;
    4680             :         }
    4681             : 
    4682          45 :         imessaging_send(imsg_ctx,
    4683             :                         server_ids[0],
    4684             :                         MSG_WINBIND_RELOAD_TRUSTED_DOMAINS,
    4685             :                         NULL);
    4686             : 
    4687          45 :         status = NT_STATUS_OK;
    4688             : 
    4689          49 : done:
    4690          49 :         if (NT_STATUS_IS_OK(status) && c_info->count != 0) {
    4691          10 :                 *r->out.collision_info = c_info;
    4692             :         }
    4693             : 
    4694          49 :         if (in_transaction) {
    4695           0 :                 ldb_transaction_cancel(p_state->sam_ldb);
    4696             :         }
    4697             : 
    4698          49 :         return status;
    4699             : }
    4700             : 
    4701             : /*
    4702             :   lsa_CREDRRENAME
    4703             : */
    4704           0 : static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4705             :                        struct lsa_CREDRRENAME *r)
    4706             : {
    4707           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    4708             : }
    4709             : 
    4710             : 
    4711             : 
    4712             : /*
    4713             :   lsa_LSAROPENPOLICYSCE
    4714             : */
    4715           0 : static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4716             :                        struct lsa_LSAROPENPOLICYSCE *r)
    4717             : {
    4718           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    4719             : }
    4720             : 
    4721             : 
    4722             : /*
    4723             :   lsa_LSARADTREGISTERSECURITYEVENTSOURCE
    4724             : */
    4725           0 : static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4726             :                        struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
    4727             : {
    4728           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    4729             : }
    4730             : 
    4731             : 
    4732             : /*
    4733             :   lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
    4734             : */
    4735           0 : static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4736             :                        struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
    4737             : {
    4738           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    4739             : }
    4740             : 
    4741             : 
    4742             : /*
    4743             :   lsa_LSARADTREPORTSECURITYEVENT
    4744             : */
    4745           0 : static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4746             :                        struct lsa_LSARADTREPORTSECURITYEVENT *r)
    4747             : {
    4748           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    4749             : }
    4750             : 
    4751             : 
    4752             : /* include the generated boilerplate */
    4753             : #include "librpc/gen_ndr/ndr_lsa_s.c"
    4754             : 
    4755             : 
    4756             : 
    4757             : /*****************************************
    4758             : NOTE! The remaining calls below were
    4759             : removed in w2k3, so the DCESRV_FAULT()
    4760             : replies are the correct implementation. Do
    4761             : not try and fill these in with anything else
    4762             : ******************************************/
    4763             : 
    4764             : /*
    4765             :   dssetup_DsRoleDnsNameToFlatName
    4766             : */
    4767           0 : static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4768             :                                         struct dssetup_DsRoleDnsNameToFlatName *r)
    4769             : {
    4770           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    4771             : }
    4772             : 
    4773             : 
    4774             : /*
    4775             :   dssetup_DsRoleDcAsDc
    4776             : */
    4777           0 : static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4778             :                              struct dssetup_DsRoleDcAsDc *r)
    4779             : {
    4780           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    4781             : }
    4782             : 
    4783             : 
    4784             : /*
    4785             :   dssetup_DsRoleDcAsReplica
    4786             : */
    4787           0 : static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4788             :                                   struct dssetup_DsRoleDcAsReplica *r)
    4789             : {
    4790           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    4791             : }
    4792             : 
    4793             : 
    4794             : /*
    4795             :   dssetup_DsRoleDemoteDc
    4796             : */
    4797           0 : static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4798             :                                struct dssetup_DsRoleDemoteDc *r)
    4799             : {
    4800           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    4801             : }
    4802             : 
    4803             : 
    4804             : /*
    4805             :   dssetup_DsRoleGetDcOperationProgress
    4806             : */
    4807           0 : static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4808             :                                              struct dssetup_DsRoleGetDcOperationProgress *r)
    4809             : {
    4810           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    4811             : }
    4812             : 
    4813             : 
    4814             : /* 
    4815             :   dssetup_DsRoleGetDcOperationResults 
    4816             : */
    4817           0 : static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4818             :                                             struct dssetup_DsRoleGetDcOperationResults *r)
    4819             : {
    4820           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    4821             : }
    4822             : 
    4823             : 
    4824             : /* 
    4825             :   dssetup_DsRoleCancel 
    4826             : */
    4827           0 : static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4828             :                              struct dssetup_DsRoleCancel *r)
    4829             : {
    4830           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    4831             : }
    4832             : 
    4833             : 
    4834             : /*
    4835             :   dssetup_DsRoleServerSaveStateForUpgrade
    4836             : */
    4837           0 : static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4838             :                                                 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
    4839             : {
    4840           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    4841             : }
    4842             : 
    4843             : 
    4844             : /*
    4845             :   dssetup_DsRoleUpgradeDownlevelServer
    4846             : */
    4847           0 : static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4848             :                                              struct dssetup_DsRoleUpgradeDownlevelServer *r)
    4849             : {
    4850           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    4851             : }
    4852             : 
    4853             : 
    4854             : /*
    4855             :   dssetup_DsRoleAbortDownlevelServerUpgrade
    4856             : */
    4857           0 : static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
    4858             :                                                   struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
    4859             : {
    4860           0 :         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
    4861             : }
    4862             : 
    4863             : 
    4864             : /* include the generated boilerplate */
    4865             : #include "librpc/gen_ndr/ndr_dssetup_s.c"
    4866             : 
    4867          64 : NTSTATUS dcerpc_server_lsa_init(TALLOC_CTX *ctx)
    4868             : {
    4869             :         NTSTATUS ret;
    4870             : 
    4871          64 :         ret = dcerpc_server_dssetup_init(ctx);
    4872          64 :         if (!NT_STATUS_IS_OK(ret)) {
    4873           0 :                 return ret;
    4874             :         }
    4875          64 :         ret = dcerpc_server_lsarpc_init(ctx);
    4876          64 :         if (!NT_STATUS_IS_OK(ret)) {
    4877           0 :                 return ret;
    4878             :         }
    4879          64 :         return ret;
    4880             : }

Generated by: LCOV version 1.13