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 2 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, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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.
30 #include "libcli/raw/libcliraw.h"
31 #include "libcli/libcli.h"
32 #include "libcli/security/proto.h"
33 #include "librpc/gen_ndr/ndr_lsa.h"
34 #include "librpc/gen_ndr/ndr_lsa_c.h"
37 struct dcerpc_pipe *pipe;
38 struct smbcli_tree *ipc_tree;
39 struct policy_handle handle;
43 establish the lsa pipe connection
45 static NTSTATUS smblsa_connect(struct smbcli_state *cli)
47 struct smblsa_state *lsa;
49 struct lsa_OpenPolicy r;
50 uint16_t system_name = '\\';
52 struct lsa_ObjectAttribute attr;
53 struct lsa_QosInfo qos;
55 if (cli->lsa != NULL) {
59 lsa = talloc(cli, struct smblsa_state);
61 return NT_STATUS_NO_MEMORY;
64 lsa->ipc_tree = smbcli_tree_init(cli->session, lsa, False);
65 if (lsa->ipc_tree == NULL) {
66 return NT_STATUS_NO_MEMORY;
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)) {
80 lsa->ipc_tree->tid = tcon.tconx.out.tid;
82 lsa->pipe = dcerpc_pipe_init(lsa, cli->transport->socket->event.ctx);
83 if (lsa->pipe == NULL) {
85 return NT_STATUS_NO_MEMORY;
88 /* open the LSA pipe */
89 status = dcerpc_pipe_open_smb(lsa->pipe->conn, lsa->ipc_tree, DCERPC_LSARPC_NAME);
90 if (!NT_STATUS_IS_OK(status)) {
95 /* bind to the LSA pipe */
96 status = dcerpc_bind_auth_none(lsa->pipe, &dcerpc_table_lsarpc);
97 if (!NT_STATUS_IS_OK(status)) {
103 /* open a lsa policy handle */
105 qos.impersonation_level = 2;
106 qos.context_mode = 1;
107 qos.effective_only = 0;
110 attr.root_dir = NULL;
111 attr.object_name = NULL;
113 attr.sec_desc = NULL;
116 r.in.system_name = &system_name;
118 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
119 r.out.handle = &lsa->handle;
121 status = dcerpc_lsa_OpenPolicy(lsa->pipe, lsa, &r);
122 if (!NT_STATUS_IS_OK(status)) {
134 return the set of privileges for the given sid
136 NTSTATUS smblsa_sid_privileges(struct smbcli_state *cli, struct dom_sid *sid,
138 struct lsa_RightSet *rights)
141 struct lsa_EnumAccountRights r;
143 status = smblsa_connect(cli);
144 if (!NT_STATUS_IS_OK(status)) {
148 r.in.handle = &cli->lsa->handle;
150 r.out.rights = rights;
152 return dcerpc_lsa_EnumAccountRights(cli->lsa->pipe, mem_ctx, &r);
157 check if a named sid has a particular named privilege
159 NTSTATUS smblsa_sid_check_privilege(struct smbcli_state *cli,
161 const char *privilege)
163 struct lsa_RightSet rights;
165 TALLOC_CTX *mem_ctx = talloc_new(cli);
169 sid = dom_sid_parse_talloc(mem_ctx, sid_str);
171 talloc_free(mem_ctx);
172 return NT_STATUS_INVALID_SID;
175 status = smblsa_sid_privileges(cli, sid, mem_ctx, &rights);
176 if (!NT_STATUS_IS_OK(status)) {
177 talloc_free(mem_ctx);
181 for (i=0;i<rights.count;i++) {
182 if (strcmp(rights.names[i].string, privilege) == 0) {
183 talloc_free(mem_ctx);
188 talloc_free(mem_ctx);
189 return NT_STATUS_NOT_FOUND;
194 lookup a SID, returning its name
196 NTSTATUS smblsa_lookup_sid(struct smbcli_state *cli,
201 struct lsa_LookupSids r;
202 struct lsa_TransNameArray names;
203 struct lsa_SidArray sids;
207 TALLOC_CTX *mem_ctx2 = talloc_new(mem_ctx);
209 status = smblsa_connect(cli);
210 if (!NT_STATUS_IS_OK(status)) {
214 sid = dom_sid_parse_talloc(mem_ctx2, sid_str);
216 return NT_STATUS_INVALID_SID;
223 sids.sids = talloc(mem_ctx2, struct lsa_SidPtr);
224 sids.sids[0].sid = sid;
226 r.in.handle = &cli->lsa->handle;
231 r.out.count = &count;
232 r.out.names = &names;
234 status = dcerpc_lsa_LookupSids(cli->lsa->pipe, mem_ctx2, &r);
235 if (!NT_STATUS_IS_OK(status)) {
236 talloc_free(mem_ctx2);
239 if (names.count != 1) {
240 talloc_free(mem_ctx2);
241 return NT_STATUS_UNSUCCESSFUL;
244 (*name) = talloc_asprintf(mem_ctx, "%s\\%s",
245 r.out.domains->domains[0].name.string,
246 names.names[0].name.string);
248 talloc_free(mem_ctx2);
254 lookup a name, returning its sid
256 NTSTATUS smblsa_lookup_name(struct smbcli_state *cli,
259 const char **sid_str)
261 struct lsa_LookupNames r;
262 struct lsa_TransSidArray sids;
263 struct lsa_String names;
267 TALLOC_CTX *mem_ctx2 = talloc_new(mem_ctx);
270 status = smblsa_connect(cli);
271 if (!NT_STATUS_IS_OK(status)) {
280 r.in.handle = &cli->lsa->handle;
286 r.out.count = &count;
289 status = dcerpc_lsa_LookupNames(cli->lsa->pipe, mem_ctx2, &r);
290 if (!NT_STATUS_IS_OK(status)) {
291 talloc_free(mem_ctx2);
294 if (sids.count != 1) {
295 talloc_free(mem_ctx2);
296 return NT_STATUS_UNSUCCESSFUL;
299 sid = r.out.domains->domains[0].sid;
300 rid = sids.sids[0].rid;
302 (*sid_str) = talloc_asprintf(mem_ctx, "%s-%u",
303 dom_sid_string(mem_ctx2, sid), rid);
305 talloc_free(mem_ctx2);
312 add a set of privileges to the given sid
314 NTSTATUS smblsa_sid_add_privileges(struct smbcli_state *cli, struct dom_sid *sid,
316 struct lsa_RightSet *rights)
319 struct lsa_AddAccountRights r;
321 status = smblsa_connect(cli);
322 if (!NT_STATUS_IS_OK(status)) {
326 r.in.handle = &cli->lsa->handle;
328 r.in.rights = rights;
330 return dcerpc_lsa_AddAccountRights(cli->lsa->pipe, mem_ctx, &r);
334 remove a set of privileges from the given sid
336 NTSTATUS smblsa_sid_del_privileges(struct smbcli_state *cli, struct dom_sid *sid,
338 struct lsa_RightSet *rights)
341 struct lsa_RemoveAccountRights r;
343 status = smblsa_connect(cli);
344 if (!NT_STATUS_IS_OK(status)) {
348 r.in.handle = &cli->lsa->handle;
351 r.in.rights = rights;
353 return dcerpc_lsa_RemoveAccountRights(cli->lsa->pipe, mem_ctx, &r);