LCOV - code coverage report
Current view: top level - source4/rpc_server/lsa - lsa_init.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 89 111 80.2 %
Date: 2024-06-13 04:01:37 Functions: 3 3 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        3056 : 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        1998 :         struct auth_session_info *session_info =
      55        1058 :                 dcesrv_call_session_info(dce_call);
      56             :         enum security_user_level security_level;
      57             :         struct lsa_policy_state *state;
      58             :         struct ldb_result *dom_res;
      59        3056 :         const char *dom_attrs[] = {
      60             :                 "objectSid", 
      61             :                 "objectGUID", 
      62             :                 "nTMixedDomain",
      63             :                 "fSMORoleOwner",
      64             :                 NULL
      65             :         };
      66             :         char *p;
      67             :         int ret;
      68             : 
      69        3056 :         state = talloc_zero(mem_ctx, struct lsa_policy_state);
      70        3056 :         if (!state) {
      71           0 :                 return NT_STATUS_NO_MEMORY;
      72             :         }
      73             : 
      74             :         /* make sure the sam database is accessible */
      75        3056 :         state->sam_ldb = dcesrv_samdb_connect_as_user(state, dce_call);
      76        3056 :         if (state->sam_ldb == NULL) {
      77           0 :                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
      78             :         }
      79             : 
      80             :         /* and the privilege database */
      81        3056 :         state->pdb = privilege_connect(state, dce_call->conn->dce_ctx->lp_ctx);
      82        3056 :         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        3056 :         state->domain_dn = ldb_get_default_basedn(state->sam_ldb);
      89        3056 :         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        3056 :         state->forest_dn = ldb_get_root_basedn(state->sam_ldb);
      96        3056 :         if (!state->forest_dn) {
      97           0 :                 return NT_STATUS_NO_MEMORY;             
      98             :         }
      99             : 
     100        3056 :         ret = ldb_search(state->sam_ldb, mem_ctx, &dom_res,
     101             :                          state->domain_dn, LDB_SCOPE_BASE, dom_attrs, NULL);
     102        3056 :         if (ret != LDB_SUCCESS) {
     103           0 :                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
     104             :         }
     105        3056 :         if (dom_res->count != 1) {
     106           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;                
     107             :         }
     108             : 
     109        3056 :         state->domain_sid = samdb_result_dom_sid(state, dom_res->msgs[0], "objectSid");
     110        3056 :         if (!state->domain_sid) {
     111           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;                
     112             :         }
     113             : 
     114        3056 :         state->domain_guid = samdb_result_guid(dom_res->msgs[0], "objectGUID");
     115             : 
     116        3056 :         state->mixed_domain = ldb_msg_find_attr_as_uint(dom_res->msgs[0], "nTMixedDomain", 0);
     117             :         
     118        3056 :         talloc_free(dom_res);
     119             : 
     120        3056 :         state->domain_name = lpcfg_sam_name(dce_call->conn->dce_ctx->lp_ctx);
     121             : 
     122        3056 :         state->domain_dns = ldb_dn_canonical_string(state, state->domain_dn);
     123        3056 :         if (!state->domain_dns) {
     124           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;                
     125             :         }
     126        3056 :         p = strchr(state->domain_dns, '/');
     127        3056 :         if (p) {
     128        3056 :                 *p = '\0';
     129             :         }
     130             : 
     131        3056 :         state->forest_dns = ldb_dn_canonical_string(state, state->forest_dn);
     132        3056 :         if (!state->forest_dns) {
     133           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;                
     134             :         }
     135        3056 :         p = strchr(state->forest_dns, '/');
     136        3056 :         if (p) {
     137        3056 :                 *p = '\0';
     138             :         }
     139             : 
     140             :         /* work out the builtin_dn - useful for so many calls its worth
     141             :            fetching here */
     142        3056 :         state->builtin_dn = samdb_search_dn(state->sam_ldb, state, state->domain_dn, "(objectClass=builtinDomain)");
     143        3056 :         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        3056 :         state->system_dn = samdb_system_container_dn(state->sam_ldb, state);
     150        3056 :         if (state->system_dn == NULL) {
     151           0 :                 return NT_STATUS_NO_MEMORY;
     152             :         }
     153             : 
     154        3056 :         state->builtin_sid = dom_sid_parse_talloc(state, SID_BUILTIN);
     155        3056 :         if (!state->builtin_sid) {
     156           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;                
     157             :         }
     158             : 
     159        3056 :         state->nt_authority_sid = dom_sid_parse_talloc(state, SID_NT_AUTHORITY);
     160        3056 :         if (!state->nt_authority_sid) {
     161           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;                
     162             :         }
     163             : 
     164        3056 :         state->creator_owner_domain_sid = dom_sid_parse_talloc(state, SID_CREATOR_OWNER_DOMAIN);
     165        3056 :         if (!state->creator_owner_domain_sid) {
     166           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;                
     167             :         }
     168             : 
     169        3056 :         state->world_domain_sid = dom_sid_parse_talloc(state, SID_WORLD_DOMAIN);
     170        3056 :         if (!state->world_domain_sid) {
     171           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;                
     172             :         }
     173             : 
     174        4114 :         state->sd = sddl_decode(state, DCESRV_LSA_POLICY_SD_SDDL,
     175        3056 :                                 state->domain_sid);
     176        3056 :         if (state->sd == NULL) {
     177           0 :                 return NT_STATUS_NO_MEMORY;
     178             :         }
     179        3056 :         state->sd->dacl->revision = SECURITY_ACL_REVISION_NT4;
     180             : 
     181        3056 :         se_map_generic(&access_desired, &dcesrv_lsa_policy_mapping);
     182        3056 :         security_acl_map_generic(state->sd->dacl, &dcesrv_lsa_policy_mapping);
     183             : 
     184        3056 :         security_level = security_session_user_level(session_info, NULL);
     185        3056 :         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         381 :                 state->access_mask = access_desired;
     191         381 :                 if (state->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
     192         259 :                         state->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
     193         259 :                         state->access_mask |= LSA_POLICY_ALL_ACCESS;
     194             :                 }
     195             :         } else {
     196             :                 NTSTATUS status;
     197             : 
     198        4413 :                 status = se_access_check(state->sd,
     199        2675 :                                          session_info->security_token,
     200             :                                          access_desired,
     201             :                                          &state->access_mask);
     202        2675 :                 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        3056 :         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        3056 :         *_state = state;
     218             : 
     219        3056 :         return NT_STATUS_OK;
     220             : }
     221             : 
     222             : /* 
     223             :   lsa_OpenPolicy2
     224             : */
     225        2847 : NTSTATUS dcesrv_lsa_OpenPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     226             :                                 struct lsa_OpenPolicy2 *r)
     227             : {
     228        1828 :         enum dcerpc_transport_t transport =
     229        2847 :                 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
     230             :         NTSTATUS status;
     231             :         struct lsa_policy_state *state;
     232             :         struct dcesrv_handle *handle;
     233             : 
     234        2847 :         if (transport != NCACN_NP && transport != NCALRPC) {
     235           3 :                 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
     236             :         }
     237             : 
     238        2844 :         ZERO_STRUCTP(r->out.handle);
     239             : 
     240        4669 :         if (r->in.attr != NULL &&
     241        2844 :             r->in.attr->root_dir != NULL) {
     242             :                 /* MS-LSAD 3.1.4.4.1 */
     243           0 :                 return NT_STATUS_INVALID_PARAMETER;
     244             :         }
     245             : 
     246        2844 :         status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx,
     247             :                                              r->in.access_mask,
     248             :                                              &state);
     249        2844 :         if (!NT_STATUS_IS_OK(status)) {
     250           0 :                 return status;
     251             :         }
     252             : 
     253        2844 :         handle = dcesrv_handle_create(dce_call, LSA_HANDLE_POLICY);
     254        2844 :         if (!handle) {
     255           0 :                 return NT_STATUS_NO_MEMORY;
     256             :         }
     257             : 
     258        2844 :         handle->data = talloc_steal(handle, state);
     259             : 
     260        2844 :         state->handle = handle;
     261        2844 :         *r->out.handle = handle->wire_handle;
     262             : 
     263             :         /* note that we have completely ignored the attr element of
     264             :            the OpenPolicy. As far as I can tell, this is what w2k3
     265             :            does */
     266             : 
     267        2844 :         return NT_STATUS_OK;
     268             : }
     269             : 
     270             : /* 
     271             :   lsa_OpenPolicy
     272             :   a wrapper around lsa_OpenPolicy2
     273             : */
     274         580 : NTSTATUS dcesrv_lsa_OpenPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     275             :                                 struct lsa_OpenPolicy *r)
     276             : {
     277         369 :         enum dcerpc_transport_t transport =
     278         580 :                 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
     279             :         struct lsa_OpenPolicy2 r2;
     280             : 
     281         580 :         if (transport != NCACN_NP && transport != NCALRPC) {
     282           3 :                 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
     283             :         }
     284             : 
     285         577 :         r2.in.system_name = NULL;
     286         577 :         r2.in.attr = r->in.attr;
     287         577 :         r2.in.access_mask = r->in.access_mask;
     288         577 :         r2.out.handle = r->out.handle;
     289             : 
     290         577 :         return dcesrv_lsa_OpenPolicy2(dce_call, mem_ctx, &r2);
     291             : }
     292             : 
     293             : 

Generated by: LCOV version 1.13