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