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