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