mirror of
https://github.com/samba-team/samba.git
synced 2025-08-26 01:49:31 +03:00
Add SMB2 lsa helper routines
Signed-off-by: David Mulder <dmulder@suse.com> Reviewed-by: Noel Power <noel.power@suse.com> Reviewed-by: Jeremy Allison <jra@samba.org> (cherry picked from commit 3763052c2a95ac9bd60f00458389a5245cf5d58d)
This commit is contained in:
committed by
Jeremy Allison
parent
2f55b662a3
commit
a3ddd679d7
@ -101,12 +101,23 @@ struct smb2_transport {
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
SMB2 LSA state
|
||||
*/
|
||||
struct smb2lsa_state {
|
||||
struct dcerpc_binding_handle *binding_handle;
|
||||
struct smb2_tree *ipc_tree;
|
||||
struct policy_handle handle;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
SMB2 tree context
|
||||
*/
|
||||
struct smb2_tree {
|
||||
struct smb2_session *session;
|
||||
struct smbXcli_tcon *smbXcli;
|
||||
struct smb2lsa_state *lsa;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
#include "includes.h"
|
||||
#include "libcli/raw/libcliraw.h"
|
||||
#include "libcli/smb2/smb2.h"
|
||||
#include "libcli/libcli.h"
|
||||
#include "libcli/security/security.h"
|
||||
#include "librpc/gen_ndr/ndr_lsa.h"
|
||||
@ -142,6 +143,81 @@ static NTSTATUS smblsa_connect(struct smbcli_state *cli)
|
||||
}
|
||||
|
||||
|
||||
static NTSTATUS smb2lsa_connect(struct smb2_tree *tree)
|
||||
{
|
||||
struct smb2lsa_state *lsa = NULL;
|
||||
struct dcerpc_pipe *lsa_pipe = NULL;
|
||||
NTSTATUS status;
|
||||
struct lsa_OpenPolicy2 r = {{0}, {0}};
|
||||
const char *system_name = "\\";
|
||||
struct lsa_ObjectAttribute attr = {0};
|
||||
struct lsa_QosInfo qos = {0};
|
||||
|
||||
if (tree->lsa != NULL) {
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
lsa = talloc(tree, struct smb2lsa_state);
|
||||
if (lsa == NULL) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
lsa_pipe = dcerpc_pipe_init(lsa, tree->session->transport->ev);
|
||||
if (lsa_pipe == NULL) {
|
||||
talloc_free(lsa);
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
/* open the LSA pipe */
|
||||
status = dcerpc_pipe_open_smb2(lsa_pipe, tree, NDR_LSARPC_NAME);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
talloc_free(lsa);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* bind to the LSA pipe */
|
||||
status = dcerpc_bind_auth_none(lsa_pipe, &ndr_table_lsarpc);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
talloc_free(lsa);
|
||||
return status;
|
||||
}
|
||||
lsa->binding_handle = lsa_pipe->binding_handle;
|
||||
|
||||
/* open a lsa policy handle */
|
||||
qos.len = 0;
|
||||
qos.impersonation_level = 2;
|
||||
qos.context_mode = 1;
|
||||
qos.effective_only = 0;
|
||||
|
||||
attr.len = 0;
|
||||
attr.root_dir = NULL;
|
||||
attr.object_name = NULL;
|
||||
attr.attributes = 0;
|
||||
attr.sec_desc = NULL;
|
||||
attr.sec_qos = &qos;
|
||||
|
||||
r.in.system_name = system_name;
|
||||
r.in.attr = &attr;
|
||||
r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
|
||||
r.out.handle = &lsa->handle;
|
||||
|
||||
status = dcerpc_lsa_OpenPolicy2_r(lsa->binding_handle, lsa, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
talloc_free(lsa);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (!NT_STATUS_IS_OK(r.out.result)) {
|
||||
talloc_free(lsa);
|
||||
return r.out.result;
|
||||
}
|
||||
|
||||
tree->lsa = lsa;
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
return the set of privileges for the given sid
|
||||
*/
|
||||
@ -170,6 +246,31 @@ NTSTATUS smblsa_sid_privileges(struct smbcli_state *cli, struct dom_sid *sid,
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS smb2lsa_sid_privileges(struct smb2_tree *tree, struct dom_sid *sid,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct lsa_RightSet *rights)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct lsa_EnumAccountRights r = {{0}, {0}};
|
||||
|
||||
status = smb2lsa_connect(tree);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
r.in.handle = &tree->lsa->handle;
|
||||
r.in.sid = sid;
|
||||
r.out.rights = rights;
|
||||
|
||||
status = dcerpc_lsa_EnumAccountRights_r(tree->lsa->binding_handle, mem_ctx, &r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
return r.out.result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
check if a named sid has a particular named privilege
|
||||
*/
|
||||
@ -207,6 +308,45 @@ NTSTATUS smblsa_sid_check_privilege(struct smbcli_state *cli,
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS smb2lsa_sid_check_privilege(struct smb2_tree *tree,
|
||||
const char *sid_str,
|
||||
const char *privilege)
|
||||
{
|
||||
struct lsa_RightSet rights = {0};
|
||||
NTSTATUS status;
|
||||
TALLOC_CTX *mem_ctx = NULL;
|
||||
struct dom_sid *sid = NULL;
|
||||
unsigned i;
|
||||
|
||||
mem_ctx = talloc_new(tree);
|
||||
if (!mem_ctx) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
sid = dom_sid_parse_talloc(mem_ctx, sid_str);
|
||||
if (sid == NULL) {
|
||||
talloc_free(mem_ctx);
|
||||
return NT_STATUS_INVALID_SID;
|
||||
}
|
||||
|
||||
status = smb2lsa_sid_privileges(tree, sid, mem_ctx, &rights);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
talloc_free(mem_ctx);
|
||||
return status;
|
||||
}
|
||||
|
||||
for (i=0;i<rights.count;i++) {
|
||||
if (strcmp(rights.names[i].string, privilege) == 0) {
|
||||
talloc_free(mem_ctx);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
talloc_free(mem_ctx);
|
||||
return NT_STATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
lookup a SID, returning its name
|
||||
*/
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "libcli/raw/libcliraw.h"
|
||||
#include "libcli/libcli.h"
|
||||
#include "librpc/gen_ndr/lsa.h"
|
||||
#include "libcli/smb2/smb2.h"
|
||||
#include "libcli/util/clilsa.h"
|
||||
#include "libcli/security/security.h"
|
||||
#include "torture/util.h"
|
||||
|
@ -34,6 +34,9 @@
|
||||
#include "torture/torture.h"
|
||||
#include "torture/smb2/proto.h"
|
||||
#include "source4/torture/util.h"
|
||||
#include "libcli/security/dom_sid.h"
|
||||
#include "librpc/gen_ndr/lsa.h"
|
||||
#include "libcli/util/clilsa.h"
|
||||
|
||||
|
||||
/*
|
||||
@ -979,3 +982,45 @@ void smb2_oplock_create(struct smb2_create *io, const char *name, uint8_t oplock
|
||||
oplock);
|
||||
}
|
||||
|
||||
/*
|
||||
a wrapper around smblsa_sid_check_privilege, that tries to take
|
||||
account of the fact that the lsa privileges calls don't expand
|
||||
group memberships, using an explicit check for administrator. There
|
||||
must be a better way ...
|
||||
*/
|
||||
NTSTATUS torture_smb2_check_privilege(struct smb2_tree *tree,
|
||||
const char *sid_str,
|
||||
const char *privilege)
|
||||
{
|
||||
struct dom_sid *sid = NULL;
|
||||
TALLOC_CTX *tmp_ctx = NULL;
|
||||
uint32_t rid;
|
||||
NTSTATUS status;
|
||||
|
||||
tmp_ctx = talloc_new(tree);
|
||||
if (tmp_ctx == NULL) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
sid = dom_sid_parse_talloc(tmp_ctx, sid_str);
|
||||
if (sid == NULL) {
|
||||
talloc_free(tmp_ctx);
|
||||
return NT_STATUS_INVALID_SID;
|
||||
}
|
||||
|
||||
status = dom_sid_split_rid(tmp_ctx, sid, NULL, &rid);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
TALLOC_FREE(tmp_ctx);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (rid == DOMAIN_RID_ADMINISTRATOR) {
|
||||
/* assume the administrator has them all */
|
||||
TALLOC_FREE(tmp_ctx);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
talloc_free(tmp_ctx);
|
||||
|
||||
return smb2lsa_sid_check_privilege(tree, sid_str, privilege);
|
||||
}
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "libcli/resolve/resolve.h"
|
||||
#include "param/param.h"
|
||||
#include "libcli/security/security.h"
|
||||
#include "libcli/smb2/smb2.h"
|
||||
#include "libcli/util/clilsa.h"
|
||||
#include "torture/util.h"
|
||||
#include "libcli/smb/smbXcli_base.h"
|
||||
|
Reference in New Issue
Block a user