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 6248eab5 Lines: 90 112 80.4 %
Date: 2021-08-25 13:27:56 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;;GA;;;BA)" \
      34             :         "(A;;GX;;;WD)" \
      35             :         "(A;;0x00000801;;;AN)" \
      36             :         "(A;;0x00001000;;;LS)" \
      37             :         "(A;;0x00001000;;;NS)" \
      38             :         "(A;;0x00001000;;;IS)" \
      39             :         "(A;;0x00000801;;;S-1-15-2-1)"
      40             : 
      41             : static const struct generic_mapping dcesrv_lsa_policy_mapping = {
      42             :         LSA_POLICY_READ,
      43             :         LSA_POLICY_WRITE,
      44             :         LSA_POLICY_EXECUTE,
      45             :         LSA_POLICY_ALL_ACCESS
      46             : };
      47             : 
      48        4460 : NTSTATUS dcesrv_lsa_get_policy_state(struct dcesrv_call_state *dce_call,
      49             :                                      TALLOC_CTX *mem_ctx,
      50             :                                      uint32_t access_desired,
      51             :                                      struct lsa_policy_state **_state)
      52             : {
      53        4460 :         struct auth_session_info *session_info =
      54             :                 dcesrv_call_session_info(dce_call);
      55             :         enum security_user_level security_level;
      56             :         struct lsa_policy_state *state;
      57             :         struct ldb_result *dom_res;
      58        4460 :         const char *dom_attrs[] = {
      59             :                 "objectSid", 
      60             :                 "objectGUID", 
      61             :                 "nTMixedDomain",
      62             :                 "fSMORoleOwner",
      63             :                 NULL
      64             :         };
      65             :         char *p;
      66             :         int ret;
      67             : 
      68        4460 :         state = talloc_zero(mem_ctx, struct lsa_policy_state);
      69        4460 :         if (!state) {
      70           0 :                 return NT_STATUS_NO_MEMORY;
      71             :         }
      72             : 
      73             :         /* make sure the sam database is accessible */
      74        8920 :         state->sam_ldb = samdb_connect(state,
      75             :                                        dce_call->event_ctx,
      76        4460 :                                        dce_call->conn->dce_ctx->lp_ctx,
      77             :                                        session_info,
      78        4460 :                                        dce_call->conn->remote_address,
      79             :                                        0);
      80        4460 :         if (state->sam_ldb == NULL) {
      81           0 :                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
      82             :         }
      83             : 
      84             :         /* and the privilege database */
      85        4460 :         state->pdb = privilege_connect(state, dce_call->conn->dce_ctx->lp_ctx);
      86        4460 :         if (state->pdb == NULL) {
      87           0 :                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
      88             :         }
      89             : 
      90             :         /* work out the domain_dn - useful for so many calls its worth
      91             :            fetching here */
      92        4460 :         state->domain_dn = ldb_get_default_basedn(state->sam_ldb);
      93        4460 :         if (!state->domain_dn) {
      94           0 :                 return NT_STATUS_NO_MEMORY;             
      95             :         }
      96             : 
      97             :         /* work out the forest root_dn - useful for so many calls its worth
      98             :            fetching here */
      99        4460 :         state->forest_dn = ldb_get_root_basedn(state->sam_ldb);
     100        4460 :         if (!state->forest_dn) {
     101           0 :                 return NT_STATUS_NO_MEMORY;             
     102             :         }
     103             : 
     104        4460 :         ret = ldb_search(state->sam_ldb, mem_ctx, &dom_res,
     105             :                          state->domain_dn, LDB_SCOPE_BASE, dom_attrs, NULL);
     106        4460 :         if (ret != LDB_SUCCESS) {
     107           0 :                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
     108             :         }
     109        4460 :         if (dom_res->count != 1) {
     110           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;                
     111             :         }
     112             : 
     113        4460 :         state->domain_sid = samdb_result_dom_sid(state, dom_res->msgs[0], "objectSid");
     114        4460 :         if (!state->domain_sid) {
     115           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;                
     116             :         }
     117             : 
     118        4460 :         state->domain_guid = samdb_result_guid(dom_res->msgs[0], "objectGUID");
     119             : 
     120        4460 :         state->mixed_domain = ldb_msg_find_attr_as_uint(dom_res->msgs[0], "nTMixedDomain", 0);
     121             :         
     122        4460 :         talloc_free(dom_res);
     123             : 
     124        4460 :         state->domain_name = lpcfg_sam_name(dce_call->conn->dce_ctx->lp_ctx);
     125             : 
     126        4460 :         state->domain_dns = ldb_dn_canonical_string(state, state->domain_dn);
     127        4460 :         if (!state->domain_dns) {
     128           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;                
     129             :         }
     130        4460 :         p = strchr(state->domain_dns, '/');
     131        4460 :         if (p) {
     132        4460 :                 *p = '\0';
     133             :         }
     134             : 
     135        4460 :         state->forest_dns = ldb_dn_canonical_string(state, state->forest_dn);
     136        4460 :         if (!state->forest_dns) {
     137           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;                
     138             :         }
     139        4460 :         p = strchr(state->forest_dns, '/');
     140        4460 :         if (p) {
     141        4460 :                 *p = '\0';
     142             :         }
     143             : 
     144             :         /* work out the builtin_dn - useful for so many calls its worth
     145             :            fetching here */
     146        4460 :         state->builtin_dn = samdb_search_dn(state->sam_ldb, state, state->domain_dn, "(objectClass=builtinDomain)");
     147        4460 :         if (!state->builtin_dn) {
     148           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;                
     149             :         }
     150             : 
     151             :         /* work out the system_dn - useful for so many calls its worth
     152             :            fetching here */
     153        4460 :         state->system_dn = samdb_search_dn(state->sam_ldb, state,
     154             :                                            state->domain_dn, "(&(objectClass=container)(cn=System))");
     155        4460 :         if (!state->system_dn) {
     156           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;                
     157             :         }
     158             : 
     159        4460 :         state->builtin_sid = dom_sid_parse_talloc(state, SID_BUILTIN);
     160        4460 :         if (!state->builtin_sid) {
     161           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;                
     162             :         }
     163             : 
     164        4460 :         state->nt_authority_sid = dom_sid_parse_talloc(state, SID_NT_AUTHORITY);
     165        4460 :         if (!state->nt_authority_sid) {
     166           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;                
     167             :         }
     168             : 
     169        4460 :         state->creator_owner_domain_sid = dom_sid_parse_talloc(state, SID_CREATOR_OWNER_DOMAIN);
     170        4460 :         if (!state->creator_owner_domain_sid) {
     171           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;                
     172             :         }
     173             : 
     174        4460 :         state->world_domain_sid = dom_sid_parse_talloc(state, SID_WORLD_DOMAIN);
     175        4460 :         if (!state->world_domain_sid) {
     176           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;                
     177             :         }
     178             : 
     179        4460 :         state->sd = sddl_decode(state, DCESRV_LSA_POLICY_SD_SDDL,
     180        4460 :                                 state->domain_sid);
     181        4460 :         if (state->sd == NULL) {
     182           0 :                 return NT_STATUS_NO_MEMORY;
     183             :         }
     184        4460 :         state->sd->dacl->revision = SECURITY_ACL_REVISION_NT4;
     185             : 
     186        4460 :         se_map_generic(&access_desired, &dcesrv_lsa_policy_mapping);
     187        4460 :         security_acl_map_generic(state->sd->dacl, &dcesrv_lsa_policy_mapping);
     188             : 
     189        4460 :         security_level = security_session_user_level(session_info, NULL);
     190        4460 :         if (security_level >= SECURITY_SYSTEM) {
     191             :                 /*
     192             :                  * The security descriptor doesn't allow system,
     193             :                  * but we want to allow system via ncalrpc as root.
     194             :                  */
     195         241 :                 state->access_mask = access_desired;
     196         241 :                 if (state->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
     197         127 :                         state->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
     198         127 :                         state->access_mask |= LSA_POLICY_ALL_ACCESS;
     199             :                 }
     200             :         } else {
     201             :                 NTSTATUS status;
     202             : 
     203        8438 :                 status = se_access_check(state->sd,
     204        4219 :                                          session_info->security_token,
     205             :                                          access_desired,
     206             :                                          &state->access_mask);
     207        4219 :                 if (!NT_STATUS_IS_OK(status)) {
     208           0 :                         DEBUG(2,("%s: access desired[0x%08X] rejected[0x%08X] - %s\n",
     209             :                                  __func__,
     210             :                                  (unsigned)access_desired,
     211             :                                  (unsigned)state->access_mask,
     212             :                                  nt_errstr(status)));
     213           0 :                         return status;
     214             :                 }
     215             :         }
     216             : 
     217        4460 :         DEBUG(10,("%s: access desired[0x%08X] granted[0x%08X] - success.\n",
     218             :                   __func__,
     219             :                  (unsigned)access_desired,
     220             :                  (unsigned)state->access_mask));
     221             : 
     222        4460 :         *_state = state;
     223             : 
     224        4460 :         return NT_STATUS_OK;
     225             : }
     226             : 
     227             : /* 
     228             :   lsa_OpenPolicy2
     229             : */
     230        3162 : NTSTATUS dcesrv_lsa_OpenPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     231             :                                 struct lsa_OpenPolicy2 *r)
     232             : {
     233        3162 :         enum dcerpc_transport_t transport =
     234        3162 :                 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
     235             :         NTSTATUS status;
     236             :         struct lsa_policy_state *state;
     237             :         struct dcesrv_handle *handle;
     238             : 
     239        3162 :         if (transport != NCACN_NP && transport != NCALRPC) {
     240           5 :                 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
     241             :         }
     242             : 
     243        3157 :         ZERO_STRUCTP(r->out.handle);
     244             : 
     245        6314 :         if (r->in.attr != NULL &&
     246        3157 :             r->in.attr->root_dir != NULL) {
     247             :                 /* MS-LSAD 3.1.4.4.1 */
     248           0 :                 return NT_STATUS_INVALID_PARAMETER;
     249             :         }
     250             : 
     251        3157 :         status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx,
     252             :                                              r->in.access_mask,
     253             :                                              &state);
     254        3157 :         if (!NT_STATUS_IS_OK(status)) {
     255           0 :                 return status;
     256             :         }
     257             : 
     258        3157 :         handle = dcesrv_handle_create(dce_call, LSA_HANDLE_POLICY);
     259        3157 :         if (!handle) {
     260           0 :                 return NT_STATUS_NO_MEMORY;
     261             :         }
     262             : 
     263        3157 :         handle->data = talloc_steal(handle, state);
     264             : 
     265        3157 :         state->handle = handle;
     266        3157 :         *r->out.handle = handle->wire_handle;
     267             : 
     268             :         /* note that we have completely ignored the attr element of
     269             :            the OpenPolicy. As far as I can tell, this is what w2k3
     270             :            does */
     271             : 
     272        3157 :         return NT_STATUS_OK;
     273             : }
     274             : 
     275             : /* 
     276             :   lsa_OpenPolicy
     277             :   a wrapper around lsa_OpenPolicy2
     278             : */
     279         523 : NTSTATUS dcesrv_lsa_OpenPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     280             :                                 struct lsa_OpenPolicy *r)
     281             : {
     282         523 :         enum dcerpc_transport_t transport =
     283         523 :                 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
     284             :         struct lsa_OpenPolicy2 r2;
     285             : 
     286         523 :         if (transport != NCACN_NP && transport != NCALRPC) {
     287           5 :                 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
     288             :         }
     289             : 
     290         518 :         r2.in.system_name = NULL;
     291         518 :         r2.in.attr = r->in.attr;
     292         518 :         r2.in.access_mask = r->in.access_mask;
     293         518 :         r2.out.handle = r->out.handle;
     294             : 
     295         518 :         return dcesrv_lsa_OpenPolicy2(dce_call, mem_ctx, &r2);
     296             : }
     297             : 
     298             : 

Generated by: LCOV version 1.13