1
0
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:
David Mulder
2019-12-20 14:10:49 -07:00
committed by Jeremy Allison
parent 2f55b662a3
commit a3ddd679d7
5 changed files with 198 additions and 0 deletions

View File

@ -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;
};
/*

View File

@ -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
*/

View File

@ -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"

View File

@ -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);
}

View File

@ -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"