r4073: - added a set of lsa helper routines to make lsa lookups that are
[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_p(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);
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_tree_connect(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.cnum;
78
79         /* open the LSA pipe */
80         status = dcerpc_pipe_open_smb(&lsa->pipe, lsa->ipc_tree, DCERPC_LSARPC_NAME);
81         if (!NT_STATUS_IS_OK(status)) {
82                 talloc_free(lsa);
83                 return status;
84         }
85
86         /* bind to the LSA pipe */
87         status = dcerpc_bind_auth_none(lsa->pipe, DCERPC_LSARPC_UUID, DCERPC_LSARPC_VERSION);
88         if (!NT_STATUS_IS_OK(status)) {
89                 talloc_free(lsa);
90                 return status;
91         }
92
93
94         /* open a lsa policy handle */
95         qos.len = 0;
96         qos.impersonation_level = 2;
97         qos.context_mode = 1;
98         qos.effective_only = 0;
99
100         attr.len = 0;
101         attr.root_dir = NULL;
102         attr.object_name = NULL;
103         attr.attributes = 0;
104         attr.sec_desc = NULL;
105         attr.sec_qos = &qos;
106
107         r.in.system_name = &system_name;
108         r.in.attr = &attr;
109         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
110         r.out.handle = &lsa->handle;
111
112         status = dcerpc_lsa_OpenPolicy(lsa->pipe, lsa, &r);
113         if (!NT_STATUS_IS_OK(status)) {
114                 talloc_free(lsa);
115                 return status;
116         }
117
118         cli->lsa = lsa;
119         
120         return NT_STATUS_OK;
121 }
122
123
124 /*
125   return the set of privileges for the given sid
126 */
127 NTSTATUS smblsa_sid_privileges(struct smbcli_state *cli, struct dom_sid *sid, 
128                                TALLOC_CTX *mem_ctx,
129                                struct lsa_RightSet *rights)
130 {
131         NTSTATUS status;
132         struct lsa_EnumAccountRights r;
133
134         status = smblsa_connect(cli);
135         if (!NT_STATUS_IS_OK(status)) {
136                 return status;
137         }
138
139         r.in.handle = &cli->lsa->handle;
140         r.in.sid = sid;
141         r.out.rights = rights;
142
143         return dcerpc_lsa_EnumAccountRights(cli->lsa->pipe, mem_ctx, &r);
144 }
145
146
147 /*
148   check if a named sid has a particular named privilege
149 */
150 NTSTATUS smblsa_sid_check_privilege(struct smbcli_state *cli, 
151                                     const char *sid_str,
152                                     const char *privilege)
153 {
154         struct lsa_RightSet rights;
155         NTSTATUS status;
156         TALLOC_CTX *mem_ctx = talloc(cli, 0);
157         struct dom_sid *sid;
158         unsigned i;
159
160         sid = dom_sid_parse_talloc(mem_ctx, sid_str);
161         if (sid == NULL) {
162                 talloc_free(mem_ctx);
163                 return NT_STATUS_INVALID_SID;
164         }
165
166         status = smblsa_sid_privileges(cli, sid, mem_ctx, &rights);
167         if (!NT_STATUS_IS_OK(status)) {
168                 talloc_free(mem_ctx);
169                 return status;
170         }
171
172         for (i=0;i<rights.count;i++) {
173                 if (strcmp(rights.names[i].string, privilege) == 0) {
174                         talloc_free(mem_ctx);
175                         return NT_STATUS_OK;
176                 }
177         }
178
179         talloc_free(mem_ctx);
180         return NT_STATUS_NOT_FOUND;
181 }
182
183
184 /*
185   lookup a SID, returning its name
186 */
187 NTSTATUS smblsa_lookup_sid(struct smbcli_state *cli, 
188                            const char *sid_str,
189                            TALLOC_CTX *mem_ctx,
190                            const char **name)
191 {
192         struct lsa_LookupSids r;
193         struct lsa_TransNameArray names;
194         struct lsa_SidArray sids;
195         uint32_t count = 1;
196         NTSTATUS status;
197         struct dom_sid *sid;
198         TALLOC_CTX *mem_ctx2 = talloc(mem_ctx, 0);
199
200         status = smblsa_connect(cli);
201         if (!NT_STATUS_IS_OK(status)) {
202                 return status;
203         }
204
205         sid = dom_sid_parse_talloc(mem_ctx2, sid_str);
206         if (sid == NULL) {
207                 return NT_STATUS_INVALID_SID;
208         }
209
210         names.count = 0;
211         names.names = NULL;
212
213         sids.num_sids = 1;
214         sids.sids = talloc_p(mem_ctx2, struct lsa_SidPtr);
215         sids.sids[0].sid = sid;
216
217         r.in.handle = &cli->lsa->handle;
218         r.in.sids = &sids;
219         r.in.names = &names;
220         r.in.level = 1;
221         r.in.count = &count;
222         r.out.count = &count;
223         r.out.names = &names;
224
225         status = dcerpc_lsa_LookupSids(cli->lsa->pipe, mem_ctx2, &r);
226         if (!NT_STATUS_IS_OK(status)) {
227                 talloc_free(mem_ctx2);
228                 return status;
229         }
230         if (names.count != 1) {
231                 talloc_free(mem_ctx2);
232                 return NT_STATUS_UNSUCCESSFUL;
233         }
234
235         (*name) = talloc_asprintf(mem_ctx, "%s\\%s", 
236                                   r.out.domains->domains[0].name.string,
237                                   names.names[0].name.string);
238
239         talloc_free(mem_ctx2);
240
241         return NT_STATUS_OK;    
242 }
243
244 /*
245   lookup a name, returning its sid
246 */
247 NTSTATUS smblsa_lookup_name(struct smbcli_state *cli, 
248                             const char *name,
249                             TALLOC_CTX *mem_ctx,
250                             const char **sid_str)
251 {
252         struct lsa_LookupNames r;
253         struct lsa_TransSidArray sids;
254         struct lsa_String names;
255         uint32_t count = 1;
256         NTSTATUS status;
257         struct dom_sid *sid;
258         TALLOC_CTX *mem_ctx2 = talloc(mem_ctx, 0);
259         uint32_t rid;
260
261         status = smblsa_connect(cli);
262         if (!NT_STATUS_IS_OK(status)) {
263                 return status;
264         }
265
266         sids.count = 0;
267         sids.sids = NULL;
268
269         names.string = name;
270
271         r.in.handle = &cli->lsa->handle;
272         r.in.num_names = 1;
273         r.in.names = &names;
274         r.in.sids = &sids;
275         r.in.level = 1;
276         r.in.count = &count;
277         r.out.count = &count;
278         r.out.sids = &sids;
279
280         status = dcerpc_lsa_LookupNames(cli->lsa->pipe, mem_ctx2, &r);
281         if (!NT_STATUS_IS_OK(status)) {
282                 talloc_free(mem_ctx2);
283                 return status;
284         }
285         if (sids.count != 1) {
286                 talloc_free(mem_ctx2);
287                 return NT_STATUS_UNSUCCESSFUL;
288         }
289
290         sid = r.out.domains->domains[0].sid;
291         rid = sids.sids[0].rid;
292         
293         (*sid_str) = talloc_asprintf(mem_ctx, "%s-%u", 
294                                      dom_sid_string(mem_ctx2, sid), rid);
295
296         talloc_free(mem_ctx2);
297
298         return NT_STATUS_OK;    
299 }