LCOV - code coverage report
Current view: top level - source4/rpc_server/lsa - lsa_init.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 123 150 82.0 %
Date: 2024-05-31 13:13:24 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    endpoint server for the lsarpc pipe
       5             : 
       6             :    Copyright (C) Andrew Tridgell 2004
       7             :    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2007
       8             : 
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : #include "rpc_server/lsa/lsa.h"
      24             : 
      25             : /*
      26             :  * This matches a Windows 2012R2 dc in
      27             :  * a domain with function level 2012R2.
      28             :  */
      29             : #define DCESRV_LSA_POLICY_SD_SDDL \
      30             :         "O:BAG:SY" \
      31             :         "D:" \
      32             :         "(D;;0x00000800;;;AN)" \
      33             :         "(A;;0x000f1fff;;;BA)" \
      34             :         "(A;;0x00020801;;;WD)" \
      35             :         "(A;;0x00000801;;;AN)" \
      36             :         "(A;;0x00001000;;;LS)" \
      37             :         "(A;;0x00001000;;;NS)" \
      38             :         "(A;;0x00001000;;;S-1-5-17)" \
      39             :         "(A;;0x00000801;;;AC)" \
      40             :         "(A;;0x00000801;;;S-1-15-2-2)"
      41             : 
      42             : static const struct generic_mapping dcesrv_lsa_policy_mapping = {
      43             :         LSA_POLICY_READ,
      44             :         LSA_POLICY_WRITE,
      45             :         LSA_POLICY_EXECUTE,
      46             :         LSA_POLICY_ALL_ACCESS
      47             : };
      48             : 
      49        3529 : NTSTATUS dcesrv_lsa_get_policy_state(struct dcesrv_call_state *dce_call,
      50             :                                      TALLOC_CTX *mem_ctx,
      51             :                                      uint32_t access_desired,
      52             :                                      struct lsa_policy_state **_state)
      53             : {
      54         147 :         struct auth_session_info *session_info =
      55        3529 :                 dcesrv_call_session_info(dce_call);
      56         147 :         enum security_user_level security_level;
      57         147 :         struct lsa_policy_state *state;
      58         147 :         struct ldb_result *dom_res;
      59        3529 :         const char *dom_attrs[] = {
      60             :                 "objectSid",
      61             :                 "objectGUID",
      62             :                 "nTMixedDomain",
      63             :                 "fSMORoleOwner",
      64             :                 NULL
      65             :         };
      66         147 :         char *p;
      67         147 :         int ret;
      68             : 
      69        3529 :         state = talloc_zero(mem_ctx, struct lsa_policy_state);
      70        3529 :         if (!state) {
      71           0 :                 return NT_STATUS_NO_MEMORY;
      72             :         }
      73             : 
      74             :         /* make sure the sam database is accessible */
      75        3529 :         state->sam_ldb = dcesrv_samdb_connect_as_user(state, dce_call);
      76        3529 :         if (state->sam_ldb == NULL) {
      77           0 :                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
      78             :         }
      79             : 
      80             :         /* and the privilege database */
      81        3529 :         state->pdb = privilege_connect(state, dce_call->conn->dce_ctx->lp_ctx);
      82        3529 :         if (state->pdb == NULL) {
      83           0 :                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
      84             :         }
      85             : 
      86             :         /* work out the domain_dn - useful for so many calls its worth
      87             :            fetching here */
      88        3529 :         state->domain_dn = ldb_get_default_basedn(state->sam_ldb);
      89        3529 :         if (!state->domain_dn) {
      90           0 :                 return NT_STATUS_NO_MEMORY;
      91             :         }
      92             : 
      93             :         /* work out the forest root_dn - useful for so many calls its worth
      94             :            fetching here */
      95        3529 :         state->forest_dn = ldb_get_root_basedn(state->sam_ldb);
      96        3529 :         if (!state->forest_dn) {
      97           0 :                 return NT_STATUS_NO_MEMORY;
      98             :         }
      99             : 
     100        3529 :         ret = ldb_search(state->sam_ldb, mem_ctx, &dom_res,
     101             :                          state->domain_dn, LDB_SCOPE_BASE, dom_attrs, NULL);
     102        3529 :         if (ret != LDB_SUCCESS) {
     103           0 :                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
     104             :         }
     105        3529 :         if (dom_res->count != 1) {
     106           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;
     107             :         }
     108             : 
     109        3529 :         state->domain_sid = samdb_result_dom_sid(state, dom_res->msgs[0], "objectSid");
     110        3529 :         if (!state->domain_sid) {
     111           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;
     112             :         }
     113             : 
     114        3529 :         state->domain_guid = samdb_result_guid(dom_res->msgs[0], "objectGUID");
     115             : 
     116        3529 :         state->mixed_domain = ldb_msg_find_attr_as_uint(dom_res->msgs[0], "nTMixedDomain", 0);
     117             : 
     118        3529 :         talloc_free(dom_res);
     119             : 
     120        3529 :         state->domain_name = lpcfg_sam_name(dce_call->conn->dce_ctx->lp_ctx);
     121             : 
     122        3529 :         state->domain_dns = ldb_dn_canonical_string(state, state->domain_dn);
     123        3529 :         if (!state->domain_dns) {
     124           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;
     125             :         }
     126        3529 :         p = strchr(state->domain_dns, '/');
     127        3529 :         if (p) {
     128        3529 :                 *p = '\0';
     129             :         }
     130             : 
     131        3529 :         state->forest_dns = ldb_dn_canonical_string(state, state->forest_dn);
     132        3529 :         if (!state->forest_dns) {
     133           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;
     134             :         }
     135        3529 :         p = strchr(state->forest_dns, '/');
     136        3529 :         if (p) {
     137        3529 :                 *p = '\0';
     138             :         }
     139             : 
     140             :         /* work out the builtin_dn - useful for so many calls its worth
     141             :            fetching here */
     142        3529 :         state->builtin_dn = samdb_search_dn(state->sam_ldb, state, state->domain_dn, "(objectClass=builtinDomain)");
     143        3529 :         if (!state->builtin_dn) {
     144           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;
     145             :         }
     146             : 
     147             :         /* work out the system_dn - useful for so many calls its worth
     148             :            fetching here */
     149        3529 :         state->system_dn = samdb_system_container_dn(state->sam_ldb, state);
     150        3529 :         if (state->system_dn == NULL) {
     151           0 :                 return NT_STATUS_NO_MEMORY;
     152             :         }
     153             : 
     154        3529 :         state->builtin_sid = dom_sid_parse_talloc(state, SID_BUILTIN);
     155        3529 :         if (!state->builtin_sid) {
     156           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;
     157             :         }
     158             : 
     159        3529 :         state->nt_authority_sid = dom_sid_parse_talloc(state, SID_NT_AUTHORITY);
     160        3529 :         if (!state->nt_authority_sid) {
     161           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;
     162             :         }
     163             : 
     164        3529 :         state->creator_owner_domain_sid = dom_sid_parse_talloc(state, SID_CREATOR_OWNER_DOMAIN);
     165        3529 :         if (!state->creator_owner_domain_sid) {
     166           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;
     167             :         }
     168             : 
     169        3529 :         state->world_domain_sid = dom_sid_parse_talloc(state, SID_WORLD_DOMAIN);
     170        3529 :         if (!state->world_domain_sid) {
     171           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;
     172             :         }
     173             : 
     174        7058 :         state->sd = sddl_decode(state, DCESRV_LSA_POLICY_SD_SDDL,
     175        3529 :                                 state->domain_sid);
     176        3529 :         if (state->sd == NULL) {
     177           0 :                 return NT_STATUS_NO_MEMORY;
     178             :         }
     179        3529 :         state->sd->dacl->revision = SECURITY_ACL_REVISION_NT4;
     180             : 
     181        3529 :         se_map_generic(&access_desired, &dcesrv_lsa_policy_mapping);
     182        3529 :         security_acl_map_generic(state->sd->dacl, &dcesrv_lsa_policy_mapping);
     183             : 
     184        3529 :         security_level = security_session_user_level(session_info, NULL);
     185        3529 :         if (security_level >= SECURITY_SYSTEM) {
     186             :                 /*
     187             :                  * The security descriptor doesn't allow system,
     188             :                  * but we want to allow system via ncalrpc as root.
     189             :                  */
     190         524 :                 state->access_mask = access_desired;
     191         524 :                 if (state->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
     192         392 :                         state->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
     193         392 :                         state->access_mask |= LSA_POLICY_ALL_ACCESS;
     194             :                 }
     195             :         } else {
     196         141 :                 NTSTATUS status;
     197             : 
     198        3005 :                 status = se_access_check(state->sd,
     199        3005 :                                          session_info->security_token,
     200             :                                          access_desired,
     201             :                                          &state->access_mask);
     202        3005 :                 if (!NT_STATUS_IS_OK(status)) {
     203           0 :                         DEBUG(2,("%s: access desired[0x%08X] rejected[0x%08X] - %s\n",
     204             :                                  __func__,
     205             :                                  (unsigned)access_desired,
     206             :                                  (unsigned)state->access_mask,
     207             :                                  nt_errstr(status)));
     208           0 :                         return status;
     209             :                 }
     210             :         }
     211             : 
     212        3529 :         DEBUG(10,("%s: access desired[0x%08X] granted[0x%08X] - success.\n",
     213             :                   __func__,
     214             :                  (unsigned)access_desired,
     215             :                  (unsigned)state->access_mask));
     216             : 
     217        3529 :         *_state = state;
     218             : 
     219        3529 :         return NT_STATUS_OK;
     220             : }
     221             : 
     222             : /*
     223             :   lsa_OpenPolicy3
     224             : */
     225         300 : NTSTATUS dcesrv_lsa_OpenPolicy3(struct dcesrv_call_state *dce_call,
     226             :                                 TALLOC_CTX *mem_ctx,
     227             :                                 struct lsa_OpenPolicy3 *r)
     228             : {
     229           2 :         enum dcerpc_transport_t transport =
     230         300 :                 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
     231         300 :         struct lsa_policy_state *state = NULL;
     232         300 :         struct dcesrv_handle *handle = NULL;
     233           2 :         NTSTATUS status;
     234             : 
     235         300 :         if (transport != NCACN_NP && transport != NCALRPC) {
     236           3 :                 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
     237             :         }
     238             : 
     239         297 :         ZERO_STRUCTP(r->out.handle);
     240             : 
     241             :         /*
     242             :          * The attributes have no effect and MUST be ignored, except the
     243             :          * root_dir which MUST be NULL.
     244             :          */
     245         297 :         if (r->in.attr != NULL && r->in.attr->root_dir != NULL) {
     246           0 :                 return NT_STATUS_INVALID_PARAMETER;
     247             :         }
     248             : 
     249         297 :         switch (r->in.in_version) {
     250         297 :         case 1:
     251         297 :                 *r->out.out_version = 1;
     252             : 
     253         297 :                 r->out.out_revision_info->info1.revision = 1;
     254         297 :                 r->out.out_revision_info->info1.supported_features =
     255             :                                 LSA_FEATURE_TDO_AUTH_INFO_AES_CIPHER;
     256             : 
     257         297 :                 break;
     258           0 :         default:
     259           0 :                 return NT_STATUS_NOT_SUPPORTED;
     260             :         }
     261             : 
     262         297 :         status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx,
     263             :                                              r->in.access_mask,
     264             :                                              &state);
     265         297 :         if (!NT_STATUS_IS_OK(status)) {
     266           0 :                 return status;
     267             :         }
     268             : 
     269         297 :         handle = dcesrv_handle_create(dce_call, LSA_HANDLE_POLICY);
     270         297 :         if (handle == NULL) {
     271           0 :                 return NT_STATUS_NO_MEMORY;
     272             :         }
     273         297 :         handle->data = talloc_steal(handle, state);
     274             : 
     275         297 :         state->handle = handle;
     276         297 :         *r->out.handle = handle->wire_handle;
     277             : 
     278         297 :         return NT_STATUS_OK;
     279             : }
     280             : 
     281             : /*
     282             :   lsa_OpenPolicy2
     283             : */
     284        2864 : NTSTATUS dcesrv_lsa_OpenPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     285             :                                 struct lsa_OpenPolicy2 *r)
     286             : {
     287          94 :         enum dcerpc_transport_t transport =
     288        2864 :                 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
     289          94 :         NTSTATUS status;
     290          94 :         struct lsa_policy_state *state;
     291          94 :         struct dcesrv_handle *handle;
     292             : 
     293        2864 :         if (transport != NCACN_NP && transport != NCALRPC) {
     294           3 :                 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
     295             :         }
     296             : 
     297        2861 :         ZERO_STRUCTP(r->out.handle);
     298             : 
     299        2861 :         if (r->in.attr != NULL &&
     300        2861 :             r->in.attr->root_dir != NULL) {
     301             :                 /* MS-LSAD 3.1.4.4.1 */
     302           0 :                 return NT_STATUS_INVALID_PARAMETER;
     303             :         }
     304             : 
     305        2861 :         status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx,
     306             :                                              r->in.access_mask,
     307             :                                              &state);
     308        2861 :         if (!NT_STATUS_IS_OK(status)) {
     309           0 :                 return status;
     310             :         }
     311             : 
     312        2861 :         handle = dcesrv_handle_create(dce_call, LSA_HANDLE_POLICY);
     313        2861 :         if (!handle) {
     314           0 :                 return NT_STATUS_NO_MEMORY;
     315             :         }
     316             : 
     317        2861 :         handle->data = talloc_steal(handle, state);
     318             : 
     319        2861 :         state->handle = handle;
     320        2861 :         *r->out.handle = handle->wire_handle;
     321             : 
     322             :         /* note that we have completely ignored the attr element of
     323             :            the OpenPolicy. As far as I can tell, this is what w2k3
     324             :            does */
     325             : 
     326        2861 :         return NT_STATUS_OK;
     327             : }
     328             : 
     329             : /*
     330             :   lsa_OpenPolicy
     331             :   a wrapper around lsa_OpenPolicy2
     332             : */
     333         786 : NTSTATUS dcesrv_lsa_OpenPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     334             :                                 struct lsa_OpenPolicy *r)
     335             : {
     336          13 :         enum dcerpc_transport_t transport =
     337         786 :                 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
     338          13 :         struct lsa_OpenPolicy2 r2;
     339             : 
     340         786 :         if (transport != NCACN_NP && transport != NCALRPC) {
     341           3 :                 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
     342             :         }
     343             : 
     344         783 :         r2 = (struct lsa_OpenPolicy2) {
     345         783 :                 .in.attr = r->in.attr,
     346         783 :                 .in.access_mask = r->in.access_mask,
     347         783 :                 .out.handle = r->out.handle,
     348             :         };
     349             : 
     350         783 :         return dcesrv_lsa_OpenPolicy2(dce_call, mem_ctx, &r2);
     351             : }
     352             : 
     353             : 

Generated by: LCOV version 1.14