#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"
}
+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
*/
}
+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
*/
}
+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
*/
#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"
/*
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);
+}