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"
35 #include "libcli/smb/smbXcli_base.h"
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
;
50 struct lsa_OpenPolicy r
;
51 uint16_t system_name
= '\\';
53 struct lsa_ObjectAttribute attr
;
54 struct lsa_QosInfo qos
;
56 if (cli
->lsa
!= NULL
) {
60 lsa
= talloc(cli
, struct smblsa_state
);
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
;
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
)) {
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
) {
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
)) {
101 /* bind to the LSA pipe */
102 status
= dcerpc_bind_auth_none(lsa
->pipe
, &ndr_table_lsarpc
);
103 if (!NT_STATUS_IS_OK(status
)) {
109 /* open a lsa policy handle */
111 qos
.impersonation_level
= 2;
112 qos
.context_mode
= 1;
113 qos
.effective_only
= 0;
116 attr
.root_dir
= NULL
;
117 attr
.object_name
= NULL
;
119 attr
.sec_desc
= NULL
;
122 r
.in
.system_name
= &system_name
;
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
)) {
133 if (!NT_STATUS_IS_OK(r
.out
.result
)) {
145 return the set of privileges for the given sid
147 NTSTATUS
smblsa_sid_privileges(struct smbcli_state
*cli
, struct dom_sid
*sid
,
149 struct lsa_RightSet
*rights
)
152 struct lsa_EnumAccountRights r
;
154 status
= smblsa_connect(cli
);
155 if (!NT_STATUS_IS_OK(status
)) {
159 r
.in
.handle
= &cli
->lsa
->handle
;
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
)) {
173 check if a named sid has a particular named privilege
175 NTSTATUS
smblsa_sid_check_privilege(struct smbcli_state
*cli
,
177 const char *privilege
)
179 struct lsa_RightSet rights
;
181 TALLOC_CTX
*mem_ctx
= talloc_new(cli
);
185 sid
= dom_sid_parse_talloc(mem_ctx
, sid_str
);
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
);
197 for (i
=0;i
<rights
.count
;i
++) {
198 if (strcmp(rights
.names
[i
].string
, privilege
) == 0) {
199 talloc_free(mem_ctx
);
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
,
217 struct lsa_LookupSids r
;
218 struct lsa_TransNameArray names
;
219 struct lsa_SidArray sids
;
220 struct lsa_RefDomainList
*domains
= NULL
;
224 TALLOC_CTX
*mem_ctx2
= talloc_new(mem_ctx
);
226 status
= smblsa_connect(cli
);
227 if (!NT_STATUS_IS_OK(status
)) {
231 sid
= dom_sid_parse_talloc(mem_ctx2
, sid_str
);
233 return NT_STATUS_INVALID_SID
;
240 sids
.sids
= talloc(mem_ctx2
, struct lsa_SidPtr
);
241 sids
.sids
[0].sid
= sid
;
243 r
.in
.handle
= &cli
->lsa
->handle
;
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
);
257 if (!NT_STATUS_IS_OK(r
.out
.result
)) {
258 talloc_free(mem_ctx2
);
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
);
290 lookup a name, returning its sid
292 NTSTATUS
smblsa_lookup_name(struct smbcli_state
*cli
,
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
;
304 TALLOC_CTX
*mem_ctx2
= talloc_new(mem_ctx
);
307 status
= smblsa_connect(cli
);
308 if (!NT_STATUS_IS_OK(status
)) {
317 r
.in
.handle
= &cli
->lsa
->handle
;
323 r
.out
.count
= &count
;
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
);
332 if (!NT_STATUS_IS_OK(r
.out
.result
)) {
333 talloc_free(mem_ctx2
);
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
);
358 add a set of privileges to the given sid
360 NTSTATUS
smblsa_sid_add_privileges(struct smbcli_state
*cli
, struct dom_sid
*sid
,
362 struct lsa_RightSet
*rights
)
365 struct lsa_AddAccountRights r
;
367 status
= smblsa_connect(cli
);
368 if (!NT_STATUS_IS_OK(status
)) {
372 r
.in
.handle
= &cli
->lsa
->handle
;
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
)) {
385 remove a set of privileges from the given sid
387 NTSTATUS
smblsa_sid_del_privileges(struct smbcli_state
*cli
, struct dom_sid
*sid
,
389 struct lsa_RightSet
*rights
)
392 struct lsa_RemoveAccountRights r
;
394 status
= smblsa_connect(cli
);
395 if (!NT_STATUS_IS_OK(status
)) {
399 r
.in
.handle
= &cli
->lsa
->handle
;
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
)) {