Merge branch 'v4-0-test' of ssh://git.samba.org/data/git/samba into v4-0-python
[sfrench/samba-autobuild/.git] / source4 / libcli / util / clilsa.c
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/libcli.h"
31 #include "libcli/security/security.h"
32 #include "librpc/gen_ndr/ndr_lsa.h"
33 #include "librpc/gen_ndr/ndr_lsa_c.h"
34 #include "libcli/util/clilsa.h"
35 #include "param/param.h"
36
37 struct smblsa_state {
38         struct dcerpc_pipe *pipe;
39         struct smbcli_tree *ipc_tree;
40         struct policy_handle handle;
41 };
42
43 /*
44   establish the lsa pipe connection
45 */
46 static NTSTATUS smblsa_connect(struct smbcli_state *cli)
47 {
48         struct smblsa_state *lsa;
49         NTSTATUS status;
50         struct lsa_OpenPolicy r;
51         uint16_t system_name = '\\';
52         union smb_tcon tcon;
53         struct lsa_ObjectAttribute attr;
54         struct lsa_QosInfo qos;
55
56         if (cli->lsa != NULL) {
57                 return NT_STATUS_OK;
58         }
59
60         lsa = talloc(cli, struct smblsa_state);
61         if (lsa == NULL) {
62                 return NT_STATUS_NO_MEMORY;
63         }
64
65         lsa->ipc_tree = smbcli_tree_init(cli->session, lsa, false);
66         if (lsa->ipc_tree == NULL) {
67                 return NT_STATUS_NO_MEMORY;
68         }
69
70         /* connect to IPC$ */
71         tcon.generic.level = RAW_TCON_TCONX;
72         tcon.tconx.in.flags = 0;
73         tcon.tconx.in.password = data_blob(NULL, 0);
74         tcon.tconx.in.path = "ipc$";
75         tcon.tconx.in.device = "IPC";   
76         status = smb_raw_tcon(lsa->ipc_tree, lsa, &tcon);
77         if (!NT_STATUS_IS_OK(status)) {
78                 talloc_free(lsa);
79                 return status;
80         }
81         lsa->ipc_tree->tid = tcon.tconx.out.tid;
82
83         lsa->pipe = dcerpc_pipe_init(lsa, cli->transport->socket->event.ctx,
84                                      lp_iconv_convenience(global_loadparm));
85         if (lsa->pipe == NULL) {
86                 talloc_free(lsa);
87                 return NT_STATUS_NO_MEMORY;
88         }
89
90         /* open the LSA pipe */
91         status = dcerpc_pipe_open_smb(lsa->pipe, lsa->ipc_tree, NDR_LSARPC_NAME);
92         if (!NT_STATUS_IS_OK(status)) {
93                 talloc_free(lsa);
94                 return status;
95         }
96
97         /* bind to the LSA pipe */
98         status = dcerpc_bind_auth_none(lsa->pipe, &ndr_table_lsarpc);
99         if (!NT_STATUS_IS_OK(status)) {
100                 talloc_free(lsa);
101                 return status;
102         }
103
104
105         /* open a lsa policy handle */
106         qos.len = 0;
107         qos.impersonation_level = 2;
108         qos.context_mode = 1;
109         qos.effective_only = 0;
110
111         attr.len = 0;
112         attr.root_dir = NULL;
113         attr.object_name = NULL;
114         attr.attributes = 0;
115         attr.sec_desc = NULL;
116         attr.sec_qos = &qos;
117
118         r.in.system_name = &system_name;
119         r.in.attr = &attr;
120         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
121         r.out.handle = &lsa->handle;
122
123         status = dcerpc_lsa_OpenPolicy(lsa->pipe, lsa, &r);
124         if (!NT_STATUS_IS_OK(status)) {
125                 talloc_free(lsa);
126                 return status;
127         }
128
129         cli->lsa = lsa;
130         
131         return NT_STATUS_OK;
132 }
133
134
135 /*
136   return the set of privileges for the given sid
137 */
138 NTSTATUS smblsa_sid_privileges(struct smbcli_state *cli, struct dom_sid *sid, 
139                                TALLOC_CTX *mem_ctx,
140                                struct lsa_RightSet *rights)
141 {
142         NTSTATUS status;
143         struct lsa_EnumAccountRights r;
144
145         status = smblsa_connect(cli);
146         if (!NT_STATUS_IS_OK(status)) {
147                 return status;
148         }
149
150         r.in.handle = &cli->lsa->handle;
151         r.in.sid = sid;
152         r.out.rights = rights;
153
154         return dcerpc_lsa_EnumAccountRights(cli->lsa->pipe, mem_ctx, &r);
155 }
156
157
158 /*
159   check if a named sid has a particular named privilege
160 */
161 NTSTATUS smblsa_sid_check_privilege(struct smbcli_state *cli, 
162                                     const char *sid_str,
163                                     const char *privilege)
164 {
165         struct lsa_RightSet rights;
166         NTSTATUS status;
167         TALLOC_CTX *mem_ctx = talloc_new(cli);
168         struct dom_sid *sid;
169         unsigned i;
170
171         sid = dom_sid_parse_talloc(mem_ctx, sid_str);
172         if (sid == NULL) {
173                 talloc_free(mem_ctx);
174                 return NT_STATUS_INVALID_SID;
175         }
176
177         status = smblsa_sid_privileges(cli, sid, mem_ctx, &rights);
178         if (!NT_STATUS_IS_OK(status)) {
179                 talloc_free(mem_ctx);
180                 return status;
181         }
182
183         for (i=0;i<rights.count;i++) {
184                 if (strcmp(rights.names[i].string, privilege) == 0) {
185                         talloc_free(mem_ctx);
186                         return NT_STATUS_OK;
187                 }
188         }
189
190         talloc_free(mem_ctx);
191         return NT_STATUS_NOT_FOUND;
192 }
193
194
195 /*
196   lookup a SID, returning its name
197 */
198 NTSTATUS smblsa_lookup_sid(struct smbcli_state *cli, 
199                            const char *sid_str,
200                            TALLOC_CTX *mem_ctx,
201                            const char **name)
202 {
203         struct lsa_LookupSids r;
204         struct lsa_TransNameArray names;
205         struct lsa_SidArray sids;
206         uint32_t count = 1;
207         NTSTATUS status;
208         struct dom_sid *sid;
209         TALLOC_CTX *mem_ctx2 = talloc_new(mem_ctx);
210
211         status = smblsa_connect(cli);
212         if (!NT_STATUS_IS_OK(status)) {
213                 return status;
214         }
215
216         sid = dom_sid_parse_talloc(mem_ctx2, sid_str);
217         if (sid == NULL) {
218                 return NT_STATUS_INVALID_SID;
219         }
220
221         names.count = 0;
222         names.names = NULL;
223
224         sids.num_sids = 1;
225         sids.sids = talloc(mem_ctx2, struct lsa_SidPtr);
226         sids.sids[0].sid = sid;
227
228         r.in.handle = &cli->lsa->handle;
229         r.in.sids = &sids;
230         r.in.names = &names;
231         r.in.level = 1;
232         r.in.count = &count;
233         r.out.count = &count;
234         r.out.names = &names;
235
236         status = dcerpc_lsa_LookupSids(cli->lsa->pipe, mem_ctx2, &r);
237         if (!NT_STATUS_IS_OK(status)) {
238                 talloc_free(mem_ctx2);
239                 return status;
240         }
241         if (names.count != 1) {
242                 talloc_free(mem_ctx2);
243                 return NT_STATUS_UNSUCCESSFUL;
244         }
245
246         (*name) = talloc_asprintf(mem_ctx, "%s\\%s", 
247                                   r.out.domains->domains[0].name.string,
248                                   names.names[0].name.string);
249
250         talloc_free(mem_ctx2);
251
252         return NT_STATUS_OK;    
253 }
254
255 /*
256   lookup a name, returning its sid
257 */
258 NTSTATUS smblsa_lookup_name(struct smbcli_state *cli, 
259                             const char *name,
260                             TALLOC_CTX *mem_ctx,
261                             const char **sid_str)
262 {
263         struct lsa_LookupNames r;
264         struct lsa_TransSidArray sids;
265         struct lsa_String names;
266         uint32_t count = 1;
267         NTSTATUS status;
268         struct dom_sid *sid;
269         TALLOC_CTX *mem_ctx2 = talloc_new(mem_ctx);
270         uint32_t rid;
271
272         status = smblsa_connect(cli);
273         if (!NT_STATUS_IS_OK(status)) {
274                 return status;
275         }
276
277         sids.count = 0;
278         sids.sids = NULL;
279
280         names.string = name;
281
282         r.in.handle = &cli->lsa->handle;
283         r.in.num_names = 1;
284         r.in.names = &names;
285         r.in.sids = &sids;
286         r.in.level = 1;
287         r.in.count = &count;
288         r.out.count = &count;
289         r.out.sids = &sids;
290
291         status = dcerpc_lsa_LookupNames(cli->lsa->pipe, mem_ctx2, &r);
292         if (!NT_STATUS_IS_OK(status)) {
293                 talloc_free(mem_ctx2);
294                 return status;
295         }
296         if (sids.count != 1) {
297                 talloc_free(mem_ctx2);
298                 return NT_STATUS_UNSUCCESSFUL;
299         }
300
301         sid = r.out.domains->domains[0].sid;
302         rid = sids.sids[0].rid;
303         
304         (*sid_str) = talloc_asprintf(mem_ctx, "%s-%u", 
305                                      dom_sid_string(mem_ctx2, sid), rid);
306
307         talloc_free(mem_ctx2);
308
309         return NT_STATUS_OK;    
310 }
311
312
313 /*
314   add a set of privileges to the given sid
315 */
316 NTSTATUS smblsa_sid_add_privileges(struct smbcli_state *cli, struct dom_sid *sid, 
317                                    TALLOC_CTX *mem_ctx,
318                                    struct lsa_RightSet *rights)
319 {
320         NTSTATUS status;
321         struct lsa_AddAccountRights r;
322
323         status = smblsa_connect(cli);
324         if (!NT_STATUS_IS_OK(status)) {
325                 return status;
326         }
327
328         r.in.handle = &cli->lsa->handle;
329         r.in.sid = sid;
330         r.in.rights = rights;
331
332         return dcerpc_lsa_AddAccountRights(cli->lsa->pipe, mem_ctx, &r);
333 }
334
335 /*
336   remove a set of privileges from the given sid
337 */
338 NTSTATUS smblsa_sid_del_privileges(struct smbcli_state *cli, struct dom_sid *sid, 
339                                    TALLOC_CTX *mem_ctx,
340                                    struct lsa_RightSet *rights)
341 {
342         NTSTATUS status;
343         struct lsa_RemoveAccountRights r;
344
345         status = smblsa_connect(cli);
346         if (!NT_STATUS_IS_OK(status)) {
347                 return status;
348         }
349
350         r.in.handle = &cli->lsa->handle;
351         r.in.sid = sid;
352         r.in.unknown = 0;
353         r.in.rights = rights;
354
355         return dcerpc_lsa_RemoveAccountRights(cli->lsa->pipe, mem_ctx, &r);
356 }