LCOV - code coverage report
Current view: top level - source4/libcli/util - clilsa.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 125 305 41.0 %
Date: 2024-04-21 15:09:00 Functions: 7 10 70.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    lsa calls for file sharing connections
       5             : 
       6             :    Copyright (C) Andrew Tridgell 2004
       7             :    
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             :    
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             :    
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : /*
      23             :   when dealing with ACLs the file sharing client code needs to
      24             :   sometimes make LSA RPC calls. This code provides an easy interface
      25             :   for doing those calls.  
      26             : */
      27             : 
      28             : #include "includes.h"
      29             : #include "libcli/raw/libcliraw.h"
      30             : #include "libcli/smb2/smb2.h"
      31             : #include "libcli/libcli.h"
      32             : #include "libcli/security/security.h"
      33             : #include "librpc/gen_ndr/ndr_lsa.h"
      34             : #include "librpc/gen_ndr/ndr_lsa_c.h"
      35             : #include "libcli/util/clilsa.h"
      36             : #include "libcli/smb/smbXcli_base.h"
      37             : 
      38             : struct smblsa_state {
      39             :         struct dcerpc_binding_handle *binding_handle;
      40             :         struct smbcli_tree *ipc_tree;
      41             :         struct policy_handle handle;
      42             : };
      43             : 
      44             : /*
      45             :   establish the lsa pipe connection
      46             : */
      47         110 : static NTSTATUS smblsa_connect(struct smbcli_state *cli)
      48             : {
      49           0 :         struct smblsa_state *lsa;
      50           0 :         struct dcerpc_pipe *lsa_pipe;
      51           0 :         NTSTATUS status;
      52           0 :         struct lsa_OpenPolicy r;
      53         110 :         uint16_t system_name = '\\';
      54           0 :         union smb_tcon tcon;
      55           0 :         struct lsa_ObjectAttribute attr;
      56           0 :         struct lsa_QosInfo qos;
      57             : 
      58         110 :         if (cli->lsa != NULL) {
      59          72 :                 return NT_STATUS_OK;
      60             :         }
      61             : 
      62          38 :         lsa = talloc(cli, struct smblsa_state);
      63          38 :         if (lsa == NULL) {
      64           0 :                 return NT_STATUS_NO_MEMORY;
      65             :         }
      66             : 
      67          38 :         lsa->ipc_tree = smbcli_tree_init(cli->session, lsa, false);
      68          38 :         if (lsa->ipc_tree == NULL) {
      69           0 :                 return NT_STATUS_NO_MEMORY;
      70             :         }
      71             : 
      72             :         /* connect to IPC$ */
      73          38 :         tcon.generic.level = RAW_TCON_TCONX;
      74          38 :         tcon.tconx.in.flags = TCONX_FLAG_EXTENDED_RESPONSE;
      75          38 :         tcon.tconx.in.flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
      76          38 :         tcon.tconx.in.password = data_blob(NULL, 0);
      77          38 :         tcon.tconx.in.path = "ipc$";
      78          38 :         tcon.tconx.in.device = "IPC"; 
      79          38 :         status = smb_raw_tcon(lsa->ipc_tree, lsa, &tcon);
      80          38 :         if (!NT_STATUS_IS_OK(status)) {
      81           0 :                 talloc_free(lsa);
      82           0 :                 return status;
      83             :         }
      84          38 :         lsa->ipc_tree->tid = tcon.tconx.out.tid;
      85             : 
      86          38 :         if (tcon.tconx.out.options & SMB_EXTENDED_SIGNATURES) {
      87           0 :                 smb1cli_session_protect_session_key(cli->session->smbXcli);
      88             :         }
      89             : 
      90          38 :         lsa_pipe = dcerpc_pipe_init(lsa, cli->transport->ev);
      91          38 :         if (lsa_pipe == NULL) {
      92           0 :                 talloc_free(lsa);
      93           0 :                 return NT_STATUS_NO_MEMORY;
      94             :         }
      95             : 
      96             :         /* open the LSA pipe */
      97          38 :         status = dcerpc_pipe_open_smb(lsa_pipe, lsa->ipc_tree, NDR_LSARPC_NAME);
      98          38 :         if (!NT_STATUS_IS_OK(status)) {
      99           0 :                 talloc_free(lsa);
     100           0 :                 return status;
     101             :         }
     102             : 
     103             :         /* bind to the LSA pipe */
     104          38 :         status = dcerpc_bind_auth_none(lsa_pipe, &ndr_table_lsarpc);
     105          38 :         if (!NT_STATUS_IS_OK(status)) {
     106           0 :                 talloc_free(lsa);
     107           0 :                 return status;
     108             :         }
     109          38 :         lsa->binding_handle = lsa_pipe->binding_handle;
     110             : 
     111             :         /* open a lsa policy handle */
     112          38 :         qos.len = 0;
     113          38 :         qos.impersonation_level = 2;
     114          38 :         qos.context_mode = 1;
     115          38 :         qos.effective_only = 0;
     116             : 
     117          38 :         attr.len = 0;
     118          38 :         attr.root_dir = NULL;
     119          38 :         attr.object_name = NULL;
     120          38 :         attr.attributes = 0;
     121          38 :         attr.sec_desc = NULL;
     122          38 :         attr.sec_qos = &qos;
     123             : 
     124          38 :         r.in.system_name = &system_name;
     125          38 :         r.in.attr = &attr;
     126          38 :         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
     127          38 :         r.out.handle = &lsa->handle;
     128             : 
     129          38 :         status = dcerpc_lsa_OpenPolicy_r(lsa->binding_handle, lsa, &r);
     130          38 :         if (!NT_STATUS_IS_OK(status)) {
     131           0 :                 talloc_free(lsa);
     132           0 :                 return status;
     133             :         }
     134             : 
     135          38 :         if (!NT_STATUS_IS_OK(r.out.result)) {
     136           0 :                 talloc_free(lsa);
     137           0 :                 return r.out.result;
     138             :         }
     139             : 
     140          38 :         cli->lsa = lsa;
     141             :         
     142          38 :         return NT_STATUS_OK;
     143             : }
     144             : 
     145             : 
     146           6 : static NTSTATUS smb2lsa_connect(struct smb2_tree *tree)
     147             : {
     148           6 :         struct smb2lsa_state *lsa = NULL;
     149           6 :         struct dcerpc_pipe *lsa_pipe = NULL;
     150           0 :         NTSTATUS status;
     151           6 :         struct lsa_OpenPolicy2 r = {{0}, {0}};
     152           6 :         const char *system_name = "\\";
     153           6 :         struct lsa_ObjectAttribute attr = {0};
     154           6 :         struct lsa_QosInfo qos = {0};
     155             : 
     156           6 :         if (tree->lsa != NULL) {
     157           0 :                 return NT_STATUS_OK;
     158             :         }
     159             : 
     160           6 :         lsa = talloc(tree, struct smb2lsa_state);
     161           6 :         if (lsa == NULL) {
     162           0 :                 return NT_STATUS_NO_MEMORY;
     163             :         }
     164             : 
     165           6 :         lsa_pipe = dcerpc_pipe_init(lsa, tree->session->transport->ev);
     166           6 :         if (lsa_pipe == NULL) {
     167           0 :                 talloc_free(lsa);
     168           0 :                 return NT_STATUS_NO_MEMORY;
     169             :         }
     170             : 
     171             :         /* open the LSA pipe */
     172           6 :         status = dcerpc_pipe_open_smb2(lsa_pipe, tree, NDR_LSARPC_NAME);
     173           6 :         if (!NT_STATUS_IS_OK(status)) {
     174           6 :                 talloc_free(lsa);
     175           6 :                 return status;
     176             :         }
     177             : 
     178             :         /* bind to the LSA pipe */
     179           0 :         status = dcerpc_bind_auth_none(lsa_pipe, &ndr_table_lsarpc);
     180           0 :         if (!NT_STATUS_IS_OK(status)) {
     181           0 :                 talloc_free(lsa);
     182           0 :                 return status;
     183             :         }
     184           0 :         lsa->binding_handle = lsa_pipe->binding_handle;
     185             : 
     186             :         /* open a lsa policy handle */
     187           0 :         qos.len = 0;
     188           0 :         qos.impersonation_level = 2;
     189           0 :         qos.context_mode = 1;
     190           0 :         qos.effective_only = 0;
     191             : 
     192           0 :         attr.len = 0;
     193           0 :         attr.root_dir = NULL;
     194           0 :         attr.object_name = NULL;
     195           0 :         attr.attributes = 0;
     196           0 :         attr.sec_desc = NULL;
     197           0 :         attr.sec_qos = &qos;
     198             : 
     199           0 :         r.in.system_name = system_name;
     200           0 :         r.in.attr = &attr;
     201           0 :         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
     202           0 :         r.out.handle = &lsa->handle;
     203             : 
     204           0 :         status = dcerpc_lsa_OpenPolicy2_r(lsa->binding_handle, lsa, &r);
     205           0 :         if (!NT_STATUS_IS_OK(status)) {
     206           0 :                 talloc_free(lsa);
     207           0 :                 return status;
     208             :         }
     209             : 
     210           0 :         if (!NT_STATUS_IS_OK(r.out.result)) {
     211           0 :                 talloc_free(lsa);
     212           0 :                 return r.out.result;
     213             :         }
     214             : 
     215           0 :         tree->lsa = lsa;
     216             : 
     217           0 :         return NT_STATUS_OK;
     218             : }
     219             : 
     220             : 
     221             : /*
     222             :   return the set of privileges for the given sid
     223             : */
     224         108 : NTSTATUS smblsa_sid_privileges(struct smbcli_state *cli, struct dom_sid *sid, 
     225             :                                TALLOC_CTX *mem_ctx,
     226             :                                struct lsa_RightSet *rights)
     227             : {
     228           0 :         NTSTATUS status;
     229           0 :         struct lsa_EnumAccountRights r;
     230             : 
     231         108 :         status = smblsa_connect(cli);
     232         108 :         if (!NT_STATUS_IS_OK(status)) {
     233           0 :                 return status;
     234             :         }
     235             : 
     236         108 :         r.in.handle = &cli->lsa->handle;
     237         108 :         r.in.sid = sid;
     238         108 :         r.out.rights = rights;
     239             : 
     240         108 :         status = dcerpc_lsa_EnumAccountRights_r(cli->lsa->binding_handle, mem_ctx, &r);
     241         108 :         if (!NT_STATUS_IS_OK(status)) {
     242           0 :                 return status;
     243             :         }
     244             : 
     245         108 :         return r.out.result;
     246             : }
     247             : 
     248             : 
     249           6 : NTSTATUS smb2lsa_sid_privileges(struct smb2_tree *tree, struct dom_sid *sid,
     250             :                                 TALLOC_CTX *mem_ctx,
     251             :                                 struct lsa_RightSet *rights)
     252             : {
     253           0 :         NTSTATUS status;
     254           6 :         struct lsa_EnumAccountRights r = {{0}, {0}};
     255             : 
     256           6 :         status = smb2lsa_connect(tree);
     257           6 :         if (!NT_STATUS_IS_OK(status)) {
     258           6 :                 return status;
     259             :         }
     260             : 
     261           0 :         r.in.handle = &tree->lsa->handle;
     262           0 :         r.in.sid = sid;
     263           0 :         r.out.rights = rights;
     264             : 
     265           0 :         status = dcerpc_lsa_EnumAccountRights_r(tree->lsa->binding_handle, mem_ctx, &r);
     266           0 :         if (!NT_STATUS_IS_OK(status)) {
     267           0 :                 return status;
     268             :         }
     269             : 
     270           0 :         return r.out.result;
     271             : }
     272             : 
     273             : 
     274             : /*
     275             :   check if a named sid has a particular named privilege
     276             : */
     277         108 : NTSTATUS smblsa_sid_check_privilege(struct smbcli_state *cli, 
     278             :                                     const char *sid_str,
     279             :                                     const char *privilege)
     280             : {
     281           0 :         struct lsa_RightSet rights;
     282           0 :         NTSTATUS status;
     283         108 :         TALLOC_CTX *mem_ctx = talloc_new(cli);
     284           0 :         struct dom_sid *sid;
     285           0 :         unsigned i;
     286             : 
     287         108 :         sid = dom_sid_parse_talloc(mem_ctx, sid_str);
     288         108 :         if (sid == NULL) {
     289           0 :                 talloc_free(mem_ctx);
     290           0 :                 return NT_STATUS_INVALID_SID;
     291             :         }
     292             : 
     293         108 :         status = smblsa_sid_privileges(cli, sid, mem_ctx, &rights);
     294         108 :         if (!NT_STATUS_IS_OK(status)) {
     295          96 :                 talloc_free(mem_ctx);
     296          96 :                 return status;
     297             :         }
     298             : 
     299          60 :         for (i=0;i<rights.count;i++) {
     300          60 :                 if (strcmp(rights.names[i].string, privilege) == 0) {
     301          12 :                         talloc_free(mem_ctx);
     302          12 :                         return NT_STATUS_OK;
     303             :                 }
     304             :         }
     305             : 
     306           0 :         talloc_free(mem_ctx);
     307           0 :         return NT_STATUS_NOT_FOUND;
     308             : }
     309             : 
     310             : 
     311           6 : NTSTATUS smb2lsa_sid_check_privilege(struct smb2_tree *tree,
     312             :                                      const char *sid_str,
     313             :                                      const char *privilege)
     314             : {
     315           6 :         struct lsa_RightSet rights = {0};
     316           0 :         NTSTATUS status;
     317           6 :         TALLOC_CTX *mem_ctx = NULL;
     318           6 :         struct dom_sid *sid = NULL;
     319           0 :         unsigned i;
     320             : 
     321           6 :         mem_ctx = talloc_new(tree);
     322           6 :         if (!mem_ctx) {
     323           0 :                 return NT_STATUS_NO_MEMORY;
     324             :         }
     325             : 
     326           6 :         sid = dom_sid_parse_talloc(mem_ctx, sid_str);
     327           6 :         if (sid == NULL) {
     328           0 :                 talloc_free(mem_ctx);
     329           0 :                 return NT_STATUS_INVALID_SID;
     330             :         }
     331             : 
     332           6 :         status = smb2lsa_sid_privileges(tree, sid, mem_ctx, &rights);
     333           6 :         if (!NT_STATUS_IS_OK(status)) {
     334           6 :                 talloc_free(mem_ctx);
     335           6 :                 return status;
     336             :         }
     337             : 
     338           0 :         for (i=0;i<rights.count;i++) {
     339           0 :                 if (strcmp(rights.names[i].string, privilege) == 0) {
     340           0 :                         talloc_free(mem_ctx);
     341           0 :                         return NT_STATUS_OK;
     342             :                 }
     343             :         }
     344             : 
     345           0 :         talloc_free(mem_ctx);
     346           0 :         return NT_STATUS_NOT_FOUND;
     347             : }
     348             : 
     349             : 
     350             : /*
     351             :   lookup a SID, returning its name
     352             : */
     353           0 : NTSTATUS smblsa_lookup_sid(struct smbcli_state *cli, 
     354             :                            const char *sid_str,
     355             :                            TALLOC_CTX *mem_ctx,
     356             :                            const char **name)
     357             : {
     358           0 :         struct lsa_LookupSids r;
     359           0 :         struct lsa_TransNameArray names;
     360           0 :         struct lsa_SidArray sids;
     361           0 :         struct lsa_RefDomainList *domains = NULL;
     362           0 :         uint32_t count = 1;
     363           0 :         NTSTATUS status;
     364           0 :         struct dom_sid *sid;
     365           0 :         TALLOC_CTX *mem_ctx2 = talloc_new(mem_ctx);
     366             : 
     367           0 :         status = smblsa_connect(cli);
     368           0 :         if (!NT_STATUS_IS_OK(status)) {
     369           0 :                 return status;
     370             :         }
     371             : 
     372           0 :         sid = dom_sid_parse_talloc(mem_ctx2, sid_str);
     373           0 :         if (sid == NULL) {
     374           0 :                 return NT_STATUS_INVALID_SID;
     375             :         }
     376             : 
     377           0 :         names.count = 0;
     378           0 :         names.names = NULL;
     379             : 
     380           0 :         sids.num_sids = 1;
     381           0 :         sids.sids = talloc(mem_ctx2, struct lsa_SidPtr);
     382           0 :         sids.sids[0].sid = sid;
     383             : 
     384           0 :         r.in.handle = &cli->lsa->handle;
     385           0 :         r.in.sids = &sids;
     386           0 :         r.in.names = &names;
     387           0 :         r.in.level = 1;
     388           0 :         r.in.count = &count;
     389           0 :         r.out.count = &count;
     390           0 :         r.out.names = &names;
     391           0 :         r.out.domains = &domains;
     392             : 
     393           0 :         status = dcerpc_lsa_LookupSids_r(cli->lsa->binding_handle, mem_ctx2, &r);
     394           0 :         if (!NT_STATUS_IS_OK(status)) {
     395           0 :                 talloc_free(mem_ctx2);
     396           0 :                 return status;
     397             :         }
     398           0 :         if (!NT_STATUS_IS_OK(r.out.result)) {
     399           0 :                 talloc_free(mem_ctx2);
     400           0 :                 return r.out.result;
     401             :         }
     402           0 :         if (names.count != 1) {
     403           0 :                 talloc_free(mem_ctx2);
     404           0 :                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
     405             :         }
     406           0 :         if (domains == NULL) {
     407           0 :                 talloc_free(mem_ctx2);
     408           0 :                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
     409             :         }
     410           0 :         if (domains->count != 1) {
     411           0 :                 talloc_free(mem_ctx2);
     412           0 :                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
     413             :         }
     414           0 :         if (names.names[0].sid_index != UINT32_MAX &&
     415           0 :             names.names[0].sid_index >= domains->count)
     416             :         {
     417           0 :                 talloc_free(mem_ctx2);
     418           0 :                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
     419             :         }
     420             : 
     421           0 :         (*name) = talloc_asprintf(mem_ctx, "%s\\%s", 
     422           0 :                                   domains->domains[0].name.string,
     423           0 :                                   names.names[0].name.string);
     424             : 
     425           0 :         talloc_free(mem_ctx2);
     426             : 
     427           0 :         return NT_STATUS_OK;    
     428             : }
     429             : 
     430             : /*
     431             :   lookup a name, returning its sid
     432             : */
     433           2 : NTSTATUS smblsa_lookup_name(struct smbcli_state *cli, 
     434             :                             const char *name,
     435             :                             TALLOC_CTX *mem_ctx,
     436             :                             const char **sid_str)
     437             : {
     438           0 :         struct lsa_LookupNames r;
     439           0 :         struct lsa_TransSidArray sids;
     440           0 :         struct lsa_String names;
     441           2 :         struct lsa_RefDomainList *domains = NULL;
     442           2 :         uint32_t count = 1;
     443           0 :         NTSTATUS status;
     444           0 :         struct dom_sid sid;
     445           2 :         TALLOC_CTX *mem_ctx2 = talloc_new(mem_ctx);
     446             : 
     447           2 :         status = smblsa_connect(cli);
     448           2 :         if (!NT_STATUS_IS_OK(status)) {
     449           0 :                 return status;
     450             :         }
     451             : 
     452           2 :         sids.count = 0;
     453           2 :         sids.sids = NULL;
     454             : 
     455           2 :         names.string = name;
     456             : 
     457           2 :         r.in.handle = &cli->lsa->handle;
     458           2 :         r.in.num_names = 1;
     459           2 :         r.in.names = &names;
     460           2 :         r.in.sids = &sids;
     461           2 :         r.in.level = 1;
     462           2 :         r.in.count = &count;
     463           2 :         r.out.count = &count;
     464           2 :         r.out.sids = &sids;
     465           2 :         r.out.domains = &domains;
     466             : 
     467           2 :         status = dcerpc_lsa_LookupNames_r(cli->lsa->binding_handle, mem_ctx2, &r);
     468           2 :         if (!NT_STATUS_IS_OK(status)) {
     469           0 :                 talloc_free(mem_ctx2);
     470           0 :                 return status;
     471             :         }
     472           2 :         if (!NT_STATUS_IS_OK(r.out.result)) {
     473           0 :                 talloc_free(mem_ctx2);
     474           0 :                 return r.out.result;
     475             :         }
     476           2 :         if (sids.count != 1) {
     477           0 :                 talloc_free(mem_ctx2);
     478           0 :                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
     479             :         }
     480           2 :         if (domains->count != 1) {
     481           0 :                 talloc_free(mem_ctx2);
     482           0 :                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
     483             :         }
     484             : 
     485           2 :         sid_compose(&sid, domains->domains[0].sid, sids.sids[0].rid);
     486             : 
     487           2 :         (*sid_str) = dom_sid_string(mem_ctx, &sid);
     488             : 
     489           2 :         talloc_free(mem_ctx2);
     490             : 
     491           2 :         return NT_STATUS_OK;    
     492             : }
     493             : 
     494             : 
     495             : /*
     496             :   add a set of privileges to the given sid
     497             : */
     498           0 : NTSTATUS smblsa_sid_add_privileges(struct smbcli_state *cli, struct dom_sid *sid, 
     499             :                                    TALLOC_CTX *mem_ctx,
     500             :                                    struct lsa_RightSet *rights)
     501             : {
     502           0 :         NTSTATUS status;
     503           0 :         struct lsa_AddAccountRights r;
     504             : 
     505           0 :         status = smblsa_connect(cli);
     506           0 :         if (!NT_STATUS_IS_OK(status)) {
     507           0 :                 return status;
     508             :         }
     509             : 
     510           0 :         r.in.handle = &cli->lsa->handle;
     511           0 :         r.in.sid = sid;
     512           0 :         r.in.rights = rights;
     513             : 
     514           0 :         status = dcerpc_lsa_AddAccountRights_r(cli->lsa->binding_handle, mem_ctx, &r);
     515           0 :         if (!NT_STATUS_IS_OK(status)) {
     516           0 :                 return status;
     517             :         }
     518             : 
     519           0 :         return r.out.result;
     520             : }
     521             : 
     522             : /*
     523             :   remove a set of privileges from the given sid
     524             : */
     525           0 : NTSTATUS smblsa_sid_del_privileges(struct smbcli_state *cli, struct dom_sid *sid, 
     526             :                                    TALLOC_CTX *mem_ctx,
     527             :                                    struct lsa_RightSet *rights)
     528             : {
     529           0 :         NTSTATUS status;
     530           0 :         struct lsa_RemoveAccountRights r;
     531             : 
     532           0 :         status = smblsa_connect(cli);
     533           0 :         if (!NT_STATUS_IS_OK(status)) {
     534           0 :                 return status;
     535             :         }
     536             : 
     537           0 :         r.in.handle = &cli->lsa->handle;
     538           0 :         r.in.sid = sid;
     539           0 :         r.in.remove_all = 0;
     540           0 :         r.in.rights = rights;
     541             : 
     542           0 :         status = dcerpc_lsa_RemoveAccountRights_r(cli->lsa->binding_handle, mem_ctx, &r);
     543           0 :         if (!NT_STATUS_IS_OK(status)) {
     544           0 :                 return status;
     545             :         }
     546             : 
     547           0 :         return r.out.result;
     548             : }

Generated by: LCOV version 1.14