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.
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"
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 cli
->transport
->iconv_convenience
);
84 if (lsa
->pipe
== NULL
) {
86 return NT_STATUS_NO_MEMORY
;
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
)) {
96 /* bind to the LSA pipe */
97 status
= dcerpc_bind_auth_none(lsa
->pipe
, &ndr_table_lsarpc
);
98 if (!NT_STATUS_IS_OK(status
)) {
104 /* open a lsa policy handle */
106 qos
.impersonation_level
= 2;
107 qos
.context_mode
= 1;
108 qos
.effective_only
= 0;
111 attr
.root_dir
= NULL
;
112 attr
.object_name
= NULL
;
114 attr
.sec_desc
= NULL
;
117 r
.in
.system_name
= &system_name
;
119 r
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
120 r
.out
.handle
= &lsa
->handle
;
122 status
= dcerpc_lsa_OpenPolicy(lsa
->pipe
, lsa
, &r
);
123 if (!NT_STATUS_IS_OK(status
)) {
135 return the set of privileges for the given sid
137 NTSTATUS
smblsa_sid_privileges(struct smbcli_state
*cli
, struct dom_sid
*sid
,
139 struct lsa_RightSet
*rights
)
142 struct lsa_EnumAccountRights r
;
144 status
= smblsa_connect(cli
);
145 if (!NT_STATUS_IS_OK(status
)) {
149 r
.in
.handle
= &cli
->lsa
->handle
;
151 r
.out
.rights
= rights
;
153 return dcerpc_lsa_EnumAccountRights(cli
->lsa
->pipe
, mem_ctx
, &r
);
158 check if a named sid has a particular named privilege
160 NTSTATUS
smblsa_sid_check_privilege(struct smbcli_state
*cli
,
162 const char *privilege
)
164 struct lsa_RightSet rights
;
166 TALLOC_CTX
*mem_ctx
= talloc_new(cli
);
170 sid
= dom_sid_parse_talloc(mem_ctx
, sid_str
);
172 talloc_free(mem_ctx
);
173 return NT_STATUS_INVALID_SID
;
176 status
= smblsa_sid_privileges(cli
, sid
, mem_ctx
, &rights
);
177 if (!NT_STATUS_IS_OK(status
)) {
178 talloc_free(mem_ctx
);
182 for (i
=0;i
<rights
.count
;i
++) {
183 if (strcmp(rights
.names
[i
].string
, privilege
) == 0) {
184 talloc_free(mem_ctx
);
189 talloc_free(mem_ctx
);
190 return NT_STATUS_NOT_FOUND
;
195 lookup a SID, returning its name
197 NTSTATUS
smblsa_lookup_sid(struct smbcli_state
*cli
,
202 struct lsa_LookupSids r
;
203 struct lsa_TransNameArray names
;
204 struct lsa_SidArray sids
;
205 struct lsa_RefDomainList
*domains
= NULL
;
209 TALLOC_CTX
*mem_ctx2
= talloc_new(mem_ctx
);
211 status
= smblsa_connect(cli
);
212 if (!NT_STATUS_IS_OK(status
)) {
216 sid
= dom_sid_parse_talloc(mem_ctx2
, sid_str
);
218 return NT_STATUS_INVALID_SID
;
225 sids
.sids
= talloc(mem_ctx2
, struct lsa_SidPtr
);
226 sids
.sids
[0].sid
= sid
;
228 r
.in
.handle
= &cli
->lsa
->handle
;
233 r
.out
.count
= &count
;
234 r
.out
.names
= &names
;
235 r
.out
.domains
= &domains
;
237 status
= dcerpc_lsa_LookupSids(cli
->lsa
->pipe
, mem_ctx2
, &r
);
238 if (!NT_STATUS_IS_OK(status
)) {
239 talloc_free(mem_ctx2
);
242 if (names
.count
!= 1) {
243 talloc_free(mem_ctx2
);
244 return NT_STATUS_UNSUCCESSFUL
;
247 (*name
) = talloc_asprintf(mem_ctx
, "%s\\%s",
248 domains
->domains
[0].name
.string
,
249 names
.names
[0].name
.string
);
251 talloc_free(mem_ctx2
);
257 lookup a name, returning its sid
259 NTSTATUS
smblsa_lookup_name(struct smbcli_state
*cli
,
262 const char **sid_str
)
264 struct lsa_LookupNames r
;
265 struct lsa_TransSidArray sids
;
266 struct lsa_String names
;
267 struct lsa_RefDomainList
*domains
= NULL
;
271 TALLOC_CTX
*mem_ctx2
= talloc_new(mem_ctx
);
274 status
= smblsa_connect(cli
);
275 if (!NT_STATUS_IS_OK(status
)) {
284 r
.in
.handle
= &cli
->lsa
->handle
;
290 r
.out
.count
= &count
;
292 r
.out
.domains
= &domains
;
294 status
= dcerpc_lsa_LookupNames(cli
->lsa
->pipe
, mem_ctx2
, &r
);
295 if (!NT_STATUS_IS_OK(status
)) {
296 talloc_free(mem_ctx2
);
299 if (sids
.count
!= 1) {
300 talloc_free(mem_ctx2
);
301 return NT_STATUS_UNSUCCESSFUL
;
304 sid
= domains
->domains
[0].sid
;
305 rid
= sids
.sids
[0].rid
;
307 (*sid_str
) = talloc_asprintf(mem_ctx
, "%s-%u",
308 dom_sid_string(mem_ctx2
, sid
), rid
);
310 talloc_free(mem_ctx2
);
317 add a set of privileges to the given sid
319 NTSTATUS
smblsa_sid_add_privileges(struct smbcli_state
*cli
, struct dom_sid
*sid
,
321 struct lsa_RightSet
*rights
)
324 struct lsa_AddAccountRights r
;
326 status
= smblsa_connect(cli
);
327 if (!NT_STATUS_IS_OK(status
)) {
331 r
.in
.handle
= &cli
->lsa
->handle
;
333 r
.in
.rights
= rights
;
335 return dcerpc_lsa_AddAccountRights(cli
->lsa
->pipe
, mem_ctx
, &r
);
339 remove a set of privileges from the given sid
341 NTSTATUS
smblsa_sid_del_privileges(struct smbcli_state
*cli
, struct dom_sid
*sid
,
343 struct lsa_RightSet
*rights
)
346 struct lsa_RemoveAccountRights r
;
348 status
= smblsa_connect(cli
);
349 if (!NT_STATUS_IS_OK(status
)) {
353 r
.in
.handle
= &cli
->lsa
->handle
;
356 r
.in
.rights
= rights
;
358 return dcerpc_lsa_RemoveAccountRights(cli
->lsa
->pipe
, mem_ctx
, &r
);