CVE-2013-4408:s3:Ensure LookupNames replies arrays are range checked.
[Samba.git] / source4 / libcli / util / clilsa.c
blob0437352e757791996fe679112241ab427838acaf
1 /*
2 Unix SMB/CIFS implementation.
4 lsa calls for file sharing connections
6 Copyright (C) Andrew Tridgell 2004
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.
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.
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/>.
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.
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 #include "libcli/smb/smbXcli_base.h"
37 struct smblsa_state {
38 struct dcerpc_pipe *pipe;
39 struct smbcli_tree *ipc_tree;
40 struct policy_handle handle;
44 establish the lsa pipe connection
46 static NTSTATUS smblsa_connect(struct smbcli_state *cli)
48 struct smblsa_state *lsa;
49 NTSTATUS status;
50 struct lsa_OpenPolicy r;
51 uint16_t system_name = '\\';
52 union smb_tcon tcon;
53 struct lsa_ObjectAttribute attr;
54 struct lsa_QosInfo qos;
56 if (cli->lsa != NULL) {
57 return NT_STATUS_OK;
60 lsa = talloc(cli, struct smblsa_state);
61 if (lsa == NULL) {
62 return NT_STATUS_NO_MEMORY;
65 lsa->ipc_tree = smbcli_tree_init(cli->session, lsa, false);
66 if (lsa->ipc_tree == NULL) {
67 return NT_STATUS_NO_MEMORY;
70 /* connect to IPC$ */
71 tcon.generic.level = RAW_TCON_TCONX;
72 tcon.tconx.in.flags = TCONX_FLAG_EXTENDED_RESPONSE;
73 tcon.tconx.in.flags |= TCONX_FLAG_EXTENDED_SIGNATURES;
74 tcon.tconx.in.password = data_blob(NULL, 0);
75 tcon.tconx.in.path = "ipc$";
76 tcon.tconx.in.device = "IPC";
77 status = smb_raw_tcon(lsa->ipc_tree, lsa, &tcon);
78 if (!NT_STATUS_IS_OK(status)) {
79 talloc_free(lsa);
80 return status;
82 lsa->ipc_tree->tid = tcon.tconx.out.tid;
84 if (tcon.tconx.out.options & SMB_EXTENDED_SIGNATURES) {
85 smb1cli_session_protect_session_key(cli->session->smbXcli);
88 lsa->pipe = dcerpc_pipe_init(lsa, cli->transport->ev);
89 if (lsa->pipe == NULL) {
90 talloc_free(lsa);
91 return NT_STATUS_NO_MEMORY;
94 /* open the LSA pipe */
95 status = dcerpc_pipe_open_smb(lsa->pipe, lsa->ipc_tree, NDR_LSARPC_NAME);
96 if (!NT_STATUS_IS_OK(status)) {
97 talloc_free(lsa);
98 return status;
101 /* bind to the LSA pipe */
102 status = dcerpc_bind_auth_none(lsa->pipe, &ndr_table_lsarpc);
103 if (!NT_STATUS_IS_OK(status)) {
104 talloc_free(lsa);
105 return status;
109 /* open a lsa policy handle */
110 qos.len = 0;
111 qos.impersonation_level = 2;
112 qos.context_mode = 1;
113 qos.effective_only = 0;
115 attr.len = 0;
116 attr.root_dir = NULL;
117 attr.object_name = NULL;
118 attr.attributes = 0;
119 attr.sec_desc = NULL;
120 attr.sec_qos = &qos;
122 r.in.system_name = &system_name;
123 r.in.attr = &attr;
124 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
125 r.out.handle = &lsa->handle;
127 status = dcerpc_lsa_OpenPolicy_r(lsa->pipe->binding_handle, lsa, &r);
128 if (!NT_STATUS_IS_OK(status)) {
129 talloc_free(lsa);
130 return status;
133 if (!NT_STATUS_IS_OK(r.out.result)) {
134 talloc_free(lsa);
135 return r.out.result;
138 cli->lsa = lsa;
140 return NT_STATUS_OK;
145 return the set of privileges for the given sid
147 NTSTATUS smblsa_sid_privileges(struct smbcli_state *cli, struct dom_sid *sid,
148 TALLOC_CTX *mem_ctx,
149 struct lsa_RightSet *rights)
151 NTSTATUS status;
152 struct lsa_EnumAccountRights r;
154 status = smblsa_connect(cli);
155 if (!NT_STATUS_IS_OK(status)) {
156 return status;
159 r.in.handle = &cli->lsa->handle;
160 r.in.sid = sid;
161 r.out.rights = rights;
163 status = dcerpc_lsa_EnumAccountRights_r(cli->lsa->pipe->binding_handle, mem_ctx, &r);
164 if (!NT_STATUS_IS_OK(status)) {
165 return status;
168 return r.out.result;
173 check if a named sid has a particular named privilege
175 NTSTATUS smblsa_sid_check_privilege(struct smbcli_state *cli,
176 const char *sid_str,
177 const char *privilege)
179 struct lsa_RightSet rights;
180 NTSTATUS status;
181 TALLOC_CTX *mem_ctx = talloc_new(cli);
182 struct dom_sid *sid;
183 unsigned i;
185 sid = dom_sid_parse_talloc(mem_ctx, sid_str);
186 if (sid == NULL) {
187 talloc_free(mem_ctx);
188 return NT_STATUS_INVALID_SID;
191 status = smblsa_sid_privileges(cli, sid, mem_ctx, &rights);
192 if (!NT_STATUS_IS_OK(status)) {
193 talloc_free(mem_ctx);
194 return status;
197 for (i=0;i<rights.count;i++) {
198 if (strcmp(rights.names[i].string, privilege) == 0) {
199 talloc_free(mem_ctx);
200 return NT_STATUS_OK;
204 talloc_free(mem_ctx);
205 return NT_STATUS_NOT_FOUND;
210 lookup a SID, returning its name
212 NTSTATUS smblsa_lookup_sid(struct smbcli_state *cli,
213 const char *sid_str,
214 TALLOC_CTX *mem_ctx,
215 const char **name)
217 struct lsa_LookupSids r;
218 struct lsa_TransNameArray names;
219 struct lsa_SidArray sids;
220 struct lsa_RefDomainList *domains = NULL;
221 uint32_t count = 1;
222 NTSTATUS status;
223 struct dom_sid *sid;
224 TALLOC_CTX *mem_ctx2 = talloc_new(mem_ctx);
226 status = smblsa_connect(cli);
227 if (!NT_STATUS_IS_OK(status)) {
228 return status;
231 sid = dom_sid_parse_talloc(mem_ctx2, sid_str);
232 if (sid == NULL) {
233 return NT_STATUS_INVALID_SID;
236 names.count = 0;
237 names.names = NULL;
239 sids.num_sids = 1;
240 sids.sids = talloc(mem_ctx2, struct lsa_SidPtr);
241 sids.sids[0].sid = sid;
243 r.in.handle = &cli->lsa->handle;
244 r.in.sids = &sids;
245 r.in.names = &names;
246 r.in.level = 1;
247 r.in.count = &count;
248 r.out.count = &count;
249 r.out.names = &names;
250 r.out.domains = &domains;
252 status = dcerpc_lsa_LookupSids_r(cli->lsa->pipe->binding_handle, mem_ctx2, &r);
253 if (!NT_STATUS_IS_OK(status)) {
254 talloc_free(mem_ctx2);
255 return status;
257 if (!NT_STATUS_IS_OK(r.out.result)) {
258 talloc_free(mem_ctx2);
259 return r.out.result;
261 if (names.count != 1) {
262 talloc_free(mem_ctx2);
263 return NT_STATUS_INVALID_NETWORK_RESPONSE;
265 if (domains == NULL) {
266 talloc_free(mem_ctx2);
267 return NT_STATUS_INVALID_NETWORK_RESPONSE;
269 if (domains->count != 1) {
270 talloc_free(mem_ctx2);
271 return NT_STATUS_INVALID_NETWORK_RESPONSE;
273 if (names.names[0].sid_index != UINT32_MAX &&
274 names.names[0].sid_index >= domains->count)
276 talloc_free(mem_ctx2);
277 return NT_STATUS_INVALID_NETWORK_RESPONSE;
280 (*name) = talloc_asprintf(mem_ctx, "%s\\%s",
281 domains->domains[0].name.string,
282 names.names[0].name.string);
284 talloc_free(mem_ctx2);
286 return NT_STATUS_OK;
290 lookup a name, returning its sid
292 NTSTATUS smblsa_lookup_name(struct smbcli_state *cli,
293 const char *name,
294 TALLOC_CTX *mem_ctx,
295 const char **sid_str)
297 struct lsa_LookupNames r;
298 struct lsa_TransSidArray sids;
299 struct lsa_String names;
300 struct lsa_RefDomainList *domains = NULL;
301 uint32_t count = 1;
302 NTSTATUS status;
303 struct dom_sid *sid;
304 TALLOC_CTX *mem_ctx2 = talloc_new(mem_ctx);
305 uint32_t rid;
307 status = smblsa_connect(cli);
308 if (!NT_STATUS_IS_OK(status)) {
309 return status;
312 sids.count = 0;
313 sids.sids = NULL;
315 names.string = name;
317 r.in.handle = &cli->lsa->handle;
318 r.in.num_names = 1;
319 r.in.names = &names;
320 r.in.sids = &sids;
321 r.in.level = 1;
322 r.in.count = &count;
323 r.out.count = &count;
324 r.out.sids = &sids;
325 r.out.domains = &domains;
327 status = dcerpc_lsa_LookupNames_r(cli->lsa->pipe->binding_handle, mem_ctx2, &r);
328 if (!NT_STATUS_IS_OK(status)) {
329 talloc_free(mem_ctx2);
330 return status;
332 if (!NT_STATUS_IS_OK(r.out.result)) {
333 talloc_free(mem_ctx2);
334 return r.out.result;
336 if (sids.count != 1) {
337 talloc_free(mem_ctx2);
338 return NT_STATUS_INVALID_NETWORK_RESPONSE;
340 if (domains->count != 1) {
341 talloc_free(mem_ctx2);
342 return NT_STATUS_INVALID_NETWORK_RESPONSE;
345 sid = domains->domains[0].sid;
346 rid = sids.sids[0].rid;
348 (*sid_str) = talloc_asprintf(mem_ctx, "%s-%u",
349 dom_sid_string(mem_ctx2, sid), rid);
351 talloc_free(mem_ctx2);
353 return NT_STATUS_OK;
358 add a set of privileges to the given sid
360 NTSTATUS smblsa_sid_add_privileges(struct smbcli_state *cli, struct dom_sid *sid,
361 TALLOC_CTX *mem_ctx,
362 struct lsa_RightSet *rights)
364 NTSTATUS status;
365 struct lsa_AddAccountRights r;
367 status = smblsa_connect(cli);
368 if (!NT_STATUS_IS_OK(status)) {
369 return status;
372 r.in.handle = &cli->lsa->handle;
373 r.in.sid = sid;
374 r.in.rights = rights;
376 status = dcerpc_lsa_AddAccountRights_r(cli->lsa->pipe->binding_handle, mem_ctx, &r);
377 if (!NT_STATUS_IS_OK(status)) {
378 return status;
381 return r.out.result;
385 remove a set of privileges from the given sid
387 NTSTATUS smblsa_sid_del_privileges(struct smbcli_state *cli, struct dom_sid *sid,
388 TALLOC_CTX *mem_ctx,
389 struct lsa_RightSet *rights)
391 NTSTATUS status;
392 struct lsa_RemoveAccountRights r;
394 status = smblsa_connect(cli);
395 if (!NT_STATUS_IS_OK(status)) {
396 return status;
399 r.in.handle = &cli->lsa->handle;
400 r.in.sid = sid;
401 r.in.remove_all = 0;
402 r.in.rights = rights;
404 status = dcerpc_lsa_RemoveAccountRights_r(cli->lsa->pipe->binding_handle, mem_ctx, &r);
405 if (!NT_STATUS_IS_OK(status)) {
406 return status;
409 return r.out.result;