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 if (lsa
->pipe
== NULL
) {
85 return NT_STATUS_NO_MEMORY
;
88 /* open the LSA pipe */
89 status
= dcerpc_pipe_open_smb(lsa
->pipe
, lsa
->ipc_tree
, NDR_LSARPC_NAME
);
90 if (!NT_STATUS_IS_OK(status
)) {
95 /* bind to the LSA pipe */
96 status
= dcerpc_bind_auth_none(lsa
->pipe
, &ndr_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_r(lsa
->pipe
->binding_handle
, lsa
, &r
);
122 if (!NT_STATUS_IS_OK(status
)) {
127 if (!NT_STATUS_IS_OK(r
.out
.result
)) {
139 return the set of privileges for the given sid
141 NTSTATUS
smblsa_sid_privileges(struct smbcli_state
*cli
, struct dom_sid
*sid
,
143 struct lsa_RightSet
*rights
)
146 struct lsa_EnumAccountRights r
;
148 status
= smblsa_connect(cli
);
149 if (!NT_STATUS_IS_OK(status
)) {
153 r
.in
.handle
= &cli
->lsa
->handle
;
155 r
.out
.rights
= rights
;
157 status
= dcerpc_lsa_EnumAccountRights_r(cli
->lsa
->pipe
->binding_handle
, mem_ctx
, &r
);
158 if (!NT_STATUS_IS_OK(status
)) {
167 check if a named sid has a particular named privilege
169 NTSTATUS
smblsa_sid_check_privilege(struct smbcli_state
*cli
,
171 const char *privilege
)
173 struct lsa_RightSet rights
;
175 TALLOC_CTX
*mem_ctx
= talloc_new(cli
);
179 sid
= dom_sid_parse_talloc(mem_ctx
, sid_str
);
181 talloc_free(mem_ctx
);
182 return NT_STATUS_INVALID_SID
;
185 status
= smblsa_sid_privileges(cli
, sid
, mem_ctx
, &rights
);
186 if (!NT_STATUS_IS_OK(status
)) {
187 talloc_free(mem_ctx
);
191 for (i
=0;i
<rights
.count
;i
++) {
192 if (strcmp(rights
.names
[i
].string
, privilege
) == 0) {
193 talloc_free(mem_ctx
);
198 talloc_free(mem_ctx
);
199 return NT_STATUS_NOT_FOUND
;
204 lookup a SID, returning its name
206 NTSTATUS
smblsa_lookup_sid(struct smbcli_state
*cli
,
211 struct lsa_LookupSids r
;
212 struct lsa_TransNameArray names
;
213 struct lsa_SidArray sids
;
214 struct lsa_RefDomainList
*domains
= NULL
;
218 TALLOC_CTX
*mem_ctx2
= talloc_new(mem_ctx
);
220 status
= smblsa_connect(cli
);
221 if (!NT_STATUS_IS_OK(status
)) {
225 sid
= dom_sid_parse_talloc(mem_ctx2
, sid_str
);
227 return NT_STATUS_INVALID_SID
;
234 sids
.sids
= talloc(mem_ctx2
, struct lsa_SidPtr
);
235 sids
.sids
[0].sid
= sid
;
237 r
.in
.handle
= &cli
->lsa
->handle
;
242 r
.out
.count
= &count
;
243 r
.out
.names
= &names
;
244 r
.out
.domains
= &domains
;
246 status
= dcerpc_lsa_LookupSids_r(cli
->lsa
->pipe
->binding_handle
, mem_ctx2
, &r
);
247 if (!NT_STATUS_IS_OK(status
)) {
248 talloc_free(mem_ctx2
);
251 if (!NT_STATUS_IS_OK(r
.out
.result
)) {
252 talloc_free(mem_ctx2
);
255 if (names
.count
!= 1) {
256 talloc_free(mem_ctx2
);
257 return NT_STATUS_UNSUCCESSFUL
;
260 (*name
) = talloc_asprintf(mem_ctx
, "%s\\%s",
261 domains
->domains
[0].name
.string
,
262 names
.names
[0].name
.string
);
264 talloc_free(mem_ctx2
);
270 lookup a name, returning its sid
272 NTSTATUS
smblsa_lookup_name(struct smbcli_state
*cli
,
275 const char **sid_str
)
277 struct lsa_LookupNames r
;
278 struct lsa_TransSidArray sids
;
279 struct lsa_String names
;
280 struct lsa_RefDomainList
*domains
= NULL
;
284 TALLOC_CTX
*mem_ctx2
= talloc_new(mem_ctx
);
287 status
= smblsa_connect(cli
);
288 if (!NT_STATUS_IS_OK(status
)) {
297 r
.in
.handle
= &cli
->lsa
->handle
;
303 r
.out
.count
= &count
;
305 r
.out
.domains
= &domains
;
307 status
= dcerpc_lsa_LookupNames_r(cli
->lsa
->pipe
->binding_handle
, mem_ctx2
, &r
);
308 if (!NT_STATUS_IS_OK(status
)) {
309 talloc_free(mem_ctx2
);
312 if (!NT_STATUS_IS_OK(r
.out
.result
)) {
313 talloc_free(mem_ctx2
);
316 if (sids
.count
!= 1) {
317 talloc_free(mem_ctx2
);
318 return NT_STATUS_UNSUCCESSFUL
;
321 sid
= domains
->domains
[0].sid
;
322 rid
= sids
.sids
[0].rid
;
324 (*sid_str
) = talloc_asprintf(mem_ctx
, "%s-%u",
325 dom_sid_string(mem_ctx2
, sid
), rid
);
327 talloc_free(mem_ctx2
);
334 add a set of privileges to the given sid
336 NTSTATUS
smblsa_sid_add_privileges(struct smbcli_state
*cli
, struct dom_sid
*sid
,
338 struct lsa_RightSet
*rights
)
341 struct lsa_AddAccountRights r
;
343 status
= smblsa_connect(cli
);
344 if (!NT_STATUS_IS_OK(status
)) {
348 r
.in
.handle
= &cli
->lsa
->handle
;
350 r
.in
.rights
= rights
;
352 status
= dcerpc_lsa_AddAccountRights_r(cli
->lsa
->pipe
->binding_handle
, mem_ctx
, &r
);
353 if (!NT_STATUS_IS_OK(status
)) {
361 remove a set of privileges from the given sid
363 NTSTATUS
smblsa_sid_del_privileges(struct smbcli_state
*cli
, struct dom_sid
*sid
,
365 struct lsa_RightSet
*rights
)
368 struct lsa_RemoveAccountRights r
;
370 status
= smblsa_connect(cli
);
371 if (!NT_STATUS_IS_OK(status
)) {
375 r
.in
.handle
= &cli
->lsa
->handle
;
378 r
.in
.rights
= rights
;
380 status
= dcerpc_lsa_RemoveAccountRights_r(cli
->lsa
->pipe
->binding_handle
, mem_ctx
, &r
);
381 if (!NT_STATUS_IS_OK(status
)) {