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