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 2b515b7d Lines: 120 149 80.5 %
Date: 2024-02-28 12:06:22 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        3766 : 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        3766 :                 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        3766 :         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        3766 :         state = talloc_zero(mem_ctx, struct lsa_policy_state);
      70        3766 :         if (!state) {
      71           0 :                 return NT_STATUS_NO_MEMORY;
      72             :         }
      73             : 
      74             :         /* make sure the sam database is accessible */
      75        3766 :         state->sam_ldb = dcesrv_samdb_connect_as_user(state, dce_call);
      76        3766 :         if (state->sam_ldb == NULL) {
      77           0 :                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
      78             :         }
      79             : 
      80             :         /* and the privilege database */
      81        3766 :         state->pdb = privilege_connect(state, dce_call->conn->dce_ctx->lp_ctx);
      82        3766 :         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        3766 :         state->domain_dn = ldb_get_default_basedn(state->sam_ldb);
      89        3766 :         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        3766 :         state->forest_dn = ldb_get_root_basedn(state->sam_ldb);
      96        3766 :         if (!state->forest_dn) {
      97           0 :                 return NT_STATUS_NO_MEMORY;
      98             :         }
      99             : 
     100        3766 :         ret = ldb_search(state->sam_ldb, mem_ctx, &dom_res,
     101             :                          state->domain_dn, LDB_SCOPE_BASE, dom_attrs, NULL);
     102        3766 :         if (ret != LDB_SUCCESS) {
     103           0 :                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
     104             :         }
     105        3766 :         if (dom_res->count != 1) {
     106           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;
     107             :         }
     108             : 
     109        3766 :         state->domain_sid = samdb_result_dom_sid(state, dom_res->msgs[0], "objectSid");
     110        3766 :         if (!state->domain_sid) {
     111           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;
     112             :         }
     113             : 
     114        3766 :         state->domain_guid = samdb_result_guid(dom_res->msgs[0], "objectGUID");
     115             : 
     116        3766 :         state->mixed_domain = ldb_msg_find_attr_as_uint(dom_res->msgs[0], "nTMixedDomain", 0);
     117             : 
     118        3766 :         talloc_free(dom_res);
     119             : 
     120        3766 :         state->domain_name = lpcfg_sam_name(dce_call->conn->dce_ctx->lp_ctx);
     121             : 
     122        3766 :         state->domain_dns = ldb_dn_canonical_string(state, state->domain_dn);
     123        3766 :         if (!state->domain_dns) {
     124           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;
     125             :         }
     126        3766 :         p = strchr(state->domain_dns, '/');
     127        3766 :         if (p) {
     128        3766 :                 *p = '\0';
     129             :         }
     130             : 
     131        3766 :         state->forest_dns = ldb_dn_canonical_string(state, state->forest_dn);
     132        3766 :         if (!state->forest_dns) {
     133           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;
     134             :         }
     135        3766 :         p = strchr(state->forest_dns, '/');
     136        3766 :         if (p) {
     137        3766 :                 *p = '\0';
     138             :         }
     139             : 
     140             :         /* work out the builtin_dn - useful for so many calls its worth
     141             :            fetching here */
     142        3766 :         state->builtin_dn = samdb_search_dn(state->sam_ldb, state, state->domain_dn, "(objectClass=builtinDomain)");
     143        3766 :         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        3766 :         state->system_dn = samdb_system_container_dn(state->sam_ldb, state);
     150        3766 :         if (state->system_dn == NULL) {
     151           0 :                 return NT_STATUS_NO_MEMORY;
     152             :         }
     153             : 
     154        3766 :         state->builtin_sid = dom_sid_parse_talloc(state, SID_BUILTIN);
     155        3766 :         if (!state->builtin_sid) {
     156           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;
     157             :         }
     158             : 
     159        3766 :         state->nt_authority_sid = dom_sid_parse_talloc(state, SID_NT_AUTHORITY);
     160        3766 :         if (!state->nt_authority_sid) {
     161           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;
     162             :         }
     163             : 
     164        3766 :         state->creator_owner_domain_sid = dom_sid_parse_talloc(state, SID_CREATOR_OWNER_DOMAIN);
     165        3766 :         if (!state->creator_owner_domain_sid) {
     166           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;
     167             :         }
     168             : 
     169        3766 :         state->world_domain_sid = dom_sid_parse_talloc(state, SID_WORLD_DOMAIN);
     170        3766 :         if (!state->world_domain_sid) {
     171           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;
     172             :         }
     173             : 
     174        7532 :         state->sd = sddl_decode(state, DCESRV_LSA_POLICY_SD_SDDL,
     175        3766 :                                 state->domain_sid);
     176        3766 :         if (state->sd == NULL) {
     177           0 :                 return NT_STATUS_NO_MEMORY;
     178             :         }
     179        3766 :         state->sd->dacl->revision = SECURITY_ACL_REVISION_NT4;
     180             : 
     181        3766 :         se_map_generic(&access_desired, &dcesrv_lsa_policy_mapping);
     182        3766 :         security_acl_map_generic(state->sd->dacl, &dcesrv_lsa_policy_mapping);
     183             : 
     184        3766 :         security_level = security_session_user_level(session_info, NULL);
     185        3766 :         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         509 :                 state->access_mask = access_desired;
     191         509 :                 if (state->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
     192         377 :                         state->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
     193         377 :                         state->access_mask |= LSA_POLICY_ALL_ACCESS;
     194             :                 }
     195             :         } else {
     196         141 :                 NTSTATUS status;
     197             : 
     198        3257 :                 status = se_access_check(state->sd,
     199        3257 :                                          session_info->security_token,
     200             :                                          access_desired,
     201             :                                          &state->access_mask);
     202        3257 :                 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        3766 :         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        3766 :         *_state = state;
     218             : 
     219        3766 :         return NT_STATUS_OK;
     220             : }
     221             : 
     222             : /*
     223             :   lsa_OpenPolicy3
     224             : */
     225          53 : NTSTATUS dcesrv_lsa_OpenPolicy3(struct dcesrv_call_state *dce_call,
     226             :                                 TALLOC_CTX *mem_ctx,
     227             :                                 struct lsa_OpenPolicy3 *r)
     228             : {
     229           0 :         enum dcerpc_transport_t transport =
     230          53 :                 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
     231          53 :         struct lsa_policy_state *state = NULL;
     232          53 :         struct dcesrv_handle *handle = NULL;
     233           0 :         NTSTATUS status;
     234             : 
     235          53 :         if (transport != NCACN_NP && transport != NCALRPC) {
     236           3 :                 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
     237             :         }
     238             : 
     239          50 :         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          50 :         if (r->in.attr != NULL && r->in.attr->root_dir != NULL) {
     246           0 :                 return NT_STATUS_INVALID_PARAMETER;
     247             :         }
     248             : 
     249          50 :         switch (r->in.in_version) {
     250          50 :         case 1:
     251          50 :                 *r->out.out_version = 1;
     252             : 
     253          50 :                 r->out.out_revision_info->info1.revision = 1;
     254             :                 /* TODO: Enable as soon as we support it */
     255             : #if 0
     256             :                 r->out.out_revision_info->info1.supported_features =
     257             :                                 LSA_FEATURE_TDO_AUTH_INFO_AES_CIPHER;
     258             : #endif
     259             : 
     260          50 :                 break;
     261           0 :         default:
     262           0 :                 return NT_STATUS_NOT_SUPPORTED;
     263             :         }
     264             : 
     265          50 :         status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx,
     266             :                                              r->in.access_mask,
     267             :                                              &state);
     268          50 :         if (!NT_STATUS_IS_OK(status)) {
     269           0 :                 return status;
     270             :         }
     271             : 
     272          50 :         handle = dcesrv_handle_create(dce_call, LSA_HANDLE_POLICY);
     273          50 :         if (handle == NULL) {
     274           0 :                 return NT_STATUS_NO_MEMORY;
     275             :         }
     276          50 :         handle->data = talloc_steal(handle, state);
     277             : 
     278          50 :         state->handle = handle;
     279          50 :         *r->out.handle = handle->wire_handle;
     280             : 
     281          50 :         return NT_STATUS_OK;
     282             : }
     283             : 
     284             : /*
     285             :   lsa_OpenPolicy2
     286             : */
     287        3348 : NTSTATUS dcesrv_lsa_OpenPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     288             :                                 struct lsa_OpenPolicy2 *r)
     289             : {
     290          96 :         enum dcerpc_transport_t transport =
     291        3348 :                 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
     292          96 :         NTSTATUS status;
     293          96 :         struct lsa_policy_state *state;
     294          96 :         struct dcesrv_handle *handle;
     295             : 
     296        3348 :         if (transport != NCACN_NP && transport != NCALRPC) {
     297           3 :                 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
     298             :         }
     299             : 
     300        3345 :         ZERO_STRUCTP(r->out.handle);
     301             : 
     302        3345 :         if (r->in.attr != NULL &&
     303        3345 :             r->in.attr->root_dir != NULL) {
     304             :                 /* MS-LSAD 3.1.4.4.1 */
     305           0 :                 return NT_STATUS_INVALID_PARAMETER;
     306             :         }
     307             : 
     308        3345 :         status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx,
     309             :                                              r->in.access_mask,
     310             :                                              &state);
     311        3345 :         if (!NT_STATUS_IS_OK(status)) {
     312           0 :                 return status;
     313             :         }
     314             : 
     315        3345 :         handle = dcesrv_handle_create(dce_call, LSA_HANDLE_POLICY);
     316        3345 :         if (!handle) {
     317           0 :                 return NT_STATUS_NO_MEMORY;
     318             :         }
     319             : 
     320        3345 :         handle->data = talloc_steal(handle, state);
     321             : 
     322        3345 :         state->handle = handle;
     323        3345 :         *r->out.handle = handle->wire_handle;
     324             : 
     325             :         /* note that we have completely ignored the attr element of
     326             :            the OpenPolicy. As far as I can tell, this is what w2k3
     327             :            does */
     328             : 
     329        3345 :         return NT_STATUS_OK;
     330             : }
     331             : 
     332             : /*
     333             :   lsa_OpenPolicy
     334             :   a wrapper around lsa_OpenPolicy2
     335             : */
     336         771 : NTSTATUS dcesrv_lsa_OpenPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
     337             :                                 struct lsa_OpenPolicy *r)
     338             : {
     339          13 :         enum dcerpc_transport_t transport =
     340         771 :                 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
     341          13 :         struct lsa_OpenPolicy2 r2;
     342             : 
     343         771 :         if (transport != NCACN_NP && transport != NCALRPC) {
     344           3 :                 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
     345             :         }
     346             : 
     347         768 :         r2 = (struct lsa_OpenPolicy2) {
     348         768 :                 .in.attr = r->in.attr,
     349         768 :                 .in.access_mask = r->in.access_mask,
     350         768 :                 .out.handle = r->out.handle,
     351             :         };
     352             : 
     353         768 :         return dcesrv_lsa_OpenPolicy2(dce_call, mem_ctx, &r2);
     354             : }
     355             : 
     356             : 

Generated by: LCOV version 1.14